Skip to content

Commit f1632d2

Browse files
authored
IR: introduce ICmpInst::isImpliedByMatchingCmp (#122597)
Create an abstraction over isImplied{True,False}ByMatchingCmp to faithfully communicate the result of both functions, cleaning up code in callsites. While at it, fix a bug in the implied-false version of the function, which was inadvertedenly dropping samesign information.
1 parent 658ec85 commit f1632d2

File tree

6 files changed

+76
-60
lines changed

6 files changed

+76
-60
lines changed

llvm/include/llvm/IR/Instructions.h

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1266,15 +1266,10 @@ class ICmpInst: public CmpInst {
12661266
return getFlippedSignednessPredicate(getPredicate());
12671267
}
12681268

1269-
/// Determine if Pred1 implies Pred2 is true when two compares have matching
1270-
/// operands.
1271-
static bool isImpliedTrueByMatchingCmp(CmpPredicate Pred1,
1272-
CmpPredicate Pred2);
1273-
1274-
/// Determine if Pred1 implies Pred2 is false when two compares have matching
1275-
/// operands.
1276-
static bool isImpliedFalseByMatchingCmp(CmpPredicate Pred1,
1277-
CmpPredicate Pred2);
1269+
/// Determine if Pred1 implies Pred2 is true, false, or if nothing can be
1270+
/// inferred about the implication, when two compares have matching operands.
1271+
static std::optional<bool> isImpliedByMatchingCmp(CmpPredicate Pred1,
1272+
CmpPredicate Pred2);
12781273

12791274
void setSameSign(bool B = true) {
12801275
SubclassOptionalData = (SubclassOptionalData & ~SameSign) | (B * SameSign);

llvm/include/llvm/SandboxIR/Instruction.h

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2547,13 +2547,9 @@ class ICmpInst : public CmpInst {
25472547
WRAP_STATIC_PREDICATE(isGE);
25482548
WRAP_STATIC_PREDICATE(isLE);
25492549

2550-
static bool isImpliedTrueByMatchingCmp(CmpPredicate Pred1,
2551-
CmpPredicate Pred2) {
2552-
return llvm::ICmpInst::isImpliedTrueByMatchingCmp(Pred1, Pred2);
2553-
}
2554-
static bool isImpliedFalseByMatchingCmp(CmpPredicate Pred1,
2555-
CmpPredicate Pred2) {
2556-
return llvm::ICmpInst::isImpliedFalseByMatchingCmp(Pred1, Pred2);
2550+
static std::optional<bool> isImpliedByMatchingCmp(CmpPredicate Pred1,
2551+
CmpPredicate Pred2) {
2552+
return llvm::ICmpInst::isImpliedByMatchingCmp(Pred1, Pred2);
25572553
}
25582554

25592555
static auto predicates() { return llvm::ICmpInst::predicates(); }

llvm/lib/Analysis/ValueTracking.cpp

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -9384,19 +9384,6 @@ isImpliedCondOperands(CmpInst::Predicate Pred, const Value *ALHS,
93849384
}
93859385
}
93869386

9387-
/// Return true if "icmp1 LPred X, Y" implies "icmp2 RPred X, Y" is true.
9388-
/// Return false if "icmp1 LPred X, Y" implies "icmp2 RPred X, Y" is false.
9389-
/// Otherwise, return std::nullopt if we can't infer anything.
9390-
static std::optional<bool> isImpliedCondMatchingOperands(CmpPredicate LPred,
9391-
CmpPredicate RPred) {
9392-
if (ICmpInst::isImpliedTrueByMatchingCmp(LPred, RPred))
9393-
return true;
9394-
if (ICmpInst::isImpliedFalseByMatchingCmp(LPred, RPred))
9395-
return false;
9396-
9397-
return std::nullopt;
9398-
}
9399-
94009387
/// Return true if "icmp LPred X, LCR" implies "icmp RPred X, RCR" is true.
94019388
/// Return false if "icmp LPred X, LCR" implies "icmp RPred X, RCR" is false.
94029389
/// Otherwise, return std::nullopt if we can't infer anything.
@@ -9489,7 +9476,7 @@ isImpliedCondICmps(const ICmpInst *LHS, CmpPredicate RPred, const Value *R0,
94899476

94909477
// Can we infer anything when the two compares have matching operands?
94919478
if (L0 == R0 && L1 == R1)
9492-
return isImpliedCondMatchingOperands(LPred, RPred);
9479+
return ICmpInst::isImpliedByMatchingCmp(LPred, RPred);
94939480

94949481
// It only really makes sense in the context of signed comparison for "X - Y
94959482
// must be positive if X >= Y and no overflow".
@@ -9499,7 +9486,7 @@ isImpliedCondICmps(const ICmpInst *LHS, CmpPredicate RPred, const Value *R0,
94999486
CmpPredicate::getMatching(LPred, ICmpInst::ICMP_SGE)) &&
95009487
match(R0, m_NSWSub(m_Specific(L0), m_Specific(L1)))) {
95019488
if (match(R1, m_NonPositive()) &&
9502-
isImpliedCondMatchingOperands(LPred, RPred) == false)
9489+
ICmpInst::isImpliedByMatchingCmp(LPred, RPred) == false)
95039490
return false;
95049491
}
95059492

@@ -9509,7 +9496,7 @@ isImpliedCondICmps(const ICmpInst *LHS, CmpPredicate RPred, const Value *R0,
95099496
CmpPredicate::getMatching(LPred, ICmpInst::ICMP_SLE)) &&
95109497
match(R0, m_NSWSub(m_Specific(L0), m_Specific(L1)))) {
95119498
if (match(R1, m_NonNegative()) &&
9512-
isImpliedCondMatchingOperands(LPred, RPred) == true)
9499+
ICmpInst::isImpliedByMatchingCmp(LPred, RPred) == true)
95139500
return true;
95149501
}
95159502

