1 //===- ReduceOperandBundes.cpp - Specialized Delta Pass -------------------===//
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
7 //===----------------------------------------------------------------------===//
9 // This file implements a function which calls the Generic Delta pass in order
10 // to reduce uninteresting operand bundes from calls.
12 //===----------------------------------------------------------------------===//
14 #include "ReduceOperandBundles.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/ADT/iterator_range.h"
22 #include "llvm/IR/InstVisitor.h"
23 #include "llvm/IR/InstrTypes.h"
24 #include "llvm/Support/raw_ostream.h"
37 /// Given ChunksToKeep, produce a map of calls and indexes of operand bundles
38 /// to be preserved for each call.
39 class OperandBundleRemapper
: public InstVisitor
<OperandBundleRemapper
> {
43 DenseMap
<CallBase
*, std::vector
<unsigned>> CallsToRefine
;
45 explicit OperandBundleRemapper(Oracle
&O
) : O(O
) {}
47 /// So far only CallBase sub-classes can have operand bundles.
48 /// Let's see which of the operand bundles of this call are to be kept.
49 void visitCallBase(CallBase
&Call
) {
50 if (!Call
.hasOperandBundles())
51 return; // No bundles to begin with.
53 // Insert this call into map, we will likely want to rebuild it.
54 auto &OperandBundlesToKeepIndexes
= CallsToRefine
[&Call
];
55 OperandBundlesToKeepIndexes
.reserve(Call
.getNumOperandBundles());
57 // Enumerate every operand bundle on this call.
58 for (unsigned BundleIndex
: seq(0U, Call
.getNumOperandBundles()))
59 if (O
.shouldKeep()) // Should we keep this one?
60 OperandBundlesToKeepIndexes
.emplace_back(BundleIndex
);
64 struct OperandBundleCounter
: public InstVisitor
<OperandBundleCounter
> {
65 /// How many features (in this case, operand bundles) did we count, total?
66 int OperandBundeCount
= 0;
68 /// So far only CallBase sub-classes can have operand bundles.
69 void visitCallBase(CallBase
&Call
) {
70 // Just accumulate the total number of operand bundles.
71 OperandBundeCount
+= Call
.getNumOperandBundles();
77 static void maybeRewriteCallWithDifferentBundles(
78 CallBase
*OrigCall
, ArrayRef
<unsigned> OperandBundlesToKeepIndexes
) {
79 if (OperandBundlesToKeepIndexes
.size() == OrigCall
->getNumOperandBundles())
80 return; // Not modifying operand bundles of this call after all.
82 std::vector
<OperandBundleDef
> NewBundles
;
83 NewBundles
.reserve(OperandBundlesToKeepIndexes
.size());
85 // Actually copy over the bundles that we want to keep.
86 transform(OperandBundlesToKeepIndexes
, std::back_inserter(NewBundles
),
87 [OrigCall
](unsigned Index
) {
88 return OperandBundleDef(OrigCall
->getOperandBundleAt(Index
));
91 // Finally actually replace the bundles on the call.
92 CallBase
*NewCall
= CallBase::Create(OrigCall
, NewBundles
, OrigCall
);
93 OrigCall
->replaceAllUsesWith(NewCall
);
94 OrigCall
->eraseFromParent();
97 /// Removes out-of-chunk operand bundles from calls.
98 static void extractOperandBundesFromModule(Oracle
&O
, Module
&Program
) {
99 OperandBundleRemapper
R(O
);
102 for (const auto &I
: R
.CallsToRefine
)
103 maybeRewriteCallWithDifferentBundles(I
.first
, I
.second
);
106 void llvm::reduceOperandBundesDeltaPass(TestRunner
&Test
) {
107 outs() << "*** Reducing OperandBundes...\n";
108 runDeltaPass(Test
, extractOperandBundesFromModule
);