Skip to content

Commit 678f32a

Browse files
committed
[ValueTracking] Add more conditions in to isTruePredicate
There is one notable "regression". This patch replaces the bespoke `or disjoint` logic we a direct match. This means we fail some simplification during `instsimplify`. All the cases we fail in `instsimplify` we do handle in `instcombine` as we add `disjoint` flags. Other than that, just some basic cases. See proofs: https://alive2.llvm.org/ce/z/_-g7C8 Closes #86083
1 parent 74447cf commit 678f32a

File tree

3 files changed

+77
-64
lines changed

3 files changed

+77
-64
lines changed

llvm/lib/Analysis/ValueTracking.cpp

Lines changed: 53 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -8393,8 +8393,7 @@ bool llvm::matchSimpleRecurrence(const BinaryOperator *I, PHINode *&P,
83938393

83948394
/// Return true if "icmp Pred LHS RHS" is always true.
83958395
static bool isTruePredicate(CmpInst::Predicate Pred, const Value *LHS,
8396-
const Value *RHS, const DataLayout &DL,
8397-
unsigned Depth) {
8396+
const Value *RHS) {
83988397
if (ICmpInst::isTrueWhenEqual(Pred) && LHS == RHS)
83998398
return true;
84008399

@@ -8406,8 +8405,26 @@ static bool isTruePredicate(CmpInst::Predicate Pred, const Value *LHS,
84068405
const APInt *C;
84078406

84088407
// LHS s<= LHS +_{nsw} C if C >= 0
8409-
if (match(RHS, m_NSWAdd(m_Specific(LHS), m_APInt(C))))
8408+
// LHS s<= LHS | C if C >= 0
8409+
if (match(RHS, m_NSWAdd(m_Specific(LHS), m_APInt(C))) ||
8410+
match(RHS, m_Or(m_Specific(LHS), m_APInt(C))))
84108411
return !C->isNegative();
8412+
8413+
// LHS s<= smax(LHS, V) for any V
8414+
if (match(RHS, m_c_SMax(m_Specific(LHS), m_Value())))
8415+
return true;
8416+
8417+
// smin(RHS, V) s<= RHS for any V
8418+
if (match(LHS, m_c_SMin(m_Specific(RHS), m_Value())))
8419+
return true;
8420+
8421+
// Match A to (X +_{nsw} CA) and B to (X +_{nsw} CB)
8422+
const Value *X;
8423+
const APInt *CLHS, *CRHS;
8424+
if (match(LHS, m_NSWAddLike(m_Value(X), m_APInt(CLHS))) &&
8425+
match(RHS, m_NSWAddLike(m_Specific(X), m_APInt(CRHS))))
8426+
return CLHS->sle(*CRHS);
8427+
84118428
return false;
84128429
}
84138430

@@ -8417,34 +8434,36 @@ static bool isTruePredicate(CmpInst::Predicate Pred, const Value *LHS,
84178434
cast<OverflowingBinaryOperator>(RHS)->hasNoUnsignedWrap())
84188435
return true;
84198436

8437+
// LHS u<= LHS | V for any V
8438+
if (match(RHS, m_c_Or(m_Specific(LHS), m_Value())))
8439+
return true;
8440+
8441+
// LHS u<= umax(LHS, V) for any V
8442+
if (match(RHS, m_c_UMax(m_Specific(LHS), m_Value())))
8443+
return true;
8444+
84208445
// RHS >> V u<= RHS for any V
84218446
if (match(LHS, m_LShr(m_Specific(RHS), m_Value())))
84228447
return true;
84238448

8424-
// Match A to (X +_{nuw} CA) and B to (X +_{nuw} CB)
8425-
auto MatchNUWAddsToSameValue = [&](const Value *A, const Value *B,
8426-
const Value *&X,
8427-
const APInt *&CA, const APInt *&CB) {
8428-
if (match(A, m_NUWAdd(m_Value(X), m_APInt(CA))) &&
8429-
match(B, m_NUWAdd(m_Specific(X), m_APInt(CB))))
8430-
return true;
8449+
// RHS u/ C_ugt_1 u<= RHS
8450+
const APInt *C;
8451+
if (match(LHS, m_UDiv(m_Specific(RHS), m_APInt(C))) && C->ugt(1))
8452+
return true;
84318453

8432-
// If X & C == 0 then (X | C) == X +_{nuw} C
8433-
if (match(A, m_Or(m_Value(X), m_APInt(CA))) &&
8434-
match(B, m_Or(m_Specific(X), m_APInt(CB)))) {
8435-
KnownBits Known(CA->getBitWidth());
8436-
computeKnownBits(X, Known, DL, Depth + 1, /*AC*/ nullptr,
8437-
/*CxtI*/ nullptr, /*DT*/ nullptr);
8438-
if (CA->isSubsetOf(Known.Zero) && CB->isSubsetOf(Known.Zero))
8439-
return true;
8440-
}
8454+
// RHS & V u<= RHS for any V
8455+
if (match(LHS, m_c_And(m_Specific(RHS), m_Value())))
8456+
return true;
84418457

8442-
return false;
8443-
};
8458+
// umin(RHS, V) u<= RHS for any V
8459+
if (match(LHS, m_c_UMin(m_Specific(RHS), m_Value())))
8460+
return true;
84448461

8462+
// Match A to (X +_{nuw} CA) and B to (X +_{nuw} CB)
84458463
const Value *X;
84468464
const APInt *CLHS, *CRHS;
8447-
if (MatchNUWAddsToSameValue(LHS, RHS, X, CLHS, CRHS))
8465+
if (match(LHS, m_NUWAddLike(m_Value(X), m_APInt(CLHS))) &&
8466+
match(RHS, m_NUWAddLike(m_Specific(X), m_APInt(CRHS))))
84488467
return CLHS->ule(*CRHS);
84498468

84508469
return false;
@@ -8456,37 +8475,36 @@ static bool isTruePredicate(CmpInst::Predicate Pred, const Value *LHS,
84568475
/// ALHS ARHS" is true. Otherwise, return std::nullopt.
84578476
static std::optional<bool>
84588477
isImpliedCondOperands(CmpInst::Predicate Pred, const Value *ALHS,
8459-
const Value *ARHS, const Value *BLHS, const Value *BRHS,
8460-
const DataLayout &DL, unsigned Depth) {
8478+
const Value *ARHS, const Value *BLHS, const Value *BRHS) {
84618479
switch (Pred) {
84628480
default:
84638481
return std::nullopt;
84648482

84658483
case CmpInst::ICMP_SLT:
84668484
case CmpInst::ICMP_SLE:
8467-
if (isTruePredicate(CmpInst::ICMP_SLE, BLHS, ALHS, DL, Depth) &&
8468-
isTruePredicate(CmpInst::ICMP_SLE, ARHS, BRHS, DL, Depth))
8485+
if (isTruePredicate(CmpInst::ICMP_SLE, BLHS, ALHS) &&
8486+
isTruePredicate(CmpInst::ICMP_SLE, ARHS, BRHS))
84698487
return true;
84708488
return std::nullopt;
84718489

84728490
case CmpInst::ICMP_SGT:
84738491
case CmpInst::ICMP_SGE:
8474-
if (isTruePredicate(CmpInst::ICMP_SLE, ALHS, BLHS, DL, Depth) &&
8475-
isTruePredicate(CmpInst::ICMP_SLE, BRHS, ARHS, DL, Depth))
8492+
if (isTruePredicate(CmpInst::ICMP_SLE, ALHS, BLHS) &&
8493+
isTruePredicate(CmpInst::ICMP_SLE, BRHS, ARHS))
84768494
return true;
84778495
return std::nullopt;
84788496

84798497
case CmpInst::ICMP_ULT:
84808498
case CmpInst::ICMP_ULE:
8481-
if (isTruePredicate(CmpInst::ICMP_ULE, BLHS, ALHS, DL, Depth) &&
8482-
isTruePredicate(CmpInst::ICMP_ULE, ARHS, BRHS, DL, Depth))
8499+
if (isTruePredicate(CmpInst::ICMP_ULE, BLHS, ALHS) &&
8500+
isTruePredicate(CmpInst::ICMP_ULE, ARHS, BRHS))
84838501
return true;
84848502
return std::nullopt;
84858503

84868504
case CmpInst::ICMP_UGT:
84878505
case CmpInst::ICMP_UGE:
8488-
if (isTruePredicate(CmpInst::ICMP_ULE, ALHS, BLHS, DL, Depth) &&
8489-
isTruePredicate(CmpInst::ICMP_ULE, BRHS, ARHS, DL, Depth))
8506+
if (isTruePredicate(CmpInst::ICMP_ULE, ALHS, BLHS) &&
8507+
isTruePredicate(CmpInst::ICMP_ULE, BRHS, ARHS))
84908508
return true;
84918509
return std::nullopt;
84928510
}
@@ -8530,7 +8548,7 @@ static std::optional<bool> isImpliedCondICmps(const ICmpInst *LHS,
85308548
CmpInst::Predicate RPred,
85318549
const Value *R0, const Value *R1,
85328550
const DataLayout &DL,
8533-
bool LHSIsTrue, unsigned Depth) {
8551+
bool LHSIsTrue) {
85348552
Value *L0 = LHS->getOperand(0);
85358553
Value *L1 = LHS->getOperand(1);
85368554

@@ -8577,7 +8595,7 @@ static std::optional<bool> isImpliedCondICmps(const ICmpInst *LHS,
85778595
return LPred == RPred;
85788596

85798597
if (LPred == RPred)
8580-
return isImpliedCondOperands(LPred, L0, L1, R0, R1, DL, Depth);
8598+
return isImpliedCondOperands(LPred, L0, L1, R0, R1);
85818599

85828600
return std::nullopt;
85838601
}
@@ -8639,8 +8657,7 @@ llvm::isImpliedCondition(const Value *LHS, CmpInst::Predicate RHSPred,
86398657
// Both LHS and RHS are icmps.
86408658
const ICmpInst *LHSCmp = dyn_cast<ICmpInst>(LHS);
86418659
if (LHSCmp)
8642-
return isImpliedCondICmps(LHSCmp, RHSPred, RHSOp0, RHSOp1, DL, LHSIsTrue,
8643-
Depth);
8660+
return isImpliedCondICmps(LHSCmp, RHSPred, RHSOp0, RHSOp1, DL, LHSIsTrue);
86448661

86458662
/// The LHS should be an 'or', 'and', or a 'select' instruction. We expect
86468663
/// the RHS to be an icmp.

llvm/test/Transforms/InstCombine/implies.ll

Lines changed: 10 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,7 @@ define i1 @or_implies_sle(i8 %x, i8 %y, i1 %other) {
77
; CHECK-NEXT: [[COND_NOT:%.*]] = icmp sgt i8 [[OR]], [[Y:%.*]]
88
; CHECK-NEXT: br i1 [[COND_NOT]], label [[F:%.*]], label [[T:%.*]]
99
; CHECK: T:
10-
; CHECK-NEXT: [[R:%.*]] = icmp sle i8 [[X]], [[Y]]
11-
; CHECK-NEXT: ret i1 [[R]]
10+
; CHECK-NEXT: ret i1 true
1211
; CHECK: F:
1312
; CHECK-NEXT: ret i1 [[OTHER:%.*]]
1413
;
@@ -49,9 +48,7 @@ define i1 @or_distjoint_implies_ule(i8 %x, i8 %y, i1 %other) {
4948
; CHECK-NEXT: [[COND_NOT:%.*]] = icmp ugt i8 [[X2]], [[Y:%.*]]
5049
; CHECK-NEXT: br i1 [[COND_NOT]], label [[F:%.*]], label [[T:%.*]]
5150
; CHECK: T:
52-
; CHECK-NEXT: [[X1:%.*]] = or disjoint i8 [[X]], 23
53-
; CHECK-NEXT: [[R:%.*]] = icmp ule i8 [[X1]], [[Y]]
54-
; CHECK-NEXT: ret i1 [[R]]
51+
; CHECK-NEXT: ret i1 true
5552
; CHECK: F:
5653
; CHECK-NEXT: ret i1 [[OTHER:%.*]]
5754
;
@@ -121,9 +118,7 @@ define i1 @src_or_distjoint_implies_sle(i8 %x, i8 %y, i1 %other) {
121118
; CHECK-NEXT: [[COND_NOT:%.*]] = icmp sgt i8 [[X2]], [[Y:%.*]]
122119
; CHECK-NEXT: br i1 [[COND_NOT]], label [[F:%.*]], label [[T:%.*]]
123120
; CHECK: T:
124-
; CHECK-NEXT: [[X1:%.*]] = or disjoint i8 [[X]], 23
125-
; CHECK-NEXT: [[R:%.*]] = icmp sle i8 [[X1]], [[Y]]
126-
; CHECK-NEXT: ret i1 [[R]]
121+
; CHECK-NEXT: ret i1 true
127122
; CHECK: F:
128123
; CHECK-NEXT: ret i1 [[OTHER:%.*]]
129124
;
@@ -169,9 +164,7 @@ define i1 @src_addnsw_implies_sle(i8 %x, i8 %y, i1 %other) {
169164
; CHECK-NEXT: [[COND_NOT:%.*]] = icmp sgt i8 [[X2]], [[Y:%.*]]
170165
; CHECK-NEXT: br i1 [[COND_NOT]], label [[F:%.*]], label [[T:%.*]]
171166
; CHECK: T:
172-
; CHECK-NEXT: [[X1:%.*]] = add nsw i8 [[X]], 23
173-
; CHECK-NEXT: [[R:%.*]] = icmp sle i8 [[X1]], [[Y]]
174-
; CHECK-NEXT: ret i1 [[R]]
167+
; CHECK-NEXT: ret i1 true
175168
; CHECK: F:
176169
; CHECK-NEXT: ret i1 [[OTHER:%.*]]
177170
;
@@ -216,9 +209,7 @@ define i1 @src_and_implies_ult(i8 %x, i8 %y, i8 %z, i1 %other) {
216209
; CHECK-NEXT: [[COND:%.*]] = icmp ult i8 [[X:%.*]], [[Z:%.*]]
217210
; CHECK-NEXT: br i1 [[COND]], label [[T:%.*]], label [[F:%.*]]
218211
; CHECK: T:
219-
; CHECK-NEXT: [[AND:%.*]] = and i8 [[Z]], [[X]]
220-
; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[AND]], [[Z]]
221-
; CHECK-NEXT: ret i1 [[R]]
212+
; CHECK-NEXT: ret i1 true
222213
; CHECK: F:
223214
; CHECK-NEXT: ret i1 [[OTHER:%.*]]
224215
;
@@ -280,8 +271,7 @@ define i1 @src_or_implies_ule(i8 %x, i8 %y, i8 %z, i1 %other) {
280271
; CHECK-NEXT: [[COND_NOT:%.*]] = icmp ugt i8 [[OR]], [[Z:%.*]]
281272
; CHECK-NEXT: br i1 [[COND_NOT]], label [[F:%.*]], label [[T:%.*]]
282273
; CHECK: T:
283-
; CHECK-NEXT: [[R:%.*]] = icmp ule i8 [[X]], [[Z]]
284-
; CHECK-NEXT: ret i1 [[R]]
274+
; CHECK-NEXT: ret i1 true
285275
; CHECK: F:
286276
; CHECK-NEXT: ret i1 [[OTHER:%.*]]
287277
;
@@ -322,9 +312,7 @@ define i1 @src_udiv_implies_ult(i8 %x, i8 %z, i1 %other) {
322312
; CHECK-NEXT: [[COND:%.*]] = icmp ugt i8 [[Z:%.*]], [[X:%.*]]
323313
; CHECK-NEXT: br i1 [[COND]], label [[T:%.*]], label [[F:%.*]]
324314
; CHECK: T:
325-
; CHECK-NEXT: [[AND:%.*]] = udiv i8 [[X]], 3
326-
; CHECK-NEXT: [[R:%.*]] = icmp ult i8 [[AND]], [[Z]]
327-
; CHECK-NEXT: ret i1 [[R]]
315+
; CHECK-NEXT: ret i1 true
328316
; CHECK: F:
329317
; CHECK-NEXT: ret i1 [[OTHER:%.*]]
330318
;
@@ -345,9 +333,7 @@ define i1 @src_udiv_implies_ult2(i8 %x, i8 %z, i1 %other) {
345333
; CHECK: T:
346334
; CHECK-NEXT: ret i1 [[OTHER:%.*]]
347335
; CHECK: F:
348-
; CHECK-NEXT: [[AND:%.*]] = udiv i8 [[X]], 3
349-
; CHECK-NEXT: [[R:%.*]] = icmp ult i8 [[AND]], [[Z]]
350-
; CHECK-NEXT: ret i1 [[R]]
336+
; CHECK-NEXT: ret i1 true
351337
;
352338
%cond = icmp ule i8 %z, %x
353339
br i1 %cond, label %T, label %F
@@ -403,8 +389,7 @@ define i1 @src_umax_implies_ule(i8 %x, i8 %y, i8 %z, i1 %other) {
403389
; CHECK-NEXT: [[COND_NOT:%.*]] = icmp ugt i8 [[UM]], [[Z:%.*]]
404390
; CHECK-NEXT: br i1 [[COND_NOT]], label [[F:%.*]], label [[T:%.*]]
405391
; CHECK: T:
406-
; CHECK-NEXT: [[R:%.*]] = icmp ule i8 [[X]], [[Z]]
407-
; CHECK-NEXT: ret i1 [[R]]
392+
; CHECK-NEXT: ret i1 true
408393
; CHECK: F:
409394
; CHECK-NEXT: ret i1 [[OTHER:%.*]]
410395
;
@@ -424,8 +409,7 @@ define i1 @src_smax_implies_sle(i8 %x, i8 %y, i8 %z, i1 %other) {
424409
; CHECK-NEXT: [[COND_NOT:%.*]] = icmp sgt i8 [[UM]], [[Z:%.*]]
425410
; CHECK-NEXT: br i1 [[COND_NOT]], label [[F:%.*]], label [[T:%.*]]
426411
; CHECK: T:
427-
; CHECK-NEXT: [[R:%.*]] = icmp sle i8 [[X]], [[Z]]
428-
; CHECK-NEXT: ret i1 [[R]]
412+
; CHECK-NEXT: ret i1 true
429413
; CHECK: F:
430414
; CHECK-NEXT: ret i1 [[OTHER:%.*]]
431415
;

llvm/test/Transforms/InstSimplify/implies.ll

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,13 @@ define i1 @test9(i32 %length.i, i32 %i) {
155155

156156
define i1 @test10(i32 %length.i, i32 %x.full) {
157157
; CHECK-LABEL: @test10(
158-
; CHECK-NEXT: ret i1 true
158+
; CHECK-NEXT: [[X:%.*]] = and i32 [[X_FULL:%.*]], -65536
159+
; CHECK-NEXT: [[LARGE:%.*]] = or i32 [[X]], 100
160+
; CHECK-NEXT: [[SMALL:%.*]] = or i32 [[X]], 90
161+
; CHECK-NEXT: [[KNOWN:%.*]] = icmp ult i32 [[LARGE]], [[LENGTH_I:%.*]]
162+
; CHECK-NEXT: [[TO_PROVE:%.*]] = icmp ult i32 [[SMALL]], [[LENGTH_I]]
163+
; CHECK-NEXT: [[RES:%.*]] = icmp ule i1 [[KNOWN]], [[TO_PROVE]]
164+
; CHECK-NEXT: ret i1 [[RES]]
159165
;
160166
%x = and i32 %x.full, 4294901760 ;; 4294901760 == 0xffff0000
161167
%large = or i32 %x, 100
@@ -229,7 +235,13 @@ define i1 @test13(i32 %length.i, i32 %x) {
229235

230236
define i1 @test14(i32 %length.i, i32 %x.full) {
231237
; CHECK-LABEL: @test14(
232-
; CHECK-NEXT: ret i1 true
238+
; CHECK-NEXT: [[X:%.*]] = and i32 [[X_FULL:%.*]], -61681
239+
; CHECK-NEXT: [[LARGE:%.*]] = or i32 [[X]], 8224
240+
; CHECK-NEXT: [[SMALL:%.*]] = or i32 [[X]], 4112
241+
; CHECK-NEXT: [[KNOWN:%.*]] = icmp ult i32 [[LARGE]], [[LENGTH_I:%.*]]
242+
; CHECK-NEXT: [[TO_PROVE:%.*]] = icmp ult i32 [[SMALL]], [[LENGTH_I]]
243+
; CHECK-NEXT: [[RES:%.*]] = icmp ule i1 [[KNOWN]], [[TO_PROVE]]
244+
; CHECK-NEXT: ret i1 [[RES]]
233245
;
234246
%x = and i32 %x.full, 4294905615 ;; 4294905615 == 0xffff0f0f
235247
%large = or i32 %x, 8224 ;; == 0x2020

0 commit comments

Comments
 (0)