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