From 481e053c0a6a630f9279eafa7b3db18ebbcf6d81 Mon Sep 17 00:00:00 2001 From: Poseydon42 Date: Wed, 4 Sep 2024 21:51:18 +0100 Subject: [PATCH 1/6] Precommit tests --- llvm/test/Transforms/InstCombine/scmp.ll | 116 +++++++++++++++++++++++ llvm/test/Transforms/InstCombine/ucmp.ll | 17 ++++ 2 files changed, 133 insertions(+) diff --git a/llvm/test/Transforms/InstCombine/scmp.ll b/llvm/test/Transforms/InstCombine/scmp.ll index 123bc64746233..8b430a44cfeb3 100644 --- a/llvm/test/Transforms/InstCombine/scmp.ll +++ b/llvm/test/Transforms/InstCombine/scmp.ll @@ -343,3 +343,119 @@ define i8 @scmp_from_select_gt_and_lt(i32 %x, i32 %y) { %r = select i1 %gt, i8 1, i8 %lt ret i8 %r } + +; (x == y) ? 0 : (x s> y ? 1 : -1) into scmp(x, y) +define i8 @scmp_from_select_eq_and_gt(i32 %x, i32 %y) { +; CHECK-LABEL: define i8 @scmp_from_select_eq_and_gt( +; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { +; CHECK-NEXT: [[EQ:%.*]] = icmp eq i32 [[X]], [[Y]] +; CHECK-NEXT: [[GT:%.*]] = icmp sgt i32 [[X]], [[Y]] +; CHECK-NEXT: [[SEL1:%.*]] = select i1 [[GT]], i8 1, i8 -1 +; CHECK-NEXT: [[R:%.*]] = select i1 [[EQ]], i8 0, i8 [[SEL1]] +; CHECK-NEXT: ret i8 [[R]] +; + %eq = icmp eq i32 %x, %y + %gt = icmp sgt i32 %x, %y + %sel1 = select i1 %gt, i8 1, i8 -1 + %r = select i1 %eq, i8 0, i8 %sel1 + ret i8 %r +} + +define i8 @scmp_from_select_eq_and_gt_commuted1(i32 %x, i32 %y) { +; CHECK-LABEL: define i8 @scmp_from_select_eq_and_gt_commuted1( +; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { +; CHECK-NEXT: [[EQ:%.*]] = icmp eq i32 [[X]], [[Y]] +; CHECK-NEXT: [[GT:%.*]] = icmp slt i32 [[X]], [[Y]] +; CHECK-NEXT: [[SEL1:%.*]] = select i1 [[GT]], i8 1, i8 -1 +; CHECK-NEXT: [[R:%.*]] = select i1 [[EQ]], i8 0, i8 [[SEL1]] +; CHECK-NEXT: ret i8 [[R]] +; + %eq = icmp eq i32 %x, %y + %gt = icmp slt i32 %x, %y + %sel1 = select i1 %gt, i8 1, i8 -1 + %r = select i1 %eq, i8 0, i8 %sel1 + ret i8 %r +} + +define i8 @scmp_from_select_eq_and_gt_commuted2(i32 %x, i32 %y) { +; CHECK-LABEL: define i8 @scmp_from_select_eq_and_gt_commuted2( +; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { +; CHECK-NEXT: [[EQ:%.*]] = icmp eq i32 [[X]], [[Y]] +; CHECK-NEXT: [[GT:%.*]] = icmp sgt i32 [[X]], [[Y]] +; CHECK-NEXT: [[SEL1:%.*]] = select i1 [[GT]], i8 -1, i8 1 +; CHECK-NEXT: [[R:%.*]] = select i1 [[EQ]], i8 0, i8 [[SEL1]] +; CHECK-NEXT: ret i8 [[R]] +; + %eq = icmp eq i32 %x, %y + %gt = icmp sgt i32 %x, %y + %sel1 = select i1 %gt, i8 -1, i8 1 + %r = select i1 %eq, i8 0, i8 %sel1 + ret i8 %r +} + +define i8 @scmp_from_select_eq_and_gt_commuted3(i32 %x, i32 %y) { +; CHECK-LABEL: define i8 @scmp_from_select_eq_and_gt_commuted3( +; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { +; CHECK-NEXT: [[EQ:%.*]] = icmp eq i32 [[X]], [[Y]] +; CHECK-NEXT: [[GT:%.*]] = icmp slt i32 [[X]], [[Y]] +; CHECK-NEXT: [[SEL1:%.*]] = select i1 [[GT]], i8 -1, i8 1 +; CHECK-NEXT: [[R:%.*]] = select i1 [[EQ]], i8 0, i8 [[SEL1]] +; CHECK-NEXT: ret i8 [[R]] +; + %eq = icmp eq i32 %x, %y + %gt = icmp slt i32 %x, %y + %sel1 = select i1 %gt, i8 -1, i8 1 + %r = select i1 %eq, i8 0, i8 %sel1 + ret i8 %r +} + +; Negative test: true value of outer select is not zero +define i8 @scmp_from_select_eq_and_gt_neg1(i32 %x, i32 %y) { +; CHECK-LABEL: define i8 @scmp_from_select_eq_and_gt_neg1( +; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { +; CHECK-NEXT: [[EQ:%.*]] = icmp eq i32 [[X]], [[Y]] +; CHECK-NEXT: [[GT:%.*]] = icmp sgt i32 [[X]], [[Y]] +; CHECK-NEXT: [[SEL1:%.*]] = select i1 [[GT]], i8 1, i8 -1 +; CHECK-NEXT: [[R:%.*]] = select i1 [[EQ]], i8 5, i8 [[SEL1]] +; CHECK-NEXT: ret i8 [[R]] +; + %eq = icmp eq i32 %x, %y + %gt = icmp sgt i32 %x, %y + %sel1 = select i1 %gt, i8 1, i8 -1 + %r = select i1 %eq, i8 5, i8 %sel1 + ret i8 %r +} + +; Negative test: true value of inner select is not 1 or -1 +define i8 @scmp_from_select_eq_and_gt_neg2(i32 %x, i32 %y) { +; CHECK-LABEL: define i8 @scmp_from_select_eq_and_gt_neg2( +; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { +; CHECK-NEXT: [[EQ:%.*]] = icmp eq i32 [[X]], [[Y]] +; CHECK-NEXT: [[GT:%.*]] = icmp sgt i32 [[X]], [[Y]] +; CHECK-NEXT: [[SEL1:%.*]] = select i1 [[GT]], i8 2, i8 -1 +; CHECK-NEXT: [[R:%.*]] = select i1 [[EQ]], i8 0, i8 [[SEL1]] +; CHECK-NEXT: ret i8 [[R]] +; + %eq = icmp eq i32 %x, %y + %gt = icmp sgt i32 %x, %y + %sel1 = select i1 %gt, i8 2, i8 -1 + %r = select i1 %eq, i8 0, i8 %sel1 + ret i8 %r +} + +; Negative test: false value of inner select is not 1 or -1 +define i8 @scmp_from_select_eq_and_gt_neg3(i32 %x, i32 %y) { +; CHECK-LABEL: define i8 @scmp_from_select_eq_and_gt_neg3( +; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { +; CHECK-NEXT: [[EQ:%.*]] = icmp eq i32 [[X]], [[Y]] +; CHECK-NEXT: [[GT:%.*]] = icmp sgt i32 [[X]], [[Y]] +; CHECK-NEXT: [[SEL1:%.*]] = select i1 [[GT]], i8 1, i8 22 +; CHECK-NEXT: [[R:%.*]] = select i1 [[EQ]], i8 0, i8 [[SEL1]] +; CHECK-NEXT: ret i8 [[R]] +; + %eq = icmp eq i32 %x, %y + %gt = icmp sgt i32 %x, %y + %sel1 = select i1 %gt, i8 1, i8 22 + %r = select i1 %eq, i8 0, i8 %sel1 + ret i8 %r +} diff --git a/llvm/test/Transforms/InstCombine/ucmp.ll b/llvm/test/Transforms/InstCombine/ucmp.ll index 13755f13bb0a1..8fe3646ec0ec5 100644 --- a/llvm/test/Transforms/InstCombine/ucmp.ll +++ b/llvm/test/Transforms/InstCombine/ucmp.ll @@ -541,3 +541,20 @@ define i8 @ucmp_from_select_gt_and_lt(i32 %x, i32 %y) { %r = select i1 %gt, i8 1, i8 %lt ret i8 %r } + +; (x == y) ? 0 : (x u> y ? 1 : -1) into ucmp(x, y) +define i8 @scmp_from_select_eq_and_gt(i32 %x, i32 %y) { +; CHECK-LABEL: define i8 @scmp_from_select_eq_and_gt( +; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { +; CHECK-NEXT: [[EQ:%.*]] = icmp eq i32 [[X]], [[Y]] +; CHECK-NEXT: [[GT:%.*]] = icmp ugt i32 [[X]], [[Y]] +; CHECK-NEXT: [[SEL1:%.*]] = select i1 [[GT]], i8 1, i8 -1 +; CHECK-NEXT: [[R:%.*]] = select i1 [[EQ]], i8 0, i8 [[SEL1]] +; CHECK-NEXT: ret i8 [[R]] +; + %eq = icmp eq i32 %x, %y + %gt = icmp ugt i32 %x, %y + %sel1 = select i1 %gt, i8 1, i8 -1 + %r = select i1 %eq, i8 0, i8 %sel1 + ret i8 %r +} From 839adc798c73acf94e18862aa34e140597176d08 Mon Sep 17 00:00:00 2001 From: Poseydon42 Date: Wed, 4 Sep 2024 21:54:37 +0100 Subject: [PATCH 2/6] Implement the fold --- .../InstCombine/InstCombineSelect.cpp | 31 +++++++++++++++++-- llvm/test/Transforms/InstCombine/scmp.ll | 20 +++--------- llvm/test/Transforms/InstCombine/ucmp.ll | 5 +-- 3 files changed, 33 insertions(+), 23 deletions(-) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp index 66f7c4592457c..92154493cd4bb 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp @@ -3551,9 +3551,7 @@ Instruction *InstCombinerImpl::foldSelectToCmp(SelectInst &SI) { Pred = ICmpInst::getSwappedPredicate(Pred); std::swap(LHS, RHS); } - - Intrinsic::ID IID = - ICmpInst::isSigned(Pred) ? Intrinsic::scmp : Intrinsic::ucmp; + bool IsSigned = ICmpInst::isSigned(Pred); bool Replace = false; ICmpInst::Predicate ExtendedCmpPredicate; @@ -3575,6 +3573,33 @@ Instruction *InstCombinerImpl::foldSelectToCmp(SelectInst &SI) { ICmpInst::getSwappedPredicate(ExtendedCmpPredicate) == Pred)) Replace = true; + // (x == y) ? 0 : (x > y ? 1 : -1) + ICmpInst::Predicate FalseBranchSelectPredicate; + ConstantInt *InnerTV, *InnerFV; + if (Pred == ICmpInst::ICMP_EQ && match(TV, m_Zero()) && + match(FV, m_Select(m_c_ICmp(FalseBranchSelectPredicate, m_Specific(LHS), + m_Specific(RHS)), + m_ConstantInt(InnerTV), m_ConstantInt(InnerFV)))) { + if (!ICmpInst::isGT(FalseBranchSelectPredicate)) { + FalseBranchSelectPredicate = + ICmpInst::getSwappedPredicate(FalseBranchSelectPredicate); + std::swap(LHS, RHS); + } + + if (!InnerTV->isOne()) { + std::swap(InnerTV, InnerFV); + std::swap(LHS, RHS); + } + + if (ICmpInst::isGT(FalseBranchSelectPredicate) && InnerTV->isOne() && + InnerFV->isAllOnesValue()) { + IsSigned = ICmpInst::isSigned(FalseBranchSelectPredicate); + Replace = true; + } + } + + Intrinsic::ID IID = + IsSigned ? Intrinsic::scmp : Intrinsic::ucmp; if (Replace) return replaceInstUsesWith( SI, Builder.CreateIntrinsic(SI.getType(), IID, {LHS, RHS})); diff --git a/llvm/test/Transforms/InstCombine/scmp.ll b/llvm/test/Transforms/InstCombine/scmp.ll index 8b430a44cfeb3..397621b8c878e 100644 --- a/llvm/test/Transforms/InstCombine/scmp.ll +++ b/llvm/test/Transforms/InstCombine/scmp.ll @@ -348,10 +348,7 @@ define i8 @scmp_from_select_gt_and_lt(i32 %x, i32 %y) { define i8 @scmp_from_select_eq_and_gt(i32 %x, i32 %y) { ; CHECK-LABEL: define i8 @scmp_from_select_eq_and_gt( ; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { -; CHECK-NEXT: [[EQ:%.*]] = icmp eq i32 [[X]], [[Y]] -; CHECK-NEXT: [[GT:%.*]] = icmp sgt i32 [[X]], [[Y]] -; CHECK-NEXT: [[SEL1:%.*]] = select i1 [[GT]], i8 1, i8 -1 -; CHECK-NEXT: [[R:%.*]] = select i1 [[EQ]], i8 0, i8 [[SEL1]] +; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.scmp.i8.i32(i32 [[X]], i32 [[Y]]) ; CHECK-NEXT: ret i8 [[R]] ; %eq = icmp eq i32 %x, %y @@ -364,10 +361,7 @@ define i8 @scmp_from_select_eq_and_gt(i32 %x, i32 %y) { define i8 @scmp_from_select_eq_and_gt_commuted1(i32 %x, i32 %y) { ; CHECK-LABEL: define i8 @scmp_from_select_eq_and_gt_commuted1( ; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { -; CHECK-NEXT: [[EQ:%.*]] = icmp eq i32 [[X]], [[Y]] -; CHECK-NEXT: [[GT:%.*]] = icmp slt i32 [[X]], [[Y]] -; CHECK-NEXT: [[SEL1:%.*]] = select i1 [[GT]], i8 1, i8 -1 -; CHECK-NEXT: [[R:%.*]] = select i1 [[EQ]], i8 0, i8 [[SEL1]] +; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.scmp.i8.i32(i32 [[Y]], i32 [[X]]) ; CHECK-NEXT: ret i8 [[R]] ; %eq = icmp eq i32 %x, %y @@ -380,10 +374,7 @@ define i8 @scmp_from_select_eq_and_gt_commuted1(i32 %x, i32 %y) { define i8 @scmp_from_select_eq_and_gt_commuted2(i32 %x, i32 %y) { ; CHECK-LABEL: define i8 @scmp_from_select_eq_and_gt_commuted2( ; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { -; CHECK-NEXT: [[EQ:%.*]] = icmp eq i32 [[X]], [[Y]] -; CHECK-NEXT: [[GT:%.*]] = icmp sgt i32 [[X]], [[Y]] -; CHECK-NEXT: [[SEL1:%.*]] = select i1 [[GT]], i8 -1, i8 1 -; CHECK-NEXT: [[R:%.*]] = select i1 [[EQ]], i8 0, i8 [[SEL1]] +; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.scmp.i8.i32(i32 [[Y]], i32 [[X]]) ; CHECK-NEXT: ret i8 [[R]] ; %eq = icmp eq i32 %x, %y @@ -396,10 +387,7 @@ define i8 @scmp_from_select_eq_and_gt_commuted2(i32 %x, i32 %y) { define i8 @scmp_from_select_eq_and_gt_commuted3(i32 %x, i32 %y) { ; CHECK-LABEL: define i8 @scmp_from_select_eq_and_gt_commuted3( ; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { -; CHECK-NEXT: [[EQ:%.*]] = icmp eq i32 [[X]], [[Y]] -; CHECK-NEXT: [[GT:%.*]] = icmp slt i32 [[X]], [[Y]] -; CHECK-NEXT: [[SEL1:%.*]] = select i1 [[GT]], i8 -1, i8 1 -; CHECK-NEXT: [[R:%.*]] = select i1 [[EQ]], i8 0, i8 [[SEL1]] +; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.scmp.i8.i32(i32 [[X]], i32 [[Y]]) ; CHECK-NEXT: ret i8 [[R]] ; %eq = icmp eq i32 %x, %y diff --git a/llvm/test/Transforms/InstCombine/ucmp.ll b/llvm/test/Transforms/InstCombine/ucmp.ll index 8fe3646ec0ec5..2d5036019740c 100644 --- a/llvm/test/Transforms/InstCombine/ucmp.ll +++ b/llvm/test/Transforms/InstCombine/ucmp.ll @@ -546,10 +546,7 @@ define i8 @ucmp_from_select_gt_and_lt(i32 %x, i32 %y) { define i8 @scmp_from_select_eq_and_gt(i32 %x, i32 %y) { ; CHECK-LABEL: define i8 @scmp_from_select_eq_and_gt( ; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { -; CHECK-NEXT: [[EQ:%.*]] = icmp eq i32 [[X]], [[Y]] -; CHECK-NEXT: [[GT:%.*]] = icmp ugt i32 [[X]], [[Y]] -; CHECK-NEXT: [[SEL1:%.*]] = select i1 [[GT]], i8 1, i8 -1 -; CHECK-NEXT: [[R:%.*]] = select i1 [[EQ]], i8 0, i8 [[SEL1]] +; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.ucmp.i8.i32(i32 [[X]], i32 [[Y]]) ; CHECK-NEXT: ret i8 [[R]] ; %eq = icmp eq i32 %x, %y From 4f388a4e59a9072c93ab1b43a8b2ec73324caeeb Mon Sep 17 00:00:00 2001 From: Poseydon42 Date: Wed, 4 Sep 2024 22:19:11 +0100 Subject: [PATCH 3/6] Update existing tests --- .../Transforms/InstCombine/compare-3way.ll | 39 +++++-------------- .../Transforms/InstCombine/select-select.ll | 30 ++++---------- .../InstCombine/sink_to_unreachable.ll | 9 ++--- 3 files changed, 20 insertions(+), 58 deletions(-) diff --git a/llvm/test/Transforms/InstCombine/compare-3way.ll b/llvm/test/Transforms/InstCombine/compare-3way.ll index e2067368fb4c3..5d443cd45238c 100644 --- a/llvm/test/Transforms/InstCombine/compare-3way.ll +++ b/llvm/test/Transforms/InstCombine/compare-3way.ll @@ -15,8 +15,7 @@ define void @test_low_sgt(i64 %a, i64 %b) { ; CHECK: normal: ; CHECK-NEXT: ret void ; CHECK: unreached: -; CHECK-NEXT: [[EQ:%.*]] = icmp ne i64 [[A]], [[B]] -; CHECK-NEXT: [[RESULT:%.*]] = zext i1 [[EQ]] to i32 +; CHECK-NEXT: [[RESULT:%.*]] = call i32 @llvm.scmp.i32.i64(i64 [[A]], i64 [[B]]) ; CHECK-NEXT: call void @use(i32 [[RESULT]]) ; CHECK-NEXT: ret void ; @@ -62,10 +61,7 @@ define void @test_low_sge(i64 %a, i64 %b) { ; CHECK: normal: ; CHECK-NEXT: ret void ; CHECK: unreached: -; CHECK-NEXT: [[EQ:%.*]] = icmp eq i64 [[A]], [[B]] -; CHECK-NEXT: [[SLT:%.*]] = icmp slt i64 [[A]], [[B]] -; CHECK-NEXT: [[DOT:%.*]] = select i1 [[SLT]], i32 -1, i32 1 -; CHECK-NEXT: [[RESULT:%.*]] = select i1 [[EQ]], i32 0, i32 [[DOT]] +; CHECK-NEXT: [[RESULT:%.*]] = call i32 @llvm.scmp.i32.i64(i64 [[A]], i64 [[B]]) ; CHECK-NEXT: call void @use(i32 [[RESULT]]) ; CHECK-NEXT: ret void ; @@ -114,8 +110,7 @@ define void @test_low_ne(i64 %a, i64 %b) { ; CHECK: normal: ; CHECK-NEXT: ret void ; CHECK: unreached: -; CHECK-NEXT: [[EQ:%.*]] = icmp ne i64 [[A]], [[B]] -; CHECK-NEXT: [[RESULT:%.*]] = zext i1 [[EQ]] to i32 +; CHECK-NEXT: [[RESULT:%.*]] = call i32 @llvm.scmp.i32.i64(i64 [[A]], i64 [[B]]) ; CHECK-NEXT: call void @use(i32 [[RESULT]]) ; CHECK-NEXT: ret void ; @@ -212,8 +207,7 @@ define void @test_mid_sge(i64 %a, i64 %b) { ; CHECK: normal: ; CHECK-NEXT: ret void ; CHECK: unreached: -; CHECK-NEXT: [[EQ:%.*]] = icmp ne i64 [[A]], [[B]] -; CHECK-NEXT: [[RESULT:%.*]] = zext i1 [[EQ]] to i32 +; CHECK-NEXT: [[RESULT:%.*]] = call i32 @llvm.scmp.i32.i64(i64 [[A]], i64 [[B]]) ; CHECK-NEXT: call void @use(i32 [[RESULT]]) ; CHECK-NEXT: ret void ; @@ -238,10 +232,7 @@ define void @test_mid_sle(i64 %a, i64 %b) { ; CHECK: normal: ; CHECK-NEXT: ret void ; CHECK: unreached: -; CHECK-NEXT: [[EQ:%.*]] = icmp eq i64 [[A]], [[B]] -; CHECK-NEXT: [[SLT:%.*]] = icmp slt i64 [[A]], [[B]] -; CHECK-NEXT: [[DOT:%.*]] = select i1 [[SLT]], i32 -1, i32 1 -; CHECK-NEXT: [[RESULT:%.*]] = select i1 [[EQ]], i32 0, i32 [[DOT]] +; CHECK-NEXT: [[RESULT:%.*]] = call i32 @llvm.scmp.i32.i64(i64 [[A]], i64 [[B]]) ; CHECK-NEXT: call void @use(i32 [[RESULT]]) ; CHECK-NEXT: ret void ; @@ -266,9 +257,8 @@ define void @test_mid_ne(i64 %a, i64 %b) { ; CHECK: normal: ; CHECK-NEXT: ret void ; CHECK: unreached: -; CHECK-NEXT: [[SLT:%.*]] = icmp slt i64 [[A]], [[B]] -; CHECK-NEXT: [[DOT:%.*]] = select i1 [[SLT]], i32 -1, i32 1 -; CHECK-NEXT: call void @use(i32 [[DOT]]) +; CHECK-NEXT: [[RESULT:%.*]] = call i32 @llvm.scmp.i32.i64(i64 [[A]], i64 [[B]]) +; CHECK-NEXT: call void @use(i32 [[RESULT]]) ; CHECK-NEXT: ret void ; %eq = icmp eq i64 %a, %b @@ -338,10 +328,7 @@ define void @test_high_slt(i64 %a, i64 %b) { ; CHECK: normal: ; CHECK-NEXT: ret void ; CHECK: unreached: -; CHECK-NEXT: [[EQ:%.*]] = icmp eq i64 [[A]], [[B]] -; CHECK-NEXT: [[SLT:%.*]] = icmp slt i64 [[A]], [[B]] -; CHECK-NEXT: [[DOT:%.*]] = select i1 [[SLT]], i32 -1, i32 1 -; CHECK-NEXT: [[RESULT:%.*]] = select i1 [[EQ]], i32 0, i32 [[DOT]] +; CHECK-NEXT: [[RESULT:%.*]] = call i32 @llvm.scmp.i32.i64(i64 [[A]], i64 [[B]]) ; CHECK-NEXT: call void @use(i32 [[RESULT]]) ; CHECK-NEXT: ret void ; @@ -389,10 +376,7 @@ define void @test_high_sle(i64 %a, i64 %b) { ; CHECK: normal: ; CHECK-NEXT: ret void ; CHECK: unreached: -; CHECK-NEXT: [[EQ:%.*]] = icmp eq i64 [[A]], [[B]] -; CHECK-NEXT: [[SLT:%.*]] = icmp slt i64 [[A]], [[B]] -; CHECK-NEXT: [[DOT:%.*]] = select i1 [[SLT]], i32 -1, i32 1 -; CHECK-NEXT: [[RESULT:%.*]] = select i1 [[EQ]], i32 0, i32 [[DOT]] +; CHECK-NEXT: [[RESULT:%.*]] = call i32 @llvm.scmp.i32.i64(i64 [[A]], i64 [[B]]) ; CHECK-NEXT: call void @use(i32 [[RESULT]]) ; CHECK-NEXT: ret void ; @@ -417,10 +401,7 @@ define void @test_high_ne(i64 %a, i64 %b) { ; CHECK: normal: ; CHECK-NEXT: ret void ; CHECK: unreached: -; CHECK-NEXT: [[EQ:%.*]] = icmp eq i64 [[A]], [[B]] -; CHECK-NEXT: [[SLT:%.*]] = icmp slt i64 [[A]], [[B]] -; CHECK-NEXT: [[DOT:%.*]] = select i1 [[SLT]], i32 -1, i32 1 -; CHECK-NEXT: [[RESULT:%.*]] = select i1 [[EQ]], i32 0, i32 [[DOT]] +; CHECK-NEXT: [[RESULT:%.*]] = call i32 @llvm.scmp.i32.i64(i64 [[A]], i64 [[B]]) ; CHECK-NEXT: call void @use(i32 [[RESULT]]) ; CHECK-NEXT: ret void ; diff --git a/llvm/test/Transforms/InstCombine/select-select.ll b/llvm/test/Transforms/InstCombine/select-select.ll index 1feae5ab504dc..94e88c2f6cbe6 100644 --- a/llvm/test/Transforms/InstCombine/select-select.ll +++ b/llvm/test/Transforms/InstCombine/select-select.ll @@ -177,10 +177,7 @@ define <2 x i8> @sel_shuf_narrowing_commute2(<4 x i8> %x, <4 x i8> %y, <2 x i8> define i8 @strong_order_cmp_slt_eq(i32 %a, i32 %b) { ; CHECK-LABEL: @strong_order_cmp_slt_eq( -; CHECK-NEXT: [[CMP_LT:%.*]] = icmp slt i32 [[A:%.*]], [[B:%.*]] -; CHECK-NEXT: [[SEL_LT:%.*]] = select i1 [[CMP_LT]], i8 -1, i8 1 -; CHECK-NEXT: [[CMP_EQ:%.*]] = icmp eq i32 [[A]], [[B]] -; CHECK-NEXT: [[SEL_EQ:%.*]] = select i1 [[CMP_EQ]], i8 0, i8 [[SEL_LT]] +; CHECK-NEXT: [[SEL_EQ:%.*]] = call i8 @llvm.scmp.i8.i32(i32 [[A:%.*]], i32 [[B:%.*]]) ; CHECK-NEXT: ret i8 [[SEL_EQ]] ; %cmp.lt = icmp slt i32 %a, %b @@ -192,10 +189,7 @@ define i8 @strong_order_cmp_slt_eq(i32 %a, i32 %b) { define i8 @strong_order_cmp_ult_eq(i32 %a, i32 %b) { ; CHECK-LABEL: @strong_order_cmp_ult_eq( -; CHECK-NEXT: [[CMP_LT:%.*]] = icmp ult i32 [[A:%.*]], [[B:%.*]] -; CHECK-NEXT: [[SEL_LT:%.*]] = select i1 [[CMP_LT]], i8 -1, i8 1 -; CHECK-NEXT: [[CMP_EQ:%.*]] = icmp eq i32 [[A]], [[B]] -; CHECK-NEXT: [[SEL_EQ:%.*]] = select i1 [[CMP_EQ]], i8 0, i8 [[SEL_LT]] +; CHECK-NEXT: [[SEL_EQ:%.*]] = call i8 @llvm.ucmp.i8.i32(i32 [[A:%.*]], i32 [[B:%.*]]) ; CHECK-NEXT: ret i8 [[SEL_EQ]] ; %cmp.lt = icmp ult i32 %a, %b @@ -252,10 +246,7 @@ define i8 @strong_order_cmp_slt_ult_wrong_pred(i32 %a, i32 %b) { define i8 @strong_order_cmp_sgt_eq(i32 %a, i32 %b) { ; CHECK-LABEL: @strong_order_cmp_sgt_eq( -; CHECK-NEXT: [[CMP_GT:%.*]] = icmp sgt i32 [[A:%.*]], [[B:%.*]] -; CHECK-NEXT: [[SEL_GT:%.*]] = select i1 [[CMP_GT]], i8 1, i8 -1 -; CHECK-NEXT: [[CMP_EQ:%.*]] = icmp eq i32 [[A]], [[B]] -; CHECK-NEXT: [[SEL_EQ:%.*]] = select i1 [[CMP_EQ]], i8 0, i8 [[SEL_GT]] +; CHECK-NEXT: [[SEL_EQ:%.*]] = call i8 @llvm.scmp.i8.i32(i32 [[A:%.*]], i32 [[B:%.*]]) ; CHECK-NEXT: ret i8 [[SEL_EQ]] ; %cmp.gt = icmp sgt i32 %a, %b @@ -267,10 +258,7 @@ define i8 @strong_order_cmp_sgt_eq(i32 %a, i32 %b) { define i8 @strong_order_cmp_ugt_eq(i32 %a, i32 %b) { ; CHECK-LABEL: @strong_order_cmp_ugt_eq( -; CHECK-NEXT: [[CMP_GT:%.*]] = icmp ugt i32 [[A:%.*]], [[B:%.*]] -; CHECK-NEXT: [[SEL_GT:%.*]] = select i1 [[CMP_GT]], i8 1, i8 -1 -; CHECK-NEXT: [[CMP_EQ:%.*]] = icmp eq i32 [[A]], [[B]] -; CHECK-NEXT: [[SEL_EQ:%.*]] = select i1 [[CMP_EQ]], i8 0, i8 [[SEL_GT]] +; CHECK-NEXT: [[SEL_EQ:%.*]] = call i8 @llvm.ucmp.i8.i32(i32 [[A:%.*]], i32 [[B:%.*]]) ; CHECK-NEXT: ret i8 [[SEL_EQ]] ; %cmp.gt = icmp ugt i32 %a, %b @@ -395,9 +383,7 @@ define i8 @strong_order_cmp_slt_eq_slt_not_oneuse(i32 %a, i32 %b) { ; CHECK-LABEL: @strong_order_cmp_slt_eq_slt_not_oneuse( ; CHECK-NEXT: [[CMP_LT:%.*]] = icmp slt i32 [[A:%.*]], [[B:%.*]] ; CHECK-NEXT: call void @use1(i1 [[CMP_LT]]) -; CHECK-NEXT: [[SEL_LT:%.*]] = select i1 [[CMP_LT]], i8 -1, i8 1 -; CHECK-NEXT: [[CMP_EQ:%.*]] = icmp eq i32 [[A]], [[B]] -; CHECK-NEXT: [[SEL_EQ:%.*]] = select i1 [[CMP_EQ]], i8 0, i8 [[SEL_LT]] +; CHECK-NEXT: [[SEL_EQ:%.*]] = call i8 @llvm.scmp.i8.i32(i32 [[A]], i32 [[B]]) ; CHECK-NEXT: ret i8 [[SEL_EQ]] ; %cmp.lt = icmp slt i32 %a, %b @@ -410,11 +396,9 @@ define i8 @strong_order_cmp_slt_eq_slt_not_oneuse(i32 %a, i32 %b) { define i8 @strong_order_cmp_sgt_eq_eq_not_oneuse(i32 %a, i32 %b) { ; CHECK-LABEL: @strong_order_cmp_sgt_eq_eq_not_oneuse( -; CHECK-NEXT: [[CMP_GT:%.*]] = icmp sgt i32 [[A:%.*]], [[B:%.*]] -; CHECK-NEXT: [[SEL_GT:%.*]] = select i1 [[CMP_GT]], i8 1, i8 -1 -; CHECK-NEXT: [[CMP_EQ:%.*]] = icmp eq i32 [[A]], [[B]] +; CHECK-NEXT: [[CMP_EQ:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]] ; CHECK-NEXT: call void @use1(i1 [[CMP_EQ]]) -; CHECK-NEXT: [[SEL_EQ:%.*]] = select i1 [[CMP_EQ]], i8 0, i8 [[SEL_GT]] +; CHECK-NEXT: [[SEL_EQ:%.*]] = call i8 @llvm.scmp.i8.i32(i32 [[A]], i32 [[B]]) ; CHECK-NEXT: ret i8 [[SEL_EQ]] ; %cmp.gt = icmp sgt i32 %a, %b diff --git a/llvm/test/Transforms/InstCombine/sink_to_unreachable.ll b/llvm/test/Transforms/InstCombine/sink_to_unreachable.ll index 01510f8e9596b..72aa6dc80df34 100644 --- a/llvm/test/Transforms/InstCombine/sink_to_unreachable.ll +++ b/llvm/test/Transforms/InstCombine/sink_to_unreachable.ll @@ -10,8 +10,7 @@ define void @test_01(i32 %x, i32 %y) { ; CHECK-NEXT: [[C2:%.*]] = icmp slt i32 [[X:%.*]], [[Y:%.*]] ; CHECK-NEXT: br i1 [[C2]], label [[EXIT:%.*]], label [[UNREACHED:%.*]] ; CHECK: unreached: -; CHECK-NEXT: [[C1:%.*]] = icmp ne i32 [[X]], [[Y]] -; CHECK-NEXT: [[COMPARATOR:%.*]] = zext i1 [[C1]] to i32 +; CHECK-NEXT: [[COMPARATOR:%.*]] = call i32 @llvm.scmp.i32.i32(i32 [[X]], i32 [[Y]]) ; CHECK-NEXT: call void @use(i32 [[COMPARATOR]]) ; CHECK-NEXT: unreachable ; CHECK: exit: @@ -42,8 +41,7 @@ define void @test_02(i32 %x, i32 %y) { ; CHECK-NEXT: [[C3:%.*]] = icmp sgt i32 [[X]], [[Y]] ; CHECK-NEXT: br i1 [[C3]], label [[EXIT]], label [[UNREACHED:%.*]] ; CHECK: unreached: -; CHECK-NEXT: [[C1:%.*]] = icmp ne i32 [[X]], [[Y]] -; CHECK-NEXT: [[COMPARATOR:%.*]] = zext i1 [[C1]] to i32 +; CHECK-NEXT: [[COMPARATOR:%.*]] = call i32 @llvm.scmp.i32.i32(i32 [[X]], i32 [[Y]]) ; CHECK-NEXT: call void @use(i32 [[COMPARATOR]]) ; CHECK-NEXT: unreachable ; CHECK: exit: @@ -77,8 +75,7 @@ define i32 @test_03(i32 %x, i32 %y) { ; CHECK-NEXT: [[C3:%.*]] = icmp sgt i32 [[X]], [[Y]] ; CHECK-NEXT: br i1 [[C3]], label [[EXIT]], label [[UNREACHED:%.*]] ; CHECK: unreached: -; CHECK-NEXT: [[C1:%.*]] = icmp ne i32 [[X]], [[Y]] -; CHECK-NEXT: [[COMPARATOR:%.*]] = zext i1 [[C1]] to i32 +; CHECK-NEXT: [[COMPARATOR:%.*]] = call i32 @llvm.scmp.i32.i32(i32 [[X]], i32 [[Y]]) ; CHECK-NEXT: ret i32 [[COMPARATOR]] ; CHECK: exit: ; CHECK-NEXT: ret i32 0 From 1a850933c953ea969dc59fe282cdc4de33508613 Mon Sep 17 00:00:00 2001 From: Poseydon42 Date: Wed, 4 Sep 2024 23:29:06 +0100 Subject: [PATCH 4/6] Fix formatting --- llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp index 92154493cd4bb..da174928a94b7 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp @@ -3598,8 +3598,7 @@ Instruction *InstCombinerImpl::foldSelectToCmp(SelectInst &SI) { } } - Intrinsic::ID IID = - IsSigned ? Intrinsic::scmp : Intrinsic::ucmp; + Intrinsic::ID IID = IsSigned ? Intrinsic::scmp : Intrinsic::ucmp; if (Replace) return replaceInstUsesWith( SI, Builder.CreateIntrinsic(SI.getType(), IID, {LHS, RHS})); From b7ee463d4f40ca8fa31d997085546be9c0001fed Mon Sep 17 00:00:00 2001 From: Poseydon42 Date: Thu, 5 Sep 2024 18:09:31 +0100 Subject: [PATCH 5/6] Handle vector types --- .../Transforms/InstCombine/InstCombineSelect.cpp | 6 +++--- llvm/test/Transforms/InstCombine/scmp.ll | 13 +++++++++++++ 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp index da174928a94b7..7476db9ee38f4 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp @@ -3575,11 +3575,11 @@ Instruction *InstCombinerImpl::foldSelectToCmp(SelectInst &SI) { // (x == y) ? 0 : (x > y ? 1 : -1) ICmpInst::Predicate FalseBranchSelectPredicate; - ConstantInt *InnerTV, *InnerFV; + const APInt *InnerTV, *InnerFV; if (Pred == ICmpInst::ICMP_EQ && match(TV, m_Zero()) && match(FV, m_Select(m_c_ICmp(FalseBranchSelectPredicate, m_Specific(LHS), m_Specific(RHS)), - m_ConstantInt(InnerTV), m_ConstantInt(InnerFV)))) { + m_APInt(InnerTV), m_APInt(InnerFV)))) { if (!ICmpInst::isGT(FalseBranchSelectPredicate)) { FalseBranchSelectPredicate = ICmpInst::getSwappedPredicate(FalseBranchSelectPredicate); @@ -3592,7 +3592,7 @@ Instruction *InstCombinerImpl::foldSelectToCmp(SelectInst &SI) { } if (ICmpInst::isGT(FalseBranchSelectPredicate) && InnerTV->isOne() && - InnerFV->isAllOnesValue()) { + InnerFV->isAllOnes()) { IsSigned = ICmpInst::isSigned(FalseBranchSelectPredicate); Replace = true; } diff --git a/llvm/test/Transforms/InstCombine/scmp.ll b/llvm/test/Transforms/InstCombine/scmp.ll index 397621b8c878e..30e6b3eae0a03 100644 --- a/llvm/test/Transforms/InstCombine/scmp.ll +++ b/llvm/test/Transforms/InstCombine/scmp.ll @@ -358,6 +358,19 @@ define i8 @scmp_from_select_eq_and_gt(i32 %x, i32 %y) { ret i8 %r } +define <4 x i8> @scmp_from_select_eq_and_gt_vec(<4 x i32> %x, <4 x i32> %y) { +; CHECK-LABEL: define <4 x i8> @scmp_from_select_eq_and_gt_vec( +; CHECK-SAME: <4 x i32> [[X:%.*]], <4 x i32> [[Y:%.*]]) { +; CHECK-NEXT: [[R:%.*]] = call <4 x i8> @llvm.scmp.v4i8.v4i32(<4 x i32> [[X]], <4 x i32> [[Y]]) +; CHECK-NEXT: ret <4 x i8> [[R]] +; + %eq = icmp eq <4 x i32> %x, %y + %gt = icmp sgt <4 x i32> %x, %y + %sel1 = select <4 x i1> %gt, <4 x i8> splat(i8 1), <4 x i8> splat(i8 -1) + %r = select <4 x i1> %eq, <4 x i8> splat(i8 0), <4 x i8> %sel1 + ret <4 x i8> %r +} + define i8 @scmp_from_select_eq_and_gt_commuted1(i32 %x, i32 %y) { ; CHECK-LABEL: define i8 @scmp_from_select_eq_and_gt_commuted1( ; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { From b841fc649a7dd06f6ec1b072d316e00de182e82c Mon Sep 17 00:00:00 2001 From: Poseydon42 Date: Thu, 5 Sep 2024 18:11:27 +0100 Subject: [PATCH 6/6] Add test for the inverse case --- llvm/test/Transforms/InstCombine/scmp.ll | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/llvm/test/Transforms/InstCombine/scmp.ll b/llvm/test/Transforms/InstCombine/scmp.ll index 30e6b3eae0a03..2140a59de3fa9 100644 --- a/llvm/test/Transforms/InstCombine/scmp.ll +++ b/llvm/test/Transforms/InstCombine/scmp.ll @@ -358,6 +358,19 @@ define i8 @scmp_from_select_eq_and_gt(i32 %x, i32 %y) { ret i8 %r } +define i8 @scmp_from_select_eq_and_gt_inverse(i32 %x, i32 %y) { +; CHECK-LABEL: define i8 @scmp_from_select_eq_and_gt_inverse( +; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { +; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.scmp.i8.i32(i32 [[X]], i32 [[Y]]) +; CHECK-NEXT: ret i8 [[R]] +; + %ne = icmp ne i32 %x, %y + %gt = icmp sgt i32 %x, %y + %sel1 = select i1 %gt, i8 1, i8 -1 + %r = select i1 %ne, i8 %sel1, i8 0 + ret i8 %r +} + define <4 x i8> @scmp_from_select_eq_and_gt_vec(<4 x i32> %x, <4 x i32> %y) { ; CHECK-LABEL: define <4 x i8> @scmp_from_select_eq_and_gt_vec( ; CHECK-SAME: <4 x i32> [[X:%.*]], <4 x i32> [[Y:%.*]]) {