[llvm] [InstCombine] Simplify select if it combinated and/or/xor (PR #73362)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Feb 14 21:41:46 PST 2024
https://github.com/ParkHanbum updated https://github.com/llvm/llvm-project/pull/73362
>From edeaf1cf4fa58f88d4061634bd9514dab07d4484 Mon Sep 17 00:00:00 2001
From: Hanbum Park <kese111 at gmail.com>
Date: Mon, 27 Nov 2023 09:11:03 +0900
Subject: [PATCH 1/2] [InstCombine] Add test for simplify select if it
combinated and/or/xor
`and/or/xor` operations can each be changed to sum of logical
operations including operators other than themselves.
`x&y -> (x|y) ^ (x^y)`
`x|y -> (x&y) | (x^y)`
`x^y -> (x|y) ^ (x&y)`
This commit contains to test these cases.
Proof: https://alive2.llvm.org/ce/z/WW8iRR
---
llvm/test/Transforms/InstCombine/select.ll | 847 +++++++++++++++++++++
1 file changed, 847 insertions(+)
diff --git a/llvm/test/Transforms/InstCombine/select.ll b/llvm/test/Transforms/InstCombine/select.ll
index c5f1b77c6d7404..0a6e89ddd2e56d 100644
--- a/llvm/test/Transforms/InstCombine/select.ll
+++ b/llvm/test/Transforms/InstCombine/select.ll
@@ -3659,6 +3659,853 @@ exit:
ret i32 %rem
}
+; Select icmp and/or/xor
+; https://alive2.llvm.org/ce/z/QXQDwF
+; X&Y==C?X|Y:X^Y, X&Y==C?X^Y:X|Y
+define i32 @src_and_eq_0_or_xor(i32 %x, i32 %y) {
+; CHECK-LABEL: @src_and_eq_0_or_xor(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[AND]], 0
+; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y]], [[X]]
+; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[Y]], [[X]]
+; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[OR]], i32 [[XOR]]
+; CHECK-NEXT: ret i32 [[COND]]
+;
+entry:
+ %and = and i32 %y, %x
+ %cmp = icmp eq i32 %and, 0
+ %or = or i32 %y, %x
+ %xor = xor i32 %y, %x
+ %cond = select i1 %cmp, i32 %or, i32 %xor
+ ret i32 %cond
+}
+
+define i32 @src_and_eq_0_xor_or(i32 %x, i32 %y) {
+; CHECK-LABEL: @src_and_eq_0_xor_or(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[AND]], 0
+; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[Y]], [[X]]
+; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y]], [[X]]
+; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[XOR]], i32 [[OR]]
+; CHECK-NEXT: ret i32 [[COND]]
+;
+entry:
+ %and = and i32 %y, %x
+ %cmp = icmp eq i32 %and, 0
+ %xor = xor i32 %y, %x
+ %or = or i32 %y, %x
+ %cond = select i1 %cmp, i32 %xor, i32 %or
+ ret i32 %cond
+}
+
+define i32 @src_and_eq_neg1_or_xor(i32 %x, i32 %y) {
+; CHECK-LABEL: @src_and_eq_neg1_or_xor(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[AND]], -1
+; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y]], [[X]]
+; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[Y]], [[X]]
+; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[OR]], i32 [[XOR]]
+; CHECK-NEXT: ret i32 [[COND]]
+;
+entry:
+ %and = and i32 %y, %x
+ %cmp = icmp eq i32 %and, -1
+ %or = or i32 %y, %x
+ %xor = xor i32 %y, %x
+ %cond = select i1 %cmp, i32 %or, i32 %xor
+ ret i32 %cond
+}
+
+define i32 @src_and_eq_neg1_xor_or(i32 %x, i32 %y) {
+; CHECK-LABEL: @src_and_eq_neg1_xor_or(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[AND]], -1
+; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[Y]], [[X]]
+; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y]], [[X]]
+; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[XOR]], i32 [[OR]]
+; CHECK-NEXT: ret i32 [[COND]]
+;
+entry:
+ %and = and i32 %y, %x
+ %cmp = icmp eq i32 %and, -1
+ %xor = xor i32 %y, %x
+ %or = or i32 %y, %x
+ %cond = select i1 %cmp, i32 %xor, i32 %or
+ ret i32 %cond
+}
+
+define i32 @src_and_eq_C_or_xororC(i32 %x, i32 %y, i32 %c) {
+; CHECK-LABEL: @src_and_eq_C_or_xororC(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[AND]], [[C:%.*]]
+; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y]], [[X]]
+; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[Y]], [[X]]
+; CHECK-NEXT: [[OR1:%.*]] = or i32 [[XOR]], [[C]]
+; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[OR]], i32 [[OR1]]
+; CHECK-NEXT: ret i32 [[COND]]
+;
+entry:
+ %and = and i32 %y, %x
+ %cmp = icmp eq i32 %and, %c
+ %or = or i32 %y, %x
+ %xor = xor i32 %y, %x
+ %or1 = or i32 %xor, %c
+ %cond = select i1 %cmp, i32 %or, i32 %or1
+ ret i32 %cond
+}
+
+define i32 @src_and_eq_C_or_xorxorC(i32 %x, i32 %y, i32 %c) {
+; CHECK-LABEL: @src_and_eq_C_or_xorxorC(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[AND]], [[C:%.*]]
+; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y]], [[X]]
+; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[Y]], [[X]]
+; CHECK-NEXT: [[XOR1:%.*]] = xor i32 [[XOR]], [[C]]
+; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[OR]], i32 [[XOR1]]
+; CHECK-NEXT: ret i32 [[COND]]
+;
+entry:
+ %and = and i32 %y, %x
+ %cmp = icmp eq i32 %and, %c
+ %or = or i32 %y, %x
+ %xor = xor i32 %y, %x
+ %xor1 = xor i32 %xor, %c
+ %cond = select i1 %cmp, i32 %or, i32 %xor1
+ ret i32 %cond
+}
+
+define i32 @src_and_eq_C_xor_OrAndNotC(i32 %x, i32 %y, i32 %c) {
+; CHECK-LABEL: @src_and_eq_C_xor_OrAndNotC(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[AND]], [[C:%.*]]
+; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[Y]], [[X]]
+; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y]], [[X]]
+; CHECK-NEXT: [[NOT:%.*]] = xor i32 [[C]], -1
+; CHECK-NEXT: [[AND1:%.*]] = and i32 [[OR]], [[NOT]]
+; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[XOR]], i32 [[AND1]]
+; CHECK-NEXT: ret i32 [[COND]]
+;
+entry:
+ %and = and i32 %y, %x
+ %cmp = icmp eq i32 %and, %c
+ %xor = xor i32 %y, %x
+ %or = or i32 %y, %x
+ %not = xor i32 %c, -1
+ %and1 = and i32 %or, %not
+ %cond = select i1 %cmp, i32 %xor, i32 %and1
+ ret i32 %cond
+}
+
+define i32 @src_and_eq_C_xor_orxorC(i32 %x, i32 %y, i32 %c) {
+; CHECK-LABEL: @src_and_eq_C_xor_orxorC(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[AND]], [[C:%.*]]
+; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[Y]], [[X]]
+; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y]], [[X]]
+; CHECK-NEXT: [[XOR1:%.*]] = xor i32 [[OR]], [[C]]
+; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[XOR]], i32 [[XOR1]]
+; CHECK-NEXT: ret i32 [[COND]]
+;
+entry:
+ %and = and i32 %y, %x
+ %cmp = icmp eq i32 %and, %c
+ %xor = xor i32 %y, %x
+ %or = or i32 %y, %x
+ %xor1 = xor i32 %or, %c
+ %cond = select i1 %cmp, i32 %xor, i32 %xor1
+ ret i32 %cond
+}
+
+; https://alive2.llvm.org/ce/z/9RPwfN
+; X|Y==C?X&Y:X^Y, X|Y==C?X^Y:X&Y
+define i32 @src_or_eq_0_and_xor(i32 %x, i32 %y) {
+; CHECK-LABEL: @src_or_eq_0_and_xor(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[OR]], 0
+; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y]], [[X]]
+; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[Y]], [[X]]
+; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[AND]], i32 [[XOR]]
+; CHECK-NEXT: ret i32 [[COND]]
+;
+entry:
+ %or = or i32 %y, %x
+ %cmp = icmp eq i32 %or, 0
+ %and = and i32 %y, %x
+ %xor = xor i32 %y, %x
+ %cond = select i1 %cmp, i32 %and, i32 %xor
+ ret i32 %cond
+}
+
+define i32 @src_or_eq_0_xor_and(i32 %x, i32 %y) {
+; CHECK-LABEL: @src_or_eq_0_xor_and(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[OR]], 0
+; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[Y]], [[X]]
+; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y]], [[X]]
+; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[XOR]], i32 [[AND]]
+; CHECK-NEXT: ret i32 [[COND]]
+;
+entry:
+ %or = or i32 %y, %x
+ %cmp = icmp eq i32 %or, 0
+ %xor = xor i32 %y, %x
+ %and = and i32 %y, %x
+ %cond = select i1 %cmp, i32 %xor, i32 %and
+ ret i32 %cond
+}
+
+define i32 @src_or_eq_neg1_and_xor(i32 %x, i32 %y) {
+; CHECK-LABEL: @src_or_eq_neg1_and_xor(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[OR]], -1
+; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y]], [[X]]
+; CHECK-NEXT: [[TMP0:%.*]] = xor i32 [[X]], [[Y]]
+; CHECK-NEXT: [[NOT:%.*]] = xor i32 [[TMP0]], -1
+; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[AND]], i32 [[NOT]]
+; CHECK-NEXT: ret i32 [[COND]]
+;
+entry:
+ %or = or i32 %y, %x
+ %cmp = icmp eq i32 %or, -1
+ %and = and i32 %y, %x
+ %0 = xor i32 %x, %y
+ %not = xor i32 %0, -1
+ %cond = select i1 %cmp, i32 %and, i32 %not
+ ret i32 %cond
+}
+
+define i32 @src_or_eq_neg1_xor_and(i32 %x, i32 %y) {
+; CHECK-LABEL: @src_or_eq_neg1_xor_and(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[OR]], -1
+; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[Y]], [[X]]
+; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y]], [[X]]
+; CHECK-NEXT: [[NOT:%.*]] = xor i32 [[AND]], -1
+; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[XOR]], i32 [[NOT]]
+; CHECK-NEXT: ret i32 [[COND]]
+;
+entry:
+ %or = or i32 %y, %x
+ %cmp = icmp eq i32 %or, -1
+ %xor = xor i32 %y, %x
+ %and = and i32 %y, %x
+ %not = xor i32 %and, -1
+ %cond = select i1 %cmp, i32 %xor, i32 %not
+ ret i32 %cond
+}
+
+define i32 @src_or_eq_C_and_xorC(i32 %x, i32 %y, i32 %c) {
+; CHECK-LABEL: @src_or_eq_C_and_xorC(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[OR]], [[C:%.*]]
+; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y]], [[X]]
+; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[Y]], [[X]]
+; CHECK-NEXT: [[XOR1:%.*]] = xor i32 [[XOR]], [[C]]
+; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[AND]], i32 [[XOR1]]
+; CHECK-NEXT: ret i32 [[COND]]
+;
+entry:
+ %or = or i32 %y, %x
+ %cmp = icmp eq i32 %or, %c
+ %and = and i32 %y, %x
+ %xor = xor i32 %y, %x
+ %xor1 = xor i32 %xor, %c
+ %cond = select i1 %cmp, i32 %and, i32 %xor1
+ ret i32 %cond
+}
+
+define i32 @src_or_eq_C_and_andnotxorC(i32 %x, i32 %y, i32 %c) {
+; CHECK-LABEL: @src_or_eq_C_and_andnotxorC(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[OR]], [[C:%.*]]
+; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y]], [[X]]
+; CHECK-NEXT: [[TMP0:%.*]] = xor i32 [[X]], [[Y]]
+; CHECK-NEXT: [[NOT:%.*]] = xor i32 [[TMP0]], -1
+; CHECK-NEXT: [[AND1:%.*]] = and i32 [[NOT]], [[C]]
+; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[AND]], i32 [[AND1]]
+; CHECK-NEXT: ret i32 [[COND]]
+;
+entry:
+ %or = or i32 %y, %x
+ %cmp = icmp eq i32 %or, %c
+ %and = and i32 %y, %x
+ %0 = xor i32 %x, %y
+ %not = xor i32 %0, -1
+ %and1 = and i32 %not, %c
+ %cond = select i1 %cmp, i32 %and, i32 %and1
+ ret i32 %cond
+}
+
+define i32 @src_or_eq_C_xor_xorandC(i32 %x, i32 %y, i32 %c) {
+; CHECK-LABEL: @src_or_eq_C_xor_xorandC(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[OR]], [[C:%.*]]
+; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[Y]], [[X]]
+; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y]], [[X]]
+; CHECK-NEXT: [[XOR1:%.*]] = xor i32 [[AND]], [[C]]
+; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[XOR]], i32 [[XOR1]]
+; CHECK-NEXT: ret i32 [[COND]]
+;
+entry:
+ %or = or i32 %y, %x
+ %cmp = icmp eq i32 %or, %c
+ %xor = xor i32 %y, %x
+ %and = and i32 %y, %x
+ %xor1 = xor i32 %and, %c
+ %cond = select i1 %cmp, i32 %xor, i32 %xor1
+ ret i32 %cond
+}
+
+define i32 @src_or_eq_C_xor_andnotandC(i32 %x, i32 %y, i32 %c) {
+; CHECK-LABEL: @src_or_eq_C_xor_andnotandC(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[OR]], [[C:%.*]]
+; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[Y]], [[X]]
+; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y]], [[X]]
+; CHECK-NEXT: [[NOT:%.*]] = xor i32 [[AND]], -1
+; CHECK-NEXT: [[AND1:%.*]] = and i32 [[NOT]], [[C]]
+; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[XOR]], i32 [[AND1]]
+; CHECK-NEXT: ret i32 [[COND]]
+;
+entry:
+ %or = or i32 %y, %x
+ %cmp = icmp eq i32 %or, %c
+ %xor = xor i32 %y, %x
+ %and = and i32 %y, %x
+ %not = xor i32 %and, -1
+ %and1 = and i32 %not, %c
+ %cond = select i1 %cmp, i32 %xor, i32 %and1
+ ret i32 %cond
+}
+
+; https://alive2.llvm.org/ce/z/c6oXi4
+; X^Y==C?X&Y:X|Y, X^Y==C?X|Y:X&Y
+define i32 @src_xor_eq_neg1_and(i32 %x, i32 %y) {
+; CHECK-LABEL: @src_xor_eq_neg1_and(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[XOR]], -1
+; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y]], [[X]]
+; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y]], [[X]]
+; CHECK-NEXT: [[NOT:%.*]] = xor i32 [[OR]], -1
+; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[AND]], i32 [[NOT]]
+; CHECK-NEXT: ret i32 [[COND]]
+;
+entry:
+ %xor = xor i32 %y, %x
+ %cmp = icmp eq i32 %xor, -1
+ %and = and i32 %y, %x
+ %or = or i32 %y, %x
+ %not = xor i32 %or, -1
+ %cond = select i1 %cmp, i32 %and, i32 %not
+ ret i32 %cond
+}
+
+define i32 @src_xor_eq_neg1_or(i32 %x, i32 %y) {
+; CHECK-LABEL: @src_xor_eq_neg1_or(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[XOR]], -1
+; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y]], [[X]]
+; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[OR]], i32 -1
+; CHECK-NEXT: ret i32 [[COND]]
+;
+entry:
+ %xor = xor i32 %y, %x
+ %cmp = icmp eq i32 %xor, -1
+ %or = or i32 %y, %x
+ %cond = select i1 %cmp, i32 %or, i32 -1
+ ret i32 %cond
+}
+
+define i32 @src_xor_eq_C_and_xororC(i32 %x, i32 %y, i32 %c) {
+; CHECK-LABEL: @src_xor_eq_C_and_xororC(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[XOR]], [[C:%.*]]
+; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y]], [[X]]
+; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y]], [[X]]
+; CHECK-NEXT: [[XOR1:%.*]] = xor i32 [[OR]], [[C]]
+; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[AND]], i32 [[XOR1]]
+; CHECK-NEXT: ret i32 [[COND]]
+;
+entry:
+ %xor = xor i32 %y, %x
+ %cmp = icmp eq i32 %xor, %c
+ %and = and i32 %y, %x
+ %or = or i32 %y, %x
+ %xor1 = xor i32 %or, %c
+ %cond = select i1 %cmp, i32 %and, i32 %xor1
+ ret i32 %cond
+}
+
+define i32 @src_xor_eq_C_and_andornotC(i32 %x, i32 %y, i32 %c) {
+; CHECK-LABEL: @src_xor_eq_C_and_andornotC(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[XOR]], [[C:%.*]]
+; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y]], [[X]]
+; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y]], [[X]]
+; CHECK-NEXT: [[NOT:%.*]] = xor i32 [[C]], -1
+; CHECK-NEXT: [[AND1:%.*]] = and i32 [[OR]], [[NOT]]
+; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[AND]], i32 [[AND1]]
+; CHECK-NEXT: ret i32 [[COND]]
+;
+entry:
+ %xor = xor i32 %y, %x
+ %cmp = icmp eq i32 %xor, %c
+ %and = and i32 %y, %x
+ %or = or i32 %y, %x
+ %not = xor i32 %c, -1
+ %and1 = and i32 %or, %not
+ %cond = select i1 %cmp, i32 %and, i32 %and1
+ ret i32 %cond
+}
+
+define i32 @src_xor_eq_C_or_xorandC(i32 %x, i32 %y, i32 %c) {
+; CHECK-LABEL: @src_xor_eq_C_or_xorandC(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[XOR]], [[C:%.*]]
+; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y]], [[X]]
+; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y]], [[X]]
+; CHECK-NEXT: [[XOR1:%.*]] = xor i32 [[AND]], [[C]]
+; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[OR]], i32 [[XOR1]]
+; CHECK-NEXT: ret i32 [[COND]]
+;
+entry:
+ %xor = xor i32 %y, %x
+ %cmp = icmp eq i32 %xor, %c
+ %or = or i32 %y, %x
+ %and = and i32 %y, %x
+ %xor1 = xor i32 %and, %c
+ %cond = select i1 %cmp, i32 %or, i32 %xor1
+ ret i32 %cond
+}
+
+define i32 @src_xor_eq_C_or_orandC(i32 %x, i32 %y, i32 %c) {
+; CHECK-LABEL: @src_xor_eq_C_or_orandC(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[XOR]], [[C:%.*]]
+; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y]], [[X]]
+; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y]], [[X]]
+; CHECK-NEXT: [[OR1:%.*]] = or i32 [[AND]], [[C]]
+; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[OR]], i32 [[OR1]]
+; CHECK-NEXT: ret i32 [[COND]]
+;
+entry:
+ %xor = xor i32 %y, %x
+ %cmp = icmp eq i32 %xor, %c
+ %or = or i32 %y, %x
+ %and = and i32 %y, %x
+ %or1 = or i32 %and, %c
+ %cond = select i1 %cmp, i32 %or, i32 %or1
+ ret i32 %cond
+}
+
+; Select icmp and/or/xor
+; NO TRANSFORMED - select condition is compare with not 0
+define i32 @src_select_and_min_positive_int(i32 %x, i32 %y) {
+; CHECK-LABEL: @src_select_and_min_positive_int(
+; CHECK-NEXT: [[AND:%.*]] = and i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT: [[AND0:%.*]] = icmp eq i32 [[AND]], 1
+; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[X]], [[Y]]
+; CHECK-NEXT: [[OR:%.*]] = or i32 [[X]], [[Y]]
+; CHECK-NEXT: [[COND:%.*]] = select i1 [[AND0]], i32 [[OR]], i32 [[XOR]]
+; CHECK-NEXT: ret i32 [[COND]]
+;
+ %and = and i32 %x, %y
+ %and0 = icmp eq i32 %and, 1
+ %xor = xor i32 %x, %y
+ %or = or i32 %x, %y
+ %cond = select i1 %and0, i32 %or, i32 %xor
+ ret i32 %cond
+}
+
+define i32 @src_select_and_max_positive_int(i32 %x, i32 %y) {
+; CHECK-LABEL: @src_select_and_max_positive_int(
+; CHECK-NEXT: [[AND:%.*]] = and i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT: [[AND0:%.*]] = icmp eq i32 [[AND]], 2147483647
+; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[X]], [[Y]]
+; CHECK-NEXT: [[OR:%.*]] = or i32 [[X]], [[Y]]
+; CHECK-NEXT: [[COND:%.*]] = select i1 [[AND0]], i32 [[OR]], i32 [[XOR]]
+; CHECK-NEXT: ret i32 [[COND]]
+;
+ %and = and i32 %x, %y
+ %and0 = icmp eq i32 %and, 2147483647
+ %xor = xor i32 %x, %y
+ %or = or i32 %x, %y
+ %cond = select i1 %and0, i32 %or, i32 %xor
+ ret i32 %cond
+}
+
+define i32 @src_select_and_min_negative_int(i32 %x, i32 %y) {
+; CHECK-LABEL: @src_select_and_min_negative_int(
+; CHECK-NEXT: [[AND:%.*]] = and i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT: [[AND0:%.*]] = icmp eq i32 [[AND]], -2147483648
+; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[X]], [[Y]]
+; CHECK-NEXT: [[OR:%.*]] = or i32 [[X]], [[Y]]
+; CHECK-NEXT: [[COND:%.*]] = select i1 [[AND0]], i32 [[OR]], i32 [[XOR]]
+; CHECK-NEXT: ret i32 [[COND]]
+;
+ %and = and i32 %x, %y
+ %and0 = icmp eq i32 %and, -2147483648
+ %xor = xor i32 %x, %y
+ %or = or i32 %x, %y
+ %cond = select i1 %and0, i32 %or, i32 %xor
+ ret i32 %cond
+}
+
+define i32 @src_select_or_min_positive_int(i32 %x, i32 %y) {
+; CHECK-LABEL: @src_select_or_min_positive_int(
+; CHECK-NEXT: [[OR:%.*]] = or i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT: [[OR0:%.*]] = icmp eq i32 [[OR]], 1
+; CHECK-NEXT: [[AND:%.*]] = and i32 [[X]], [[Y]]
+; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[X]], [[Y]]
+; CHECK-NEXT: [[COND:%.*]] = select i1 [[OR0]], i32 [[AND]], i32 [[XOR]]
+; CHECK-NEXT: ret i32 [[COND]]
+;
+ %or = or i32 %x, %y
+ %or0 = icmp eq i32 %or, 1
+ %and = and i32 %x, %y
+ %xor = xor i32 %x, %y
+ %cond = select i1 %or0, i32 %and, i32 %xor
+ ret i32 %cond
+}
+
+define i32 @src_select_or_max_positive_int(i32 %x, i32 %y) {
+; CHECK-LABEL: @src_select_or_max_positive_int(
+; CHECK-NEXT: [[OR:%.*]] = or i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT: [[OR0:%.*]] = icmp eq i32 [[OR]], 2147483647
+; CHECK-NEXT: [[AND:%.*]] = and i32 [[X]], [[Y]]
+; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[X]], [[Y]]
+; CHECK-NEXT: [[COND:%.*]] = select i1 [[OR0]], i32 [[AND]], i32 [[XOR]]
+; CHECK-NEXT: ret i32 [[COND]]
+;
+ %or = or i32 %x, %y
+ %or0 = icmp eq i32 %or, 2147483647
+ %and = and i32 %x, %y
+ %xor = xor i32 %x, %y
+ %cond = select i1 %or0, i32 %and, i32 %xor
+ ret i32 %cond
+}
+
+define i32 @src_select_or_min_negative_int(i32 %x, i32 %y) {
+; CHECK-LABEL: @src_select_or_min_negative_int(
+; CHECK-NEXT: [[OR:%.*]] = or i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT: [[OR0:%.*]] = icmp eq i32 [[OR]], -2147483648
+; CHECK-NEXT: [[AND:%.*]] = and i32 [[X]], [[Y]]
+; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[X]], [[Y]]
+; CHECK-NEXT: [[COND:%.*]] = select i1 [[OR0]], i32 [[AND]], i32 [[XOR]]
+; CHECK-NEXT: ret i32 [[COND]]
+;
+ %or = or i32 %x, %y
+ %or0 = icmp eq i32 %or, -2147483648
+ %and = and i32 %x, %y
+ %xor = xor i32 %x, %y
+ %cond = select i1 %or0, i32 %and, i32 %xor
+ ret i32 %cond
+}
+
+define i32 @src_select_or_max_negative_int(i32 %x, i32 %y) {
+; CHECK-LABEL: @src_select_or_max_negative_int(
+; CHECK-NEXT: [[OR:%.*]] = or i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT: [[OR0:%.*]] = icmp eq i32 [[OR]], -1
+; CHECK-NEXT: [[AND:%.*]] = and i32 [[X]], [[Y]]
+; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[X]], [[Y]]
+; CHECK-NEXT: [[COND:%.*]] = select i1 [[OR0]], i32 [[AND]], i32 [[XOR]]
+; CHECK-NEXT: ret i32 [[COND]]
+;
+ %or = or i32 %x, %y
+ %or0 = icmp eq i32 %or, -1
+ %and = and i32 %x, %y
+ %xor = xor i32 %x, %y
+ %cond = select i1 %or0, i32 %and, i32 %xor
+ ret i32 %cond
+}
+
+define i32 @src_select_xor_min_positive_int(i32 %x, i32 %y) {
+; CHECK-LABEL: @src_select_xor_min_positive_int(
+; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT: [[XOR0:%.*]] = icmp eq i32 [[XOR]], 1
+; CHECK-NEXT: [[AND:%.*]] = and i32 [[X]], [[Y]]
+; CHECK-NEXT: [[OR:%.*]] = or i32 [[X]], [[Y]]
+; CHECK-NEXT: [[COND:%.*]] = select i1 [[XOR0]], i32 [[AND]], i32 [[OR]]
+; CHECK-NEXT: ret i32 [[COND]]
+;
+ %xor = xor i32 %x, %y
+ %xor0 = icmp eq i32 %xor, 1
+ %and = and i32 %x, %y
+ %or = or i32 %x, %y
+ %cond = select i1 %xor0, i32 %and, i32 %or
+ ret i32 %cond
+}
+
+define i32 @src_select_xor_max_positive_int(i32 %x, i32 %y) {
+; CHECK-LABEL: @src_select_xor_max_positive_int(
+; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT: [[XOR0:%.*]] = icmp eq i32 [[XOR]], 2147483647
+; CHECK-NEXT: [[AND:%.*]] = and i32 [[X]], [[Y]]
+; CHECK-NEXT: [[OR:%.*]] = or i32 [[X]], [[Y]]
+; CHECK-NEXT: [[COND:%.*]] = select i1 [[XOR0]], i32 [[AND]], i32 [[OR]]
+; CHECK-NEXT: ret i32 [[COND]]
+;
+ %xor = xor i32 %x, %y
+ %xor0 = icmp eq i32 %xor, 2147483647
+ %and = and i32 %x, %y
+ %or = or i32 %x, %y
+ %cond = select i1 %xor0, i32 %and, i32 %or
+ ret i32 %cond
+}
+
+define i32 @src_select_xor_min_negative_int(i32 %x, i32 %y) {
+; CHECK-LABEL: @src_select_xor_min_negative_int(
+; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT: [[XOR0:%.*]] = icmp eq i32 [[XOR]], -2147483648
+; CHECK-NEXT: [[AND:%.*]] = and i32 [[X]], [[Y]]
+; CHECK-NEXT: [[OR:%.*]] = or i32 [[X]], [[Y]]
+; CHECK-NEXT: [[COND:%.*]] = select i1 [[XOR0]], i32 [[AND]], i32 [[OR]]
+; CHECK-NEXT: ret i32 [[COND]]
+;
+ %xor = xor i32 %x, %y
+ %xor0 = icmp eq i32 %xor, -2147483648
+ %and = and i32 %x, %y
+ %or = or i32 %x, %y
+ %cond = select i1 %xor0, i32 %and, i32 %or
+ ret i32 %cond
+}
+
+define i32 @src_select_xor_max_negative_int(i32 %x, i32 %y) {
+; CHECK-LABEL: @src_select_xor_max_negative_int(
+; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT: [[XOR0:%.*]] = icmp eq i32 [[XOR]], -1
+; CHECK-NEXT: [[AND:%.*]] = and i32 [[X]], [[Y]]
+; CHECK-NEXT: [[OR:%.*]] = or i32 [[X]], [[Y]]
+; CHECK-NEXT: [[COND:%.*]] = select i1 [[XOR0]], i32 [[AND]], i32 [[OR]]
+; CHECK-NEXT: ret i32 [[COND]]
+;
+ %xor = xor i32 %x, %y
+ %xor0 = icmp eq i32 %xor, -1
+ %and = and i32 %x, %y
+ %or = or i32 %x, %y
+ %cond = select i1 %xor0, i32 %and, i32 %or
+ ret i32 %cond
+}
+
+; Select icmp and/or/xor
+; https://alive2.llvm.org/ce/z/BVgrJ-
+; NO TRANSFORMED - not supported
+define i32 @src_no_trans_select_and_eq0_and_or(i32 %x, i32 %y) {
+; CHECK-LABEL: @src_no_trans_select_and_eq0_and_or(
+; CHECK-NEXT: [[AND:%.*]] = and i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT: [[AND0:%.*]] = icmp eq i32 [[AND]], 0
+; CHECK-NEXT: [[OR:%.*]] = or i32 [[X]], [[Y]]
+; CHECK-NEXT: [[COND:%.*]] = select i1 [[AND0]], i32 0, i32 [[OR]]
+; CHECK-NEXT: ret i32 [[COND]]
+;
+ %and = and i32 %x, %y
+ %and0 = icmp eq i32 %and, 0
+ %or = or i32 %x, %y
+ %cond = select i1 %and0, i32 %and, i32 %or
+ ret i32 %cond
+}
+
+define i32 @src_no_trans_select_and_eq0_and_xor(i32 %x, i32 %y) {
+; CHECK-LABEL: @src_no_trans_select_and_eq0_and_xor(
+; CHECK-NEXT: [[AND:%.*]] = and i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT: [[AND0:%.*]] = icmp eq i32 [[AND]], 0
+; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[X]], [[Y]]
+; CHECK-NEXT: [[COND:%.*]] = select i1 [[AND0]], i32 0, i32 [[XOR]]
+; CHECK-NEXT: ret i32 [[COND]]
+;
+ %and = and i32 %x, %y
+ %and0 = icmp eq i32 %and, 0
+ %xor = xor i32 %x, %y
+ %cond = select i1 %and0, i32 %and, i32 %xor
+ ret i32 %cond
+}
+
+define i32 @src_no_trans_select_and_eq0_or_and(i32 %x, i32 %y) {
+; CHECK-LABEL: @src_no_trans_select_and_eq0_or_and(
+; CHECK-NEXT: [[AND:%.*]] = and i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT: [[AND0:%.*]] = icmp eq i32 [[AND]], 0
+; CHECK-NEXT: [[OR:%.*]] = or i32 [[X]], [[Y]]
+; CHECK-NEXT: [[COND:%.*]] = select i1 [[AND0]], i32 [[OR]], i32 [[AND]]
+; CHECK-NEXT: ret i32 [[COND]]
+;
+ %and = and i32 %x, %y
+ %and0 = icmp eq i32 %and, 0
+ %or = or i32 %x, %y
+ %cond = select i1 %and0, i32 %or, i32 %and
+ ret i32 %cond
+}
+
+define i32 @src_no_trans_select_and_eq0_xor_and(i32 %x, i32 %y) {
+; CHECK-LABEL: @src_no_trans_select_and_eq0_xor_and(
+; CHECK-NEXT: [[AND:%.*]] = and i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT: [[AND0:%.*]] = icmp eq i32 [[AND]], 0
+; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[X]], [[Y]]
+; CHECK-NEXT: [[COND:%.*]] = select i1 [[AND0]], i32 [[XOR]], i32 [[AND]]
+; CHECK-NEXT: ret i32 [[COND]]
+;
+ %and = and i32 %x, %y
+ %and0 = icmp eq i32 %and, 0
+ %xor = xor i32 %x, %y
+ %cond = select i1 %and0, i32 %xor, i32 %and
+ ret i32 %cond
+}
+
+define i32 @src_no_trans_select_or_eq0_or_and(i32 %x, i32 %y) {
+; CHECK-LABEL: @src_no_trans_select_or_eq0_or_and(
+; CHECK-NEXT: [[OR:%.*]] = or i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT: [[OR0:%.*]] = icmp eq i32 [[OR]], 0
+; CHECK-NEXT: [[AND:%.*]] = and i32 [[X]], [[Y]]
+; CHECK-NEXT: [[COND:%.*]] = select i1 [[OR0]], i32 0, i32 [[AND]]
+; CHECK-NEXT: ret i32 [[COND]]
+;
+ %or = or i32 %x, %y
+ %or0 = icmp eq i32 %or, 0
+ %and = and i32 %x, %y
+ %cond = select i1 %or0, i32 %or, i32 %and
+ ret i32 %cond
+}
+
+define i32 @src_no_trans_select_or_eq0_or_xor(i32 %x, i32 %y) {
+; CHECK-LABEL: @src_no_trans_select_or_eq0_or_xor(
+; CHECK-NEXT: [[OR:%.*]] = or i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT: [[OR0:%.*]] = icmp eq i32 [[OR]], 0
+; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[X]], [[Y]]
+; CHECK-NEXT: [[COND:%.*]] = select i1 [[OR0]], i32 0, i32 [[XOR]]
+; CHECK-NEXT: ret i32 [[COND]]
+;
+ %or = or i32 %x, %y
+ %or0 = icmp eq i32 %or, 0
+ %xor = xor i32 %x, %y
+ %cond = select i1 %or0, i32 %or, i32 %xor
+ ret i32 %cond
+}
+
+define i32 @src_no_trans_select_or_eq0_and_or(i32 %x, i32 %y) {
+; CHECK-LABEL: @src_no_trans_select_or_eq0_and_or(
+; CHECK-NEXT: [[OR:%.*]] = or i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT: [[OR0:%.*]] = icmp eq i32 [[OR]], 0
+; CHECK-NEXT: [[AND:%.*]] = and i32 [[X]], [[Y]]
+; CHECK-NEXT: [[COND:%.*]] = select i1 [[OR0]], i32 [[AND]], i32 [[OR]]
+; CHECK-NEXT: ret i32 [[COND]]
+;
+ %or = or i32 %x, %y
+ %or0 = icmp eq i32 %or, 0
+ %and = and i32 %x, %y
+ %cond = select i1 %or0, i32 %and, i32 %or
+ ret i32 %cond
+}
+
+define i32 @src_no_trans_select_or_eq0_xor_or(i32 %x, i32 %y) {
+; CHECK-LABEL: @src_no_trans_select_or_eq0_xor_or(
+; CHECK-NEXT: [[OR:%.*]] = or i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT: [[OR0:%.*]] = icmp eq i32 [[OR]], 0
+; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[X]], [[Y]]
+; CHECK-NEXT: [[COND:%.*]] = select i1 [[OR0]], i32 [[XOR]], i32 [[OR]]
+; CHECK-NEXT: ret i32 [[COND]]
+;
+ %or = or i32 %x, %y
+ %or0 = icmp eq i32 %or, 0
+ %xor = xor i32 %x, %y
+ %cond = select i1 %or0, i32 %xor, i32 %or
+ ret i32 %cond
+}
+
+define i32 @src_no_trans_select_and_ne0_xor_or(i32 %x, i32 %y) {
+; CHECK-LABEL: @src_no_trans_select_and_ne0_xor_or(
+; CHECK-NEXT: [[OR:%.*]] = or i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT: [[OR0_NOT:%.*]] = icmp eq i32 [[OR]], 0
+; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[X]], [[Y]]
+; CHECK-NEXT: [[COND:%.*]] = select i1 [[OR0_NOT]], i32 0, i32 [[XOR]]
+; CHECK-NEXT: ret i32 [[COND]]
+;
+ %or = or i32 %x, %y
+ %or0 = icmp ne i32 %or, 0
+ %xor = xor i32 %x, %y
+ %cond = select i1 %or0, i32 %xor, i32 %or
+ ret i32 %cond
+}
+
+define i32 @src_no_trans_select_xor_eq0_xor_and(i32 %x, i32 %y) {
+; CHECK-LABEL: @src_no_trans_select_xor_eq0_xor_and(
+; CHECK-NEXT: [[XOR0:%.*]] = icmp eq i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT: [[AND:%.*]] = and i32 [[X]], [[Y]]
+; CHECK-NEXT: [[COND:%.*]] = select i1 [[XOR0]], i32 0, i32 [[AND]]
+; CHECK-NEXT: ret i32 [[COND]]
+;
+ %xor = xor i32 %x, %y
+ %xor0 = icmp eq i32 %xor, 0
+ %and = and i32 %x, %y
+ %cond = select i1 %xor0, i32 %xor, i32 %and
+ ret i32 %cond
+}
+
+define i32 @src_no_trans_select_xor_eq0_xor_or(i32 %x, i32 %y) {
+; CHECK-LABEL: @src_no_trans_select_xor_eq0_xor_or(
+; CHECK-NEXT: [[XOR0:%.*]] = icmp eq i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT: [[OR:%.*]] = or i32 [[X]], [[Y]]
+; CHECK-NEXT: [[COND:%.*]] = select i1 [[XOR0]], i32 0, i32 [[OR]]
+; CHECK-NEXT: ret i32 [[COND]]
+;
+ %xor = xor i32 %x, %y
+ %xor0 = icmp eq i32 %xor, 0
+ %or = or i32 %x, %y
+ %cond = select i1 %xor0, i32 %xor, i32 %or
+ ret i32 %cond
+}
+
+define i32 @src_no_trans_select_xor_eq0_and_xor(i32 %x, i32 %y) {
+; CHECK-LABEL: @src_no_trans_select_xor_eq0_and_xor(
+; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT: [[XOR0:%.*]] = icmp eq i32 [[XOR]], 0
+; CHECK-NEXT: [[AND:%.*]] = and i32 [[X]], [[Y]]
+; CHECK-NEXT: [[COND:%.*]] = select i1 [[XOR0]], i32 [[AND]], i32 [[XOR]]
+; CHECK-NEXT: ret i32 [[COND]]
+;
+ %xor = xor i32 %x, %y
+ %xor0 = icmp eq i32 %xor, 0
+ %and = and i32 %x, %y
+ %cond = select i1 %xor0, i32 %and, i32 %xor
+ ret i32 %cond
+}
+
+; https://alive2.llvm.org/ce/z/SBe8ei
+define i32 @src_no_trans_select_xor_eq0_or_xor(i32 %x, i32 %y) {
+; CHECK-LABEL: @src_no_trans_select_xor_eq0_or_xor(
+; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT: [[XOR0:%.*]] = icmp eq i32 [[XOR]], 0
+; CHECK-NEXT: [[OR:%.*]] = or i32 [[X]], [[Y]]
+; CHECK-NEXT: [[COND:%.*]] = select i1 [[XOR0]], i32 [[OR]], i32 [[XOR]]
+; CHECK-NEXT: ret i32 [[COND]]
+;
+ %xor = xor i32 %x, %y
+ %xor0 = icmp eq i32 %xor, 0
+ %or = or i32 %x, %y
+ %cond = select i1 %xor0, i32 %or, i32 %xor
+ ret i32 %cond
+}
+
; (X == C) ? X : Y -> (X == C) ? C : Y
; Fixed #77553
define i32 @src_select_xxory_eq0_xorxy_y(i32 %x, i32 %y) {
>From 4bb117d4f09aa8e9072af5547edd767da93fff3e Mon Sep 17 00:00:00 2001
From: Hanbum Park <kese111 at gmail.com>
Date: Fri, 24 Nov 2023 06:37:57 +0900
Subject: [PATCH 2/2] [InstCombine] Simplify select if it combinated
`and/or/xor`
`and/or/xor` operations can each be changed to sum of logical
operations including operators other than themselves.
`x&y -> (x|y) ^ (x^y)`
`x|y -> (x&y) | (x^y)`
`x^y -> (x|y) ^ (x&y)`
if left of condition of `SelectInst` is `and/or/xor` logical
operation and right is equal to `0, -1`, or a `constant`, and
if `TrueVal` consist of `and/or/xor` logical operation then we
can optimize this case.
This patch implements this combination.
Proof: https://alive2.llvm.org/ce/z/WW8iRR
Fixed llvm#71792.
---
.../InstCombine/InstCombineSelect.cpp | 140 +++++++++++++
llvm/test/Transforms/InstCombine/select.ll | 188 +++++-------------
2 files changed, 193 insertions(+), 135 deletions(-)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
index 527037881edb19..b2de89f7593fd9 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
@@ -1672,6 +1672,143 @@ static Value *foldSelectInstWithICmpConst(SelectInst &SI, ICmpInst *ICI,
return nullptr;
}
+static Instruction *foldSelectICmpEq(SelectInst &SI, ICmpInst *ICI,
+ InstCombinerImpl &IC) {
+ ICmpInst::Predicate Pred = ICI->getPredicate();
+ if (!ICmpInst::isEquality(Pred))
+ return nullptr;
+
+ Value *TrueVal = SI.getTrueValue();
+ Value *FalseVal = SI.getFalseValue();
+ Value *CmpLHS = ICI->getOperand(0);
+ Value *CmpRHS = ICI->getOperand(1);
+
+ if (Pred == ICmpInst::ICMP_NE) {
+ Pred = ICmpInst::ICMP_EQ;
+ std::swap(TrueVal, FalseVal);
+ }
+
+ // Transform (X == C) ? X : Y -> (X == C) ? C : Y
+ // specific handling for Bitwise operation.
+ // https://alive2.llvm.org/ce/z/mW3eYR
+ // x&y -> (x|y) ^ (x^y) or (x|y) & ~(x^y)
+ // x|y -> (x&y) | (x^y) or (x&y) ^ (x^y)
+ // x^y -> (x|y) ^ (x&y) or (x|y) & ~(x&y)
+ Value *X, *Y;
+ if (!(match(CmpLHS, m_BitwiseLogic(m_Value(X), m_Value(Y)))) ||
+ !(match(TrueVal, m_BitwiseLogic(m_Specific(X), m_Specific(Y)))))
+ return nullptr;
+
+ Value *AllOnes = Constant::getAllOnesValue(TrueVal->getType());
+ Value *Null = Constant::getNullValue(TrueVal->getType());
+ Instruction *ISI = &cast<Instruction>(SI);
+ const unsigned AndOps = Instruction::And, OrOps = Instruction::Or,
+ XorOps = Instruction::Xor, NoOps = 0;
+ enum NotMask { None = 0, NotInner, NotRHS };
+
+ auto matchFalseVal = [&](Value *FalseVal, Value *CmpRHS, Value *X, Value *Y,
+ unsigned OuterOpc, unsigned InnerOpc,
+ unsigned NotMask) {
+ auto matchInner = m_c_BinOp(InnerOpc, m_Specific(X), m_Specific(Y));
+ if (OuterOpc == NoOps) {
+ if (match(CmpRHS, m_Zero()))
+ return match(FalseVal, matchInner);
+ else
+ return false;
+ }
+
+ if (NotMask == NotInner) {
+ return match(FalseVal,
+ m_c_BinOp(OuterOpc, m_Not(matchInner), m_Specific(CmpRHS)));
+ } else if (NotMask == NotRHS) {
+ return match(FalseVal,
+ m_c_BinOp(OuterOpc, matchInner, m_Not(m_Specific(CmpRHS))));
+ } else {
+ return match(FalseVal,
+ m_c_BinOp(OuterOpc, matchInner, m_Specific(CmpRHS)));
+ }
+ };
+
+ // https://alive2.llvm.org/ce/z/rw7XWv
+ // (X&Y)==C ? X|Y : X^Y -> (X^Y)|C : X^Y or (X^Y)^ C : X^Y
+ // (X&Y)==C ? X^Y : X|Y -> (X|Y)^C : X|Y or (X|Y)&~C : X|Y
+ if (match(CmpLHS, m_And(m_Value(X), m_Value(Y)))) {
+ if (match(TrueVal, m_c_Or(m_Specific(X), m_Specific(Y)))) {
+ // (X&Y)==0 ? X|Y : X^Y -> (X^Y)|0 : X^Y -> X^Y
+ if (matchFalseVal(FalseVal, CmpRHS, X, Y, NoOps, XorOps, None) ||
+ // (X&Y)==C ? X|Y : (X^Y)|C -> (X^Y)|C : (X^Y)|C -> (X|Y)^C
+ matchFalseVal(FalseVal, CmpRHS, X, Y, OrOps, XorOps, None) ||
+ // (X&Y)==C ? X|Y : (X^Y)^C -> (X^Y)^C : (X^Y)^C -> (X^Y)^C
+ matchFalseVal(FalseVal, CmpRHS, X, Y, XorOps, XorOps, None))
+ return IC.replaceInstUsesWith(*ISI, FalseVal);
+ // (X&Y)==-1 ? X|Y : FV -> -1 : FV
+ else if (match(CmpRHS, m_AllOnes()))
+ return IC.replaceOperand(SI, 1, AllOnes);
+ } else if (match(TrueVal, m_c_Xor(m_Specific(X), m_Specific(Y)))) {
+ // (X&Y)==0 ? X^Y : X|Y -> (X|Y)^0 : X|Y -> X:Y
+ if (matchFalseVal(FalseVal, CmpRHS, X, Y, NoOps, OrOps, None) ||
+ // (X&Y)==C ? X^Y : (X|Y)^ C -> (X|Y)^ C : (X|Y)^ C -> (X|Y)^ C
+ matchFalseVal(FalseVal, CmpRHS, X, Y, XorOps, OrOps, None) ||
+ // (X&Y)==C ? X^Y : (X|Y)&~C -> (X|Y)&~C : (X|Y)&~C -> (X|Y)&~C
+ matchFalseVal(FalseVal, CmpRHS, X, Y, AndOps, OrOps, NotRHS))
+ return IC.replaceInstUsesWith(*ISI, FalseVal);
+ // (X&Y)==-1 ? X^Y : FV -> 0 : FV
+ else if (match(CmpRHS, m_AllOnes()))
+ return IC.replaceOperand(SI, 1, Null);
+ }
+ }
+
+ // https://alive2.llvm.org/ce/z/5yaUzR
+ // (X|Y)==C ? X&Y : X^Y -> (X^Y)^C : X^Y or ~(X^Y)&C : X^Y
+ // (X|Y)==C ? X^Y : X&Y -> (X&Y)^C : X&Y or ~(X&Y)&C : X&Y
+ if (match(CmpLHS, m_Or(m_Value(X), m_Value(Y)))) {
+ if (match(TrueVal, m_c_And(m_Specific(X), m_Specific(Y)))) {
+ // (X|Y)==0 ? X&Y : X^Y -> (X^Y)^0 : X^Y -> X^Y
+ if (matchFalseVal(FalseVal, CmpRHS, X, Y, NoOps, XorOps, None) ||
+ // (X|Y)==C ? X&Y: (X^Y)^C -> (X^Y)^C: (X^Y)^C -> (X^Y)^C
+ matchFalseVal(FalseVal, CmpRHS, X, Y, XorOps, XorOps, None) ||
+ // (X|Y)==C ? X&Y:~(X^Y)&C ->~(X^Y)&C:~(X^Y)&C -> ~(X^Y)&C
+ matchFalseVal(FalseVal, CmpRHS, X, Y, AndOps, XorOps, NotInner))
+ return IC.replaceInstUsesWith(*ISI, FalseVal);
+ } else if (match(TrueVal, m_c_Xor(m_Specific(X), m_Specific(Y)))) {
+ // (X|Y)==0 ? X^Y : X&Y -> (X&Y)^0 : X&Y -> X&Y
+ if (matchFalseVal(FalseVal, CmpRHS, X, Y, NoOps, AndOps, None) ||
+ // (X|Y)==C ? X^Y : (X&Y)^C -> (X&Y)^C : (X&Y)^C -> (X&Y)^C
+ matchFalseVal(FalseVal, CmpRHS, X, Y, XorOps, AndOps, None) ||
+ // (X|Y)==C ? X^Y :~(X&Y)&C -> ~(X&Y)&C :~(X&Y)&C -> ~(X&Y)&C
+ matchFalseVal(FalseVal, CmpRHS, X, Y, AndOps, AndOps, NotInner))
+ return IC.replaceInstUsesWith(*ISI, FalseVal);
+ } else if (match(TrueVal, m_BitwiseLogic(m_Specific(X), m_Specific(Y))) &&
+ match(CmpRHS, m_Zero()))
+ // (X|Y)==0 ? (X BitwiseLogic Y) : FV -> (X|Y)==0 ? 0 : FV
+ return IC.replaceOperand(SI, 1, Null);
+ }
+
+ // https://alive2.llvm.org/ce/z/dA9Hy-
+ // (X^Y)==C ? X&Y : X|Y -> (X|Y)^C : X|Y or (X|Y)&~C : X|Y
+ // (X^Y)==C ? X|Y : X&Y -> (X&Y)|C : X&Y or (X&Y)^ C : X&Y
+ if (match(CmpLHS, m_Xor(m_Value(X), m_Value(Y)))) {
+ if ((match(TrueVal, m_c_And(m_Specific(X), m_Specific(Y))))) {
+ // (X^Y)==C ? X&Y : (X|Y)^C -> (X|Y)^C
+ if (matchFalseVal(FalseVal, CmpRHS, X, Y, XorOps, OrOps, None) ||
+ // (X^Y)==C ? X&Y : (X|Y)&~C -> (X|Y)&~C
+ matchFalseVal(FalseVal, CmpRHS, X, Y, AndOps, OrOps, NotRHS))
+ return IC.replaceInstUsesWith(*ISI, FalseVal);
+ } else if (match(TrueVal, m_c_Or(m_Specific(X), m_Specific(Y)))) {
+ // (X^Y)==C ? (X|Y) : (X&Y)|C -> (X&Y)|C
+ if (matchFalseVal(FalseVal, CmpRHS, X, Y, OrOps, AndOps, None) ||
+ // (X^Y)==C ? (X|Y) : (X&Y)^C -> (X&Y)^C
+ matchFalseVal(FalseVal, CmpRHS, X, Y, XorOps, AndOps, None))
+ return IC.replaceInstUsesWith(*ISI, FalseVal);
+ // (X^Y)==-1 ? (X|Y) : FV -> -1 : FV
+ if (match(CmpRHS, m_AllOnes()))
+ return IC.replaceOperand(SI, 1, AllOnes);
+ }
+ }
+
+ return nullptr;
+}
+
/// Visit a SelectInst that has an ICmpInst as its first operand.
Instruction *InstCombinerImpl::foldSelectInstWithICmp(SelectInst &SI,
ICmpInst *ICI) {
@@ -1714,6 +1851,9 @@ Instruction *InstCombinerImpl::foldSelectInstWithICmp(SelectInst &SI,
}
}
+ if (Instruction *NewSel = foldSelectICmpEq(SI, ICI, *this))
+ return NewSel;
+
// Canonicalize a signbit condition to use zero constant by swapping:
// (CmpLHS > -1) ? TV : FV --> (CmpLHS < 0) ? FV : TV
// To avoid conflicts (infinite loops) with other canonicalizations, this is
diff --git a/llvm/test/Transforms/InstCombine/select.ll b/llvm/test/Transforms/InstCombine/select.ll
index 0a6e89ddd2e56d..0ac9eddf051550 100644
--- a/llvm/test/Transforms/InstCombine/select.ll
+++ b/llvm/test/Transforms/InstCombine/select.ll
@@ -3665,12 +3665,8 @@ exit:
define i32 @src_and_eq_0_or_xor(i32 %x, i32 %y) {
; CHECK-LABEL: @src_and_eq_0_or_xor(
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y:%.*]], [[X:%.*]]
-; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[AND]], 0
-; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y]], [[X]]
-; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[Y]], [[X]]
-; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[OR]], i32 [[XOR]]
-; CHECK-NEXT: ret i32 [[COND]]
+; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT: ret i32 [[XOR]]
;
entry:
%and = and i32 %y, %x
@@ -3684,12 +3680,8 @@ entry:
define i32 @src_and_eq_0_xor_or(i32 %x, i32 %y) {
; CHECK-LABEL: @src_and_eq_0_xor_or(
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y:%.*]], [[X:%.*]]
-; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[AND]], 0
-; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[Y]], [[X]]
-; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y]], [[X]]
-; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[XOR]], i32 [[OR]]
-; CHECK-NEXT: ret i32 [[COND]]
+; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT: ret i32 [[OR]]
;
entry:
%and = and i32 %y, %x
@@ -3705,9 +3697,8 @@ define i32 @src_and_eq_neg1_or_xor(i32 %x, i32 %y) {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y:%.*]], [[X:%.*]]
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[AND]], -1
-; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y]], [[X]]
; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[Y]], [[X]]
-; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[OR]], i32 [[XOR]]
+; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 -1, i32 [[XOR]]
; CHECK-NEXT: ret i32 [[COND]]
;
entry:
@@ -3724,9 +3715,8 @@ define i32 @src_and_eq_neg1_xor_or(i32 %x, i32 %y) {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y:%.*]], [[X:%.*]]
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[AND]], -1
-; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[Y]], [[X]]
; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y]], [[X]]
-; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[XOR]], i32 [[OR]]
+; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 0, i32 [[OR]]
; CHECK-NEXT: ret i32 [[COND]]
;
entry:
@@ -3741,13 +3731,9 @@ entry:
define i32 @src_and_eq_C_or_xororC(i32 %x, i32 %y, i32 %c) {
; CHECK-LABEL: @src_and_eq_C_or_xororC(
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y:%.*]], [[X:%.*]]
-; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[AND]], [[C:%.*]]
-; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y]], [[X]]
-; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[Y]], [[X]]
-; CHECK-NEXT: [[OR1:%.*]] = or i32 [[XOR]], [[C]]
-; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[OR]], i32 [[OR1]]
-; CHECK-NEXT: ret i32 [[COND]]
+; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT: [[OR1:%.*]] = or i32 [[XOR]], [[C:%.*]]
+; CHECK-NEXT: ret i32 [[OR1]]
;
entry:
%and = and i32 %y, %x
@@ -3762,13 +3748,9 @@ entry:
define i32 @src_and_eq_C_or_xorxorC(i32 %x, i32 %y, i32 %c) {
; CHECK-LABEL: @src_and_eq_C_or_xorxorC(
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y:%.*]], [[X:%.*]]
-; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[AND]], [[C:%.*]]
-; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y]], [[X]]
-; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[Y]], [[X]]
-; CHECK-NEXT: [[XOR1:%.*]] = xor i32 [[XOR]], [[C]]
-; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[OR]], i32 [[XOR1]]
-; CHECK-NEXT: ret i32 [[COND]]
+; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT: [[XOR1:%.*]] = xor i32 [[XOR]], [[C:%.*]]
+; CHECK-NEXT: ret i32 [[XOR1]]
;
entry:
%and = and i32 %y, %x
@@ -3783,14 +3765,10 @@ entry:
define i32 @src_and_eq_C_xor_OrAndNotC(i32 %x, i32 %y, i32 %c) {
; CHECK-LABEL: @src_and_eq_C_xor_OrAndNotC(
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y:%.*]], [[X:%.*]]
-; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[AND]], [[C:%.*]]
-; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[Y]], [[X]]
-; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y]], [[X]]
-; CHECK-NEXT: [[NOT:%.*]] = xor i32 [[C]], -1
+; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT: [[NOT:%.*]] = xor i32 [[C:%.*]], -1
; CHECK-NEXT: [[AND1:%.*]] = and i32 [[OR]], [[NOT]]
-; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[XOR]], i32 [[AND1]]
-; CHECK-NEXT: ret i32 [[COND]]
+; CHECK-NEXT: ret i32 [[AND1]]
;
entry:
%and = and i32 %y, %x
@@ -3806,13 +3784,9 @@ entry:
define i32 @src_and_eq_C_xor_orxorC(i32 %x, i32 %y, i32 %c) {
; CHECK-LABEL: @src_and_eq_C_xor_orxorC(
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y:%.*]], [[X:%.*]]
-; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[AND]], [[C:%.*]]
-; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[Y]], [[X]]
-; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y]], [[X]]
-; CHECK-NEXT: [[XOR1:%.*]] = xor i32 [[OR]], [[C]]
-; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[XOR]], i32 [[XOR1]]
-; CHECK-NEXT: ret i32 [[COND]]
+; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT: [[XOR1:%.*]] = xor i32 [[OR]], [[C:%.*]]
+; CHECK-NEXT: ret i32 [[XOR1]]
;
entry:
%and = and i32 %y, %x
@@ -3829,12 +3803,8 @@ entry:
define i32 @src_or_eq_0_and_xor(i32 %x, i32 %y) {
; CHECK-LABEL: @src_or_eq_0_and_xor(
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y:%.*]], [[X:%.*]]
-; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[OR]], 0
-; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y]], [[X]]
-; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[Y]], [[X]]
-; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[AND]], i32 [[XOR]]
-; CHECK-NEXT: ret i32 [[COND]]
+; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT: ret i32 [[XOR]]
;
entry:
%or = or i32 %y, %x
@@ -3848,12 +3818,8 @@ entry:
define i32 @src_or_eq_0_xor_and(i32 %x, i32 %y) {
; CHECK-LABEL: @src_or_eq_0_xor_and(
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y:%.*]], [[X:%.*]]
-; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[OR]], 0
-; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[Y]], [[X]]
-; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y]], [[X]]
-; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[XOR]], i32 [[AND]]
-; CHECK-NEXT: ret i32 [[COND]]
+; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT: ret i32 [[AND]]
;
entry:
%or = or i32 %y, %x
@@ -3867,13 +3833,9 @@ entry:
define i32 @src_or_eq_neg1_and_xor(i32 %x, i32 %y) {
; CHECK-LABEL: @src_or_eq_neg1_and_xor(
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y:%.*]], [[X:%.*]]
-; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[OR]], -1
-; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y]], [[X]]
-; CHECK-NEXT: [[TMP0:%.*]] = xor i32 [[X]], [[Y]]
+; CHECK-NEXT: [[TMP0:%.*]] = xor i32 [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: [[NOT:%.*]] = xor i32 [[TMP0]], -1
-; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[AND]], i32 [[NOT]]
-; CHECK-NEXT: ret i32 [[COND]]
+; CHECK-NEXT: ret i32 [[NOT]]
;
entry:
%or = or i32 %y, %x
@@ -3888,13 +3850,9 @@ entry:
define i32 @src_or_eq_neg1_xor_and(i32 %x, i32 %y) {
; CHECK-LABEL: @src_or_eq_neg1_xor_and(
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y:%.*]], [[X:%.*]]
-; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[OR]], -1
-; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[Y]], [[X]]
-; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y]], [[X]]
+; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y:%.*]], [[X:%.*]]
; CHECK-NEXT: [[NOT:%.*]] = xor i32 [[AND]], -1
-; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[XOR]], i32 [[NOT]]
-; CHECK-NEXT: ret i32 [[COND]]
+; CHECK-NEXT: ret i32 [[NOT]]
;
entry:
%or = or i32 %y, %x
@@ -3909,13 +3867,9 @@ entry:
define i32 @src_or_eq_C_and_xorC(i32 %x, i32 %y, i32 %c) {
; CHECK-LABEL: @src_or_eq_C_and_xorC(
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y:%.*]], [[X:%.*]]
-; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[OR]], [[C:%.*]]
-; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y]], [[X]]
-; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[Y]], [[X]]
-; CHECK-NEXT: [[XOR1:%.*]] = xor i32 [[XOR]], [[C]]
-; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[AND]], i32 [[XOR1]]
-; CHECK-NEXT: ret i32 [[COND]]
+; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT: [[XOR1:%.*]] = xor i32 [[XOR]], [[C:%.*]]
+; CHECK-NEXT: ret i32 [[XOR1]]
;
entry:
%or = or i32 %y, %x
@@ -3930,14 +3884,10 @@ entry:
define i32 @src_or_eq_C_and_andnotxorC(i32 %x, i32 %y, i32 %c) {
; CHECK-LABEL: @src_or_eq_C_and_andnotxorC(
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y:%.*]], [[X:%.*]]
-; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[OR]], [[C:%.*]]
-; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y]], [[X]]
-; CHECK-NEXT: [[TMP0:%.*]] = xor i32 [[X]], [[Y]]
+; CHECK-NEXT: [[TMP0:%.*]] = xor i32 [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: [[NOT:%.*]] = xor i32 [[TMP0]], -1
-; CHECK-NEXT: [[AND1:%.*]] = and i32 [[NOT]], [[C]]
-; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[AND]], i32 [[AND1]]
-; CHECK-NEXT: ret i32 [[COND]]
+; CHECK-NEXT: [[AND1:%.*]] = and i32 [[NOT]], [[C:%.*]]
+; CHECK-NEXT: ret i32 [[AND1]]
;
entry:
%or = or i32 %y, %x
@@ -3953,13 +3903,9 @@ entry:
define i32 @src_or_eq_C_xor_xorandC(i32 %x, i32 %y, i32 %c) {
; CHECK-LABEL: @src_or_eq_C_xor_xorandC(
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y:%.*]], [[X:%.*]]
-; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[OR]], [[C:%.*]]
-; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[Y]], [[X]]
-; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y]], [[X]]
-; CHECK-NEXT: [[XOR1:%.*]] = xor i32 [[AND]], [[C]]
-; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[XOR]], i32 [[XOR1]]
-; CHECK-NEXT: ret i32 [[COND]]
+; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT: [[XOR1:%.*]] = xor i32 [[AND]], [[C:%.*]]
+; CHECK-NEXT: ret i32 [[XOR1]]
;
entry:
%or = or i32 %y, %x
@@ -3974,14 +3920,10 @@ entry:
define i32 @src_or_eq_C_xor_andnotandC(i32 %x, i32 %y, i32 %c) {
; CHECK-LABEL: @src_or_eq_C_xor_andnotandC(
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y:%.*]], [[X:%.*]]
-; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[OR]], [[C:%.*]]
-; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[Y]], [[X]]
-; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y]], [[X]]
+; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y:%.*]], [[X:%.*]]
; CHECK-NEXT: [[NOT:%.*]] = xor i32 [[AND]], -1
-; CHECK-NEXT: [[AND1:%.*]] = and i32 [[NOT]], [[C]]
-; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[XOR]], i32 [[AND1]]
-; CHECK-NEXT: ret i32 [[COND]]
+; CHECK-NEXT: [[AND1:%.*]] = and i32 [[NOT]], [[C:%.*]]
+; CHECK-NEXT: ret i32 [[AND1]]
;
entry:
%or = or i32 %y, %x
@@ -3999,13 +3941,9 @@ entry:
define i32 @src_xor_eq_neg1_and(i32 %x, i32 %y) {
; CHECK-LABEL: @src_xor_eq_neg1_and(
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[Y:%.*]], [[X:%.*]]
-; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[XOR]], -1
-; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y]], [[X]]
-; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y]], [[X]]
+; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y:%.*]], [[X:%.*]]
; CHECK-NEXT: [[NOT:%.*]] = xor i32 [[OR]], -1
-; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[AND]], i32 [[NOT]]
-; CHECK-NEXT: ret i32 [[COND]]
+; CHECK-NEXT: ret i32 [[NOT]]
;
entry:
%xor = xor i32 %y, %x
@@ -4020,11 +3958,7 @@ entry:
define i32 @src_xor_eq_neg1_or(i32 %x, i32 %y) {
; CHECK-LABEL: @src_xor_eq_neg1_or(
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[Y:%.*]], [[X:%.*]]
-; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[XOR]], -1
-; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y]], [[X]]
-; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[OR]], i32 -1
-; CHECK-NEXT: ret i32 [[COND]]
+; CHECK-NEXT: ret i32 -1
;
entry:
%xor = xor i32 %y, %x
@@ -4037,13 +3971,9 @@ entry:
define i32 @src_xor_eq_C_and_xororC(i32 %x, i32 %y, i32 %c) {
; CHECK-LABEL: @src_xor_eq_C_and_xororC(
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[Y:%.*]], [[X:%.*]]
-; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[XOR]], [[C:%.*]]
-; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y]], [[X]]
-; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y]], [[X]]
-; CHECK-NEXT: [[XOR1:%.*]] = xor i32 [[OR]], [[C]]
-; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[AND]], i32 [[XOR1]]
-; CHECK-NEXT: ret i32 [[COND]]
+; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT: [[XOR1:%.*]] = xor i32 [[OR]], [[C:%.*]]
+; CHECK-NEXT: ret i32 [[XOR1]]
;
entry:
%xor = xor i32 %y, %x
@@ -4058,14 +3988,10 @@ entry:
define i32 @src_xor_eq_C_and_andornotC(i32 %x, i32 %y, i32 %c) {
; CHECK-LABEL: @src_xor_eq_C_and_andornotC(
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[Y:%.*]], [[X:%.*]]
-; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[XOR]], [[C:%.*]]
-; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y]], [[X]]
-; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y]], [[X]]
-; CHECK-NEXT: [[NOT:%.*]] = xor i32 [[C]], -1
+; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT: [[NOT:%.*]] = xor i32 [[C:%.*]], -1
; CHECK-NEXT: [[AND1:%.*]] = and i32 [[OR]], [[NOT]]
-; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[AND]], i32 [[AND1]]
-; CHECK-NEXT: ret i32 [[COND]]
+; CHECK-NEXT: ret i32 [[AND1]]
;
entry:
%xor = xor i32 %y, %x
@@ -4081,13 +4007,9 @@ entry:
define i32 @src_xor_eq_C_or_xorandC(i32 %x, i32 %y, i32 %c) {
; CHECK-LABEL: @src_xor_eq_C_or_xorandC(
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[Y:%.*]], [[X:%.*]]
-; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[XOR]], [[C:%.*]]
-; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y]], [[X]]
-; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y]], [[X]]
-; CHECK-NEXT: [[XOR1:%.*]] = xor i32 [[AND]], [[C]]
-; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[OR]], i32 [[XOR1]]
-; CHECK-NEXT: ret i32 [[COND]]
+; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT: [[XOR1:%.*]] = xor i32 [[AND]], [[C:%.*]]
+; CHECK-NEXT: ret i32 [[XOR1]]
;
entry:
%xor = xor i32 %y, %x
@@ -4102,13 +4024,9 @@ entry:
define i32 @src_xor_eq_C_or_orandC(i32 %x, i32 %y, i32 %c) {
; CHECK-LABEL: @src_xor_eq_C_or_orandC(
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[Y:%.*]], [[X:%.*]]
-; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[XOR]], [[C:%.*]]
-; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y]], [[X]]
-; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y]], [[X]]
-; CHECK-NEXT: [[OR1:%.*]] = or i32 [[AND]], [[C]]
-; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[OR]], i32 [[OR1]]
-; CHECK-NEXT: ret i32 [[COND]]
+; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT: [[OR1:%.*]] = or i32 [[AND]], [[C:%.*]]
+; CHECK-NEXT: ret i32 [[OR1]]
;
entry:
%xor = xor i32 %y, %x
More information about the llvm-commits
mailing list