[llvm] [BasicAA] Account for wrapping when using abs(Scale*V0 + (-Scale)*V1) >= abs(Scale) (PR #137755)

Craig Topper via llvm-commits llvm-commits at lists.llvm.org
Tue Apr 29 08:58:29 PDT 2025


https://github.com/topperc updated https://github.com/llvm/llvm-project/pull/137755

>From 9a0cb9035b1e9b325badf113fc6f16edbefbac43 Mon Sep 17 00:00:00 2001
From: Craig Topper <craig.topper at sifive.com>
Date: Mon, 28 Apr 2025 22:14:43 -0700
Subject: [PATCH 1/3] precommit testcase

---
 llvm/test/Analysis/BasicAA/gep-modulo.ll | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/llvm/test/Analysis/BasicAA/gep-modulo.ll b/llvm/test/Analysis/BasicAA/gep-modulo.ll
index 159aaf94039d3..6309ef86e58a0 100644
--- a/llvm/test/Analysis/BasicAA/gep-modulo.ll
+++ b/llvm/test/Analysis/BasicAA/gep-modulo.ll
@@ -393,3 +393,17 @@ entry:
 }
 
 declare void @llvm.assume(i1)
+
+define i64 @mul_may_overflow_var_nonzero_minabsvarindex_two_index(i64 %arg, ptr %arg1) {
+; CHECK-LABEL:  Function: mul_may_overflow_var_nonzero_minabsvarindex_two_index
+; CHECK-LABEL:  NoAlias:      i64* %getelementptr, i64* %getelementptr2
+bb:
+  %xor = xor i64 %arg, -9223372036854775808
+  %getelementptr = getelementptr i64, ptr %arg1, i64 %xor
+  %load = load i64, ptr %getelementptr, align 8
+  %getelementptr2 = getelementptr i64, ptr %arg1, i64 %arg
+  store i64 1, ptr %getelementptr2, align 8
+  %load3 = load i64, ptr %getelementptr, align 8
+  %mul = mul i64 %load, %load3
+  ret i64 %mul
+}

>From b5b9544b71b262ea33658493e0659aa0215b1010 Mon Sep 17 00:00:00 2001
From: Craig Topper <craig.topper at sifive.com>
Date: Fri, 25 Apr 2025 16:21:16 -0700
Subject: [PATCH 2/3] [BasicAA] Account for wrapping when using abs(Scale*V0 +
 (-Scale)*V1) >= abs(Scale)

Similar to 1b7ef6aac8a3cad245c0ed14fe21725e31261f73, add a check to
only set MinAbsVarIndex if abs(Scale*V0) and abs((-Scale)*V1) won't
wrap. In the absence of IsNSW, try to use the bitwidths of the
original V and Scale to rule out wrapping
---
 llvm/lib/Analysis/BasicAliasAnalysis.cpp | 36 +++++++++++++-----------
 llvm/test/Analysis/BasicAA/gep-modulo.ll |  2 +-
 2 files changed, 20 insertions(+), 18 deletions(-)

