xref: /aosp_15_r20/external/llvm/lib/Target/AMDGPU/AMDGPUAnnotateKernelFeatures.cpp (revision 9880d6810fe72a1726cb53787c6711e909410d58)
1*9880d681SAndroid Build Coastguard Worker //===-- AMDGPUAnnotateKernelFeaturesPass.cpp ------------------------------===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker //                     The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker //
10*9880d681SAndroid Build Coastguard Worker /// \file This pass adds target attributes to functions which use intrinsics
11*9880d681SAndroid Build Coastguard Worker /// which will impact calling convention lowering.
12*9880d681SAndroid Build Coastguard Worker //
13*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
14*9880d681SAndroid Build Coastguard Worker 
15*9880d681SAndroid Build Coastguard Worker #include "AMDGPU.h"
16*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Constants.h"
17*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Instructions.h"
18*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Module.h"
19*9880d681SAndroid Build Coastguard Worker 
20*9880d681SAndroid Build Coastguard Worker #define DEBUG_TYPE "amdgpu-annotate-kernel-features"
21*9880d681SAndroid Build Coastguard Worker 
22*9880d681SAndroid Build Coastguard Worker using namespace llvm;
23*9880d681SAndroid Build Coastguard Worker 
24*9880d681SAndroid Build Coastguard Worker namespace {
25*9880d681SAndroid Build Coastguard Worker 
26*9880d681SAndroid Build Coastguard Worker class AMDGPUAnnotateKernelFeatures : public ModulePass {
27*9880d681SAndroid Build Coastguard Worker private:
28*9880d681SAndroid Build Coastguard Worker   static bool hasAddrSpaceCast(const Function &F);
29*9880d681SAndroid Build Coastguard Worker 
30*9880d681SAndroid Build Coastguard Worker   void addAttrToCallers(Function *Intrin, StringRef AttrName);
31*9880d681SAndroid Build Coastguard Worker   bool addAttrsForIntrinsics(Module &M, ArrayRef<StringRef[2]>);
32*9880d681SAndroid Build Coastguard Worker 
33*9880d681SAndroid Build Coastguard Worker public:
34*9880d681SAndroid Build Coastguard Worker   static char ID;
35*9880d681SAndroid Build Coastguard Worker 
AMDGPUAnnotateKernelFeatures()36*9880d681SAndroid Build Coastguard Worker   AMDGPUAnnotateKernelFeatures() : ModulePass(ID) { }
37*9880d681SAndroid Build Coastguard Worker   bool runOnModule(Module &M) override;
getPassName() const38*9880d681SAndroid Build Coastguard Worker   const char *getPassName() const override {
39*9880d681SAndroid Build Coastguard Worker     return "AMDGPU Annotate Kernel Features";
40*9880d681SAndroid Build Coastguard Worker   }
41*9880d681SAndroid Build Coastguard Worker 
getAnalysisUsage(AnalysisUsage & AU) const42*9880d681SAndroid Build Coastguard Worker   void getAnalysisUsage(AnalysisUsage &AU) const override {
43*9880d681SAndroid Build Coastguard Worker     AU.setPreservesAll();
44*9880d681SAndroid Build Coastguard Worker     ModulePass::getAnalysisUsage(AU);
45*9880d681SAndroid Build Coastguard Worker   }
46*9880d681SAndroid Build Coastguard Worker 
47*9880d681SAndroid Build Coastguard Worker   static bool visitConstantExpr(const ConstantExpr *CE);
48*9880d681SAndroid Build Coastguard Worker   static bool visitConstantExprsRecursively(
49*9880d681SAndroid Build Coastguard Worker     const Constant *EntryC,
50*9880d681SAndroid Build Coastguard Worker     SmallPtrSet<const Constant *, 8> &ConstantExprVisited);
51*9880d681SAndroid Build Coastguard Worker };
52*9880d681SAndroid Build Coastguard Worker 
53*9880d681SAndroid Build Coastguard Worker }
54*9880d681SAndroid Build Coastguard Worker 
55*9880d681SAndroid Build Coastguard Worker char AMDGPUAnnotateKernelFeatures::ID = 0;
56*9880d681SAndroid Build Coastguard Worker 
57*9880d681SAndroid Build Coastguard Worker char &llvm::AMDGPUAnnotateKernelFeaturesID = AMDGPUAnnotateKernelFeatures::ID;
58*9880d681SAndroid Build Coastguard Worker 
59*9880d681SAndroid Build Coastguard Worker INITIALIZE_PASS(AMDGPUAnnotateKernelFeatures, DEBUG_TYPE,
60*9880d681SAndroid Build Coastguard Worker                 "Add AMDGPU function attributes", false, false)
61*9880d681SAndroid Build Coastguard Worker 
62*9880d681SAndroid Build Coastguard Worker 
63*9880d681SAndroid Build Coastguard Worker // The queue ptr is only needed when casting to flat, not from it.
castRequiresQueuePtr(unsigned SrcAS)64*9880d681SAndroid Build Coastguard Worker static bool castRequiresQueuePtr(unsigned SrcAS) {
65*9880d681SAndroid Build Coastguard Worker   return SrcAS == AMDGPUAS::LOCAL_ADDRESS || SrcAS == AMDGPUAS::PRIVATE_ADDRESS;
66*9880d681SAndroid Build Coastguard Worker }
67*9880d681SAndroid Build Coastguard Worker 
castRequiresQueuePtr(const AddrSpaceCastInst * ASC)68*9880d681SAndroid Build Coastguard Worker static bool castRequiresQueuePtr(const AddrSpaceCastInst *ASC) {
69*9880d681SAndroid Build Coastguard Worker   return castRequiresQueuePtr(ASC->getSrcAddressSpace());
70*9880d681SAndroid Build Coastguard Worker }
71*9880d681SAndroid Build Coastguard Worker 
visitConstantExpr(const ConstantExpr * CE)72*9880d681SAndroid Build Coastguard Worker bool AMDGPUAnnotateKernelFeatures::visitConstantExpr(const ConstantExpr *CE) {
73*9880d681SAndroid Build Coastguard Worker   if (CE->getOpcode() == Instruction::AddrSpaceCast) {
74*9880d681SAndroid Build Coastguard Worker     unsigned SrcAS = CE->getOperand(0)->getType()->getPointerAddressSpace();
75*9880d681SAndroid Build Coastguard Worker     return castRequiresQueuePtr(SrcAS);
76*9880d681SAndroid Build Coastguard Worker   }
77*9880d681SAndroid Build Coastguard Worker 
78*9880d681SAndroid Build Coastguard Worker   return false;
79*9880d681SAndroid Build Coastguard Worker }
80*9880d681SAndroid Build Coastguard Worker 
visitConstantExprsRecursively(const Constant * EntryC,SmallPtrSet<const Constant *,8> & ConstantExprVisited)81*9880d681SAndroid Build Coastguard Worker bool AMDGPUAnnotateKernelFeatures::visitConstantExprsRecursively(
82*9880d681SAndroid Build Coastguard Worker   const Constant *EntryC,
83*9880d681SAndroid Build Coastguard Worker   SmallPtrSet<const Constant *, 8> &ConstantExprVisited) {
84*9880d681SAndroid Build Coastguard Worker 
85*9880d681SAndroid Build Coastguard Worker   if (!ConstantExprVisited.insert(EntryC).second)
86*9880d681SAndroid Build Coastguard Worker     return false;
87*9880d681SAndroid Build Coastguard Worker 
88*9880d681SAndroid Build Coastguard Worker   SmallVector<const Constant *, 16> Stack;
89*9880d681SAndroid Build Coastguard Worker   Stack.push_back(EntryC);
90*9880d681SAndroid Build Coastguard Worker 
91*9880d681SAndroid Build Coastguard Worker   while (!Stack.empty()) {
92*9880d681SAndroid Build Coastguard Worker     const Constant *C = Stack.pop_back_val();
93*9880d681SAndroid Build Coastguard Worker 
94*9880d681SAndroid Build Coastguard Worker     // Check this constant expression.
95*9880d681SAndroid Build Coastguard Worker     if (const auto *CE = dyn_cast<ConstantExpr>(C)) {
96*9880d681SAndroid Build Coastguard Worker       if (visitConstantExpr(CE))
97*9880d681SAndroid Build Coastguard Worker         return true;
98*9880d681SAndroid Build Coastguard Worker     }
99*9880d681SAndroid Build Coastguard Worker 
100*9880d681SAndroid Build Coastguard Worker     // Visit all sub-expressions.
101*9880d681SAndroid Build Coastguard Worker     for (const Use &U : C->operands()) {
102*9880d681SAndroid Build Coastguard Worker       const auto *OpC = dyn_cast<Constant>(U);
103*9880d681SAndroid Build Coastguard Worker       if (!OpC)
104*9880d681SAndroid Build Coastguard Worker         continue;
105*9880d681SAndroid Build Coastguard Worker 
106*9880d681SAndroid Build Coastguard Worker       if (!ConstantExprVisited.insert(OpC).second)
107*9880d681SAndroid Build Coastguard Worker         continue;
108*9880d681SAndroid Build Coastguard Worker 
109*9880d681SAndroid Build Coastguard Worker       Stack.push_back(OpC);
110*9880d681SAndroid Build Coastguard Worker     }
111*9880d681SAndroid Build Coastguard Worker   }
112*9880d681SAndroid Build Coastguard Worker 
113*9880d681SAndroid Build Coastguard Worker   return false;
114*9880d681SAndroid Build Coastguard Worker }
115*9880d681SAndroid Build Coastguard Worker 
116*9880d681SAndroid Build Coastguard Worker // Return true if an addrspacecast is used that requires the queue ptr.
hasAddrSpaceCast(const Function & F)117*9880d681SAndroid Build Coastguard Worker bool AMDGPUAnnotateKernelFeatures::hasAddrSpaceCast(const Function &F) {
118*9880d681SAndroid Build Coastguard Worker   SmallPtrSet<const Constant *, 8> ConstantExprVisited;
119*9880d681SAndroid Build Coastguard Worker 
120*9880d681SAndroid Build Coastguard Worker   for (const BasicBlock &BB : F) {
121*9880d681SAndroid Build Coastguard Worker     for (const Instruction &I : BB) {
122*9880d681SAndroid Build Coastguard Worker       if (const AddrSpaceCastInst *ASC = dyn_cast<AddrSpaceCastInst>(&I)) {
123*9880d681SAndroid Build Coastguard Worker         if (castRequiresQueuePtr(ASC))
124*9880d681SAndroid Build Coastguard Worker           return true;
125*9880d681SAndroid Build Coastguard Worker       }
126*9880d681SAndroid Build Coastguard Worker 
127*9880d681SAndroid Build Coastguard Worker       for (const Use &U : I.operands()) {
128*9880d681SAndroid Build Coastguard Worker         const auto *OpC = dyn_cast<Constant>(U);
129*9880d681SAndroid Build Coastguard Worker         if (!OpC)
130*9880d681SAndroid Build Coastguard Worker           continue;
131*9880d681SAndroid Build Coastguard Worker 
132*9880d681SAndroid Build Coastguard Worker         if (visitConstantExprsRecursively(OpC, ConstantExprVisited))
133*9880d681SAndroid Build Coastguard Worker           return true;
134*9880d681SAndroid Build Coastguard Worker       }
135*9880d681SAndroid Build Coastguard Worker     }
136*9880d681SAndroid Build Coastguard Worker   }
137*9880d681SAndroid Build Coastguard Worker 
138*9880d681SAndroid Build Coastguard Worker   return false;
139*9880d681SAndroid Build Coastguard Worker }
140*9880d681SAndroid Build Coastguard Worker 
addAttrToCallers(Function * Intrin,StringRef AttrName)141*9880d681SAndroid Build Coastguard Worker void AMDGPUAnnotateKernelFeatures::addAttrToCallers(Function *Intrin,
142*9880d681SAndroid Build Coastguard Worker                                                     StringRef AttrName) {
143*9880d681SAndroid Build Coastguard Worker   SmallPtrSet<Function *, 4> SeenFuncs;
144*9880d681SAndroid Build Coastguard Worker 
145*9880d681SAndroid Build Coastguard Worker   for (User *U : Intrin->users()) {
146*9880d681SAndroid Build Coastguard Worker     // CallInst is the only valid user for an intrinsic.
147*9880d681SAndroid Build Coastguard Worker     CallInst *CI = cast<CallInst>(U);
148*9880d681SAndroid Build Coastguard Worker 
149*9880d681SAndroid Build Coastguard Worker     Function *CallingFunction = CI->getParent()->getParent();
150*9880d681SAndroid Build Coastguard Worker     if (SeenFuncs.insert(CallingFunction).second)
151*9880d681SAndroid Build Coastguard Worker       CallingFunction->addFnAttr(AttrName);
152*9880d681SAndroid Build Coastguard Worker   }
153*9880d681SAndroid Build Coastguard Worker }
154*9880d681SAndroid Build Coastguard Worker 
addAttrsForIntrinsics(Module & M,ArrayRef<StringRef[2]> IntrinsicToAttr)155*9880d681SAndroid Build Coastguard Worker bool AMDGPUAnnotateKernelFeatures::addAttrsForIntrinsics(
156*9880d681SAndroid Build Coastguard Worker   Module &M,
157*9880d681SAndroid Build Coastguard Worker   ArrayRef<StringRef[2]> IntrinsicToAttr) {
158*9880d681SAndroid Build Coastguard Worker   bool Changed = false;
159*9880d681SAndroid Build Coastguard Worker 
160*9880d681SAndroid Build Coastguard Worker   for (const StringRef *Arr  : IntrinsicToAttr) {
161*9880d681SAndroid Build Coastguard Worker     if (Function *Fn = M.getFunction(Arr[0])) {
162*9880d681SAndroid Build Coastguard Worker       addAttrToCallers(Fn, Arr[1]);
163*9880d681SAndroid Build Coastguard Worker       Changed = true;
164*9880d681SAndroid Build Coastguard Worker     }
165*9880d681SAndroid Build Coastguard Worker   }
166*9880d681SAndroid Build Coastguard Worker 
167*9880d681SAndroid Build Coastguard Worker   return Changed;
168*9880d681SAndroid Build Coastguard Worker }
169*9880d681SAndroid Build Coastguard Worker 
runOnModule(Module & M)170*9880d681SAndroid Build Coastguard Worker bool AMDGPUAnnotateKernelFeatures::runOnModule(Module &M) {
171*9880d681SAndroid Build Coastguard Worker   Triple TT(M.getTargetTriple());
172*9880d681SAndroid Build Coastguard Worker 
173*9880d681SAndroid Build Coastguard Worker   static const StringRef IntrinsicToAttr[][2] = {
174*9880d681SAndroid Build Coastguard Worker     // .x omitted
175*9880d681SAndroid Build Coastguard Worker     { "llvm.amdgcn.workitem.id.y", "amdgpu-work-item-id-y" },
176*9880d681SAndroid Build Coastguard Worker     { "llvm.amdgcn.workitem.id.z", "amdgpu-work-item-id-z" },
177*9880d681SAndroid Build Coastguard Worker 
178*9880d681SAndroid Build Coastguard Worker     { "llvm.amdgcn.workgroup.id.y", "amdgpu-work-group-id-y" },
179*9880d681SAndroid Build Coastguard Worker     { "llvm.amdgcn.workgroup.id.z", "amdgpu-work-group-id-z" },
180*9880d681SAndroid Build Coastguard Worker 
181*9880d681SAndroid Build Coastguard Worker     { "llvm.r600.read.tgid.y", "amdgpu-work-group-id-y" },
182*9880d681SAndroid Build Coastguard Worker     { "llvm.r600.read.tgid.z", "amdgpu-work-group-id-z" },
183*9880d681SAndroid Build Coastguard Worker 
184*9880d681SAndroid Build Coastguard Worker     // .x omitted
185*9880d681SAndroid Build Coastguard Worker     { "llvm.r600.read.tidig.y", "amdgpu-work-item-id-y" },
186*9880d681SAndroid Build Coastguard Worker     { "llvm.r600.read.tidig.z", "amdgpu-work-item-id-z" }
187*9880d681SAndroid Build Coastguard Worker   };
188*9880d681SAndroid Build Coastguard Worker 
189*9880d681SAndroid Build Coastguard Worker   static const StringRef HSAIntrinsicToAttr[][2] = {
190*9880d681SAndroid Build Coastguard Worker     { "llvm.amdgcn.dispatch.ptr", "amdgpu-dispatch-ptr" },
191*9880d681SAndroid Build Coastguard Worker     { "llvm.amdgcn.queue.ptr", "amdgpu-queue-ptr" }
192*9880d681SAndroid Build Coastguard Worker   };
193*9880d681SAndroid Build Coastguard Worker 
194*9880d681SAndroid Build Coastguard Worker   // TODO: We should not add the attributes if the known compile time workgroup
195*9880d681SAndroid Build Coastguard Worker   // size is 1 for y/z.
196*9880d681SAndroid Build Coastguard Worker 
197*9880d681SAndroid Build Coastguard Worker   // TODO: Intrinsics that require queue ptr.
198*9880d681SAndroid Build Coastguard Worker 
199*9880d681SAndroid Build Coastguard Worker   // We do not need to note the x workitem or workgroup id because they are
200*9880d681SAndroid Build Coastguard Worker   // always initialized.
201*9880d681SAndroid Build Coastguard Worker 
202*9880d681SAndroid Build Coastguard Worker   bool Changed = addAttrsForIntrinsics(M, IntrinsicToAttr);
203*9880d681SAndroid Build Coastguard Worker   if (TT.getOS() == Triple::AMDHSA) {
204*9880d681SAndroid Build Coastguard Worker     Changed |= addAttrsForIntrinsics(M, HSAIntrinsicToAttr);
205*9880d681SAndroid Build Coastguard Worker 
206*9880d681SAndroid Build Coastguard Worker     for (Function &F : M) {
207*9880d681SAndroid Build Coastguard Worker       if (F.hasFnAttribute("amdgpu-queue-ptr"))
208*9880d681SAndroid Build Coastguard Worker         continue;
209*9880d681SAndroid Build Coastguard Worker 
210*9880d681SAndroid Build Coastguard Worker       if (hasAddrSpaceCast(F))
211*9880d681SAndroid Build Coastguard Worker         F.addFnAttr("amdgpu-queue-ptr");
212*9880d681SAndroid Build Coastguard Worker     }
213*9880d681SAndroid Build Coastguard Worker   }
214*9880d681SAndroid Build Coastguard Worker 
215*9880d681SAndroid Build Coastguard Worker   return Changed;
216*9880d681SAndroid Build Coastguard Worker }
217*9880d681SAndroid Build Coastguard Worker 
createAMDGPUAnnotateKernelFeaturesPass()218*9880d681SAndroid Build Coastguard Worker ModulePass *llvm::createAMDGPUAnnotateKernelFeaturesPass() {
219*9880d681SAndroid Build Coastguard Worker   return new AMDGPUAnnotateKernelFeatures();
220*9880d681SAndroid Build Coastguard Worker }
221