Skip to content

Commit eaed8a7

Browse files
committed
[Analysis] Add Scalable field in MemoryLocation.h
This is the first of a series of patch to improve Alias Analysis on Scalable quantities. Keep Scalable information from TypeSize which will be used in Alias Analysis.
1 parent 98c6c98 commit eaed8a7

File tree

3 files changed

+44
-20
lines changed

3 files changed

+44
-20
lines changed

llvm/include/llvm/Analysis/MemoryLocation.h

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -67,13 +67,14 @@ class Value;
6767
class LocationSize {
6868
enum : uint64_t {
6969
BeforeOrAfterPointer = ~uint64_t(0),
70-
AfterPointer = BeforeOrAfterPointer - 1,
71-
MapEmpty = BeforeOrAfterPointer - 2,
72-
MapTombstone = BeforeOrAfterPointer - 3,
70+
ScalableBit = uint64_t(1) << 62,
71+
AfterPointer = (BeforeOrAfterPointer - 1) & ~ScalableBit,
72+
MapEmpty = (BeforeOrAfterPointer - 2) & ~ScalableBit,
73+
MapTombstone = (BeforeOrAfterPointer - 3) & ~ScalableBit,
7374
ImpreciseBit = uint64_t(1) << 63,
7475

7576
// The maximum value we can represent without falling back to 'unknown'.
76-
MaxValue = (MapTombstone - 1) & ~ImpreciseBit,
77+
MaxValue = (MapTombstone - 1) & ~(ImpreciseBit | ScalableBit),
7778
};
7879

7980
uint64_t Value;
@@ -88,6 +89,8 @@ class LocationSize {
8889
"AfterPointer is imprecise by definition.");
8990
static_assert(BeforeOrAfterPointer & ImpreciseBit,
9091
"BeforeOrAfterPointer is imprecise by definition.");
92+
static_assert(~(MaxValue & ScalableBit),
93+
"Max value don't have bit 62 set");
9194

9295
public:
9396
// FIXME: Migrate all users to construct via either `precise` or `upperBound`,
@@ -98,12 +101,16 @@ class LocationSize {
98101
// this assumes the provided value is precise.
99102
constexpr LocationSize(uint64_t Raw)
100103
: Value(Raw > MaxValue ? AfterPointer : Raw) {}
104+
constexpr LocationSize(uint64_t Raw, bool Scalable)
105+
: Value(Raw > MaxValue ? AfterPointer : Raw | (Scalable ? ScalableBit : uint64_t(0)) ) {}
101106

102-
static LocationSize precise(uint64_t Value) { return LocationSize(Value); }
107+
// Make construction of LocationSize that takes in uint64_t to set Scalable
108+
// information as false
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) {
@@ -159,7 +166,8 @@ class LocationSize {
159166
}
160167
uint64_t getValue() const {
161168
assert(hasValue() && "Getting value from an unknown LocationSize!");
162-
return Value & ~ImpreciseBit;
169+
assert((Value & ~(ImpreciseBit | ScalableBit)) < MaxValue && "Scalable bit of value should be masked");
170+
return Value & ~(ImpreciseBit | ScalableBit);
163171
}
164172

165173
// Returns whether or not this value is precise. Note that if a value is
@@ -168,6 +176,8 @@ class LocationSize {
168176
return (Value & ImpreciseBit) == 0;
169177
}
170178

179+
bool isScalable() const { return (Value & ScalableBit); }
180+
171181
// Convenience method to check if this LocationSize's value is 0.
172182
bool isZero() const { return hasValue() && getValue() == 0; }
173183

@@ -292,6 +302,10 @@ class MemoryLocation {
292302
const AAMDNodes &AATags = AAMDNodes())
293303
: Ptr(Ptr), Size(Size), AATags(AATags) {}
294304

305+
explicit MemoryLocation(const Value *Ptr, uint64_t Size,
306+
const AAMDNodes &AATags = AAMDNodes())
307+
: Ptr(Ptr), Size(Size, false), AATags(AATags) {}
308+
295309
MemoryLocation getWithNewPtr(const Value *NewPtr) const {
296310
MemoryLocation Copy(*this);
297311
Copy.Ptr = NewPtr;

llvm/lib/Analysis/BasicAliasAnalysis.cpp

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ bool BasicAAResult::invalidate(Function &Fn, const PreservedAnalyses &PA,
101101
//===----------------------------------------------------------------------===//
102102

103103
/// Returns the size of the object specified by V or UnknownSize if unknown.
104-
static uint64_t getObjectSize(const Value *V, const DataLayout &DL,
104+
static LocationSize getObjectSize(const Value *V, const DataLayout &DL,
105105
const TargetLibraryInfo &TLI,
106106
bool NullIsValidLoc,
107107
bool RoundToAlign = false) {
@@ -110,13 +110,13 @@ static uint64_t getObjectSize(const Value *V, const DataLayout &DL,
110110
Opts.RoundToAlign = RoundToAlign;
111111
Opts.NullIsUnknownSize = NullIsValidLoc;
112112
if (getObjectSize(V, Size, DL, &TLI, Opts))
113-
return Size;
114-
return MemoryLocation::UnknownSize;
113+
return LocationSize(Size, DL.getTypeAllocSize(V->getType()).isScalable());
114+
return LocationSize(MemoryLocation::UnknownSize);
115115
}
116116

117117
/// Returns true if we can prove that the object specified by V is smaller than
118118
/// Size.
119-
static bool isObjectSmallerThan(const Value *V, uint64_t Size,
119+
static bool isObjectSmallerThan(const Value *V, LocationSize Size,
120120
const DataLayout &DL,
121121
const TargetLibraryInfo &TLI,
122122
bool NullIsValidLoc) {
@@ -151,16 +151,20 @@ static bool isObjectSmallerThan(const Value *V, uint64_t Size,
151151

152152
// This function needs to use the aligned object size because we allow
153153
// reads a bit past the end given sufficient alignment.
154-
uint64_t ObjectSize = getObjectSize(V, DL, TLI, NullIsValidLoc,
154+
LocationSize ObjectSize = getObjectSize(V, DL, TLI, NullIsValidLoc,
155155
/*RoundToAlign*/ true);
156156

157-
return ObjectSize != MemoryLocation::UnknownSize && ObjectSize < Size;
157+
// Bail on comparing V and Size if their scalability differs
158+
if (ObjectSize.isScalable() != Size.isScalable())
159+
return false;
160+
161+
return ObjectSize != MemoryLocation::UnknownSize && ObjectSize.getValue() < Size.getValue();
158162
}
159163

160164
/// Return the minimal extent from \p V to the end of the underlying object,
161165
/// assuming the result is used in an aliasing query. E.g., we do use the query
162166
/// location size and the fact that null pointers cannot alias here.
163-
static uint64_t getMinimalExtentFrom(const Value &V,
167+
static LocationSize getMinimalExtentFrom(const Value &V,
164168
const LocationSize &LocSize,
165169
const DataLayout &DL,
166170
bool NullIsValidLoc) {
@@ -176,14 +180,14 @@ static uint64_t getMinimalExtentFrom(const Value &V,
176180
// accessed, thus valid.
177181
if (LocSize.isPrecise())
178182
DerefBytes = std::max(DerefBytes, LocSize.getValue());
179-
return DerefBytes;
183+
return LocationSize(DerefBytes, LocSize.isScalable());
180184
}
181185

182186
/// Returns true if we can prove that the object specified by V has size Size.
183187
static bool isObjectSize(const Value *V, uint64_t Size, const DataLayout &DL,
184188
const TargetLibraryInfo &TLI, bool NullIsValidLoc) {
185-
uint64_t ObjectSize = getObjectSize(V, DL, TLI, NullIsValidLoc);
186-
return ObjectSize != MemoryLocation::UnknownSize && ObjectSize == Size;
189+
LocationSize ObjectSize = getObjectSize(V, DL, TLI, NullIsValidLoc);
190+
return ObjectSize != MemoryLocation::UnknownSize && ObjectSize.getValue() == Size;
187191
}
188192

189193
//===----------------------------------------------------------------------===//
@@ -1087,6 +1091,10 @@ AliasResult BasicAAResult::aliasGEP(
10871091
return BaseAlias;
10881092
}
10891093

1094+
// Bail on analysing scalable LocationSize
1095+
if (V1Size.isScalable() || V2Size.isScalable())
1096+
return AliasResult::MayAlias;
1097+
10901098
// If there is a constant difference between the pointers, but the difference
10911099
// is less than the size of the associated memory object, then we know
10921100
// that the objects are partially overlapping. If the difference is

llvm/lib/Analysis/MemoryLocation.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,10 @@ void LocationSize::print(raw_ostream &OS) const {
2727
OS << "mapEmpty";
2828
else if (*this == mapTombstone())
2929
OS << "mapTombstone";
30-
else if (isPrecise())
30+
else if (isPrecise() & !isScalable())
3131
OS << "precise(" << getValue() << ')';
32+
else if (isPrecise() & isScalable())
33+
OS << "precise(vscale x " << getValue() << ')';
3234
else
3335
OS << "upperBound(" << getValue() << ')';
3436
}

0 commit comments

Comments
 (0)