[llvm] [BasicAA] Handle scalable type sizes with constant offsets (PR #80445)
David Green via llvm-commits
llvm-commits at lists.llvm.org
Mon Feb 5 02:01:47 PST 2024
https://github.com/davemgreen updated https://github.com/llvm/llvm-project/pull/80445
>From 7805c3ebd6384413b70430dc54f05c44939c7ec1 Mon Sep 17 00:00:00 2001
From: David Green <david.green at arm.com>
Date: Mon, 5 Feb 2024 09:59:32 +0000
Subject: [PATCH] [BasicAA] Handle scalable type sizes with constant offsets
This is a separate, but related issue to #69152 that was attempting to improve
AA with scalable dependency distances. This patch attempts to improve when
there are scalable accesses with a constant offset between them. We happen to
get a report of such a thing recently, where so long as the vscale_range is
known, the maximum size of the access can be assessed and better aliasing
results can be returned.
The Upper range of the vscale_range, along with known part of the typesize are
used to prove that Off >= CR.upper * LSize. It does not try to produce
PartialAlias results at the moment from the lower vscale_range.
---
llvm/lib/Analysis/BasicAliasAnalysis.cpp | 46 ++++++++++++--------
llvm/test/Analysis/AliasSet/memloc-vscale.ll | 3 +-
llvm/test/Analysis/BasicAA/vscale.ll | 14 +++---
3 files changed, 37 insertions(+), 26 deletions(-)
diff --git a/llvm/lib/Analysis/BasicAliasAnalysis.cpp b/llvm/lib/Analysis/BasicAliasAnalysis.cpp
index 1028b52a79123..19c4393add6ab 100644
--- a/llvm/lib/Analysis/BasicAliasAnalysis.cpp
+++ b/llvm/lib/Analysis/BasicAliasAnalysis.cpp
@@ -1113,10 +1113,6 @@ AliasResult BasicAAResult::aliasGEP(
return BaseAlias;
}
- // Bail on analysing scalable LocationSize
- if (V1Size.isScalable() || V2Size.isScalable())
- return AliasResult::MayAlias;
-
// If there is a constant difference between the pointers, but the difference
// is less than the size of the associated memory object, then we know
// that the objects are partially overlapping. If the difference is
@@ -1146,24 +1142,38 @@ AliasResult BasicAAResult::aliasGEP(
if (!VLeftSize.hasValue())
return AliasResult::MayAlias;
- const uint64_t LSize = VLeftSize.getValue();
- if (Off.ult(LSize)) {
- // Conservatively drop processing if a phi was visited and/or offset is
- // too big.
- AliasResult AR = AliasResult::PartialAlias;
- if (VRightSize.hasValue() && Off.ule(INT32_MAX) &&
- (Off + VRightSize.getValue()).ule(LSize)) {
- // Memory referenced by right pointer is nested. Save the offset in
- // cache. Note that originally offset estimated as GEP1-V2, but
- // AliasResult contains the shift that represents GEP1+Offset=V2.
- AR.setOffset(-Off.getSExtValue());
- AR.swap(Swapped);
+ const TypeSize LSize = VLeftSize.getValue();
+ if (!LSize.isScalable()) {
+ if (Off.ult(LSize)) {
+ // Conservatively drop processing if a phi was visited and/or offset is
+ // too big.
+ AliasResult AR = AliasResult::PartialAlias;
+ if (VRightSize.hasValue() && !VRightSize.isScalable() &&
+ Off.ule(INT32_MAX) && (Off + VRightSize.getValue()).ule(LSize)) {
+ // Memory referenced by right pointer is nested. Save the offset in
+ // cache. Note that originally offset estimated as GEP1-V2, but
+ // AliasResult contains the shift that represents GEP1+Offset=V2.
+ AR.setOffset(-Off.getSExtValue());
+ AR.swap(Swapped);
+ }
+ return AR;
}
- return AR;
+ return AliasResult::NoAlias;
+ } else {
+ // We can use the getVScaleRange to prove that Off >= (CR.upper * LSize).
+ ConstantRange CR = getVScaleRange(&F, Off.getBitWidth());
+ bool Overflow;
+ APInt UpperRange = CR.getUnsignedMax().umul_ov(
+ APInt(Off.getBitWidth(), LSize.getKnownMinValue()), Overflow);
+ if (!Overflow && Off.uge(UpperRange))
+ return AliasResult::NoAlias;
}
- return AliasResult::NoAlias;
}
+ // Bail on analysing scalable LocationSize
+ if (V1Size.isScalable() || V2Size.isScalable())
+ return AliasResult::MayAlias;
+
// We need to know both acess sizes for all the following heuristics.
if (!V1Size.hasValue() || !V2Size.hasValue())
return AliasResult::MayAlias;
diff --git a/llvm/test/Analysis/AliasSet/memloc-vscale.ll b/llvm/test/Analysis/AliasSet/memloc-vscale.ll
index 1c7ca79c8db11..6b41604637405 100644
--- a/llvm/test/Analysis/AliasSet/memloc-vscale.ll
+++ b/llvm/test/Analysis/AliasSet/memloc-vscale.ll
@@ -34,7 +34,8 @@ define void @ss2(ptr %p) {
ret void
}
; CHECK-LABEL: Alias sets for function 'son':
-; CHECK: AliasSet[{{.*}}, 2] may alias, Mod Memory locations: (ptr %g, LocationSize::precise(vscale x 16)), (ptr %p, LocationSize::precise(8))
+; CHECK: AliasSet[{{.*}}, 1] must alias, Mod Memory locations: (ptr %g, LocationSize::precise(vscale x 16))
+; CHECK: AliasSet[{{.*}}, 1] must alias, Mod Memory locations: (ptr %p, LocationSize::precise(8))
define void @son(ptr %p) {
%g = getelementptr i8, ptr %p, i64 8
store <vscale x 2 x i64> zeroinitializer, ptr %g, align 2
diff --git a/llvm/test/Analysis/BasicAA/vscale.ll b/llvm/test/Analysis/BasicAA/vscale.ll
index 5c3c185af9141..339e4400abc0f 100644
--- a/llvm/test/Analysis/BasicAA/vscale.ll
+++ b/llvm/test/Analysis/BasicAA/vscale.ll
@@ -292,7 +292,7 @@ define void @gep_pos_scalable(ptr %p) vscale_range(1,16) {
; CHECK-DAG: MayAlias: <vscale x 4 x i32>* %m16, <4 x i32>* %p
; CHECK-DAG: MayAlias: <vscale x 4 x i32>* %m16, <vscale x 4 x i32>* %vm16
; CHECK-DAG: MayAlias: <vscale x 4 x i32>* %m16, <4 x i32>* %vm16
-; CHECK-DAG: MayAlias: <4 x i32>* %m16, <vscale x 4 x i32>* %p
+; CHECK-DAG: NoAlias: <4 x i32>* %m16, <vscale x 4 x i32>* %p
; CHECK-DAG: NoAlias: <4 x i32>* %m16, <4 x i32>* %p
; CHECK-DAG: MayAlias: <4 x i32>* %m16, <vscale x 4 x i32>* %vm16
; CHECK-DAG: MayAlias: <4 x i32>* %m16, <4 x i32>* %vm16
@@ -453,14 +453,14 @@ define void @gep_2048(ptr %p) {
; CHECK-LABEL: gep_2048_vscalerange
; CHECK-DAG: MayAlias: <vscale x 4 x i32>* %off255, <vscale x 4 x i32>* %p
; CHECK-DAG: MayAlias: <vscale x 4 x i32>* %noff255, <vscale x 4 x i32>* %p
-; CHECK-DAG: MayAlias: <vscale x 4 x i32>* %noff255, <vscale x 4 x i32>* %off255
-; CHECK-DAG: MayAlias: <vscale x 4 x i32>* %off256, <vscale x 4 x i32>* %p
+; CHECK-DAG: NoAlias: <vscale x 4 x i32>* %noff255, <vscale x 4 x i32>* %off255
+; CHECK-DAG: NoAlias: <vscale x 4 x i32>* %off256, <vscale x 4 x i32>* %p
; CHECK-DAG: MayAlias: <vscale x 4 x i32>* %off255, <vscale x 4 x i32>* %off256
-; CHECK-DAG: MayAlias: <vscale x 4 x i32>* %noff255, <vscale x 4 x i32>* %off256
-; CHECK-DAG: MayAlias: <vscale x 4 x i32>* %noff256, <vscale x 4 x i32>* %p
-; CHECK-DAG: MayAlias: <vscale x 4 x i32>* %noff256, <vscale x 4 x i32>* %off255
+; CHECK-DAG: NoAlias: <vscale x 4 x i32>* %noff255, <vscale x 4 x i32>* %off256
+; CHECK-DAG: NoAlias: <vscale x 4 x i32>* %noff256, <vscale x 4 x i32>* %p
+; CHECK-DAG: NoAlias: <vscale x 4 x i32>* %noff256, <vscale x 4 x i32>* %off255
; CHECK-DAG: MayAlias: <vscale x 4 x i32>* %noff255, <vscale x 4 x i32>* %noff256
-; CHECK-DAG: MayAlias: <vscale x 4 x i32>* %noff256, <vscale x 4 x i32>* %off256
+; CHECK-DAG: NoAlias: <vscale x 4 x i32>* %noff256, <vscale x 4 x i32>* %off256
define void @gep_2048_vscalerange(ptr %p) vscale_range(1,16) {
%off255 = getelementptr i8, ptr %p, i64 255
%noff255 = getelementptr i8, ptr %p, i64 -255
More information about the llvm-commits
mailing list