[llvm] [InstCombine] Fold `select (or/and (icmp eq/ne a, b), other_cond), a, b` to `select (other_cond), a, b` (PR #76203)
via llvm-commits
llvm-commits at lists.llvm.org
Fri Dec 29 05:51:39 PST 2023
- Previous message: [llvm] [InstCombine] Fold `select (or/and (icmp eq/ne a, b), other_cond), a, b` to `select (other_cond), a, b` (PR #76203)
- Next message: [llvm] [InstCombine] Fold `select (or/and (icmp eq/ne a, b), other_cond), a, b` to `select (other_cond), a, b` (PR #76203)
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
https://github.com/XChy updated https://github.com/llvm/llvm-project/pull/76203
>From 31ea022fea517cbfc5816d7b1fa033c800114a89 Mon Sep 17 00:00:00 2001
From: XChy <xxs_chy at outlook.com>
Date: Fri, 22 Dec 2023 01:18:57 +0800
Subject: [PATCH 1/2] [InstCombine][NFC] Precommit tests for PR75784
---
.../Transforms/InstCombine/select-and-or.ll | 248 ++++++++++++++++--
1 file changed, 224 insertions(+), 24 deletions(-)
diff --git a/llvm/test/Transforms/InstCombine/select-and-or.ll b/llvm/test/Transforms/InstCombine/select-and-or.ll
index 7edcd767b86ecb..2c79cae17c7145 100644
--- a/llvm/test/Transforms/InstCombine/select-and-or.ll
+++ b/llvm/test/Transforms/InstCombine/select-and-or.ll
@@ -613,9 +613,9 @@ define i1 @and_or2_wrong_operand(i1 %a, i1 %b, i1 %c, i1 %d) {
define i1 @and_or3(i1 %a, i1 %b, i32 %x, i32 %y) {
; CHECK-LABEL: @and_or3(
-; CHECK-NEXT: [[C:%.*]] = icmp ne i32 [[X:%.*]], [[Y:%.*]]
-; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[C]], i1 true, i1 [[A:%.*]]
-; CHECK-NEXT: [[R:%.*]] = select i1 [[B:%.*]], i1 [[TMP1]], i1 false
+; CHECK-NEXT: [[TMP1:%.*]] = icmp ne i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[TMP1]], i1 true, i1 [[A:%.*]]
+; CHECK-NEXT: [[R:%.*]] = select i1 [[B:%.*]], i1 [[TMP2]], i1 false
; CHECK-NEXT: ret i1 [[R]]
;
%c = icmp eq i32 %x, %y
@@ -626,9 +626,9 @@ define i1 @and_or3(i1 %a, i1 %b, i32 %x, i32 %y) {
define i1 @and_or3_commuted(i1 %a, i1 %b, i32 %x, i32 %y) {
; CHECK-LABEL: @and_or3_commuted(
-; CHECK-NEXT: [[C:%.*]] = icmp ne i32 [[X:%.*]], [[Y:%.*]]
-; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[C]], i1 true, i1 [[A:%.*]]
-; CHECK-NEXT: [[R:%.*]] = select i1 [[B:%.*]], i1 [[TMP1]], i1 false
+; CHECK-NEXT: [[TMP1:%.*]] = icmp ne i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[TMP1]], i1 true, i1 [[A:%.*]]
+; CHECK-NEXT: [[R:%.*]] = select i1 [[B:%.*]], i1 [[TMP2]], i1 false
; CHECK-NEXT: ret i1 [[R]]
;
%c = icmp eq i32 %x, %y
@@ -665,9 +665,9 @@ define i1 @and_or3_multiuse(i1 %a, i1 %b, i32 %x, i32 %y) {
define <2 x i1> @and_or3_vec(<2 x i1> %a, <2 x i1> %b, <2 x i32> %x, <2 x i32> %y) {
; CHECK-LABEL: @and_or3_vec(
-; CHECK-NEXT: [[C:%.*]] = icmp ne <2 x i32> [[X:%.*]], [[Y:%.*]]
-; CHECK-NEXT: [[TMP1:%.*]] = select <2 x i1> [[C]], <2 x i1> <i1 true, i1 true>, <2 x i1> [[A:%.*]]
-; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[B:%.*]], <2 x i1> [[TMP1]], <2 x i1> zeroinitializer
+; CHECK-NEXT: [[TMP1:%.*]] = icmp ne <2 x i32> [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT: [[TMP2:%.*]] = select <2 x i1> [[TMP1]], <2 x i1> <i1 true, i1 true>, <2 x i1> [[A:%.*]]
+; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[B:%.*]], <2 x i1> [[TMP2]], <2 x i1> zeroinitializer
; CHECK-NEXT: ret <2 x i1> [[R]]
;
%c = icmp eq <2 x i32> %x, %y
@@ -678,9 +678,9 @@ define <2 x i1> @and_or3_vec(<2 x i1> %a, <2 x i1> %b, <2 x i32> %x, <2 x i32> %
define <2 x i1> @and_or3_vec_commuted(<2 x i1> %a, <2 x i1> %b, <2 x i32> %x, <2 x i32> %y) {
; CHECK-LABEL: @and_or3_vec_commuted(
-; CHECK-NEXT: [[C:%.*]] = icmp ne <2 x i32> [[X:%.*]], [[Y:%.*]]
-; CHECK-NEXT: [[TMP1:%.*]] = select <2 x i1> [[C]], <2 x i1> <i1 true, i1 true>, <2 x i1> [[A:%.*]]
-; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[B:%.*]], <2 x i1> [[TMP1]], <2 x i1> zeroinitializer
+; CHECK-NEXT: [[TMP1:%.*]] = icmp ne <2 x i32> [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT: [[TMP2:%.*]] = select <2 x i1> [[TMP1]], <2 x i1> <i1 true, i1 true>, <2 x i1> [[A:%.*]]
+; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[B:%.*]], <2 x i1> [[TMP2]], <2 x i1> zeroinitializer
; CHECK-NEXT: ret <2 x i1> [[R]]
;
%c = icmp eq <2 x i32> %x, %y
@@ -877,9 +877,9 @@ entry:
define i1 @or_and3(i1 %a, i1 %b, i32 %x, i32 %y) {
; CHECK-LABEL: @or_and3(
-; CHECK-NEXT: [[C:%.*]] = icmp ne i32 [[X:%.*]], [[Y:%.*]]
-; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[C]], i1 [[B:%.*]], i1 false
-; CHECK-NEXT: [[R:%.*]] = select i1 [[A:%.*]], i1 true, i1 [[TMP1]]
+; CHECK-NEXT: [[TMP1:%.*]] = icmp ne i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[TMP1]], i1 [[B:%.*]], i1 false
+; CHECK-NEXT: [[R:%.*]] = select i1 [[A:%.*]], i1 true, i1 [[TMP2]]
; CHECK-NEXT: ret i1 [[R]]
;
%c = icmp eq i32 %x, %y
@@ -890,9 +890,9 @@ define i1 @or_and3(i1 %a, i1 %b, i32 %x, i32 %y) {
define i1 @or_and3_commuted(i1 %a, i1 %b, i32 %x, i32 %y) {
; CHECK-LABEL: @or_and3_commuted(
-; CHECK-NEXT: [[C:%.*]] = icmp ne i32 [[X:%.*]], [[Y:%.*]]
-; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[C]], i1 [[B:%.*]], i1 false
-; CHECK-NEXT: [[R:%.*]] = select i1 [[A:%.*]], i1 true, i1 [[TMP1]]
+; CHECK-NEXT: [[TMP1:%.*]] = icmp ne i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[TMP1]], i1 [[B:%.*]], i1 false
+; CHECK-NEXT: [[R:%.*]] = select i1 [[A:%.*]], i1 true, i1 [[TMP2]]
; CHECK-NEXT: ret i1 [[R]]
;
%c = icmp eq i32 %x, %y
@@ -929,9 +929,9 @@ define i1 @or_and3_multiuse(i1 %a, i1 %b, i32 %x, i32 %y) {
define <2 x i1> @or_and3_vec(<2 x i1> %a, <2 x i1> %b, <2 x i32> %x, <2 x i32> %y) {
; CHECK-LABEL: @or_and3_vec(
-; CHECK-NEXT: [[C:%.*]] = icmp ne <2 x i32> [[X:%.*]], [[Y:%.*]]
-; CHECK-NEXT: [[TMP1:%.*]] = select <2 x i1> [[C]], <2 x i1> [[B:%.*]], <2 x i1> zeroinitializer
-; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[A:%.*]], <2 x i1> <i1 true, i1 true>, <2 x i1> [[TMP1]]
+; CHECK-NEXT: [[TMP1:%.*]] = icmp ne <2 x i32> [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT: [[TMP2:%.*]] = select <2 x i1> [[TMP1]], <2 x i1> [[B:%.*]], <2 x i1> zeroinitializer
+; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[A:%.*]], <2 x i1> <i1 true, i1 true>, <2 x i1> [[TMP2]]
; CHECK-NEXT: ret <2 x i1> [[R]]
;
%c = icmp eq <2 x i32> %x, %y
@@ -942,9 +942,9 @@ define <2 x i1> @or_and3_vec(<2 x i1> %a, <2 x i1> %b, <2 x i32> %x, <2 x i32> %
define <2 x i1> @or_and3_vec_commuted(<2 x i1> %a, <2 x i1> %b, <2 x i32> %x, <2 x i32> %y) {
; CHECK-LABEL: @or_and3_vec_commuted(
-; CHECK-NEXT: [[C:%.*]] = icmp ne <2 x i32> [[X:%.*]], [[Y:%.*]]
-; CHECK-NEXT: [[TMP1:%.*]] = select <2 x i1> [[C]], <2 x i1> [[B:%.*]], <2 x i1> zeroinitializer
-; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[A:%.*]], <2 x i1> <i1 true, i1 true>, <2 x i1> [[TMP1]]
+; CHECK-NEXT: [[TMP1:%.*]] = icmp ne <2 x i32> [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT: [[TMP2:%.*]] = select <2 x i1> [[TMP1]], <2 x i1> [[B:%.*]], <2 x i1> zeroinitializer
+; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[A:%.*]], <2 x i1> <i1 true, i1 true>, <2 x i1> [[TMP2]]
; CHECK-NEXT: ret <2 x i1> [[R]]
;
%c = icmp eq <2 x i32> %x, %y
@@ -965,3 +965,203 @@ define i1 @or_and3_wrong_operand(i1 %a, i1 %b, i32 %x, i32 %y, i1 %d) {
%r = select i1 %cond, i1 %d, i1 %b
ret i1 %r
}
+
+define i32 @or_eq_a_b(i1 %other_cond, i32 %a, i32 %b) {
+; CHECK-LABEL: @or_eq_a_b(
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]]
+; CHECK-NEXT: [[COND:%.*]] = or i1 [[CMP]], [[OTHER_COND:%.*]]
+; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], i32 [[A]], i32 [[B]]
+; CHECK-NEXT: ret i32 [[SELECT]]
+;
+ %cmp = icmp eq i32 %a, %b
+ %cond = or i1 %other_cond, %cmp
+ %select = select i1 %cond, i32 %a, i32 %b
+ ret i32 %select
+}
+
+define i32 @and_ne_a_b(i1 %other_cond, i32 %a, i32 %b) {
+; CHECK-LABEL: @and_ne_a_b(
+; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[A:%.*]], [[B:%.*]]
+; CHECK-NEXT: [[COND:%.*]] = and i1 [[CMP]], [[OTHER_COND:%.*]]
+; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], i32 [[A]], i32 [[B]]
+; CHECK-NEXT: ret i32 [[SELECT]]
+;
+ %cmp = icmp ne i32 %a, %b
+ %cond = and i1 %other_cond, %cmp
+ %select = select i1 %cond, i32 %a, i32 %b
+ ret i32 %select
+}
+
+define i32 @or_eq_a_b_commuted(i1 %other_cond, i32 %a, i32 %b) {
+; CHECK-LABEL: @or_eq_a_b_commuted(
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]]
+; CHECK-NEXT: [[COND:%.*]] = or i1 [[CMP]], [[OTHER_COND:%.*]]
+; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], i32 [[B]], i32 [[A]]
+; CHECK-NEXT: ret i32 [[SELECT]]
+;
+ %cmp = icmp eq i32 %a, %b
+ %cond = or i1 %other_cond, %cmp
+ %select = select i1 %cond, i32 %b, i32 %a
+ ret i32 %select
+}
+
+define i32 @and_ne_a_b_commuted(i1 %other_cond, i32 %a, i32 %b) {
+; CHECK-LABEL: @and_ne_a_b_commuted(
+; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[A:%.*]], [[B:%.*]]
+; CHECK-NEXT: [[COND:%.*]] = and i1 [[CMP]], [[OTHER_COND:%.*]]
+; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], i32 [[B]], i32 [[A]]
+; CHECK-NEXT: ret i32 [[SELECT]]
+;
+ %cmp = icmp ne i32 %a, %b
+ %cond = and i1 %other_cond, %cmp
+ %select = select i1 %cond, i32 %b, i32 %a
+ ret i32 %select
+}
+
+define i32 @or_eq_different_operands(i32 %a, i32 %b, i32 %c) {
+; CHECK-LABEL: @or_eq_different_operands(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[A:%.*]], [[C:%.*]]
+; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[B:%.*]], [[A]]
+; CHECK-NEXT: [[COND:%.*]] = or i1 [[CMP]], [[CMP1]]
+; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], i32 [[A]], i32 [[B]]
+; CHECK-NEXT: ret i32 [[SELECT]]
+;
+entry:
+ %cmp = icmp eq i32 %a, %c
+ %cmp1 = icmp eq i32 %b, %a
+ %cond = or i1 %cmp, %cmp1
+ %select = select i1 %cond, i32 %a, i32 %b
+ ret i32 %select
+}
+
+define i32 @or_eq_a_b_multi_use(i1 %other_cond, i32 %a, i32 %b) {
+; CHECK-LABEL: @or_eq_a_b_multi_use(
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]]
+; CHECK-NEXT: [[COND:%.*]] = or i1 [[CMP]], [[OTHER_COND:%.*]]
+; CHECK-NEXT: call void @use(i1 [[CMP]])
+; CHECK-NEXT: call void @use(i1 [[COND]])
+; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], i32 [[A]], i32 [[B]]
+; CHECK-NEXT: ret i32 [[SELECT]]
+;
+ %cmp = icmp eq i32 %a, %b
+ %cond = or i1 %other_cond, %cmp
+ call void @use(i1 %cmp)
+ call void @use(i1 %cond)
+ %select = select i1 %cond, i32 %a, i32 %b
+ ret i32 %select
+}
+
+define <2 x i32> @or_eq_a_b_vec(<2 x i1> %other_cond ,<2 x i32> %a, <2 x i32> %b) {
+; CHECK-LABEL: @or_eq_a_b_vec(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq <2 x i32> [[A:%.*]], [[B:%.*]]
+; CHECK-NEXT: [[COND:%.*]] = or <2 x i1> [[CMP]], [[OTHER_COND:%.*]]
+; CHECK-NEXT: [[SELECT:%.*]] = select <2 x i1> [[COND]], <2 x i32> [[A]], <2 x i32> [[B]]
+; CHECK-NEXT: ret <2 x i32> [[SELECT]]
+;
+entry:
+ %cmp = icmp eq <2 x i32> %a, %b
+ %cond = or <2 x i1> %other_cond, %cmp
+ %select = select <2 x i1> %cond, <2 x i32> %a, <2 x i32> %b
+ ret <2 x i32> %select
+}
+
+define i32 @or_slt_a_b_fail(i1 %other_cond ,i32 %a, i32 %b) {
+; CHECK-LABEL: @or_slt_a_b_fail(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[A:%.*]], [[B:%.*]]
+; CHECK-NEXT: [[COND:%.*]] = or i1 [[CMP]], [[OTHER_COND:%.*]]
+; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], i32 [[A]], i32 [[B]]
+; CHECK-NEXT: ret i32 [[SELECT]]
+; CHECK: 0:
+; CHECK-NEXT: ret i32 [[SELECT]]
+;
+entry:
+ %cmp = icmp slt i32 %a, %b
+ %cond = or i1 %other_cond, %cmp
+ %select = select i1 %cond, i32 %a, i32 %b
+ ret i32 %select ret i32 %select
+}
+
+define i32 @or_ne_a_b_fail(i1 %other_cond, i32 %a, i32 %b) {
+; CHECK-LABEL: @or_ne_a_b_fail(
+; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[A:%.*]], [[B:%.*]]
+; CHECK-NEXT: [[COND:%.*]] = or i1 [[CMP]], [[OTHER_COND:%.*]]
+; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], i32 [[A]], i32 [[B]]
+; CHECK-NEXT: ret i32 [[SELECT]]
+;
+ %cmp = icmp ne i32 %a, %b
+ %cond = or i1 %other_cond, %cmp
+ %select = select i1 %cond, i32 %a, i32 %b
+ ret i32 %select
+}
+
+define i32 @and_ne_different_operands_fail(i32 %a, i32 %b, i32 %c) {
+; CHECK-LABEL: @and_ne_different_operands_fail(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[A:%.*]], [[C:%.*]]
+; CHECK-NEXT: [[CMP1:%.*]] = icmp ne i32 [[B:%.*]], [[C]]
+; CHECK-NEXT: [[COND:%.*]] = and i1 [[CMP]], [[CMP1]]
+; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], i32 [[B]], i32 [[A]]
+; CHECK-NEXT: ret i32 [[SELECT]]
+;
+entry:
+ %cmp = icmp ne i32 %a, %c
+ %cmp1 = icmp ne i32 %b, %c
+ %cond = and i1 %cmp, %cmp1
+ %select = select i1 %cond, i32 %b, i32 %a
+ ret i32 %select
+}
+
+define i32 @logical_or_eq_a_b(i1 %other_cond, i32 %a, i32 %b) {
+; CHECK-LABEL: @logical_or_eq_a_b(
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]]
+; CHECK-NEXT: [[OR_COND:%.*]] = select i1 [[OTHER_COND:%.*]], i1 true, i1 [[CMP]]
+; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[OR_COND]], i32 [[A]], i32 [[B]]
+; CHECK-NEXT: ret i32 [[SELECT]]
+;
+ %cmp = icmp eq i32 %a, %b
+ %or.cond = select i1 %other_cond, i1 true, i1 %cmp
+ %select = select i1 %or.cond, i32 %a, i32 %b
+ ret i32 %select
+}
+
+define i32 @logical_commuted_or_eq_a_b(i1 %other_cond, i32 %a, i32 %b) {
+; CHECK-LABEL: @logical_commuted_or_eq_a_b(
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]]
+; CHECK-NEXT: [[OR_COND:%.*]] = select i1 [[CMP]], i1 true, i1 [[OTHER_COND:%.*]]
+; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[OR_COND]], i32 [[A]], i32 [[B]]
+; CHECK-NEXT: ret i32 [[SELECT]]
+;
+ %cmp = icmp eq i32 %a, %b
+ %or.cond = select i1 %cmp, i1 true, i1 %other_cond
+ %select = select i1 %or.cond, i32 %a, i32 %b
+ ret i32 %select
+}
+
+define i32 @logical_and_ne_a_b(i1 %other_cond, i32 %a, i32 %b) {
+; CHECK-LABEL: @logical_and_ne_a_b(
+; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[A:%.*]], [[B:%.*]]
+; CHECK-NEXT: [[OR_COND:%.*]] = select i1 [[OTHER_COND:%.*]], i1 [[CMP]], i1 false
+; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[OR_COND]], i32 [[A]], i32 [[B]]
+; CHECK-NEXT: ret i32 [[SELECT]]
+;
+ %cmp = icmp ne i32 %a, %b
+ %or.cond = select i1 %other_cond, i1 %cmp, i1 false
+ %select = select i1 %or.cond, i32 %a, i32 %b
+ ret i32 %select
+}
+
+define i32 @logical_commuted_and_ne_a_b(i1 %other_cond, i32 %a, i32 %b) {
+; CHECK-LABEL: @logical_commuted_and_ne_a_b(
+; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[A:%.*]], [[B:%.*]]
+; CHECK-NEXT: [[OR_COND:%.*]] = select i1 [[CMP]], i1 [[OTHER_COND:%.*]], i1 false
+; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[OR_COND]], i32 [[A]], i32 [[B]]
+; CHECK-NEXT: ret i32 [[SELECT]]
+;
+ %cmp = icmp ne i32 %a, %b
+ %or.cond = select i1 %cmp, i1 %other_cond, i1 false
+ %select = select i1 %or.cond, i32 %a, i32 %b
+ ret i32 %select
+}
>From a56467d18d35c07ceb7567261d8c823b4573d66c Mon Sep 17 00:00:00 2001
From: XChy <xxs_chy at outlook.com>
Date: Fri, 22 Dec 2023 03:49:05 +0800
Subject: [PATCH 2/2] [InstCombine] Fold select of and/or(icmp, other_cond) to
select of other_cond
---
.../InstCombine/InstCombineInternal.h | 2 +-
.../InstCombine/InstCombineSelect.cpp | 53 +++++++++++++++++++
.../Transforms/InstCombine/select-and-or.ll | 44 +++++----------
llvm/test/Transforms/Reassociate/basictest.ll | 4 +-
4 files changed, 68 insertions(+), 35 deletions(-)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineInternal.h b/llvm/lib/Transforms/InstCombine/InstCombineInternal.h
index 9e76a0cf17b183..0667b08af99f51 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineInternal.h
+++ b/llvm/lib/Transforms/InstCombine/InstCombineInternal.h
@@ -442,7 +442,7 @@ class LLVM_LIBRARY_VISIBILITY InstCombinerImpl final
// into simplier select instruction using isImpliedCondition.
Instruction *foldAndOrOfSelectUsingImpliedCond(Value *Op, SelectInst &SI,
bool IsAnd);
-
+ Instruction *foldSelectOfAndOr(SelectInst &SI);
Instruction *hoistFNegAboveFMulFDiv(Value *FNegOp, Instruction &FMFSource);
public:
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
index 20bf00344b144b..6e561fd75be0d0 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
@@ -2683,6 +2683,56 @@ Instruction *InstCombinerImpl::foldAndOrOfSelectUsingImpliedCond(Value *Op,
}
}
+Instruction *InstCombinerImpl::foldSelectOfAndOr(SelectInst &SI) {
+ Value *CondVal = SI.getCondition();
+ Value *CondLHS, *CondRHS;
+ bool IsBitwise = !isa<SelectInst>(CondVal);
+ bool IsAnd;
+
+ if (match(CondVal, m_LogicalOr(m_Value(CondLHS), m_Value(CondRHS))))
+ IsAnd = false;
+ else if (match(CondVal, m_LogicalAnd(m_Value(CondLHS), m_Value(CondRHS))))
+ IsAnd = true;
+ else
+ return nullptr;
+
+ Value *TrueVal = SI.getTrueValue(), *FalseVal = SI.getFalseValue();
+
+ // %cmp = icmp eq i32 %a, %b
+ // %cond = or i1 %other_cond, %cmp
+ // %select = select i1 %cond, i32 %a, i32 %b
+ // =>
+ // %select = select i1 %other_cond, i32 %a, i32 %b
+
+ // Or for an inverted version, we fold it like:
+ // %cmp = icmp ne i32 %a, %b
+ // %cond = and i1 %other_cond, %cmp
+ // %select = select i1 %cond, i32 %a, i32 %b
+ // =>
+ // %select = select i1 %other_cond, i32 %a, i32 %b
+
+ auto FoldAndOrOfEquality = [&](Value *Cmp, Value *OtherCond,
+ bool NeedToFreeze) -> Instruction * {
+ ICmpInst::Predicate Pred;
+ if (!match(Cmp, m_c_ICmp(Pred, m_Specific(TrueVal), m_Specific(FalseVal))))
+ return nullptr;
+ if (Pred != (IsAnd ? ICmpInst::ICMP_NE : ICmpInst::ICMP_EQ))
+ return nullptr;
+ if (NeedToFreeze)
+ OtherCond = Builder.CreateFreeze(OtherCond);
+ return SelectInst::Create(OtherCond, TrueVal, FalseVal);
+ };
+
+ // Order doesn't matter for bitwise and/or. We care about FreezeInst only when
+ // and/or is logical.
+ if (Instruction *Ret = FoldAndOrOfEquality(CondLHS, CondRHS, !IsBitwise))
+ return Ret;
+ if (Instruction *Ret = FoldAndOrOfEquality(CondRHS, CondLHS, false))
+ return Ret;
+
+ return nullptr;
+}
+
// Canonicalize select with fcmp to fabs(). -0.0 makes this tricky. We need
// fast-math-flags (nsz) or fsub with +0.0 (not fneg) for this to work.
static Instruction *foldSelectWithFCmpToFabs(SelectInst &SI,
@@ -3409,6 +3459,9 @@ Instruction *InstCombinerImpl::visitSelectInst(SelectInst &SI) {
}
}
+ if (Instruction *I = foldSelectOfAndOr(SI))
+ return I;
+
auto *SIFPOp = dyn_cast<FPMathOperator>(&SI);
if (auto *FCmp = dyn_cast<FCmpInst>(CondVal)) {
diff --git a/llvm/test/Transforms/InstCombine/select-and-or.ll b/llvm/test/Transforms/InstCombine/select-and-or.ll
index 2c79cae17c7145..d73569cdc1f22f 100644
--- a/llvm/test/Transforms/InstCombine/select-and-or.ll
+++ b/llvm/test/Transforms/InstCombine/select-and-or.ll
@@ -968,9 +968,7 @@ define i1 @or_and3_wrong_operand(i1 %a, i1 %b, i32 %x, i32 %y, i1 %d) {
define i32 @or_eq_a_b(i1 %other_cond, i32 %a, i32 %b) {
; CHECK-LABEL: @or_eq_a_b(
-; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]]
-; CHECK-NEXT: [[COND:%.*]] = or i1 [[CMP]], [[OTHER_COND:%.*]]
-; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], i32 [[A]], i32 [[B]]
+; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[OTHER_COND:%.*]], i32 [[A:%.*]], i32 [[B:%.*]]
; CHECK-NEXT: ret i32 [[SELECT]]
;
%cmp = icmp eq i32 %a, %b
@@ -981,9 +979,7 @@ define i32 @or_eq_a_b(i1 %other_cond, i32 %a, i32 %b) {
define i32 @and_ne_a_b(i1 %other_cond, i32 %a, i32 %b) {
; CHECK-LABEL: @and_ne_a_b(
-; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[A:%.*]], [[B:%.*]]
-; CHECK-NEXT: [[COND:%.*]] = and i1 [[CMP]], [[OTHER_COND:%.*]]
-; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], i32 [[A]], i32 [[B]]
+; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[OTHER_COND:%.*]], i32 [[A:%.*]], i32 [[B:%.*]]
; CHECK-NEXT: ret i32 [[SELECT]]
;
%cmp = icmp ne i32 %a, %b
@@ -994,9 +990,7 @@ define i32 @and_ne_a_b(i1 %other_cond, i32 %a, i32 %b) {
define i32 @or_eq_a_b_commuted(i1 %other_cond, i32 %a, i32 %b) {
; CHECK-LABEL: @or_eq_a_b_commuted(
-; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]]
-; CHECK-NEXT: [[COND:%.*]] = or i1 [[CMP]], [[OTHER_COND:%.*]]
-; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], i32 [[B]], i32 [[A]]
+; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[OTHER_COND:%.*]], i32 [[B:%.*]], i32 [[A:%.*]]
; CHECK-NEXT: ret i32 [[SELECT]]
;
%cmp = icmp eq i32 %a, %b
@@ -1007,9 +1001,7 @@ define i32 @or_eq_a_b_commuted(i1 %other_cond, i32 %a, i32 %b) {
define i32 @and_ne_a_b_commuted(i1 %other_cond, i32 %a, i32 %b) {
; CHECK-LABEL: @and_ne_a_b_commuted(
-; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[A:%.*]], [[B:%.*]]
-; CHECK-NEXT: [[COND:%.*]] = and i1 [[CMP]], [[OTHER_COND:%.*]]
-; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], i32 [[B]], i32 [[A]]
+; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[OTHER_COND:%.*]], i32 [[B:%.*]], i32 [[A:%.*]]
; CHECK-NEXT: ret i32 [[SELECT]]
;
%cmp = icmp ne i32 %a, %b
@@ -1022,9 +1014,7 @@ define i32 @or_eq_different_operands(i32 %a, i32 %b, i32 %c) {
; CHECK-LABEL: @or_eq_different_operands(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[A:%.*]], [[C:%.*]]
-; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[B:%.*]], [[A]]
-; CHECK-NEXT: [[COND:%.*]] = or i1 [[CMP]], [[CMP1]]
-; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], i32 [[A]], i32 [[B]]
+; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], i32 [[A]], i32 [[B:%.*]]
; CHECK-NEXT: ret i32 [[SELECT]]
;
entry:
@@ -1041,7 +1031,7 @@ define i32 @or_eq_a_b_multi_use(i1 %other_cond, i32 %a, i32 %b) {
; CHECK-NEXT: [[COND:%.*]] = or i1 [[CMP]], [[OTHER_COND:%.*]]
; CHECK-NEXT: call void @use(i1 [[CMP]])
; CHECK-NEXT: call void @use(i1 [[COND]])
-; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], i32 [[A]], i32 [[B]]
+; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[OTHER_COND]], i32 [[A]], i32 [[B]]
; CHECK-NEXT: ret i32 [[SELECT]]
;
%cmp = icmp eq i32 %a, %b
@@ -1055,9 +1045,7 @@ define i32 @or_eq_a_b_multi_use(i1 %other_cond, i32 %a, i32 %b) {
define <2 x i32> @or_eq_a_b_vec(<2 x i1> %other_cond ,<2 x i32> %a, <2 x i32> %b) {
; CHECK-LABEL: @or_eq_a_b_vec(
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[CMP:%.*]] = icmp eq <2 x i32> [[A:%.*]], [[B:%.*]]
-; CHECK-NEXT: [[COND:%.*]] = or <2 x i1> [[CMP]], [[OTHER_COND:%.*]]
-; CHECK-NEXT: [[SELECT:%.*]] = select <2 x i1> [[COND]], <2 x i32> [[A]], <2 x i32> [[B]]
+; CHECK-NEXT: [[SELECT:%.*]] = select <2 x i1> [[OTHER_COND:%.*]], <2 x i32> [[A:%.*]], <2 x i32> [[B:%.*]]
; CHECK-NEXT: ret <2 x i32> [[SELECT]]
;
entry:
@@ -1116,9 +1104,7 @@ entry:
define i32 @logical_or_eq_a_b(i1 %other_cond, i32 %a, i32 %b) {
; CHECK-LABEL: @logical_or_eq_a_b(
-; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]]
-; CHECK-NEXT: [[OR_COND:%.*]] = select i1 [[OTHER_COND:%.*]], i1 true, i1 [[CMP]]
-; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[OR_COND]], i32 [[A]], i32 [[B]]
+; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[OTHER_COND:%.*]], i32 [[A:%.*]], i32 [[B:%.*]]
; CHECK-NEXT: ret i32 [[SELECT]]
;
%cmp = icmp eq i32 %a, %b
@@ -1129,9 +1115,8 @@ define i32 @logical_or_eq_a_b(i1 %other_cond, i32 %a, i32 %b) {
define i32 @logical_commuted_or_eq_a_b(i1 %other_cond, i32 %a, i32 %b) {
; CHECK-LABEL: @logical_commuted_or_eq_a_b(
-; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]]
-; CHECK-NEXT: [[OR_COND:%.*]] = select i1 [[CMP]], i1 true, i1 [[OTHER_COND:%.*]]
-; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[OR_COND]], i32 [[A]], i32 [[B]]
+; CHECK-NEXT: [[TMP1:%.*]] = freeze i1 [[OTHER_COND:%.*]]
+; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[TMP1]], i32 [[A:%.*]], i32 [[B:%.*]]
; CHECK-NEXT: ret i32 [[SELECT]]
;
%cmp = icmp eq i32 %a, %b
@@ -1142,9 +1127,7 @@ define i32 @logical_commuted_or_eq_a_b(i1 %other_cond, i32 %a, i32 %b) {
define i32 @logical_and_ne_a_b(i1 %other_cond, i32 %a, i32 %b) {
; CHECK-LABEL: @logical_and_ne_a_b(
-; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[A:%.*]], [[B:%.*]]
-; CHECK-NEXT: [[OR_COND:%.*]] = select i1 [[OTHER_COND:%.*]], i1 [[CMP]], i1 false
-; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[OR_COND]], i32 [[A]], i32 [[B]]
+; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[OTHER_COND:%.*]], i32 [[A:%.*]], i32 [[B:%.*]]
; CHECK-NEXT: ret i32 [[SELECT]]
;
%cmp = icmp ne i32 %a, %b
@@ -1155,9 +1138,8 @@ define i32 @logical_and_ne_a_b(i1 %other_cond, i32 %a, i32 %b) {
define i32 @logical_commuted_and_ne_a_b(i1 %other_cond, i32 %a, i32 %b) {
; CHECK-LABEL: @logical_commuted_and_ne_a_b(
-; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[A:%.*]], [[B:%.*]]
-; CHECK-NEXT: [[OR_COND:%.*]] = select i1 [[CMP]], i1 [[OTHER_COND:%.*]], i1 false
-; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[OR_COND]], i32 [[A]], i32 [[B]]
+; CHECK-NEXT: [[TMP1:%.*]] = freeze i1 [[OTHER_COND:%.*]]
+; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[TMP1]], i32 [[A:%.*]], i32 [[B:%.*]]
; CHECK-NEXT: ret i32 [[SELECT]]
;
%cmp = icmp ne i32 %a, %b
diff --git a/llvm/test/Transforms/Reassociate/basictest.ll b/llvm/test/Transforms/Reassociate/basictest.ll
index 6205256a31048a..3f4057dd14e7e1 100644
--- a/llvm/test/Transforms/Reassociate/basictest.ll
+++ b/llvm/test/Transforms/Reassociate/basictest.ll
@@ -239,10 +239,8 @@ define i32 @test14(i32 %X1, i32 %X2) {
define i32 @test15(i32 %X1, i32 %X2, i32 %X3) {
; CHECK-LABEL: @test15(
-; CHECK-NEXT: [[A:%.*]] = icmp ne i32 [[X1:%.*]], 0
; CHECK-NEXT: [[B:%.*]] = icmp slt i32 [[X2:%.*]], [[X3:%.*]]
-; CHECK-NEXT: [[C:%.*]] = and i1 [[A]], [[B]]
-; CHECK-NEXT: [[D:%.*]] = select i1 [[C]], i32 [[X1]], i32 0
+; CHECK-NEXT: [[D:%.*]] = select i1 [[B]], i32 [[X1:%.*]], i32 0
; CHECK-NEXT: ret i32 [[D]]
;
%A = icmp ne i32 %X1, 0
- Previous message: [llvm] [InstCombine] Fold `select (or/and (icmp eq/ne a, b), other_cond), a, b` to `select (other_cond), a, b` (PR #76203)
- Next message: [llvm] [InstCombine] Fold `select (or/and (icmp eq/ne a, b), other_cond), a, b` to `select (other_cond), a, b` (PR #76203)
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
More information about the llvm-commits
mailing list