1//===- AMDGPUAnnotateKernelFeaturesPass.cpp -------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9/// \file This pass propagates the uniform-work-group-size attribute from
10/// kernels to leaf functions when possible. It also adds additional attributes
11/// to hint ABI lowering optimizations later.
12//
13//===----------------------------------------------------------------------===//
14
15#include "AMDGPU.h"
16#include "GCNSubtarget.h"
17#include "llvm/Analysis/CallGraph.h"
18#include "llvm/Analysis/CallGraphSCCPass.h"
19#include "llvm/CodeGen/TargetPassConfig.h"
20#include "llvm/IR/IntrinsicsAMDGPU.h"
21#include "llvm/IR/IntrinsicsR600.h"
22#include "llvm/Target/TargetMachine.h"
23
24#define DEBUG_TYPE "amdgpu-annotate-kernel-features"
25
26using namespace llvm;
27
28namespace {
29class AMDGPUAnnotateKernelFeatures : public CallGraphSCCPass {
30private:
31 const TargetMachine *TM = nullptr;
32
33 bool addFeatureAttributes(Function &F);
34
35public:
36 static char ID;
37
38 AMDGPUAnnotateKernelFeatures() : CallGraphSCCPass(ID) {}
39
40 bool doInitialization(CallGraph &CG) override;
41 bool runOnSCC(CallGraphSCC &SCC) override;
42
43 StringRef getPassName() const override {
44 return "AMDGPU Annotate Kernel Features";
45 }
46
47 void getAnalysisUsage(AnalysisUsage &AU) const override {
48 AU.setPreservesAll();
49 CallGraphSCCPass::getAnalysisUsage(Info&: AU);
50 }
51};
52
53} // end anonymous namespace
54
55char AMDGPUAnnotateKernelFeatures::ID = 0;
56
57char &llvm::AMDGPUAnnotateKernelFeaturesID = AMDGPUAnnotateKernelFeatures::ID;
58
59INITIALIZE_PASS(AMDGPUAnnotateKernelFeatures, DEBUG_TYPE,
60 "Add AMDGPU function attributes", false, false)
61
62bool AMDGPUAnnotateKernelFeatures::addFeatureAttributes(Function &F) {
63 bool HaveStackObjects = false;
64 bool Changed = false;
65 bool HaveCall = false;
66 bool IsFunc = !AMDGPU::isEntryFunctionCC(CC: F.getCallingConv());
67
68 for (BasicBlock &BB : F) {
69 for (Instruction &I : BB) {
70 if (isa<AllocaInst>(Val: I)) {
71 HaveStackObjects = true;
72 continue;
73 }
74
75 if (auto *CB = dyn_cast<CallBase>(Val: &I)) {
76 const Function *Callee =
77 dyn_cast<Function>(Val: CB->getCalledOperand()->stripPointerCasts());
78
79 // Note the occurrence of indirect call.
80 if (!Callee) {
81 if (!CB->isInlineAsm())
82 HaveCall = true;
83
84 continue;
85 }
86
87 Intrinsic::ID IID = Callee->getIntrinsicID();
88 if (IID == Intrinsic::not_intrinsic) {
89 HaveCall = true;
90 Changed = true;
91 }
92 }
93 }
94 }
95
96 // TODO: We could refine this to captured pointers that could possibly be
97 // accessed by flat instructions. For now this is mostly a poor way of
98 // estimating whether there are calls before argument lowering.
99 if (!IsFunc && HaveCall) {
100 F.addFnAttr(Kind: "amdgpu-calls");
101 Changed = true;
102 }
103
104 if (HaveStackObjects) {
105 F.addFnAttr(Kind: "amdgpu-stack-objects");
106 Changed = true;
107 }
108
109 return Changed;
110}
111
112bool AMDGPUAnnotateKernelFeatures::runOnSCC(CallGraphSCC &SCC) {
113 bool Changed = false;
114
115 for (CallGraphNode *I : SCC) {
116 Function *F = I->getFunction();
117 // Ignore functions with graphics calling conventions, these are currently
118 // not allowed to have kernel arguments.
119 if (!F || F->isDeclaration() || AMDGPU::isGraphics(CC: F->getCallingConv()))
120 continue;
121 // Add feature attributes
122 Changed |= addFeatureAttributes(F&: *F);
123 }
124
125 return Changed;
126}
127
128bool AMDGPUAnnotateKernelFeatures::doInitialization(CallGraph &CG) {
129 auto *TPC = getAnalysisIfAvailable<TargetPassConfig>();
130 if (!TPC)
131 report_fatal_error(reason: "TargetMachine is required");
132
133 TM = &TPC->getTM<TargetMachine>();
134 return false;
135}
136
137Pass *llvm::createAMDGPUAnnotateKernelFeaturesPass() {
138 return new AMDGPUAnnotateKernelFeatures();
139}
140