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 "AMDGPUSubtarget.h" 12 #include "llvm/CodeGen/TargetPassConfig.h" 13 #include "llvm/IR/Constants.h" 14 #include "llvm/IR/Instructions.h" 15 #include "llvm/IR/IntrinsicInst.h" 16 #include "llvm/IR/Module.h" 17 #include "llvm/Transforms/Utils/LowerMemIntrinsics.h" 18 19 #define DEBUG_TYPE "amdgpu-lower-intrinsics" 20 21 using namespace llvm; 22 23 namespace { 24 25 const unsigned MaxStaticSize = 1024; 26 27 class AMDGPULowerIntrinsics : public ModulePass { 28 private: 29 bool makeLIDRangeMetadata(Function &F) const; 30 31 public: 32 static char ID; 33 34 AMDGPULowerIntrinsics() : ModulePass(ID) {} 35 36 bool runOnModule(Module &M) override; 37 StringRef getPassName() const override { 38 return "AMDGPU Lower Intrinsics"; 39 } 40 }; 41 42 } 43 44 char AMDGPULowerIntrinsics::ID = 0; 45 46 char &llvm::AMDGPULowerIntrinsicsID = AMDGPULowerIntrinsics::ID; 47 48 INITIALIZE_PASS(AMDGPULowerIntrinsics, DEBUG_TYPE, "Lower intrinsics", false, 49 false) 50 51 // TODO: Should refine based on estimated number of accesses (e.g. does it 52 // require splitting based on alignment) 53 static bool shouldExpandOperationWithSize(Value *Size) { 54 ConstantInt *CI = dyn_cast<ConstantInt>(Size); 55 return !CI || (CI->getZExtValue() > MaxStaticSize); 56 } 57 58 static bool expandMemIntrinsicUses(Function &F) { 59 Intrinsic::ID ID = F.getIntrinsicID(); 60 bool Changed = false; 61 62 for (auto I = F.user_begin(), E = F.user_end(); I != E;) { 63 Instruction *Inst = cast<Instruction>(*I); 64 ++I; 65 66 switch (ID) { 67 case Intrinsic::memcpy: { 68 auto *Memcpy = cast<MemCpyInst>(Inst); 69 if (shouldExpandOperationWithSize(Memcpy->getLength())) { 70 expandMemCpyAsLoop(Memcpy); 71 Changed = true; 72 Memcpy->eraseFromParent(); 73 } 74 75 break; 76 } 77 case Intrinsic::memmove: { 78 auto *Memmove = cast<MemMoveInst>(Inst); 79 if (shouldExpandOperationWithSize(Memmove->getLength())) { 80 expandMemMoveAsLoop(Memmove); 81 Changed = true; 82 Memmove->eraseFromParent(); 83 } 84 85 break; 86 } 87 case Intrinsic::memset: { 88 auto *Memset = cast<MemSetInst>(Inst); 89 if (shouldExpandOperationWithSize(Memset->getLength())) { 90 expandMemSetAsLoop(Memset); 91 Changed = true; 92 Memset->eraseFromParent(); 93 } 94 95 break; 96 } 97 default: 98 break; 99 } 100 } 101 102 return Changed; 103 } 104 105 bool AMDGPULowerIntrinsics::makeLIDRangeMetadata(Function &F) const { 106 auto *TPC = getAnalysisIfAvailable<TargetPassConfig>(); 107 if (!TPC) 108 return false; 109 110 const TargetMachine &TM = TPC->getTM<TargetMachine>(); 111 const AMDGPUSubtarget &ST = TM.getSubtarget<AMDGPUSubtarget>(F); 112 bool Changed = false; 113 114 for (auto *U : F.users()) { 115 auto *CI = dyn_cast<CallInst>(U); 116 if (!CI) 117 continue; 118 119 Changed |= ST.makeLIDRangeMetadata(CI); 120 } 121 return Changed; 122 } 123 124 bool AMDGPULowerIntrinsics::runOnModule(Module &M) { 125 bool Changed = false; 126 127 for (Function &F : M) { 128 if (!F.isDeclaration()) 129 continue; 130 131 switch (F.getIntrinsicID()) { 132 case Intrinsic::memcpy: 133 case Intrinsic::memmove: 134 case Intrinsic::memset: 135 if (expandMemIntrinsicUses(F)) 136 Changed = true; 137 break; 138 139 case Intrinsic::amdgcn_workitem_id_x: 140 case Intrinsic::r600_read_tidig_x: 141 case Intrinsic::amdgcn_workitem_id_y: 142 case Intrinsic::r600_read_tidig_y: 143 case Intrinsic::amdgcn_workitem_id_z: 144 case Intrinsic::r600_read_tidig_z: 145 case Intrinsic::r600_read_local_size_x: 146 case Intrinsic::r600_read_local_size_y: 147 case Intrinsic::r600_read_local_size_z: 148 Changed |= makeLIDRangeMetadata(F); 149 break; 150 151 default: 152 break; 153 } 154 } 155 156 return Changed; 157 } 158 159 ModulePass *llvm::createAMDGPULowerIntrinsicsPass() { 160 return new AMDGPULowerIntrinsics(); 161 } 162