109467b48Spatrick //===--- AMDGPUPropagateAttributes.cpp --------------------------*- C++ -*-===//
209467b48Spatrick //
309467b48Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
409467b48Spatrick // See https://llvm.org/LICENSE.txt for license information.
509467b48Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
609467b48Spatrick //
709467b48Spatrick //===----------------------------------------------------------------------===//
809467b48Spatrick //
909467b48Spatrick /// \file
1009467b48Spatrick /// \brief This pass propagates attributes from kernels to the non-entry
1109467b48Spatrick /// functions. Most of the library functions were not compiled for specific ABI,
12*d415bd75Srobert /// yet will be correctly compiled if proper attributes are propagated from the
1309467b48Spatrick /// caller.
1409467b48Spatrick ///
1509467b48Spatrick /// The pass analyzes call graph and propagates ABI target features through the
1609467b48Spatrick /// call graph.
1709467b48Spatrick ///
1809467b48Spatrick /// It can run in two modes: as a function or module pass. A function pass
1909467b48Spatrick /// simply propagates attributes. A module pass clones functions if there are
20*d415bd75Srobert /// callers with different ABI. If a function is cloned all call sites will
2109467b48Spatrick /// be updated to use a correct clone.
2209467b48Spatrick ///
2309467b48Spatrick /// A function pass is limited in functionality but can run early in the
2409467b48Spatrick /// pipeline. A module pass is more powerful but has to run late, so misses
2509467b48Spatrick /// library folding opportunities.
2609467b48Spatrick //
2709467b48Spatrick //===----------------------------------------------------------------------===//
2809467b48Spatrick 
2909467b48Spatrick #include "AMDGPU.h"
3009467b48Spatrick #include "MCTargetDesc/AMDGPUMCTargetDesc.h"
3109467b48Spatrick #include "Utils/AMDGPUBaseInfo.h"
3209467b48Spatrick #include "llvm/ADT/SmallSet.h"
3373471bf0Spatrick #include "llvm/CodeGen/TargetPassConfig.h"
3473471bf0Spatrick #include "llvm/CodeGen/TargetSubtargetInfo.h"
3573471bf0Spatrick #include "llvm/IR/InstrTypes.h"
3609467b48Spatrick #include "llvm/Target/TargetMachine.h"
3709467b48Spatrick #include "llvm/Transforms/Utils/Cloning.h"
3809467b48Spatrick 
3909467b48Spatrick #define DEBUG_TYPE "amdgpu-propagate-attributes"
4009467b48Spatrick 
4109467b48Spatrick using namespace llvm;
4209467b48Spatrick 
4309467b48Spatrick namespace llvm {
4409467b48Spatrick extern const SubtargetFeatureKV AMDGPUFeatureKV[AMDGPU::NumSubtargetFeatures-1];
4509467b48Spatrick }
4609467b48Spatrick 
4709467b48Spatrick namespace {
4809467b48Spatrick 
49097a140dSpatrick // Target features to propagate.
50097a140dSpatrick static constexpr const FeatureBitset TargetFeatures = {
5109467b48Spatrick   AMDGPU::FeatureWavefrontSize16,
5209467b48Spatrick   AMDGPU::FeatureWavefrontSize32,
5309467b48Spatrick   AMDGPU::FeatureWavefrontSize64
5409467b48Spatrick };
5509467b48Spatrick 
56097a140dSpatrick // Attributes to propagate.
5773471bf0Spatrick // TODO: Support conservative min/max merging instead of cloning.
58*d415bd75Srobert static constexpr const char *AttributeNames[] = {"amdgpu-waves-per-eu"};
59097a140dSpatrick 
60*d415bd75Srobert static constexpr unsigned NumAttr = std::size(AttributeNames);
61097a140dSpatrick 
62097a140dSpatrick class AMDGPUPropagateAttributes {
63097a140dSpatrick 
64097a140dSpatrick   class FnProperties {
65097a140dSpatrick   private:
FnProperties(const FeatureBitset && FB)66097a140dSpatrick     explicit FnProperties(const FeatureBitset &&FB) : Features(FB) {}
67097a140dSpatrick 
68097a140dSpatrick   public:
FnProperties(const TargetMachine & TM,const Function & F)69097a140dSpatrick     explicit FnProperties(const TargetMachine &TM, const Function &F) {
70097a140dSpatrick       Features = TM.getSubtargetImpl(F)->getFeatureBits();
71097a140dSpatrick 
72097a140dSpatrick       for (unsigned I = 0; I < NumAttr; ++I)
73097a140dSpatrick         if (F.hasFnAttribute(AttributeNames[I]))
74097a140dSpatrick           Attributes[I] = F.getFnAttribute(AttributeNames[I]);
75097a140dSpatrick     }
76097a140dSpatrick 
operator ==(const FnProperties & Other) const77097a140dSpatrick     bool operator == (const FnProperties &Other) const {
78097a140dSpatrick       if ((Features & TargetFeatures) != (Other.Features & TargetFeatures))
79097a140dSpatrick         return false;
80097a140dSpatrick       for (unsigned I = 0; I < NumAttr; ++I)
81097a140dSpatrick         if (Attributes[I] != Other.Attributes[I])
82097a140dSpatrick           return false;
83097a140dSpatrick       return true;
84097a140dSpatrick     }
85097a140dSpatrick 
adjustToCaller(const FnProperties & CallerProps) const86097a140dSpatrick     FnProperties adjustToCaller(const FnProperties &CallerProps) const {
87097a140dSpatrick       FnProperties New((Features & ~TargetFeatures) | CallerProps.Features);
88097a140dSpatrick       for (unsigned I = 0; I < NumAttr; ++I)
89097a140dSpatrick         New.Attributes[I] = CallerProps.Attributes[I];
90097a140dSpatrick       return New;
91097a140dSpatrick     }
92097a140dSpatrick 
93097a140dSpatrick     FeatureBitset Features;
94*d415bd75Srobert     std::optional<Attribute> Attributes[NumAttr];
95097a140dSpatrick   };
96097a140dSpatrick 
9709467b48Spatrick   class Clone {
9809467b48Spatrick   public:
Clone(const FnProperties & Props,Function * OrigF,Function * NewF)99097a140dSpatrick     Clone(const FnProperties &Props, Function *OrigF, Function *NewF) :
100097a140dSpatrick       Properties(Props), OrigF(OrigF), NewF(NewF) {}
10109467b48Spatrick 
102097a140dSpatrick     FnProperties Properties;
10309467b48Spatrick     Function *OrigF;
10409467b48Spatrick     Function *NewF;
10509467b48Spatrick   };
10609467b48Spatrick 
10709467b48Spatrick   const TargetMachine *TM;
10809467b48Spatrick 
10909467b48Spatrick   // Clone functions as needed or just set attributes.
11009467b48Spatrick   bool AllowClone;
11109467b48Spatrick 
11209467b48Spatrick   // Option propagation roots.
11309467b48Spatrick   SmallSet<Function *, 32> Roots;
11409467b48Spatrick 
11509467b48Spatrick   // Clones of functions with their attributes.
11609467b48Spatrick   SmallVector<Clone, 32> Clones;
11709467b48Spatrick 
11809467b48Spatrick   // Find a clone with required features.
119097a140dSpatrick   Function *findFunction(const FnProperties &PropsNeeded,
12009467b48Spatrick                          Function *OrigF);
12109467b48Spatrick 
122097a140dSpatrick   // Clone function \p F and set \p NewProps on the clone.
12309467b48Spatrick   // Cole takes the name of original function.
124097a140dSpatrick   Function *cloneWithProperties(Function &F, const FnProperties &NewProps);
12509467b48Spatrick 
12609467b48Spatrick   // Set new function's features in place.
12709467b48Spatrick   void setFeatures(Function &F, const FeatureBitset &NewFeatures);
12809467b48Spatrick 
129097a140dSpatrick   // Set new function's attributes in place.
130*d415bd75Srobert   void setAttributes(Function &F,
131*d415bd75Srobert                      const ArrayRef<std::optional<Attribute>> NewAttrs);
132097a140dSpatrick 
13309467b48Spatrick   std::string getFeatureString(const FeatureBitset &Features) const;
13409467b48Spatrick 
13509467b48Spatrick   // Propagate attributes from Roots.
13609467b48Spatrick   bool process();
13709467b48Spatrick 
13809467b48Spatrick public:
AMDGPUPropagateAttributes(const TargetMachine * TM,bool AllowClone)13909467b48Spatrick   AMDGPUPropagateAttributes(const TargetMachine *TM, bool AllowClone) :
14009467b48Spatrick     TM(TM), AllowClone(AllowClone) {}
14109467b48Spatrick 
14209467b48Spatrick   // Use F as a root and propagate its attributes.
14309467b48Spatrick   bool process(Function &F);
14409467b48Spatrick 
14509467b48Spatrick   // Propagate attributes starting from kernel functions.
14609467b48Spatrick   bool process(Module &M);
14709467b48Spatrick };
14809467b48Spatrick 
149*d415bd75Srobert // Allows to propagate attributes early, but no cloning is allowed as it must
15009467b48Spatrick // be a function pass to run before any optimizations.
15109467b48Spatrick // TODO: We shall only need a one instance of module pass, but that needs to be
15209467b48Spatrick // in the linker pipeline which is currently not possible.
15309467b48Spatrick class AMDGPUPropagateAttributesEarly : public FunctionPass {
15409467b48Spatrick   const TargetMachine *TM;
15509467b48Spatrick 
15609467b48Spatrick public:
15709467b48Spatrick   static char ID; // Pass identification
15809467b48Spatrick 
AMDGPUPropagateAttributesEarly(const TargetMachine * TM=nullptr)15909467b48Spatrick   AMDGPUPropagateAttributesEarly(const TargetMachine *TM = nullptr) :
16009467b48Spatrick     FunctionPass(ID), TM(TM) {
16109467b48Spatrick     initializeAMDGPUPropagateAttributesEarlyPass(
16209467b48Spatrick       *PassRegistry::getPassRegistry());
16309467b48Spatrick   }
16409467b48Spatrick 
16509467b48Spatrick   bool runOnFunction(Function &F) override;
16609467b48Spatrick };
16709467b48Spatrick 
168*d415bd75Srobert // Allows to propagate attributes with cloning but does that late in the
16909467b48Spatrick // pipeline.
17009467b48Spatrick class AMDGPUPropagateAttributesLate : public ModulePass {
17109467b48Spatrick   const TargetMachine *TM;
17209467b48Spatrick 
17309467b48Spatrick public:
17409467b48Spatrick   static char ID; // Pass identification
17509467b48Spatrick 
AMDGPUPropagateAttributesLate(const TargetMachine * TM=nullptr)17609467b48Spatrick   AMDGPUPropagateAttributesLate(const TargetMachine *TM = nullptr) :
17709467b48Spatrick     ModulePass(ID), TM(TM) {
17809467b48Spatrick     initializeAMDGPUPropagateAttributesLatePass(
17909467b48Spatrick       *PassRegistry::getPassRegistry());
18009467b48Spatrick   }
18109467b48Spatrick 
18209467b48Spatrick   bool runOnModule(Module &M) override;
18309467b48Spatrick };
18409467b48Spatrick 
18509467b48Spatrick }  // end anonymous namespace.
18609467b48Spatrick 
18709467b48Spatrick char AMDGPUPropagateAttributesEarly::ID = 0;
18809467b48Spatrick char AMDGPUPropagateAttributesLate::ID = 0;
18909467b48Spatrick 
19009467b48Spatrick INITIALIZE_PASS(AMDGPUPropagateAttributesEarly,
19109467b48Spatrick                 "amdgpu-propagate-attributes-early",
19209467b48Spatrick                 "Early propagate attributes from kernels to functions",
19309467b48Spatrick                 false, false)
19409467b48Spatrick INITIALIZE_PASS(AMDGPUPropagateAttributesLate,
19509467b48Spatrick                 "amdgpu-propagate-attributes-late",
19609467b48Spatrick                 "Late propagate attributes from kernels to functions",
19709467b48Spatrick                 false, false)
19809467b48Spatrick 
19909467b48Spatrick Function *
findFunction(const FnProperties & PropsNeeded,Function * OrigF)200097a140dSpatrick AMDGPUPropagateAttributes::findFunction(const FnProperties &PropsNeeded,
20109467b48Spatrick                                         Function *OrigF) {
20209467b48Spatrick   // TODO: search for clone's clones.
20309467b48Spatrick   for (Clone &C : Clones)
204097a140dSpatrick     if (C.OrigF == OrigF && PropsNeeded == C.Properties)
20509467b48Spatrick       return C.NewF;
20609467b48Spatrick 
20709467b48Spatrick   return nullptr;
20809467b48Spatrick }
20909467b48Spatrick 
process(Module & M)21009467b48Spatrick bool AMDGPUPropagateAttributes::process(Module &M) {
21109467b48Spatrick   for (auto &F : M.functions())
212*d415bd75Srobert     if (AMDGPU::isKernel(F.getCallingConv()))
21309467b48Spatrick       Roots.insert(&F);
21409467b48Spatrick 
215*d415bd75Srobert   return Roots.empty() ? false : process();
21609467b48Spatrick }
21709467b48Spatrick 
process(Function & F)21809467b48Spatrick bool AMDGPUPropagateAttributes::process(Function &F) {
21909467b48Spatrick   Roots.insert(&F);
22009467b48Spatrick   return process();
22109467b48Spatrick }
22209467b48Spatrick 
process()22309467b48Spatrick bool AMDGPUPropagateAttributes::process() {
22409467b48Spatrick   bool Changed = false;
22509467b48Spatrick   SmallSet<Function *, 32> NewRoots;
22609467b48Spatrick   SmallSet<Function *, 32> Replaced;
22709467b48Spatrick 
228*d415bd75Srobert   assert(!Roots.empty());
22909467b48Spatrick   Module &M = *(*Roots.begin())->getParent();
23009467b48Spatrick 
23109467b48Spatrick   do {
23209467b48Spatrick     Roots.insert(NewRoots.begin(), NewRoots.end());
23309467b48Spatrick     NewRoots.clear();
23409467b48Spatrick 
23509467b48Spatrick     for (auto &F : M.functions()) {
236097a140dSpatrick       if (F.isDeclaration())
23709467b48Spatrick         continue;
23809467b48Spatrick 
239097a140dSpatrick       const FnProperties CalleeProps(*TM, F);
24009467b48Spatrick       SmallVector<std::pair<CallBase *, Function *>, 32> ToReplace;
241097a140dSpatrick       SmallSet<CallBase *, 32> Visited;
24209467b48Spatrick 
24309467b48Spatrick       for (User *U : F.users()) {
24409467b48Spatrick         Instruction *I = dyn_cast<Instruction>(U);
24509467b48Spatrick         if (!I)
24609467b48Spatrick           continue;
24709467b48Spatrick         CallBase *CI = dyn_cast<CallBase>(I);
24873471bf0Spatrick         // Only propagate attributes if F is the called function. Specifically,
24973471bf0Spatrick         // do not propagate attributes if F is passed as an argument.
25073471bf0Spatrick         // FIXME: handle bitcasted callee, e.g.
25173471bf0Spatrick         // %retval = call i8* bitcast (i32* ()* @f to i8* ()*)()
25273471bf0Spatrick         if (!CI || CI->getCalledOperand() != &F)
25309467b48Spatrick           continue;
25409467b48Spatrick         Function *Caller = CI->getCaller();
255097a140dSpatrick         if (!Caller || !Visited.insert(CI).second)
25609467b48Spatrick           continue;
257097a140dSpatrick         if (!Roots.count(Caller) && !NewRoots.count(Caller))
25809467b48Spatrick           continue;
25909467b48Spatrick 
260097a140dSpatrick         const FnProperties CallerProps(*TM, *Caller);
26109467b48Spatrick 
262097a140dSpatrick         if (CalleeProps == CallerProps) {
263097a140dSpatrick           if (!Roots.count(&F))
26409467b48Spatrick             NewRoots.insert(&F);
26509467b48Spatrick           continue;
26609467b48Spatrick         }
26709467b48Spatrick 
268097a140dSpatrick         Function *NewF = findFunction(CallerProps, &F);
26909467b48Spatrick         if (!NewF) {
270097a140dSpatrick           const FnProperties NewProps = CalleeProps.adjustToCaller(CallerProps);
27109467b48Spatrick           if (!AllowClone) {
272*d415bd75Srobert             // This may set different features on different iterations if
27309467b48Spatrick             // there is a contradiction in callers' attributes. In this case
27409467b48Spatrick             // we rely on a second pass running on Module, which is allowed
27509467b48Spatrick             // to clone.
276097a140dSpatrick             setFeatures(F, NewProps.Features);
277097a140dSpatrick             setAttributes(F, NewProps.Attributes);
27809467b48Spatrick             NewRoots.insert(&F);
27909467b48Spatrick             Changed = true;
28009467b48Spatrick             break;
28109467b48Spatrick           }
28209467b48Spatrick 
283097a140dSpatrick           NewF = cloneWithProperties(F, NewProps);
284097a140dSpatrick           Clones.push_back(Clone(CallerProps, &F, NewF));
28509467b48Spatrick           NewRoots.insert(NewF);
28609467b48Spatrick         }
28709467b48Spatrick 
288*d415bd75Srobert         ToReplace.push_back(std::pair(CI, NewF));
28909467b48Spatrick         Replaced.insert(&F);
29009467b48Spatrick 
29109467b48Spatrick         Changed = true;
29209467b48Spatrick       }
29309467b48Spatrick 
29409467b48Spatrick       while (!ToReplace.empty()) {
29509467b48Spatrick         auto R = ToReplace.pop_back_val();
29609467b48Spatrick         R.first->setCalledFunction(R.second);
29709467b48Spatrick       }
29809467b48Spatrick     }
29909467b48Spatrick   } while (!NewRoots.empty());
30009467b48Spatrick 
30109467b48Spatrick   for (Function *F : Replaced) {
30209467b48Spatrick     if (F->use_empty())
30309467b48Spatrick       F->eraseFromParent();
30409467b48Spatrick   }
30509467b48Spatrick 
306097a140dSpatrick   Roots.clear();
307097a140dSpatrick   Clones.clear();
308097a140dSpatrick 
30909467b48Spatrick   return Changed;
31009467b48Spatrick }
31109467b48Spatrick 
31209467b48Spatrick Function *
cloneWithProperties(Function & F,const FnProperties & NewProps)313097a140dSpatrick AMDGPUPropagateAttributes::cloneWithProperties(Function &F,
314097a140dSpatrick                                                const FnProperties &NewProps) {
31509467b48Spatrick   LLVM_DEBUG(dbgs() << "Cloning " << F.getName() << '\n');
31609467b48Spatrick 
31709467b48Spatrick   ValueToValueMapTy dummy;
31809467b48Spatrick   Function *NewF = CloneFunction(&F, dummy);
319097a140dSpatrick   setFeatures(*NewF, NewProps.Features);
320097a140dSpatrick   setAttributes(*NewF, NewProps.Attributes);
321097a140dSpatrick   NewF->setVisibility(GlobalValue::DefaultVisibility);
322097a140dSpatrick   NewF->setLinkage(GlobalValue::InternalLinkage);
32309467b48Spatrick 
32409467b48Spatrick   // Swap names. If that is the only clone it will retain the name of now
325097a140dSpatrick   // dead value. Preserve original name for externally visible functions.
326097a140dSpatrick   if (F.hasName() && F.hasLocalLinkage()) {
327097a140dSpatrick     std::string NewName = std::string(NewF->getName());
32809467b48Spatrick     NewF->takeName(&F);
32909467b48Spatrick     F.setName(NewName);
33009467b48Spatrick   }
33109467b48Spatrick 
33209467b48Spatrick   return NewF;
33309467b48Spatrick }
33409467b48Spatrick 
setFeatures(Function & F,const FeatureBitset & NewFeatures)33509467b48Spatrick void AMDGPUPropagateAttributes::setFeatures(Function &F,
33609467b48Spatrick                                             const FeatureBitset &NewFeatures) {
33709467b48Spatrick   std::string NewFeatureStr = getFeatureString(NewFeatures);
33809467b48Spatrick 
33909467b48Spatrick   LLVM_DEBUG(dbgs() << "Set features "
34009467b48Spatrick                     << getFeatureString(NewFeatures & TargetFeatures)
34109467b48Spatrick                     << " on " << F.getName() << '\n');
34209467b48Spatrick 
34309467b48Spatrick   F.removeFnAttr("target-features");
34409467b48Spatrick   F.addFnAttr("target-features", NewFeatureStr);
34509467b48Spatrick }
34609467b48Spatrick 
setAttributes(Function & F,const ArrayRef<std::optional<Attribute>> NewAttrs)347*d415bd75Srobert void AMDGPUPropagateAttributes::setAttributes(
348*d415bd75Srobert     Function &F, const ArrayRef<std::optional<Attribute>> NewAttrs) {
349097a140dSpatrick   LLVM_DEBUG(dbgs() << "Set attributes on " << F.getName() << ":\n");
350097a140dSpatrick   for (unsigned I = 0; I < NumAttr; ++I) {
351097a140dSpatrick     F.removeFnAttr(AttributeNames[I]);
352097a140dSpatrick     if (NewAttrs[I]) {
353097a140dSpatrick       LLVM_DEBUG(dbgs() << '\t' << NewAttrs[I]->getAsString() << '\n');
354097a140dSpatrick       F.addFnAttr(*NewAttrs[I]);
355097a140dSpatrick     }
356097a140dSpatrick   }
357097a140dSpatrick }
358097a140dSpatrick 
35909467b48Spatrick std::string
getFeatureString(const FeatureBitset & Features) const36009467b48Spatrick AMDGPUPropagateAttributes::getFeatureString(const FeatureBitset &Features) const
36109467b48Spatrick {
36209467b48Spatrick   std::string Ret;
36309467b48Spatrick   for (const SubtargetFeatureKV &KV : AMDGPUFeatureKV) {
36409467b48Spatrick     if (Features[KV.Value])
36509467b48Spatrick       Ret += (StringRef("+") + KV.Key + ",").str();
36609467b48Spatrick     else if (TargetFeatures[KV.Value])
36709467b48Spatrick       Ret += (StringRef("-") + KV.Key + ",").str();
36809467b48Spatrick   }
36909467b48Spatrick   Ret.pop_back(); // Remove last comma.
37009467b48Spatrick   return Ret;
37109467b48Spatrick }
37209467b48Spatrick 
runOnFunction(Function & F)37309467b48Spatrick bool AMDGPUPropagateAttributesEarly::runOnFunction(Function &F) {
37473471bf0Spatrick   if (!TM) {
37573471bf0Spatrick     auto *TPC = getAnalysisIfAvailable<TargetPassConfig>();
37673471bf0Spatrick     if (!TPC)
37773471bf0Spatrick       return false;
37873471bf0Spatrick 
37973471bf0Spatrick     TM = &TPC->getTM<TargetMachine>();
38073471bf0Spatrick   }
38173471bf0Spatrick 
382*d415bd75Srobert   if (!AMDGPU::isKernel(F.getCallingConv()))
38309467b48Spatrick     return false;
38409467b48Spatrick 
38509467b48Spatrick   return AMDGPUPropagateAttributes(TM, false).process(F);
38609467b48Spatrick }
38709467b48Spatrick 
runOnModule(Module & M)38809467b48Spatrick bool AMDGPUPropagateAttributesLate::runOnModule(Module &M) {
38973471bf0Spatrick   if (!TM) {
39073471bf0Spatrick     auto *TPC = getAnalysisIfAvailable<TargetPassConfig>();
39173471bf0Spatrick     if (!TPC)
39209467b48Spatrick       return false;
39309467b48Spatrick 
39473471bf0Spatrick     TM = &TPC->getTM<TargetMachine>();
39573471bf0Spatrick   }
39673471bf0Spatrick 
39709467b48Spatrick   return AMDGPUPropagateAttributes(TM, true).process(M);
39809467b48Spatrick }
39909467b48Spatrick 
40009467b48Spatrick FunctionPass
createAMDGPUPropagateAttributesEarlyPass(const TargetMachine * TM)40109467b48Spatrick *llvm::createAMDGPUPropagateAttributesEarlyPass(const TargetMachine *TM) {
40209467b48Spatrick   return new AMDGPUPropagateAttributesEarly(TM);
40309467b48Spatrick }
40409467b48Spatrick 
40509467b48Spatrick ModulePass
createAMDGPUPropagateAttributesLatePass(const TargetMachine * TM)40609467b48Spatrick *llvm::createAMDGPUPropagateAttributesLatePass(const TargetMachine *TM) {
40709467b48Spatrick   return new AMDGPUPropagateAttributesLate(TM);
40809467b48Spatrick }
40973471bf0Spatrick 
41073471bf0Spatrick PreservedAnalyses
run(Function & F,FunctionAnalysisManager & AM)41173471bf0Spatrick AMDGPUPropagateAttributesEarlyPass::run(Function &F,
41273471bf0Spatrick                                         FunctionAnalysisManager &AM) {
41373471bf0Spatrick   if (!AMDGPU::isEntryFunctionCC(F.getCallingConv()))
41473471bf0Spatrick     return PreservedAnalyses::all();
41573471bf0Spatrick 
41673471bf0Spatrick   return AMDGPUPropagateAttributes(&TM, false).process(F)
41773471bf0Spatrick              ? PreservedAnalyses::none()
41873471bf0Spatrick              : PreservedAnalyses::all();
41973471bf0Spatrick }
42073471bf0Spatrick 
42173471bf0Spatrick PreservedAnalyses
run(Module & M,ModuleAnalysisManager & AM)42273471bf0Spatrick AMDGPUPropagateAttributesLatePass::run(Module &M, ModuleAnalysisManager &AM) {
42373471bf0Spatrick   return AMDGPUPropagateAttributes(&TM, true).process(M)
42473471bf0Spatrick              ? PreservedAnalyses::none()
42573471bf0Spatrick              : PreservedAnalyses::all();
42673471bf0Spatrick }
427