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"),
142class SelectInstToUnfold {
149 SelectInst *getInst() {
return SI; }
150 PHINode *getUse() {
return SIUse; }
152 explicit operator bool()
const {
return SI && SIUse; }
155class DFAJumpThreading {
157 DFAJumpThreading(AssumptionCache *AC, DomTreeUpdater *DTU, LoopInfo *LI,
158 TargetTransformInfo *TTI, OptimizationRemarkEmitter *ORE)
159 : AC(AC), DTU(DTU), LI(LI), TTI(TTI), ORE(ORE) {}
169 while (!
Stack.empty()) {
170 SelectInstToUnfold SIToUnfold =
Stack.pop_back_val();
172 std::vector<SelectInstToUnfold> NewSIsToUnfold;
173 std::vector<BasicBlock *> NewBBs;
174 unfold(DTU, LI, SIToUnfold, &NewSIsToUnfold, &NewBBs);
181 static void unfold(DomTreeUpdater *DTU, LoopInfo *LI,
182 SelectInstToUnfold SIToUnfold,
183 std::vector<SelectInstToUnfold> *NewSIsToUnfold,
184 std::vector<BasicBlock *> *NewBBs);
189 TargetTransformInfo *TTI;
190 OptimizationRemarkEmitter *ORE;
202 SelectInstToUnfold SIToUnfold,
203 std::vector<SelectInstToUnfold> *NewSIsToUnfold,
204 std::vector<BasicBlock *> *NewBBs) {
205 SelectInst *
SI = SIToUnfold.getInst();
206 PHINode *SIUse = SIToUnfold.getUse();
211 if (UncondBrInst *StartBlockTerm =
216 SI->getContext(), Twine(
SI->getName(),
".si.unfold.false"),
218 NewBBs->push_back(NewBlock);
224 StartBlockTerm->getDebugLoc(),
SI->getDebugLoc());
227 DTU->
applyUpdates({{DominatorTree::Insert, NewBlock, EndBlock}});
234 Value *SIOp1 =
SI->getTrueValue();
235 Value *SIOp2 =
SI->getFalseValue();
238 Twine(SIOp2->
getName(),
".si.unfold.phi"),
243 for (PHINode &Phi : EndBlock->
phis()) {
246 Phi.addIncoming(
Phi.getIncomingValueForBlock(StartBlock), NewBlock);
255 Twine(
SI->getName(),
".si.unfold.phi"),
258 if (Pred != StartBlock && Pred != NewBlock)
269 NewSIsToUnfold->push_back(SelectInstToUnfold(OpSi, SIUse));
271 NewSIsToUnfold->push_back(SelectInstToUnfold(OpSi, NewPhi));
274 StartBlockTerm->eraseFromParent();
277 BI->setDebugLoc(SelectBranchLoc);
278 BI->setMetadata(LLVMContext::MD_prof,
279 SI->getMetadata(LLVMContext::MD_prof));
280 DTU->
applyUpdates({{DominatorTree::Insert, StartBlock, NewBlock}});
284 SI->getContext(), Twine(
SI->getName(),
".si.unfold.true"),
287 SI->getContext(), Twine(
SI->getName(),
".si.unfold.false"),
290 NewBBs->push_back(NewBlockT);
291 NewBBs->push_back(NewBlockF);
319 BI->setDebugLoc(SelectLoc);
320 BI->setMetadata(LLVMContext::MD_prof,
321 SI->getMetadata(LLVMContext::MD_prof));
322 DTU->
applyUpdates({{DominatorTree::Insert, NewBlockT, NewBlockF},
323 {DominatorTree::Insert, NewBlockT, EndBlock},
324 {DominatorTree::Insert, NewBlockF, EndBlock}});
339 NewSIsToUnfold->push_back(SelectInstToUnfold(TrueSI, NewPhiT));
341 NewSIsToUnfold->push_back(SelectInstToUnfold(FalseSi, NewPhiF));
348 for (PHINode &Phi : EndBlock->
phis()) {
351 Phi.addIncoming(
Phi.getIncomingValueForBlock(StartBlock), NewBlockT);
352 Phi.addIncoming(
Phi.getIncomingValueForBlock(StartBlock), NewBlockF);
353 Phi.removeIncomingValue(StartBlock);
359 unsigned SuccNum = CondBr->
getSuccessor(1) == EndBlock ? 1 : 0;
361 DTU->
applyUpdates({{DominatorTree::Delete, StartBlock, EndBlock},
362 {DominatorTree::Insert, StartBlock, NewBlockT}});
367 for (BasicBlock *NewBB : *NewBBs)
368 L->addBasicBlockToLoop(NewBB, *LI);
372 assert(
SI->use_empty() &&
"Select must be dead now");
373 SI->eraseFromParent();
400 OS <<
"< " <<
llvm::join(BBNames,
", ") <<
" >";
409struct ThreadingPath {
411 APInt getExitValue()
const {
return ExitVal; }
412 void setExitValue(
const ConstantInt *V) {
413 ExitVal =
V->getValue();
416 void setExitValue(
const APInt &V) {
420 bool isExitValueSet()
const {
return IsExitValSet; }
423 const BasicBlock *getDeterminatorBB()
const {
return DBB; }
424 void setDeterminator(
const BasicBlock *BB) { DBB = BB; }
427 const PathType &getPath()
const {
return Path; }
428 void setPath(
const PathType &NewPath) { Path = NewPath; }
429 void push_back(BasicBlock *BB) { Path.push_back(BB); }
430 void push_front(BasicBlock *BB) { Path.push_front(BB); }
431 void appendExcludingFirst(
const PathType &OtherPath) {
435 void print(raw_ostream &OS)
const {
443 bool IsExitValSet =
false;
447inline raw_ostream &
operator<<(raw_ostream &OS,
const ThreadingPath &TPath) {
454 MainSwitch(SwitchInst *SI, LoopInfo *LI, OptimizationRemarkEmitter *ORE)
460 return OptimizationRemarkMissed(
DEBUG_TYPE,
"SwitchNotPredictable", SI)
461 <<
"Switch instruction is not predictable.";
466 virtual ~MainSwitch() =
default;
468 SwitchInst *getInstr()
const {
return Instr; }
479 std::deque<std::pair<Value *, BasicBlock *>> Q;
480 SmallPtrSet<Value *, 16> SeenValues;
483 Value *SICond =
SI->getCondition();
493 addToQueue(SICond,
nullptr, Q, SeenValues);
496 Value *Current = Q.front().first;
497 BasicBlock *CurrentIncomingBB = Q.front().second;
501 for (BasicBlock *IncomingBB :
Phi->blocks()) {
502 Value *Incoming =
Phi->getIncomingValueForBlock(IncomingBB);
503 addToQueue(Incoming, IncomingBB, Q, SeenValues);
507 if (!isValidSelectInst(SelI))
509 addToQueue(SelI->getTrueValue(), CurrentIncomingBB, Q, SeenValues);
510 addToQueue(SelI->getFalseValue(), CurrentIncomingBB, Q, SeenValues);
513 SelectInsts.push_back(SelectInstToUnfold(SelI, SelIUse));
531 <<
"\tExiting early due to unpredictability heuristic.\n");
542 void addToQueue(
Value *Val, BasicBlock *BB,
543 std::deque<std::pair<Value *, BasicBlock *>> &Q,
544 SmallPtrSet<Value *, 16> &SeenValues) {
545 if (SeenValues.
insert(Val).second)
546 Q.push_back({Val, BB});
549 bool isValidSelectInst(SelectInst *SI) {
550 if (!
SI->hasOneUse())
575 for (SelectInstToUnfold SIToUnfold : SelectInsts) {
576 SelectInst *PrevSI = SIToUnfold.getInst();
586 SwitchInst *Instr =
nullptr;
590struct AllSwitchPaths {
591 AllSwitchPaths(
const MainSwitch *MSwitch, OptimizationRemarkEmitter *ORE,
592 LoopInfo *LI,
Loop *L)
593 : Switch(MSwitch->getInstr()), SwitchBlock(Switch->
getParent()), ORE(ORE),
594 LI(LI), SwitchOuterLoop(
L) {}
596 std::vector<ThreadingPath> &getThreadingPaths() {
return TPaths; }
597 unsigned getNumThreadingPaths() {
return TPaths.size(); }
598 SwitchInst *getSwitchInst() {
return Switch; }
599 BasicBlock *getSwitchBlock() {
return SwitchBlock; }
609 typedef DenseMap<const BasicBlock *, const PHINode *> StateDefMap;
610 std::vector<ThreadingPath> getPathsFromStateDefMap(StateDefMap &StateDef,
613 unsigned PathsLimit) {
614 std::vector<ThreadingPath> Res;
615 auto *PhiBB =
Phi->getParent();
619 for (
auto *IncomingBB :
Phi->blocks()) {
620 if (Res.size() >= PathsLimit)
622 if (!UniqueBlocks.
insert(IncomingBB).second)
624 if (!SwitchOuterLoop->
contains(IncomingBB))
627 Value *IncomingValue =
Phi->getIncomingValueForBlock(IncomingBB);
631 if (PhiBB == SwitchBlock &&
634 ThreadingPath NewPath;
635 NewPath.setDeterminator(PhiBB);
636 NewPath.setExitValue(
C);
638 if (IncomingBB != SwitchBlock) {
642 NewPath.push_back(IncomingBB);
644 NewPath.push_back(PhiBB);
645 Res.push_back(NewPath);
649 if (VB.
contains(IncomingBB) || IncomingBB == SwitchBlock)
655 auto *IncomingPhiDefBB = IncomingPhi->getParent();
656 if (!StateDef.contains(IncomingPhiDefBB))
660 if (IncomingPhiDefBB == IncomingBB) {
661 assert(PathsLimit > Res.size());
662 std::vector<ThreadingPath> PredPaths = getPathsFromStateDefMap(
663 StateDef, IncomingPhi, VB, PathsLimit - Res.size());
664 for (ThreadingPath &Path : PredPaths) {
665 Path.push_back(PhiBB);
666 Res.push_back(std::move(Path));
676 assert(PathsLimit > Res.size());
677 auto InterPathLimit = PathsLimit - Res.size();
678 IntermediatePaths = paths(IncomingPhiDefBB, IncomingBB, VB,
680 if (IntermediatePaths.empty())
683 assert(InterPathLimit >= IntermediatePaths.size());
684 auto PredPathLimit = InterPathLimit / IntermediatePaths.size();
685 std::vector<ThreadingPath> PredPaths =
686 getPathsFromStateDefMap(StateDef, IncomingPhi, VB, PredPathLimit);
687 for (
const ThreadingPath &Path : PredPaths) {
688 for (
const PathType &IPath : IntermediatePaths) {
689 ThreadingPath NewPath(Path);
690 NewPath.appendExcludingFirst(IPath);
691 NewPath.push_back(PhiBB);
692 Res.push_back(NewPath);
701 unsigned PathDepth,
unsigned PathsLimit) {
707 return OptimizationRemarkAnalysis(
DEBUG_TYPE,
"MaxPathLengthReached",
709 <<
"Exploration stopped after visiting MaxPathLength="
726 SmallPtrSet<BasicBlock *, 4> Successors;
728 if (Res.size() >= PathsLimit)
730 if (!Successors.
insert(Succ).second)
735 Res.push_back({BB, ToBB});
745 if (Succ == CurrLoop->getHeader())
751 assert(PathsLimit > Res.size());
753 paths(Succ, ToBB, Visited, PathDepth + 1, PathsLimit - Res.size());
768 StateDefMap getStateDefMap()
const {
770 DenseSet<const BasicBlock *> MultipleDefBBs;
772 assert(FirstDef &&
"The first definition must be a phi.");
775 Stack.push_back(FirstDef);
776 SmallPtrSet<Value *, 16> SeenValues;
778 while (!
Stack.empty()) {
779 PHINode *CurPhi =
Stack.pop_back_val();
782 auto [
_,
Inserted] = Res.try_emplace(CurDefBlock, CurPhi);
784 MultipleDefBBs.
insert(CurDefBlock);
786 SeenValues.
insert(CurPhi);
788 for (BasicBlock *IncomingBB : CurPhi->
blocks()) {
789 PHINode *IncomingPhi =
793 bool IsOutsideLoops = !SwitchOuterLoop->
contains(IncomingBB);
794 if (SeenValues.
contains(IncomingPhi) || IsOutsideLoops)
797 Stack.push_back(IncomingPhi);
807 for (
auto *BB : MultipleDefBBs) {
808 LLVM_DEBUG(
dbgs() <<
"Not a state-defining block: Multiple defs in "
817 StateDefMap StateDef = getStateDefMap();
818 if (StateDef.empty()) {
820 return OptimizationRemarkMissed(
DEBUG_TYPE,
"SwitchNotPredictable",
822 <<
"Switch instruction is not predictable.";
828 auto *SwitchPhiDefBB = SwitchPhi->getParent();
831 std::vector<ThreadingPath> PathsToPhiDef =
832 getPathsFromStateDefMap(StateDef, SwitchPhi, VB,
MaxNumPaths);
833 if (SwitchPhiDefBB == SwitchBlock || PathsToPhiDef.empty()) {
834 TPaths = std::move(PathsToPhiDef);
839 auto PathsLimit =
MaxNumPaths / PathsToPhiDef.size();
842 paths(SwitchPhiDefBB, SwitchBlock, VB, 1, PathsLimit);
843 if (PathsToSwitchBB.empty())
846 std::vector<ThreadingPath> TempList;
847 for (
const ThreadingPath &Path : PathsToPhiDef) {
848 SmallPtrSet<BasicBlock *, 32> PathSet(
Path.getPath().begin(),
849 Path.getPath().end());
850 for (
const PathType &PathToSw : PathsToSwitchBB) {
852 [&](
const BasicBlock *BB) {
return PathSet.contains(BB); }))
854 ThreadingPath PathCopy(Path);
855 PathCopy.appendExcludingFirst(PathToSw);
856 TempList.push_back(PathCopy);
859 TPaths = std::move(TempList);
864 BasicBlock *getNextCaseSuccessor(
const APInt &NextState) {
866 if (CaseValToDest.empty()) {
867 for (
auto Case : Switch->
cases()) {
868 APInt CaseVal = Case.getCaseValue()->getValue();
869 CaseValToDest[CaseVal] = Case.getCaseSuccessor();
873 auto SuccIt = CaseValToDest.find(NextState);
881 SmallDenseMap<BasicBlock *, APInt> DestToState;
882 for (ThreadingPath &Path : TPaths) {
883 APInt NextState =
Path.getExitValue();
884 BasicBlock *Dest = getNextCaseSuccessor(NextState);
888 if (NextState != StateIt->second) {
889 LLVM_DEBUG(
dbgs() <<
"Next state in " << Path <<
" is equivalent to "
890 << StateIt->second <<
"\n");
891 Path.setExitValue(StateIt->second);
896 unsigned NumVisited = 0;
899 OptimizationRemarkEmitter *ORE;
900 std::vector<ThreadingPath> TPaths;
901 DenseMap<APInt, BasicBlock *> CaseValToDest;
903 Loop *SwitchOuterLoop;
907 TransformDFA(AllSwitchPaths *SwitchPaths, DomTreeUpdater *DTU,
908 AssumptionCache *AC, TargetTransformInfo *
TTI,
909 OptimizationRemarkEmitter *ORE,
910 SmallPtrSet<const Value *, 32> EphValues)
911 : SwitchPaths(SwitchPaths), DTU(DTU), AC(AC),
TTI(
TTI), ORE(ORE),
912 EphValues(EphValues) {}
915 if (isLegalAndProfitableToTransform()) {
916 createAllExitPaths();
928 bool isLegalAndProfitableToTransform() {
931 SwitchInst *
Switch = SwitchPaths->getSwitchInst();
934 if (
Switch->getNumSuccessors() <= 1)
940 for (ThreadingPath &TPath : SwitchPaths->getThreadingPaths()) {
942 APInt NextState = TPath.getExitValue();
943 const BasicBlock *Determinator = TPath.getDeterminatorBB();
946 BasicBlock *BB = SwitchPaths->getSwitchBlock();
947 BasicBlock *VisitedBB = getClonedBB(BB, NextState, DuplicateMap);
949 Metrics.analyzeBasicBlock(BB, *
TTI, EphValues);
950 NumClonedInst += BB->
size();
951 DuplicateMap[BB].push_back({BB, NextState});
956 if (PathBBs.front() == Determinator)
961 auto DetIt =
llvm::find(PathBBs, Determinator);
962 for (
auto BBIt = DetIt; BBIt != PathBBs.end(); BBIt++) {
964 VisitedBB = getClonedBB(BB, NextState, DuplicateMap);
967 Metrics.analyzeBasicBlock(BB, *
TTI, EphValues);
968 NumClonedInst += BB->
size();
969 DuplicateMap[BB].push_back({BB, NextState});
973 LLVM_DEBUG(
dbgs() <<
"DFA Jump Threading: Not jump threading, contains "
974 <<
"non-duplicatable instructions.\n");
976 return OptimizationRemarkMissed(
DEBUG_TYPE,
"NonDuplicatableInst",
978 <<
"Contains non-duplicatable instructions.";
984 if (
Metrics.Convergence != ConvergenceKind::None) {
985 LLVM_DEBUG(
dbgs() <<
"DFA Jump Threading: Not jump threading, contains "
986 <<
"convergent instructions.\n");
988 return OptimizationRemarkMissed(
DEBUG_TYPE,
"ConvergentInst", Switch)
989 <<
"Contains convergent instructions.";
994 if (!
Metrics.NumInsts.isValid()) {
995 LLVM_DEBUG(
dbgs() <<
"DFA Jump Threading: Not jump threading, contains "
996 <<
"instructions with invalid cost.\n");
998 return OptimizationRemarkMissed(
DEBUG_TYPE,
"ConvergentInst", Switch)
999 <<
"Contains instructions with invalid cost.";
1010 for (
auto *BB : DuplicateMap.
keys()) {
1011 NumOrigInst += BB->
size();
1015 if (!DuplicateMap.
count(Succ) && Succ->getSinglePredecessor())
1019 if (
double(NumClonedInst) /
double(NumOrigInst) >
MaxClonedRate) {
1020 LLVM_DEBUG(
dbgs() <<
"DFA Jump Threading: Not jump threading, too much "
1021 "instructions wll be cloned\n");
1023 return OptimizationRemarkMissed(
DEBUG_TYPE,
"NotProfitable", Switch)
1024 <<
"Too much instructions will be cloned.";
1034 LLVM_DEBUG(
dbgs() <<
"DFA Jump Threading: Not jump threading, too much "
1035 "blocks with outer uses\n");
1037 return OptimizationRemarkMissed(
DEBUG_TYPE,
"NotProfitable", Switch)
1038 <<
"Too much blocks with outer uses.";
1045 unsigned JumpTableSize = 0;
1048 if (JumpTableSize == 0) {
1052 unsigned CondBranches =
1053 APInt(32,
Switch->getNumSuccessors()).ceilLogBase2();
1054 assert(CondBranches > 0 &&
1055 "The threaded switch must have multiple branches");
1056 DuplicationCost =
Metrics.NumInsts / CondBranches;
1064 DuplicationCost =
Metrics.NumInsts / JumpTableSize;
1067 LLVM_DEBUG(
dbgs() <<
"\nDFA Jump Threading: Cost to jump thread block "
1068 << SwitchPaths->getSwitchBlock()->getName()
1069 <<
" is: " << DuplicationCost <<
"\n\n");
1072 LLVM_DEBUG(
dbgs() <<
"Not jump threading, duplication cost exceeds the "
1073 <<
"cost threshold.\n");
1075 return OptimizationRemarkMissed(
DEBUG_TYPE,
"NotProfitable", Switch)
1076 <<
"Duplication cost exceeds the cost threshold (cost="
1077 <<
ore::NV(
"Cost", DuplicationCost)
1084 return OptimizationRemark(
DEBUG_TYPE,
"JumpThreaded", Switch)
1085 <<
"Switch statement jump-threaded.";
1092 void createAllExitPaths() {
1094 BasicBlock *SwitchBlock = SwitchPaths->getSwitchBlock();
1095 for (ThreadingPath &TPath : SwitchPaths->getThreadingPaths()) {
1099 TPath.push_front(SwitchBlock);
1106 SmallSetVector<BasicBlock *, 16> BlocksToClean;
1109 for (
const ThreadingPath &TPath : SwitchPaths->getThreadingPaths()) {
1110 createExitPath(NewDefs, TPath, DuplicateMap, BlocksToClean, DTU);
1116 for (
const ThreadingPath &TPath : SwitchPaths->getThreadingPaths())
1117 updateLastSuccessor(TPath, DuplicateMap, DTU);
1123 for (BasicBlock *BB : BlocksToClean)
1133 void createExitPath(
DefMap &NewDefs,
const ThreadingPath &Path,
1135 SmallSetVector<BasicBlock *, 16> &BlocksToClean,
1136 DomTreeUpdater *DTU) {
1137 APInt NextState =
Path.getExitValue();
1142 if (PathBBs.front() == Determinator)
1143 PathBBs.pop_front();
1145 auto DetIt =
llvm::find(PathBBs, Determinator);
1148 BasicBlock *PrevBB = PathBBs.size() == 1 ? *DetIt : *std::prev(DetIt);
1149 for (
auto BBIt = DetIt; BBIt != PathBBs.end(); BBIt++) {
1151 BlocksToClean.
insert(BB);
1155 BasicBlock *NextBB = getClonedBB(BB, NextState, DuplicateMap);
1157 updatePredecessor(PrevBB, BB, NextBB, DTU);
1163 BasicBlock *NewBB = cloneBlockAndUpdatePredecessor(
1164 BB, PrevBB, NextState, DuplicateMap, NewDefs, DTU);
1165 DuplicateMap[BB].push_back({NewBB, NextState});
1166 BlocksToClean.
insert(NewBB);
1178 SSAUpdaterBulk SSAUpdate;
1179 SmallVector<Use *, 16> UsesToRename;
1181 for (
const auto &KV : NewDefs) {
1184 std::vector<Instruction *> Cloned = KV.second;
1188 for (Use &U :
I->uses()) {
1191 if (UserPN->getIncomingBlock(U) == BB)
1193 }
else if (
User->getParent() == BB) {
1202 if (UsesToRename.
empty())
1210 unsigned VarNum = SSAUpdate.
AddVariable(
I->getName(),
I->getType());
1212 for (Instruction *New : Cloned)
1215 while (!UsesToRename.
empty())
1229 static BasicBlock *getNextCaseSuccessor(SwitchInst *Switch,
1230 const APInt &NextState) {
1232 for (
auto Case :
Switch->cases()) {
1233 if (Case.getCaseValue()->getValue() == NextState) {
1234 NextCase = Case.getCaseSuccessor();
1239 NextCase =
Switch->getDefaultDest();
1247 BasicBlock *cloneBlockAndUpdatePredecessor(BasicBlock *BB, BasicBlock *PrevBB,
1248 const APInt &NextState,
1251 DomTreeUpdater *DTU) {
1265 for (Instruction &
I : *NewBB) {
1277 updateSuccessorPhis(BB, NewBB, NextState, VMap, DuplicateMap);
1278 updatePredecessor(PrevBB, BB, NewBB, DTU);
1279 updateDefMap(NewDefs, VMap);
1282 SmallPtrSet<BasicBlock *, 4> SuccSet;
1284 if (SuccSet.
insert(SuccBB).second)
1285 DTU->
applyUpdates({{DominatorTree::Insert, NewBB, SuccBB}});
1295 void updateSuccessorPhis(BasicBlock *BB, BasicBlock *ClonedBB,
1298 std::vector<BasicBlock *> BlocksToUpdate;
1302 if (BB == SwitchPaths->getSwitchBlock()) {
1303 SwitchInst *
Switch = SwitchPaths->getSwitchInst();
1304 BasicBlock *NextCase = getNextCaseSuccessor(Switch, NextState);
1305 BlocksToUpdate.push_back(NextCase);
1306 BasicBlock *ClonedSucc = getClonedBB(NextCase, NextState, DuplicateMap);
1308 BlocksToUpdate.push_back(ClonedSucc);
1313 BlocksToUpdate.push_back(Succ);
1318 BasicBlock *ClonedSucc = getClonedBB(Succ, NextState, DuplicateMap);
1320 BlocksToUpdate.push_back(ClonedSucc);
1327 for (BasicBlock *Succ : BlocksToUpdate) {
1328 for (PHINode &Phi : Succ->phis()) {
1329 Value *Incoming =
Phi.getIncomingValueForBlock(BB);
1332 Phi.addIncoming(Incoming, ClonedBB);
1335 Value *ClonedVal = VMap[Incoming];
1337 Phi.addIncoming(ClonedVal, ClonedBB);
1339 Phi.addIncoming(Incoming, ClonedBB);
1347 void updatePredecessor(BasicBlock *PrevBB, BasicBlock *OldBB,
1348 BasicBlock *NewBB, DomTreeUpdater *DTU) {
1351 if (!isPredecessor(OldBB, PrevBB))
1361 DTU->
applyUpdates({{DominatorTree::Delete, PrevBB, OldBB},
1362 {DominatorTree::Insert, PrevBB, NewBB}});
1371 for (
auto Entry : VMap) {
1374 if (!Inst || !
Entry.second ||
1382 NewDefsVector.
push_back({Inst, Cloned});
1386 sort(NewDefsVector, [](
const auto &
LHS,
const auto &
RHS) {
1387 if (
LHS.first ==
RHS.first)
1388 return LHS.second->comesBefore(
RHS.second);
1389 return LHS.first->comesBefore(
RHS.first);
1392 for (
const auto &KV : NewDefsVector)
1393 NewDefs[KV.first].push_back(KV.second);
1401 void updateLastSuccessor(
const ThreadingPath &TPath,
1403 DomTreeUpdater *DTU) {
1404 APInt NextState = TPath.getExitValue();
1406 BasicBlock *LastBlock = getClonedBB(BB, NextState, DuplicateMap);
1413 BasicBlock *NextCase = getNextCaseSuccessor(Switch, NextState);
1415 std::vector<DominatorTree::UpdateType> DTUpdates;
1416 SmallPtrSet<BasicBlock *, 4> SuccSet;
1417 for (BasicBlock *Succ :
successors(LastBlock)) {
1418 if (Succ != NextCase && SuccSet.
insert(Succ).second)
1419 DTUpdates.push_back({DominatorTree::Delete, LastBlock, Succ});
1423 Switch->eraseFromParent();
1431 void cleanPhiNodes(BasicBlock *BB) {
1436 PN.eraseFromParent();
1442 for (PHINode &Phi : BB->
phis())
1443 Phi.removeIncomingValueIf([&](
unsigned Index) {
1445 return !isPredecessor(BB, IncomingBB);
1451 BasicBlock *getClonedBB(BasicBlock *BB,
const APInt &NextState,
1457 auto It =
llvm::find_if(ClonedBBs, [NextState](
const ClonedBlock &
C) {
1458 return C.State == NextState;
1460 return It != ClonedBBs.end() ? (*It).BB :
nullptr;
1464 bool isPredecessor(BasicBlock *BB, BasicBlock *IncomingBB) {
1468 AllSwitchPaths *SwitchPaths;
1469 DomTreeUpdater *DTU;
1470 AssumptionCache *AC;
1471 TargetTransformInfo *
TTI;
1472 OptimizationRemarkEmitter *ORE;
1473 SmallPtrSet<const Value *, 32> EphValues;
1474 std::vector<ThreadingPath> TPaths;
1478bool DFAJumpThreading::run(
Function &
F) {
1479 LLVM_DEBUG(
dbgs() <<
"\nDFA Jump threading: " <<
F.getName() <<
"\n");
1481 if (
F.hasOptSize()) {
1482 LLVM_DEBUG(
dbgs() <<
"Skipping due to the 'minsize' attribute\n");
1490 bool MadeChanges =
false;
1491 LoopInfoBroken =
false;
1493 for (BasicBlock &BB :
F) {
1499 <<
" is a candidate\n");
1500 MainSwitch
Switch(SI, LI, ORE);
1502 if (!
Switch.getInstr()) {
1504 <<
"candidate for jump threading\n");
1509 <<
"candidate for jump threading\n");
1512 unfoldSelectInstrs(
Switch.getSelectInsts());
1513 if (!
Switch.getSelectInsts().empty())
1516 AllSwitchPaths SwitchPaths(&Switch, ORE, LI,
1520 if (SwitchPaths.getNumThreadingPaths() > 0) {
1537 SmallPtrSet<const Value *, 32> EphValues;
1538 if (ThreadableLoops.
size() > 0)
1541 for (AllSwitchPaths SwitchPaths : ThreadableLoops) {
1542 TransformDFA Transform(&SwitchPaths, DTU, AC,
TTI, ORE, EphValues);
1543 if (Transform.run())
1544 MadeChanges = LoopInfoBroken =
true;
1549#ifdef EXPENSIVE_CHECKS
1555 "Failed to maintain validity of domtree!");
1570 DFAJumpThreading ThreadImpl(&AC, &DTU, &LI, &
TTI, &ORE);
1571 if (!ThreadImpl.run(
F))
1576 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...
PointerTypeMap run(const Module &M)
Compute the PointerTypeMap for the 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.
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.