Index: llvm/include/llvm/Analysis/AliasAnalysis.h =================================================================== --- llvm/include/llvm/Analysis/AliasAnalysis.h +++ llvm/include/llvm/Analysis/AliasAnalysis.h @@ -407,7 +407,8 @@ /// 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(V1, LocationSize::unknownMaybeNegative(), + V2, LocationSize::unknownMaybeNegative()); } /// A trivial helper function to check to see if the specified pointers are Index: llvm/include/llvm/Analysis/MemoryDependenceAnalysis.h =================================================================== --- llvm/include/llvm/Analysis/MemoryDependenceAnalysis.h +++ llvm/include/llvm/Analysis/MemoryDependenceAnalysis.h @@ -302,7 +302,7 @@ /// The maximum size of the dereferences of the pointer. /// /// May be UnknownSize if the sizes are unknown. - LocationSize Size = LocationSize::unknown(); + LocationSize Size = LocationSize::unknownNonNegative(); /// The AA tags associated with dereferences of the pointer. /// /// The members may be null if there are no tags or conflicting tags. Index: llvm/include/llvm/Analysis/MemoryLocation.h =================================================================== --- llvm/include/llvm/Analysis/MemoryLocation.h +++ llvm/include/llvm/Analysis/MemoryLocation.h @@ -64,10 +64,11 @@ // None. class LocationSize { enum : uint64_t { - Unknown = ~uint64_t(0), + UnknownNonNegative = ~uint64_t(0), + UnknownMaybeNegative = UnknownNonNegative - 1, + MapEmpty = UnknownNonNegative - 2, + MapTombstone = UnknownNonNegative - 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,10 @@ constexpr LocationSize(uint64_t Raw, DirectConstruction): Value(Raw) {} - static_assert(Unknown & ImpreciseBit, "Unknown is imprecise by definition."); + static_assert(UnknownNonNegative & ImpreciseBit, + "UnknownNonNegative is imprecise by definition."); + static_assert(UnknownMaybeNegative & ImpreciseBit, + "UnknownMaybeNegative 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 +94,12 @@ // 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 ? UnknownNonNegative : Raw) {} static LocationSize precise(uint64_t Value) { return LocationSize(Value); } static LocationSize precise(TypeSize Value) { if (Value.isScalable()) - return unknown(); + return unknownNonNegative(); return precise(Value.getFixedSize()); } @@ -104,17 +108,25 @@ if (LLVM_UNLIKELY(Value == 0)) return precise(0); if (LLVM_UNLIKELY(Value > MaxValue)) - return unknown(); + return unknownNonNegative(); return LocationSize(Value | ImpreciseBit, Direct); } static LocationSize upperBound(TypeSize Value) { if (Value.isScalable()) - return unknown(); + return unknownNonNegative(); return upperBound(Value.getFixedSize()); } - constexpr static LocationSize unknown() { - return LocationSize(Unknown, Direct); + /// Unknown, but non-negative, location size. This means that only memory + /// after the base pointer may be accessed. + constexpr static LocationSize unknownNonNegative() { + return LocationSize(UnknownNonNegative, Direct); + } + + /// Completely unknown location size, which also permits accesses before the + /// base pointer. + constexpr static LocationSize unknownMaybeNegative() { + return LocationSize(UnknownMaybeNegative, Direct); } // Sentinel values, generally used for maps. @@ -131,20 +143,24 @@ if (Other == *this) return *this; - if (!hasValue() || !Other.hasValue()) - return unknown(); + if (Value == UnknownMaybeNegative || Other.Value == UnknownMaybeNegative) + return unknownMaybeNegative(); + if (Value == UnknownNonNegative || Other.Value == UnknownNonNegative) + return unknownNonNegative(); return upperBound(std::max(getValue(), Other.getValue())); } - bool hasValue() const { return Value != Unknown; } + bool hasValue() const { + return Value != UnknownNonNegative && Value != UnknownMaybeNegative; + } 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 +168,9 @@ // Convenience method to check if this LocationSize's value is 0. bool isZero() const { return hasValue() && getValue() == 0; } + /// Whether accesses below the base pointer are possible. + bool mayBeNegative() const { return Value == UnknownMaybeNegative; } + bool operator==(const LocationSize &Other) const { return Value == Other.Value; } @@ -249,7 +268,8 @@ } explicit MemoryLocation(const Value *Ptr = nullptr, - LocationSize Size = LocationSize::unknown(), + LocationSize Size = + LocationSize::unknownNonNegative(), const AAMDNodes &AATags = AAMDNodes()) : Ptr(Ptr), Size(Size), AATags(AATags) {} Index: llvm/include/llvm/Analysis/MemorySSA.h =================================================================== --- llvm/include/llvm/Analysis/MemorySSA.h +++ llvm/include/llvm/Analysis/MemorySSA.h @@ -1248,7 +1248,8 @@ // catch loop carried dependences. if (Location.Ptr && !IsGuaranteedLoopInvariant(const_cast(Location.Ptr))) - CurrentPair.second = Location.getWithNewSize(LocationSize::unknown()); + CurrentPair.second = + Location.getWithNewSize(LocationSize::unknownMaybeNegative()); PHITransAddr Translator( const_cast(Location.Ptr), OriginalAccess->getBlock()->getModule()->getDataLayout(), nullptr); @@ -1263,7 +1264,8 @@ if (TransAddr && !IsGuaranteedLoopInvariant(const_cast(TransAddr))) CurrentPair.second = - CurrentPair.second.getWithNewSize(LocationSize::unknown()); + CurrentPair.second.getWithNewSize( + LocationSize::unknownMaybeNegative()); if (PerformedPhiTranslation) *PerformedPhiTranslation = true; Index: llvm/include/llvm/LinkAllPasses.h =================================================================== --- llvm/include/llvm/LinkAllPasses.h +++ llvm/include/llvm/LinkAllPasses.h @@ -239,7 +239,7 @@ llvm::TargetLibraryInfo TLI(TLII); llvm::AliasAnalysis AA(TLI); llvm::AliasSetTracker X(AA); - X.add(nullptr, llvm::LocationSize::unknown(), + X.add(nullptr, llvm::LocationSize::unknownNonNegative(), llvm::AAMDNodes()); // for -print-alias-sets (void) llvm::AreStatisticsEnabled(); (void) llvm::sys::RunningOnValgrind(); Index: llvm/lib/Analysis/AliasAnalysisEvaluator.cpp =================================================================== --- llvm/lib/Analysis/AliasAnalysisEvaluator.cpp +++ llvm/lib/Analysis/AliasAnalysisEvaluator.cpp @@ -140,13 +140,13 @@ // iterate over the worklist, and run the full (n^2)/2 disambiguations for (SetVector::iterator I1 = Pointers.begin(), E = Pointers.end(); I1 != E; ++I1) { - auto I1Size = LocationSize::unknown(); + auto I1Size = LocationSize::unknownNonNegative(); Type *I1ElTy = cast((*I1)->getType())->getElementType(); if (I1ElTy->isSized()) I1Size = LocationSize::precise(DL.getTypeStoreSize(I1ElTy)); for (SetVector::iterator I2 = Pointers.begin(); I2 != I1; ++I2) { - auto I2Size = LocationSize::unknown(); + auto I2Size = LocationSize::unknownNonNegative(); Type *I2ElTy = cast((*I2)->getType())->getElementType(); if (I2ElTy->isSized()) I2Size = LocationSize::precise(DL.getTypeStoreSize(I2ElTy)); @@ -239,7 +239,7 @@ // 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::unknownNonNegative(); Type *ElTy = cast(Pointer->getType())->getElementType(); if (ElTy->isSized()) Size = LocationSize::precise(DL.getTypeStoreSize(ElTy)); Index: llvm/lib/Analysis/AliasSetTracker.cpp =================================================================== --- llvm/lib/Analysis/AliasSetTracker.cpp +++ llvm/lib/Analysis/AliasSetTracker.cpp @@ -670,8 +670,10 @@ 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::unknownNonNegative()) + OS << ", unknown non-negative)"; + else if (I.getSize() == LocationSize::unknownMaybeNegative()) + OS << ", unknown maybe-negative)"; else OS << ", " << I.getSize() << ")"; } Index: llvm/lib/Analysis/BasicAliasAnalysis.cpp =================================================================== --- llvm/lib/Analysis/BasicAliasAnalysis.cpp +++ llvm/lib/Analysis/BasicAliasAnalysis.cpp @@ -1045,8 +1045,7 @@ // If we don't know the size of the accesses through both GEPs, we can't // determine whether the struct fields accessed can't alias. - if (MaybeV1Size == LocationSize::unknown() || - MaybeV2Size == LocationSize::unknown()) + if (!MaybeV1Size.hasValue() || !MaybeV2Size.hasValue()) return MayAlias; const uint64_t V1Size = MaybeV1Size.getValue(); @@ -1219,7 +1218,7 @@ const DecomposedGEP &DecompGEP, const DecomposedGEP &DecompObject, LocationSize MaybeObjectAccessSize) { // If the object access size is unknown, or the GEP isn't inbounds, bail. - if (MaybeObjectAccessSize == LocationSize::unknown() || !GEPOp->isInBounds()) + if (!MaybeObjectAccessSize.hasValue() || !GEPOp->isInBounds()) return false; const uint64_t ObjectAccessSize = MaybeObjectAccessSize.getValue(); @@ -1290,8 +1289,9 @@ return NoAlias; // Do the base pointers alias? AliasResult BaseAlias = - aliasCheck(UnderlyingV1, LocationSize::unknown(), AAMDNodes(), - UnderlyingV2, LocationSize::unknown(), AAMDNodes(), AAQI); + aliasCheck(UnderlyingV1, LocationSize::unknownMaybeNegative(), + AAMDNodes(), UnderlyingV2, + LocationSize::unknownMaybeNegative(), AAMDNodes(), AAQI); // For GEPs with identical offsets, we can preserve the size and AAInfo // when performing the alias check on the underlying objects. @@ -1336,12 +1336,13 @@ // pointer, we know they cannot alias. // If both accesses are unknown size, we can't do anything useful here. - if (V1Size == LocationSize::unknown() && V2Size == LocationSize::unknown()) + 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::unknownMaybeNegative(), + 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 @@ -1368,7 +1369,7 @@ // greater, we know they do not overlap. if (GEP1BaseOffset != 0 && DecompGEP1.VarIndices.empty()) { if (GEP1BaseOffset.sge(0)) { - if (V2Size != LocationSize::unknown()) { + if (V2Size.hasValue()) { if (GEP1BaseOffset.ult(V2Size.getValue())) return PartialAlias; return NoAlias; @@ -1382,8 +1383,8 @@ // GEP1 V2 // We need to know that V2Size is not unknown, otherwise we might have // stripped a gep with negative index ('gep , -1, ...). - if (V1Size != LocationSize::unknown() && - V2Size != LocationSize::unknown()) { + // TODO: The V2Size.hasValue() check is unnecessary. + if (V1Size.hasValue() && V2Size.hasValue()) { if ((-GEP1BaseOffset).ult(V1Size.getValue())) return PartialAlias; return NoAlias; @@ -1434,8 +1435,8 @@ // mod Modulo. Check whether that difference guarantees that the // two locations do not alias. APInt ModOffset = GEP1BaseOffset & (Modulo - 1); - if (V1Size != LocationSize::unknown() && - V2Size != LocationSize::unknown() && ModOffset.uge(V2Size.getValue()) && + if (V1Size.hasValue() && V2Size.hasValue() && + ModOffset.uge(V2Size.getValue()) && (Modulo - ModOffset).uge(V1Size.getValue())) return NoAlias; @@ -1443,14 +1444,14 @@ // also non-negative and >= GEP1BaseOffset. We have the following layout: // [0, V2Size) ... [TotalOffset, TotalOffer+V1Size] // If GEP1BaseOffset >= V2Size, the accesses don't alias. - if (AllNonNegative && V2Size != LocationSize::unknown() && + if (AllNonNegative && V2Size.hasValue() && GEP1BaseOffset.uge(V2Size.getValue())) return NoAlias; // Similarly, if the variables are non-positive, then the total offset is // also non-positive and <= GEP1BaseOffset. We have the following layout: // [TotalOffset, TotalOffset+V1Size) ... [0, V2Size) // If -GEP1BaseOffset >= V1Size, the accesses don't alias. - if (AllNonPositive && V1Size != LocationSize::unknown() && + if (AllNonPositive && V1Size.hasValue() && (-GEP1BaseOffset).uge(V1Size.getValue())) return NoAlias; @@ -1632,7 +1633,8 @@ // unknown to represent all the possible values the GEP could advance the // pointer to. if (isRecursive) - PNSize = LocationSize::unknown(); + // TODO: Relax GEP checks above and use unknownMaybeNegative(). + PNSize = LocationSize::unknownNonNegative(); // In the recursive alias queries below, we may compare values from two // different loop iterations. Keep track of visited phi blocks, which will @@ -1770,6 +1772,17 @@ TLI, NullIsValidLocation))) return NoAlias; + // If one the accesses may be negative (i.e. below the accessed pointer), + // canonicalize this by using unknown non-negative sizes for both accesses. + // This is equivalent, because regardless of which pointer is lower, the + // non-negative unknown sizes will always intersect. We do this so that the + // rest of BasicAA does not have to deal with negative access sizes, and to + // improve cache utilization by merging equivalent states. + if (V1Size.mayBeNegative() || V2Size.mayBeNegative()) { + V1Size = LocationSize::unknownNonNegative(); + V2Size = LocationSize::unknownNonNegative(); + } + // Check the cache before climbing up use-def chains. This also terminates // otherwise infinitely recursive queries. AAQueryInfo::LocPair Locs(MemoryLocation(V1, V1Size, V1AAInfo), @@ -1910,8 +1923,8 @@ const SmallVectorImpl &VarIndices, LocationSize MaybeV1Size, LocationSize MaybeV2Size, const APInt &BaseOffset, AssumptionCache *AC, DominatorTree *DT) { - if (VarIndices.size() != 2 || MaybeV1Size == LocationSize::unknown() || - MaybeV2Size == LocationSize::unknown()) + if (VarIndices.size() != 2 || !MaybeV1Size.hasValue() || + !MaybeV2Size.hasValue()) return false; const uint64_t V1Size = MaybeV1Size.getValue(); Index: llvm/lib/Analysis/CFLAndersAliasAnalysis.cpp =================================================================== --- llvm/lib/Analysis/CFLAndersAliasAnalysis.cpp +++ llvm/lib/Analysis/CFLAndersAliasAnalysis.cpp @@ -559,8 +559,7 @@ if (RangePair.first != RangePair.second) { // Be conservative about unknown sizes - if (MaybeLHSSize == LocationSize::unknown() || - MaybeRHSSize == LocationSize::unknown()) + if (!MaybeLHSSize.hasValue() || !MaybeRHSSize.hasValue()) return true; const uint64_t LHSSize = MaybeLHSSize.getValue(); Index: llvm/lib/Analysis/DependenceAnalysis.cpp =================================================================== --- llvm/lib/Analysis/DependenceAnalysis.cpp +++ llvm/lib/Analysis/DependenceAnalysis.cpp @@ -653,8 +653,10 @@ 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(LocA.Ptr, LocationSize::unknownMaybeNegative(), + LocA.AATags); + MemoryLocation LocBS(LocB.Ptr, LocationSize::unknownMaybeNegative(), + LocB.AATags); if (AA->alias(LocAS, LocBS) == NoAlias) return NoAlias; Index: llvm/lib/Analysis/Lint.cpp =================================================================== --- llvm/lib/Analysis/Lint.cpp +++ llvm/lib/Analysis/Lint.cpp @@ -295,7 +295,7 @@ // 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::unknownNonNegative(); if (const ConstantInt *Len = dyn_cast(findValue(MCI->getLength(), /*OffsetOk=*/false))) Index: llvm/lib/Analysis/LoopAccessAnalysis.cpp =================================================================== --- llvm/lib/Analysis/LoopAccessAnalysis.cpp +++ llvm/lib/Analysis/LoopAccessAnalysis.cpp @@ -518,7 +518,7 @@ /// Register a load and whether it is only read from. void addLoad(MemoryLocation &Loc, bool IsReadOnly) { Value *Ptr = const_cast(Loc.Ptr); - AST.add(Ptr, LocationSize::unknown(), Loc.AATags); + AST.add(Ptr, LocationSize::unknownNonNegative(), Loc.AATags); Accesses.insert(MemAccessInfo(Ptr, false)); if (IsReadOnly) ReadOnlyPtr.insert(Ptr); @@ -527,7 +527,7 @@ /// Register a store. void addStore(MemoryLocation &Loc) { Value *Ptr = const_cast(Loc.Ptr); - AST.add(Ptr, LocationSize::unknown(), Loc.AATags); + AST.add(Ptr, LocationSize::unknownNonNegative(), Loc.AATags); Accesses.insert(MemAccessInfo(Ptr, true)); } Index: llvm/lib/Analysis/MemoryLocation.cpp =================================================================== --- llvm/lib/Analysis/MemoryLocation.cpp +++ llvm/lib/Analysis/MemoryLocation.cpp @@ -20,8 +20,10 @@ void LocationSize::print(raw_ostream &OS) const { OS << "LocationSize::"; - if (*this == unknown()) - OS << "unknown"; + if (*this == unknownNonNegative()) + OS << "unknown non-negative"; + if (*this == unknownMaybeNegative()) + OS << "unknown maybe-negative"; else if (*this == mapEmpty()) OS << "mapEmpty"; else if (*this == mapTombstone()) @@ -57,8 +59,8 @@ AAMDNodes AATags; VI->getAAMetadata(AATags); - return MemoryLocation(VI->getPointerOperand(), LocationSize::unknown(), - AATags); + return MemoryLocation(VI->getPointerOperand(), + LocationSize::unknownNonNegative(), AATags); } MemoryLocation MemoryLocation::get(const AtomicCmpXchgInst *CXI) { @@ -109,7 +111,7 @@ } MemoryLocation MemoryLocation::getForSource(const AnyMemTransferInst *MTI) { - auto Size = LocationSize::unknown(); + auto Size = LocationSize::unknownNonNegative(); if (ConstantInt *C = dyn_cast(MTI->getLength())) Size = LocationSize::precise(C->getValue().getZExtValue()); @@ -130,7 +132,7 @@ } MemoryLocation MemoryLocation::getForDest(const AnyMemIntrinsic *MI) { - auto Size = LocationSize::unknown(); + auto Size = LocationSize::unknownNonNegative(); if (ConstantInt *C = dyn_cast(MI->getLength())) Size = LocationSize::precise(C->getValue().getZExtValue()); @@ -269,6 +271,6 @@ } // FIXME: Handle memset_pattern4 and memset_pattern8 also. - return MemoryLocation(Call->getArgOperand(ArgIdx), LocationSize::unknown(), - AATags); + return MemoryLocation(Call->getArgOperand(ArgIdx), + LocationSize::unknownMaybeNegative(), AATags); } Index: llvm/lib/Analysis/ScalarEvolutionAliasAnalysis.cpp =================================================================== --- llvm/lib/Analysis/ScalarEvolutionAliasAnalysis.cpp +++ llvm/lib/Analysis/ScalarEvolutionAliasAnalysis.cpp @@ -82,10 +82,12 @@ 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::unknownMaybeNegative() + : LocA.Size, AO ? AAMDNodes() : LocA.AATags), MemoryLocation(BO ? BO : LocB.Ptr, - BO ? LocationSize::unknown() : LocB.Size, + BO ? LocationSize::unknownMaybeNegative() + : LocB.Size, BO ? AAMDNodes() : LocB.AATags), AAQI) == NoAlias) return NoAlias; Index: llvm/lib/CodeGen/ImplicitNullChecks.cpp =================================================================== --- llvm/lib/CodeGen/ImplicitNullChecks.cpp +++ llvm/lib/CodeGen/ImplicitNullChecks.cpp @@ -354,9 +354,11 @@ continue; } llvm::AliasResult AAResult = - AA->alias(MemoryLocation(MMO1->getValue(), LocationSize::unknown(), + AA->alias(MemoryLocation(MMO1->getValue(), + LocationSize::unknownNonNegative(), MMO1->getAAInfo()), - MemoryLocation(MMO2->getValue(), LocationSize::unknown(), + MemoryLocation(MMO2->getValue(), + LocationSize::unknownNonNegative(), MMO2->getAAInfo())); if (AAResult != NoAlias) return AR_MayAlias; Index: llvm/lib/CodeGen/MachinePipeliner.cpp =================================================================== --- llvm/lib/CodeGen/MachinePipeliner.cpp +++ llvm/lib/CodeGen/MachinePipeliner.cpp @@ -803,9 +803,11 @@ continue; } AliasResult AAResult = AA->alias( - MemoryLocation(MMO1->getValue(), LocationSize::unknown(), + MemoryLocation(MMO1->getValue(), + LocationSize::unknownNonNegative(), MMO1->getAAInfo()), - MemoryLocation(MMO2->getValue(), LocationSize::unknown(), + MemoryLocation(MMO2->getValue(), + LocationSize::unknownNonNegative(), MMO2->getAAInfo())); if (AAResult != NoAlias) { Index: llvm/lib/Target/ARM/ARMParallelDSP.cpp =================================================================== --- llvm/lib/Target/ARM/ARMParallelDSP.cpp +++ llvm/lib/Target/ARM/ARMParallelDSP.cpp @@ -374,7 +374,7 @@ DepMap RAWDeps; // Record any writes that may alias a load. - const auto Size = LocationSize::unknown(); + const auto Size = LocationSize::unknownMaybeNegative(); for (auto Write : Writes) { for (auto Read : Loads) { MemoryLocation ReadLoc = Index: llvm/lib/Target/Hexagon/HexagonLoopIdiomRecognition.cpp =================================================================== --- llvm/lib/Target/Hexagon/HexagonLoopIdiomRecognition.cpp +++ llvm/lib/Target/Hexagon/HexagonLoopIdiomRecognition.cpp @@ -1973,7 +1973,7 @@ // 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::unknownNonNegative(); // 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 Index: llvm/lib/Transforms/IPO/FunctionAttrs.cpp =================================================================== --- llvm/lib/Transforms/IPO/FunctionAttrs.cpp +++ llvm/lib/Transforms/IPO/FunctionAttrs.cpp @@ -166,7 +166,7 @@ AAMDNodes AAInfo; I->getAAMetadata(AAInfo); - MemoryLocation Loc(Arg, LocationSize::unknown(), AAInfo); + MemoryLocation Loc(Arg, LocationSize::unknownMaybeNegative(), AAInfo); // Skip accesses to local or constant memory as they don't impact the // externally visible mod/ref behavior. Index: llvm/lib/Transforms/Scalar/LICM.cpp =================================================================== --- llvm/lib/Transforms/Scalar/LICM.cpp +++ llvm/lib/Transforms/Scalar/LICM.cpp @@ -1207,7 +1207,8 @@ bool Invalidated; if (CurAST) Invalidated = pointerInvalidatedByLoop( - MemoryLocation(Op, LocationSize::unknown(), AAMDNodes()), + MemoryLocation(Op, LocationSize::unknownMaybeNegative(), + AAMDNodes()), CurAST, CurLoop, AA); else Invalidated = pointerInvalidatedByLoopWithMSSA( Index: llvm/lib/Transforms/Scalar/LoopIdiomRecognize.cpp =================================================================== --- llvm/lib/Transforms/Scalar/LoopIdiomRecognize.cpp +++ llvm/lib/Transforms/Scalar/LoopIdiomRecognize.cpp @@ -844,7 +844,7 @@ // 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::unknownNonNegative(); // 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 Index: llvm/test/Analysis/AliasSet/argmemonly.ll =================================================================== --- llvm/test/Analysis/AliasSet/argmemonly.ll +++ llvm/test/Analysis/AliasSet/argmemonly.ll @@ -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 maybe-negative), (i8* %s, unknown maybe-negative) define void @test_alloca_argmemonly(i8* %s, i8* %d) { entry: %a = alloca i8, align 1 @@ -17,8 +17,8 @@ ; 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 maybe-negative) +; CHECK-NEXT: AliasSet[0x{{[0-9a-f]+}}, 1] must alias, Ref Pointers: (i8* %s, unknown maybe-negative) 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 @@ ; 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 maybe-negative), (i8* %s, unknown maybe-negative) define void @test_noalias_argmemonly(i8* noalias %a, i8* %s, i8* %d) { entry: store i8 1, i8* %a, align 1 @@ -39,8 +39,8 @@ ; 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 maybe-negative) +; CHECK-NEXT: AliasSet[0x{{[0-9a-f]+}}, 1] must alias, Mod Pointers: (i8* %b, unknown maybe-negative) define void @test5(i8* noalias %a, i8* noalias %b) { entry: store i8 1, i8* %a, align 1 @@ -51,8 +51,8 @@ ; 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 maybe-negative) +; CHECK-NEXT: AliasSet[0x{{[0-9a-f]+}}, 1] must alias, Mod/Ref Pointers: (i8* %b, unknown maybe-negative) define void @test_argcollapse(i8* noalias %a, i8* noalias %b) { entry: store i8 1, i8* %a, align 1 @@ -63,8 +63,8 @@ ; 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 maybe-negative) +; CHECK-NEXT: AliasSet[0x{{[0-9a-f]+}}, 1] must alias, Mod/Ref Pointers: (i8* %a, unknown maybe-negative) 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 @@ ; 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 maybe-negative) define void @test_memset1() { entry: %a = alloca i8, align 1 @@ -84,7 +84,7 @@ ; 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 maybe-negative) define void @test_memset2(i8* %a) { entry: call void @my_memset(i8* %a, i8 0, i64 1) @@ -93,7 +93,7 @@ ; 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 maybe-negative), (i8* %b, unknown maybe-negative) define void @test_memset3(i8* %a, i8* %b) { entry: call void @my_memset(i8* %a, i8 0, i64 1) @@ -105,8 +105,8 @@ ; 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 maybe-negative) +; CHECK-NEXT: AliasSet[0x{{[0-9a-f]+}}, 1] must alias, Mod Pointers: (i8* %b, unknown maybe-negative) define void @test_memset4(i8* noalias %a, i8* noalias %b) { entry: call void @my_memset(i8* %a, i8 0, i64 1) Index: llvm/test/Analysis/AliasSet/memset.ll =================================================================== --- llvm/test/Analysis/AliasSet/memset.ll +++ llvm/test/Analysis/AliasSet/memset.ll @@ -14,7 +14,7 @@ ; 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 non-negative) 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 @@ ; 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 non-negative) 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) Index: llvm/test/Analysis/AliasSet/memtransfer.ll =================================================================== --- llvm/test/Analysis/AliasSet/memtransfer.ll +++ llvm/test/Analysis/AliasSet/memtransfer.ll @@ -16,8 +16,8 @@ ; 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 non-negative) +; CHECK: AliasSet[0x{{[0-9a-f]+}}, 1] must alias, Ref Pointers: (i8* %s, unknown non-negative) 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) Index: llvm/test/Analysis/BasicAA/cs-cs.ll =================================================================== --- llvm/test/Analysis/BasicAA/cs-cs.ll +++ llvm/test/Analysis/BasicAA/cs-cs.ll @@ -273,9 +273,9 @@ ; 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 @@ ; 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"() ] Index: llvm/unittests/Analysis/AliasAnalysisTest.cpp =================================================================== --- llvm/unittests/Analysis/AliasAnalysisTest.cpp +++ llvm/unittests/Analysis/AliasAnalysisTest.cpp @@ -55,8 +55,8 @@ for (Value *P1 : Pointers) for (Value *P2 : Pointers) - (void)AA.alias(P1, LocationSize::unknown(), P2, - LocationSize::unknown()); + (void)AA.alias(P1, LocationSize::unknownMaybeNegative(), P2, + LocationSize::unknownMaybeNegative()); return false; }