1 //===- AMDGPUAnnotateKernelFeaturesPass.cpp -------------------------------===//
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
7 //===----------------------------------------------------------------------===//
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.
13 //===----------------------------------------------------------------------===//
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"
24 #define DEBUG_TYPE "amdgpu-annotate-kernel-features"
29 class AMDGPUAnnotateKernelFeatures
: public CallGraphSCCPass
{
31 const TargetMachine
*TM
= nullptr;
33 bool addFeatureAttributes(Function
&F
);
38 AMDGPUAnnotateKernelFeatures() : CallGraphSCCPass(ID
) {}
40 bool doInitialization(CallGraph
&CG
) override
;
41 bool runOnSCC(CallGraphSCC
&SCC
) override
;
43 StringRef
getPassName() const override
{
44 return "AMDGPU Annotate Kernel Features";
47 void getAnalysisUsage(AnalysisUsage
&AU
) const override
{
49 CallGraphSCCPass::getAnalysisUsage(AU
);
53 } // end anonymous namespace
55 char AMDGPUAnnotateKernelFeatures::ID
= 0;
57 char &llvm::AMDGPUAnnotateKernelFeaturesID
= AMDGPUAnnotateKernelFeatures::ID
;
59 INITIALIZE_PASS(AMDGPUAnnotateKernelFeatures
, DEBUG_TYPE
,
60 "Add AMDGPU function attributes", false, false)
62 bool AMDGPUAnnotateKernelFeatures::addFeatureAttributes(Function
&F
) {
63 bool HaveStackObjects
= false;
65 bool HaveCall
= false;
66 bool IsFunc
= !AMDGPU::isEntryFunctionCC(F
.getCallingConv());
68 for (BasicBlock
&BB
: F
) {
69 for (Instruction
&I
: BB
) {
70 if (isa
<AllocaInst
>(I
)) {
71 HaveStackObjects
= true;
75 if (auto *CB
= dyn_cast
<CallBase
>(&I
)) {
76 const Function
*Callee
=
77 dyn_cast
<Function
>(CB
->getCalledOperand()->stripPointerCasts());
79 // Note the occurrence of indirect call.
81 if (!CB
->isInlineAsm())
87 Intrinsic::ID IID
= Callee
->getIntrinsicID();
88 if (IID
== Intrinsic::not_intrinsic
) {
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("amdgpu-calls");
104 if (HaveStackObjects
) {
105 F
.addFnAttr("amdgpu-stack-objects");
112 bool AMDGPUAnnotateKernelFeatures::runOnSCC(CallGraphSCC
&SCC
) {
113 bool Changed
= false;
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(F
->getCallingConv()))
121 // Add feature attributes
122 Changed
|= addFeatureAttributes(*F
);
128 bool AMDGPUAnnotateKernelFeatures::doInitialization(CallGraph
&CG
) {
129 auto *TPC
= getAnalysisIfAvailable
<TargetPassConfig
>();
131 report_fatal_error("TargetMachine is required");
133 TM
= &TPC
->getTM
<TargetMachine
>();
137 Pass
*llvm::createAMDGPUAnnotateKernelFeaturesPass() {
138 return new AMDGPUAnnotateKernelFeatures();