1ad04e7adSStanislav Mekhanoshin //===--- AMDGPUPropagateAttributes.cpp --------------------------*- C++ -*-===//
2ad04e7adSStanislav Mekhanoshin //
3ad04e7adSStanislav Mekhanoshin // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4ad04e7adSStanislav Mekhanoshin // See https://llvm.org/LICENSE.txt for license information.
5ad04e7adSStanislav Mekhanoshin // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6ad04e7adSStanislav Mekhanoshin //
7ad04e7adSStanislav Mekhanoshin //===----------------------------------------------------------------------===//
8ad04e7adSStanislav Mekhanoshin //
9ad04e7adSStanislav Mekhanoshin /// \file
10ad04e7adSStanislav Mekhanoshin /// \brief This pass propagates attributes from kernels to the non-entry
11ad04e7adSStanislav Mekhanoshin /// functions. Most of the library functions were not compiled for specific ABI,
12ad04e7adSStanislav Mekhanoshin /// yet will be correctly compiled if proper attrbutes are propagated from the
13ad04e7adSStanislav Mekhanoshin /// caller.
14ad04e7adSStanislav Mekhanoshin ///
15ad04e7adSStanislav Mekhanoshin /// The pass analyzes call graph and propagates ABI target features through the
16ad04e7adSStanislav Mekhanoshin /// call graph.
17ad04e7adSStanislav Mekhanoshin ///
18ad04e7adSStanislav Mekhanoshin /// It can run in two modes: as a function or module pass. A function pass
19ad04e7adSStanislav Mekhanoshin /// simply propagates attributes. A module pass clones functions if there are
20ad04e7adSStanislav Mekhanoshin /// callers with different ABI. If a function is clonned all call sites will
21ad04e7adSStanislav Mekhanoshin /// be updated to use a correct clone.
22ad04e7adSStanislav Mekhanoshin ///
23ad04e7adSStanislav Mekhanoshin /// A function pass is limited in functionality but can run early in the
24ad04e7adSStanislav Mekhanoshin /// pipeline. A module pass is more powerful but has to run late, so misses
25ad04e7adSStanislav Mekhanoshin /// library folding opportunities.
26ad04e7adSStanislav Mekhanoshin //
27ad04e7adSStanislav Mekhanoshin //===----------------------------------------------------------------------===//
28ad04e7adSStanislav Mekhanoshin 
29ad04e7adSStanislav Mekhanoshin #include "AMDGPU.h"
30ad04e7adSStanislav Mekhanoshin #include "AMDGPUSubtarget.h"
31ad04e7adSStanislav Mekhanoshin #include "MCTargetDesc/AMDGPUMCTargetDesc.h"
32ad04e7adSStanislav Mekhanoshin #include "Utils/AMDGPUBaseInfo.h"
33ad04e7adSStanislav Mekhanoshin #include "llvm/ADT/SmallSet.h"
34ad04e7adSStanislav Mekhanoshin #include "llvm/ADT/SmallVector.h"
35ad04e7adSStanislav Mekhanoshin #include "llvm/IR/Function.h"
36ad04e7adSStanislav Mekhanoshin #include "llvm/IR/Module.h"
37ad04e7adSStanislav Mekhanoshin #include "llvm/Target/TargetMachine.h"
38ad04e7adSStanislav Mekhanoshin #include "llvm/Transforms/Utils/Cloning.h"
39ad04e7adSStanislav Mekhanoshin #include <string>
40ad04e7adSStanislav Mekhanoshin 
415e643036SMatt Arsenault #define DEBUG_TYPE "amdgpu-propagate-attributes"
425e643036SMatt Arsenault 
43ad04e7adSStanislav Mekhanoshin using namespace llvm;
44ad04e7adSStanislav Mekhanoshin 
45ad04e7adSStanislav Mekhanoshin namespace llvm {
46ad04e7adSStanislav Mekhanoshin extern const SubtargetFeatureKV AMDGPUFeatureKV[AMDGPU::NumSubtargetFeatures-1];
47ad04e7adSStanislav Mekhanoshin }
48ad04e7adSStanislav Mekhanoshin 
49ad04e7adSStanislav Mekhanoshin namespace {
50ad04e7adSStanislav Mekhanoshin 
51ad04e7adSStanislav Mekhanoshin class AMDGPUPropagateAttributes {
52ad04e7adSStanislav Mekhanoshin   const FeatureBitset TargetFeatures = {
53ad04e7adSStanislav Mekhanoshin     AMDGPU::FeatureWavefrontSize16,
54ad04e7adSStanislav Mekhanoshin     AMDGPU::FeatureWavefrontSize32,
55ad04e7adSStanislav Mekhanoshin     AMDGPU::FeatureWavefrontSize64
56ad04e7adSStanislav Mekhanoshin   };
57ad04e7adSStanislav Mekhanoshin 
58ad04e7adSStanislav Mekhanoshin   class Clone{
59ad04e7adSStanislav Mekhanoshin   public:
60ad04e7adSStanislav Mekhanoshin     Clone(FeatureBitset FeatureMask, Function *OrigF, Function *NewF) :
61ad04e7adSStanislav Mekhanoshin       FeatureMask(FeatureMask), OrigF(OrigF), NewF(NewF) {}
62ad04e7adSStanislav Mekhanoshin 
63ad04e7adSStanislav Mekhanoshin     FeatureBitset FeatureMask;
64ad04e7adSStanislav Mekhanoshin     Function *OrigF;
65ad04e7adSStanislav Mekhanoshin     Function *NewF;
66ad04e7adSStanislav Mekhanoshin   };
67ad04e7adSStanislav Mekhanoshin 
68ad04e7adSStanislav Mekhanoshin   const TargetMachine *TM;
69ad04e7adSStanislav Mekhanoshin 
70ad04e7adSStanislav Mekhanoshin   // Clone functions as needed or just set attributes.
71ad04e7adSStanislav Mekhanoshin   bool AllowClone;
72ad04e7adSStanislav Mekhanoshin 
73ad04e7adSStanislav Mekhanoshin   // Option propagation roots.
74ad04e7adSStanislav Mekhanoshin   SmallSet<Function *, 32> Roots;
75ad04e7adSStanislav Mekhanoshin 
76ad04e7adSStanislav Mekhanoshin   // Clones of functions with their attributes.
77ad04e7adSStanislav Mekhanoshin   SmallVector<Clone, 32> Clones;
78ad04e7adSStanislav Mekhanoshin 
79ad04e7adSStanislav Mekhanoshin   // Find a clone with required features.
80ad04e7adSStanislav Mekhanoshin   Function *findFunction(const FeatureBitset &FeaturesNeeded,
81ad04e7adSStanislav Mekhanoshin                          Function *OrigF);
82ad04e7adSStanislav Mekhanoshin 
83ad04e7adSStanislav Mekhanoshin   // Clone function F and set NewFeatures on the clone.
84ad04e7adSStanislav Mekhanoshin   // Cole takes the name of original function.
85ad04e7adSStanislav Mekhanoshin   Function *cloneWithFeatures(Function &F,
86ad04e7adSStanislav Mekhanoshin                               const FeatureBitset &NewFeatures);
87ad04e7adSStanislav Mekhanoshin 
88ad04e7adSStanislav Mekhanoshin   // Set new function's features in place.
89ad04e7adSStanislav Mekhanoshin   void setFeatures(Function &F, const FeatureBitset &NewFeatures);
90ad04e7adSStanislav Mekhanoshin 
91ad04e7adSStanislav Mekhanoshin   std::string getFeatureString(const FeatureBitset &Features) const;
92ad04e7adSStanislav Mekhanoshin 
93ad04e7adSStanislav Mekhanoshin   // Propagate attributes from Roots.
94ad04e7adSStanislav Mekhanoshin   bool process();
95ad04e7adSStanislav Mekhanoshin 
96ad04e7adSStanislav Mekhanoshin public:
97ad04e7adSStanislav Mekhanoshin   AMDGPUPropagateAttributes(const TargetMachine *TM, bool AllowClone) :
98ad04e7adSStanislav Mekhanoshin     TM(TM), AllowClone(AllowClone) {}
99ad04e7adSStanislav Mekhanoshin 
100ad04e7adSStanislav Mekhanoshin   // Use F as a root and propagate its attributes.
101ad04e7adSStanislav Mekhanoshin   bool process(Function &F);
102ad04e7adSStanislav Mekhanoshin 
103ad04e7adSStanislav Mekhanoshin   // Propagate attributes starting from kernel functions.
104ad04e7adSStanislav Mekhanoshin   bool process(Module &M);
105ad04e7adSStanislav Mekhanoshin };
106ad04e7adSStanislav Mekhanoshin 
107ad04e7adSStanislav Mekhanoshin // Allows to propagate attributes early, but no clonning is allowed as it must
108ad04e7adSStanislav Mekhanoshin // be a function pass to run before any optimizations.
109ad04e7adSStanislav Mekhanoshin // TODO: We shall only need a one instance of module pass, but that needs to be
110ad04e7adSStanislav Mekhanoshin // in the linker pipeline which is currently not possible.
111ad04e7adSStanislav Mekhanoshin class AMDGPUPropagateAttributesEarly : public FunctionPass {
112ad04e7adSStanislav Mekhanoshin   const TargetMachine *TM;
113ad04e7adSStanislav Mekhanoshin 
114ad04e7adSStanislav Mekhanoshin public:
115ad04e7adSStanislav Mekhanoshin   static char ID; // Pass identification
116ad04e7adSStanislav Mekhanoshin 
117ad04e7adSStanislav Mekhanoshin   AMDGPUPropagateAttributesEarly(const TargetMachine *TM = nullptr) :
118ad04e7adSStanislav Mekhanoshin     FunctionPass(ID), TM(TM) {
119ad04e7adSStanislav Mekhanoshin     initializeAMDGPUPropagateAttributesEarlyPass(
120ad04e7adSStanislav Mekhanoshin       *PassRegistry::getPassRegistry());
121ad04e7adSStanislav Mekhanoshin   }
122ad04e7adSStanislav Mekhanoshin 
123ad04e7adSStanislav Mekhanoshin   bool runOnFunction(Function &F) override;
124ad04e7adSStanislav Mekhanoshin };
125ad04e7adSStanislav Mekhanoshin 
126ad04e7adSStanislav Mekhanoshin // Allows to propagate attributes with clonning but does that late in the
127ad04e7adSStanislav Mekhanoshin // pipeline.
128ad04e7adSStanislav Mekhanoshin class AMDGPUPropagateAttributesLate : public ModulePass {
129ad04e7adSStanislav Mekhanoshin   const TargetMachine *TM;
130ad04e7adSStanislav Mekhanoshin 
131ad04e7adSStanislav Mekhanoshin public:
132ad04e7adSStanislav Mekhanoshin   static char ID; // Pass identification
133ad04e7adSStanislav Mekhanoshin 
134ad04e7adSStanislav Mekhanoshin   AMDGPUPropagateAttributesLate(const TargetMachine *TM = nullptr) :
135ad04e7adSStanislav Mekhanoshin     ModulePass(ID), TM(TM) {
136ad04e7adSStanislav Mekhanoshin     initializeAMDGPUPropagateAttributesLatePass(
137ad04e7adSStanislav Mekhanoshin       *PassRegistry::getPassRegistry());
138ad04e7adSStanislav Mekhanoshin   }
139ad04e7adSStanislav Mekhanoshin 
140ad04e7adSStanislav Mekhanoshin   bool runOnModule(Module &M) override;
141ad04e7adSStanislav Mekhanoshin };
142ad04e7adSStanislav Mekhanoshin 
143ad04e7adSStanislav Mekhanoshin }  // end anonymous namespace.
144ad04e7adSStanislav Mekhanoshin 
145ad04e7adSStanislav Mekhanoshin char AMDGPUPropagateAttributesEarly::ID = 0;
146ad04e7adSStanislav Mekhanoshin char AMDGPUPropagateAttributesLate::ID = 0;
147ad04e7adSStanislav Mekhanoshin 
148ad04e7adSStanislav Mekhanoshin INITIALIZE_PASS(AMDGPUPropagateAttributesEarly,
149ad04e7adSStanislav Mekhanoshin                 "amdgpu-propagate-attributes-early",
150ad04e7adSStanislav Mekhanoshin                 "Early propagate attributes from kernels to functions",
151ad04e7adSStanislav Mekhanoshin                 false, false)
152ad04e7adSStanislav Mekhanoshin INITIALIZE_PASS(AMDGPUPropagateAttributesLate,
153ad04e7adSStanislav Mekhanoshin                 "amdgpu-propagate-attributes-late",
154ad04e7adSStanislav Mekhanoshin                 "Late propagate attributes from kernels to functions",
155ad04e7adSStanislav Mekhanoshin                 false, false)
156ad04e7adSStanislav Mekhanoshin 
157ad04e7adSStanislav Mekhanoshin Function *
158ad04e7adSStanislav Mekhanoshin AMDGPUPropagateAttributes::findFunction(const FeatureBitset &FeaturesNeeded,
159ad04e7adSStanislav Mekhanoshin                                         Function *OrigF) {
160ad04e7adSStanislav Mekhanoshin   // TODO: search for clone's clones.
161ad04e7adSStanislav Mekhanoshin   for (Clone &C : Clones)
162ad04e7adSStanislav Mekhanoshin     if (C.OrigF == OrigF && FeaturesNeeded == C.FeatureMask)
163ad04e7adSStanislav Mekhanoshin       return C.NewF;
164ad04e7adSStanislav Mekhanoshin 
165ad04e7adSStanislav Mekhanoshin   return nullptr;
166ad04e7adSStanislav Mekhanoshin }
167ad04e7adSStanislav Mekhanoshin 
168ad04e7adSStanislav Mekhanoshin bool AMDGPUPropagateAttributes::process(Module &M) {
169ad04e7adSStanislav Mekhanoshin   for (auto &F : M.functions())
170ad04e7adSStanislav Mekhanoshin     if (AMDGPU::isEntryFunctionCC(F.getCallingConv()))
171ad04e7adSStanislav Mekhanoshin       Roots.insert(&F);
172ad04e7adSStanislav Mekhanoshin 
173ad04e7adSStanislav Mekhanoshin   return process();
174ad04e7adSStanislav Mekhanoshin }
175ad04e7adSStanislav Mekhanoshin 
176ad04e7adSStanislav Mekhanoshin bool AMDGPUPropagateAttributes::process(Function &F) {
177ad04e7adSStanislav Mekhanoshin   Roots.insert(&F);
178ad04e7adSStanislav Mekhanoshin   return process();
179ad04e7adSStanislav Mekhanoshin }
180ad04e7adSStanislav Mekhanoshin 
181ad04e7adSStanislav Mekhanoshin bool AMDGPUPropagateAttributes::process() {
182ad04e7adSStanislav Mekhanoshin   bool Changed = false;
183ad04e7adSStanislav Mekhanoshin   SmallSet<Function *, 32> NewRoots;
184ad04e7adSStanislav Mekhanoshin   SmallSet<Function *, 32> Replaced;
185ad04e7adSStanislav Mekhanoshin 
186ad04e7adSStanislav Mekhanoshin   if (Roots.empty())
187ad04e7adSStanislav Mekhanoshin     return false;
188ad04e7adSStanislav Mekhanoshin   Module &M = *(*Roots.begin())->getParent();
189ad04e7adSStanislav Mekhanoshin 
190ad04e7adSStanislav Mekhanoshin   do {
191ad04e7adSStanislav Mekhanoshin     Roots.insert(NewRoots.begin(), NewRoots.end());
192ad04e7adSStanislav Mekhanoshin     NewRoots.clear();
193ad04e7adSStanislav Mekhanoshin 
194ad04e7adSStanislav Mekhanoshin     for (auto &F : M.functions()) {
195*e06d707aSStanislav Mekhanoshin       if (F.isDeclaration())
196ad04e7adSStanislav Mekhanoshin         continue;
197ad04e7adSStanislav Mekhanoshin 
198ad04e7adSStanislav Mekhanoshin       const FeatureBitset &CalleeBits =
199ad04e7adSStanislav Mekhanoshin         TM->getSubtargetImpl(F)->getFeatureBits();
200ad04e7adSStanislav Mekhanoshin       SmallVector<std::pair<CallBase *, Function *>, 32> ToReplace;
201*e06d707aSStanislav Mekhanoshin       SmallSet<CallBase *, 32> Visited;
202ad04e7adSStanislav Mekhanoshin 
203ad04e7adSStanislav Mekhanoshin       for (User *U : F.users()) {
204ad04e7adSStanislav Mekhanoshin         Instruction *I = dyn_cast<Instruction>(U);
205ad04e7adSStanislav Mekhanoshin         if (!I)
206ad04e7adSStanislav Mekhanoshin           continue;
207ad04e7adSStanislav Mekhanoshin         CallBase *CI = dyn_cast<CallBase>(I);
208ad04e7adSStanislav Mekhanoshin         if (!CI)
209ad04e7adSStanislav Mekhanoshin           continue;
210ad04e7adSStanislav Mekhanoshin         Function *Caller = CI->getCaller();
211*e06d707aSStanislav Mekhanoshin         if (!Caller || !Visited.insert(CI).second)
212ad04e7adSStanislav Mekhanoshin           continue;
213*e06d707aSStanislav Mekhanoshin         if (!Roots.count(Caller) && !NewRoots.count(Caller))
214ad04e7adSStanislav Mekhanoshin           continue;
215ad04e7adSStanislav Mekhanoshin 
216ad04e7adSStanislav Mekhanoshin         const FeatureBitset &CallerBits =
217ad04e7adSStanislav Mekhanoshin           TM->getSubtargetImpl(*Caller)->getFeatureBits() & TargetFeatures;
218ad04e7adSStanislav Mekhanoshin 
219ad04e7adSStanislav Mekhanoshin         if (CallerBits == (CalleeBits  & TargetFeatures)) {
220*e06d707aSStanislav Mekhanoshin           if (!Roots.count(&F))
221ad04e7adSStanislav Mekhanoshin             NewRoots.insert(&F);
222ad04e7adSStanislav Mekhanoshin           continue;
223ad04e7adSStanislav Mekhanoshin         }
224ad04e7adSStanislav Mekhanoshin 
225ad04e7adSStanislav Mekhanoshin         Function *NewF = findFunction(CallerBits, &F);
226ad04e7adSStanislav Mekhanoshin         if (!NewF) {
227ad04e7adSStanislav Mekhanoshin           FeatureBitset NewFeatures((CalleeBits & ~TargetFeatures) |
228ad04e7adSStanislav Mekhanoshin                                     CallerBits);
229ad04e7adSStanislav Mekhanoshin           if (!AllowClone) {
230ad04e7adSStanislav Mekhanoshin             // This may set different features on different iteartions if
231ad04e7adSStanislav Mekhanoshin             // there is a contradiction in callers' attributes. In this case
232ad04e7adSStanislav Mekhanoshin             // we rely on a second pass running on Module, which is allowed
233ad04e7adSStanislav Mekhanoshin             // to clone.
234ad04e7adSStanislav Mekhanoshin             setFeatures(F, NewFeatures);
235ad04e7adSStanislav Mekhanoshin             NewRoots.insert(&F);
236ad04e7adSStanislav Mekhanoshin             Changed = true;
237ad04e7adSStanislav Mekhanoshin             break;
238ad04e7adSStanislav Mekhanoshin           }
239ad04e7adSStanislav Mekhanoshin 
240ad04e7adSStanislav Mekhanoshin           NewF = cloneWithFeatures(F, NewFeatures);
241ad04e7adSStanislav Mekhanoshin           Clones.push_back(Clone(CallerBits, &F, NewF));
242ad04e7adSStanislav Mekhanoshin           NewRoots.insert(NewF);
243ad04e7adSStanislav Mekhanoshin         }
244ad04e7adSStanislav Mekhanoshin 
245ad04e7adSStanislav Mekhanoshin         ToReplace.push_back(std::make_pair(CI, NewF));
246ad04e7adSStanislav Mekhanoshin         Replaced.insert(&F);
247ad04e7adSStanislav Mekhanoshin 
248ad04e7adSStanislav Mekhanoshin         Changed = true;
249ad04e7adSStanislav Mekhanoshin       }
250ad04e7adSStanislav Mekhanoshin 
251ad04e7adSStanislav Mekhanoshin       while (!ToReplace.empty()) {
252ad04e7adSStanislav Mekhanoshin         auto R = ToReplace.pop_back_val();
253ad04e7adSStanislav Mekhanoshin         R.first->setCalledFunction(R.second);
254ad04e7adSStanislav Mekhanoshin       }
255ad04e7adSStanislav Mekhanoshin     }
256ad04e7adSStanislav Mekhanoshin   } while (!NewRoots.empty());
257ad04e7adSStanislav Mekhanoshin 
258ad04e7adSStanislav Mekhanoshin   for (Function *F : Replaced) {
259ad04e7adSStanislav Mekhanoshin     if (F->use_empty())
260ad04e7adSStanislav Mekhanoshin       F->eraseFromParent();
261ad04e7adSStanislav Mekhanoshin   }
262ad04e7adSStanislav Mekhanoshin 
263*e06d707aSStanislav Mekhanoshin   Roots.clear();
264*e06d707aSStanislav Mekhanoshin   Clones.clear();
265*e06d707aSStanislav Mekhanoshin 
266ad04e7adSStanislav Mekhanoshin   return Changed;
267ad04e7adSStanislav Mekhanoshin }
268ad04e7adSStanislav Mekhanoshin 
269ad04e7adSStanislav Mekhanoshin Function *
270ad04e7adSStanislav Mekhanoshin AMDGPUPropagateAttributes::cloneWithFeatures(Function &F,
271ad04e7adSStanislav Mekhanoshin                                              const FeatureBitset &NewFeatures) {
272ad04e7adSStanislav Mekhanoshin   LLVM_DEBUG(dbgs() << "Cloning " << F.getName() << '\n');
273ad04e7adSStanislav Mekhanoshin 
274ad04e7adSStanislav Mekhanoshin   ValueToValueMapTy dummy;
275ad04e7adSStanislav Mekhanoshin   Function *NewF = CloneFunction(&F, dummy);
276ad04e7adSStanislav Mekhanoshin   setFeatures(*NewF, NewFeatures);
2776e00e3fcSStanislav Mekhanoshin   NewF->setVisibility(GlobalValue::DefaultVisibility);
2786e00e3fcSStanislav Mekhanoshin   NewF->setLinkage(GlobalValue::InternalLinkage);
279ad04e7adSStanislav Mekhanoshin 
280ad04e7adSStanislav Mekhanoshin   // Swap names. If that is the only clone it will retain the name of now
2816e00e3fcSStanislav Mekhanoshin   // dead value. Preserve original name for externally visible functions.
2826e00e3fcSStanislav Mekhanoshin   if (F.hasName() && F.hasLocalLinkage()) {
283adcd0268SBenjamin Kramer     std::string NewName = std::string(NewF->getName());
284ad04e7adSStanislav Mekhanoshin     NewF->takeName(&F);
285ad04e7adSStanislav Mekhanoshin     F.setName(NewName);
286ad04e7adSStanislav Mekhanoshin   }
287ad04e7adSStanislav Mekhanoshin 
288ad04e7adSStanislav Mekhanoshin   return NewF;
289ad04e7adSStanislav Mekhanoshin }
290ad04e7adSStanislav Mekhanoshin 
291ad04e7adSStanislav Mekhanoshin void AMDGPUPropagateAttributes::setFeatures(Function &F,
292ad04e7adSStanislav Mekhanoshin                                             const FeatureBitset &NewFeatures) {
293ad04e7adSStanislav Mekhanoshin   std::string NewFeatureStr = getFeatureString(NewFeatures);
294ad04e7adSStanislav Mekhanoshin 
295ad04e7adSStanislav Mekhanoshin   LLVM_DEBUG(dbgs() << "Set features "
296ad04e7adSStanislav Mekhanoshin                     << getFeatureString(NewFeatures & TargetFeatures)
297ad04e7adSStanislav Mekhanoshin                     << " on " << F.getName() << '\n');
298ad04e7adSStanislav Mekhanoshin 
299ad04e7adSStanislav Mekhanoshin   F.removeFnAttr("target-features");
300ad04e7adSStanislav Mekhanoshin   F.addFnAttr("target-features", NewFeatureStr);
301ad04e7adSStanislav Mekhanoshin }
302ad04e7adSStanislav Mekhanoshin 
303ad04e7adSStanislav Mekhanoshin std::string
304ad04e7adSStanislav Mekhanoshin AMDGPUPropagateAttributes::getFeatureString(const FeatureBitset &Features) const
305ad04e7adSStanislav Mekhanoshin {
306ad04e7adSStanislav Mekhanoshin   std::string Ret;
307ad04e7adSStanislav Mekhanoshin   for (const SubtargetFeatureKV &KV : AMDGPUFeatureKV) {
308ad04e7adSStanislav Mekhanoshin     if (Features[KV.Value])
309ad04e7adSStanislav Mekhanoshin       Ret += (StringRef("+") + KV.Key + ",").str();
310ad04e7adSStanislav Mekhanoshin     else if (TargetFeatures[KV.Value])
311ad04e7adSStanislav Mekhanoshin       Ret += (StringRef("-") + KV.Key + ",").str();
312ad04e7adSStanislav Mekhanoshin   }
313ad04e7adSStanislav Mekhanoshin   Ret.pop_back(); // Remove last comma.
314ad04e7adSStanislav Mekhanoshin   return Ret;
315ad04e7adSStanislav Mekhanoshin }
316ad04e7adSStanislav Mekhanoshin 
317ad04e7adSStanislav Mekhanoshin bool AMDGPUPropagateAttributesEarly::runOnFunction(Function &F) {
318ad04e7adSStanislav Mekhanoshin   if (!TM || !AMDGPU::isEntryFunctionCC(F.getCallingConv()))
319ad04e7adSStanislav Mekhanoshin     return false;
320ad04e7adSStanislav Mekhanoshin 
321ad04e7adSStanislav Mekhanoshin   return AMDGPUPropagateAttributes(TM, false).process(F);
322ad04e7adSStanislav Mekhanoshin }
323ad04e7adSStanislav Mekhanoshin 
324ad04e7adSStanislav Mekhanoshin bool AMDGPUPropagateAttributesLate::runOnModule(Module &M) {
325ad04e7adSStanislav Mekhanoshin   if (!TM)
326ad04e7adSStanislav Mekhanoshin     return false;
327ad04e7adSStanislav Mekhanoshin 
328ad04e7adSStanislav Mekhanoshin   return AMDGPUPropagateAttributes(TM, true).process(M);
329ad04e7adSStanislav Mekhanoshin }
330ad04e7adSStanislav Mekhanoshin 
331ad04e7adSStanislav Mekhanoshin FunctionPass
332ad04e7adSStanislav Mekhanoshin *llvm::createAMDGPUPropagateAttributesEarlyPass(const TargetMachine *TM) {
333ad04e7adSStanislav Mekhanoshin   return new AMDGPUPropagateAttributesEarly(TM);
334ad04e7adSStanislav Mekhanoshin }
335ad04e7adSStanislav Mekhanoshin 
336ad04e7adSStanislav Mekhanoshin ModulePass
337ad04e7adSStanislav Mekhanoshin *llvm::createAMDGPUPropagateAttributesLatePass(const TargetMachine *TM) {
338ad04e7adSStanislav Mekhanoshin   return new AMDGPUPropagateAttributesLate(TM);
339ad04e7adSStanislav Mekhanoshin }
340