@@ -426,7 +426,10 @@ void SCCPSolver::inferArgAttributes() const {
426426class SCCPInstVisitor : public InstVisitor <SCCPInstVisitor> {
427427 const DataLayout &DL;
428428 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;
430433 DenseMap<Value *, ValueLatticeElement>
431434 ValueState; // The state each value is in.
432435
@@ -466,15 +469,14 @@ class SCCPInstVisitor : public InstVisitor<SCCPInstVisitor> {
466469 // / constants.
467470 SmallPtrSet<Function *, 16 > TrackingIncomingArguments;
468471
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 ;
478480
479481 // The BasicBlock work list
480482 SmallVector<BasicBlock *, 64 > BBWorkList;
@@ -497,12 +499,15 @@ class SCCPInstVisitor : public InstVisitor<SCCPInstVisitor> {
497499 return dyn_cast_or_null<ConstantInt>(getConstant (IV, Ty));
498500 }
499501
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);
502507
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);
506511
507512 // markConstant - Make a value be marked as "constant". If the value
508513 // is not already a constant, add it to the instruction work list so that
@@ -661,46 +666,9 @@ class SCCPInstVisitor : public InstVisitor<SCCPInstVisitor> {
661666 // successors are reachable from a given terminator instruction.
662667 void getFeasibleSuccessors (Instruction &TI, SmallVectorImpl<bool > &Succs);
663668
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-
672669 // Add U as additional user of V.
673670 void addAdditionalUser (Value *V, User *U) { AdditionalUsers[V].insert (U); }
674671
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- }
704672 void handleCallOverdefined (CallBase &CB);
705673 void handleCallResult (CallBase &CB);
706674 void handleCallArguments (CallBase &CB);
@@ -985,27 +953,49 @@ bool SCCPInstVisitor::markBlockExecutable(BasicBlock *BB) {
985953 return true ;
986954}
987955
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))
992962 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);
993984 }
994- if (InstWorkList.empty () || InstWorkList.back () != V)
995- InstWorkList.push_back (V);
996985}
997986
998- void SCCPInstVisitor::pushToWorkListMsg (ValueLatticeElement &IV, Value *V) {
987+ void SCCPInstVisitor::pushUsersToWorkListMsg (ValueLatticeElement &IV,
988+ Value *V) {
999989 LLVM_DEBUG (dbgs () << " updated " << IV << " : " << *V << ' \n ' );
1000- pushToWorkList (IV, V);
990+ pushUsersToWorkList ( V);
1001991}
1002992
1003993bool SCCPInstVisitor::markConstant (ValueLatticeElement &IV, Value *V,
1004994 Constant *C, bool MayIncludeUndef) {
1005995 if (!IV.markConstant (C, MayIncludeUndef))
1006996 return false ;
1007997 LLVM_DEBUG (dbgs () << " markConstant: " << *C << " : " << *V << ' \n ' );
1008- pushToWorkList (IV, V);
998+ pushUsersToWorkList ( V);
1009999 return true ;
10101000}
10111001
@@ -1014,7 +1004,7 @@ bool SCCPInstVisitor::markNotConstant(ValueLatticeElement &IV, Value *V,
10141004 if (!IV.markNotConstant (C))
10151005 return false ;
10161006 LLVM_DEBUG (dbgs () << " markNotConstant: " << *C << " : " << *V << ' \n ' );
1017- pushToWorkList (IV, V);
1007+ pushUsersToWorkList ( V);
10181008 return true ;
10191009}
10201010
@@ -1023,7 +1013,7 @@ bool SCCPInstVisitor::markConstantRange(ValueLatticeElement &IV, Value *V,
10231013 if (!IV.markConstantRange (CR))
10241014 return false ;
10251015 LLVM_DEBUG (dbgs () << " markConstantRange: " << CR << " : " << *V << ' \n ' );
1026- pushToWorkList (IV, V);
1016+ pushUsersToWorkList ( V);
10271017 return true ;
10281018}
10291019
@@ -1036,7 +1026,7 @@ bool SCCPInstVisitor::markOverdefined(ValueLatticeElement &IV, Value *V) {
10361026 << " Function '" << F->getName () << " '\n " ;
10371027 else dbgs () << *V << ' \n ' );
10381028 // Only instructions go on the work list
1039- pushToWorkList (IV, V);
1029+ pushUsersToWorkList ( V);
10401030 return true ;
10411031}
10421032
@@ -1144,7 +1134,7 @@ bool SCCPInstVisitor::mergeInValue(ValueLatticeElement &IV, Value *V,
11441134 ValueLatticeElement MergeWithV,
11451135 ValueLatticeElement::MergeOptions Opts) {
11461136 if (IV.mergeIn (MergeWithV, Opts)) {
1147- pushToWorkList (IV, V);
1137+ pushUsersToWorkList ( V);
11481138 LLVM_DEBUG (dbgs () << " Merged " << MergeWithV << " into " << *V << " : "
11491139 << IV << " \n " );
11501140 return true ;
@@ -1164,7 +1154,7 @@ bool SCCPInstVisitor::markEdgeExecutable(BasicBlock *Source, BasicBlock *Dest) {
11641154 << " -> " << Dest->getName () << ' \n ' );
11651155
11661156 for (PHINode &PN : Dest->phis ())
1167- visitPHINode ( PN);
1157+ pushToWorkList (& PN);
11681158 }
11691159 return true ;
11701160}
@@ -1540,7 +1530,7 @@ void SCCPInstVisitor::visitSelectInst(SelectInst &I) {
15401530 bool Changed = State.mergeIn (TVal);
15411531 Changed |= State.mergeIn (FVal);
15421532 if (Changed)
1543- pushToWorkListMsg (State, &I);
1533+ pushUsersToWorkListMsg (State, &I);
15441534}
15451535
15461536// Handle Unary Operators.
@@ -2039,53 +2029,28 @@ void SCCPInstVisitor::handleCallResult(CallBase &CB) {
20392029
20402030void SCCPInstVisitor::solve () {
20412031 // 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 ()) {
20622033 // Process the instruction work list.
20632034 while (!InstWorkList.empty ()) {
2064- Value *I = InstWorkList.pop_back_val ();
2035+ Instruction *I = InstWorkList.pop_back_val ();
20652036 Invalidated.erase (I);
20662037
20672038 LLVM_DEBUG (dbgs () << " \n Popped off I-WL: " << *I << ' \n ' );
20682039
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);
20782041 }
20792042
20802043 // Process the basic block work list.
20812044 while (!BBWorkList.empty ()) {
20822045 BasicBlock *BB = BBWorkList.pop_back_val ();
2046+ BBVisited.insert (BB);
20832047
20842048 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 ;
20892054 }
20902055 }
20912056}
0 commit comments