[InstCombine] Fold nested selects
authorRoman Lebedev <lebedev.ri@gmail.com>
Sat, 10 Dec 2022 21:51:03 +0000 (00:51 +0300)
committerRoman Lebedev <lebedev.ri@gmail.com>
Sat, 10 Dec 2022 22:00:31 +0000 (01:00 +0300)
https://alive2.llvm.org/ce/z/GjCXkB
https://alive2.llvm.org/ce/z/Guz2tt

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

llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
llvm/test/Transforms/InstCombine/nested-select.ll
llvm/test/Transforms/InstCombine/select-factorize.ll

index 0633388..b832857 100644 (file)
@@ -2669,6 +2669,80 @@ foldRoundUpIntegerWithPow2Alignment(SelectInst &SI,
   return R;
 }
 
+/// Look for patterns like
+///   %outer.cond = select i1 %inner.cond, i1 %alt.cond, i1 false
+///   %inner.sel = select i1 %inner.cond, i8 %inner.sel.t, i8 %inner.sel.f
+///   %outer.sel = select i1 %outer.cond, i8 %outer.sel.t, i8 %inner.sel
+/// and rewrite it as
+///   %inner.sel = select i1 %cond.alternative, i8 %sel.outer.t, i8 %sel.inner.t
+///   %sel.outer = select i1 %cond.inner, i8 %inner.sel, i8 %sel.inner.f
+static Instruction *foldNestedSelects(SelectInst &OuterSel,
+                                      InstCombiner::BuilderTy &Builder) {
+  // We must start with a `select`.
+  Value *OuterCond, *InnerSel, *OuterSelFalseVal;
+  match(&OuterSel, m_Select(m_Value(OuterCond), m_Value(InnerSel),
+                            m_Value(OuterSelFalseVal)));
+
+  // Canonicalize inversion of the outermost `select`'s condition.
+  if (match(OuterCond, m_Not(m_Value(OuterCond))))
+    std::swap(InnerSel, OuterSelFalseVal);
+
+  auto m_c_LogicalOp = [](auto L, auto R) {
+    return m_CombineOr(m_c_LogicalAnd(L, R), m_c_LogicalOr(L, R));
+  };
+
+  // The condition of the outermost select must be an `and`/`or`.
+  if (!match(OuterCond, m_c_LogicalOp(m_Value(), m_Value())))
+    return nullptr;
+
+  // To simplify logic, prefer the pattern variant with an `or`.
+  bool IsAndVariant = match(OuterCond, m_LogicalAnd());
+  if (match(OuterCond, m_LogicalAnd()))
+    std::swap(InnerSel, OuterSelFalseVal);
+
+  // Profitability check - avoid increasing instruction count.
+  if (none_of(ArrayRef<Value *>({OuterCond, InnerSel}),
+              [](Value *V) { return V->hasOneUse(); }))
+    return nullptr;
+
+  // The appropriate hand of the outermost `select` must be a select itself.
+  Value *InnerCond, *InnerSelTrueVal, *InnerSelFalseVal;
+  if (!match(InnerSel, m_Select(m_Value(InnerCond), m_Value(InnerSelTrueVal),
+                                m_Value(InnerSelFalseVal))))
+    return nullptr;
+
+  // Canonicalize inversion of the innermost `select`'s condition.
+  if (match(InnerCond, m_Not(m_Value(InnerCond))))
+    std::swap(InnerSelTrueVal, InnerSelFalseVal);
+
+  Value *AltCond = nullptr;
+  auto matchOuterCond = [OuterCond, m_c_LogicalOp, &AltCond](auto m_InnerCond) {
+    return match(OuterCond, m_c_LogicalOp(m_InnerCond, m_Value(AltCond)));
+  };
+
+  // Finally, match the condition that was driving the outermost `select`,
+  // it should be a logical operation between the condition that was driving
+  // the innermost `select` (after accounting for the possible inversions
+  // of the condition), and some other condition.
+  if (matchOuterCond(m_Specific(InnerCond))) {
+    // Done!
+  } else if (Value * NotInnerCond; matchOuterCond(m_CombineAnd(
+                 m_Not(m_Specific(InnerCond)), m_Value(NotInnerCond)))) {
+    // Done!
+    std::swap(InnerSelTrueVal, InnerSelFalseVal);
+    InnerCond = NotInnerCond;
+  } else // Not the pattern we were looking for.
+    return nullptr;
+
+  Value *SelInner = Builder.CreateSelect(
+      AltCond, IsAndVariant ? OuterSelFalseVal : InnerSelFalseVal,
+      IsAndVariant ? InnerSelTrueVal : OuterSelFalseVal);
+  SelInner->takeName(InnerSel);
+  return SelectInst::Create(InnerCond,
+                            IsAndVariant ? SelInner : InnerSelTrueVal,
+                            IsAndVariant ? InnerSelFalseVal : SelInner);
+}
+
 Instruction *InstCombinerImpl::foldSelectOfBools(SelectInst &SI) {
   Value *CondVal = SI.getCondition();
   Value *TrueVal = SI.getTrueValue();
@@ -3292,5 +3366,8 @@ Instruction *InstCombinerImpl::visitSelectInst(SelectInst &SI) {
     }
   }
 
+  if (Instruction *I = foldNestedSelects(SI, Builder))
+    return I;
+
   return nullptr;
 }
