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