[llvm] [InstCombine] Introduce `foldICmpBinOpWithConstantViaTruthTable` folding (PR #139109)

Antonio Frighetto via llvm-commits llvm-commits at lists.llvm.org
Thu May 8 10:08:18 PDT 2025


https://github.com/antoniofrighetto created https://github.com/llvm/llvm-project/pull/139109

Match icmps of binops where both operands are select with constant arms, i.e., `icmp pred (select A ? C1 : C2) binop (select B ? C3 : C4), C5`. Fold such patterns by creating a truth table of the possible four constant variants, and materialize back the optimal logic from it via `createLogicFromTable` helper.

Proofs: https://alive2.llvm.org/ce/z/_kkUfJ.

Fixes: https://github.com/llvm/llvm-project/issues/138212.

>From 9bfdae457c010ecf274c6cc11513235993d5b9f6 Mon Sep 17 00:00:00 2001
From: Antonio Frighetto <me at antoniofrighetto.com>
Date: Thu, 8 May 2025 11:21:56 +0200
Subject: [PATCH 1/2] [InstCombine] Precommit tests for PR139109 (NFC)

---
 .../test/Transforms/InstCombine/icmp-binop.ll | 108 ++++++++++++++++++
 1 file changed, 108 insertions(+)

diff --git a/llvm/test/Transforms/InstCombine/icmp-binop.ll b/llvm/test/Transforms/InstCombine/icmp-binop.ll
index 356489716fff9..ce24a51dba04d 100644
--- a/llvm/test/Transforms/InstCombine/icmp-binop.ll
+++ b/llvm/test/Transforms/InstCombine/icmp-binop.ll
@@ -359,3 +359,111 @@ define i1 @test_icmp_sgt_and_negpow2_invalid_c(i32 %add) {
   %cmp = icmp sgt i32 %and, 48
   ret i1 %cmp
 }
+
+define i1 @icmp_eq_or_of_selects_with_constant(i1 %a, i1 %b) {
+; CHECK-LABEL: @icmp_eq_or_of_selects_with_constant(
+; CHECK-NEXT:    [[S1:%.*]] = select i1 [[A:%.*]], i64 65536, i64 0
+; CHECK-NEXT:    [[S2:%.*]] = select i1 [[B:%.*]], i64 256, i64 0
+; CHECK-NEXT:    [[OR:%.*]] = or disjoint i64 [[S1]], [[S2]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i64 [[OR]], 65792
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+  %s1 = select i1 %a, i64 65536, i64 0
+  %s2 = select i1 %b, i64 256, i64 0
+  %or = or i64 %s1, %s2
+  %cmp = icmp eq i64 %or, 65792
+  ret i1 %cmp
+}
+
+define i1 @icmp_slt_and_of_selects_with_constant(i1 %a, i1 %b) {
+; CHECK-LABEL: @icmp_slt_and_of_selects_with_constant(
+; CHECK-NEXT:    [[S1:%.*]] = select i1 [[A:%.*]], i8 1, i8 -4
+; CHECK-NEXT:    [[S2:%.*]] = select i1 [[B:%.*]], i8 1, i8 -3
+; CHECK-NEXT:    [[AND:%.*]] = and i8 [[S1]], [[S2]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i8 [[AND]], -2
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+  %s1 = select i1 %a, i8 1, i8 254
+  %s2 = select i1 %b, i8 1, i8 253
+  %and = and i8 %s1, %s2
+  %cmp = icmp slt i8 %and, 254
+  ret i1 %cmp
+}
+
+define i1 @icmp_sge_add_of_selects_with_constant(i1 %a, i1 %b) {
+; CHECK-LABEL: @icmp_sge_add_of_selects_with_constant(
+; CHECK-NEXT:    [[S1:%.*]] = select i1 [[A:%.*]], i8 -8, i8 7
+; CHECK-NEXT:    [[S2:%.*]] = select i1 [[B:%.*]], i8 16, i8 0
+; CHECK-NEXT:    [[ADD:%.*]] = add nsw i8 [[S1]], [[S2]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i8 [[ADD]], -10
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+  %s1 = select i1 %a, i8 248, i8 7
+  %s2 = select i1 %b, i8 16, i8 0
+  %add = add i8 %s1, %s2
+  %cmp = icmp sge i8 %add, 247
+  ret i1 %cmp
+}
+
+define <2 x i1> @icmp_eq_or_of_selects_with_constant_vectorized(<2 x i1> %a, <2 x i1> %b) {
+; CHECK-LABEL: @icmp_eq_or_of_selects_with_constant_vectorized(
+; CHECK-NEXT:    [[S1:%.*]] = select <2 x i1> [[A:%.*]], <2 x i64> splat (i64 65536), <2 x i64> zeroinitializer
+; CHECK-NEXT:    [[S2:%.*]] = select <2 x i1> [[B:%.*]], <2 x i64> splat (i64 256), <2 x i64> zeroinitializer
+; CHECK-NEXT:    [[OR:%.*]] = or disjoint <2 x i64> [[S1]], [[S2]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq <2 x i64> [[OR]], splat (i64 65792)
+; CHECK-NEXT:    ret <2 x i1> [[CMP]]
+;
+  %s1 = select <2 x i1> %a, <2 x i64> <i64 65536, i64 65536>, <2 x i64> zeroinitializer
+  %s2 = select <2 x i1> %b, <2 x i64> <i64 256, i64 256>, <2 x i64> zeroinitializer
+  %or = or <2 x i64> %s1, %s2
+  %cmp = icmp eq <2 x i64> %or, <i64 65792, i64 65792>
+  ret <2 x i1> %cmp
+}
+
+; Negative tests.
+define i1 @icmp_eq_or_of_selects_with_constant_and_arg(i1 %a, i1 %b, i64 %arg) {
+; CHECK-LABEL: @icmp_eq_or_of_selects_with_constant_and_arg(
+; CHECK-NEXT:    [[S1:%.*]] = select i1 [[A:%.*]], i64 65536, i64 [[ARG:%.*]]
+; CHECK-NEXT:    [[S2:%.*]] = select i1 [[B:%.*]], i64 256, i64 0
+; CHECK-NEXT:    [[OR:%.*]] = or i64 [[S1]], [[S2]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i64 [[OR]], 65792
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+  %s1 = select i1 %a, i64 65536, i64 %arg
+  %s2 = select i1 %b, i64 256, i64 0
+  %or = or i64 %s1, %s2
+  %cmp = icmp eq i64 %or, 65792
+  ret i1 %cmp
+}
+
+define i1 @icmp_eq_or_of_selects_with_constant_multiuse(i1 %a, i1 %b) {
+; CHECK-LABEL: @icmp_eq_or_of_selects_with_constant_multiuse(
+; CHECK-NEXT:    [[S1:%.*]] = select i1 [[A:%.*]], i64 0, i64 65536
+; CHECK-NEXT:    [[S2:%.*]] = select i1 [[B:%.*]], i64 0, i64 256
+; CHECK-NEXT:    [[OR:%.*]] = or disjoint i64 [[S1]], [[S2]]
+; CHECK-NEXT:    call void @use64(i64 [[OR]])
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i64 [[OR]], 65792
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+  %s1 = select i1 %a, i64 0, i64 65536
+  %s2 = select i1 %b, i64 0, i64 256
+  %or = or i64 %s1, %s2
+  call void @use64(i64 %or)
+  %cmp = icmp eq i64 %or, 65792
+  ret i1 %cmp
+}
+
+define <2 x i1> @icmp_eq_or_of_selects_with_constant_vectorized_nonsplat(<2 x i1> %a, <2 x i1> %b) {
+; CHECK-LABEL: @icmp_eq_or_of_selects_with_constant_vectorized_nonsplat(
+; CHECK-NEXT:    [[S1:%.*]] = select <2 x i1> [[A:%.*]], <2 x i64> splat (i64 65536), <2 x i64> zeroinitializer
+; CHECK-NEXT:    [[S2:%.*]] = select <2 x i1> [[B:%.*]], <2 x i64> <i64 256, i64 128>, <2 x i64> zeroinitializer
+; CHECK-NEXT:    [[OR:%.*]] = or disjoint <2 x i64> [[S1]], [[S2]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq <2 x i64> [[OR]], <i64 65792, i64 65664>
+; CHECK-NEXT:    ret <2 x i1> [[CMP]]
+;
+  %s1 = select <2 x i1> %a, <2 x i64> <i64 65536, i64 65536>, <2 x i64> zeroinitializer
+  %s2 = select <2 x i1> %b, <2 x i64> <i64 256, i64 128>, <2 x i64> zeroinitializer
+  %or = or <2 x i64> %s1, %s2
+  %cmp = icmp eq <2 x i64> %or, <i64 65792, i64 65664>
+  ret <2 x i1> %cmp
+}

>From f7fba648055dce4d40097fecb28ffb40c128171b Mon Sep 17 00:00:00 2001
From: Antonio Frighetto <me at antoniofrighetto.com>
Date: Thu, 8 May 2025 11:58:41 +0200
Subject: [PATCH 2/2] [InstCombine] Introduce
 `foldICmpBinOpWithConstantViaTruthTable` folding

Match icmps of binops where both operands are select with constant arms,
i.e., `icmp pred (select A ? C1 : C2) binop (select B ? C3 : C4), C5`.
Fold such patterns by creating a truth table of the possible four
constant variants, and materialize back the optimal logic from it via
`createLogicFromTable` helper.

Proofs: https://alive2.llvm.org/ce/z/_kkUfJ.

Fixes: https://github.com/llvm/llvm-project/issues/138212.
---
 .../InstCombine/InstCombineCompares.cpp       | 46 +++++++++++++++-
 .../InstCombine/InstCombineInternal.h         |  3 ++
 .../test/Transforms/InstCombine/icmp-binop.ll | 22 ++------
 .../Transforms/InstCombine/icmp-select.ll     | 52 +++++--------------
 4 files changed, 65 insertions(+), 58 deletions(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
index 252781e54ab06..9cb3a80c2ea20 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -3110,6 +3110,44 @@ static Value *createLogicFromTable(const std::bitset<4> &Table, Value *Op0,
   return nullptr;
 }
 
+Instruction *InstCombinerImpl::foldICmpBinOpWithConstantViaTruthTable(
+    ICmpInst &Cmp, BinaryOperator *BO, const APInt &C) {
+  Value *A, *B;
+  Constant *C1, *C2, *C3, *C4;
+  if (match(BO->getOperand(0),
+            m_Select(m_Value(A), m_Constant(C1), m_Constant(C2))) &&
+      match(BO->getOperand(1),
+            m_Select(m_Value(B), m_Constant(C3), m_Constant(C4)))) {
+    std::bitset<4> Table;
+    auto ComputeTable = [&](bool First, bool Second) -> std::optional<bool> {
+      Constant *L = First ? C1 : C2;
+      Constant *R = Second ? C3 : C4;
+      if (auto *Res = ConstantFoldBinaryOpOperands(BO->getOpcode(), L, R, DL)) {
+        auto *Val = Res->getType()->isVectorTy() ? Res->getSplatValue() : Res;
+        if (auto *CI = dyn_cast_or_null<ConstantInt>(Val))
+          return ICmpInst::compare(CI->getValue(), C, Cmp.getPredicate());
+      }
+      return std::nullopt;
+    };
+
+    for (unsigned I = 0; I < 4; ++I) {
+      bool First = (I >> 1) & 1;
+      bool Second = I & 1;
+      if (auto Res = ComputeTable(First, Second))
+        Table[I] = *Res;
+      else
+        return nullptr;
+    }
+
+    // Synthesize optimal logic.
+    if (auto *Cond =
+            createLogicFromTable(Table, A, B, Builder, BO->hasOneUse()))
+      return replaceInstUsesWith(Cmp, Cond);
+  }
+
+  return nullptr;
+}
+
 /// Fold icmp (add X, Y), C.
 Instruction *InstCombinerImpl::foldICmpAddConstant(ICmpInst &Cmp,
                                                    BinaryOperator *Add,
@@ -4014,7 +4052,13 @@ Instruction *InstCombinerImpl::foldICmpBinOpWithConstant(ICmpInst &Cmp,
   }
 
   // TODO: These folds could be refactored to be part of the above calls.
-  return foldICmpBinOpEqualityWithConstant(Cmp, BO, C);
+  if (Instruction *I = foldICmpBinOpEqualityWithConstant(Cmp, BO, C))
+    return I;
+
+  // Fall back to handling `icmp pred (select A ? C1 : C2) binop (select B ? C3
+  // : C4), C5` pattern, by computing a truth table of the four constant
+  // variants.
+  return foldICmpBinOpWithConstantViaTruthTable(Cmp, BO, C);
 }
 
 static Instruction *
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineInternal.h b/llvm/lib/Transforms/InstCombine/InstCombineInternal.h
index 324738ef8c88e..8b657b3f8555c 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineInternal.h
+++ b/llvm/lib/Transforms/InstCombine/InstCombineInternal.h
@@ -736,6 +736,9 @@ class LLVM_LIBRARY_VISIBILITY InstCombinerImpl final
   Instruction *foldICmpShlConstConst(ICmpInst &I, Value *ShAmt, const APInt &C1,
                                      const APInt &C2);
 
+  Instruction *foldICmpBinOpWithConstantViaTruthTable(ICmpInst &Cmp,
+                                                      BinaryOperator *BO,
+                                                      const APInt &C);
   Instruction *foldICmpBinOpEqualityWithConstant(ICmpInst &Cmp,
                                                  BinaryOperator *BO,
                                                  const APInt &C);
diff --git a/llvm/test/Transforms/InstCombine/icmp-binop.ll b/llvm/test/Transforms/InstCombine/icmp-binop.ll
index ce24a51dba04d..e240bf1cd95f9 100644
--- a/llvm/test/Transforms/InstCombine/icmp-binop.ll
+++ b/llvm/test/Transforms/InstCombine/icmp-binop.ll
@@ -362,10 +362,7 @@ define i1 @test_icmp_sgt_and_negpow2_invalid_c(i32 %add) {
 
 define i1 @icmp_eq_or_of_selects_with_constant(i1 %a, i1 %b) {
 ; CHECK-LABEL: @icmp_eq_or_of_selects_with_constant(
-; CHECK-NEXT:    [[S1:%.*]] = select i1 [[A:%.*]], i64 65536, i64 0
-; CHECK-NEXT:    [[S2:%.*]] = select i1 [[B:%.*]], i64 256, i64 0
-; CHECK-NEXT:    [[OR:%.*]] = or disjoint i64 [[S1]], [[S2]]
-; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i64 [[OR]], 65792
+; CHECK-NEXT:    [[CMP:%.*]] = and i1 [[A:%.*]], [[B:%.*]]
 ; CHECK-NEXT:    ret i1 [[CMP]]
 ;
   %s1 = select i1 %a, i64 65536, i64 0
@@ -377,10 +374,8 @@ define i1 @icmp_eq_or_of_selects_with_constant(i1 %a, i1 %b) {
 
 define i1 @icmp_slt_and_of_selects_with_constant(i1 %a, i1 %b) {
 ; CHECK-LABEL: @icmp_slt_and_of_selects_with_constant(
-; CHECK-NEXT:    [[S1:%.*]] = select i1 [[A:%.*]], i8 1, i8 -4
-; CHECK-NEXT:    [[S2:%.*]] = select i1 [[B:%.*]], i8 1, i8 -3
-; CHECK-NEXT:    [[AND:%.*]] = and i8 [[S1]], [[S2]]
-; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i8 [[AND]], -2
+; CHECK-NEXT:    [[TMP1:%.*]] = or i1 [[A:%.*]], [[B:%.*]]
+; CHECK-NEXT:    [[CMP:%.*]] = xor i1 [[TMP1]], true
 ; CHECK-NEXT:    ret i1 [[CMP]]
 ;
   %s1 = select i1 %a, i8 1, i8 254
@@ -392,11 +387,7 @@ define i1 @icmp_slt_and_of_selects_with_constant(i1 %a, i1 %b) {
 
 define i1 @icmp_sge_add_of_selects_with_constant(i1 %a, i1 %b) {
 ; CHECK-LABEL: @icmp_sge_add_of_selects_with_constant(
-; CHECK-NEXT:    [[S1:%.*]] = select i1 [[A:%.*]], i8 -8, i8 7
-; CHECK-NEXT:    [[S2:%.*]] = select i1 [[B:%.*]], i8 16, i8 0
-; CHECK-NEXT:    [[ADD:%.*]] = add nsw i8 [[S1]], [[S2]]
-; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i8 [[ADD]], -10
-; CHECK-NEXT:    ret i1 [[CMP]]
+; CHECK-NEXT:    ret i1 true
 ;
   %s1 = select i1 %a, i8 248, i8 7
   %s2 = select i1 %b, i8 16, i8 0
@@ -407,10 +398,7 @@ define i1 @icmp_sge_add_of_selects_with_constant(i1 %a, i1 %b) {
 
 define <2 x i1> @icmp_eq_or_of_selects_with_constant_vectorized(<2 x i1> %a, <2 x i1> %b) {
 ; CHECK-LABEL: @icmp_eq_or_of_selects_with_constant_vectorized(
-; CHECK-NEXT:    [[S1:%.*]] = select <2 x i1> [[A:%.*]], <2 x i64> splat (i64 65536), <2 x i64> zeroinitializer
-; CHECK-NEXT:    [[S2:%.*]] = select <2 x i1> [[B:%.*]], <2 x i64> splat (i64 256), <2 x i64> zeroinitializer
-; CHECK-NEXT:    [[OR:%.*]] = or disjoint <2 x i64> [[S1]], [[S2]]
-; CHECK-NEXT:    [[CMP:%.*]] = icmp eq <2 x i64> [[OR]], splat (i64 65792)
+; CHECK-NEXT:    [[CMP:%.*]] = and <2 x i1> [[A:%.*]], [[B:%.*]]
 ; CHECK-NEXT:    ret <2 x i1> [[CMP]]
 ;
   %s1 = select <2 x i1> %a, <2 x i64> <i64 65536, i64 65536>, <2 x i64> zeroinitializer
diff --git a/llvm/test/Transforms/InstCombine/icmp-select.ll b/llvm/test/Transforms/InstCombine/icmp-select.ll
index 1aae91302dab1..a038731abbc48 100644
--- a/llvm/test/Transforms/InstCombine/icmp-select.ll
+++ b/llvm/test/Transforms/InstCombine/icmp-select.ll
@@ -328,10 +328,7 @@ define i1 @select_constants_and_icmp_eq0_common_bit(i1 %x, i1 %y) {
 
 define i1 @select_constants_and_icmp_eq0_no_common_op1(i1 %x, i1 %y) {
 ; CHECK-LABEL: @select_constants_and_icmp_eq0_no_common_op1(
-; CHECK-NEXT:    [[S1:%.*]] = select i1 [[X:%.*]], i8 16, i8 3
-; CHECK-NEXT:    [[S2:%.*]] = select i1 [[Y:%.*]], i8 24, i8 3
-; CHECK-NEXT:    [[AND:%.*]] = and i8 [[S1]], [[S2]]
-; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i8 [[AND]], 0
+; CHECK-NEXT:    [[CMP:%.*]] = xor i1 [[X:%.*]], [[Y:%.*]]
 ; CHECK-NEXT:    ret i1 [[CMP]]
 ;
   %s1 = select i1 %x, i8 16, i8 3
@@ -345,10 +342,7 @@ define i1 @select_constants_and_icmp_eq0_no_common_op1(i1 %x, i1 %y) {
 
 define i1 @select_constants_and_icmp_eq0_no_common_op2(i1 %x, i1 %y) {
 ; CHECK-LABEL: @select_constants_and_icmp_eq0_no_common_op2(
-; CHECK-NEXT:    [[S1:%.*]] = select i1 [[X:%.*]], i8 16, i8 3
-; CHECK-NEXT:    [[S2:%.*]] = select i1 [[Y:%.*]], i8 16, i8 7
-; CHECK-NEXT:    [[AND:%.*]] = and i8 [[S1]], [[S2]]
-; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i8 [[AND]], 0
+; CHECK-NEXT:    [[CMP:%.*]] = xor i1 [[X:%.*]], [[Y:%.*]]
 ; CHECK-NEXT:    ret i1 [[CMP]]
 ;
   %s1 = select i1 %x, i8 16, i8 3
@@ -387,14 +381,9 @@ define i1 @select_constants_and_icmp_eq0_zero_fval(i1 %x, i1 %y) {
   ret i1 %cmp
 }
 
-; TODO: x & y
-
 define i1 @select_constants_and_icmp_eq_tval(i1 %x, i1 %y) {
 ; CHECK-LABEL: @select_constants_and_icmp_eq_tval(
-; CHECK-NEXT:    [[S1:%.*]] = select i1 [[X:%.*]], i8 6, i8 1
-; CHECK-NEXT:    [[S2:%.*]] = select i1 [[Y:%.*]], i8 6, i8 1
-; CHECK-NEXT:    [[AND:%.*]] = and i8 [[S1]], [[S2]]
-; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i8 [[AND]], 6
+; CHECK-NEXT:    [[CMP:%.*]] = and i1 [[X:%.*]], [[Y:%.*]]
 ; CHECK-NEXT:    ret i1 [[CMP]]
 ;
   %s1 = select i1 %x, i8 6, i8 1
@@ -404,14 +393,10 @@ define i1 @select_constants_and_icmp_eq_tval(i1 %x, i1 %y) {
   ret i1 %cmp
 }
 
-; TODO: ~(x | y)
-
 define i1 @select_constants_and_icmp_eq_fval(i1 %x, i1 %y) {
 ; CHECK-LABEL: @select_constants_and_icmp_eq_fval(
-; CHECK-NEXT:    [[S1:%.*]] = select i1 [[X:%.*]], i8 12, i8 3
-; CHECK-NEXT:    [[S2:%.*]] = select i1 [[Y:%.*]], i8 12, i8 3
-; CHECK-NEXT:    [[AND:%.*]] = and i8 [[S1]], [[S2]]
-; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i8 [[AND]], 3
+; CHECK-NEXT:    [[TMP1:%.*]] = or i1 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[CMP:%.*]] = xor i1 [[TMP1]], true
 ; CHECK-NEXT:    ret i1 [[CMP]]
 ;
   %s1 = select i1 %x, i8 12, i8 3
@@ -512,10 +497,8 @@ define i1 @select_constants_and_icmp_ne0_common_bit(i1 %x, i1 %y) {
 
 define i1 @select_constants_and_icmp_ne0_no_common_op1(i1 %x, i1 %y) {
 ; CHECK-LABEL: @select_constants_and_icmp_ne0_no_common_op1(
-; CHECK-NEXT:    [[S1:%.*]] = select i1 [[X:%.*]], i8 16, i8 3
-; CHECK-NEXT:    [[S2:%.*]] = select i1 [[Y:%.*]], i8 24, i8 3
-; CHECK-NEXT:    [[AND:%.*]] = and i8 [[S1]], [[S2]]
-; CHECK-NEXT:    [[CMP:%.*]] = icmp ne i8 [[AND]], 0
+; CHECK-NEXT:    [[TMP1:%.*]] = xor i1 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[CMP:%.*]] = xor i1 [[TMP1]], true
 ; CHECK-NEXT:    ret i1 [[CMP]]
 ;
   %s1 = select i1 %x, i8 16, i8 3
@@ -529,10 +512,8 @@ define i1 @select_constants_and_icmp_ne0_no_common_op1(i1 %x, i1 %y) {
 
 define i1 @select_constants_and_icmp_ne0_no_common_op2(i1 %x, i1 %y) {
 ; CHECK-LABEL: @select_constants_and_icmp_ne0_no_common_op2(
-; CHECK-NEXT:    [[S1:%.*]] = select i1 [[X:%.*]], i8 16, i8 3
-; CHECK-NEXT:    [[S2:%.*]] = select i1 [[Y:%.*]], i8 16, i8 7
-; CHECK-NEXT:    [[AND:%.*]] = and i8 [[S1]], [[S2]]
-; CHECK-NEXT:    [[CMP:%.*]] = icmp ne i8 [[AND]], 0
+; CHECK-NEXT:    [[TMP1:%.*]] = xor i1 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[CMP:%.*]] = xor i1 [[TMP1]], true
 ; CHECK-NEXT:    ret i1 [[CMP]]
 ;
   %s1 = select i1 %x, i8 16, i8 3
@@ -571,14 +552,10 @@ define i1 @select_constants_and_icmp_ne0_zero_fval(i1 %x, i1 %y) {
   ret i1 %cmp
 }
 
-; TODO: ~(x & y)
-
 define i1 @select_constants_and_icmp_ne_tval(i1 %x, i1 %y) {
 ; CHECK-LABEL: @select_constants_and_icmp_ne_tval(
-; CHECK-NEXT:    [[S1:%.*]] = select i1 [[X:%.*]], i8 6, i8 1
-; CHECK-NEXT:    [[S2:%.*]] = select i1 [[Y:%.*]], i8 6, i8 1
-; CHECK-NEXT:    [[AND:%.*]] = and i8 [[S1]], [[S2]]
-; CHECK-NEXT:    [[CMP:%.*]] = icmp ne i8 [[AND]], 6
+; CHECK-NEXT:    [[TMP1:%.*]] = and i1 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[CMP:%.*]] = xor i1 [[TMP1]], true
 ; CHECK-NEXT:    ret i1 [[CMP]]
 ;
   %s1 = select i1 %x, i8 6, i8 1
@@ -588,14 +565,9 @@ define i1 @select_constants_and_icmp_ne_tval(i1 %x, i1 %y) {
   ret i1 %cmp
 }
 
-; TODO: (x | y)
-
 define i1 @select_constants_and_icmp_ne_fval(i1 %x, i1 %y) {
 ; CHECK-LABEL: @select_constants_and_icmp_ne_fval(
-; CHECK-NEXT:    [[S1:%.*]] = select i1 [[X:%.*]], i8 12, i8 3
-; CHECK-NEXT:    [[S2:%.*]] = select i1 [[Y:%.*]], i8 12, i8 3
-; CHECK-NEXT:    [[AND:%.*]] = and i8 [[S1]], [[S2]]
-; CHECK-NEXT:    [[CMP:%.*]] = icmp ne i8 [[AND]], 3
+; CHECK-NEXT:    [[CMP:%.*]] = or i1 [[X:%.*]], [[Y:%.*]]
 ; CHECK-NEXT:    ret i1 [[CMP]]
 ;
   %s1 = select i1 %x, i8 12, i8 3



More information about the llvm-commits mailing list