From b44cd97241643dedfb300d1afcd5a3a51bc1eab5 Mon Sep 17 00:00:00 2001 From: Matt Arsenault Date: Mon, 2 Jan 2023 13:33:17 -0500 Subject: [PATCH] llvm-reduce: Simplify attribute reduction implementation There's no need to construct a map of attributes to modify throughout the whole function before applying them all at once. The attribute classes already have the necessary set behavior. --- llvm/tools/llvm-reduce/deltas/ReduceAttributes.cpp | 119 +++++++++------------ 1 file changed, 48 insertions(+), 71 deletions(-) diff --git a/llvm/tools/llvm-reduce/deltas/ReduceAttributes.cpp b/llvm/tools/llvm-reduce/deltas/ReduceAttributes.cpp index 0bd16ff..036f0fb 100644 --- a/llvm/tools/llvm-reduce/deltas/ReduceAttributes.cpp +++ b/llvm/tools/llvm-reduce/deltas/ReduceAttributes.cpp @@ -42,65 +42,74 @@ using namespace llvm; namespace { -using AttrPtrVecTy = std::vector; -using AttrPtrIdxVecVecTy = std::pair; -using AttrPtrVecVecTy = SmallVector; - /// Given ChunksToKeep, produce a map of global variables/functions/calls /// and indexes of attributes to be preserved for each of them. class AttributeRemapper : public InstVisitor { Oracle &O; + LLVMContext &Context; public: - DenseMap GlobalVariablesToRefine; - DenseMap FunctionsToRefine; - DenseMap CallsToRefine; - - explicit AttributeRemapper(Oracle &O) : O(O) {} + AttributeRemapper(Oracle &O, LLVMContext &C) : O(O), Context(C) {} void visitModule(Module &M) { - for (GlobalVariable &GV : M.getGlobalList()) + for (GlobalVariable &GV : M.globals()) visitGlobalVariable(GV); } void visitGlobalVariable(GlobalVariable &GV) { // Global variables only have one attribute set. - const AttributeSet &AS = GV.getAttributes(); - if (AS.hasAttributes()) - visitAttributeSet(AS, GlobalVariablesToRefine[&GV]); + AttributeSet AS = GV.getAttributes(); + if (AS.hasAttributes()) { + AttrBuilder AttrsToPreserve(Context); + visitAttributeSet(AS, AttrsToPreserve); + GV.setAttributes(AttributeSet::get(Context, AttrsToPreserve)); + } } void visitFunction(Function &F) { - if (F.getIntrinsicID() != Intrinsic::not_intrinsic) - return; // We can neither add nor remove attributes from intrinsics. - visitAttributeList(F.getAttributes(), FunctionsToRefine[&F]); + // We can neither add nor remove attributes from intrinsics. + if (F.getIntrinsicID() == Intrinsic::not_intrinsic) + F.setAttributes(visitAttributeList(F.getAttributes())); + } + + void visitCallBase(CallBase &CB) { + CB.setAttributes(visitAttributeList(CB.getAttributes())); } - void visitCallBase(CallBase &I) { - visitAttributeList(I.getAttributes(), CallsToRefine[&I]); + AttributeSet visitAttributeIndex(AttributeList AL, unsigned Index) { + AttrBuilder AttributesToPreserve(Context); + visitAttributeSet(AL.getAttributes(Index), AttributesToPreserve); + + if (AttributesToPreserve.attrs().empty()) + return {}; + return AttributeSet::get(Context, AttributesToPreserve); } - void visitAttributeList(const AttributeList &AL, - AttrPtrVecVecTy &AttributeSetsToPreserve) { - assert(AttributeSetsToPreserve.empty() && "Should not be sharing vectors."); - AttributeSetsToPreserve.reserve(AL.getNumAttrSets()); + AttributeList visitAttributeList(AttributeList AL) { + SmallVector> NewAttrList; + NewAttrList.reserve(AL.getNumAttrSets()); + for (unsigned SetIdx : AL.indexes()) { - AttrPtrIdxVecVecTy AttributesToPreserve; - AttributesToPreserve.first = SetIdx; - visitAttributeSet(AL.getAttributes(AttributesToPreserve.first), - AttributesToPreserve.second); - if (!AttributesToPreserve.second.empty()) - AttributeSetsToPreserve.emplace_back(std::move(AttributesToPreserve)); + if (SetIdx == AttributeList::FunctionIndex) + continue; + + AttributeSet AttrSet = visitAttributeIndex(AL, SetIdx); + if (AttrSet.hasAttributes()) + NewAttrList.emplace_back(SetIdx, AttrSet); } - } - // FIXME: Should just directly use AttrBuilder instead of going through - // AttrPtrVecTy - void visitAttributeSet(const AttributeSet &AS, - AttrPtrVecTy &AttrsToPreserve) { - assert(AttrsToPreserve.empty() && "Should not be sharing vectors."); - AttrsToPreserve.reserve(AS.getNumAttributes()); + // FIXME: It's ridiculous that indexes() doesn't give us the correct order + // for contructing a new AttributeList. Special case the function index so + // we don't have to sort. + AttributeSet FnAttrSet = + visitAttributeIndex(AL, AttributeList::FunctionIndex); + if (FnAttrSet.hasAttributes()) + NewAttrList.emplace_back(AttributeList::FunctionIndex, FnAttrSet); + return AttributeList::get(Context, NewAttrList); + } + + void visitAttributeSet(const AttributeSet &AS, AttrBuilder &AttrsToPreserve) { // Optnone requires noinline, so removing noinline requires removing the // pair. Attribute NoInline = AS.getAttribute(Attribute::NoInline); @@ -108,7 +117,7 @@ public: if (NoInline.isValid()) { RemoveNoInline = !O.shouldKeep(); if (!RemoveNoInline) - AttrsToPreserve.emplace_back(NoInline); + AttrsToPreserve.addAttribute(NoInline); } for (Attribute A : AS) { @@ -123,55 +132,23 @@ public: // TODO: Could only remove this if there are no constrained calls in the // function. if (Kind == Attribute::StrictFP) { - AttrsToPreserve.emplace_back(A); + AttrsToPreserve.addAttribute(A); continue; } } if (O.shouldKeep()) - AttrsToPreserve.emplace_back(A); + AttrsToPreserve.addAttribute(A); } } }; } // namespace -AttributeSet convertAttributeRefToAttributeSet(LLVMContext &C, - ArrayRef Attributes) { - AttrBuilder B(C); - for (Attribute A : Attributes) - B.addAttribute(A); - return AttributeSet::get(C, B); -} - -AttributeList convertAttributeRefVecToAttributeList( - LLVMContext &C, ArrayRef AttributeSets) { - std::vector> SetVec; - SetVec.reserve(AttributeSets.size()); - - transform(AttributeSets, std::back_inserter(SetVec), - [&C](const AttrPtrIdxVecVecTy &V) { - return std::make_pair( - V.first, convertAttributeRefToAttributeSet(C, V.second)); - }); - - llvm::sort(SetVec, llvm::less_first()); // All values are unique. - - return AttributeList::get(C, SetVec); -} - /// Removes out-of-chunk attributes from module. static void extractAttributesFromModule(Oracle &O, Module &Program) { - AttributeRemapper R(O); + AttributeRemapper R(O, Program.getContext()); R.visit(Program); - - LLVMContext &C = Program.getContext(); - for (const auto &I : R.GlobalVariablesToRefine) - I.first->setAttributes(convertAttributeRefToAttributeSet(C, I.second)); - for (const auto &I : R.FunctionsToRefine) - I.first->setAttributes(convertAttributeRefVecToAttributeList(C, I.second)); - for (const auto &I : R.CallsToRefine) - I.first->setAttributes(convertAttributeRefVecToAttributeList(C, I.second)); } void llvm::reduceAttributesDeltaPass(TestRunner &Test) { -- 2.7.4