Skip to content

Commit db22e70

Browse files
committed
[ConstraintSolver] Add isConditionImplied helper.
This patch adds a isConditionImplied function that takes a constraint and returns true if the constraint is implied by the current constraints in the system. Reviewed By: spatel Differential Revision: https://reviews.llvm.org/D84545
1 parent 98e07b5 commit db22e70

File tree

3 files changed

+93
-1
lines changed

3 files changed

+93
-1
lines changed

llvm/include/llvm/Analysis/ConstraintSystem.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,17 @@ class ConstraintSystem {
5151

5252
/// Returns true if there may be a solution for the constraints in the system.
5353
bool mayHaveSolution();
54+
55+
static SmallVector<int64_t, 8> negate(SmallVector<int64_t, 8> R) {
56+
// The negated constraint R is obtained by multiplying by -1 and adding 1 to
57+
// the constant.
58+
R[0] += 1;
59+
for (auto &C : R)
60+
C *= -1;
61+
return R;
62+
}
63+
64+
bool isConditionImplied(SmallVector<int64_t, 8> R);
5465
};
5566
} // namespace llvm
5667

llvm/lib/Analysis/ConstraintSystem.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,3 +140,13 @@ bool ConstraintSystem::mayHaveSolution() {
140140
LLVM_DEBUG(dbgs() << (HasSolution ? "sat" : "unsat") << "\n");
141141
return HasSolution;
142142
}
143+
144+
bool ConstraintSystem::isConditionImplied(SmallVector<int64_t, 8> R) {
145+
// If there is no solution with the negation of R added to the system, the
146+
// condition must hold based on the existing constraints.
147+
R = ConstraintSystem::negate(R);
148+
149+
auto NewSystem = *this;
150+
NewSystem.addVariableRow(R);
151+
return !NewSystem.mayHaveSolution();
152+
}

llvm/unittests/Analysis/ConstraintSystemTest.cpp

Lines changed: 72 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ using namespace llvm;
1313

1414
namespace {
1515

16-
TEST(ConstraintSloverTest, TestSolutionChecks) {
16+
TEST(ConstraintSolverTest, TestSolutionChecks) {
1717
{
1818
ConstraintSystem CS;
1919
// x + y <= 10, x >= 5, y >= 6, x <= 10, y <= 10
@@ -79,4 +79,75 @@ TEST(ConstraintSloverTest, TestSolutionChecks) {
7979
EXPECT_TRUE(CS.mayHaveSolution());
8080
}
8181
}
82+
83+
TEST(ConstraintSolverTest, IsConditionImplied) {
84+
{
85+
// For the test below, we assume we know
86+
// x <= 5 && y <= 3
87+
ConstraintSystem CS;
88+
CS.addVariableRow({5, 1, 0});
89+
CS.addVariableRow({3, 0, 1});
90+
91+
// x + y <= 6 does not hold.
92+
EXPECT_FALSE(CS.isConditionImplied({6, 1, 1}));
93+
// x + y <= 7 does not hold.
94+
EXPECT_FALSE(CS.isConditionImplied({7, 1, 1}));
95+
// x + y <= 8 does hold.
96+
EXPECT_TRUE(CS.isConditionImplied({8, 1, 1}));
97+
98+
// 2 * x + y <= 12 does hold.
99+
EXPECT_FALSE(CS.isConditionImplied({12, 2, 1}));
100+
// 2 * x + y <= 13 does hold.
101+
EXPECT_TRUE(CS.isConditionImplied({13, 2, 1}));
102+
103+
// x + y <= 12 does hold.
104+
EXPECT_FALSE(CS.isConditionImplied({12, 2, 1}));
105+
// 2 * x + y <= 13 does hold.
106+
EXPECT_TRUE(CS.isConditionImplied({13, 2, 1}));
107+
108+
// x <= y == x - y <= 0 does not hold.
109+
EXPECT_FALSE(CS.isConditionImplied({0, 1, -1}));
110+
// y <= x == -x + y <= 0 does not hold.
111+
EXPECT_FALSE(CS.isConditionImplied({0, -1, 1}));
112+
}
113+
114+
{
115+
// For the test below, we assume we know
116+
// x + 1 <= y + 1 == x - y <= 0
117+
ConstraintSystem CS;
118+
CS.addVariableRow({0, 1, -1});
119+
120+
// x <= y == x - y <= 0 does hold.
121+
EXPECT_TRUE(CS.isConditionImplied({0, 1, -1}));
122+
// y <= x == -x + y <= 0 does not hold.
123+
EXPECT_FALSE(CS.isConditionImplied({0, -1, 1}));
124+
125+
// x <= y + 10 == x - y <= 10 does hold.
126+
EXPECT_TRUE(CS.isConditionImplied({10, 1, -1}));
127+
// x + 10 <= y == x - y <= -10 does NOT hold.
128+
EXPECT_FALSE(CS.isConditionImplied({-10, 1, -1}));
129+
}
130+
131+
{
132+
// For the test below, we assume we know
133+
// x <= y == x - y <= 0
134+
// y <= z == y - x <= 0
135+
ConstraintSystem CS;
136+
CS.addVariableRow({0, 1, -1, 0});
137+
CS.addVariableRow({0, 0, 1, -1});
138+
139+
// z <= y == -y + z <= 0 does not hold.
140+
EXPECT_FALSE(CS.isConditionImplied({0, 0, -1, 1}));
141+
// x <= z == x - z <= 0 does hold.
142+
EXPECT_TRUE(CS.isConditionImplied({0, 1, 0, -1}));
143+
}
144+
}
145+
146+
TEST(ConstraintSolverTest, IsConditionImpliedOverflow) {
147+
ConstraintSystem CS;
148+
// Make sure isConditionImplied returns false when there is an overflow.
149+
int64_t Limit = std::numeric_limits<int64_t>::max();
150+
CS.addVariableRow({Limit - 1, Limit - 2, Limit - 3});
151+
EXPECT_FALSE(CS.isConditionImplied({Limit - 1, Limit - 2, Limit - 3}));
152+
}
82153
} // namespace

0 commit comments

Comments
 (0)