[llvm] [BasicAA] Compute minimal access extents lazily (PR #226931)
Dávid Bolvanský via llvm-commits
llvm-commits at lists.llvm.org
Mon Sep 28 03:29:01 PDT 2026
https://github.com/davidbolvansky updated https://github.com/llvm/llvm-project/pull/226931
>From deac9d6085608c50e44c8a4a0a99318407eb54ba Mon Sep 17 00:00:00 2001
From: David Bolvansky <david.bolvansky at gmail.com>
Date: Mon, 28 Sep 2026 10:15:24 +0200
Subject: [PATCH 1/2] BasicAA: Compute minimal access extents lazily
---
llvm/lib/Analysis/BasicAliasAnalysis.cpp | 58 ++++++++++++------------
1 file changed, 28 insertions(+), 30 deletions(-)
diff --git a/llvm/lib/Analysis/BasicAliasAnalysis.cpp b/llvm/lib/Analysis/BasicAliasAnalysis.cpp
index fd9a7bb935170c..331873130a7cf3 100644
--- a/llvm/lib/Analysis/BasicAliasAnalysis.cpp
+++ b/llvm/lib/Analysis/BasicAliasAnalysis.cpp
@@ -117,11 +117,33 @@ static std::optional<TypeSize> getObjectSize(const Value *V,
return std::nullopt;
}
+/// Return the minimal extent from \p V to the end of the underlying object,
+/// assuming the result is used in an aliasing query. E.g., we do use the query
+/// location size and the fact that null pointers cannot alias here.
+static TypeSize getMinimalExtentFrom(const Value &V,
+ const LocationSize &LocSize,
+ const DataLayout &DL,
+ bool NullIsValidLoc) {
+ // If we have dereferenceability information we know a lower bound for the
+ // extent as accesses for a lower offset would be valid. We need to exclude
+ // the "or null" part if null is a valid pointer. We can ignore frees, as an
+ // access after free would be undefined behavior.
+ bool CanBeNull;
+ uint64_t DerefBytes =
+ V.getPointerDereferenceableBytes(DL, CanBeNull, /*CanBeFreed=*/nullptr);
+ DerefBytes = (CanBeNull && NullIsValidLoc) ? 0 : DerefBytes;
+ // If queried with a precise location size, we assume that location size to be
+ // accessed, thus valid.
+ if (LocSize.isPrecise())
+ DerefBytes = std::max(DerefBytes, LocSize.getValue().getKnownMinValue());
+ return TypeSize::getFixed(DerefBytes);
+}
+
/// Returns true if we can prove that the object specified by V is smaller than
/// Size. Bails out early unless the root object is passed as the first
/// parameter.
-static bool isObjectSmallerThan(const Value *V, TypeSize Size,
- const DataLayout &DL,
+static bool isObjectSmallerThan(const Value *V, const Value &OtherV,
+ LocationSize OtherSize, const DataLayout &DL,
const TargetLibraryInfo &TLI,
bool NullIsValidLoc) {
// Note that the meanings of the "object" are slightly different in the
@@ -147,6 +169,8 @@ static bool isObjectSmallerThan(const Value *V, TypeSize Size,
if (!isIdentifiedObject(V))
return false;
+ TypeSize Size = getMinimalExtentFrom(OtherV, OtherSize, DL, NullIsValidLoc);
+
// This function needs to use the aligned object size because we allow
// reads a bit past the end given sufficient alignment.
std::optional<TypeSize> ObjectSize = getObjectSize(V, DL, TLI, NullIsValidLoc,
@@ -155,28 +179,6 @@ static bool isObjectSmallerThan(const Value *V, TypeSize Size,
return ObjectSize && TypeSize::isKnownLT(*ObjectSize, Size);
}
-/// Return the minimal extent from \p V to the end of the underlying object,
-/// assuming the result is used in an aliasing query. E.g., we do use the query
-/// location size and the fact that null pointers cannot alias here.
-static TypeSize getMinimalExtentFrom(const Value &V,
- const LocationSize &LocSize,
- const DataLayout &DL,
- bool NullIsValidLoc) {
- // If we have dereferenceability information we know a lower bound for the
- // extent as accesses for a lower offset would be valid. We need to exclude
- // the "or null" part if null is a valid pointer. We can ignore frees, as an
- // access after free would be undefined behavior.
- bool CanBeNull;
- uint64_t DerefBytes =
- V.getPointerDereferenceableBytes(DL, CanBeNull, /*CanBeFreed=*/nullptr);
- DerefBytes = (CanBeNull && NullIsValidLoc) ? 0 : DerefBytes;
- // If queried with a precise location size, we assume that location size to be
- // accessed, thus valid.
- if (LocSize.isPrecise())
- DerefBytes = std::max(DerefBytes, LocSize.getValue().getKnownMinValue());
- return TypeSize::getFixed(DerefBytes);
-}
-
/// Returns true if we can prove that the object specified by V has size Size.
static bool isObjectSize(const Value *V, TypeSize Size, const DataLayout &DL,
const TargetLibraryInfo &TLI, bool NullIsValidLoc) {
@@ -1615,12 +1617,8 @@ AliasResult BasicAAResult::aliasCheck(const Value *V1, LocationSize V1Size,
// If the size of one access is larger than the entire object on the other
// side, then we know such behavior is undefined and can assume no alias.
bool NullIsValidLocation = NullPointerIsDefined(&F);
- if ((isObjectSmallerThan(
- O2, getMinimalExtentFrom(*V1, V1Size, DL, NullIsValidLocation), DL,
- TLI, NullIsValidLocation)) ||
- (isObjectSmallerThan(
- O1, getMinimalExtentFrom(*V2, V2Size, DL, NullIsValidLocation), DL,
- TLI, NullIsValidLocation)))
+ if (isObjectSmallerThan(O2, *V1, V1Size, DL, TLI, NullIsValidLocation) ||
+ isObjectSmallerThan(O1, *V2, V2Size, DL, TLI, NullIsValidLocation))
return AliasResult::NoAlias;
if (EnableSeparateStorageAnalysis) {
>From 54a4ba3c06bb85cc8fb5430f9af53e38fb6ab025 Mon Sep 17 00:00:00 2001
From: David Bolvansky <david.bolvansky at gmail.com>
Date: Mon, 28 Sep 2026 12:28:38 +0200
Subject: [PATCH 2/2] BasicAA: Defer minimal extent until object size is known
---
llvm/lib/Analysis/BasicAliasAnalysis.cpp | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/llvm/lib/Analysis/BasicAliasAnalysis.cpp b/llvm/lib/Analysis/BasicAliasAnalysis.cpp
index 331873130a7cf3..9c79a3d7d0cfdb 100644
--- a/llvm/lib/Analysis/BasicAliasAnalysis.cpp
+++ b/llvm/lib/Analysis/BasicAliasAnalysis.cpp
@@ -169,14 +169,15 @@ static bool isObjectSmallerThan(const Value *V, const Value &OtherV,
if (!isIdentifiedObject(V))
return false;
- TypeSize Size = getMinimalExtentFrom(OtherV, OtherSize, DL, NullIsValidLoc);
-
// This function needs to use the aligned object size because we allow
// reads a bit past the end given sufficient alignment.
std::optional<TypeSize> ObjectSize = getObjectSize(V, DL, TLI, NullIsValidLoc,
/*RoundToAlign*/ true);
+ if (!ObjectSize)
+ return false;
- return ObjectSize && TypeSize::isKnownLT(*ObjectSize, Size);
+ TypeSize Size = getMinimalExtentFrom(OtherV, OtherSize, DL, NullIsValidLoc);
+ return TypeSize::isKnownLT(*ObjectSize, Size);
}
/// Returns true if we can prove that the object specified by V has size Size.
More information about the llvm-commits
mailing list