1 | //===- ControlFlowUtils.cpp - Control Flow Utilities -----------------------==// |
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 | // Utilities to manipulate the CFG and restore SSA for the new control flow. |
10 | // |
11 | //===----------------------------------------------------------------------===// |
12 | |
13 | #include "llvm/Transforms/Utils/ControlFlowUtils.h" |
14 | #include "llvm/ADT/SetVector.h" |
15 | #include "llvm/ADT/SmallSet.h" |
16 | #include "llvm/Analysis/DomTreeUpdater.h" |
17 | #include "llvm/IR/Constants.h" |
18 | #include "llvm/IR/Instructions.h" |
19 | #include "llvm/IR/ValueHandle.h" |
20 | #include "llvm/Transforms/Utils/Local.h" |
21 | |
22 | #define DEBUG_TYPE "control-flow-hub" |
23 | |
24 | using namespace llvm; |
25 | |
26 | using BBPredicates = DenseMap<BasicBlock *, Instruction *>; |
27 | using EdgeDescriptor = ControlFlowHub::BranchDescriptor; |
28 | |
29 | // Redirects the terminator of the incoming block to the first guard block in |
30 | // the hub. Returns the branch condition from `BB` if it exits. |
31 | // - If only one of Succ0 or Succ1 is not null, the corresponding branch |
32 | // successor is redirected to the FirstGuardBlock. |
33 | // - Else both are not null, and branch is replaced with an unconditional |
34 | // branch to the FirstGuardBlock. |
35 | static Value *redirectToHub(BasicBlock *BB, BasicBlock *Succ0, |
36 | BasicBlock *Succ1, BasicBlock *FirstGuardBlock) { |
37 | assert(isa<BranchInst>(BB->getTerminator()) && |
38 | "Only support branch terminator." ); |
39 | auto *Branch = cast<BranchInst>(Val: BB->getTerminator()); |
40 | auto *Condition = Branch->isConditional() ? Branch->getCondition() : nullptr; |
41 | |
42 | assert(Succ0 || Succ1); |
43 | |
44 | if (Branch->isUnconditional()) { |
45 | assert(Succ0 == Branch->getSuccessor(0)); |
46 | assert(!Succ1); |
47 | Branch->setSuccessor(idx: 0, NewSucc: FirstGuardBlock); |
48 | } else { |
49 | assert(!Succ1 || Succ1 == Branch->getSuccessor(1)); |
50 | if (Succ0 && !Succ1) { |
51 | Branch->setSuccessor(idx: 0, NewSucc: FirstGuardBlock); |
52 | } else if (Succ1 && !Succ0) { |
53 | Branch->setSuccessor(idx: 1, NewSucc: FirstGuardBlock); |
54 | } else { |
55 | Branch->eraseFromParent(); |
56 | BranchInst::Create(IfTrue: FirstGuardBlock, InsertBefore: BB); |
57 | } |
58 | } |
59 | |
60 | return Condition; |
61 | } |
62 | |
63 | // Setup the branch instructions for guard blocks. |
64 | // |
65 | // Each guard block terminates in a conditional branch that transfers |
66 | // control to the corresponding outgoing block or the next guard |
67 | // block. The last guard block has two outgoing blocks as successors. |
68 | static void setupBranchForGuard(ArrayRef<BasicBlock *> GuardBlocks, |
69 | ArrayRef<BasicBlock *> Outgoing, |
70 | BBPredicates &GuardPredicates) { |
71 | assert(Outgoing.size() > 1); |
72 | assert(GuardBlocks.size() == Outgoing.size() - 1); |
73 | int I = 0; |
74 | for (int E = GuardBlocks.size() - 1; I != E; ++I) { |
75 | BasicBlock *Out = Outgoing[I]; |
76 | BranchInst::Create(IfTrue: Out, IfFalse: GuardBlocks[I + 1], Cond: GuardPredicates[Out], |
77 | InsertBefore: GuardBlocks[I]); |
78 | } |
79 | BasicBlock *Out = Outgoing[I]; |
80 | BranchInst::Create(IfTrue: Out, IfFalse: Outgoing[I + 1], Cond: GuardPredicates[Out], |
81 | InsertBefore: GuardBlocks[I]); |
82 | } |
83 | |
84 | // Assign an index to each outgoing block. At the corresponding guard |
85 | // block, compute the branch condition by comparing this index. |
86 | static void calcPredicateUsingInteger(ArrayRef<EdgeDescriptor> Branches, |
87 | ArrayRef<BasicBlock *> Outgoing, |
88 | ArrayRef<BasicBlock *> GuardBlocks, |
89 | BBPredicates &GuardPredicates) { |
90 | LLVMContext &Context = GuardBlocks.front()->getContext(); |
91 | BasicBlock *FirstGuardBlock = GuardBlocks.front(); |
92 | Type *Int32Ty = Type::getInt32Ty(C&: Context); |
93 | |
94 | auto *Phi = PHINode::Create(Ty: Int32Ty, NumReservedValues: Branches.size(), NameStr: "merged.bb.idx" , |
95 | InsertBefore: FirstGuardBlock); |
96 | |
97 | for (auto [BB, Succ0, Succ1] : Branches) { |
98 | Value *Condition = redirectToHub(BB, Succ0, Succ1, FirstGuardBlock); |
99 | Value *IncomingId = nullptr; |
100 | if (Succ0 && Succ1) { |
101 | auto Succ0Iter = find(Range&: Outgoing, Val: Succ0); |
102 | auto Succ1Iter = find(Range&: Outgoing, Val: Succ1); |
103 | Value *Id0 = |
104 | ConstantInt::get(Ty: Int32Ty, V: std::distance(first: Outgoing.begin(), last: Succ0Iter)); |
105 | Value *Id1 = |
106 | ConstantInt::get(Ty: Int32Ty, V: std::distance(first: Outgoing.begin(), last: Succ1Iter)); |
107 | IncomingId = SelectInst::Create(C: Condition, S1: Id0, S2: Id1, NameStr: "target.bb.idx" , |
108 | InsertBefore: BB->getTerminator()->getIterator()); |
109 | } else { |
110 | // Get the index of the non-null successor. |
111 | auto SuccIter = Succ0 ? find(Range&: Outgoing, Val: Succ0) : find(Range&: Outgoing, Val: Succ1); |
112 | IncomingId = |
113 | ConstantInt::get(Ty: Int32Ty, V: std::distance(first: Outgoing.begin(), last: SuccIter)); |
114 | } |
115 | Phi->addIncoming(V: IncomingId, BB); |
116 | } |
117 | |
118 | for (int I = 0, E = Outgoing.size() - 1; I != E; ++I) { |
119 | BasicBlock *Out = Outgoing[I]; |
120 | LLVM_DEBUG(dbgs() << "Creating integer guard for " << Out->getName() |
121 | << "\n" ); |
122 | auto *Cmp = ICmpInst::Create(Op: Instruction::ICmp, Pred: ICmpInst::ICMP_EQ, S1: Phi, |
123 | S2: ConstantInt::get(Ty: Int32Ty, V: I), |
124 | Name: Out->getName() + ".predicate" , InsertBefore: GuardBlocks[I]); |
125 | GuardPredicates[Out] = Cmp; |
126 | } |
127 | } |
128 | |
129 | // Determine the branch condition to be used at each guard block from the |
130 | // original boolean values. |
131 | static void calcPredicateUsingBooleans( |
132 | ArrayRef<EdgeDescriptor> Branches, ArrayRef<BasicBlock *> Outgoing, |
133 | SmallVectorImpl<BasicBlock *> &GuardBlocks, BBPredicates &GuardPredicates, |
134 | SmallVectorImpl<WeakVH> &DeletionCandidates) { |
135 | LLVMContext &Context = GuardBlocks.front()->getContext(); |
136 | auto *BoolTrue = ConstantInt::getTrue(Context); |
137 | auto *BoolFalse = ConstantInt::getFalse(Context); |
138 | BasicBlock *FirstGuardBlock = GuardBlocks.front(); |
139 | |
140 | // The predicate for the last outgoing is trivially true, and so we |
141 | // process only the first N-1 successors. |
142 | for (int I = 0, E = Outgoing.size() - 1; I != E; ++I) { |
143 | BasicBlock *Out = Outgoing[I]; |
144 | LLVM_DEBUG(dbgs() << "Creating boolean guard for " << Out->getName() |
145 | << "\n" ); |
146 | |
147 | auto *Phi = |
148 | PHINode::Create(Ty: Type::getInt1Ty(C&: Context), NumReservedValues: Branches.size(), |
149 | NameStr: StringRef("Guard." ) + Out->getName(), InsertBefore: FirstGuardBlock); |
150 | GuardPredicates[Out] = Phi; |
151 | } |
152 | |
153 | for (auto [BB, Succ0, Succ1] : Branches) { |
154 | Value *Condition = redirectToHub(BB, Succ0, Succ1, FirstGuardBlock); |
155 | |
156 | // Optimization: Consider an incoming block A with both successors |
157 | // Succ0 and Succ1 in the set of outgoing blocks. The predicates |
158 | // for Succ0 and Succ1 complement each other. If Succ0 is visited |
159 | // first in the loop below, control will branch to Succ0 using the |
160 | // corresponding predicate. But if that branch is not taken, then |
161 | // control must reach Succ1, which means that the incoming value of |
162 | // the predicate from `BB` is true for Succ1. |
163 | bool OneSuccessorDone = false; |
164 | for (int I = 0, E = Outgoing.size() - 1; I != E; ++I) { |
165 | BasicBlock *Out = Outgoing[I]; |
166 | PHINode *Phi = cast<PHINode>(Val: GuardPredicates[Out]); |
167 | if (Out != Succ0 && Out != Succ1) { |
168 | Phi->addIncoming(V: BoolFalse, BB); |
169 | } else if (!Succ0 || !Succ1 || OneSuccessorDone) { |
170 | // Optimization: When only one successor is an outgoing block, |
171 | // the incoming predicate from `BB` is always true. |
172 | Phi->addIncoming(V: BoolTrue, BB); |
173 | } else { |
174 | assert(Succ0 && Succ1); |
175 | if (Out == Succ0) { |
176 | Phi->addIncoming(V: Condition, BB); |
177 | } else { |
178 | Value *Inverted = invertCondition(Condition); |
179 | DeletionCandidates.push_back(Elt: Condition); |
180 | Phi->addIncoming(V: Inverted, BB); |
181 | } |
182 | OneSuccessorDone = true; |
183 | } |
184 | } |
185 | } |
186 | } |
187 | |
188 | // Capture the existing control flow as guard predicates, and redirect |
189 | // control flow from \p Incoming block through the \p GuardBlocks to the |
190 | // \p Outgoing blocks. |
191 | // |
192 | // There is one guard predicate for each outgoing block OutBB. The |
193 | // predicate represents whether the hub should transfer control flow |
194 | // to OutBB. These predicates are NOT ORTHOGONAL. The Hub evaluates |
195 | // them in the same order as the Outgoing set-vector, and control |
196 | // branches to the first outgoing block whose predicate evaluates to true. |
197 | // |
198 | // The last guard block has two outgoing blocks as successors since the |
199 | // condition for the final outgoing block is trivially true. So we create one |
200 | // less block (including the first guard block) than the number of outgoing |
201 | // blocks. |
202 | static void convertToGuardPredicates( |
203 | ArrayRef<EdgeDescriptor> Branches, ArrayRef<BasicBlock *> Outgoing, |
204 | SmallVectorImpl<BasicBlock *> &GuardBlocks, |
205 | SmallVectorImpl<WeakVH> &DeletionCandidates, const StringRef Prefix, |
206 | std::optional<unsigned> MaxControlFlowBooleans) { |
207 | BBPredicates GuardPredicates; |
208 | Function *F = Outgoing.front()->getParent(); |
209 | |
210 | for (int I = 0, E = Outgoing.size() - 1; I != E; ++I) |
211 | GuardBlocks.push_back( |
212 | Elt: BasicBlock::Create(Context&: F->getContext(), Name: Prefix + ".guard" , Parent: F)); |
213 | |
214 | // When we are using an integer to record which target block to jump to, we |
215 | // are creating less live values, actually we are using one single integer to |
216 | // store the index of the target block. When we are using booleans to store |
217 | // the branching information, we need (N-1) boolean values, where N is the |
218 | // number of outgoing block. |
219 | if (!MaxControlFlowBooleans || Outgoing.size() <= *MaxControlFlowBooleans) |
220 | calcPredicateUsingBooleans(Branches, Outgoing, GuardBlocks, GuardPredicates, |
221 | DeletionCandidates); |
222 | else |
223 | calcPredicateUsingInteger(Branches, Outgoing, GuardBlocks, GuardPredicates); |
224 | |
225 | setupBranchForGuard(GuardBlocks, Outgoing, GuardPredicates); |
226 | } |
227 | |
228 | // After creating a control flow hub, the operands of PHINodes in an outgoing |
229 | // block Out no longer match the predecessors of that block. Predecessors of Out |
230 | // that are incoming blocks to the hub are now replaced by just one edge from |
231 | // the hub. To match this new control flow, the corresponding values from each |
232 | // PHINode must now be moved a new PHINode in the first guard block of the hub. |
233 | // |
234 | // This operation cannot be performed with SSAUpdater, because it involves one |
235 | // new use: If the block Out is in the list of Incoming blocks, then the newly |
236 | // created PHI in the Hub will use itself along that edge from Out to Hub. |
237 | static void reconnectPhis(BasicBlock *Out, BasicBlock *GuardBlock, |
238 | ArrayRef<EdgeDescriptor> Incoming, |
239 | BasicBlock *FirstGuardBlock) { |
240 | auto I = Out->begin(); |
241 | while (I != Out->end() && isa<PHINode>(Val: I)) { |
242 | auto *Phi = cast<PHINode>(Val&: I); |
243 | auto *NewPhi = |
244 | PHINode::Create(Ty: Phi->getType(), NumReservedValues: Incoming.size(), |
245 | NameStr: Phi->getName() + ".moved" , InsertBefore: FirstGuardBlock->begin()); |
246 | bool AllUndef = true; |
247 | for (auto [BB, Succ0, Succ1] : Incoming) { |
248 | Value *V = PoisonValue::get(T: Phi->getType()); |
249 | if (Phi->getBasicBlockIndex(BB) != -1) { |
250 | V = Phi->removeIncomingValue(BB, DeletePHIIfEmpty: false); |
251 | if (BB == Out) { |
252 | V = NewPhi; |
253 | } |
254 | AllUndef &= isa<UndefValue>(Val: V); |
255 | } |
256 | |
257 | NewPhi->addIncoming(V, BB); |
258 | } |
259 | assert(NewPhi->getNumIncomingValues() == Incoming.size()); |
260 | Value *NewV = NewPhi; |
261 | if (AllUndef) { |
262 | NewPhi->eraseFromParent(); |
263 | NewV = PoisonValue::get(T: Phi->getType()); |
264 | } |
265 | if (Phi->getNumOperands() == 0) { |
266 | Phi->replaceAllUsesWith(V: NewV); |
267 | I = Phi->eraseFromParent(); |
268 | continue; |
269 | } |
270 | Phi->addIncoming(V: NewV, BB: GuardBlock); |
271 | ++I; |
272 | } |
273 | } |
274 | |
275 | std::pair<BasicBlock *, bool> ControlFlowHub::finalize( |
276 | DomTreeUpdater *DTU, SmallVectorImpl<BasicBlock *> &GuardBlocks, |
277 | const StringRef Prefix, std::optional<unsigned> MaxControlFlowBooleans) { |
278 | #ifndef NDEBUG |
279 | SmallSet<BasicBlock *, 8> Incoming; |
280 | #endif |
281 | SetVector<BasicBlock *> Outgoing; |
282 | |
283 | for (auto [BB, Succ0, Succ1] : Branches) { |
284 | #ifndef NDEBUG |
285 | assert(Incoming.insert(BB).second && "Duplicate entry for incoming block." ); |
286 | #endif |
287 | if (Succ0) |
288 | Outgoing.insert(X: Succ0); |
289 | if (Succ1) |
290 | Outgoing.insert(X: Succ1); |
291 | } |
292 | |
293 | if (Outgoing.size() < 2) |
294 | return {Outgoing.front(), false}; |
295 | |
296 | SmallVector<DominatorTree::UpdateType, 16> Updates; |
297 | if (DTU) { |
298 | for (auto [BB, Succ0, Succ1] : Branches) { |
299 | if (Succ0) |
300 | Updates.push_back(Elt: {DominatorTree::Delete, BB, Succ0}); |
301 | if (Succ1) |
302 | Updates.push_back(Elt: {DominatorTree::Delete, BB, Succ1}); |
303 | } |
304 | } |
305 | |
306 | SmallVector<WeakVH, 8> DeletionCandidates; |
307 | convertToGuardPredicates(Branches, Outgoing: Outgoing.getArrayRef(), GuardBlocks, |
308 | DeletionCandidates, Prefix, MaxControlFlowBooleans); |
309 | BasicBlock *FirstGuardBlock = GuardBlocks.front(); |
310 | |
311 | // Update the PHINodes in each outgoing block to match the new control flow. |
312 | for (int I = 0, E = GuardBlocks.size(); I != E; ++I) |
313 | reconnectPhis(Out: Outgoing[I], GuardBlock: GuardBlocks[I], Incoming: Branches, FirstGuardBlock); |
314 | // Process the Nth (last) outgoing block with the (N-1)th (last) guard block. |
315 | reconnectPhis(Out: Outgoing.back(), GuardBlock: GuardBlocks.back(), Incoming: Branches, FirstGuardBlock); |
316 | |
317 | if (DTU) { |
318 | int NumGuards = GuardBlocks.size(); |
319 | |
320 | for (auto [BB, Succ0, Succ1] : Branches) |
321 | Updates.push_back(Elt: {DominatorTree::Insert, BB, FirstGuardBlock}); |
322 | |
323 | for (int I = 0; I != NumGuards - 1; ++I) { |
324 | Updates.push_back(Elt: {DominatorTree::Insert, GuardBlocks[I], Outgoing[I]}); |
325 | Updates.push_back( |
326 | Elt: {DominatorTree::Insert, GuardBlocks[I], GuardBlocks[I + 1]}); |
327 | } |
328 | // The second successor of the last guard block is an outgoing block instead |
329 | // of having a "next" guard block. |
330 | Updates.push_back(Elt: {DominatorTree::Insert, GuardBlocks[NumGuards - 1], |
331 | Outgoing[NumGuards - 1]}); |
332 | Updates.push_back(Elt: {DominatorTree::Insert, GuardBlocks[NumGuards - 1], |
333 | Outgoing[NumGuards]}); |
334 | DTU->applyUpdates(Updates); |
335 | } |
336 | |
337 | for (auto I : DeletionCandidates) { |
338 | if (I->use_empty()) |
339 | if (auto *Inst = dyn_cast_or_null<Instruction>(Val&: I)) |
340 | Inst->eraseFromParent(); |
341 | } |
342 | |
343 | return {FirstGuardBlock, true}; |
344 | } |
345 | |