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" 16e823d92fSMatt Arsenault #include "AMDGPUSubtarget.h" 172ffe8fd2SMatt Arsenault #include "llvm/ADT/Triple.h" 183b2e2a59SMatt Arsenault #include "llvm/IR/Constants.h" 193931948bSMatt Arsenault #include "llvm/IR/Instructions.h" 203931948bSMatt Arsenault #include "llvm/IR/Module.h" 213931948bSMatt Arsenault 223931948bSMatt Arsenault #define DEBUG_TYPE "amdgpu-annotate-kernel-features" 233931948bSMatt Arsenault 243931948bSMatt Arsenault using namespace llvm; 253931948bSMatt Arsenault 263931948bSMatt Arsenault namespace { 273931948bSMatt Arsenault 283931948bSMatt Arsenault class AMDGPUAnnotateKernelFeatures : public ModulePass { 293931948bSMatt Arsenault private: 30e823d92fSMatt Arsenault const TargetMachine *TM; 31*1a14bfa0SYaxun Liu AMDGPUAS AS; 32*1a14bfa0SYaxun Liu static bool hasAddrSpaceCast(const Function &F, AMDGPUAS AS); 3399c14524SMatt Arsenault 343931948bSMatt Arsenault void addAttrToCallers(Function *Intrin, StringRef AttrName); 353931948bSMatt Arsenault bool addAttrsForIntrinsics(Module &M, ArrayRef<StringRef[2]>); 363931948bSMatt Arsenault 373931948bSMatt Arsenault public: 383931948bSMatt Arsenault static char ID; 393931948bSMatt Arsenault 40e823d92fSMatt Arsenault AMDGPUAnnotateKernelFeatures(const TargetMachine *TM_ = nullptr) : 41e823d92fSMatt Arsenault ModulePass(ID), TM(TM_) {} 423931948bSMatt Arsenault bool runOnModule(Module &M) override; 43117296c0SMehdi Amini StringRef getPassName() const override { 443931948bSMatt Arsenault return "AMDGPU Annotate Kernel Features"; 453931948bSMatt Arsenault } 463931948bSMatt Arsenault 473931948bSMatt Arsenault void getAnalysisUsage(AnalysisUsage &AU) const override { 483931948bSMatt Arsenault AU.setPreservesAll(); 493931948bSMatt Arsenault ModulePass::getAnalysisUsage(AU); 503931948bSMatt Arsenault } 513b2e2a59SMatt Arsenault 52*1a14bfa0SYaxun Liu static bool visitConstantExpr(const ConstantExpr *CE, AMDGPUAS AS); 533b2e2a59SMatt Arsenault static bool visitConstantExprsRecursively( 543b2e2a59SMatt Arsenault const Constant *EntryC, 55*1a14bfa0SYaxun Liu SmallPtrSet<const Constant *, 8> &ConstantExprVisited, 56*1a14bfa0SYaxun Liu AMDGPUAS AS); 573931948bSMatt Arsenault }; 583931948bSMatt Arsenault 593931948bSMatt Arsenault } 603931948bSMatt Arsenault 613931948bSMatt Arsenault char AMDGPUAnnotateKernelFeatures::ID = 0; 623931948bSMatt Arsenault 633931948bSMatt Arsenault char &llvm::AMDGPUAnnotateKernelFeaturesID = AMDGPUAnnotateKernelFeatures::ID; 643931948bSMatt Arsenault 6599c14524SMatt Arsenault INITIALIZE_PASS(AMDGPUAnnotateKernelFeatures, DEBUG_TYPE, 663931948bSMatt Arsenault "Add AMDGPU function attributes", false, false) 673931948bSMatt Arsenault 6899c14524SMatt Arsenault 6999c14524SMatt Arsenault // The queue ptr is only needed when casting to flat, not from it. 70*1a14bfa0SYaxun Liu static bool castRequiresQueuePtr(unsigned SrcAS, const AMDGPUAS &AS) { 71*1a14bfa0SYaxun Liu return SrcAS == AS.LOCAL_ADDRESS || SrcAS == AS.PRIVATE_ADDRESS; 7299c14524SMatt Arsenault } 7399c14524SMatt Arsenault 74*1a14bfa0SYaxun Liu static bool castRequiresQueuePtr(const AddrSpaceCastInst *ASC, 75*1a14bfa0SYaxun Liu const AMDGPUAS &AS) { 76*1a14bfa0SYaxun Liu return castRequiresQueuePtr(ASC->getSrcAddressSpace(), AS); 773b2e2a59SMatt Arsenault } 783b2e2a59SMatt Arsenault 79*1a14bfa0SYaxun Liu bool AMDGPUAnnotateKernelFeatures::visitConstantExpr(const ConstantExpr *CE, 80*1a14bfa0SYaxun Liu AMDGPUAS AS) { 813b2e2a59SMatt Arsenault if (CE->getOpcode() == Instruction::AddrSpaceCast) { 823b2e2a59SMatt Arsenault unsigned SrcAS = CE->getOperand(0)->getType()->getPointerAddressSpace(); 83*1a14bfa0SYaxun Liu return castRequiresQueuePtr(SrcAS, AS); 843b2e2a59SMatt Arsenault } 853b2e2a59SMatt Arsenault 863b2e2a59SMatt Arsenault return false; 873b2e2a59SMatt Arsenault } 883b2e2a59SMatt Arsenault 893b2e2a59SMatt Arsenault bool AMDGPUAnnotateKernelFeatures::visitConstantExprsRecursively( 903b2e2a59SMatt Arsenault const Constant *EntryC, 91*1a14bfa0SYaxun Liu SmallPtrSet<const Constant *, 8> &ConstantExprVisited, 92*1a14bfa0SYaxun Liu AMDGPUAS AS) { 933b2e2a59SMatt Arsenault 943b2e2a59SMatt Arsenault if (!ConstantExprVisited.insert(EntryC).second) 953b2e2a59SMatt Arsenault return false; 963b2e2a59SMatt Arsenault 973b2e2a59SMatt Arsenault SmallVector<const Constant *, 16> Stack; 983b2e2a59SMatt Arsenault Stack.push_back(EntryC); 993b2e2a59SMatt Arsenault 1003b2e2a59SMatt Arsenault while (!Stack.empty()) { 1013b2e2a59SMatt Arsenault const Constant *C = Stack.pop_back_val(); 1023b2e2a59SMatt Arsenault 1033b2e2a59SMatt Arsenault // Check this constant expression. 1043b2e2a59SMatt Arsenault if (const auto *CE = dyn_cast<ConstantExpr>(C)) { 105*1a14bfa0SYaxun Liu if (visitConstantExpr(CE, AS)) 1063b2e2a59SMatt Arsenault return true; 1073b2e2a59SMatt Arsenault } 1083b2e2a59SMatt Arsenault 1093b2e2a59SMatt Arsenault // Visit all sub-expressions. 1103b2e2a59SMatt Arsenault for (const Use &U : C->operands()) { 1113b2e2a59SMatt Arsenault const auto *OpC = dyn_cast<Constant>(U); 1123b2e2a59SMatt Arsenault if (!OpC) 1133b2e2a59SMatt Arsenault continue; 1143b2e2a59SMatt Arsenault 1153b2e2a59SMatt Arsenault if (!ConstantExprVisited.insert(OpC).second) 1163b2e2a59SMatt Arsenault continue; 1173b2e2a59SMatt Arsenault 1183b2e2a59SMatt Arsenault Stack.push_back(OpC); 1193b2e2a59SMatt Arsenault } 1203b2e2a59SMatt Arsenault } 1213b2e2a59SMatt Arsenault 1223b2e2a59SMatt Arsenault return false; 1233b2e2a59SMatt Arsenault } 1243b2e2a59SMatt Arsenault 12599c14524SMatt Arsenault // Return true if an addrspacecast is used that requires the queue ptr. 126*1a14bfa0SYaxun Liu bool AMDGPUAnnotateKernelFeatures::hasAddrSpaceCast(const Function &F, 127*1a14bfa0SYaxun Liu AMDGPUAS AS) { 1283b2e2a59SMatt Arsenault SmallPtrSet<const Constant *, 8> ConstantExprVisited; 1293b2e2a59SMatt Arsenault 13099c14524SMatt Arsenault for (const BasicBlock &BB : F) { 13199c14524SMatt Arsenault for (const Instruction &I : BB) { 13299c14524SMatt Arsenault if (const AddrSpaceCastInst *ASC = dyn_cast<AddrSpaceCastInst>(&I)) { 133*1a14bfa0SYaxun Liu if (castRequiresQueuePtr(ASC, AS)) 13499c14524SMatt Arsenault return true; 13599c14524SMatt Arsenault } 1363b2e2a59SMatt Arsenault 1373b2e2a59SMatt Arsenault for (const Use &U : I.operands()) { 1383b2e2a59SMatt Arsenault const auto *OpC = dyn_cast<Constant>(U); 1393b2e2a59SMatt Arsenault if (!OpC) 1403b2e2a59SMatt Arsenault continue; 1413b2e2a59SMatt Arsenault 142*1a14bfa0SYaxun Liu if (visitConstantExprsRecursively(OpC, ConstantExprVisited, AS)) 1433b2e2a59SMatt Arsenault return true; 1443b2e2a59SMatt Arsenault } 14599c14524SMatt Arsenault } 14699c14524SMatt Arsenault } 14799c14524SMatt Arsenault 14899c14524SMatt Arsenault return false; 14999c14524SMatt Arsenault } 1503931948bSMatt Arsenault 1513931948bSMatt Arsenault void AMDGPUAnnotateKernelFeatures::addAttrToCallers(Function *Intrin, 1523931948bSMatt Arsenault StringRef AttrName) { 1533931948bSMatt Arsenault SmallPtrSet<Function *, 4> SeenFuncs; 1543931948bSMatt Arsenault 1553931948bSMatt Arsenault for (User *U : Intrin->users()) { 1563931948bSMatt Arsenault // CallInst is the only valid user for an intrinsic. 1573931948bSMatt Arsenault CallInst *CI = cast<CallInst>(U); 1583931948bSMatt Arsenault 1593931948bSMatt Arsenault Function *CallingFunction = CI->getParent()->getParent(); 1603931948bSMatt Arsenault if (SeenFuncs.insert(CallingFunction).second) 1613931948bSMatt Arsenault CallingFunction->addFnAttr(AttrName); 1623931948bSMatt Arsenault } 1633931948bSMatt Arsenault } 1643931948bSMatt Arsenault 1653931948bSMatt Arsenault bool AMDGPUAnnotateKernelFeatures::addAttrsForIntrinsics( 1663931948bSMatt Arsenault Module &M, 1673931948bSMatt Arsenault ArrayRef<StringRef[2]> IntrinsicToAttr) { 1683931948bSMatt Arsenault bool Changed = false; 1693931948bSMatt Arsenault 1703931948bSMatt Arsenault for (const StringRef *Arr : IntrinsicToAttr) { 1713931948bSMatt Arsenault if (Function *Fn = M.getFunction(Arr[0])) { 1723931948bSMatt Arsenault addAttrToCallers(Fn, Arr[1]); 1733931948bSMatt Arsenault Changed = true; 1743931948bSMatt Arsenault } 1753931948bSMatt Arsenault } 1763931948bSMatt Arsenault 1773931948bSMatt Arsenault return Changed; 1783931948bSMatt Arsenault } 1793931948bSMatt Arsenault 1803931948bSMatt Arsenault bool AMDGPUAnnotateKernelFeatures::runOnModule(Module &M) { 1813931948bSMatt Arsenault Triple TT(M.getTargetTriple()); 182*1a14bfa0SYaxun Liu AS = AMDGPU::getAMDGPUAS(M); 1833931948bSMatt Arsenault 1843931948bSMatt Arsenault static const StringRef IntrinsicToAttr[][2] = { 1853931948bSMatt Arsenault // .x omitted 18643976df0SMatt Arsenault { "llvm.amdgcn.workitem.id.y", "amdgpu-work-item-id-y" }, 18743976df0SMatt Arsenault { "llvm.amdgcn.workitem.id.z", "amdgpu-work-item-id-z" }, 18843976df0SMatt Arsenault 18943976df0SMatt Arsenault { "llvm.amdgcn.workgroup.id.y", "amdgpu-work-group-id-y" }, 19043976df0SMatt Arsenault { "llvm.amdgcn.workgroup.id.z", "amdgpu-work-group-id-z" }, 19143976df0SMatt Arsenault 1923931948bSMatt Arsenault { "llvm.r600.read.tgid.y", "amdgpu-work-group-id-y" }, 1933931948bSMatt Arsenault { "llvm.r600.read.tgid.z", "amdgpu-work-group-id-z" }, 1943931948bSMatt Arsenault 1953931948bSMatt Arsenault // .x omitted 1963931948bSMatt Arsenault { "llvm.r600.read.tidig.y", "amdgpu-work-item-id-y" }, 1973931948bSMatt Arsenault { "llvm.r600.read.tidig.z", "amdgpu-work-item-id-z" } 1983931948bSMatt Arsenault }; 1993931948bSMatt Arsenault 2003931948bSMatt Arsenault static const StringRef HSAIntrinsicToAttr[][2] = { 20148ab526fSMatt Arsenault { "llvm.amdgcn.dispatch.ptr", "amdgpu-dispatch-ptr" }, 2028d718dcfSMatt Arsenault { "llvm.amdgcn.queue.ptr", "amdgpu-queue-ptr" }, 203ee21a36fSWei Ding { "llvm.amdgcn.dispatch.id", "amdgpu-dispatch-id" }, 204205bfdb3SWei Ding { "llvm.trap", "amdgpu-queue-ptr" }, 205205bfdb3SWei Ding { "llvm.debugtrap", "amdgpu-queue-ptr" } 2063931948bSMatt Arsenault }; 2073931948bSMatt Arsenault 208d0799df7SMatt Arsenault // TODO: We should not add the attributes if the known compile time workgroup 209d0799df7SMatt Arsenault // size is 1 for y/z. 210d0799df7SMatt Arsenault 2113931948bSMatt Arsenault // TODO: Intrinsics that require queue ptr. 2123931948bSMatt Arsenault 2133931948bSMatt Arsenault // We do not need to note the x workitem or workgroup id because they are 2143931948bSMatt Arsenault // always initialized. 2153931948bSMatt Arsenault 2163931948bSMatt Arsenault bool Changed = addAttrsForIntrinsics(M, IntrinsicToAttr); 2170b76fc4cSTom Stellard if (TT.getOS() == Triple::AMDHSA || TT.getOS() == Triple::Mesa3D) { 2183931948bSMatt Arsenault Changed |= addAttrsForIntrinsics(M, HSAIntrinsicToAttr); 2193931948bSMatt Arsenault 22099c14524SMatt Arsenault for (Function &F : M) { 22199c14524SMatt Arsenault if (F.hasFnAttribute("amdgpu-queue-ptr")) 22299c14524SMatt Arsenault continue; 22399c14524SMatt Arsenault 224e823d92fSMatt Arsenault bool HasApertureRegs = 225e823d92fSMatt Arsenault TM && TM->getSubtarget<AMDGPUSubtarget>(F).hasApertureRegs(); 226*1a14bfa0SYaxun Liu if (!HasApertureRegs && hasAddrSpaceCast(F, AS)) 22799c14524SMatt Arsenault F.addFnAttr("amdgpu-queue-ptr"); 22899c14524SMatt Arsenault } 22999c14524SMatt Arsenault } 23099c14524SMatt Arsenault 2313931948bSMatt Arsenault return Changed; 2323931948bSMatt Arsenault } 2333931948bSMatt Arsenault 234e823d92fSMatt Arsenault ModulePass *llvm::createAMDGPUAnnotateKernelFeaturesPass(const TargetMachine *TM) { 235e823d92fSMatt Arsenault return new AMDGPUAnnotateKernelFeatures(TM); 2363931948bSMatt Arsenault } 237