[llvm] [BasicAA] Cancel common scalable GEP offsets (PR #218195)
via llvm-commits
llvm-commits at lists.llvm.org
Sat Aug 22 23:01:28 PDT 2026
https://github.com/SomeFlyingThing updated https://github.com/llvm/llvm-project/pull/218195
>From 135c83163129cb5998f3bc7f1b8c9963ebd7593f Mon Sep 17 00:00:00 2001
From: SomeFlyingThing <306498559+SomeFlyingThing at users.noreply.github.com>
Date: Sun, 23 Aug 2026 15:56:23 +1200
Subject: [PATCH 1/2] [BasicAA] Cancel common scalable GEP offsets
---
llvm/lib/Analysis/BasicAliasAnalysis.cpp | 22 ++++++++++++++++++----
llvm/test/Analysis/BasicAA/vscale.ll | 16 +++++++---------
2 files changed, 25 insertions(+), 13 deletions(-)
diff --git a/llvm/lib/Analysis/BasicAliasAnalysis.cpp b/llvm/lib/Analysis/BasicAliasAnalysis.cpp
index 7df62577e04db..6b874a1efd224 100644
--- a/llvm/lib/Analysis/BasicAliasAnalysis.cpp
+++ b/llvm/lib/Analysis/BasicAliasAnalysis.cpp
@@ -560,8 +560,10 @@ struct VariableGEPIndex {
struct BasicAAResult::DecomposedGEP {
// Base pointer of the GEP
const Value *Base;
- // Total constant offset from base.
+ // Total fixed constant offset from base.
APInt Offset;
+ // Coefficient of vscale in the constant offset from base.
+ APInt ScalableOffset;
// Scaled variable (non-constant) indices.
SmallVector<VariableGEPIndex, 4> VarIndices;
// Nowrap flags common to all GEP operations involved in expression.
@@ -575,6 +577,7 @@ struct BasicAAResult::DecomposedGEP {
OS << ", inbounds=" << (NWFlags.isInBounds() ? "1" : "0")
<< ", nuw=" << (NWFlags.hasNoUnsignedWrap() ? "1" : "0")
<< "(DecomposedGEP Base=" << Base->getName() << ", Offset=" << Offset
+ << ", ScalableOffset=" << ScalableOffset
<< ", VarIndices=[";
for (size_t i = 0; i < VarIndices.size(); i++) {
if (i != 0)
@@ -604,6 +607,7 @@ BasicAAResult::DecomposeGEPExpression(const Value *V, const DataLayout &DL,
unsigned IndexSize = DL.getIndexTypeSizeInBits(V->getType());
DecomposedGEP Decomposed;
Decomposed.Offset = APInt(IndexSize, 0);
+ Decomposed.ScalableOffset = APInt(IndexSize, 0);
do {
// See if this is a bitcast or GEP.
const Operator *Op = dyn_cast<Operator>(V);
@@ -692,11 +696,14 @@ BasicAAResult::DecomposeGEPExpression(const Value *V, const DataLayout &DL,
if (CIdx->isZero())
continue;
- // Don't attempt to analyze GEPs if the scalable index is not zero.
TypeSize AllocTypeSize = GTI.getSequentialElementStride(DL);
if (AllocTypeSize.isScalable()) {
- Decomposed.Base = V;
- return Decomposed;
+ // Keep constant scalable offsets separate from fixed offsets. This
+ // lets equal scalable terms cancel when two GEPs are compared.
+ Decomposed.ScalableOffset +=
+ APInt(IndexSize, AllocTypeSize.getKnownMinValue()) *
+ CIdx->getValue().sextOrTrunc(IndexSize);
+ continue;
}
Decomposed.Offset += AllocTypeSize.getFixedValue() *
@@ -1163,6 +1170,12 @@ AliasResult BasicAAResult::aliasGEP(
// symbolic difference.
subtractDecomposedGEPs(DecompGEP1, DecompGEP2, AAQI);
+ // Scalable offsets can be compared only after common terms cancel. Keep
+ // the existing fixed-offset reasoning for that useful case, and otherwise
+ // fall back to comparing the base objects.
+ if (!DecompGEP1.ScalableOffset.isZero())
+ return BaseObjectsAlias();
+
// If an inbounds GEP would have to start from an out of bounds address
// for the two to alias, then we can assume noalias.
// TODO: Remove !isScalable() once BasicAA fully support scalable location
@@ -1952,6 +1965,7 @@ void BasicAAResult::subtractDecomposedGEPs(DecomposedGEP &DestGEP,
DestGEP.NWFlags = DestGEP.NWFlags.withoutNoUnsignedWrap();
DestGEP.Offset -= SrcGEP.Offset;
+ DestGEP.ScalableOffset -= SrcGEP.ScalableOffset;
for (const VariableGEPIndex &Src : SrcGEP.VarIndices) {
// Find V in Dest. This is N^2, but pointer indices almost never have more
// than a few variable indexes.
diff --git a/llvm/test/Analysis/BasicAA/vscale.ll b/llvm/test/Analysis/BasicAA/vscale.ll
index 05b9b6b3c3a97..c08068df1a3a6 100644
--- a/llvm/test/Analysis/BasicAA/vscale.ll
+++ b/llvm/test/Analysis/BasicAA/vscale.ll
@@ -19,8 +19,7 @@ define void @gep_alloca_const_offset_1() {
; CHECK-LABEL: gep_alloca_const_offset_2
; CHECK-DAG: MayAlias: <vscale x 4 x i32>* %alloc, <vscale x 4 x i32>* %gep1
; CHECK-DAG: MayAlias: <vscale x 4 x i32>* %alloc, <vscale x 4 x i32>* %gep2
-; TODO: AliasResult for gep1,gep2 can be improved as MustAlias
-; CHECK-DAG: MayAlias: <vscale x 4 x i32>* %gep1, <vscale x 4 x i32>* %gep2
+; CHECK-DAG: MustAlias: <vscale x 4 x i32>* %gep1, <vscale x 4 x i32>* %gep2
define void @gep_alloca_const_offset_2() {
%alloc = alloca <vscale x 4 x i32>
%gep1 = getelementptr <vscale x 4 x i32>, ptr %alloc, i64 1
@@ -76,8 +75,7 @@ define void @gep_alloca_symbolic_offset(i64 %idx1, i64 %idx2) {
; CHECK-LABEL: gep_same_base_const_offset
; CHECK-DAG: MayAlias: i32* %gep1, <vscale x 4 x i32>* %p
; CHECK-DAG: MayAlias: i32* %gep2, <vscale x 4 x i32>* %p
-; TODO: AliasResult for gep1,gep2 can be improved as NoAlias
-; CHECK-DAG: MayAlias: i32* %gep1, i32* %gep2
+; CHECK-DAG: NoAlias: i32* %gep1, i32* %gep2
define void @gep_same_base_const_offset(ptr %p) {
%gep1 = getelementptr <vscale x 4 x i32>, ptr %p, i64 1, i64 0
%gep2 = getelementptr <vscale x 4 x i32>, ptr %p, i64 1, i64 1
@@ -171,7 +169,7 @@ define void @gep_bitcast_1(ptr %p) {
; CHECK-DAG: MayAlias: i32* %gep1, <vscale x 4 x i32>* %p
; CHECK-DAG: MayAlias: i32* %gep1, <vscale x 4 x float>* %p
; CHECK-DAG: MayAlias: float* %gep2, <vscale x 4 x i32>* %p
-; CHECK-DAG: MayAlias: i32* %gep1, float* %gep2
+; CHECK-DAG: MustAlias: i32* %gep1, float* %gep2
; CHECK-DAG: MayAlias: float* %gep2, <vscale x 4 x float>* %p
define void @gep_bitcast_2(ptr %p) {
%gep1 = getelementptr <vscale x 4 x i32>, ptr %p, i64 1, i64 0
@@ -216,7 +214,7 @@ define void @gep_neg_notscalable(ptr %p) vscale_range(1,16) {
; CHECK-DAG: MayAlias: <vscale x 4 x i32>* %p, <vscale x 4 x i32>* %vm16m16
; CHECK-DAG: MayAlias: <vscale x 4 x i32>* %vm16, <vscale x 4 x i32>* %vm16m16
; CHECK-DAG: MayAlias: <vscale x 4 x i32>* %m16, <vscale x 4 x i32>* %vm16m16
-; CHECK-DAG: MayAlias: <vscale x 4 x i32>* %m16pv16, <vscale x 4 x i32>* %p
+; CHECK-DAG: MustAlias: <vscale x 4 x i32>* %m16pv16, <vscale x 4 x i32>* %p
; CHECK-DAG: MayAlias: <vscale x 4 x i32>* %m16pv16, <vscale x 4 x i32>* %vm16
; CHECK-DAG: MayAlias: <vscale x 4 x i32>* %m16, <vscale x 4 x i32>* %m16pv16
; CHECK-DAG: MayAlias: <vscale x 4 x i32>* %m16pv16, <vscale x 4 x i32>* %vm16m16
@@ -240,9 +238,9 @@ define void @gep_neg_scalable(ptr %p) vscale_range(1,16) {
; CHECK-DAG: MayAlias: <4 x i32>* %p, <4 x i32>* %vm16m16
; CHECK-DAG: NoAlias: <4 x i32>* %vm16, <4 x i32>* %vm16m16
; CHECK-DAG: MayAlias: <4 x i32>* %m16, <4 x i32>* %vm16m16
-; CHECK-DAG: MayAlias: <4 x i32>* %m16pv16, <4 x i32>* %p
+; CHECK-DAG: MustAlias: <4 x i32>* %m16pv16, <4 x i32>* %p
; CHECK-DAG: MayAlias: <4 x i32>* %m16pv16, <4 x i32>* %vm16
-; CHECK-DAG: MayAlias: <4 x i32>* %m16, <4 x i32>* %m16pv16
+; CHECK-DAG: NoAlias: <4 x i32>* %m16, <4 x i32>* %m16pv16
; CHECK-DAG: MayAlias: <4 x i32>* %m16pv16, <4 x i32>* %vm16m16
define void @gep_pos_notscalable(ptr %p) vscale_range(1,16) {
%vm16 = getelementptr <vscale x 4 x i32>, ptr %p, i64 1
@@ -264,7 +262,7 @@ define void @gep_pos_notscalable(ptr %p) vscale_range(1,16) {
; CHECK-DAG: MayAlias: <vscale x 4 x i32>* %p, <vscale x 4 x i32>* %vm16m16
; CHECK-DAG: MayAlias: <vscale x 4 x i32>* %vm16, <vscale x 4 x i32>* %vm16m16
; CHECK-DAG: MayAlias: <vscale x 4 x i32>* %m16, <vscale x 4 x i32>* %vm16m16
-; CHECK-DAG: MayAlias: <vscale x 4 x i32>* %m16pv16, <vscale x 4 x i32>* %p
+; CHECK-DAG: MustAlias: <vscale x 4 x i32>* %m16pv16, <vscale x 4 x i32>* %p
; CHECK-DAG: MayAlias: <vscale x 4 x i32>* %m16pv16, <vscale x 4 x i32>* %vm16
; CHECK-DAG: MayAlias: <vscale x 4 x i32>* %m16, <vscale x 4 x i32>* %m16pv16
; CHECK-DAG: MayAlias: <vscale x 4 x i32>* %m16pv16, <vscale x 4 x i32>* %vm16m16
>From ca4fdd3392fafca95376d7a68a6cdda946c2eb53 Mon Sep 17 00:00:00 2001
From: SomeFlyingThing <306498559+SomeFlyingThing at users.noreply.github.com>
Date: Sun, 23 Aug 2026 18:01:18 +1200
Subject: [PATCH 2/2] [BasicAA] Apply clang-format
---
llvm/lib/Analysis/BasicAliasAnalysis.cpp | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/llvm/lib/Analysis/BasicAliasAnalysis.cpp b/llvm/lib/Analysis/BasicAliasAnalysis.cpp
index 6b874a1efd224..ef316c6beb94c 100644
--- a/llvm/lib/Analysis/BasicAliasAnalysis.cpp
+++ b/llvm/lib/Analysis/BasicAliasAnalysis.cpp
@@ -577,8 +577,7 @@ struct BasicAAResult::DecomposedGEP {
OS << ", inbounds=" << (NWFlags.isInBounds() ? "1" : "0")
<< ", nuw=" << (NWFlags.hasNoUnsignedWrap() ? "1" : "0")
<< "(DecomposedGEP Base=" << Base->getName() << ", Offset=" << Offset
- << ", ScalableOffset=" << ScalableOffset
- << ", VarIndices=[";
+ << ", ScalableOffset=" << ScalableOffset << ", VarIndices=[";
for (size_t i = 0; i < VarIndices.size(); i++) {
if (i != 0)
OS << ", ";
More information about the llvm-commits
mailing list