[llvm] 0b28d75 - [ConstraintElimination] Add support for EQ predicates.
Florian Hahn via llvm-commits
llvm-commits at lists.llvm.org
Mon Feb 1 12:53:52 PST 2021
Author: Florian Hahn
Date: 2021-02-01T20:48:31Z
New Revision: 0b28d756af183b9f294ddca5432a0ad5054ac9c2
URL: https://github.com/llvm/llvm-project/commit/0b28d756af183b9f294ddca5432a0ad5054ac9c2
DIFF: https://github.com/llvm/llvm-project/commit/0b28d756af183b9f294ddca5432a0ad5054ac9c2.diff
LOG: [ConstraintElimination] Add support for EQ predicates.
A == B map to A >= B && A <= B
(https://alive2.llvm.org/ce/z/_dwxKn).
This extends the constraint construction to return a list of
constraints, which can be used to properly de-compose nested AND & OR.
Added:
Modified:
llvm/lib/Transforms/Scalar/ConstraintElimination.cpp
llvm/test/Transforms/ConstraintElimination/eq.ll
Removed:
################################################################################
diff --git a/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp b/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp
index dc105e4eaaa7..84c3ec98b029 100644
--- a/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp
+++ b/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp
@@ -92,10 +92,19 @@ static SmallVector<std::pair<int64_t, Value *>, 4> decompose(Value *V) {
return {{0, nullptr}, {1, V}};
}
+struct ConstraintTy {
+ SmallVector<int64_t, 8> Coefficients;
+
+ ConstraintTy(SmallVector<int64_t, 8> Coefficients)
+ : Coefficients(Coefficients) {}
+
+ unsigned size() const { return Coefficients.size(); }
+};
+
/// Turn a condition \p CmpI into a constraint vector, using indices from \p
/// Value2Index. If \p ShouldAdd is true, new indices are added for values not
/// yet in \p Value2Index.
-static SmallVector<int64_t, 8>
+static SmallVector<ConstraintTy, 4>
getConstraint(CmpInst::Predicate Pred, Value *Op0, Value *Op1,
DenseMap<Value *, unsigned> &Value2Index, bool ShouldAdd) {
int64_t Offset1 = 0;
@@ -117,6 +126,13 @@ getConstraint(CmpInst::Predicate Pred, Value *Op0, Value *Op1,
return getConstraint(CmpInst::getSwappedPredicate(Pred), Op1, Op0,
Value2Index, ShouldAdd);
+ if (Pred == CmpInst::ICMP_EQ) {
+ auto A = getConstraint(CmpInst::ICMP_UGE, Op0, Op1, Value2Index, ShouldAdd);
+ auto B = getConstraint(CmpInst::ICMP_ULE, Op0, Op1, Value2Index, ShouldAdd);
+ append_range(A, B);
+ return A;
+ }
+
// Only ULE and ULT predicates are supported at the moment.
if (Pred != CmpInst::ICMP_ULE && Pred != CmpInst::ICMP_ULT)
return {};
@@ -156,10 +172,10 @@ getConstraint(CmpInst::Predicate Pred, Value *Op0, Value *Op1,
R[Value2Index[KV.second]] -= KV.first;
R[0] = Offset1 + Offset2 + (Pred == CmpInst::ICMP_ULT ? -1 : 0);
- return R;
+ return {R};
}
-static SmallVector<int64_t, 8>
+static SmallVector<ConstraintTy, 4>
getConstraint(CmpInst *Cmp, DenseMap<Value *, unsigned> &Value2Index,
bool ShouldAdd) {
return getConstraint(Cmp->getPredicate(), Cmp->getOperand(0),
@@ -301,9 +317,9 @@ static bool eliminateConstraints(Function &F, DominatorTree &DT) {
if (!Cmp)
continue;
auto R = getConstraint(Cmp, Value2Index, false);
- if (R.empty() || R.size() == 1)
+ if (R.size() != 1 || R[0].size() == 1)
continue;
- if (CS.isConditionImplied(R)) {
+ if (CS.isConditionImplied(R[0].Coefficients)) {
if (!DebugCounter::shouldExecute(EliminatedCounter))
continue;
@@ -318,7 +334,8 @@ static bool eliminateConstraints(Function &F, DominatorTree &DT) {
NumCondsRemoved++;
Changed = true;
}
- if (CS.isConditionImplied(ConstraintSystem::negate(R))) {
+ if (CS.isConditionImplied(
+ ConstraintSystem::negate(R[0].Coefficients))) {
if (!DebugCounter::shouldExecute(EliminatedCounter))
continue;
@@ -360,11 +377,16 @@ static bool eliminateConstraints(Function &F, DominatorTree &DT) {
continue;
LLVM_DEBUG(dbgs() << "Adding " << *CB.Condition << " " << CB.Not << "\n");
-
- // If R has been added to the system, queue it for removal once it goes
- // out-of-scope.
- if (CS.addVariableRowFill(R))
- DFSInStack.emplace_back(CB.NumIn, CB.NumOut, CB.Condition, CB.Not);
+ bool Added = false;
+ for (auto &C : R) {
+ auto Coeffs = C.Coefficients;
+
+ Added |= CS.addVariableRowFill(Coeffs);
+ // If R has been added to the system, queue it for removal once it goes
+ // out-of-scope.
+ if (Added)
+ DFSInStack.emplace_back(CB.NumIn, CB.NumOut, CB.Condition, CB.Not);
+ }
}
assert(CS.size() == DFSInStack.size() &&
diff --git a/llvm/test/Transforms/ConstraintElimination/eq.ll b/llvm/test/Transforms/ConstraintElimination/eq.ll
index 4015d75cb2e5..9f47f9cee1d2 100644
--- a/llvm/test/Transforms/ConstraintElimination/eq.ll
+++ b/llvm/test/Transforms/ConstraintElimination/eq.ll
@@ -9,15 +9,15 @@ define i1 @test_eq_1(i8 %a, i8 %b) {
; CHECK: then:
; CHECK-NEXT: [[T_1:%.*]] = icmp uge i8 [[A]], [[B]]
; CHECK-NEXT: [[T_2:%.*]] = icmp ule i8 [[A]], [[B]]
-; CHECK-NEXT: [[RES_1:%.*]] = xor i1 [[T_1]], [[T_2]]
+; CHECK-NEXT: [[RES_1:%.*]] = xor i1 true, true
; CHECK-NEXT: [[T_3:%.*]] = icmp eq i8 [[A]], [[B]]
; CHECK-NEXT: [[RES_2:%.*]] = xor i1 [[RES_1]], [[T_3]]
; CHECK-NEXT: [[T_4:%.*]] = icmp eq i8 [[B]], [[A]]
; CHECK-NEXT: [[RES_3:%.*]] = xor i1 [[RES_2]], [[T_4]]
; CHECK-NEXT: [[F_1:%.*]] = icmp ugt i8 [[B]], [[A]]
-; CHECK-NEXT: [[RES_4:%.*]] = xor i1 [[RES_3]], [[F_1]]
+; CHECK-NEXT: [[RES_4:%.*]] = xor i1 [[RES_3]], false
; CHECK-NEXT: [[F_2:%.*]] = icmp ult i8 [[B]], [[A]]
-; CHECK-NEXT: [[RES_5:%.*]] = xor i1 [[RES_4]], [[F_2]]
+; CHECK-NEXT: [[RES_5:%.*]] = xor i1 [[RES_4]], false
; CHECK-NEXT: [[C_1:%.*]] = icmp ult i8 [[B]], 99
; CHECK-NEXT: [[RES_6:%.*]] = xor i1 [[RES_5]], [[C_1]]
; CHECK-NEXT: ret i1 [[RES_6]]
@@ -95,13 +95,13 @@ define i1 @test_eq_2(i8 %a, i8 %b) {
; CHECK: then.then:
; CHECK-NEXT: [[T_1:%.*]] = icmp ult i8 [[A]], 100
; CHECK-NEXT: [[T_2:%.*]] = icmp ult i8 [[B]], 100
-; CHECK-NEXT: [[XOR_1:%.*]] = xor i1 [[T_1]], true
+; CHECK-NEXT: [[XOR_1:%.*]] = xor i1 true, true
; CHECK-NEXT: [[F_1:%.*]] = icmp uge i8 [[A]], 100
-; CHECK-NEXT: [[XOR_2:%.*]] = xor i1 [[XOR_1]], [[F_1]]
+; CHECK-NEXT: [[XOR_2:%.*]] = xor i1 [[XOR_1]], false
; CHECK-NEXT: [[F_2:%.*]] = icmp uge i8 [[B]], 100
; CHECK-NEXT: [[XOR_3:%.*]] = xor i1 [[XOR_2]], false
; CHECK-NEXT: [[F_3_1:%.*]] = icmp ugt i8 [[A]], 99
-; CHECK-NEXT: [[XOR_4:%.*]] = xor i1 [[XOR_3]], [[F_3_1]]
+; CHECK-NEXT: [[XOR_4:%.*]] = xor i1 [[XOR_3]], false
; CHECK-NEXT: [[C_1:%.*]] = icmp ult i8 [[A]], 99
; CHECK-NEXT: [[XOR_5:%.*]] = xor i1 [[XOR_4]], [[C_1]]
; CHECK-NEXT: [[C_2:%.*]] = icmp ugt i8 [[A]], 98
@@ -110,17 +110,17 @@ define i1 @test_eq_2(i8 %a, i8 %b) {
; CHECK: then.else:
; CHECK-NEXT: [[F_4:%.*]] = icmp ult i8 [[A]], 100
; CHECK-NEXT: [[F_5:%.*]] = icmp ult i8 [[B]], 100
-; CHECK-NEXT: [[XOR_7:%.*]] = xor i1 [[F_4]], false
+; CHECK-NEXT: [[XOR_7:%.*]] = xor i1 false, false
; CHECK-NEXT: [[T_3:%.*]] = icmp uge i8 [[A]], 100
-; CHECK-NEXT: [[XOR_8:%.*]] = xor i1 [[XOR_7]], [[T_3]]
+; CHECK-NEXT: [[XOR_8:%.*]] = xor i1 [[XOR_7]], true
; CHECK-NEXT: [[T_4:%.*]] = icmp uge i8 [[B]], 100
; CHECK-NEXT: [[XOR_9:%.*]] = xor i1 [[XOR_8]], true
; CHECK-NEXT: [[T_5:%.*]] = icmp ugt i8 [[A]], 99
-; CHECK-NEXT: [[XOR_10:%.*]] = xor i1 [[XOR_9]], [[T_5]]
+; CHECK-NEXT: [[XOR_10:%.*]] = xor i1 [[XOR_9]], true
; CHECK-NEXT: [[C_3:%.*]] = icmp ult i8 [[A]], 99
-; CHECK-NEXT: [[XOR_11:%.*]] = xor i1 [[XOR_10]], [[C_3]]
+; CHECK-NEXT: [[XOR_11:%.*]] = xor i1 [[XOR_10]], false
; CHECK-NEXT: [[C_4:%.*]] = icmp ugt i8 [[A]], 98
-; CHECK-NEXT: [[XOR_12:%.*]] = xor i1 [[XOR_11]], [[C_4]]
+; CHECK-NEXT: [[XOR_12:%.*]] = xor i1 [[XOR_11]], true
; CHECK-NEXT: ret i1 [[XOR_12]]
; CHECK: else:
; CHECK-NEXT: [[CMP_2:%.*]] = icmp ult i8 [[A]], 100
@@ -298,13 +298,13 @@ define i1 @test_eq_ult_and(i8 %a, i8 %b) {
; CHECK: then:
; CHECK-NEXT: [[T_1:%.*]] = icmp ult i8 [[A]], 100
; CHECK-NEXT: [[T_2:%.*]] = icmp ult i8 [[B]], 100
-; CHECK-NEXT: [[XOR_1:%.*]] = xor i1 [[T_1]], true
+; CHECK-NEXT: [[XOR_1:%.*]] = xor i1 true, true
; CHECK-NEXT: [[F_1:%.*]] = icmp uge i8 [[A]], 100
-; CHECK-NEXT: [[XOR_2:%.*]] = xor i1 [[XOR_1]], [[F_1]]
+; CHECK-NEXT: [[XOR_2:%.*]] = xor i1 [[XOR_1]], false
; CHECK-NEXT: [[F_2:%.*]] = icmp uge i8 [[B]], 100
; CHECK-NEXT: [[XOR_3:%.*]] = xor i1 [[XOR_2]], false
; CHECK-NEXT: [[F_3_1:%.*]] = icmp ugt i8 [[A]], 99
-; CHECK-NEXT: [[XOR_4:%.*]] = xor i1 [[XOR_3]], [[F_3_1]]
+; CHECK-NEXT: [[XOR_4:%.*]] = xor i1 [[XOR_3]], false
; CHECK-NEXT: [[C_1:%.*]] = icmp ult i8 [[A]], 99
; CHECK-NEXT: [[XOR_5:%.*]] = xor i1 [[XOR_4]], [[C_1]]
; CHECK-NEXT: [[C_2:%.*]] = icmp ugt i8 [[A]], 98
More information about the llvm-commits
mailing list