[llvm] [LAA] Add stencil group merging to reduce runtime pointer checks (PR #187252)

Igor Kirillov via llvm-commits llvm-commits at lists.llvm.org
Wed May 13 02:16:45 PDT 2026


================
@@ -737,6 +752,367 @@ void RuntimePointerChecking::groupChecks(
   }
 }
 
+/// Result of decomposing a SCEV expression into stencil offset form:
+///   Offset = Constant + sum(Coefficients[stride] * stride)
+/// where each stride is a loop-invariant SCEV expression.
+struct StencilDecomposition {
+  int64_t Constant = 0;
+  /// Map from loop-invariant stride SCEV to its integer coefficient.
+  SmallMapVector<const SCEV *, int64_t, 4> Coefficients;
+};
+
+/// Try to decompose \p Expr into a stencil offset function of loop-invariant
+/// strides: C + a1*s1 + a2*s2 + ...
+/// Relies on SCEV's canonical form: AddExpr operands are flattened,
+/// MulExpr has the constant operand first.
+/// Returns std::nullopt if the expression contains non-stencil terms.
+static std::optional<StencilDecomposition>
+decomposeStencilOffset(const SCEV *Expr, ScalarEvolution &SE, const Loop &L) {
+  StencilDecomposition D;
+
+  // Collect top-level additive terms.
+  SmallVector<const SCEV *, 4> Terms;
+  if (auto *Add = dyn_cast<SCEVAddExpr>(Expr))
+    Terms.append(Add->operands().begin(), Add->operands().end());
+  else
+    Terms.push_back(Expr);
+
+  for (const SCEV *Term : Terms) {
+    if (auto *C = dyn_cast<SCEVConstant>(Term)) {
+      D.Constant += C->getAPInt().getSExtValue();
+    } else if (auto *Mul = dyn_cast<SCEVMulExpr>(Term)) {
+      // SCEV canonical form: constant is operand 0 in a MulExpr.
+      if (Mul->getNumOperands() != 2)
----------------
igogo-x86 wrote:

Yes. `8 * a * b` where both `a` and `b` are loop-invariant canonicalises to a single 3-operand `SCEVMulExpr(8, a, b)` (constant first, then the rest). My code treats this as not-decomposable, so the DepSet gets skipped.

The original motivating workload does not need this. There the strides come in as `(C * (sext i32 (...) to i64))`, where the i32 multiplication of the grid dimensions happens inside the `sext`, so the outer `SCEVMulExpr` is already binary (constant × opaque-loop-invariant).

Supporting n-operand `SCEVMulExpr` is not that simple; I can do that as a follow-up patch if needed.

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


More information about the llvm-commits mailing list