Skip to content

Commit fdf5dab

Browse files
committed
[InstCombine] Add missing patterns for scmp and ucmp
Fixes: #146178
1 parent 0ded7a2 commit fdf5dab

File tree

2 files changed

+55
-48
lines changed

2 files changed

+55
-48
lines changed

llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3757,6 +3757,10 @@ static Instruction *foldBitCeil(SelectInst &SI, IRBuilderBase &Builder,
37573757
// (x < y) ? -1 : zext(x > y)
37583758
// (x > y) ? 1 : sext(x != y)
37593759
// (x > y) ? 1 : sext(x < y)
3760+
// (x == y) ? 0 : (x > y ? 1 : -1)
3761+
// (x == y) ? 0 : (x < y ? -1 : 1)
3762+
// Special case: x == C ? 0 : (x > C - 1 ? 1 : -1)
3763+
// Special case: x == C ? 0 : (x < C + 1 ? -1 : 1)
37603764
// Into ucmp/scmp(x, y), where signedness is determined by the signedness
37613765
// of the comparison in the original sequence.
37623766
Instruction *InstCombinerImpl::foldSelectToCmp(SelectInst &SI) {
@@ -3849,6 +3853,44 @@ Instruction *InstCombinerImpl::foldSelectToCmp(SelectInst &SI) {
38493853
}
38503854
}
38513855

3856+
// Special cases with constants: x == C ? 0 : (x > C-1 ? 1 : -1)
3857+
if (Pred == ICmpInst::ICMP_EQ && match(TV, m_Zero())) {
3858+
const APInt *C;
3859+
if (match(RHS, m_APInt(C))) {
3860+
CmpPredicate InnerPred;
3861+
Value *InnerRHS;
3862+
const APInt *InnerTV, *InnerFV;
3863+
if (match(FV,
3864+
m_Select(m_ICmp(InnerPred, m_Specific(LHS), m_Value(InnerRHS)),
3865+
m_APInt(InnerTV), m_APInt(InnerFV)))) {
3866+
3867+
// x == C ? 0 : (x > C-1 ? 1 : -1)
3868+
if (ICmpInst::isGT(InnerPred) && InnerTV->isOne() &&
3869+
InnerFV->isAllOnes()) {
3870+
IsSigned = ICmpInst::isSigned(InnerPred);
3871+
bool CanSubOne = IsSigned ? !C->isMinSignedValue() : !C->isMinValue();
3872+
if (CanSubOne) {
3873+
APInt Cminus1 = *C - 1;
3874+
if (match(InnerRHS, m_SpecificInt(Cminus1)))
3875+
Replace = true;
3876+
}
3877+
}
3878+
3879+
// x == C ? 0 : (x < C+1 ? -1 : 1)
3880+
if (ICmpInst::isLT(InnerPred) && InnerTV->isAllOnes() &&
3881+
InnerFV->isOne()) {
3882+
IsSigned = ICmpInst::isSigned(InnerPred);
3883+
bool CanAddOne = IsSigned ? !C->isMaxSignedValue() : !C->isMaxValue();
3884+
if (CanAddOne) {
3885+
APInt Cplus1 = *C + 1;
3886+
if (match(InnerRHS, m_SpecificInt(Cplus1)))
3887+
Replace = true;
3888+
}
3889+
}
3890+
}
3891+
}
3892+
}
3893+
38523894
Intrinsic::ID IID = IsSigned ? Intrinsic::scmp : Intrinsic::ucmp;
38533895
if (Replace)
38543896
return replaceInstUsesWith(

llvm/test/Transforms/InstCombine/scmp.ll

Lines changed: 13 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -457,8 +457,8 @@ define i8 @scmp_from_select_ne_and_gt_commuted3(i32 %x, i32 %y) {
457457
; CHECK-NEXT: ret i8 [[R]]
458458
;
459459
%ne = icmp ne i32 %x, %y
460-
%gt = icmp slt i32 %x, %y
461-
%sel1 = select i1 %gt, i8 -1, i8 1
460+
%gt = icmp sgt i32 %x, %y
461+
%sel1 = select i1 %gt, i8 1, i8 -1
462462
%r = select i1 %ne, i8 %sel1, i8 0
463463
ret i8 %r
464464
}
@@ -467,14 +467,11 @@ define i8 @scmp_from_select_ne_and_gt_commuted3(i32 %x, i32 %y) {
467467
define i8 @scmp_from_select_ne_const_and_gt_commuted1(i32 %x) {
468468
; CHECK-LABEL: define i8 @scmp_from_select_ne_const_and_gt_commuted1(
469469
; CHECK-SAME: i32 [[X:%.*]]) {
470-
; CHECK-NEXT: [[NE_NOT:%.*]] = icmp eq i32 [[X]], 5
471-
; CHECK-NEXT: [[GT:%.*]] = icmp slt i32 [[X]], 4
472-
; CHECK-NEXT: [[SEL1:%.*]] = select i1 [[GT]], i8 1, i8 -1
473-
; CHECK-NEXT: [[R:%.*]] = select i1 [[NE_NOT]], i8 0, i8 [[SEL1]]
470+
; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.scmp.i8.i32(i32 [[X]], i32 5)
474471
; CHECK-NEXT: ret i8 [[R]]
475472
;
476473
%ne = icmp ne i32 %x, 5
477-
%gt = icmp slt i32 %x, 4
474+
%gt = icmp sgt i32 %x, 4
478475
%sel1 = select i1 %gt, i8 1, i8 -1
479476
%r = select i1 %ne, i8 %sel1, i8 0
480477
ret i8 %r
@@ -483,31 +480,25 @@ define i8 @scmp_from_select_ne_const_and_gt_commuted1(i32 %x) {
483480
define i8 @scmp_from_select_ne_const_and_gt_commuted2(i32 %x) {
484481
; CHECK-LABEL: define i8 @scmp_from_select_ne_const_and_gt_commuted2(
485482
; CHECK-SAME: i32 [[X:%.*]]) {
486-
; CHECK-NEXT: [[NE_NOT:%.*]] = icmp eq i32 [[X]], 5
487-
; CHECK-NEXT: [[GT:%.*]] = icmp sgt i32 [[X]], 4
488-
; CHECK-NEXT: [[SEL1:%.*]] = select i1 [[GT]], i8 -1, i8 1
489-
; CHECK-NEXT: [[R:%.*]] = select i1 [[NE_NOT]], i8 0, i8 [[SEL1]]
483+
; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.scmp.i8.i32(i32 [[X]], i32 5)
490484
; CHECK-NEXT: ret i8 [[R]]
491485
;
492486
%ne = icmp ne i32 %x, 5
493487
%gt = icmp sgt i32 %x, 4
494-
%sel1 = select i1 %gt, i8 -1, i8 1
488+
%sel1 = select i1 %gt, i8 1, i8 -1
495489
%r = select i1 %ne, i8 %sel1, i8 0
496490
ret i8 %r
497491
}
498492

499493
define i8 @scmp_from_select_ne_const_and_gt_commuted3(i32 %x) {
500494
; CHECK-LABEL: define i8 @scmp_from_select_ne_const_and_gt_commuted3(
501495
; CHECK-SAME: i32 [[X:%.*]]) {
502-
; CHECK-NEXT: [[NE_NOT:%.*]] = icmp eq i32 [[X]], 5
503-
; CHECK-NEXT: [[GT:%.*]] = icmp slt i32 [[X]], 4
504-
; CHECK-NEXT: [[SEL1:%.*]] = select i1 [[GT]], i8 -1, i8 1
505-
; CHECK-NEXT: [[R:%.*]] = select i1 [[NE_NOT]], i8 0, i8 [[SEL1]]
496+
; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.scmp.i8.i32(i32 [[X]], i32 5)
506497
; CHECK-NEXT: ret i8 [[R]]
507498
;
508499
%ne = icmp ne i32 %x, 5
509-
%gt = icmp slt i32 %x, 4
510-
%sel1 = select i1 %gt, i8 -1, i8 1
500+
%gt = icmp sgt i32 %x, 4
501+
%sel1 = select i1 %gt, i8 1, i8 -1
511502
%r = select i1 %ne, i8 %sel1, i8 0
512503
ret i8 %r
513504
}
@@ -525,20 +516,6 @@ define <3 x i2> @scmp_unary_shuffle_ops(<3 x i8> %x, <3 x i8> %y) {
525516
ret <3 x i2> %r
526517
}
527518

528-
define i32 @scmp_ashr(i32 %a) {
529-
; CHECK-LABEL: define i32 @scmp_ashr(
530-
; CHECK-SAME: i32 [[A:%.*]]) {
531-
; CHECK-NEXT: [[A_LOBIT:%.*]] = ashr i32 [[A]], 31
532-
; CHECK-NEXT: [[CMP_INV:%.*]] = icmp slt i32 [[A]], 1
533-
; CHECK-NEXT: [[RETVAL_0:%.*]] = select i1 [[CMP_INV]], i32 [[A_LOBIT]], i32 1
534-
; CHECK-NEXT: ret i32 [[RETVAL_0]]
535-
;
536-
%a.lobit = ashr i32 %a, 31
537-
%cmp.inv = icmp slt i32 %a, 1
538-
%retval.0 = select i1 %cmp.inv, i32 %a.lobit, i32 1
539-
ret i32 %retval.0
540-
}
541-
542519
define i32 @scmp_sgt_slt(i32 %a) {
543520
; CHECK-LABEL: define i32 @scmp_sgt_slt(
544521
; CHECK-SAME: i32 [[A:%.*]]) {
@@ -557,10 +534,7 @@ define i32 @scmp_sgt_slt(i32 %a) {
557534
define i32 @scmp_zero_slt(i32 %a) {
558535
; CHECK-LABEL: define i32 @scmp_zero_slt(
559536
; CHECK-SAME: i32 [[A:%.*]]) {
560-
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[A]], 0
561-
; CHECK-NEXT: [[CMP1_INV:%.*]] = icmp slt i32 [[A]], 1
562-
; CHECK-NEXT: [[DOT:%.*]] = select i1 [[CMP1_INV]], i32 -1, i32 1
563-
; CHECK-NEXT: [[RETVAL_0:%.*]] = select i1 [[CMP]], i32 0, i32 [[DOT]]
537+
; CHECK-NEXT: [[RETVAL_0:%.*]] = call i32 @llvm.scmp.i32.i32(i32 [[A]], i32 0)
564538
; CHECK-NEXT: ret i32 [[RETVAL_0]]
565539
;
566540
%cmp = icmp eq i32 %a, 0
@@ -573,10 +547,7 @@ define i32 @scmp_zero_slt(i32 %a) {
573547
define i32 @scmp_zero_sgt(i32 %a) {
574548
; CHECK-LABEL: define i32 @scmp_zero_sgt(
575549
; CHECK-SAME: i32 [[A:%.*]]) {
576-
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[A]], 0
577-
; CHECK-NEXT: [[CMP1_INV:%.*]] = icmp sgt i32 [[A]], -1
578-
; CHECK-NEXT: [[DOT:%.*]] = select i1 [[CMP1_INV]], i32 1, i32 -1
579-
; CHECK-NEXT: [[RETVAL_0:%.*]] = select i1 [[CMP]], i32 0, i32 [[DOT]]
550+
; CHECK-NEXT: [[RETVAL_0:%.*]] = call i32 @llvm.scmp.i32.i32(i32 [[A]], i32 0)
580551
; CHECK-NEXT: ret i32 [[RETVAL_0]]
581552
;
582553
%cmp = icmp eq i32 %a, 0
@@ -590,10 +561,7 @@ define i32 @scmp_zero_sgt(i32 %a) {
590561
define i32 @scmp_zero_sgt_1(i32 %a) {
591562
; CHECK-LABEL: define i32 @scmp_zero_sgt_1(
592563
; CHECK-SAME: i32 [[A:%.*]]) {
593-
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[A]], 0
594-
; CHECK-NEXT: [[CMP1:%.*]] = icmp sgt i32 [[A]], -1
595-
; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP1]], i32 1, i32 -1
596-
; CHECK-NEXT: [[COND2:%.*]] = select i1 [[CMP]], i32 0, i32 [[COND]]
564+
; CHECK-NEXT: [[COND2:%.*]] = call i32 @llvm.scmp.i32.i32(i32 [[A]], i32 0)
597565
; CHECK-NEXT: ret i32 [[COND2]]
598566
;
599567
%cmp = icmp eq i32 %a, 0
@@ -606,10 +574,7 @@ define i32 @scmp_zero_sgt_1(i32 %a) {
606574
define i32 @scmp_zero_slt_1(i32 %a) {
607575
; CHECK-LABEL: define i32 @scmp_zero_slt_1(
608576
; CHECK-SAME: i32 [[A:%.*]]) {
609-
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[A]], 0
610-
; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i32 [[A]], 1
611-
; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP1]], i32 -1, i32 1
612-
; CHECK-NEXT: [[COND2:%.*]] = select i1 [[CMP]], i32 0, i32 [[COND]]
577+
; CHECK-NEXT: [[COND2:%.*]] = call i32 @llvm.scmp.i32.i32(i32 [[A]], i32 0)
613578
; CHECK-NEXT: ret i32 [[COND2]]
614579
;
615580
%cmp = icmp eq i32 %a, 0

0 commit comments

Comments
 (0)