index 6a40de6..2f4e911 100644 (file)
@@ -8,9 +8,8 @@ declare void @use.i8(i8)
 
 define i8 @andcond(i1 %inner.cond, i1 %alt.cond, i8 %inner.sel.trueval, i8 %inner.sel.falseval, i8 %outer.sel.trueval) {
 ; CHECK-LABEL: @andcond(
-; CHECK-NEXT:    [[OUTER_COND:%.*]] = select i1 [[INNER_COND:%.*]], i1 [[ALT_COND:%.*]], i1 false
-; CHECK-NEXT:    [[INNER_SEL:%.*]] = select i1 [[INNER_COND]], i8 [[INNER_SEL_TRUEVAL:%.*]], i8 [[INNER_SEL_FALSEVAL:%.*]]
-; CHECK-NEXT:    [[OUTER_SEL:%.*]] = select i1 [[OUTER_COND]], i8 [[OUTER_SEL_TRUEVAL:%.*]], i8 [[INNER_SEL]]
+; CHECK-NEXT:    [[INNER_SEL:%.*]] = select i1 [[ALT_COND:%.*]], i8 [[OUTER_SEL_TRUEVAL:%.*]], i8 [[INNER_SEL_TRUEVAL:%.*]]
+; CHECK-NEXT:    [[OUTER_SEL:%.*]] = select i1 [[INNER_COND:%.*]], i8 [[INNER_SEL]], i8 [[INNER_SEL_FALSEVAL:%.*]]
 ; CHECK-NEXT:    ret i8 [[OUTER_SEL]]
 ;
   %outer.cond = select i1 %inner.cond, i1 %alt.cond, i1 false ; and %inner.cond, %alt.cond
@@ -20,9 +19,8 @@ define i8 @andcond(i1 %inner.cond, i1 %alt.cond, i8 %inner.sel.trueval, i8 %inne
 }
 define i8 @orcond(i1 %inner.cond, i1 %alt.cond, i8 %inner.sel.trueval, i8 %inner.sel.falseval, i8 %outer.sel.falseval) {
 ; CHECK-LABEL: @orcond(
-; CHECK-NEXT:    [[OUTER_COND:%.*]] = select i1 [[INNER_COND:%.*]], i1 true, i1 [[ALT_COND:%.*]]
-; CHECK-NEXT:    [[INNER_SEL:%.*]] = select i1 [[INNER_COND]], i8 [[INNER_SEL_TRUEVAL:%.*]], i8 [[INNER_SEL_FALSEVAL:%.*]]
-; CHECK-NEXT:    [[OUTER_SEL:%.*]] = select i1 [[OUTER_COND]], i8 [[INNER_SEL]], i8 [[OUTER_SEL_FALSEVAL:%.*]]
+; CHECK-NEXT:    [[INNER_SEL:%.*]] = select i1 [[ALT_COND:%.*]], i8 [[INNER_SEL_FALSEVAL:%.*]], i8 [[OUTER_SEL_FALSEVAL:%.*]]
+; CHECK-NEXT:    [[OUTER_SEL:%.*]] = select i1 [[INNER_COND:%.*]], i8 [[INNER_SEL_TRUEVAL:%.*]], i8 [[INNER_SEL]]
 ; CHECK-NEXT:    ret i8 [[OUTER_SEL]]
 ;
   %outer.cond = select i1 %inner.cond, i1 true, i1 %alt.cond ; or %inner.cond, %alt.cond
@@ -37,8 +35,8 @@ define i8 @andcond.extrause0(i1 %inner.cond, i1 %alt.cond, i8 %inner.sel.trueval
 ; CHECK-LABEL: @andcond.extrause0(
 ; CHECK-NEXT:    [[OUTER_COND:%.*]] = select i1 [[INNER_COND:%.*]], i1 [[ALT_COND:%.*]], i1 false
 ; CHECK-NEXT:    call void @use.i1(i1 [[OUTER_COND]])
-; CHECK-NEXT:    [[INNER_SEL:%.*]] = select i1 [[INNER_COND]], i8 [[INNER_SEL_TRUEVAL:%.*]], i8 [[INNER_SEL_FALSEVAL:%.*]]
-; CHECK-NEXT:    [[OUTER_SEL:%.*]] = select i1 [[OUTER_COND]], i8 [[OUTER_SEL_TRUEVAL:%.*]], i8 [[INNER_SEL]]
+; CHECK-NEXT:    [[INNER_SEL:%.*]] = select i1 [[ALT_COND]], i8 [[OUTER_SEL_TRUEVAL:%.*]], i8 [[INNER_SEL_TRUEVAL:%.*]]
+; CHECK-NEXT:    [[OUTER_SEL:%.*]] = select i1 [[INNER_COND]], i8 [[INNER_SEL]], i8 [[INNER_SEL_FALSEVAL:%.*]]
 ; CHECK-NEXT:    ret i8 [[OUTER_SEL]]
 ;
   %outer.cond = select i1 %inner.cond, i1 %alt.cond, i1 false
@@ -51,8 +49,8 @@ define i8 @orcond.extrause0(i1 %inner.cond, i1 %alt.cond, i8 %inner.sel.trueval,
 ; CHECK-LABEL: @orcond.extrause0(
 ; CHECK-NEXT:    [[OUTER_COND:%.*]] = select i1 [[INNER_COND:%.*]], i1 true, i1 [[ALT_COND:%.*]]
 ; CHECK-NEXT:    call void @use.i1(i1 [[OUTER_COND]])
-; CHECK-NEXT:    [[INNER_SEL:%.*]] = select i1 [[INNER_COND]], i8 [[INNER_SEL_TRUEVAL:%.*]], i8 [[INNER_SEL_FALSEVAL:%.*]]
-; CHECK-NEXT:    [[OUTER_SEL:%.*]] = select i1 [[OUTER_COND]], i8 [[INNER_SEL]], i8 [[OUTER_SEL_FALSEVAL:%.*]]
+; CHECK-NEXT:    [[INNER_SEL:%.*]] = select i1 [[ALT_COND]], i8 [[INNER_SEL_FALSEVAL:%.*]], i8 [[OUTER_SEL_FALSEVAL:%.*]]
+; CHECK-NEXT:    [[OUTER_SEL:%.*]] = select i1 [[INNER_COND]], i8 [[INNER_SEL_TRUEVAL:%.*]], i8 [[INNER_SEL]]
 ; CHECK-NEXT:    ret i8 [[OUTER_SEL]]
 ;
   %outer.cond = select i1 %inner.cond, i1 true, i1 %alt.cond
@@ -64,10 +62,10 @@ define i8 @orcond.extrause0(i1 %inner.cond, i1 %alt.cond, i8 %inner.sel.trueval,
 
 define i8 @andcond.extrause1(i1 %inner.cond, i1 %alt.cond, i8 %inner.sel.trueval, i8 %inner.sel.falseval, i8 %outer.sel.trueval) {
 ; CHECK-LABEL: @andcond.extrause1(
-; CHECK-NEXT:    [[OUTER_COND:%.*]] = select i1 [[INNER_COND:%.*]], i1 [[ALT_COND:%.*]], i1 false
-; CHECK-NEXT:    [[INNER_SEL:%.*]] = select i1 [[INNER_COND]], i8 [[INNER_SEL_TRUEVAL:%.*]], i8 [[INNER_SEL_FALSEVAL:%.*]]
-; CHECK-NEXT:    call void @use.i8(i8 [[INNER_SEL]])
-; CHECK-NEXT:    [[OUTER_SEL:%.*]] = select i1 [[OUTER_COND]], i8 [[OUTER_SEL_TRUEVAL:%.*]], i8 [[INNER_SEL]]
+; CHECK-NEXT:    [[TMP1:%.*]] = select i1 [[INNER_COND:%.*]], i8 [[INNER_SEL_TRUEVAL:%.*]], i8 [[INNER_SEL_FALSEVAL:%.*]]
+; CHECK-NEXT:    call void @use.i8(i8 [[TMP1]])
+; CHECK-NEXT:    [[INNER_SEL:%.*]] = select i1 [[ALT_COND:%.*]], i8 [[OUTER_SEL_TRUEVAL:%.*]], i8 [[INNER_SEL_TRUEVAL]]
+; CHECK-NEXT:    [[OUTER_SEL:%.*]] = select i1 [[INNER_COND]], i8 [[INNER_SEL]], i8 [[INNER_SEL_FALSEVAL]]
 ; CHECK-NEXT:    ret i8 [[OUTER_SEL]]
 ;
   %outer.cond = select i1 %inner.cond, i1 %alt.cond, i1 false
@@ -78,10 +76,10 @@ define i8 @andcond.extrause1(i1 %inner.cond, i1 %alt.cond, i8 %inner.sel.trueval
 }
 define i8 @orcond.extrause1(i1 %inner.cond, i1 %alt.cond, i8 %inner.sel.trueval, i8 %inner.sel.falseval, i8 %outer.sel.falseval) {
 ; CHECK-LABEL: @orcond.extrause1(
-; CHECK-NEXT:    [[OUTER_COND:%.*]] = select i1 [[INNER_COND:%.*]], i1 true, i1 [[ALT_COND:%.*]]
-; CHECK-NEXT:    [[INNER_SEL:%.*]] = select i1 [[INNER_COND]], i8 [[INNER_SEL_TRUEVAL:%.*]], i8 [[INNER_SEL_FALSEVAL:%.*]]
-; CHECK-NEXT:    call void @use.i8(i8 [[INNER_SEL]])
-; CHECK-NEXT:    [[OUTER_SEL:%.*]] = select i1 [[OUTER_COND]], i8 [[INNER_SEL]], i8 [[OUTER_SEL_FALSEVAL:%.*]]
+; CHECK-NEXT:    [[TMP1:%.*]] = select i1 [[INNER_COND:%.*]], i8 [[INNER_SEL_TRUEVAL:%.*]], i8 [[INNER_SEL_FALSEVAL:%.*]]
+; CHECK-NEXT:    call void @use.i8(i8 [[TMP1]])
+; CHECK-NEXT:    [[INNER_SEL:%.*]] = select i1 [[ALT_COND:%.*]], i8 [[INNER_SEL_FALSEVAL]], i8 [[OUTER_SEL_FALSEVAL:%.*]]
+; CHECK-NEXT:    [[OUTER_SEL:%.*]] = select i1 [[INNER_COND]], i8 [[INNER_SEL_TRUEVAL]], i8 [[INNER_SEL]]
 ; CHECK-NEXT:    ret i8 [[OUTER_SEL]]
 ;
   %outer.cond = select i1 %inner.cond, i1 true, i1 %alt.cond
@@ -248,10 +246,9 @@ define i1 @orcond.different.inner.cond.inverted.in.inner.sel(i1 %inner.cond.v0,
 ; In %outer.sel, %outer.cond is inverted
 define i1 @andcond.001.inv.outer.cond(i1 %inner.cond, i1 %alt.cond, i1 %inner.sel.trueval, i1 %inner.sel.falseval, i1 %outer.sel.trueval) {
 ; CHECK-LABEL: @andcond.001.inv.outer.cond(
-; CHECK-NEXT:    [[OUTER_COND:%.*]] = select i1 [[INNER_COND:%.*]], i1 [[ALT_COND:%.*]], i1 false
-; CHECK-NEXT:    [[INNER_SEL:%.*]] = select i1 [[INNER_COND]], i1 [[INNER_SEL_TRUEVAL:%.*]], i1 [[INNER_SEL_FALSEVAL:%.*]]
-; CHECK-NEXT:    [[NOT_OUTER_COND:%.*]] = xor i1 [[OUTER_COND]], true
-; CHECK-NEXT:    [[OUTER_SEL:%.*]] = select i1 [[NOT_OUTER_COND]], i1 [[INNER_SEL]], i1 false
+; CHECK-NEXT:    [[NOT_ALT_COND:%.*]] = xor i1 [[ALT_COND:%.*]], true
+; CHECK-NEXT:    [[INNER_SEL:%.*]] = select i1 [[NOT_ALT_COND]], i1 [[INNER_SEL_TRUEVAL:%.*]], i1 false
+; CHECK-NEXT:    [[OUTER_SEL:%.*]] = select i1 [[INNER_COND:%.*]], i1 [[INNER_SEL]], i1 [[INNER_SEL_FALSEVAL:%.*]]
 ; CHECK-NEXT:    ret i1 [[OUTER_SEL]]
 ;
   %outer.cond = select i1 %inner.cond, i1 %alt.cond, i1 false ; and %inner.cond, %alt.cond
@@ -262,10 +259,9 @@ define i1 @andcond.001.inv.outer.cond(i1 %inner.cond, i1 %alt.cond, i1 %inner.se
 }
 define i1 @orcond.001.inv.outer.cond(i1 %inner.cond, i1 %alt.cond, i1 %inner.sel.trueval, i1 %inner.sel.falseval, i1 %outer.sel.falseval) {
 ; CHECK-LABEL: @orcond.001.inv.outer.cond(
-; CHECK-NEXT:    [[OUTER_COND:%.*]] = select i1 [[INNER_COND:%.*]], i1 true, i1 [[ALT_COND:%.*]]
-; CHECK-NEXT:    [[INNER_SEL:%.*]] = select i1 [[INNER_COND]], i1 [[INNER_SEL_TRUEVAL:%.*]], i1 [[INNER_SEL_FALSEVAL:%.*]]
-; CHECK-NEXT:    [[NOT_OUTER_COND:%.*]] = xor i1 [[OUTER_COND]], true
-; CHECK-NEXT:    [[OUTER_SEL:%.*]] = select i1 [[NOT_OUTER_COND]], i1 true, i1 [[INNER_SEL]]
+; CHECK-NEXT:    [[NOT_ALT_COND:%.*]] = xor i1 [[ALT_COND:%.*]], true
+; CHECK-NEXT:    [[INNER_SEL:%.*]] = select i1 [[NOT_ALT_COND]], i1 true, i1 [[INNER_SEL_FALSEVAL:%.*]]
+; CHECK-NEXT:    [[OUTER_SEL:%.*]] = select i1 [[INNER_COND:%.*]], i1 [[INNER_SEL_TRUEVAL:%.*]], i1 [[INNER_SEL]]
 ; CHECK-NEXT:    ret i1 [[OUTER_SEL]]
 ;
   %outer.cond = select i1 %inner.cond, i1 true, i1 %alt.cond ; or %inner.cond, %alt.cond
@@ -278,10 +274,8 @@ define i1 @orcond.001.inv.outer.cond(i1 %inner.cond, i1 %alt.cond, i1 %inner.sel
 ; In %inner.sel, %inner.cond is inverted
 define i1 @andcond.010.inv.inner.cond.in.inner.sel(i1 %inner.cond, i1 %alt.cond, i1 %inner.sel.trueval, i1 %inner.sel.falseval, i1 %outer.sel.trueval) {
 ; CHECK-LABEL: @andcond.010.inv.inner.cond.in.inner.sel(
-; CHECK-NEXT:    [[OUTER_COND:%.*]] = select i1 [[INNER_COND:%.*]], i1 [[ALT_COND:%.*]], i1 false
-; CHECK-NEXT:    [[NOT_INNER_COND:%.*]] = xor i1 [[INNER_COND]], true
-; CHECK-NEXT:    [[INNER_SEL:%.*]] = select i1 [[NOT_INNER_COND]], i1 [[INNER_SEL_FALSEVAL:%.*]], i1 false
-; CHECK-NEXT:    [[OUTER_SEL:%.*]] = select i1 [[OUTER_COND]], i1 [[OUTER_SEL_TRUEVAL:%.*]], i1 [[INNER_SEL]]
+; CHECK-NEXT:    [[INNER_SEL:%.*]] = select i1 [[ALT_COND:%.*]], i1 [[OUTER_SEL_TRUEVAL:%.*]], i1 false
+; CHECK-NEXT:    [[OUTER_SEL:%.*]] = select i1 [[INNER_COND:%.*]], i1 [[INNER_SEL]], i1 [[INNER_SEL_FALSEVAL:%.*]]
 ; CHECK-NEXT:    ret i1 [[OUTER_SEL]]
 ;
   %outer.cond = select i1 %inner.cond, i1 %alt.cond, i1 false ; and %inner.cond, %alt.cond
@@ -292,10 +286,8 @@ define i1 @andcond.010.inv.inner.cond.in.inner.sel(i1 %inner.cond, i1 %alt.cond,
 }
 define i1 @orcond.010.inv.inner.cond.in.inner.sel(i1 %inner.cond, i1 %alt.cond, i1 %inner.sel.trueval, i1 %inner.sel.falseval, i1 %outer.sel.falseval) {
 ; CHECK-LABEL: @orcond.010.inv.inner.cond.in.inner.sel(
-; CHECK-NEXT:    [[OUTER_COND:%.*]] = select i1 [[INNER_COND:%.*]], i1 true, i1 [[ALT_COND:%.*]]
-; CHECK-NEXT:    [[NOT_INNER_COND:%.*]] = xor i1 [[INNER_COND]], true
-; CHECK-NEXT:    [[INNER_SEL:%.*]] = select i1 [[NOT_INNER_COND]], i1 true, i1 [[INNER_SEL_TRUEVAL:%.*]]
-; CHECK-NEXT:    [[OUTER_SEL:%.*]] = select i1 [[OUTER_COND]], i1 [[INNER_SEL]], i1 [[OUTER_SEL_FALSEVAL:%.*]]
+; CHECK-NEXT:    [[INNER_SEL:%.*]] = select i1 [[ALT_COND:%.*]], i1 true, i1 [[OUTER_SEL_FALSEVAL:%.*]]
+; CHECK-NEXT:    [[OUTER_SEL:%.*]] = select i1 [[INNER_COND:%.*]], i1 [[INNER_SEL_TRUEVAL:%.*]], i1 [[INNER_SEL]]
 ; CHECK-NEXT:    ret i1 [[OUTER_SEL]]
 ;
   %outer.cond = select i1 %inner.cond, i1 true, i1 %alt.cond ; or %inner.cond, %alt.cond
@@ -308,10 +300,8 @@ define i1 @orcond.010.inv.inner.cond.in.inner.sel(i1 %inner.cond, i1 %alt.cond,
 ; In %outer.cond, %inner.cond is inverted
 define i8 @andcond.100.inv.inner.cond.in.outer.cond(i1 %inner.cond, i1 %alt.cond, i8 %inner.sel.trueval, i8 %inner.sel.falseval, i8 %outer.sel.trueval) {
 ; CHECK-LABEL: @andcond.100.inv.inner.cond.in.outer.cond(
-; CHECK-NEXT:    [[NOT_INNER_COND:%.*]] = xor i1 [[INNER_COND:%.*]], true
-; CHECK-NEXT:    [[OUTER_COND:%.*]] = select i1 [[NOT_INNER_COND]], i1 [[ALT_COND:%.*]], i1 false
-; CHECK-NEXT:    [[INNER_SEL:%.*]] = select i1 [[INNER_COND]], i8 [[INNER_SEL_TRUEVAL:%.*]], i8 [[INNER_SEL_FALSEVAL:%.*]]
-; CHECK-NEXT:    [[OUTER_SEL:%.*]] = select i1 [[OUTER_COND]], i8 [[OUTER_SEL_TRUEVAL:%.*]], i8 [[INNER_SEL]]
+; CHECK-NEXT:    [[INNER_SEL:%.*]] = select i1 [[ALT_COND:%.*]], i8 [[OUTER_SEL_TRUEVAL:%.*]], i8 [[INNER_SEL_FALSEVAL:%.*]]
+; CHECK-NEXT:    [[OUTER_SEL:%.*]] = select i1 [[INNER_COND:%.*]], i8 [[INNER_SEL_TRUEVAL:%.*]], i8 [[INNER_SEL]]
 ; CHECK-NEXT:    ret i8 [[OUTER_SEL]]
 ;
   %not.inner.cond = xor i1 %inner.cond, -1
@@ -322,10 +312,8 @@ define i8 @andcond.100.inv.inner.cond.in.outer.cond(i1 %inner.cond, i1 %alt.cond
 }
 define i8 @orcond.100.inv.inner.cond.in.outer.cond(i1 %inner.cond, i1 %alt.cond, i8 %inner.sel.trueval, i8 %inner.sel.falseval, i8 %outer.sel.falseval) {
 ; CHECK-LABEL: @orcond.100.inv.inner.cond.in.outer.cond(
-; CHECK-NEXT:    [[NOT_INNER_COND:%.*]] = xor i1 [[INNER_COND:%.*]], true
-; CHECK-NEXT:    [[OUTER_COND:%.*]] = select i1 [[NOT_INNER_COND]], i1 true, i1 [[ALT_COND:%.*]]
-; CHECK-NEXT:    [[INNER_SEL:%.*]] = select i1 [[INNER_COND]], i8 [[INNER_SEL_TRUEVAL:%.*]], i8 [[INNER_SEL_FALSEVAL:%.*]]
-; CHECK-NEXT:    [[OUTER_SEL:%.*]] = select i1 [[OUTER_COND]], i8 [[INNER_SEL]], i8 [[OUTER_SEL_FALSEVAL:%.*]]
+; CHECK-NEXT:    [[INNER_SEL:%.*]] = select i1 [[ALT_COND:%.*]], i8 [[INNER_SEL_TRUEVAL:%.*]], i8 [[OUTER_SEL_FALSEVAL:%.*]]
+; CHECK-NEXT:    [[OUTER_SEL:%.*]] = select i1 [[INNER_COND:%.*]], i8 [[INNER_SEL]], i8 [[INNER_SEL_FALSEVAL:%.*]]
 ; CHECK-NEXT:    ret i8 [[OUTER_SEL]]
 ;
   %not.inner.cond = xor i1 %inner.cond, -1
@@ -339,12 +327,13 @@ define i8 @orcond.100.inv.inner.cond.in.outer.cond(i1 %inner.cond, i1 %alt.cond,
 ; In %inner.sel, %inner.cond is inverted
 define i1 @andcond.011.inv.outer.cond.inv.inner.cond.in.inner.sel(i1 %inner.cond, i1 %alt.cond, i1 %inner.sel.trueval, i1 %inner.sel.falseval, i1 %outer.sel.trueval) {
 ; CHECK-LABEL: @andcond.011.inv.outer.cond.inv.inner.cond.in.inner.sel(
-; CHECK-NEXT:    [[OUTER_COND:%.*]] = select i1 [[INNER_COND:%.*]], i1 [[ALT_COND:%.*]], i1 false
-; CHECK-NEXT:    [[NOT_INNER_COND:%.*]] = xor i1 [[INNER_COND]], true
-; CHECK-NEXT:    [[INNER_SEL:%.*]] = select i1 [[NOT_INNER_COND]], i1 true, i1 [[INNER_SEL_FALSEVAL:%.*]]
-; CHECK-NEXT:    [[NOT_OUTER_COND:%.*]] = xor i1 [[OUTER_COND]], true
-; CHECK-NEXT:    call void @use.i1(i1 [[INNER_SEL]])
-; CHECK-NEXT:    [[OUTER_SEL:%.*]] = select i1 [[NOT_OUTER_COND]], i1 [[INNER_SEL]], i1 false
+; CHECK-NEXT:    [[NOT_INNER_COND:%.*]] = xor i1 [[INNER_COND:%.*]], true
+; CHECK-NEXT:    [[TMP1:%.*]] = select i1 [[NOT_INNER_COND]], i1 true, i1 [[INNER_SEL_FALSEVAL:%.*]]
+; CHECK-NEXT:    call void @use.i1(i1 [[TMP1]])
+; CHECK-NEXT:    [[NOT_ALT_COND:%.*]] = xor i1 [[ALT_COND:%.*]], true
+; CHECK-NEXT:    [[INNER_SEL:%.*]] = select i1 [[NOT_ALT_COND]], i1 [[INNER_SEL_FALSEVAL]], i1 false
+; CHECK-NEXT:    [[NOT_INNER_COND1:%.*]] = xor i1 [[INNER_COND]], true
+; CHECK-NEXT:    [[OUTER_SEL:%.*]] = select i1 [[NOT_INNER_COND1]], i1 true, i1 [[INNER_SEL]]
 ; CHECK-NEXT:    ret i1 [[OUTER_SEL]]
 ;
   %outer.cond = select i1 %inner.cond, i1 %alt.cond, i1 false ; and %inner.cond, %alt.cond
@@ -357,12 +346,13 @@ define i1 @andcond.011.inv.outer.cond.inv.inner.cond.in.inner.sel(i1 %inner.cond
 }
 define i1 @orcond.011.inv.outer.cond.inv.inner.cond.in.inner.sel(i1 %inner.cond, i1 %alt.cond, i1 %inner.sel.trueval, i1 %inner.sel.falseval, i1 %outer.sel.falseval) {
 ; CHECK-LABEL: @orcond.011.inv.outer.cond.inv.inner.cond.in.inner.sel(
-; CHECK-NEXT:    [[OUTER_COND:%.*]] = select i1 [[INNER_COND:%.*]], i1 true, i1 [[ALT_COND:%.*]]
-; CHECK-NEXT:    [[NOT_INNER_COND:%.*]] = xor i1 [[INNER_COND]], true
-; CHECK-NEXT:    [[INNER_SEL:%.*]] = select i1 [[NOT_INNER_COND]], i1 [[INNER_SEL_TRUEVAL:%.*]], i1 false
-; CHECK-NEXT:    call void @use.i1(i1 [[INNER_SEL]])
-; CHECK-NEXT:    [[NOT_OUTER_COND:%.*]] = xor i1 [[OUTER_COND]], true
-; CHECK-NEXT:    [[OUTER_SEL:%.*]] = select i1 [[NOT_OUTER_COND]], i1 true, i1 [[INNER_SEL]]
+; CHECK-NEXT:    [[NOT_INNER_COND:%.*]] = xor i1 [[INNER_COND:%.*]], true
+; CHECK-NEXT:    [[TMP1:%.*]] = select i1 [[NOT_INNER_COND]], i1 [[INNER_SEL_TRUEVAL:%.*]], i1 false
+; CHECK-NEXT:    call void @use.i1(i1 [[TMP1]])
+; CHECK-NEXT:    [[NOT_ALT_COND:%.*]] = xor i1 [[ALT_COND:%.*]], true
+; CHECK-NEXT:    [[INNER_SEL:%.*]] = select i1 [[NOT_ALT_COND]], i1 true, i1 [[INNER_SEL_TRUEVAL]]
+; CHECK-NEXT:    [[NOT_INNER_COND1:%.*]] = xor i1 [[INNER_COND]], true
+; CHECK-NEXT:    [[OUTER_SEL:%.*]] = select i1 [[NOT_INNER_COND1]], i1 [[INNER_SEL]], i1 false
 ; CHECK-NEXT:    ret i1 [[OUTER_SEL]]
 ;
   %outer.cond = select i1 %inner.cond, i1 true, i1 %alt.cond ; or %inner.cond, %alt.cond
@@ -378,11 +368,11 @@ define i1 @orcond.011.inv.outer.cond.inv.inner.cond.in.inner.sel(i1 %inner.cond,
 ; In %outer.cond, %inner.cond is inverted
 define i1 @andcond.101.inv.outer.cond.inv.inner.cond.in.outer.cond(i1 %inner.cond, i1 %alt.cond, i1 %inner.sel.trueval, i1 %inner.sel.falseval, i1 %outer.sel.trueval) {
 ; CHECK-LABEL: @andcond.101.inv.outer.cond.inv.inner.cond.in.outer.cond(
-; CHECK-NEXT:    [[INNER_SEL:%.*]] = select i1 [[INNER_COND:%.*]], i1 [[INNER_SEL_TRUEVAL:%.*]], i1 [[INNER_SEL_FALSEVAL:%.*]]
-; CHECK-NEXT:    call void @use.i1(i1 [[INNER_SEL]])
+; CHECK-NEXT:    [[TMP1:%.*]] = select i1 [[INNER_COND:%.*]], i1 [[INNER_SEL_TRUEVAL:%.*]], i1 [[INNER_SEL_FALSEVAL:%.*]]
+; CHECK-NEXT:    call void @use.i1(i1 [[TMP1]])
 ; CHECK-NEXT:    [[ALT_COND_NOT:%.*]] = xor i1 [[ALT_COND:%.*]], true
-; CHECK-NEXT:    [[NOT_OUTER_COND:%.*]] = select i1 [[INNER_COND]], i1 true, i1 [[ALT_COND_NOT]]
-; CHECK-NEXT:    [[OUTER_SEL:%.*]] = select i1 [[NOT_OUTER_COND]], i1 [[INNER_SEL]], i1 false
+; CHECK-NEXT:    [[INNER_SEL:%.*]] = select i1 [[ALT_COND_NOT]], i1 [[INNER_SEL_FALSEVAL]], i1 false
+; CHECK-NEXT:    [[OUTER_SEL:%.*]] = select i1 [[INNER_COND]], i1 [[INNER_SEL_TRUEVAL]], i1 [[INNER_SEL]]
 ; CHECK-NEXT:    ret i1 [[OUTER_SEL]]
 ;
   %not.inner.cond = xor i1 %inner.cond, -1
@@ -395,11 +385,11 @@ define i1 @andcond.101.inv.outer.cond.inv.inner.cond.in.outer.cond(i1 %inner.con
 }
 define i1 @orcond.101.inv.outer.cond.inv.inner.cond.in.outer.cond(i1 %inner.cond, i1 %alt.cond, i1 %inner.sel.trueval, i1 %inner.sel.falseval, i1 %outer.sel.falseval) {
 ; CHECK-LABEL: @orcond.101.inv.outer.cond.inv.inner.cond.in.outer.cond(
-; CHECK-NEXT:    [[INNER_SEL:%.*]] = select i1 [[INNER_COND:%.*]], i1 [[INNER_SEL_TRUEVAL:%.*]], i1 [[INNER_SEL_FALSEVAL:%.*]]
-; CHECK-NEXT:    call void @use.i1(i1 [[INNER_SEL]])
+; CHECK-NEXT:    [[TMP1:%.*]] = select i1 [[INNER_COND:%.*]], i1 [[INNER_SEL_TRUEVAL:%.*]], i1 [[INNER_SEL_FALSEVAL:%.*]]
+; CHECK-NEXT:    call void @use.i1(i1 [[TMP1]])
 ; CHECK-NEXT:    [[ALT_COND_NOT:%.*]] = xor i1 [[ALT_COND:%.*]], true
-; CHECK-NEXT:    [[NOT_OUTER_COND:%.*]] = select i1 [[INNER_COND]], i1 [[ALT_COND_NOT]], i1 false
-; CHECK-NEXT:    [[OUTER_SEL:%.*]] = select i1 [[NOT_OUTER_COND]], i1 true, i1 [[INNER_SEL]]
+; CHECK-NEXT:    [[INNER_SEL:%.*]] = select i1 [[ALT_COND_NOT]], i1 true, i1 [[INNER_SEL_TRUEVAL]]
+; CHECK-NEXT:    [[OUTER_SEL:%.*]] = select i1 [[INNER_COND]], i1 [[INNER_SEL]], i1 [[INNER_SEL_FALSEVAL]]
 ; CHECK-NEXT:    ret i1 [[OUTER_SEL]]
 ;
   %not.inner.cond = xor i1 %inner.cond, -1
@@ -416,10 +406,8 @@ define i1 @orcond.101.inv.outer.cond.inv.inner.cond.in.outer.cond(i1 %inner.cond
 define i1 @andcond.110.inv.inner.cond.in.inner.sel.inv.inner.cond.in.outer.cond(i1 %inner.cond, i1 %alt.cond, i1 %inner.sel.trueval, i1 %inner.sel.falseval, i1 %outer.sel.trueval) {
 ; CHECK-LABEL: @andcond.110.inv.inner.cond.in.inner.sel.inv.inner.cond.in.outer.cond(
 ; CHECK-NEXT:    [[NOT_INNER_COND_0:%.*]] = xor i1 [[INNER_COND:%.*]], true
-; CHECK-NEXT:    [[OUTER_COND:%.*]] = select i1 [[NOT_INNER_COND_0]], i1 [[ALT_COND:%.*]], i1 false
-; CHECK-NEXT:    [[NOT_INNER_COND_1:%.*]] = xor i1 [[INNER_COND]], true
-; CHECK-NEXT:    [[INNER_SEL:%.*]] = select i1 [[NOT_INNER_COND_1]], i1 [[INNER_SEL_FALSEVAL:%.*]], i1 false
-; CHECK-NEXT:    [[OUTER_SEL:%.*]] = select i1 [[OUTER_COND]], i1 [[OUTER_SEL_TRUEVAL:%.*]], i1 [[INNER_SEL]]
+; CHECK-NEXT:    [[INNER_SEL:%.*]] = select i1 [[ALT_COND:%.*]], i1 [[OUTER_SEL_TRUEVAL:%.*]], i1 [[INNER_SEL_FALSEVAL:%.*]]
+; CHECK-NEXT:    [[OUTER_SEL:%.*]] = select i1 [[NOT_INNER_COND_0]], i1 [[INNER_SEL]], i1 false
 ; CHECK-NEXT:    ret i1 [[OUTER_SEL]]
 ;
   %not.inner.cond.0 = xor i1 %inner.cond, -1
@@ -432,10 +420,8 @@ define i1 @andcond.110.inv.inner.cond.in.inner.sel.inv.inner.cond.in.outer.cond(
 define i1 @orcond.110.inv.inner.cond.in.inner.sel.inv.inner.cond.in.outer.cond(i1 %inner.cond, i1 %alt.cond, i1 %inner.sel.trueval, i1 %inner.sel.falseval, i1 %outer.sel.falseval) {
 ; CHECK-LABEL: @orcond.110.inv.inner.cond.in.inner.sel.inv.inner.cond.in.outer.cond(
 ; CHECK-NEXT:    [[NOT_INNER_COND_0:%.*]] = xor i1 [[INNER_COND:%.*]], true
-; CHECK-NEXT:    [[OUTER_COND:%.*]] = select i1 [[NOT_INNER_COND_0]], i1 true, i1 [[ALT_COND:%.*]]
-; CHECK-NEXT:    [[NOT_INNER_COND_1:%.*]] = xor i1 [[INNER_COND]], true
-; CHECK-NEXT:    [[INNER_SEL:%.*]] = select i1 [[NOT_INNER_COND_1]], i1 true, i1 [[INNER_SEL_TRUEVAL:%.*]]
-; CHECK-NEXT:    [[OUTER_SEL:%.*]] = select i1 [[OUTER_COND]], i1 [[INNER_SEL]], i1 [[OUTER_SEL_FALSEVAL:%.*]]
+; CHECK-NEXT:    [[INNER_SEL:%.*]] = select i1 [[ALT_COND:%.*]], i1 [[INNER_SEL_TRUEVAL:%.*]], i1 [[OUTER_SEL_FALSEVAL:%.*]]
+; CHECK-NEXT:    [[OUTER_SEL:%.*]] = select i1 [[NOT_INNER_COND_0]], i1 true, i1 [[INNER_SEL]]
 ; CHECK-NEXT:    ret i1 [[OUTER_SEL]]
 ;
   %not.inner.cond.0 = xor i1 %inner.cond, -1
index bb2527f..9b86b39 100644 (file)
@@ -3,13 +3,10 @@
 
 declare void @use(i1)
 
-; TODO: C && A || C && B --> (A || B) && C
-
 define i1 @logic_and_logic_or_1(i1 %c, i1 %a, i1 %b) {
 ; CHECK-LABEL: @logic_and_logic_or_1(
-; CHECK-NEXT:    [[AC:%.*]] = select i1 [[C:%.*]], i1 [[A:%.*]], i1 false
-; CHECK-NEXT:    [[BC:%.*]] = select i1 [[C]], i1 [[B:%.*]], i1 false
-; CHECK-NEXT:    [[OR:%.*]] = select i1 [[AC]], i1 true, i1 [[BC]]
+; CHECK-NEXT:    [[BC:%.*]] = select i1 [[A:%.*]], i1 true, i1 [[B:%.*]]
+; CHECK-NEXT:    [[OR:%.*]] = select i1 [[C:%.*]], i1 [[BC]], i1 false
 ; CHECK-NEXT:    ret i1 [[OR]]
 ;
   %ac = select i1 %c, i1 %a, i1 false
@@ -20,9 +17,8 @@ define i1 @logic_and_logic_or_1(i1 %c, i1 %a, i1 %b) {
 
 define i1 @logic_and_logic_or_2(i1 %c, i1 %a, i1 %b) {
 ; CHECK-LABEL: @logic_and_logic_or_2(
-; CHECK-NEXT:    [[AC:%.*]] = select i1 [[A:%.*]], i1 [[C:%.*]], i1 false
-; CHECK-NEXT:    [[BC:%.*]] = select i1 [[C]], i1 [[B:%.*]], i1 false
-; CHECK-NEXT:    [[OR:%.*]] = select i1 [[AC]], i1 true, i1 [[BC]]
+; CHECK-NEXT:    [[BC:%.*]] = select i1 [[A:%.*]], i1 true, i1 [[B:%.*]]
+; CHECK-NEXT:    [[OR:%.*]] = select i1 [[C:%.*]], i1 [[BC]], i1 false
 ; CHECK-NEXT:    ret i1 [[OR]]
 ;
   %ac = select i1 %a, i1 %c, i1 false
@@ -59,9 +55,8 @@ define i1 @logic_and_logic_or_4(i1 %c, i1 %a, i1 %b) {
 
 define i1 @logic_and_logic_or_5(i1 %c, i1 %a, i1 %b) {
 ; CHECK-LABEL: @logic_and_logic_or_5(
-; CHECK-NEXT:    [[AC:%.*]] = select i1 [[C:%.*]], i1 [[A:%.*]], i1 false
-; CHECK-NEXT:    [[BC:%.*]] = select i1 [[C]], i1 [[B:%.*]], i1 false
-; CHECK-NEXT:    [[OR:%.*]] = select i1 [[BC]], i1 true, i1 [[AC]]
+; CHECK-NEXT:    [[AC:%.*]] = select i1 [[B:%.*]], i1 true, i1 [[A:%.*]]
+; CHECK-NEXT:    [[OR:%.*]] = select i1 [[C:%.*]], i1 [[AC]], i1 false
 ; CHECK-NEXT:    ret i1 [[OR]]
 ;
   %ac = select i1 %c, i1 %a, i1 false
@@ -98,9 +93,8 @@ define i1 @logic_and_logic_or_7(i1 %c, i1 %a, i1 %b) {
 
 define i1 @logic_and_logic_or_8(i1 %c, i1 %a, i1 %b) {
 ; CHECK-LABEL: @logic_and_logic_or_8(
-; CHECK-NEXT:    [[AC:%.*]] = select i1 [[C:%.*]], i1 [[A:%.*]], i1 false
-; CHECK-NEXT:    [[BC:%.*]] = select i1 [[B:%.*]], i1 [[C]], i1 false
-; CHECK-NEXT:    [[OR:%.*]] = select i1 [[BC]], i1 true, i1 [[AC]]
+; CHECK-NEXT:    [[AC:%.*]] = select i1 [[B:%.*]], i1 true, i1 [[A:%.*]]
+; CHECK-NEXT:    [[OR:%.*]] = select i1 [[C:%.*]], i1 [[AC]], i1 false
 ; CHECK-NEXT:    ret i1 [[OR]]
 ;
   %ac = select i1 %c, i1 %a, i1 false
@@ -111,9 +105,8 @@ define i1 @logic_and_logic_or_8(i1 %c, i1 %a, i1 %b) {
 
 define <3 x i1> @logic_and_logic_or_vector(<3 x i1> %c, <3 x i1> %a, <3 x i1> %b) {
 ; CHECK-LABEL: @logic_and_logic_or_vector(
-; CHECK-NEXT:    [[AC:%.*]] = select <3 x i1> [[C:%.*]], <3 x i1> [[A:%.*]], <3 x i1> zeroinitializer
-; CHECK-NEXT:    [[BC:%.*]] = select <3 x i1> [[C]], <3 x i1> [[B:%.*]], <3 x i1> zeroinitializer
-; CHECK-NEXT:    [[OR:%.*]] = select <3 x i1> [[AC]], <3 x i1> <i1 true, i1 true, i1 true>, <3 x i1> [[BC]]
+; CHECK-NEXT:    [[BC:%.*]] = select <3 x i1> [[A:%.*]], <3 x i1> <i1 true, i1 true, i1 true>, <3 x i1> [[B:%.*]]
+; CHECK-NEXT:    [[OR:%.*]] = select <3 x i1> [[C:%.*]], <3 x i1> [[BC]], <3 x i1> zeroinitializer
 ; CHECK-NEXT:    ret <3 x i1> [[OR]]
 ;
   %ac = select <3 x i1> %c, <3 x i1> %a, <3 x i1> <i1 false, i1 false, i1 false>
@@ -124,9 +117,8 @@ define <3 x i1> @logic_and_logic_or_vector(<3 x i1> %c, <3 x i1> %a, <3 x i1> %b
 
 define <3 x i1> @logic_and_logic_or_vector_poison1(<3 x i1> %c, <3 x i1> %a, <3 x i1> %b) {
 ; CHECK-LABEL: @logic_and_logic_or_vector_poison1(
-; CHECK-NEXT:    [[AC:%.*]] = select <3 x i1> [[C:%.*]], <3 x i1> [[A:%.*]], <3 x i1> zeroinitializer
-; CHECK-NEXT:    [[BC:%.*]] = select <3 x i1> [[C]], <3 x i1> [[B:%.*]], <3 x i1> zeroinitializer
-; CHECK-NEXT:    [[OR:%.*]] = select <3 x i1> [[AC]], <3 x i1> <i1 true, i1 true, i1 poison>, <3 x i1> [[BC]]
+; CHECK-NEXT:    [[BC:%.*]] = select <3 x i1> [[A:%.*]], <3 x i1> <i1 true, i1 true, i1 poison>, <3 x i1> [[B:%.*]]
+; CHECK-NEXT:    [[OR:%.*]] = select <3 x i1> [[C:%.*]], <3 x i1> [[BC]], <3 x i1> zeroinitializer
 ; CHECK-NEXT:    ret <3 x i1> [[OR]]
 ;
   %ac = select <3 x i1> %c, <3 x i1> %a, <3 x i1> <i1 false, i1 false, i1 false>
@@ -150,9 +142,8 @@ define <3 x i1> @logic_and_logic_or_vector_poison2(<3 x i1> %c, <3 x i1> %a, <3
 
 define <3 x i1> @logic_and_logic_or_vector_poison3(<3 x i1> %c, <3 x i1> %a, <3 x i1> %b) {
 ; CHECK-LABEL: @logic_and_logic_or_vector_poison3(
-; CHECK-NEXT:    [[AC:%.*]] = select <3 x i1> [[C:%.*]], <3 x i1> [[A:%.*]], <3 x i1> zeroinitializer
-; CHECK-NEXT:    [[BC:%.*]] = select <3 x i1> [[C]], <3 x i1> [[B:%.*]], <3 x i1> <i1 poison, i1 false, i1 false>
-; CHECK-NEXT:    [[OR:%.*]] = select <3 x i1> [[AC]], <3 x i1> <i1 true, i1 true, i1 true>, <3 x i1> [[BC]]
+; CHECK-NEXT:    [[BC:%.*]] = select <3 x i1> [[A:%.*]], <3 x i1> <i1 true, i1 true, i1 true>, <3 x i1> [[B:%.*]]
+; CHECK-NEXT:    [[OR:%.*]] = select <3 x i1> [[C:%.*]], <3 x i1> [[BC]], <3 x i1> <i1 poison, i1 false, i1 false>
 ; CHECK-NEXT:    ret <3 x i1> [[OR]]
 ;
   %ac = select <3 x i1> %c, <3 x i1> %a, <3 x i1> <i1 false, i1 false, i1 false>
@@ -180,9 +171,8 @@ define i1 @logic_and_logic_or_not_one_use(i1 %c, i1 %a, i1 %b) {
 
 define i1 @and_logic_and_logic_or_1(i1 %c, i1 %a, i1 %b) {
 ; CHECK-LABEL: @and_logic_and_logic_or_1(
-; CHECK-NEXT:    [[AC:%.*]] = and i1 [[C:%.*]], [[A:%.*]]
-; CHECK-NEXT:    [[BC:%.*]] = select i1 [[C]], i1 [[B:%.*]], i1 false
-; CHECK-NEXT:    [[OR:%.*]] = select i1 [[AC]], i1 true, i1 [[BC]]
+; CHECK-NEXT:    [[BC:%.*]] = select i1 [[A:%.*]], i1 true, i1 [[B:%.*]]
+; CHECK-NEXT:    [[OR:%.*]] = select i1 [[C:%.*]], i1 [[BC]], i1 false
 ; CHECK-NEXT:    ret i1 [[OR]]
 ;
   %ac = and i1 %c, %a
@@ -206,9 +196,8 @@ define i1 @and_logic_and_logic_or_2(i1 %c, i1 %a, i1 %b) {
 
 define i1 @and_logic_and_logic_or_3(i1 %c, i1 %a, i1 %b) {
 ; CHECK-LABEL: @and_logic_and_logic_or_3(
-; CHECK-NEXT:    [[AC:%.*]] = and i1 [[A:%.*]], [[C:%.*]]
-; CHECK-NEXT:    [[BC:%.*]] = select i1 [[C]], i1 [[B:%.*]], i1 false
-; CHECK-NEXT:    [[OR:%.*]] = select i1 [[AC]], i1 true, i1 [[BC]]
+; CHECK-NEXT:    [[BC:%.*]] = select i1 [[A:%.*]], i1 true, i1 [[B:%.*]]
+; CHECK-NEXT:    [[OR:%.*]] = select i1 [[C:%.*]], i1 [[BC]], i1 false
 ; CHECK-NEXT:    ret i1 [[OR]]
 ;
   %ac = and i1 %a, %c
@@ -232,9 +221,8 @@ define i1 @and_logic_and_logic_or_4(i1 %c, i1 %a, i1 %b) {
 
 define <3 x i1> @and_logic_and_logic_or_vector(<3 x i1> %c, <3 x i1> %a, <3 x i1> %b) {
 ; CHECK-LABEL: @and_logic_and_logic_or_vector(
-; CHECK-NEXT:    [[AC:%.*]] = and <3 x i1> [[C:%.*]], [[A:%.*]]
-; CHECK-NEXT:    [[BC:%.*]] = select <3 x i1> [[C]], <3 x i1> [[B:%.*]], <3 x i1> zeroinitializer
-; CHECK-NEXT:    [[OR:%.*]] = select <3 x i1> [[AC]], <3 x i1> <i1 true, i1 true, i1 true>, <3 x i1> [[BC]]
+; CHECK-NEXT:    [[BC:%.*]] = select <3 x i1> [[A:%.*]], <3 x i1> <i1 true, i1 true, i1 true>, <3 x i1> [[B:%.*]]
+; CHECK-NEXT:    [[OR:%.*]] = select <3 x i1> [[C:%.*]], <3 x i1> [[BC]], <3 x i1> zeroinitializer
 ; CHECK-NEXT:    ret <3 x i1> [[OR]]
 ;
   %ac = and <3 x i1> %c, %a
@@ -245,9 +233,8 @@ define <3 x i1> @and_logic_and_logic_or_vector(<3 x i1> %c, <3 x i1> %a, <3 x i1
 
 define <3 x i1> @and_logic_and_logic_or_vector_poison1(<3 x i1> %c, <3 x i1> %a, <3 x i1> %b) {
 ; CHECK-LABEL: @and_logic_and_logic_or_vector_poison1(
-; CHECK-NEXT:    [[AC:%.*]] = and <3 x i1> [[C:%.*]], [[A:%.*]]
-; CHECK-NEXT:    [[BC:%.*]] = select <3 x i1> [[C]], <3 x i1> [[B:%.*]], <3 x i1> <i1 false, i1 poison, i1 false>
-; CHECK-NEXT:    [[OR:%.*]] = select <3 x i1> [[AC]], <3 x i1> <i1 true, i1 true, i1 true>, <3 x i1> [[BC]]
+; CHECK-NEXT:    [[BC:%.*]] = select <3 x i1> [[A:%.*]], <3 x i1> <i1 true, i1 true, i1 true>, <3 x i1> [[B:%.*]]
+; CHECK-NEXT:    [[OR:%.*]] = select <3 x i1> [[C:%.*]], <3 x i1> [[BC]], <3 x i1> <i1 false, i1 poison, i1 false>
 ; CHECK-NEXT:    ret <3 x i1> [[OR]]
 ;
   %ac = and <3 x i1> %c, %a
@@ -258,9 +245,8 @@ define <3 x i1> @and_logic_and_logic_or_vector_poison1(<3 x i1> %c, <3 x i1> %a,
 
 define <3 x i1> @and_logic_and_logic_or_vector_poison2(<3 x i1> %c, <3 x i1> %a, <3 x i1> %b) {
 ; CHECK-LABEL: @and_logic_and_logic_or_vector_poison2(
-; CHECK-NEXT:    [[AC:%.*]] = and <3 x i1> [[C:%.*]], [[A:%.*]]
-; CHECK-NEXT:    [[BC:%.*]] = select <3 x i1> [[C]], <3 x i1> [[B:%.*]], <3 x i1> zeroinitializer
-; CHECK-NEXT:    [[OR:%.*]] = select <3 x i1> [[AC]], <3 x i1> <i1 poison, i1 true, i1 true>, <3 x i1> [[BC]]
+; CHECK-NEXT:    [[BC:%.*]] = select <3 x i1> [[A:%.*]], <3 x i1> <i1 poison, i1 true, i1 true>, <3 x i1> [[B:%.*]]
+; CHECK-NEXT:    [[OR:%.*]] = select <3 x i1> [[C:%.*]], <3 x i1> [[BC]], <3 x i1> zeroinitializer
 ; CHECK-NEXT:    ret <3 x i1> [[OR]]
 ;
   %ac = and <3 x i1> %c, %a
@@ -355,13 +341,10 @@ define i1 @and_and_logic_or_not_one_use(i1 %c, i1 %a, i1 %b) {
   ret i1 %or
 }
 
-; TODO: (C || A) && (C || B) --> (A && B) || C
-
 define i1 @logic_or_logic_and_1(i1 %c, i1 %a, i1 %b) {
 ; CHECK-LABEL: @logic_or_logic_and_1(
-; CHECK-NEXT:    [[AC:%.*]] = select i1 [[C:%.*]], i1 true, i1 [[A:%.*]]
-; CHECK-NEXT:    [[BC:%.*]] = select i1 [[C]], i1 true, i1 [[B:%.*]]
-; CHECK-NEXT:    [[OR:%.*]] = select i1 [[AC]], i1 [[BC]], i1 false
+; CHECK-NEXT:    [[BC:%.*]] = select i1 [[A:%.*]], i1 [[B:%.*]], i1 false
+; CHECK-NEXT:    [[OR:%.*]] = select i1 [[C:%.*]], i1 true, i1 [[BC]]
 ; CHECK-NEXT:    ret i1 [[OR]]
 ;
   %ac = select i1 %c, i1 true, i1 %a
@@ -372,9 +355,8 @@ define i1 @logic_or_logic_and_1(i1 %c, i1 %a, i1 %b) {
 
 define i1 @logic_or_logic_and_2(i1 %c, i1 %a, i1 %b) {
 ; CHECK-LABEL: @logic_or_logic_and_2(
-; CHECK-NEXT:    [[AC:%.*]] = select i1 [[A:%.*]], i1 true, i1 [[C:%.*]]
-; CHECK-NEXT:    [[BC:%.*]] = select i1 [[C]], i1 true, i1 [[B:%.*]]
-; CHECK-NEXT:    [[OR:%.*]] = select i1 [[AC]], i1 [[BC]], i1 false
+; CHECK-NEXT:    [[BC:%.*]] = select i1 [[A:%.*]], i1 [[B:%.*]], i1 false
+; CHECK-NEXT:    [[OR:%.*]] = select i1 [[C:%.*]], i1 true, i1 [[BC]]
 ; CHECK-NEXT:    ret i1 [[OR]]
 ;
   %ac = select i1 %a, i1 true, i1 %c
@@ -411,9 +393,8 @@ define i1 @logic_or_logic_and_4(i1 %c, i1 %a, i1 %b) {
 
 define i1 @logic_or_logic_and_5(i1 %c, i1 %a, i1 %b) {
 ; CHECK-LABEL: @logic_or_logic_and_5(
-; CHECK-NEXT:    [[AC:%.*]] = select i1 [[C:%.*]], i1 true, i1 [[A:%.*]]
-; CHECK-NEXT:    [[BC:%.*]] = select i1 [[C]], i1 true, i1 [[B:%.*]]
-; CHECK-NEXT:    [[OR:%.*]] = select i1 [[BC]], i1 [[AC]], i1 false
+; CHECK-NEXT:    [[AC:%.*]] = select i1 [[B:%.*]], i1 [[A:%.*]], i1 false
+; CHECK-NEXT:    [[OR:%.*]] = select i1 [[C:%.*]], i1 true, i1 [[AC]]
 ; CHECK-NEXT:    ret i1 [[OR]]
 ;
   %ac = select i1 %c, i1 true, i1 %a
@@ -450,9 +431,8 @@ define i1 @logic_or_logic_and_7(i1 %c, i1 %a, i1 %b) {
 
 define i1 @logic_or_logic_and_8(i1 %c, i1 %a, i1 %b) {
 ; CHECK-LABEL: @logic_or_logic_and_8(
-; CHECK-NEXT:    [[AC:%.*]] = select i1 [[C:%.*]], i1 true, i1 [[A:%.*]]
-; CHECK-NEXT:    [[BC:%.*]] = select i1 [[B:%.*]], i1 true, i1 [[C]]
-; CHECK-NEXT:    [[OR:%.*]] = select i1 [[BC]], i1 [[AC]], i1 false
+; CHECK-NEXT:    [[AC:%.*]] = select i1 [[B:%.*]], i1 [[A:%.*]], i1 false
+; CHECK-NEXT:    [[OR:%.*]] = select i1 [[C:%.*]], i1 true, i1 [[AC]]
 ; CHECK-NEXT:    ret i1 [[OR]]
 ;
   %ac = select i1 %c, i1 true, i1 %a
@@ -463,9 +443,8 @@ define i1 @logic_or_logic_and_8(i1 %c, i1 %a, i1 %b) {
 
 define <3 x i1> @logic_or_logic_and_vector(<3 x i1> %c, <3 x i1> %a, <3 x i1> %b) {
 ; CHECK-LABEL: @logic_or_logic_and_vector(
-; CHECK-NEXT:    [[AC:%.*]] = select <3 x i1> [[C:%.*]], <3 x i1> <i1 true, i1 true, i1 true>, <3 x i1> [[A:%.*]]
-; CHECK-NEXT:    [[BC:%.*]] = select <3 x i1> [[C]], <3 x i1> <i1 true, i1 true, i1 true>, <3 x i1> [[B:%.*]]
-; CHECK-NEXT:    [[OR:%.*]] = select <3 x i1> [[AC]], <3 x i1> [[BC]], <3 x i1> zeroinitializer
+; CHECK-NEXT:    [[BC:%.*]] = select <3 x i1> [[A:%.*]], <3 x i1> [[B:%.*]], <3 x i1> zeroinitializer
+; CHECK-NEXT:    [[OR:%.*]] = select <3 x i1> [[C:%.*]], <3 x i1> <i1 true, i1 true, i1 true>, <3 x i1> [[BC]]
 ; CHECK-NEXT:    ret <3 x i1> [[OR]]
 ;
   %ac = select <3 x i1> %c, <3 x i1> <i1 true, i1 true, i1 true>, <3 x i1> %a
@@ -489,9 +468,8 @@ define <3 x i1> @logic_or_logic_and_vector_poison1(<3 x i1> %c, <3 x i1> %a, <3
 
 define <3 x i1> @logic_or_logic_and_vector_poison2(<3 x i1> %c, <3 x i1> %a, <3 x i1> %b) {
 ; CHECK-LABEL: @logic_or_logic_and_vector_poison2(
-; CHECK-NEXT:    [[AC:%.*]] = select <3 x i1> [[C:%.*]], <3 x i1> <i1 true, i1 true, i1 true>, <3 x i1> [[A:%.*]]
-; CHECK-NEXT:    [[BC:%.*]] = select <3 x i1> [[C]], <3 x i1> <i1 true, i1 poison, i1 true>, <3 x i1> [[B:%.*]]
-; CHECK-NEXT:    [[OR:%.*]] = select <3 x i1> [[AC]], <3 x i1> [[BC]], <3 x i1> zeroinitializer
+; CHECK-NEXT:    [[BC:%.*]] = select <3 x i1> [[A:%.*]], <3 x i1> [[B:%.*]], <3 x i1> zeroinitializer
+; CHECK-NEXT:    [[OR:%.*]] = select <3 x i1> [[C:%.*]], <3 x i1> <i1 true, i1 poison, i1 true>, <3 x i1> [[BC]]
 ; CHECK-NEXT:    ret <3 x i1> [[OR]]
 ;
   %ac = select <3 x i1> %c, <3 x i1> <i1 true, i1 true, i1 true>, <3 x i1> %a
@@ -502,9 +480,8 @@ define <3 x i1> @logic_or_logic_and_vector_poison2(<3 x i1> %c, <3 x i1> %a, <3
 
 define <3 x i1> @logic_or_logic_and_vector_poison3(<3 x i1> %c, <3 x i1> %a, <3 x i1> %b) {
 ; CHECK-LABEL: @logic_or_logic_and_vector_poison3(
-; CHECK-NEXT:    [[AC:%.*]] = select <3 x i1> [[C:%.*]], <3 x i1> <i1 true, i1 true, i1 true>, <3 x i1> [[A:%.*]]
-; CHECK-NEXT:    [[BC:%.*]] = select <3 x i1> [[C]], <3 x i1> <i1 true, i1 true, i1 true>, <3 x i1> [[B:%.*]]
-; CHECK-NEXT:    [[OR:%.*]] = select <3 x i1> [[AC]], <3 x i1> [[BC]], <3 x i1> <i1 false, i1 false, i1 poison>
+; CHECK-NEXT:    [[BC:%.*]] = select <3 x i1> [[A:%.*]], <3 x i1> [[B:%.*]], <3 x i1> <i1 false, i1 false, i1 poison>
+; CHECK-NEXT:    [[OR:%.*]] = select <3 x i1> [[C:%.*]], <3 x i1> <i1 true, i1 true, i1 true>, <3 x i1> [[BC]]
 ; CHECK-NEXT:    ret <3 x i1> [[OR]]
 ;
   %ac = select <3 x i1> %c, <3 x i1> <i1 true, i1 true, i1 true>, <3 x i1> %a
@@ -532,9 +509,8 @@ define i1 @logic_or_logic_and_not_one_use(i1 %c, i1 %a, i1 %b) {
 
 define i1 @or_logic_or_logic_and_1(i1 %c, i1 %a, i1 %b) {
 ; CHECK-LABEL: @or_logic_or_logic_and_1(
-; CHECK-NEXT:    [[AC:%.*]] = or i1 [[C:%.*]], [[A:%.*]]
-; CHECK-NEXT:    [[BC:%.*]] = select i1 [[C]], i1 true, i1 [[B:%.*]]
-; CHECK-NEXT:    [[OR:%.*]] = select i1 [[AC]], i1 [[BC]], i1 false
+; CHECK-NEXT:    [[BC:%.*]] = select i1 [[A:%.*]], i1 [[B:%.*]], i1 false
+; CHECK-NEXT:    [[OR:%.*]] = select i1 [[C:%.*]], i1 true, i1 [[BC]]
 ; CHECK-NEXT:    ret i1 [[OR]]
 ;
   %ac = or i1 %c, %a
@@ -584,9 +560,8 @@ define i1 @or_logic_or_logic_and_4(i1 %c, i1 %a, i1 %b) {
 
 define <3 x i1> @or_logic_or_logic_and_vector(<3 x i1> %c, <3 x i1> %a, <3 x i1> %b) {
 ; CHECK-LABEL: @or_logic_or_logic_and_vector(
-; CHECK-NEXT:    [[AC:%.*]] = or <3 x i1> [[C:%.*]], [[A:%.*]]
-; CHECK-NEXT:    [[BC:%.*]] = select <3 x i1> [[C]], <3 x i1> <i1 true, i1 true, i1 true>, <3 x i1> [[B:%.*]]
-; CHECK-NEXT:    [[OR:%.*]] = select <3 x i1> [[AC]], <3 x i1> [[BC]], <3 x i1> zeroinitializer
+; CHECK-NEXT:    [[BC:%.*]] = select <3 x i1> [[A:%.*]], <3 x i1> [[B:%.*]], <3 x i1> zeroinitializer
+; CHECK-NEXT:    [[OR:%.*]] = select <3 x i1> [[C:%.*]], <3 x i1> <i1 true, i1 true, i1 true>, <3 x i1> [[BC]]
 ; CHECK-NEXT:    ret <3 x i1> [[OR]]
 ;
   %ac = or <3 x i1> %c, %a
@@ -597,9 +572,8 @@ define <3 x i1> @or_logic_or_logic_and_vector(<3 x i1> %c, <3 x i1> %a, <3 x i1>
 
 define <3 x i1> @or_logic_or_logic_and_vector_poison1(<3 x i1> %c, <3 x i1> %a, <3 x i1> %b) {
 ; CHECK-LABEL: @or_logic_or_logic_and_vector_poison1(
-; CHECK-NEXT:    [[AC:%.*]] = or <3 x i1> [[C:%.*]], [[A:%.*]]
-; CHECK-NEXT:    [[BC:%.*]] = select <3 x i1> [[C]], <3 x i1> <i1 true, i1 poison, i1 true>, <3 x i1> [[B:%.*]]
-; CHECK-NEXT:    [[OR:%.*]] = select <3 x i1> [[AC]], <3 x i1> [[BC]], <3 x i1> zeroinitializer
+; CHECK-NEXT:    [[BC:%.*]] = select <3 x i1> [[A:%.*]], <3 x i1> [[B:%.*]], <3 x i1> zeroinitializer
+; CHECK-NEXT:    [[OR:%.*]] = select <3 x i1> [[C:%.*]], <3 x i1> <i1 true, i1 poison, i1 true>, <3 x i1> [[BC]]
 ; CHECK-NEXT:    ret <3 x i1> [[OR]]
 ;
   %ac = or <3 x i1> %c, %a
@@ -610,9 +584,8 @@ define <3 x i1> @or_logic_or_logic_and_vector_poison1(<3 x i1> %c, <3 x i1> %a,
 
 define <3 x i1> @or_logic_or_logic_and_vector_poison2(<3 x i1> %c, <3 x i1> %a, <3 x i1> %b) {
 ; CHECK-LABEL: @or_logic_or_logic_and_vector_poison2(
-; CHECK-NEXT:    [[AC:%.*]] = or <3 x i1> [[C:%.*]], [[A:%.*]]
-; CHECK-NEXT:    [[BC:%.*]] = select <3 x i1> [[C]], <3 x i1> <i1 true, i1 true, i1 true>, <3 x i1> [[B:%.*]]
-; CHECK-NEXT:    [[OR:%.*]] = select <3 x i1> [[AC]], <3 x i1> [[BC]], <3 x i1> <i1 false, i1 false, i1 poison>
+; CHECK-NEXT:    [[BC:%.*]] = select <3 x i1> [[A:%.*]], <3 x i1> [[B:%.*]], <3 x i1> <i1 false, i1 false, i1 poison>
+; CHECK-NEXT:    [[OR:%.*]] = select <3 x i1> [[C:%.*]], <3 x i1> <i1 true, i1 true, i1 true>, <3 x i1> [[BC]]
 ; CHECK-NEXT:    ret <3 x i1> [[OR]]
 ;
   %ac = or <3 x i1> %c, %a