@@ -126,7 +126,7 @@ class SelectInstToUnfold {
126
126
explicit operator bool () const { return SI && SIUse; }
127
127
};
128
128
129
- void unfold (DomTreeUpdater *DTU, SelectInstToUnfold SIToUnfold,
129
+ void unfold (DomTreeUpdater *DTU, LoopInfo *LI, SelectInstToUnfold SIToUnfold,
130
130
std::vector<SelectInstToUnfold> *NewSIsToUnfold,
131
131
std::vector<BasicBlock *> *NewBBs);
132
132
@@ -152,7 +152,7 @@ class DFAJumpThreading {
152
152
153
153
std::vector<SelectInstToUnfold> NewSIsToUnfold;
154
154
std::vector<BasicBlock *> NewBBs;
155
- unfold (&DTU, SIToUnfold, &NewSIsToUnfold, &NewBBs);
155
+ unfold (&DTU, LI, SIToUnfold, &NewSIsToUnfold, &NewBBs);
156
156
157
157
// Put newly discovered select instructions into the work list.
158
158
for (const SelectInstToUnfold &NewSIToUnfold : NewSIsToUnfold)
@@ -196,7 +196,7 @@ void createBasicBlockAndSinkSelectInst(
196
196
// / created basic blocks into \p NewBBs.
197
197
// /
198
198
// / TODO: merge it with CodeGenPrepare::optimizeSelectInst() if possible.
199
- void unfold (DomTreeUpdater *DTU, SelectInstToUnfold SIToUnfold,
199
+ void unfold (DomTreeUpdater *DTU, LoopInfo *LI, SelectInstToUnfold SIToUnfold,
200
200
std::vector<SelectInstToUnfold> *NewSIsToUnfold,
201
201
std::vector<BasicBlock *> *NewBBs) {
202
202
SelectInst *SI = SIToUnfold.getInst ();
@@ -302,6 +302,12 @@ void unfold(DomTreeUpdater *DTU, SelectInstToUnfold SIToUnfold,
302
302
DTU->applyUpdates ({{DominatorTree::Insert, StartBlock, TT},
303
303
{DominatorTree::Insert, StartBlock, FT}});
304
304
305
+ // Preserve loop info
306
+ if (Loop *L = LI->getLoopFor (SI->getParent ())) {
307
+ for (BasicBlock *NewBB : *NewBBs)
308
+ L->addBasicBlockToLoop (NewBB, *LI);
309
+ }
310
+
305
311
// The select is now dead.
306
312
assert (SI->use_empty () && " Select must be dead now" );
307
313
SI->eraseFromParent ();
@@ -501,9 +507,10 @@ struct MainSwitch {
501
507
};
502
508
503
509
struct AllSwitchPaths {
504
- AllSwitchPaths (const MainSwitch *MSwitch, OptimizationRemarkEmitter *ORE)
505
- : Switch(MSwitch->getInstr ()), SwitchBlock(Switch->getParent ()),
506
- ORE(ORE) {}
510
+ AllSwitchPaths (const MainSwitch *MSwitch, OptimizationRemarkEmitter *ORE,
511
+ LoopInfo *LI)
512
+ : Switch(MSwitch->getInstr ()), SwitchBlock(Switch->getParent ()), ORE(ORE),
513
+ LI(LI) {}
507
514
508
515
std::vector<ThreadingPath> &getThreadingPaths () { return TPaths; }
509
516
unsigned getNumThreadingPaths () { return TPaths.size (); }
@@ -575,6 +582,12 @@ struct AllSwitchPaths {
575
582
576
583
Visited.insert (BB);
577
584
585
+ // Stop if we have reached the BB out of loop, since its successors have no
586
+ // impact on the DFA.
587
+ // TODO: Do we need to stop exploring if BB is the outer loop of the switch?
588
+ if (!LI->getLoopFor (BB))
589
+ return Res;
590
+
578
591
// Some blocks have multiple edges to the same successor, and this set
579
592
// is used to prevent a duplicate path from being generated
580
593
SmallSet<BasicBlock *, 4 > Successors;
@@ -716,6 +729,7 @@ struct AllSwitchPaths {
716
729
BasicBlock *SwitchBlock;
717
730
OptimizationRemarkEmitter *ORE;
718
731
std::vector<ThreadingPath> TPaths;
732
+ LoopInfo *LI;
719
733
};
720
734
721
735
struct TransformDFA {
@@ -1283,7 +1297,7 @@ bool DFAJumpThreading::run(Function &F) {
1283
1297
if (!Switch.getSelectInsts ().empty ())
1284
1298
MadeChanges = true ;
1285
1299
1286
- AllSwitchPaths SwitchPaths (&Switch, ORE);
1300
+ AllSwitchPaths SwitchPaths (&Switch, ORE, LI );
1287
1301
SwitchPaths.run ();
1288
1302
1289
1303
if (SwitchPaths.getNumThreadingPaths () > 0 ) {
0 commit comments