83#ifdef EXPENSIVE_CHECKS
89#define DEBUG_TYPE "dfa-jump-threading"
91STATISTIC(NumTransforms,
"Number of transformations done");
93STATISTIC(NumPaths,
"Number of individual paths threaded");
98 cl::desc(
"View the CFG before DFA Jump Threading"),
102 "dfa-early-exit-heuristic",
103 cl::desc(
"Exit early if an unpredictable value come from the same loop"),
107 "dfa-max-path-length",
108 cl::desc(
"Max number of blocks searched to find a threading path"),
112 "dfa-max-num-visited-paths",
114 "Max number of blocks visited while enumerating paths around a switch"),
119 cl::desc(
"Max number of paths enumerated around a switch"),
124 cl::desc(
"Maximum cost accepted for the transformation"),
128 "dfa-max-cloned-rate",
130 "Maximum cloned instructions rate accepted for the transformation"),
135 cl::desc(
"Maximum unduplicated blocks with outer uses "
136 "accepted for the transformation"),
144class SelectInstToUnfold {
151 SelectInst *getInst() {
return SI; }
152 PHINode *getUse() {
return SIUse; }
154 explicit operator bool()
const {
return SI && SIUse; }
157class DFAJumpThreading {
159 DFAJumpThreading(AssumptionCache *AC, DomTreeUpdater *DTU, LoopInfo *LI,
160 TargetTransformInfo *TTI, OptimizationRemarkEmitter *ORE)
161 : AC(AC), DTU(DTU), LI(LI), TTI(TTI), ORE(ORE) {}
171 while (!
Stack.empty()) {
172 SelectInstToUnfold SIToUnfold =
Stack.pop_back_val();
174 std::vector<SelectInstToUnfold> NewSIsToUnfold;
175 std::vector<BasicBlock *> NewBBs;
176 unfold(DTU, LI, SIToUnfold, &NewSIsToUnfold, &NewBBs);
183 static void unfold(DomTreeUpdater *DTU, LoopInfo *LI,
184 SelectInstToUnfold SIToUnfold,
185 std::vector<SelectInstToUnfold> *NewSIsToUnfold,
186 std::vector<BasicBlock *> *NewBBs);
191 TargetTransformInfo *TTI;
192 OptimizationRemarkEmitter *ORE;
204 SelectInstToUnfold SIToUnfold,
205 std::vector<SelectInstToUnfold> *NewSIsToUnfold,
206 std::vector<BasicBlock *> *NewBBs) {
207 SelectInst *
SI = SIToUnfold.getInst();
208 PHINode *SIUse = SIToUnfold.getUse();
213 if (UncondBrInst *StartBlockTerm =
218 SI->getContext(), Twine(
SI->getName(),
".si.unfold.false"),
220 NewBBs->push_back(NewBlock);
226 StartBlockTerm->getDebugLoc(),
SI->getDebugLoc());
229 DTU->
applyUpdates({{DominatorTree::Insert, NewBlock, EndBlock}});
236 Value *SIOp1 =
SI->getTrueValue();
237 Value *SIOp2 =
SI->getFalseValue();
240 Twine(SIOp2->
getName(),
".si.unfold.phi"),
245 for (PHINode &Phi : EndBlock->
phis()) {
248 Phi.addIncoming(
Phi.getIncomingValueForBlock(StartBlock), NewBlock);
257 Twine(
SI->getName(),
".si.unfold.phi"),
260 if (Pred != StartBlock && Pred != NewBlock)
271 NewSIsToUnfold->push_back(SelectInstToUnfold(OpSi, SIUse));
273 NewSIsToUnfold->push_back(SelectInstToUnfold(OpSi, NewPhi));
276 StartBlockTerm->eraseFromParent();
279 BI->setDebugLoc(SelectBranchLoc);
281 BI->setMetadata(LLVMContext::MD_prof,
282 SI->getMetadata(LLVMContext::MD_prof));
283 DTU->
applyUpdates({{DominatorTree::Insert, StartBlock, NewBlock}});
287 SI->getContext(), Twine(
SI->getName(),
".si.unfold.true"),
290 SI->getContext(), Twine(
SI->getName(),
".si.unfold.false"),
293 NewBBs->push_back(NewBlockT);
294 NewBBs->push_back(NewBlockF);
322 BI->setDebugLoc(SelectLoc);
324 BI->setMetadata(LLVMContext::MD_prof,
325 SI->getMetadata(LLVMContext::MD_prof));
326 DTU->
applyUpdates({{DominatorTree::Insert, NewBlockT, NewBlockF},
327 {DominatorTree::Insert, NewBlockT, EndBlock},
328 {DominatorTree::Insert, NewBlockF, EndBlock}});
343 NewSIsToUnfold->push_back(SelectInstToUnfold(TrueSI, NewPhiT));
345 NewSIsToUnfold->push_back(SelectInstToUnfold(FalseSi, NewPhiF));
352 for (PHINode &Phi : EndBlock->
phis()) {
355 Phi.addIncoming(
Phi.getIncomingValueForBlock(StartBlock), NewBlockT);
356 Phi.addIncoming(
Phi.getIncomingValueForBlock(StartBlock), NewBlockF);
357 Phi.removeIncomingValue(StartBlock);
363 unsigned SuccNum = CondBr->
getSuccessor(1) == EndBlock ? 1 : 0;
365 DTU->
applyUpdates({{DominatorTree::Delete, StartBlock, EndBlock},
366 {DominatorTree::Insert, StartBlock, NewBlockT}});
371 for (BasicBlock *NewBB : *NewBBs)
372 L->addBasicBlockToLoop(NewBB, *LI);
376 assert(
SI->use_empty() &&
"Select must be dead now");
377 SI->eraseFromParent();
404 OS <<
"< " <<
llvm::join(BBNames,
", ") <<
" >";
413struct ThreadingPath {
415 APInt getExitValue()
const {
return ExitVal; }
416 void setExitValue(
const ConstantInt *V) {
417 ExitVal =
V->getValue();
420 void setExitValue(
const APInt &V) {
424 bool isExitValueSet()
const {
return IsExitValSet; }
427 const BasicBlock *getDeterminatorBB()
const {
return DBB; }
428 void setDeterminator(
const BasicBlock *BB) { DBB = BB; }
431 const PathType &getPath()
const {
return Path; }
432 void setPath(
const PathType &NewPath) { Path = NewPath; }
433 void push_back(BasicBlock *BB) { Path.push_back(BB); }
434 void push_front(BasicBlock *BB) { Path.push_front(BB); }
435 void appendExcludingFirst(
const PathType &OtherPath) {
439 void print(raw_ostream &OS)
const {
447 bool IsExitValSet =
false;
451inline raw_ostream &
operator<<(raw_ostream &OS,
const ThreadingPath &TPath) {
458 MainSwitch(SwitchInst *SI, LoopInfo *LI, OptimizationRemarkEmitter *ORE)
464 return OptimizationRemarkMissed(
DEBUG_TYPE,
"SwitchNotPredictable", SI)
465 <<
"Switch instruction is not predictable.";
470 virtual ~MainSwitch() =
default;
472 SwitchInst *getInstr()
const {
return Instr; }
483 std::deque<std::pair<Value *, BasicBlock *>> Q;
484 SmallPtrSet<Value *, 16> SeenValues;
487 Value *SICond =
SI->getCondition();
497 addToQueue(SICond,
nullptr, Q, SeenValues);
500 Value *Current = Q.front().first;
501 BasicBlock *CurrentIncomingBB = Q.front().second;
505 for (BasicBlock *IncomingBB :
Phi->blocks()) {
506 Value *Incoming =
Phi->getIncomingValueForBlock(IncomingBB);
507 addToQueue(Incoming, IncomingBB, Q, SeenValues);
511 if (!isValidSelectInst(SelI))
513 addToQueue(SelI->getTrueValue(), CurrentIncomingBB, Q, SeenValues);
514 addToQueue(SelI->getFalseValue(), CurrentIncomingBB, Q, SeenValues);
517 SelectInsts.push_back(SelectInstToUnfold(SelI, SelIUse));
535 <<
"\tExiting early due to unpredictability heuristic.\n");
546 void addToQueue(
Value *Val, BasicBlock *BB,
547 std::deque<std::pair<Value *, BasicBlock *>> &Q,
548 SmallPtrSet<Value *, 16> &SeenValues) {
549 if (SeenValues.
insert(Val).second)
550 Q.push_back({Val, BB});
553 bool isValidSelectInst(SelectInst *SI) {
554 if (!
SI->hasOneUse())
579 for (SelectInstToUnfold SIToUnfold : SelectInsts) {
580 SelectInst *PrevSI = SIToUnfold.getInst();
590 SwitchInst *Instr =
nullptr;
594struct AllSwitchPaths {
595 AllSwitchPaths(
const MainSwitch *MSwitch, OptimizationRemarkEmitter *ORE,
596 LoopInfo *LI,
Loop *L)
597 : Switch(MSwitch->getInstr()), SwitchBlock(Switch->
getParent()), ORE(ORE),
598 LI(LI), SwitchOuterLoop(
L) {}
600 std::vector<ThreadingPath> &getThreadingPaths() {
return TPaths; }
601 unsigned getNumThreadingPaths() {
return TPaths.size(); }
602 SwitchInst *getSwitchInst() {
return Switch; }
603 BasicBlock *getSwitchBlock() {
return SwitchBlock; }
613 typedef DenseMap<const BasicBlock *, const PHINode *> StateDefMap;
614 std::vector<ThreadingPath> getPathsFromStateDefMap(StateDefMap &StateDef,
617 unsigned PathsLimit) {
618 std::vector<ThreadingPath> Res;
619 auto *PhiBB =
Phi->getParent();
623 for (
auto *IncomingBB :
Phi->blocks()) {
624 if (Res.size() >= PathsLimit)
626 if (!UniqueBlocks.
insert(IncomingBB).second)
628 if (!SwitchOuterLoop->
contains(IncomingBB))
631 Value *IncomingValue =
Phi->getIncomingValueForBlock(IncomingBB);
635 if (PhiBB == SwitchBlock &&
638 ThreadingPath NewPath;
639 NewPath.setDeterminator(PhiBB);
640 NewPath.setExitValue(
C);
642 if (IncomingBB != SwitchBlock) {
646 NewPath.push_back(IncomingBB);
648 NewPath.push_back(PhiBB);
649 Res.push_back(NewPath);
653 if (VB.
contains(IncomingBB) || IncomingBB == SwitchBlock)
659 auto *IncomingPhiDefBB = IncomingPhi->getParent();
660 if (!StateDef.contains(IncomingPhiDefBB))
664 if (IncomingPhiDefBB == IncomingBB) {
665 assert(PathsLimit > Res.size());
666 std::vector<ThreadingPath> PredPaths = getPathsFromStateDefMap(
667 StateDef, IncomingPhi, VB, PathsLimit - Res.size());
668 for (ThreadingPath &Path : PredPaths) {
669 Path.push_back(PhiBB);
670 Res.push_back(std::move(Path));
680 assert(PathsLimit > Res.size());
681 auto InterPathLimit = PathsLimit - Res.size();
682 IntermediatePaths = paths(IncomingPhiDefBB, IncomingBB, VB,
684 if (IntermediatePaths.empty())
687 assert(InterPathLimit >= IntermediatePaths.size());
688 auto PredPathLimit = InterPathLimit / IntermediatePaths.size();
689 std::vector<ThreadingPath> PredPaths =
690 getPathsFromStateDefMap(StateDef, IncomingPhi, VB, PredPathLimit);
691 for (
const ThreadingPath &Path : PredPaths) {
692 for (
const PathType &IPath : IntermediatePaths) {
693 ThreadingPath NewPath(Path);
694 NewPath.appendExcludingFirst(IPath);
695 NewPath.push_back(PhiBB);
696 Res.push_back(NewPath);
705 unsigned PathDepth,
unsigned PathsLimit) {
711 return OptimizationRemarkAnalysis(
DEBUG_TYPE,
"MaxPathLengthReached",
713 <<
"Exploration stopped after visiting MaxPathLength="
730 SmallPtrSet<BasicBlock *, 4> Successors;
732 if (Res.size() >= PathsLimit)
734 if (!Successors.
insert(Succ).second)
739 Res.push_back({BB, ToBB});
749 if (Succ == CurrLoop->getHeader())
755 assert(PathsLimit > Res.size());
757 paths(Succ, ToBB, Visited, PathDepth + 1, PathsLimit - Res.size());
772 StateDefMap getStateDefMap()
const {
774 DenseSet<const BasicBlock *> MultipleDefBBs;
776 assert(FirstDef &&
"The first definition must be a phi.");
779 Stack.push_back(FirstDef);
780 SmallPtrSet<Value *, 16> SeenValues;
782 while (!
Stack.empty()) {
783 PHINode *CurPhi =
Stack.pop_back_val();
786 auto [
_,
Inserted] = Res.try_emplace(CurDefBlock, CurPhi);
788 MultipleDefBBs.
insert(CurDefBlock);
790 SeenValues.
insert(CurPhi);
792 for (BasicBlock *IncomingBB : CurPhi->
blocks()) {
793 PHINode *IncomingPhi =
797 bool IsOutsideLoops = !SwitchOuterLoop->
contains(IncomingBB);
798 if (SeenValues.
contains(IncomingPhi) || IsOutsideLoops)
801 Stack.push_back(IncomingPhi);
811 for (
auto *BB : MultipleDefBBs) {
812 LLVM_DEBUG(
dbgs() <<
"Not a state-defining block: Multiple defs in "
821 StateDefMap StateDef = getStateDefMap();
822 if (StateDef.empty()) {
824 return OptimizationRemarkMissed(
DEBUG_TYPE,
"SwitchNotPredictable",
826 <<
"Switch instruction is not predictable.";
832 auto *SwitchPhiDefBB = SwitchPhi->getParent();
835 std::vector<ThreadingPath> PathsToPhiDef =
836 getPathsFromStateDefMap(StateDef, SwitchPhi, VB,
MaxNumPaths);
837 if (SwitchPhiDefBB == SwitchBlock || PathsToPhiDef.empty()) {
838 TPaths = std::move(PathsToPhiDef);
843 auto PathsLimit =
MaxNumPaths / PathsToPhiDef.size();
846 paths(SwitchPhiDefBB, SwitchBlock, VB, 1, PathsLimit);
847 if (PathsToSwitchBB.empty())
850 std::vector<ThreadingPath> TempList;
851 for (
const ThreadingPath &Path : PathsToPhiDef) {
852 SmallPtrSet<BasicBlock *, 32> PathSet(
Path.getPath().begin(),
853 Path.getPath().end());
854 for (
const PathType &PathToSw : PathsToSwitchBB) {
856 [&](
const BasicBlock *BB) {
return PathSet.contains(BB); }))
858 ThreadingPath PathCopy(Path);
859 PathCopy.appendExcludingFirst(PathToSw);
860 TempList.push_back(PathCopy);
863 TPaths = std::move(TempList);
868 BasicBlock *getNextCaseSuccessor(
const APInt &NextState) {
870 if (CaseValToDest.empty()) {
871 for (
auto Case : Switch->
cases()) {
872 APInt CaseVal = Case.getCaseValue()->getValue();
873 CaseValToDest[CaseVal] = Case.getCaseSuccessor();
877 auto SuccIt = CaseValToDest.find(NextState);
885 SmallDenseMap<BasicBlock *, APInt> DestToState;
886 for (ThreadingPath &Path : TPaths) {
887 APInt NextState =
Path.getExitValue();
888 BasicBlock *Dest = getNextCaseSuccessor(NextState);
892 if (NextState != StateIt->second) {
893 LLVM_DEBUG(
dbgs() <<
"Next state in " << Path <<
" is equivalent to "
894 << StateIt->second <<
"\n");
895 Path.setExitValue(StateIt->second);
900 unsigned NumVisited = 0;
903 OptimizationRemarkEmitter *ORE;
904 std::vector<ThreadingPath> TPaths;
905 DenseMap<APInt, BasicBlock *> CaseValToDest;
907 Loop *SwitchOuterLoop;
911 TransformDFA(AllSwitchPaths *SwitchPaths, DomTreeUpdater *DTU,
912 AssumptionCache *AC, TargetTransformInfo *
TTI,
913 OptimizationRemarkEmitter *ORE,
914 SmallPtrSet<const Value *, 32> EphValues)
915 : SwitchPaths(SwitchPaths), DTU(DTU), AC(AC),
TTI(
TTI), ORE(ORE),
916 EphValues(EphValues) {}
919 if (isLegalAndProfitableToTransform()) {
920 createAllExitPaths();
932 bool isLegalAndProfitableToTransform() {
934 uint64_t NumClonedInst = 0;
935 SwitchInst *
Switch = SwitchPaths->getSwitchInst();
938 if (
Switch->getNumSuccessors() <= 1)
944 for (ThreadingPath &TPath : SwitchPaths->getThreadingPaths()) {
946 APInt NextState = TPath.getExitValue();
947 const BasicBlock *Determinator = TPath.getDeterminatorBB();
950 BasicBlock *BB = SwitchPaths->getSwitchBlock();
951 BasicBlock *VisitedBB = getClonedBB(BB, NextState, DuplicateMap);
953 Metrics.analyzeBasicBlock(BB, *
TTI, EphValues);
954 NumClonedInst += BB->
size();
955 DuplicateMap[BB].push_back({BB, NextState});
960 if (PathBBs.front() == Determinator)
965 auto DetIt =
llvm::find(PathBBs, Determinator);
966 for (
auto BBIt = DetIt; BBIt != PathBBs.end(); BBIt++) {
968 VisitedBB = getClonedBB(BB, NextState, DuplicateMap);
971 Metrics.analyzeBasicBlock(BB, *
TTI, EphValues);
972 NumClonedInst += BB->
size();
973 DuplicateMap[BB].push_back({BB, NextState});
977 LLVM_DEBUG(
dbgs() <<
"DFA Jump Threading: Not jump threading, contains "
978 <<
"non-duplicatable instructions.\n");
980 return OptimizationRemarkMissed(
DEBUG_TYPE,
"NonDuplicatableInst",
982 <<
"Contains non-duplicatable instructions.";
988 if (
Metrics.Convergence != ConvergenceKind::None) {
989 LLVM_DEBUG(
dbgs() <<
"DFA Jump Threading: Not jump threading, contains "
990 <<
"convergent instructions.\n");
992 return OptimizationRemarkMissed(
DEBUG_TYPE,
"ConvergentInst", Switch)
993 <<
"Contains convergent instructions.";
998 if (!
Metrics.NumInsts.isValid()) {
999 LLVM_DEBUG(
dbgs() <<
"DFA Jump Threading: Not jump threading, contains "
1000 <<
"instructions with invalid cost.\n");
1002 return OptimizationRemarkMissed(
DEBUG_TYPE,
"ConvergentInst", Switch)
1003 <<
"Contains instructions with invalid cost.";
1012 uint64_t NumOrigInst = 0;
1013 uint64_t NumOuterUseBlock = 0;
1014 for (
auto *BB : DuplicateMap.
keys()) {
1015 NumOrigInst += BB->
size();
1019 if (!DuplicateMap.
count(Succ) && Succ->getSinglePredecessor())
1023 if (
double(NumClonedInst) /
double(NumOrigInst) >
MaxClonedRate) {
1024 LLVM_DEBUG(
dbgs() <<
"DFA Jump Threading: Not jump threading, too much "
1025 "instructions wll be cloned\n");
1027 return OptimizationRemarkMissed(
DEBUG_TYPE,
"NotProfitable", Switch)
1028 <<
"Too much instructions will be cloned.";
1038 LLVM_DEBUG(
dbgs() <<
"DFA Jump Threading: Not jump threading, too much "
1039 "blocks with outer uses\n");
1041 return OptimizationRemarkMissed(
DEBUG_TYPE,
"NotProfitable", Switch)
1042 <<
"Too much blocks with outer uses.";
1049 unsigned JumpTableSize = 0;
1052 if (JumpTableSize == 0) {
1056 unsigned CondBranches =
1057 APInt(32,
Switch->getNumSuccessors()).ceilLogBase2();
1058 assert(CondBranches > 0 &&
1059 "The threaded switch must have multiple branches");
1060 DuplicationCost =
Metrics.NumInsts / CondBranches;
1068 DuplicationCost =
Metrics.NumInsts / JumpTableSize;
1071 LLVM_DEBUG(
dbgs() <<
"\nDFA Jump Threading: Cost to jump thread block "
1072 << SwitchPaths->getSwitchBlock()->getName()
1073 <<
" is: " << DuplicationCost <<
"\n\n");
1076 LLVM_DEBUG(
dbgs() <<
"Not jump threading, duplication cost exceeds the "
1077 <<
"cost threshold.\n");
1079 return OptimizationRemarkMissed(
DEBUG_TYPE,
"NotProfitable", Switch)
1080 <<
"Duplication cost exceeds the cost threshold (cost="
1081 <<
ore::NV(
"Cost", DuplicationCost)
1088 return OptimizationRemark(
DEBUG_TYPE,
"JumpThreaded", Switch)
1089 <<
"Switch statement jump-threaded.";
1096 void createAllExitPaths() {
1098 BasicBlock *SwitchBlock = SwitchPaths->getSwitchBlock();
1099 for (ThreadingPath &TPath : SwitchPaths->getThreadingPaths()) {
1103 TPath.push_front(SwitchBlock);
1110 SmallSetVector<BasicBlock *, 16> BlocksToClean;
1113 for (
const ThreadingPath &TPath : SwitchPaths->getThreadingPaths()) {
1114 createExitPath(NewDefs, TPath, DuplicateMap, BlocksToClean, DTU);
1120 for (
const ThreadingPath &TPath : SwitchPaths->getThreadingPaths())
1121 updateLastSuccessor(TPath, DuplicateMap, DTU);
1127 for (BasicBlock *BB : BlocksToClean)
1137 void createExitPath(
DefMap &NewDefs,
const ThreadingPath &Path,
1139 SmallSetVector<BasicBlock *, 16> &BlocksToClean,
1140 DomTreeUpdater *DTU) {
1141 APInt NextState =
Path.getExitValue();
1146 if (PathBBs.front() == Determinator)
1147 PathBBs.pop_front();
1149 auto DetIt =
llvm::find(PathBBs, Determinator);
1152 BasicBlock *PrevBB = PathBBs.size() == 1 ? *DetIt : *std::prev(DetIt);
1153 for (
auto BBIt = DetIt; BBIt != PathBBs.end(); BBIt++) {
1155 BlocksToClean.
insert(BB);
1159 BasicBlock *NextBB = getClonedBB(BB, NextState, DuplicateMap);
1161 updatePredecessor(PrevBB, BB, NextBB, DTU);
1167 BasicBlock *NewBB = cloneBlockAndUpdatePredecessor(
1168 BB, PrevBB, NextState, DuplicateMap, NewDefs, DTU);
1169 DuplicateMap[BB].push_back({NewBB, NextState});
1170 BlocksToClean.
insert(NewBB);
1182 SSAUpdaterBulk SSAUpdate;
1183 SmallVector<Use *, 16> UsesToRename;
1185 for (
const auto &KV : NewDefs) {
1188 std::vector<Instruction *> Cloned = KV.second;
1192 for (Use &U :
I->uses()) {
1195 if (UserPN->getIncomingBlock(U) == BB)
1197 }
else if (
User->getParent() == BB) {
1206 if (UsesToRename.
empty())
1214 unsigned VarNum = SSAUpdate.
AddVariable(
I->getName(),
I->getType());
1216 for (Instruction *New : Cloned)
1219 while (!UsesToRename.
empty())
1233 static BasicBlock *getNextCaseSuccessor(SwitchInst *Switch,
1234 const APInt &NextState) {
1236 for (
auto Case :
Switch->cases()) {
1237 if (Case.getCaseValue()->getValue() == NextState) {
1238 NextCase = Case.getCaseSuccessor();
1243 NextCase =
Switch->getDefaultDest();
1251 BasicBlock *cloneBlockAndUpdatePredecessor(BasicBlock *BB, BasicBlock *PrevBB,
1252 const APInt &NextState,
1255 DomTreeUpdater *DTU) {
1269 for (Instruction &
I : *NewBB) {
1281 updateSuccessorPhis(BB, NewBB, NextState, VMap, DuplicateMap);
1282 updatePredecessor(PrevBB, BB, NewBB, DTU);
1283 updateDefMap(NewDefs, VMap);
1286 SmallPtrSet<BasicBlock *, 4> SuccSet;
1288 if (SuccSet.
insert(SuccBB).second)
1289 DTU->
applyUpdates({{DominatorTree::Insert, NewBB, SuccBB}});
1299 void updateSuccessorPhis(BasicBlock *BB, BasicBlock *ClonedBB,
1302 std::vector<BasicBlock *> BlocksToUpdate;
1306 if (BB == SwitchPaths->getSwitchBlock()) {
1307 SwitchInst *
Switch = SwitchPaths->getSwitchInst();
1308 BasicBlock *NextCase = getNextCaseSuccessor(Switch, NextState);
1309 BlocksToUpdate.push_back(NextCase);
1310 BasicBlock *ClonedSucc = getClonedBB(NextCase, NextState, DuplicateMap);
1312 BlocksToUpdate.push_back(ClonedSucc);
1317 BlocksToUpdate.push_back(Succ);
1322 BasicBlock *ClonedSucc = getClonedBB(Succ, NextState, DuplicateMap);
1324 BlocksToUpdate.push_back(ClonedSucc);
1331 for (BasicBlock *Succ : BlocksToUpdate) {
1332 for (PHINode &Phi : Succ->phis()) {
1333 Value *Incoming =
Phi.getIncomingValueForBlock(BB);
1336 Phi.addIncoming(Incoming, ClonedBB);
1339 Value *ClonedVal = VMap[Incoming];
1341 Phi.addIncoming(ClonedVal, ClonedBB);
1343 Phi.addIncoming(Incoming, ClonedBB);
1351 void updatePredecessor(BasicBlock *PrevBB, BasicBlock *OldBB,
1352 BasicBlock *NewBB, DomTreeUpdater *DTU) {
1355 if (!isPredecessor(OldBB, PrevBB))
1365 DTU->
applyUpdates({{DominatorTree::Delete, PrevBB, OldBB},
1366 {DominatorTree::Insert, PrevBB, NewBB}});
1375 for (
auto Entry : VMap) {
1378 if (!Inst || !
Entry.second ||
1386 NewDefsVector.
push_back({Inst, Cloned});
1390 sort(NewDefsVector, [](
const auto &
LHS,
const auto &
RHS) {
1391 if (
LHS.first ==
RHS.first)
1392 return LHS.second->comesBefore(
RHS.second);
1393 return LHS.first->comesBefore(
RHS.first);
1396 for (
const auto &KV : NewDefsVector)
1397 NewDefs[KV.first].push_back(KV.second);
1405 void updateLastSuccessor(
const ThreadingPath &TPath,
1407 DomTreeUpdater *DTU) {
1408 APInt NextState = TPath.getExitValue();
1410 BasicBlock *LastBlock = getClonedBB(BB, NextState, DuplicateMap);
1417 BasicBlock *NextCase = getNextCaseSuccessor(Switch, NextState);
1419 std::vector<DominatorTree::UpdateType> DTUpdates;
1420 SmallPtrSet<BasicBlock *, 4> SuccSet;
1421 for (BasicBlock *Succ :
successors(LastBlock)) {
1422 if (Succ != NextCase && SuccSet.
insert(Succ).second)
1423 DTUpdates.push_back({DominatorTree::Delete, LastBlock, Succ});
1427 Switch->eraseFromParent();
1435 void cleanPhiNodes(BasicBlock *BB) {
1440 PN.eraseFromParent();
1446 for (PHINode &Phi : BB->
phis())
1447 Phi.removeIncomingValueIf([&](
unsigned Index) {
1449 return !isPredecessor(BB, IncomingBB);
1455 BasicBlock *getClonedBB(BasicBlock *BB,
const APInt &NextState,
1461 auto It =
llvm::find_if(ClonedBBs, [NextState](
const ClonedBlock &
C) {
1462 return C.State == NextState;
1464 return It != ClonedBBs.end() ? (*It).BB :
nullptr;
1468 bool isPredecessor(BasicBlock *BB, BasicBlock *IncomingBB) {
1472 AllSwitchPaths *SwitchPaths;
1473 DomTreeUpdater *DTU;
1474 AssumptionCache *AC;
1475 TargetTransformInfo *
TTI;
1476 OptimizationRemarkEmitter *ORE;
1477 SmallPtrSet<const Value *, 32> EphValues;
1478 std::vector<ThreadingPath> TPaths;
1482bool DFAJumpThreading::run(
Function &
F) {
1483 LLVM_DEBUG(
dbgs() <<
"\nDFA Jump threading: " <<
F.getName() <<
"\n");
1485 if (
F.hasOptSize()) {
1486 LLVM_DEBUG(
dbgs() <<
"Skipping due to the 'minsize' attribute\n");
1494 bool MadeChanges =
false;
1495 LoopInfoBroken =
false;
1497 for (BasicBlock &BB :
F) {
1503 <<
" is a candidate\n");
1504 MainSwitch
Switch(SI, LI, ORE);
1506 if (!
Switch.getInstr()) {
1508 <<
"candidate for jump threading\n");
1513 <<
"candidate for jump threading\n");
1516 unfoldSelectInstrs(
Switch.getSelectInsts());
1517 if (!
Switch.getSelectInsts().empty())
1520 AllSwitchPaths SwitchPaths(&Switch, ORE, LI,
1524 if (SwitchPaths.getNumThreadingPaths() > 0) {
1541 SmallPtrSet<const Value *, 32> EphValues;
1542 if (ThreadableLoops.
size() > 0)
1545 for (AllSwitchPaths SwitchPaths : ThreadableLoops) {
1546 TransformDFA Transform(&SwitchPaths, DTU, AC,
TTI, ORE, EphValues);
1547 if (Transform.run())
1548 MadeChanges = LoopInfoBroken =
true;
1553#ifdef EXPENSIVE_CHECKS
1559 "Failed to maintain validity of domtree!");
1574 DFAJumpThreading ThreadImpl(&AC, &DTU, &LI, &
TTI, &ORE);
1575 if (!ThreadImpl.run(
F))
1580 if (!ThreadImpl.LoopInfoBroken)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file implements a class to represent arbitrary precision integral constant values and operations...
static void print(raw_ostream &Out, object::Archive::Kind Kind, T Val)
static const Function * getParent(const Value *V)
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
SmallPtrSet< const BasicBlock *, 8 > VisitedBlocks
std::deque< BasicBlock * > PathType
std::vector< PathType > PathsType
MapVector< Instruction *, std::vector< Instruction * > > DefMap
std::vector< ClonedBlock > CloneList
DenseMap< BasicBlock *, CloneList > DuplicateBlockMap
This file defines the DenseMap class.
This file defines the DenseSet and SmallDenseSet classes.
This file provides various utilities for inspecting and working with the control flow graph in LLVM I...
static void updateSSA(DominatorTree &DT, CallBrInst *CBR, CallInst *Intrinsic, SSAUpdater &SSAUpdate)
static bool isCandidate(const MachineInstr *MI, Register &DefedReg, Register FrameReg)
uint64_t IntrinsicInst * II
This file implements a set that has insertion order iteration characteristics.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
uint64_t getLimitedValue(uint64_t Limit=UINT64_MAX) const
If this value is smaller than the specified limit, return it, otherwise return the limit value.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
A function analysis which provides an AssumptionCache.
A cache of @llvm.assume calls within a function.
LLVM_ABI void registerAssumption(AssumeInst *CI)
Add an @llvm.assume intrinsic to this function's cache.
LLVM Basic Block Representation.
iterator_range< const_phi_iterator > phis() const
Returns a range that iterates over the phis in the basic block.
LLVM_ABI const_iterator getFirstInsertionPt() const
Returns an iterator to the first instruction in this block that is suitable for inserting a non-PHI i...
const Function * getParent() const
Return the enclosing method, or null if none.
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
LLVM_ABI void moveAfter(BasicBlock *MovePos)
Unlink this basic block from its current function and insert it right after MovePos in the function M...
LLVM_ABI const BasicBlock * getUniqueSuccessor() const
Return the successor of this block if it has a unique successor.
LLVM_ABI LLVMContext & getContext() const
Get the context in which this basic block lives.
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction; assumes that the block is well-formed.
LLVM_ABI void removePredecessor(BasicBlock *Pred, bool KeepOneInputPHIs=false)
Update PHI nodes in this BasicBlock before removal of predecessor Pred.
static CondBrInst * Create(Value *Cond, BasicBlock *IfTrue, BasicBlock *IfFalse, InsertPosition InsertBefore=nullptr)
void setSuccessor(unsigned idx, BasicBlock *NewSucc)
BasicBlock * getSuccessor(unsigned i) const
static LLVM_ABI DebugLoc getMergedLocation(DebugLoc LocA, DebugLoc LocB)
When two instructions are combined into a single instruction we also need to combine the original loc...
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
size_type count(const_arg_type_t< KeyT > Val) const
Return 1 if the specified key is in the map, 0 otherwise.
Analysis pass which computes a DominatorTree.
bool verify(VerificationLevel VL=VerificationLevel::Full) const
verify - checks if the tree is correct.
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
DomTreeT & getDomTree()
Flush DomTree updates and return DomTree.
void applyUpdates(ArrayRef< UpdateT > Updates)
Submit updates to all available trees.
void flush()
Apply all pending updates to available trees and flush all BasicBlocks awaiting deletion.
LLVM_ABI unsigned getNumSuccessors() const LLVM_READONLY
Return the number of successors that this instruction has.
LLVM_ABI BasicBlock * getSuccessor(unsigned Idx) const LLVM_READONLY
Return the specified successor. This instruction must be a terminator.
void setDebugLoc(DebugLoc Loc)
Set the debug location information for this instruction.
LLVM_ABI void setSuccessor(unsigned Idx, BasicBlock *BB)
Update the specified successor to point at the provided block.
Analysis pass that exposes the LoopInfo for a function.
bool contains(const LoopT *L) const
Return true if the specified loop is contained within this loop.
const LoopT * getOutermostLoop() const
Get the outermost loop in which this loop is contained.
LoopT * getLoopFor(const BlockT *BB) const
Return the inner most loop that BB lives in.
This class implements a map that also provides access to all stored values in a deterministic order.
void addIncoming(Value *V, BasicBlock *BB)
Add an incoming value to the end of the PHI list.
iterator_range< const_block_iterator > blocks() const
LLVM_ABI Value * removeIncomingValue(unsigned Idx, bool DeletePHIIfEmpty=true)
Remove an incoming value.
Value * getIncomingValueForBlock(const BasicBlock *BB) const
BasicBlock * getIncomingBlock(unsigned i) const
Return incoming basic block number i.
static PHINode * Create(Type *Ty, unsigned NumReservedValues, const Twine &NameStr="", InsertPosition InsertBefore=nullptr)
Constructors - NumReservedValues is a hint for the number of incoming edges that this phi node will h...
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
PreservedAnalyses & preserve()
Mark an analysis as preserved.
LLVM_ABI unsigned AddVariable(StringRef Name, Type *Ty)
Add a new variable to the SSA rewriter.
LLVM_ABI void AddAvailableValue(unsigned Var, BasicBlock *BB, Value *V)
Indicate that a rewritten value is available in the specified block with the specified value.
LLVM_ABI void RewriteAllUses(DominatorTree *DT, SmallVectorImpl< PHINode * > *InsertedPHIs=nullptr)
Perform all the necessary updates, including new PHI-nodes insertion and the requested uses update.
LLVM_ABI void AddUse(unsigned Var, Use *U)
Record a use of the symbolic value.
This class represents the LLVM 'select' instruction.
const Value * getFalseValue() const
const Value * getTrueValue() const
void insert_range(Range &&R)
bool insert(const value_type &X)
Insert a new element into the SetVector.
bool erase(PtrType Ptr)
Remove pointer from the set.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
bool contains(ConstPtrType Ptr) const
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
void reserve(size_type N)
void push_back(const T &Elt)
BasicBlock * getDefaultDest() const
iterator_range< CaseIt > cases()
Iteration adapter for range-for loops.
Analysis pass providing the TargetTransformInfo.
static UncondBrInst * Create(BasicBlock *Target, InsertPosition InsertBefore=nullptr)
LLVM_ABI bool replaceUsesOfWith(Value *From, Value *To)
Replace uses of one Value with another.
Value * getOperand(unsigned i) const
Type * getType() const
All values are typed, get the type of this value.
LLVM_ABI std::string getNameOrAsOperand() const
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
std::pair< iterator, bool > insert(const ValueT &V)
const ParentTy * getParent() const
This class implements an extremely fast bulk output stream that can only output to a stream.
@ BasicBlock
Various leaf nodes.
initializer< Ty > init(const Ty &Val)
@ Switch
The "resume-switch" lowering, where there are separate resume and destroy functions that are shared b...
DXILDebugInfoMap run(Module &M)
@ User
could "use" a pointer
DiagnosticInfoOptimizationBase::Argument NV
NodeAddr< PhiNode * > Phi
friend class Instruction
Iterator for Instructions in a `BasicBlock.
This is an optimization pass for GlobalISel generic memory operations.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
auto find(R &&Range, const T &Val)
Provide wrappers to std::find which take ranges instead of having to pass begin/end explicitly.
LLVM_ABI cl::opt< bool > ProfcheckDisableMetadataFixes
static cl::opt< unsigned > MaxNumPaths("dfa-max-num-paths", cl::desc("Max number of paths enumerated around a switch"), cl::Hidden, cl::init(200))
LLVM_ABI BasicBlock * CloneBasicBlock(const BasicBlock *BB, ValueToValueMapTy &VMap, const Twine &NameSuffix="", Function *F=nullptr, ClonedCodeInfo *CodeInfo=nullptr, bool MapAtoms=true)
Return a copy of the specified basic block, but without embedding the block into a particular functio...
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI bool verifyFunction(const Function &F, raw_ostream *OS=nullptr)
Check a function for errors, useful for use when debugging a pass.
auto successors(const MachineBasicBlock *BB)
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
auto pred_size(const MachineBasicBlock *BB)
static cl::opt< bool > ClViewCfgBefore("dfa-jump-view-cfg-before", cl::desc("View the CFG before DFA Jump Threading"), cl::Hidden, cl::init(false))
auto map_range(ContainerTy &&C, FuncTy F)
Return a range that applies F to the elements of C.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
static cl::opt< double > MaxClonedRate("dfa-max-cloned-rate", cl::desc("Maximum cloned instructions rate accepted for the transformation"), cl::Hidden, cl::init(7.5))
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
void sort(IteratorTy Start, IteratorTy End)
@ RF_IgnoreMissingLocals
If this flag is set, the remapper ignores missing function-local entries (Argument,...
@ RF_NoModuleLevelChanges
If this flag is set, the remapper knows that only local values within a function (such as an instruct...
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
static cl::opt< unsigned > MaxNumVisitiedPaths("dfa-max-num-visited-paths", cl::desc("Max number of blocks visited while enumerating paths around a switch"), cl::Hidden, cl::init(2500))
std::string join(IteratorT Begin, IteratorT End, StringRef Separator)
Joins the strings in the range [Begin, End), adding Separator between the elements.
static cl::opt< bool > EarlyExitHeuristic("dfa-early-exit-heuristic", cl::desc("Exit early if an unpredictable value come from the same loop"), cl::Hidden, cl::init(true))
void RemapInstruction(Instruction *I, ValueToValueMapTy &VM, RemapFlags Flags=RF_None, ValueMapTypeRemapper *TypeMapper=nullptr, ValueMaterializer *Materializer=nullptr, const MetadataPredicate *IdentityMD=nullptr)
Convert the instruction operands from referencing the current values into those specified by VM.
LLVM_ABI void cloneAndAdaptNoAliasScopes(ArrayRef< MDNode * > NoAliasDeclScopes, ArrayRef< BasicBlock * > NewBlocks, LLVMContext &Context, StringRef Ext)
Clone the specified noalias decl scopes.
raw_ostream & operator<<(raw_ostream &OS, const APFixedPoint &FX)
LLVM_ABI bool VerifyDomInfo
Enables verification of dominator trees.
static cl::opt< unsigned > MaxOuterUseBlocks("dfa-max-out-use-blocks", cl::desc("Maximum unduplicated blocks with outer uses " "accepted for the transformation"), cl::Hidden, cl::init(40))
ValueMap< const Value *, WeakTrackingVH > ValueToValueMapTy
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
static cl::opt< unsigned > MaxPathLength("dfa-max-path-length", cl::desc("Max number of blocks searched to find a threading path"), cl::Hidden, cl::init(20))
auto predecessors(const MachineBasicBlock *BB)
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
static cl::opt< unsigned > CostThreshold("dfa-cost-threshold", cl::desc("Maximum cost accepted for the transformation"), cl::Hidden, cl::init(50))
bool pred_empty(const BasicBlock *BB)
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
LLVM_ABI void identifyNoAliasScopesToClone(ArrayRef< BasicBlock * > BBs, SmallVectorImpl< MDNode * > &NoAliasDeclScopes)
Find the 'llvm.experimental.noalias.scope.decl' intrinsics in the specified basic blocks and extract ...
static LLVM_ABI void collectEphemeralValues(const Loop *L, AssumptionCache *AC, SmallPtrSetImpl< const Value * > &EphValues)
Collect a loop's ephemeral values (those used only by an assume or similar intrinsics in the loop).
LLVM_ABI PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)
Integrate with the new Pass Manager.