@@ -358,6 +358,13 @@ struct TypeTreeLeafTypeRange {
358
358
endEltOffset >= range.endEltOffset ;
359
359
}
360
360
361
+ // / Sets each bit in \p bits corresponding to an element of this range.
362
+ void setBits (SmallBitVector &bits) {
363
+ for (auto element : getRange ()) {
364
+ bits.set (element);
365
+ }
366
+ }
367
+
361
368
IntRange<unsigned > getRange () const {
362
369
return range (startEltOffset, endEltOffset);
363
370
}
@@ -666,17 +673,60 @@ class FieldSensitivePrunedLiveness {
666
673
FieldSensitivePrunedLiveBlocks liveBlocks;
667
674
668
675
public:
676
+ enum IsInterestingUser { NonUser, NonLifetimeEndingUse, LifetimeEndingUse };
677
+
669
678
struct InterestingUser {
670
- TypeTreeLeafTypeRange subEltSpan ;
671
- bool isConsuming ;
679
+ SmallBitVector liveBits ;
680
+ SmallBitVector consumingBits ;
672
681
673
- InterestingUser () : subEltSpan(), isConsuming(false ) {}
674
- InterestingUser (TypeTreeLeafTypeRange subEltSpan, bool isConsuming)
675
- : subEltSpan(subEltSpan), isConsuming(isConsuming) {}
682
+ InterestingUser (unsigned bitCount)
683
+ : liveBits(bitCount), consumingBits(bitCount) {}
676
684
677
- InterestingUser &operator &=(bool otherValue) {
678
- isConsuming &= otherValue;
679
- return *this ;
685
+ InterestingUser (unsigned bitCount, TypeTreeLeafTypeRange range,
686
+ bool lifetimeEnding)
687
+ : liveBits(bitCount), consumingBits(bitCount) {
688
+ addUses (range, lifetimeEnding);
689
+ }
690
+
691
+ // / Record that the instruction uses the bits of the value in \p range.
692
+ void addUses (TypeTreeLeafTypeRange range, bool lifetimeEnding) {
693
+ range.setBits (liveBits);
694
+ if (lifetimeEnding) {
695
+ range.setBits (consumingBits);
696
+ }
697
+ }
698
+
699
+ // / Populates the provided vector with contiguous ranges of bits which are
700
+ // / users of the same sort.
701
+ void getContiguousRanges (
702
+ SmallVectorImpl<std::pair<TypeTreeLeafTypeRange, IsInterestingUser>>
703
+ &ranges) const {
704
+ if (liveBits.size () == 0 )
705
+ return ;
706
+
707
+ assert (ranges.empty ());
708
+ Optional<std::pair<unsigned , IsInterestingUser>> current = llvm::None;
709
+ for (unsigned bit = 0 , size = liveBits.size (); bit < size; ++bit) {
710
+ auto interesting = isInterestingUser (bit);
711
+ if (!current) {
712
+ current = {bit, interesting};
713
+ continue ;
714
+ }
715
+ if (current->second != interesting) {
716
+ ranges.push_back (
717
+ {TypeTreeLeafTypeRange (current->first , bit), current->second });
718
+ current = {bit, interesting};
719
+ }
720
+ }
721
+ ranges.push_back ({TypeTreeLeafTypeRange (current->first , liveBits.size ()),
722
+ current->second });
723
+ }
724
+
725
+ IsInterestingUser isInterestingUser (unsigned element) const {
726
+ if (!liveBits.test (element))
727
+ return NonUser;
728
+ return consumingBits.test (element) ? LifetimeEndingUse
729
+ : NonLifetimeEndingUse;
680
730
}
681
731
};
682
732
@@ -758,42 +808,6 @@ class FieldSensitivePrunedLiveness {
758
808
return llvm::make_range (users.begin (), users.end ());
759
809
}
760
810
761
- using LifetimeEndingUserRange = OptionalTransformRange<
762
- UserRange,
763
- function_ref<Optional<std::pair<SILInstruction *, TypeTreeLeafTypeRange>>(
764
- const std::pair<SILInstruction *, InterestingUser> &)>>;
765
- LifetimeEndingUserRange getAllLifetimeEndingUses () const {
766
- assert (isInitialized ());
767
- function_ref<Optional<std::pair<SILInstruction *, TypeTreeLeafTypeRange>>(
768
- const std::pair<SILInstruction *, InterestingUser> &)>
769
- op;
770
- op = [](const std::pair<SILInstruction *, InterestingUser> &pair)
771
- -> Optional<std::pair<SILInstruction *, TypeTreeLeafTypeRange>> {
772
- if (pair.second .isConsuming )
773
- return {{pair.first , pair.second .subEltSpan }};
774
- return None;
775
- };
776
- return LifetimeEndingUserRange (getAllUsers (), op);
777
- }
778
-
779
- using NonLifetimeEndingUserRange = OptionalTransformRange<
780
- UserRange,
781
- function_ref<Optional<std::pair<SILInstruction *, TypeTreeLeafTypeRange>>(
782
- const std::pair<SILInstruction *, InterestingUser> &)>>;
783
- NonLifetimeEndingUserRange getAllNonLifetimeEndingUses () const {
784
- assert (isInitialized ());
785
- function_ref<Optional<std::pair<SILInstruction *, TypeTreeLeafTypeRange>>(
786
- const std::pair<SILInstruction *, InterestingUser> &)>
787
- op;
788
- op = [](const std::pair<SILInstruction *, InterestingUser> &pair)
789
- -> Optional<std::pair<SILInstruction *, TypeTreeLeafTypeRange>> {
790
- if (!pair.second .isConsuming )
791
- return {{pair.first , pair.second .subEltSpan }};
792
- return None;
793
- };
794
- return NonLifetimeEndingUserRange (getAllUsers (), op);
795
- }
796
-
797
811
using UserBlockRange = TransformRange<
798
812
UserRange, function_ref<SILBasicBlock *(
799
813
const std::pair<SILInstruction *, InterestingUser> &)>>;
@@ -848,19 +862,37 @@ class FieldSensitivePrunedLiveness {
848
862
SmallBitVector &liveOutBits,
849
863
SmallBitVector &deadBits) const ;
850
864
851
- enum IsInterestingUser { NonUser, NonLifetimeEndingUse, LifetimeEndingUse };
865
+ // / If \p user has had uses recored, return a pointer to the InterestingUser
866
+ // / where they've been recorded.
867
+ InterestingUser const *getInterestingUser (SILInstruction *user) const {
868
+ auto iter = users.find (user);
869
+ if (iter == users.end ())
870
+ return nullptr ;
871
+ return &iter->second ;
872
+ }
852
873
853
- // / Return a result indicating whether the given user was identified as an
854
- // / interesting use of the current def and whether it ends the lifetime.
855
- std::pair<IsInterestingUser, Optional<TypeTreeLeafTypeRange>>
856
- isInterestingUser (SILInstruction *user) const {
874
+ // / How \p user uses the field at \p element.
875
+ IsInterestingUser isInterestingUser (SILInstruction *user,
876
+ unsigned element) const {
857
877
assert (isInitialized ());
858
- auto useIter = users.find (user);
859
- if (useIter == users.end ())
860
- return {NonUser, None};
861
- auto isInteresting =
862
- useIter->second .isConsuming ? LifetimeEndingUse : NonLifetimeEndingUse;
863
- return {isInteresting, useIter->second .subEltSpan };
878
+ auto *record = getInterestingUser (user);
879
+ if (!record)
880
+ return NonUser;
881
+ return record->isInterestingUser (element);
882
+ }
883
+
884
+ // / Whether \p user uses the fields in \p range as indicated by \p kind.
885
+ bool isInterestingUserOfKind (SILInstruction *user, IsInterestingUser kind,
886
+ TypeTreeLeafTypeRange range) const {
887
+ auto *record = getInterestingUser (user);
888
+ if (!record)
889
+ return kind == IsInterestingUser::NonUser;
890
+
891
+ for (auto element : range.getRange ()) {
892
+ if (isInterestingUser (user, element) != kind)
893
+ return false ;
894
+ }
895
+ return true ;
864
896
}
865
897
866
898
unsigned getNumSubElements () const { return liveBlocks.getNumBitsToTrack (); }
@@ -886,10 +918,11 @@ class FieldSensitivePrunedLiveness {
886
918
// / argument must be copied.
887
919
void addInterestingUser (SILInstruction *user, TypeTreeLeafTypeRange range,
888
920
bool lifetimeEnding) {
889
- auto iterAndSuccess =
890
- users.insert ({user, InterestingUser (range, lifetimeEnding)});
891
- if (!iterAndSuccess.second )
892
- iterAndSuccess.first ->second &= lifetimeEnding;
921
+ auto iter = users.find (user);
922
+ if (iter == users.end ()) {
923
+ iter = users.insert ({user, InterestingUser (getNumSubElements ())}).first ;
924
+ }
925
+ iter->second .addUses (range, lifetimeEnding);
893
926
}
894
927
};
895
928
0 commit comments