forked from OSchip/llvm-project
[AA] Split up LocationSize::unknown()
Currently, we have some confusion in the codebase regarding the meaning of LocationSize::unknown(): Some parts (including most of BasicAA) assume that LocationSize::unknown() only allows accesses after the base pointer. Some parts (various callers of AA) assume that LocationSize::unknown() allows accesses both before and after the base pointer (but within the underlying object). This patch splits up LocationSize::unknown() into LocationSize::afterPointer() and LocationSize::beforeOrAfterPointer() to make this completely unambiguous. I tried my best to determine which one is appropriate for all the existing uses. The test changes in cs-cs.ll in particular illustrate a previously clearly incorrect AA result: We were effectively assuming that argmemonly functions were only allowed to access their arguments after the passed pointer, but not before it. I'm pretty sure that this was not intentional, and it's certainly not specified by LangRef that way. Differential Revision: https://reviews.llvm.org/D91649
This commit is contained in:
parent
668da8c361
commit
4df8efce80
|
@ -407,7 +407,8 @@ public:
|
|||
|
||||
/// A convenience wrapper around the primary \c alias interface.
|
||||
AliasResult alias(const Value *V1, const Value *V2) {
|
||||
return alias(V1, LocationSize::unknown(), V2, LocationSize::unknown());
|
||||
return alias(MemoryLocation::getBeforeOrAfter(V1),
|
||||
MemoryLocation::getBeforeOrAfter(V2));
|
||||
}
|
||||
|
||||
/// A trivial helper function to check to see if the specified pointers are
|
||||
|
@ -424,8 +425,8 @@ public:
|
|||
|
||||
/// A convenience wrapper around the \c isNoAlias helper interface.
|
||||
bool isNoAlias(const Value *V1, const Value *V2) {
|
||||
return isNoAlias(MemoryLocation(V1, LocationSize::unknown()),
|
||||
MemoryLocation(V2, LocationSize::unknown()));
|
||||
return isNoAlias(MemoryLocation::getBeforeOrAfter(V1),
|
||||
MemoryLocation::getBeforeOrAfter(V2));
|
||||
}
|
||||
|
||||
/// A trivial helper function to check to see if the specified pointers are
|
||||
|
@ -447,8 +448,7 @@ public:
|
|||
/// A convenience wrapper around the primary \c pointsToConstantMemory
|
||||
/// interface.
|
||||
bool pointsToConstantMemory(const Value *P, bool OrLocal = false) {
|
||||
return pointsToConstantMemory(MemoryLocation(P, LocationSize::unknown()),
|
||||
OrLocal);
|
||||
return pointsToConstantMemory(MemoryLocation::getBeforeOrAfter(P), OrLocal);
|
||||
}
|
||||
|
||||
/// @}
|
||||
|
|
|
@ -302,7 +302,7 @@ private:
|
|||
/// The maximum size of the dereferences of the pointer.
|
||||
///
|
||||
/// May be UnknownSize if the sizes are unknown.
|
||||
LocationSize Size = LocationSize::unknown();
|
||||
LocationSize Size = LocationSize::afterPointer();
|
||||
/// The AA tags associated with dereferences of the pointer.
|
||||
///
|
||||
/// The members may be null if there are no tags or conflicting tags.
|
||||
|
|
|
@ -64,10 +64,11 @@ class VAArgInst;
|
|||
// None.
|
||||
class LocationSize {
|
||||
enum : uint64_t {
|
||||
Unknown = ~uint64_t(0),
|
||||
BeforeOrAfterPointer = ~uint64_t(0),
|
||||
AfterPointer = BeforeOrAfterPointer - 1,
|
||||
MapEmpty = BeforeOrAfterPointer - 2,
|
||||
MapTombstone = BeforeOrAfterPointer - 3,
|
||||
ImpreciseBit = uint64_t(1) << 63,
|
||||
MapEmpty = Unknown - 1,
|
||||
MapTombstone = Unknown - 2,
|
||||
|
||||
// The maximum value we can represent without falling back to 'unknown'.
|
||||
MaxValue = (MapTombstone - 1) & ~ImpreciseBit,
|
||||
|
@ -81,7 +82,11 @@ class LocationSize {
|
|||
|
||||
constexpr LocationSize(uint64_t Raw, DirectConstruction): Value(Raw) {}
|
||||
|
||||
static_assert(Unknown & ImpreciseBit, "Unknown is imprecise by definition.");
|
||||
static_assert(AfterPointer & ImpreciseBit,
|
||||
"AfterPointer is imprecise by definition.");
|
||||
static_assert(BeforeOrAfterPointer & ImpreciseBit,
|
||||
"BeforeOrAfterPointer is imprecise by definition.");
|
||||
|
||||
public:
|
||||
// FIXME: Migrate all users to construct via either `precise` or `upperBound`,
|
||||
// to make it more obvious at the callsite the kind of size that they're
|
||||
|
@ -90,12 +95,12 @@ public:
|
|||
// Since the overwhelming majority of users of this provide precise values,
|
||||
// this assumes the provided value is precise.
|
||||
constexpr LocationSize(uint64_t Raw)
|
||||
: Value(Raw > MaxValue ? Unknown : Raw) {}
|
||||
: Value(Raw > MaxValue ? AfterPointer : Raw) {}
|
||||
|
||||
static LocationSize precise(uint64_t Value) { return LocationSize(Value); }
|
||||
static LocationSize precise(TypeSize Value) {
|
||||
if (Value.isScalable())
|
||||
return unknown();
|
||||
return afterPointer();
|
||||
return precise(Value.getFixedSize());
|
||||
}
|
||||
|
||||
|
@ -104,17 +109,25 @@ public:
|
|||
if (LLVM_UNLIKELY(Value == 0))
|
||||
return precise(0);
|
||||
if (LLVM_UNLIKELY(Value > MaxValue))
|
||||
return unknown();
|
||||
return afterPointer();
|
||||
return LocationSize(Value | ImpreciseBit, Direct);
|
||||
}
|
||||
static LocationSize upperBound(TypeSize Value) {
|
||||
if (Value.isScalable())
|
||||
return unknown();
|
||||
return afterPointer();
|
||||
return upperBound(Value.getFixedSize());
|
||||
}
|
||||
|
||||
constexpr static LocationSize unknown() {
|
||||
return LocationSize(Unknown, Direct);
|
||||
/// Any location after the base pointer (but still within the underlying
|
||||
/// object).
|
||||
constexpr static LocationSize afterPointer() {
|
||||
return LocationSize(AfterPointer, Direct);
|
||||
}
|
||||
|
||||
/// Any location before or after the base pointer (but still within the
|
||||
/// underlying object).
|
||||
constexpr static LocationSize beforeOrAfterPointer() {
|
||||
return LocationSize(BeforeOrAfterPointer, Direct);
|
||||
}
|
||||
|
||||
// Sentinel values, generally used for maps.
|
||||
|
@ -131,20 +144,24 @@ public:
|
|||
if (Other == *this)
|
||||
return *this;
|
||||
|
||||
if (!hasValue() || !Other.hasValue())
|
||||
return unknown();
|
||||
if (Value == BeforeOrAfterPointer || Other.Value == BeforeOrAfterPointer)
|
||||
return beforeOrAfterPointer();
|
||||
if (Value == AfterPointer || Other.Value == AfterPointer)
|
||||
return afterPointer();
|
||||
|
||||
return upperBound(std::max(getValue(), Other.getValue()));
|
||||
}
|
||||
|
||||
bool hasValue() const { return Value != Unknown; }
|
||||
bool hasValue() const {
|
||||
return Value != AfterPointer && Value != BeforeOrAfterPointer;
|
||||
}
|
||||
uint64_t getValue() const {
|
||||
assert(hasValue() && "Getting value from an unknown LocationSize!");
|
||||
return Value & ~ImpreciseBit;
|
||||
}
|
||||
|
||||
// Returns whether or not this value is precise. Note that if a value is
|
||||
// precise, it's guaranteed to not be `unknown()`.
|
||||
// precise, it's guaranteed to not be unknown.
|
||||
bool isPrecise() const {
|
||||
return (Value & ImpreciseBit) == 0;
|
||||
}
|
||||
|
@ -152,6 +169,9 @@ public:
|
|||
// Convenience method to check if this LocationSize's value is 0.
|
||||
bool isZero() const { return hasValue() && getValue() == 0; }
|
||||
|
||||
/// Whether accesses before the base pointer are possible.
|
||||
bool mayBeBeforePointer() const { return Value == BeforeOrAfterPointer; }
|
||||
|
||||
bool operator==(const LocationSize &Other) const {
|
||||
return Value == Other.Value;
|
||||
}
|
||||
|
@ -242,13 +262,28 @@ public:
|
|||
return getForArgument(Call, ArgIdx, &TLI);
|
||||
}
|
||||
|
||||
/// Return a location that may access any location after Ptr, while remaining
|
||||
/// within the underlying object.
|
||||
static MemoryLocation getAfter(const Value *Ptr,
|
||||
const AAMDNodes &AATags = AAMDNodes()) {
|
||||
return MemoryLocation(Ptr, LocationSize::afterPointer(), AATags);
|
||||
}
|
||||
|
||||
/// Return a location that may access any location before or after Ptr, while
|
||||
/// remaining within the underlying object.
|
||||
static MemoryLocation
|
||||
getBeforeOrAfter(const Value *Ptr, const AAMDNodes &AATags = AAMDNodes()) {
|
||||
return MemoryLocation(Ptr, LocationSize::beforeOrAfterPointer(), AATags);
|
||||
}
|
||||
|
||||
// Return the exact size if the exact size is known at compiletime,
|
||||
// otherwise return MemoryLocation::UnknownSize.
|
||||
static uint64_t getSizeOrUnknown(const TypeSize &T) {
|
||||
return T.isScalable() ? UnknownSize : T.getFixedSize();
|
||||
}
|
||||
|
||||
MemoryLocation() : Ptr(nullptr), Size(LocationSize::unknown()), AATags() {}
|
||||
MemoryLocation()
|
||||
: Ptr(nullptr), Size(LocationSize::beforeOrAfterPointer()), AATags() {}
|
||||
|
||||
explicit MemoryLocation(const Value *Ptr, LocationSize Size,
|
||||
const AAMDNodes &AATags = AAMDNodes())
|
||||
|
|
|
@ -1248,7 +1248,8 @@ private:
|
|||
// catch loop carried dependences.
|
||||
if (Location.Ptr &&
|
||||
!IsGuaranteedLoopInvariant(const_cast<Value *>(Location.Ptr)))
|
||||
CurrentPair.second = Location.getWithNewSize(LocationSize::unknown());
|
||||
CurrentPair.second =
|
||||
Location.getWithNewSize(LocationSize::beforeOrAfterPointer());
|
||||
PHITransAddr Translator(
|
||||
const_cast<Value *>(Location.Ptr),
|
||||
OriginalAccess->getBlock()->getModule()->getDataLayout(), nullptr);
|
||||
|
@ -1262,8 +1263,8 @@ private:
|
|||
|
||||
if (TransAddr &&
|
||||
!IsGuaranteedLoopInvariant(const_cast<Value *>(TransAddr)))
|
||||
CurrentPair.second =
|
||||
CurrentPair.second.getWithNewSize(LocationSize::unknown());
|
||||
CurrentPair.second = CurrentPair.second.getWithNewSize(
|
||||
LocationSize::beforeOrAfterPointer());
|
||||
|
||||
if (PerformedPhiTranslation)
|
||||
*PerformedPhiTranslation = true;
|
||||
|
|
|
@ -239,7 +239,7 @@ namespace {
|
|||
llvm::TargetLibraryInfo TLI(TLII);
|
||||
llvm::AliasAnalysis AA(TLI);
|
||||
llvm::AliasSetTracker X(AA);
|
||||
X.add(nullptr, llvm::LocationSize::unknown(),
|
||||
X.add(nullptr, llvm::LocationSize::beforeOrAfterPointer(),
|
||||
llvm::AAMDNodes()); // for -print-alias-sets
|
||||
(void) llvm::AreStatisticsEnabled();
|
||||
(void) llvm::sys::RunningOnValgrind();
|
||||
|
|
|
@ -140,13 +140,13 @@ void AAEvaluator::runInternal(Function &F, AAResults &AA) {
|
|||
// iterate over the worklist, and run the full (n^2)/2 disambiguations
|
||||
for (SetVector<Value *>::iterator I1 = Pointers.begin(), E = Pointers.end();
|
||||
I1 != E; ++I1) {
|
||||
auto I1Size = LocationSize::unknown();
|
||||
auto I1Size = LocationSize::afterPointer();
|
||||
Type *I1ElTy = cast<PointerType>((*I1)->getType())->getElementType();
|
||||
if (I1ElTy->isSized())
|
||||
I1Size = LocationSize::precise(DL.getTypeStoreSize(I1ElTy));
|
||||
|
||||
for (SetVector<Value *>::iterator I2 = Pointers.begin(); I2 != I1; ++I2) {
|
||||
auto I2Size = LocationSize::unknown();
|
||||
auto I2Size = LocationSize::afterPointer();
|
||||
Type *I2ElTy = cast<PointerType>((*I2)->getType())->getElementType();
|
||||
if (I2ElTy->isSized())
|
||||
I2Size = LocationSize::precise(DL.getTypeStoreSize(I2ElTy));
|
||||
|
@ -231,7 +231,7 @@ void AAEvaluator::runInternal(Function &F, AAResults &AA) {
|
|||
// Mod/ref alias analysis: compare all pairs of calls and values
|
||||
for (CallBase *Call : Calls) {
|
||||
for (auto Pointer : Pointers) {
|
||||
auto Size = LocationSize::unknown();
|
||||
auto Size = LocationSize::afterPointer();
|
||||
Type *ElTy = cast<PointerType>(Pointer->getType())->getElementType();
|
||||
if (ElTy->isSized())
|
||||
Size = LocationSize::precise(DL.getTypeStoreSize(ElTy));
|
||||
|
|
|
@ -671,8 +671,10 @@ void AliasSet::print(raw_ostream &OS) const {
|
|||
for (iterator I = begin(), E = end(); I != E; ++I) {
|
||||
if (I != begin()) OS << ", ";
|
||||
I.getPointer()->printAsOperand(OS << "(");
|
||||
if (I.getSize() == LocationSize::unknown())
|
||||
OS << ", unknown)";
|
||||
if (I.getSize() == LocationSize::afterPointer())
|
||||
OS << ", unknown after)";
|
||||
else if (I.getSize() == LocationSize::beforeOrAfterPointer())
|
||||
OS << ", unknown before-or-after)";
|
||||
else
|
||||
OS << ", " << I.getSize() << ")";
|
||||
}
|
||||
|
|
|
@ -877,8 +877,8 @@ ModRefInfo BasicAAResult::getModRefInfo(const CallBase *Call,
|
|||
// If this is a no-capture pointer argument, see if we can tell that it
|
||||
// is impossible to alias the pointer we're checking.
|
||||
AliasResult AR = getBestAAResults().alias(
|
||||
MemoryLocation(*CI, LocationSize::unknown()),
|
||||
MemoryLocation(Object, LocationSize::unknown()), AAQI);
|
||||
MemoryLocation::getBeforeOrAfter(*CI),
|
||||
MemoryLocation::getBeforeOrAfter(Object), AAQI);
|
||||
if (AR != MustAlias)
|
||||
IsMustAlias = false;
|
||||
// Operand doesn't alias 'Object', continue looking for other aliases
|
||||
|
@ -924,7 +924,7 @@ ModRefInfo BasicAAResult::getModRefInfo(const CallBase *Call,
|
|||
if (isMallocOrCallocLikeFn(Call, &TLI)) {
|
||||
// Be conservative if the accessed pointer may alias the allocation -
|
||||
// fallback to the generic handling below.
|
||||
if (getBestAAResults().alias(MemoryLocation(Call, LocationSize::unknown()),
|
||||
if (getBestAAResults().alias(MemoryLocation::getBeforeOrAfter(Call),
|
||||
Loc, AAQI) == NoAlias)
|
||||
return ModRefInfo::NoModRef;
|
||||
}
|
||||
|
@ -1245,9 +1245,9 @@ AliasResult BasicAAResult::aliasGEP(
|
|||
if (isGEPBaseAtNegativeOffset(GEP2, DecompGEP2, DecompGEP1, V1Size))
|
||||
return NoAlias;
|
||||
// Do the base pointers alias?
|
||||
AliasResult BaseAlias =
|
||||
aliasCheck(UnderlyingV1, LocationSize::unknown(), AAMDNodes(),
|
||||
UnderlyingV2, LocationSize::unknown(), AAMDNodes(), AAQI);
|
||||
AliasResult BaseAlias = aliasCheck(
|
||||
UnderlyingV1, LocationSize::beforeOrAfterPointer(), AAMDNodes(),
|
||||
UnderlyingV2, LocationSize::beforeOrAfterPointer(), AAMDNodes(), AAQI);
|
||||
|
||||
// For GEPs with identical offsets, we can preserve the size and AAInfo
|
||||
// when performing the alias check on the underlying objects.
|
||||
|
@ -1295,9 +1295,9 @@ AliasResult BasicAAResult::aliasGEP(
|
|||
if (!V1Size.hasValue() && !V2Size.hasValue())
|
||||
return MayAlias;
|
||||
|
||||
AliasResult R = aliasCheck(UnderlyingV1, LocationSize::unknown(),
|
||||
AAMDNodes(), V2, LocationSize::unknown(),
|
||||
V2AAInfo, AAQI, nullptr, UnderlyingV2);
|
||||
AliasResult R = aliasCheck(
|
||||
UnderlyingV1, LocationSize::beforeOrAfterPointer(), AAMDNodes(),
|
||||
V2, V2Size, V2AAInfo, AAQI, nullptr, UnderlyingV2);
|
||||
if (R != MustAlias) {
|
||||
// If V2 may alias GEP base pointer, conservatively returns MayAlias.
|
||||
// If V2 is known not to alias GEP base pointer, then the two values
|
||||
|
@ -1588,7 +1588,11 @@ AliasResult BasicAAResult::aliasPHI(const PHINode *PN, LocationSize PNSize,
|
|||
// unknown to represent all the possible values the GEP could advance the
|
||||
// pointer to.
|
||||
if (isRecursive)
|
||||
PNSize = LocationSize::unknown();
|
||||
// TODO: We are checking above that the addrec GEP has a positive offset
|
||||
// and can thus assume that all accesses happen after the base pointer.
|
||||
// It might be better to drop the offset requirement and use
|
||||
// beforeOrAfterPointer().
|
||||
PNSize = LocationSize::afterPointer();
|
||||
|
||||
// In the recursive alias queries below, we may compare values from two
|
||||
// different loop iterations. Keep track of visited phi blocks, which will
|
||||
|
@ -1726,6 +1730,18 @@ AliasResult BasicAAResult::aliasCheck(const Value *V1, LocationSize V1Size,
|
|||
TLI, NullIsValidLocation)))
|
||||
return NoAlias;
|
||||
|
||||
// If one the accesses may be before the accessed pointer, canonicalize this
|
||||
// by using unknown after-pointer sizes for both accesses. This is
|
||||
// equivalent, because regardless of which pointer is lower, one of them
|
||||
// will always came after the other, as long as the underlying objects aren't
|
||||
// disjoint. We do this so that the rest of BasicAA does not have to deal
|
||||
// with accesses before the base pointer, and to improve cache utilization by
|
||||
// merging equivalent states.
|
||||
if (V1Size.mayBeBeforePointer() || V2Size.mayBeBeforePointer()) {
|
||||
V1Size = LocationSize::afterPointer();
|
||||
V2Size = LocationSize::afterPointer();
|
||||
}
|
||||
|
||||
// Check the cache before climbing up use-def chains. This also terminates
|
||||
// otherwise infinitely recursive queries.
|
||||
AAQueryInfo::LocPair Locs(MemoryLocation(V1, V1Size, V1AAInfo),
|
||||
|
|
|
@ -653,8 +653,10 @@ static AliasResult underlyingObjectsAlias(AAResults *AA,
|
|||
const MemoryLocation &LocB) {
|
||||
// Check the original locations (minus size) for noalias, which can happen for
|
||||
// tbaa, incompatible underlying object locations, etc.
|
||||
MemoryLocation LocAS(LocA.Ptr, LocationSize::unknown(), LocA.AATags);
|
||||
MemoryLocation LocBS(LocB.Ptr, LocationSize::unknown(), LocB.AATags);
|
||||
MemoryLocation LocAS =
|
||||
MemoryLocation::getBeforeOrAfter(LocA.Ptr, LocA.AATags);
|
||||
MemoryLocation LocBS =
|
||||
MemoryLocation::getBeforeOrAfter(LocB.Ptr, LocB.AATags);
|
||||
if (AA->alias(LocAS, LocBS) == NoAlias)
|
||||
return NoAlias;
|
||||
|
||||
|
|
|
@ -921,8 +921,8 @@ ModRefInfo GlobalsAAResult::getModRefInfoForArgument(const CallBase *Call,
|
|||
if (!all_of(Objects, isIdentifiedObject) &&
|
||||
// Try ::alias to see if all objects are known not to alias GV.
|
||||
!all_of(Objects, [&](const Value *V) {
|
||||
return this->alias(MemoryLocation(V, LocationSize::unknown()),
|
||||
MemoryLocation(GV, LocationSize::unknown()),
|
||||
return this->alias(MemoryLocation::getBeforeOrAfter(V),
|
||||
MemoryLocation::getBeforeOrAfter(GV),
|
||||
AAQI) == NoAlias;
|
||||
}))
|
||||
return ConservativeResult;
|
||||
|
|
|
@ -190,8 +190,8 @@ void Lint::visitFunction(Function &F) {
|
|||
void Lint::visitCallBase(CallBase &I) {
|
||||
Value *Callee = I.getCalledOperand();
|
||||
|
||||
visitMemoryReference(I, MemoryLocation(Callee, LocationSize::unknown()),
|
||||
None, nullptr, MemRef::Callee);
|
||||
visitMemoryReference(I, MemoryLocation::getAfter(Callee), None, nullptr,
|
||||
MemRef::Callee);
|
||||
|
||||
if (Function *F = dyn_cast<Function>(findValue(Callee,
|
||||
/*OffsetOk=*/false))) {
|
||||
|
@ -295,7 +295,7 @@ void Lint::visitCallBase(CallBase &I) {
|
|||
// Check that the memcpy arguments don't overlap. The AliasAnalysis API
|
||||
// isn't expressive enough for what we really want to do. Known partial
|
||||
// overlap is not distinguished from the case where nothing is known.
|
||||
auto Size = LocationSize::unknown();
|
||||
auto Size = LocationSize::afterPointer();
|
||||
if (const ConstantInt *Len =
|
||||
dyn_cast<ConstantInt>(findValue(MCI->getLength(),
|
||||
/*OffsetOk=*/false)))
|
||||
|
@ -586,9 +586,8 @@ void Lint::visitVAArgInst(VAArgInst &I) {
|
|||
}
|
||||
|
||||
void Lint::visitIndirectBrInst(IndirectBrInst &I) {
|
||||
visitMemoryReference(
|
||||
I, MemoryLocation(I.getAddress(), LocationSize::unknown()),
|
||||
None, nullptr, MemRef::Branchee);
|
||||
visitMemoryReference(I, MemoryLocation::getAfter(I.getAddress()), None,
|
||||
nullptr, MemRef::Branchee);
|
||||
|
||||
Assert(I.getNumDestinations() != 0,
|
||||
"Undefined behavior: indirectbr with no destinations", &I);
|
||||
|
|
|
@ -514,7 +514,7 @@ public:
|
|||
/// Register a load and whether it is only read from.
|
||||
void addLoad(MemoryLocation &Loc, bool IsReadOnly) {
|
||||
Value *Ptr = const_cast<Value*>(Loc.Ptr);
|
||||
AST.add(Ptr, LocationSize::unknown(), Loc.AATags);
|
||||
AST.add(Ptr, LocationSize::beforeOrAfterPointer(), Loc.AATags);
|
||||
Accesses.insert(MemAccessInfo(Ptr, false));
|
||||
if (IsReadOnly)
|
||||
ReadOnlyPtr.insert(Ptr);
|
||||
|
@ -523,7 +523,7 @@ public:
|
|||
/// Register a store.
|
||||
void addStore(MemoryLocation &Loc) {
|
||||
Value *Ptr = const_cast<Value*>(Loc.Ptr);
|
||||
AST.add(Ptr, LocationSize::unknown(), Loc.AATags);
|
||||
AST.add(Ptr, LocationSize::beforeOrAfterPointer(), Loc.AATags);
|
||||
Accesses.insert(MemAccessInfo(Ptr, true));
|
||||
}
|
||||
|
||||
|
|
|
@ -148,7 +148,7 @@ static ModRefInfo GetLocation(const Instruction *Inst, MemoryLocation &Loc,
|
|||
|
||||
if (const CallInst *CI = isFreeCall(Inst, &TLI)) {
|
||||
// calls to free() deallocate the entire structure
|
||||
Loc = MemoryLocation(CI->getArgOperand(0), LocationSize::unknown());
|
||||
Loc = MemoryLocation::getAfter(CI->getArgOperand(0));
|
||||
return ModRefInfo::Mod;
|
||||
}
|
||||
|
||||
|
@ -455,7 +455,7 @@ MemDepResult MemoryDependenceResults::getSimplePointerDependencyFrom(
|
|||
// pointer, not on query pointers that are indexed off of them. It'd
|
||||
// be nice to handle that at some point (the right approach is to use
|
||||
// GetPointerBaseWithConstantOffset).
|
||||
MemoryLocation ArgLoc(II->getArgOperand(1), LocationSize::unknown());
|
||||
MemoryLocation ArgLoc = MemoryLocation::getAfter(II->getArgOperand(1));
|
||||
if (BatchAA.isMustAlias(ArgLoc, MemLoc))
|
||||
return MemDepResult::getDef(II);
|
||||
continue;
|
||||
|
|
|
@ -20,8 +20,10 @@ using namespace llvm;
|
|||
|
||||
void LocationSize::print(raw_ostream &OS) const {
|
||||
OS << "LocationSize::";
|
||||
if (*this == unknown())
|
||||
OS << "unknown";
|
||||
if (*this == beforeOrAfterPointer())
|
||||
OS << "beforeOrAfterPointer";
|
||||
if (*this == afterPointer())
|
||||
OS << "afterPointer";
|
||||
else if (*this == mapEmpty())
|
||||
OS << "mapEmpty";
|
||||
else if (*this == mapTombstone())
|
||||
|
@ -57,8 +59,8 @@ MemoryLocation MemoryLocation::get(const VAArgInst *VI) {
|
|||
AAMDNodes AATags;
|
||||
VI->getAAMetadata(AATags);
|
||||
|
||||
return MemoryLocation(VI->getPointerOperand(), LocationSize::unknown(),
|
||||
AATags);
|
||||
return MemoryLocation(VI->getPointerOperand(),
|
||||
LocationSize::afterPointer(), AATags);
|
||||
}
|
||||
|
||||
MemoryLocation MemoryLocation::get(const AtomicCmpXchgInst *CXI) {
|
||||
|
@ -109,7 +111,7 @@ MemoryLocation MemoryLocation::getForSource(const AtomicMemTransferInst *MTI) {
|
|||
}
|
||||
|
||||
MemoryLocation MemoryLocation::getForSource(const AnyMemTransferInst *MTI) {
|
||||
auto Size = LocationSize::unknown();
|
||||
auto Size = LocationSize::afterPointer();
|
||||
if (ConstantInt *C = dyn_cast<ConstantInt>(MTI->getLength()))
|
||||
Size = LocationSize::precise(C->getValue().getZExtValue());
|
||||
|
||||
|
@ -130,7 +132,7 @@ MemoryLocation MemoryLocation::getForDest(const AtomicMemIntrinsic *MI) {
|
|||
}
|
||||
|
||||
MemoryLocation MemoryLocation::getForDest(const AnyMemIntrinsic *MI) {
|
||||
auto Size = LocationSize::unknown();
|
||||
auto Size = LocationSize::afterPointer();
|
||||
if (ConstantInt *C = dyn_cast<ConstantInt>(MI->getLength()))
|
||||
Size = LocationSize::precise(C->getValue().getZExtValue());
|
||||
|
||||
|
@ -165,7 +167,7 @@ MemoryLocation MemoryLocation::getForArgument(const CallBase *Call,
|
|||
if (ConstantInt *LenCI = dyn_cast<ConstantInt>(II->getArgOperand(2)))
|
||||
return MemoryLocation(Arg, LocationSize::precise(LenCI->getZExtValue()),
|
||||
AATags);
|
||||
break;
|
||||
return MemoryLocation::getAfter(Arg, AATags);
|
||||
|
||||
case Intrinsic::lifetime_start:
|
||||
case Intrinsic::lifetime_end:
|
||||
|
@ -237,7 +239,7 @@ MemoryLocation MemoryLocation::getForArgument(const CallBase *Call,
|
|||
dyn_cast<ConstantInt>(Call->getArgOperand(2)))
|
||||
return MemoryLocation(Arg, LocationSize::precise(LenCI->getZExtValue()),
|
||||
AATags);
|
||||
break;
|
||||
return MemoryLocation::getAfter(Arg, AATags);
|
||||
case LibFunc_bcmp:
|
||||
case LibFunc_memcmp:
|
||||
assert((ArgIdx == 0 || ArgIdx == 1) &&
|
||||
|
@ -246,14 +248,14 @@ MemoryLocation MemoryLocation::getForArgument(const CallBase *Call,
|
|||
dyn_cast<ConstantInt>(Call->getArgOperand(2)))
|
||||
return MemoryLocation(Arg, LocationSize::precise(LenCI->getZExtValue()),
|
||||
AATags);
|
||||
break;
|
||||
return MemoryLocation::getAfter(Arg, AATags);
|
||||
case LibFunc_memchr:
|
||||
assert((ArgIdx == 0) && "Invalid argument index for memchr");
|
||||
if (const ConstantInt *LenCI =
|
||||
dyn_cast<ConstantInt>(Call->getArgOperand(2)))
|
||||
return MemoryLocation(Arg, LocationSize::precise(LenCI->getZExtValue()),
|
||||
AATags);
|
||||
break;
|
||||
return MemoryLocation::getAfter(Arg, AATags);
|
||||
case LibFunc_memccpy:
|
||||
assert((ArgIdx == 0 || ArgIdx == 1) &&
|
||||
"Invalid argument index for memccpy");
|
||||
|
@ -262,13 +264,12 @@ MemoryLocation MemoryLocation::getForArgument(const CallBase *Call,
|
|||
dyn_cast<ConstantInt>(Call->getArgOperand(3)))
|
||||
return MemoryLocation(
|
||||
Arg, LocationSize::upperBound(LenCI->getZExtValue()), AATags);
|
||||
break;
|
||||
return MemoryLocation::getAfter(Arg, AATags);
|
||||
default:
|
||||
break;
|
||||
};
|
||||
}
|
||||
// FIXME: Handle memset_pattern4 and memset_pattern8 also.
|
||||
|
||||
return MemoryLocation(Call->getArgOperand(ArgIdx), LocationSize::unknown(),
|
||||
AATags);
|
||||
return MemoryLocation::getBeforeOrAfter(Call->getArgOperand(ArgIdx), AATags);
|
||||
}
|
||||
|
|
|
@ -363,7 +363,7 @@ static bool lifetimeEndsAt(MemoryDef *MD, const MemoryLocation &Loc,
|
|||
if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(Inst)) {
|
||||
switch (II->getIntrinsicID()) {
|
||||
case Intrinsic::lifetime_end: {
|
||||
MemoryLocation ArgLoc(II->getArgOperand(1), LocationSize::unknown());
|
||||
MemoryLocation ArgLoc = MemoryLocation::getAfter(II->getArgOperand(1));
|
||||
return AA.alias(ArgLoc, Loc) == MustAlias;
|
||||
}
|
||||
default:
|
||||
|
|
|
@ -57,9 +57,8 @@ AliasResult ObjCARCAAResult::alias(const MemoryLocation &LocA,
|
|||
const Value *UA = GetUnderlyingObjCPtr(SA);
|
||||
const Value *UB = GetUnderlyingObjCPtr(SB);
|
||||
if (UA != SA || UB != SB) {
|
||||
Result = AAResultBase::alias(
|
||||
MemoryLocation(UA, LocationSize::unknown()),
|
||||
MemoryLocation(UB, LocationSize::unknown()), AAQI);
|
||||
Result = AAResultBase::alias(MemoryLocation::getBeforeOrAfter(UA),
|
||||
MemoryLocation::getBeforeOrAfter(UB), AAQI);
|
||||
// We can't use MustAlias or PartialAlias results here because
|
||||
// GetUnderlyingObjCPtr may return an offsetted pointer value.
|
||||
if (Result == NoAlias)
|
||||
|
@ -88,7 +87,7 @@ bool ObjCARCAAResult::pointsToConstantMemory(const MemoryLocation &Loc,
|
|||
const Value *U = GetUnderlyingObjCPtr(S);
|
||||
if (U != S)
|
||||
return AAResultBase::pointsToConstantMemory(
|
||||
MemoryLocation(U, LocationSize::unknown()), AAQI, OrLocal);
|
||||
MemoryLocation::getBeforeOrAfter(U), AAQI, OrLocal);
|
||||
|
||||
// If that failed, fail. We don't need to chain here, since that's covered
|
||||
// by the earlier precise query.
|
||||
|
|
|
@ -82,10 +82,12 @@ AliasResult SCEVAAResult::alias(const MemoryLocation &LocA,
|
|||
Value *BO = GetBaseValue(BS);
|
||||
if ((AO && AO != LocA.Ptr) || (BO && BO != LocB.Ptr))
|
||||
if (alias(MemoryLocation(AO ? AO : LocA.Ptr,
|
||||
AO ? LocationSize::unknown() : LocA.Size,
|
||||
AO ? LocationSize::beforeOrAfterPointer()
|
||||
: LocA.Size,
|
||||
AO ? AAMDNodes() : LocA.AATags),
|
||||
MemoryLocation(BO ? BO : LocB.Ptr,
|
||||
BO ? LocationSize::unknown() : LocB.Size,
|
||||
BO ? LocationSize::beforeOrAfterPointer()
|
||||
: LocB.Size,
|
||||
BO ? AAMDNodes() : LocB.AATags),
|
||||
AAQI) == NoAlias)
|
||||
return NoAlias;
|
||||
|
|
|
@ -353,11 +353,9 @@ ImplicitNullChecks::areMemoryOpsAliased(const MachineInstr &MI,
|
|||
return AR_MayAlias;
|
||||
continue;
|
||||
}
|
||||
llvm::AliasResult AAResult =
|
||||
AA->alias(MemoryLocation(MMO1->getValue(), LocationSize::unknown(),
|
||||
MMO1->getAAInfo()),
|
||||
MemoryLocation(MMO2->getValue(), LocationSize::unknown(),
|
||||
MMO2->getAAInfo()));
|
||||
llvm::AliasResult AAResult = AA->alias(
|
||||
MemoryLocation::getAfter(MMO1->getValue(), MMO1->getAAInfo()),
|
||||
MemoryLocation::getAfter(MMO2->getValue(), MMO2->getAAInfo()));
|
||||
if (AAResult != NoAlias)
|
||||
return AR_MayAlias;
|
||||
}
|
||||
|
|
|
@ -803,10 +803,8 @@ void SwingSchedulerDAG::addLoopCarriedDependences(AliasAnalysis *AA) {
|
|||
continue;
|
||||
}
|
||||
AliasResult AAResult = AA->alias(
|
||||
MemoryLocation(MMO1->getValue(), LocationSize::unknown(),
|
||||
MMO1->getAAInfo()),
|
||||
MemoryLocation(MMO2->getValue(), LocationSize::unknown(),
|
||||
MMO2->getAAInfo()));
|
||||
MemoryLocation::getAfter(MMO1->getValue(), MMO1->getAAInfo()),
|
||||
MemoryLocation::getAfter(MMO2->getValue(), MMO2->getAAInfo()));
|
||||
|
||||
if (AAResult != NoAlias) {
|
||||
SDep Dep(Load, SDep::Barrier);
|
||||
|
|
|
@ -4358,7 +4358,7 @@ void SelectionDAGBuilder::visitMaskedLoad(const CallInst &I, bool IsExpanding) {
|
|||
// Do not serialize masked loads of constant memory with anything.
|
||||
MemoryLocation ML;
|
||||
if (VT.isScalableVector())
|
||||
ML = MemoryLocation(PtrOperand, LocationSize::unknown());
|
||||
ML = MemoryLocation::getAfter(PtrOperand);
|
||||
else
|
||||
ML = MemoryLocation(PtrOperand, LocationSize::precise(
|
||||
DAG.getDataLayout().getTypeStoreSize(I.getType())),
|
||||
|
|
|
@ -109,7 +109,7 @@ bool AMDGPUAnnotateUniformValues::isClobberedInFunction(LoadInst * Load) {
|
|||
BasicBlock::iterator StartIt = (!L && (BB == Load->getParent())) ?
|
||||
BasicBlock::iterator(Load) : BB->end();
|
||||
auto Q = MDR->getPointerDependencyFrom(
|
||||
MemoryLocation(Ptr, LocationSize::unknown()), true, StartIt, BB, Load);
|
||||
MemoryLocation::getBeforeOrAfter(Ptr), true, StartIt, BB, Load);
|
||||
if (Q.isClobber() || Q.isUnknown())
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -304,8 +304,7 @@ bool AMDGPURewriteOutArguments::runOnFunction(Function &F) {
|
|||
BasicBlock *BB = RI->getParent();
|
||||
|
||||
MemDepResult Q = MDA->getPointerDependencyFrom(
|
||||
MemoryLocation(OutArg, LocationSize::unknown()), true, BB->end(),
|
||||
BB, RI);
|
||||
MemoryLocation::getBeforeOrAfter(OutArg), true, BB->end(), BB, RI);
|
||||
StoreInst *SI = nullptr;
|
||||
if (Q.isDef())
|
||||
SI = dyn_cast<StoreInst>(Q.getInst());
|
||||
|
|
|
@ -374,7 +374,7 @@ bool ARMParallelDSP::RecordMemoryOps(BasicBlock *BB) {
|
|||
DepMap RAWDeps;
|
||||
|
||||
// Record any writes that may alias a load.
|
||||
const auto Size = LocationSize::unknown();
|
||||
const auto Size = LocationSize::beforeOrAfterPointer();
|
||||
for (auto Write : Writes) {
|
||||
for (auto Read : Loads) {
|
||||
MemoryLocation ReadLoc =
|
||||
|
|
|
@ -1992,7 +1992,7 @@ mayLoopAccessLocation(Value *Ptr, ModRefInfo Access, Loop *L,
|
|||
// Get the location that may be stored across the loop. Since the access
|
||||
// is strided positively through memory, we say that the modified location
|
||||
// starts at the pointer and has infinite size.
|
||||
LocationSize AccessSize = LocationSize::unknown();
|
||||
LocationSize AccessSize = LocationSize::afterPointer();
|
||||
|
||||
// If the loop iterates a fixed number of times, we can refine the access
|
||||
// size to be exactly the size of the memset, which is (BECount+1)*StoreSize
|
||||
|
|
|
@ -167,7 +167,7 @@ static MemoryAccessKind checkFunctionMemoryAccess(Function &F, bool ThisBody,
|
|||
|
||||
AAMDNodes AAInfo;
|
||||
I->getAAMetadata(AAInfo);
|
||||
MemoryLocation Loc(Arg, LocationSize::unknown(), AAInfo);
|
||||
MemoryLocation Loc = MemoryLocation::getBeforeOrAfter(Arg, AAInfo);
|
||||
|
||||
// Skip accesses to local or constant memory as they don't impact the
|
||||
// externally visible mod/ref behavior.
|
||||
|
|
|
@ -275,7 +275,7 @@ static MemoryLocation getLocForWrite(Instruction *Inst,
|
|||
default:
|
||||
return MemoryLocation(); // Unhandled intrinsic.
|
||||
case Intrinsic::init_trampoline:
|
||||
return MemoryLocation(II->getArgOperand(0), LocationSize::unknown());
|
||||
return MemoryLocation::getAfter(II->getArgOperand(0));
|
||||
case Intrinsic::masked_store:
|
||||
return MemoryLocation::getForArgument(II, 1, TLI);
|
||||
case Intrinsic::lifetime_end: {
|
||||
|
@ -287,7 +287,7 @@ static MemoryLocation getLocForWrite(Instruction *Inst,
|
|||
if (auto *CB = dyn_cast<CallBase>(Inst))
|
||||
// All the supported TLI functions so far happen to have dest as their
|
||||
// first argument.
|
||||
return MemoryLocation(CB->getArgOperand(0), LocationSize::unknown());
|
||||
return MemoryLocation::getAfter(CB->getArgOperand(0));
|
||||
return MemoryLocation();
|
||||
}
|
||||
|
||||
|
@ -828,8 +828,7 @@ static bool handleFree(CallInst *F, AliasAnalysis *AA,
|
|||
MapVector<Instruction *, bool> &ThrowableInst) {
|
||||
bool MadeChange = false;
|
||||
|
||||
MemoryLocation Loc = MemoryLocation(F->getOperand(0),
|
||||
LocationSize::unknown());
|
||||
MemoryLocation Loc = MemoryLocation::getAfter(F->getOperand(0));
|
||||
SmallVector<BasicBlock *, 16> Blocks;
|
||||
Blocks.push_back(F->getParent());
|
||||
|
||||
|
@ -1726,15 +1725,14 @@ struct DSEState {
|
|||
case LibFunc_strncpy:
|
||||
case LibFunc_strcat:
|
||||
case LibFunc_strncat:
|
||||
return {MemoryLocation(CB->getArgOperand(0),
|
||||
LocationSize::unknown())};
|
||||
return {MemoryLocation::getAfter(CB->getArgOperand(0))};
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
switch (CB->getIntrinsicID()) {
|
||||
case Intrinsic::init_trampoline:
|
||||
return {MemoryLocation(CB->getArgOperand(0), LocationSize::unknown())};
|
||||
return {MemoryLocation::getAfter(CB->getArgOperand(0))};
|
||||
case Intrinsic::masked_store:
|
||||
return {MemoryLocation::getForArgument(CB, 1, TLI)};
|
||||
default:
|
||||
|
@ -1829,8 +1827,7 @@ struct DSEState {
|
|||
|
||||
if (auto *CB = dyn_cast<CallBase>(I)) {
|
||||
if (isFreeCall(I, &TLI))
|
||||
return {std::make_pair(MemoryLocation(CB->getArgOperand(0),
|
||||
LocationSize::unknown()),
|
||||
return {std::make_pair(MemoryLocation::getAfter(CB->getArgOperand(0)),
|
||||
true)};
|
||||
}
|
||||
|
||||
|
|
|
@ -1209,8 +1209,7 @@ bool llvm::canSinkOrHoistInst(Instruction &I, AAResults *AA, DominatorTree *DT,
|
|||
bool Invalidated;
|
||||
if (CurAST)
|
||||
Invalidated = pointerInvalidatedByLoop(
|
||||
MemoryLocation(Op, LocationSize::unknown(), AAMDNodes()),
|
||||
CurAST, CurLoop, AA);
|
||||
MemoryLocation::getBeforeOrAfter(Op), CurAST, CurLoop, AA);
|
||||
else
|
||||
Invalidated = pointerInvalidatedByLoopWithMSSA(
|
||||
MSSA, cast<MemoryUse>(MSSA->getMemoryAccess(CI)), CurLoop, I,
|
||||
|
|
|
@ -844,7 +844,7 @@ mayLoopAccessLocation(Value *Ptr, ModRefInfo Access, Loop *L,
|
|||
// Get the location that may be stored across the loop. Since the access is
|
||||
// strided positively through memory, we say that the modified location starts
|
||||
// at the pointer and has infinite size.
|
||||
LocationSize AccessSize = LocationSize::unknown();
|
||||
LocationSize AccessSize = LocationSize::afterPointer();
|
||||
|
||||
// If the loop iterates a fixed number of times, we can refine the access size
|
||||
// to be exactly the size of the memset, which is (BECount+1)*StoreSize
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
; CHECK: Alias sets for function 'test_alloca_argmemonly':
|
||||
; CHECK-NEXT: Alias Set Tracker: 2 alias sets for 3 pointer values.
|
||||
; CHECK-NEXT: AliasSet[0x{{[0-9a-f]+}}, 1] must alias, Mod Pointers: (i8* %a, LocationSize::precise(1))
|
||||
; CHECK-NEXT: AliasSet[0x{{[0-9a-f]+}}, 2] may alias, Mod/Ref Pointers: (i8* %d, unknown), (i8* %s, unknown)
|
||||
; CHECK-NEXT: AliasSet[0x{{[0-9a-f]+}}, 2] may alias, Mod/Ref Pointers: (i8* %d, unknown before-or-after), (i8* %s, unknown before-or-after)
|
||||
define void @test_alloca_argmemonly(i8* %s, i8* %d) {
|
||||
entry:
|
||||
%a = alloca i8, align 1
|
||||
|
@ -17,8 +17,8 @@ entry:
|
|||
|
||||
; CHECK: Alias sets for function 'test_readonly_arg'
|
||||
; CHECK-NEXT: Alias Set Tracker: 2 alias sets for 2 pointer values.
|
||||
; CHECK-NEXT: AliasSet[0x{{[0-9a-f]+}}, 1] must alias, Mod Pointers: (i8* %d, unknown)
|
||||
; CHECK-NEXT: AliasSet[0x{{[0-9a-f]+}}, 1] must alias, Ref Pointers: (i8* %s, unknown)
|
||||
; CHECK-NEXT: AliasSet[0x{{[0-9a-f]+}}, 1] must alias, Mod Pointers: (i8* %d, unknown before-or-after)
|
||||
; CHECK-NEXT: AliasSet[0x{{[0-9a-f]+}}, 1] must alias, Ref Pointers: (i8* %s, unknown before-or-after)
|
||||
define i8 @test_readonly_arg(i8* noalias %s, i8* noalias %d) {
|
||||
entry:
|
||||
call void @my_memcpy(i8* %d, i8* %s, i64 1)
|
||||
|
@ -29,7 +29,7 @@ entry:
|
|||
; CHECK: Alias sets for function 'test_noalias_argmemonly':
|
||||
; CHECK-NEXT: Alias Set Tracker: 2 alias sets for 3 pointer values.
|
||||
; CHECK-NEXT: AliasSet[0x{{[0-9a-f]+}}, 1] must alias, Mod Pointers: (i8* %a, LocationSize::precise(1))
|
||||
; CHECK-NEXT: AliasSet[0x{{[0-9a-f]+}}, 2] may alias, Mod/Ref Pointers: (i8* %d, unknown), (i8* %s, unknown)
|
||||
; CHECK-NEXT: AliasSet[0x{{[0-9a-f]+}}, 2] may alias, Mod/Ref Pointers: (i8* %d, unknown before-or-after), (i8* %s, unknown before-or-after)
|
||||
define void @test_noalias_argmemonly(i8* noalias %a, i8* %s, i8* %d) {
|
||||
entry:
|
||||
store i8 1, i8* %a, align 1
|
||||
|
@ -39,8 +39,8 @@ entry:
|
|||
|
||||
; CHECK: Alias sets for function 'test5':
|
||||
; CHECK-NEXT: Alias Set Tracker: 2 alias sets for 2 pointer values.
|
||||
; CHECK-NEXT: AliasSet[0x{{[0-9a-f]+}}, 1] must alias, Mod/Ref Pointers: (i8* %a, unknown)
|
||||
; CHECK-NEXT: AliasSet[0x{{[0-9a-f]+}}, 1] must alias, Mod Pointers: (i8* %b, unknown)
|
||||
; CHECK-NEXT: AliasSet[0x{{[0-9a-f]+}}, 1] must alias, Mod/Ref Pointers: (i8* %a, unknown before-or-after)
|
||||
; CHECK-NEXT: AliasSet[0x{{[0-9a-f]+}}, 1] must alias, Mod Pointers: (i8* %b, unknown before-or-after)
|
||||
define void @test5(i8* noalias %a, i8* noalias %b) {
|
||||
entry:
|
||||
store i8 1, i8* %a, align 1
|
||||
|
@ -51,8 +51,8 @@ entry:
|
|||
|
||||
; CHECK: Alias sets for function 'test_argcollapse':
|
||||
; CHECK-NEXT: Alias Set Tracker: 2 alias sets for 2 pointer values.
|
||||
; CHECK-NEXT: AliasSet[0x{{[0-9a-f]+}}, 1] must alias, Mod/Ref Pointers: (i8* %a, unknown)
|
||||
; CHECK-NEXT: AliasSet[0x{{[0-9a-f]+}}, 1] must alias, Mod/Ref Pointers: (i8* %b, unknown)
|
||||
; CHECK-NEXT: AliasSet[0x{{[0-9a-f]+}}, 1] must alias, Mod/Ref Pointers: (i8* %a, unknown before-or-after)
|
||||
; CHECK-NEXT: AliasSet[0x{{[0-9a-f]+}}, 1] must alias, Mod/Ref Pointers: (i8* %b, unknown before-or-after)
|
||||
define void @test_argcollapse(i8* noalias %a, i8* noalias %b) {
|
||||
entry:
|
||||
store i8 1, i8* %a, align 1
|
||||
|
@ -63,8 +63,8 @@ entry:
|
|||
|
||||
; CHECK: Alias sets for function 'test_memcpy1':
|
||||
; CHECK-NEXT: Alias Set Tracker: 2 alias sets for 2 pointer values.
|
||||
; CHECK-NEXT: AliasSet[0x{{[0-9a-f]+}}, 1] must alias, Mod/Ref Pointers: (i8* %b, unknown)
|
||||
; CHECK-NEXT: AliasSet[0x{{[0-9a-f]+}}, 1] must alias, Mod/Ref Pointers: (i8* %a, unknown)
|
||||
; CHECK-NEXT: AliasSet[0x{{[0-9a-f]+}}, 1] must alias, Mod/Ref Pointers: (i8* %b, unknown before-or-after)
|
||||
; CHECK-NEXT: AliasSet[0x{{[0-9a-f]+}}, 1] must alias, Mod/Ref Pointers: (i8* %a, unknown before-or-after)
|
||||
define void @test_memcpy1(i8* noalias %a, i8* noalias %b) {
|
||||
entry:
|
||||
call void @my_memcpy(i8* %b, i8* %a, i64 1)
|
||||
|
@ -74,7 +74,7 @@ entry:
|
|||
|
||||
; CHECK: Alias sets for function 'test_memset1':
|
||||
; CHECK-NEXT: Alias Set Tracker: 1 alias sets for 1 pointer values.
|
||||
; CHECK-NEXT: AliasSet[0x{{[0-9a-f]+}}, 1] must alias, Mod Pointers: (i8* %a, unknown)
|
||||
; CHECK-NEXT: AliasSet[0x{{[0-9a-f]+}}, 1] must alias, Mod Pointers: (i8* %a, unknown before-or-after)
|
||||
define void @test_memset1() {
|
||||
entry:
|
||||
%a = alloca i8, align 1
|
||||
|
@ -84,7 +84,7 @@ entry:
|
|||
|
||||
; CHECK: Alias sets for function 'test_memset2':
|
||||
; CHECK-NEXT: Alias Set Tracker: 1 alias sets for 1 pointer values.
|
||||
; CHECK-NEXT: AliasSet[0x{{[0-9a-f]+}}, 1] must alias, Mod Pointers: (i8* %a, unknown)
|
||||
; CHECK-NEXT: AliasSet[0x{{[0-9a-f]+}}, 1] must alias, Mod Pointers: (i8* %a, unknown before-or-after)
|
||||
define void @test_memset2(i8* %a) {
|
||||
entry:
|
||||
call void @my_memset(i8* %a, i8 0, i64 1)
|
||||
|
@ -93,7 +93,7 @@ entry:
|
|||
|
||||
; CHECK: Alias sets for function 'test_memset3':
|
||||
; CHECK-NEXT: Alias Set Tracker: 1 alias sets for 2 pointer values.
|
||||
; CHECK-NEXT: AliasSet[0x{{[0-9a-f]+}}, 2] may alias, Mod Pointers: (i8* %a, unknown), (i8* %b, unknown)
|
||||
; CHECK-NEXT: AliasSet[0x{{[0-9a-f]+}}, 2] may alias, Mod Pointers: (i8* %a, unknown before-or-after), (i8* %b, unknown before-or-after)
|
||||
define void @test_memset3(i8* %a, i8* %b) {
|
||||
entry:
|
||||
call void @my_memset(i8* %a, i8 0, i64 1)
|
||||
|
@ -105,8 +105,8 @@ entry:
|
|||
|
||||
; CHECK: Alias sets for function 'test_memset4':
|
||||
; CHECK-NEXT: Alias Set Tracker: 2 alias sets for 2 pointer values.
|
||||
; CHECK-NEXT: AliasSet[0x{{[0-9a-f]+}}, 1] must alias, Mod Pointers: (i8* %a, unknown)
|
||||
; CHECK-NEXT: AliasSet[0x{{[0-9a-f]+}}, 1] must alias, Mod Pointers: (i8* %b, unknown)
|
||||
; CHECK-NEXT: AliasSet[0x{{[0-9a-f]+}}, 1] must alias, Mod Pointers: (i8* %a, unknown before-or-after)
|
||||
; CHECK-NEXT: AliasSet[0x{{[0-9a-f]+}}, 1] must alias, Mod Pointers: (i8* %b, unknown before-or-after)
|
||||
define void @test_memset4(i8* noalias %a, i8* noalias %b) {
|
||||
entry:
|
||||
call void @my_memset(i8* %a, i8 0, i64 1)
|
||||
|
|
|
@ -14,7 +14,7 @@ entry:
|
|||
|
||||
; CHECK: Alias sets for function 'test_unknown_size':
|
||||
; CHECK: Alias Set Tracker: 1 alias sets for 1 pointer values.
|
||||
; CHECK: AliasSet[0x{{[0-9a-f]+}}, 1] must alias, Mod Pointers: (i8* %d, unknown)
|
||||
; CHECK: AliasSet[0x{{[0-9a-f]+}}, 1] must alias, Mod Pointers: (i8* %d, unknown after)
|
||||
define void @test_unknown_size(i8* noalias %d, i64 %len) {
|
||||
entry:
|
||||
call void @llvm.memset.p0i8.i64(i8* align 1 %d, i8 0, i64 %len, i1 false)
|
||||
|
@ -33,7 +33,7 @@ entry:
|
|||
|
||||
; CHECK: Alias sets for function 'test_atomic_unknown_size':
|
||||
; CHECK: Alias Set Tracker: 1 alias sets for 1 pointer values.
|
||||
; CHECK: AliasSet[0x{{[0-9a-f]+}}, 1] must alias, Mod Pointers: (i8* %d, unknown)
|
||||
; CHECK: AliasSet[0x{{[0-9a-f]+}}, 1] must alias, Mod Pointers: (i8* %d, unknown after)
|
||||
define void @test_atomic_unknown_size(i8* noalias %d, i64 %len) {
|
||||
entry:
|
||||
call void @llvm.memset.element.unordered.atomic.p0i8.i32(i8* align 1 %d, i8 0, i64 %len, i32 1)
|
||||
|
|
|
@ -16,8 +16,8 @@ entry:
|
|||
|
||||
; CHECK: Alias sets for function 'test_unknown_size':
|
||||
; CHECK: Alias Set Tracker: 2 alias sets for 2 pointer values.
|
||||
; CHECK: AliasSet[0x{{[0-9a-f]+}}, 1] must alias, Mod Pointers: (i8* %d, unknown)
|
||||
; CHECK: AliasSet[0x{{[0-9a-f]+}}, 1] must alias, Ref Pointers: (i8* %s, unknown)
|
||||
; CHECK: AliasSet[0x{{[0-9a-f]+}}, 1] must alias, Mod Pointers: (i8* %d, unknown after)
|
||||
; CHECK: AliasSet[0x{{[0-9a-f]+}}, 1] must alias, Ref Pointers: (i8* %s, unknown after)
|
||||
define void @test_unknown_size(i8* noalias %s, i8* noalias %d, i64 %len) {
|
||||
entry:
|
||||
call void @llvm.memcpy.p0i8.p0i8.i64(i8* %d, i8* %s, i64 %len, i1 false)
|
||||
|
|
|
@ -273,9 +273,9 @@ entry:
|
|||
; CHECK-LABEL: Function: test8
|
||||
; CHECK: NoModRef: Ptr: i8* %p <-> call void @an_inaccessiblememonly_func()
|
||||
; CHECK: NoModRef: Ptr: i8* %q <-> call void @an_inaccessiblememonly_func()
|
||||
; CHECK: NoModRef: Ptr: i8* %p <-> call void @an_inaccessibleorargmemonly_func(i8* %q)
|
||||
; CHECK: Both ModRef: Ptr: i8* %p <-> call void @an_inaccessibleorargmemonly_func(i8* %q)
|
||||
; CHECK: Both ModRef (MustAlias): Ptr: i8* %q <-> call void @an_inaccessibleorargmemonly_func(i8* %q)
|
||||
; CHECK: NoModRef: Ptr: i8* %p <-> call void @an_argmemonly_func(i8* %q)
|
||||
; CHECK: Both ModRef: Ptr: i8* %p <-> call void @an_argmemonly_func(i8* %q)
|
||||
; CHECK: Both ModRef (MustAlias): Ptr: i8* %q <-> call void @an_argmemonly_func(i8* %q)
|
||||
; CHECK: Just Ref: call void @a_readonly_func(i8* %p) <-> call void @an_inaccessiblememonly_func()
|
||||
; CHECK: Just Ref: call void @a_readonly_func(i8* %p) <-> call void @an_inaccessibleorargmemonly_func(i8* %q)
|
||||
|
@ -368,9 +368,9 @@ entry:
|
|||
; CHECK: Just Ref: Ptr: i8* %q <-> call void @a_readonly_func(i8* %p) #9 [ "unknown"() ]
|
||||
; CHECK: NoModRef: Ptr: i8* %p <-> call void @an_inaccessiblememonly_func() #10 [ "unknown"() ]
|
||||
; CHECK: NoModRef: Ptr: i8* %q <-> call void @an_inaccessiblememonly_func() #10 [ "unknown"() ]
|
||||
; CHECK: NoModRef: Ptr: i8* %p <-> call void @an_inaccessibleorargmemonly_func(i8* %q) #11 [ "unknown"() ]
|
||||
; CHECK: Both ModRef: Ptr: i8* %p <-> call void @an_inaccessibleorargmemonly_func(i8* %q) #11 [ "unknown"() ]
|
||||
; CHECK: Both ModRef (MustAlias): Ptr: i8* %q <-> call void @an_inaccessibleorargmemonly_func(i8* %q) #11 [ "unknown"() ]
|
||||
; CHECK: NoModRef: Ptr: i8* %p <-> call void @an_argmemonly_func(i8* %q) #12 [ "unknown"() ]
|
||||
; CHECK: Both ModRef: Ptr: i8* %p <-> call void @an_argmemonly_func(i8* %q) #12 [ "unknown"() ]
|
||||
; CHECK: Both ModRef (MustAlias): Ptr: i8* %q <-> call void @an_argmemonly_func(i8* %q) #12 [ "unknown"() ]
|
||||
; CHECK: Just Ref: call void @a_readonly_func(i8* %p) #9 [ "unknown"() ] <-> call void @an_inaccessiblememonly_func() #10 [ "unknown"() ]
|
||||
; CHECK: Just Ref: call void @a_readonly_func(i8* %p) #9 [ "unknown"() ] <-> call void @an_inaccessibleorargmemonly_func(i8* %q) #11 [ "unknown"() ]
|
||||
|
|
|
@ -9,8 +9,9 @@
|
|||
; #####################################################################
|
||||
|
||||
; Load from %arg1 has no-alias store in Loop - arg1[i+1] never alias arg1[i]
|
||||
; However, our analysis cannot detect this.
|
||||
|
||||
; CHECK: s_load_dword
|
||||
; CHECK: flat_load_dword
|
||||
|
||||
; #####################################################################
|
||||
|
||||
|
|
|
@ -55,8 +55,8 @@ struct AATestPass : FunctionPass {
|
|||
|
||||
for (Value *P1 : Pointers)
|
||||
for (Value *P2 : Pointers)
|
||||
(void)AA.alias(P1, LocationSize::unknown(), P2,
|
||||
LocationSize::unknown());
|
||||
(void)AA.alias(P1, LocationSize::beforeOrAfterPointer(), P2,
|
||||
LocationSize::beforeOrAfterPointer());
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -1277,7 +1277,7 @@ TEST_F(MemorySSATest, LifetimeMarkersAreClobbers) {
|
|||
|
||||
MemoryAccess *LifetimeStartClobber =
|
||||
MSSA.getWalker()->getClobberingMemoryAccess(
|
||||
LifetimeStartAccess, MemoryLocation(Foo, LocationSize::unknown()));
|
||||
LifetimeStartAccess, MemoryLocation::getAfter(Foo));
|
||||
EXPECT_EQ(LifetimeStartClobber, LifetimeStartAccess);
|
||||
}
|
||||
|
||||
|
|
|
@ -1129,7 +1129,7 @@ bool ScopDetection::isValidAccess(Instruction *Inst, const SCEV *AF,
|
|||
AAMDNodes AATags;
|
||||
Inst->getAAMetadata(AATags);
|
||||
AliasSet &AS = Context.AST.getAliasSetFor(
|
||||
MemoryLocation(BP->getValue(), LocationSize::unknown(), AATags));
|
||||
MemoryLocation::getBeforeOrAfter(BP->getValue(), AATags));
|
||||
|
||||
if (!AS.isMustAlias()) {
|
||||
if (PollyUseRuntimeAliasChecks) {
|
||||
|
|
Loading…
Reference in New Issue