@@ -103,6 +103,11 @@ static cl::opt<unsigned> MaxPathLength(
103
103
cl::desc (" Max number of blocks searched to find a threading path" ),
104
104
cl::Hidden, cl::init(20 ));
105
105
106
+ static cl::opt<unsigned > MaxNumPaths (
107
+ " dfa-max-num-paths" ,
108
+ cl::desc (" Max number of paths enumerated around a switch" ),
109
+ cl::Hidden, cl::init(200 ));
110
+
106
111
static cl::opt<unsigned >
107
112
CostThreshold (" dfa-cost-threshold" ,
108
113
cl::desc (" Maximum cost accepted for the transformation" ),
@@ -415,7 +420,7 @@ inline raw_ostream &operator<<(raw_ostream &OS, const ThreadingPath &TPath) {
415
420
416
421
struct MainSwitch {
417
422
MainSwitch (SwitchInst *SI, OptimizationRemarkEmitter *ORE) {
418
- if (isPredictable (SI)) {
423
+ if (isCandidate (SI)) {
419
424
Instr = SI;
420
425
} else {
421
426
ORE->emit ([&]() {
@@ -433,83 +438,60 @@ struct MainSwitch {
433
438
}
434
439
435
440
private:
436
- // / Do a use-def chain traversal. Make sure the value of the switch variable
437
- // / is always a known constant. This means that all conditional jumps based on
438
- // / switch variable can be converted to unconditional jumps.
439
- bool isPredictable (const SwitchInst *SI) {
440
- std::deque<Instruction *> Q;
441
+ // / Do a use-def chain traversal starting from the switch condition to see if
442
+ // / \p SI is a potential condidate.
443
+ // /
444
+ // / Also, collect select instructions to unfold.
445
+ bool isCandidate (const SwitchInst *SI) {
446
+ std::deque<Value *> Q;
441
447
SmallSet<Value *, 16 > SeenValues;
442
448
SelectInsts.clear ();
443
449
444
- Value *FirstDef = SI->getOperand (0 );
445
- auto *Inst = dyn_cast<Instruction>(FirstDef);
446
-
447
- // If this is a function argument or another non-instruction, then give up.
448
- // We are interested in loop local variables.
449
- if (!Inst)
450
+ Value *SICond = SI->getCondition ();
451
+ LLVM_DEBUG (dbgs () << " \t SICond: " << *SICond << " \n " );
452
+ if (!isa<PHINode>(SICond))
450
453
return false ;
451
454
452
- // Require the first definition to be a PHINode
453
- if (!isa<PHINode>(Inst))
454
- return false ;
455
-
456
- LLVM_DEBUG (dbgs () << " \t isPredictable() FirstDef: " << *Inst << " \n " );
457
-
458
- Q.push_back (Inst);
459
- SeenValues.insert (FirstDef);
455
+ addToQueue (SICond, Q, SeenValues);
460
456
461
457
while (!Q.empty ()) {
462
- Instruction *Current = Q.front ();
458
+ Value *Current = Q.front ();
463
459
Q.pop_front ();
464
460
465
461
if (auto *Phi = dyn_cast<PHINode>(Current)) {
466
462
for (Value *Incoming : Phi->incoming_values ()) {
467
- if (!isPredictableValue (Incoming, SeenValues))
468
- return false ;
469
- addInstToQueue (Incoming, Q, SeenValues);
463
+ addToQueue (Incoming, Q, SeenValues);
470
464
}
471
- LLVM_DEBUG (dbgs () << " \t isPredictable() phi : " << *Phi << " \n " );
465
+ LLVM_DEBUG (dbgs () << " \t phi : " << *Phi << " \n " );
472
466
} else if (SelectInst *SelI = dyn_cast<SelectInst>(Current)) {
473
467
if (!isValidSelectInst (SelI))
474
468
return false ;
475
- if (!isPredictableValue (SelI->getTrueValue (), SeenValues) ||
476
- !isPredictableValue (SelI->getFalseValue (), SeenValues)) {
477
- return false ;
478
- }
479
- addInstToQueue (SelI->getTrueValue (), Q, SeenValues);
480
- addInstToQueue (SelI->getFalseValue (), Q, SeenValues);
481
- LLVM_DEBUG (dbgs () << " \t isPredictable() select: " << *SelI << " \n " );
469
+ addToQueue (SelI->getTrueValue (), Q, SeenValues);
470
+ addToQueue (SelI->getFalseValue (), Q, SeenValues);
471
+ LLVM_DEBUG (dbgs () << " \t select: " << *SelI << " \n " );
482
472
if (auto *SelIUse = dyn_cast<PHINode>(SelI->user_back ()))
483
473
SelectInsts.push_back (SelectInstToUnfold (SelI, SelIUse));
474
+ } else if (isa<Constant>(Current)) {
475
+ LLVM_DEBUG (dbgs () << " \t const: " << *Current << " \n " );
476
+ continue ;
484
477
} else {
485
- // If it is neither a phi nor a select, then we give up.
486
- return false ;
478
+ LLVM_DEBUG (dbgs () << " \t other: " << *Current << " \n " );
479
+ // Allow unpredictable values. The hope is that those will be the
480
+ // initial switch values that can be ignored (they will hit the
481
+ // unthreaded switch) but this assumption will get checked later after
482
+ // paths have been enumerated (in function getStateDefMap).
483
+ continue ;
487
484
}
488
485
}
489
486
490
487
return true ;
491
488
}
492
489
493
- bool isPredictableValue (Value *InpVal, SmallSet<Value *, 16 > &SeenValues) {
494
- if (SeenValues.contains (InpVal))
495
- return true ;
496
-
497
- if (isa<ConstantInt>(InpVal))
498
- return true ;
499
-
500
- // If this is a function argument or another non-instruction, then give up.
501
- if (!isa<Instruction>(InpVal))
502
- return false ;
503
-
504
- return true ;
505
- }
506
-
507
- void addInstToQueue (Value *Val, std::deque<Instruction *> &Q,
508
- SmallSet<Value *, 16 > &SeenValues) {
490
+ void addToQueue (Value *Val, std::deque<Value *> &Q,
491
+ SmallSet<Value *, 16 > &SeenValues) {
509
492
if (SeenValues.contains (Val))
510
493
return ;
511
- if (Instruction *I = dyn_cast<Instruction>(Val))
512
- Q.push_back (I);
494
+ Q.push_back (Val);
513
495
SeenValues.insert (Val);
514
496
}
515
497
@@ -563,7 +545,16 @@ struct AllSwitchPaths {
563
545
void run () {
564
546
VisitedBlocks Visited;
565
547
PathsType LoopPaths = paths (SwitchBlock, Visited, /* PathDepth = */ 1 );
566
- StateDefMap StateDef = getStateDefMap ();
548
+ StateDefMap StateDef = getStateDefMap (LoopPaths);
549
+
550
+ if (StateDef.empty ()) {
551
+ ORE->emit ([&]() {
552
+ return OptimizationRemarkMissed (DEBUG_TYPE, " SwitchNotPredictable" ,
553
+ Switch)
554
+ << " Switch instruction is not predictable." ;
555
+ });
556
+ return ;
557
+ }
567
558
568
559
for (PathType Path : LoopPaths) {
569
560
ThreadingPath TPath;
@@ -638,6 +629,9 @@ struct AllSwitchPaths {
638
629
PathType NewPath (Path);
639
630
NewPath.push_front (BB);
640
631
Res.push_back (NewPath);
632
+ if (Res.size () >= MaxNumPaths) {
633
+ return Res;
634
+ }
641
635
}
642
636
}
643
637
// This block could now be visited again from a different predecessor. Note
@@ -648,14 +642,22 @@ struct AllSwitchPaths {
648
642
}
649
643
650
644
// / Walk the use-def chain and collect all the state-defining instructions.
651
- StateDefMap getStateDefMap () const {
645
+ // /
646
+ // / Return an empty map if unpredictable values encountered inside the basic
647
+ // / blocks of \p LoopPaths.
648
+ StateDefMap getStateDefMap (const PathsType &LoopPaths) const {
652
649
StateDefMap Res;
653
650
651
+ // Basic blocks belonging to any of the loops around the switch statement.
652
+ SmallPtrSet<BasicBlock *, 16 > LoopBBs;
653
+ for (const PathType &Path : LoopPaths) {
654
+ for (BasicBlock *BB : Path)
655
+ LoopBBs.insert (BB);
656
+ }
657
+
654
658
Value *FirstDef = Switch->getOperand (0 );
655
659
656
- assert (isa<PHINode>(FirstDef) && " After select unfolding, all state "
657
- " definitions are expected to be phi "
658
- " nodes." );
660
+ assert (isa<PHINode>(FirstDef) && " The first definition must be a phi." );
659
661
660
662
SmallVector<PHINode *, 8 > Stack;
661
663
Stack.push_back (dyn_cast<PHINode>(FirstDef));
@@ -667,15 +669,17 @@ struct AllSwitchPaths {
667
669
Res[CurPhi->getParent ()] = CurPhi;
668
670
SeenValues.insert (CurPhi);
669
671
670
- for (Value *Incoming : CurPhi->incoming_values ()) {
672
+ for (BasicBlock *IncomingBB : CurPhi->blocks ()) {
673
+ Value *Incoming = CurPhi->getIncomingValueForBlock (IncomingBB);
674
+ bool IsOutsideLoops = LoopBBs.count (IncomingBB) == 0 ;
671
675
if (Incoming == FirstDef || isa<ConstantInt>(Incoming) ||
672
- SeenValues.contains (Incoming)) {
676
+ SeenValues.contains (Incoming) || IsOutsideLoops ) {
673
677
continue ;
674
678
}
675
679
676
- assert (isa<PHINode>(Incoming) && " After select unfolding, all state "
677
- " definitions are expected to be phi "
678
- " nodes. " );
680
+ // Any unpredictable value inside the loops means we must bail out.
681
+ if (!isa<PHINode>(Incoming))
682
+ return StateDefMap ( );
679
683
680
684
Stack.push_back (cast<PHINode>(Incoming));
681
685
}
@@ -1279,7 +1283,7 @@ bool DFAJumpThreading::run(Function &F) {
1279
1283
continue ;
1280
1284
1281
1285
LLVM_DEBUG (dbgs () << " \n Check if SwitchInst in BB " << BB.getName ()
1282
- << " is predictable \n " );
1286
+ << " is a candidate \n " );
1283
1287
MainSwitch Switch (SI, ORE);
1284
1288
1285
1289
if (!Switch.getInstr ())
0 commit comments