blob: 09d3ff716e6e5493e13194789f45f22b7f6b1257 [file] [log] [blame]
Matt Arsenault39319482015-11-06 18:01:57 +00001//===-- 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"
Matt Arsenaulte823d922017-02-18 18:29:53 +000016#include "AMDGPUSubtarget.h"
Matt Arsenault2ffe8fd2016-08-11 19:18:50 +000017#include "llvm/ADT/Triple.h"
Matt Arsenault3b2e2a52016-06-06 20:03:31 +000018#include "llvm/IR/Constants.h"
Matt Arsenault39319482015-11-06 18:01:57 +000019#include "llvm/IR/Instructions.h"
20#include "llvm/IR/Module.h"
21
22#define DEBUG_TYPE "amdgpu-annotate-kernel-features"
23
24using namespace llvm;
25
26namespace {
27
28class AMDGPUAnnotateKernelFeatures : public ModulePass {
29private:
Matt Arsenaulte823d922017-02-18 18:29:53 +000030 const TargetMachine *TM;
Matt Arsenault99c14522016-04-25 19:27:24 +000031 static bool hasAddrSpaceCast(const Function &F);
32
Matt Arsenault39319482015-11-06 18:01:57 +000033 void addAttrToCallers(Function *Intrin, StringRef AttrName);
34 bool addAttrsForIntrinsics(Module &M, ArrayRef<StringRef[2]>);
35
36public:
37 static char ID;
38
Matt Arsenaulte823d922017-02-18 18:29:53 +000039 AMDGPUAnnotateKernelFeatures(const TargetMachine *TM_ = nullptr) :
40 ModulePass(ID), TM(TM_) {}
Matt Arsenault39319482015-11-06 18:01:57 +000041 bool runOnModule(Module &M) override;
Mehdi Amini117296c2016-10-01 02:56:57 +000042 StringRef getPassName() const override {
Matt Arsenault39319482015-11-06 18:01:57 +000043 return "AMDGPU Annotate Kernel Features";
44 }
45
46 void getAnalysisUsage(AnalysisUsage &AU) const override {
47 AU.setPreservesAll();
48 ModulePass::getAnalysisUsage(AU);
49 }
Matt Arsenault3b2e2a52016-06-06 20:03:31 +000050
51 static bool visitConstantExpr(const ConstantExpr *CE);
52 static bool visitConstantExprsRecursively(
53 const Constant *EntryC,
54 SmallPtrSet<const Constant *, 8> &ConstantExprVisited);
Matt Arsenault39319482015-11-06 18:01:57 +000055};
56
57}
58
59char AMDGPUAnnotateKernelFeatures::ID = 0;
60
61char &llvm::AMDGPUAnnotateKernelFeaturesID = AMDGPUAnnotateKernelFeatures::ID;
62
Matt Arsenault99c14522016-04-25 19:27:24 +000063INITIALIZE_PASS(AMDGPUAnnotateKernelFeatures, DEBUG_TYPE,
64 "Add AMDGPU function attributes", false, false)
Matt Arsenault39319482015-11-06 18:01:57 +000065
Matt Arsenault39319482015-11-06 18:01:57 +000066
Matt Arsenault3b2e2a52016-06-06 20:03:31 +000067// The queue ptr is only needed when casting to flat, not from it.
68static bool castRequiresQueuePtr(unsigned SrcAS) {
Matt Arsenault99c14522016-04-25 19:27:24 +000069 return SrcAS == AMDGPUAS::LOCAL_ADDRESS || SrcAS == AMDGPUAS::PRIVATE_ADDRESS;
70}
71
Matt Arsenault3b2e2a52016-06-06 20:03:31 +000072static bool castRequiresQueuePtr(const AddrSpaceCastInst *ASC) {
73 return castRequiresQueuePtr(ASC->getSrcAddressSpace());
74}
75
76bool AMDGPUAnnotateKernelFeatures::visitConstantExpr(const ConstantExpr *CE) {
77 if (CE->getOpcode() == Instruction::AddrSpaceCast) {
78 unsigned SrcAS = CE->getOperand(0)->getType()->getPointerAddressSpace();
79 return castRequiresQueuePtr(SrcAS);
80 }
81
82 return false;
83}
84
85bool AMDGPUAnnotateKernelFeatures::visitConstantExprsRecursively(
86 const Constant *EntryC,
87 SmallPtrSet<const Constant *, 8> &ConstantExprVisited) {
88
89 if (!ConstantExprVisited.insert(EntryC).second)
90 return false;
91
92 SmallVector<const Constant *, 16> Stack;
93 Stack.push_back(EntryC);
94
95 while (!Stack.empty()) {
96 const Constant *C = Stack.pop_back_val();
97
98 // Check this constant expression.
99 if (const auto *CE = dyn_cast<ConstantExpr>(C)) {
100 if (visitConstantExpr(CE))
101 return true;
102 }
103
104 // Visit all sub-expressions.
105 for (const Use &U : C->operands()) {
106 const auto *OpC = dyn_cast<Constant>(U);
107 if (!OpC)
108 continue;
109
110 if (!ConstantExprVisited.insert(OpC).second)
111 continue;
112
113 Stack.push_back(OpC);
114 }
115 }
116
117 return false;
118}
119
Matt Arsenault99c14522016-04-25 19:27:24 +0000120// Return true if an addrspacecast is used that requires the queue ptr.
121bool AMDGPUAnnotateKernelFeatures::hasAddrSpaceCast(const Function &F) {
Matt Arsenault3b2e2a52016-06-06 20:03:31 +0000122 SmallPtrSet<const Constant *, 8> ConstantExprVisited;
123
Matt Arsenault99c14522016-04-25 19:27:24 +0000124 for (const BasicBlock &BB : F) {
125 for (const Instruction &I : BB) {
126 if (const AddrSpaceCastInst *ASC = dyn_cast<AddrSpaceCastInst>(&I)) {
127 if (castRequiresQueuePtr(ASC))
128 return true;
129 }
Matt Arsenault3b2e2a52016-06-06 20:03:31 +0000130
131 for (const Use &U : I.operands()) {
132 const auto *OpC = dyn_cast<Constant>(U);
133 if (!OpC)
134 continue;
135
136 if (visitConstantExprsRecursively(OpC, ConstantExprVisited))
137 return true;
138 }
Matt Arsenault99c14522016-04-25 19:27:24 +0000139 }
140 }
141
142 return false;
143}
Matt Arsenault39319482015-11-06 18:01:57 +0000144
145void AMDGPUAnnotateKernelFeatures::addAttrToCallers(Function *Intrin,
146 StringRef AttrName) {
147 SmallPtrSet<Function *, 4> SeenFuncs;
148
149 for (User *U : Intrin->users()) {
150 // CallInst is the only valid user for an intrinsic.
151 CallInst *CI = cast<CallInst>(U);
152
153 Function *CallingFunction = CI->getParent()->getParent();
154 if (SeenFuncs.insert(CallingFunction).second)
155 CallingFunction->addFnAttr(AttrName);
156 }
157}
158
159bool AMDGPUAnnotateKernelFeatures::addAttrsForIntrinsics(
160 Module &M,
161 ArrayRef<StringRef[2]> IntrinsicToAttr) {
162 bool Changed = false;
163
164 for (const StringRef *Arr : IntrinsicToAttr) {
165 if (Function *Fn = M.getFunction(Arr[0])) {
166 addAttrToCallers(Fn, Arr[1]);
167 Changed = true;
168 }
169 }
170
171 return Changed;
172}
173
174bool AMDGPUAnnotateKernelFeatures::runOnModule(Module &M) {
175 Triple TT(M.getTargetTriple());
176
177 static const StringRef IntrinsicToAttr[][2] = {
178 // .x omitted
Matt Arsenault43976df2016-01-30 04:25:19 +0000179 { "llvm.amdgcn.workitem.id.y", "amdgpu-work-item-id-y" },
180 { "llvm.amdgcn.workitem.id.z", "amdgpu-work-item-id-z" },
181
182 { "llvm.amdgcn.workgroup.id.y", "amdgpu-work-group-id-y" },
183 { "llvm.amdgcn.workgroup.id.z", "amdgpu-work-group-id-z" },
184
Matt Arsenault39319482015-11-06 18:01:57 +0000185 { "llvm.r600.read.tgid.y", "amdgpu-work-group-id-y" },
186 { "llvm.r600.read.tgid.z", "amdgpu-work-group-id-z" },
187
188 // .x omitted
189 { "llvm.r600.read.tidig.y", "amdgpu-work-item-id-y" },
190 { "llvm.r600.read.tidig.z", "amdgpu-work-item-id-z" }
Matt Arsenault39319482015-11-06 18:01:57 +0000191 };
192
193 static const StringRef HSAIntrinsicToAttr[][2] = {
Matt Arsenault48ab5262016-04-25 19:27:18 +0000194 { "llvm.amdgcn.dispatch.ptr", "amdgpu-dispatch-ptr" },
Matt Arsenault8d718dc2016-07-22 17:01:30 +0000195 { "llvm.amdgcn.queue.ptr", "amdgpu-queue-ptr" },
Wei Dingee21a362017-01-24 06:41:21 +0000196 { "llvm.amdgcn.dispatch.id", "amdgpu-dispatch-id" },
Wei Ding205bfdb2017-02-10 02:15:29 +0000197 { "llvm.trap", "amdgpu-queue-ptr" },
198 { "llvm.debugtrap", "amdgpu-queue-ptr" }
Matt Arsenault39319482015-11-06 18:01:57 +0000199 };
200
Matt Arsenaultd0799df2016-01-30 05:10:59 +0000201 // TODO: We should not add the attributes if the known compile time workgroup
202 // size is 1 for y/z.
203
Matt Arsenault39319482015-11-06 18:01:57 +0000204 // TODO: Intrinsics that require queue ptr.
205
206 // We do not need to note the x workitem or workgroup id because they are
207 // always initialized.
208
209 bool Changed = addAttrsForIntrinsics(M, IntrinsicToAttr);
Tom Stellard0b76fc4c2016-09-16 21:34:26 +0000210 if (TT.getOS() == Triple::AMDHSA || TT.getOS() == Triple::Mesa3D) {
Matt Arsenault39319482015-11-06 18:01:57 +0000211 Changed |= addAttrsForIntrinsics(M, HSAIntrinsicToAttr);
212
Matt Arsenault99c14522016-04-25 19:27:24 +0000213 for (Function &F : M) {
214 if (F.hasFnAttribute("amdgpu-queue-ptr"))
215 continue;
216
Matt Arsenaulte823d922017-02-18 18:29:53 +0000217 bool HasApertureRegs =
218 TM && TM->getSubtarget<AMDGPUSubtarget>(F).hasApertureRegs();
219 if (!HasApertureRegs && hasAddrSpaceCast(F))
Matt Arsenault99c14522016-04-25 19:27:24 +0000220 F.addFnAttr("amdgpu-queue-ptr");
221 }
222 }
223
Matt Arsenault39319482015-11-06 18:01:57 +0000224 return Changed;
225}
226
Matt Arsenaulte823d922017-02-18 18:29:53 +0000227ModulePass *llvm::createAMDGPUAnnotateKernelFeaturesPass(const TargetMachine *TM) {
228 return new AMDGPUAnnotateKernelFeatures(TM);
Matt Arsenault39319482015-11-06 18:01:57 +0000229}