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" 67*81ad6265SDimitry Andric #include "llvm/Analysis/DomTreeUpdater.h" 68fe6060f1SDimitry Andric #include "llvm/Analysis/OptimizationRemarkEmitter.h" 69fe6060f1SDimitry Andric #include "llvm/Analysis/TargetTransformInfo.h" 70fe6060f1SDimitry Andric #include "llvm/IR/CFG.h" 71fe6060f1SDimitry Andric #include "llvm/IR/Constants.h" 72fe6060f1SDimitry Andric #include "llvm/IR/IntrinsicInst.h" 73fe6060f1SDimitry Andric #include "llvm/InitializePasses.h" 74fe6060f1SDimitry Andric #include "llvm/Pass.h" 75fe6060f1SDimitry Andric #include "llvm/Support/CommandLine.h" 76fe6060f1SDimitry Andric #include "llvm/Support/Debug.h" 77fe6060f1SDimitry Andric #include "llvm/Transforms/Scalar.h" 78fe6060f1SDimitry Andric #include "llvm/Transforms/Utils/Cloning.h" 79fe6060f1SDimitry Andric #include "llvm/Transforms/Utils/SSAUpdaterBulk.h" 80fe6060f1SDimitry Andric #include "llvm/Transforms/Utils/ValueMapper.h" 81fe6060f1SDimitry Andric #include <algorithm> 82fe6060f1SDimitry Andric #include <deque> 83fe6060f1SDimitry Andric 84*81ad6265SDimitry Andric #ifdef EXPENSIVE_CHECKS 85*81ad6265SDimitry Andric #include "llvm/IR/Verifier.h" 86*81ad6265SDimitry Andric #endif 87*81ad6265SDimitry Andric 88fe6060f1SDimitry Andric using namespace llvm; 89fe6060f1SDimitry Andric 90fe6060f1SDimitry Andric #define DEBUG_TYPE "dfa-jump-threading" 91fe6060f1SDimitry Andric 92fe6060f1SDimitry Andric STATISTIC(NumTransforms, "Number of transformations done"); 93fe6060f1SDimitry Andric STATISTIC(NumCloned, "Number of blocks cloned"); 94fe6060f1SDimitry Andric STATISTIC(NumPaths, "Number of individual paths threaded"); 95fe6060f1SDimitry Andric 96fe6060f1SDimitry Andric static cl::opt<bool> 97fe6060f1SDimitry Andric ClViewCfgBefore("dfa-jump-view-cfg-before", 98fe6060f1SDimitry Andric cl::desc("View the CFG before DFA Jump Threading"), 99fe6060f1SDimitry Andric cl::Hidden, cl::init(false)); 100fe6060f1SDimitry Andric 101fe6060f1SDimitry Andric static cl::opt<unsigned> MaxPathLength( 102fe6060f1SDimitry Andric "dfa-max-path-length", 103fe6060f1SDimitry Andric cl::desc("Max number of blocks searched to find a threading path"), 104fe6060f1SDimitry Andric cl::Hidden, cl::init(20)); 105fe6060f1SDimitry Andric 106*81ad6265SDimitry Andric static cl::opt<unsigned> MaxNumPaths( 107*81ad6265SDimitry Andric "dfa-max-num-paths", 108*81ad6265SDimitry Andric cl::desc("Max number of paths enumerated around a switch"), 109*81ad6265SDimitry Andric cl::Hidden, cl::init(200)); 110*81ad6265SDimitry Andric 111fe6060f1SDimitry Andric static cl::opt<unsigned> 112fe6060f1SDimitry Andric CostThreshold("dfa-cost-threshold", 113fe6060f1SDimitry Andric cl::desc("Maximum cost accepted for the transformation"), 114fe6060f1SDimitry Andric cl::Hidden, cl::init(50)); 115fe6060f1SDimitry Andric 116fe6060f1SDimitry Andric namespace { 117fe6060f1SDimitry Andric 118fe6060f1SDimitry Andric class SelectInstToUnfold { 119fe6060f1SDimitry Andric SelectInst *SI; 120fe6060f1SDimitry Andric PHINode *SIUse; 121fe6060f1SDimitry Andric 122fe6060f1SDimitry Andric public: 123fe6060f1SDimitry Andric SelectInstToUnfold(SelectInst *SI, PHINode *SIUse) : SI(SI), SIUse(SIUse) {} 124fe6060f1SDimitry Andric 125fe6060f1SDimitry Andric SelectInst *getInst() { return SI; } 126fe6060f1SDimitry Andric PHINode *getUse() { return SIUse; } 127fe6060f1SDimitry Andric 128fe6060f1SDimitry Andric explicit operator bool() const { return SI && SIUse; } 129fe6060f1SDimitry Andric }; 130fe6060f1SDimitry Andric 131fe6060f1SDimitry Andric void unfold(DomTreeUpdater *DTU, SelectInstToUnfold SIToUnfold, 132fe6060f1SDimitry Andric std::vector<SelectInstToUnfold> *NewSIsToUnfold, 133fe6060f1SDimitry Andric std::vector<BasicBlock *> *NewBBs); 134fe6060f1SDimitry Andric 135fe6060f1SDimitry Andric class DFAJumpThreading { 136fe6060f1SDimitry Andric public: 137fe6060f1SDimitry Andric DFAJumpThreading(AssumptionCache *AC, DominatorTree *DT, 138fe6060f1SDimitry Andric TargetTransformInfo *TTI, OptimizationRemarkEmitter *ORE) 139fe6060f1SDimitry Andric : AC(AC), DT(DT), TTI(TTI), ORE(ORE) {} 140fe6060f1SDimitry Andric 141fe6060f1SDimitry Andric bool run(Function &F); 142fe6060f1SDimitry Andric 143fe6060f1SDimitry Andric private: 144fe6060f1SDimitry Andric void 145fe6060f1SDimitry Andric unfoldSelectInstrs(DominatorTree *DT, 146fe6060f1SDimitry Andric const SmallVector<SelectInstToUnfold, 4> &SelectInsts) { 147fe6060f1SDimitry Andric DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Eager); 148fe6060f1SDimitry Andric SmallVector<SelectInstToUnfold, 4> Stack; 149fe6060f1SDimitry Andric for (SelectInstToUnfold SIToUnfold : SelectInsts) 150fe6060f1SDimitry Andric Stack.push_back(SIToUnfold); 151fe6060f1SDimitry Andric 152fe6060f1SDimitry Andric while (!Stack.empty()) { 153349cc55cSDimitry Andric SelectInstToUnfold SIToUnfold = Stack.pop_back_val(); 154fe6060f1SDimitry Andric 155fe6060f1SDimitry Andric std::vector<SelectInstToUnfold> NewSIsToUnfold; 156fe6060f1SDimitry Andric std::vector<BasicBlock *> NewBBs; 157fe6060f1SDimitry Andric unfold(&DTU, SIToUnfold, &NewSIsToUnfold, &NewBBs); 158fe6060f1SDimitry Andric 159fe6060f1SDimitry Andric // Put newly discovered select instructions into the work list. 160fe6060f1SDimitry Andric for (const SelectInstToUnfold &NewSIToUnfold : NewSIsToUnfold) 161fe6060f1SDimitry Andric Stack.push_back(NewSIToUnfold); 162fe6060f1SDimitry Andric } 163fe6060f1SDimitry Andric } 164fe6060f1SDimitry Andric 165fe6060f1SDimitry Andric AssumptionCache *AC; 166fe6060f1SDimitry Andric DominatorTree *DT; 167fe6060f1SDimitry Andric TargetTransformInfo *TTI; 168fe6060f1SDimitry Andric OptimizationRemarkEmitter *ORE; 169fe6060f1SDimitry Andric }; 170fe6060f1SDimitry Andric 171fe6060f1SDimitry Andric class DFAJumpThreadingLegacyPass : public FunctionPass { 172fe6060f1SDimitry Andric public: 173fe6060f1SDimitry Andric static char ID; // Pass identification 174fe6060f1SDimitry Andric DFAJumpThreadingLegacyPass() : FunctionPass(ID) {} 175fe6060f1SDimitry Andric 176fe6060f1SDimitry Andric void getAnalysisUsage(AnalysisUsage &AU) const override { 177fe6060f1SDimitry Andric AU.addRequired<AssumptionCacheTracker>(); 178fe6060f1SDimitry Andric AU.addRequired<DominatorTreeWrapperPass>(); 179349cc55cSDimitry Andric AU.addPreserved<DominatorTreeWrapperPass>(); 180fe6060f1SDimitry Andric AU.addRequired<TargetTransformInfoWrapperPass>(); 181fe6060f1SDimitry Andric AU.addRequired<OptimizationRemarkEmitterWrapperPass>(); 182fe6060f1SDimitry Andric } 183fe6060f1SDimitry Andric 184fe6060f1SDimitry Andric bool runOnFunction(Function &F) override { 185fe6060f1SDimitry Andric if (skipFunction(F)) 186fe6060f1SDimitry Andric return false; 187fe6060f1SDimitry Andric 188fe6060f1SDimitry Andric AssumptionCache *AC = 189fe6060f1SDimitry Andric &getAnalysis<AssumptionCacheTracker>().getAssumptionCache(F); 190fe6060f1SDimitry Andric DominatorTree *DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree(); 191fe6060f1SDimitry Andric TargetTransformInfo *TTI = 192fe6060f1SDimitry Andric &getAnalysis<TargetTransformInfoWrapperPass>().getTTI(F); 193fe6060f1SDimitry Andric OptimizationRemarkEmitter *ORE = 194fe6060f1SDimitry Andric &getAnalysis<OptimizationRemarkEmitterWrapperPass>().getORE(); 195fe6060f1SDimitry Andric 196fe6060f1SDimitry Andric return DFAJumpThreading(AC, DT, TTI, ORE).run(F); 197fe6060f1SDimitry Andric } 198fe6060f1SDimitry Andric }; 199fe6060f1SDimitry Andric } // end anonymous namespace 200fe6060f1SDimitry Andric 201fe6060f1SDimitry Andric char DFAJumpThreadingLegacyPass::ID = 0; 202fe6060f1SDimitry Andric INITIALIZE_PASS_BEGIN(DFAJumpThreadingLegacyPass, "dfa-jump-threading", 203fe6060f1SDimitry Andric "DFA Jump Threading", false, false) 204fe6060f1SDimitry Andric INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker) 205fe6060f1SDimitry Andric INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass) 206fe6060f1SDimitry Andric INITIALIZE_PASS_DEPENDENCY(TargetTransformInfoWrapperPass) 207fe6060f1SDimitry Andric INITIALIZE_PASS_DEPENDENCY(OptimizationRemarkEmitterWrapperPass) 208fe6060f1SDimitry Andric INITIALIZE_PASS_END(DFAJumpThreadingLegacyPass, "dfa-jump-threading", 209fe6060f1SDimitry Andric "DFA Jump Threading", false, false) 210fe6060f1SDimitry Andric 211fe6060f1SDimitry Andric // Public interface to the DFA Jump Threading pass 212fe6060f1SDimitry Andric FunctionPass *llvm::createDFAJumpThreadingPass() { 213fe6060f1SDimitry Andric return new DFAJumpThreadingLegacyPass(); 214fe6060f1SDimitry Andric } 215fe6060f1SDimitry Andric 216fe6060f1SDimitry Andric namespace { 217fe6060f1SDimitry Andric 218fe6060f1SDimitry Andric /// Create a new basic block and sink \p SIToSink into it. 219fe6060f1SDimitry Andric void createBasicBlockAndSinkSelectInst( 220fe6060f1SDimitry Andric DomTreeUpdater *DTU, SelectInst *SI, PHINode *SIUse, SelectInst *SIToSink, 221fe6060f1SDimitry Andric BasicBlock *EndBlock, StringRef NewBBName, BasicBlock **NewBlock, 222fe6060f1SDimitry Andric BranchInst **NewBranch, std::vector<SelectInstToUnfold> *NewSIsToUnfold, 223fe6060f1SDimitry Andric std::vector<BasicBlock *> *NewBBs) { 224fe6060f1SDimitry Andric assert(SIToSink->hasOneUse()); 225fe6060f1SDimitry Andric assert(NewBlock); 226fe6060f1SDimitry Andric assert(NewBranch); 227fe6060f1SDimitry Andric *NewBlock = BasicBlock::Create(SI->getContext(), NewBBName, 228fe6060f1SDimitry Andric EndBlock->getParent(), EndBlock); 229fe6060f1SDimitry Andric NewBBs->push_back(*NewBlock); 230fe6060f1SDimitry Andric *NewBranch = BranchInst::Create(EndBlock, *NewBlock); 231fe6060f1SDimitry Andric SIToSink->moveBefore(*NewBranch); 232fe6060f1SDimitry Andric NewSIsToUnfold->push_back(SelectInstToUnfold(SIToSink, SIUse)); 233fe6060f1SDimitry Andric DTU->applyUpdates({{DominatorTree::Insert, *NewBlock, EndBlock}}); 234fe6060f1SDimitry Andric } 235fe6060f1SDimitry Andric 236fe6060f1SDimitry Andric /// Unfold the select instruction held in \p SIToUnfold by replacing it with 237fe6060f1SDimitry Andric /// control flow. 238fe6060f1SDimitry Andric /// 239fe6060f1SDimitry Andric /// Put newly discovered select instructions into \p NewSIsToUnfold. Put newly 240fe6060f1SDimitry Andric /// created basic blocks into \p NewBBs. 241fe6060f1SDimitry Andric /// 242fe6060f1SDimitry Andric /// TODO: merge it with CodeGenPrepare::optimizeSelectInst() if possible. 243fe6060f1SDimitry Andric void unfold(DomTreeUpdater *DTU, SelectInstToUnfold SIToUnfold, 244fe6060f1SDimitry Andric std::vector<SelectInstToUnfold> *NewSIsToUnfold, 245fe6060f1SDimitry Andric std::vector<BasicBlock *> *NewBBs) { 246fe6060f1SDimitry Andric SelectInst *SI = SIToUnfold.getInst(); 247fe6060f1SDimitry Andric PHINode *SIUse = SIToUnfold.getUse(); 248fe6060f1SDimitry Andric BasicBlock *StartBlock = SI->getParent(); 249fe6060f1SDimitry Andric BasicBlock *EndBlock = SIUse->getParent(); 250fe6060f1SDimitry Andric BranchInst *StartBlockTerm = 251fe6060f1SDimitry Andric dyn_cast<BranchInst>(StartBlock->getTerminator()); 252fe6060f1SDimitry Andric 253fe6060f1SDimitry Andric assert(StartBlockTerm && StartBlockTerm->isUnconditional()); 254fe6060f1SDimitry Andric assert(SI->hasOneUse()); 255fe6060f1SDimitry Andric 256fe6060f1SDimitry Andric // These are the new basic blocks for the conditional branch. 257fe6060f1SDimitry Andric // At least one will become an actual new basic block. 258fe6060f1SDimitry Andric BasicBlock *TrueBlock = nullptr; 259fe6060f1SDimitry Andric BasicBlock *FalseBlock = nullptr; 260fe6060f1SDimitry Andric BranchInst *TrueBranch = nullptr; 261fe6060f1SDimitry Andric BranchInst *FalseBranch = nullptr; 262fe6060f1SDimitry Andric 263fe6060f1SDimitry Andric // Sink select instructions to be able to unfold them later. 264fe6060f1SDimitry Andric if (SelectInst *SIOp = dyn_cast<SelectInst>(SI->getTrueValue())) { 265fe6060f1SDimitry Andric createBasicBlockAndSinkSelectInst(DTU, SI, SIUse, SIOp, EndBlock, 266fe6060f1SDimitry Andric "si.unfold.true", &TrueBlock, &TrueBranch, 267fe6060f1SDimitry Andric NewSIsToUnfold, NewBBs); 268fe6060f1SDimitry Andric } 269fe6060f1SDimitry Andric if (SelectInst *SIOp = dyn_cast<SelectInst>(SI->getFalseValue())) { 270fe6060f1SDimitry Andric createBasicBlockAndSinkSelectInst(DTU, SI, SIUse, SIOp, EndBlock, 271fe6060f1SDimitry Andric "si.unfold.false", &FalseBlock, 272fe6060f1SDimitry Andric &FalseBranch, NewSIsToUnfold, NewBBs); 273fe6060f1SDimitry Andric } 274fe6060f1SDimitry Andric 275fe6060f1SDimitry Andric // If there was nothing to sink, then arbitrarily choose the 'false' side 276fe6060f1SDimitry Andric // for a new input value to the PHI. 277fe6060f1SDimitry Andric if (!TrueBlock && !FalseBlock) { 278fe6060f1SDimitry Andric FalseBlock = BasicBlock::Create(SI->getContext(), "si.unfold.false", 279fe6060f1SDimitry Andric EndBlock->getParent(), EndBlock); 280fe6060f1SDimitry Andric NewBBs->push_back(FalseBlock); 281fe6060f1SDimitry Andric BranchInst::Create(EndBlock, FalseBlock); 282fe6060f1SDimitry Andric DTU->applyUpdates({{DominatorTree::Insert, FalseBlock, EndBlock}}); 283fe6060f1SDimitry Andric } 284fe6060f1SDimitry Andric 285fe6060f1SDimitry Andric // Insert the real conditional branch based on the original condition. 286fe6060f1SDimitry Andric // If we did not create a new block for one of the 'true' or 'false' paths 287fe6060f1SDimitry Andric // of the condition, it means that side of the branch goes to the end block 288fe6060f1SDimitry Andric // directly and the path originates from the start block from the point of 289fe6060f1SDimitry Andric // view of the new PHI. 290fe6060f1SDimitry Andric BasicBlock *TT = EndBlock; 291fe6060f1SDimitry Andric BasicBlock *FT = EndBlock; 292fe6060f1SDimitry Andric if (TrueBlock && FalseBlock) { 293fe6060f1SDimitry Andric // A diamond. 294fe6060f1SDimitry Andric TT = TrueBlock; 295fe6060f1SDimitry Andric FT = FalseBlock; 296fe6060f1SDimitry Andric 297fe6060f1SDimitry Andric // Update the phi node of SI. 298fe6060f1SDimitry Andric SIUse->removeIncomingValue(StartBlock, /* DeletePHIIfEmpty = */ false); 299fe6060f1SDimitry Andric SIUse->addIncoming(SI->getTrueValue(), TrueBlock); 300fe6060f1SDimitry Andric SIUse->addIncoming(SI->getFalseValue(), FalseBlock); 301fe6060f1SDimitry Andric 302fe6060f1SDimitry Andric // Update any other PHI nodes in EndBlock. 303fe6060f1SDimitry Andric for (PHINode &Phi : EndBlock->phis()) { 304fe6060f1SDimitry Andric if (&Phi != SIUse) { 305fe6060f1SDimitry Andric Phi.addIncoming(Phi.getIncomingValueForBlock(StartBlock), TrueBlock); 306fe6060f1SDimitry Andric Phi.addIncoming(Phi.getIncomingValueForBlock(StartBlock), FalseBlock); 307fe6060f1SDimitry Andric } 308fe6060f1SDimitry Andric } 309fe6060f1SDimitry Andric } else { 310fe6060f1SDimitry Andric BasicBlock *NewBlock = nullptr; 311fe6060f1SDimitry Andric Value *SIOp1 = SI->getTrueValue(); 312fe6060f1SDimitry Andric Value *SIOp2 = SI->getFalseValue(); 313fe6060f1SDimitry Andric 314fe6060f1SDimitry Andric // A triangle pointing right. 315fe6060f1SDimitry Andric if (!TrueBlock) { 316fe6060f1SDimitry Andric NewBlock = FalseBlock; 317fe6060f1SDimitry Andric FT = FalseBlock; 318fe6060f1SDimitry Andric } 319fe6060f1SDimitry Andric // A triangle pointing left. 320fe6060f1SDimitry Andric else { 321fe6060f1SDimitry Andric NewBlock = TrueBlock; 322fe6060f1SDimitry Andric TT = TrueBlock; 323fe6060f1SDimitry Andric std::swap(SIOp1, SIOp2); 324fe6060f1SDimitry Andric } 325fe6060f1SDimitry Andric 326fe6060f1SDimitry Andric // Update the phi node of SI. 327fe6060f1SDimitry Andric for (unsigned Idx = 0; Idx < SIUse->getNumIncomingValues(); ++Idx) { 328fe6060f1SDimitry Andric if (SIUse->getIncomingBlock(Idx) == StartBlock) 329fe6060f1SDimitry Andric SIUse->setIncomingValue(Idx, SIOp1); 330fe6060f1SDimitry Andric } 331fe6060f1SDimitry Andric SIUse->addIncoming(SIOp2, NewBlock); 332fe6060f1SDimitry Andric 333fe6060f1SDimitry Andric // Update any other PHI nodes in EndBlock. 334fe6060f1SDimitry Andric for (auto II = EndBlock->begin(); PHINode *Phi = dyn_cast<PHINode>(II); 335fe6060f1SDimitry Andric ++II) { 336fe6060f1SDimitry Andric if (Phi != SIUse) 337fe6060f1SDimitry Andric Phi->addIncoming(Phi->getIncomingValueForBlock(StartBlock), NewBlock); 338fe6060f1SDimitry Andric } 339fe6060f1SDimitry Andric } 340fe6060f1SDimitry Andric StartBlockTerm->eraseFromParent(); 341fe6060f1SDimitry Andric BranchInst::Create(TT, FT, SI->getCondition(), StartBlock); 342fe6060f1SDimitry Andric DTU->applyUpdates({{DominatorTree::Insert, StartBlock, TT}, 343fe6060f1SDimitry Andric {DominatorTree::Insert, StartBlock, FT}}); 344fe6060f1SDimitry Andric 345fe6060f1SDimitry Andric // The select is now dead. 346fe6060f1SDimitry Andric SI->eraseFromParent(); 347fe6060f1SDimitry Andric } 348fe6060f1SDimitry Andric 349fe6060f1SDimitry Andric struct ClonedBlock { 350fe6060f1SDimitry Andric BasicBlock *BB; 351fe6060f1SDimitry Andric uint64_t State; ///< \p State corresponds to the next value of a switch stmnt. 352fe6060f1SDimitry Andric }; 353fe6060f1SDimitry Andric 354fe6060f1SDimitry Andric typedef std::deque<BasicBlock *> PathType; 355fe6060f1SDimitry Andric typedef std::vector<PathType> PathsType; 356349cc55cSDimitry Andric typedef SmallPtrSet<const BasicBlock *, 8> VisitedBlocks; 357fe6060f1SDimitry Andric typedef std::vector<ClonedBlock> CloneList; 358fe6060f1SDimitry Andric 359fe6060f1SDimitry Andric // This data structure keeps track of all blocks that have been cloned. If two 360fe6060f1SDimitry Andric // different ThreadingPaths clone the same block for a certain state it should 361fe6060f1SDimitry Andric // be reused, and it can be looked up in this map. 362fe6060f1SDimitry Andric typedef DenseMap<BasicBlock *, CloneList> DuplicateBlockMap; 363fe6060f1SDimitry Andric 364fe6060f1SDimitry Andric // This map keeps track of all the new definitions for an instruction. This 365fe6060f1SDimitry Andric // information is needed when restoring SSA form after cloning blocks. 3661fd87a68SDimitry Andric typedef MapVector<Instruction *, std::vector<Instruction *>> DefMap; 367fe6060f1SDimitry Andric 368fe6060f1SDimitry Andric inline raw_ostream &operator<<(raw_ostream &OS, const PathType &Path) { 369fe6060f1SDimitry Andric OS << "< "; 370fe6060f1SDimitry Andric for (const BasicBlock *BB : Path) { 371fe6060f1SDimitry Andric std::string BBName; 372fe6060f1SDimitry Andric if (BB->hasName()) 373fe6060f1SDimitry Andric raw_string_ostream(BBName) << BB->getName(); 374fe6060f1SDimitry Andric else 375fe6060f1SDimitry Andric raw_string_ostream(BBName) << BB; 376fe6060f1SDimitry Andric OS << BBName << " "; 377fe6060f1SDimitry Andric } 378fe6060f1SDimitry Andric OS << ">"; 379fe6060f1SDimitry Andric return OS; 380fe6060f1SDimitry Andric } 381fe6060f1SDimitry Andric 382fe6060f1SDimitry Andric /// ThreadingPath is a path in the control flow of a loop that can be threaded 383fe6060f1SDimitry Andric /// by cloning necessary basic blocks and replacing conditional branches with 384fe6060f1SDimitry Andric /// unconditional ones. A threading path includes a list of basic blocks, the 385fe6060f1SDimitry Andric /// exit state, and the block that determines the next state. 386fe6060f1SDimitry Andric struct ThreadingPath { 387fe6060f1SDimitry Andric /// Exit value is DFA's exit state for the given path. 388fe6060f1SDimitry Andric uint64_t getExitValue() const { return ExitVal; } 389fe6060f1SDimitry Andric void setExitValue(const ConstantInt *V) { 390fe6060f1SDimitry Andric ExitVal = V->getZExtValue(); 391fe6060f1SDimitry Andric IsExitValSet = true; 392fe6060f1SDimitry Andric } 393fe6060f1SDimitry Andric bool isExitValueSet() const { return IsExitValSet; } 394fe6060f1SDimitry Andric 395fe6060f1SDimitry Andric /// Determinator is the basic block that determines the next state of the DFA. 396fe6060f1SDimitry Andric const BasicBlock *getDeterminatorBB() const { return DBB; } 397fe6060f1SDimitry Andric void setDeterminator(const BasicBlock *BB) { DBB = BB; } 398fe6060f1SDimitry Andric 399fe6060f1SDimitry Andric /// Path is a list of basic blocks. 400fe6060f1SDimitry Andric const PathType &getPath() const { return Path; } 401fe6060f1SDimitry Andric void setPath(const PathType &NewPath) { Path = NewPath; } 402fe6060f1SDimitry Andric 403fe6060f1SDimitry Andric void print(raw_ostream &OS) const { 404fe6060f1SDimitry Andric OS << Path << " [ " << ExitVal << ", " << DBB->getName() << " ]"; 405fe6060f1SDimitry Andric } 406fe6060f1SDimitry Andric 407fe6060f1SDimitry Andric private: 408fe6060f1SDimitry Andric PathType Path; 409fe6060f1SDimitry Andric uint64_t ExitVal; 410fe6060f1SDimitry Andric const BasicBlock *DBB = nullptr; 411fe6060f1SDimitry Andric bool IsExitValSet = false; 412fe6060f1SDimitry Andric }; 413fe6060f1SDimitry Andric 414fe6060f1SDimitry Andric #ifndef NDEBUG 415fe6060f1SDimitry Andric inline raw_ostream &operator<<(raw_ostream &OS, const ThreadingPath &TPath) { 416fe6060f1SDimitry Andric TPath.print(OS); 417fe6060f1SDimitry Andric return OS; 418fe6060f1SDimitry Andric } 419fe6060f1SDimitry Andric #endif 420fe6060f1SDimitry Andric 421fe6060f1SDimitry Andric struct MainSwitch { 422fe6060f1SDimitry Andric MainSwitch(SwitchInst *SI, OptimizationRemarkEmitter *ORE) { 423*81ad6265SDimitry Andric if (isCandidate(SI)) { 424fe6060f1SDimitry Andric Instr = SI; 425fe6060f1SDimitry Andric } else { 426fe6060f1SDimitry Andric ORE->emit([&]() { 427fe6060f1SDimitry Andric return OptimizationRemarkMissed(DEBUG_TYPE, "SwitchNotPredictable", SI) 428fe6060f1SDimitry Andric << "Switch instruction is not predictable."; 429fe6060f1SDimitry Andric }); 430fe6060f1SDimitry Andric } 431fe6060f1SDimitry Andric } 432fe6060f1SDimitry Andric 433fe6060f1SDimitry Andric virtual ~MainSwitch() = default; 434fe6060f1SDimitry Andric 435fe6060f1SDimitry Andric SwitchInst *getInstr() const { return Instr; } 436fe6060f1SDimitry Andric const SmallVector<SelectInstToUnfold, 4> getSelectInsts() { 437fe6060f1SDimitry Andric return SelectInsts; 438fe6060f1SDimitry Andric } 439fe6060f1SDimitry Andric 440fe6060f1SDimitry Andric private: 441*81ad6265SDimitry Andric /// Do a use-def chain traversal starting from the switch condition to see if 442*81ad6265SDimitry Andric /// \p SI is a potential condidate. 443*81ad6265SDimitry Andric /// 444*81ad6265SDimitry Andric /// Also, collect select instructions to unfold. 445*81ad6265SDimitry Andric bool isCandidate(const SwitchInst *SI) { 446*81ad6265SDimitry Andric std::deque<Value *> Q; 447fe6060f1SDimitry Andric SmallSet<Value *, 16> SeenValues; 448fe6060f1SDimitry Andric SelectInsts.clear(); 449fe6060f1SDimitry Andric 450*81ad6265SDimitry Andric Value *SICond = SI->getCondition(); 451*81ad6265SDimitry Andric LLVM_DEBUG(dbgs() << "\tSICond: " << *SICond << "\n"); 452*81ad6265SDimitry Andric if (!isa<PHINode>(SICond)) 453fe6060f1SDimitry Andric return false; 454fe6060f1SDimitry Andric 455*81ad6265SDimitry Andric addToQueue(SICond, Q, SeenValues); 456fe6060f1SDimitry Andric 457fe6060f1SDimitry Andric while (!Q.empty()) { 458*81ad6265SDimitry Andric Value *Current = Q.front(); 459fe6060f1SDimitry Andric Q.pop_front(); 460fe6060f1SDimitry Andric 461fe6060f1SDimitry Andric if (auto *Phi = dyn_cast<PHINode>(Current)) { 462fe6060f1SDimitry Andric for (Value *Incoming : Phi->incoming_values()) { 463*81ad6265SDimitry Andric addToQueue(Incoming, Q, SeenValues); 464fe6060f1SDimitry Andric } 465*81ad6265SDimitry Andric LLVM_DEBUG(dbgs() << "\tphi: " << *Phi << "\n"); 466fe6060f1SDimitry Andric } else if (SelectInst *SelI = dyn_cast<SelectInst>(Current)) { 467fe6060f1SDimitry Andric if (!isValidSelectInst(SelI)) 468fe6060f1SDimitry Andric return false; 469*81ad6265SDimitry Andric addToQueue(SelI->getTrueValue(), Q, SeenValues); 470*81ad6265SDimitry Andric addToQueue(SelI->getFalseValue(), Q, SeenValues); 471*81ad6265SDimitry Andric LLVM_DEBUG(dbgs() << "\tselect: " << *SelI << "\n"); 472fe6060f1SDimitry Andric if (auto *SelIUse = dyn_cast<PHINode>(SelI->user_back())) 473fe6060f1SDimitry Andric SelectInsts.push_back(SelectInstToUnfold(SelI, SelIUse)); 474*81ad6265SDimitry Andric } else if (isa<Constant>(Current)) { 475*81ad6265SDimitry Andric LLVM_DEBUG(dbgs() << "\tconst: " << *Current << "\n"); 476*81ad6265SDimitry Andric continue; 477fe6060f1SDimitry Andric } else { 478*81ad6265SDimitry Andric LLVM_DEBUG(dbgs() << "\tother: " << *Current << "\n"); 479*81ad6265SDimitry Andric // Allow unpredictable values. The hope is that those will be the 480*81ad6265SDimitry Andric // initial switch values that can be ignored (they will hit the 481*81ad6265SDimitry Andric // unthreaded switch) but this assumption will get checked later after 482*81ad6265SDimitry Andric // paths have been enumerated (in function getStateDefMap). 483*81ad6265SDimitry Andric continue; 484fe6060f1SDimitry Andric } 485fe6060f1SDimitry Andric } 486fe6060f1SDimitry Andric 487fe6060f1SDimitry Andric return true; 488fe6060f1SDimitry Andric } 489fe6060f1SDimitry Andric 490*81ad6265SDimitry Andric void addToQueue(Value *Val, std::deque<Value *> &Q, 491fe6060f1SDimitry Andric SmallSet<Value *, 16> &SeenValues) { 492349cc55cSDimitry Andric if (SeenValues.contains(Val)) 493fe6060f1SDimitry Andric return; 494*81ad6265SDimitry Andric Q.push_back(Val); 495fe6060f1SDimitry Andric SeenValues.insert(Val); 496fe6060f1SDimitry Andric } 497fe6060f1SDimitry Andric 498fe6060f1SDimitry Andric bool isValidSelectInst(SelectInst *SI) { 499fe6060f1SDimitry Andric if (!SI->hasOneUse()) 500fe6060f1SDimitry Andric return false; 501fe6060f1SDimitry Andric 502fe6060f1SDimitry Andric Instruction *SIUse = dyn_cast<Instruction>(SI->user_back()); 503fe6060f1SDimitry Andric // The use of the select inst should be either a phi or another select. 504fe6060f1SDimitry Andric if (!SIUse && !(isa<PHINode>(SIUse) || isa<SelectInst>(SIUse))) 505fe6060f1SDimitry Andric return false; 506fe6060f1SDimitry Andric 507fe6060f1SDimitry Andric BasicBlock *SIBB = SI->getParent(); 508fe6060f1SDimitry Andric 509fe6060f1SDimitry Andric // Currently, we can only expand select instructions in basic blocks with 510fe6060f1SDimitry Andric // one successor. 511fe6060f1SDimitry Andric BranchInst *SITerm = dyn_cast<BranchInst>(SIBB->getTerminator()); 512fe6060f1SDimitry Andric if (!SITerm || !SITerm->isUnconditional()) 513fe6060f1SDimitry Andric return false; 514fe6060f1SDimitry Andric 515fe6060f1SDimitry Andric if (isa<PHINode>(SIUse) && 516349cc55cSDimitry Andric SIBB->getSingleSuccessor() != cast<Instruction>(SIUse)->getParent()) 517fe6060f1SDimitry Andric return false; 518fe6060f1SDimitry Andric 519fe6060f1SDimitry Andric // If select will not be sunk during unfolding, and it is in the same basic 520fe6060f1SDimitry Andric // block as another state defining select, then cannot unfold both. 521fe6060f1SDimitry Andric for (SelectInstToUnfold SIToUnfold : SelectInsts) { 522fe6060f1SDimitry Andric SelectInst *PrevSI = SIToUnfold.getInst(); 523fe6060f1SDimitry Andric if (PrevSI->getTrueValue() != SI && PrevSI->getFalseValue() != SI && 524fe6060f1SDimitry Andric PrevSI->getParent() == SI->getParent()) 525fe6060f1SDimitry Andric return false; 526fe6060f1SDimitry Andric } 527fe6060f1SDimitry Andric 528fe6060f1SDimitry Andric return true; 529fe6060f1SDimitry Andric } 530fe6060f1SDimitry Andric 531fe6060f1SDimitry Andric SwitchInst *Instr = nullptr; 532fe6060f1SDimitry Andric SmallVector<SelectInstToUnfold, 4> SelectInsts; 533fe6060f1SDimitry Andric }; 534fe6060f1SDimitry Andric 535fe6060f1SDimitry Andric struct AllSwitchPaths { 536fe6060f1SDimitry Andric AllSwitchPaths(const MainSwitch *MSwitch, OptimizationRemarkEmitter *ORE) 537fe6060f1SDimitry Andric : Switch(MSwitch->getInstr()), SwitchBlock(Switch->getParent()), 538fe6060f1SDimitry Andric ORE(ORE) {} 539fe6060f1SDimitry Andric 540fe6060f1SDimitry Andric std::vector<ThreadingPath> &getThreadingPaths() { return TPaths; } 541fe6060f1SDimitry Andric unsigned getNumThreadingPaths() { return TPaths.size(); } 542fe6060f1SDimitry Andric SwitchInst *getSwitchInst() { return Switch; } 543fe6060f1SDimitry Andric BasicBlock *getSwitchBlock() { return SwitchBlock; } 544fe6060f1SDimitry Andric 545fe6060f1SDimitry Andric void run() { 546fe6060f1SDimitry Andric VisitedBlocks Visited; 547fe6060f1SDimitry Andric PathsType LoopPaths = paths(SwitchBlock, Visited, /* PathDepth = */ 1); 548*81ad6265SDimitry Andric StateDefMap StateDef = getStateDefMap(LoopPaths); 549*81ad6265SDimitry Andric 550*81ad6265SDimitry Andric if (StateDef.empty()) { 551*81ad6265SDimitry Andric ORE->emit([&]() { 552*81ad6265SDimitry Andric return OptimizationRemarkMissed(DEBUG_TYPE, "SwitchNotPredictable", 553*81ad6265SDimitry Andric Switch) 554*81ad6265SDimitry Andric << "Switch instruction is not predictable."; 555*81ad6265SDimitry Andric }); 556*81ad6265SDimitry Andric return; 557*81ad6265SDimitry Andric } 558fe6060f1SDimitry Andric 559fe6060f1SDimitry Andric for (PathType Path : LoopPaths) { 560fe6060f1SDimitry Andric ThreadingPath TPath; 561fe6060f1SDimitry Andric 562fe6060f1SDimitry Andric const BasicBlock *PrevBB = Path.back(); 563fe6060f1SDimitry Andric for (const BasicBlock *BB : Path) { 564fe6060f1SDimitry Andric if (StateDef.count(BB) != 0) { 565fe6060f1SDimitry Andric const PHINode *Phi = dyn_cast<PHINode>(StateDef[BB]); 566fe6060f1SDimitry Andric assert(Phi && "Expected a state-defining instr to be a phi node."); 567fe6060f1SDimitry Andric 568fe6060f1SDimitry Andric const Value *V = Phi->getIncomingValueForBlock(PrevBB); 569fe6060f1SDimitry Andric if (const ConstantInt *C = dyn_cast<const ConstantInt>(V)) { 570fe6060f1SDimitry Andric TPath.setExitValue(C); 571fe6060f1SDimitry Andric TPath.setDeterminator(BB); 572fe6060f1SDimitry Andric TPath.setPath(Path); 573fe6060f1SDimitry Andric } 574fe6060f1SDimitry Andric } 575fe6060f1SDimitry Andric 576fe6060f1SDimitry Andric // Switch block is the determinator, this is the final exit value. 577fe6060f1SDimitry Andric if (TPath.isExitValueSet() && BB == Path.front()) 578fe6060f1SDimitry Andric break; 579fe6060f1SDimitry Andric 580fe6060f1SDimitry Andric PrevBB = BB; 581fe6060f1SDimitry Andric } 582fe6060f1SDimitry Andric 5830eae32dcSDimitry Andric if (TPath.isExitValueSet() && isSupported(TPath)) 584fe6060f1SDimitry Andric TPaths.push_back(TPath); 585fe6060f1SDimitry Andric } 586fe6060f1SDimitry Andric } 587fe6060f1SDimitry Andric 588fe6060f1SDimitry Andric private: 589fe6060f1SDimitry Andric // Value: an instruction that defines a switch state; 590fe6060f1SDimitry Andric // Key: the parent basic block of that instruction. 591fe6060f1SDimitry Andric typedef DenseMap<const BasicBlock *, const PHINode *> StateDefMap; 592fe6060f1SDimitry Andric 593fe6060f1SDimitry Andric PathsType paths(BasicBlock *BB, VisitedBlocks &Visited, 594fe6060f1SDimitry Andric unsigned PathDepth) const { 595fe6060f1SDimitry Andric PathsType Res; 596fe6060f1SDimitry Andric 597fe6060f1SDimitry Andric // Stop exploring paths after visiting MaxPathLength blocks 598fe6060f1SDimitry Andric if (PathDepth > MaxPathLength) { 599fe6060f1SDimitry Andric ORE->emit([&]() { 600fe6060f1SDimitry Andric return OptimizationRemarkAnalysis(DEBUG_TYPE, "MaxPathLengthReached", 601fe6060f1SDimitry Andric Switch) 602fe6060f1SDimitry Andric << "Exploration stopped after visiting MaxPathLength=" 603fe6060f1SDimitry Andric << ore::NV("MaxPathLength", MaxPathLength) << " blocks."; 604fe6060f1SDimitry Andric }); 605fe6060f1SDimitry Andric return Res; 606fe6060f1SDimitry Andric } 607fe6060f1SDimitry Andric 608fe6060f1SDimitry Andric Visited.insert(BB); 609fe6060f1SDimitry Andric 610fe6060f1SDimitry Andric // Some blocks have multiple edges to the same successor, and this set 611fe6060f1SDimitry Andric // is used to prevent a duplicate path from being generated 612fe6060f1SDimitry Andric SmallSet<BasicBlock *, 4> Successors; 613349cc55cSDimitry Andric for (BasicBlock *Succ : successors(BB)) { 614349cc55cSDimitry Andric if (!Successors.insert(Succ).second) 615fe6060f1SDimitry Andric continue; 616fe6060f1SDimitry Andric 617fe6060f1SDimitry Andric // Found a cycle through the SwitchBlock 618fe6060f1SDimitry Andric if (Succ == SwitchBlock) { 619fe6060f1SDimitry Andric Res.push_back({BB}); 620fe6060f1SDimitry Andric continue; 621fe6060f1SDimitry Andric } 622fe6060f1SDimitry Andric 623fe6060f1SDimitry Andric // We have encountered a cycle, do not get caught in it 624349cc55cSDimitry Andric if (Visited.contains(Succ)) 625fe6060f1SDimitry Andric continue; 626fe6060f1SDimitry Andric 627fe6060f1SDimitry Andric PathsType SuccPaths = paths(Succ, Visited, PathDepth + 1); 628fe6060f1SDimitry Andric for (PathType Path : SuccPaths) { 629fe6060f1SDimitry Andric PathType NewPath(Path); 630fe6060f1SDimitry Andric NewPath.push_front(BB); 631fe6060f1SDimitry Andric Res.push_back(NewPath); 632*81ad6265SDimitry Andric if (Res.size() >= MaxNumPaths) { 633*81ad6265SDimitry Andric return Res; 634*81ad6265SDimitry Andric } 635fe6060f1SDimitry Andric } 636fe6060f1SDimitry Andric } 637fe6060f1SDimitry Andric // This block could now be visited again from a different predecessor. Note 638fe6060f1SDimitry Andric // that this will result in exponential runtime. Subpaths could possibly be 639fe6060f1SDimitry Andric // cached but it takes a lot of memory to store them. 640fe6060f1SDimitry Andric Visited.erase(BB); 641fe6060f1SDimitry Andric return Res; 642fe6060f1SDimitry Andric } 643fe6060f1SDimitry Andric 644fe6060f1SDimitry Andric /// Walk the use-def chain and collect all the state-defining instructions. 645*81ad6265SDimitry Andric /// 646*81ad6265SDimitry Andric /// Return an empty map if unpredictable values encountered inside the basic 647*81ad6265SDimitry Andric /// blocks of \p LoopPaths. 648*81ad6265SDimitry Andric StateDefMap getStateDefMap(const PathsType &LoopPaths) const { 649fe6060f1SDimitry Andric StateDefMap Res; 650fe6060f1SDimitry Andric 651*81ad6265SDimitry Andric // Basic blocks belonging to any of the loops around the switch statement. 652*81ad6265SDimitry Andric SmallPtrSet<BasicBlock *, 16> LoopBBs; 653*81ad6265SDimitry Andric for (const PathType &Path : LoopPaths) { 654*81ad6265SDimitry Andric for (BasicBlock *BB : Path) 655*81ad6265SDimitry Andric LoopBBs.insert(BB); 656*81ad6265SDimitry Andric } 657*81ad6265SDimitry Andric 658fe6060f1SDimitry Andric Value *FirstDef = Switch->getOperand(0); 659fe6060f1SDimitry Andric 660*81ad6265SDimitry Andric assert(isa<PHINode>(FirstDef) && "The first definition must be a phi."); 661fe6060f1SDimitry Andric 662fe6060f1SDimitry Andric SmallVector<PHINode *, 8> Stack; 663fe6060f1SDimitry Andric Stack.push_back(dyn_cast<PHINode>(FirstDef)); 664fe6060f1SDimitry Andric SmallSet<Value *, 16> SeenValues; 665fe6060f1SDimitry Andric 666fe6060f1SDimitry Andric while (!Stack.empty()) { 667349cc55cSDimitry Andric PHINode *CurPhi = Stack.pop_back_val(); 668fe6060f1SDimitry Andric 669fe6060f1SDimitry Andric Res[CurPhi->getParent()] = CurPhi; 670fe6060f1SDimitry Andric SeenValues.insert(CurPhi); 671fe6060f1SDimitry Andric 672*81ad6265SDimitry Andric for (BasicBlock *IncomingBB : CurPhi->blocks()) { 673*81ad6265SDimitry Andric Value *Incoming = CurPhi->getIncomingValueForBlock(IncomingBB); 674*81ad6265SDimitry Andric bool IsOutsideLoops = LoopBBs.count(IncomingBB) == 0; 675fe6060f1SDimitry Andric if (Incoming == FirstDef || isa<ConstantInt>(Incoming) || 676*81ad6265SDimitry Andric SeenValues.contains(Incoming) || IsOutsideLoops) { 677fe6060f1SDimitry Andric continue; 678fe6060f1SDimitry Andric } 679fe6060f1SDimitry Andric 680*81ad6265SDimitry Andric // Any unpredictable value inside the loops means we must bail out. 681*81ad6265SDimitry Andric if (!isa<PHINode>(Incoming)) 682*81ad6265SDimitry Andric return StateDefMap(); 683fe6060f1SDimitry Andric 684fe6060f1SDimitry Andric Stack.push_back(cast<PHINode>(Incoming)); 685fe6060f1SDimitry Andric } 686fe6060f1SDimitry Andric } 687fe6060f1SDimitry Andric 688fe6060f1SDimitry Andric return Res; 689fe6060f1SDimitry Andric } 690fe6060f1SDimitry Andric 6910eae32dcSDimitry Andric /// The determinator BB should precede the switch-defining BB. 6920eae32dcSDimitry Andric /// 6930eae32dcSDimitry Andric /// Otherwise, it is possible that the state defined in the determinator block 6940eae32dcSDimitry Andric /// defines the state for the next iteration of the loop, rather than for the 6950eae32dcSDimitry Andric /// current one. 6960eae32dcSDimitry Andric /// 6970eae32dcSDimitry Andric /// Currently supported paths: 6980eae32dcSDimitry Andric /// \code 6990eae32dcSDimitry Andric /// < switch bb1 determ def > [ 42, determ ] 7000eae32dcSDimitry Andric /// < switch_and_def bb1 determ > [ 42, determ ] 7010eae32dcSDimitry Andric /// < switch_and_def_and_determ bb1 > [ 42, switch_and_def_and_determ ] 7020eae32dcSDimitry Andric /// \endcode 7030eae32dcSDimitry Andric /// 7040eae32dcSDimitry Andric /// Unsupported paths: 7050eae32dcSDimitry Andric /// \code 7060eae32dcSDimitry Andric /// < switch bb1 def determ > [ 43, determ ] 7070eae32dcSDimitry Andric /// < switch_and_determ bb1 def > [ 43, switch_and_determ ] 7080eae32dcSDimitry Andric /// \endcode 7090eae32dcSDimitry Andric bool isSupported(const ThreadingPath &TPath) { 7100eae32dcSDimitry Andric Instruction *SwitchCondI = dyn_cast<Instruction>(Switch->getCondition()); 7110eae32dcSDimitry Andric assert(SwitchCondI); 7120eae32dcSDimitry Andric if (!SwitchCondI) 7130eae32dcSDimitry Andric return false; 7140eae32dcSDimitry Andric 7150eae32dcSDimitry Andric const BasicBlock *SwitchCondDefBB = SwitchCondI->getParent(); 7160eae32dcSDimitry Andric const BasicBlock *SwitchCondUseBB = Switch->getParent(); 7170eae32dcSDimitry Andric const BasicBlock *DeterminatorBB = TPath.getDeterminatorBB(); 7180eae32dcSDimitry Andric 7190eae32dcSDimitry Andric assert( 7200eae32dcSDimitry Andric SwitchCondUseBB == TPath.getPath().front() && 7210eae32dcSDimitry Andric "The first BB in a threading path should have the switch instruction"); 7220eae32dcSDimitry Andric if (SwitchCondUseBB != TPath.getPath().front()) 7230eae32dcSDimitry Andric return false; 7240eae32dcSDimitry Andric 7250eae32dcSDimitry Andric // Make DeterminatorBB the first element in Path. 7260eae32dcSDimitry Andric PathType Path = TPath.getPath(); 7270eae32dcSDimitry Andric auto ItDet = std::find(Path.begin(), Path.end(), DeterminatorBB); 7280eae32dcSDimitry Andric std::rotate(Path.begin(), ItDet, Path.end()); 7290eae32dcSDimitry Andric 7300eae32dcSDimitry Andric bool IsDetBBSeen = false; 7310eae32dcSDimitry Andric bool IsDefBBSeen = false; 7320eae32dcSDimitry Andric bool IsUseBBSeen = false; 7330eae32dcSDimitry Andric for (BasicBlock *BB : Path) { 7340eae32dcSDimitry Andric if (BB == DeterminatorBB) 7350eae32dcSDimitry Andric IsDetBBSeen = true; 7360eae32dcSDimitry Andric if (BB == SwitchCondDefBB) 7370eae32dcSDimitry Andric IsDefBBSeen = true; 7380eae32dcSDimitry Andric if (BB == SwitchCondUseBB) 7390eae32dcSDimitry Andric IsUseBBSeen = true; 7400eae32dcSDimitry Andric if (IsDetBBSeen && IsUseBBSeen && !IsDefBBSeen) 7410eae32dcSDimitry Andric return false; 7420eae32dcSDimitry Andric } 7430eae32dcSDimitry Andric 7440eae32dcSDimitry Andric return true; 7450eae32dcSDimitry Andric } 7460eae32dcSDimitry Andric 747fe6060f1SDimitry Andric SwitchInst *Switch; 748fe6060f1SDimitry Andric BasicBlock *SwitchBlock; 749fe6060f1SDimitry Andric OptimizationRemarkEmitter *ORE; 750fe6060f1SDimitry Andric std::vector<ThreadingPath> TPaths; 751fe6060f1SDimitry Andric }; 752fe6060f1SDimitry Andric 753fe6060f1SDimitry Andric struct TransformDFA { 754fe6060f1SDimitry Andric TransformDFA(AllSwitchPaths *SwitchPaths, DominatorTree *DT, 755fe6060f1SDimitry Andric AssumptionCache *AC, TargetTransformInfo *TTI, 756fe6060f1SDimitry Andric OptimizationRemarkEmitter *ORE, 757fe6060f1SDimitry Andric SmallPtrSet<const Value *, 32> EphValues) 758fe6060f1SDimitry Andric : SwitchPaths(SwitchPaths), DT(DT), AC(AC), TTI(TTI), ORE(ORE), 759fe6060f1SDimitry Andric EphValues(EphValues) {} 760fe6060f1SDimitry Andric 761fe6060f1SDimitry Andric void run() { 762fe6060f1SDimitry Andric if (isLegalAndProfitableToTransform()) { 763fe6060f1SDimitry Andric createAllExitPaths(); 764fe6060f1SDimitry Andric NumTransforms++; 765fe6060f1SDimitry Andric } 766fe6060f1SDimitry Andric } 767fe6060f1SDimitry Andric 768fe6060f1SDimitry Andric private: 769fe6060f1SDimitry Andric /// This function performs both a legality check and profitability check at 770fe6060f1SDimitry Andric /// the same time since it is convenient to do so. It iterates through all 771fe6060f1SDimitry Andric /// blocks that will be cloned, and keeps track of the duplication cost. It 772fe6060f1SDimitry Andric /// also returns false if it is illegal to clone some required block. 773fe6060f1SDimitry Andric bool isLegalAndProfitableToTransform() { 774fe6060f1SDimitry Andric CodeMetrics Metrics; 775fe6060f1SDimitry Andric SwitchInst *Switch = SwitchPaths->getSwitchInst(); 776fe6060f1SDimitry Andric 777fe6060f1SDimitry Andric // Note that DuplicateBlockMap is not being used as intended here. It is 778fe6060f1SDimitry Andric // just being used to ensure (BB, State) pairs are only counted once. 779fe6060f1SDimitry Andric DuplicateBlockMap DuplicateMap; 780fe6060f1SDimitry Andric 781fe6060f1SDimitry Andric for (ThreadingPath &TPath : SwitchPaths->getThreadingPaths()) { 782fe6060f1SDimitry Andric PathType PathBBs = TPath.getPath(); 783fe6060f1SDimitry Andric uint64_t NextState = TPath.getExitValue(); 784fe6060f1SDimitry Andric const BasicBlock *Determinator = TPath.getDeterminatorBB(); 785fe6060f1SDimitry Andric 786fe6060f1SDimitry Andric // Update Metrics for the Switch block, this is always cloned 787fe6060f1SDimitry Andric BasicBlock *BB = SwitchPaths->getSwitchBlock(); 788fe6060f1SDimitry Andric BasicBlock *VisitedBB = getClonedBB(BB, NextState, DuplicateMap); 789fe6060f1SDimitry Andric if (!VisitedBB) { 790fe6060f1SDimitry Andric Metrics.analyzeBasicBlock(BB, *TTI, EphValues); 791fe6060f1SDimitry Andric DuplicateMap[BB].push_back({BB, NextState}); 792fe6060f1SDimitry Andric } 793fe6060f1SDimitry Andric 794fe6060f1SDimitry Andric // If the Switch block is the Determinator, then we can continue since 795fe6060f1SDimitry Andric // this is the only block that is cloned and we already counted for it. 796fe6060f1SDimitry Andric if (PathBBs.front() == Determinator) 797fe6060f1SDimitry Andric continue; 798fe6060f1SDimitry Andric 799fe6060f1SDimitry Andric // Otherwise update Metrics for all blocks that will be cloned. If any 800fe6060f1SDimitry Andric // block is already cloned and would be reused, don't double count it. 801fe6060f1SDimitry Andric auto DetIt = std::find(PathBBs.begin(), PathBBs.end(), Determinator); 802fe6060f1SDimitry Andric for (auto BBIt = DetIt; BBIt != PathBBs.end(); BBIt++) { 803fe6060f1SDimitry Andric BB = *BBIt; 804fe6060f1SDimitry Andric VisitedBB = getClonedBB(BB, NextState, DuplicateMap); 805fe6060f1SDimitry Andric if (VisitedBB) 806fe6060f1SDimitry Andric continue; 807fe6060f1SDimitry Andric Metrics.analyzeBasicBlock(BB, *TTI, EphValues); 808fe6060f1SDimitry Andric DuplicateMap[BB].push_back({BB, NextState}); 809fe6060f1SDimitry Andric } 810fe6060f1SDimitry Andric 811fe6060f1SDimitry Andric if (Metrics.notDuplicatable) { 812fe6060f1SDimitry Andric LLVM_DEBUG(dbgs() << "DFA Jump Threading: Not jump threading, contains " 813fe6060f1SDimitry Andric << "non-duplicatable instructions.\n"); 814fe6060f1SDimitry Andric ORE->emit([&]() { 815fe6060f1SDimitry Andric return OptimizationRemarkMissed(DEBUG_TYPE, "NonDuplicatableInst", 816fe6060f1SDimitry Andric Switch) 817fe6060f1SDimitry Andric << "Contains non-duplicatable instructions."; 818fe6060f1SDimitry Andric }); 819fe6060f1SDimitry Andric return false; 820fe6060f1SDimitry Andric } 821fe6060f1SDimitry Andric 822fe6060f1SDimitry Andric if (Metrics.convergent) { 823fe6060f1SDimitry Andric LLVM_DEBUG(dbgs() << "DFA Jump Threading: Not jump threading, contains " 824fe6060f1SDimitry Andric << "convergent instructions.\n"); 825fe6060f1SDimitry Andric ORE->emit([&]() { 826fe6060f1SDimitry Andric return OptimizationRemarkMissed(DEBUG_TYPE, "ConvergentInst", Switch) 827fe6060f1SDimitry Andric << "Contains convergent instructions."; 828fe6060f1SDimitry Andric }); 829fe6060f1SDimitry Andric return false; 830fe6060f1SDimitry Andric } 831*81ad6265SDimitry Andric 832*81ad6265SDimitry Andric if (!Metrics.NumInsts.isValid()) { 833*81ad6265SDimitry Andric LLVM_DEBUG(dbgs() << "DFA Jump Threading: Not jump threading, contains " 834*81ad6265SDimitry Andric << "instructions with invalid cost.\n"); 835*81ad6265SDimitry Andric ORE->emit([&]() { 836*81ad6265SDimitry Andric return OptimizationRemarkMissed(DEBUG_TYPE, "ConvergentInst", Switch) 837*81ad6265SDimitry Andric << "Contains instructions with invalid cost."; 838*81ad6265SDimitry Andric }); 839*81ad6265SDimitry Andric return false; 840*81ad6265SDimitry Andric } 841fe6060f1SDimitry Andric } 842fe6060f1SDimitry Andric 843fe6060f1SDimitry Andric unsigned DuplicationCost = 0; 844fe6060f1SDimitry Andric 845fe6060f1SDimitry Andric unsigned JumpTableSize = 0; 846fe6060f1SDimitry Andric TTI->getEstimatedNumberOfCaseClusters(*Switch, JumpTableSize, nullptr, 847fe6060f1SDimitry Andric nullptr); 848fe6060f1SDimitry Andric if (JumpTableSize == 0) { 849fe6060f1SDimitry Andric // Factor in the number of conditional branches reduced from jump 850fe6060f1SDimitry Andric // threading. Assume that lowering the switch block is implemented by 851fe6060f1SDimitry Andric // using binary search, hence the LogBase2(). 852fe6060f1SDimitry Andric unsigned CondBranches = 853fe6060f1SDimitry Andric APInt(32, Switch->getNumSuccessors()).ceilLogBase2(); 854*81ad6265SDimitry Andric DuplicationCost = *Metrics.NumInsts.getValue() / CondBranches; 855fe6060f1SDimitry Andric } else { 856fe6060f1SDimitry Andric // Compared with jump tables, the DFA optimizer removes an indirect branch 857fe6060f1SDimitry Andric // on each loop iteration, thus making branch prediction more precise. The 858fe6060f1SDimitry Andric // more branch targets there are, the more likely it is for the branch 859fe6060f1SDimitry Andric // predictor to make a mistake, and the more benefit there is in the DFA 860fe6060f1SDimitry Andric // optimizer. Thus, the more branch targets there are, the lower is the 861fe6060f1SDimitry Andric // cost of the DFA opt. 862*81ad6265SDimitry Andric DuplicationCost = *Metrics.NumInsts.getValue() / JumpTableSize; 863fe6060f1SDimitry Andric } 864fe6060f1SDimitry Andric 865fe6060f1SDimitry Andric LLVM_DEBUG(dbgs() << "\nDFA Jump Threading: Cost to jump thread block " 866fe6060f1SDimitry Andric << SwitchPaths->getSwitchBlock()->getName() 867fe6060f1SDimitry Andric << " is: " << DuplicationCost << "\n\n"); 868fe6060f1SDimitry Andric 869fe6060f1SDimitry Andric if (DuplicationCost > CostThreshold) { 870fe6060f1SDimitry Andric LLVM_DEBUG(dbgs() << "Not jump threading, duplication cost exceeds the " 871fe6060f1SDimitry Andric << "cost threshold.\n"); 872fe6060f1SDimitry Andric ORE->emit([&]() { 873fe6060f1SDimitry Andric return OptimizationRemarkMissed(DEBUG_TYPE, "NotProfitable", Switch) 874fe6060f1SDimitry Andric << "Duplication cost exceeds the cost threshold (cost=" 875fe6060f1SDimitry Andric << ore::NV("Cost", DuplicationCost) 876fe6060f1SDimitry Andric << ", threshold=" << ore::NV("Threshold", CostThreshold) << ")."; 877fe6060f1SDimitry Andric }); 878fe6060f1SDimitry Andric return false; 879fe6060f1SDimitry Andric } 880fe6060f1SDimitry Andric 881fe6060f1SDimitry Andric ORE->emit([&]() { 882fe6060f1SDimitry Andric return OptimizationRemark(DEBUG_TYPE, "JumpThreaded", Switch) 883fe6060f1SDimitry Andric << "Switch statement jump-threaded."; 884fe6060f1SDimitry Andric }); 885fe6060f1SDimitry Andric 886fe6060f1SDimitry Andric return true; 887fe6060f1SDimitry Andric } 888fe6060f1SDimitry Andric 889fe6060f1SDimitry Andric /// Transform each threading path to effectively jump thread the DFA. 890fe6060f1SDimitry Andric void createAllExitPaths() { 891fe6060f1SDimitry Andric DomTreeUpdater DTU(*DT, DomTreeUpdater::UpdateStrategy::Eager); 892fe6060f1SDimitry Andric 893fe6060f1SDimitry Andric // Move the switch block to the end of the path, since it will be duplicated 894fe6060f1SDimitry Andric BasicBlock *SwitchBlock = SwitchPaths->getSwitchBlock(); 895fe6060f1SDimitry Andric for (ThreadingPath &TPath : SwitchPaths->getThreadingPaths()) { 896fe6060f1SDimitry Andric LLVM_DEBUG(dbgs() << TPath << "\n"); 897fe6060f1SDimitry Andric PathType NewPath(TPath.getPath()); 898fe6060f1SDimitry Andric NewPath.push_back(SwitchBlock); 899fe6060f1SDimitry Andric TPath.setPath(NewPath); 900fe6060f1SDimitry Andric } 901fe6060f1SDimitry Andric 902fe6060f1SDimitry Andric // Transform the ThreadingPaths and keep track of the cloned values 903fe6060f1SDimitry Andric DuplicateBlockMap DuplicateMap; 904fe6060f1SDimitry Andric DefMap NewDefs; 905fe6060f1SDimitry Andric 906fe6060f1SDimitry Andric SmallSet<BasicBlock *, 16> BlocksToClean; 907fe6060f1SDimitry Andric for (BasicBlock *BB : successors(SwitchBlock)) 908fe6060f1SDimitry Andric BlocksToClean.insert(BB); 909fe6060f1SDimitry Andric 910fe6060f1SDimitry Andric for (ThreadingPath &TPath : SwitchPaths->getThreadingPaths()) { 911fe6060f1SDimitry Andric createExitPath(NewDefs, TPath, DuplicateMap, BlocksToClean, &DTU); 912fe6060f1SDimitry Andric NumPaths++; 913fe6060f1SDimitry Andric } 914fe6060f1SDimitry Andric 915fe6060f1SDimitry Andric // After all paths are cloned, now update the last successor of the cloned 916fe6060f1SDimitry Andric // path so it skips over the switch statement 917fe6060f1SDimitry Andric for (ThreadingPath &TPath : SwitchPaths->getThreadingPaths()) 918fe6060f1SDimitry Andric updateLastSuccessor(TPath, DuplicateMap, &DTU); 919fe6060f1SDimitry Andric 920fe6060f1SDimitry Andric // For each instruction that was cloned and used outside, update its uses 921fe6060f1SDimitry Andric updateSSA(NewDefs); 922fe6060f1SDimitry Andric 923fe6060f1SDimitry Andric // Clean PHI Nodes for the newly created blocks 924fe6060f1SDimitry Andric for (BasicBlock *BB : BlocksToClean) 925fe6060f1SDimitry Andric cleanPhiNodes(BB); 926fe6060f1SDimitry Andric } 927fe6060f1SDimitry Andric 928fe6060f1SDimitry Andric /// For a specific ThreadingPath \p Path, create an exit path starting from 929fe6060f1SDimitry Andric /// the determinator block. 930fe6060f1SDimitry Andric /// 931fe6060f1SDimitry Andric /// To remember the correct destination, we have to duplicate blocks 932fe6060f1SDimitry Andric /// corresponding to each state. Also update the terminating instruction of 933fe6060f1SDimitry Andric /// the predecessors, and phis in the successor blocks. 934fe6060f1SDimitry Andric void createExitPath(DefMap &NewDefs, ThreadingPath &Path, 935fe6060f1SDimitry Andric DuplicateBlockMap &DuplicateMap, 936fe6060f1SDimitry Andric SmallSet<BasicBlock *, 16> &BlocksToClean, 937fe6060f1SDimitry Andric DomTreeUpdater *DTU) { 938fe6060f1SDimitry Andric uint64_t NextState = Path.getExitValue(); 939fe6060f1SDimitry Andric const BasicBlock *Determinator = Path.getDeterminatorBB(); 940fe6060f1SDimitry Andric PathType PathBBs = Path.getPath(); 941fe6060f1SDimitry Andric 942fe6060f1SDimitry Andric // Don't select the placeholder block in front 943fe6060f1SDimitry Andric if (PathBBs.front() == Determinator) 944fe6060f1SDimitry Andric PathBBs.pop_front(); 945fe6060f1SDimitry Andric 946fe6060f1SDimitry Andric auto DetIt = std::find(PathBBs.begin(), PathBBs.end(), Determinator); 947fe6060f1SDimitry Andric auto Prev = std::prev(DetIt); 948fe6060f1SDimitry Andric BasicBlock *PrevBB = *Prev; 949fe6060f1SDimitry Andric for (auto BBIt = DetIt; BBIt != PathBBs.end(); BBIt++) { 950fe6060f1SDimitry Andric BasicBlock *BB = *BBIt; 951fe6060f1SDimitry Andric BlocksToClean.insert(BB); 952fe6060f1SDimitry Andric 953fe6060f1SDimitry Andric // We already cloned BB for this NextState, now just update the branch 954fe6060f1SDimitry Andric // and continue. 955fe6060f1SDimitry Andric BasicBlock *NextBB = getClonedBB(BB, NextState, DuplicateMap); 956fe6060f1SDimitry Andric if (NextBB) { 957fe6060f1SDimitry Andric updatePredecessor(PrevBB, BB, NextBB, DTU); 958fe6060f1SDimitry Andric PrevBB = NextBB; 959fe6060f1SDimitry Andric continue; 960fe6060f1SDimitry Andric } 961fe6060f1SDimitry Andric 962fe6060f1SDimitry Andric // Clone the BB and update the successor of Prev to jump to the new block 963fe6060f1SDimitry Andric BasicBlock *NewBB = cloneBlockAndUpdatePredecessor( 964fe6060f1SDimitry Andric BB, PrevBB, NextState, DuplicateMap, NewDefs, DTU); 965fe6060f1SDimitry Andric DuplicateMap[BB].push_back({NewBB, NextState}); 966fe6060f1SDimitry Andric BlocksToClean.insert(NewBB); 967fe6060f1SDimitry Andric PrevBB = NewBB; 968fe6060f1SDimitry Andric } 969fe6060f1SDimitry Andric } 970fe6060f1SDimitry Andric 971fe6060f1SDimitry Andric /// Restore SSA form after cloning blocks. 972fe6060f1SDimitry Andric /// 973fe6060f1SDimitry Andric /// Each cloned block creates new defs for a variable, and the uses need to be 974fe6060f1SDimitry Andric /// updated to reflect this. The uses may be replaced with a cloned value, or 975fe6060f1SDimitry Andric /// some derived phi instruction. Note that all uses of a value defined in the 976fe6060f1SDimitry Andric /// same block were already remapped when cloning the block. 977fe6060f1SDimitry Andric void updateSSA(DefMap &NewDefs) { 978fe6060f1SDimitry Andric SSAUpdaterBulk SSAUpdate; 979fe6060f1SDimitry Andric SmallVector<Use *, 16> UsesToRename; 980fe6060f1SDimitry Andric 981fe6060f1SDimitry Andric for (auto KV : NewDefs) { 982fe6060f1SDimitry Andric Instruction *I = KV.first; 983fe6060f1SDimitry Andric BasicBlock *BB = I->getParent(); 984fe6060f1SDimitry Andric std::vector<Instruction *> Cloned = KV.second; 985fe6060f1SDimitry Andric 986fe6060f1SDimitry Andric // Scan all uses of this instruction to see if it is used outside of its 987fe6060f1SDimitry Andric // block, and if so, record them in UsesToRename. 988fe6060f1SDimitry Andric for (Use &U : I->uses()) { 989fe6060f1SDimitry Andric Instruction *User = cast<Instruction>(U.getUser()); 990fe6060f1SDimitry Andric if (PHINode *UserPN = dyn_cast<PHINode>(User)) { 991fe6060f1SDimitry Andric if (UserPN->getIncomingBlock(U) == BB) 992fe6060f1SDimitry Andric continue; 993fe6060f1SDimitry Andric } else if (User->getParent() == BB) { 994fe6060f1SDimitry Andric continue; 995fe6060f1SDimitry Andric } 996fe6060f1SDimitry Andric 997fe6060f1SDimitry Andric UsesToRename.push_back(&U); 998fe6060f1SDimitry Andric } 999fe6060f1SDimitry Andric 1000fe6060f1SDimitry Andric // If there are no uses outside the block, we're done with this 1001fe6060f1SDimitry Andric // instruction. 1002fe6060f1SDimitry Andric if (UsesToRename.empty()) 1003fe6060f1SDimitry Andric continue; 1004fe6060f1SDimitry Andric LLVM_DEBUG(dbgs() << "DFA-JT: Renaming non-local uses of: " << *I 1005fe6060f1SDimitry Andric << "\n"); 1006fe6060f1SDimitry Andric 1007fe6060f1SDimitry Andric // We found a use of I outside of BB. Rename all uses of I that are 1008fe6060f1SDimitry Andric // outside its block to be uses of the appropriate PHI node etc. See 1009fe6060f1SDimitry Andric // ValuesInBlocks with the values we know. 1010fe6060f1SDimitry Andric unsigned VarNum = SSAUpdate.AddVariable(I->getName(), I->getType()); 1011fe6060f1SDimitry Andric SSAUpdate.AddAvailableValue(VarNum, BB, I); 1012fe6060f1SDimitry Andric for (Instruction *New : Cloned) 1013fe6060f1SDimitry Andric SSAUpdate.AddAvailableValue(VarNum, New->getParent(), New); 1014fe6060f1SDimitry Andric 1015fe6060f1SDimitry Andric while (!UsesToRename.empty()) 1016fe6060f1SDimitry Andric SSAUpdate.AddUse(VarNum, UsesToRename.pop_back_val()); 1017fe6060f1SDimitry Andric 1018fe6060f1SDimitry Andric LLVM_DEBUG(dbgs() << "\n"); 1019fe6060f1SDimitry Andric } 1020fe6060f1SDimitry Andric // SSAUpdater handles phi placement and renaming uses with the appropriate 1021fe6060f1SDimitry Andric // value. 1022fe6060f1SDimitry Andric SSAUpdate.RewriteAllUses(DT); 1023fe6060f1SDimitry Andric } 1024fe6060f1SDimitry Andric 1025fe6060f1SDimitry Andric /// Clones a basic block, and adds it to the CFG. 1026fe6060f1SDimitry Andric /// 1027fe6060f1SDimitry Andric /// This function also includes updating phi nodes in the successors of the 1028fe6060f1SDimitry Andric /// BB, and remapping uses that were defined locally in the cloned BB. 1029fe6060f1SDimitry Andric BasicBlock *cloneBlockAndUpdatePredecessor(BasicBlock *BB, BasicBlock *PrevBB, 1030fe6060f1SDimitry Andric uint64_t NextState, 1031fe6060f1SDimitry Andric DuplicateBlockMap &DuplicateMap, 1032fe6060f1SDimitry Andric DefMap &NewDefs, 1033fe6060f1SDimitry Andric DomTreeUpdater *DTU) { 1034fe6060f1SDimitry Andric ValueToValueMapTy VMap; 1035fe6060f1SDimitry Andric BasicBlock *NewBB = CloneBasicBlock( 1036fe6060f1SDimitry Andric BB, VMap, ".jt" + std::to_string(NextState), BB->getParent()); 1037fe6060f1SDimitry Andric NewBB->moveAfter(BB); 1038fe6060f1SDimitry Andric NumCloned++; 1039fe6060f1SDimitry Andric 1040fe6060f1SDimitry Andric for (Instruction &I : *NewBB) { 1041fe6060f1SDimitry Andric // Do not remap operands of PHINode in case a definition in BB is an 1042fe6060f1SDimitry Andric // incoming value to a phi in the same block. This incoming value will 1043fe6060f1SDimitry Andric // be renamed later while restoring SSA. 1044fe6060f1SDimitry Andric if (isa<PHINode>(&I)) 1045fe6060f1SDimitry Andric continue; 1046fe6060f1SDimitry Andric RemapInstruction(&I, VMap, 1047fe6060f1SDimitry Andric RF_IgnoreMissingLocals | RF_NoModuleLevelChanges); 1048fe6060f1SDimitry Andric if (AssumeInst *II = dyn_cast<AssumeInst>(&I)) 1049fe6060f1SDimitry Andric AC->registerAssumption(II); 1050fe6060f1SDimitry Andric } 1051fe6060f1SDimitry Andric 1052fe6060f1SDimitry Andric updateSuccessorPhis(BB, NewBB, NextState, VMap, DuplicateMap); 1053fe6060f1SDimitry Andric updatePredecessor(PrevBB, BB, NewBB, DTU); 1054fe6060f1SDimitry Andric updateDefMap(NewDefs, VMap); 1055fe6060f1SDimitry Andric 1056fe6060f1SDimitry Andric // Add all successors to the DominatorTree 1057fe6060f1SDimitry Andric SmallPtrSet<BasicBlock *, 4> SuccSet; 1058fe6060f1SDimitry Andric for (auto *SuccBB : successors(NewBB)) { 1059fe6060f1SDimitry Andric if (SuccSet.insert(SuccBB).second) 1060fe6060f1SDimitry Andric DTU->applyUpdates({{DominatorTree::Insert, NewBB, SuccBB}}); 1061fe6060f1SDimitry Andric } 1062fe6060f1SDimitry Andric SuccSet.clear(); 1063fe6060f1SDimitry Andric return NewBB; 1064fe6060f1SDimitry Andric } 1065fe6060f1SDimitry Andric 1066fe6060f1SDimitry Andric /// Update the phi nodes in BB's successors. 1067fe6060f1SDimitry Andric /// 1068fe6060f1SDimitry Andric /// This means creating a new incoming value from NewBB with the new 1069fe6060f1SDimitry Andric /// instruction wherever there is an incoming value from BB. 1070fe6060f1SDimitry Andric void updateSuccessorPhis(BasicBlock *BB, BasicBlock *ClonedBB, 1071fe6060f1SDimitry Andric uint64_t NextState, ValueToValueMapTy &VMap, 1072fe6060f1SDimitry Andric DuplicateBlockMap &DuplicateMap) { 1073fe6060f1SDimitry Andric std::vector<BasicBlock *> BlocksToUpdate; 1074fe6060f1SDimitry Andric 1075fe6060f1SDimitry Andric // If BB is the last block in the path, we can simply update the one case 1076fe6060f1SDimitry Andric // successor that will be reached. 1077fe6060f1SDimitry Andric if (BB == SwitchPaths->getSwitchBlock()) { 1078fe6060f1SDimitry Andric SwitchInst *Switch = SwitchPaths->getSwitchInst(); 1079fe6060f1SDimitry Andric BasicBlock *NextCase = getNextCaseSuccessor(Switch, NextState); 1080fe6060f1SDimitry Andric BlocksToUpdate.push_back(NextCase); 1081fe6060f1SDimitry Andric BasicBlock *ClonedSucc = getClonedBB(NextCase, NextState, DuplicateMap); 1082fe6060f1SDimitry Andric if (ClonedSucc) 1083fe6060f1SDimitry Andric BlocksToUpdate.push_back(ClonedSucc); 1084fe6060f1SDimitry Andric } 1085fe6060f1SDimitry Andric // Otherwise update phis in all successors. 1086fe6060f1SDimitry Andric else { 1087fe6060f1SDimitry Andric for (BasicBlock *Succ : successors(BB)) { 1088fe6060f1SDimitry Andric BlocksToUpdate.push_back(Succ); 1089fe6060f1SDimitry Andric 1090fe6060f1SDimitry Andric // Check if a successor has already been cloned for the particular exit 1091fe6060f1SDimitry Andric // value. In this case if a successor was already cloned, the phi nodes 1092fe6060f1SDimitry Andric // in the cloned block should be updated directly. 1093fe6060f1SDimitry Andric BasicBlock *ClonedSucc = getClonedBB(Succ, NextState, DuplicateMap); 1094fe6060f1SDimitry Andric if (ClonedSucc) 1095fe6060f1SDimitry Andric BlocksToUpdate.push_back(ClonedSucc); 1096fe6060f1SDimitry Andric } 1097fe6060f1SDimitry Andric } 1098fe6060f1SDimitry Andric 1099fe6060f1SDimitry Andric // If there is a phi with an incoming value from BB, create a new incoming 1100fe6060f1SDimitry Andric // value for the new predecessor ClonedBB. The value will either be the same 1101fe6060f1SDimitry Andric // value from BB or a cloned value. 1102fe6060f1SDimitry Andric for (BasicBlock *Succ : BlocksToUpdate) { 1103fe6060f1SDimitry Andric for (auto II = Succ->begin(); PHINode *Phi = dyn_cast<PHINode>(II); 1104fe6060f1SDimitry Andric ++II) { 1105fe6060f1SDimitry Andric Value *Incoming = Phi->getIncomingValueForBlock(BB); 1106fe6060f1SDimitry Andric if (Incoming) { 1107fe6060f1SDimitry Andric if (isa<Constant>(Incoming)) { 1108fe6060f1SDimitry Andric Phi->addIncoming(Incoming, ClonedBB); 1109fe6060f1SDimitry Andric continue; 1110fe6060f1SDimitry Andric } 1111fe6060f1SDimitry Andric Value *ClonedVal = VMap[Incoming]; 1112fe6060f1SDimitry Andric if (ClonedVal) 1113fe6060f1SDimitry Andric Phi->addIncoming(ClonedVal, ClonedBB); 1114fe6060f1SDimitry Andric else 1115fe6060f1SDimitry Andric Phi->addIncoming(Incoming, ClonedBB); 1116fe6060f1SDimitry Andric } 1117fe6060f1SDimitry Andric } 1118fe6060f1SDimitry Andric } 1119fe6060f1SDimitry Andric } 1120fe6060f1SDimitry Andric 1121fe6060f1SDimitry Andric /// Sets the successor of PrevBB to be NewBB instead of OldBB. Note that all 1122fe6060f1SDimitry Andric /// other successors are kept as well. 1123fe6060f1SDimitry Andric void updatePredecessor(BasicBlock *PrevBB, BasicBlock *OldBB, 1124fe6060f1SDimitry Andric BasicBlock *NewBB, DomTreeUpdater *DTU) { 1125fe6060f1SDimitry Andric // When a path is reused, there is a chance that predecessors were already 1126fe6060f1SDimitry Andric // updated before. Check if the predecessor needs to be updated first. 1127fe6060f1SDimitry Andric if (!isPredecessor(OldBB, PrevBB)) 1128fe6060f1SDimitry Andric return; 1129fe6060f1SDimitry Andric 1130fe6060f1SDimitry Andric Instruction *PrevTerm = PrevBB->getTerminator(); 1131fe6060f1SDimitry Andric for (unsigned Idx = 0; Idx < PrevTerm->getNumSuccessors(); Idx++) { 1132fe6060f1SDimitry Andric if (PrevTerm->getSuccessor(Idx) == OldBB) { 1133fe6060f1SDimitry Andric OldBB->removePredecessor(PrevBB, /* KeepOneInputPHIs = */ true); 1134fe6060f1SDimitry Andric PrevTerm->setSuccessor(Idx, NewBB); 1135fe6060f1SDimitry Andric } 1136fe6060f1SDimitry Andric } 1137fe6060f1SDimitry Andric DTU->applyUpdates({{DominatorTree::Delete, PrevBB, OldBB}, 1138fe6060f1SDimitry Andric {DominatorTree::Insert, PrevBB, NewBB}}); 1139fe6060f1SDimitry Andric } 1140fe6060f1SDimitry Andric 1141fe6060f1SDimitry Andric /// Add new value mappings to the DefMap to keep track of all new definitions 1142fe6060f1SDimitry Andric /// for a particular instruction. These will be used while updating SSA form. 1143fe6060f1SDimitry Andric void updateDefMap(DefMap &NewDefs, ValueToValueMapTy &VMap) { 11441fd87a68SDimitry Andric SmallVector<std::pair<Instruction *, Instruction *>> NewDefsVector; 11451fd87a68SDimitry Andric NewDefsVector.reserve(VMap.size()); 11461fd87a68SDimitry Andric 1147fe6060f1SDimitry Andric for (auto Entry : VMap) { 1148fe6060f1SDimitry Andric Instruction *Inst = 1149fe6060f1SDimitry Andric dyn_cast<Instruction>(const_cast<Value *>(Entry.first)); 1150fe6060f1SDimitry Andric if (!Inst || !Entry.second || isa<BranchInst>(Inst) || 1151fe6060f1SDimitry Andric isa<SwitchInst>(Inst)) { 1152fe6060f1SDimitry Andric continue; 1153fe6060f1SDimitry Andric } 1154fe6060f1SDimitry Andric 1155fe6060f1SDimitry Andric Instruction *Cloned = dyn_cast<Instruction>(Entry.second); 1156fe6060f1SDimitry Andric if (!Cloned) 1157fe6060f1SDimitry Andric continue; 1158fe6060f1SDimitry Andric 11591fd87a68SDimitry Andric NewDefsVector.push_back({Inst, Cloned}); 1160fe6060f1SDimitry Andric } 11611fd87a68SDimitry Andric 11621fd87a68SDimitry Andric // Sort the defs to get deterministic insertion order into NewDefs. 11631fd87a68SDimitry Andric sort(NewDefsVector, [](const auto &LHS, const auto &RHS) { 11641fd87a68SDimitry Andric if (LHS.first == RHS.first) 11651fd87a68SDimitry Andric return LHS.second->comesBefore(RHS.second); 11661fd87a68SDimitry Andric return LHS.first->comesBefore(RHS.first); 11671fd87a68SDimitry Andric }); 11681fd87a68SDimitry Andric 11691fd87a68SDimitry Andric for (const auto &KV : NewDefsVector) 11701fd87a68SDimitry Andric NewDefs[KV.first].push_back(KV.second); 1171fe6060f1SDimitry Andric } 1172fe6060f1SDimitry Andric 1173fe6060f1SDimitry Andric /// Update the last branch of a particular cloned path to point to the correct 1174fe6060f1SDimitry Andric /// case successor. 1175fe6060f1SDimitry Andric /// 1176fe6060f1SDimitry Andric /// Note that this is an optional step and would have been done in later 1177fe6060f1SDimitry Andric /// optimizations, but it makes the CFG significantly easier to work with. 1178fe6060f1SDimitry Andric void updateLastSuccessor(ThreadingPath &TPath, 1179fe6060f1SDimitry Andric DuplicateBlockMap &DuplicateMap, 1180fe6060f1SDimitry Andric DomTreeUpdater *DTU) { 1181fe6060f1SDimitry Andric uint64_t NextState = TPath.getExitValue(); 1182fe6060f1SDimitry Andric BasicBlock *BB = TPath.getPath().back(); 1183fe6060f1SDimitry Andric BasicBlock *LastBlock = getClonedBB(BB, NextState, DuplicateMap); 1184fe6060f1SDimitry Andric 1185fe6060f1SDimitry Andric // Note multiple paths can end at the same block so check that it is not 1186fe6060f1SDimitry Andric // updated yet 1187fe6060f1SDimitry Andric if (!isa<SwitchInst>(LastBlock->getTerminator())) 1188fe6060f1SDimitry Andric return; 1189fe6060f1SDimitry Andric SwitchInst *Switch = cast<SwitchInst>(LastBlock->getTerminator()); 1190fe6060f1SDimitry Andric BasicBlock *NextCase = getNextCaseSuccessor(Switch, NextState); 1191fe6060f1SDimitry Andric 1192fe6060f1SDimitry Andric std::vector<DominatorTree::UpdateType> DTUpdates; 1193fe6060f1SDimitry Andric SmallPtrSet<BasicBlock *, 4> SuccSet; 1194fe6060f1SDimitry Andric for (BasicBlock *Succ : successors(LastBlock)) { 1195fe6060f1SDimitry Andric if (Succ != NextCase && SuccSet.insert(Succ).second) 1196fe6060f1SDimitry Andric DTUpdates.push_back({DominatorTree::Delete, LastBlock, Succ}); 1197fe6060f1SDimitry Andric } 1198fe6060f1SDimitry Andric 1199fe6060f1SDimitry Andric Switch->eraseFromParent(); 1200fe6060f1SDimitry Andric BranchInst::Create(NextCase, LastBlock); 1201fe6060f1SDimitry Andric 1202fe6060f1SDimitry Andric DTU->applyUpdates(DTUpdates); 1203fe6060f1SDimitry Andric } 1204fe6060f1SDimitry Andric 1205fe6060f1SDimitry Andric /// After cloning blocks, some of the phi nodes have extra incoming values 1206fe6060f1SDimitry Andric /// that are no longer used. This function removes them. 1207fe6060f1SDimitry Andric void cleanPhiNodes(BasicBlock *BB) { 1208fe6060f1SDimitry Andric // If BB is no longer reachable, remove any remaining phi nodes 1209fe6060f1SDimitry Andric if (pred_empty(BB)) { 1210fe6060f1SDimitry Andric std::vector<PHINode *> PhiToRemove; 1211fe6060f1SDimitry Andric for (auto II = BB->begin(); PHINode *Phi = dyn_cast<PHINode>(II); ++II) { 1212fe6060f1SDimitry Andric PhiToRemove.push_back(Phi); 1213fe6060f1SDimitry Andric } 1214fe6060f1SDimitry Andric for (PHINode *PN : PhiToRemove) { 1215*81ad6265SDimitry Andric PN->replaceAllUsesWith(PoisonValue::get(PN->getType())); 1216fe6060f1SDimitry Andric PN->eraseFromParent(); 1217fe6060f1SDimitry Andric } 1218fe6060f1SDimitry Andric return; 1219fe6060f1SDimitry Andric } 1220fe6060f1SDimitry Andric 1221fe6060f1SDimitry Andric // Remove any incoming values that come from an invalid predecessor 1222fe6060f1SDimitry Andric for (auto II = BB->begin(); PHINode *Phi = dyn_cast<PHINode>(II); ++II) { 1223fe6060f1SDimitry Andric std::vector<BasicBlock *> BlocksToRemove; 1224fe6060f1SDimitry Andric for (BasicBlock *IncomingBB : Phi->blocks()) { 1225fe6060f1SDimitry Andric if (!isPredecessor(BB, IncomingBB)) 1226fe6060f1SDimitry Andric BlocksToRemove.push_back(IncomingBB); 1227fe6060f1SDimitry Andric } 1228fe6060f1SDimitry Andric for (BasicBlock *BB : BlocksToRemove) 1229fe6060f1SDimitry Andric Phi->removeIncomingValue(BB); 1230fe6060f1SDimitry Andric } 1231fe6060f1SDimitry Andric } 1232fe6060f1SDimitry Andric 1233fe6060f1SDimitry Andric /// Checks if BB was already cloned for a particular next state value. If it 1234fe6060f1SDimitry Andric /// was then it returns this cloned block, and otherwise null. 1235fe6060f1SDimitry Andric BasicBlock *getClonedBB(BasicBlock *BB, uint64_t NextState, 1236fe6060f1SDimitry Andric DuplicateBlockMap &DuplicateMap) { 1237fe6060f1SDimitry Andric CloneList ClonedBBs = DuplicateMap[BB]; 1238fe6060f1SDimitry Andric 1239fe6060f1SDimitry Andric // Find an entry in the CloneList with this NextState. If it exists then 1240fe6060f1SDimitry Andric // return the corresponding BB 1241fe6060f1SDimitry Andric auto It = llvm::find_if(ClonedBBs, [NextState](const ClonedBlock &C) { 1242fe6060f1SDimitry Andric return C.State == NextState; 1243fe6060f1SDimitry Andric }); 1244fe6060f1SDimitry Andric return It != ClonedBBs.end() ? (*It).BB : nullptr; 1245fe6060f1SDimitry Andric } 1246fe6060f1SDimitry Andric 1247fe6060f1SDimitry Andric /// Helper to get the successor corresponding to a particular case value for 1248fe6060f1SDimitry Andric /// a switch statement. 1249fe6060f1SDimitry Andric BasicBlock *getNextCaseSuccessor(SwitchInst *Switch, uint64_t NextState) { 1250fe6060f1SDimitry Andric BasicBlock *NextCase = nullptr; 1251fe6060f1SDimitry Andric for (auto Case : Switch->cases()) { 1252fe6060f1SDimitry Andric if (Case.getCaseValue()->getZExtValue() == NextState) { 1253fe6060f1SDimitry Andric NextCase = Case.getCaseSuccessor(); 1254fe6060f1SDimitry Andric break; 1255fe6060f1SDimitry Andric } 1256fe6060f1SDimitry Andric } 1257fe6060f1SDimitry Andric if (!NextCase) 1258fe6060f1SDimitry Andric NextCase = Switch->getDefaultDest(); 1259fe6060f1SDimitry Andric return NextCase; 1260fe6060f1SDimitry Andric } 1261fe6060f1SDimitry Andric 1262fe6060f1SDimitry Andric /// Returns true if IncomingBB is a predecessor of BB. 1263fe6060f1SDimitry Andric bool isPredecessor(BasicBlock *BB, BasicBlock *IncomingBB) { 1264*81ad6265SDimitry Andric return llvm::is_contained(predecessors(BB), IncomingBB); 1265fe6060f1SDimitry Andric } 1266fe6060f1SDimitry Andric 1267fe6060f1SDimitry Andric AllSwitchPaths *SwitchPaths; 1268fe6060f1SDimitry Andric DominatorTree *DT; 1269fe6060f1SDimitry Andric AssumptionCache *AC; 1270fe6060f1SDimitry Andric TargetTransformInfo *TTI; 1271fe6060f1SDimitry Andric OptimizationRemarkEmitter *ORE; 1272fe6060f1SDimitry Andric SmallPtrSet<const Value *, 32> EphValues; 1273fe6060f1SDimitry Andric std::vector<ThreadingPath> TPaths; 1274fe6060f1SDimitry Andric }; 1275fe6060f1SDimitry Andric 1276fe6060f1SDimitry Andric bool DFAJumpThreading::run(Function &F) { 1277fe6060f1SDimitry Andric LLVM_DEBUG(dbgs() << "\nDFA Jump threading: " << F.getName() << "\n"); 1278fe6060f1SDimitry Andric 1279fe6060f1SDimitry Andric if (F.hasOptSize()) { 1280fe6060f1SDimitry Andric LLVM_DEBUG(dbgs() << "Skipping due to the 'minsize' attribute\n"); 1281fe6060f1SDimitry Andric return false; 1282fe6060f1SDimitry Andric } 1283fe6060f1SDimitry Andric 1284fe6060f1SDimitry Andric if (ClViewCfgBefore) 1285fe6060f1SDimitry Andric F.viewCFG(); 1286fe6060f1SDimitry Andric 1287fe6060f1SDimitry Andric SmallVector<AllSwitchPaths, 2> ThreadableLoops; 1288fe6060f1SDimitry Andric bool MadeChanges = false; 1289fe6060f1SDimitry Andric 1290fe6060f1SDimitry Andric for (BasicBlock &BB : F) { 1291fe6060f1SDimitry Andric auto *SI = dyn_cast<SwitchInst>(BB.getTerminator()); 1292fe6060f1SDimitry Andric if (!SI) 1293fe6060f1SDimitry Andric continue; 1294fe6060f1SDimitry Andric 1295fe6060f1SDimitry Andric LLVM_DEBUG(dbgs() << "\nCheck if SwitchInst in BB " << BB.getName() 1296*81ad6265SDimitry Andric << " is a candidate\n"); 1297fe6060f1SDimitry Andric MainSwitch Switch(SI, ORE); 1298fe6060f1SDimitry Andric 1299fe6060f1SDimitry Andric if (!Switch.getInstr()) 1300fe6060f1SDimitry Andric continue; 1301fe6060f1SDimitry Andric 1302fe6060f1SDimitry Andric LLVM_DEBUG(dbgs() << "\nSwitchInst in BB " << BB.getName() << " is a " 1303fe6060f1SDimitry Andric << "candidate for jump threading\n"); 1304fe6060f1SDimitry Andric LLVM_DEBUG(SI->dump()); 1305fe6060f1SDimitry Andric 1306fe6060f1SDimitry Andric unfoldSelectInstrs(DT, Switch.getSelectInsts()); 1307fe6060f1SDimitry Andric if (!Switch.getSelectInsts().empty()) 1308fe6060f1SDimitry Andric MadeChanges = true; 1309fe6060f1SDimitry Andric 1310fe6060f1SDimitry Andric AllSwitchPaths SwitchPaths(&Switch, ORE); 1311fe6060f1SDimitry Andric SwitchPaths.run(); 1312fe6060f1SDimitry Andric 1313fe6060f1SDimitry Andric if (SwitchPaths.getNumThreadingPaths() > 0) { 1314fe6060f1SDimitry Andric ThreadableLoops.push_back(SwitchPaths); 1315fe6060f1SDimitry Andric 1316fe6060f1SDimitry Andric // For the time being limit this optimization to occurring once in a 1317fe6060f1SDimitry Andric // function since it can change the CFG significantly. This is not a 1318fe6060f1SDimitry Andric // strict requirement but it can cause buggy behavior if there is an 1319fe6060f1SDimitry Andric // overlap of blocks in different opportunities. There is a lot of room to 1320fe6060f1SDimitry Andric // experiment with catching more opportunities here. 1321fe6060f1SDimitry Andric break; 1322fe6060f1SDimitry Andric } 1323fe6060f1SDimitry Andric } 1324fe6060f1SDimitry Andric 1325fe6060f1SDimitry Andric SmallPtrSet<const Value *, 32> EphValues; 1326fe6060f1SDimitry Andric if (ThreadableLoops.size() > 0) 1327fe6060f1SDimitry Andric CodeMetrics::collectEphemeralValues(&F, AC, EphValues); 1328fe6060f1SDimitry Andric 1329fe6060f1SDimitry Andric for (AllSwitchPaths SwitchPaths : ThreadableLoops) { 1330fe6060f1SDimitry Andric TransformDFA Transform(&SwitchPaths, DT, AC, TTI, ORE, EphValues); 1331fe6060f1SDimitry Andric Transform.run(); 1332fe6060f1SDimitry Andric MadeChanges = true; 1333fe6060f1SDimitry Andric } 1334fe6060f1SDimitry Andric 1335fe6060f1SDimitry Andric #ifdef EXPENSIVE_CHECKS 1336fe6060f1SDimitry Andric assert(DT->verify(DominatorTree::VerificationLevel::Full)); 1337fe6060f1SDimitry Andric verifyFunction(F, &dbgs()); 1338fe6060f1SDimitry Andric #endif 1339fe6060f1SDimitry Andric 1340fe6060f1SDimitry Andric return MadeChanges; 1341fe6060f1SDimitry Andric } 1342fe6060f1SDimitry Andric 1343fe6060f1SDimitry Andric } // end anonymous namespace 1344fe6060f1SDimitry Andric 1345fe6060f1SDimitry Andric /// Integrate with the new Pass Manager 1346fe6060f1SDimitry Andric PreservedAnalyses DFAJumpThreadingPass::run(Function &F, 1347fe6060f1SDimitry Andric FunctionAnalysisManager &AM) { 1348fe6060f1SDimitry Andric AssumptionCache &AC = AM.getResult<AssumptionAnalysis>(F); 1349fe6060f1SDimitry Andric DominatorTree &DT = AM.getResult<DominatorTreeAnalysis>(F); 1350fe6060f1SDimitry Andric TargetTransformInfo &TTI = AM.getResult<TargetIRAnalysis>(F); 1351fe6060f1SDimitry Andric OptimizationRemarkEmitter ORE(&F); 1352fe6060f1SDimitry Andric 1353fe6060f1SDimitry Andric if (!DFAJumpThreading(&AC, &DT, &TTI, &ORE).run(F)) 1354fe6060f1SDimitry Andric return PreservedAnalyses::all(); 1355fe6060f1SDimitry Andric 1356fe6060f1SDimitry Andric PreservedAnalyses PA; 1357fe6060f1SDimitry Andric PA.preserve<DominatorTreeAnalysis>(); 1358fe6060f1SDimitry Andric return PA; 1359fe6060f1SDimitry Andric } 1360