[llvm] [InstCombine] Try optimizing with knownbits which determined from Cond (PR #91762)

via llvm-commits llvm-commits at lists.llvm.org
Thu May 16 12:40:57 PDT 2024


https://github.com/ParkHanbum updated https://github.com/llvm/llvm-project/pull/91762

>From 15e9bf0023047111266978729db0bc6bbe43ea19 Mon Sep 17 00:00:00 2001
From: hanbeom <kese111 at gmail.com>
Date: Tue, 7 May 2024 06:00:04 +0900
Subject: [PATCH 1/4] [NFC] [InstCombine] Modify and Added tests for
 select-of-bittest

Tests that begin with n in select-of-bittest are negative tests.
However, n5 test is different from the intent of the test because
bits in %t and %t2 are the same. This is probably a mistake,
so corrected it.

Also added tests for cases where the and/or/xor might be optimized
if it is placed in the cond and truval of selectInst.

proof : https://alive2.llvm.org/ce/z/KJbbbp
---
 .../InstCombine/select-of-bittest.ll          | 439 +++++++++++++++++-
 llvm/test/Transforms/InstCombine/select.ll    | 379 +++++++++++----
 2 files changed, 722 insertions(+), 96 deletions(-)

diff --git a/llvm/test/Transforms/InstCombine/select-of-bittest.ll b/llvm/test/Transforms/InstCombine/select-of-bittest.ll
index e3eb76de459e2..46c1a183f3ede 100644
--- a/llvm/test/Transforms/InstCombine/select-of-bittest.ll
+++ b/llvm/test/Transforms/InstCombine/select-of-bittest.ll
@@ -3,7 +3,440 @@
 
 ; https://bugs.llvm.org/show_bug.cgi?id=36950
 
-; These all should be just and+icmp, there should be no select.
+; ====================== AND =======================
+define i8 @src_and_bit(i8 %x, i8 %y) {
+; CHECK-LABEL: @src_and_bit(
+; CHECK-NEXT:    [[AND:%.*]] = and i8 [[X:%.*]], 3
+; CHECK-NEXT:    [[AND1:%.*]] = and i8 [[X]], 2
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i8 [[AND]], 2
+; CHECK-NEXT:    [[COND:%.*]] = select i1 [[CMP]], i8 [[AND1]], i8 1
+; CHECK-NEXT:    ret i8 [[COND]]
+;
+  %and = and i8 %x, 3
+  %and1 = and i8 %x, 2
+  %and2 = and i8 %and, %x
+  %cmp = icmp eq i8 %and2, 2
+  %cond = select i1 %cmp, i8 %and1, i8 1
+  ret i8 %cond
+}
+
+define <2 x i8> @src_and_bit_vec(<2 x i8> %x, <2 x i8> %y) {
+; CHECK-LABEL: @src_and_bit_vec(
+; CHECK-NEXT:    [[AND:%.*]] = and <2 x i8> [[X:%.*]], <i8 3, i8 3>
+; CHECK-NEXT:    [[AND1:%.*]] = and <2 x i8> [[X]], <i8 2, i8 2>
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq <2 x i8> [[AND]], <i8 2, i8 2>
+; CHECK-NEXT:    [[COND:%.*]] = select <2 x i1> [[CMP]], <2 x i8> [[AND1]], <2 x i8> <i8 1, i8 1>
+; CHECK-NEXT:    ret <2 x i8> [[COND]]
+;
+  %and = and <2 x i8> %x, <i8 3, i8 3>
+  %and1 = and <2 x i8> %x, <i8 2, i8 2>
+  %and2 = and <2 x i8> %and, %x
+  %cmp = icmp eq <2 x i8> %and2, <i8 2, i8 2>
+  %cond = select <2 x i1> %cmp, <2 x i8> %and1, <2 x i8><i8 1, i8 1>
+  ret <2 x i8> %cond
+}
+
+define <2 x i8> @src_and_bit_vec_poison(<2 x i8> %x, <2 x i8> %y) {
+; CHECK-LABEL: @src_and_bit_vec_poison(
+; CHECK-NEXT:    [[AND:%.*]] = and <2 x i8> [[X:%.*]], <i8 poison, i8 3>
+; CHECK-NEXT:    [[AND1:%.*]] = and <2 x i8> [[X]], <i8 poison, i8 2>
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq <2 x i8> [[AND]], <i8 2, i8 2>
+; CHECK-NEXT:    [[COND:%.*]] = select <2 x i1> [[CMP]], <2 x i8> [[AND1]], <2 x i8> <i8 1, i8 1>
+; CHECK-NEXT:    ret <2 x i8> [[COND]]
+;
+  %and = and <2 x i8> %x, <i8 poison, i8 3>
+  %and1 = and <2 x i8> %x, <i8 poison, i8 2>
+  %and2 = and <2 x i8> %and, %x
+  %cmp = icmp eq <2 x i8> %and2, <i8 2, i8 2>
+  %cond = select <2 x i1> %cmp, <2 x i8> %and1, <2 x i8><i8 1, i8 1>
+  ret <2 x i8> %cond
+}
+
+define <2 x i8> @src_and_bit_vec_poison2(<2 x i8> %x, <2 x i8> %y) {
+; CHECK-LABEL: @src_and_bit_vec_poison2(
+; CHECK-NEXT:    [[AND:%.*]] = and <2 x i8> [[X:%.*]], <i8 poison, i8 3>
+; CHECK-NEXT:    [[AND1:%.*]] = and <2 x i8> [[X]], <i8 poison, i8 2>
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq <2 x i8> [[AND]], <i8 2, i8 2>
+; CHECK-NEXT:    [[COND:%.*]] = select <2 x i1> [[CMP]], <2 x i8> [[AND1]], <2 x i8> <i8 1, i8 1>
+; CHECK-NEXT:    ret <2 x i8> [[COND]]
+;
+  %and = and <2 x i8> %x, <i8 poison, i8 3>
+  %and1 = and <2 x i8> %x, <i8 poison, i8 2>
+  %and2 = and <2 x i8> %and, %x
+  %cmp = icmp eq <2 x i8> %and2, <i8 2, i8 2>
+  %cond = select <2 x i1> %cmp, <2 x i8> %and1, <2 x i8><i8 1, i8 1>
+  ret <2 x i8> %cond
+}
+
+define i8 @src_and_bit_ne(i8 %x, i8 %y) {
+; CHECK-LABEL: @src_and_bit_ne(
+; CHECK-NEXT:    [[AND:%.*]] = and i8 [[X:%.*]], 3
+; CHECK-NEXT:    [[AND1:%.*]] = and i8 [[X]], 2
+; CHECK-NEXT:    [[CMP_NOT:%.*]] = icmp eq i8 [[AND]], 2
+; CHECK-NEXT:    [[COND:%.*]] = select i1 [[CMP_NOT]], i8 [[AND1]], i8 1
+; CHECK-NEXT:    ret i8 [[COND]]
+;
+  %and = and i8 %x, 3
+  %and1 = and i8 %x, 2
+  %and2 = and i8 %and, %x
+  %cmp = icmp ne i8 %and2, 2
+  %cond = select i1 %cmp, i8 1, i8 %and1
+  ret i8 %cond
+}
+
+define <2 x i8> @src_and_bit_vec_ne(<2 x i8> %x, <2 x i8> %y) {
+; CHECK-LABEL: @src_and_bit_vec_ne(
+; CHECK-NEXT:    [[AND:%.*]] = and <2 x i8> [[X:%.*]], <i8 3, i8 3>
+; CHECK-NEXT:    [[AND1:%.*]] = and <2 x i8> [[X]], <i8 2, i8 2>
+; CHECK-NEXT:    [[CMP_NOT:%.*]] = icmp eq <2 x i8> [[AND]], <i8 2, i8 2>
+; CHECK-NEXT:    [[COND:%.*]] = select <2 x i1> [[CMP_NOT]], <2 x i8> [[AND1]], <2 x i8> <i8 1, i8 1>
+; CHECK-NEXT:    ret <2 x i8> [[COND]]
+;
+  %and = and <2 x i8> %x, <i8 3, i8 3>
+  %and1 = and <2 x i8> %x, <i8 2, i8 2>
+  %and2 = and <2 x i8> %and, %x
+  %cmp = icmp ne <2 x i8> %and2, <i8 2, i8 2>
+  %cond = select <2 x i1> %cmp, <2 x i8><i8 1, i8 1>, <2 x i8> %and1
+  ret <2 x i8> %cond
+}
+
+define <2 x i8> @src_and_bit_vec_poison_ne(<2 x i8> %x, <2 x i8> %y) {
+; CHECK-LABEL: @src_and_bit_vec_poison_ne(
+; CHECK-NEXT:    [[AND:%.*]] = and <2 x i8> [[X:%.*]], <i8 poison, i8 3>
+; CHECK-NEXT:    [[AND1:%.*]] = and <2 x i8> [[X]], <i8 poison, i8 2>
+; CHECK-NEXT:    [[CMP_NOT:%.*]] = icmp eq <2 x i8> [[AND]], <i8 2, i8 2>
+; CHECK-NEXT:    [[COND:%.*]] = select <2 x i1> [[CMP_NOT]], <2 x i8> [[AND1]], <2 x i8> <i8 1, i8 1>
+; CHECK-NEXT:    ret <2 x i8> [[COND]]
+;
+  %and = and <2 x i8> %x, <i8 poison, i8 3>
+  %and1 = and <2 x i8> %x, <i8 poison, i8 2>
+  %and2 = and <2 x i8> %and, %x
+  %cmp = icmp ne <2 x i8> %and2, <i8 2, i8 2>
+  %cond = select <2 x i1> %cmp, <2 x i8><i8 1, i8 1>, <2 x i8> %and1
+  ret <2 x i8> %cond
+}
+
+define <2 x i8> @src_and_bit_vec_poison2_ne(<2 x i8> %x, <2 x i8> %y) {
+; CHECK-LABEL: @src_and_bit_vec_poison2_ne(
+; CHECK-NEXT:    [[AND:%.*]] = and <2 x i8> [[X:%.*]], <i8 poison, i8 3>
+; CHECK-NEXT:    [[AND1:%.*]] = and <2 x i8> [[X]], <i8 poison, i8 2>
+; CHECK-NEXT:    [[CMP_NOT:%.*]] = icmp eq <2 x i8> [[AND]], <i8 2, i8 2>
+; CHECK-NEXT:    [[COND:%.*]] = select <2 x i1> [[CMP_NOT]], <2 x i8> [[AND1]], <2 x i8> <i8 1, i8 1>
+; CHECK-NEXT:    ret <2 x i8> [[COND]]
+;
+  %and = and <2 x i8> %x, <i8 poison, i8 3>
+  %and1 = and <2 x i8> %x, <i8 poison, i8 2>
+  %and2 = and <2 x i8> %and, %x
+  %cmp = icmp ne <2 x i8> %and2, <i8 2, i8 2>
+  %cond = select <2 x i1> %cmp, <2 x i8><i8 1, i8 1>, <2 x i8> %and1
+  ret <2 x i8> %cond
+}
+
+; ====================== OR =======================
+define i8 @src_or_bit(i8 %x, i8 %y, i8 %z) {
+; CHECK-LABEL: @src_or_bit(
+; CHECK-NEXT:    [[AND:%.*]] = and i8 [[Z:%.*]], 3
+; CHECK-NEXT:    [[AND1:%.*]] = shl i8 [[Y:%.*]], 2
+; CHECK-NEXT:    [[SHL:%.*]] = and i8 [[AND1]], 12
+; CHECK-NEXT:    [[OR:%.*]] = or i8 [[SHL]], [[X:%.*]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i8 [[OR]], 3
+; CHECK-NEXT:    [[OR2:%.*]] = or i8 [[AND]], [[X]]
+; CHECK-NEXT:    [[COND:%.*]] = select i1 [[CMP]], i8 [[OR2]], i8 1
+; CHECK-NEXT:    ret i8 [[COND]]
+;
+  %and = and i8 %z, 3
+  %and1 = shl i8 %y, 2
+  %shl = and i8 %and1, 12
+  %or = or i8 %shl, %x
+  %cmp = icmp eq i8 %or, 3
+  %or2 = or i8 %and, %x
+  %cond = select i1 %cmp, i8 %or2, i8 1
+  ret i8 %cond
+}
+
+define <2 x i8> @src_or_bit_vec(<2 x i8> %x, <2 x i8> %y, <2 x i8> %z) {
+; CHECK-LABEL: @src_or_bit_vec(
+; CHECK-NEXT:    [[AND:%.*]] = and <2 x i8> [[Z:%.*]], <i8 3, i8 3>
+; CHECK-NEXT:    [[AND1:%.*]] = shl <2 x i8> [[Y:%.*]], <i8 2, i8 2>
+; CHECK-NEXT:    [[SHL:%.*]] = and <2 x i8> [[AND1]], <i8 12, i8 12>
+; CHECK-NEXT:    [[OR:%.*]] = or <2 x i8> [[SHL]], [[X:%.*]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq <2 x i8> [[OR]], <i8 3, i8 3>
+; CHECK-NEXT:    [[OR2:%.*]] = or <2 x i8> [[AND]], [[X]]
+; CHECK-NEXT:    [[COND:%.*]] = select <2 x i1> [[CMP]], <2 x i8> [[OR2]], <2 x i8> <i8 1, i8 1>
+; CHECK-NEXT:    ret <2 x i8> [[COND]]
+;
+  %and = and <2 x i8> %z, <i8 3, i8 3>
+  %and1 = shl <2 x i8> %y, <i8 2, i8 2>
+  %shl = and <2 x i8> %and1, <i8 12, i8 12>
+  %or = or <2 x i8> %shl, %x
+  %cmp = icmp eq <2 x i8> %or, <i8 3, i8 3>
+  %or2 = or <2 x i8> %and, %x
+  %cond = select <2x i1> %cmp, <2 x i8> %or2, <2 x i8> <i8 1, i8 1>
+  ret <2 x i8> %cond
+}
+
+define <2 x i8> @src_or_bit_vec_poison(<2 x i8> %x, <2 x i8> %y, <2 x i8> %z) {
+; CHECK-LABEL: @src_or_bit_vec_poison(
+; CHECK-NEXT:    [[AND:%.*]] = and <2 x i8> [[Z:%.*]], <i8 3, i8 poison>
+; CHECK-NEXT:    [[AND1:%.*]] = shl <2 x i8> [[Y:%.*]], <i8 2, i8 poison>
+; CHECK-NEXT:    [[SHL:%.*]] = and <2 x i8> [[AND1]], <i8 12, i8 poison>
+; CHECK-NEXT:    [[OR:%.*]] = or <2 x i8> [[SHL]], [[X:%.*]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq <2 x i8> [[OR]], <i8 3, i8 3>
+; CHECK-NEXT:    [[OR2:%.*]] = or <2 x i8> [[AND]], [[X]]
+; CHECK-NEXT:    [[COND:%.*]] = select <2 x i1> [[CMP]], <2 x i8> [[OR2]], <2 x i8> <i8 1, i8 1>
+; CHECK-NEXT:    ret <2 x i8> [[COND]]
+;
+  %and = and <2 x i8> %z, <i8 3, i8 poison>
+  %and1 = shl <2 x i8> %y, <i8 2, i8 poison>
+  %shl = and <2 x i8> %and1, <i8 12, i8 poison>
+  %or = or <2 x i8> %shl, %x
+  %cmp = icmp eq <2 x i8> %or, <i8 3, i8 3>
+  %or2 = or <2 x i8> %and, %x
+  %cond = select <2 x i1> %cmp, <2 x i8> %or2, <2 x i8> <i8 1, i8 1>
+  ret <2 x i8> %cond
+}
+
+define <2 x i8> @src_or_bit_vec_poison2(<2 x i8> %x, <2 x i8> %y, <2 x i8> %z) {
+; CHECK-LABEL: @src_or_bit_vec_poison2(
+; CHECK-NEXT:    [[AND:%.*]] = and <2 x i8> [[Z:%.*]], <i8 poison, i8 3>
+; CHECK-NEXT:    [[AND1:%.*]] = shl <2 x i8> [[Y:%.*]], <i8 poison, i8 2>
+; CHECK-NEXT:    [[SHL:%.*]] = and <2 x i8> [[AND1]], <i8 poison, i8 12>
+; CHECK-NEXT:    [[OR:%.*]] = or <2 x i8> [[SHL]], [[X:%.*]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq <2 x i8> [[OR]], <i8 3, i8 3>
+; CHECK-NEXT:    [[OR2:%.*]] = or <2 x i8> [[AND]], [[X]]
+; CHECK-NEXT:    [[COND:%.*]] = select <2 x i1> [[CMP]], <2 x i8> [[OR2]], <2 x i8> <i8 1, i8 1>
+; CHECK-NEXT:    ret <2 x i8> [[COND]]
+;
+  %and = and <2 x i8> %z, <i8 poison, i8 3>
+  %and1 = shl <2 x i8> %y, <i8 poison, i8 2>
+  %shl = and <2 x i8> %and1, <i8 poison, i8 12>
+  %or = or <2 x i8> %shl, %x
+  %cmp = icmp eq <2 x i8> %or, <i8 3, i8 3>
+  %or2 = or <2 x i8> %and, %x
+  %cond = select <2 x i1> %cmp, <2 x i8> %or2, <2 x i8> <i8 1, i8 1>
+  ret <2 x i8> %cond
+}
+
+define i8 @src_or_bit_ne(i8 %x, i8 %y, i8 %z) {
+; CHECK-LABEL: @src_or_bit_ne(
+; CHECK-NEXT:    [[AND:%.*]] = and i8 [[Z:%.*]], 3
+; CHECK-NEXT:    [[AND1:%.*]] = shl i8 [[Y:%.*]], 2
+; CHECK-NEXT:    [[SHL:%.*]] = and i8 [[AND1]], 12
+; CHECK-NEXT:    [[OR:%.*]] = or i8 [[SHL]], [[X:%.*]]
+; CHECK-NEXT:    [[CMP_NOT:%.*]] = icmp eq i8 [[OR]], 3
+; CHECK-NEXT:    [[OR2:%.*]] = or i8 [[AND]], [[X]]
+; CHECK-NEXT:    [[COND:%.*]] = select i1 [[CMP_NOT]], i8 [[OR2]], i8 1
+; CHECK-NEXT:    ret i8 [[COND]]
+;
+  %and = and i8 %z, 3
+  %and1 = shl i8 %y, 2
+  %shl = and i8 %and1, 12
+  %or = or i8 %shl, %x
+  %cmp = icmp ne i8 %or, 3
+  %or2 = or i8 %and, %x
+  %cond = select i1 %cmp, i8 1, i8 %or2
+  ret i8 %cond
+}
+
+define <2 x i8> @src_or_bit_vec_ne(<2 x i8> %x, <2 x i8> %y, <2 x i8> %z) {
+; CHECK-LABEL: @src_or_bit_vec_ne(
+; CHECK-NEXT:    [[AND:%.*]] = and <2 x i8> [[Z:%.*]], <i8 3, i8 3>
+; CHECK-NEXT:    [[AND1:%.*]] = shl <2 x i8> [[Y:%.*]], <i8 2, i8 2>
+; CHECK-NEXT:    [[SHL:%.*]] = and <2 x i8> [[AND1]], <i8 12, i8 12>
+; CHECK-NEXT:    [[OR:%.*]] = or <2 x i8> [[SHL]], [[X:%.*]]
+; CHECK-NEXT:    [[CMP_NOT:%.*]] = icmp eq <2 x i8> [[OR]], <i8 3, i8 3>
+; CHECK-NEXT:    [[OR2:%.*]] = or <2 x i8> [[AND]], [[X]]
+; CHECK-NEXT:    [[COND:%.*]] = select <2 x i1> [[CMP_NOT]], <2 x i8> [[OR2]], <2 x i8> <i8 1, i8 1>
+; CHECK-NEXT:    ret <2 x i8> [[COND]]
+;
+  %and = and <2 x i8> %z, <i8 3, i8 3>
+  %and1 = shl <2 x i8> %y, <i8 2, i8 2>
+  %shl = and <2 x i8> %and1, <i8 12, i8 12>
+  %or = or <2 x i8> %shl, %x
+  %cmp = icmp ne <2 x i8> %or, <i8 3, i8 3>
+  %or2 = or <2 x i8> %and, %x
+  %cond = select <2x i1> %cmp, <2 x i8> <i8 1, i8 1>, <2 x i8> %or2
+  ret <2 x i8> %cond
+}
+
+define <2 x i8> @src_or_bit_vec_poison_ne(<2 x i8> %x, <2 x i8> %y, <2 x i8> %z) {
+; CHECK-LABEL: @src_or_bit_vec_poison_ne(
+; CHECK-NEXT:    [[AND:%.*]] = and <2 x i8> [[Z:%.*]], <i8 3, i8 poison>
+; CHECK-NEXT:    [[AND1:%.*]] = shl <2 x i8> [[Y:%.*]], <i8 2, i8 poison>
+; CHECK-NEXT:    [[SHL:%.*]] = and <2 x i8> [[AND1]], <i8 12, i8 poison>
+; CHECK-NEXT:    [[OR:%.*]] = or <2 x i8> [[SHL]], [[X:%.*]]
+; CHECK-NEXT:    [[CMP_NOT:%.*]] = icmp eq <2 x i8> [[OR]], <i8 3, i8 3>
+; CHECK-NEXT:    [[OR2:%.*]] = or <2 x i8> [[AND]], [[X]]
+; CHECK-NEXT:    [[COND:%.*]] = select <2 x i1> [[CMP_NOT]], <2 x i8> [[OR2]], <2 x i8> <i8 1, i8 1>
+; CHECK-NEXT:    ret <2 x i8> [[COND]]
+;
+  %and = and <2 x i8> %z, <i8 3, i8 poison>
+  %and1 = shl <2 x i8> %y, <i8 2, i8 poison>
+  %shl = and <2 x i8> %and1, <i8 12, i8 poison>
+  %or = or <2 x i8> %shl, %x
+  %cmp = icmp ne <2 x i8> %or, <i8 3, i8 3>
+  %or2 = or <2 x i8> %and, %x
+  %cond = select <2 x i1> %cmp, <2 x i8> <i8 1, i8 1>, <2 x i8> %or2
+  ret <2 x i8> %cond
+}
+
+define <2 x i8> @src_or_bit_vec_poison2_ne(<2 x i8> %x, <2 x i8> %y, <2 x i8> %z) {
+; CHECK-LABEL: @src_or_bit_vec_poison2_ne(
+; CHECK-NEXT:    [[AND:%.*]] = and <2 x i8> [[Z:%.*]], <i8 poison, i8 3>
+; CHECK-NEXT:    [[AND1:%.*]] = shl <2 x i8> [[Y:%.*]], <i8 poison, i8 2>
+; CHECK-NEXT:    [[SHL:%.*]] = and <2 x i8> [[AND1]], <i8 poison, i8 12>
+; CHECK-NEXT:    [[OR:%.*]] = or <2 x i8> [[SHL]], [[X:%.*]]
+; CHECK-NEXT:    [[CMP_NOT:%.*]] = icmp eq <2 x i8> [[OR]], <i8 3, i8 3>
+; CHECK-NEXT:    [[OR2:%.*]] = or <2 x i8> [[AND]], [[X]]
+; CHECK-NEXT:    [[COND:%.*]] = select <2 x i1> [[CMP_NOT]], <2 x i8> [[OR2]], <2 x i8> <i8 1, i8 1>
+; CHECK-NEXT:    ret <2 x i8> [[COND]]
+;
+  %and = and <2 x i8> %z, <i8 poison, i8 3>
+  %and1 = shl <2 x i8> %y, <i8 poison, i8 2>
+  %shl = and <2 x i8> %and1, <i8 poison, i8 12>
+  %or = or <2 x i8> %shl, %x
+  %cmp = icmp ne <2 x i8> %or, <i8 3, i8 3>
+  %or2 = or <2 x i8> %and, %x
+  %cond = select <2 x i1> %cmp, <2 x i8> <i8 1, i8 1>, <2 x i8> %or2
+  ret <2 x i8> %cond
+}
+
+; ====================== OR =======================
+define i8 @src_xor_bit(i8 %x, i8 %y) {
+; CHECK-LABEL: @src_xor_bit(
+; CHECK-NEXT:    [[AND:%.*]] = and i8 [[Y:%.*]], 12
+; CHECK-NEXT:    [[XOR:%.*]] = xor i8 [[AND]], [[X:%.*]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i8 [[XOR]], 3
+; CHECK-NEXT:    [[AND1:%.*]] = and i8 [[X]], 3
+; CHECK-NEXT:    [[COND:%.*]] = select i1 [[CMP]], i8 [[AND1]], i8 1
+; CHECK-NEXT:    ret i8 [[COND]]
+;
+  %and = and i8 %y, 12
+  %xor = xor i8 %and, %x
+  %cmp = icmp eq i8 %xor, 3
+  %and1 = and i8 %x, 3
+  %cond = select i1 %cmp, i8 %and1, i8 1
+  ret i8 %cond
+}
+
+define <2 x i8> @src_xor_bit_vec(<2 x i8> %x, <2 x i8> %y) {
+; CHECK-LABEL: @src_xor_bit_vec(
+; CHECK-NEXT:    [[AND:%.*]] = and <2 x i8> [[Y:%.*]], <i8 12, i8 12>
+; CHECK-NEXT:    [[XOR:%.*]] = xor <2 x i8> [[AND]], [[X:%.*]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq <2 x i8> [[XOR]], <i8 3, i8 3>
+; CHECK-NEXT:    [[AND1:%.*]] = and <2 x i8> [[X]], <i8 3, i8 3>
+; CHECK-NEXT:    [[COND:%.*]] = select <2 x i1> [[CMP]], <2 x i8> [[AND1]], <2 x i8> <i8 1, i8 1>
+; CHECK-NEXT:    ret <2 x i8> [[COND]]
+;
+  %and = and <2 x i8> %y, <i8 12, i8 12>
+  %xor = xor <2 x i8> %and, %x
+  %cmp = icmp eq <2 x i8> %xor, <i8 3, i8 3>
+  %and1 = and <2 x i8> %x, <i8 3, i8 3>
+  %cond = select <2 x i1> %cmp, <2 x i8> %and1, <2 x i8> <i8 1, i8 1>
+  ret <2 x i8> %cond
+}
+
+define <2 x i8> @src_xor_bit_vec_poison(<2 x i8> %x, <2 x i8> %y) {
+; CHECK-LABEL: @src_xor_bit_vec_poison(
+; CHECK-NEXT:    [[AND:%.*]] = and <2 x i8> [[Y:%.*]], <i8 poison, i8 12>
+; CHECK-NEXT:    [[XOR:%.*]] = xor <2 x i8> [[AND]], [[X:%.*]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq <2 x i8> [[XOR]], <i8 3, i8 3>
+; CHECK-NEXT:    [[AND1:%.*]] = and <2 x i8> [[X]], <i8 poison, i8 3>
+; CHECK-NEXT:    [[COND:%.*]] = select <2 x i1> [[CMP]], <2 x i8> [[AND1]], <2 x i8> <i8 1, i8 1>
+; CHECK-NEXT:    ret <2 x i8> [[COND]]
+;
+  %and = and <2 x i8> %y, <i8 poison, i8 12>
+  %xor = xor <2 x i8> %and, %x
+  %cmp = icmp eq <2 x i8> %xor, <i8 3, i8 3>
+  %and1 = and <2 x i8> %x, <i8 poison, i8 3>
+  %cond = select <2 x i1> %cmp, <2 x i8> %and1, <2 x i8> <i8 1, i8 1>
+  ret <2 x i8> %cond
+}
+
+define <2 x i8> @src_xor_bit_vec_poison2(<2 x i8> %x, <2 x i8> %y) {
+; CHECK-LABEL: @src_xor_bit_vec_poison2(
+; CHECK-NEXT:    [[AND:%.*]] = and <2 x i8> [[Y:%.*]], <i8 poison, i8 12>
+; CHECK-NEXT:    [[XOR:%.*]] = xor <2 x i8> [[AND]], [[X:%.*]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq <2 x i8> [[XOR]], <i8 3, i8 3>
+; CHECK-NEXT:    [[AND1:%.*]] = and <2 x i8> [[X]], <i8 3, i8 3>
+; CHECK-NEXT:    [[COND:%.*]] = select <2 x i1> [[CMP]], <2 x i8> [[AND1]], <2 x i8> <i8 1, i8 1>
+; CHECK-NEXT:    ret <2 x i8> [[COND]]
+;
+  %and = and <2 x i8> %y, <i8 poison, i8 12>
+  %xor = xor <2 x i8> %and, %x
+  %cmp = icmp eq <2 x i8> %xor, <i8 3, i8 3>
+  %and1 = and <2 x i8> %x, <i8 3, i8 3>
+  %cond = select <2 x i1> %cmp, <2 x i8> %and1, <2 x i8> <i8 1, i8 1>
+  ret <2 x i8> %cond
+}
+
+define i8 @src_xor_bit_ne(i8 %x, i8 %y) {
+; CHECK-LABEL: @src_xor_bit_ne(
+; CHECK-NEXT:    [[AND:%.*]] = and i8 [[Y:%.*]], 12
+; CHECK-NEXT:    [[XOR:%.*]] = xor i8 [[AND]], [[X:%.*]]
+; CHECK-NEXT:    [[CMP_NOT:%.*]] = icmp eq i8 [[XOR]], 3
+; CHECK-NEXT:    [[AND1:%.*]] = and i8 [[X]], 3
+; CHECK-NEXT:    [[COND:%.*]] = select i1 [[CMP_NOT]], i8 [[AND1]], i8 1
+; CHECK-NEXT:    ret i8 [[COND]]
+;
+  %and = and i8 %y, 12
+  %xor = xor i8 %and, %x
+  %cmp = icmp ne i8 %xor, 3
+  %and1 = and i8 %x, 3
+  %cond = select i1 %cmp, i8 1, i8 %and1
+  ret i8 %cond
+}
+
+define <2 x i8> @src_xor_bit_vec_ne(<2 x i8> %x, <2 x i8> %y) {
+; CHECK-LABEL: @src_xor_bit_vec_ne(
+; CHECK-NEXT:    [[AND:%.*]] = and <2 x i8> [[Y:%.*]], <i8 12, i8 12>
+; CHECK-NEXT:    [[XOR:%.*]] = xor <2 x i8> [[AND]], [[X:%.*]]
+; CHECK-NEXT:    [[CMP_NOT:%.*]] = icmp eq <2 x i8> [[XOR]], <i8 3, i8 3>
+; CHECK-NEXT:    [[AND1:%.*]] = and <2 x i8> [[X]], <i8 3, i8 3>
+; CHECK-NEXT:    [[COND:%.*]] = select <2 x i1> [[CMP_NOT]], <2 x i8> [[AND1]], <2 x i8> <i8 1, i8 1>
+; CHECK-NEXT:    ret <2 x i8> [[COND]]
+;
+  %and = and <2 x i8> %y, <i8 12, i8 12>
+  %xor = xor <2 x i8> %and, %x
+  %cmp = icmp ne <2 x i8> %xor, <i8 3, i8 3>
+  %and1 = and <2 x i8> %x, <i8 3, i8 3>
+  %cond = select <2 x i1> %cmp, <2 x i8> <i8 1, i8 1>, <2 x i8> %and1
+  ret <2 x i8> %cond
+}
+
+define <2 x i8> @src_xor_bit_vec_poison_ne(<2 x i8> %x, <2 x i8> %y) {
+; CHECK-LABEL: @src_xor_bit_vec_poison_ne(
+; CHECK-NEXT:    [[AND:%.*]] = and <2 x i8> [[Y:%.*]], <i8 poison, i8 12>
+; CHECK-NEXT:    [[XOR:%.*]] = xor <2 x i8> [[AND]], [[X:%.*]]
+; CHECK-NEXT:    [[CMP_NOT:%.*]] = icmp eq <2 x i8> [[XOR]], <i8 3, i8 3>
+; CHECK-NEXT:    [[AND1:%.*]] = and <2 x i8> [[X]], <i8 poison, i8 3>
+; CHECK-NEXT:    [[COND:%.*]] = select <2 x i1> [[CMP_NOT]], <2 x i8> [[AND1]], <2 x i8> <i8 1, i8 1>
+; CHECK-NEXT:    ret <2 x i8> [[COND]]
+;
+  %and = and <2 x i8> %y, <i8 poison, i8 12>
+  %xor = xor <2 x i8> %and, %x
+  %cmp = icmp ne <2 x i8> %xor, <i8 3, i8 3>
+  %and1 = and <2 x i8> %x, <i8 poison, i8 3>
+  %cond = select <2 x i1> %cmp, <2 x i8> <i8 1, i8 1>, <2 x i8> %and1
+  ret <2 x i8> %cond
+}
+
+define <2 x i8> @src_xor_bit_vec_poison2_ne(<2 x i8> %x, <2 x i8> %y) {
+; CHECK-LABEL: @src_xor_bit_vec_poison2_ne(
+; CHECK-NEXT:    [[AND:%.*]] = and <2 x i8> [[Y:%.*]], <i8 poison, i8 12>
+; CHECK-NEXT:    [[XOR:%.*]] = xor <2 x i8> [[AND]], [[X:%.*]]
+; CHECK-NEXT:    [[CMP_NOT:%.*]] = icmp eq <2 x i8> [[XOR]], <i8 3, i8 3>
+; CHECK-NEXT:    [[AND1:%.*]] = and <2 x i8> [[X]], <i8 3, i8 3>
+; CHECK-NEXT:    [[COND:%.*]] = select <2 x i1> [[CMP_NOT]], <2 x i8> [[AND1]], <2 x i8> <i8 1, i8 1>
+; CHECK-NEXT:    ret <2 x i8> [[COND]]
+;
+  %and = and <2 x i8> %y, <i8 poison, i8 12>
+  %xor = xor <2 x i8> %and, %x
+  %cmp = icmp ne <2 x i8> %xor, <i8 3, i8 3>
+  %and1 = and <2 x i8> %x, <i8 3, i8 3>
+  %cond = select <2 x i1> %cmp, <2 x i8> <i8 1, i8 1>, <2 x i8> %and1
+  ret <2 x i8> %cond
+}
 
 define i32 @and_lshr_and(i32 %arg) {
 ; CHECK-LABEL: @and_lshr_and(
@@ -590,13 +1023,13 @@ define i32 @n5(i32 %arg) {
 ; CHECK-LABEL: @n5(
 ; CHECK-NEXT:    [[T:%.*]] = and i32 [[ARG:%.*]], 2
 ; CHECK-NEXT:    [[T1:%.*]] = icmp eq i32 [[T]], 0
-; CHECK-NEXT:    [[T2:%.*]] = and i32 [[ARG]], 2
+; CHECK-NEXT:    [[T2:%.*]] = and i32 [[ARG]], 3
 ; CHECK-NEXT:    [[T3:%.*]] = select i1 [[T1]], i32 [[T2]], i32 1
 ; CHECK-NEXT:    ret i32 [[T3]]
 ;
   %t = and i32 %arg, 2
   %t1 = icmp eq i32 %t, 0
-  %t2 = and i32 %arg, 2 ; 2 instead of 1
+  %t2 = and i32 %arg, 3 ; 3 instead of 2
   %t3 = select i1 %t1, i32 %t2, i32 1
   ret i32 %t3
 }
diff --git a/llvm/test/Transforms/InstCombine/select.ll b/llvm/test/Transforms/InstCombine/select.ll
index 2efe2742ca491..1a8ff9ab6a9f6 100644
--- a/llvm/test/Transforms/InstCombine/select.ll
+++ b/llvm/test/Transforms/InstCombine/select.ll
@@ -3717,6 +3717,23 @@ entry:
   ret i32 %cond
 }
 
+define i32 @src_and_ne_0_xor_or(i32 %x, i32 %y) {
+; CHECK-LABEL: @src_and_ne_0_xor_or(
+; CHECK-NEXT:    [[AND:%.*]] = and i32 [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT:    [[CMP_NOT:%.*]] = 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_NOT]], i32 [[OR]], i32 [[XOR]]
+; CHECK-NEXT:    ret i32 [[COND]]
+;
+  %and = and i32 %y, %x
+  %cmp = icmp ne i32 %and, 0
+  %or = or i32 %y, %x
+  %xor = xor i32 %y, %x
+  %cond = select i1 %cmp, i32 %xor, i32 %or
+  ret i32 %cond
+}
+
 ; TODO: X&Y==0 could imply no_common_bit to TrueValue
 define i32 @src_and_eq_0_xor_or(i32 %x, i32 %y) {
 ; CHECK-LABEL: @src_and_eq_0_xor_or(
@@ -3737,6 +3754,23 @@ entry:
   ret i32 %cond
 }
 
+define i32 @src_and_ne_0_or_xor(i32 %x, i32 %y) {
+; CHECK-LABEL: @src_and_ne_0_or_xor(
+; CHECK-NEXT:    [[AND:%.*]] = and i32 [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT:    [[CMP_NOT:%.*]] = 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_NOT]], i32 [[XOR]], i32 [[OR]]
+; CHECK-NEXT:    ret i32 [[COND]]
+;
+  %and = and i32 %y, %x
+  %cmp = icmp ne i32 %and, 0
+  %xor = xor i32 %y, %x
+  %or = or i32 %y, %x
+  %cond = select i1 %cmp, i32 %or, i32 %xor
+  ret i32 %cond
+}
+
 ; TODO: X&Y==-1 could imply all_common_bit to TrueValue
 define i32 @src_and_eq_neg1_or_xor(i32 %x, i32 %y) {
 ; CHECK-LABEL: @src_and_eq_neg1_or_xor(
@@ -3757,6 +3791,23 @@ entry:
   ret i32 %cond
 }
 
+define i32 @src_and_ne_neg1_xor_or(i32 %x, i32 %y) {
+; CHECK-LABEL: @src_and_ne_neg1_xor_or(
+; CHECK-NEXT:    [[AND:%.*]] = and i32 [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT:    [[CMP_NOT:%.*]] = 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_NOT]], i32 [[OR]], i32 [[XOR]]
+; CHECK-NEXT:    ret i32 [[COND]]
+;
+  %and = and i32 %y, %x
+  %cmp = icmp ne i32 %and, -1
+  %or = or i32 %y, %x
+  %xor = xor i32 %y, %x
+  %cond = select i1 %cmp, i32 %xor, i32 %or
+  ret i32 %cond
+}
+
 ; TODO: X&Y==-1 could imply all_common_bit to TrueValue
 define i32 @src_and_eq_neg1_xor_or(i32 %x, i32 %y) {
 ; CHECK-LABEL: @src_and_eq_neg1_xor_or(
@@ -3777,6 +3828,23 @@ entry:
   ret i32 %cond
 }
 
+define i32 @src_and_ne_neg1_or_xor(i32 %x, i32 %y) {
+; CHECK-LABEL: @src_and_ne_neg1_or_xor(
+; CHECK-NEXT:    [[AND:%.*]] = and i32 [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT:    [[CMP_NOT:%.*]] = 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_NOT]], i32 [[XOR]], i32 [[OR]]
+; CHECK-NEXT:    ret i32 [[COND]]
+;
+  %and = and i32 %y, %x
+  %cmp = icmp ne i32 %and, -1
+  %xor = xor i32 %y, %x
+  %or = or i32 %y, %x
+  %cond = select i1 %cmp, i32 %or, i32 %xor
+  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:
@@ -3892,6 +3960,23 @@ entry:
   ret i32 %cond
 }
 
+define i32 @src_or_ne_0_xor_and(i32 %x, i32 %y) {
+; CHECK-LABEL: @src_or_ne_0_xor_and(
+; CHECK-NEXT:    [[OR:%.*]] = or i32 [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT:    [[CMP_NOT:%.*]] = 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_NOT]], i32 [[AND]], i32 [[XOR]]
+; CHECK-NEXT:    ret i32 [[COND]]
+;
+  %or = or i32 %y, %x
+  %cmp = icmp ne i32 %or, 0
+  %and = and i32 %y, %x
+  %xor = xor i32 %y, %x
+  %cond = select i1 %cmp, i32 %xor, i32 %and
+  ret i32 %cond
+}
+
 ; TODO: X|Y==0 could imply no_common_bit to TrueValue
 define i32 @src_or_eq_0_xor_and(i32 %x, i32 %y) {
 ; CHECK-LABEL: @src_or_eq_0_xor_and(
@@ -3912,6 +3997,23 @@ entry:
   ret i32 %cond
 }
 
+define i32 @src_or_ne_0_and_xor(i32 %x, i32 %y) {
+; CHECK-LABEL: @src_or_ne_0_and_xor(
+; CHECK-NEXT:    [[OR:%.*]] = or i32 [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT:    [[CMP_NOT:%.*]] = 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_NOT]], i32 [[XOR]], i32 [[AND]]
+; CHECK-NEXT:    ret i32 [[COND]]
+;
+  %or = or i32 %y, %x
+  %cmp = icmp ne i32 %or, 0
+  %xor = xor i32 %y, %x
+  %and = and i32 %y, %x
+  %cond = select i1 %cmp, i32 %and, i32 %xor
+  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:
@@ -4125,6 +4227,190 @@ entry:
   ret i32 %cond
 }
 
+define i32 @src_select_or_eq0_or_xor(i32 %x, i32 %y) {
+; CHECK-LABEL: @src_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_select_or_ne0_xor_or(i32 %x, i32 %y) {
+; CHECK-LABEL: @src_select_or_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_select_or_eq0_and_or(i32 %x, i32 %y) {
+; CHECK-LABEL: @src_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_select_or_ne0_or_and(i32 %x, i32 %y) {
+; CHECK-LABEL: @src_select_or_ne0_or_and(
+; CHECK-NEXT:    [[OR:%.*]] = or i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[OR0_NOT:%.*]] = icmp eq i32 [[OR]], 0
+; CHECK-NEXT:    [[AND:%.*]] = and i32 [[X]], [[Y]]
+; CHECK-NEXT:    [[COND:%.*]] = select i1 [[OR0_NOT]], i32 [[AND]], i32 [[OR]]
+; CHECK-NEXT:    ret i32 [[COND]]
+;
+  %or = or i32 %x, %y
+  %or0 = icmp ne i32 %or, 0
+  %and = and i32 %x, %y
+  %cond = select i1 %or0, i32 %or, i32 %and
+  ret i32 %cond
+}
+
+define i32 @src_select_xor_eq0_and_xor(i32 %x, i32 %y) {
+; CHECK-LABEL: @src_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
+}
+
+define i32 @src_select_xor_ne0_xor_and(i32 %x, i32 %y) {
+; CHECK-LABEL: @src_select_xor_ne0_xor_and(
+; CHECK-NEXT:    [[XOR:%.*]] = xor i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[XOR0_NOT:%.*]] = icmp eq i32 [[XOR]], 0
+; CHECK-NEXT:    [[AND:%.*]] = and i32 [[X]], [[Y]]
+; CHECK-NEXT:    [[COND:%.*]] = select i1 [[XOR0_NOT]], i32 [[AND]], i32 [[XOR]]
+; CHECK-NEXT:    ret i32 [[COND]]
+;
+  %xor = xor i32 %x, %y
+  %xor0 = icmp ne i32 %xor, 0
+  %and = and i32 %x, %y
+  %cond = select i1 %xor0, i32 %xor, i32 %and
+  ret i32 %cond
+}
+
+define i32 @src_select_xor_eq0_or_xor(i32 %x, i32 %y) {
+; CHECK-LABEL: @src_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
+}
+
+define i32 @src_select_xor_ne0_xor_or(i32 %x, i32 %y) {
+; CHECK-LABEL: @src_select_xor_ne0_xor_or(
+; CHECK-NEXT:    [[XOR:%.*]] = xor i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[XOR0_NOT:%.*]] = icmp eq i32 [[XOR]], 0
+; CHECK-NEXT:    [[OR:%.*]] = or i32 [[X]], [[Y]]
+; CHECK-NEXT:    [[COND:%.*]] = select i1 [[XOR0_NOT]], i32 [[OR]], i32 [[XOR]]
+; CHECK-NEXT:    ret i32 [[COND]]
+;
+  %xor = xor i32 %x, %y
+  %xor0 = icmp ne i32 %xor, 0
+  %or = or i32 %x, %y
+  %cond = select i1 %xor0, i32 %xor, i32 %or
+  ret i32 %cond
+}
+
+define i32 @src_select_or_eq0_xor_or(i32 %x, i32 %y) {
+; CHECK-LABEL: @src_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_select_or_ne0_or_xor(i32 %x, i32 %y) {
+; CHECK-LABEL: @src_select_or_ne0_or_xor(
+; 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 [[XOR]], i32 [[OR]]
+; 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 %or, i32 %xor
+  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
+}
+
+define i32 @src_select_xor_max_negative_int_ne(i32 %x, i32 %y) {
+; CHECK-LABEL: @src_select_xor_max_negative_int_ne(
+; CHECK-NEXT:    [[XOR:%.*]] = xor i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[XOR0_NOT:%.*]] = 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_NOT]], i32 [[AND]], i32 [[OR]]
+; CHECK-NEXT:    ret i32 [[COND]]
+;
+  %xor = xor i32 %x, %y
+  %xor0 = icmp ne i32 %xor, -1
+  %and = and i32 %x, %y
+  %or = or i32 %x, %y
+  %cond = select i1 %xor0, i32 %or, i32 %and
+  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) {
@@ -4297,23 +4583,6 @@ define i32 @src_select_xor_min_negative_int(i32 %x, i32 %y) {
   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
@@ -4392,51 +4661,6 @@ define i32 @src_no_trans_select_or_eq0_or_and(i32 %x, i32 %y) {
   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:%.*]]
@@ -4480,37 +4704,6 @@ define i32 @src_no_trans_select_xor_eq0_xor_or(i32 %x, i32 %y) {
   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 e8143b7d76643dd7a355f3bced4322e0e4c3127f Mon Sep 17 00:00:00 2001
From: hanbeom <kese111 at gmail.com>
Date: Tue, 7 May 2024 06:01:11 +0900
Subject: [PATCH 2/4] [InstCombine] Export computeKnownBitsFromCond in
 ValueTracking

to use `Cond` in `SelectInst` for compute KnownBits.
---
 llvm/include/llvm/Analysis/ValueTracking.h | 4 ++++
 llvm/lib/Analysis/ValueTracking.cpp        | 6 +++---
 2 files changed, 7 insertions(+), 3 deletions(-)

diff --git a/llvm/include/llvm/Analysis/ValueTracking.h b/llvm/include/llvm/Analysis/ValueTracking.h
index 571e44cdac265..0bf8c4ce0faa7 100644
--- a/llvm/include/llvm/Analysis/ValueTracking.h
+++ b/llvm/include/llvm/Analysis/ValueTracking.h
@@ -94,6 +94,10 @@ void computeKnownBitsFromRangeMetadata(const MDNode &Ranges, KnownBits &Known);
 void computeKnownBitsFromContext(const Value *V, KnownBits &Known,
                                  unsigned Depth, const SimplifyQuery &Q);
 
+void computeKnownBitsFromCond(const Value *V, Value *Cond, KnownBits &Known,
+                              unsigned Depth, const SimplifyQuery &SQ,
+                              bool Invert);
+
 /// Using KnownBits LHS/RHS produce the known bits for logic op (and/xor/or).
 KnownBits analyzeKnownBitsFromAndXorOr(const Operator *I,
                                        const KnownBits &KnownLHS,
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index de38eddaa98fe..dba9b394ff165 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -735,9 +735,9 @@ static void computeKnownBitsFromICmpCond(const Value *V, ICmpInst *Cmp,
   computeKnownBitsFromCmp(V, Pred, LHS, RHS, Known, SQ);
 }
 
-static void computeKnownBitsFromCond(const Value *V, Value *Cond,
-                                     KnownBits &Known, unsigned Depth,
-                                     const SimplifyQuery &SQ, bool Invert) {
+void llvm::computeKnownBitsFromCond(const Value *V, Value *Cond,
+                                    KnownBits &Known, unsigned Depth,
+                                    const SimplifyQuery &SQ, bool Invert) {
   Value *A, *B;
   if (Depth < MaxAnalysisRecursionDepth &&
       match(Cond, m_LogicalOp(m_Value(A), m_Value(B)))) {

>From e1025d90f21d03567063ae5a67f61a6f5b044328 Mon Sep 17 00:00:00 2001
From: hanbeom <kese111 at gmail.com>
Date: Tue, 7 May 2024 06:04:30 +0900
Subject: [PATCH 3/4] [InstCombine] Try optimizing with knownbits which
 determined from SelectInst Cond

ICmpInst of SelectInst is not included in the calculation of KnownBits
so we are missing the opportunity to optimize the Value of the True or
False Condition via ICmpInst with KnownBits.

Consider:
  %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

Expect:
  %or = or i32 %x, %y
  ret i32 %or

We could know what bit was enabled for %x, %y by ICmpInst in SelectInst.
This patch is an implementation that calculates the known bits over ICmp
and optimizes them where possible.

Proof : https://alive2.llvm.org/ce/z/kJ4YBF
---
 .../Transforms/InstCombine/InstCombiner.h     |   7 +
 .../InstCombine/InstCombineSelect.cpp         | 156 ++++++++++++++++++
 2 files changed, 163 insertions(+)

diff --git a/llvm/include/llvm/Transforms/InstCombine/InstCombiner.h b/llvm/include/llvm/Transforms/InstCombine/InstCombiner.h
index ea1f4fc3b85dc..e654eeb1b234a 100644
--- a/llvm/include/llvm/Transforms/InstCombine/InstCombiner.h
+++ b/llvm/include/llvm/Transforms/InstCombine/InstCombiner.h
@@ -438,6 +438,13 @@ class LLVM_LIBRARY_VISIBILITY InstCombiner {
     return llvm::computeKnownBits(V, Depth, SQ.getWithInstruction(CxtI));
   }
 
+  void computeKnownBitsFromCond(const Value *V, ICmpInst *Cmp, KnownBits &Known,
+                                unsigned Depth, const Instruction *CxtI,
+                                bool Invert) const {
+    llvm::computeKnownBitsFromCond(V, Cmp, Known, Depth,
+                                   SQ.getWithInstruction(CxtI), Invert);
+  }
+
   bool isKnownToBeAPowerOfTwo(const Value *V, bool OrZero = false,
                               unsigned Depth = 0,
                               const Instruction *CxtI = nullptr) {
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
index 117eb7a1dcc93..3835c554faa69 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
@@ -1790,6 +1790,158 @@ static Instruction *foldSelectICmpEq(SelectInst &SI, ICmpInst *ICI,
   return nullptr;
 }
 
+// ICmpInst of SelectInst is not included in the calculation of KnownBits
+// so we are missing the opportunity to optimize the Value of the True or
+// False Condition via ICmpInst with KnownBits.
+//
+// Consider:
+//   %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
+//
+// Expect:
+//   %or = or i32 %x, %y
+//   ret i32 %or
+//
+// We could know what bit was enabled for %x, %y by ICmpInst in SelectInst.
+static Instruction *foldSelectICmpBinOp(SelectInst &SI, ICmpInst *ICI,
+                                        Value *CmpLHS, Value *CmpRHS,
+                                        Value *TVal, Value *FVal,
+                                        InstCombinerImpl &IC) {
+  Value *X, *Y;
+  const APInt *C;
+
+  if (!((match(CmpLHS, m_BinOp(m_Value(X), m_Value(Y))) &&
+         match(CmpRHS, m_APInt(C))) &&
+        (match(TVal, m_c_BinOp(m_Specific(X), m_Value())) ||
+         match(TVal, m_c_BinOp(m_Specific(Y), m_Value())))))
+    return nullptr;
+
+  enum SpecialKnownBits {
+    NothingSpecial = 0,
+    NoCommonBits = 1 << 1,
+    AllCommonBits = 1 << 2,
+    AllBitsEnabled = 1 << 3,
+  };
+
+  // We cannot know exactly what bits is known in X Y.
+  // Instead, we just know what relationship exist for.
+  auto isSpecialKnownBitsFor = [&](const Instruction *CmpLHS,
+                                   const APInt *CmpRHS) -> unsigned {
+    unsigned Opc = CmpLHS->getOpcode();
+    if (Opc == Instruction::And) {
+      if (CmpRHS->isZero())
+        return NoCommonBits;
+    } else if (Opc == Instruction::Xor) {
+      if (CmpRHS->isAllOnes())
+        return NoCommonBits | AllBitsEnabled;
+      if (CmpRHS->isZero())
+        return AllCommonBits;
+    }
+
+    return NothingSpecial;
+  };
+
+  auto hasOperandAt = [&](Instruction *I, Value *Op) -> int {
+    for (unsigned Idx = 0; Idx < I->getNumOperands(); Idx++) {
+      if (I->getOperand(Idx) == Op)
+        return Idx + 1;
+    }
+    return 0;
+  };
+
+  Type *TValTy = TVal->getType();
+  unsigned BitWidth = TVal->getType()->getScalarSizeInBits();
+  auto TValBop = cast<BinaryOperator>(TVal);
+  auto CmpLHSBop = cast<BinaryOperator>(CmpLHS);
+  unsigned XOrder = hasOperandAt(TValBop, X);
+  unsigned YOrder = hasOperandAt(TValBop, Y);
+  unsigned SKB = isSpecialKnownBitsFor(CmpLHSBop, C);
+
+  KnownBits Known;
+  if (TValBop->isBitwiseLogicOp()) {
+    if (SKB != SpecialKnownBits::NothingSpecial && XOrder && YOrder) {
+      if (SKB & SpecialKnownBits::NoCommonBits) {
+        if (SKB & (SpecialKnownBits::AllBitsEnabled)) {
+          if (TValBop->getOpcode() == Instruction::Xor)
+            Known = KnownBits::makeConstant(APInt(BitWidth, -1));
+        }
+        if (TValBop->getOpcode() == Instruction::And)
+          Known = KnownBits::makeConstant(APInt(BitWidth, 0));
+        else if ((match(TVal, m_c_Or(m_Specific(X), m_Specific(Y))) &&
+                  match(FVal, m_c_Xor(m_Specific(X), m_Specific(Y)))) ||
+                 (match(TVal, m_c_Xor(m_Specific(X), m_Specific(Y))) &&
+                  match(FVal, m_c_Or(m_Specific(X), m_Specific(Y)))))
+          return IC.replaceInstUsesWith(SI, FVal);
+      } else if (SKB & SpecialKnownBits::AllCommonBits) {
+        if (TValBop->getOpcode() == Instruction::And ||
+            TValBop->getOpcode() == Instruction::Or)
+          if (TValBop->hasOneUse())
+            return IC.replaceOperand(SI, 1, X);
+      } else if (SKB & SpecialKnownBits::AllBitsEnabled) {
+        if (TValBop->getOpcode() == Instruction::Or)
+          Known = KnownBits::makeConstant(APInt(BitWidth, -1));
+      }
+    } else {
+      KnownBits XKnown, YKnown, Temp;
+      KnownBits TValBop0KB, TValBop1KB;
+      XKnown = IC.computeKnownBits(X, 0, &SI);
+      IC.computeKnownBitsFromCond(X, ICI, XKnown, 0, &SI, false);
+      YKnown = IC.computeKnownBits(Y, 0, &SI);
+      IC.computeKnownBitsFromCond(Y, ICI, YKnown, 0, &SI, false);
+
+      // Estimate additional KnownBits from the relationship between X and Y
+      CmpInst::Predicate Pred = ICI->getPredicate();
+      if (Pred == ICmpInst::ICMP_EQ) {
+        if (CmpLHSBop->getOpcode() == Instruction::And) {
+          XKnown.Zero |= ~*C & YKnown.One;
+          YKnown.Zero |= ~*C & XKnown.One;
+        }
+        if (CmpLHSBop->getOpcode() == Instruction::Or) {
+          XKnown.One |= *C & YKnown.Zero;
+          YKnown.One |= *C & XKnown.Zero;
+        }
+        if (CmpLHSBop->getOpcode() == Instruction::Xor) {
+          XKnown.One |= *C & YKnown.Zero;
+          XKnown.Zero |= *C & YKnown.One;
+          YKnown.One |= *C & XKnown.Zero;
+          YKnown.Zero |= *C & XKnown.One;
+          XKnown.Zero |= ~*C & YKnown.Zero;
+          XKnown.One |= ~*C & YKnown.One;
+          YKnown.Zero |= ~*C & XKnown.Zero;
+          YKnown.One |= ~*C & XKnown.One;
+        }
+      }
+
+      auto getTValBopKB = [&](unsigned OpNum) -> KnownBits {
+        unsigned Order = OpNum + 1;
+        if (Order == XOrder)
+          return XKnown;
+        else if (Order == YOrder)
+          return YKnown;
+
+        Value *V = TValBop->getOperand(OpNum);
+        KnownBits Known = IC.computeKnownBits(V, 0, &SI);
+        return Known;
+      };
+      TValBop0KB = getTValBopKB(0);
+      TValBop1KB = getTValBopKB(1);
+      Known = analyzeKnownBitsFromAndXorOr(
+          cast<Operator>(TValBop), TValBop0KB, TValBop1KB, 0,
+          IC.getSimplifyQuery().getWithInstruction(&SI));
+    }
+  }
+
+  if (Known.isConstant()) {
+    auto Const = ConstantInt::get(TValTy, Known.getConstant());
+    return IC.replaceOperand(SI, 1, Const);
+  }
+
+  return nullptr;
+}
+
 /// Visit a SelectInst that has an ICmpInst as its first operand.
 Instruction *InstCombinerImpl::foldSelectInstWithICmp(SelectInst &SI,
                                                       ICmpInst *ICI) {
@@ -1932,6 +2084,10 @@ Instruction *InstCombinerImpl::foldSelectInstWithICmp(SelectInst &SI,
   if (Value *V = foldAbsDiff(ICI, TrueVal, FalseVal, Builder))
     return replaceInstUsesWith(SI, V);
 
+  if (Instruction *NewSel = foldSelectICmpBinOp(SI, ICI, CmpLHS, CmpRHS,
+                                                TrueVal, FalseVal, *this))
+    return NewSel;
+
   return Changed ? &SI : nullptr;
 }
 

>From 79aa50845dcd781070eaac1c1fb6dd0894ca9891 Mon Sep 17 00:00:00 2001
From: hanbeom <kese111 at gmail.com>
Date: Fri, 10 May 2024 22:41:32 +0900
Subject: [PATCH 4/4] [InstCombine] Optimize TrueVal through knownbits from
 cond in selectInst

There are two type of change with this patch.

When the Cond of SelectInst is ICmpInst.

first is a special case where optimizations can be made. For example,
in the case of (icmp eq (xor x, y) -1), it is impossible to estimate
the bits of x and y, but the relationship between the bits of x and y
is known. We define this as NoCommonBits | AllCommonBits.
if (and x, y) is a trueval with this cond, then x and y are in
NoCommonBits state, so (and x, y) is zero.

second is that if the cond allows us to estimate the KnownBits of X
or Y, then if TrueVal is a BinOp consisting of X or Y, we can optimize
it. For example, if (icmp eq (or x, y) 0), then both x and y have
KnownBits that can be estimated to be 0. Therefore, something like
(select (icmp eq (or x, y) 0), (xor x, y), (or x, y)) can be optimized
to (or x, y).
---
 .../InstCombine/select-of-bittest.ll          | 80 +++++------------
 llvm/test/Transforms/InstCombine/select.ll    | 90 +++++--------------
 2 files changed, 48 insertions(+), 122 deletions(-)

diff --git a/llvm/test/Transforms/InstCombine/select-of-bittest.ll b/llvm/test/Transforms/InstCombine/select-of-bittest.ll
index 46c1a183f3ede..ce10e01fda634 100644
--- a/llvm/test/Transforms/InstCombine/select-of-bittest.ll
+++ b/llvm/test/Transforms/InstCombine/select-of-bittest.ll
@@ -7,9 +7,8 @@
 define i8 @src_and_bit(i8 %x, i8 %y) {
 ; CHECK-LABEL: @src_and_bit(
 ; CHECK-NEXT:    [[AND:%.*]] = and i8 [[X:%.*]], 3
-; CHECK-NEXT:    [[AND1:%.*]] = and i8 [[X]], 2
 ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i8 [[AND]], 2
-; CHECK-NEXT:    [[COND:%.*]] = select i1 [[CMP]], i8 [[AND1]], i8 1
+; CHECK-NEXT:    [[COND:%.*]] = select i1 [[CMP]], i8 2, i8 1
 ; CHECK-NEXT:    ret i8 [[COND]]
 ;
   %and = and i8 %x, 3
@@ -23,9 +22,8 @@ define i8 @src_and_bit(i8 %x, i8 %y) {
 define <2 x i8> @src_and_bit_vec(<2 x i8> %x, <2 x i8> %y) {
 ; CHECK-LABEL: @src_and_bit_vec(
 ; CHECK-NEXT:    [[AND:%.*]] = and <2 x i8> [[X:%.*]], <i8 3, i8 3>
-; CHECK-NEXT:    [[AND1:%.*]] = and <2 x i8> [[X]], <i8 2, i8 2>
 ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq <2 x i8> [[AND]], <i8 2, i8 2>
-; CHECK-NEXT:    [[COND:%.*]] = select <2 x i1> [[CMP]], <2 x i8> [[AND1]], <2 x i8> <i8 1, i8 1>
+; CHECK-NEXT:    [[COND:%.*]] = select <2 x i1> [[CMP]], <2 x i8> <i8 2, i8 2>, <2 x i8> <i8 1, i8 1>
 ; CHECK-NEXT:    ret <2 x i8> [[COND]]
 ;
   %and = and <2 x i8> %x, <i8 3, i8 3>
@@ -39,9 +37,8 @@ define <2 x i8> @src_and_bit_vec(<2 x i8> %x, <2 x i8> %y) {
 define <2 x i8> @src_and_bit_vec_poison(<2 x i8> %x, <2 x i8> %y) {
 ; CHECK-LABEL: @src_and_bit_vec_poison(
 ; CHECK-NEXT:    [[AND:%.*]] = and <2 x i8> [[X:%.*]], <i8 poison, i8 3>
-; CHECK-NEXT:    [[AND1:%.*]] = and <2 x i8> [[X]], <i8 poison, i8 2>
 ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq <2 x i8> [[AND]], <i8 2, i8 2>
-; CHECK-NEXT:    [[COND:%.*]] = select <2 x i1> [[CMP]], <2 x i8> [[AND1]], <2 x i8> <i8 1, i8 1>
+; CHECK-NEXT:    [[COND:%.*]] = select <2 x i1> [[CMP]], <2 x i8> <i8 2, i8 2>, <2 x i8> <i8 1, i8 1>
 ; CHECK-NEXT:    ret <2 x i8> [[COND]]
 ;
   %and = and <2 x i8> %x, <i8 poison, i8 3>
@@ -55,9 +52,8 @@ define <2 x i8> @src_and_bit_vec_poison(<2 x i8> %x, <2 x i8> %y) {
 define <2 x i8> @src_and_bit_vec_poison2(<2 x i8> %x, <2 x i8> %y) {
 ; CHECK-LABEL: @src_and_bit_vec_poison2(
 ; CHECK-NEXT:    [[AND:%.*]] = and <2 x i8> [[X:%.*]], <i8 poison, i8 3>
-; CHECK-NEXT:    [[AND1:%.*]] = and <2 x i8> [[X]], <i8 poison, i8 2>
 ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq <2 x i8> [[AND]], <i8 2, i8 2>
-; CHECK-NEXT:    [[COND:%.*]] = select <2 x i1> [[CMP]], <2 x i8> [[AND1]], <2 x i8> <i8 1, i8 1>
+; CHECK-NEXT:    [[COND:%.*]] = select <2 x i1> [[CMP]], <2 x i8> <i8 2, i8 2>, <2 x i8> <i8 1, i8 1>
 ; CHECK-NEXT:    ret <2 x i8> [[COND]]
 ;
   %and = and <2 x i8> %x, <i8 poison, i8 3>
@@ -71,9 +67,8 @@ define <2 x i8> @src_and_bit_vec_poison2(<2 x i8> %x, <2 x i8> %y) {
 define i8 @src_and_bit_ne(i8 %x, i8 %y) {
 ; CHECK-LABEL: @src_and_bit_ne(
 ; CHECK-NEXT:    [[AND:%.*]] = and i8 [[X:%.*]], 3
-; CHECK-NEXT:    [[AND1:%.*]] = and i8 [[X]], 2
 ; CHECK-NEXT:    [[CMP_NOT:%.*]] = icmp eq i8 [[AND]], 2
-; CHECK-NEXT:    [[COND:%.*]] = select i1 [[CMP_NOT]], i8 [[AND1]], i8 1
+; CHECK-NEXT:    [[COND:%.*]] = select i1 [[CMP_NOT]], i8 2, i8 1
 ; CHECK-NEXT:    ret i8 [[COND]]
 ;
   %and = and i8 %x, 3
@@ -87,9 +82,8 @@ define i8 @src_and_bit_ne(i8 %x, i8 %y) {
 define <2 x i8> @src_and_bit_vec_ne(<2 x i8> %x, <2 x i8> %y) {
 ; CHECK-LABEL: @src_and_bit_vec_ne(
 ; CHECK-NEXT:    [[AND:%.*]] = and <2 x i8> [[X:%.*]], <i8 3, i8 3>
-; CHECK-NEXT:    [[AND1:%.*]] = and <2 x i8> [[X]], <i8 2, i8 2>
 ; CHECK-NEXT:    [[CMP_NOT:%.*]] = icmp eq <2 x i8> [[AND]], <i8 2, i8 2>
-; CHECK-NEXT:    [[COND:%.*]] = select <2 x i1> [[CMP_NOT]], <2 x i8> [[AND1]], <2 x i8> <i8 1, i8 1>
+; CHECK-NEXT:    [[COND:%.*]] = select <2 x i1> [[CMP_NOT]], <2 x i8> <i8 2, i8 2>, <2 x i8> <i8 1, i8 1>
 ; CHECK-NEXT:    ret <2 x i8> [[COND]]
 ;
   %and = and <2 x i8> %x, <i8 3, i8 3>
@@ -103,9 +97,8 @@ define <2 x i8> @src_and_bit_vec_ne(<2 x i8> %x, <2 x i8> %y) {
 define <2 x i8> @src_and_bit_vec_poison_ne(<2 x i8> %x, <2 x i8> %y) {
 ; CHECK-LABEL: @src_and_bit_vec_poison_ne(
 ; CHECK-NEXT:    [[AND:%.*]] = and <2 x i8> [[X:%.*]], <i8 poison, i8 3>
-; CHECK-NEXT:    [[AND1:%.*]] = and <2 x i8> [[X]], <i8 poison, i8 2>
 ; CHECK-NEXT:    [[CMP_NOT:%.*]] = icmp eq <2 x i8> [[AND]], <i8 2, i8 2>
-; CHECK-NEXT:    [[COND:%.*]] = select <2 x i1> [[CMP_NOT]], <2 x i8> [[AND1]], <2 x i8> <i8 1, i8 1>
+; CHECK-NEXT:    [[COND:%.*]] = select <2 x i1> [[CMP_NOT]], <2 x i8> <i8 2, i8 2>, <2 x i8> <i8 1, i8 1>
 ; CHECK-NEXT:    ret <2 x i8> [[COND]]
 ;
   %and = and <2 x i8> %x, <i8 poison, i8 3>
@@ -119,9 +112,8 @@ define <2 x i8> @src_and_bit_vec_poison_ne(<2 x i8> %x, <2 x i8> %y) {
 define <2 x i8> @src_and_bit_vec_poison2_ne(<2 x i8> %x, <2 x i8> %y) {
 ; CHECK-LABEL: @src_and_bit_vec_poison2_ne(
 ; CHECK-NEXT:    [[AND:%.*]] = and <2 x i8> [[X:%.*]], <i8 poison, i8 3>
-; CHECK-NEXT:    [[AND1:%.*]] = and <2 x i8> [[X]], <i8 poison, i8 2>
 ; CHECK-NEXT:    [[CMP_NOT:%.*]] = icmp eq <2 x i8> [[AND]], <i8 2, i8 2>
-; CHECK-NEXT:    [[COND:%.*]] = select <2 x i1> [[CMP_NOT]], <2 x i8> [[AND1]], <2 x i8> <i8 1, i8 1>
+; CHECK-NEXT:    [[COND:%.*]] = select <2 x i1> [[CMP_NOT]], <2 x i8> <i8 2, i8 2>, <2 x i8> <i8 1, i8 1>
 ; CHECK-NEXT:    ret <2 x i8> [[COND]]
 ;
   %and = and <2 x i8> %x, <i8 poison, i8 3>
@@ -135,13 +127,11 @@ define <2 x i8> @src_and_bit_vec_poison2_ne(<2 x i8> %x, <2 x i8> %y) {
 ; ====================== OR =======================
 define i8 @src_or_bit(i8 %x, i8 %y, i8 %z) {
 ; CHECK-LABEL: @src_or_bit(
-; CHECK-NEXT:    [[AND:%.*]] = and i8 [[Z:%.*]], 3
 ; CHECK-NEXT:    [[AND1:%.*]] = shl i8 [[Y:%.*]], 2
 ; CHECK-NEXT:    [[SHL:%.*]] = and i8 [[AND1]], 12
 ; CHECK-NEXT:    [[OR:%.*]] = or i8 [[SHL]], [[X:%.*]]
 ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i8 [[OR]], 3
-; CHECK-NEXT:    [[OR2:%.*]] = or i8 [[AND]], [[X]]
-; CHECK-NEXT:    [[COND:%.*]] = select i1 [[CMP]], i8 [[OR2]], i8 1
+; CHECK-NEXT:    [[COND:%.*]] = select i1 [[CMP]], i8 3, i8 1
 ; CHECK-NEXT:    ret i8 [[COND]]
 ;
   %and = and i8 %z, 3
@@ -156,13 +146,11 @@ define i8 @src_or_bit(i8 %x, i8 %y, i8 %z) {
 
 define <2 x i8> @src_or_bit_vec(<2 x i8> %x, <2 x i8> %y, <2 x i8> %z) {
 ; CHECK-LABEL: @src_or_bit_vec(
-; CHECK-NEXT:    [[AND:%.*]] = and <2 x i8> [[Z:%.*]], <i8 3, i8 3>
 ; CHECK-NEXT:    [[AND1:%.*]] = shl <2 x i8> [[Y:%.*]], <i8 2, i8 2>
 ; CHECK-NEXT:    [[SHL:%.*]] = and <2 x i8> [[AND1]], <i8 12, i8 12>
 ; CHECK-NEXT:    [[OR:%.*]] = or <2 x i8> [[SHL]], [[X:%.*]]
 ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq <2 x i8> [[OR]], <i8 3, i8 3>
-; CHECK-NEXT:    [[OR2:%.*]] = or <2 x i8> [[AND]], [[X]]
-; CHECK-NEXT:    [[COND:%.*]] = select <2 x i1> [[CMP]], <2 x i8> [[OR2]], <2 x i8> <i8 1, i8 1>
+; CHECK-NEXT:    [[COND:%.*]] = select <2 x i1> [[CMP]], <2 x i8> <i8 3, i8 3>, <2 x i8> <i8 1, i8 1>
 ; CHECK-NEXT:    ret <2 x i8> [[COND]]
 ;
   %and = and <2 x i8> %z, <i8 3, i8 3>
@@ -177,13 +165,11 @@ define <2 x i8> @src_or_bit_vec(<2 x i8> %x, <2 x i8> %y, <2 x i8> %z) {
 
 define <2 x i8> @src_or_bit_vec_poison(<2 x i8> %x, <2 x i8> %y, <2 x i8> %z) {
 ; CHECK-LABEL: @src_or_bit_vec_poison(
-; CHECK-NEXT:    [[AND:%.*]] = and <2 x i8> [[Z:%.*]], <i8 3, i8 poison>
 ; CHECK-NEXT:    [[AND1:%.*]] = shl <2 x i8> [[Y:%.*]], <i8 2, i8 poison>
 ; CHECK-NEXT:    [[SHL:%.*]] = and <2 x i8> [[AND1]], <i8 12, i8 poison>
 ; CHECK-NEXT:    [[OR:%.*]] = or <2 x i8> [[SHL]], [[X:%.*]]
 ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq <2 x i8> [[OR]], <i8 3, i8 3>
-; CHECK-NEXT:    [[OR2:%.*]] = or <2 x i8> [[AND]], [[X]]
-; CHECK-NEXT:    [[COND:%.*]] = select <2 x i1> [[CMP]], <2 x i8> [[OR2]], <2 x i8> <i8 1, i8 1>
+; CHECK-NEXT:    [[COND:%.*]] = select <2 x i1> [[CMP]], <2 x i8> <i8 3, i8 3>, <2 x i8> <i8 1, i8 1>
 ; CHECK-NEXT:    ret <2 x i8> [[COND]]
 ;
   %and = and <2 x i8> %z, <i8 3, i8 poison>
@@ -198,13 +184,11 @@ define <2 x i8> @src_or_bit_vec_poison(<2 x i8> %x, <2 x i8> %y, <2 x i8> %z) {
 
 define <2 x i8> @src_or_bit_vec_poison2(<2 x i8> %x, <2 x i8> %y, <2 x i8> %z) {
 ; CHECK-LABEL: @src_or_bit_vec_poison2(
-; CHECK-NEXT:    [[AND:%.*]] = and <2 x i8> [[Z:%.*]], <i8 poison, i8 3>
 ; CHECK-NEXT:    [[AND1:%.*]] = shl <2 x i8> [[Y:%.*]], <i8 poison, i8 2>
 ; CHECK-NEXT:    [[SHL:%.*]] = and <2 x i8> [[AND1]], <i8 poison, i8 12>
 ; CHECK-NEXT:    [[OR:%.*]] = or <2 x i8> [[SHL]], [[X:%.*]]
 ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq <2 x i8> [[OR]], <i8 3, i8 3>
-; CHECK-NEXT:    [[OR2:%.*]] = or <2 x i8> [[AND]], [[X]]
-; CHECK-NEXT:    [[COND:%.*]] = select <2 x i1> [[CMP]], <2 x i8> [[OR2]], <2 x i8> <i8 1, i8 1>
+; CHECK-NEXT:    [[COND:%.*]] = select <2 x i1> [[CMP]], <2 x i8> <i8 3, i8 3>, <2 x i8> <i8 1, i8 1>
 ; CHECK-NEXT:    ret <2 x i8> [[COND]]
 ;
   %and = and <2 x i8> %z, <i8 poison, i8 3>
@@ -219,13 +203,11 @@ define <2 x i8> @src_or_bit_vec_poison2(<2 x i8> %x, <2 x i8> %y, <2 x i8> %z) {
 
 define i8 @src_or_bit_ne(i8 %x, i8 %y, i8 %z) {
 ; CHECK-LABEL: @src_or_bit_ne(
-; CHECK-NEXT:    [[AND:%.*]] = and i8 [[Z:%.*]], 3
 ; CHECK-NEXT:    [[AND1:%.*]] = shl i8 [[Y:%.*]], 2
 ; CHECK-NEXT:    [[SHL:%.*]] = and i8 [[AND1]], 12
 ; CHECK-NEXT:    [[OR:%.*]] = or i8 [[SHL]], [[X:%.*]]
 ; CHECK-NEXT:    [[CMP_NOT:%.*]] = icmp eq i8 [[OR]], 3
-; CHECK-NEXT:    [[OR2:%.*]] = or i8 [[AND]], [[X]]
-; CHECK-NEXT:    [[COND:%.*]] = select i1 [[CMP_NOT]], i8 [[OR2]], i8 1
+; CHECK-NEXT:    [[COND:%.*]] = select i1 [[CMP_NOT]], i8 3, i8 1
 ; CHECK-NEXT:    ret i8 [[COND]]
 ;
   %and = and i8 %z, 3
@@ -240,13 +222,11 @@ define i8 @src_or_bit_ne(i8 %x, i8 %y, i8 %z) {
 
 define <2 x i8> @src_or_bit_vec_ne(<2 x i8> %x, <2 x i8> %y, <2 x i8> %z) {
 ; CHECK-LABEL: @src_or_bit_vec_ne(
-; CHECK-NEXT:    [[AND:%.*]] = and <2 x i8> [[Z:%.*]], <i8 3, i8 3>
 ; CHECK-NEXT:    [[AND1:%.*]] = shl <2 x i8> [[Y:%.*]], <i8 2, i8 2>
 ; CHECK-NEXT:    [[SHL:%.*]] = and <2 x i8> [[AND1]], <i8 12, i8 12>
 ; CHECK-NEXT:    [[OR:%.*]] = or <2 x i8> [[SHL]], [[X:%.*]]
 ; CHECK-NEXT:    [[CMP_NOT:%.*]] = icmp eq <2 x i8> [[OR]], <i8 3, i8 3>
-; CHECK-NEXT:    [[OR2:%.*]] = or <2 x i8> [[AND]], [[X]]
-; CHECK-NEXT:    [[COND:%.*]] = select <2 x i1> [[CMP_NOT]], <2 x i8> [[OR2]], <2 x i8> <i8 1, i8 1>
+; CHECK-NEXT:    [[COND:%.*]] = select <2 x i1> [[CMP_NOT]], <2 x i8> <i8 3, i8 3>, <2 x i8> <i8 1, i8 1>
 ; CHECK-NEXT:    ret <2 x i8> [[COND]]
 ;
   %and = and <2 x i8> %z, <i8 3, i8 3>
@@ -261,13 +241,11 @@ define <2 x i8> @src_or_bit_vec_ne(<2 x i8> %x, <2 x i8> %y, <2 x i8> %z) {
 
 define <2 x i8> @src_or_bit_vec_poison_ne(<2 x i8> %x, <2 x i8> %y, <2 x i8> %z) {
 ; CHECK-LABEL: @src_or_bit_vec_poison_ne(
-; CHECK-NEXT:    [[AND:%.*]] = and <2 x i8> [[Z:%.*]], <i8 3, i8 poison>
 ; CHECK-NEXT:    [[AND1:%.*]] = shl <2 x i8> [[Y:%.*]], <i8 2, i8 poison>
 ; CHECK-NEXT:    [[SHL:%.*]] = and <2 x i8> [[AND1]], <i8 12, i8 poison>
 ; CHECK-NEXT:    [[OR:%.*]] = or <2 x i8> [[SHL]], [[X:%.*]]
 ; CHECK-NEXT:    [[CMP_NOT:%.*]] = icmp eq <2 x i8> [[OR]], <i8 3, i8 3>
-; CHECK-NEXT:    [[OR2:%.*]] = or <2 x i8> [[AND]], [[X]]
-; CHECK-NEXT:    [[COND:%.*]] = select <2 x i1> [[CMP_NOT]], <2 x i8> [[OR2]], <2 x i8> <i8 1, i8 1>
+; CHECK-NEXT:    [[COND:%.*]] = select <2 x i1> [[CMP_NOT]], <2 x i8> <i8 3, i8 3>, <2 x i8> <i8 1, i8 1>
 ; CHECK-NEXT:    ret <2 x i8> [[COND]]
 ;
   %and = and <2 x i8> %z, <i8 3, i8 poison>
@@ -282,13 +260,11 @@ define <2 x i8> @src_or_bit_vec_poison_ne(<2 x i8> %x, <2 x i8> %y, <2 x i8> %z)
 
 define <2 x i8> @src_or_bit_vec_poison2_ne(<2 x i8> %x, <2 x i8> %y, <2 x i8> %z) {
 ; CHECK-LABEL: @src_or_bit_vec_poison2_ne(
-; CHECK-NEXT:    [[AND:%.*]] = and <2 x i8> [[Z:%.*]], <i8 poison, i8 3>
 ; CHECK-NEXT:    [[AND1:%.*]] = shl <2 x i8> [[Y:%.*]], <i8 poison, i8 2>
 ; CHECK-NEXT:    [[SHL:%.*]] = and <2 x i8> [[AND1]], <i8 poison, i8 12>
 ; CHECK-NEXT:    [[OR:%.*]] = or <2 x i8> [[SHL]], [[X:%.*]]
 ; CHECK-NEXT:    [[CMP_NOT:%.*]] = icmp eq <2 x i8> [[OR]], <i8 3, i8 3>
-; CHECK-NEXT:    [[OR2:%.*]] = or <2 x i8> [[AND]], [[X]]
-; CHECK-NEXT:    [[COND:%.*]] = select <2 x i1> [[CMP_NOT]], <2 x i8> [[OR2]], <2 x i8> <i8 1, i8 1>
+; CHECK-NEXT:    [[COND:%.*]] = select <2 x i1> [[CMP_NOT]], <2 x i8> <i8 3, i8 3>, <2 x i8> <i8 1, i8 1>
 ; CHECK-NEXT:    ret <2 x i8> [[COND]]
 ;
   %and = and <2 x i8> %z, <i8 poison, i8 3>
@@ -307,8 +283,7 @@ define i8 @src_xor_bit(i8 %x, i8 %y) {
 ; CHECK-NEXT:    [[AND:%.*]] = and i8 [[Y:%.*]], 12
 ; CHECK-NEXT:    [[XOR:%.*]] = xor i8 [[AND]], [[X:%.*]]
 ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i8 [[XOR]], 3
-; CHECK-NEXT:    [[AND1:%.*]] = and i8 [[X]], 3
-; CHECK-NEXT:    [[COND:%.*]] = select i1 [[CMP]], i8 [[AND1]], i8 1
+; CHECK-NEXT:    [[COND:%.*]] = select i1 [[CMP]], i8 3, i8 1
 ; CHECK-NEXT:    ret i8 [[COND]]
 ;
   %and = and i8 %y, 12
@@ -324,8 +299,7 @@ define <2 x i8> @src_xor_bit_vec(<2 x i8> %x, <2 x i8> %y) {
 ; CHECK-NEXT:    [[AND:%.*]] = and <2 x i8> [[Y:%.*]], <i8 12, i8 12>
 ; CHECK-NEXT:    [[XOR:%.*]] = xor <2 x i8> [[AND]], [[X:%.*]]
 ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq <2 x i8> [[XOR]], <i8 3, i8 3>
-; CHECK-NEXT:    [[AND1:%.*]] = and <2 x i8> [[X]], <i8 3, i8 3>
-; CHECK-NEXT:    [[COND:%.*]] = select <2 x i1> [[CMP]], <2 x i8> [[AND1]], <2 x i8> <i8 1, i8 1>
+; CHECK-NEXT:    [[COND:%.*]] = select <2 x i1> [[CMP]], <2 x i8> <i8 3, i8 3>, <2 x i8> <i8 1, i8 1>
 ; CHECK-NEXT:    ret <2 x i8> [[COND]]
 ;
   %and = and <2 x i8> %y, <i8 12, i8 12>
@@ -341,8 +315,7 @@ define <2 x i8> @src_xor_bit_vec_poison(<2 x i8> %x, <2 x i8> %y) {
 ; CHECK-NEXT:    [[AND:%.*]] = and <2 x i8> [[Y:%.*]], <i8 poison, i8 12>
 ; CHECK-NEXT:    [[XOR:%.*]] = xor <2 x i8> [[AND]], [[X:%.*]]
 ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq <2 x i8> [[XOR]], <i8 3, i8 3>
-; CHECK-NEXT:    [[AND1:%.*]] = and <2 x i8> [[X]], <i8 poison, i8 3>
-; CHECK-NEXT:    [[COND:%.*]] = select <2 x i1> [[CMP]], <2 x i8> [[AND1]], <2 x i8> <i8 1, i8 1>
+; CHECK-NEXT:    [[COND:%.*]] = select <2 x i1> [[CMP]], <2 x i8> <i8 3, i8 3>, <2 x i8> <i8 1, i8 1>
 ; CHECK-NEXT:    ret <2 x i8> [[COND]]
 ;
   %and = and <2 x i8> %y, <i8 poison, i8 12>
@@ -358,8 +331,7 @@ define <2 x i8> @src_xor_bit_vec_poison2(<2 x i8> %x, <2 x i8> %y) {
 ; CHECK-NEXT:    [[AND:%.*]] = and <2 x i8> [[Y:%.*]], <i8 poison, i8 12>
 ; CHECK-NEXT:    [[XOR:%.*]] = xor <2 x i8> [[AND]], [[X:%.*]]
 ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq <2 x i8> [[XOR]], <i8 3, i8 3>
-; CHECK-NEXT:    [[AND1:%.*]] = and <2 x i8> [[X]], <i8 3, i8 3>
-; CHECK-NEXT:    [[COND:%.*]] = select <2 x i1> [[CMP]], <2 x i8> [[AND1]], <2 x i8> <i8 1, i8 1>
+; CHECK-NEXT:    [[COND:%.*]] = select <2 x i1> [[CMP]], <2 x i8> <i8 3, i8 3>, <2 x i8> <i8 1, i8 1>
 ; CHECK-NEXT:    ret <2 x i8> [[COND]]
 ;
   %and = and <2 x i8> %y, <i8 poison, i8 12>
@@ -375,8 +347,7 @@ define i8 @src_xor_bit_ne(i8 %x, i8 %y) {
 ; CHECK-NEXT:    [[AND:%.*]] = and i8 [[Y:%.*]], 12
 ; CHECK-NEXT:    [[XOR:%.*]] = xor i8 [[AND]], [[X:%.*]]
 ; CHECK-NEXT:    [[CMP_NOT:%.*]] = icmp eq i8 [[XOR]], 3
-; CHECK-NEXT:    [[AND1:%.*]] = and i8 [[X]], 3
-; CHECK-NEXT:    [[COND:%.*]] = select i1 [[CMP_NOT]], i8 [[AND1]], i8 1
+; CHECK-NEXT:    [[COND:%.*]] = select i1 [[CMP_NOT]], i8 3, i8 1
 ; CHECK-NEXT:    ret i8 [[COND]]
 ;
   %and = and i8 %y, 12
@@ -392,8 +363,7 @@ define <2 x i8> @src_xor_bit_vec_ne(<2 x i8> %x, <2 x i8> %y) {
 ; CHECK-NEXT:    [[AND:%.*]] = and <2 x i8> [[Y:%.*]], <i8 12, i8 12>
 ; CHECK-NEXT:    [[XOR:%.*]] = xor <2 x i8> [[AND]], [[X:%.*]]
 ; CHECK-NEXT:    [[CMP_NOT:%.*]] = icmp eq <2 x i8> [[XOR]], <i8 3, i8 3>
-; CHECK-NEXT:    [[AND1:%.*]] = and <2 x i8> [[X]], <i8 3, i8 3>
-; CHECK-NEXT:    [[COND:%.*]] = select <2 x i1> [[CMP_NOT]], <2 x i8> [[AND1]], <2 x i8> <i8 1, i8 1>
+; CHECK-NEXT:    [[COND:%.*]] = select <2 x i1> [[CMP_NOT]], <2 x i8> <i8 3, i8 3>, <2 x i8> <i8 1, i8 1>
 ; CHECK-NEXT:    ret <2 x i8> [[COND]]
 ;
   %and = and <2 x i8> %y, <i8 12, i8 12>
@@ -409,8 +379,7 @@ define <2 x i8> @src_xor_bit_vec_poison_ne(<2 x i8> %x, <2 x i8> %y) {
 ; CHECK-NEXT:    [[AND:%.*]] = and <2 x i8> [[Y:%.*]], <i8 poison, i8 12>
 ; CHECK-NEXT:    [[XOR:%.*]] = xor <2 x i8> [[AND]], [[X:%.*]]
 ; CHECK-NEXT:    [[CMP_NOT:%.*]] = icmp eq <2 x i8> [[XOR]], <i8 3, i8 3>
-; CHECK-NEXT:    [[AND1:%.*]] = and <2 x i8> [[X]], <i8 poison, i8 3>
-; CHECK-NEXT:    [[COND:%.*]] = select <2 x i1> [[CMP_NOT]], <2 x i8> [[AND1]], <2 x i8> <i8 1, i8 1>
+; CHECK-NEXT:    [[COND:%.*]] = select <2 x i1> [[CMP_NOT]], <2 x i8> <i8 3, i8 3>, <2 x i8> <i8 1, i8 1>
 ; CHECK-NEXT:    ret <2 x i8> [[COND]]
 ;
   %and = and <2 x i8> %y, <i8 poison, i8 12>
@@ -426,8 +395,7 @@ define <2 x i8> @src_xor_bit_vec_poison2_ne(<2 x i8> %x, <2 x i8> %y) {
 ; CHECK-NEXT:    [[AND:%.*]] = and <2 x i8> [[Y:%.*]], <i8 poison, i8 12>
 ; CHECK-NEXT:    [[XOR:%.*]] = xor <2 x i8> [[AND]], [[X:%.*]]
 ; CHECK-NEXT:    [[CMP_NOT:%.*]] = icmp eq <2 x i8> [[XOR]], <i8 3, i8 3>
-; CHECK-NEXT:    [[AND1:%.*]] = and <2 x i8> [[X]], <i8 3, i8 3>
-; CHECK-NEXT:    [[COND:%.*]] = select <2 x i1> [[CMP_NOT]], <2 x i8> [[AND1]], <2 x i8> <i8 1, i8 1>
+; CHECK-NEXT:    [[COND:%.*]] = select <2 x i1> [[CMP_NOT]], <2 x i8> <i8 3, i8 3>, <2 x i8> <i8 1, i8 1>
 ; CHECK-NEXT:    ret <2 x i8> [[COND]]
 ;
   %and = and <2 x i8> %y, <i8 poison, i8 12>
diff --git a/llvm/test/Transforms/InstCombine/select.ll b/llvm/test/Transforms/InstCombine/select.ll
index 1a8ff9ab6a9f6..088ca83745376 100644
--- a/llvm/test/Transforms/InstCombine/select.ll
+++ b/llvm/test/Transforms/InstCombine/select.ll
@@ -3697,16 +3697,11 @@ exit:
 ; 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
-; TODO: X&Y==0 could imply no_common_bit to TrueValue
 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
@@ -3719,12 +3714,8 @@ entry:
 
 define i32 @src_and_ne_0_xor_or(i32 %x, i32 %y) {
 ; CHECK-LABEL: @src_and_ne_0_xor_or(
-; CHECK-NEXT:    [[AND:%.*]] = and i32 [[Y:%.*]], [[X:%.*]]
-; CHECK-NEXT:    [[CMP_NOT:%.*]] = 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_NOT]], i32 [[OR]], i32 [[XOR]]
-; CHECK-NEXT:    ret i32 [[COND]]
+; CHECK-NEXT:    [[XOR:%.*]] = xor i32 [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT:    ret i32 [[XOR]]
 ;
   %and = and i32 %y, %x
   %cmp = icmp ne i32 %and, 0
@@ -3734,16 +3725,11 @@ define i32 @src_and_ne_0_xor_or(i32 %x, i32 %y) {
   ret i32 %cond
 }
 
-; TODO: X&Y==0 could imply no_common_bit to TrueValue
 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
@@ -3756,12 +3742,8 @@ entry:
 
 define i32 @src_and_ne_0_or_xor(i32 %x, i32 %y) {
 ; CHECK-LABEL: @src_and_ne_0_or_xor(
-; CHECK-NEXT:    [[AND:%.*]] = and i32 [[Y:%.*]], [[X:%.*]]
-; CHECK-NEXT:    [[CMP_NOT:%.*]] = 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_NOT]], i32 [[XOR]], i32 [[OR]]
-; CHECK-NEXT:    ret i32 [[COND]]
+; CHECK-NEXT:    [[OR:%.*]] = or i32 [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT:    ret i32 [[OR]]
 ;
   %and = and i32 %y, %x
   %cmp = icmp ne i32 %and, 0
@@ -3771,15 +3753,13 @@ define i32 @src_and_ne_0_or_xor(i32 %x, i32 %y) {
   ret i32 %cond
 }
 
-; TODO: X&Y==-1 could imply all_common_bit to TrueValue
 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:    [[COND:%.*]] = select i1 [[CMP]], i32 -1, i32 [[XOR]]
 ; CHECK-NEXT:    ret i32 [[COND]]
 ;
 entry:
@@ -3795,9 +3775,8 @@ define i32 @src_and_ne_neg1_xor_or(i32 %x, i32 %y) {
 ; CHECK-LABEL: @src_and_ne_neg1_xor_or(
 ; CHECK-NEXT:    [[AND:%.*]] = and i32 [[Y:%.*]], [[X:%.*]]
 ; CHECK-NEXT:    [[CMP_NOT:%.*]] = 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_NOT]], i32 [[OR]], i32 [[XOR]]
+; CHECK-NEXT:    [[COND:%.*]] = select i1 [[CMP_NOT]], i32 -1, i32 [[XOR]]
 ; CHECK-NEXT:    ret i32 [[COND]]
 ;
   %and = and i32 %y, %x
@@ -3808,15 +3787,13 @@ define i32 @src_and_ne_neg1_xor_or(i32 %x, i32 %y) {
   ret i32 %cond
 }
 
-; TODO: X&Y==-1 could imply all_common_bit to TrueValue
 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:    [[COND:%.*]] = select i1 [[CMP]], i32 0, i32 [[OR]]
 ; CHECK-NEXT:    ret i32 [[COND]]
 ;
 entry:
@@ -3832,9 +3809,8 @@ define i32 @src_and_ne_neg1_or_xor(i32 %x, i32 %y) {
 ; CHECK-LABEL: @src_and_ne_neg1_or_xor(
 ; CHECK-NEXT:    [[AND:%.*]] = and i32 [[Y:%.*]], [[X:%.*]]
 ; CHECK-NEXT:    [[CMP_NOT:%.*]] = 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_NOT]], i32 [[XOR]], i32 [[OR]]
+; CHECK-NEXT:    [[COND:%.*]] = select i1 [[CMP_NOT]], i32 0, i32 [[OR]]
 ; CHECK-NEXT:    ret i32 [[COND]]
 ;
   %and = and i32 %y, %x
@@ -3940,15 +3916,13 @@ entry:
 
 ; https://alive2.llvm.org/ce/z/9RPwfN
 ; X|Y==C?X&Y:X^Y, X|Y==C?X^Y:X&Y
-; TODO: X|Y==0 could imply no_common_bit to TrueValue
 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:    [[COND:%.*]] = select i1 [[CMP]], i32 0, i32 [[XOR]]
 ; CHECK-NEXT:    ret i32 [[COND]]
 ;
 entry:
@@ -3964,9 +3938,8 @@ define i32 @src_or_ne_0_xor_and(i32 %x, i32 %y) {
 ; CHECK-LABEL: @src_or_ne_0_xor_and(
 ; CHECK-NEXT:    [[OR:%.*]] = or i32 [[Y:%.*]], [[X:%.*]]
 ; CHECK-NEXT:    [[CMP_NOT:%.*]] = 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_NOT]], i32 [[AND]], i32 [[XOR]]
+; CHECK-NEXT:    [[COND:%.*]] = select i1 [[CMP_NOT]], i32 0, i32 [[XOR]]
 ; CHECK-NEXT:    ret i32 [[COND]]
 ;
   %or = or i32 %y, %x
@@ -3977,15 +3950,13 @@ define i32 @src_or_ne_0_xor_and(i32 %x, i32 %y) {
   ret i32 %cond
 }
 
-; TODO: X|Y==0 could imply no_common_bit to TrueValue
 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:    [[COND:%.*]] = select i1 [[CMP]], i32 0, i32 [[AND]]
 ; CHECK-NEXT:    ret i32 [[COND]]
 ;
 entry:
@@ -4001,9 +3972,8 @@ define i32 @src_or_ne_0_and_xor(i32 %x, i32 %y) {
 ; CHECK-LABEL: @src_or_ne_0_and_xor(
 ; CHECK-NEXT:    [[OR:%.*]] = or i32 [[Y:%.*]], [[X:%.*]]
 ; CHECK-NEXT:    [[CMP_NOT:%.*]] = 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_NOT]], i32 [[XOR]], i32 [[AND]]
+; CHECK-NEXT:    [[COND:%.*]] = select i1 [[CMP_NOT]], i32 0, i32 [[AND]]
 ; CHECK-NEXT:    ret i32 [[COND]]
 ;
   %or = or i32 %y, %x
@@ -4260,10 +4230,7 @@ define i32 @src_select_or_ne0_xor_or(i32 %x, i32 %y) {
 define i32 @src_select_or_eq0_and_or(i32 %x, i32 %y) {
 ; CHECK-LABEL: @src_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]]
+; CHECK-NEXT:    ret i32 [[OR]]
 ;
   %or = or i32 %x, %y
   %or0 = icmp eq i32 %or, 0
@@ -4275,10 +4242,7 @@ define i32 @src_select_or_eq0_and_or(i32 %x, i32 %y) {
 define i32 @src_select_or_ne0_or_and(i32 %x, i32 %y) {
 ; CHECK-LABEL: @src_select_or_ne0_or_and(
 ; CHECK-NEXT:    [[OR:%.*]] = or i32 [[X:%.*]], [[Y:%.*]]
-; CHECK-NEXT:    [[OR0_NOT:%.*]] = icmp eq i32 [[OR]], 0
-; CHECK-NEXT:    [[AND:%.*]] = and i32 [[X]], [[Y]]
-; CHECK-NEXT:    [[COND:%.*]] = select i1 [[OR0_NOT]], i32 [[AND]], i32 [[OR]]
-; CHECK-NEXT:    ret i32 [[COND]]
+; CHECK-NEXT:    ret i32 [[OR]]
 ;
   %or = or i32 %x, %y
   %or0 = icmp ne i32 %or, 0
@@ -4291,8 +4255,7 @@ define i32 @src_select_xor_eq0_and_xor(i32 %x, i32 %y) {
 ; CHECK-LABEL: @src_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:    [[COND:%.*]] = select i1 [[XOR0]], i32 [[X]], i32 [[XOR]]
 ; CHECK-NEXT:    ret i32 [[COND]]
 ;
   %xor = xor i32 %x, %y
@@ -4306,8 +4269,7 @@ define i32 @src_select_xor_ne0_xor_and(i32 %x, i32 %y) {
 ; CHECK-LABEL: @src_select_xor_ne0_xor_and(
 ; CHECK-NEXT:    [[XOR:%.*]] = xor i32 [[X:%.*]], [[Y:%.*]]
 ; CHECK-NEXT:    [[XOR0_NOT:%.*]] = icmp eq i32 [[XOR]], 0
-; CHECK-NEXT:    [[AND:%.*]] = and i32 [[X]], [[Y]]
-; CHECK-NEXT:    [[COND:%.*]] = select i1 [[XOR0_NOT]], i32 [[AND]], i32 [[XOR]]
+; CHECK-NEXT:    [[COND:%.*]] = select i1 [[XOR0_NOT]], i32 [[X]], i32 [[XOR]]
 ; CHECK-NEXT:    ret i32 [[COND]]
 ;
   %xor = xor i32 %x, %y
@@ -4321,8 +4283,7 @@ define i32 @src_select_xor_eq0_or_xor(i32 %x, i32 %y) {
 ; CHECK-LABEL: @src_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:    [[COND:%.*]] = select i1 [[XOR0]], i32 [[X]], i32 [[XOR]]
 ; CHECK-NEXT:    ret i32 [[COND]]
 ;
   %xor = xor i32 %x, %y
@@ -4336,8 +4297,7 @@ define i32 @src_select_xor_ne0_xor_or(i32 %x, i32 %y) {
 ; CHECK-LABEL: @src_select_xor_ne0_xor_or(
 ; CHECK-NEXT:    [[XOR:%.*]] = xor i32 [[X:%.*]], [[Y:%.*]]
 ; CHECK-NEXT:    [[XOR0_NOT:%.*]] = icmp eq i32 [[XOR]], 0
-; CHECK-NEXT:    [[OR:%.*]] = or i32 [[X]], [[Y]]
-; CHECK-NEXT:    [[COND:%.*]] = select i1 [[XOR0_NOT]], i32 [[OR]], i32 [[XOR]]
+; CHECK-NEXT:    [[COND:%.*]] = select i1 [[XOR0_NOT]], i32 [[X]], i32 [[XOR]]
 ; CHECK-NEXT:    ret i32 [[COND]]
 ;
   %xor = xor i32 %x, %y
@@ -4381,9 +4341,8 @@ 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:    [[COND:%.*]] = select i1 [[XOR0]], i32 0, i32 [[OR]]
 ; CHECK-NEXT:    ret i32 [[COND]]
 ;
   %xor = xor i32 %x, %y
@@ -4398,9 +4357,8 @@ define i32 @src_select_xor_max_negative_int_ne(i32 %x, i32 %y) {
 ; CHECK-LABEL: @src_select_xor_max_negative_int_ne(
 ; CHECK-NEXT:    [[XOR:%.*]] = xor i32 [[X:%.*]], [[Y:%.*]]
 ; CHECK-NEXT:    [[XOR0_NOT:%.*]] = 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_NOT]], i32 [[AND]], i32 [[OR]]
+; CHECK-NEXT:    [[COND:%.*]] = select i1 [[XOR0_NOT]], i32 0, i32 [[OR]]
 ; CHECK-NEXT:    ret i32 [[COND]]
 ;
   %xor = xor i32 %x, %y



More information about the llvm-commits mailing list