88
99#include " llvm/Transforms/Scalar/StructurizeCFG.h"
1010#include " llvm/ADT/DenseMap.h"
11- #include " llvm/ADT/EquivalenceClasses.h"
1211#include " llvm/ADT/MapVector.h"
1312#include " llvm/ADT/SCCIterator.h"
1413#include " llvm/ADT/STLExtras.h"
@@ -289,10 +288,6 @@ class StructurizeCFG {
289288 void findUndefBlocks (BasicBlock *PHIBlock,
290289 const SmallSet<BasicBlock *, 8 > &Incomings,
291290 SmallVector<BasicBlock *> &UndefBlks) const ;
292-
293- void mergeIfCompatible (EquivalenceClasses<PHINode *> &PhiClasses, PHINode *A,
294- PHINode *B);
295-
296291 void setPhiValues ();
297292
298293 void simplifyAffectedPhis ();
@@ -715,131 +710,39 @@ void StructurizeCFG::findUndefBlocks(
715710 }
716711}
717712
718- // If two phi nodes have compatible incoming values (for each
719- // incoming block, either they have the same incoming value or only one phi
720- // node has an incoming value), let them share the merged incoming values. The
721- // merge process is guided by the equivalence information from \p PhiClasses.
722- // The function will possibly update the incoming values of leader phi in
723- // DeletedPhis.
724- void StructurizeCFG::mergeIfCompatible (
725- EquivalenceClasses<PHINode *> &PhiClasses, PHINode *A, PHINode *B) {
726- auto ItA = PhiClasses.findLeader (PhiClasses.insert (A));
727- auto ItB = PhiClasses.findLeader (PhiClasses.insert (B));
728- // They are already in the same class, no work needed.
729- if (ItA == ItB)
730- return ;
731-
732- PHINode *LeaderA = *ItA;
733- PHINode *LeaderB = *ItB;
734- BBValueVector &IncomingA = DeletedPhis[LeaderA->getParent ()][LeaderA];
735- BBValueVector &IncomingB = DeletedPhis[LeaderB->getParent ()][LeaderB];
736-
737- DenseMap<BasicBlock *, Value *> Mergeable (IncomingA.begin (), IncomingA.end ());
738- for (auto [BB, V] : IncomingB) {
739- auto BBIt = Mergeable.find (BB);
740- if (BBIt != Mergeable.end () && BBIt->second != V)
741- return ;
742- // Either IncomingA does not have this value or IncomingA has the same
743- // value.
744- Mergeable.insert ({BB, V});
745- }
746-
747- // Update the incoming value of leaderA.
748- IncomingA.assign (Mergeable.begin (), Mergeable.end ());
749- PhiClasses.unionSets (ItA, ItB);
750- }
751-
752713// / Add the real PHI value as soon as everything is set up
753714void StructurizeCFG::setPhiValues () {
754715 SmallVector<PHINode *, 8 > InsertedPhis;
755716 SSAUpdater Updater (&InsertedPhis);
756- DenseMap<BasicBlock *, SmallVector<BasicBlock *>> UndefBlksMap;
757-
758- // Find phi nodes that have compatible incoming values (either they have
759- // the same value for the same block or only one phi node has an incoming
760- // value, see example below). We only search again the phi's that are
761- // referenced by another phi, which is the case we care about.
762- //
763- // For example (-- means no incoming value):
764- // phi1 : BB1:phi2 BB2:v BB3:--
765- // phi2: BB1:-- BB2:v BB3:w
766- //
767- // Then we can merge these incoming values and let phi1, phi2 use the
768- // same set of incoming values:
769- //
770- // phi1&phi2: BB1:phi2 BB2:v BB3:w
771- //
772- // By doing this, phi1 and phi2 would share more intermediate phi nodes.
773- // This would help reduce the number of phi nodes during SSA reconstruction
774- // and ultimately result in fewer COPY instructions.
775- //
776- // This should be correct, because if a phi node does not have incoming
777- // value from certain block, this means the block is not the predecessor
778- // of the parent block, so we actually don't care about its incoming value.
779- EquivalenceClasses<PHINode *> PhiClasses;
780- for (const auto &[To, From] : AddedPhis) {
781- auto OldPhiIt = DeletedPhis.find (To);
782- if (OldPhiIt == DeletedPhis.end ())
783- continue ;
784-
785- PhiMap &BlkPhis = OldPhiIt->second ;
786- SmallVector<BasicBlock *> &UndefBlks =
787- UndefBlksMap.FindAndConstruct (To).second ;
788- SmallSet<BasicBlock *, 8 > Incomings;
789-
790- // Get the undefined blocks shared by all the phi nodes.
791- if (!BlkPhis.empty ()) {
792- for (const auto &VI : BlkPhis.front ().second )
793- Incomings.insert (VI.first );
794- findUndefBlocks (To, Incomings, UndefBlks);
795- }
796-
797- for (const auto &[Phi, Incomings] : OldPhiIt->second ) {
798- SmallVector<PHINode *> IncomingPHIs;
799- for (const auto &[BB, V] : Incomings) {
800- // First, for each phi, check whether it has incoming value which is
801- // another phi.
802- if (PHINode *P = dyn_cast<PHINode>(V))
803- IncomingPHIs.push_back (P);
804- }
805-
806- for (auto *OtherPhi : IncomingPHIs) {
807- // Skip phis that are unrelated to the phi reconstruction for now.
808- if (!DeletedPhis.contains (OtherPhi->getParent ()))
809- continue ;
810- mergeIfCompatible (PhiClasses, Phi, OtherPhi);
811- }
812- }
813- }
814-
815717 for (const auto &AddedPhi : AddedPhis) {
816718 BasicBlock *To = AddedPhi.first ;
817719 const BBVector &From = AddedPhi.second ;
818720
819721 if (!DeletedPhis.count (To))
820722 continue ;
821723
724+ SmallVector<BasicBlock *> UndefBlks;
725+ bool CachedUndefs = false ;
822726 PhiMap &Map = DeletedPhis[To];
823- SmallVector<BasicBlock *> &UndefBlks = UndefBlksMap[To];
824- for ( const auto &[ Phi, Incoming] : Map) {
727+ for ( const auto &PI : Map) {
728+ PHINode * Phi = PI. first ;
825729 Value *Undef = UndefValue::get (Phi->getType ());
826730 Updater.Initialize (Phi->getType (), " " );
827731 Updater.AddAvailableValue (&Func->getEntryBlock (), Undef);
828732 Updater.AddAvailableValue (To, Undef);
829733
830- // Use leader phi's incoming if there is.
831- auto LeaderIt = PhiClasses.findLeader (Phi);
832- bool UseIncomingOfLeader =
833- LeaderIt != PhiClasses.member_end () && *LeaderIt != Phi;
834- const auto &IncomingMap =
835- UseIncomingOfLeader ? DeletedPhis[(*LeaderIt)->getParent ()][*LeaderIt]
836- : Incoming;
837-
734+ SmallSet<BasicBlock *, 8 > Incomings;
838735 SmallVector<BasicBlock *> ConstantPreds;
839- for (const auto &[BB, V] : IncomingMap) {
840- Updater.AddAvailableValue (BB, V);
841- if (isa<Constant>(V))
842- ConstantPreds.push_back (BB);
736+ for (const auto &VI : PI.second ) {
737+ Incomings.insert (VI.first );
738+ Updater.AddAvailableValue (VI.first , VI.second );
739+ if (isa<Constant>(VI.second ))
740+ ConstantPreds.push_back (VI.first );
741+ }
742+
743+ if (!CachedUndefs) {
744+ findUndefBlocks (To, Incomings, UndefBlks);
745+ CachedUndefs = true ;
843746 }
844747
845748 for (auto UB : UndefBlks) {
@@ -850,18 +753,17 @@ void StructurizeCFG::setPhiValues() {
850753 if (any_of (ConstantPreds,
851754 [&](BasicBlock *CP) { return DT->dominates (CP, UB); }))
852755 continue ;
853- // Maybe already get a value through sharing with other phi nodes.
854- if (Updater.HasValueForBlock (UB))
855- continue ;
856-
857756 Updater.AddAvailableValue (UB, Undef);
858757 }
859758
860759 for (BasicBlock *FI : From)
861760 Phi->setIncomingValueForBlock (FI, Updater.GetValueAtEndOfBlock (FI));
862761 AffectedPhis.push_back (Phi);
863762 }
763+
764+ DeletedPhis.erase (To);
864765 }
766+ assert (DeletedPhis.empty ());
865767
866768 AffectedPhis.append (InsertedPhis.begin (), InsertedPhis.end ());
867769}
0 commit comments