481 changes: 481 additions & 0 deletions llvm/test/Transforms/InstCombine/nested-select.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,481 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt -passes=instcombine -S < %s | FileCheck %s

declare void @use.i1(i1)
declare void @use.i8(i8)

; Basic test

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: [[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
%inner.sel = select i1 %inner.cond, i8 %inner.sel.trueval, i8 %inner.sel.falseval
%outer.sel = select i1 %outer.cond, i8 %outer.sel.trueval, i8 %inner.sel
ret i8 %outer.sel
}
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: [[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
%inner.sel = select i1 %inner.cond, i8 %inner.sel.trueval, i8 %inner.sel.falseval
%outer.sel = select i1 %outer.cond, i8 %inner.sel, i8 %outer.sel.falseval
ret i8 %outer.sel
}

; Extra use tests (basic test, no inversions)

define i8 @andcond.extrause0(i1 %inner.cond, i1 %alt.cond, i8 %inner.sel.trueval, i8 %inner.sel.falseval, i8 %outer.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 [[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
call void @use.i1(i1 %outer.cond)
%inner.sel = select i1 %inner.cond, i8 %inner.sel.trueval, i8 %inner.sel.falseval
%outer.sel = select i1 %outer.cond, i8 %outer.sel.trueval, i8 %inner.sel
ret i8 %outer.sel
}
define i8 @orcond.extrause0(i1 %inner.cond, i1 %alt.cond, i8 %inner.sel.trueval, i8 %inner.sel.falseval, i8 %outer.sel.falseval) {
; 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 [[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
call void @use.i1(i1 %outer.cond)
%inner.sel = select i1 %inner.cond, i8 %inner.sel.trueval, i8 %inner.sel.falseval
%outer.sel = select i1 %outer.cond, i8 %inner.sel, i8 %outer.sel.falseval
ret i8 %outer.sel
}

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: [[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
%inner.sel = select i1 %inner.cond, i8 %inner.sel.trueval, i8 %inner.sel.falseval
call void @use.i8(i8 %inner.sel)
%outer.sel = select i1 %outer.cond, i8 %outer.sel.trueval, i8 %inner.sel
ret i8 %outer.sel
}
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: [[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
%inner.sel = select i1 %inner.cond, i8 %inner.sel.trueval, i8 %inner.sel.falseval
call void @use.i8(i8 %inner.sel)
%outer.sel = select i1 %outer.cond, i8 %inner.sel, i8 %outer.sel.falseval
ret i8 %outer.sel
}

define i8 @andcond.extrause2(i1 %inner.cond, i1 %alt.cond, i8 %inner.sel.trueval, i8 %inner.sel.falseval, i8 %outer.sel.trueval) {
; CHECK-LABEL: @andcond.extrause2(
; 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: call void @use.i8(i8 [[INNER_SEL]])
; CHECK-NEXT: [[OUTER_SEL:%.*]] = select i1 [[OUTER_COND]], i8 [[OUTER_SEL_TRUEVAL:%.*]], i8 [[INNER_SEL]]
; CHECK-NEXT: ret i8 [[OUTER_SEL]]
;
%outer.cond = select i1 %inner.cond, i1 %alt.cond, i1 false
call void @use.i1(i1 %outer.cond)
%inner.sel = select i1 %inner.cond, i8 %inner.sel.trueval, i8 %inner.sel.falseval
call void @use.i8(i8 %inner.sel)
%outer.sel = select i1 %outer.cond, i8 %outer.sel.trueval, i8 %inner.sel
ret i8 %outer.sel
}
define i8 @orcond.extrause2(i1 %inner.cond, i1 %alt.cond, i8 %inner.sel.trueval, i8 %inner.sel.falseval, i8 %outer.sel.falseval) {
; CHECK-LABEL: @orcond.extrause2(
; 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: call void @use.i8(i8 [[INNER_SEL]])
; CHECK-NEXT: [[OUTER_SEL:%.*]] = select i1 [[OUTER_COND]], i8 [[INNER_SEL]], i8 [[OUTER_SEL_FALSEVAL:%.*]]
; CHECK-NEXT: ret i8 [[OUTER_SEL]]
;
%outer.cond = select i1 %inner.cond, i1 true, i1 %alt.cond
call void @use.i1(i1 %outer.cond)
%inner.sel = select i1 %inner.cond, i8 %inner.sel.trueval, i8 %inner.sel.falseval
call void @use.i8(i8 %inner.sel)
%outer.sel = select i1 %outer.cond, i8 %inner.sel, i8 %outer.sel.falseval
ret i8 %outer.sel
}

; Mismatched 'common' cond

define i8 @andcond.different.inner.cond(i1 %inner.cond.v0, i1 %inner.cond.v1, i1 %alt.cond, i8 %inner.sel.trueval, i8 %inner.sel.falseval, i8 %outer.sel.trueval) {
; CHECK-LABEL: @andcond.different.inner.cond(
; CHECK-NEXT: [[OUTER_COND:%.*]] = select i1 [[INNER_COND_V0:%.*]], i1 [[ALT_COND:%.*]], i1 false
; CHECK-NEXT: [[INNER_SEL:%.*]] = select i1 [[INNER_COND_V1:%.*]], 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: ret i8 [[OUTER_SEL]]
;

%outer.cond = select i1 %inner.cond.v0, i1 %alt.cond, i1 false
%inner.sel = select i1 %inner.cond.v1, i8 %inner.sel.trueval, i8 %inner.sel.falseval
%outer.sel = select i1 %outer.cond, i8 %outer.sel.trueval, i8 %inner.sel
ret i8 %outer.sel
}
define i8 @orcond.different.inner.cond(i1 %inner.cond.v0, i1 %inner.cond.v1, i1 %alt.cond, i8 %inner.sel.trueval, i8 %inner.sel.falseval, i8 %outer.sel.falseval) {
; CHECK-LABEL: @orcond.different.inner.cond(
; CHECK-NEXT: [[OUTER_COND:%.*]] = select i1 [[INNER_COND_V0:%.*]], i1 true, i1 [[ALT_COND:%.*]]
; CHECK-NEXT: [[INNER_SEL:%.*]] = select i1 [[INNER_COND_V1:%.*]], 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: ret i8 [[OUTER_SEL]]
;
%outer.cond = select i1 %inner.cond.v0, i1 true, i1 %alt.cond
%inner.sel = select i1 %inner.cond.v1, i8 %inner.sel.trueval, i8 %inner.sel.falseval
%outer.sel = select i1 %outer.cond, i8 %inner.sel, i8 %outer.sel.falseval
ret i8 %outer.sel
}

define i1 @andcond.different.inner.cond.both.inverted(i1 %inner.cond.v0, i1 %inner.cond.v1, i1 %alt.cond, i1 %inner.sel.trueval, i1 %inner.sel.falseval, i1 %outer.sel.trueval) {
; CHECK-LABEL: @andcond.different.inner.cond.both.inverted(
; CHECK-NEXT: [[NOT_INNER_COND_0:%.*]] = xor i1 [[INNER_COND_V0:%.*]], 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_V1:%.*]], 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: ret i1 [[OUTER_SEL]]
;
%not.inner.cond.0 = xor i1 %inner.cond.v0, -1
%outer.cond = select i1 %not.inner.cond.0, i1 %alt.cond, i1 false ; and %inner.cond, %alt.cond
%not.inner.cond.1 = xor i1 %inner.cond.v1, -1
%inner.sel = select i1 %not.inner.cond.1, i1 %inner.sel.falseval, i1 false
%outer.sel = select i1 %outer.cond, i1 %outer.sel.trueval, i1 %inner.sel
ret i1 %outer.sel
}
define i1 @orcond.different.inner.cond.both.inverted(i1 %inner.cond.v0, i1 %inner.cond.v1, i1 %alt.cond, i1 %inner.sel.trueval, i1 %inner.sel.falseval, i1 %outer.sel.falseval) {
; CHECK-LABEL: @orcond.different.inner.cond.both.inverted(
; CHECK-NEXT: [[NOT_INNER_COND_0:%.*]] = xor i1 [[INNER_COND_V0:%.*]], 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_V1:%.*]], 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: ret i1 [[OUTER_SEL]]
;
%not.inner.cond.0 = xor i1 %inner.cond.v0, -1
%outer.cond = select i1 %not.inner.cond.0, i1 true, i1 %alt.cond ; or %inner.cond, %alt.cond
%not.inner.cond.1 = xor i1 %inner.cond.v1, -1
%inner.sel = select i1 %not.inner.cond.1, i1 true, i1 %inner.sel.trueval
%outer.sel = select i1 %outer.cond, i1 %inner.sel, i1 %outer.sel.falseval
ret i1 %outer.sel
}

define i1 @andcond.different.inner.cond.inverted.in.outer.cond(i1 %inner.cond.v0, i1 %inner.cond.v1, i1 %alt.cond, i1 %inner.sel.trueval, i1 %inner.sel.falseval, i1 %outer.sel.trueval) {
; CHECK-LABEL: @andcond.different.inner.cond.inverted.in.outer.cond(
; CHECK-NEXT: [[NOT_INNER_COND_0:%.*]] = xor i1 [[INNER_COND_V0:%.*]], true
; CHECK-NEXT: [[OUTER_COND:%.*]] = select i1 [[NOT_INNER_COND_0]], i1 [[ALT_COND:%.*]], i1 false
; CHECK-NEXT: [[INNER_SEL:%.*]] = select i1 [[INNER_COND_V1:%.*]], i1 [[INNER_SEL_FALSEVAL:%.*]], i1 false
; CHECK-NEXT: [[OUTER_SEL:%.*]] = select i1 [[OUTER_COND]], i1 [[OUTER_SEL_TRUEVAL:%.*]], i1 [[INNER_SEL]]
; CHECK-NEXT: ret i1 [[OUTER_SEL]]
;
%not.inner.cond.0 = xor i1 %inner.cond.v0, -1
%outer.cond = select i1 %not.inner.cond.0, i1 %alt.cond, i1 false ; and %inner.cond, %alt.cond
%inner.sel = select i1 %inner.cond.v1, i1 %inner.sel.falseval, i1 false
%outer.sel = select i1 %outer.cond, i1 %outer.sel.trueval, i1 %inner.sel
ret i1 %outer.sel
}
define i1 @orcond.different.inner.cond.inverted.in.outer.cond(i1 %inner.cond.v0, i1 %inner.cond.v1, i1 %alt.cond, i1 %inner.sel.trueval, i1 %inner.sel.falseval, i1 %outer.sel.falseval) {
; CHECK-LABEL: @orcond.different.inner.cond.inverted.in.outer.cond(
; CHECK-NEXT: [[NOT_INNER_COND_0:%.*]] = xor i1 [[INNER_COND_V0:%.*]], true
; CHECK-NEXT: [[OUTER_COND:%.*]] = select i1 [[NOT_INNER_COND_0]], i1 true, i1 [[ALT_COND:%.*]]
; CHECK-NEXT: [[INNER_SEL:%.*]] = select i1 [[INNER_COND_V1:%.*]], i1 true, i1 [[INNER_SEL_TRUEVAL:%.*]]
; CHECK-NEXT: [[OUTER_SEL:%.*]] = select i1 [[OUTER_COND]], i1 [[INNER_SEL]], i1 [[OUTER_SEL_FALSEVAL:%.*]]
; CHECK-NEXT: ret i1 [[OUTER_SEL]]
;
%not.inner.cond.0 = xor i1 %inner.cond.v0, -1
%outer.cond = select i1 %not.inner.cond.0, i1 true, i1 %alt.cond ; or %inner.cond, %alt.cond
%inner.sel = select i1 %inner.cond.v1, i1 true, i1 %inner.sel.trueval
%outer.sel = select i1 %outer.cond, i1 %inner.sel, i1 %outer.sel.falseval
ret i1 %outer.sel
}

define i1 @andcond.different.inner.cond.inverted.in.inner.sel(i1 %inner.cond.v0, i1 %inner.cond.v1, i1 %alt.cond, i1 %inner.sel.trueval, i1 %inner.sel.falseval, i1 %outer.sel.trueval) {
; CHECK-LABEL: @andcond.different.inner.cond.inverted.in.inner.sel(
; CHECK-NEXT: [[OUTER_COND:%.*]] = select i1 [[INNER_COND_V0:%.*]], i1 [[ALT_COND:%.*]], i1 false
; CHECK-NEXT: [[NOT_INNER_COND_1:%.*]] = xor i1 [[INNER_COND_V1:%.*]], 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: ret i1 [[OUTER_SEL]]
;
%outer.cond = select i1 %inner.cond.v0, i1 %alt.cond, i1 false ; and %inner.cond, %alt.cond
%not.inner.cond.1 = xor i1 %inner.cond.v1, -1
%inner.sel = select i1 %not.inner.cond.1, i1 %inner.sel.falseval, i1 false
%outer.sel = select i1 %outer.cond, i1 %outer.sel.trueval, i1 %inner.sel
ret i1 %outer.sel
}
define i1 @orcond.different.inner.cond.inverted.in.inner.sel(i1 %inner.cond.v0, i1 %inner.cond.v1, i1 %alt.cond, i1 %inner.sel.trueval, i1 %inner.sel.falseval, i1 %outer.sel.falseval) {
; CHECK-LABEL: @orcond.different.inner.cond.inverted.in.inner.sel(
; CHECK-NEXT: [[OUTER_COND:%.*]] = select i1 [[INNER_COND_V0:%.*]], i1 true, i1 [[ALT_COND:%.*]]
; CHECK-NEXT: [[NOT_INNER_COND_1:%.*]] = xor i1 [[INNER_COND_V1:%.*]], 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: ret i1 [[OUTER_SEL]]
;
%outer.cond = select i1 %inner.cond.v0, i1 true, i1 %alt.cond ; or %inner.cond, %alt.cond
%not.inner.cond.1 = xor i1 %inner.cond.v1, -1
%inner.sel = select i1 %not.inner.cond.1, i1 true, i1 %inner.sel.trueval
%outer.sel = select i1 %outer.cond, i1 %inner.sel, i1 %outer.sel.falseval
ret i1 %outer.sel
}

; Tests with intervening inversions

; 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: [[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
%inner.sel = select i1 %inner.cond, i1 %inner.sel.trueval, i1 %inner.sel.falseval
%not.outer.cond = xor i1 %outer.cond, -1
%outer.sel = select i1 %not.outer.cond, i1 %inner.sel, i1 false
ret i1 %outer.sel
}
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: [[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
%inner.sel = select i1 %inner.cond, i1 %inner.sel.trueval, i1 %inner.sel.falseval
%not.outer.cond = xor i1 %outer.cond, -1
%outer.sel = select i1 %not.outer.cond, i1 true, i1 %inner.sel
ret i1 %outer.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: [[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
%not.inner.cond = xor i1 %inner.cond, -1
%inner.sel = select i1 %not.inner.cond, i1 %inner.sel.falseval, i1 false
%outer.sel = select i1 %outer.cond, i1 %outer.sel.trueval, i1 %inner.sel
ret i1 %outer.sel
}
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: [[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
%not.inner.cond = xor i1 %inner.cond, -1
%inner.sel = select i1 %not.inner.cond, i1 true, i1 %inner.sel.trueval
%outer.sel = select i1 %outer.cond, i1 %inner.sel, i1 %outer.sel.falseval
ret i1 %outer.sel
}

; 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: [[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
%outer.cond = select i1 %not.inner.cond, i1 %alt.cond, i1 false ; and %inner.cond, %alt.cond
%inner.sel = select i1 %inner.cond, i8 %inner.sel.trueval, i8 %inner.sel.falseval
%outer.sel = select i1 %outer.cond, i8 %outer.sel.trueval, i8 %inner.sel
ret i8 %outer.sel
}
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: [[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
%outer.cond = select i1 %not.inner.cond, i1 true, i1 %alt.cond ; or %inner.cond, %alt.cond
%inner.sel = select i1 %inner.cond, i8 %inner.sel.trueval, i8 %inner.sel.falseval
%outer.sel = select i1 %outer.cond, i8 %inner.sel, i8 %outer.sel.falseval
ret i8 %outer.sel
}

; In %outer.sel, %outer.cond is inverted
; 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: [[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
%not.inner.cond = xor i1 %inner.cond, -1
%inner.sel = select i1 %not.inner.cond, i1 true, i1 %inner.sel.falseval
%not.outer.cond = xor i1 %outer.cond, -1
call void @use.i1(i1 %inner.sel)
%outer.sel = select i1 %not.outer.cond, i1 %inner.sel, i1 false
ret i1 %outer.sel
}
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: [[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
%not.inner.cond = xor i1 %inner.cond, -1
%inner.sel = select i1 %not.inner.cond, i1 %inner.sel.trueval, i1 false
call void @use.i1(i1 %inner.sel)
%not.outer.cond = xor i1 %outer.cond, -1
%outer.sel = select i1 %not.outer.cond, i1 true, i1 %inner.sel
ret i1 %outer.sel
}

; In %outer.sel, %outer.cond is inverted
; 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: [[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: [[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
%outer.cond = select i1 %not.inner.cond, i1 %alt.cond, i1 false ; and %inner.cond, %alt.cond
%inner.sel = select i1 %inner.cond, i1 %inner.sel.trueval, i1 %inner.sel.falseval
call void @use.i1(i1 %inner.sel)
%not.outer.cond = xor i1 %outer.cond, -1
%outer.sel = select i1 %not.outer.cond, i1 %inner.sel, i1 false
ret i1 %outer.sel
}
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: [[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: [[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
%outer.cond = select i1 %not.inner.cond, i1 true, i1 %alt.cond ; or %inner.cond, %alt.cond
%inner.sel = select i1 %inner.cond, i1 %inner.sel.trueval, i1 %inner.sel.falseval
call void @use.i1(i1 %inner.sel)
%not.outer.cond = xor i1 %outer.cond, -1
%outer.sel = select i1 %not.outer.cond, i1 true, i1 %inner.sel
ret i1 %outer.sel
}

; In %inner.sel, %inner.cond is inverted
; In %outer.cond, %inner.cond is inverted
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: [[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
%outer.cond = select i1 %not.inner.cond.0, i1 %alt.cond, i1 false ; and %inner.cond, %alt.cond
%not.inner.cond.1 = xor i1 %inner.cond, -1
%inner.sel = select i1 %not.inner.cond.1, i1 %inner.sel.falseval, i1 false
%outer.sel = select i1 %outer.cond, i1 %outer.sel.trueval, i1 %inner.sel
ret i1 %outer.sel
}
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: [[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
%outer.cond = select i1 %not.inner.cond.0, i1 true, i1 %alt.cond ; or %inner.cond, %alt.cond
%not.inner.cond.1 = xor i1 %inner.cond, -1
%inner.sel = select i1 %not.inner.cond.1, i1 true, i1 %inner.sel.trueval
%outer.sel = select i1 %outer.cond, i1 %inner.sel, i1 %outer.sel.falseval
ret i1 %outer.sel
}

; In %outer.sel, %outer.cond is inverted
; In %inner.sel, %inner.cond is inverted
; In %outer.cond, %inner.cond is inverted
define i1 @andcond.111.inv.all.conds(i1 %inner.cond, i1 %alt.cond, i1 %inner.sel.trueval, i1 %inner.sel.falseval, i1 %outer.sel.trueval) {
; CHECK-LABEL: @andcond.111.inv.all.conds(
; 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: call void @use.i1(i1 [[OUTER_COND]])
; 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: 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 [[INNER_SEL]], i1 false
; CHECK-NEXT: ret i1 [[OUTER_SEL]]
;
%not.inner.cond.0 = xor i1 %inner.cond, -1
%outer.cond = select i1 %not.inner.cond.0, i1 %alt.cond, i1 false ; and %inner.cond, %alt.cond
call void @use.i1(i1 %outer.cond)
%not.inner.cond.1 = xor i1 %inner.cond, -1
%inner.sel = select i1 %not.inner.cond.1, i1 %inner.sel.falseval, i1 false
call void @use.i1(i1 %inner.sel)
%not.outer.cond = xor i1 %outer.cond, -1
%outer.sel = select i1 %not.outer.cond, i1 %inner.sel, i1 false
ret i1 %outer.sel
}
define i1 @orcond.111.inv.all.conds(i1 %inner.cond, i1 %alt.cond, i1 %inner.sel.trueval, i1 %inner.sel.falseval, i1 %outer.sel.falseval) {
; CHECK-LABEL: @orcond.111.inv.all.conds(
; 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: call void @use.i1(i1 [[OUTER_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: 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: ret i1 [[OUTER_SEL]]
;
%not.inner.cond.0 = xor i1 %inner.cond, -1
%outer.cond = select i1 %not.inner.cond.0, i1 true, i1 %alt.cond ; or %inner.cond, %alt.cond
call void @use.i1(i1 %outer.cond)
%not.inner.cond.1 = xor i1 %inner.cond, -1
%inner.sel = select i1 %not.inner.cond.1, i1 true, i1 %inner.sel.trueval
call void @use.i1(i1 %inner.sel)
%not.outer.cond = xor i1 %outer.cond, -1
%outer.sel = select i1 %not.outer.cond, i1 true, i1 %inner.sel
ret i1 %outer.sel
}
119 changes: 46 additions & 73 deletions llvm/test/Transforms/InstCombine/select-factorize.ll
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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>
Expand All @@ -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>
Expand All @@ -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>
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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
Expand Down