[llvm] 05f2b5c - [llvm-reduce] Reducing call operand bundles
Roman Lebedev via llvm-commits
llvm-commits at lists.llvm.org
Mon Jul 6 15:18:17 PDT 2020
Author: Roman Lebedev
Date: 2020-07-07T01:16:37+03:00
New Revision: 05f2b5ccfc5d8b1f182b00fc80dfbe804fd0357a
URL: https://github.com/llvm/llvm-project/commit/05f2b5ccfc5d8b1f182b00fc80dfbe804fd0357a
DIFF: https://github.com/llvm/llvm-project/commit/05f2b5ccfc5d8b1f182b00fc80dfbe804fd0357a.diff
LOG: [llvm-reduce] Reducing call operand bundles
Summary:
This would have been marginally useful to me during/for rG7ea46aee3670981827c04df89b2c3a1cbdc7561b.
With ongoing migration to representing assumes via operand bundles on the assume, this will be gradually more useful.
Reviewers: nickdesaulniers, diegotf, dblaikie, george.burgess.iv, jdoerfert, Tyker
Reviewed By: nickdesaulniers
Subscribers: hiraditya, mgorny, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D83177
Added:
llvm/test/Reduce/remove-operand-bundles.ll
llvm/tools/llvm-reduce/deltas/ReduceOperandBundles.cpp
llvm/tools/llvm-reduce/deltas/ReduceOperandBundles.h
Modified:
llvm/tools/llvm-reduce/CMakeLists.txt
llvm/tools/llvm-reduce/DeltaManager.h
llvm/utils/gn/secondary/llvm/tools/llvm-reduce/BUILD.gn
Removed:
################################################################################
diff --git a/llvm/test/Reduce/remove-operand-bundles.ll b/llvm/test/Reduce/remove-operand-bundles.ll
new file mode 100644
index 000000000000..39c0af6c9ae5
--- /dev/null
+++ b/llvm/test/Reduce/remove-operand-bundles.ll
@@ -0,0 +1,41 @@
+; Test that llvm-reduce can remove uninteresting operand bundles from calls.
+;
+; RUN: rm -rf %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 void @f1()
+; CHECK-ALL: declare void @f2()
+; CHECK-ALL: declare void @f3()
+declare void @f1()
+declare void @f2()
+declare void @f3()
+
+; CHECK-FINAL-LABEL: define void @interesting(i32 %arg0, i32 %arg1, i32 %arg2) {
+; CHECK-FINAL-NEXT: entry:
+; CHECK-FINAL-NEXT: call void @f1() [ "bundle0"(), "align"(i32 %arg0), "whatever0"() ]
+; CHECK-FINAL-NEXT: call void @f2()
+; CHECK-FINAL-NEXT: call void @f3() [ "align"(i32 %arg2) ]
+; CHECK-FINAL-NEXT: ret void
+; CHECK-FINAL-NEXT: }
+define void @interesting(i32 %arg0, i32 %arg1, i32 %arg2) {
+entry:
+; CHECK-INTERESTINGNESS-LABEL: @interesting(
+
+; CHECK-INTERESTINGNESS: call void @f1()
+; CHECK-INTERESTINGNESS: "bundle0"()
+; CHECK-INTERESTINGNESS: "align"(i32 %arg0)
+; CHECK-INTERESTINGNESS: "whatever0"()
+
+; CHECK-INTERESTINGNESS: call void @f2()
+
+; CHECK-INTERESTINGNESS: call void @f3()
+; CHECK-INTERESTINGNESS: "align"(i32 %arg2)
+
+; CHECK-INTERESTINGNESS: ret
+
+ call void @f1() [ "bundle0"(), "align"(i32 %arg0), "whatever0"() ]
+ call void @f2() [ "align"(i32 %arg1), "whatever1"(), "bundle1"() ]
+ call void @f3() [ "whatever2"(), "bundle2"(), "align"(i32 %arg2) ]
+ ret void
+}
diff --git a/llvm/tools/llvm-reduce/CMakeLists.txt b/llvm/tools/llvm-reduce/CMakeLists.txt
index 48de0ffa78a1..24eedac613f5 100644
--- a/llvm/tools/llvm-reduce/CMakeLists.txt
+++ b/llvm/tools/llvm-reduce/CMakeLists.txt
@@ -11,15 +11,16 @@ set(LLVM_LINK_COMPONENTS
)
add_llvm_tool(llvm-reduce
- llvm-reduce.cpp
TestRunner.cpp
deltas/Delta.cpp
- deltas/ReduceFunctions.cpp
- deltas/ReduceGlobalVars.cpp
- deltas/ReduceMetadata.cpp
deltas/ReduceArguments.cpp
deltas/ReduceBasicBlocks.cpp
+ deltas/ReduceFunctions.cpp
+ deltas/ReduceGlobalVars.cpp
deltas/ReduceInstructions.cpp
+ deltas/ReduceMetadata.cpp
+ deltas/ReduceOperandBundles.cpp
+ llvm-reduce.cpp
DEPENDS
intrinsics_gen
diff --git a/llvm/tools/llvm-reduce/DeltaManager.h b/llvm/tools/llvm-reduce/DeltaManager.h
index 2309c3adf4e6..5635352b43d8 100644
--- a/llvm/tools/llvm-reduce/DeltaManager.h
+++ b/llvm/tools/llvm-reduce/DeltaManager.h
@@ -17,8 +17,9 @@
#include "deltas/ReduceBasicBlocks.h"
#include "deltas/ReduceFunctions.h"
#include "deltas/ReduceGlobalVars.h"
-#include "deltas/ReduceMetadata.h"
#include "deltas/ReduceInstructions.h"
+#include "deltas/ReduceMetadata.h"
+#include "deltas/ReduceOperandBundles.h"
namespace llvm {
@@ -30,6 +31,7 @@ inline void runDeltaPasses(TestRunner &Tester) {
reduceMetadataDeltaPass(Tester);
reduceArgumentsDeltaPass(Tester);
reduceInstructionsDeltaPass(Tester);
+ reduceOperandBundesDeltaPass(Tester);
// TODO: Implement the remaining Delta Passes
}
diff --git a/llvm/tools/llvm-reduce/deltas/ReduceOperandBundles.cpp b/llvm/tools/llvm-reduce/deltas/ReduceOperandBundles.cpp
new file mode 100644
index 000000000000..c6de6e9d567c
--- /dev/null
+++ b/llvm/tools/llvm-reduce/deltas/ReduceOperandBundles.cpp
@@ -0,0 +1,161 @@
+//===- ReduceOperandBundes.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 operand bundes from calls.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ReduceOperandBundles.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/ScopeExit.h"
+#include "llvm/ADT/Sequence.h"
+#include "llvm/ADT/iterator_range.h"
+#include "llvm/IR/InstVisitor.h"
+#include "llvm/IR/InstrTypes.h"
+#include "llvm/Support/raw_ostream.h"
+#include <algorithm>
+#include <iterator>
+#include <vector>
+
+namespace {
+class Module;
+} // namespace
+
+using namespace llvm;
+
+namespace {
+
+/// Provides opaque interface for querying into ChunksToKeep without having to
+/// actually understand what is going on.
+struct Oracle {
+ /// Out of all the features that we promised to be,
+ /// how many have we already processed? 1-based!
+ int Index = 1;
+
+ /// The actual workhorse, contains the knowledge whether or not
+ /// some particular feature should be preserved this time.
+ ArrayRef<Chunk> ChunksToKeep;
+
+public:
+ Oracle(ArrayRef<Chunk> ChunksToKeep_) : ChunksToKeep(ChunksToKeep_) {}
+
+ /// Should be called for each feature on which we are operating.
+ /// Name is self-explanatory - if returns true, then it should be preserved.
+ bool shouldKeep() {
+ if (ChunksToKeep.empty())
+ return false; // All further features are to be discarded.
+
+ // Does the current (front) chunk contain such a feature?
+ bool ShouldKeep = ChunksToKeep.front().contains(Index);
+ auto _ = make_scope_exit([&]() { ++Index; }); // Next time - next feature.
+
+ // Is this the last feature in the chunk?
+ if (ChunksToKeep.front().end == Index)
+ ChunksToKeep = ChunksToKeep.drop_front(); // Onto next chunk.
+
+ return ShouldKeep;
+ }
+};
+
+/// Given ChunksToKeep, produce a map of calls and indexes of operand bundles
+/// to be preserved for each call.
+class OperandBundleRemapper : public InstVisitor<OperandBundleRemapper> {
+ Oracle O;
+
+public:
+ DenseMap<CallBase *, std::vector<unsigned>> CallsToRefine;
+
+ explicit OperandBundleRemapper(ArrayRef<Chunk> ChunksToKeep)
+ : O(ChunksToKeep) {}
+
+ /// So far only CallBase sub-classes can have operand bundles.
+ /// Let's see which of the operand bundles of this call are to be kept.
+ void visitCallBase(CallBase &Call) {
+ if (!Call.hasOperandBundles())
+ return; // No bundles to begin with.
+
+ // Insert this call into map, we will likely want to rebuild it.
+ auto &OperandBundlesToKeepIndexes = CallsToRefine[&Call];
+ OperandBundlesToKeepIndexes.reserve(Call.getNumOperandBundles());
+
+ // Enumerate every operand bundle on this call.
+ for_each(seq(0U, Call.getNumOperandBundles()), [&](unsigned BundleIndex) {
+ if (O.shouldKeep()) // Should we keep this one?
+ OperandBundlesToKeepIndexes.emplace_back(BundleIndex);
+ });
+ }
+};
+
+struct OperandBundleCounter : public InstVisitor<OperandBundleCounter> {
+ /// 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.
+ OperandBundeCount += Call.getNumOperandBundles();
+ }
+};
+
+} // namespace
+
+static void maybeRewriteCallWithDifferentBundles(
+ CallBase *OrigCall, ArrayRef<unsigned> OperandBundlesToKeepIndexes) {
+ if (OperandBundlesToKeepIndexes.size() == OrigCall->getNumOperandBundles())
+ return; // Not modifying operand bundles of this call after all.
+
+ std::vector<OperandBundleDef> NewBundles;
+ NewBundles.reserve(OperandBundlesToKeepIndexes.size());
+
+ // Actually copy over the bundles that we want to keep.
+ transform(OperandBundlesToKeepIndexes, std::back_inserter(NewBundles),
+ [OrigCall](unsigned Index) {
+ return OperandBundleDef(OrigCall->getOperandBundleAt(Index));
+ });
+
+ // Finally actually replace the bundles on the call.
+ CallBase *NewCall = CallBase::Create(OrigCall, NewBundles, OrigCall);
+ OrigCall->replaceAllUsesWith(NewCall);
+ OrigCall->eraseFromParent();
+}
+
+/// Removes out-of-chunk operand bundles from calls.
+static void extractOperandBundesFromModule(std::vector<Chunk> ChunksToKeep,
+ Module *Program) {
+ OperandBundleRemapper R(ChunksToKeep);
+ R.visit(Program);
+
+ for_each(R.CallsToRefine, [](const auto &P) {
+ return maybeRewriteCallWithDifferentBundles(P.first, P.second);
+ });
+}
+
+/// Counts the amount of operand bundles.
+static int countOperandBundes(Module *Program) {
+ OperandBundleCounter C;
+
+ // TODO: Silence index with --quiet flag
+ outs() << "----------------------------\n";
+ C.visit(Program);
+ outs() << "Number of operand bundles: " << C.OperandBundeCount << "\n";
+
+ return C.OperandBundeCount;
+}
+
+void llvm::reduceOperandBundesDeltaPass(TestRunner &Test) {
+ outs() << "*** Reducing OperandBundes...\n";
+ int OperandBundeCount = countOperandBundes(Test.getProgram());
+ runDeltaPass(Test, OperandBundeCount, extractOperandBundesFromModule);
+}
diff --git a/llvm/tools/llvm-reduce/deltas/ReduceOperandBundles.h b/llvm/tools/llvm-reduce/deltas/ReduceOperandBundles.h
new file mode 100644
index 000000000000..382c5cb5691d
--- /dev/null
+++ b/llvm/tools/llvm-reduce/deltas/ReduceOperandBundles.h
@@ -0,0 +1,20 @@
+//===- ReduceOperandBundes.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 operand bundes from calls.
+//
+//===----------------------------------------------------------------------===//
+
+namespace llvm {
+
+class TestRunner;
+
+void reduceOperandBundesDeltaPass(TestRunner &Test);
+
+} // namespace llvm
diff --git a/llvm/utils/gn/secondary/llvm/tools/llvm-reduce/BUILD.gn b/llvm/utils/gn/secondary/llvm/tools/llvm-reduce/BUILD.gn
index efa80c1b86d8..34e99f4fe32a 100644
--- a/llvm/utils/gn/secondary/llvm/tools/llvm-reduce/BUILD.gn
+++ b/llvm/utils/gn/secondary/llvm/tools/llvm-reduce/BUILD.gn
@@ -17,6 +17,7 @@ executable("llvm-reduce") {
"deltas/ReduceGlobalVars.cpp",
"deltas/ReduceInstructions.cpp",
"deltas/ReduceMetadata.cpp",
+ "deltas/ReduceOperandBundes.cpp",
"llvm-reduce.cpp",
]
}
More information about the llvm-commits
mailing list