diff --git a/llvm/docs/CodingStandards.rst b/llvm/docs/CodingStandards.rst --- a/llvm/docs/CodingStandards.rst +++ b/llvm/docs/CodingStandards.rst @@ -1302,6 +1302,8 @@ for (Instruction &I : *BB) ... use I ... +Usage of ``std::for_each()``/``llvm::for_each()`` functions is discouraged. + Don't evaluate ``end()`` every time through a loop ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/llvm/test/Reduce/remove-args.ll b/llvm/test/Reduce/remove-args.ll --- a/llvm/test/Reduce/remove-args.ll +++ b/llvm/test/Reduce/remove-args.ll @@ -1,6 +1,6 @@ ; Test that llvm-reduce can remove uninteresting function arguments from function definitions as well as their calls. ; -; RUN: rm -rf %t +; RUN: rm -f %t ; RUN: llvm-reduce --test %python --test-arg %p/Inputs/remove-args.py %s -o %t ; RUN: cat %t | FileCheck -implicit-check-not=uninteresting %s diff --git a/llvm/test/Reduce/remove-attributes-from-intrinsic-like-functions.ll b/llvm/test/Reduce/remove-attributes-from-intrinsic-like-functions.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Reduce/remove-attributes-from-intrinsic-like-functions.ll @@ -0,0 +1,41 @@ +; Just because a function is named like an intrinsic does not mean we should skip it's attributes. +; +; RUN: rm -f %t +; RUN: llvm-reduce --test FileCheck --test-arg --check-prefixes=CHECK-ALL,CHECK-INTERESTINGNESS --test-arg %s --test-arg --input-file %s -o %t +; RUN: cat %t | FileCheck --check-prefixes=CHECK-ALL,CHECK-FINAL %s + +; CHECK-ALL: declare i32 @llvm.not.really.an.intrinsic(i32, i32) #0 +declare i32 @llvm.not.really.an.intrinsic(i32, i32) #0 + +define i32 @t(i32 %a) { +; CHECK-ALL-LABEL: @t( + +; CHECK-INTERESTINGNESS: %r = +; CHECK-INTERESTINGNESS-SAME: call +; CHECK-INTERESTINGNESS-SAME: "arg0" +; CHECK-INTERESTINGNESS-SAME: i32 @llvm.not.really.an.intrinsic(i32 +; CHECK-INTERESTINGNESS-SAME: "arg3" +; CHECK-INTERESTINGNESS-SAME: %a +; CHECK-INTERESTINGNESS-SAME: i32 +; CHECK-INTERESTINGNESS-SAME: %a +; CHECK-INTERESTINGNESS-SAME: #1 + +; CHECK-FINAL: %r = call "arg0" i32 @llvm.not.really.an.intrinsic(i32 "arg3" %a, i32 %a) #1 +; CHECK-ALL: ret i32 %r + + %r = call "arg0" "arg1" i32 @llvm.not.really.an.intrinsic(i32 "arg2" "arg3" %a, i32 %a) "arg4" "arg5" + ret i32 %r +} + +; CHECK-INTERESTINGNESS: attributes #0 = { +; CHECK-INTERESTINGNESS-SAME: "arg6" + +; CHECK-INTERESTINGNESS: attributes #1 = { +; CHECK-INTERESTINGNESS-SAME: "arg4" + +; CHECK-FINAL: attributes #0 = { "arg6" } +; CHECK-FINAL: attributes #1 = { "arg4" } + +; CHECK-ALL-NOT: attributes # + +attributes #0 = { "arg6" "arg7" } diff --git a/llvm/test/Reduce/remove-attributes-from-intrinsics.ll b/llvm/test/Reduce/remove-attributes-from-intrinsics.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Reduce/remove-attributes-from-intrinsics.ll @@ -0,0 +1,39 @@ +; We can't actually put attributes on intrinsic declarations, only on call sites. +; +; RUN: rm -f %t +; RUN: llvm-reduce --test FileCheck --test-arg --check-prefixes=CHECK-ALL,CHECK-INTERESTINGNESS --test-arg %s --test-arg --input-file %s -o %t +; RUN: cat %t | FileCheck --check-prefixes=CHECK-ALL,CHECK-FINAL %s + +define i32 @t(i32 %a) { +; CHECK-ALL-LABEL: @t( + +; CHECK-INTERESTINGNESS: %r = +; CHECK-INTERESTINGNESS-SAME: call +; CHECK-INTERESTINGNESS-SAME: "arg0" +; CHECK-INTERESTINGNESS-SAME: i32 @llvm.uadd.sat.i32(i32 +; CHECK-INTERESTINGNESS-SAME: "arg3" +; CHECK-INTERESTINGNESS-SAME: %a +; CHECK-INTERESTINGNESS-SAME: i32 +; CHECK-INTERESTINGNESS-SAME: %a +; CHECK-INTERESTINGNESS-SAME: #1 + +; CHECK-FINAL: %r = call "arg0" i32 @llvm.uadd.sat.i32(i32 "arg3" %a, i32 %a) #1 +; CHECK-ALL: ret i32 %r + + %r = call "arg0" "arg1" i32 @llvm.uadd.sat.i32(i32 "arg2" "arg3" %a, i32 %a) "arg4" "arg5" + ret i32 %r +} + +; CHECK-ALL: declare i32 @llvm.uadd.sat.i32(i32, i32) #0 +declare i32 @llvm.uadd.sat.i32(i32, i32) #0 + +; CHECK-ALL: attributes #0 = { nounwind readnone speculatable willreturn } + +; CHECK-INTERESTINGNESS: attributes #1 = { +; CHECK-INTERESTINGNESS-SAME: "arg4" + +; CHECK-FINAL: attributes #1 = { "arg4" } + +; CHECK-ALL-NOT: attributes # + +attributes #0 = { "arg6" "arg7" } diff --git a/llvm/test/Reduce/remove-call-site-attributes.ll b/llvm/test/Reduce/remove-call-site-attributes.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Reduce/remove-call-site-attributes.ll @@ -0,0 +1,39 @@ +; Test that llvm-reduce can remove uninteresting operand bundles from calls. +; +; RUN: rm -f %t +; RUN: llvm-reduce --test FileCheck --test-arg --check-prefixes=CHECK-ALL,CHECK-INTERESTINGNESS --test-arg %s --test-arg --input-file %s -o %t +; RUN: cat %t | FileCheck --check-prefixes=CHECK-ALL,CHECK-FINAL %s + +; CHECK-ALL: declare i32 @f1(i32, i32) +declare i32 @f1(i32, i32) + +; CHECK-FINAL-LABEL: define i32 @interesting(i32 %arg0, i32 %arg1) { +; CHECK-FINAL-NEXT: entry: +; CHECK-FINAL-NEXT: %r = call "attr0" i32 @f1(i32 "attr4" %arg0, i32 %arg1) #0 +; CHECK-FINAL-NEXT: ret i32 %r +; CHECK-FINAL-NEXT: } +define i32 @interesting(i32 %arg0, i32 %arg1) { +entry: +; CHECK-INTERESTINGNESS-LABEL: @interesting( + +; CHECK-INTERESTINGNESS: %r = call +; CHECK-INTERESTINGNESS-SAME: "attr0" +; CHECK-INTERESTINGNESS-SAME: i32 @f1( +; CHECK-INTERESTINGNESS-SAME: i32 +; CHECK-INTERESTINGNESS-SAME: "attr4" +; CHECK-INTERESTINGNESS-SAME: %arg0 +; CHECK-INTERESTINGNESS-SAME: i32 +; CHECK-INTERESTINGNESS-SAME: %arg1 +; CHECK-INTERESTINGNESS-SAME: #0 +; CHECK-INTERESTINGNESS: ret i32 %r + + %r = call "attr0" "attr1" "attr2" i32 @f1(i32 "attr3" "attr4" "attr5" %arg0, i32 "attr6" "attr7" "attr8" %arg1) #0 + ret i32 %r +} + +; CHECK-INTERESTINGNESS: attributes #0 = { +; CHECK-INTERESTINGNESS-SAME: "attr10" + +; CHECK-FINAL: attributes #0 = { "attr10" } + +attributes #0 = { "attr9" "attr10" "attr11" } diff --git a/llvm/test/Reduce/remove-funcs.ll b/llvm/test/Reduce/remove-funcs.ll --- a/llvm/test/Reduce/remove-funcs.ll +++ b/llvm/test/Reduce/remove-funcs.ll @@ -1,7 +1,7 @@ ; Test that llvm-reduce can remove uninteresting functions as well as ; their InstCalls. ; -; RUN: rm -rf %t +; RUN: rm -f %t ; RUN: llvm-reduce --test %python --test-arg %p/Inputs/remove-funcs.py %s -o %t ; RUN: cat %t | FileCheck -implicit-check-not=uninteresting %s diff --git a/llvm/test/Reduce/remove-function-attributes.ll b/llvm/test/Reduce/remove-function-attributes.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Reduce/remove-function-attributes.ll @@ -0,0 +1,24 @@ +; Test that llvm-reduce can remove uninteresting attributes. +; +; RUN: rm -f %t +; RUN: llvm-reduce --test FileCheck --test-arg --check-prefixes=CHECK-ALL,CHECK-INTERESTINGNESS --test-arg %s --test-arg --input-file %s -o %t +; RUN: cat %t | FileCheck --check-prefixes=CHECK-ALL,CHECK-FINAL %s + +; CHECK-INTERESTINGNESS: declare +; CHECK-INTERESTINGNESS-SAME: "attr0" +; CHECK-INTERESTINGNESS-SAME: void @f0 +; CHECK-INTERESTINGNESS-SAME: i32 +; CHECK-INTERESTINGNESS-SAME: i32 +; CHECK-INTERESTINGNESS-SAME: "attr6" +; CHECK-INTERESTINGNESS-SAME: #0 + +; CHECK-FINAL: declare "attr0" void @f0(i32, i32 "attr6") #0 + +declare "attr0" "attr1" "attr2" void @f0(i32 "attr3" "attr4" "attr5", i32 "attr6" "attr7" "attr8") #0 + +; CHECK-INTERESTINGNESS: attributes #0 = { +; CHECK-INTERESTINGNESS-SAME: "attr10" + +; CHECK-FINAL: attributes #0 = { "attr10" } + +attributes #0 = { "attr9" "attr10" "attr11" } diff --git a/llvm/test/Reduce/remove-global-variable-attributes.ll b/llvm/test/Reduce/remove-global-variable-attributes.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Reduce/remove-global-variable-attributes.ll @@ -0,0 +1,28 @@ +; Test that llvm-reduce can remove uninteresting attributes. +; +; RUN: rm -f %t +; RUN: llvm-reduce --test FileCheck --test-arg --check-prefixes=CHECK-ALL,CHECK-INTERESTINGNESS --test-arg %s --test-arg --input-file %s -o %t +; RUN: cat %t | FileCheck --check-prefixes=CHECK-ALL,CHECK-FINAL %s + +; CHECK-ALL: @gv0 = global i32 0 #0 +; CHECK-ALL-NEXT: @gv1 = global i32 0 #1 +; CHECK-ALL-NEXT: @gv2 = global i32 0 +@gv0 = global i32 0 #0 +@gv1 = global i32 0 #1 +@gv2 = global i32 0 #2 + +; CHECK-INTERESTINGNESS: attributes #0 = { +; CHECK-INTERESTINGNESS-SAME: "attr0" +; CHECK-INTERESTINGNESS-SAME: "attr2" + +; CHECK-INTERESTINGNESS-NEXT: attributes #1 = { +; CHECK-INTERESTINGNESS-SAME: "attr4" + +; CHECK-FINAL: attributes #0 = { "attr0" "attr2" } +; CHECK-FINAL-NEXT: attributes #1 = { "attr4" } + +; CHECK-FINAL-NOT: attributes #2 + +attributes #0 = { "attr0" "attr1" "attr2"} +attributes #1 = { "attr3" "attr4" "attr5"} +attributes #2 = { "attr6" "attr7" "attr8"} diff --git a/llvm/test/Reduce/remove-global-vars.ll b/llvm/test/Reduce/remove-global-vars.ll --- a/llvm/test/Reduce/remove-global-vars.ll +++ b/llvm/test/Reduce/remove-global-vars.ll @@ -1,7 +1,7 @@ ; Test that llvm-reduce can remove uninteresting Global Variables as well as ; their direct uses (which in turn are replaced with 'undef'). ; -; RUN: rm -rf %t +; RUN: rm -f %t ; RUN: llvm-reduce --test %python --test-arg %p/Inputs/remove-global-vars.py %s -o %t ; RUN: cat %t | FileCheck -implicit-check-not=uninteresting %s diff --git a/llvm/test/Reduce/remove-metadata.ll b/llvm/test/Reduce/remove-metadata.ll --- a/llvm/test/Reduce/remove-metadata.ll +++ b/llvm/test/Reduce/remove-metadata.ll @@ -1,7 +1,7 @@ ; Test that llvm-reduce can remove uninteresting metadata from an IR file. ; The Metadata pass erases named & unnamed metadata nodes. ; -; RUN: rm -rf %t +; RUN: rm -f %t ; RUN: llvm-reduce --test %python --test-arg %p/Inputs/remove-metadata.py %s -o %t ; RUN: cat %t | FileCheck -implicit-check-not=! %s diff --git a/llvm/test/Reduce/remove-multiple-use-of-args-in-same-instruction.ll b/llvm/test/Reduce/remove-multiple-use-of-args-in-same-instruction.ll --- a/llvm/test/Reduce/remove-multiple-use-of-args-in-same-instruction.ll +++ b/llvm/test/Reduce/remove-multiple-use-of-args-in-same-instruction.ll @@ -1,6 +1,6 @@ ; Test that llvm-reduce can remove uninteresting function arguments from function definitions as well as their calls. ; -; RUN: rm -rf %t +; RUN: rm -f %t ; RUN: llvm-reduce --test %python --test-arg %p/Inputs/remove-multiple-use-of-args-in-same-instruction.py %s -o %t ; RUN: cat %t | FileCheck -implicit-check-not=uninteresting %s diff --git a/llvm/test/Reduce/remove-multiple-use-of-global-vars-in-same-instruction.ll b/llvm/test/Reduce/remove-multiple-use-of-global-vars-in-same-instruction.ll --- a/llvm/test/Reduce/remove-multiple-use-of-global-vars-in-same-instruction.ll +++ b/llvm/test/Reduce/remove-multiple-use-of-global-vars-in-same-instruction.ll @@ -1,6 +1,6 @@ ; Test that llvm-reduce can remove uninteresting function arguments from function definitions as well as their calls. ; -; RUN: rm -rf %t +; RUN: rm -f %t ; RUN: llvm-reduce --test %python --test-arg %p/Inputs/remove-multiple-use-of-global-vars-in-same-instruction.py %s -o %t ; RUN: cat %t | FileCheck -implicit-check-not=uninteresting %s diff --git a/llvm/test/Reduce/remove-operand-bundles.ll b/llvm/test/Reduce/remove-operand-bundles.ll --- a/llvm/test/Reduce/remove-operand-bundles.ll +++ b/llvm/test/Reduce/remove-operand-bundles.ll @@ -1,6 +1,6 @@ ; Test that llvm-reduce can remove uninteresting operand bundles from calls. ; -; RUN: rm -rf %t +; RUN: rm -f %t ; RUN: llvm-reduce --test FileCheck --test-arg --check-prefixes=CHECK-ALL,CHECK-INTERESTINGNESS --test-arg %s --test-arg --input-file %s -o %t ; RUN: cat %t | FileCheck --check-prefixes=CHECK-ALL,CHECK-FINAL %s diff --git a/llvm/tools/llvm-reduce/CMakeLists.txt b/llvm/tools/llvm-reduce/CMakeLists.txt --- a/llvm/tools/llvm-reduce/CMakeLists.txt +++ b/llvm/tools/llvm-reduce/CMakeLists.txt @@ -14,6 +14,7 @@ TestRunner.cpp deltas/Delta.cpp deltas/ReduceArguments.cpp + deltas/ReduceAttributes.cpp deltas/ReduceBasicBlocks.cpp deltas/ReduceFunctions.cpp deltas/ReduceGlobalVars.cpp diff --git a/llvm/tools/llvm-reduce/DeltaManager.h b/llvm/tools/llvm-reduce/DeltaManager.h --- a/llvm/tools/llvm-reduce/DeltaManager.h +++ b/llvm/tools/llvm-reduce/DeltaManager.h @@ -14,6 +14,7 @@ #include "TestRunner.h" #include "deltas/Delta.h" #include "deltas/ReduceArguments.h" +#include "deltas/ReduceAttributes.h" #include "deltas/ReduceBasicBlocks.h" #include "deltas/ReduceFunctions.h" #include "deltas/ReduceGlobalVars.h" @@ -32,6 +33,7 @@ reduceArgumentsDeltaPass(Tester); reduceInstructionsDeltaPass(Tester); reduceOperandBundesDeltaPass(Tester); + reduceAttributesDeltaPass(Tester); // TODO: Implement the remaining Delta Passes } diff --git a/llvm/tools/llvm-reduce/deltas/ReduceAttributes.h b/llvm/tools/llvm-reduce/deltas/ReduceAttributes.h new file mode 100644 --- /dev/null +++ b/llvm/tools/llvm-reduce/deltas/ReduceAttributes.h @@ -0,0 +1,20 @@ +//===- ReduceAttributes.h - Specialized Delta Pass ------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file implements a function which calls the Generic Delta pass in order +// to reduce uninteresting attributes. +// +//===----------------------------------------------------------------------===// + +namespace llvm { + +class TestRunner; + +void reduceAttributesDeltaPass(TestRunner &Test); + +} // namespace llvm diff --git a/llvm/tools/llvm-reduce/deltas/ReduceAttributes.cpp b/llvm/tools/llvm-reduce/deltas/ReduceAttributes.cpp new file mode 100644 --- /dev/null +++ b/llvm/tools/llvm-reduce/deltas/ReduceAttributes.cpp @@ -0,0 +1,200 @@ +//===- ReduceAttributes.cpp - Specialized Delta Pass -------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file implements a function which calls the Generic Delta pass in order +// to reduce uninteresting attributes. +// +//===----------------------------------------------------------------------===// + +#include "ReduceAttributes.h" +#include "Delta.h" +#include "TestRunner.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/Sequence.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/iterator_range.h" +#include "llvm/IR/Attributes.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/GlobalVariable.h" +#include "llvm/IR/InstVisitor.h" +#include "llvm/IR/InstrTypes.h" +#include "llvm/IR/Intrinsics.h" +#include "llvm/IR/Module.h" +#include "llvm/Support/raw_ostream.h" +#include +#include +#include +#include +#include + +namespace llvm { +class LLVMContext; +} // namespace llvm + +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; + +public: + DenseMap GlobalVariablesToRefine; + DenseMap FunctionsToRefine; + DenseMap CallsToRefine; + + explicit AttributeRemapper(ArrayRef ChunksToKeep) : O(ChunksToKeep) {} + + void visitModule(Module &M) { + for (GlobalVariable &GV : M.getGlobalList()) + 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]); + } + + 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]); + } + + void visitCallBase(CallBase &I) { + visitAttributeList(I.getAttributes(), CallsToRefine[&I]); + } + + void visitAttributeList(const AttributeList &AL, + AttrPtrVecVecTy &AttributeSetsToPreserve) { + assert(AttributeSetsToPreserve.empty() && "Should not be sharing vectors."); + AttributeSetsToPreserve.reserve(AL.getNumAttrSets()); + for (unsigned SetIdx : seq(AL.index_begin(), AL.index_end())) { + AttrPtrIdxVecVecTy AttributesToPreserve; + AttributesToPreserve.first = SetIdx; + visitAttributeSet(AL.getAttributes(AttributesToPreserve.first), + AttributesToPreserve.second); + if (!AttributesToPreserve.second.empty()) + AttributeSetsToPreserve.emplace_back(std::move(AttributesToPreserve)); + } + } + + void visitAttributeSet(const AttributeSet &AS, + AttrPtrVecTy &AttrsToPreserve) { + assert(AttrsToPreserve.empty() && "Should not be sharing vectors."); + AttrsToPreserve.reserve(AS.getNumAttributes()); + for (const Attribute &A : AS) + if (O.shouldKeep()) + AttrsToPreserve.emplace_back(&A); + } +}; + +struct AttributeCounter : public InstVisitor { + /// How many features (in this case, attributes) did we count, total? + int AttributeCount = 0; + + void visitModule(Module &M) { + for (GlobalVariable &GV : M.getGlobalList()) + visitGlobalVariable(GV); + } + + void visitGlobalVariable(GlobalVariable &GV) { + // Global variables only have one attribute set. + visitAttributeSet(GV.getAttributes()); + } + + void visitFunction(Function &F) { + if (F.getIntrinsicID() != Intrinsic::not_intrinsic) + return; // We can neither add nor remove attributes from intrinsics. + visitAttributeList(F.getAttributes()); + } + + void visitCallBase(CallBase &I) { visitAttributeList(I.getAttributes()); } + + void visitAttributeList(const AttributeList &AL) { + for (const AttributeSet &AS : AL) + visitAttributeSet(AS); + } + + void visitAttributeSet(const AttributeSet &AS) { + AttributeCount += AS.getNumAttributes(); + } +}; + +} // namespace + +AttributeSet +convertAttributeRefToAttributeSet(LLVMContext &C, + ArrayRef Attributes) { + AttrBuilder B; + for (const 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)); + }); + + sort(SetVec, [](const std::pair &LHS, + const std::pair &RHS) { + return LHS.first < RHS.first; // All values are unique. + }); + + return AttributeList::get(C, SetVec); +} + +/// Removes out-of-chunk attributes from module. +static void extractAttributesFromModule(std::vector ChunksToKeep, + Module *Program) { + AttributeRemapper R(ChunksToKeep); + 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)); +} + +/// Counts the amount of attributes. +static int countAttributes(Module *Program) { + AttributeCounter C; + + // TODO: Silence index with --quiet flag + outs() << "----------------------------\n"; + C.visit(Program); + outs() << "Number of attributes: " << C.AttributeCount << "\n"; + + return C.AttributeCount; +} + +void llvm::reduceAttributesDeltaPass(TestRunner &Test) { + outs() << "*** Reducing Attributes...\n"; + int AttributeCount = countAttributes(Test.getProgram()); + runDeltaPass(Test, AttributeCount, extractAttributesFromModule); +} diff --git a/llvm/tools/llvm-reduce/deltas/ReduceOperandBundles.cpp b/llvm/tools/llvm-reduce/deltas/ReduceOperandBundles.cpp --- a/llvm/tools/llvm-reduce/deltas/ReduceOperandBundles.cpp +++ b/llvm/tools/llvm-reduce/deltas/ReduceOperandBundles.cpp @@ -56,10 +56,9 @@ OperandBundlesToKeepIndexes.reserve(Call.getNumOperandBundles()); // Enumerate every operand bundle on this call. - for_each(seq(0U, Call.getNumOperandBundles()), [&](unsigned BundleIndex) { + for (unsigned BundleIndex : seq(0U, Call.getNumOperandBundles())) if (O.shouldKeep()) // Should we keep this one? OperandBundlesToKeepIndexes.emplace_back(BundleIndex); - }); } }; @@ -67,8 +66,6 @@ /// How many features (in this case, operand bundles) did we count, total? int OperandBundeCount = 0; - OperandBundleCounter() {} - /// So far only CallBase sub-classes can have operand bundles. void visitCallBase(CallBase &Call) { // Just accumulate the total number of operand bundles. @@ -104,9 +101,8 @@ OperandBundleRemapper R(ChunksToKeep); R.visit(Program); - for_each(R.CallsToRefine, [](const auto &P) { - return maybeRewriteCallWithDifferentBundles(P.first, P.second); - }); + for (const auto &I : R.CallsToRefine) + maybeRewriteCallWithDifferentBundles(I.first, I.second); } /// Counts the amount of operand bundles. diff --git a/llvm/utils/gn/secondary/llvm/tools/llvm-reduce/BUILD.gn b/llvm/utils/gn/secondary/llvm/tools/llvm-reduce/BUILD.gn --- a/llvm/utils/gn/secondary/llvm/tools/llvm-reduce/BUILD.gn +++ b/llvm/utils/gn/secondary/llvm/tools/llvm-reduce/BUILD.gn @@ -12,6 +12,7 @@ "TestRunner.cpp", "deltas/Delta.cpp", "deltas/ReduceArguments.cpp", + "deltas/ReduceAttributes.cpp", "deltas/ReduceBasicBlocks.cpp", "deltas/ReduceFunctions.cpp", "deltas/ReduceGlobalVars.cpp",