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