llvm/lib/IR/Instructions.cpp

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3886,8 +3886,7 @@ bool CmpInst::isFalseWhenEqual(Predicate predicate) {
38863886
}
38873887
}
38883888

3889-
bool ICmpInst::isImpliedTrueByMatchingCmp(CmpPredicate Pred1,
3890-
CmpPredicate Pred2) {
3889+
static bool isImpliedTrueByMatchingCmp(CmpPredicate Pred1, CmpPredicate Pred2) {
38913890
// If the predicates match, then we know the first condition implies the
38923891
// second is true.
38933892
if (CmpPredicate::getMatching(Pred1, Pred2))
@@ -3901,25 +3900,35 @@ bool ICmpInst::isImpliedTrueByMatchingCmp(CmpPredicate Pred1,
39013900
switch (Pred1) {
39023901
default:
39033902
break;
3904-
case ICMP_EQ:
3903+
case CmpInst::ICMP_EQ:
39053904
// A == B implies A >=u B, A <=u B, A >=s B, and A <=s B are true.
3906-
return Pred2 == ICMP_UGE || Pred2 == ICMP_ULE || Pred2 == ICMP_SGE ||
3907-
Pred2 == ICMP_SLE;
3908-
case ICMP_UGT: // A >u B implies A != B and A >=u B are true.
3909-
return Pred2 == ICMP_NE || Pred2 == ICMP_UGE;
3910-
case ICMP_ULT: // A <u B implies A != B and A <=u B are true.
3911-
return Pred2 == ICMP_NE || Pred2 == ICMP_ULE;
3912-
case ICMP_SGT: // A >s B implies A != B and A >=s B are true.
3913-
return Pred2 == ICMP_NE || Pred2 == ICMP_SGE;
3914-
case ICMP_SLT: // A <s B implies A != B and A <=s B are true.
3915-
return Pred2 == ICMP_NE || Pred2 == ICMP_SLE;
3905+
return Pred2 == CmpInst::ICMP_UGE || Pred2 == CmpInst::ICMP_ULE ||
3906+
Pred2 == CmpInst::ICMP_SGE || Pred2 == CmpInst::ICMP_SLE;
3907+
case CmpInst::ICMP_UGT: // A >u B implies A != B and A >=u B are true.
3908+
return Pred2 == CmpInst::ICMP_NE || Pred2 == CmpInst::ICMP_UGE;
3909+
case CmpInst::ICMP_ULT: // A <u B implies A != B and A <=u B are true.
3910+
return Pred2 == CmpInst::ICMP_NE || Pred2 == CmpInst::ICMP_ULE;
3911+
case CmpInst::ICMP_SGT: // A >s B implies A != B and A >=s B are true.
3912+
return Pred2 == CmpInst::ICMP_NE || Pred2 == CmpInst::ICMP_SGE;
3913+
case CmpInst::ICMP_SLT: // A <s B implies A != B and A <=s B are true.
3914+
return Pred2 == CmpInst::ICMP_NE || Pred2 == CmpInst::ICMP_SLE;
39163915
}
39173916
return false;
39183917
}
39193918

3920-
bool ICmpInst::isImpliedFalseByMatchingCmp(CmpPredicate Pred1,
3921-
CmpPredicate Pred2) {
3922-
return isImpliedTrueByMatchingCmp(Pred1, getInversePredicate(Pred2));
3919+
static bool isImpliedFalseByMatchingCmp(CmpPredicate Pred1,
3920+
CmpPredicate Pred2) {
3921+
return isImpliedTrueByMatchingCmp(Pred1,
3922+
ICmpInst::getInverseCmpPredicate(Pred2));
3923+
}
3924+
3925+
std::optional<bool> ICmpInst::isImpliedByMatchingCmp(CmpPredicate Pred1,
3926+
CmpPredicate Pred2) {
3927+
if (isImpliedTrueByMatchingCmp(Pred1, Pred2))
3928+
return true;
3929+
if (isImpliedFalseByMatchingCmp(Pred1, Pred2))
3930+
return false;
3931+
return std::nullopt;
39233932
}
39243933

39253934
//===----------------------------------------------------------------------===//

llvm/lib/Transforms/Scalar/NewGVN.cpp

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1964,18 +1964,10 @@ NewGVN::ExprResult NewGVN::performSymbolicCmpEvaluation(Instruction *I) const {
19641964
if (PBranch->TrueEdge) {
19651965
// If we know the previous predicate is true and we are in the true
19661966
// edge then we may be implied true or false.
1967-
if (ICmpInst::isImpliedTrueByMatchingCmp(BranchPredicate,
1968-
OurPredicate)) {
1969-
return ExprResult::some(
1970-
createConstantExpression(ConstantInt::getTrue(CI->getType())),
1971-
PI);
1972-
}
1973-
1974-
if (ICmpInst::isImpliedFalseByMatchingCmp(BranchPredicate,
1975-
OurPredicate)) {
1976-
return ExprResult::some(
1977-
createConstantExpression(ConstantInt::getFalse(CI->getType())),
1978-
PI);
1967+
if (auto R = ICmpInst::isImpliedByMatchingCmp(BranchPredicate,
1968+
OurPredicate)) {
1969+
auto *C = ConstantInt::getBool(CI->getType(), *R);
1970+
return ExprResult::some(createConstantExpression(C), PI);
19791971
}
19801972
} else {
19811973
// Just handle the ne and eq cases, where if we have the same

llvm/test/Analysis/ValueTracking/implied-condition-samesign.ll

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,19 @@ define i1 @sgt_implies_ge_via_assume(i32 %i, i32 %j) {
126126
ret i1 %i.ge.j
127127
}
128128

129+
define i1 @sgt_implies_false_le_via_assume(i32 %i, i32 %j) {
130+
; CHECK-LABEL: define i1 @sgt_implies_false_le_via_assume(
131+
; CHECK-SAME: i32 [[I:%.*]], i32 [[J:%.*]]) {
132+
; CHECK-NEXT: [[I_SGT_J:%.*]] = icmp sgt i32 [[I]], [[J]]
133+
; CHECK-NEXT: call void @llvm.assume(i1 [[I_SGT_J]])
134+
; CHECK-NEXT: ret i1 false
135+
;
136+
%i.sgt.j = icmp sgt i32 %i, %j
137+
call void @llvm.assume(i1 %i.sgt.j)
138+
%i.le.j = icmp samesign ule i32 %i, %j
139+
ret i1 %i.le.j
140+
}
141+
129142
define i32 @gt_implies_sge_dominating(i32 %a, i32 %len) {
130143
; CHECK-LABEL: define i32 @gt_implies_sge_dominating(
131144
; CHECK-SAME: i32 [[A:%.*]], i32 [[LEN:%.*]]) {
@@ -150,6 +163,30 @@ end:
150163
ret i32 -1
151164
}
152165

166+
define i32 @gt_implies_false_sle_dominating(i32 %a, i32 %len) {
167+
; CHECK-LABEL: define i32 @gt_implies_false_sle_dominating(
168+
; CHECK-SAME: i32 [[A:%.*]], i32 [[LEN:%.*]]) {
169+
; CHECK-NEXT: [[ENTRY:.*:]]
170+
; CHECK-NEXT: [[A_GT_LEN:%.*]] = icmp samesign ugt i32 [[A]], [[LEN]]
171+
; CHECK-NEXT: br i1 [[A_GT_LEN]], label %[[TAKEN:.*]], label %[[END:.*]]
172+
; CHECK: [[TAKEN]]:
173+
; CHECK-NEXT: ret i32 0
174+
; CHECK: [[END]]:
175+
; CHECK-NEXT: ret i32 -1
176+
;
177+
entry:
178+
%a.gt.len = icmp samesign ugt i32 %a, %len
179+
br i1 %a.gt.len, label %taken, label %end
180+
181+
taken:
182+
%a.sle.len = icmp sle i32 %a, %len
183+
%res = select i1 %a.sle.len, i32 30, i32 0
184+
ret i32 %res
185+
186+
end:
187+
ret i32 -1
188+
}
189+
153190
define i32 @gt_implies_sge_dominating_cr(i32 %a, i32 %len) {
154191
; CHECK-LABEL: define i32 @gt_implies_sge_dominating_cr(
155192
; CHECK-SAME: i32 [[A:%.*]], i32 [[LEN:%.*]]) {

0 commit comments

Comments
 (0)