Skip to content

Commit 51d44fd

Browse files
committed
[InstCombine] Fold (X / C pred X) and (X >> C pred X) into X ~pred 0
1 parent 2d19adb commit 51d44fd

File tree

2 files changed

+39
-12
lines changed

2 files changed

+39
-12
lines changed

llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7103,6 +7103,39 @@ Instruction *InstCombinerImpl::foldICmpCommutative(ICmpInst::Predicate Pred,
71037103
if (Value *V = foldICmpWithLowBitMaskedVal(Pred, Op0, Op1, Q, *this))
71047104
return replaceInstUsesWith(CxtI, V);
71057105

7106+
// Folding (X / Y) pred X => X ~pred 0 for some constant Y other than 0 or 1
7107+
{
7108+
const APInt *Divisor;
7109+
if (match(Op0, m_UDiv(m_Specific(Op1), m_APInt(Divisor))) &&
7110+
Divisor->ugt(1)) {
7111+
return new ICmpInst(ICmpInst::getSwappedPredicate(Pred), Op1,
7112+
Constant::getNullValue(Op1->getType()));
7113+
}
7114+
7115+
if (!ICmpInst::isUnsigned(Pred) &&
7116+
match(Op0, m_SDiv(m_Specific(Op1), m_APInt(Divisor))) &&
7117+
Divisor->ugt(1)) {
7118+
return new ICmpInst(ICmpInst::getSwappedPredicate(Pred), Op1,
7119+
Constant::getNullValue(Op1->getType()));
7120+
}
7121+
}
7122+
7123+
// Another case of this fold is (X >> Y) pred X => X ~pred 0 if Y != 0
7124+
{
7125+
const APInt *Shift;
7126+
if (match(Op0, m_LShr(m_Specific(Op1), m_APInt(Shift))) && Shift->ugt(0)) {
7127+
return new ICmpInst(ICmpInst::getSwappedPredicate(Pred), Op1,
7128+
Constant::getNullValue(Op1->getType()));
7129+
}
7130+
7131+
if ((Pred == CmpInst::ICMP_SLT || Pred == CmpInst::ICMP_SGE) &&
7132+
match(Op0, m_AShr(m_Specific(Op1), m_APInt(Shift))) &&
7133+
Shift->ugt(0)) {
7134+
return new ICmpInst(ICmpInst::getSwappedPredicate(Pred), Op1,
7135+
Constant::getNullValue(Op1->getType()));
7136+
}
7137+
}
7138+
71067139
return nullptr;
71077140
}
71087141

llvm/test/Transforms/InstCombine/icmp-div-constant.ll

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -381,8 +381,7 @@ define i1 @sdiv_eq_smin_use(i32 %x, i32 %y) {
381381

382382
define i1 @sdiv_x_by_const_cmp_x(i32 %x) {
383383
; CHECK-LABEL: @sdiv_x_by_const_cmp_x(
384-
; CHECK-NEXT: [[V:%.*]] = sdiv i32 [[X:%.*]], 13
385-
; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[V]], [[X]]
384+
; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[X:%.*]], 0
386385
; CHECK-NEXT: ret i1 [[TMP1]]
387386
;
388387
%v = sdiv i32 %x, 13
@@ -392,8 +391,7 @@ define i1 @sdiv_x_by_const_cmp_x(i32 %x) {
392391

393392
define i1 @udiv_x_by_const_cmp_x(i32 %x) {
394393
; CHECK-LABEL: @udiv_x_by_const_cmp_x(
395-
; CHECK-NEXT: [[TMP2:%.*]] = udiv i32 [[X:%.*]], 123
396-
; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i32 [[TMP2]], [[X]]
394+
; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i32 [[X:%.*]], 0
397395
; CHECK-NEXT: ret i1 [[TMP1]]
398396
;
399397
%1 = udiv i32 %x, 123
@@ -405,8 +403,7 @@ define i1 @udiv_x_by_const_cmp_x(i32 %x) {
405403

406404
define i1 @lshr_x_by_const_cmp_x(i32 %x) {
407405
; CHECK-LABEL: @lshr_x_by_const_cmp_x(
408-
; CHECK-NEXT: [[V:%.*]] = lshr i32 [[X:%.*]], 1
409-
; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[V]], [[X]]
406+
; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[X:%.*]], 0
410407
; CHECK-NEXT: ret i1 [[TMP1]]
411408
;
412409
%v = lshr i32 %x, 1
@@ -416,8 +413,7 @@ define i1 @lshr_x_by_const_cmp_x(i32 %x) {
416413

417414
define <4 x i1> @lshr_by_const_cmp_sle_value(<4 x i32> %x) {
418415
; CHECK-LABEL: @lshr_by_const_cmp_sle_value(
419-
; CHECK-NEXT: [[V:%.*]] = lshr <4 x i32> [[X:%.*]], <i32 3, i32 3, i32 3, i32 3>
420-
; CHECK-NEXT: [[R:%.*]] = icmp sle <4 x i32> [[V]], [[X]]
416+
; CHECK-NEXT: [[R:%.*]] = icmp sgt <4 x i32> [[X:%.*]], <i32 -1, i32 -1, i32 -1, i32 -1>
421417
; CHECK-NEXT: ret <4 x i1> [[R]]
422418
;
423419
%v = lshr <4 x i32> %x, <i32 3, i32 3, i32 3, i32 3>
@@ -427,8 +423,7 @@ define <4 x i1> @lshr_by_const_cmp_sle_value(<4 x i32> %x) {
427423

428424
define i1 @lshr_by_const_cmp_uge_value(i32 %x) {
429425
; CHECK-LABEL: @lshr_by_const_cmp_uge_value(
430-
; CHECK-NEXT: [[V:%.*]] = lshr i32 [[X:%.*]], 3
431-
; CHECK-NEXT: [[R:%.*]] = icmp sle i32 [[V]], [[X]]
426+
; CHECK-NEXT: [[R:%.*]] = icmp sgt i32 [[X:%.*]], -1
432427
; CHECK-NEXT: ret i1 [[R]]
433428
;
434429
%v = lshr i32 %x, 3
@@ -438,8 +433,7 @@ define i1 @lshr_by_const_cmp_uge_value(i32 %x) {
438433

439434
define i1 @ashr_x_by_const_cmp_sge_x(i32 %x) {
440435
; CHECK-LABEL: @ashr_x_by_const_cmp_sge_x(
441-
; CHECK-NEXT: [[V:%.*]] = ashr i32 [[X:%.*]], 5
442-
; CHECK-NEXT: [[R:%.*]] = icmp sge i32 [[V]], [[X]]
436+
; CHECK-NEXT: [[R:%.*]] = icmp slt i32 [[X:%.*]], 1
443437
; CHECK-NEXT: ret i1 [[R]]
444438
;
445439
%v = ashr i32 %x, 5

0 commit comments

Comments
 (0)