@@ -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,59 @@ 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) : liveBits(bitCount), consumingBits(bitCount) {}
676
683
677
- InterestingUser &operator &=(bool otherValue) {
678
- isConsuming &= otherValue;
679
- return *this ;
684
+ InterestingUser (unsigned bitCount, TypeTreeLeafTypeRange range,
685
+ bool lifetimeEnding)
686
+ : liveBits(bitCount), consumingBits(bitCount) {
687
+ addUses (range, lifetimeEnding);
688
+ }
689
+
690
+ // / Record that the instruction uses the bits of the value in \p range.
691
+ void addUses (TypeTreeLeafTypeRange range, bool lifetimeEnding) {
692
+ range.setBits (liveBits);
693
+ if (lifetimeEnding) {
694
+ range.setBits (consumingBits);
695
+ }
696
+ }
697
+
698
+ // / Populates the provided vector with contiguous ranges of bits which are
699
+ // / users of the same sort.
700
+ void getContiguousRanges (
701
+ SmallVectorImpl<std::pair<TypeTreeLeafTypeRange, IsInterestingUser>>
702
+ &ranges) const {
703
+ if (liveBits.size () == 0 )
704
+ return ;
705
+
706
+ assert (ranges.empty ());
707
+ Optional<std::pair<unsigned , IsInterestingUser>> current = llvm::None;
708
+ for (unsigned bit = 0 , size = liveBits.size (); bit < size; ++bit) {
709
+ auto interesting = isInterestingUser (bit);
710
+ if (!current) {
711
+ current = {bit, interesting};
712
+ continue ;
713
+ }
714
+ if (current->second != interesting) {
715
+ ranges.push_back (
716
+ {TypeTreeLeafTypeRange (current->first , bit), current->second });
717
+ current = {bit, interesting};
718
+ }
719
+ }
720
+ ranges.push_back ({TypeTreeLeafTypeRange (current->first , liveBits.size ()),
721
+ current->second });
722
+ }
723
+
724
+ IsInterestingUser isInterestingUser (unsigned element) const {
725
+ if (!liveBits.test (element))
726
+ return NonUser;
727
+ return consumingBits.test (element) ? LifetimeEndingUse
728
+ : NonLifetimeEndingUse;
680
729
}
681
730
};
682
731
@@ -758,42 +807,6 @@ class FieldSensitivePrunedLiveness {
758
807
return llvm::make_range (users.begin (), users.end ());
759
808
}
760
809
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
810
using UserBlockRange = TransformRange<
798
811
UserRange, function_ref<SILBasicBlock *(
799
812
const std::pair<SILInstruction *, InterestingUser> &)>>;
@@ -848,19 +861,39 @@ class FieldSensitivePrunedLiveness {
848
861
SmallBitVector &liveOutBits,
849
862
SmallBitVector &deadBits) const ;
850
863
851
- enum IsInterestingUser { NonUser, NonLifetimeEndingUse, LifetimeEndingUse };
864
+ // / If \p user has had uses recored, return a pointer to the InterestingUser
865
+ // / where they've been recorded.
866
+ InterestingUser const *getInterestingUser (SILInstruction *user) const {
867
+ auto iter = users.find (user);
868
+ if (iter == users.end ())
869
+ return nullptr ;
870
+ return &iter->second ;
871
+ }
852
872
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 {
873
+ // / How \p user uses the field at \p element.
874
+ IsInterestingUser isInterestingUser (SILInstruction *user,
875
+ unsigned element) const {
857
876
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 };
877
+ auto *record = getInterestingUser (user);
878
+ if (!record)
879
+ return NonUser;
880
+ return record->isInterestingUser (element);
881
+ }
882
+
883
+ // / Whether \p user uses the fields in \p range as indicated by \p kind.
884
+ bool
885
+ isInterestingUserOfKind (SILInstruction *user,
886
+ IsInterestingUser kind,
887
+ TypeTreeLeafTypeRange range) const {
888
+ auto *record = getInterestingUser (user);
889
+ if (!record)
890
+ return kind == IsInterestingUser::NonUser;
891
+
892
+ for (auto element : range.getRange ()) {
893
+ if (isInterestingUser (user, element) != kind)
894
+ return false ;
895
+ }
896
+ return true ;
864
897
}
865
898
866
899
unsigned getNumSubElements () const { return liveBlocks.getNumBitsToTrack (); }
@@ -886,10 +919,13 @@ class FieldSensitivePrunedLiveness {
886
919
// / argument must be copied.
887
920
void addInterestingUser (SILInstruction *user, TypeTreeLeafTypeRange range,
888
921
bool lifetimeEnding) {
889
- auto iterAndSuccess =
890
- users.insert ({user, InterestingUser (range, lifetimeEnding)});
891
- if (!iterAndSuccess.second )
892
- iterAndSuccess.first ->second &= lifetimeEnding;
922
+ auto iter = users.find (user);
923
+ if (iter == users.end ()) {
924
+ iter = users
925
+ .insert ({user, InterestingUser (getNumSubElements ())})
926
+ .first ;
927
+ }
928
+ iter->second .addUses (range, lifetimeEnding);
893
929
}
894
930
};
895
931
0 commit comments