82#ifdef EXPENSIVE_CHECKS
88#define DEBUG_TYPE "dfa-jump-threading"
90STATISTIC(NumTransforms,
"Number of transformations done");
92STATISTIC(NumPaths,
"Number of individual paths threaded");
97 cl::desc(
"View the CFG before DFA Jump Threading"),
101 "dfa-early-exit-heuristic",
102 cl::desc(
"Exit early if an unpredictable value come from the same loop"),
106 "dfa-max-path-length",
107 cl::desc(
"Max number of blocks searched to find a threading path"),
111 "dfa-max-num-visited-paths",
113 "Max number of blocks visited while enumerating paths around a switch"),
118 cl::desc(
"Max number of paths enumerated around a switch"),
123 cl::desc(
"Maximum cost accepted for the transformation"),
127 "dfa-max-cloned-rate",
129 "Maximum cloned instructions rate accepted for the transformation"),
134 cl::desc(
"Maximum unduplicated blocks with outer uses "
135 "accepted for the transformation"),
143class SelectInstToUnfold {
150 SelectInst *getInst() {
return SI; }
151 PHINode *getUse() {
return SIUse; }
153 explicit operator bool()
const {
return SI && SIUse; }
156class DFAJumpThreading {
158 DFAJumpThreading(AssumptionCache *AC, DomTreeUpdater *DTU, LoopInfo *LI,
159 TargetTransformInfo *TTI, OptimizationRemarkEmitter *ORE)
160 : AC(AC), DTU(DTU), LI(LI), TTI(TTI), ORE(ORE) {}
162 bool run(Function &
F);
170 while (!
Stack.empty()) {
171 SelectInstToUnfold SIToUnfold =
Stack.pop_back_val();
173 std::vector<SelectInstToUnfold> NewSIsToUnfold;
174 std::vector<BasicBlock *> NewBBs;
175 unfold(DTU, LI, SIToUnfold, &NewSIsToUnfold, &NewBBs);
182 static void unfold(DomTreeUpdater *DTU, LoopInfo *LI,
183 SelectInstToUnfold SIToUnfold,
184 std::vector<SelectInstToUnfold> *NewSIsToUnfold,
185 std::vector<BasicBlock *> *NewBBs);
190 TargetTransformInfo *TTI;
191 OptimizationRemarkEmitter *ORE;
203 SelectInstToUnfold SIToUnfold,
204 std::vector<SelectInstToUnfold> *NewSIsToUnfold,
205 std::vector<BasicBlock *> *NewBBs) {
206 SelectInst *
SI = SIToUnfold.getInst();
207 PHINode *SIUse = SIToUnfold.getUse();
212 if (UncondBrInst *StartBlockTerm =
217 SI->getContext(), Twine(
SI->getName(),
".si.unfold.false"),
219 NewBBs->push_back(NewBlock);
225 StartBlockTerm->getDebugLoc(),
SI->getDebugLoc());
228 DTU->
applyUpdates({{DominatorTree::Insert, NewBlock, EndBlock}});
235 Value *SIOp1 =
SI->getTrueValue();
236 Value *SIOp2 =
SI->getFalseValue();
239 Twine(SIOp2->
getName(),
".si.unfold.phi"),
244 for (PHINode &Phi : EndBlock->
phis()) {
247 Phi.addIncoming(
Phi.getIncomingValueForBlock(StartBlock), NewBlock);
256 Twine(
SI->getName(),
".si.unfold.phi"),
259 if (Pred != StartBlock && Pred != NewBlock)
270 NewSIsToUnfold->push_back(SelectInstToUnfold(OpSi, SIUse));
272 NewSIsToUnfold->push_back(SelectInstToUnfold(OpSi, NewPhi));
275 StartBlockTerm->eraseFromParent();
278 BI->setDebugLoc(SelectBranchLoc);
280 BI->setMetadata(LLVMContext::MD_prof,
281 SI->getMetadata(LLVMContext::MD_prof));
282 DTU->
applyUpdates({{DominatorTree::Insert, StartBlock, NewBlock}});
286 SI->getContext(), Twine(
SI->getName(),
".si.unfold.true"),
289 SI->getContext(), Twine(
SI->getName(),
".si.unfold.false"),
292 NewBBs->push_back(NewBlockT);
293 NewBBs->push_back(NewBlockF);
321 BI->setDebugLoc(SelectLoc);
323 BI->setMetadata(LLVMContext::MD_prof,
324 SI->getMetadata(LLVMContext::MD_prof));
325 DTU->
applyUpdates({{DominatorTree::Insert, NewBlockT, NewBlockF},
326 {DominatorTree::Insert, NewBlockT, EndBlock},
327 {DominatorTree::Insert, NewBlockF, EndBlock}});
342 NewSIsToUnfold->push_back(SelectInstToUnfold(TrueSI, NewPhiT));
344 NewSIsToUnfold->push_back(SelectInstToUnfold(FalseSi, NewPhiF));
351 for (PHINode &Phi : EndBlock->
phis()) {
354 Phi.addIncoming(
Phi.getIncomingValueForBlock(StartBlock), NewBlockT);
355 Phi.addIncoming(
Phi.getIncomingValueForBlock(StartBlock), NewBlockF);
356 Phi.removeIncomingValue(StartBlock);
362 unsigned SuccNum = CondBr->
getSuccessor(1) == EndBlock ? 1 : 0;
364 DTU->
applyUpdates({{DominatorTree::Delete, StartBlock, EndBlock},
365 {DominatorTree::Insert, StartBlock, NewBlockT}});
370 for (BasicBlock *NewBB : *NewBBs)
371 L->addBasicBlockToLoop(NewBB, *LI);
375 assert(
SI->use_empty() &&
"Select must be dead now");
376 SI->eraseFromParent();
403 OS <<
"< " <<
llvm::join(BBNames,
", ") <<
" >";
412struct ThreadingPath {
414 APInt getExitValue()
const {
return ExitVal; }
415 void setExitValue(
const ConstantInt *V) {
416 ExitVal =
V->getValue();
419 void setExitValue(
const APInt &V) {
423 bool isExitValueSet()
const {
return IsExitValSet; }
426 const BasicBlock *getDeterminatorBB()
const {
return DBB; }
427 void setDeterminator(
const BasicBlock *BB) { DBB = BB; }
430 const PathType &getPath()
const {
return Path; }
431 void setPath(
const PathType &NewPath) { Path = NewPath; }
432 void push_back(BasicBlock *BB) { Path.push_back(BB); }
433 void push_front(BasicBlock *BB) { Path.push_front(BB); }
434 void appendExcludingFirst(
const PathType &OtherPath) {
438 void print(raw_ostream &OS)
const {
446 bool IsExitValSet =
false;
450inline raw_ostream &
operator<<(raw_ostream &OS,
const ThreadingPath &TPath) {
457 MainSwitch(SwitchInst *SI, LoopInfo *LI, OptimizationRemarkEmitter *ORE)
463 return OptimizationRemarkMissed(
DEBUG_TYPE,
"SwitchNotPredictable", SI)
464 <<
"Switch instruction is not predictable.";
469 virtual ~MainSwitch() =
default;
471 SwitchInst *getInstr()
const {
return Instr; }
482 std::deque<std::pair<Value *, BasicBlock *>> Q;
483 SmallPtrSet<Value *, 16> SeenValues;
486 Value *SICond =
SI->getCondition();
496 addToQueue(SICond,
nullptr, Q, SeenValues);
499 Value *Current = Q.front().first;
500 BasicBlock *CurrentIncomingBB = Q.front().second;
504 for (BasicBlock *IncomingBB :
Phi->blocks()) {
505 Value *Incoming =
Phi->getIncomingValueForBlock(IncomingBB);
506 addToQueue(Incoming, IncomingBB, Q, SeenValues);
510 if (!isValidSelectInst(SelI))
512 addToQueue(SelI->getTrueValue(), CurrentIncomingBB, Q, SeenValues);
513 addToQueue(SelI->getFalseValue(), CurrentIncomingBB, Q, SeenValues);
516 SelectInsts.push_back(SelectInstToUnfold(SelI, SelIUse));
534 <<
"\tExiting early due to unpredictability heuristic.\n");
545 void addToQueue(
Value *Val, BasicBlock *BB,
546 std::deque<std::pair<Value *, BasicBlock *>> &Q,
547 SmallPtrSet<Value *, 16> &SeenValues) {
548 if (SeenValues.
insert(Val).second)
549 Q.push_back({Val, BB});
552 bool isValidSelectInst(SelectInst *SI) {
553 if (!
SI->hasOneUse())
578 for (SelectInstToUnfold SIToUnfold : SelectInsts) {
579 SelectInst *PrevSI = SIToUnfold.getInst();
589 SwitchInst *Instr =
nullptr;
593struct AllSwitchPaths {
594 AllSwitchPaths(
const MainSwitch *MSwitch, OptimizationRemarkEmitter *ORE,
595 LoopInfo *LI, Loop *L)
596 : Switch(MSwitch->getInstr()), SwitchBlock(Switch->
getParent()), ORE(ORE),
597 LI(LI), SwitchOuterLoop(
L) {}
599 std::vector<ThreadingPath> &getThreadingPaths() {
return TPaths; }
600 unsigned getNumThreadingPaths() {
return TPaths.size(); }
601 SwitchInst *getSwitchInst() {
return Switch; }
602 BasicBlock *getSwitchBlock() {
return SwitchBlock; }
612 typedef DenseMap<const BasicBlock *, const PHINode *> StateDefMap;
613 std::vector<ThreadingPath> getPathsFromStateDefMap(StateDefMap &StateDef,
616 unsigned PathsLimit) {
617 std::vector<ThreadingPath> Res;
618 auto *PhiBB =
Phi->getParent();
622 for (
auto *IncomingBB :
Phi->blocks()) {
623 if (Res.size() >= PathsLimit)
625 if (!UniqueBlocks.
insert(IncomingBB).second)
627 if (!SwitchOuterLoop->
contains(IncomingBB))
630 Value *IncomingValue =
Phi->getIncomingValueForBlock(IncomingBB);
634 if (PhiBB == SwitchBlock &&
637 ThreadingPath NewPath;
638 NewPath.setDeterminator(PhiBB);
639 NewPath.setExitValue(
C);
641 if (IncomingBB != SwitchBlock) {
645 NewPath.push_back(IncomingBB);
647 NewPath.push_back(PhiBB);
648 Res.push_back(NewPath);
652 if (VB.
contains(IncomingBB) || IncomingBB == SwitchBlock)
658 auto *IncomingPhiDefBB = IncomingPhi->getParent();
659 if (!StateDef.contains(IncomingPhiDefBB))
663 if (IncomingPhiDefBB == IncomingBB) {
664 assert(PathsLimit > Res.size());
665 std::vector<ThreadingPath> PredPaths = getPathsFromStateDefMap(
666 StateDef, IncomingPhi, VB, PathsLimit - Res.size());
667 for (ThreadingPath &Path : PredPaths) {
668 Path.push_back(PhiBB);
669 Res.push_back(std::move(Path));
679 assert(PathsLimit > Res.size());
680 auto InterPathLimit = PathsLimit - Res.size();
681 IntermediatePaths = paths(IncomingPhiDefBB, IncomingBB, VB,
683 if (IntermediatePaths.empty())
686 assert(InterPathLimit >= IntermediatePaths.size());
687 auto PredPathLimit = InterPathLimit / IntermediatePaths.size();
688 std::vector<ThreadingPath> PredPaths =
689 getPathsFromStateDefMap(StateDef, IncomingPhi, VB, PredPathLimit);
690 for (
const ThreadingPath &Path : PredPaths) {
691 for (
const PathType &IPath : IntermediatePaths) {
692 ThreadingPath NewPath(Path);
693 NewPath.appendExcludingFirst(IPath);
694 NewPath.push_back(PhiBB);
695 Res.push_back(NewPath);
704 unsigned PathDepth,
unsigned PathsLimit) {
710 return OptimizationRemarkAnalysis(
DEBUG_TYPE,
"MaxPathLengthReached",
712 <<
"Exploration stopped after visiting MaxPathLength="
729 SmallPtrSet<BasicBlock *, 4> Successors;
731 if (Res.size() >= PathsLimit)
733 if (!Successors.
insert(Succ).second)
738 Res.push_back({BB, ToBB});
748 if (Succ == CurrLoop->getHeader())
754 assert(PathsLimit > Res.size());
756 paths(Succ, ToBB, Visited, PathDepth + 1, PathsLimit - Res.size());
771 StateDefMap getStateDefMap()
const {
773 DenseSet<const BasicBlock *> MultipleDefBBs;
775 assert(FirstDef &&
"The first definition must be a phi.");
778 Stack.push_back(FirstDef);
779 SmallPtrSet<Value *, 16> SeenValues;
781 while (!
Stack.empty()) {
782 PHINode *CurPhi =
Stack.pop_back_val();
785 auto [
_,
Inserted] = Res.try_emplace(CurDefBlock, CurPhi);
787 MultipleDefBBs.
insert(CurDefBlock);
789 SeenValues.
insert(CurPhi);
791 for (BasicBlock *IncomingBB : CurPhi->
blocks()) {
792 PHINode *IncomingPhi =
796 bool IsOutsideLoops = !SwitchOuterLoop->
contains(IncomingBB);
797 if (SeenValues.
contains(IncomingPhi) || IsOutsideLoops)
800 Stack.push_back(IncomingPhi);
810 for (
auto *BB : MultipleDefBBs) {
811 LLVM_DEBUG(
dbgs() <<
"Not a state-defining block: Multiple defs in "
820 StateDefMap StateDef = getStateDefMap();
821 if (StateDef.empty()) {
823 return OptimizationRemarkMissed(
DEBUG_TYPE,
"SwitchNotPredictable",
825 <<
"Switch instruction is not predictable.";
831 auto *SwitchPhiDefBB = SwitchPhi->getParent();
834 std::vector<ThreadingPath> PathsToPhiDef =
835 getPathsFromStateDefMap(StateDef, SwitchPhi, VB,
MaxNumPaths);
836 if (SwitchPhiDefBB == SwitchBlock || PathsToPhiDef.empty()) {
837 TPaths = std::move(PathsToPhiDef);
842 auto PathsLimit =
MaxNumPaths / PathsToPhiDef.size();
845 paths(SwitchPhiDefBB, SwitchBlock, VB, 1, PathsLimit);
846 if (PathsToSwitchBB.empty())
849 std::vector<ThreadingPath> TempList;
850 for (
const ThreadingPath &Path : PathsToPhiDef) {
851 SmallPtrSet<BasicBlock *, 32> PathSet(
Path.getPath().begin(),
852 Path.getPath().end());
853 for (
const PathType &PathToSw : PathsToSwitchBB) {
855 [&](
const BasicBlock *BB) {
return PathSet.contains(BB); }))
857 ThreadingPath PathCopy(Path);
858 PathCopy.appendExcludingFirst(PathToSw);
859 TempList.push_back(PathCopy);
862 TPaths = std::move(TempList);
867 BasicBlock *getNextCaseSuccessor(
const APInt &NextState) {
869 if (CaseValToDest.empty()) {
870 for (
auto Case : Switch->
cases()) {
871 APInt CaseVal = Case.getCaseValue()->getValue();
872 CaseValToDest[CaseVal] = Case.getCaseSuccessor();
876 auto SuccIt = CaseValToDest.find(NextState);
884 SmallDenseMap<BasicBlock *, APInt> DestToState;
885 for (ThreadingPath &Path : TPaths) {
886 APInt NextState =
Path.getExitValue();
887 BasicBlock *Dest = getNextCaseSuccessor(NextState);
891 if (NextState != StateIt->second) {
892 LLVM_DEBUG(
dbgs() <<
"Next state in " << Path <<
" is equivalent to "
893 << StateIt->second <<
"\n");
894 Path.setExitValue(StateIt->second);
899 unsigned NumVisited = 0;
902 OptimizationRemarkEmitter *ORE;
903 std::vector<ThreadingPath> TPaths;
904 DenseMap<APInt, BasicBlock *> CaseValToDest;
906 Loop *SwitchOuterLoop;
910 TransformDFA(AllSwitchPaths *SwitchPaths, DomTreeUpdater *DTU,
911 AssumptionCache *AC, TargetTransformInfo *
TTI,
912 OptimizationRemarkEmitter *ORE,
913 SmallPtrSet<const Value *, 32> EphValues)
914 : SwitchPaths(SwitchPaths), DTU(DTU), AC(AC),
TTI(
TTI), ORE(ORE),
915 EphValues(EphValues) {}
918 if (isLegalAndProfitableToTransform()) {
919 createAllExitPaths();
931 bool isLegalAndProfitableToTransform() {
933 uint64_t NumClonedInst = 0;
934 SwitchInst *
Switch = SwitchPaths->getSwitchInst();
937 if (
Switch->getNumSuccessors() <= 1)
943 for (ThreadingPath &TPath : SwitchPaths->getThreadingPaths()) {
945 APInt NextState = TPath.getExitValue();
946 const BasicBlock *Determinator = TPath.getDeterminatorBB();
949 BasicBlock *BB = SwitchPaths->getSwitchBlock();
950 BasicBlock *VisitedBB = getClonedBB(BB, NextState, DuplicateMap);
952 Metrics.analyzeBasicBlock(BB, *
TTI, EphValues);
953 NumClonedInst += BB->
size();
954 DuplicateMap[BB].push_back({BB, NextState});
959 if (PathBBs.front() == Determinator)
964 auto DetIt =
llvm::find(PathBBs, Determinator);
965 for (
auto BBIt = DetIt; BBIt != PathBBs.end(); BBIt++) {
967 VisitedBB = getClonedBB(BB, NextState, DuplicateMap);
970 Metrics.analyzeBasicBlock(BB, *
TTI, EphValues);
971 NumClonedInst += BB->
size();
972 DuplicateMap[BB].push_back({BB, NextState});
976 LLVM_DEBUG(
dbgs() <<
"DFA Jump Threading: Not jump threading, contains "
977 <<
"non-duplicatable instructions.\n");
979 return OptimizationRemarkMissed(
DEBUG_TYPE,
"NonDuplicatableInst",
981 <<
"Contains non-duplicatable instructions.";
987 if (
Metrics.Convergence != ConvergenceKind::None) {
988 LLVM_DEBUG(
dbgs() <<
"DFA Jump Threading: Not jump threading, contains "
989 <<
"convergent instructions.\n");
991 return OptimizationRemarkMissed(
DEBUG_TYPE,
"ConvergentInst", Switch)
992 <<
"Contains convergent instructions.";
997 if (!
Metrics.NumInsts.isValid()) {
998 LLVM_DEBUG(
dbgs() <<
"DFA Jump Threading: Not jump threading, contains "
999 <<
"instructions with invalid cost.\n");
1001 return OptimizationRemarkMissed(
DEBUG_TYPE,
"ConvergentInst", Switch)
1002 <<
"Contains instructions with invalid cost.";
1011 uint64_t NumOrigInst = 0;
1012 uint64_t NumOuterUseBlock = 0;
1013 for (
auto *BB : DuplicateMap.
keys()) {
1014 NumOrigInst += BB->
size();
1018 if (!DuplicateMap.
count(Succ) && Succ->getSinglePredecessor())
1022 if (
double(NumClonedInst) /
double(NumOrigInst) >
MaxClonedRate) {
1023 LLVM_DEBUG(
dbgs() <<
"DFA Jump Threading: Not jump threading, too much "
1024 "instructions wll be cloned\n");
1026 return OptimizationRemarkMissed(
DEBUG_TYPE,
"NotProfitable", Switch)
1027 <<
"Too much instructions will be cloned.";
1037 LLVM_DEBUG(
dbgs() <<
"DFA Jump Threading: Not jump threading, too much "
1038 "blocks with outer uses\n");
1040 return OptimizationRemarkMissed(
DEBUG_TYPE,
"NotProfitable", Switch)
1041 <<
"Too much blocks with outer uses.";
1048 unsigned JumpTableSize = 0;
1051 if (JumpTableSize == 0) {
1055 unsigned CondBranches =
1056 APInt(32,
Switch->getNumSuccessors()).ceilLogBase2();
1057 assert(CondBranches > 0 &&
1058 "The threaded switch must have multiple branches");
1059 DuplicationCost =
Metrics.NumInsts / CondBranches;
1067 DuplicationCost =
Metrics.NumInsts / JumpTableSize;
1070 LLVM_DEBUG(
dbgs() <<
"\nDFA Jump Threading: Cost to jump thread block "
1071 << SwitchPaths->getSwitchBlock()->getName()
1072 <<
" is: " << DuplicationCost <<
"\n\n");
1075 LLVM_DEBUG(
dbgs() <<
"Not jump threading, duplication cost exceeds the "
1076 <<
"cost threshold.\n");
1078 return OptimizationRemarkMissed(
DEBUG_TYPE,
"NotProfitable", Switch)
1079 <<
"Duplication cost exceeds the cost threshold (cost="
1080 <<
ore::NV(
"Cost", DuplicationCost)
1087 return OptimizationRemark(
DEBUG_TYPE,
"JumpThreaded", Switch)
1088 <<
"Switch statement jump-threaded.";
1095 void createAllExitPaths() {
1097 BasicBlock *SwitchBlock = SwitchPaths->getSwitchBlock();
1098 for (ThreadingPath &TPath : SwitchPaths->getThreadingPaths()) {
1102 TPath.push_front(SwitchBlock);
1109 SmallPtrSet<BasicBlock *, 16> BlocksToClean;
1112 for (
const ThreadingPath &TPath : SwitchPaths->getThreadingPaths()) {
1113 createExitPath(NewDefs, TPath, DuplicateMap, BlocksToClean, DTU);
1119 for (
const ThreadingPath &TPath : SwitchPaths->getThreadingPaths())
1120 updateLastSuccessor(TPath, DuplicateMap, DTU);
1126 for (BasicBlock *BB : BlocksToClean)
1136 void createExitPath(
DefMap &NewDefs,
const ThreadingPath &Path,
1138 SmallPtrSet<BasicBlock *, 16> &BlocksToClean,
1139 DomTreeUpdater *DTU) {
1140 APInt NextState =
Path.getExitValue();
1145 if (PathBBs.front() == Determinator)
1146 PathBBs.pop_front();
1148 auto DetIt =
llvm::find(PathBBs, Determinator);
1151 BasicBlock *PrevBB = PathBBs.size() == 1 ? *DetIt : *std::prev(DetIt);
1152 for (
auto BBIt = DetIt; BBIt != PathBBs.end(); BBIt++) {
1154 BlocksToClean.
insert(BB);
1158 BasicBlock *NextBB = getClonedBB(BB, NextState, DuplicateMap);
1160 updatePredecessor(PrevBB, BB, NextBB, DTU);
1166 BasicBlock *NewBB = cloneBlockAndUpdatePredecessor(
1167 BB, PrevBB, NextState, DuplicateMap, NewDefs, DTU);
1168 DuplicateMap[BB].push_back({NewBB, NextState});
1169 BlocksToClean.
insert(NewBB);
1181 SSAUpdaterBulk SSAUpdate;
1182 SmallVector<Use *, 16> UsesToRename;
1184 for (
const auto &KV : NewDefs) {
1187 std::vector<Instruction *> Cloned = KV.second;
1191 for (Use &U :
I->uses()) {
1194 if (UserPN->getIncomingBlock(U) == BB)
1196 }
else if (
User->getParent() == BB) {
1205 if (UsesToRename.
empty())
1213 unsigned VarNum = SSAUpdate.
AddVariable(
I->getName(),
I->getType());
1215 for (Instruction *New : Cloned)
1218 while (!UsesToRename.
empty())
1232 static BasicBlock *getNextCaseSuccessor(SwitchInst *Switch,
1233 const APInt &NextState) {
1235 for (
auto Case :
Switch->cases()) {
1236 if (Case.getCaseValue()->getValue() == NextState) {
1237 NextCase = Case.getCaseSuccessor();
1242 NextCase =
Switch->getDefaultDest();
1250 BasicBlock *cloneBlockAndUpdatePredecessor(BasicBlock *BB, BasicBlock *PrevBB,
1251 const APInt &NextState,
1254 DomTreeUpdater *DTU) {
1268 for (Instruction &
I : *NewBB) {
1280 updateSuccessorPhis(BB, NewBB, NextState, VMap, DuplicateMap);
1281 updatePredecessor(PrevBB, BB, NewBB, DTU);
1282 updateDefMap(NewDefs, VMap);
1285 SmallPtrSet<BasicBlock *, 4> SuccSet;
1287 if (SuccSet.
insert(SuccBB).second)
1288 DTU->
applyUpdates({{DominatorTree::Insert, NewBB, SuccBB}});
1298 void updateSuccessorPhis(BasicBlock *BB, BasicBlock *ClonedBB,
1301 std::vector<BasicBlock *> BlocksToUpdate;
1305 if (BB == SwitchPaths->getSwitchBlock()) {
1306 SwitchInst *
Switch = SwitchPaths->getSwitchInst();
1307 BasicBlock *NextCase = getNextCaseSuccessor(Switch, NextState);
1308 BlocksToUpdate.push_back(NextCase);
1309 BasicBlock *ClonedSucc = getClonedBB(NextCase, NextState, DuplicateMap);
1311 BlocksToUpdate.push_back(ClonedSucc);
1316 BlocksToUpdate.push_back(Succ);
1321 BasicBlock *ClonedSucc = getClonedBB(Succ, NextState, DuplicateMap);
1323 BlocksToUpdate.push_back(ClonedSucc);
1330 for (BasicBlock *Succ : BlocksToUpdate) {
1331 for (PHINode &Phi : Succ->phis()) {
1332 Value *Incoming =
Phi.getIncomingValueForBlock(BB);
1335 Phi.addIncoming(Incoming, ClonedBB);
1338 Value *ClonedVal = VMap[Incoming];
1340 Phi.addIncoming(ClonedVal, ClonedBB);
1342 Phi.addIncoming(Incoming, ClonedBB);
1350 void updatePredecessor(BasicBlock *PrevBB, BasicBlock *OldBB,
1351 BasicBlock *NewBB, DomTreeUpdater *DTU) {
1354 if (!isPredecessor(OldBB, PrevBB))
1364 DTU->
applyUpdates({{DominatorTree::Delete, PrevBB, OldBB},
1365 {DominatorTree::Insert, PrevBB, NewBB}});
1374 for (
auto Entry : VMap) {
1377 if (!Inst || !
Entry.second ||
1385 NewDefsVector.
push_back({Inst, Cloned});
1389 sort(NewDefsVector, [](
const auto &
LHS,
const auto &
RHS) {
1390 if (
LHS.first ==
RHS.first)
1391 return LHS.second->comesBefore(
RHS.second);
1392 return LHS.first->comesBefore(
RHS.first);
1395 for (
const auto &KV : NewDefsVector)
1396 NewDefs[KV.first].push_back(KV.second);
1404 void updateLastSuccessor(
const ThreadingPath &TPath,
1406 DomTreeUpdater *DTU) {
1407 APInt NextState = TPath.getExitValue();
1409 BasicBlock *LastBlock = getClonedBB(BB, NextState, DuplicateMap);
1416 BasicBlock *NextCase = getNextCaseSuccessor(Switch, NextState);
1418 std::vector<DominatorTree::UpdateType> DTUpdates;
1419 SmallPtrSet<BasicBlock *, 4> SuccSet;
1420 for (BasicBlock *Succ :
successors(LastBlock)) {
1421 if (Succ != NextCase && SuccSet.
insert(Succ).second)
1422 DTUpdates.push_back({DominatorTree::Delete, LastBlock, Succ});
1426 Switch->eraseFromParent();
1434 void cleanPhiNodes(BasicBlock *BB) {
1439 PN.eraseFromParent();
1445 for (PHINode &Phi : BB->
phis())
1446 Phi.removeIncomingValueIf([&](
unsigned Index) {
1448 return !isPredecessor(BB, IncomingBB);
1454 BasicBlock *getClonedBB(BasicBlock *BB,
const APInt &NextState,
1460 auto It =
llvm::find_if(ClonedBBs, [NextState](
const ClonedBlock &
C) {
1461 return C.State == NextState;
1463 return It != ClonedBBs.end() ? (*It).BB :
nullptr;
1467 bool isPredecessor(BasicBlock *BB, BasicBlock *IncomingBB) {
1471 AllSwitchPaths *SwitchPaths;
1472 DomTreeUpdater *DTU;
1473 AssumptionCache *AC;
1474 TargetTransformInfo *
TTI;
1475 OptimizationRemarkEmitter *ORE;
1476 SmallPtrSet<const Value *, 32> EphValues;
1477 std::vector<ThreadingPath> TPaths;
1481bool DFAJumpThreading::run(Function &
F) {
1482 LLVM_DEBUG(
dbgs() <<
"\nDFA Jump threading: " <<
F.getName() <<
"\n");
1484 if (
F.hasOptSize()) {
1485 LLVM_DEBUG(
dbgs() <<
"Skipping due to the 'minsize' attribute\n");
1493 bool MadeChanges =
false;
1494 LoopInfoBroken =
false;
1496 for (BasicBlock &BB :
F) {
1502 <<
" is a candidate\n");
1503 MainSwitch
Switch(SI, LI, ORE);
1505 if (!
Switch.getInstr()) {
1507 <<
"candidate for jump threading\n");
1512 <<
"candidate for jump threading\n");
1515 unfoldSelectInstrs(
Switch.getSelectInsts());
1516 if (!
Switch.getSelectInsts().empty())
1519 AllSwitchPaths SwitchPaths(&Switch, ORE, LI,
1523 if (SwitchPaths.getNumThreadingPaths() > 0) {
1540 SmallPtrSet<const Value *, 32> EphValues;
1541 if (ThreadableLoops.
size() > 0)
1544 for (AllSwitchPaths SwitchPaths : ThreadableLoops) {
1545 TransformDFA Transform(&SwitchPaths, DTU, AC,
TTI, ORE, EphValues);
1546 if (Transform.run())
1547 MadeChanges = LoopInfoBroken =
true;
1552#ifdef EXPENSIVE_CHECKS
1558 "Failed to maintain validity of domtree!");
1573 DFAJumpThreading ThreadImpl(&AC, &DTU, &LI, &
TTI, &ORE);
1574 if (!ThreadImpl.run(
F))
1579 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)
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 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 in this loop.
const LoopT * getOutermostLoop() const
Get the outermost loop in which this loop is contained.
void verify(const DominatorTreeBase< BlockT, false > &DomTree) const
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
bool erase(PtrType Ptr)
Remove pointer from the set.
void insert_range(Range &&R)
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.
@ C
The default llvm calling convention, compatible with C.
@ 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.