[llvm] [BasicAA] Extend two-variable MinAbsVarIndex heuristic to different scales (PR #218639)

Antonio Frighetto via llvm-commits llvm-commits at lists.llvm.org
Wed Sep 9 05:09:35 PDT 2026


================
@@ -2018,14 +2036,48 @@ std::optional<APInt> BasicAAResult::computeMinAbsVarOffset(
     // inequality of values across loop iterations.
     const VariableGEPIndex &Var0 = VarIndices[0];
     const VariableGEPIndex &Var1 = VarIndices[1];
-    if (Var0.hasNegatedScaleOf(Var1) && Var0.Val.TruncBits == 0 &&
-        Var0.Val.hasSameCastsAs(Var1.Val) && !AAQI.MayBeCrossIteration &&
-        MultiplyByScaleNoWrap(Var0) && MultiplyByScaleNoWrap(Var1) &&
+    bool Preconditions =
+        Var0.Val.TruncBits == 0 && Var0.Val.hasSameCastsAs(Var1.Val) &&
+        !AAQI.MayBeCrossIteration && MultiplyByScaleNoWrap(Var0) &&
+        MultiplyByScaleNoWrap(Var1);
+    if (Var0.hasNegatedScaleOf(Var1) && Preconditions &&
         isKnownNonEqual(Var0.Val.V, Var1.Val.V,
                         SimplifyQuery(DL, DT, &AC, /*CxtI=*/Var0.CxtI
                                                        ? Var0.CxtI
                                                        : Var1.CxtI)))
       return Var0.Scale.abs();
+
+    if (!Preconditions)
+      return std::nullopt;
+
+    // On the chance we have not found a min abs, fallback to the generalization
+    // of the two variables case being handled to different scales:
+    // VarIndex = Scale0*V0 + (-Scale1)*V1 = ScaleGCD*(C0*V0 - C1*V1)
+    // where C0 = abs(Scale0)/ScaleGCD, C1 = abs(Scale1)/ScaleGCD.
+    // If C0*V0 != C1*V1, then abs(VarIndex) >= ScaleGCD, leading to the min
+    // absolute value being ScaleGCD.
+
+    // Ensure scales, after subtraction, have opposite signs.
+    bool EffectiveNeg0 = Var0.IsNegated ^ Var0.Scale.isNegative();
+    bool EffectiveNeg1 = Var1.IsNegated ^ Var1.Scale.isNegative();
+    if (EffectiveNeg0 != EffectiveNeg1) {
+      APInt AbsScale0 = Var0.Scale.abs();
+      APInt AbsScale1 = Var1.Scale.abs();
+      APInt ScaleGCD = APIntOps::GreatestCommonDivisor(AbsScale0, AbsScale1);
----------------
antoniofrighetto wrote:

I think that might require refactoring the GCD computation in analyzeVariableOffsets(), as the precomputed GCD may have been adjusted by the known trailing zeroes of one of the variable indices; and it looks like directly reusing it would be unsound.

For instance, in the snippet in https://alive2.llvm.org/ce/z/fDcNJD, `Scale1 = 3` is shifted left by 1, so we precompute `GCD(2, 6) = 2` (rather than the GCD of the scales, i.e.,`GCD(2, 3) = 1`). Using 2 as GCD would yield to `C0 = 2/2 = 1` and `C1 = 3/2 = 1`, causing it to reason about `2*(i − j)` while the actual offset is `2*i − 3*j` (thus incorrectly concluding NoAlias). Not sure if that would end up being cleaner.

https://github.com/llvm/llvm-project/pull/218639


More information about the llvm-commits mailing list