xref: /llvm-project/llvm/tools/llvm-reduce/deltas/ReduceOperandBundles.cpp (revision 2b1122eaec0d0b335feeac4adfaab2e3e04b7bd9)
1 //===- ReduceOperandBundes.cpp - Specialized Delta Pass -------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file implements a function which calls the Generic Delta pass in order
10 // to reduce uninteresting operand bundes from calls.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "ReduceOperandBundles.h"
15 #include "Delta.h"
16 #include "TestRunner.h"
17 #include "llvm/ADT/ArrayRef.h"
18 #include "llvm/ADT/DenseMap.h"
19 #include "llvm/ADT/STLExtras.h"
20 #include "llvm/ADT/Sequence.h"
21 #include "llvm/IR/InstVisitor.h"
22 #include "llvm/IR/InstrTypes.h"
23 #include "llvm/Support/raw_ostream.h"
24 #include <algorithm>
25 #include <iterator>
26 #include <vector>
27 
28 namespace llvm {
29 class Module;
30 } // namespace llvm
31 
32 using namespace llvm;
33 
34 namespace {
35 
36 /// Given ChunksToKeep, produce a map of calls and indexes of operand bundles
37 /// to be preserved for each call.
38 class OperandBundleRemapper : public InstVisitor<OperandBundleRemapper> {
39   Oracle &O;
40 
41 public:
42   DenseMap<CallBase *, std::vector<unsigned>> CallsToRefine;
43 
44   explicit OperandBundleRemapper(Oracle &O) : O(O) {}
45 
46   /// So far only CallBase sub-classes can have operand bundles.
47   /// Let's see which of the operand bundles of this call are to be kept.
48   void visitCallBase(CallBase &Call) {
49     if (!Call.hasOperandBundles())
50       return; // No bundles to begin with.
51 
52     // Insert this call into map, we will likely want to rebuild it.
53     auto &OperandBundlesToKeepIndexes = CallsToRefine[&Call];
54     OperandBundlesToKeepIndexes.reserve(Call.getNumOperandBundles());
55 
56     // Enumerate every operand bundle on this call.
57     for (unsigned BundleIndex : seq(Call.getNumOperandBundles()))
58       if (O.shouldKeep()) // Should we keep this one?
59         OperandBundlesToKeepIndexes.emplace_back(BundleIndex);
60   }
61 };
62 
63 struct OperandBundleCounter : public InstVisitor<OperandBundleCounter> {
64   /// How many features (in this case, operand bundles) did we count, total?
65   int OperandBundeCount = 0;
66 
67   /// So far only CallBase sub-classes can have operand bundles.
68   void visitCallBase(CallBase &Call) {
69     // Just accumulate the total number of operand bundles.
70     OperandBundeCount += Call.getNumOperandBundles();
71   }
72 };
73 
74 } // namespace
75 
76 static void maybeRewriteCallWithDifferentBundles(
77     CallBase *OrigCall, ArrayRef<unsigned> OperandBundlesToKeepIndexes) {
78   if (OperandBundlesToKeepIndexes.size() == OrigCall->getNumOperandBundles())
79     return; // Not modifying operand bundles of this call after all.
80 
81   std::vector<OperandBundleDef> NewBundles;
82   NewBundles.reserve(OperandBundlesToKeepIndexes.size());
83 
84   // Actually copy over the bundles that we want to keep.
85   transform(OperandBundlesToKeepIndexes, std::back_inserter(NewBundles),
86             [OrigCall](unsigned Index) {
87               return OperandBundleDef(OrigCall->getOperandBundleAt(Index));
88             });
89 
90   // Finally actually replace the bundles on the call.
91   CallBase *NewCall =
92       CallBase::Create(OrigCall, NewBundles, OrigCall->getIterator());
93   OrigCall->replaceAllUsesWith(NewCall);
94   OrigCall->eraseFromParent();
95 }
96 
97 /// Removes out-of-chunk operand bundles from calls.
98 static void extractOperandBundesFromModule(Oracle &O,
99                                            ReducerWorkItem &WorkItem) {
100   Module &Program = WorkItem.getModule();
101   OperandBundleRemapper R(O);
102   R.visit(Program);
103 
104   for (const auto &I : R.CallsToRefine)
105     maybeRewriteCallWithDifferentBundles(I.first, I.second);
106 }
107 
108 void llvm::reduceOperandBundesDeltaPass(TestRunner &Test) {
109   runDeltaPass(Test, extractOperandBundesFromModule,
110                "Reducing Operand Bundles");
111 }
112