[llvm] [DA] runtime predicates for delinearization bounds checks (PR #170713)

Sjoerd Meijer via llvm-commits llvm-commits at lists.llvm.org
Fri Dec 5 08:26:39 PST 2025


================
@@ -753,37 +753,137 @@ static bool isKnownLessThan(ScalarEvolution *SE, const SCEV *S,
   return SE->isKnownNegative(LimitedBound);
 }
 
-bool llvm::validateDelinearizationResult(ScalarEvolution &SE,
-                                         ArrayRef<const SCEV *> Sizes,
-                                         ArrayRef<const SCEV *> Subscripts,
-                                         const Value *Ptr) {
+bool llvm::validateDelinearizationResult(
+    ScalarEvolution &SE, ArrayRef<const SCEV *> Sizes,
+    ArrayRef<const SCEV *> Subscripts, const Value *Ptr,
+    SmallVectorImpl<const SCEVPredicate *> *Assume) {
   // Sizes and Subscripts are as follows:
-  //
   //   Sizes:      [UNK][S_2]...[S_n]
   //   Subscripts: [I_1][I_2]...[I_n]
   //
   // where the size of the outermost dimension is unknown (UNK).
 
-  auto AddOverflow = [&](const SCEV *A, const SCEV *B) -> const SCEV * {
-    if (!SE.willNotOverflow(Instruction::Add, /*IsSigned=*/true, A, B))
+  // Unify types of two SCEVs to the wider type.
+  auto UnifyTypes =
+      [&](const SCEV *&A,
+          const SCEV *&B) -> std::pair<const SCEV *, const SCEV *> {
+    Type *WiderType = SE.getWiderType(A->getType(), B->getType());
+    return {SE.getNoopOrSignExtend(A, WiderType),
+            SE.getNoopOrSignExtend(B, WiderType)};
+  };
+
+  // Get a type with twice the bit width of T.
+  auto GetWiderType = [&](Type *T) -> Type * {
+    unsigned BitWidth = SE.getTypeSizeInBits(T);
+    return IntegerType::get(T->getContext(), BitWidth * 2);
+  };
+
+  // Check if the result of A + B (signed) does not overflow. If it can be
+  // proven at compile-time, return the result. If it might overflow and Assume
+  // is provided, add a runtime equality predicate and return the result.
+  // Otherwise return nullptr.
+  auto AddNoOverflow = [&](const SCEV *A, const SCEV *B) -> const SCEV * {
+    std::tie(A, B) = UnifyTypes(A, B);
+    if (SE.willNotOverflow(Instruction::Add, /*IsSigned=*/true, A, B))
+      return SE.getAddExpr(A, B);
+    if (!Assume)
       return nullptr;
-    return SE.getAddExpr(A, B);
+
+    // Compute the addition in a wider type to detect overflow.
+    // If (sext A) + (sext B) == sext(A + B), then A + B does not overflow.
----------------
sjoerdmeijer wrote:

Is exactly this not implemented in [ScalarEvolution::willNotOverflow()](https://llvm.org/doxygen/classllvm_1_1ScalarEvolution.html#a267fd27cb9e177fa5f48cbb8828339a1)?
Can we use that instead of roll our own?

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


More information about the llvm-commits mailing list