12
12
// ===----------------------------------------------------------------------===//
13
13
14
14
#include " llvm/Transforms/Utils/CodeMoverUtils.h"
15
+ #include " llvm/ADT/Optional.h"
15
16
#include " llvm/ADT/Statistic.h"
16
17
#include " llvm/Analysis/DependenceAnalysis.h"
18
+ #include " llvm/Analysis/OrderedInstructions.h"
17
19
#include " llvm/Analysis/PostDominators.h"
18
20
#include " llvm/Analysis/ValueTracking.h"
19
21
#include " llvm/IR/Dominators.h"
@@ -30,6 +32,189 @@ STATISTIC(NotControlFlowEquivalent,
30
32
STATISTIC (NotMovedPHINode, " Movement of PHINodes are not supported" );
31
33
STATISTIC (NotMovedTerminator, " Movement of Terminator are not supported" );
32
34
35
+ namespace {
36
+ // / Represent a control condition. A control condition is a condition of a
37
+ // / terminator to decide which successors to execute. The pointer field
38
+ // / represents the address of the condition of the terminator. The integer field
39
+ // / is a bool, it is true when the basic block is executed when V is true. For
40
+ // / example, `br %cond, bb0, bb1` %cond is a control condition of bb0 with the
41
+ // / integer field equals to true, while %cond is a control condition of bb1 with
42
+ // / the integer field equals to false.
43
+ using ControlCondition = PointerIntPair<Value *, 1 , bool >;
44
+ #ifndef NDEBUG
45
+ raw_ostream &operator <<(raw_ostream &OS, const ControlCondition &C) {
46
+ OS << " [" << *C.getPointer () << " , " << (C.getInt () ? " true" : " false" )
47
+ << " ]" ;
48
+ return OS;
49
+ }
50
+ #endif
51
+
52
+ // / Represent a set of control conditions required to execute ToBB from FromBB.
53
+ class ControlConditions {
54
+ using ConditionVectorTy = SmallVector<ControlCondition, 6 >;
55
+
56
+ // / A SmallVector of control conditions.
57
+ ConditionVectorTy Conditions;
58
+
59
+ public:
60
+ // / Return a ControlConditions which stores all conditions required to execute
61
+ // / \p BB from \p Dominator. If \p MaxLookup is non-zero, it limits the
62
+ // / number of conditions to collect. Return None if not all conditions are
63
+ // / collected successfully, or we hit the limit.
64
+ static Optional<const ControlConditions>
65
+ collectControlConditions (const BasicBlock &BB, const BasicBlock &Dominator,
66
+ const DominatorTree &DT,
67
+ const PostDominatorTree &PDT,
68
+ unsigned MaxLookup = 6 );
69
+
70
+ // / Return true if there exists no control conditions required to execute ToBB
71
+ // / from FromBB.
72
+ bool isUnconditional () const { return Conditions.empty (); }
73
+
74
+ // / Return a constant reference of Conditions.
75
+ const ConditionVectorTy &getControlConditions () const { return Conditions; }
76
+
77
+ // / Add \p V as one of the ControlCondition in Condition with IsTrueCondition
78
+ // / equals to \p True. Return true if inserted successfully.
79
+ bool addControlCondition (ControlCondition C);
80
+
81
+ // / Return true if for all control conditions in Conditions, there exists an
82
+ // / equivalent control condition in \p Other.Conditions.
83
+ bool isEquivalent (const ControlConditions &Other) const ;
84
+
85
+ // / Return true if \p C1 and \p C2 are equivalent.
86
+ static bool isEquivalent (const ControlCondition &C1,
87
+ const ControlCondition &C2);
88
+
89
+ private:
90
+ ControlConditions () = default ;
91
+
92
+ static bool isEquivalent (const Value &V1, const Value &V2);
93
+ static bool isInverse (const Value &V1, const Value &V2);
94
+ };
95
+ } // namespace
96
+
97
+ Optional<const ControlConditions> ControlConditions::collectControlConditions (
98
+ const BasicBlock &BB, const BasicBlock &Dominator, const DominatorTree &DT,
99
+ const PostDominatorTree &PDT, unsigned MaxLookup) {
100
+ assert (DT.dominates (&Dominator, &BB) && " Expecting Dominator to dominate BB" );
101
+
102
+ ControlConditions Conditions;
103
+ unsigned NumConditions = 0 ;
104
+
105
+ // BB is executed unconditional from itself.
106
+ if (&Dominator == &BB)
107
+ return Conditions;
108
+
109
+ const BasicBlock *CurBlock = &BB;
110
+ // Walk up the dominator tree from the associated DT node for BB to the
111
+ // associated DT node for Dominator.
112
+ do {
113
+ assert (DT.getNode (CurBlock) && " Expecting a valid DT node for CurBlock" );
114
+ BasicBlock *IDom = DT.getNode (CurBlock)->getIDom ()->getBlock ();
115
+ assert (DT.dominates (&Dominator, IDom) &&
116
+ " Expecting Dominator to dominate IDom" );
117
+
118
+ // Limitation: can only handle branch instruction currently.
119
+ const BranchInst *BI = dyn_cast<BranchInst>(IDom->getTerminator ());
120
+ if (!BI)
121
+ return None;
122
+
123
+ bool Inserted = false ;
124
+ if (PDT.dominates (CurBlock, IDom)) {
125
+ LLVM_DEBUG (dbgs () << CurBlock->getName ()
126
+ << " is executed unconditionally from "
127
+ << IDom->getName () << " \n " );
128
+ } else if (PDT.dominates (CurBlock, BI->getSuccessor (0 ))) {
129
+ LLVM_DEBUG (dbgs () << CurBlock->getName () << " is executed when \" "
130
+ << *BI->getCondition () << " \" is true from "
131
+ << IDom->getName () << " \n " );
132
+ Inserted = Conditions.addControlCondition (
133
+ ControlCondition (BI->getCondition (), true ));
134
+ } else if (PDT.dominates (CurBlock, BI->getSuccessor (1 ))) {
135
+ LLVM_DEBUG (dbgs () << CurBlock->getName () << " is executed when \" "
136
+ << *BI->getCondition () << " \" is false from "
137
+ << IDom->getName () << " \n " );
138
+ Inserted = Conditions.addControlCondition (
139
+ ControlCondition (BI->getCondition (), false ));
140
+ } else
141
+ return None;
142
+
143
+ if (Inserted)
144
+ ++NumConditions;
145
+
146
+ if (MaxLookup != 0 && NumConditions > MaxLookup)
147
+ return None;
148
+
149
+ CurBlock = IDom;
150
+ } while (CurBlock != &Dominator);
151
+
152
+ return Conditions;
153
+ }
154
+
155
+ bool ControlConditions::addControlCondition (ControlCondition C) {
156
+ bool Inserted = false ;
157
+ if (none_of (Conditions, [&C](ControlCondition &Exists) {
158
+ return ControlConditions::isEquivalent (C, Exists);
159
+ })) {
160
+ Conditions.push_back (C);
161
+ Inserted = true ;
162
+ }
163
+
164
+ LLVM_DEBUG (dbgs () << (Inserted ? " Inserted " : " Not inserted " ) << C << " \n " );
165
+ return Inserted;
166
+ }
167
+
168
+ bool ControlConditions::isEquivalent (const ControlConditions &Other) const {
169
+ if (Conditions.empty () && Other.Conditions .empty ())
170
+ return true ;
171
+
172
+ if (Conditions.size () != Other.Conditions .size ())
173
+ return false ;
174
+
175
+ return all_of (Conditions, [&Other](const ControlCondition &C) {
176
+ return any_of (Other.Conditions , [&C](const ControlCondition &OtherC) {
177
+ return ControlConditions::isEquivalent (C, OtherC);
178
+ });
179
+ });
180
+ }
181
+
182
+ bool ControlConditions::isEquivalent (const ControlCondition &C1,
183
+ const ControlCondition &C2) {
184
+ if (C1.getInt () == C2.getInt ()) {
185
+ if (isEquivalent (*C1.getPointer (), *C2.getPointer ()))
186
+ return true ;
187
+ } else if (isInverse (*C1.getPointer (), *C2.getPointer ()))
188
+ return true ;
189
+
190
+ return false ;
191
+ }
192
+
193
+ // FIXME: Use SCEV and reuse GVN/CSE logic to check for equivalence between
194
+ // Values.
195
+ // Currently, isEquivalent rely on other passes to ensure equivalent conditions
196
+ // have the same value, e.g. GVN.
197
+ bool ControlConditions::isEquivalent (const Value &V1, const Value &V2) {
198
+ return &V1 == &V2;
199
+ }
200
+
201
+ bool ControlConditions::isInverse (const Value &V1, const Value &V2) {
202
+ if (const CmpInst *Cmp1 = dyn_cast<CmpInst>(&V1))
203
+ if (const CmpInst *Cmp2 = dyn_cast<CmpInst>(&V2)) {
204
+ if (Cmp1->getPredicate () == Cmp2->getInversePredicate () &&
205
+ Cmp1->getOperand (0 ) == Cmp2->getOperand (0 ) &&
206
+ Cmp1->getOperand (1 ) == Cmp2->getOperand (1 ))
207
+ return true ;
208
+
209
+ if (Cmp1->getPredicate () ==
210
+ CmpInst::getSwappedPredicate (Cmp2->getInversePredicate ()) &&
211
+ Cmp1->getOperand (0 ) == Cmp2->getOperand (1 ) &&
212
+ Cmp1->getOperand (1 ) == Cmp2->getOperand (0 ))
213
+ return true ;
214
+ }
215
+ return false ;
216
+ }
217
+
33
218
bool llvm::isControlFlowEquivalent (const Instruction &I0, const Instruction &I1,
34
219
const DominatorTree &DT,
35
220
const PostDominatorTree &PDT) {
@@ -42,8 +227,30 @@ bool llvm::isControlFlowEquivalent(const BasicBlock &BB0, const BasicBlock &BB1,
42
227
if (&BB0 == &BB1)
43
228
return true ;
44
229
45
- return ((DT.dominates (&BB0, &BB1) && PDT.dominates (&BB1, &BB0)) ||
46
- (PDT.dominates (&BB0, &BB1) && DT.dominates (&BB1, &BB0)));
230
+ if ((DT.dominates (&BB0, &BB1) && PDT.dominates (&BB1, &BB0)) ||
231
+ (PDT.dominates (&BB0, &BB1) && DT.dominates (&BB1, &BB0)))
232
+ return true ;
233
+
234
+ // If the set of conditions required to execute BB0 and BB1 from their common
235
+ // dominator are the same, then BB0 and BB1 are control flow equivalent.
236
+ const BasicBlock *CommonDominator = DT.findNearestCommonDominator (&BB0, &BB1);
237
+ LLVM_DEBUG (dbgs () << " The nearest common dominator of " << BB0.getName ()
238
+ << " and " << BB1.getName () << " is "
239
+ << CommonDominator->getName () << " \n " );
240
+
241
+ Optional<const ControlConditions> BB0Conditions =
242
+ ControlConditions::collectControlConditions (BB0, *CommonDominator, DT,
243
+ PDT);
244
+ if (BB0Conditions == None)
245
+ return false ;
246
+
247
+ Optional<const ControlConditions> BB1Conditions =
248
+ ControlConditions::collectControlConditions (BB1, *CommonDominator, DT,
249
+ PDT);
250
+ if (BB1Conditions == None)
251
+ return false ;
252
+
253
+ return BB0Conditions->isEquivalent (*BB1Conditions);
47
254
}
48
255
49
256
static bool reportInvalidCandidate (const Instruction &I,
@@ -90,8 +297,7 @@ collectInstructionsInBetween(Instruction &StartInst, const Instruction &EndInst,
90
297
}
91
298
92
299
bool llvm::isSafeToMoveBefore (Instruction &I, Instruction &InsertPoint,
93
- const DominatorTree &DT,
94
- const PostDominatorTree &PDT,
300
+ DominatorTree &DT, const PostDominatorTree &PDT,
95
301
DependenceInfo &DI) {
96
302
// Cannot move itself before itself.
97
303
if (&I == &InsertPoint)
@@ -111,9 +317,9 @@ bool llvm::isSafeToMoveBefore(Instruction &I, Instruction &InsertPoint,
111
317
if (!isControlFlowEquivalent (I, InsertPoint, DT, PDT))
112
318
return reportInvalidCandidate (I, NotControlFlowEquivalent);
113
319
114
- // As I and InsertPoint are control flow equivalent, if I dominates
115
- // InsertPoint, then I comes before InsertPoint.
116
- const bool MoveForward = DT. dominates (&I, &InsertPoint);
320
+ OrderedInstructions OI (&DT);
321
+ DT. updateDFSNumbers ();
322
+ const bool MoveForward = OI. dfsBefore (&I, &InsertPoint);
117
323
if (MoveForward) {
118
324
// When I is being moved forward, we need to make sure the InsertPoint
119
325
// dominates every users. Or else, a user may be using an undefined I.
@@ -126,7 +332,7 @@ bool llvm::isSafeToMoveBefore(Instruction &I, Instruction &InsertPoint,
126
332
// dominates the InsertPoint. Or else, an operand may be undefined for I.
127
333
for (const Value *Op : I.operands ())
128
334
if (auto *OpInst = dyn_cast<Instruction>(Op))
129
- if (&InsertPoint == OpInst || !DT .dominates (OpInst, &InsertPoint))
335
+ if (&InsertPoint == OpInst || !OI .dominates (OpInst, &InsertPoint))
130
336
return false ;
131
337
}
132
338
@@ -174,9 +380,10 @@ bool llvm::isSafeToMoveBefore(Instruction &I, Instruction &InsertPoint,
174
380
return true ;
175
381
}
176
382
177
- void llvm::moveInstsBottomUp (BasicBlock &FromBB, BasicBlock &ToBB,
178
- const DominatorTree &DT,
179
- const PostDominatorTree &PDT, DependenceInfo &DI) {
383
+ void llvm::moveInstructionsToTheBeginning (BasicBlock &FromBB, BasicBlock &ToBB,
384
+ DominatorTree &DT,
385
+ const PostDominatorTree &PDT,
386
+ DependenceInfo &DI) {
180
387
for (auto It = ++FromBB.rbegin (); It != FromBB.rend ();) {
181
388
Instruction *MovePos = ToBB.getFirstNonPHIOrDbg ();
182
389
Instruction &I = *It;
0 commit comments