8
8
9
9
#include " llvm/Transforms/Scalar/StructurizeCFG.h"
10
10
#include " llvm/ADT/DenseMap.h"
11
+ #include " llvm/ADT/EquivalenceClasses.h"
11
12
#include " llvm/ADT/MapVector.h"
12
13
#include " llvm/ADT/SCCIterator.h"
13
14
#include " llvm/ADT/STLExtras.h"
@@ -325,6 +326,10 @@ class StructurizeCFG {
325
326
void findUndefBlocks (BasicBlock *PHIBlock,
326
327
const SmallSet<BasicBlock *, 8 > &Incomings,
327
328
SmallVector<BasicBlock *> &UndefBlks) const ;
329
+
330
+ void mergeIfCompatible (EquivalenceClasses<PHINode *> &PhiClasses, PHINode *A,
331
+ PHINode *B);
332
+
328
333
void setPhiValues ();
329
334
330
335
void simplifyAffectedPhis ();
@@ -755,39 +760,130 @@ void StructurizeCFG::findUndefBlocks(
755
760
}
756
761
}
757
762
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
+
758
797
// / Add the real PHI value as soon as everything is set up
759
798
void StructurizeCFG::setPhiValues () {
760
799
SmallVector<PHINode *, 8 > InsertedPhis;
761
800
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
+
762
859
for (const auto &AddedPhi : AddedPhis) {
763
860
BasicBlock *To = AddedPhi.first ;
764
861
const BBVector &From = AddedPhi.second ;
765
862
766
863
if (!DeletedPhis.count (To))
767
864
continue ;
768
865
769
- SmallVector<BasicBlock *> UndefBlks;
770
- bool CachedUndefs = false ;
771
866
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) {
774
869
Value *Undef = UndefValue::get (Phi->getType ());
775
870
Updater.Initialize (Phi->getType (), " " );
776
871
Updater.AddAvailableValue (&Func->getEntryBlock (), Undef);
777
872
Updater.AddAvailableValue (To, Undef);
778
873
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;
787
881
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);
791
887
}
792
888
793
889
for (auto UB : UndefBlks) {
@@ -798,17 +894,18 @@ void StructurizeCFG::setPhiValues() {
798
894
if (any_of (ConstantPreds,
799
895
[&](BasicBlock *CP) { return DT->dominates (CP, UB); }))
800
896
continue ;
897
+ // Maybe already get a value through sharing with other phi nodes.
898
+ if (Updater.HasValueForBlock (UB))
899
+ continue ;
900
+
801
901
Updater.AddAvailableValue (UB, Undef);
802
902
}
803
903
804
904
for (BasicBlock *FI : From)
805
905
Phi->setIncomingValueForBlock (FI, Updater.GetValueAtEndOfBlock (FI));
806
906
AffectedPhis.push_back (Phi);
807
907
}
808
-
809
- DeletedPhis.erase (To);
810
908
}
811
- assert (DeletedPhis.empty ());
812
909
813
910
AffectedPhis.append (InsertedPhis.begin (), InsertedPhis.end ());
814
911
}
0 commit comments