Skip to content

Commit bbd90a3

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

File tree

2 files changed

+56
-34
lines changed

2 files changed

+56
-34
lines changed

llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp

Lines changed: 43 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,45 @@ 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+
Value *X;
3859+
const APInt *C;
3860+
if (match(LHS, m_Value(X)) && match(RHS, m_APInt(C))) {
3861+
CmpPredicate InnerPred;
3862+
Value *InnerLHS, *InnerRHS;
3863+
const APInt *InnerTV, *InnerFV;
3864+
if (match(FV, m_Select(
3865+
m_ICmp(InnerPred, m_Value(InnerLHS), m_Value(InnerRHS)),
3866+
m_APInt(InnerTV), m_APInt(InnerFV)))) {
3867+
3868+
// x == C ? 0 : (x > C-1 ? 1 : -1)
3869+
if (ICmpInst::isGT(InnerPred) && InnerTV->isOne() &&
3870+
InnerFV->isAllOnes()) {
3871+
IsSigned = ICmpInst::isSigned(InnerPred);
3872+
bool CanSubOne = IsSigned ? !C->isMinSignedValue() : !C->isMinValue();
3873+
if (CanSubOne) {
3874+
APInt Cminus1 = *C - 1;
3875+
if (InnerLHS == X && match(InnerRHS, m_SpecificInt(Cminus1)))
3876+
Replace = true;
3877+
}
3878+
}
3879+
3880+
// x == C ? 0 : (x < C+1 ? -1 : 1)
3881+
if (ICmpInst::isLT(InnerPred) && InnerTV->isAllOnes() &&
3882+
InnerFV->isOne()) {
3883+
IsSigned = ICmpInst::isSigned(InnerPred);
3884+
bool CanAddOne = IsSigned ? !C->isMaxSignedValue() : !C->isMaxValue();
3885+
if (CanAddOne) {
3886+
APInt Cplus1 = *C + 1;
3887+
if (InnerLHS == X && match(InnerRHS, m_SpecificInt(Cplus1)))
3888+
Replace = true;
3889+
}
3890+
}
3891+
}
3892+
}
3893+
}
3894+
38523895
Intrinsic::ID IID = IsSigned ? Intrinsic::scmp : Intrinsic::ucmp;
38533896
if (Replace)
38543897
return replaceInstUsesWith(

llvm/test/Transforms/InstCombine/scmp.ll

Lines changed: 13 additions & 34 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
}
@@ -557,10 +548,7 @@ define i32 @scmp_sgt_slt(i32 %a) {
557548
define i32 @scmp_zero_slt(i32 %a) {
558549
; CHECK-LABEL: define i32 @scmp_zero_slt(
559550
; 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]]
551+
; CHECK-NEXT: [[RETVAL_0:%.*]] = call i32 @llvm.scmp.i32.i32(i32 [[A]], i32 0)
564552
; CHECK-NEXT: ret i32 [[RETVAL_0]]
565553
;
566554
%cmp = icmp eq i32 %a, 0
@@ -573,10 +561,7 @@ define i32 @scmp_zero_slt(i32 %a) {
573561
define i32 @scmp_zero_sgt(i32 %a) {
574562
; CHECK-LABEL: define i32 @scmp_zero_sgt(
575563
; 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]]
564+
; CHECK-NEXT: [[RETVAL_0:%.*]] = call i32 @llvm.scmp.i32.i32(i32 [[A]], i32 0)
580565
; CHECK-NEXT: ret i32 [[RETVAL_0]]
581566
;
582567
%cmp = icmp eq i32 %a, 0
@@ -590,10 +575,7 @@ define i32 @scmp_zero_sgt(i32 %a) {
590575
define i32 @scmp_zero_sgt_1(i32 %a) {
591576
; CHECK-LABEL: define i32 @scmp_zero_sgt_1(
592577
; 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]]
578+
; CHECK-NEXT: [[COND2:%.*]] = call i32 @llvm.scmp.i32.i32(i32 [[A]], i32 0)
597579
; CHECK-NEXT: ret i32 [[COND2]]
598580
;
599581
%cmp = icmp eq i32 %a, 0
@@ -606,10 +588,7 @@ define i32 @scmp_zero_sgt_1(i32 %a) {
606588
define i32 @scmp_zero_slt_1(i32 %a) {
607589
; CHECK-LABEL: define i32 @scmp_zero_slt_1(
608590
; 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]]
591+
; CHECK-NEXT: [[COND2:%.*]] = call i32 @llvm.scmp.i32.i32(i32 [[A]], i32 0)
613592
; CHECK-NEXT: ret i32 [[COND2]]
614593
;
615594
%cmp = icmp eq i32 %a, 0

0 commit comments

Comments
 (0)