[llvm] be26b1a - [ConstraintElim] Skip rows implied by a single existing row. (#227688)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Oct 1 04:32:28 PDT 2026
Author: Florian Hahn
Date: 2026-10-01T11:32:17Z
New Revision: be26b1af2bd9c18be1477ca5b828157a4cefebc3
URL: https://github.com/llvm/llvm-project/commit/be26b1af2bd9c18be1477ca5b828157a4cefebc3
DIFF: https://github.com/llvm/llvm-project/commit/be26b1af2bd9c18be1477ca5b828157a4cefebc3.diff
LOG: [ConstraintElim] Skip rows implied by a single existing row. (#227688)
There are a number of cases where we add duplicated rows (e.g. from
transferring facts between the signed and unsigned systems, or from
tightening a non-strict bound using !=).
Before adding rows, check if the system already has a row that the same
variable coefficient and a constant that is <= the current constant.
This helps reduce compile-time, as each row adds extra work during
constraint solving:
stage1-O3: -0.02%
stage1-ReleaseThinLTO: -0.05%
stage1-ReleaseLTO-g: -0.02%
stage1-aarch64-O3: -0.00%
stage2-O3: -0.01%
stage2-clang: -0.00%
https://llvm-compile-time-tracker.com/compare.php?from=5da194580292bc90f6577f3959dda3a9bb6d5366&to=67f7d35c131b156663342cfae20d55e7a4187196&stat=instructions:u
The impact depends on the specific module and mostly in cases where the
number of facts is on the larger side. See additional compile-time
impact here
https://github.com/dtcxzyw/llvm-opt-benchmark-nightly/pull/1527
Fewer rows in the system can improve results in a few cases where we
previously hit the maximum rows cutoff:
https://github.com/dtcxzyw/llvm-opt-benchmark-nightly/pull/1526.
PR: https://github.com/llvm/llvm-project/pull/227688
Added:
Modified:
llvm/include/llvm/Analysis/ConstraintSystem.h
llvm/lib/Analysis/ConstraintSystem.cpp
llvm/lib/Transforms/Scalar/ConstraintElimination.cpp
llvm/unittests/Analysis/ConstraintSystemTest.cpp
Removed:
################################################################################
diff --git a/llvm/include/llvm/Analysis/ConstraintSystem.h b/llvm/include/llvm/Analysis/ConstraintSystem.h
index 11f40de9968c5..c14e0fbd8b9cf 100644
--- a/llvm/include/llvm/Analysis/ConstraintSystem.h
+++ b/llvm/include/llvm/Analysis/ConstraintSystem.h
@@ -155,6 +155,9 @@ class ConstraintSystem {
LLVM_ABI std::pair<ConstraintSystem, RowTy>
getSubSystem(ArrayRef<Entry> R) const;
+ /// Returns true if a single row of the system implies \p R.
+ LLVM_ABI bool isImpliedBySingleRow(ArrayRef<Entry> R) const;
+
LLVM_ABI bool isConditionImplied(RowTy R) const;
LLVM_ABI bool isConditionImpliedInSubSystem(ArrayRef<Entry> R) const;
diff --git a/llvm/lib/Analysis/ConstraintSystem.cpp b/llvm/lib/Analysis/ConstraintSystem.cpp
index 85ac780b5f720..c659b4de3bb13 100644
--- a/llvm/lib/Analysis/ConstraintSystem.cpp
+++ b/llvm/lib/Analysis/ConstraintSystem.cpp
@@ -279,6 +279,21 @@ ConstraintSystem::getSubSystem(ArrayRef<Entry> R) const {
return {std::move(SubSystem), std::move(NewR)};
}
+bool ConstraintSystem::isImpliedBySingleRow(ArrayRef<Entry> R) const {
+ int64_t C = getConstant(R);
+ if (hasConstantEntry(R))
+ R = R.drop_front();
+ return any_of(Constraints, [&](ArrayRef<Entry> Row) {
+ if (getConstant(Row) > C)
+ return false;
+ if (hasConstantEntry(Row))
+ Row = Row.drop_front();
+ return equal(Row, R, [](const Entry &A, const Entry &B) {
+ return A.Id == B.Id && A.Coefficient == B.Coefficient;
+ });
+ });
+}
+
bool ConstraintSystem::isConditionImplied(RowTy R) const {
// If all variable coefficients are 0, we have 'C >= 0'. If the constant is >=
// 0, R is always true, regardless of the system.
diff --git a/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp b/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp
index f58bc933d1de2..16ecfd3a76068 100644
--- a/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp
+++ b/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp
@@ -2268,9 +2268,14 @@ void ConstraintInfo::addFactImpl(CmpInst::Predicate Pred, Value *A, Value *B,
if (R.empty() || R.isNe())
return;
+ auto &CSToUse = getCS(R.IsSigned);
+ // A row implied by a single existing row adds no information. Rows in the
+ // system are removed in reverse order, so the existing row outlives R.
+ if (!R.isEq() && NewVariables.empty() &&
+ CSToUse.isImpliedBySingleRow(R.Coefficients))
+ return;
LLVM_DEBUG(dbgs() << "Adding '"; dumpUnpackedICmp(dbgs(), Pred, A, B);
dbgs() << "'\n");
- auto &CSToUse = getCS(R.IsSigned);
bool Added = CSToUse.addRow(R.Coefficients, R.NumVars);
if (!Added)
return;
diff --git a/llvm/unittests/Analysis/ConstraintSystemTest.cpp b/llvm/unittests/Analysis/ConstraintSystemTest.cpp
index a40131d4d2809..edd7fdd89aac3 100644
--- a/llvm/unittests/Analysis/ConstraintSystemTest.cpp
+++ b/llvm/unittests/Analysis/ConstraintSystemTest.cpp
@@ -169,6 +169,29 @@ TEST(ConstraintSolverTest, IsConditionImplied) {
}
}
+TEST(ConstraintSolverTest, IsImpliedBySingleRow) {
+ ConstraintSystem CS;
+ // x - y <= 0, y <= 5
+ addVariableRow(CS, {0, 1, -1});
+ addVariableRow(CS, {5, 0, 1});
+
+ // The same row, or one with a larger constant.
+ EXPECT_TRUE(CS.isImpliedBySingleRow(toRow({0, 1, -1})));
+ EXPECT_TRUE(CS.isImpliedBySingleRow(toRow({1, 1, -1})));
+ EXPECT_TRUE(CS.isImpliedBySingleRow(toRow({5, 0, 1})));
+ EXPECT_TRUE(CS.isImpliedBySingleRow(toRow({7, 0, 1})));
+ // A smaller constant.
+ EXPECT_FALSE(CS.isImpliedBySingleRow(toRow({-1, 1, -1})));
+ EXPECT_FALSE(CS.isImpliedBySingleRow(toRow({4, 0, 1})));
+ // Different coefficients.
+ EXPECT_FALSE(CS.isImpliedBySingleRow(toRow({0, 2, -2})));
+ EXPECT_FALSE(CS.isImpliedBySingleRow(toRow({0, -1, 1})));
+ EXPECT_FALSE(CS.isImpliedBySingleRow(toRow({5, 1, 1})));
+ // x <= 5 is implied by both rows together, but not by a single one.
+ EXPECT_TRUE(isConditionImplied(CS, {5, 1, 0}));
+ EXPECT_FALSE(CS.isImpliedBySingleRow(toRow({5, 1, 0})));
+}
+
TEST(ConstraintSolverTest, IsConditionImpliedOverflow) {
ConstraintSystem CS;
// Make sure isConditionImplied returns false when there is an overflow.
More information about the llvm-commits
mailing list