[llvm] [BasicAA] Check for Overflow using vscale_range (PR #81144)
David Green via llvm-commits
llvm-commits at lists.llvm.org
Thu Feb 8 07:30:26 PST 2024
https://github.com/davemgreen created https://github.com/llvm/llvm-project/pull/81144
This extends #80818 when IsNSW is lost (possibly due to looking through multiple GEPs), to check the vscale_range for an access that will not overflow even with the maximum range.
>From 4b2f7f830fb3c9478340c95c03a4e2f18c069b09 Mon Sep 17 00:00:00 2001
From: David Green <david.green at arm.com>
Date: Thu, 8 Feb 2024 12:39:25 +0000
Subject: [PATCH 1/2] [BasicAA] Add extra onevscale test for multiple dependent
geps that lose the NSW flag. NFC
---
llvm/test/Analysis/BasicAA/vscale.ll | 20 +++++++++++++++++++-
1 file changed, 19 insertions(+), 1 deletion(-)
diff --git a/llvm/test/Analysis/BasicAA/vscale.ll b/llvm/test/Analysis/BasicAA/vscale.ll
index ce0c6f145d1c88..7a28858f4a7acc 100644
--- a/llvm/test/Analysis/BasicAA/vscale.ll
+++ b/llvm/test/Analysis/BasicAA/vscale.ll
@@ -458,11 +458,29 @@ define void @vscale_v1v2types(ptr %p) {
ret void
}
+; CHECK-LABEL: onevscale
+; CHECK-DAG: MustAlias: <vscale x 4 x i32>* %vp161, <vscale x 4 x i32>* %vp162
+; CHECK-DAG: MayAlias: <vscale x 4 x i32>* %vp161, <vscale x 4 x i32>* %vp161b
+; CHECK-DAG: MayAlias: <vscale x 4 x i32>* %vp161b, <vscale x 4 x i32>* %vp162
+define void @onevscale(ptr %p) vscale_range(1,16) {
+ %v1 = call i64 @llvm.vscale.i64()
+ %vp1 = mul nsw i64 %v1, 16
+ %vp2 = mul nsw i64 %v1, 16
+ %vp3 = mul nsw i64 %v1, 17
+ %vp161 = getelementptr i8, ptr %p, i64 %vp1
+ %vp162 = getelementptr i8, ptr %p, i64 %vp2
+ %vp161b = getelementptr i8, ptr %vp161, i64 %vp3
+ load <vscale x 4 x i32>, ptr %vp161
+ load <vscale x 4 x i32>, ptr %vp162
+ load <vscale x 4 x i32>, ptr %vp161b
+ ret void
+}
+
; CHECK-LABEL: twovscales
; CHECK-DAG: MayAlias: <vscale x 4 x i32>* %vp161, <vscale x 4 x i32>* %vp162
; CHECK-DAG: MayAlias: <vscale x 4 x i32>* %vp161, <vscale x 4 x i32>* %vp161b
; CHECK-DAG: MayAlias: <vscale x 4 x i32>* %vp161b, <vscale x 4 x i32>* %vp162
-define void @twovscales(ptr %p) {
+define void @twovscales(ptr %p) vscale_range(1,16) {
%v1 = call i64 @llvm.vscale.i64()
%v2 = call i64 @llvm.vscale.i64()
%vp1 = mul nsw i64 %v1, 16
>From 05624b3aa9a84bccae46f5b0303b16b1fe6323db Mon Sep 17 00:00:00 2001
From: David Green <david.green at arm.com>
Date: Thu, 8 Feb 2024 15:26:34 +0000
Subject: [PATCH 2/2] [BasicAA] Test for Overflow using vscale_range
This extends #80818 when IsNSW is lost (possibly due to looking through
multiple GEPs), to check the vscale_range for an access that will not overflow
even with the maximum range.
---
llvm/lib/Analysis/BasicAliasAnalysis.cpp | 24 +++++++++++++++++-------
llvm/test/Analysis/BasicAA/vscale.ll | 6 +++---
2 files changed, 20 insertions(+), 10 deletions(-)
diff --git a/llvm/lib/Analysis/BasicAliasAnalysis.cpp b/llvm/lib/Analysis/BasicAliasAnalysis.cpp
index ae31814bb06735..38dba376ae6c55 100644
--- a/llvm/lib/Analysis/BasicAliasAnalysis.cpp
+++ b/llvm/lib/Analysis/BasicAliasAnalysis.cpp
@@ -1173,7 +1173,7 @@ AliasResult BasicAAResult::aliasGEP(
// VScale Alias Analysis - Given one scalable offset between accesses and a
// scalable typesize, we can divide each side by vscale, treating both values
// as a constant. We prove that Offset/vscale >= TypeSize/vscale.
- if (DecompGEP1.VarIndices.size() == 1 && DecompGEP1.VarIndices[0].IsNSW &&
+ if (DecompGEP1.VarIndices.size() == 1 &&
DecompGEP1.VarIndices[0].Val.TruncBits == 0 &&
DecompGEP1.Offset.isZero() &&
PatternMatch::match(DecompGEP1.VarIndices[0].Val.V,
@@ -1183,12 +1183,22 @@ AliasResult BasicAAResult::aliasGEP(
ScalableVar.IsNegated ? -ScalableVar.Scale : ScalableVar.Scale;
LocationSize VLeftSize = Scale.isNegative() ? V1Size : V2Size;
- // Note that we do not check that the typesize is scalable, as vscale >= 1
- // so noalias still holds so long as the dependency distance is at least as
- // big as the typesize.
- if (VLeftSize.hasValue() &&
- Scale.uge(VLeftSize.getValue().getKnownMinValue()))
- return AliasResult::NoAlias;
+ // Check if the offset is known to not overflow, if it does then attempt to
+ // prove it with the known values of vscale_range.
+ bool Overflows = !DecompGEP1.VarIndices[0].IsNSW;
+ if (Overflows) {
+ ConstantRange CR = getVScaleRange(&F, Scale.getBitWidth());
+ (void)CR.getSignedMax().smul_ov(Scale, Overflows);
+ }
+
+ if (!Overflows) {
+ // Note that we do not check that the typesize is scalable, as vscale >= 1
+ // so noalias still holds so long as the dependency distance is at least as
+ // big as the typesize.
+ if (VLeftSize.hasValue() &&
+ Scale.uge(VLeftSize.getValue().getKnownMinValue()))
+ return AliasResult::NoAlias;
+ }
}
// Bail on analysing scalable LocationSize
diff --git a/llvm/test/Analysis/BasicAA/vscale.ll b/llvm/test/Analysis/BasicAA/vscale.ll
index 7a28858f4a7acc..15a2d01c88d3b6 100644
--- a/llvm/test/Analysis/BasicAA/vscale.ll
+++ b/llvm/test/Analysis/BasicAA/vscale.ll
@@ -460,8 +460,8 @@ define void @vscale_v1v2types(ptr %p) {
; CHECK-LABEL: onevscale
; CHECK-DAG: MustAlias: <vscale x 4 x i32>* %vp161, <vscale x 4 x i32>* %vp162
-; CHECK-DAG: MayAlias: <vscale x 4 x i32>* %vp161, <vscale x 4 x i32>* %vp161b
-; CHECK-DAG: MayAlias: <vscale x 4 x i32>* %vp161b, <vscale x 4 x i32>* %vp162
+; CHECK-DAG: NoAlias: <vscale x 4 x i32>* %vp161, <vscale x 4 x i32>* %vp161b
+; CHECK-DAG: NoAlias: <vscale x 4 x i32>* %vp161b, <vscale x 4 x i32>* %vp162
define void @onevscale(ptr %p) vscale_range(1,16) {
%v1 = call i64 @llvm.vscale.i64()
%vp1 = mul nsw i64 %v1, 16
@@ -478,7 +478,7 @@ define void @onevscale(ptr %p) vscale_range(1,16) {
; CHECK-LABEL: twovscales
; CHECK-DAG: MayAlias: <vscale x 4 x i32>* %vp161, <vscale x 4 x i32>* %vp162
-; CHECK-DAG: MayAlias: <vscale x 4 x i32>* %vp161, <vscale x 4 x i32>* %vp161b
+; CHECK-DAG: NoAlias: <vscale x 4 x i32>* %vp161, <vscale x 4 x i32>* %vp161b
; CHECK-DAG: MayAlias: <vscale x 4 x i32>* %vp161b, <vscale x 4 x i32>* %vp162
define void @twovscales(ptr %p) vscale_range(1,16) {
%v1 = call i64 @llvm.vscale.i64()
More information about the llvm-commits
mailing list