[llvm] [BasicAA] Preserve constant offset correlations through select indices (PR #228778)

Dávid Bolvanský via llvm-commits llvm-commits at lists.llvm.org
Sat Oct 3 14:54:01 PDT 2026


https://github.com/davidbolvansky created https://github.com/llvm/llvm-project/pull/228778

BasicAA currently returns `MayAlias` for accesses indexed by `select(c, x + 1, x + 2)` and `x + 3`, despite their disjoint offsets.

Check constant differences between matching linear expressions in each select alternative, with a budget of eight comparisons. This resolves the existing `select_in_gep2` TODO to `NoAlias`; compile-time tracker results are neutral.


>From 9fcc3f729efe6dbe6183bf24d2d6c9c1c3d9eb48 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?D=C3=A1vid=20Bolvansk=C3=BD?= <david.bolvansky at gmail.com>
Date: Sat, 3 Oct 2026 23:06:24 +0200
Subject: [PATCH] [BasicAA] Check constant offsets in select index alternatives

---
 llvm/lib/Analysis/BasicAliasAnalysis.cpp      | 32 +++++++++++++++++++
 .../test/Analysis/BasicAA/non-equal-select.ll |  3 +-
 2 files changed, 33 insertions(+), 2 deletions(-)

diff --git a/llvm/lib/Analysis/BasicAliasAnalysis.cpp b/llvm/lib/Analysis/BasicAliasAnalysis.cpp
index 3aece3ca7d769..d6eaa2aa4dda7 100644
--- a/llvm/lib/Analysis/BasicAliasAnalysis.cpp
+++ b/llvm/lib/Analysis/BasicAliasAnalysis.cpp
@@ -2107,6 +2107,38 @@ bool BasicAAResult::computeConstantOffsetHeuristic(const DecomposedGEP &GEP,
       Var0.Val.V->getType() != Var1.Val.V->getType())
     return false;
 
+  // Without extensions, matching linear expressions have an exact modular
+  // difference. Check each select alternative before losing that correlation.
+  if (!AAQI.MayBeCrossIteration && !Var0.Val.ZExtBits && !Var0.Val.SExtBits &&
+      Var0.Val.getBitWidth() == GEP.Offset.getBitWidth() &&
+      (isa<SelectInst>(Var0.Val.V) || isa<SelectInst>(Var1.Val.V))) {
+    unsigned Budget = 8;
+    auto Check = [&](auto &&Check, const Value *V0, const Value *V1) -> bool {
+      if (!Budget)
+        return false;
+      --Budget;
+      LinearExpression E0 = GetLinearExpression(CastedValue(V0), DL, 0, AC, DT);
+      LinearExpression E1 = GetLinearExpression(CastedValue(V1), DL, 0, AC, DT);
+      if (E0.Scale == E1.Scale && E0.Val.hasSameCastsAs(E1.Val) &&
+          isValueEqualInPotentialCycles(E0.Val.V, E1.Val.V, AAQI)) {
+        APInt Offset = (E0.Offset - E1.Offset) * Var0.Scale;
+        if (Var0.IsNegated)
+          Offset = -Offset;
+        Offset += GEP.Offset;
+        return Offset.uge(V2Size) && (-Offset).uge(V1Size);
+      }
+      if (const auto *SI = dyn_cast<SelectInst>(V0))
+        return Check(Check, SI->getTrueValue(), V1) &&
+               Check(Check, SI->getFalseValue(), V1);
+      if (const auto *SI = dyn_cast<SelectInst>(V1))
+        return Check(Check, V0, SI->getTrueValue()) &&
+               Check(Check, V0, SI->getFalseValue());
+      return false;
+    };
+    if (Check(Check, Var0.Val.V, Var1.Val.V))
+      return true;
+  }
+
   // We'll strip off the Extensions of Var0 and Var1 and do another round
   // of GetLinearExpression decomposition. In the example above, if Var0
   // is zext(%x + 1) we should get V1 == %x and V1Offset == 1.
diff --git a/llvm/test/Analysis/BasicAA/non-equal-select.ll b/llvm/test/Analysis/BasicAA/non-equal-select.ll
index fe38a57eeb1b4..76986fbf4e0e1 100644
--- a/llvm/test/Analysis/BasicAA/non-equal-select.ll
+++ b/llvm/test/Analysis/BasicAA/non-equal-select.ll
@@ -17,9 +17,8 @@ entry:
 
 define void @select_in_gep2(i1 %c, i64 %x) {
 entry:
-  ; TODO: should be "NoAlias" here as well.
 ; CHECK-LABEL: Function: select_in_gep2
-; CHECK: MayAlias:     i32* %arrayidx1, i32* %arrayidx2
+; CHECK: NoAlias:      i32* %arrayidx1, i32* %arrayidx2
   %add1_ = add nsw i64 %x, 1
   %add2_ = add nsw i64 %x, 2
   %add3_ = add nsw i64 %x, 3



More information about the llvm-commits mailing list