1 //===-- AMDGPUAnnotateKernelFeaturesPass.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 /// \file This pass adds target attributes to functions which use intrinsics 11 /// which will impact calling convention lowering. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #include "AMDGPU.h" 16 #include "llvm/IR/Instructions.h" 17 #include "llvm/IR/Module.h" 18 19 #define DEBUG_TYPE "amdgpu-annotate-kernel-features" 20 21 using namespace llvm; 22 23 namespace { 24 25 class AMDGPUAnnotateKernelFeatures : public ModulePass { 26 private: 27 void addAttrToCallers(Function *Intrin, StringRef AttrName); 28 bool addAttrsForIntrinsics(Module &M, ArrayRef<StringRef[2]>); 29 30 public: 31 static char ID; 32 33 AMDGPUAnnotateKernelFeatures() : ModulePass(ID) { } 34 bool runOnModule(Module &M) override; 35 const char *getPassName() const override { 36 return "AMDGPU Annotate Kernel Features"; 37 } 38 39 void getAnalysisUsage(AnalysisUsage &AU) const override { 40 AU.setPreservesAll(); 41 ModulePass::getAnalysisUsage(AU); 42 } 43 }; 44 45 } 46 47 char AMDGPUAnnotateKernelFeatures::ID = 0; 48 49 char &llvm::AMDGPUAnnotateKernelFeaturesID = AMDGPUAnnotateKernelFeatures::ID; 50 51 52 INITIALIZE_PASS_BEGIN(AMDGPUAnnotateKernelFeatures, DEBUG_TYPE, 53 "Add AMDGPU function attributes", false, false) 54 INITIALIZE_PASS_END(AMDGPUAnnotateKernelFeatures, DEBUG_TYPE, 55 "Add AMDGPU function attributes", false, false) 56 57 58 void AMDGPUAnnotateKernelFeatures::addAttrToCallers(Function *Intrin, 59 StringRef AttrName) { 60 SmallPtrSet<Function *, 4> SeenFuncs; 61 62 for (User *U : Intrin->users()) { 63 // CallInst is the only valid user for an intrinsic. 64 CallInst *CI = cast<CallInst>(U); 65 66 Function *CallingFunction = CI->getParent()->getParent(); 67 if (SeenFuncs.insert(CallingFunction).second) 68 CallingFunction->addFnAttr(AttrName); 69 } 70 } 71 72 bool AMDGPUAnnotateKernelFeatures::addAttrsForIntrinsics( 73 Module &M, 74 ArrayRef<StringRef[2]> IntrinsicToAttr) { 75 bool Changed = false; 76 77 for (const StringRef *Arr : IntrinsicToAttr) { 78 if (Function *Fn = M.getFunction(Arr[0])) { 79 addAttrToCallers(Fn, Arr[1]); 80 Changed = true; 81 } 82 } 83 84 return Changed; 85 } 86 87 bool AMDGPUAnnotateKernelFeatures::runOnModule(Module &M) { 88 Triple TT(M.getTargetTriple()); 89 90 static const StringRef IntrinsicToAttr[][2] = { 91 // .x omitted 92 { "llvm.amdgcn.workitem.id.y", "amdgpu-work-item-id-y" }, 93 { "llvm.amdgcn.workitem.id.z", "amdgpu-work-item-id-z" }, 94 95 { "llvm.amdgcn.workgroup.id.y", "amdgpu-work-group-id-y" }, 96 { "llvm.amdgcn.workgroup.id.z", "amdgpu-work-group-id-z" }, 97 98 { "llvm.r600.read.tgid.y", "amdgpu-work-group-id-y" }, 99 { "llvm.r600.read.tgid.z", "amdgpu-work-group-id-z" }, 100 101 // .x omitted 102 { "llvm.r600.read.tidig.y", "amdgpu-work-item-id-y" }, 103 { "llvm.r600.read.tidig.z", "amdgpu-work-item-id-z" } 104 }; 105 106 static const StringRef HSAIntrinsicToAttr[][2] = { 107 { "llvm.amdgcn.dispatch.ptr", "amdgpu-dispatch-ptr" } 108 }; 109 110 // TODO: We should not add the attributes if the known compile time workgroup 111 // size is 1 for y/z. 112 113 // TODO: Intrinsics that require queue ptr. 114 115 // We do not need to note the x workitem or workgroup id because they are 116 // always initialized. 117 118 bool Changed = addAttrsForIntrinsics(M, IntrinsicToAttr); 119 if (TT.getOS() == Triple::AMDHSA) 120 Changed |= addAttrsForIntrinsics(M, HSAIntrinsicToAttr); 121 122 return Changed; 123 } 124 125 ModulePass *llvm::createAMDGPUAnnotateKernelFeaturesPass() { 126 return new AMDGPUAnnotateKernelFeatures(); 127 } 128