1fe6060f1SDimitry Andric //===- DFAJumpThreading.cpp - Threads a switch statement inside a loop ----===// 2fe6060f1SDimitry Andric // 3349cc55cSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4349cc55cSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5349cc55cSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6fe6060f1SDimitry Andric // 7fe6060f1SDimitry Andric //===----------------------------------------------------------------------===// 8fe6060f1SDimitry Andric // 9fe6060f1SDimitry Andric // Transform each threading path to effectively jump thread the DFA. For 10fe6060f1SDimitry Andric // example, the CFG below could be transformed as follows, where the cloned 11fe6060f1SDimitry Andric // blocks unconditionally branch to the next correct case based on what is 12fe6060f1SDimitry Andric // identified in the analysis. 13fe6060f1SDimitry Andric // 14fe6060f1SDimitry Andric // sw.bb sw.bb 15fe6060f1SDimitry Andric // / | \ / | \ 16fe6060f1SDimitry Andric // case1 case2 case3 case1 case2 case3 17fe6060f1SDimitry Andric // \ | / | | | 18fe6060f1SDimitry Andric // determinator det.2 det.3 det.1 19fe6060f1SDimitry Andric // br sw.bb / | \ 20fe6060f1SDimitry Andric // sw.bb.2 sw.bb.3 sw.bb.1 21fe6060f1SDimitry Andric // br case2 br case3 br case1§ 22fe6060f1SDimitry Andric // 23fe6060f1SDimitry Andric // Definitions and Terminology: 24fe6060f1SDimitry Andric // 25fe6060f1SDimitry Andric // * Threading path: 26fe6060f1SDimitry Andric // a list of basic blocks, the exit state, and the block that determines 27fe6060f1SDimitry Andric // the next state, for which the following notation will be used: 28fe6060f1SDimitry Andric // < path of BBs that form a cycle > [ state, determinator ] 29fe6060f1SDimitry Andric // 30fe6060f1SDimitry Andric // * Predictable switch: 31fe6060f1SDimitry Andric // The switch variable is always a known constant so that all conditional 32fe6060f1SDimitry Andric // jumps based on switch variable can be converted to unconditional jump. 33fe6060f1SDimitry Andric // 34fe6060f1SDimitry Andric // * Determinator: 35fe6060f1SDimitry Andric // The basic block that determines the next state of the DFA. 36fe6060f1SDimitry Andric // 37fe6060f1SDimitry Andric // Representing the optimization in C-like pseudocode: the code pattern on the 38fe6060f1SDimitry Andric // left could functionally be transformed to the right pattern if the switch 39fe6060f1SDimitry Andric // condition is predictable. 40fe6060f1SDimitry Andric // 41fe6060f1SDimitry Andric // X = A goto A 42fe6060f1SDimitry Andric // for (...) A: 43fe6060f1SDimitry Andric // switch (X) ... 44fe6060f1SDimitry Andric // case A goto B 45fe6060f1SDimitry Andric // X = B B: 46fe6060f1SDimitry Andric // case B ... 47fe6060f1SDimitry Andric // X = C goto C 48fe6060f1SDimitry Andric // 49fe6060f1SDimitry Andric // The pass first checks that switch variable X is decided by the control flow 50fe6060f1SDimitry Andric // path taken in the loop; for example, in case B, the next value of X is 51fe6060f1SDimitry Andric // decided to be C. It then enumerates through all paths in the loop and labels 52fe6060f1SDimitry Andric // the basic blocks where the next state is decided. 53fe6060f1SDimitry Andric // 54fe6060f1SDimitry Andric // Using this information it creates new paths that unconditionally branch to 55fe6060f1SDimitry Andric // the next case. This involves cloning code, so it only gets triggered if the 56fe6060f1SDimitry Andric // amount of code duplicated is below a threshold. 57fe6060f1SDimitry Andric // 58fe6060f1SDimitry Andric //===----------------------------------------------------------------------===// 59fe6060f1SDimitry Andric 60fe6060f1SDimitry Andric #include "llvm/Transforms/Scalar/DFAJumpThreading.h" 61fe6060f1SDimitry Andric #include "llvm/ADT/APInt.h" 62fe6060f1SDimitry Andric #include "llvm/ADT/DenseMap.h" 63fe6060f1SDimitry Andric #include "llvm/ADT/SmallSet.h" 64fe6060f1SDimitry Andric #include "llvm/ADT/Statistic.h" 65fe6060f1SDimitry Andric #include "llvm/Analysis/AssumptionCache.h" 66fe6060f1SDimitry Andric #include "llvm/Analysis/CodeMetrics.h" 6781ad6265SDimitry Andric #include "llvm/Analysis/DomTreeUpdater.h" 68*0fca6ea1SDimitry Andric #include "llvm/Analysis/LoopInfo.h" 69fe6060f1SDimitry Andric #include "llvm/Analysis/OptimizationRemarkEmitter.h" 70fe6060f1SDimitry Andric #include "llvm/Analysis/TargetTransformInfo.h" 71fe6060f1SDimitry Andric #include "llvm/IR/CFG.h" 72fe6060f1SDimitry Andric #include "llvm/IR/Constants.h" 73fe6060f1SDimitry Andric #include "llvm/IR/IntrinsicInst.h" 74fe6060f1SDimitry Andric #include "llvm/Support/CommandLine.h" 75fe6060f1SDimitry Andric #include "llvm/Support/Debug.h" 76fe6060f1SDimitry Andric #include "llvm/Transforms/Utils/Cloning.h" 77fe6060f1SDimitry Andric #include "llvm/Transforms/Utils/SSAUpdaterBulk.h" 78fe6060f1SDimitry Andric #include "llvm/Transforms/Utils/ValueMapper.h" 79fe6060f1SDimitry Andric #include <algorithm> 80fe6060f1SDimitry Andric #include <deque> 81fe6060f1SDimitry Andric 8281ad6265SDimitry Andric #ifdef EXPENSIVE_CHECKS 8381ad6265SDimitry Andric #include "llvm/IR/Verifier.h" 8481ad6265SDimitry Andric #endif 8581ad6265SDimitry Andric 86fe6060f1SDimitry Andric using namespace llvm; 87fe6060f1SDimitry Andric 88fe6060f1SDimitry Andric #define DEBUG_TYPE "dfa-jump-threading" 89fe6060f1SDimitry Andric 90fe6060f1SDimitry Andric STATISTIC(NumTransforms, "Number of transformations done"); 91fe6060f1SDimitry Andric STATISTIC(NumCloned, "Number of blocks cloned"); 92fe6060f1SDimitry Andric STATISTIC(NumPaths, "Number of individual paths threaded"); 93fe6060f1SDimitry Andric 94fe6060f1SDimitry Andric static cl::opt<bool> 95fe6060f1SDimitry Andric ClViewCfgBefore("dfa-jump-view-cfg-before", 96fe6060f1SDimitry Andric cl::desc("View the CFG before DFA Jump Threading"), 97fe6060f1SDimitry Andric cl::Hidden, cl::init(false)); 98fe6060f1SDimitry Andric 99*0fca6ea1SDimitry Andric static cl::opt<bool> EarlyExitHeuristic( 100*0fca6ea1SDimitry Andric "dfa-early-exit-heuristic", 101*0fca6ea1SDimitry Andric cl::desc("Exit early if an unpredictable value come from the same loop"), 102*0fca6ea1SDimitry Andric cl::Hidden, cl::init(true)); 103*0fca6ea1SDimitry Andric 104fe6060f1SDimitry Andric static cl::opt<unsigned> MaxPathLength( 105fe6060f1SDimitry Andric "dfa-max-path-length", 106fe6060f1SDimitry Andric cl::desc("Max number of blocks searched to find a threading path"), 107fe6060f1SDimitry Andric cl::Hidden, cl::init(20)); 108fe6060f1SDimitry Andric 1095f757f3fSDimitry Andric static cl::opt<unsigned> 1105f757f3fSDimitry Andric MaxNumPaths("dfa-max-num-paths", 11181ad6265SDimitry Andric cl::desc("Max number of paths enumerated around a switch"), 11281ad6265SDimitry Andric cl::Hidden, cl::init(200)); 11381ad6265SDimitry Andric 114fe6060f1SDimitry Andric static cl::opt<unsigned> 115fe6060f1SDimitry Andric CostThreshold("dfa-cost-threshold", 116fe6060f1SDimitry Andric cl::desc("Maximum cost accepted for the transformation"), 117fe6060f1SDimitry Andric cl::Hidden, cl::init(50)); 118fe6060f1SDimitry Andric 119fe6060f1SDimitry Andric namespace { 120fe6060f1SDimitry Andric 121fe6060f1SDimitry Andric class SelectInstToUnfold { 122fe6060f1SDimitry Andric SelectInst *SI; 123fe6060f1SDimitry Andric PHINode *SIUse; 124fe6060f1SDimitry Andric 125fe6060f1SDimitry Andric public: 126fe6060f1SDimitry Andric SelectInstToUnfold(SelectInst *SI, PHINode *SIUse) : SI(SI), SIUse(SIUse) {} 127fe6060f1SDimitry Andric 128fe6060f1SDimitry Andric SelectInst *getInst() { return SI; } 129fe6060f1SDimitry Andric PHINode *getUse() { return SIUse; } 130fe6060f1SDimitry Andric 131fe6060f1SDimitry Andric explicit operator bool() const { return SI && SIUse; } 132fe6060f1SDimitry Andric }; 133fe6060f1SDimitry Andric 134*0fca6ea1SDimitry Andric void unfold(DomTreeUpdater *DTU, LoopInfo *LI, SelectInstToUnfold SIToUnfold, 135fe6060f1SDimitry Andric std::vector<SelectInstToUnfold> *NewSIsToUnfold, 136fe6060f1SDimitry Andric std::vector<BasicBlock *> *NewBBs); 137fe6060f1SDimitry Andric 138fe6060f1SDimitry Andric class DFAJumpThreading { 139fe6060f1SDimitry Andric public: 140*0fca6ea1SDimitry Andric DFAJumpThreading(AssumptionCache *AC, DominatorTree *DT, LoopInfo *LI, 141fe6060f1SDimitry Andric TargetTransformInfo *TTI, OptimizationRemarkEmitter *ORE) 142*0fca6ea1SDimitry Andric : AC(AC), DT(DT), LI(LI), TTI(TTI), ORE(ORE) {} 143fe6060f1SDimitry Andric 144fe6060f1SDimitry Andric bool run(Function &F); 145*0fca6ea1SDimitry Andric bool LoopInfoBroken; 146fe6060f1SDimitry Andric 147fe6060f1SDimitry Andric private: 148fe6060f1SDimitry Andric void 149fe6060f1SDimitry Andric unfoldSelectInstrs(DominatorTree *DT, 150fe6060f1SDimitry Andric const SmallVector<SelectInstToUnfold, 4> &SelectInsts) { 151fe6060f1SDimitry Andric DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Eager); 152fe6060f1SDimitry Andric SmallVector<SelectInstToUnfold, 4> Stack; 153fe6060f1SDimitry Andric for (SelectInstToUnfold SIToUnfold : SelectInsts) 154fe6060f1SDimitry Andric Stack.push_back(SIToUnfold); 155fe6060f1SDimitry Andric 156fe6060f1SDimitry Andric while (!Stack.empty()) { 157349cc55cSDimitry Andric SelectInstToUnfold SIToUnfold = Stack.pop_back_val(); 158fe6060f1SDimitry Andric 159fe6060f1SDimitry Andric std::vector<SelectInstToUnfold> NewSIsToUnfold; 160fe6060f1SDimitry Andric std::vector<BasicBlock *> NewBBs; 161*0fca6ea1SDimitry Andric unfold(&DTU, LI, SIToUnfold, &NewSIsToUnfold, &NewBBs); 162fe6060f1SDimitry Andric 163fe6060f1SDimitry Andric // Put newly discovered select instructions into the work list. 164fe6060f1SDimitry Andric for (const SelectInstToUnfold &NewSIToUnfold : NewSIsToUnfold) 165fe6060f1SDimitry Andric Stack.push_back(NewSIToUnfold); 166fe6060f1SDimitry Andric } 167fe6060f1SDimitry Andric } 168fe6060f1SDimitry Andric 169fe6060f1SDimitry Andric AssumptionCache *AC; 170fe6060f1SDimitry Andric DominatorTree *DT; 171*0fca6ea1SDimitry Andric LoopInfo *LI; 172fe6060f1SDimitry Andric TargetTransformInfo *TTI; 173fe6060f1SDimitry Andric OptimizationRemarkEmitter *ORE; 174fe6060f1SDimitry Andric }; 175fe6060f1SDimitry Andric 176fe6060f1SDimitry Andric } // end anonymous namespace 177fe6060f1SDimitry Andric 178fe6060f1SDimitry Andric namespace { 179fe6060f1SDimitry Andric 180fe6060f1SDimitry Andric /// Create a new basic block and sink \p SIToSink into it. 181fe6060f1SDimitry Andric void createBasicBlockAndSinkSelectInst( 182fe6060f1SDimitry Andric DomTreeUpdater *DTU, SelectInst *SI, PHINode *SIUse, SelectInst *SIToSink, 183fe6060f1SDimitry Andric BasicBlock *EndBlock, StringRef NewBBName, BasicBlock **NewBlock, 184fe6060f1SDimitry Andric BranchInst **NewBranch, std::vector<SelectInstToUnfold> *NewSIsToUnfold, 185fe6060f1SDimitry Andric std::vector<BasicBlock *> *NewBBs) { 186fe6060f1SDimitry Andric assert(SIToSink->hasOneUse()); 187fe6060f1SDimitry Andric assert(NewBlock); 188fe6060f1SDimitry Andric assert(NewBranch); 189fe6060f1SDimitry Andric *NewBlock = BasicBlock::Create(SI->getContext(), NewBBName, 190fe6060f1SDimitry Andric EndBlock->getParent(), EndBlock); 191fe6060f1SDimitry Andric NewBBs->push_back(*NewBlock); 192fe6060f1SDimitry Andric *NewBranch = BranchInst::Create(EndBlock, *NewBlock); 193fe6060f1SDimitry Andric SIToSink->moveBefore(*NewBranch); 194fe6060f1SDimitry Andric NewSIsToUnfold->push_back(SelectInstToUnfold(SIToSink, SIUse)); 195fe6060f1SDimitry Andric DTU->applyUpdates({{DominatorTree::Insert, *NewBlock, EndBlock}}); 196fe6060f1SDimitry Andric } 197fe6060f1SDimitry Andric 198fe6060f1SDimitry Andric /// Unfold the select instruction held in \p SIToUnfold by replacing it with 199fe6060f1SDimitry Andric /// control flow. 200fe6060f1SDimitry Andric /// 201fe6060f1SDimitry Andric /// Put newly discovered select instructions into \p NewSIsToUnfold. Put newly 202fe6060f1SDimitry Andric /// created basic blocks into \p NewBBs. 203fe6060f1SDimitry Andric /// 204fe6060f1SDimitry Andric /// TODO: merge it with CodeGenPrepare::optimizeSelectInst() if possible. 205*0fca6ea1SDimitry Andric void unfold(DomTreeUpdater *DTU, LoopInfo *LI, SelectInstToUnfold SIToUnfold, 206fe6060f1SDimitry Andric std::vector<SelectInstToUnfold> *NewSIsToUnfold, 207fe6060f1SDimitry Andric std::vector<BasicBlock *> *NewBBs) { 208fe6060f1SDimitry Andric SelectInst *SI = SIToUnfold.getInst(); 209fe6060f1SDimitry Andric PHINode *SIUse = SIToUnfold.getUse(); 210fe6060f1SDimitry Andric BasicBlock *StartBlock = SI->getParent(); 211fe6060f1SDimitry Andric BasicBlock *EndBlock = SIUse->getParent(); 212fe6060f1SDimitry Andric BranchInst *StartBlockTerm = 213fe6060f1SDimitry Andric dyn_cast<BranchInst>(StartBlock->getTerminator()); 214fe6060f1SDimitry Andric 215fe6060f1SDimitry Andric assert(StartBlockTerm && StartBlockTerm->isUnconditional()); 216fe6060f1SDimitry Andric assert(SI->hasOneUse()); 217fe6060f1SDimitry Andric 218fe6060f1SDimitry Andric // These are the new basic blocks for the conditional branch. 219fe6060f1SDimitry Andric // At least one will become an actual new basic block. 220fe6060f1SDimitry Andric BasicBlock *TrueBlock = nullptr; 221fe6060f1SDimitry Andric BasicBlock *FalseBlock = nullptr; 222fe6060f1SDimitry Andric BranchInst *TrueBranch = nullptr; 223fe6060f1SDimitry Andric BranchInst *FalseBranch = nullptr; 224fe6060f1SDimitry Andric 225fe6060f1SDimitry Andric // Sink select instructions to be able to unfold them later. 226fe6060f1SDimitry Andric if (SelectInst *SIOp = dyn_cast<SelectInst>(SI->getTrueValue())) { 227fe6060f1SDimitry Andric createBasicBlockAndSinkSelectInst(DTU, SI, SIUse, SIOp, EndBlock, 228fe6060f1SDimitry Andric "si.unfold.true", &TrueBlock, &TrueBranch, 229fe6060f1SDimitry Andric NewSIsToUnfold, NewBBs); 230fe6060f1SDimitry Andric } 231fe6060f1SDimitry Andric if (SelectInst *SIOp = dyn_cast<SelectInst>(SI->getFalseValue())) { 232fe6060f1SDimitry Andric createBasicBlockAndSinkSelectInst(DTU, SI, SIUse, SIOp, EndBlock, 233fe6060f1SDimitry Andric "si.unfold.false", &FalseBlock, 234fe6060f1SDimitry Andric &FalseBranch, NewSIsToUnfold, NewBBs); 235fe6060f1SDimitry Andric } 236fe6060f1SDimitry Andric 237fe6060f1SDimitry Andric // If there was nothing to sink, then arbitrarily choose the 'false' side 238fe6060f1SDimitry Andric // for a new input value to the PHI. 239fe6060f1SDimitry Andric if (!TrueBlock && !FalseBlock) { 240fe6060f1SDimitry Andric FalseBlock = BasicBlock::Create(SI->getContext(), "si.unfold.false", 241fe6060f1SDimitry Andric EndBlock->getParent(), EndBlock); 242fe6060f1SDimitry Andric NewBBs->push_back(FalseBlock); 243fe6060f1SDimitry Andric BranchInst::Create(EndBlock, FalseBlock); 244fe6060f1SDimitry Andric DTU->applyUpdates({{DominatorTree::Insert, FalseBlock, EndBlock}}); 245fe6060f1SDimitry Andric } 246fe6060f1SDimitry Andric 247fe6060f1SDimitry Andric // Insert the real conditional branch based on the original condition. 248fe6060f1SDimitry Andric // If we did not create a new block for one of the 'true' or 'false' paths 249fe6060f1SDimitry Andric // of the condition, it means that side of the branch goes to the end block 250fe6060f1SDimitry Andric // directly and the path originates from the start block from the point of 251fe6060f1SDimitry Andric // view of the new PHI. 252fe6060f1SDimitry Andric BasicBlock *TT = EndBlock; 253fe6060f1SDimitry Andric BasicBlock *FT = EndBlock; 254fe6060f1SDimitry Andric if (TrueBlock && FalseBlock) { 255fe6060f1SDimitry Andric // A diamond. 256fe6060f1SDimitry Andric TT = TrueBlock; 257fe6060f1SDimitry Andric FT = FalseBlock; 258fe6060f1SDimitry Andric 259fe6060f1SDimitry Andric // Update the phi node of SI. 260fe6060f1SDimitry Andric SIUse->addIncoming(SI->getTrueValue(), TrueBlock); 261fe6060f1SDimitry Andric SIUse->addIncoming(SI->getFalseValue(), FalseBlock); 262fe6060f1SDimitry Andric 263fe6060f1SDimitry Andric // Update any other PHI nodes in EndBlock. 264fe6060f1SDimitry Andric for (PHINode &Phi : EndBlock->phis()) { 265fe6060f1SDimitry Andric if (&Phi != SIUse) { 2665f757f3fSDimitry Andric Value *OrigValue = Phi.getIncomingValueForBlock(StartBlock); 2675f757f3fSDimitry Andric Phi.addIncoming(OrigValue, TrueBlock); 2685f757f3fSDimitry Andric Phi.addIncoming(OrigValue, FalseBlock); 269fe6060f1SDimitry Andric } 2705f757f3fSDimitry Andric 2715f757f3fSDimitry Andric // Remove incoming place of original StartBlock, which comes in a indirect 2725f757f3fSDimitry Andric // way (through TrueBlock and FalseBlock) now. 2735f757f3fSDimitry Andric Phi.removeIncomingValue(StartBlock, /* DeletePHIIfEmpty = */ false); 274fe6060f1SDimitry Andric } 275fe6060f1SDimitry Andric } else { 276fe6060f1SDimitry Andric BasicBlock *NewBlock = nullptr; 277fe6060f1SDimitry Andric Value *SIOp1 = SI->getTrueValue(); 278fe6060f1SDimitry Andric Value *SIOp2 = SI->getFalseValue(); 279fe6060f1SDimitry Andric 280fe6060f1SDimitry Andric // A triangle pointing right. 281fe6060f1SDimitry Andric if (!TrueBlock) { 282fe6060f1SDimitry Andric NewBlock = FalseBlock; 283fe6060f1SDimitry Andric FT = FalseBlock; 284fe6060f1SDimitry Andric } 285fe6060f1SDimitry Andric // A triangle pointing left. 286fe6060f1SDimitry Andric else { 287fe6060f1SDimitry Andric NewBlock = TrueBlock; 288fe6060f1SDimitry Andric TT = TrueBlock; 289fe6060f1SDimitry Andric std::swap(SIOp1, SIOp2); 290fe6060f1SDimitry Andric } 291fe6060f1SDimitry Andric 292fe6060f1SDimitry Andric // Update the phi node of SI. 293fe6060f1SDimitry Andric for (unsigned Idx = 0; Idx < SIUse->getNumIncomingValues(); ++Idx) { 294fe6060f1SDimitry Andric if (SIUse->getIncomingBlock(Idx) == StartBlock) 295fe6060f1SDimitry Andric SIUse->setIncomingValue(Idx, SIOp1); 296fe6060f1SDimitry Andric } 297fe6060f1SDimitry Andric SIUse->addIncoming(SIOp2, NewBlock); 298fe6060f1SDimitry Andric 299fe6060f1SDimitry Andric // Update any other PHI nodes in EndBlock. 300fe6060f1SDimitry Andric for (auto II = EndBlock->begin(); PHINode *Phi = dyn_cast<PHINode>(II); 301fe6060f1SDimitry Andric ++II) { 302fe6060f1SDimitry Andric if (Phi != SIUse) 303fe6060f1SDimitry Andric Phi->addIncoming(Phi->getIncomingValueForBlock(StartBlock), NewBlock); 304fe6060f1SDimitry Andric } 305fe6060f1SDimitry Andric } 306fe6060f1SDimitry Andric StartBlockTerm->eraseFromParent(); 307fe6060f1SDimitry Andric BranchInst::Create(TT, FT, SI->getCondition(), StartBlock); 308fe6060f1SDimitry Andric DTU->applyUpdates({{DominatorTree::Insert, StartBlock, TT}, 309fe6060f1SDimitry Andric {DominatorTree::Insert, StartBlock, FT}}); 310fe6060f1SDimitry Andric 311*0fca6ea1SDimitry Andric // Preserve loop info 312*0fca6ea1SDimitry Andric if (Loop *L = LI->getLoopFor(SI->getParent())) { 313*0fca6ea1SDimitry Andric for (BasicBlock *NewBB : *NewBBs) 314*0fca6ea1SDimitry Andric L->addBasicBlockToLoop(NewBB, *LI); 315*0fca6ea1SDimitry Andric } 316*0fca6ea1SDimitry Andric 317fe6060f1SDimitry Andric // The select is now dead. 3185f757f3fSDimitry Andric assert(SI->use_empty() && "Select must be dead now"); 319fe6060f1SDimitry Andric SI->eraseFromParent(); 320fe6060f1SDimitry Andric } 321fe6060f1SDimitry Andric 322fe6060f1SDimitry Andric struct ClonedBlock { 323fe6060f1SDimitry Andric BasicBlock *BB; 3247a6dacacSDimitry Andric APInt State; ///< \p State corresponds to the next value of a switch stmnt. 325fe6060f1SDimitry Andric }; 326fe6060f1SDimitry Andric 327fe6060f1SDimitry Andric typedef std::deque<BasicBlock *> PathType; 328fe6060f1SDimitry Andric typedef std::vector<PathType> PathsType; 329349cc55cSDimitry Andric typedef SmallPtrSet<const BasicBlock *, 8> VisitedBlocks; 330fe6060f1SDimitry Andric typedef std::vector<ClonedBlock> CloneList; 331fe6060f1SDimitry Andric 332fe6060f1SDimitry Andric // This data structure keeps track of all blocks that have been cloned. If two 333fe6060f1SDimitry Andric // different ThreadingPaths clone the same block for a certain state it should 334fe6060f1SDimitry Andric // be reused, and it can be looked up in this map. 335fe6060f1SDimitry Andric typedef DenseMap<BasicBlock *, CloneList> DuplicateBlockMap; 336fe6060f1SDimitry Andric 337fe6060f1SDimitry Andric // This map keeps track of all the new definitions for an instruction. This 338fe6060f1SDimitry Andric // information is needed when restoring SSA form after cloning blocks. 3391fd87a68SDimitry Andric typedef MapVector<Instruction *, std::vector<Instruction *>> DefMap; 340fe6060f1SDimitry Andric 341fe6060f1SDimitry Andric inline raw_ostream &operator<<(raw_ostream &OS, const PathType &Path) { 342fe6060f1SDimitry Andric OS << "< "; 343fe6060f1SDimitry Andric for (const BasicBlock *BB : Path) { 344fe6060f1SDimitry Andric std::string BBName; 345fe6060f1SDimitry Andric if (BB->hasName()) 346fe6060f1SDimitry Andric raw_string_ostream(BBName) << BB->getName(); 347fe6060f1SDimitry Andric else 348fe6060f1SDimitry Andric raw_string_ostream(BBName) << BB; 349fe6060f1SDimitry Andric OS << BBName << " "; 350fe6060f1SDimitry Andric } 351fe6060f1SDimitry Andric OS << ">"; 352fe6060f1SDimitry Andric return OS; 353fe6060f1SDimitry Andric } 354fe6060f1SDimitry Andric 355fe6060f1SDimitry Andric /// ThreadingPath is a path in the control flow of a loop that can be threaded 356fe6060f1SDimitry Andric /// by cloning necessary basic blocks and replacing conditional branches with 357fe6060f1SDimitry Andric /// unconditional ones. A threading path includes a list of basic blocks, the 358fe6060f1SDimitry Andric /// exit state, and the block that determines the next state. 359fe6060f1SDimitry Andric struct ThreadingPath { 360fe6060f1SDimitry Andric /// Exit value is DFA's exit state for the given path. 3617a6dacacSDimitry Andric APInt getExitValue() const { return ExitVal; } 362fe6060f1SDimitry Andric void setExitValue(const ConstantInt *V) { 3637a6dacacSDimitry Andric ExitVal = V->getValue(); 364fe6060f1SDimitry Andric IsExitValSet = true; 365fe6060f1SDimitry Andric } 366fe6060f1SDimitry Andric bool isExitValueSet() const { return IsExitValSet; } 367fe6060f1SDimitry Andric 368fe6060f1SDimitry Andric /// Determinator is the basic block that determines the next state of the DFA. 369fe6060f1SDimitry Andric const BasicBlock *getDeterminatorBB() const { return DBB; } 370fe6060f1SDimitry Andric void setDeterminator(const BasicBlock *BB) { DBB = BB; } 371fe6060f1SDimitry Andric 372fe6060f1SDimitry Andric /// Path is a list of basic blocks. 373fe6060f1SDimitry Andric const PathType &getPath() const { return Path; } 374fe6060f1SDimitry Andric void setPath(const PathType &NewPath) { Path = NewPath; } 375fe6060f1SDimitry Andric 376fe6060f1SDimitry Andric void print(raw_ostream &OS) const { 377fe6060f1SDimitry Andric OS << Path << " [ " << ExitVal << ", " << DBB->getName() << " ]"; 378fe6060f1SDimitry Andric } 379fe6060f1SDimitry Andric 380fe6060f1SDimitry Andric private: 381fe6060f1SDimitry Andric PathType Path; 3827a6dacacSDimitry Andric APInt ExitVal; 383fe6060f1SDimitry Andric const BasicBlock *DBB = nullptr; 384fe6060f1SDimitry Andric bool IsExitValSet = false; 385fe6060f1SDimitry Andric }; 386fe6060f1SDimitry Andric 387fe6060f1SDimitry Andric #ifndef NDEBUG 388fe6060f1SDimitry Andric inline raw_ostream &operator<<(raw_ostream &OS, const ThreadingPath &TPath) { 389fe6060f1SDimitry Andric TPath.print(OS); 390fe6060f1SDimitry Andric return OS; 391fe6060f1SDimitry Andric } 392fe6060f1SDimitry Andric #endif 393fe6060f1SDimitry Andric 394fe6060f1SDimitry Andric struct MainSwitch { 395*0fca6ea1SDimitry Andric MainSwitch(SwitchInst *SI, LoopInfo *LI, OptimizationRemarkEmitter *ORE) 396*0fca6ea1SDimitry Andric : LI(LI) { 39781ad6265SDimitry Andric if (isCandidate(SI)) { 398fe6060f1SDimitry Andric Instr = SI; 399fe6060f1SDimitry Andric } else { 400fe6060f1SDimitry Andric ORE->emit([&]() { 401fe6060f1SDimitry Andric return OptimizationRemarkMissed(DEBUG_TYPE, "SwitchNotPredictable", SI) 402fe6060f1SDimitry Andric << "Switch instruction is not predictable."; 403fe6060f1SDimitry Andric }); 404fe6060f1SDimitry Andric } 405fe6060f1SDimitry Andric } 406fe6060f1SDimitry Andric 407fe6060f1SDimitry Andric virtual ~MainSwitch() = default; 408fe6060f1SDimitry Andric 409fe6060f1SDimitry Andric SwitchInst *getInstr() const { return Instr; } 410fe6060f1SDimitry Andric const SmallVector<SelectInstToUnfold, 4> getSelectInsts() { 411fe6060f1SDimitry Andric return SelectInsts; 412fe6060f1SDimitry Andric } 413fe6060f1SDimitry Andric 414fe6060f1SDimitry Andric private: 41581ad6265SDimitry Andric /// Do a use-def chain traversal starting from the switch condition to see if 41681ad6265SDimitry Andric /// \p SI is a potential condidate. 41781ad6265SDimitry Andric /// 41881ad6265SDimitry Andric /// Also, collect select instructions to unfold. 41981ad6265SDimitry Andric bool isCandidate(const SwitchInst *SI) { 420*0fca6ea1SDimitry Andric std::deque<std::pair<Value *, BasicBlock *>> Q; 421fe6060f1SDimitry Andric SmallSet<Value *, 16> SeenValues; 422fe6060f1SDimitry Andric SelectInsts.clear(); 423fe6060f1SDimitry Andric 42481ad6265SDimitry Andric Value *SICond = SI->getCondition(); 42581ad6265SDimitry Andric LLVM_DEBUG(dbgs() << "\tSICond: " << *SICond << "\n"); 42681ad6265SDimitry Andric if (!isa<PHINode>(SICond)) 427fe6060f1SDimitry Andric return false; 428fe6060f1SDimitry Andric 429*0fca6ea1SDimitry Andric // The switch must be in a loop. 430*0fca6ea1SDimitry Andric const Loop *L = LI->getLoopFor(SI->getParent()); 431*0fca6ea1SDimitry Andric if (!L) 432*0fca6ea1SDimitry Andric return false; 433*0fca6ea1SDimitry Andric 434*0fca6ea1SDimitry Andric addToQueue(SICond, nullptr, Q, SeenValues); 435fe6060f1SDimitry Andric 436fe6060f1SDimitry Andric while (!Q.empty()) { 437*0fca6ea1SDimitry Andric Value *Current = Q.front().first; 438*0fca6ea1SDimitry Andric BasicBlock *CurrentIncomingBB = Q.front().second; 439fe6060f1SDimitry Andric Q.pop_front(); 440fe6060f1SDimitry Andric 441fe6060f1SDimitry Andric if (auto *Phi = dyn_cast<PHINode>(Current)) { 442*0fca6ea1SDimitry Andric for (BasicBlock *IncomingBB : Phi->blocks()) { 443*0fca6ea1SDimitry Andric Value *Incoming = Phi->getIncomingValueForBlock(IncomingBB); 444*0fca6ea1SDimitry Andric addToQueue(Incoming, IncomingBB, Q, SeenValues); 445fe6060f1SDimitry Andric } 44681ad6265SDimitry Andric LLVM_DEBUG(dbgs() << "\tphi: " << *Phi << "\n"); 447fe6060f1SDimitry Andric } else if (SelectInst *SelI = dyn_cast<SelectInst>(Current)) { 448fe6060f1SDimitry Andric if (!isValidSelectInst(SelI)) 449fe6060f1SDimitry Andric return false; 450*0fca6ea1SDimitry Andric addToQueue(SelI->getTrueValue(), CurrentIncomingBB, Q, SeenValues); 451*0fca6ea1SDimitry Andric addToQueue(SelI->getFalseValue(), CurrentIncomingBB, Q, SeenValues); 45281ad6265SDimitry Andric LLVM_DEBUG(dbgs() << "\tselect: " << *SelI << "\n"); 453fe6060f1SDimitry Andric if (auto *SelIUse = dyn_cast<PHINode>(SelI->user_back())) 454fe6060f1SDimitry Andric SelectInsts.push_back(SelectInstToUnfold(SelI, SelIUse)); 45581ad6265SDimitry Andric } else if (isa<Constant>(Current)) { 45681ad6265SDimitry Andric LLVM_DEBUG(dbgs() << "\tconst: " << *Current << "\n"); 45781ad6265SDimitry Andric continue; 458fe6060f1SDimitry Andric } else { 45981ad6265SDimitry Andric LLVM_DEBUG(dbgs() << "\tother: " << *Current << "\n"); 46081ad6265SDimitry Andric // Allow unpredictable values. The hope is that those will be the 46181ad6265SDimitry Andric // initial switch values that can be ignored (they will hit the 46281ad6265SDimitry Andric // unthreaded switch) but this assumption will get checked later after 46381ad6265SDimitry Andric // paths have been enumerated (in function getStateDefMap). 464*0fca6ea1SDimitry Andric 465*0fca6ea1SDimitry Andric // If the unpredictable value comes from the same inner loop it is 466*0fca6ea1SDimitry Andric // likely that it will also be on the enumerated paths, causing us to 467*0fca6ea1SDimitry Andric // exit after we have enumerated all the paths. This heuristic save 468*0fca6ea1SDimitry Andric // compile time because a search for all the paths can become expensive. 469*0fca6ea1SDimitry Andric if (EarlyExitHeuristic && 470*0fca6ea1SDimitry Andric L->contains(LI->getLoopFor(CurrentIncomingBB))) { 471*0fca6ea1SDimitry Andric LLVM_DEBUG(dbgs() 472*0fca6ea1SDimitry Andric << "\tExiting early due to unpredictability heuristic.\n"); 473*0fca6ea1SDimitry Andric return false; 474*0fca6ea1SDimitry Andric } 475*0fca6ea1SDimitry Andric 47681ad6265SDimitry Andric continue; 477fe6060f1SDimitry Andric } 478fe6060f1SDimitry Andric } 479fe6060f1SDimitry Andric 480fe6060f1SDimitry Andric return true; 481fe6060f1SDimitry Andric } 482fe6060f1SDimitry Andric 483*0fca6ea1SDimitry Andric void addToQueue(Value *Val, BasicBlock *BB, 484*0fca6ea1SDimitry Andric std::deque<std::pair<Value *, BasicBlock *>> &Q, 485fe6060f1SDimitry Andric SmallSet<Value *, 16> &SeenValues) { 486349cc55cSDimitry Andric if (SeenValues.contains(Val)) 487fe6060f1SDimitry Andric return; 488*0fca6ea1SDimitry Andric Q.push_back({Val, BB}); 489fe6060f1SDimitry Andric SeenValues.insert(Val); 490fe6060f1SDimitry Andric } 491fe6060f1SDimitry Andric 492fe6060f1SDimitry Andric bool isValidSelectInst(SelectInst *SI) { 493fe6060f1SDimitry Andric if (!SI->hasOneUse()) 494fe6060f1SDimitry Andric return false; 495fe6060f1SDimitry Andric 496fe6060f1SDimitry Andric Instruction *SIUse = dyn_cast<Instruction>(SI->user_back()); 497fe6060f1SDimitry Andric // The use of the select inst should be either a phi or another select. 498fe6060f1SDimitry Andric if (!SIUse && !(isa<PHINode>(SIUse) || isa<SelectInst>(SIUse))) 499fe6060f1SDimitry Andric return false; 500fe6060f1SDimitry Andric 501fe6060f1SDimitry Andric BasicBlock *SIBB = SI->getParent(); 502fe6060f1SDimitry Andric 503fe6060f1SDimitry Andric // Currently, we can only expand select instructions in basic blocks with 504fe6060f1SDimitry Andric // one successor. 505fe6060f1SDimitry Andric BranchInst *SITerm = dyn_cast<BranchInst>(SIBB->getTerminator()); 506fe6060f1SDimitry Andric if (!SITerm || !SITerm->isUnconditional()) 507fe6060f1SDimitry Andric return false; 508fe6060f1SDimitry Andric 5095f757f3fSDimitry Andric // Only fold the select coming from directly where it is defined. 5105f757f3fSDimitry Andric PHINode *PHIUser = dyn_cast<PHINode>(SIUse); 5115f757f3fSDimitry Andric if (PHIUser && PHIUser->getIncomingBlock(*SI->use_begin()) != SIBB) 512fe6060f1SDimitry Andric return false; 513fe6060f1SDimitry Andric 514fe6060f1SDimitry Andric // If select will not be sunk during unfolding, and it is in the same basic 515fe6060f1SDimitry Andric // block as another state defining select, then cannot unfold both. 516fe6060f1SDimitry Andric for (SelectInstToUnfold SIToUnfold : SelectInsts) { 517fe6060f1SDimitry Andric SelectInst *PrevSI = SIToUnfold.getInst(); 518fe6060f1SDimitry Andric if (PrevSI->getTrueValue() != SI && PrevSI->getFalseValue() != SI && 519fe6060f1SDimitry Andric PrevSI->getParent() == SI->getParent()) 520fe6060f1SDimitry Andric return false; 521fe6060f1SDimitry Andric } 522fe6060f1SDimitry Andric 523fe6060f1SDimitry Andric return true; 524fe6060f1SDimitry Andric } 525fe6060f1SDimitry Andric 526*0fca6ea1SDimitry Andric LoopInfo *LI; 527fe6060f1SDimitry Andric SwitchInst *Instr = nullptr; 528fe6060f1SDimitry Andric SmallVector<SelectInstToUnfold, 4> SelectInsts; 529fe6060f1SDimitry Andric }; 530fe6060f1SDimitry Andric 531fe6060f1SDimitry Andric struct AllSwitchPaths { 532*0fca6ea1SDimitry Andric AllSwitchPaths(const MainSwitch *MSwitch, OptimizationRemarkEmitter *ORE, 533*0fca6ea1SDimitry Andric LoopInfo *LI) 534*0fca6ea1SDimitry Andric : Switch(MSwitch->getInstr()), SwitchBlock(Switch->getParent()), ORE(ORE), 535*0fca6ea1SDimitry Andric LI(LI) {} 536fe6060f1SDimitry Andric 537fe6060f1SDimitry Andric std::vector<ThreadingPath> &getThreadingPaths() { return TPaths; } 538fe6060f1SDimitry Andric unsigned getNumThreadingPaths() { return TPaths.size(); } 539fe6060f1SDimitry Andric SwitchInst *getSwitchInst() { return Switch; } 540fe6060f1SDimitry Andric BasicBlock *getSwitchBlock() { return SwitchBlock; } 541fe6060f1SDimitry Andric 542fe6060f1SDimitry Andric void run() { 543fe6060f1SDimitry Andric VisitedBlocks Visited; 544fe6060f1SDimitry Andric PathsType LoopPaths = paths(SwitchBlock, Visited, /* PathDepth = */ 1); 54581ad6265SDimitry Andric StateDefMap StateDef = getStateDefMap(LoopPaths); 54681ad6265SDimitry Andric 54781ad6265SDimitry Andric if (StateDef.empty()) { 54881ad6265SDimitry Andric ORE->emit([&]() { 54981ad6265SDimitry Andric return OptimizationRemarkMissed(DEBUG_TYPE, "SwitchNotPredictable", 55081ad6265SDimitry Andric Switch) 55181ad6265SDimitry Andric << "Switch instruction is not predictable."; 55281ad6265SDimitry Andric }); 55381ad6265SDimitry Andric return; 55481ad6265SDimitry Andric } 555fe6060f1SDimitry Andric 556*0fca6ea1SDimitry Andric for (const PathType &Path : LoopPaths) { 557fe6060f1SDimitry Andric ThreadingPath TPath; 558fe6060f1SDimitry Andric 559fe6060f1SDimitry Andric const BasicBlock *PrevBB = Path.back(); 560fe6060f1SDimitry Andric for (const BasicBlock *BB : Path) { 561cb14a3feSDimitry Andric if (StateDef.contains(BB)) { 562fe6060f1SDimitry Andric const PHINode *Phi = dyn_cast<PHINode>(StateDef[BB]); 563fe6060f1SDimitry Andric assert(Phi && "Expected a state-defining instr to be a phi node."); 564fe6060f1SDimitry Andric 565fe6060f1SDimitry Andric const Value *V = Phi->getIncomingValueForBlock(PrevBB); 566fe6060f1SDimitry Andric if (const ConstantInt *C = dyn_cast<const ConstantInt>(V)) { 567fe6060f1SDimitry Andric TPath.setExitValue(C); 568fe6060f1SDimitry Andric TPath.setDeterminator(BB); 569fe6060f1SDimitry Andric TPath.setPath(Path); 570fe6060f1SDimitry Andric } 571fe6060f1SDimitry Andric } 572fe6060f1SDimitry Andric 573fe6060f1SDimitry Andric // Switch block is the determinator, this is the final exit value. 574fe6060f1SDimitry Andric if (TPath.isExitValueSet() && BB == Path.front()) 575fe6060f1SDimitry Andric break; 576fe6060f1SDimitry Andric 577fe6060f1SDimitry Andric PrevBB = BB; 578fe6060f1SDimitry Andric } 579fe6060f1SDimitry Andric 5800eae32dcSDimitry Andric if (TPath.isExitValueSet() && isSupported(TPath)) 581fe6060f1SDimitry Andric TPaths.push_back(TPath); 582fe6060f1SDimitry Andric } 583fe6060f1SDimitry Andric } 584fe6060f1SDimitry Andric 585fe6060f1SDimitry Andric private: 586fe6060f1SDimitry Andric // Value: an instruction that defines a switch state; 587fe6060f1SDimitry Andric // Key: the parent basic block of that instruction. 588fe6060f1SDimitry Andric typedef DenseMap<const BasicBlock *, const PHINode *> StateDefMap; 589fe6060f1SDimitry Andric 590fe6060f1SDimitry Andric PathsType paths(BasicBlock *BB, VisitedBlocks &Visited, 591fe6060f1SDimitry Andric unsigned PathDepth) const { 592fe6060f1SDimitry Andric PathsType Res; 593fe6060f1SDimitry Andric 594fe6060f1SDimitry Andric // Stop exploring paths after visiting MaxPathLength blocks 595fe6060f1SDimitry Andric if (PathDepth > MaxPathLength) { 596fe6060f1SDimitry Andric ORE->emit([&]() { 597fe6060f1SDimitry Andric return OptimizationRemarkAnalysis(DEBUG_TYPE, "MaxPathLengthReached", 598fe6060f1SDimitry Andric Switch) 599fe6060f1SDimitry Andric << "Exploration stopped after visiting MaxPathLength=" 600fe6060f1SDimitry Andric << ore::NV("MaxPathLength", MaxPathLength) << " blocks."; 601fe6060f1SDimitry Andric }); 602fe6060f1SDimitry Andric return Res; 603fe6060f1SDimitry Andric } 604fe6060f1SDimitry Andric 605fe6060f1SDimitry Andric Visited.insert(BB); 606fe6060f1SDimitry Andric 607*0fca6ea1SDimitry Andric // Stop if we have reached the BB out of loop, since its successors have no 608*0fca6ea1SDimitry Andric // impact on the DFA. 609*0fca6ea1SDimitry Andric // TODO: Do we need to stop exploring if BB is the outer loop of the switch? 610*0fca6ea1SDimitry Andric if (!LI->getLoopFor(BB)) 611*0fca6ea1SDimitry Andric return Res; 612*0fca6ea1SDimitry Andric 613fe6060f1SDimitry Andric // Some blocks have multiple edges to the same successor, and this set 614fe6060f1SDimitry Andric // is used to prevent a duplicate path from being generated 615fe6060f1SDimitry Andric SmallSet<BasicBlock *, 4> Successors; 616349cc55cSDimitry Andric for (BasicBlock *Succ : successors(BB)) { 617349cc55cSDimitry Andric if (!Successors.insert(Succ).second) 618fe6060f1SDimitry Andric continue; 619fe6060f1SDimitry Andric 620fe6060f1SDimitry Andric // Found a cycle through the SwitchBlock 621fe6060f1SDimitry Andric if (Succ == SwitchBlock) { 622fe6060f1SDimitry Andric Res.push_back({BB}); 623fe6060f1SDimitry Andric continue; 624fe6060f1SDimitry Andric } 625fe6060f1SDimitry Andric 626fe6060f1SDimitry Andric // We have encountered a cycle, do not get caught in it 627349cc55cSDimitry Andric if (Visited.contains(Succ)) 628fe6060f1SDimitry Andric continue; 629fe6060f1SDimitry Andric 630fe6060f1SDimitry Andric PathsType SuccPaths = paths(Succ, Visited, PathDepth + 1); 63106c3fb27SDimitry Andric for (const PathType &Path : SuccPaths) { 632fe6060f1SDimitry Andric PathType NewPath(Path); 633fe6060f1SDimitry Andric NewPath.push_front(BB); 634fe6060f1SDimitry Andric Res.push_back(NewPath); 63581ad6265SDimitry Andric if (Res.size() >= MaxNumPaths) { 63681ad6265SDimitry Andric return Res; 63781ad6265SDimitry Andric } 638fe6060f1SDimitry Andric } 639fe6060f1SDimitry Andric } 640fe6060f1SDimitry Andric // This block could now be visited again from a different predecessor. Note 641fe6060f1SDimitry Andric // that this will result in exponential runtime. Subpaths could possibly be 642fe6060f1SDimitry Andric // cached but it takes a lot of memory to store them. 643fe6060f1SDimitry Andric Visited.erase(BB); 644fe6060f1SDimitry Andric return Res; 645fe6060f1SDimitry Andric } 646fe6060f1SDimitry Andric 647fe6060f1SDimitry Andric /// Walk the use-def chain and collect all the state-defining instructions. 64881ad6265SDimitry Andric /// 64981ad6265SDimitry Andric /// Return an empty map if unpredictable values encountered inside the basic 65081ad6265SDimitry Andric /// blocks of \p LoopPaths. 65181ad6265SDimitry Andric StateDefMap getStateDefMap(const PathsType &LoopPaths) const { 652fe6060f1SDimitry Andric StateDefMap Res; 653fe6060f1SDimitry Andric 65481ad6265SDimitry Andric // Basic blocks belonging to any of the loops around the switch statement. 65581ad6265SDimitry Andric SmallPtrSet<BasicBlock *, 16> LoopBBs; 65681ad6265SDimitry Andric for (const PathType &Path : LoopPaths) { 65781ad6265SDimitry Andric for (BasicBlock *BB : Path) 65881ad6265SDimitry Andric LoopBBs.insert(BB); 65981ad6265SDimitry Andric } 66081ad6265SDimitry Andric 661fe6060f1SDimitry Andric Value *FirstDef = Switch->getOperand(0); 662fe6060f1SDimitry Andric 66381ad6265SDimitry Andric assert(isa<PHINode>(FirstDef) && "The first definition must be a phi."); 664fe6060f1SDimitry Andric 665fe6060f1SDimitry Andric SmallVector<PHINode *, 8> Stack; 666fe6060f1SDimitry Andric Stack.push_back(dyn_cast<PHINode>(FirstDef)); 667fe6060f1SDimitry Andric SmallSet<Value *, 16> SeenValues; 668fe6060f1SDimitry Andric 669fe6060f1SDimitry Andric while (!Stack.empty()) { 670349cc55cSDimitry Andric PHINode *CurPhi = Stack.pop_back_val(); 671fe6060f1SDimitry Andric 672fe6060f1SDimitry Andric Res[CurPhi->getParent()] = CurPhi; 673fe6060f1SDimitry Andric SeenValues.insert(CurPhi); 674fe6060f1SDimitry Andric 67581ad6265SDimitry Andric for (BasicBlock *IncomingBB : CurPhi->blocks()) { 67681ad6265SDimitry Andric Value *Incoming = CurPhi->getIncomingValueForBlock(IncomingBB); 67781ad6265SDimitry Andric bool IsOutsideLoops = LoopBBs.count(IncomingBB) == 0; 678fe6060f1SDimitry Andric if (Incoming == FirstDef || isa<ConstantInt>(Incoming) || 67981ad6265SDimitry Andric SeenValues.contains(Incoming) || IsOutsideLoops) { 680fe6060f1SDimitry Andric continue; 681fe6060f1SDimitry Andric } 682fe6060f1SDimitry Andric 68381ad6265SDimitry Andric // Any unpredictable value inside the loops means we must bail out. 68481ad6265SDimitry Andric if (!isa<PHINode>(Incoming)) 68581ad6265SDimitry Andric return StateDefMap(); 686fe6060f1SDimitry Andric 687fe6060f1SDimitry Andric Stack.push_back(cast<PHINode>(Incoming)); 688fe6060f1SDimitry Andric } 689fe6060f1SDimitry Andric } 690fe6060f1SDimitry Andric 691fe6060f1SDimitry Andric return Res; 692fe6060f1SDimitry Andric } 693fe6060f1SDimitry Andric 6940eae32dcSDimitry Andric /// The determinator BB should precede the switch-defining BB. 6950eae32dcSDimitry Andric /// 6960eae32dcSDimitry Andric /// Otherwise, it is possible that the state defined in the determinator block 6970eae32dcSDimitry Andric /// defines the state for the next iteration of the loop, rather than for the 6980eae32dcSDimitry Andric /// current one. 6990eae32dcSDimitry Andric /// 7000eae32dcSDimitry Andric /// Currently supported paths: 7010eae32dcSDimitry Andric /// \code 7020eae32dcSDimitry Andric /// < switch bb1 determ def > [ 42, determ ] 7030eae32dcSDimitry Andric /// < switch_and_def bb1 determ > [ 42, determ ] 7040eae32dcSDimitry Andric /// < switch_and_def_and_determ bb1 > [ 42, switch_and_def_and_determ ] 7050eae32dcSDimitry Andric /// \endcode 7060eae32dcSDimitry Andric /// 7070eae32dcSDimitry Andric /// Unsupported paths: 7080eae32dcSDimitry Andric /// \code 7090eae32dcSDimitry Andric /// < switch bb1 def determ > [ 43, determ ] 7100eae32dcSDimitry Andric /// < switch_and_determ bb1 def > [ 43, switch_and_determ ] 7110eae32dcSDimitry Andric /// \endcode 7120eae32dcSDimitry Andric bool isSupported(const ThreadingPath &TPath) { 7130eae32dcSDimitry Andric Instruction *SwitchCondI = dyn_cast<Instruction>(Switch->getCondition()); 7140eae32dcSDimitry Andric assert(SwitchCondI); 7150eae32dcSDimitry Andric if (!SwitchCondI) 7160eae32dcSDimitry Andric return false; 7170eae32dcSDimitry Andric 7180eae32dcSDimitry Andric const BasicBlock *SwitchCondDefBB = SwitchCondI->getParent(); 7190eae32dcSDimitry Andric const BasicBlock *SwitchCondUseBB = Switch->getParent(); 7200eae32dcSDimitry Andric const BasicBlock *DeterminatorBB = TPath.getDeterminatorBB(); 7210eae32dcSDimitry Andric 7220eae32dcSDimitry Andric assert( 7230eae32dcSDimitry Andric SwitchCondUseBB == TPath.getPath().front() && 7240eae32dcSDimitry Andric "The first BB in a threading path should have the switch instruction"); 7250eae32dcSDimitry Andric if (SwitchCondUseBB != TPath.getPath().front()) 7260eae32dcSDimitry Andric return false; 7270eae32dcSDimitry Andric 7280eae32dcSDimitry Andric // Make DeterminatorBB the first element in Path. 7290eae32dcSDimitry Andric PathType Path = TPath.getPath(); 730bdd1243dSDimitry Andric auto ItDet = llvm::find(Path, DeterminatorBB); 7310eae32dcSDimitry Andric std::rotate(Path.begin(), ItDet, Path.end()); 7320eae32dcSDimitry Andric 7330eae32dcSDimitry Andric bool IsDetBBSeen = false; 7340eae32dcSDimitry Andric bool IsDefBBSeen = false; 7350eae32dcSDimitry Andric bool IsUseBBSeen = false; 7360eae32dcSDimitry Andric for (BasicBlock *BB : Path) { 7370eae32dcSDimitry Andric if (BB == DeterminatorBB) 7380eae32dcSDimitry Andric IsDetBBSeen = true; 7390eae32dcSDimitry Andric if (BB == SwitchCondDefBB) 7400eae32dcSDimitry Andric IsDefBBSeen = true; 7410eae32dcSDimitry Andric if (BB == SwitchCondUseBB) 7420eae32dcSDimitry Andric IsUseBBSeen = true; 7430eae32dcSDimitry Andric if (IsDetBBSeen && IsUseBBSeen && !IsDefBBSeen) 7440eae32dcSDimitry Andric return false; 7450eae32dcSDimitry Andric } 7460eae32dcSDimitry Andric 7470eae32dcSDimitry Andric return true; 7480eae32dcSDimitry Andric } 7490eae32dcSDimitry Andric 750fe6060f1SDimitry Andric SwitchInst *Switch; 751fe6060f1SDimitry Andric BasicBlock *SwitchBlock; 752fe6060f1SDimitry Andric OptimizationRemarkEmitter *ORE; 753fe6060f1SDimitry Andric std::vector<ThreadingPath> TPaths; 754*0fca6ea1SDimitry Andric LoopInfo *LI; 755fe6060f1SDimitry Andric }; 756fe6060f1SDimitry Andric 757fe6060f1SDimitry Andric struct TransformDFA { 758fe6060f1SDimitry Andric TransformDFA(AllSwitchPaths *SwitchPaths, DominatorTree *DT, 759fe6060f1SDimitry Andric AssumptionCache *AC, TargetTransformInfo *TTI, 760fe6060f1SDimitry Andric OptimizationRemarkEmitter *ORE, 761fe6060f1SDimitry Andric SmallPtrSet<const Value *, 32> EphValues) 762fe6060f1SDimitry Andric : SwitchPaths(SwitchPaths), DT(DT), AC(AC), TTI(TTI), ORE(ORE), 763fe6060f1SDimitry Andric EphValues(EphValues) {} 764fe6060f1SDimitry Andric 765fe6060f1SDimitry Andric void run() { 766fe6060f1SDimitry Andric if (isLegalAndProfitableToTransform()) { 767fe6060f1SDimitry Andric createAllExitPaths(); 768fe6060f1SDimitry Andric NumTransforms++; 769fe6060f1SDimitry Andric } 770fe6060f1SDimitry Andric } 771fe6060f1SDimitry Andric 772fe6060f1SDimitry Andric private: 773fe6060f1SDimitry Andric /// This function performs both a legality check and profitability check at 774fe6060f1SDimitry Andric /// the same time since it is convenient to do so. It iterates through all 775fe6060f1SDimitry Andric /// blocks that will be cloned, and keeps track of the duplication cost. It 776fe6060f1SDimitry Andric /// also returns false if it is illegal to clone some required block. 777fe6060f1SDimitry Andric bool isLegalAndProfitableToTransform() { 778fe6060f1SDimitry Andric CodeMetrics Metrics; 779fe6060f1SDimitry Andric SwitchInst *Switch = SwitchPaths->getSwitchInst(); 780fe6060f1SDimitry Andric 7815f757f3fSDimitry Andric // Don't thread switch without multiple successors. 7825f757f3fSDimitry Andric if (Switch->getNumSuccessors() <= 1) 7835f757f3fSDimitry Andric return false; 7845f757f3fSDimitry Andric 785fe6060f1SDimitry Andric // Note that DuplicateBlockMap is not being used as intended here. It is 786fe6060f1SDimitry Andric // just being used to ensure (BB, State) pairs are only counted once. 787fe6060f1SDimitry Andric DuplicateBlockMap DuplicateMap; 788fe6060f1SDimitry Andric 789fe6060f1SDimitry Andric for (ThreadingPath &TPath : SwitchPaths->getThreadingPaths()) { 790fe6060f1SDimitry Andric PathType PathBBs = TPath.getPath(); 7917a6dacacSDimitry Andric APInt NextState = TPath.getExitValue(); 792fe6060f1SDimitry Andric const BasicBlock *Determinator = TPath.getDeterminatorBB(); 793fe6060f1SDimitry Andric 794fe6060f1SDimitry Andric // Update Metrics for the Switch block, this is always cloned 795fe6060f1SDimitry Andric BasicBlock *BB = SwitchPaths->getSwitchBlock(); 796fe6060f1SDimitry Andric BasicBlock *VisitedBB = getClonedBB(BB, NextState, DuplicateMap); 797fe6060f1SDimitry Andric if (!VisitedBB) { 798fe6060f1SDimitry Andric Metrics.analyzeBasicBlock(BB, *TTI, EphValues); 799fe6060f1SDimitry Andric DuplicateMap[BB].push_back({BB, NextState}); 800fe6060f1SDimitry Andric } 801fe6060f1SDimitry Andric 802fe6060f1SDimitry Andric // If the Switch block is the Determinator, then we can continue since 803fe6060f1SDimitry Andric // this is the only block that is cloned and we already counted for it. 804fe6060f1SDimitry Andric if (PathBBs.front() == Determinator) 805fe6060f1SDimitry Andric continue; 806fe6060f1SDimitry Andric 807fe6060f1SDimitry Andric // Otherwise update Metrics for all blocks that will be cloned. If any 808fe6060f1SDimitry Andric // block is already cloned and would be reused, don't double count it. 809bdd1243dSDimitry Andric auto DetIt = llvm::find(PathBBs, Determinator); 810fe6060f1SDimitry Andric for (auto BBIt = DetIt; BBIt != PathBBs.end(); BBIt++) { 811fe6060f1SDimitry Andric BB = *BBIt; 812fe6060f1SDimitry Andric VisitedBB = getClonedBB(BB, NextState, DuplicateMap); 813fe6060f1SDimitry Andric if (VisitedBB) 814fe6060f1SDimitry Andric continue; 815fe6060f1SDimitry Andric Metrics.analyzeBasicBlock(BB, *TTI, EphValues); 816fe6060f1SDimitry Andric DuplicateMap[BB].push_back({BB, NextState}); 817fe6060f1SDimitry Andric } 818fe6060f1SDimitry Andric 819fe6060f1SDimitry Andric if (Metrics.notDuplicatable) { 820fe6060f1SDimitry Andric LLVM_DEBUG(dbgs() << "DFA Jump Threading: Not jump threading, contains " 821fe6060f1SDimitry Andric << "non-duplicatable instructions.\n"); 822fe6060f1SDimitry Andric ORE->emit([&]() { 823fe6060f1SDimitry Andric return OptimizationRemarkMissed(DEBUG_TYPE, "NonDuplicatableInst", 824fe6060f1SDimitry Andric Switch) 825fe6060f1SDimitry Andric << "Contains non-duplicatable instructions."; 826fe6060f1SDimitry Andric }); 827fe6060f1SDimitry Andric return false; 828fe6060f1SDimitry Andric } 829fe6060f1SDimitry Andric 830*0fca6ea1SDimitry Andric // FIXME: Allow jump threading with controlled convergence. 831*0fca6ea1SDimitry Andric if (Metrics.Convergence != ConvergenceKind::None) { 832fe6060f1SDimitry Andric LLVM_DEBUG(dbgs() << "DFA Jump Threading: Not jump threading, contains " 833fe6060f1SDimitry Andric << "convergent instructions.\n"); 834fe6060f1SDimitry Andric ORE->emit([&]() { 835fe6060f1SDimitry Andric return OptimizationRemarkMissed(DEBUG_TYPE, "ConvergentInst", Switch) 836fe6060f1SDimitry Andric << "Contains convergent instructions."; 837fe6060f1SDimitry Andric }); 838fe6060f1SDimitry Andric return false; 839fe6060f1SDimitry Andric } 84081ad6265SDimitry Andric 84181ad6265SDimitry Andric if (!Metrics.NumInsts.isValid()) { 84281ad6265SDimitry Andric LLVM_DEBUG(dbgs() << "DFA Jump Threading: Not jump threading, contains " 84381ad6265SDimitry Andric << "instructions with invalid cost.\n"); 84481ad6265SDimitry Andric ORE->emit([&]() { 84581ad6265SDimitry Andric return OptimizationRemarkMissed(DEBUG_TYPE, "ConvergentInst", Switch) 84681ad6265SDimitry Andric << "Contains instructions with invalid cost."; 84781ad6265SDimitry Andric }); 84881ad6265SDimitry Andric return false; 84981ad6265SDimitry Andric } 850fe6060f1SDimitry Andric } 851fe6060f1SDimitry Andric 852bdd1243dSDimitry Andric InstructionCost DuplicationCost = 0; 853fe6060f1SDimitry Andric 854fe6060f1SDimitry Andric unsigned JumpTableSize = 0; 855fe6060f1SDimitry Andric TTI->getEstimatedNumberOfCaseClusters(*Switch, JumpTableSize, nullptr, 856fe6060f1SDimitry Andric nullptr); 857fe6060f1SDimitry Andric if (JumpTableSize == 0) { 858fe6060f1SDimitry Andric // Factor in the number of conditional branches reduced from jump 859fe6060f1SDimitry Andric // threading. Assume that lowering the switch block is implemented by 860fe6060f1SDimitry Andric // using binary search, hence the LogBase2(). 861fe6060f1SDimitry Andric unsigned CondBranches = 862fe6060f1SDimitry Andric APInt(32, Switch->getNumSuccessors()).ceilLogBase2(); 8635f757f3fSDimitry Andric assert(CondBranches > 0 && 8645f757f3fSDimitry Andric "The threaded switch must have multiple branches"); 865bdd1243dSDimitry Andric DuplicationCost = Metrics.NumInsts / CondBranches; 866fe6060f1SDimitry Andric } else { 867fe6060f1SDimitry Andric // Compared with jump tables, the DFA optimizer removes an indirect branch 868fe6060f1SDimitry Andric // on each loop iteration, thus making branch prediction more precise. The 869fe6060f1SDimitry Andric // more branch targets there are, the more likely it is for the branch 870fe6060f1SDimitry Andric // predictor to make a mistake, and the more benefit there is in the DFA 871fe6060f1SDimitry Andric // optimizer. Thus, the more branch targets there are, the lower is the 872fe6060f1SDimitry Andric // cost of the DFA opt. 873bdd1243dSDimitry Andric DuplicationCost = Metrics.NumInsts / JumpTableSize; 874fe6060f1SDimitry Andric } 875fe6060f1SDimitry Andric 876fe6060f1SDimitry Andric LLVM_DEBUG(dbgs() << "\nDFA Jump Threading: Cost to jump thread block " 877fe6060f1SDimitry Andric << SwitchPaths->getSwitchBlock()->getName() 878fe6060f1SDimitry Andric << " is: " << DuplicationCost << "\n\n"); 879fe6060f1SDimitry Andric 880fe6060f1SDimitry Andric if (DuplicationCost > CostThreshold) { 881fe6060f1SDimitry Andric LLVM_DEBUG(dbgs() << "Not jump threading, duplication cost exceeds the " 882fe6060f1SDimitry Andric << "cost threshold.\n"); 883fe6060f1SDimitry Andric ORE->emit([&]() { 884fe6060f1SDimitry Andric return OptimizationRemarkMissed(DEBUG_TYPE, "NotProfitable", Switch) 885fe6060f1SDimitry Andric << "Duplication cost exceeds the cost threshold (cost=" 886fe6060f1SDimitry Andric << ore::NV("Cost", DuplicationCost) 887fe6060f1SDimitry Andric << ", threshold=" << ore::NV("Threshold", CostThreshold) << ")."; 888fe6060f1SDimitry Andric }); 889fe6060f1SDimitry Andric return false; 890fe6060f1SDimitry Andric } 891fe6060f1SDimitry Andric 892fe6060f1SDimitry Andric ORE->emit([&]() { 893fe6060f1SDimitry Andric return OptimizationRemark(DEBUG_TYPE, "JumpThreaded", Switch) 894fe6060f1SDimitry Andric << "Switch statement jump-threaded."; 895fe6060f1SDimitry Andric }); 896fe6060f1SDimitry Andric 897fe6060f1SDimitry Andric return true; 898fe6060f1SDimitry Andric } 899fe6060f1SDimitry Andric 900fe6060f1SDimitry Andric /// Transform each threading path to effectively jump thread the DFA. 901fe6060f1SDimitry Andric void createAllExitPaths() { 902fe6060f1SDimitry Andric DomTreeUpdater DTU(*DT, DomTreeUpdater::UpdateStrategy::Eager); 903fe6060f1SDimitry Andric 904fe6060f1SDimitry Andric // Move the switch block to the end of the path, since it will be duplicated 905fe6060f1SDimitry Andric BasicBlock *SwitchBlock = SwitchPaths->getSwitchBlock(); 906fe6060f1SDimitry Andric for (ThreadingPath &TPath : SwitchPaths->getThreadingPaths()) { 907fe6060f1SDimitry Andric LLVM_DEBUG(dbgs() << TPath << "\n"); 908fe6060f1SDimitry Andric PathType NewPath(TPath.getPath()); 909fe6060f1SDimitry Andric NewPath.push_back(SwitchBlock); 910fe6060f1SDimitry Andric TPath.setPath(NewPath); 911fe6060f1SDimitry Andric } 912fe6060f1SDimitry Andric 913fe6060f1SDimitry Andric // Transform the ThreadingPaths and keep track of the cloned values 914fe6060f1SDimitry Andric DuplicateBlockMap DuplicateMap; 915fe6060f1SDimitry Andric DefMap NewDefs; 916fe6060f1SDimitry Andric 917fe6060f1SDimitry Andric SmallSet<BasicBlock *, 16> BlocksToClean; 918fe6060f1SDimitry Andric for (BasicBlock *BB : successors(SwitchBlock)) 919fe6060f1SDimitry Andric BlocksToClean.insert(BB); 920fe6060f1SDimitry Andric 921fe6060f1SDimitry Andric for (ThreadingPath &TPath : SwitchPaths->getThreadingPaths()) { 922fe6060f1SDimitry Andric createExitPath(NewDefs, TPath, DuplicateMap, BlocksToClean, &DTU); 923fe6060f1SDimitry Andric NumPaths++; 924fe6060f1SDimitry Andric } 925fe6060f1SDimitry Andric 926fe6060f1SDimitry Andric // After all paths are cloned, now update the last successor of the cloned 927fe6060f1SDimitry Andric // path so it skips over the switch statement 928fe6060f1SDimitry Andric for (ThreadingPath &TPath : SwitchPaths->getThreadingPaths()) 929fe6060f1SDimitry Andric updateLastSuccessor(TPath, DuplicateMap, &DTU); 930fe6060f1SDimitry Andric 931fe6060f1SDimitry Andric // For each instruction that was cloned and used outside, update its uses 932fe6060f1SDimitry Andric updateSSA(NewDefs); 933fe6060f1SDimitry Andric 934fe6060f1SDimitry Andric // Clean PHI Nodes for the newly created blocks 935fe6060f1SDimitry Andric for (BasicBlock *BB : BlocksToClean) 936fe6060f1SDimitry Andric cleanPhiNodes(BB); 937fe6060f1SDimitry Andric } 938fe6060f1SDimitry Andric 939fe6060f1SDimitry Andric /// For a specific ThreadingPath \p Path, create an exit path starting from 940fe6060f1SDimitry Andric /// the determinator block. 941fe6060f1SDimitry Andric /// 942fe6060f1SDimitry Andric /// To remember the correct destination, we have to duplicate blocks 943fe6060f1SDimitry Andric /// corresponding to each state. Also update the terminating instruction of 944fe6060f1SDimitry Andric /// the predecessors, and phis in the successor blocks. 945fe6060f1SDimitry Andric void createExitPath(DefMap &NewDefs, ThreadingPath &Path, 946fe6060f1SDimitry Andric DuplicateBlockMap &DuplicateMap, 947fe6060f1SDimitry Andric SmallSet<BasicBlock *, 16> &BlocksToClean, 948fe6060f1SDimitry Andric DomTreeUpdater *DTU) { 9497a6dacacSDimitry Andric APInt NextState = Path.getExitValue(); 950fe6060f1SDimitry Andric const BasicBlock *Determinator = Path.getDeterminatorBB(); 951fe6060f1SDimitry Andric PathType PathBBs = Path.getPath(); 952fe6060f1SDimitry Andric 953fe6060f1SDimitry Andric // Don't select the placeholder block in front 954fe6060f1SDimitry Andric if (PathBBs.front() == Determinator) 955fe6060f1SDimitry Andric PathBBs.pop_front(); 956fe6060f1SDimitry Andric 957bdd1243dSDimitry Andric auto DetIt = llvm::find(PathBBs, Determinator); 9587a6dacacSDimitry Andric // When there is only one BB in PathBBs, the determinator takes itself as a 9597a6dacacSDimitry Andric // direct predecessor. 9607a6dacacSDimitry Andric BasicBlock *PrevBB = PathBBs.size() == 1 ? *DetIt : *std::prev(DetIt); 961fe6060f1SDimitry Andric for (auto BBIt = DetIt; BBIt != PathBBs.end(); BBIt++) { 962fe6060f1SDimitry Andric BasicBlock *BB = *BBIt; 963fe6060f1SDimitry Andric BlocksToClean.insert(BB); 964fe6060f1SDimitry Andric 965fe6060f1SDimitry Andric // We already cloned BB for this NextState, now just update the branch 966fe6060f1SDimitry Andric // and continue. 967fe6060f1SDimitry Andric BasicBlock *NextBB = getClonedBB(BB, NextState, DuplicateMap); 968fe6060f1SDimitry Andric if (NextBB) { 969fe6060f1SDimitry Andric updatePredecessor(PrevBB, BB, NextBB, DTU); 970fe6060f1SDimitry Andric PrevBB = NextBB; 971fe6060f1SDimitry Andric continue; 972fe6060f1SDimitry Andric } 973fe6060f1SDimitry Andric 974fe6060f1SDimitry Andric // Clone the BB and update the successor of Prev to jump to the new block 975fe6060f1SDimitry Andric BasicBlock *NewBB = cloneBlockAndUpdatePredecessor( 976fe6060f1SDimitry Andric BB, PrevBB, NextState, DuplicateMap, NewDefs, DTU); 977fe6060f1SDimitry Andric DuplicateMap[BB].push_back({NewBB, NextState}); 978fe6060f1SDimitry Andric BlocksToClean.insert(NewBB); 979fe6060f1SDimitry Andric PrevBB = NewBB; 980fe6060f1SDimitry Andric } 981fe6060f1SDimitry Andric } 982fe6060f1SDimitry Andric 983fe6060f1SDimitry Andric /// Restore SSA form after cloning blocks. 984fe6060f1SDimitry Andric /// 985fe6060f1SDimitry Andric /// Each cloned block creates new defs for a variable, and the uses need to be 986fe6060f1SDimitry Andric /// updated to reflect this. The uses may be replaced with a cloned value, or 987fe6060f1SDimitry Andric /// some derived phi instruction. Note that all uses of a value defined in the 988fe6060f1SDimitry Andric /// same block were already remapped when cloning the block. 989fe6060f1SDimitry Andric void updateSSA(DefMap &NewDefs) { 990fe6060f1SDimitry Andric SSAUpdaterBulk SSAUpdate; 991fe6060f1SDimitry Andric SmallVector<Use *, 16> UsesToRename; 992fe6060f1SDimitry Andric 99306c3fb27SDimitry Andric for (const auto &KV : NewDefs) { 994fe6060f1SDimitry Andric Instruction *I = KV.first; 995fe6060f1SDimitry Andric BasicBlock *BB = I->getParent(); 996fe6060f1SDimitry Andric std::vector<Instruction *> Cloned = KV.second; 997fe6060f1SDimitry Andric 998fe6060f1SDimitry Andric // Scan all uses of this instruction to see if it is used outside of its 999fe6060f1SDimitry Andric // block, and if so, record them in UsesToRename. 1000fe6060f1SDimitry Andric for (Use &U : I->uses()) { 1001fe6060f1SDimitry Andric Instruction *User = cast<Instruction>(U.getUser()); 1002fe6060f1SDimitry Andric if (PHINode *UserPN = dyn_cast<PHINode>(User)) { 1003fe6060f1SDimitry Andric if (UserPN->getIncomingBlock(U) == BB) 1004fe6060f1SDimitry Andric continue; 1005fe6060f1SDimitry Andric } else if (User->getParent() == BB) { 1006fe6060f1SDimitry Andric continue; 1007fe6060f1SDimitry Andric } 1008fe6060f1SDimitry Andric 1009fe6060f1SDimitry Andric UsesToRename.push_back(&U); 1010fe6060f1SDimitry Andric } 1011fe6060f1SDimitry Andric 1012fe6060f1SDimitry Andric // If there are no uses outside the block, we're done with this 1013fe6060f1SDimitry Andric // instruction. 1014fe6060f1SDimitry Andric if (UsesToRename.empty()) 1015fe6060f1SDimitry Andric continue; 1016fe6060f1SDimitry Andric LLVM_DEBUG(dbgs() << "DFA-JT: Renaming non-local uses of: " << *I 1017fe6060f1SDimitry Andric << "\n"); 1018fe6060f1SDimitry Andric 1019fe6060f1SDimitry Andric // We found a use of I outside of BB. Rename all uses of I that are 1020fe6060f1SDimitry Andric // outside its block to be uses of the appropriate PHI node etc. See 1021fe6060f1SDimitry Andric // ValuesInBlocks with the values we know. 1022fe6060f1SDimitry Andric unsigned VarNum = SSAUpdate.AddVariable(I->getName(), I->getType()); 1023fe6060f1SDimitry Andric SSAUpdate.AddAvailableValue(VarNum, BB, I); 1024fe6060f1SDimitry Andric for (Instruction *New : Cloned) 1025fe6060f1SDimitry Andric SSAUpdate.AddAvailableValue(VarNum, New->getParent(), New); 1026fe6060f1SDimitry Andric 1027fe6060f1SDimitry Andric while (!UsesToRename.empty()) 1028fe6060f1SDimitry Andric SSAUpdate.AddUse(VarNum, UsesToRename.pop_back_val()); 1029fe6060f1SDimitry Andric 1030fe6060f1SDimitry Andric LLVM_DEBUG(dbgs() << "\n"); 1031fe6060f1SDimitry Andric } 1032fe6060f1SDimitry Andric // SSAUpdater handles phi placement and renaming uses with the appropriate 1033fe6060f1SDimitry Andric // value. 1034fe6060f1SDimitry Andric SSAUpdate.RewriteAllUses(DT); 1035fe6060f1SDimitry Andric } 1036fe6060f1SDimitry Andric 1037fe6060f1SDimitry Andric /// Clones a basic block, and adds it to the CFG. 1038fe6060f1SDimitry Andric /// 1039fe6060f1SDimitry Andric /// This function also includes updating phi nodes in the successors of the 1040fe6060f1SDimitry Andric /// BB, and remapping uses that were defined locally in the cloned BB. 1041fe6060f1SDimitry Andric BasicBlock *cloneBlockAndUpdatePredecessor(BasicBlock *BB, BasicBlock *PrevBB, 10427a6dacacSDimitry Andric const APInt &NextState, 1043fe6060f1SDimitry Andric DuplicateBlockMap &DuplicateMap, 1044fe6060f1SDimitry Andric DefMap &NewDefs, 1045fe6060f1SDimitry Andric DomTreeUpdater *DTU) { 1046fe6060f1SDimitry Andric ValueToValueMapTy VMap; 1047fe6060f1SDimitry Andric BasicBlock *NewBB = CloneBasicBlock( 10487a6dacacSDimitry Andric BB, VMap, ".jt" + std::to_string(NextState.getLimitedValue()), 10497a6dacacSDimitry Andric BB->getParent()); 1050fe6060f1SDimitry Andric NewBB->moveAfter(BB); 1051fe6060f1SDimitry Andric NumCloned++; 1052fe6060f1SDimitry Andric 1053fe6060f1SDimitry Andric for (Instruction &I : *NewBB) { 1054fe6060f1SDimitry Andric // Do not remap operands of PHINode in case a definition in BB is an 1055fe6060f1SDimitry Andric // incoming value to a phi in the same block. This incoming value will 1056fe6060f1SDimitry Andric // be renamed later while restoring SSA. 1057fe6060f1SDimitry Andric if (isa<PHINode>(&I)) 1058fe6060f1SDimitry Andric continue; 1059fe6060f1SDimitry Andric RemapInstruction(&I, VMap, 1060fe6060f1SDimitry Andric RF_IgnoreMissingLocals | RF_NoModuleLevelChanges); 1061fe6060f1SDimitry Andric if (AssumeInst *II = dyn_cast<AssumeInst>(&I)) 1062fe6060f1SDimitry Andric AC->registerAssumption(II); 1063fe6060f1SDimitry Andric } 1064fe6060f1SDimitry Andric 1065fe6060f1SDimitry Andric updateSuccessorPhis(BB, NewBB, NextState, VMap, DuplicateMap); 1066fe6060f1SDimitry Andric updatePredecessor(PrevBB, BB, NewBB, DTU); 1067fe6060f1SDimitry Andric updateDefMap(NewDefs, VMap); 1068fe6060f1SDimitry Andric 1069fe6060f1SDimitry Andric // Add all successors to the DominatorTree 1070fe6060f1SDimitry Andric SmallPtrSet<BasicBlock *, 4> SuccSet; 1071fe6060f1SDimitry Andric for (auto *SuccBB : successors(NewBB)) { 1072fe6060f1SDimitry Andric if (SuccSet.insert(SuccBB).second) 1073fe6060f1SDimitry Andric DTU->applyUpdates({{DominatorTree::Insert, NewBB, SuccBB}}); 1074fe6060f1SDimitry Andric } 1075fe6060f1SDimitry Andric SuccSet.clear(); 1076fe6060f1SDimitry Andric return NewBB; 1077fe6060f1SDimitry Andric } 1078fe6060f1SDimitry Andric 1079fe6060f1SDimitry Andric /// Update the phi nodes in BB's successors. 1080fe6060f1SDimitry Andric /// 1081fe6060f1SDimitry Andric /// This means creating a new incoming value from NewBB with the new 1082fe6060f1SDimitry Andric /// instruction wherever there is an incoming value from BB. 1083fe6060f1SDimitry Andric void updateSuccessorPhis(BasicBlock *BB, BasicBlock *ClonedBB, 10847a6dacacSDimitry Andric const APInt &NextState, ValueToValueMapTy &VMap, 1085fe6060f1SDimitry Andric DuplicateBlockMap &DuplicateMap) { 1086fe6060f1SDimitry Andric std::vector<BasicBlock *> BlocksToUpdate; 1087fe6060f1SDimitry Andric 1088fe6060f1SDimitry Andric // If BB is the last block in the path, we can simply update the one case 1089fe6060f1SDimitry Andric // successor that will be reached. 1090fe6060f1SDimitry Andric if (BB == SwitchPaths->getSwitchBlock()) { 1091fe6060f1SDimitry Andric SwitchInst *Switch = SwitchPaths->getSwitchInst(); 1092fe6060f1SDimitry Andric BasicBlock *NextCase = getNextCaseSuccessor(Switch, NextState); 1093fe6060f1SDimitry Andric BlocksToUpdate.push_back(NextCase); 1094fe6060f1SDimitry Andric BasicBlock *ClonedSucc = getClonedBB(NextCase, NextState, DuplicateMap); 1095fe6060f1SDimitry Andric if (ClonedSucc) 1096fe6060f1SDimitry Andric BlocksToUpdate.push_back(ClonedSucc); 1097fe6060f1SDimitry Andric } 1098fe6060f1SDimitry Andric // Otherwise update phis in all successors. 1099fe6060f1SDimitry Andric else { 1100fe6060f1SDimitry Andric for (BasicBlock *Succ : successors(BB)) { 1101fe6060f1SDimitry Andric BlocksToUpdate.push_back(Succ); 1102fe6060f1SDimitry Andric 1103fe6060f1SDimitry Andric // Check if a successor has already been cloned for the particular exit 1104fe6060f1SDimitry Andric // value. In this case if a successor was already cloned, the phi nodes 1105fe6060f1SDimitry Andric // in the cloned block should be updated directly. 1106fe6060f1SDimitry Andric BasicBlock *ClonedSucc = getClonedBB(Succ, NextState, DuplicateMap); 1107fe6060f1SDimitry Andric if (ClonedSucc) 1108fe6060f1SDimitry Andric BlocksToUpdate.push_back(ClonedSucc); 1109fe6060f1SDimitry Andric } 1110fe6060f1SDimitry Andric } 1111fe6060f1SDimitry Andric 1112fe6060f1SDimitry Andric // If there is a phi with an incoming value from BB, create a new incoming 1113fe6060f1SDimitry Andric // value for the new predecessor ClonedBB. The value will either be the same 1114fe6060f1SDimitry Andric // value from BB or a cloned value. 1115fe6060f1SDimitry Andric for (BasicBlock *Succ : BlocksToUpdate) { 1116fe6060f1SDimitry Andric for (auto II = Succ->begin(); PHINode *Phi = dyn_cast<PHINode>(II); 1117fe6060f1SDimitry Andric ++II) { 1118fe6060f1SDimitry Andric Value *Incoming = Phi->getIncomingValueForBlock(BB); 1119fe6060f1SDimitry Andric if (Incoming) { 1120fe6060f1SDimitry Andric if (isa<Constant>(Incoming)) { 1121fe6060f1SDimitry Andric Phi->addIncoming(Incoming, ClonedBB); 1122fe6060f1SDimitry Andric continue; 1123fe6060f1SDimitry Andric } 1124fe6060f1SDimitry Andric Value *ClonedVal = VMap[Incoming]; 1125fe6060f1SDimitry Andric if (ClonedVal) 1126fe6060f1SDimitry Andric Phi->addIncoming(ClonedVal, ClonedBB); 1127fe6060f1SDimitry Andric else 1128fe6060f1SDimitry Andric Phi->addIncoming(Incoming, ClonedBB); 1129fe6060f1SDimitry Andric } 1130fe6060f1SDimitry Andric } 1131fe6060f1SDimitry Andric } 1132fe6060f1SDimitry Andric } 1133fe6060f1SDimitry Andric 1134fe6060f1SDimitry Andric /// Sets the successor of PrevBB to be NewBB instead of OldBB. Note that all 1135fe6060f1SDimitry Andric /// other successors are kept as well. 1136fe6060f1SDimitry Andric void updatePredecessor(BasicBlock *PrevBB, BasicBlock *OldBB, 1137fe6060f1SDimitry Andric BasicBlock *NewBB, DomTreeUpdater *DTU) { 1138fe6060f1SDimitry Andric // When a path is reused, there is a chance that predecessors were already 1139fe6060f1SDimitry Andric // updated before. Check if the predecessor needs to be updated first. 1140fe6060f1SDimitry Andric if (!isPredecessor(OldBB, PrevBB)) 1141fe6060f1SDimitry Andric return; 1142fe6060f1SDimitry Andric 1143fe6060f1SDimitry Andric Instruction *PrevTerm = PrevBB->getTerminator(); 1144fe6060f1SDimitry Andric for (unsigned Idx = 0; Idx < PrevTerm->getNumSuccessors(); Idx++) { 1145fe6060f1SDimitry Andric if (PrevTerm->getSuccessor(Idx) == OldBB) { 1146fe6060f1SDimitry Andric OldBB->removePredecessor(PrevBB, /* KeepOneInputPHIs = */ true); 1147fe6060f1SDimitry Andric PrevTerm->setSuccessor(Idx, NewBB); 1148fe6060f1SDimitry Andric } 1149fe6060f1SDimitry Andric } 1150fe6060f1SDimitry Andric DTU->applyUpdates({{DominatorTree::Delete, PrevBB, OldBB}, 1151fe6060f1SDimitry Andric {DominatorTree::Insert, PrevBB, NewBB}}); 1152fe6060f1SDimitry Andric } 1153fe6060f1SDimitry Andric 1154fe6060f1SDimitry Andric /// Add new value mappings to the DefMap to keep track of all new definitions 1155fe6060f1SDimitry Andric /// for a particular instruction. These will be used while updating SSA form. 1156fe6060f1SDimitry Andric void updateDefMap(DefMap &NewDefs, ValueToValueMapTy &VMap) { 11571fd87a68SDimitry Andric SmallVector<std::pair<Instruction *, Instruction *>> NewDefsVector; 11581fd87a68SDimitry Andric NewDefsVector.reserve(VMap.size()); 11591fd87a68SDimitry Andric 1160fe6060f1SDimitry Andric for (auto Entry : VMap) { 1161fe6060f1SDimitry Andric Instruction *Inst = 1162fe6060f1SDimitry Andric dyn_cast<Instruction>(const_cast<Value *>(Entry.first)); 1163fe6060f1SDimitry Andric if (!Inst || !Entry.second || isa<BranchInst>(Inst) || 1164fe6060f1SDimitry Andric isa<SwitchInst>(Inst)) { 1165fe6060f1SDimitry Andric continue; 1166fe6060f1SDimitry Andric } 1167fe6060f1SDimitry Andric 1168fe6060f1SDimitry Andric Instruction *Cloned = dyn_cast<Instruction>(Entry.second); 1169fe6060f1SDimitry Andric if (!Cloned) 1170fe6060f1SDimitry Andric continue; 1171fe6060f1SDimitry Andric 11721fd87a68SDimitry Andric NewDefsVector.push_back({Inst, Cloned}); 1173fe6060f1SDimitry Andric } 11741fd87a68SDimitry Andric 11751fd87a68SDimitry Andric // Sort the defs to get deterministic insertion order into NewDefs. 11761fd87a68SDimitry Andric sort(NewDefsVector, [](const auto &LHS, const auto &RHS) { 11771fd87a68SDimitry Andric if (LHS.first == RHS.first) 11781fd87a68SDimitry Andric return LHS.second->comesBefore(RHS.second); 11791fd87a68SDimitry Andric return LHS.first->comesBefore(RHS.first); 11801fd87a68SDimitry Andric }); 11811fd87a68SDimitry Andric 11821fd87a68SDimitry Andric for (const auto &KV : NewDefsVector) 11831fd87a68SDimitry Andric NewDefs[KV.first].push_back(KV.second); 1184fe6060f1SDimitry Andric } 1185fe6060f1SDimitry Andric 1186fe6060f1SDimitry Andric /// Update the last branch of a particular cloned path to point to the correct 1187fe6060f1SDimitry Andric /// case successor. 1188fe6060f1SDimitry Andric /// 1189fe6060f1SDimitry Andric /// Note that this is an optional step and would have been done in later 1190fe6060f1SDimitry Andric /// optimizations, but it makes the CFG significantly easier to work with. 1191fe6060f1SDimitry Andric void updateLastSuccessor(ThreadingPath &TPath, 1192fe6060f1SDimitry Andric DuplicateBlockMap &DuplicateMap, 1193fe6060f1SDimitry Andric DomTreeUpdater *DTU) { 11947a6dacacSDimitry Andric APInt NextState = TPath.getExitValue(); 1195fe6060f1SDimitry Andric BasicBlock *BB = TPath.getPath().back(); 1196fe6060f1SDimitry Andric BasicBlock *LastBlock = getClonedBB(BB, NextState, DuplicateMap); 1197fe6060f1SDimitry Andric 1198fe6060f1SDimitry Andric // Note multiple paths can end at the same block so check that it is not 1199fe6060f1SDimitry Andric // updated yet 1200fe6060f1SDimitry Andric if (!isa<SwitchInst>(LastBlock->getTerminator())) 1201fe6060f1SDimitry Andric return; 1202fe6060f1SDimitry Andric SwitchInst *Switch = cast<SwitchInst>(LastBlock->getTerminator()); 1203fe6060f1SDimitry Andric BasicBlock *NextCase = getNextCaseSuccessor(Switch, NextState); 1204fe6060f1SDimitry Andric 1205fe6060f1SDimitry Andric std::vector<DominatorTree::UpdateType> DTUpdates; 1206fe6060f1SDimitry Andric SmallPtrSet<BasicBlock *, 4> SuccSet; 1207fe6060f1SDimitry Andric for (BasicBlock *Succ : successors(LastBlock)) { 1208fe6060f1SDimitry Andric if (Succ != NextCase && SuccSet.insert(Succ).second) 1209fe6060f1SDimitry Andric DTUpdates.push_back({DominatorTree::Delete, LastBlock, Succ}); 1210fe6060f1SDimitry Andric } 1211fe6060f1SDimitry Andric 1212fe6060f1SDimitry Andric Switch->eraseFromParent(); 1213fe6060f1SDimitry Andric BranchInst::Create(NextCase, LastBlock); 1214fe6060f1SDimitry Andric 1215fe6060f1SDimitry Andric DTU->applyUpdates(DTUpdates); 1216fe6060f1SDimitry Andric } 1217fe6060f1SDimitry Andric 1218fe6060f1SDimitry Andric /// After cloning blocks, some of the phi nodes have extra incoming values 1219fe6060f1SDimitry Andric /// that are no longer used. This function removes them. 1220fe6060f1SDimitry Andric void cleanPhiNodes(BasicBlock *BB) { 1221fe6060f1SDimitry Andric // If BB is no longer reachable, remove any remaining phi nodes 1222fe6060f1SDimitry Andric if (pred_empty(BB)) { 1223fe6060f1SDimitry Andric std::vector<PHINode *> PhiToRemove; 1224fe6060f1SDimitry Andric for (auto II = BB->begin(); PHINode *Phi = dyn_cast<PHINode>(II); ++II) { 1225fe6060f1SDimitry Andric PhiToRemove.push_back(Phi); 1226fe6060f1SDimitry Andric } 1227fe6060f1SDimitry Andric for (PHINode *PN : PhiToRemove) { 122881ad6265SDimitry Andric PN->replaceAllUsesWith(PoisonValue::get(PN->getType())); 1229fe6060f1SDimitry Andric PN->eraseFromParent(); 1230fe6060f1SDimitry Andric } 1231fe6060f1SDimitry Andric return; 1232fe6060f1SDimitry Andric } 1233fe6060f1SDimitry Andric 1234fe6060f1SDimitry Andric // Remove any incoming values that come from an invalid predecessor 1235fe6060f1SDimitry Andric for (auto II = BB->begin(); PHINode *Phi = dyn_cast<PHINode>(II); ++II) { 1236fe6060f1SDimitry Andric std::vector<BasicBlock *> BlocksToRemove; 1237fe6060f1SDimitry Andric for (BasicBlock *IncomingBB : Phi->blocks()) { 1238fe6060f1SDimitry Andric if (!isPredecessor(BB, IncomingBB)) 1239fe6060f1SDimitry Andric BlocksToRemove.push_back(IncomingBB); 1240fe6060f1SDimitry Andric } 1241fe6060f1SDimitry Andric for (BasicBlock *BB : BlocksToRemove) 1242fe6060f1SDimitry Andric Phi->removeIncomingValue(BB); 1243fe6060f1SDimitry Andric } 1244fe6060f1SDimitry Andric } 1245fe6060f1SDimitry Andric 1246fe6060f1SDimitry Andric /// Checks if BB was already cloned for a particular next state value. If it 1247fe6060f1SDimitry Andric /// was then it returns this cloned block, and otherwise null. 12487a6dacacSDimitry Andric BasicBlock *getClonedBB(BasicBlock *BB, const APInt &NextState, 1249fe6060f1SDimitry Andric DuplicateBlockMap &DuplicateMap) { 1250fe6060f1SDimitry Andric CloneList ClonedBBs = DuplicateMap[BB]; 1251fe6060f1SDimitry Andric 1252fe6060f1SDimitry Andric // Find an entry in the CloneList with this NextState. If it exists then 1253fe6060f1SDimitry Andric // return the corresponding BB 1254fe6060f1SDimitry Andric auto It = llvm::find_if(ClonedBBs, [NextState](const ClonedBlock &C) { 1255fe6060f1SDimitry Andric return C.State == NextState; 1256fe6060f1SDimitry Andric }); 1257fe6060f1SDimitry Andric return It != ClonedBBs.end() ? (*It).BB : nullptr; 1258fe6060f1SDimitry Andric } 1259fe6060f1SDimitry Andric 1260fe6060f1SDimitry Andric /// Helper to get the successor corresponding to a particular case value for 1261fe6060f1SDimitry Andric /// a switch statement. 12627a6dacacSDimitry Andric BasicBlock *getNextCaseSuccessor(SwitchInst *Switch, const APInt &NextState) { 1263fe6060f1SDimitry Andric BasicBlock *NextCase = nullptr; 1264fe6060f1SDimitry Andric for (auto Case : Switch->cases()) { 12657a6dacacSDimitry Andric if (Case.getCaseValue()->getValue() == NextState) { 1266fe6060f1SDimitry Andric NextCase = Case.getCaseSuccessor(); 1267fe6060f1SDimitry Andric break; 1268fe6060f1SDimitry Andric } 1269fe6060f1SDimitry Andric } 1270fe6060f1SDimitry Andric if (!NextCase) 1271fe6060f1SDimitry Andric NextCase = Switch->getDefaultDest(); 1272fe6060f1SDimitry Andric return NextCase; 1273fe6060f1SDimitry Andric } 1274fe6060f1SDimitry Andric 1275fe6060f1SDimitry Andric /// Returns true if IncomingBB is a predecessor of BB. 1276fe6060f1SDimitry Andric bool isPredecessor(BasicBlock *BB, BasicBlock *IncomingBB) { 127781ad6265SDimitry Andric return llvm::is_contained(predecessors(BB), IncomingBB); 1278fe6060f1SDimitry Andric } 1279fe6060f1SDimitry Andric 1280fe6060f1SDimitry Andric AllSwitchPaths *SwitchPaths; 1281fe6060f1SDimitry Andric DominatorTree *DT; 1282fe6060f1SDimitry Andric AssumptionCache *AC; 1283fe6060f1SDimitry Andric TargetTransformInfo *TTI; 1284fe6060f1SDimitry Andric OptimizationRemarkEmitter *ORE; 1285fe6060f1SDimitry Andric SmallPtrSet<const Value *, 32> EphValues; 1286fe6060f1SDimitry Andric std::vector<ThreadingPath> TPaths; 1287fe6060f1SDimitry Andric }; 1288fe6060f1SDimitry Andric 1289fe6060f1SDimitry Andric bool DFAJumpThreading::run(Function &F) { 1290fe6060f1SDimitry Andric LLVM_DEBUG(dbgs() << "\nDFA Jump threading: " << F.getName() << "\n"); 1291fe6060f1SDimitry Andric 1292fe6060f1SDimitry Andric if (F.hasOptSize()) { 1293fe6060f1SDimitry Andric LLVM_DEBUG(dbgs() << "Skipping due to the 'minsize' attribute\n"); 1294fe6060f1SDimitry Andric return false; 1295fe6060f1SDimitry Andric } 1296fe6060f1SDimitry Andric 1297fe6060f1SDimitry Andric if (ClViewCfgBefore) 1298fe6060f1SDimitry Andric F.viewCFG(); 1299fe6060f1SDimitry Andric 1300fe6060f1SDimitry Andric SmallVector<AllSwitchPaths, 2> ThreadableLoops; 1301fe6060f1SDimitry Andric bool MadeChanges = false; 1302*0fca6ea1SDimitry Andric LoopInfoBroken = false; 1303fe6060f1SDimitry Andric 1304fe6060f1SDimitry Andric for (BasicBlock &BB : F) { 1305fe6060f1SDimitry Andric auto *SI = dyn_cast<SwitchInst>(BB.getTerminator()); 1306fe6060f1SDimitry Andric if (!SI) 1307fe6060f1SDimitry Andric continue; 1308fe6060f1SDimitry Andric 1309fe6060f1SDimitry Andric LLVM_DEBUG(dbgs() << "\nCheck if SwitchInst in BB " << BB.getName() 131081ad6265SDimitry Andric << " is a candidate\n"); 1311*0fca6ea1SDimitry Andric MainSwitch Switch(SI, LI, ORE); 1312fe6060f1SDimitry Andric 1313fe6060f1SDimitry Andric if (!Switch.getInstr()) 1314fe6060f1SDimitry Andric continue; 1315fe6060f1SDimitry Andric 1316fe6060f1SDimitry Andric LLVM_DEBUG(dbgs() << "\nSwitchInst in BB " << BB.getName() << " is a " 1317fe6060f1SDimitry Andric << "candidate for jump threading\n"); 1318fe6060f1SDimitry Andric LLVM_DEBUG(SI->dump()); 1319fe6060f1SDimitry Andric 1320fe6060f1SDimitry Andric unfoldSelectInstrs(DT, Switch.getSelectInsts()); 1321fe6060f1SDimitry Andric if (!Switch.getSelectInsts().empty()) 1322fe6060f1SDimitry Andric MadeChanges = true; 1323fe6060f1SDimitry Andric 1324*0fca6ea1SDimitry Andric AllSwitchPaths SwitchPaths(&Switch, ORE, LI); 1325fe6060f1SDimitry Andric SwitchPaths.run(); 1326fe6060f1SDimitry Andric 1327fe6060f1SDimitry Andric if (SwitchPaths.getNumThreadingPaths() > 0) { 1328fe6060f1SDimitry Andric ThreadableLoops.push_back(SwitchPaths); 1329fe6060f1SDimitry Andric 1330fe6060f1SDimitry Andric // For the time being limit this optimization to occurring once in a 1331fe6060f1SDimitry Andric // function since it can change the CFG significantly. This is not a 1332fe6060f1SDimitry Andric // strict requirement but it can cause buggy behavior if there is an 1333fe6060f1SDimitry Andric // overlap of blocks in different opportunities. There is a lot of room to 1334fe6060f1SDimitry Andric // experiment with catching more opportunities here. 1335*0fca6ea1SDimitry Andric // NOTE: To release this contraint, we must handle LoopInfo invalidation 1336fe6060f1SDimitry Andric break; 1337fe6060f1SDimitry Andric } 1338fe6060f1SDimitry Andric } 1339fe6060f1SDimitry Andric 1340*0fca6ea1SDimitry Andric #ifdef NDEBUG 1341*0fca6ea1SDimitry Andric LI->verify(*DT); 1342*0fca6ea1SDimitry Andric #endif 1343*0fca6ea1SDimitry Andric 1344fe6060f1SDimitry Andric SmallPtrSet<const Value *, 32> EphValues; 1345fe6060f1SDimitry Andric if (ThreadableLoops.size() > 0) 1346fe6060f1SDimitry Andric CodeMetrics::collectEphemeralValues(&F, AC, EphValues); 1347fe6060f1SDimitry Andric 1348fe6060f1SDimitry Andric for (AllSwitchPaths SwitchPaths : ThreadableLoops) { 1349fe6060f1SDimitry Andric TransformDFA Transform(&SwitchPaths, DT, AC, TTI, ORE, EphValues); 1350fe6060f1SDimitry Andric Transform.run(); 1351fe6060f1SDimitry Andric MadeChanges = true; 1352*0fca6ea1SDimitry Andric LoopInfoBroken = true; 1353fe6060f1SDimitry Andric } 1354fe6060f1SDimitry Andric 1355fe6060f1SDimitry Andric #ifdef EXPENSIVE_CHECKS 1356fe6060f1SDimitry Andric assert(DT->verify(DominatorTree::VerificationLevel::Full)); 1357fe6060f1SDimitry Andric verifyFunction(F, &dbgs()); 1358fe6060f1SDimitry Andric #endif 1359fe6060f1SDimitry Andric 1360fe6060f1SDimitry Andric return MadeChanges; 1361fe6060f1SDimitry Andric } 1362fe6060f1SDimitry Andric 1363fe6060f1SDimitry Andric } // end anonymous namespace 1364fe6060f1SDimitry Andric 1365fe6060f1SDimitry Andric /// Integrate with the new Pass Manager 1366fe6060f1SDimitry Andric PreservedAnalyses DFAJumpThreadingPass::run(Function &F, 1367fe6060f1SDimitry Andric FunctionAnalysisManager &AM) { 1368fe6060f1SDimitry Andric AssumptionCache &AC = AM.getResult<AssumptionAnalysis>(F); 1369fe6060f1SDimitry Andric DominatorTree &DT = AM.getResult<DominatorTreeAnalysis>(F); 1370*0fca6ea1SDimitry Andric LoopInfo &LI = AM.getResult<LoopAnalysis>(F); 1371fe6060f1SDimitry Andric TargetTransformInfo &TTI = AM.getResult<TargetIRAnalysis>(F); 1372fe6060f1SDimitry Andric OptimizationRemarkEmitter ORE(&F); 1373*0fca6ea1SDimitry Andric DFAJumpThreading ThreadImpl(&AC, &DT, &LI, &TTI, &ORE); 1374*0fca6ea1SDimitry Andric if (!ThreadImpl.run(F)) 1375fe6060f1SDimitry Andric return PreservedAnalyses::all(); 1376fe6060f1SDimitry Andric 1377fe6060f1SDimitry Andric PreservedAnalyses PA; 1378fe6060f1SDimitry Andric PA.preserve<DominatorTreeAnalysis>(); 1379*0fca6ea1SDimitry Andric if (!ThreadImpl.LoopInfoBroken) 1380*0fca6ea1SDimitry Andric PA.preserve<LoopAnalysis>(); 1381fe6060f1SDimitry Andric return PA; 1382fe6060f1SDimitry Andric } 1383