diff options
Diffstat (limited to 'llvm/lib/Target/AMDGPU/AMDGPUPropagateAttributes.cpp')
-rw-r--r-- | llvm/lib/Target/AMDGPU/AMDGPUPropagateAttributes.cpp | 137 |
1 files changed, 98 insertions, 39 deletions
diff --git a/llvm/lib/Target/AMDGPU/AMDGPUPropagateAttributes.cpp b/llvm/lib/Target/AMDGPU/AMDGPUPropagateAttributes.cpp index 7a7addd0f5cfe..982aae3748849 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPUPropagateAttributes.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPUPropagateAttributes.cpp @@ -48,19 +48,62 @@ extern const SubtargetFeatureKV AMDGPUFeatureKV[AMDGPU::NumSubtargetFeatures-1]; namespace { +// Target features to propagate. +static constexpr const FeatureBitset TargetFeatures = { + AMDGPU::FeatureWavefrontSize16, + AMDGPU::FeatureWavefrontSize32, + AMDGPU::FeatureWavefrontSize64 +}; + +// Attributes to propagate. +static constexpr const char* AttributeNames[] = { + "amdgpu-waves-per-eu" +}; + +static constexpr unsigned NumAttr = + sizeof(AttributeNames) / sizeof(AttributeNames[0]); + class AMDGPUPropagateAttributes { - const FeatureBitset TargetFeatures = { - AMDGPU::FeatureWavefrontSize16, - AMDGPU::FeatureWavefrontSize32, - AMDGPU::FeatureWavefrontSize64 + + class FnProperties { + private: + explicit FnProperties(const FeatureBitset &&FB) : Features(FB) {} + + public: + explicit FnProperties(const TargetMachine &TM, const Function &F) { + Features = TM.getSubtargetImpl(F)->getFeatureBits(); + + for (unsigned I = 0; I < NumAttr; ++I) + if (F.hasFnAttribute(AttributeNames[I])) + Attributes[I] = F.getFnAttribute(AttributeNames[I]); + } + + bool operator == (const FnProperties &Other) const { + if ((Features & TargetFeatures) != (Other.Features & TargetFeatures)) + return false; + for (unsigned I = 0; I < NumAttr; ++I) + if (Attributes[I] != Other.Attributes[I]) + return false; + return true; + } + + FnProperties adjustToCaller(const FnProperties &CallerProps) const { + FnProperties New((Features & ~TargetFeatures) | CallerProps.Features); + for (unsigned I = 0; I < NumAttr; ++I) + New.Attributes[I] = CallerProps.Attributes[I]; + return New; + } + + FeatureBitset Features; + Optional<Attribute> Attributes[NumAttr]; }; - class Clone{ + class Clone { public: - Clone(FeatureBitset FeatureMask, Function *OrigF, Function *NewF) : - FeatureMask(FeatureMask), OrigF(OrigF), NewF(NewF) {} + Clone(const FnProperties &Props, Function *OrigF, Function *NewF) : + Properties(Props), OrigF(OrigF), NewF(NewF) {} - FeatureBitset FeatureMask; + FnProperties Properties; Function *OrigF; Function *NewF; }; @@ -77,17 +120,19 @@ class AMDGPUPropagateAttributes { SmallVector<Clone, 32> Clones; // Find a clone with required features. - Function *findFunction(const FeatureBitset &FeaturesNeeded, + Function *findFunction(const FnProperties &PropsNeeded, Function *OrigF); - // Clone function F and set NewFeatures on the clone. + // Clone function \p F and set \p NewProps on the clone. // Cole takes the name of original function. - Function *cloneWithFeatures(Function &F, - const FeatureBitset &NewFeatures); + Function *cloneWithProperties(Function &F, const FnProperties &NewProps); // Set new function's features in place. void setFeatures(Function &F, const FeatureBitset &NewFeatures); + // Set new function's attributes in place. + void setAttributes(Function &F, const ArrayRef<Optional<Attribute>> NewAttrs); + std::string getFeatureString(const FeatureBitset &Features) const; // Propagate attributes from Roots. @@ -155,11 +200,11 @@ INITIALIZE_PASS(AMDGPUPropagateAttributesLate, false, false) Function * -AMDGPUPropagateAttributes::findFunction(const FeatureBitset &FeaturesNeeded, +AMDGPUPropagateAttributes::findFunction(const FnProperties &PropsNeeded, Function *OrigF) { // TODO: search for clone's clones. for (Clone &C : Clones) - if (C.OrigF == OrigF && FeaturesNeeded == C.FeatureMask) + if (C.OrigF == OrigF && PropsNeeded == C.Properties) return C.NewF; return nullptr; @@ -192,12 +237,12 @@ bool AMDGPUPropagateAttributes::process() { NewRoots.clear(); for (auto &F : M.functions()) { - if (F.isDeclaration() || Roots.count(&F) || Roots.count(&F)) + if (F.isDeclaration()) continue; - const FeatureBitset &CalleeBits = - TM->getSubtargetImpl(F)->getFeatureBits(); + const FnProperties CalleeProps(*TM, F); SmallVector<std::pair<CallBase *, Function *>, 32> ToReplace; + SmallSet<CallBase *, 32> Visited; for (User *U : F.users()) { Instruction *I = dyn_cast<Instruction>(U); @@ -207,36 +252,36 @@ bool AMDGPUPropagateAttributes::process() { if (!CI) continue; Function *Caller = CI->getCaller(); - if (!Caller) + if (!Caller || !Visited.insert(CI).second) continue; - if (!Roots.count(Caller)) + if (!Roots.count(Caller) && !NewRoots.count(Caller)) continue; - const FeatureBitset &CallerBits = - TM->getSubtargetImpl(*Caller)->getFeatureBits() & TargetFeatures; + const FnProperties CallerProps(*TM, *Caller); - if (CallerBits == (CalleeBits & TargetFeatures)) { - NewRoots.insert(&F); + if (CalleeProps == CallerProps) { + if (!Roots.count(&F)) + NewRoots.insert(&F); continue; } - Function *NewF = findFunction(CallerBits, &F); + Function *NewF = findFunction(CallerProps, &F); if (!NewF) { - FeatureBitset NewFeatures((CalleeBits & ~TargetFeatures) | - CallerBits); + const FnProperties NewProps = CalleeProps.adjustToCaller(CallerProps); if (!AllowClone) { // This may set different features on different iteartions if // there is a contradiction in callers' attributes. In this case // we rely on a second pass running on Module, which is allowed // to clone. - setFeatures(F, NewFeatures); + setFeatures(F, NewProps.Features); + setAttributes(F, NewProps.Attributes); NewRoots.insert(&F); Changed = true; break; } - NewF = cloneWithFeatures(F, NewFeatures); - Clones.push_back(Clone(CallerBits, &F, NewF)); + NewF = cloneWithProperties(F, NewProps); + Clones.push_back(Clone(CallerProps, &F, NewF)); NewRoots.insert(NewF); } @@ -258,28 +303,30 @@ bool AMDGPUPropagateAttributes::process() { F->eraseFromParent(); } + Roots.clear(); + Clones.clear(); + return Changed; } Function * -AMDGPUPropagateAttributes::cloneWithFeatures(Function &F, - const FeatureBitset &NewFeatures) { +AMDGPUPropagateAttributes::cloneWithProperties(Function &F, + const FnProperties &NewProps) { LLVM_DEBUG(dbgs() << "Cloning " << F.getName() << '\n'); ValueToValueMapTy dummy; Function *NewF = CloneFunction(&F, dummy); - setFeatures(*NewF, NewFeatures); + setFeatures(*NewF, NewProps.Features); + setAttributes(*NewF, NewProps.Attributes); + NewF->setVisibility(GlobalValue::DefaultVisibility); + NewF->setLinkage(GlobalValue::InternalLinkage); // Swap names. If that is the only clone it will retain the name of now - // dead value. - if (F.hasName()) { - std::string NewName = NewF->getName(); + // dead value. Preserve original name for externally visible functions. + if (F.hasName() && F.hasLocalLinkage()) { + std::string NewName = std::string(NewF->getName()); NewF->takeName(&F); F.setName(NewName); - - // Name has changed, it does not need an external symbol. - F.setVisibility(GlobalValue::DefaultVisibility); - F.setLinkage(GlobalValue::InternalLinkage); } return NewF; @@ -297,6 +344,18 @@ void AMDGPUPropagateAttributes::setFeatures(Function &F, F.addFnAttr("target-features", NewFeatureStr); } +void AMDGPUPropagateAttributes::setAttributes(Function &F, + const ArrayRef<Optional<Attribute>> NewAttrs) { + LLVM_DEBUG(dbgs() << "Set attributes on " << F.getName() << ":\n"); + for (unsigned I = 0; I < NumAttr; ++I) { + F.removeFnAttr(AttributeNames[I]); + if (NewAttrs[I]) { + LLVM_DEBUG(dbgs() << '\t' << NewAttrs[I]->getAsString() << '\n'); + F.addFnAttr(*NewAttrs[I]); + } + } +} + std::string AMDGPUPropagateAttributes::getFeatureString(const FeatureBitset &Features) const { |