88
99#include " llvm/Transforms/Scalar/StructurizeCFG.h"
1010#include " llvm/ADT/DenseMap.h"
11+ #include " llvm/ADT/EquivalenceClasses.h"
1112#include " llvm/ADT/MapVector.h"
1213#include " llvm/ADT/SCCIterator.h"
1314#include " llvm/ADT/STLExtras.h"
@@ -325,6 +326,10 @@ class StructurizeCFG {
325326 void findUndefBlocks (BasicBlock *PHIBlock,
326327 const SmallSet<BasicBlock *, 8 > &Incomings,
327328 SmallVector<BasicBlock *> &UndefBlks) const ;
329+
330+ void mergeIfCompatible (EquivalenceClasses<PHINode *> &PhiClasses, PHINode *A,
331+ PHINode *B);
332+
328333 void setPhiValues ();
329334
330335 void simplifyAffectedPhis ();
@@ -755,39 +760,130 @@ void StructurizeCFG::findUndefBlocks(
755760 }
756761}
757762
763+ // If two phi nodes have compatible incoming values (for each
764+ // incoming block, either they have the same incoming value or only one phi
765+ // node has an incoming value), let them share the merged incoming values. The
766+ // merge process is guided by the equivalence information from \p PhiClasses.
767+ // The function will possibly update the incoming values of leader phi in
768+ // DeletedPhis.
769+ void StructurizeCFG::mergeIfCompatible (
770+ EquivalenceClasses<PHINode *> &PhiClasses, PHINode *A, PHINode *B) {
771+ auto ItA = PhiClasses.findLeader (PhiClasses.insert (A));
772+ auto ItB = PhiClasses.findLeader (PhiClasses.insert (B));
773+ // They are already in the same class, no work needed.
774+ if (ItA == ItB)
775+ return ;
776+
777+ PHINode *LeaderA = *ItA;
778+ PHINode *LeaderB = *ItB;
779+ BBValueVector &IncomingA = DeletedPhis[LeaderA->getParent ()][LeaderA];
780+ BBValueVector &IncomingB = DeletedPhis[LeaderB->getParent ()][LeaderB];
781+
782+ DenseMap<BasicBlock *, Value *> Mergeable (IncomingA.begin (), IncomingA.end ());
783+ for (auto [BB, V] : IncomingB) {
784+ auto BBIt = Mergeable.find (BB);
785+ if (BBIt != Mergeable.end () && BBIt->second != V)
786+ return ;
787+ // Either IncomingA does not have this value or IncomingA has the same
788+ // value.
789+ Mergeable.insert ({BB, V});
790+ }
791+
792+ // Update the incoming value of leaderA.
793+ IncomingA.assign (Mergeable.begin (), Mergeable.end ());
794+ PhiClasses.unionSets (ItA, ItB);
795+ }
796+
758797// / Add the real PHI value as soon as everything is set up
759798void StructurizeCFG::setPhiValues () {
760799 SmallVector<PHINode *, 8 > InsertedPhis;
761800 SSAUpdater Updater (&InsertedPhis);
801+ DenseMap<BasicBlock *, SmallVector<BasicBlock *>> UndefBlksMap;
802+
803+ // Find phi nodes that have compatible incoming values (either they have
804+ // the same value for the same block or only one phi node has an incoming
805+ // value, see example below). We only search again the phi's that are
806+ // referenced by another phi, which is the case we care about.
807+ //
808+ // For example (-- means no incoming value):
809+ // phi1 : BB1:phi2 BB2:v BB3:--
810+ // phi2: BB1:-- BB2:v BB3:w
811+ //
812+ // Then we can merge these incoming values and let phi1, phi2 use the
813+ // same set of incoming values:
814+ //
815+ // phi1&phi2: BB1:phi2 BB2:v BB3:w
816+ //
817+ // By doing this, phi1 and phi2 would share more intermediate phi nodes.
818+ // This would help reduce the number of phi nodes during SSA reconstruction
819+ // and ultimately result in fewer COPY instructions.
820+ //
821+ // This should be correct, because if a phi node does not have incoming
822+ // value from certain block, this means the block is not the predecessor
823+ // of the parent block, so we actually don't care about its incoming value.
824+ EquivalenceClasses<PHINode *> PhiClasses;
825+ for (const auto &[To, From] : AddedPhis) {
826+ auto OldPhiIt = DeletedPhis.find (To);
827+ if (OldPhiIt == DeletedPhis.end ())
828+ continue ;
829+
830+ PhiMap &BlkPhis = OldPhiIt->second ;
831+ SmallVector<BasicBlock *> &UndefBlks = UndefBlksMap[To];
832+ SmallSet<BasicBlock *, 8 > Incomings;
833+
834+ // Get the undefined blocks shared by all the phi nodes.
835+ if (!BlkPhis.empty ()) {
836+ for (const auto &VI : BlkPhis.front ().second )
837+ Incomings.insert (VI.first );
838+ findUndefBlocks (To, Incomings, UndefBlks);
839+ }
840+
841+ for (const auto &[Phi, Incomings] : OldPhiIt->second ) {
842+ SmallVector<PHINode *> IncomingPHIs;
843+ for (const auto &[BB, V] : Incomings) {
844+ // First, for each phi, check whether it has incoming value which is
845+ // another phi.
846+ if (PHINode *P = dyn_cast<PHINode>(V))
847+ IncomingPHIs.push_back (P);
848+ }
849+
850+ for (auto *OtherPhi : IncomingPHIs) {
851+ // Skip phis that are unrelated to the phi reconstruction for now.
852+ if (!DeletedPhis.contains (OtherPhi->getParent ()))
853+ continue ;
854+ mergeIfCompatible (PhiClasses, Phi, OtherPhi);
855+ }
856+ }
857+ }
858+
762859 for (const auto &AddedPhi : AddedPhis) {
763860 BasicBlock *To = AddedPhi.first ;
764861 const BBVector &From = AddedPhi.second ;
765862
766863 if (!DeletedPhis.count (To))
767864 continue ;
768865
769- SmallVector<BasicBlock *> UndefBlks;
770- bool CachedUndefs = false ;
771866 PhiMap &Map = DeletedPhis[To];
772- for ( const auto &PI : Map) {
773- PHINode * Phi = PI. first ;
867+ SmallVector<BasicBlock *> &UndefBlks = UndefBlksMap[To];
868+ for ( const auto &[ Phi, Incoming] : Map) {
774869 Value *Undef = UndefValue::get (Phi->getType ());
775870 Updater.Initialize (Phi->getType (), " " );
776871 Updater.AddAvailableValue (&Func->getEntryBlock (), Undef);
777872 Updater.AddAvailableValue (To, Undef);
778873
779- SmallSet<BasicBlock *, 8 > Incomings;
780- SmallVector<BasicBlock *> ConstantPreds;
781- for (const auto &VI : PI.second ) {
782- Incomings.insert (VI.first );
783- Updater.AddAvailableValue (VI.first , VI.second );
784- if (isa<Constant>(VI.second ))
785- ConstantPreds.push_back (VI.first );
786- }
874+ // Use leader phi's incoming if there is.
875+ auto LeaderIt = PhiClasses.findLeader (Phi);
876+ bool UseIncomingOfLeader =
877+ LeaderIt != PhiClasses.member_end () && *LeaderIt != Phi;
878+ const auto &IncomingMap =
879+ UseIncomingOfLeader ? DeletedPhis[(*LeaderIt)->getParent ()][*LeaderIt]
880+ : Incoming;
787881
788- if (!CachedUndefs) {
789- findUndefBlocks (To, Incomings, UndefBlks);
790- CachedUndefs = true ;
882+ SmallVector<BasicBlock *> ConstantPreds;
883+ for (const auto &[BB, V] : IncomingMap) {
884+ Updater.AddAvailableValue (BB, V);
885+ if (isa<Constant>(V))
886+ ConstantPreds.push_back (BB);
791887 }
792888
793889 for (auto UB : UndefBlks) {
@@ -798,17 +894,18 @@ void StructurizeCFG::setPhiValues() {
798894 if (any_of (ConstantPreds,
799895 [&](BasicBlock *CP) { return DT->dominates (CP, UB); }))
800896 continue ;
897+ // Maybe already get a value through sharing with other phi nodes.
898+ if (Updater.HasValueForBlock (UB))
899+ continue ;
900+
801901 Updater.AddAvailableValue (UB, Undef);
802902 }
803903
804904 for (BasicBlock *FI : From)
805905 Phi->setIncomingValueForBlock (FI, Updater.GetValueAtEndOfBlock (FI));
806906 AffectedPhis.push_back (Phi);
807907 }
808-
809- DeletedPhis.erase (To);
810908 }
811- assert (DeletedPhis.empty ());
812909
813910 AffectedPhis.append (InsertedPhis.begin (), InsertedPhis.end ());
814911}
0 commit comments