File indexing completed on 2026-05-10 08:43:14
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #ifndef LLVM_ANALYSIS_MEMORYLOCATION_H
0016 #define LLVM_ANALYSIS_MEMORYLOCATION_H
0017
0018 #include "llvm/ADT/DenseMapInfo.h"
0019 #include "llvm/IR/Metadata.h"
0020 #include "llvm/Support/TypeSize.h"
0021
0022 #include <optional>
0023
0024 namespace llvm {
0025
0026 class CallBase;
0027 class Instruction;
0028 class LoadInst;
0029 class StoreInst;
0030 class MemTransferInst;
0031 class MemIntrinsic;
0032 class AtomicCmpXchgInst;
0033 class AtomicMemTransferInst;
0034 class AtomicMemIntrinsic;
0035 class AtomicRMWInst;
0036 class AnyMemTransferInst;
0037 class AnyMemIntrinsic;
0038 class TargetLibraryInfo;
0039 class VAArgInst;
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068 class LocationSize {
0069 enum : uint64_t {
0070 BeforeOrAfterPointer = ~uint64_t(0),
0071 ScalableBit = uint64_t(1) << 62,
0072 AfterPointer = (BeforeOrAfterPointer - 1) & ~ScalableBit,
0073 MapEmpty = BeforeOrAfterPointer - 2,
0074 MapTombstone = BeforeOrAfterPointer - 3,
0075 ImpreciseBit = uint64_t(1) << 63,
0076
0077
0078 MaxValue = (MapTombstone - 1) & ~(ImpreciseBit | ScalableBit),
0079 };
0080
0081 uint64_t Value;
0082
0083
0084
0085 enum DirectConstruction { Direct };
0086
0087 constexpr LocationSize(uint64_t Raw, DirectConstruction) : Value(Raw) {}
0088 constexpr LocationSize(uint64_t Raw, bool Scalable)
0089 : Value(Raw > MaxValue ? AfterPointer
0090 : Raw | (Scalable ? ScalableBit : uint64_t(0))) {}
0091
0092 static_assert(AfterPointer & ImpreciseBit,
0093 "AfterPointer is imprecise by definition.");
0094 static_assert(BeforeOrAfterPointer & ImpreciseBit,
0095 "BeforeOrAfterPointer is imprecise by definition.");
0096 static_assert(~(MaxValue & ScalableBit), "Max value don't have bit 62 set");
0097
0098 public:
0099
0100
0101
0102
0103
0104
0105 constexpr LocationSize(uint64_t Raw)
0106 : Value(Raw > MaxValue ? AfterPointer : Raw) {}
0107
0108 static LocationSize precise(uint64_t Value) {
0109 return LocationSize(Value, false );
0110 }
0111 static LocationSize precise(TypeSize Value) {
0112 return LocationSize(Value.getKnownMinValue(), Value.isScalable());
0113 }
0114
0115 static LocationSize upperBound(uint64_t Value) {
0116
0117 if (LLVM_UNLIKELY(Value == 0))
0118 return precise(0);
0119 if (LLVM_UNLIKELY(Value > MaxValue))
0120 return afterPointer();
0121 return LocationSize(Value | ImpreciseBit, Direct);
0122 }
0123 static LocationSize upperBound(TypeSize Value) {
0124 if (Value.isScalable())
0125 return afterPointer();
0126 return upperBound(Value.getFixedValue());
0127 }
0128
0129
0130
0131 constexpr static LocationSize afterPointer() {
0132 return LocationSize(AfterPointer, Direct);
0133 }
0134
0135
0136
0137 constexpr static LocationSize beforeOrAfterPointer() {
0138 return LocationSize(BeforeOrAfterPointer, Direct);
0139 }
0140
0141
0142 constexpr static LocationSize mapTombstone() {
0143 return LocationSize(MapTombstone, Direct);
0144 }
0145 constexpr static LocationSize mapEmpty() {
0146 return LocationSize(MapEmpty, Direct);
0147 }
0148
0149
0150
0151 LocationSize unionWith(LocationSize Other) const {
0152 if (Other == *this)
0153 return *this;
0154
0155 if (Value == BeforeOrAfterPointer || Other.Value == BeforeOrAfterPointer)
0156 return beforeOrAfterPointer();
0157 if (Value == AfterPointer || Other.Value == AfterPointer)
0158 return afterPointer();
0159 if (isScalable() || Other.isScalable())
0160 return afterPointer();
0161
0162 return upperBound(std::max(getValue(), Other.getValue()));
0163 }
0164
0165 bool hasValue() const {
0166 return Value != AfterPointer && Value != BeforeOrAfterPointer;
0167 }
0168 bool isScalable() const { return (Value & ScalableBit); }
0169
0170 TypeSize getValue() const {
0171 assert(hasValue() && "Getting value from an unknown LocationSize!");
0172 assert((Value & ~(ImpreciseBit | ScalableBit)) < MaxValue &&
0173 "Scalable bit of value should be masked");
0174 return {Value & ~(ImpreciseBit | ScalableBit), isScalable()};
0175 }
0176
0177
0178
0179 bool isPrecise() const { return (Value & ImpreciseBit) == 0; }
0180
0181
0182 bool isZero() const {
0183 return hasValue() && getValue().getKnownMinValue() == 0;
0184 }
0185
0186
0187 bool mayBeBeforePointer() const { return Value == BeforeOrAfterPointer; }
0188
0189 bool operator==(const LocationSize &Other) const {
0190 return Value == Other.Value;
0191 }
0192
0193 bool operator==(const TypeSize &Other) const {
0194 return hasValue() && getValue() == Other;
0195 }
0196
0197 bool operator!=(const LocationSize &Other) const { return !(*this == Other); }
0198
0199 bool operator!=(const TypeSize &Other) const { return !(*this == Other); }
0200
0201
0202
0203
0204
0205
0206 void print(raw_ostream &OS) const;
0207
0208
0209
0210 uint64_t toRaw() const { return Value; }
0211 };
0212
0213 inline raw_ostream &operator<<(raw_ostream &OS, LocationSize Size) {
0214 Size.print(OS);
0215 return OS;
0216 }
0217
0218
0219
0220
0221
0222
0223
0224
0225
0226
0227 class MemoryLocation {
0228 public:
0229
0230
0231
0232 enum : uint64_t { UnknownSize = ~UINT64_C(0) };
0233
0234
0235 const Value *Ptr;
0236
0237
0238
0239
0240
0241
0242
0243
0244 LocationSize Size;
0245
0246
0247
0248 AAMDNodes AATags;
0249
0250 void print(raw_ostream &OS) const { OS << *Ptr << " " << Size << "\n"; }
0251
0252
0253
0254 static MemoryLocation get(const LoadInst *LI);
0255 static MemoryLocation get(const StoreInst *SI);
0256 static MemoryLocation get(const VAArgInst *VI);
0257 static MemoryLocation get(const AtomicCmpXchgInst *CXI);
0258 static MemoryLocation get(const AtomicRMWInst *RMWI);
0259 static MemoryLocation get(const Instruction *Inst) {
0260 return *MemoryLocation::getOrNone(Inst);
0261 }
0262 static std::optional<MemoryLocation> getOrNone(const Instruction *Inst);
0263
0264
0265 static MemoryLocation getForSource(const MemTransferInst *MTI);
0266 static MemoryLocation getForSource(const AtomicMemTransferInst *MTI);
0267 static MemoryLocation getForSource(const AnyMemTransferInst *MTI);
0268
0269
0270
0271 static MemoryLocation getForDest(const MemIntrinsic *MI);
0272 static MemoryLocation getForDest(const AtomicMemIntrinsic *MI);
0273 static MemoryLocation getForDest(const AnyMemIntrinsic *MI);
0274 static std::optional<MemoryLocation> getForDest(const CallBase *CI,
0275 const TargetLibraryInfo &TLI);
0276
0277
0278 static MemoryLocation getForArgument(const CallBase *Call, unsigned ArgIdx,
0279 const TargetLibraryInfo *TLI);
0280 static MemoryLocation getForArgument(const CallBase *Call, unsigned ArgIdx,
0281 const TargetLibraryInfo &TLI) {
0282 return getForArgument(Call, ArgIdx, &TLI);
0283 }
0284
0285
0286
0287 static MemoryLocation getAfter(const Value *Ptr,
0288 const AAMDNodes &AATags = AAMDNodes()) {
0289 return MemoryLocation(Ptr, LocationSize::afterPointer(), AATags);
0290 }
0291
0292
0293
0294 static MemoryLocation
0295 getBeforeOrAfter(const Value *Ptr, const AAMDNodes &AATags = AAMDNodes()) {
0296 return MemoryLocation(Ptr, LocationSize::beforeOrAfterPointer(), AATags);
0297 }
0298
0299 MemoryLocation() : Ptr(nullptr), Size(LocationSize::beforeOrAfterPointer()) {}
0300
0301 explicit MemoryLocation(const Value *Ptr, LocationSize Size,
0302 const AAMDNodes &AATags = AAMDNodes())
0303 : Ptr(Ptr), Size(Size), AATags(AATags) {}
0304
0305 MemoryLocation getWithNewPtr(const Value *NewPtr) const {
0306 MemoryLocation Copy(*this);
0307 Copy.Ptr = NewPtr;
0308 return Copy;
0309 }
0310
0311 MemoryLocation getWithNewSize(LocationSize NewSize) const {
0312 MemoryLocation Copy(*this);
0313 Copy.Size = NewSize;
0314 return Copy;
0315 }
0316
0317 MemoryLocation getWithoutAATags() const {
0318 MemoryLocation Copy(*this);
0319 Copy.AATags = AAMDNodes();
0320 return Copy;
0321 }
0322
0323 bool operator==(const MemoryLocation &Other) const {
0324 return Ptr == Other.Ptr && Size == Other.Size && AATags == Other.AATags;
0325 }
0326 };
0327
0328
0329 template <> struct DenseMapInfo<LocationSize> {
0330 static inline LocationSize getEmptyKey() { return LocationSize::mapEmpty(); }
0331 static inline LocationSize getTombstoneKey() {
0332 return LocationSize::mapTombstone();
0333 }
0334 static unsigned getHashValue(const LocationSize &Val) {
0335 return DenseMapInfo<uint64_t>::getHashValue(Val.toRaw());
0336 }
0337 static bool isEqual(const LocationSize &LHS, const LocationSize &RHS) {
0338 return LHS == RHS;
0339 }
0340 };
0341
0342 template <> struct DenseMapInfo<MemoryLocation> {
0343 static inline MemoryLocation getEmptyKey() {
0344 return MemoryLocation(DenseMapInfo<const Value *>::getEmptyKey(),
0345 DenseMapInfo<LocationSize>::getEmptyKey());
0346 }
0347 static inline MemoryLocation getTombstoneKey() {
0348 return MemoryLocation(DenseMapInfo<const Value *>::getTombstoneKey(),
0349 DenseMapInfo<LocationSize>::getTombstoneKey());
0350 }
0351 static unsigned getHashValue(const MemoryLocation &Val) {
0352 return DenseMapInfo<const Value *>::getHashValue(Val.Ptr) ^
0353 DenseMapInfo<LocationSize>::getHashValue(Val.Size) ^
0354 DenseMapInfo<AAMDNodes>::getHashValue(Val.AATags);
0355 }
0356 static bool isEqual(const MemoryLocation &LHS, const MemoryLocation &RHS) {
0357 return LHS == RHS;
0358 }
0359 };
0360 }
0361
0362 #endif