13931948bSMatt Arsenault //===-- AMDGPUAnnotateKernelFeaturesPass.cpp ------------------------------===//
23931948bSMatt Arsenault //
33931948bSMatt Arsenault //                     The LLVM Compiler Infrastructure
43931948bSMatt Arsenault //
53931948bSMatt Arsenault // This file is distributed under the University of Illinois Open Source
63931948bSMatt Arsenault // License. See LICENSE.TXT for details.
73931948bSMatt Arsenault //
83931948bSMatt Arsenault //===----------------------------------------------------------------------===//
93931948bSMatt Arsenault //
103931948bSMatt Arsenault /// \file This pass adds target attributes to functions which use intrinsics
113931948bSMatt Arsenault /// which will impact calling convention lowering.
123931948bSMatt Arsenault //
133931948bSMatt Arsenault //===----------------------------------------------------------------------===//
143931948bSMatt Arsenault 
153931948bSMatt Arsenault #include "AMDGPU.h"
163931948bSMatt Arsenault #include "llvm/IR/Instructions.h"
173931948bSMatt Arsenault #include "llvm/IR/Module.h"
183931948bSMatt Arsenault 
193931948bSMatt Arsenault #define DEBUG_TYPE "amdgpu-annotate-kernel-features"
203931948bSMatt Arsenault 
213931948bSMatt Arsenault using namespace llvm;
223931948bSMatt Arsenault 
233931948bSMatt Arsenault namespace {
243931948bSMatt Arsenault 
253931948bSMatt Arsenault class AMDGPUAnnotateKernelFeatures : public ModulePass {
263931948bSMatt Arsenault private:
273931948bSMatt Arsenault   void addAttrToCallers(Function *Intrin, StringRef AttrName);
283931948bSMatt Arsenault   bool addAttrsForIntrinsics(Module &M, ArrayRef<StringRef[2]>);
293931948bSMatt Arsenault 
303931948bSMatt Arsenault public:
313931948bSMatt Arsenault   static char ID;
323931948bSMatt Arsenault 
333931948bSMatt Arsenault   AMDGPUAnnotateKernelFeatures() : ModulePass(ID) { }
343931948bSMatt Arsenault   bool runOnModule(Module &M) override;
353931948bSMatt Arsenault   const char *getPassName() const override {
363931948bSMatt Arsenault     return "AMDGPU Annotate Kernel Features";
373931948bSMatt Arsenault   }
383931948bSMatt Arsenault 
393931948bSMatt Arsenault   void getAnalysisUsage(AnalysisUsage &AU) const override {
403931948bSMatt Arsenault     AU.setPreservesAll();
413931948bSMatt Arsenault     ModulePass::getAnalysisUsage(AU);
423931948bSMatt Arsenault   }
433931948bSMatt Arsenault };
443931948bSMatt Arsenault 
453931948bSMatt Arsenault }
463931948bSMatt Arsenault 
473931948bSMatt Arsenault char AMDGPUAnnotateKernelFeatures::ID = 0;
483931948bSMatt Arsenault 
493931948bSMatt Arsenault char &llvm::AMDGPUAnnotateKernelFeaturesID = AMDGPUAnnotateKernelFeatures::ID;
503931948bSMatt Arsenault 
513931948bSMatt Arsenault 
523931948bSMatt Arsenault INITIALIZE_PASS_BEGIN(AMDGPUAnnotateKernelFeatures, DEBUG_TYPE,
533931948bSMatt Arsenault                       "Add AMDGPU function attributes", false, false)
543931948bSMatt Arsenault INITIALIZE_PASS_END(AMDGPUAnnotateKernelFeatures, DEBUG_TYPE,
553931948bSMatt Arsenault                     "Add AMDGPU function attributes", false, false)
563931948bSMatt Arsenault 
573931948bSMatt Arsenault 
583931948bSMatt Arsenault void AMDGPUAnnotateKernelFeatures::addAttrToCallers(Function *Intrin,
593931948bSMatt Arsenault                                                     StringRef AttrName) {
603931948bSMatt Arsenault   SmallPtrSet<Function *, 4> SeenFuncs;
613931948bSMatt Arsenault 
623931948bSMatt Arsenault   for (User *U : Intrin->users()) {
633931948bSMatt Arsenault     // CallInst is the only valid user for an intrinsic.
643931948bSMatt Arsenault     CallInst *CI = cast<CallInst>(U);
653931948bSMatt Arsenault 
663931948bSMatt Arsenault     Function *CallingFunction = CI->getParent()->getParent();
673931948bSMatt Arsenault     if (SeenFuncs.insert(CallingFunction).second)
683931948bSMatt Arsenault       CallingFunction->addFnAttr(AttrName);
693931948bSMatt Arsenault   }
703931948bSMatt Arsenault }
713931948bSMatt Arsenault 
723931948bSMatt Arsenault bool AMDGPUAnnotateKernelFeatures::addAttrsForIntrinsics(
733931948bSMatt Arsenault   Module &M,
743931948bSMatt Arsenault   ArrayRef<StringRef[2]> IntrinsicToAttr) {
753931948bSMatt Arsenault   bool Changed = false;
763931948bSMatt Arsenault 
773931948bSMatt Arsenault   for (const StringRef *Arr  : IntrinsicToAttr) {
783931948bSMatt Arsenault     if (Function *Fn = M.getFunction(Arr[0])) {
793931948bSMatt Arsenault       addAttrToCallers(Fn, Arr[1]);
803931948bSMatt Arsenault       Changed = true;
813931948bSMatt Arsenault     }
823931948bSMatt Arsenault   }
833931948bSMatt Arsenault 
843931948bSMatt Arsenault   return Changed;
853931948bSMatt Arsenault }
863931948bSMatt Arsenault 
873931948bSMatt Arsenault bool AMDGPUAnnotateKernelFeatures::runOnModule(Module &M) {
883931948bSMatt Arsenault   Triple TT(M.getTargetTriple());
893931948bSMatt Arsenault 
903931948bSMatt Arsenault   static const StringRef IntrinsicToAttr[][2] = {
913931948bSMatt Arsenault     // .x omitted
9243976df0SMatt Arsenault     { "llvm.amdgcn.workitem.id.y", "amdgpu-work-item-id-y" },
9343976df0SMatt Arsenault     { "llvm.amdgcn.workitem.id.z", "amdgpu-work-item-id-z" },
9443976df0SMatt Arsenault 
9543976df0SMatt Arsenault     { "llvm.amdgcn.workgroup.id.y", "amdgpu-work-group-id-y" },
9643976df0SMatt Arsenault     { "llvm.amdgcn.workgroup.id.z", "amdgpu-work-group-id-z" },
9743976df0SMatt Arsenault 
983931948bSMatt Arsenault     { "llvm.r600.read.tgid.y", "amdgpu-work-group-id-y" },
993931948bSMatt Arsenault     { "llvm.r600.read.tgid.z", "amdgpu-work-group-id-z" },
1003931948bSMatt Arsenault 
1013931948bSMatt Arsenault     // .x omitted
1023931948bSMatt Arsenault     { "llvm.r600.read.tidig.y", "amdgpu-work-item-id-y" },
1033931948bSMatt Arsenault     { "llvm.r600.read.tidig.z", "amdgpu-work-item-id-z" }
1043931948bSMatt Arsenault   };
1053931948bSMatt Arsenault 
1063931948bSMatt Arsenault   static const StringRef HSAIntrinsicToAttr[][2] = {
10748f29f21STom Stellard     { "llvm.amdgcn.dispatch.ptr", "amdgpu-dispatch-ptr" }
1083931948bSMatt Arsenault   };
1093931948bSMatt Arsenault 
110*d0799df7SMatt Arsenault   // TODO: We should not add the attributes if the known compile time workgroup
111*d0799df7SMatt Arsenault   // size is 1 for y/z.
112*d0799df7SMatt Arsenault 
1133931948bSMatt Arsenault   // TODO: Intrinsics that require queue ptr.
1143931948bSMatt Arsenault 
1153931948bSMatt Arsenault   // We do not need to note the x workitem or workgroup id because they are
1163931948bSMatt Arsenault   // always initialized.
1173931948bSMatt Arsenault 
1183931948bSMatt Arsenault   bool Changed = addAttrsForIntrinsics(M, IntrinsicToAttr);
1193931948bSMatt Arsenault   if (TT.getOS() == Triple::AMDHSA)
1203931948bSMatt Arsenault     Changed |= addAttrsForIntrinsics(M, HSAIntrinsicToAttr);
1213931948bSMatt Arsenault 
1223931948bSMatt Arsenault   return Changed;
1233931948bSMatt Arsenault }
1243931948bSMatt Arsenault 
1253931948bSMatt Arsenault ModulePass *llvm::createAMDGPUAnnotateKernelFeaturesPass() {
1263931948bSMatt Arsenault   return new AMDGPUAnnotateKernelFeatures();
1273931948bSMatt Arsenault }
128