| 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 | |