[llvm] e146e27 - [ConstraintElim] Use largest usable bound to check no-wrap regions. (#222295)

via llvm-commits llvm-commits at lists.llvm.org
Wed Sep 9 10:51:29 PDT 2026


Author: Florian Hahn
Date: 2026-09-09T17:51:23Z
New Revision: e146e27ab993d013ab16a706f0fd84ab3818b575

URL: https://github.com/llvm/llvm-project/commit/e146e27ab993d013ab16a706f0fd84ab3818b575
DIFF: https://github.com/llvm/llvm-project/commit/e146e27ab993d013ab16a706f0fd84ab3818b575.diff

LOG: [ConstraintElim] Use largest usable bound to check no-wrap regions. (#222295)

The unsigned no-wrap region of an add with a constant operand has
UMAX - C as upper bound. For 64 bit operations, the upper bound is
usually larger than MaxConstraintValue, so it will be decomposed as
variable instead of a constant value.

This improves results end-to-end in a few more cases, without any
additional queries:
https://github.com/dtcxzyw/llvm-opt-benchmark-nightly/pull/1234.

PR: https://github.com/llvm/llvm-project/pull/222295

Added: 
    

Modified: 
    llvm/lib/Transforms/Scalar/ConstraintElimination.cpp
    llvm/test/Transforms/ConstraintElimination/add-nsw.ll
    llvm/test/Transforms/ConstraintElimination/pr70510.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp b/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp
index e33c6c3fdd116..3f96887d16fec 100644
--- a/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp
+++ b/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp
@@ -1361,6 +1361,10 @@ static bool doesHoldInRange(const ConstraintInfo &Info, Value *Op,
                         : APInt::getMinValue(BitWidth);
   APInt MaxVal = Signed ? APInt::getSignedMaxValue(BitWidth)
                         : APInt::getMaxValue(BitWidth);
+  // Replace bound too large to be decomposed by the largest usable one.
+  if (!Signed && Max.uge(MaxConstraintValue))
+    Max = APInt(BitWidth, MaxConstraintValue - 1);
+
   Type *Ty = Op->getType();
   if (Min != MinVal &&
       !Info.doesHold(Signed ? CmpInst::ICMP_SGE : CmpInst::ICMP_UGE, Op,

diff  --git a/llvm/test/Transforms/ConstraintElimination/add-nsw.ll b/llvm/test/Transforms/ConstraintElimination/add-nsw.ll
index 34a6ea0910e03..8d9c61cb0c7c5 100644
--- a/llvm/test/Transforms/ConstraintElimination/add-nsw.ll
+++ b/llvm/test/Transforms/ConstraintElimination/add-nsw.ll
@@ -1166,3 +1166,42 @@ define i8 @add_nsw_no_nuw(i8 %x) {
   %add = add nsw i8 %x, 20
   ret i8 %add
 }
+
+; %x <=u 100 implies %x + 3 does not wrap unsigned.
+define i64 @add_i64_gains_nuw_with_large_bound(i64 %x) {
+; CHECK-LABEL: @add_i64_gains_nuw_with_large_bound(
+; CHECK-NEXT:    [[C:%.*]] = icmp ule i64 [[X:%.*]], 100
+; CHECK-NEXT:    call void @llvm.assume(i1 [[C]])
+; CHECK-NEXT:    [[ADD:%.*]] = add nuw nsw i64 [[X]], 3
+; CHECK-NEXT:    ret i64 [[ADD]]
+;
+  %c = icmp ule i64 %x, 100
+  call void @llvm.assume(i1 %c)
+  %add = add i64 %x, 3
+  ret i64 %add
+}
+
+; No bound on %x, so no flags can be added.
+define i64 @add_i64_no_bound(i64 %x) {
+; CHECK-LABEL: @add_i64_no_bound(
+; CHECK-NEXT:    [[ADD:%.*]] = add i64 [[X:%.*]], 3
+; CHECK-NEXT:    ret i64 [[ADD]]
+;
+  %add = add i64 %x, 3
+  ret i64 %add
+}
+
+; %x <=u 2^63 also implies %x + 3 does not wrap unsigned, but the assumed bound
+; is too large to represent as constant in the constraint system.
+define i64 @add_i64_bound_above_max_constraint_value(i64 %x) {
+; CHECK-LABEL: @add_i64_bound_above_max_constraint_value(
+; CHECK-NEXT:    [[C:%.*]] = icmp ule i64 [[X:%.*]], -9223372036854775808
+; CHECK-NEXT:    call void @llvm.assume(i1 [[C]])
+; CHECK-NEXT:    [[ADD:%.*]] = add i64 [[X]], 3
+; CHECK-NEXT:    ret i64 [[ADD]]
+;
+  %c = icmp ule i64 %x, -9223372036854775808
+  call void @llvm.assume(i1 %c)
+  %add = add i64 %x, 3
+  ret i64 %add
+}

diff  --git a/llvm/test/Transforms/ConstraintElimination/pr70510.ll b/llvm/test/Transforms/ConstraintElimination/pr70510.ll
index 31d0a85d8c210..99e69383709f0 100644
--- a/llvm/test/Transforms/ConstraintElimination/pr70510.ll
+++ b/llvm/test/Transforms/ConstraintElimination/pr70510.ll
@@ -13,7 +13,7 @@ define i32 @test_loop_varying_bound_add_rec() {
 ; CHECK-NEXT:    br i1 [[CMP6]], label [[EXIT1:%.*]], label [[FOR_LATCH]]
 ; CHECK:       for.latch:
 ; CHECK-NEXT:    [[IND2_I]] = add i64 [[IND2]], 1
-; CHECK-NEXT:    [[IND1_I]] = add nsw i64 [[IND1]], 1
+; CHECK-NEXT:    [[IND1_I]] = add nuw nsw i64 [[IND1]], 1
 ; CHECK-NEXT:    [[COND:%.*]] = icmp eq i64 [[IND1_I]], 8
 ; CHECK-NEXT:    br i1 [[COND]], label [[EXIT2:%.*]], label [[FOR_HEADER]]
 ; CHECK:       exit2:
@@ -60,7 +60,7 @@ define i32 @test_loop_varying_bound_call() {
 ; CHECK-NEXT:    [[CMP6:%.*]] = icmp eq i64 [[IND1]], [[VAL]]
 ; CHECK-NEXT:    br i1 [[CMP6]], label [[EXIT1:%.*]], label [[FOR_LATCH]]
 ; CHECK:       for.latch:
-; CHECK-NEXT:    [[IND1_I]] = add nsw i64 [[IND1]], 1
+; CHECK-NEXT:    [[IND1_I]] = add nuw nsw i64 [[IND1]], 1
 ; CHECK-NEXT:    [[COND:%.*]] = icmp eq i64 [[IND1_I]], 8
 ; CHECK-NEXT:    br i1 [[COND]], label [[EXIT2:%.*]], label [[FOR_HEADER]]
 ; CHECK:       exit2:


        


More information about the llvm-commits mailing list