83#ifdef EXPENSIVE_CHECKS
89#define DEBUG_TYPE "dfa-jump-threading"
91STATISTIC(NumTransforms,
"Number of transformations done");
93STATISTIC(NumPaths,
"Number of individual paths threaded");
96class SelectInstToUnfold {
103 SelectInst *getInst() {
return SI; }
104 PHINode *getUse() {
return SIUse; }
106 explicit operator bool()
const {
return SI && SIUse; }
109class DFAJumpThreading {
111 DFAJumpThreading(AssumptionCache *AC, DomTreeUpdater *DTU, LoopInfo *LI,
112 TargetTransformInfo *TTI, OptimizationRemarkEmitter *ORE)
113 : Opts(ScalarOptions::
Global), AC(AC), DTU(DTU), LI(LI), TTI(TTI),
124 while (!
Stack.empty()) {
125 SelectInstToUnfold SIToUnfold =
Stack.pop_back_val();
127 std::vector<SelectInstToUnfold> NewSIsToUnfold;
128 std::vector<BasicBlock *> NewBBs;
129 unfold(DTU, LI, SIToUnfold, &NewSIsToUnfold, &NewBBs);
136 static void unfold(DomTreeUpdater *DTU, LoopInfo *LI,
137 SelectInstToUnfold SIToUnfold,
138 std::vector<SelectInstToUnfold> *NewSIsToUnfold,
139 std::vector<BasicBlock *> *NewBBs);
141 const ScalarOptions &Opts;
145 TargetTransformInfo *TTI;
146 OptimizationRemarkEmitter *ORE;
158 SelectInstToUnfold SIToUnfold,
159 std::vector<SelectInstToUnfold> *NewSIsToUnfold,
160 std::vector<BasicBlock *> *NewBBs) {
161 SelectInst *
SI = SIToUnfold.getInst();
162 PHINode *SIUse = SIToUnfold.getUse();
167 if (UncondBrInst *StartBlockTerm =
172 SI->getContext(), Twine(
SI->getName(),
".si.unfold.false"),
174 NewBBs->push_back(NewBlock);
180 StartBlockTerm->getDebugLoc(),
SI->getDebugLoc());
183 DTU->
applyUpdates({{DominatorTree::Insert, NewBlock, EndBlock}});
190 Value *SIOp1 =
SI->getTrueValue();
191 Value *SIOp2 =
SI->getFalseValue();
194 Twine(SIOp2->
getName(),
".si.unfold.phi"),
199 for (PHINode &Phi : EndBlock->
phis()) {
202 Phi.addIncoming(
Phi.getIncomingValueForBlock(StartBlock), NewBlock);
211 Twine(
SI->getName(),
".si.unfold.phi"),
214 if (Pred != StartBlock && Pred != NewBlock)
225 NewSIsToUnfold->push_back(SelectInstToUnfold(OpSi, SIUse));
227 NewSIsToUnfold->push_back(SelectInstToUnfold(OpSi, NewPhi));
230 StartBlockTerm->eraseFromParent();
233 BI->setDebugLoc(SelectBranchLoc);
234 BI->setMetadata(LLVMContext::MD_prof,
235 SI->getMetadata(LLVMContext::MD_prof));
236 DTU->
applyUpdates({{DominatorTree::Insert, StartBlock, NewBlock}});
240 SI->getContext(), Twine(
SI->getName(),
".si.unfold.true"),
243 SI->getContext(), Twine(
SI->getName(),
".si.unfold.false"),
246 NewBBs->push_back(NewBlockT);
247 NewBBs->push_back(NewBlockF);
275 BI->setDebugLoc(SelectLoc);
276 BI->setMetadata(LLVMContext::MD_prof,
277 SI->getMetadata(LLVMContext::MD_prof));
278 DTU->
applyUpdates({{DominatorTree::Insert, NewBlockT, NewBlockF},
279 {DominatorTree::Insert, NewBlockT, EndBlock},
280 {DominatorTree::Insert, NewBlockF, EndBlock}});
295 NewSIsToUnfold->push_back(SelectInstToUnfold(TrueSI, NewPhiT));
297 NewSIsToUnfold->push_back(SelectInstToUnfold(FalseSi, NewPhiF));
304 for (PHINode &Phi : EndBlock->
phis()) {
307 Phi.addIncoming(
Phi.getIncomingValueForBlock(StartBlock), NewBlockT);
308 Phi.addIncoming(
Phi.getIncomingValueForBlock(StartBlock), NewBlockF);
309 Phi.removeIncomingValue(StartBlock);
315 unsigned SuccNum = CondBr->
getSuccessor(1) == EndBlock ? 1 : 0;
317 DTU->
applyUpdates({{DominatorTree::Delete, StartBlock, EndBlock},
318 {DominatorTree::Insert, StartBlock, NewBlockT}});
323 for (BasicBlock *NewBB : *NewBBs)
324 L->addBasicBlockToLoop(NewBB, *LI);
328 assert(
SI->use_empty() &&
"Select must be dead now");
329 SI->eraseFromParent();
356 OS <<
"< " <<
llvm::join(BBNames,
", ") <<
" >";
365struct ThreadingPath {
367 APInt getExitValue()
const {
return ExitVal; }
368 void setExitValue(
const ConstantInt *V) {
369 ExitVal =
V->getValue();
372 void setExitValue(
const APInt &V) {
376 bool isExitValueSet()
const {
return IsExitValSet; }
379 const BasicBlock *getDeterminatorBB()
const {
return DBB; }
380 void setDeterminator(
const BasicBlock *BB) { DBB = BB; }
383 const PathType &getPath()
const {
return Path; }
384 void setPath(
const PathType &NewPath) { Path = NewPath; }
385 void push_back(BasicBlock *BB) { Path.push_back(BB); }
386 void push_front(BasicBlock *BB) { Path.push_front(BB); }
387 void appendExcludingFirst(
const PathType &OtherPath) {
391 void print(raw_ostream &OS)
const {
399 bool IsExitValSet =
false;
403inline raw_ostream &
operator<<(raw_ostream &OS,
const ThreadingPath &TPath) {
410 MainSwitch(
const ScalarOptions &Opts, SwitchInst *SI, LoopInfo *LI,
411 OptimizationRemarkEmitter *ORE)
417 return OptimizationRemarkMissed(
DEBUG_TYPE,
"SwitchNotPredictable", SI)
418 <<
"Switch instruction is not predictable.";
423 virtual ~MainSwitch() =
default;
425 SwitchInst *getInstr()
const {
return Instr; }
435 bool isCandidate(
const SwitchInst *SI,
const ScalarOptions &Opts) {
436 std::deque<std::pair<Value *, BasicBlock *>> Q;
437 SmallPtrSet<Value *, 16> SeenValues;
440 Value *SICond =
SI->getCondition();
450 addToQueue(SICond,
nullptr, Q, SeenValues);
453 Value *Current = Q.front().first;
454 BasicBlock *CurrentIncomingBB = Q.front().second;
458 for (BasicBlock *IncomingBB :
Phi->blocks()) {
459 Value *Incoming =
Phi->getIncomingValueForBlock(IncomingBB);
460 addToQueue(Incoming, IncomingBB, Q, SeenValues);
464 if (!isValidSelectInst(SelI))
466 addToQueue(SelI->getTrueValue(), CurrentIncomingBB, Q, SeenValues);
467 addToQueue(SelI->getFalseValue(), CurrentIncomingBB, Q, SeenValues);
470 SelectInsts.push_back(SelectInstToUnfold(SelI, SelIUse));
485 if (Opts.dfa_early_exit_heuristic &&
488 <<
"\tExiting early due to unpredictability heuristic.\n");
499 void addToQueue(
Value *Val, BasicBlock *BB,
500 std::deque<std::pair<Value *, BasicBlock *>> &Q,
501 SmallPtrSet<Value *, 16> &SeenValues) {
502 if (SeenValues.
insert(Val).second)
503 Q.push_back({Val, BB});
506 bool isValidSelectInst(SelectInst *SI) {
507 if (!
SI->hasOneUse())
532 for (SelectInstToUnfold SIToUnfold : SelectInsts) {
533 SelectInst *PrevSI = SIToUnfold.getInst();
543 SwitchInst *Instr =
nullptr;
547struct AllSwitchPaths {
548 AllSwitchPaths(
const ScalarOptions &Opts,
const MainSwitch *MSwitch,
549 OptimizationRemarkEmitter *ORE, LoopInfo *LI,
Loop *L)
550 : Opts(Opts), Switch(MSwitch->getInstr()),
551 SwitchBlock(Switch->
getParent()), ORE(ORE), LI(LI), SwitchOuterLoop(
L) {
554 std::vector<ThreadingPath> &getThreadingPaths() {
return TPaths; }
555 unsigned getNumThreadingPaths() {
return TPaths.size(); }
556 SwitchInst *getSwitchInst() {
return Switch; }
557 BasicBlock *getSwitchBlock() {
return SwitchBlock; }
567 typedef DenseMap<const BasicBlock *, const PHINode *> StateDefMap;
568 std::vector<ThreadingPath> getPathsFromStateDefMap(StateDefMap &StateDef,
571 unsigned PathsLimit) {
572 std::vector<ThreadingPath> Res;
573 auto *PhiBB =
Phi->getParent();
577 for (
auto *IncomingBB :
Phi->blocks()) {
578 if (Res.size() >= PathsLimit)
580 if (!UniqueBlocks.
insert(IncomingBB).second)
582 if (!SwitchOuterLoop->
contains(IncomingBB))
585 Value *IncomingValue =
Phi->getIncomingValueForBlock(IncomingBB);
589 if (PhiBB == SwitchBlock &&
592 ThreadingPath NewPath;
593 NewPath.setDeterminator(PhiBB);
594 NewPath.setExitValue(
C);
596 if (IncomingBB != SwitchBlock) {
600 NewPath.push_back(IncomingBB);
602 NewPath.push_back(PhiBB);
603 Res.push_back(NewPath);
607 if (VB.
contains(IncomingBB) || IncomingBB == SwitchBlock)
613 auto *IncomingPhiDefBB = IncomingPhi->getParent();
614 if (!StateDef.contains(IncomingPhiDefBB))
618 if (IncomingPhiDefBB == IncomingBB) {
619 assert(PathsLimit > Res.size());
620 std::vector<ThreadingPath> PredPaths = getPathsFromStateDefMap(
621 StateDef, IncomingPhi, VB, PathsLimit - Res.size());
622 for (ThreadingPath &Path : PredPaths) {
623 Path.push_back(PhiBB);
624 Res.push_back(std::move(Path));
634 assert(PathsLimit > Res.size());
635 auto InterPathLimit = PathsLimit - Res.size();
636 IntermediatePaths = paths(IncomingPhiDefBB, IncomingBB, VB,
638 if (IntermediatePaths.empty())
641 assert(InterPathLimit >= IntermediatePaths.size());
642 auto PredPathLimit = InterPathLimit / IntermediatePaths.size();
643 std::vector<ThreadingPath> PredPaths =
644 getPathsFromStateDefMap(StateDef, IncomingPhi, VB, PredPathLimit);
645 for (
const ThreadingPath &Path : PredPaths) {
646 for (
const PathType &IPath : IntermediatePaths) {
647 ThreadingPath NewPath(Path);
648 NewPath.appendExcludingFirst(IPath);
649 NewPath.push_back(PhiBB);
650 Res.push_back(NewPath);
659 unsigned PathDepth,
unsigned PathsLimit) {
663 if (PathDepth > Opts.dfa_max_path_length) {
665 return OptimizationRemarkAnalysis(
DEBUG_TYPE,
"MaxPathLengthReached",
667 <<
"Exploration stopped after visiting MaxPathLength="
668 <<
ore::NV(
"MaxPathLength", Opts.dfa_max_path_length)
675 if (++NumVisited > Opts.dfa_max_num_visited_paths)
685 SmallPtrSet<BasicBlock *, 4> Successors;
687 if (Res.size() >= PathsLimit)
689 if (!Successors.
insert(Succ).second)
694 Res.push_back({BB, ToBB});
704 if (Succ == CurrLoop->getHeader())
710 assert(PathsLimit > Res.size());
712 paths(Succ, ToBB, Visited, PathDepth + 1, PathsLimit - Res.size());
727 StateDefMap getStateDefMap()
const {
729 DenseSet<const BasicBlock *> MultipleDefBBs;
731 assert(FirstDef &&
"The first definition must be a phi.");
734 Stack.push_back(FirstDef);
735 SmallPtrSet<Value *, 16> SeenValues;
737 while (!
Stack.empty()) {
738 PHINode *CurPhi =
Stack.pop_back_val();
741 auto [
_,
Inserted] = Res.try_emplace(CurDefBlock, CurPhi);
743 MultipleDefBBs.
insert(CurDefBlock);
745 SeenValues.
insert(CurPhi);
747 for (BasicBlock *IncomingBB : CurPhi->
blocks()) {
748 PHINode *IncomingPhi =
752 bool IsOutsideLoops = !SwitchOuterLoop->
contains(IncomingBB);
753 if (SeenValues.
contains(IncomingPhi) || IsOutsideLoops)
756 Stack.push_back(IncomingPhi);
766 for (
auto *BB : MultipleDefBBs) {
767 LLVM_DEBUG(
dbgs() <<
"Not a state-defining block: Multiple defs in "
776 StateDefMap StateDef = getStateDefMap();
777 if (StateDef.empty()) {
779 return OptimizationRemarkMissed(
DEBUG_TYPE,
"SwitchNotPredictable",
781 <<
"Switch instruction is not predictable.";
787 auto *SwitchPhiDefBB = SwitchPhi->getParent();
790 std::vector<ThreadingPath> PathsToPhiDef = getPathsFromStateDefMap(
791 StateDef, SwitchPhi, VB, Opts.dfa_max_num_paths);
792 if (SwitchPhiDefBB == SwitchBlock || PathsToPhiDef.empty()) {
793 TPaths = std::move(PathsToPhiDef);
797 assert(Opts.dfa_max_num_paths >= PathsToPhiDef.size() &&
798 !PathsToPhiDef.empty());
799 auto PathsLimit = Opts.dfa_max_num_paths / PathsToPhiDef.size();
802 paths(SwitchPhiDefBB, SwitchBlock, VB, 1, PathsLimit);
803 if (PathsToSwitchBB.empty())
806 std::vector<ThreadingPath> TempList;
807 for (
const ThreadingPath &Path : PathsToPhiDef) {
808 SmallPtrSet<BasicBlock *, 32> PathSet(
Path.getPath().begin(),
809 Path.getPath().end());
810 for (
const PathType &PathToSw : PathsToSwitchBB) {
812 [&](
const BasicBlock *BB) {
return PathSet.contains(BB); }))
814 ThreadingPath PathCopy(Path);
815 PathCopy.appendExcludingFirst(PathToSw);
816 TempList.push_back(PathCopy);
819 TPaths = std::move(TempList);
824 BasicBlock *getNextCaseSuccessor(
const APInt &NextState) {
826 if (CaseValToDest.empty()) {
827 for (
auto Case : Switch->
cases()) {
828 APInt CaseVal = Case.getCaseValue()->getValue();
829 CaseValToDest[CaseVal] = Case.getCaseSuccessor();
833 auto SuccIt = CaseValToDest.find(NextState);
841 SmallDenseMap<BasicBlock *, APInt> DestToState;
842 for (ThreadingPath &Path : TPaths) {
843 APInt NextState =
Path.getExitValue();
844 BasicBlock *Dest = getNextCaseSuccessor(NextState);
848 if (NextState != StateIt->second) {
849 LLVM_DEBUG(
dbgs() <<
"Next state in " << Path <<
" is equivalent to "
850 << StateIt->second <<
"\n");
851 Path.setExitValue(StateIt->second);
856 const ScalarOptions &Opts;
857 unsigned NumVisited = 0;
860 OptimizationRemarkEmitter *ORE;
861 std::vector<ThreadingPath> TPaths;
862 DenseMap<APInt, BasicBlock *> CaseValToDest;
864 Loop *SwitchOuterLoop;
868 TransformDFA(
const ScalarOptions &Opts, AllSwitchPaths *SwitchPaths,
869 DomTreeUpdater *DTU, AssumptionCache *AC,
870 TargetTransformInfo *
TTI, OptimizationRemarkEmitter *ORE,
871 SmallPtrSet<const Value *, 32> EphValues)
872 : Opts(Opts), SwitchPaths(SwitchPaths), DTU(DTU), AC(AC),
TTI(
TTI),
873 ORE(ORE), EphValues(EphValues) {}
876 if (isLegalAndProfitableToTransform()) {
877 createAllExitPaths();
889 bool isLegalAndProfitableToTransform() {
892 SwitchInst *
Switch = SwitchPaths->getSwitchInst();
895 if (
Switch->getNumSuccessors() <= 1)
901 for (ThreadingPath &TPath : SwitchPaths->getThreadingPaths()) {
903 APInt NextState = TPath.getExitValue();
904 const BasicBlock *Determinator = TPath.getDeterminatorBB();
907 BasicBlock *BB = SwitchPaths->getSwitchBlock();
908 BasicBlock *VisitedBB = getClonedBB(BB, NextState, DuplicateMap);
910 Metrics.analyzeBasicBlock(BB, *
TTI, EphValues);
911 NumClonedInst += BB->
size();
912 DuplicateMap[BB].push_back({BB, NextState});
917 if (PathBBs.front() == Determinator)
922 auto DetIt =
llvm::find(PathBBs, Determinator);
923 for (
auto BBIt = DetIt; BBIt != PathBBs.end(); BBIt++) {
925 VisitedBB = getClonedBB(BB, NextState, DuplicateMap);
928 Metrics.analyzeBasicBlock(BB, *
TTI, EphValues);
929 NumClonedInst += BB->
size();
930 DuplicateMap[BB].push_back({BB, NextState});
934 LLVM_DEBUG(
dbgs() <<
"DFA Jump Threading: Not jump threading, contains "
935 <<
"non-duplicatable instructions.\n");
937 return OptimizationRemarkMissed(
DEBUG_TYPE,
"NonDuplicatableInst",
939 <<
"Contains non-duplicatable instructions.";
945 if (
Metrics.Convergence != ConvergenceKind::None) {
946 LLVM_DEBUG(
dbgs() <<
"DFA Jump Threading: Not jump threading, contains "
947 <<
"convergent instructions.\n");
949 return OptimizationRemarkMissed(
DEBUG_TYPE,
"ConvergentInst", Switch)
950 <<
"Contains convergent instructions.";
955 if (!
Metrics.NumInsts.isValid()) {
956 LLVM_DEBUG(
dbgs() <<
"DFA Jump Threading: Not jump threading, contains "
957 <<
"instructions with invalid cost.\n");
959 return OptimizationRemarkMissed(
DEBUG_TYPE,
"ConvergentInst", Switch)
960 <<
"Contains instructions with invalid cost.";
971 for (
auto *BB : DuplicateMap.
keys()) {
972 NumOrigInst += BB->
size();
976 if (!DuplicateMap.
count(Succ) && Succ->getSinglePredecessor())
980 if (
double(NumClonedInst) /
double(NumOrigInst) >
981 Opts.dfa_max_cloned_rate) {
982 LLVM_DEBUG(
dbgs() <<
"DFA Jump Threading: Not jump threading, too much "
983 "instructions wll be cloned\n");
985 return OptimizationRemarkMissed(
DEBUG_TYPE,
"NotProfitable", Switch)
986 <<
"Too much instructions will be cloned.";
995 if (NumOuterUseBlock > Opts.dfa_max_out_use_blocks) {
996 LLVM_DEBUG(
dbgs() <<
"DFA Jump Threading: Not jump threading, too much "
997 "blocks with outer uses\n");
999 return OptimizationRemarkMissed(
DEBUG_TYPE,
"NotProfitable", Switch)
1000 <<
"Too much blocks with outer uses.";
1007 unsigned JumpTableSize = 0;
1010 if (JumpTableSize == 0) {
1014 unsigned CondBranches =
1015 APInt(32,
Switch->getNumSuccessors()).ceilLogBase2();
1016 assert(CondBranches > 0 &&
1017 "The threaded switch must have multiple branches");
1018 DuplicationCost =
Metrics.NumInsts / CondBranches;
1026 DuplicationCost =
Metrics.NumInsts / JumpTableSize;
1029 LLVM_DEBUG(
dbgs() <<
"\nDFA Jump Threading: Cost to jump thread block "
1030 << SwitchPaths->getSwitchBlock()->getName()
1031 <<
" is: " << DuplicationCost <<
"\n\n");
1033 if (DuplicationCost > Opts.dfa_cost_threshold) {
1034 LLVM_DEBUG(
dbgs() <<
"Not jump threading, duplication cost exceeds the "
1035 <<
"cost threshold.\n");
1037 return OptimizationRemarkMissed(
DEBUG_TYPE,
"NotProfitable", Switch)
1038 <<
"Duplication cost exceeds the cost threshold (cost="
1039 <<
ore::NV(
"Cost", DuplicationCost) <<
", threshold="
1040 <<
ore::NV(
"Threshold", Opts.dfa_cost_threshold) <<
").";
1046 return OptimizationRemark(
DEBUG_TYPE,
"JumpThreaded", Switch)
1047 <<
"Switch statement jump-threaded.";
1054 void createAllExitPaths() {
1056 BasicBlock *SwitchBlock = SwitchPaths->getSwitchBlock();
1057 for (ThreadingPath &TPath : SwitchPaths->getThreadingPaths()) {
1061 TPath.push_front(SwitchBlock);
1068 SmallSetVector<BasicBlock *, 16> BlocksToClean;
1071 for (
const ThreadingPath &TPath : SwitchPaths->getThreadingPaths()) {
1072 createExitPath(NewDefs, TPath, DuplicateMap, BlocksToClean, DTU);
1078 for (
const ThreadingPath &TPath : SwitchPaths->getThreadingPaths())
1079 updateLastSuccessor(TPath, DuplicateMap, DTU);
1085 for (BasicBlock *BB : BlocksToClean)
1095 void createExitPath(
DefMap &NewDefs,
const ThreadingPath &Path,
1097 SmallSetVector<BasicBlock *, 16> &BlocksToClean,
1098 DomTreeUpdater *DTU) {
1099 APInt NextState =
Path.getExitValue();
1104 if (PathBBs.front() == Determinator)
1105 PathBBs.pop_front();
1107 auto DetIt =
llvm::find(PathBBs, Determinator);
1110 BasicBlock *PrevBB = PathBBs.size() == 1 ? *DetIt : *std::prev(DetIt);
1111 for (
auto BBIt = DetIt; BBIt != PathBBs.end(); BBIt++) {
1113 BlocksToClean.
insert(BB);
1117 BasicBlock *NextBB = getClonedBB(BB, NextState, DuplicateMap);
1119 updatePredecessor(PrevBB, BB, NextBB, DTU);
1125 BasicBlock *NewBB = cloneBlockAndUpdatePredecessor(
1126 BB, PrevBB, NextState, DuplicateMap, NewDefs, DTU);
1127 DuplicateMap[BB].push_back({NewBB, NextState});
1128 BlocksToClean.
insert(NewBB);
1140 SSAUpdaterBulk SSAUpdate;
1141 SmallVector<Use *, 16> UsesToRename;
1143 for (
const auto &KV : NewDefs) {
1146 std::vector<Instruction *> Cloned = KV.second;
1150 for (Use &U :
I->uses()) {
1153 if (UserPN->getIncomingBlock(U) == BB)
1155 }
else if (
User->getParent() == BB) {
1164 if (UsesToRename.
empty())
1172 unsigned VarNum = SSAUpdate.
AddVariable(
I->getName(),
I->getType());
1174 for (Instruction *New : Cloned)
1177 while (!UsesToRename.
empty())
1191 static BasicBlock *getNextCaseSuccessor(SwitchInst *Switch,
1192 const APInt &NextState) {
1194 for (
auto Case :
Switch->cases()) {
1195 if (Case.getCaseValue()->getValue() == NextState) {
1196 NextCase = Case.getCaseSuccessor();
1201 NextCase =
Switch->getDefaultDest();
1209 BasicBlock *cloneBlockAndUpdatePredecessor(BasicBlock *BB, BasicBlock *PrevBB,
1210 const APInt &NextState,
1213 DomTreeUpdater *DTU) {
1227 for (Instruction &
I : *NewBB) {
1239 updateSuccessorPhis(BB, NewBB, NextState, VMap, DuplicateMap);
1240 updatePredecessor(PrevBB, BB, NewBB, DTU);
1241 updateDefMap(NewDefs, VMap);
1244 SmallPtrSet<BasicBlock *, 4> SuccSet;
1246 if (SuccSet.
insert(SuccBB).second)
1247 DTU->
applyUpdates({{DominatorTree::Insert, NewBB, SuccBB}});
1257 void updateSuccessorPhis(BasicBlock *BB, BasicBlock *ClonedBB,
1260 std::vector<BasicBlock *> BlocksToUpdate;
1264 if (BB == SwitchPaths->getSwitchBlock()) {
1265 SwitchInst *
Switch = SwitchPaths->getSwitchInst();
1266 BasicBlock *NextCase = getNextCaseSuccessor(Switch, NextState);
1267 BlocksToUpdate.push_back(NextCase);
1268 BasicBlock *ClonedSucc = getClonedBB(NextCase, NextState, DuplicateMap);
1270 BlocksToUpdate.push_back(ClonedSucc);
1275 BlocksToUpdate.push_back(Succ);
1280 BasicBlock *ClonedSucc = getClonedBB(Succ, NextState, DuplicateMap);
1282 BlocksToUpdate.push_back(ClonedSucc);
1289 for (BasicBlock *Succ : BlocksToUpdate) {
1290 for (PHINode &Phi : Succ->phis()) {
1291 Value *Incoming =
Phi.getIncomingValueForBlock(BB);
1294 Phi.addIncoming(Incoming, ClonedBB);
1297 Value *ClonedVal = VMap[Incoming];
1299 Phi.addIncoming(ClonedVal, ClonedBB);
1301 Phi.addIncoming(Incoming, ClonedBB);
1309 void updatePredecessor(BasicBlock *PrevBB, BasicBlock *OldBB,
1310 BasicBlock *NewBB, DomTreeUpdater *DTU) {
1313 if (!isPredecessor(OldBB, PrevBB))
1323 DTU->
applyUpdates({{DominatorTree::Delete, PrevBB, OldBB},
1324 {DominatorTree::Insert, PrevBB, NewBB}});
1333 for (
auto Entry : VMap) {
1336 if (!Inst || !
Entry.second ||
1344 NewDefsVector.
push_back({Inst, Cloned});
1348 sort(NewDefsVector, [](
const auto &
LHS,
const auto &
RHS) {
1349 if (
LHS.first ==
RHS.first)
1350 return LHS.second->comesBefore(
RHS.second);
1351 return LHS.first->comesBefore(
RHS.first);
1354 for (
const auto &KV : NewDefsVector)
1355 NewDefs[KV.first].push_back(KV.second);
1363 void updateLastSuccessor(
const ThreadingPath &TPath,
1365 DomTreeUpdater *DTU) {
1366 APInt NextState = TPath.getExitValue();
1368 BasicBlock *LastBlock = getClonedBB(BB, NextState, DuplicateMap);
1375 BasicBlock *NextCase = getNextCaseSuccessor(Switch, NextState);
1377 std::vector<DominatorTree::UpdateType> DTUpdates;
1378 SmallPtrSet<BasicBlock *, 4> SuccSet;
1379 for (BasicBlock *Succ :
successors(LastBlock)) {
1380 if (Succ != NextCase && SuccSet.
insert(Succ).second)
1381 DTUpdates.push_back({DominatorTree::Delete, LastBlock, Succ});
1385 Switch->eraseFromParent();
1393 void cleanPhiNodes(BasicBlock *BB) {
1398 PN.eraseFromParent();
1404 for (PHINode &Phi : BB->
phis())
1405 Phi.removeIncomingValueIf([&](
unsigned Index) {
1407 return !isPredecessor(BB, IncomingBB);
1413 BasicBlock *getClonedBB(BasicBlock *BB,
const APInt &NextState,
1419 auto It =
llvm::find_if(ClonedBBs, [NextState](
const ClonedBlock &
C) {
1420 return C.State == NextState;
1422 return It != ClonedBBs.end() ? (*It).BB :
nullptr;
1426 bool isPredecessor(BasicBlock *BB, BasicBlock *IncomingBB) {
1430 const ScalarOptions &Opts;
1431 AllSwitchPaths *SwitchPaths;
1432 DomTreeUpdater *DTU;
1433 AssumptionCache *AC;
1434 TargetTransformInfo *
TTI;
1435 OptimizationRemarkEmitter *ORE;
1436 SmallPtrSet<const Value *, 32> EphValues;
1437 std::vector<ThreadingPath> TPaths;
1441bool DFAJumpThreading::run(
Function &
F) {
1442 LLVM_DEBUG(
dbgs() <<
"\nDFA Jump threading: " <<
F.getName() <<
"\n");
1444 if (
F.hasOptSize()) {
1445 LLVM_DEBUG(
dbgs() <<
"Skipping due to the 'minsize' attribute\n");
1449 if (Opts.dfa_jump_view_cfg_before)
1453 bool MadeChanges =
false;
1454 LoopInfoBroken =
false;
1456 for (BasicBlock &BB :
F) {
1462 <<
" is a candidate\n");
1463 MainSwitch
Switch(Opts, SI, LI, ORE);
1465 if (!
Switch.getInstr()) {
1467 <<
"candidate for jump threading\n");
1472 <<
"candidate for jump threading\n");
1475 unfoldSelectInstrs(
Switch.getSelectInsts());
1476 if (!
Switch.getSelectInsts().empty())
1479 AllSwitchPaths SwitchPaths(Opts, &Switch, ORE, LI,
1483 if (SwitchPaths.getNumThreadingPaths() > 0) {
1500 SmallPtrSet<const Value *, 32> EphValues;
1501 if (ThreadableLoops.
size() > 0)
1504 for (AllSwitchPaths SwitchPaths : ThreadableLoops) {
1505 TransformDFA Transform(Opts, &SwitchPaths, DTU, AC,
TTI, ORE, EphValues);
1506 if (Transform.run())
1507 MadeChanges = LoopInfoBroken =
true;
1512#ifdef EXPENSIVE_CHECKS
1518 "Failed to maintain validity of domtree!");
1533 DFAJumpThreading ThreadImpl(&AC, &DTU, &LI, &
TTI, &ORE);
1534 if (!ThreadImpl.run(
F))
1539 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...
size_type count(const_arg_type_t< KeyT > Val) const
Return 1 if the specified key is in the map, 0 otherwise.
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
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.
@ 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.
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)
auto map_range(ContainerTy &&C, FuncTy F)
Return a range that applies F to the elements of C.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
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...
@ Global
Append to llvm.global_dtors.
std::string join(IteratorT Begin, IteratorT End, StringRef Separator)
Joins the strings in the range [Begin, End), adding Separator between the elements.
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.
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.
auto predecessors(const MachineBasicBlock *BB)
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
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.