@@ -64,16 +64,19 @@ class Value;
6464//
6565// If asked to represent a pathologically large value, this will degrade to
6666// std::nullopt.
67+ // Store Scalable information in bit 62 of Value. Scalable information is
68+ // required to do Alias Analysis on Scalable quantities
6769class LocationSize {
6870 enum : uint64_t {
6971 BeforeOrAfterPointer = ~uint64_t (0 ),
70- AfterPointer = BeforeOrAfterPointer - 1 ,
72+ ScalableBit = uint64_t (1 ) << 62 ,
73+ AfterPointer = (BeforeOrAfterPointer - 1 ) & ~ScalableBit,
7174 MapEmpty = BeforeOrAfterPointer - 2 ,
7275 MapTombstone = BeforeOrAfterPointer - 3 ,
7376 ImpreciseBit = uint64_t (1 ) << 63 ,
7477
7578 // The maximum value we can represent without falling back to 'unknown'.
76- MaxValue = (MapTombstone - 1 ) & ~ImpreciseBit,
79+ MaxValue = (MapTombstone - 1 ) & ~( ImpreciseBit | ScalableBit) ,
7780 };
7881
7982 uint64_t Value;
@@ -82,12 +85,16 @@ class LocationSize {
8285 // public LocationSize ctor goes away.
8386 enum DirectConstruction { Direct };
8487
85- constexpr LocationSize (uint64_t Raw, DirectConstruction): Value(Raw) {}
88+ constexpr LocationSize (uint64_t Raw, DirectConstruction) : Value(Raw) {}
89+ constexpr LocationSize (uint64_t Raw, bool Scalable)
90+ : Value(Raw > MaxValue ? AfterPointer
91+ : Raw | (Scalable ? ScalableBit : uint64_t (0 ))) {}
8692
8793 static_assert (AfterPointer & ImpreciseBit,
8894 " AfterPointer is imprecise by definition." );
8995 static_assert (BeforeOrAfterPointer & ImpreciseBit,
9096 " BeforeOrAfterPointer is imprecise by definition." );
97+ static_assert (~(MaxValue & ScalableBit), " Max value don't have bit 62 set" );
9198
9299public:
93100 // FIXME: Migrate all users to construct via either `precise` or `upperBound`,
@@ -98,12 +105,12 @@ class LocationSize {
98105 // this assumes the provided value is precise.
99106 constexpr LocationSize (uint64_t Raw)
100107 : Value(Raw > MaxValue ? AfterPointer : Raw) {}
101-
102- static LocationSize precise (uint64_t Value) { return LocationSize (Value); }
108+ // Create non-scalable LocationSize
109+ static LocationSize precise (uint64_t Value) {
110+ return LocationSize (Value, false /* Scalable*/ );
111+ }
103112 static LocationSize precise (TypeSize Value) {
104- if (Value.isScalable ())
105- return afterPointer ();
106- return precise (Value.getFixedValue ());
113+ return LocationSize (Value.getKnownMinValue (), Value.isScalable ());
107114 }
108115
109116 static LocationSize upperBound (uint64_t Value) {
@@ -150,26 +157,32 @@ class LocationSize {
150157 return beforeOrAfterPointer ();
151158 if (Value == AfterPointer || Other.Value == AfterPointer)
152159 return afterPointer ();
160+ if (isScalable () || Other.isScalable ())
161+ return afterPointer ();
153162
154163 return upperBound (std::max (getValue (), Other.getValue ()));
155164 }
156165
157166 bool hasValue () const {
158167 return Value != AfterPointer && Value != BeforeOrAfterPointer;
159168 }
160- uint64_t getValue () const {
169+ bool isScalable () const { return (Value & ScalableBit); }
170+
171+ TypeSize getValue () const {
161172 assert (hasValue () && " Getting value from an unknown LocationSize!" );
162- return Value & ~ImpreciseBit;
173+ assert ((Value & ~(ImpreciseBit | ScalableBit)) < MaxValue &&
174+ " Scalable bit of value should be masked" );
175+ return {Value & ~(ImpreciseBit | ScalableBit), isScalable ()};
163176 }
164177
165178 // Returns whether or not this value is precise. Note that if a value is
166179 // precise, it's guaranteed to not be unknown.
167- bool isPrecise () const {
168- return (Value & ImpreciseBit) == 0 ;
169- }
180+ bool isPrecise () const { return (Value & ImpreciseBit) == 0 ; }
170181
171182 // Convenience method to check if this LocationSize's value is 0.
172- bool isZero () const { return hasValue () && getValue () == 0 ; }
183+ bool isZero () const {
184+ return hasValue () && getValue ().getKnownMinValue () == 0 ;
185+ }
173186
174187 // / Whether accesses before the base pointer are possible.
175188 bool mayBeBeforePointer () const { return Value == BeforeOrAfterPointer; }
@@ -178,9 +191,7 @@ class LocationSize {
178191 return Value == Other.Value ;
179192 }
180193
181- bool operator !=(const LocationSize &Other) const {
182- return !(*this == Other);
183- }
194+ bool operator !=(const LocationSize &Other) const { return !(*this == Other); }
184195
185196 // Ordering operators are not provided, since it's unclear if there's only one
186197 // reasonable way to compare:
@@ -317,9 +328,7 @@ class MemoryLocation {
317328
318329// Specialize DenseMapInfo.
319330template <> struct DenseMapInfo <LocationSize> {
320- static inline LocationSize getEmptyKey () {
321- return LocationSize::mapEmpty ();
322- }
331+ static inline LocationSize getEmptyKey () { return LocationSize::mapEmpty (); }
323332 static inline LocationSize getTombstoneKey () {
324333 return LocationSize::mapTombstone ();
325334 }
@@ -349,6 +358,6 @@ template <> struct DenseMapInfo<MemoryLocation> {
349358 return LHS == RHS;
350359 }
351360};
352- }
361+ } // namespace llvm
353362
354363#endif
0 commit comments