Skip to content

Commit a876476

Browse files
AZero13nikicdtcxzyw
committed
[InstCombine] smin(smax(X, -1), 1) -> scmp(X, 0) and smax(smin(X, 1), -1) -> scmp(X, 0)
Motivating case: https://godbolt.org/z/Wxcc51jcj Alive2: https://alive2.llvm.org/ce/z/-bPPAg Co-Authored-By: Nikita Popov <[email protected]> Co-Authored-By: Yingwei Zheng <[email protected]>
1 parent b16eb26 commit a876476

File tree

2 files changed

+30
-6
lines changed

2 files changed

+30
-6
lines changed

llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1972,6 +1972,21 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
19721972
return BinaryOperator::CreateOr(I0, I1);
19731973
}
19741974

1975+
// smin(smax(X, -1), 1) -> scmp(X, 0)
1976+
// smax(smin(X, 1), -1) -> scmp(X, 0)
1977+
// At this point, smax(smin(X, 1), -1) is changed to smin(smax(X, -1)
1978+
// And i1's have been changed to and/ors
1979+
// So we only need to check for smin
1980+
if (IID == Intrinsic::smin) {
1981+
if (match(I0, m_OneUse(m_SMax(m_Value(X), m_AllOnes()))) &&
1982+
match(I1, m_One())) {
1983+
Value *Zero = ConstantInt::get(X->getType(), 0);
1984+
return replaceInstUsesWith(
1985+
CI,
1986+
Builder.CreateIntrinsic(II->getType(), Intrinsic::scmp, {X, Zero}));
1987+
}
1988+
}
1989+
19751990
if (IID == Intrinsic::smax || IID == Intrinsic::smin) {
19761991
// smax (neg nsw X), (neg nsw Y) --> neg nsw (smin X, Y)
19771992
// smin (neg nsw X), (neg nsw Y) --> neg nsw (smax X, Y)

llvm/test/Transforms/InstCombine/compare-3way.ll

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -564,8 +564,7 @@ unreached:
564564
define i32 @smax_smin_to_scmp(i32 %x) {
565565
; CHECK-LABEL: define i32 @smax_smin_to_scmp
566566
; CHECK-SAME: (i32 [[X:%.*]]) {
567-
; CHECK-NEXT: [[COND:%.*]] = call i32 @llvm.smax.i32(i32 [[X]], i32 -1)
568-
; CHECK-NEXT: [[COND5:%.*]] = call i32 @llvm.smin.i32(i32 [[COND]], i32 1)
567+
; CHECK-NEXT: [[COND5:%.*]] = call i32 @llvm.scmp.i32.i32(i32 [[X]], i32 0)
569568
; CHECK-NEXT: ret i32 [[COND5]]
570569
;
571570
%cond = call i32 @llvm.smax.i32(i32 %x, i32 -1)
@@ -576,8 +575,7 @@ define i32 @smax_smin_to_scmp(i32 %x) {
576575
define i16 @smax_smin_to_scmp_i16(i16 %x) {
577576
; CHECK-LABEL: define i16 @smax_smin_to_scmp_i16
578577
; CHECK-SAME: (i16 [[X:%.*]]) {
579-
; CHECK-NEXT: [[COND:%.*]] = call i16 @llvm.smax.i16(i16 [[X]], i16 -1)
580-
; CHECK-NEXT: [[COND5:%.*]] = call i16 @llvm.smin.i16(i16 [[COND]], i16 1)
578+
; CHECK-NEXT: [[COND5:%.*]] = call i16 @llvm.scmp.i16.i16(i16 [[X]], i16 0)
581579
; CHECK-NEXT: ret i16 [[COND5]]
582580
;
583581
%cond = call i16 @llvm.smax.i16(i16 %x, i16 -1)
@@ -589,8 +587,7 @@ define i16 @smax_smin_to_scmp_i16(i16 %x) {
589587
define i32 @smin_smax_to_scmp(i32 %x) {
590588
; CHECK-LABEL: define i32 @smin_smax_to_scmp
591589
; CHECK-SAME: (i32 [[X:%.*]]) {
592-
; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.smax.i32(i32 [[X]], i32 -1)
593-
; CHECK-NEXT: [[COND5:%.*]] = call i32 @llvm.smin.i32(i32 [[TMP1]], i32 1)
590+
; CHECK-NEXT: [[COND5:%.*]] = call i32 @llvm.scmp.i32.i32(i32 [[X]], i32 0)
594591
; CHECK-NEXT: ret i32 [[COND5]]
595592
;
596593
%cond = call i32 @llvm.smin.i32(i32 %x, i32 1)
@@ -610,6 +607,18 @@ define i32 @test_max_min_neg(i32 %x) {
610607
ret i32 %cond5
611608
}
612609

610+
define i32 @test_max_min_neg_2(i32 %x) {
611+
; CHECK-LABEL: define i32 @test_max_min_neg_2
612+
; CHECK-SAME: (i32 [[X:%.*]]) {
613+
; CHECK-NEXT: [[COND:%.*]] = call i32 @llvm.smax.i32(i32 [[X]], i32 -1)
614+
; CHECK-NEXT: [[COND5:%.*]] = call i32 @llvm.smin.i32(i32 [[COND]], i32 2)
615+
; CHECK-NEXT: ret i32 [[COND5]]
616+
;
617+
%cond = call i32 @llvm.smax.i32(i32 %x, i32 -1)
618+
%cond5 = call i32 @llvm.smin.i32(i32 %cond, i32 2)
619+
ret i32 %cond5
620+
}
621+
613622
define i32 @test_multiple_uses(i32 %x) {
614623
; CHECK-LABEL: define i32 @test_multiple_uses
615624
; CHECK-SAME: (i32 [[X:%.*]]) {

0 commit comments

Comments
 (0)