[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