[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