diff --git a/llvm/lib/Analysis/BasicAliasAnalysis.cpp b/llvm/lib/Analysis/BasicAliasAnalysis.cpp
index cbec13c7808be..03977551afadd 100644
--- a/llvm/lib/Analysis/BasicAliasAnalysis.cpp
+++ b/llvm/lib/Analysis/BasicAliasAnalysis.cpp
@@ -1301,6 +1301,23 @@ AliasResult BasicAAResult::aliasGEP(
   if (Range1.intersectWith(Range2).isEmptySet())
     return AliasResult::NoAlias;
 
+  // Check if abs(V*Scale) >= abs(Scale) holds in the presence of
+  // potentially wrapping math.
+  auto MultiplyByScaleNoWrap = [](const VariableGEPIndex &Var) {
+    if (Var.IsNSW)
+      return true;
+
+    int ValOrigBW = Var.Val.V->getType()->getPrimitiveSizeInBits();
+    // If Scale is small enough so that abs(V*Scale) >= abs(Scale) holds.
+    // The max value of abs(V) is 2^ValOrigBW - 1. Multiplying with a
+    // constant smaller than 2^(bitwidth(Val) - ValOrigBW) won't wrap.
+    int MaxScaleValueBW = Var.Val.getBitWidth() - ValOrigBW;
+    if (MaxScaleValueBW <= 0)
+      return false;
+    return Var.Scale.ule(
+        APInt::getMaxValue(MaxScaleValueBW).zext(Var.Scale.getBitWidth()));
+  };
+
   // Try to determine the range of values for VarIndex such that
   // VarIndex <= -MinAbsVarIndex || MinAbsVarIndex <= VarIndex.
   std::optional<APInt> MinAbsVarIndex;
@@ -1309,22 +1326,6 @@ AliasResult BasicAAResult::aliasGEP(
     const VariableGEPIndex &Var = DecompGEP1.VarIndices[0];
     if (Var.Val.TruncBits == 0 &&
         isKnownNonZero(Var.Val.V, SimplifyQuery(DL, DT, &AC, Var.CxtI))) {
-      // Check if abs(V*Scale) >= abs(Scale) holds in the presence of
-      // potentially wrapping math.
-      auto MultiplyByScaleNoWrap = [](const VariableGEPIndex &Var) {
-        if (Var.IsNSW)
-          return true;
-
-        int ValOrigBW = Var.Val.V->getType()->getPrimitiveSizeInBits();
-        // If Scale is small enough so that abs(V*Scale) >= abs(Scale) holds.
-        // The max value of abs(V) is 2^ValOrigBW - 1. Multiplying with a
-        // constant smaller than 2^(bitwidth(Val) - ValOrigBW) won't wrap.
-        int MaxScaleValueBW = Var.Val.getBitWidth() - ValOrigBW;
-        if (MaxScaleValueBW <= 0)
-          return false;
-        return Var.Scale.ule(
-            APInt::getMaxValue(MaxScaleValueBW).zext(Var.Scale.getBitWidth()));
-      };
       // Refine MinAbsVarIndex, if abs(Scale*V) >= abs(Scale) holds in the
       // presence of potentially wrapping math.
       if (MultiplyByScaleNoWrap(Var)) {
@@ -1345,7 +1346,8 @@ AliasResult BasicAAResult::aliasGEP(
                         SimplifyQuery(DL, DT, &AC, /*CxtI=*/Var0.CxtI
                                                        ? Var0.CxtI
                                                        : Var1.CxtI)))
-      MinAbsVarIndex = Var0.Scale.abs();
+      if (MultiplyByScaleNoWrap(Var0) && MultiplyByScaleNoWrap(Var1))
+        MinAbsVarIndex = Var0.Scale.abs();
   }
 
   if (MinAbsVarIndex) {
diff --git a/llvm/test/Analysis/BasicAA/gep-modulo.ll b/llvm/test/Analysis/BasicAA/gep-modulo.ll
index 6309ef86e58a0..9ca69b2d7bbdd 100644
--- a/llvm/test/Analysis/BasicAA/gep-modulo.ll
+++ b/llvm/test/Analysis/BasicAA/gep-modulo.ll
@@ -396,7 +396,7 @@ declare void @llvm.assume(i1)
 
 define i64 @mul_may_overflow_var_nonzero_minabsvarindex_two_index(i64 %arg, ptr %arg1) {
 ; CHECK-LABEL:  Function: mul_may_overflow_var_nonzero_minabsvarindex_two_index
-; CHECK-LABEL:  NoAlias:      i64* %getelementptr, i64* %getelementptr2
+; CHECK-LABEL:  MayAlias:      i64* %getelementptr, i64* %getelementptr2
 bb:
   %xor = xor i64 %arg, -9223372036854775808
   %getelementptr = getelementptr i64, ptr %arg1, i64 %xor

>From 7f184fa319bfb10ff2bc43d3a5b594aeef074ee9 Mon Sep 17 00:00:00 2001
From: Craig Topper <craig.topper at sifive.com>
Date: Tue, 29 Apr 2025 08:58:01 -0700
Subject: [PATCH 3/3] fixup! reorder checks.

---
 llvm/lib/Analysis/BasicAliasAnalysis.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/llvm/lib/Analysis/BasicAliasAnalysis.cpp b/llvm/lib/Analysis/BasicAliasAnalysis.cpp
index 03977551afadd..a46edc0b75f54 100644
--- a/llvm/lib/Analysis/BasicAliasAnalysis.cpp
+++ b/llvm/lib/Analysis/BasicAliasAnalysis.cpp
@@ -1342,12 +1342,12 @@ AliasResult BasicAAResult::aliasGEP(
     const VariableGEPIndex &Var1 = DecompGEP1.VarIndices[1];
     if (Var0.hasNegatedScaleOf(Var1) && Var0.Val.TruncBits == 0 &&
         Var0.Val.hasSameCastsAs(Var1.Val) && !AAQI.MayBeCrossIteration &&
+        MultiplyByScaleNoWrap(Var0) && MultiplyByScaleNoWrap(Var1) &&
         isKnownNonEqual(Var0.Val.V, Var1.Val.V,
                         SimplifyQuery(DL, DT, &AC, /*CxtI=*/Var0.CxtI
                                                        ? Var0.CxtI
                                                        : Var1.CxtI)))
-      if (MultiplyByScaleNoWrap(Var0) && MultiplyByScaleNoWrap(Var1))
-        MinAbsVarIndex = Var0.Scale.abs();
+      MinAbsVarIndex = Var0.Scale.abs();
   }
 
   if (MinAbsVarIndex) {



More information about the llvm-commits mailing list