@@ -131,7 +131,7 @@ class SelectInstToUnfold {
131
131
explicit operator bool () const { return SI && SIUse; }
132
132
};
133
133
134
- void unfold (DomTreeUpdater *DTU, SelectInstToUnfold SIToUnfold,
134
+ void unfold (DomTreeUpdater *DTU, LoopInfo *LI, SelectInstToUnfold SIToUnfold,
135
135
std::vector<SelectInstToUnfold> *NewSIsToUnfold,
136
136
std::vector<BasicBlock *> *NewBBs);
137
137
@@ -157,7 +157,7 @@ class DFAJumpThreading {
157
157
158
158
std::vector<SelectInstToUnfold> NewSIsToUnfold;
159
159
std::vector<BasicBlock *> NewBBs;
160
- unfold (&DTU, SIToUnfold, &NewSIsToUnfold, &NewBBs);
160
+ unfold (&DTU, LI, SIToUnfold, &NewSIsToUnfold, &NewBBs);
161
161
162
162
// Put newly discovered select instructions into the work list.
163
163
for (const SelectInstToUnfold &NewSIToUnfold : NewSIsToUnfold)
@@ -201,7 +201,7 @@ void createBasicBlockAndSinkSelectInst(
201
201
// / created basic blocks into \p NewBBs.
202
202
// /
203
203
// / TODO: merge it with CodeGenPrepare::optimizeSelectInst() if possible.
204
- void unfold (DomTreeUpdater *DTU, SelectInstToUnfold SIToUnfold,
204
+ void unfold (DomTreeUpdater *DTU, LoopInfo *LI, SelectInstToUnfold SIToUnfold,
205
205
std::vector<SelectInstToUnfold> *NewSIsToUnfold,
206
206
std::vector<BasicBlock *> *NewBBs) {
207
207
SelectInst *SI = SIToUnfold.getInst ();
@@ -307,6 +307,12 @@ void unfold(DomTreeUpdater *DTU, SelectInstToUnfold SIToUnfold,
307
307
DTU->applyUpdates ({{DominatorTree::Insert, StartBlock, TT},
308
308
{DominatorTree::Insert, StartBlock, FT}});
309
309
310
+ // Preserve loop info
311
+ if (Loop *L = LI->getLoopFor (SI->getParent ())) {
312
+ for (BasicBlock *NewBB : *NewBBs)
313
+ L->addBasicBlockToLoop (NewBB, *LI);
314
+ }
315
+
310
316
// The select is now dead.
311
317
assert (SI->use_empty () && " Select must be dead now" );
312
318
SI->eraseFromParent ();
@@ -522,9 +528,10 @@ struct MainSwitch {
522
528
};
523
529
524
530
struct AllSwitchPaths {
525
- AllSwitchPaths (const MainSwitch *MSwitch, OptimizationRemarkEmitter *ORE)
526
- : Switch(MSwitch->getInstr ()), SwitchBlock(Switch->getParent ()),
527
- ORE(ORE) {}
531
+ AllSwitchPaths (const MainSwitch *MSwitch, OptimizationRemarkEmitter *ORE,
532
+ LoopInfo *LI)
533
+ : Switch(MSwitch->getInstr ()), SwitchBlock(Switch->getParent ()), ORE(ORE),
534
+ LI(LI) {}
528
535
529
536
std::vector<ThreadingPath> &getThreadingPaths () { return TPaths; }
530
537
unsigned getNumThreadingPaths () { return TPaths.size (); }
@@ -596,6 +603,12 @@ struct AllSwitchPaths {
596
603
597
604
Visited.insert (BB);
598
605
606
+ // Stop if we have reached the BB out of loop, since its successors have no
607
+ // impact on the DFA.
608
+ // TODO: Do we need to stop exploring if BB is the outer loop of the switch?
609
+ if (!LI->getLoopFor (BB))
610
+ return Res;
611
+
599
612
// Some blocks have multiple edges to the same successor, and this set
600
613
// is used to prevent a duplicate path from being generated
601
614
SmallSet<BasicBlock *, 4 > Successors;
@@ -737,6 +750,7 @@ struct AllSwitchPaths {
737
750
BasicBlock *SwitchBlock;
738
751
OptimizationRemarkEmitter *ORE;
739
752
std::vector<ThreadingPath> TPaths;
753
+ LoopInfo *LI;
740
754
};
741
755
742
756
struct TransformDFA {
@@ -1304,7 +1318,7 @@ bool DFAJumpThreading::run(Function &F) {
1304
1318
if (!Switch.getSelectInsts ().empty ())
1305
1319
MadeChanges = true ;
1306
1320
1307
- AllSwitchPaths SwitchPaths (&Switch, ORE);
1321
+ AllSwitchPaths SwitchPaths (&Switch, ORE, LI );
1308
1322
SwitchPaths.run ();
1309
1323
1310
1324
if (SwitchPaths.getNumThreadingPaths () > 0 ) {
0 commit comments