@@ -426,7 +426,10 @@ void SCCPSolver::inferArgAttributes() const {
426
426
class SCCPInstVisitor : public InstVisitor <SCCPInstVisitor> {
427
427
const DataLayout &DL;
428
428
std::function<const TargetLibraryInfo &(Function &)> GetTLI;
429
- SmallPtrSet<BasicBlock *, 8 > BBExecutable; // The BBs that are executable.
429
+ // / Basic blocks that are executable (but may not have been visited yet).
430
+ SmallPtrSet<BasicBlock *, 8 > BBExecutable;
431
+ // / Basic blocks that are executable and have been visited at least once.
432
+ SmallPtrSet<BasicBlock *, 8 > BBVisited;
430
433
DenseMap<Value *, ValueLatticeElement>
431
434
ValueState; // The state each value is in.
432
435
@@ -466,15 +469,14 @@ class SCCPInstVisitor : public InstVisitor<SCCPInstVisitor> {
466
469
// / constants.
467
470
SmallPtrSet<Function *, 16 > TrackingIncomingArguments;
468
471
469
- // / The reason for two worklists is that overdefined is the lowest state
470
- // / on the lattice, and moving things to overdefined as fast as possible
471
- // / makes SCCP converge much faster.
472
- // /
473
- // / By having a separate worklist, we accomplish this because everything
474
- // / possibly overdefined will become overdefined at the soonest possible
475
- // / point.
476
- SmallVector<Value *, 64 > OverdefinedInstWorkList;
477
- SmallVector<Value *, 64 > InstWorkList;
472
+ // / Worklist of instructions to re-visit. This only includes instructions
473
+ // / in blocks that have already been visited at least once.
474
+ SmallSetVector<Instruction *, 16 > InstWorkList;
475
+
476
+ // / Current instruction while visiting a block for the first time, used to
477
+ // / avoid unnecessary instruction worklist insertions. Null if an instruction
478
+ // / is visited outside a whole-block visitation.
479
+ Instruction *CurI = nullptr ;
478
480
479
481
// The BasicBlock work list
480
482
SmallVector<BasicBlock *, 64 > BBWorkList;
@@ -497,12 +499,15 @@ class SCCPInstVisitor : public InstVisitor<SCCPInstVisitor> {
497
499
return dyn_cast_or_null<ConstantInt>(getConstant (IV, Ty));
498
500
}
499
501
500
- // pushToWorkList - Helper for markConstant/markOverdefined
501
- void pushToWorkList (ValueLatticeElement &IV, Value *V);
502
+ // / Push instruction \p I to the worklist.
503
+ void pushToWorkList (Instruction *I);
504
+
505
+ // / Push users of value \p V to the worklist.
506
+ void pushUsersToWorkList (Value *V);
502
507
503
- // Helper to push \p V to the worklist, after updating it to \p IV. Also
504
- // prints a debug message with the updated value.
505
- void pushToWorkListMsg (ValueLatticeElement &IV, Value *V);
508
+ // / Like pushUsersToWorkList(), but also prints a debug message with the
509
+ // / updated value.
510
+ void pushUsersToWorkListMsg (ValueLatticeElement &IV, Value *V);
506
511
507
512
// markConstant - Make a value be marked as "constant". If the value
508
513
// is not already a constant, add it to the instruction work list so that
@@ -661,46 +666,9 @@ class SCCPInstVisitor : public InstVisitor<SCCPInstVisitor> {
661
666
// successors are reachable from a given terminator instruction.
662
667
void getFeasibleSuccessors (Instruction &TI, SmallVectorImpl<bool > &Succs);
663
668
664
- // OperandChangedState - This method is invoked on all of the users of an
665
- // instruction that was just changed state somehow. Based on this
666
- // information, we need to update the specified user of this instruction.
667
- void operandChangedState (Instruction *I) {
668
- if (BBExecutable.count (I->getParent ())) // Inst is executable?
669
- visit (*I);
670
- }
671
-
672
669
// Add U as additional user of V.
673
670
void addAdditionalUser (Value *V, User *U) { AdditionalUsers[V].insert (U); }
674
671
675
- // Mark I's users as changed, including AdditionalUsers.
676
- void markUsersAsChanged (Value *I) {
677
- // Functions include their arguments in the use-list. Changed function
678
- // values mean that the result of the function changed. We only need to
679
- // update the call sites with the new function result and do not have to
680
- // propagate the call arguments.
681
- if (isa<Function>(I)) {
682
- for (User *U : I->users ()) {
683
- if (auto *CB = dyn_cast<CallBase>(U))
684
- handleCallResult (*CB);
685
- }
686
- } else {
687
- for (User *U : I->users ())
688
- if (auto *UI = dyn_cast<Instruction>(U))
689
- operandChangedState (UI);
690
- }
691
-
692
- auto Iter = AdditionalUsers.find (I);
693
- if (Iter != AdditionalUsers.end ()) {
694
- // Copy additional users before notifying them of changes, because new
695
- // users may be added, potentially invalidating the iterator.
696
- SmallVector<Instruction *, 2 > ToNotify;
697
- for (User *U : Iter->second )
698
- if (auto *UI = dyn_cast<Instruction>(U))
699
- ToNotify.push_back (UI);
700
- for (Instruction *UI : ToNotify)
701
- operandChangedState (UI);
702
- }
703
- }
704
672
void handleCallOverdefined (CallBase &CB);
705
673
void handleCallResult (CallBase &CB);
706
674
void handleCallArguments (CallBase &CB);
@@ -985,27 +953,49 @@ bool SCCPInstVisitor::markBlockExecutable(BasicBlock *BB) {
985
953
return true ;
986
954
}
987
955
988
- void SCCPInstVisitor::pushToWorkList (ValueLatticeElement &IV, Value *V) {
989
- if (IV.isOverdefined ()) {
990
- if (OverdefinedInstWorkList.empty () || OverdefinedInstWorkList.back () != V)
991
- OverdefinedInstWorkList.push_back (V);
956
+ void SCCPInstVisitor::pushToWorkList (Instruction *I) {
957
+ // If we're currently visiting a block, do not push any instructions in the
958
+ // same blocks that are after the current one, as they will be visited
959
+ // anyway. We do have to push updates to earlier instructions (e.g. phi
960
+ // nodes or loads of tracked globals).
961
+ if (CurI && I->getParent () == CurI->getParent () && !I->comesBefore (CurI))
992
962
return ;
963
+ // Only push instructions in already visited blocks. Otherwise we'll handle
964
+ // it when we visit the block for the first time.
965
+ if (BBVisited.contains (I->getParent ()))
966
+ InstWorkList.insert (I);
967
+ }
968
+
969
+ void SCCPInstVisitor::pushUsersToWorkList (Value *V) {
970
+ for (User *U : V->users ())
971
+ if (auto *UI = dyn_cast<Instruction>(U))
972
+ pushToWorkList (UI);
973
+
974
+ auto Iter = AdditionalUsers.find (V);
975
+ if (Iter != AdditionalUsers.end ()) {
976
+ // Copy additional users before notifying them of changes, because new
977
+ // users may be added, potentially invalidating the iterator.
978
+ SmallVector<Instruction *, 2 > ToNotify;
979
+ for (User *U : Iter->second )
980
+ if (auto *UI = dyn_cast<Instruction>(U))
981
+ ToNotify.push_back (UI);
982
+ for (Instruction *UI : ToNotify)
983
+ pushToWorkList (UI);
993
984
}
994
- if (InstWorkList.empty () || InstWorkList.back () != V)
995
- InstWorkList.push_back (V);
996
985
}
997
986
998
- void SCCPInstVisitor::pushToWorkListMsg (ValueLatticeElement &IV, Value *V) {
987
+ void SCCPInstVisitor::pushUsersToWorkListMsg (ValueLatticeElement &IV,
988
+ Value *V) {
999
989
LLVM_DEBUG (dbgs () << " updated " << IV << " : " << *V << ' \n ' );
1000
- pushToWorkList (IV, V);
990
+ pushUsersToWorkList ( V);
1001
991
}
1002
992
1003
993
bool SCCPInstVisitor::markConstant (ValueLatticeElement &IV, Value *V,
1004
994
Constant *C, bool MayIncludeUndef) {
1005
995
if (!IV.markConstant (C, MayIncludeUndef))
1006
996
return false ;
1007
997
LLVM_DEBUG (dbgs () << " markConstant: " << *C << " : " << *V << ' \n ' );
1008
- pushToWorkList (IV, V);
998
+ pushUsersToWorkList ( V);
1009
999
return true ;
1010
1000
}
1011
1001
@@ -1014,7 +1004,7 @@ bool SCCPInstVisitor::markNotConstant(ValueLatticeElement &IV, Value *V,
1014
1004
if (!IV.markNotConstant (C))
1015
1005
return false ;
1016
1006
LLVM_DEBUG (dbgs () << " markNotConstant: " << *C << " : " << *V << ' \n ' );
1017
- pushToWorkList (IV, V);
1007
+ pushUsersToWorkList ( V);
1018
1008
return true ;
1019
1009
}
1020
1010
@@ -1023,7 +1013,7 @@ bool SCCPInstVisitor::markConstantRange(ValueLatticeElement &IV, Value *V,
1023
1013
if (!IV.markConstantRange (CR))
1024
1014
return false ;
1025
1015
LLVM_DEBUG (dbgs () << " markConstantRange: " << CR << " : " << *V << ' \n ' );
1026
- pushToWorkList (IV, V);
1016
+ pushUsersToWorkList ( V);
1027
1017
return true ;
1028
1018
}
1029
1019
@@ -1036,7 +1026,7 @@ bool SCCPInstVisitor::markOverdefined(ValueLatticeElement &IV, Value *V) {
1036
1026
<< " Function '" << F->getName () << " '\n " ;
1037
1027
else dbgs () << *V << ' \n ' );
1038
1028
// Only instructions go on the work list
1039
- pushToWorkList (IV, V);
1029
+ pushUsersToWorkList ( V);
1040
1030
return true ;
1041
1031
}
1042
1032
@@ -1144,7 +1134,7 @@ bool SCCPInstVisitor::mergeInValue(ValueLatticeElement &IV, Value *V,
1144
1134
ValueLatticeElement MergeWithV,
1145
1135
ValueLatticeElement::MergeOptions Opts) {
1146
1136
if (IV.mergeIn (MergeWithV, Opts)) {
1147
- pushToWorkList (IV, V);
1137
+ pushUsersToWorkList ( V);
1148
1138
LLVM_DEBUG (dbgs () << " Merged " << MergeWithV << " into " << *V << " : "
1149
1139
<< IV << " \n " );
1150
1140
return true ;
@@ -1164,7 +1154,7 @@ bool SCCPInstVisitor::markEdgeExecutable(BasicBlock *Source, BasicBlock *Dest) {
1164
1154
<< " -> " << Dest->getName () << ' \n ' );
1165
1155
1166
1156
for (PHINode &PN : Dest->phis ())
1167
- visitPHINode ( PN);
1157
+ pushToWorkList (& PN);
1168
1158
}
1169
1159
return true ;
1170
1160
}
@@ -1540,7 +1530,7 @@ void SCCPInstVisitor::visitSelectInst(SelectInst &I) {
1540
1530
bool Changed = State.mergeIn (TVal);
1541
1531
Changed |= State.mergeIn (FVal);
1542
1532
if (Changed)
1543
- pushToWorkListMsg (State, &I);
1533
+ pushUsersToWorkListMsg (State, &I);
1544
1534
}
1545
1535
1546
1536
// Handle Unary Operators.
@@ -2039,53 +2029,28 @@ void SCCPInstVisitor::handleCallResult(CallBase &CB) {
2039
2029
2040
2030
void SCCPInstVisitor::solve () {
2041
2031
// Process the work lists until they are empty!
2042
- while (!BBWorkList.empty () || !InstWorkList.empty () ||
2043
- !OverdefinedInstWorkList.empty ()) {
2044
- // Process the overdefined instruction's work list first, which drives other
2045
- // things to overdefined more quickly.
2046
- while (!OverdefinedInstWorkList.empty ()) {
2047
- Value *I = OverdefinedInstWorkList.pop_back_val ();
2048
- Invalidated.erase (I);
2049
-
2050
- LLVM_DEBUG (dbgs () << " \n Popped off OI-WL: " << *I << ' \n ' );
2051
-
2052
- // "I" got into the work list because it either made the transition from
2053
- // bottom to constant, or to overdefined.
2054
- //
2055
- // Anything on this worklist that is overdefined need not be visited
2056
- // since all of its users will have already been marked as overdefined
2057
- // Update all of the users of this instruction's value.
2058
- //
2059
- markUsersAsChanged (I);
2060
- }
2061
-
2032
+ while (!BBWorkList.empty () || !InstWorkList.empty ()) {
2062
2033
// Process the instruction work list.
2063
2034
while (!InstWorkList.empty ()) {
2064
- Value *I = InstWorkList.pop_back_val ();
2035
+ Instruction *I = InstWorkList.pop_back_val ();
2065
2036
Invalidated.erase (I);
2066
2037
2067
2038
LLVM_DEBUG (dbgs () << " \n Popped off I-WL: " << *I << ' \n ' );
2068
2039
2069
- // "I" got into the work list because it made the transition from undef to
2070
- // constant.
2071
- //
2072
- // Anything on this worklist that is overdefined need not be visited
2073
- // since all of its users will have already been marked as overdefined.
2074
- // Update all of the users of this instruction's value.
2075
- //
2076
- if (I->getType ()->isStructTy () || !getValueState (I).isOverdefined ())
2077
- markUsersAsChanged (I);
2040
+ visit (I);
2078
2041
}
2079
2042
2080
2043
// Process the basic block work list.
2081
2044
while (!BBWorkList.empty ()) {
2082
2045
BasicBlock *BB = BBWorkList.pop_back_val ();
2046
+ BBVisited.insert (BB);
2083
2047
2084
2048
LLVM_DEBUG (dbgs () << " \n Popped off BBWL: " << *BB << ' \n ' );
2085
-
2086
- // Notify all instructions in this basic block that they are newly
2087
- // executable.
2088
- visit (BB);
2049
+ for (Instruction &I : *BB) {
2050
+ CurI = &I;
2051
+ visit (I);
2052
+ }
2053
+ CurI = nullptr ;
2089
2054
}
2090
2055
}
2091
2056
}
0 commit comments