1 //===-- AMDGPULowerIntrinsics.cpp -----------------------------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "AMDGPU.h" 11 #include "llvm/IR/Constants.h" 12 #include "llvm/IR/Instructions.h" 13 #include "llvm/IR/IntrinsicInst.h" 14 #include "llvm/IR/Module.h" 15 #include "llvm/Transforms/Utils/LowerMemIntrinsics.h" 16 17 #define DEBUG_TYPE "amdgpu-lower-intrinsics" 18 19 using namespace llvm; 20 21 namespace { 22 23 const unsigned MaxStaticSize = 1024; 24 25 class AMDGPULowerIntrinsics : public ModulePass { 26 public: 27 static char ID; 28 29 AMDGPULowerIntrinsics() : ModulePass(ID) { } 30 bool runOnModule(Module &M) override; 31 StringRef getPassName() const override { 32 return "AMDGPU Lower Intrinsics"; 33 } 34 }; 35 36 } 37 38 char AMDGPULowerIntrinsics::ID = 0; 39 40 char &llvm::AMDGPULowerIntrinsicsID = AMDGPULowerIntrinsics::ID; 41 42 INITIALIZE_PASS(AMDGPULowerIntrinsics, DEBUG_TYPE, 43 "Lower intrinsics", false, false) 44 45 // TODO: Should refine based on estimated number of accesses (e.g. does it 46 // require splitting based on alignment) 47 static bool shouldExpandOperationWithSize(Value *Size) { 48 ConstantInt *CI = dyn_cast<ConstantInt>(Size); 49 return !CI || (CI->getZExtValue() > MaxStaticSize); 50 } 51 52 static bool expandMemIntrinsicUses(Function &F) { 53 Intrinsic::ID ID = F.getIntrinsicID(); 54 bool Changed = false; 55 56 for (auto I = F.user_begin(), E = F.user_end(); I != E;) { 57 Instruction *Inst = cast<Instruction>(*I); 58 ++I; 59 60 switch (ID) { 61 case Intrinsic::memcpy: { 62 auto *Memcpy = cast<MemCpyInst>(Inst); 63 if (shouldExpandOperationWithSize(Memcpy->getLength())) { 64 expandMemCpyAsLoop(Memcpy); 65 Changed = true; 66 Memcpy->eraseFromParent(); 67 } 68 69 break; 70 } 71 case Intrinsic::memmove: { 72 auto *Memmove = cast<MemMoveInst>(Inst); 73 if (shouldExpandOperationWithSize(Memmove->getLength())) { 74 expandMemMoveAsLoop(Memmove); 75 Changed = true; 76 Memmove->eraseFromParent(); 77 } 78 79 break; 80 } 81 case Intrinsic::memset: { 82 auto *Memset = cast<MemSetInst>(Inst); 83 if (shouldExpandOperationWithSize(Memset->getLength())) { 84 expandMemSetAsLoop(Memset); 85 Changed = true; 86 Memset->eraseFromParent(); 87 } 88 89 break; 90 } 91 default: 92 break; 93 } 94 } 95 96 return Changed; 97 } 98 99 bool AMDGPULowerIntrinsics::runOnModule(Module &M) { 100 bool Changed = false; 101 102 for (Function &F : M) { 103 if (!F.isDeclaration()) 104 continue; 105 106 switch (F.getIntrinsicID()) { 107 case Intrinsic::memcpy: 108 case Intrinsic::memmove: 109 case Intrinsic::memset: 110 if (expandMemIntrinsicUses(F)) 111 Changed = true; 112 break; 113 default: 114 break; 115 } 116 } 117 118 return Changed; 119 } 120 121 ModulePass *llvm::createAMDGPULowerIntrinsicsPass() { 122 return new AMDGPULowerIntrinsics(); 123 } 124