[llvm] [ConstraintElim] Skip overflowing row combinations in FM elimination. (PR #208404)

Florian Hahn via llvm-commits llvm-commits at lists.llvm.org
Thu Jul 9 02:27:08 PDT 2026


https://github.com/fhahn created https://github.com/llvm/llvm-project/pull/208404

The constraint system uses 64-bit coefficients and previously aborted the entire elimination as soon as a single row combination overflowed.

This is unnecessary pessimistic and can lead to lost optimizations if the system contains constraints with large coefficients which do not contribute to a particular solution (e.g. signed wrap checks).

Instead, skip only the overflowing row combination and continue.

Compile-time impact is in the noise:
https://llvm-compile-time-tracker.com/compare.php?from=4f41b6be1a89796d6ce89188a4fd4e0cde9d06b7&to=1dedecc1cefea9c94631cdb272717d898ac6696b&stat=instructions:u

>From b09d7f001ed84f123a307e24782ee6a793112dc1 Mon Sep 17 00:00:00 2001
From: Florian Hahn <flo at fhahn.com>
Date: Sun, 5 Jul 2026 08:32:46 +0100
Subject: [PATCH] [ConstraintElim] Skip overflowing row combinations in FM
 elimination.

The constraint system uses 64-bit coefficients and previously aborted
the entire elimination as soon as a single row combination overflowed.

This is unnecessary pessimistic and can lead to lost optimizations if
the system contains constraints with large coefficients which do not
contribute to a particular solution (e.g. signed wrap checks).

Instead, skip only the overflowing row combination and continue.

Compile-time impact is in the noise:
https://llvm-compile-time-tracker.com/compare.php?from=4f41b6be1a89796d6ce89188a4fd4e0cde9d06b7&to=1dedecc1cefea9c94631cdb272717d898ac6696b&stat=instructions:u
---
 llvm/lib/Analysis/ConstraintSystem.cpp        | 23 +++++++++++++------
 .../constraint-overflow.ll                    |  6 ++---
 2 files changed, 18 insertions(+), 11 deletions(-)

diff --git a/llvm/lib/Analysis/ConstraintSystem.cpp b/llvm/lib/Analysis/ConstraintSystem.cpp
index 62545586b3554..bc08e76cf4753 100644
--- a/llvm/lib/Analysis/ConstraintSystem.cpp
+++ b/llvm/lib/Analysis/ConstraintSystem.cpp
@@ -79,6 +79,9 @@ bool ConstraintSystem::eliminateUsingFM() {
       unsigned IdxLower = 0;
       auto &LowerRow = RemainingRows[LowerR];
       auto &UpperRow = RemainingRows[UpperR];
+      // Combine the two rows to eliminate the variable. If any coefficient
+      // computation overflows, skip them.
+      bool Overflow = false;
       // Update constant and coefficients of both constraints.
       // Stops until every coefficient is updated or overflows.
       while (true) {
@@ -101,15 +104,19 @@ bool ConstraintSystem::eliminateUsingFM() {
           IdxUpper++;
         }
 
-        if (MulOverflow(UpperV, -1 * LowerLast, M1))
-          return false;
+        if (MulOverflow(UpperV, -1 * LowerLast, M1)) {
+          Overflow = true;
+          break;
+        }
         if (IdxLower < LowerRow.size() && LowerRow[IdxLower].Id == CurrentId) {
           LowerV = LowerRow[IdxLower].Coefficient;
           IdxLower++;
         }
 
-        if (MulOverflow(LowerV, UpperLast, M2))
-          return false;
+        if (MulOverflow(LowerV, UpperLast, M2)) {
+          Overflow = true;
+          break;
+        }
         // This algorithm is a variant of sparse Gaussian elimination.
         //
         // The new coefficient for CurrentId is
@@ -124,14 +131,16 @@ bool ConstraintSystem::eliminateUsingFM() {
         //
         // Eliminates y after addition:
         // N: { 6, 7, 0 } => 6 >= 7 * x
-        if (AddOverflow(M1, M2, N))
-          return false;
+        if (AddOverflow(M1, M2, N)) {
+          Overflow = true;
+          break;
+        }
         // Skip variable that is completely eliminated.
         if (N == 0)
           continue;
         NR.emplace_back(N, CurrentId);
       }
-      if (NR.empty())
+      if (Overflow || NR.empty())
         continue;
       Constraints.push_back(std::move(NR));
       // Give up if the new system gets too big.
diff --git a/llvm/test/Transforms/ConstraintElimination/constraint-overflow.ll b/llvm/test/Transforms/ConstraintElimination/constraint-overflow.ll
index 044e24feba4e9..008e2ba222fce 100644
--- a/llvm/test/Transforms/ConstraintElimination/constraint-overflow.ll
+++ b/llvm/test/Transforms/ConstraintElimination/constraint-overflow.ll
@@ -13,8 +13,7 @@ define i32 @f(i64 %a3, i64 %numElements) {
 ; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i64 [[A1]], [[A3]]
 ; CHECK-NEXT:    br i1 [[CMP]], label [[IF_END_I:%.*]], label [[ABORT:%.*]]
 ; CHECK:       if.end.i:
-; CHECK-NEXT:    [[CMP2_NOT_I:%.*]] = icmp ult i64 [[A1]], [[A3]]
-; CHECK-NEXT:    br i1 [[CMP2_NOT_I]], label [[ABORT]], label [[EXIT:%.*]]
+; CHECK-NEXT:    br i1 false, label [[ABORT]], label [[EXIT:%.*]]
 ; CHECK:       abort:
 ; CHECK-NEXT:    ret i32 -1
 ; CHECK:       exit:
@@ -90,8 +89,7 @@ define i1 @fm_overflow_recovery(i64 %n, i64 %i, i64 %lim) {
 ; CHECK-NEXT:    [[F2:%.*]] = icmp ult i64 [[N4M4]], [[LIM]]
 ; CHECK-NEXT:    call void @llvm.assume(i1 [[F2]])
 ; CHECK-NEXT:    [[I4:%.*]] = shl nuw i64 [[I]], 2
-; CHECK-NEXT:    [[C:%.*]] = icmp ult i64 [[I4]], [[LIM]]
-; CHECK-NEXT:    ret i1 [[C]]
+; CHECK-NEXT:    ret i1 true
 ;
 entry:
   %big = icmp ule i64 %n, 2305843009213693952



More information about the llvm-commits mailing list