[AArch64][NFC] NFC for const vector as Instruction operand (#116790)
[llvm-project.git] / llvm / test / Transforms / InstCombine / nested-select.ll
blobb8a7d4e8ab78944b7454e81e3716d1326130fcb6
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt -passes=instcombine -S < %s | FileCheck %s
4 declare void @use.i1(i1)
5 declare void @use.i8(i8)
7 ; Basic test
9 define i8 @andcond(i1 %inner.cond, i1 %alt.cond, i8 %inner.sel.trueval, i8 %inner.sel.falseval, i8 %outer.sel.trueval) {
10 ; CHECK-LABEL: @andcond(
11 ; CHECK-NEXT:    [[INNER_SEL:%.*]] = select i1 [[ALT_COND:%.*]], i8 [[OUTER_SEL_TRUEVAL:%.*]], i8 [[INNER_SEL_TRUEVAL:%.*]]
12 ; CHECK-NEXT:    [[OUTER_SEL:%.*]] = select i1 [[INNER_COND:%.*]], i8 [[INNER_SEL]], i8 [[INNER_SEL_FALSEVAL:%.*]]
13 ; CHECK-NEXT:    ret i8 [[OUTER_SEL]]
15   %outer.cond = select i1 %inner.cond, i1 %alt.cond, i1 false ; and %inner.cond, %alt.cond
16   %inner.sel = select i1 %inner.cond, i8 %inner.sel.trueval, i8 %inner.sel.falseval
17   %outer.sel = select i1 %outer.cond, i8 %outer.sel.trueval, i8 %inner.sel
18   ret i8 %outer.sel
20 define i8 @orcond(i1 %inner.cond, i1 %alt.cond, i8 %inner.sel.trueval, i8 %inner.sel.falseval, i8 %outer.sel.falseval) {
21 ; CHECK-LABEL: @orcond(
22 ; CHECK-NEXT:    [[INNER_SEL:%.*]] = select i1 [[ALT_COND:%.*]], i8 [[INNER_SEL_FALSEVAL:%.*]], i8 [[OUTER_SEL_FALSEVAL:%.*]]
23 ; CHECK-NEXT:    [[OUTER_SEL:%.*]] = select i1 [[INNER_COND:%.*]], i8 [[INNER_SEL_TRUEVAL:%.*]], i8 [[INNER_SEL]]
24 ; CHECK-NEXT:    ret i8 [[OUTER_SEL]]
26   %outer.cond = select i1 %inner.cond, i1 true, i1 %alt.cond ; or %inner.cond, %alt.cond
27   %inner.sel = select i1 %inner.cond, i8 %inner.sel.trueval, i8 %inner.sel.falseval
28   %outer.sel = select i1 %outer.cond, i8 %inner.sel, i8 %outer.sel.falseval
29   ret i8 %outer.sel
32 ; Extra use tests (basic test, no inversions)
34 define i8 @andcond.extrause0(i1 %inner.cond, i1 %alt.cond, i8 %inner.sel.trueval, i8 %inner.sel.falseval, i8 %outer.sel.trueval) {
35 ; CHECK-LABEL: @andcond.extrause0(
36 ; CHECK-NEXT:    [[OUTER_COND:%.*]] = select i1 [[INNER_COND:%.*]], i1 [[ALT_COND:%.*]], i1 false
37 ; CHECK-NEXT:    call void @use.i1(i1 [[OUTER_COND]])
38 ; CHECK-NEXT:    [[INNER_SEL:%.*]] = select i1 [[ALT_COND]], i8 [[OUTER_SEL_TRUEVAL:%.*]], i8 [[INNER_SEL_TRUEVAL:%.*]]
39 ; CHECK-NEXT:    [[OUTER_SEL:%.*]] = select i1 [[INNER_COND]], i8 [[INNER_SEL]], i8 [[INNER_SEL_FALSEVAL:%.*]]
40 ; CHECK-NEXT:    ret i8 [[OUTER_SEL]]
42   %outer.cond = select i1 %inner.cond, i1 %alt.cond, i1 false
43   call void @use.i1(i1 %outer.cond)
44   %inner.sel = select i1 %inner.cond, i8 %inner.sel.trueval, i8 %inner.sel.falseval
45   %outer.sel = select i1 %outer.cond, i8 %outer.sel.trueval, i8 %inner.sel
46   ret i8 %outer.sel
48 define i8 @orcond.extrause0(i1 %inner.cond, i1 %alt.cond, i8 %inner.sel.trueval, i8 %inner.sel.falseval, i8 %outer.sel.falseval) {
49 ; CHECK-LABEL: @orcond.extrause0(
50 ; CHECK-NEXT:    [[OUTER_COND:%.*]] = select i1 [[INNER_COND:%.*]], i1 true, i1 [[ALT_COND:%.*]]
51 ; CHECK-NEXT:    call void @use.i1(i1 [[OUTER_COND]])
52 ; CHECK-NEXT:    [[INNER_SEL:%.*]] = select i1 [[ALT_COND]], i8 [[INNER_SEL_FALSEVAL:%.*]], i8 [[OUTER_SEL_FALSEVAL:%.*]]
53 ; CHECK-NEXT:    [[OUTER_SEL:%.*]] = select i1 [[INNER_COND]], i8 [[INNER_SEL_TRUEVAL:%.*]], i8 [[INNER_SEL]]
54 ; CHECK-NEXT:    ret i8 [[OUTER_SEL]]
56   %outer.cond = select i1 %inner.cond, i1 true, i1 %alt.cond
57   call void @use.i1(i1 %outer.cond)
58   %inner.sel = select i1 %inner.cond, i8 %inner.sel.trueval, i8 %inner.sel.falseval
59   %outer.sel = select i1 %outer.cond, i8 %inner.sel, i8 %outer.sel.falseval
60   ret i8 %outer.sel
63 define i8 @andcond.extrause1(i1 %inner.cond, i1 %alt.cond, i8 %inner.sel.trueval, i8 %inner.sel.falseval, i8 %outer.sel.trueval) {
64 ; CHECK-LABEL: @andcond.extrause1(
65 ; CHECK-NEXT:    [[TMP1:%.*]] = select i1 [[INNER_COND:%.*]], i8 [[INNER_SEL_TRUEVAL:%.*]], i8 [[INNER_SEL_FALSEVAL:%.*]]
66 ; CHECK-NEXT:    call void @use.i8(i8 [[TMP1]])
67 ; CHECK-NEXT:    [[INNER_SEL:%.*]] = select i1 [[ALT_COND:%.*]], i8 [[OUTER_SEL_TRUEVAL:%.*]], i8 [[INNER_SEL_TRUEVAL]]
68 ; CHECK-NEXT:    [[OUTER_SEL:%.*]] = select i1 [[INNER_COND]], i8 [[INNER_SEL]], i8 [[INNER_SEL_FALSEVAL]]
69 ; CHECK-NEXT:    ret i8 [[OUTER_SEL]]
71   %outer.cond = select i1 %inner.cond, i1 %alt.cond, i1 false
72   %inner.sel = select i1 %inner.cond, i8 %inner.sel.trueval, i8 %inner.sel.falseval
73   call void @use.i8(i8 %inner.sel)
74   %outer.sel = select i1 %outer.cond, i8 %outer.sel.trueval, i8 %inner.sel
75   ret i8 %outer.sel
77 define i8 @orcond.extrause1(i1 %inner.cond, i1 %alt.cond, i8 %inner.sel.trueval, i8 %inner.sel.falseval, i8 %outer.sel.falseval) {
78 ; CHECK-LABEL: @orcond.extrause1(
79 ; CHECK-NEXT:    [[TMP1:%.*]] = select i1 [[INNER_COND:%.*]], i8 [[INNER_SEL_TRUEVAL:%.*]], i8 [[INNER_SEL_FALSEVAL:%.*]]
80 ; CHECK-NEXT:    call void @use.i8(i8 [[TMP1]])
81 ; CHECK-NEXT:    [[INNER_SEL:%.*]] = select i1 [[ALT_COND:%.*]], i8 [[INNER_SEL_FALSEVAL]], i8 [[OUTER_SEL_FALSEVAL:%.*]]
82 ; CHECK-NEXT:    [[OUTER_SEL:%.*]] = select i1 [[INNER_COND]], i8 [[INNER_SEL_TRUEVAL]], i8 [[INNER_SEL]]
83 ; CHECK-NEXT:    ret i8 [[OUTER_SEL]]
85   %outer.cond = select i1 %inner.cond, i1 true, i1 %alt.cond
86   %inner.sel = select i1 %inner.cond, i8 %inner.sel.trueval, i8 %inner.sel.falseval
87   call void @use.i8(i8 %inner.sel)
88   %outer.sel = select i1 %outer.cond, i8 %inner.sel, i8 %outer.sel.falseval
89   ret i8 %outer.sel
92 define i8 @andcond.extrause2(i1 %inner.cond, i1 %alt.cond, i8 %inner.sel.trueval, i8 %inner.sel.falseval, i8 %outer.sel.trueval) {
93 ; CHECK-LABEL: @andcond.extrause2(
94 ; CHECK-NEXT:    [[OUTER_COND:%.*]] = select i1 [[INNER_COND:%.*]], i1 [[ALT_COND:%.*]], i1 false
95 ; CHECK-NEXT:    call void @use.i1(i1 [[OUTER_COND]])
96 ; CHECK-NEXT:    [[INNER_SEL:%.*]] = select i1 [[INNER_COND]], i8 [[INNER_SEL_TRUEVAL:%.*]], i8 [[INNER_SEL_FALSEVAL:%.*]]
97 ; CHECK-NEXT:    call void @use.i8(i8 [[INNER_SEL]])
98 ; CHECK-NEXT:    [[OUTER_SEL:%.*]] = select i1 [[OUTER_COND]], i8 [[OUTER_SEL_TRUEVAL:%.*]], i8 [[INNER_SEL]]
99 ; CHECK-NEXT:    ret i8 [[OUTER_SEL]]
101   %outer.cond = select i1 %inner.cond, i1 %alt.cond, i1 false
102   call void @use.i1(i1 %outer.cond)
103   %inner.sel = select i1 %inner.cond, i8 %inner.sel.trueval, i8 %inner.sel.falseval
104   call void @use.i8(i8 %inner.sel)
105   %outer.sel = select i1 %outer.cond, i8 %outer.sel.trueval, i8 %inner.sel
106   ret i8 %outer.sel
108 define i8 @orcond.extrause2(i1 %inner.cond, i1 %alt.cond, i8 %inner.sel.trueval, i8 %inner.sel.falseval, i8 %outer.sel.falseval) {
109 ; CHECK-LABEL: @orcond.extrause2(
110 ; CHECK-NEXT:    [[OUTER_COND:%.*]] = select i1 [[INNER_COND:%.*]], i1 true, i1 [[ALT_COND:%.*]]
111 ; CHECK-NEXT:    call void @use.i1(i1 [[OUTER_COND]])
112 ; CHECK-NEXT:    [[INNER_SEL:%.*]] = select i1 [[INNER_COND]], i8 [[INNER_SEL_TRUEVAL:%.*]], i8 [[INNER_SEL_FALSEVAL:%.*]]
113 ; CHECK-NEXT:    call void @use.i8(i8 [[INNER_SEL]])
114 ; CHECK-NEXT:    [[OUTER_SEL:%.*]] = select i1 [[OUTER_COND]], i8 [[INNER_SEL]], i8 [[OUTER_SEL_FALSEVAL:%.*]]
115 ; CHECK-NEXT:    ret i8 [[OUTER_SEL]]
117   %outer.cond = select i1 %inner.cond, i1 true, i1 %alt.cond
118   call void @use.i1(i1 %outer.cond)
119   %inner.sel = select i1 %inner.cond, i8 %inner.sel.trueval, i8 %inner.sel.falseval
120   call void @use.i8(i8 %inner.sel)
121   %outer.sel = select i1 %outer.cond, i8 %inner.sel, i8 %outer.sel.falseval
122   ret i8 %outer.sel
125 ; Mismatched 'common' cond
127 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) {
128 ; CHECK-LABEL: @andcond.different.inner.cond(
129 ; CHECK-NEXT:    [[OUTER_COND:%.*]] = select i1 [[INNER_COND_V0:%.*]], i1 [[ALT_COND:%.*]], i1 false
130 ; CHECK-NEXT:    [[INNER_SEL:%.*]] = select i1 [[INNER_COND_V1:%.*]], i8 [[INNER_SEL_TRUEVAL:%.*]], i8 [[INNER_SEL_FALSEVAL:%.*]]
131 ; CHECK-NEXT:    [[OUTER_SEL:%.*]] = select i1 [[OUTER_COND]], i8 [[OUTER_SEL_TRUEVAL:%.*]], i8 [[INNER_SEL]]
132 ; CHECK-NEXT:    ret i8 [[OUTER_SEL]]
135   %outer.cond = select i1 %inner.cond.v0, i1 %alt.cond, i1 false
136   %inner.sel = select i1 %inner.cond.v1, i8 %inner.sel.trueval, i8 %inner.sel.falseval
137   %outer.sel = select i1 %outer.cond, i8 %outer.sel.trueval, i8 %inner.sel
138   ret i8 %outer.sel
140 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) {
141 ; CHECK-LABEL: @orcond.different.inner.cond(
142 ; CHECK-NEXT:    [[OUTER_COND:%.*]] = select i1 [[INNER_COND_V0:%.*]], i1 true, i1 [[ALT_COND:%.*]]
143 ; CHECK-NEXT:    [[INNER_SEL:%.*]] = select i1 [[INNER_COND_V1:%.*]], i8 [[INNER_SEL_TRUEVAL:%.*]], i8 [[INNER_SEL_FALSEVAL:%.*]]
144 ; CHECK-NEXT:    [[OUTER_SEL:%.*]] = select i1 [[OUTER_COND]], i8 [[INNER_SEL]], i8 [[OUTER_SEL_FALSEVAL:%.*]]
145 ; CHECK-NEXT:    ret i8 [[OUTER_SEL]]
147   %outer.cond = select i1 %inner.cond.v0, i1 true, i1 %alt.cond
148   %inner.sel = select i1 %inner.cond.v1, i8 %inner.sel.trueval, i8 %inner.sel.falseval
149   %outer.sel = select i1 %outer.cond, i8 %inner.sel, i8 %outer.sel.falseval
150   ret i8 %outer.sel
153 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) {
154 ; CHECK-LABEL: @andcond.different.inner.cond.both.inverted(
155 ; CHECK-NEXT:    [[NOT_INNER_COND_0:%.*]] = xor i1 [[INNER_COND_V0:%.*]], true
156 ; CHECK-NEXT:    [[OUTER_COND:%.*]] = select i1 [[NOT_INNER_COND_0]], i1 [[ALT_COND:%.*]], i1 false
157 ; CHECK-NEXT:    [[NOT_INNER_COND_1:%.*]] = xor i1 [[INNER_COND_V1:%.*]], true
158 ; CHECK-NEXT:    [[INNER_SEL:%.*]] = select i1 [[NOT_INNER_COND_1]], i1 [[INNER_SEL_FALSEVAL:%.*]], i1 false
159 ; CHECK-NEXT:    [[OUTER_SEL:%.*]] = select i1 [[OUTER_COND]], i1 [[OUTER_SEL_TRUEVAL:%.*]], i1 [[INNER_SEL]]
160 ; CHECK-NEXT:    ret i1 [[OUTER_SEL]]
162   %not.inner.cond.0 = xor i1 %inner.cond.v0, -1
163   %outer.cond = select i1 %not.inner.cond.0, i1 %alt.cond, i1 false ; and %inner.cond, %alt.cond
164   %not.inner.cond.1 = xor i1 %inner.cond.v1, -1
165   %inner.sel = select i1 %not.inner.cond.1, i1 %inner.sel.falseval, i1 false
166   %outer.sel = select i1 %outer.cond, i1 %outer.sel.trueval, i1 %inner.sel
167   ret i1 %outer.sel
169 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) {
170 ; CHECK-LABEL: @orcond.different.inner.cond.both.inverted(
171 ; CHECK-NEXT:    [[NOT_INNER_COND_0:%.*]] = xor i1 [[INNER_COND_V0:%.*]], true
172 ; CHECK-NEXT:    [[OUTER_COND:%.*]] = select i1 [[NOT_INNER_COND_0]], i1 true, i1 [[ALT_COND:%.*]]
173 ; CHECK-NEXT:    [[NOT_INNER_COND_1:%.*]] = xor i1 [[INNER_COND_V1:%.*]], true
174 ; CHECK-NEXT:    [[INNER_SEL:%.*]] = select i1 [[NOT_INNER_COND_1]], i1 true, i1 [[INNER_SEL_TRUEVAL:%.*]]
175 ; CHECK-NEXT:    [[OUTER_SEL:%.*]] = select i1 [[OUTER_COND]], i1 [[INNER_SEL]], i1 [[OUTER_SEL_FALSEVAL:%.*]]
176 ; CHECK-NEXT:    ret i1 [[OUTER_SEL]]
178   %not.inner.cond.0 = xor i1 %inner.cond.v0, -1
179   %outer.cond = select i1 %not.inner.cond.0, i1 true, i1 %alt.cond ; or %inner.cond, %alt.cond
180   %not.inner.cond.1 = xor i1 %inner.cond.v1, -1
181   %inner.sel = select i1 %not.inner.cond.1, i1 true, i1 %inner.sel.trueval
182   %outer.sel = select i1 %outer.cond, i1 %inner.sel, i1 %outer.sel.falseval
183   ret i1 %outer.sel
186 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) {
187 ; CHECK-LABEL: @andcond.different.inner.cond.inverted.in.outer.cond(
188 ; CHECK-NEXT:    [[NOT_INNER_COND_0:%.*]] = xor i1 [[INNER_COND_V0:%.*]], true
189 ; CHECK-NEXT:    [[OUTER_COND:%.*]] = select i1 [[NOT_INNER_COND_0]], i1 [[ALT_COND:%.*]], i1 false
190 ; CHECK-NEXT:    [[INNER_SEL:%.*]] = select i1 [[INNER_COND_V1:%.*]], i1 [[INNER_SEL_FALSEVAL:%.*]], i1 false
191 ; CHECK-NEXT:    [[OUTER_SEL:%.*]] = select i1 [[OUTER_COND]], i1 [[OUTER_SEL_TRUEVAL:%.*]], i1 [[INNER_SEL]]
192 ; CHECK-NEXT:    ret i1 [[OUTER_SEL]]
194   %not.inner.cond.0 = xor i1 %inner.cond.v0, -1
195   %outer.cond = select i1 %not.inner.cond.0, i1 %alt.cond, i1 false ; and %inner.cond, %alt.cond
196   %inner.sel = select i1 %inner.cond.v1, i1 %inner.sel.falseval, i1 false
197   %outer.sel = select i1 %outer.cond, i1 %outer.sel.trueval, i1 %inner.sel
198   ret i1 %outer.sel
200 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) {
201 ; CHECK-LABEL: @orcond.different.inner.cond.inverted.in.outer.cond(
202 ; CHECK-NEXT:    [[NOT_INNER_COND_0:%.*]] = xor i1 [[INNER_COND_V0:%.*]], true
203 ; CHECK-NEXT:    [[OUTER_COND:%.*]] = select i1 [[NOT_INNER_COND_0]], i1 true, i1 [[ALT_COND:%.*]]
204 ; CHECK-NEXT:    [[INNER_SEL:%.*]] = select i1 [[INNER_COND_V1:%.*]], i1 true, i1 [[INNER_SEL_TRUEVAL:%.*]]
205 ; CHECK-NEXT:    [[OUTER_SEL:%.*]] = select i1 [[OUTER_COND]], i1 [[INNER_SEL]], i1 [[OUTER_SEL_FALSEVAL:%.*]]
206 ; CHECK-NEXT:    ret i1 [[OUTER_SEL]]
208   %not.inner.cond.0 = xor i1 %inner.cond.v0, -1
209   %outer.cond = select i1 %not.inner.cond.0, i1 true, i1 %alt.cond ; or %inner.cond, %alt.cond
210   %inner.sel = select i1 %inner.cond.v1, i1 true, i1 %inner.sel.trueval
211   %outer.sel = select i1 %outer.cond, i1 %inner.sel, i1 %outer.sel.falseval
212   ret i1 %outer.sel
215 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) {
216 ; CHECK-LABEL: @andcond.different.inner.cond.inverted.in.inner.sel(
217 ; CHECK-NEXT:    [[OUTER_COND:%.*]] = select i1 [[INNER_COND_V0:%.*]], i1 [[ALT_COND:%.*]], i1 false
218 ; CHECK-NEXT:    [[NOT_INNER_COND_1:%.*]] = xor i1 [[INNER_COND_V1:%.*]], true
219 ; CHECK-NEXT:    [[INNER_SEL:%.*]] = select i1 [[NOT_INNER_COND_1]], i1 [[INNER_SEL_FALSEVAL:%.*]], i1 false
220 ; CHECK-NEXT:    [[OUTER_SEL:%.*]] = select i1 [[OUTER_COND]], i1 [[OUTER_SEL_TRUEVAL:%.*]], i1 [[INNER_SEL]]
221 ; CHECK-NEXT:    ret i1 [[OUTER_SEL]]
223   %outer.cond = select i1 %inner.cond.v0, i1 %alt.cond, i1 false ; and %inner.cond, %alt.cond
224   %not.inner.cond.1 = xor i1 %inner.cond.v1, -1
225   %inner.sel = select i1 %not.inner.cond.1, i1 %inner.sel.falseval, i1 false
226   %outer.sel = select i1 %outer.cond, i1 %outer.sel.trueval, i1 %inner.sel
227   ret i1 %outer.sel
229 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) {
230 ; CHECK-LABEL: @orcond.different.inner.cond.inverted.in.inner.sel(
231 ; CHECK-NEXT:    [[OUTER_COND:%.*]] = select i1 [[INNER_COND_V0:%.*]], i1 true, i1 [[ALT_COND:%.*]]
232 ; CHECK-NEXT:    [[NOT_INNER_COND_1:%.*]] = xor i1 [[INNER_COND_V1:%.*]], true
233 ; CHECK-NEXT:    [[INNER_SEL:%.*]] = select i1 [[NOT_INNER_COND_1]], i1 true, i1 [[INNER_SEL_TRUEVAL:%.*]]
234 ; CHECK-NEXT:    [[OUTER_SEL:%.*]] = select i1 [[OUTER_COND]], i1 [[INNER_SEL]], i1 [[OUTER_SEL_FALSEVAL:%.*]]
235 ; CHECK-NEXT:    ret i1 [[OUTER_SEL]]
237   %outer.cond = select i1 %inner.cond.v0, i1 true, i1 %alt.cond ; or %inner.cond, %alt.cond
238   %not.inner.cond.1 = xor i1 %inner.cond.v1, -1
239   %inner.sel = select i1 %not.inner.cond.1, i1 true, i1 %inner.sel.trueval
240   %outer.sel = select i1 %outer.cond, i1 %inner.sel, i1 %outer.sel.falseval
241   ret i1 %outer.sel
244 ; Not an inversion
245 ; Based on reproduced from https://reviews.llvm.org/D139275#4001580
246 define i8 @D139275_c4001580(i1 %c0, i1 %c1, i1 %c2, i8 %inner.sel.trueval, i8 %inner.sel.falseval, i8 %outer.sel.trueval) {
247 ; CHECK-LABEL: @D139275_c4001580(
248 ; CHECK-NEXT:    [[INNER_COND:%.*]] = xor i1 [[C0:%.*]], [[C1:%.*]]
249 ; CHECK-NEXT:    [[OUTER_COND:%.*]] = and i1 [[C2:%.*]], [[C1]]
250 ; CHECK-NEXT:    [[INNER_SEL:%.*]] = select i1 [[INNER_COND]], i8 [[INNER_SEL_TRUEVAL:%.*]], i8 [[INNER_SEL_FALSEVAL:%.*]]
251 ; CHECK-NEXT:    [[OUTER_SEL:%.*]] = select i1 [[OUTER_COND]], i8 [[OUTER_SEL_TRUEVAL:%.*]], i8 [[INNER_SEL]]
252 ; CHECK-NEXT:    ret i8 [[OUTER_SEL]]
254   %inner.cond = xor i1 %c0, %c1
255   %outer.cond = and i1 %c2, %c1
256   %inner.sel = select i1 %inner.cond, i8 %inner.sel.trueval, i8 %inner.sel.falseval
257   %outer.sel = select i1 %outer.cond, i8 %outer.sel.trueval, i8 %inner.sel
258   ret i8 %outer.sel
261 ; Tests with intervening inversions
263 ; In %outer.sel, %outer.cond is inverted
264 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) {
265 ; CHECK-LABEL: @andcond.001.inv.outer.cond(
266 ; CHECK-NEXT:    [[NOT_ALT_COND:%.*]] = xor i1 [[ALT_COND:%.*]], true
267 ; CHECK-NEXT:    [[INNER_SEL:%.*]] = select i1 [[NOT_ALT_COND]], i1 [[INNER_SEL_TRUEVAL:%.*]], i1 false
268 ; CHECK-NEXT:    [[OUTER_SEL:%.*]] = select i1 [[INNER_COND:%.*]], i1 [[INNER_SEL]], i1 [[INNER_SEL_FALSEVAL:%.*]]
269 ; CHECK-NEXT:    ret i1 [[OUTER_SEL]]
271   %outer.cond = select i1 %inner.cond, i1 %alt.cond, i1 false ; and %inner.cond, %alt.cond
272   %inner.sel = select i1 %inner.cond, i1 %inner.sel.trueval, i1 %inner.sel.falseval
273   %not.outer.cond = xor i1 %outer.cond, -1
274   %outer.sel = select i1 %not.outer.cond, i1 %inner.sel, i1 false
275   ret i1 %outer.sel
277 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) {
278 ; CHECK-LABEL: @orcond.001.inv.outer.cond(
279 ; CHECK-NEXT:    [[NOT_ALT_COND:%.*]] = xor i1 [[ALT_COND:%.*]], true
280 ; CHECK-NEXT:    [[INNER_SEL:%.*]] = select i1 [[NOT_ALT_COND]], i1 true, i1 [[INNER_SEL_FALSEVAL:%.*]]
281 ; CHECK-NEXT:    [[OUTER_SEL:%.*]] = select i1 [[INNER_COND:%.*]], i1 [[INNER_SEL_TRUEVAL:%.*]], i1 [[INNER_SEL]]
282 ; CHECK-NEXT:    ret i1 [[OUTER_SEL]]
284   %outer.cond = select i1 %inner.cond, i1 true, i1 %alt.cond ; or %inner.cond, %alt.cond
285   %inner.sel = select i1 %inner.cond, i1 %inner.sel.trueval, i1 %inner.sel.falseval
286   %not.outer.cond = xor i1 %outer.cond, -1
287   %outer.sel = select i1 %not.outer.cond, i1 true, i1 %inner.sel
288   ret i1 %outer.sel
291 ; In %inner.sel, %inner.cond is inverted
292 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) {
293 ; CHECK-LABEL: @andcond.010.inv.inner.cond.in.inner.sel(
294 ; CHECK-NEXT:    [[INNER_SEL:%.*]] = select i1 [[ALT_COND:%.*]], i1 [[OUTER_SEL_TRUEVAL:%.*]], i1 false
295 ; CHECK-NEXT:    [[OUTER_SEL:%.*]] = select i1 [[INNER_COND:%.*]], i1 [[INNER_SEL]], i1 [[INNER_SEL_FALSEVAL:%.*]]
296 ; CHECK-NEXT:    ret i1 [[OUTER_SEL]]
298   %outer.cond = select i1 %inner.cond, i1 %alt.cond, i1 false ; and %inner.cond, %alt.cond
299   %not.inner.cond = xor i1 %inner.cond, -1
300   %inner.sel = select i1 %not.inner.cond, i1 %inner.sel.falseval, i1 false
301   %outer.sel = select i1 %outer.cond, i1 %outer.sel.trueval, i1 %inner.sel
302   ret i1 %outer.sel
304 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) {
305 ; CHECK-LABEL: @orcond.010.inv.inner.cond.in.inner.sel(
306 ; CHECK-NEXT:    [[INNER_SEL:%.*]] = select i1 [[ALT_COND:%.*]], i1 true, i1 [[OUTER_SEL_FALSEVAL:%.*]]
307 ; CHECK-NEXT:    [[OUTER_SEL:%.*]] = select i1 [[INNER_COND:%.*]], i1 [[INNER_SEL_TRUEVAL:%.*]], i1 [[INNER_SEL]]
308 ; CHECK-NEXT:    ret i1 [[OUTER_SEL]]
310   %outer.cond = select i1 %inner.cond, i1 true, i1 %alt.cond ; or %inner.cond, %alt.cond
311   %not.inner.cond = xor i1 %inner.cond, -1
312   %inner.sel = select i1 %not.inner.cond, i1 true, i1 %inner.sel.trueval
313   %outer.sel = select i1 %outer.cond, i1 %inner.sel, i1 %outer.sel.falseval
314   ret i1 %outer.sel
317 ; In %outer.cond, %inner.cond is inverted
318 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) {
319 ; CHECK-LABEL: @andcond.100.inv.inner.cond.in.outer.cond(
320 ; CHECK-NEXT:    [[INNER_SEL:%.*]] = select i1 [[ALT_COND:%.*]], i8 [[OUTER_SEL_TRUEVAL:%.*]], i8 [[INNER_SEL_FALSEVAL:%.*]]
321 ; CHECK-NEXT:    [[OUTER_SEL:%.*]] = select i1 [[INNER_COND:%.*]], i8 [[INNER_SEL_TRUEVAL:%.*]], i8 [[INNER_SEL]]
322 ; CHECK-NEXT:    ret i8 [[OUTER_SEL]]
324   %not.inner.cond = xor i1 %inner.cond, -1
325   %outer.cond = select i1 %not.inner.cond, i1 %alt.cond, i1 false ; and %inner.cond, %alt.cond
326   %inner.sel = select i1 %inner.cond, i8 %inner.sel.trueval, i8 %inner.sel.falseval
327   %outer.sel = select i1 %outer.cond, i8 %outer.sel.trueval, i8 %inner.sel
328   ret i8 %outer.sel
330 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) {
331 ; CHECK-LABEL: @orcond.100.inv.inner.cond.in.outer.cond(
332 ; CHECK-NEXT:    [[INNER_SEL:%.*]] = select i1 [[ALT_COND:%.*]], i8 [[INNER_SEL_TRUEVAL:%.*]], i8 [[OUTER_SEL_FALSEVAL:%.*]]
333 ; CHECK-NEXT:    [[OUTER_SEL:%.*]] = select i1 [[INNER_COND:%.*]], i8 [[INNER_SEL]], i8 [[INNER_SEL_FALSEVAL:%.*]]
334 ; CHECK-NEXT:    ret i8 [[OUTER_SEL]]
336   %not.inner.cond = xor i1 %inner.cond, -1
337   %outer.cond = select i1 %not.inner.cond, i1 true, i1 %alt.cond ; or %inner.cond, %alt.cond
338   %inner.sel = select i1 %inner.cond, i8 %inner.sel.trueval, i8 %inner.sel.falseval
339   %outer.sel = select i1 %outer.cond, i8 %inner.sel, i8 %outer.sel.falseval
340   ret i8 %outer.sel
343 ; In %outer.sel, %outer.cond is inverted
344 ; In %inner.sel, %inner.cond is inverted
345 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) {
346 ; CHECK-LABEL: @andcond.011.inv.outer.cond.inv.inner.cond.in.inner.sel(
347 ; CHECK-NEXT:    [[NOT_INNER_COND:%.*]] = xor i1 [[INNER_COND:%.*]], true
348 ; CHECK-NEXT:    [[TMP1:%.*]] = select i1 [[NOT_INNER_COND]], i1 true, i1 [[INNER_SEL_FALSEVAL:%.*]]
349 ; CHECK-NEXT:    call void @use.i1(i1 [[TMP1]])
350 ; CHECK-NEXT:    [[NOT_ALT_COND:%.*]] = xor i1 [[ALT_COND:%.*]], true
351 ; CHECK-NEXT:    [[INNER_SEL:%.*]] = select i1 [[NOT_ALT_COND]], i1 [[INNER_SEL_FALSEVAL]], i1 false
352 ; CHECK-NEXT:    [[NOT_INNER_COND1:%.*]] = xor i1 [[INNER_COND]], true
353 ; CHECK-NEXT:    [[OUTER_SEL:%.*]] = select i1 [[NOT_INNER_COND1]], i1 true, i1 [[INNER_SEL]]
354 ; CHECK-NEXT:    ret i1 [[OUTER_SEL]]
356   %outer.cond = select i1 %inner.cond, i1 %alt.cond, i1 false ; and %inner.cond, %alt.cond
357   %not.inner.cond = xor i1 %inner.cond, -1
358   %inner.sel = select i1 %not.inner.cond, i1 true, i1 %inner.sel.falseval
359   %not.outer.cond = xor i1 %outer.cond, -1
360   call void @use.i1(i1 %inner.sel)
361   %outer.sel = select i1 %not.outer.cond, i1 %inner.sel, i1 false
362   ret i1 %outer.sel
364 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) {
365 ; CHECK-LABEL: @orcond.011.inv.outer.cond.inv.inner.cond.in.inner.sel(
366 ; CHECK-NEXT:    [[NOT_INNER_COND:%.*]] = xor i1 [[INNER_COND:%.*]], true
367 ; CHECK-NEXT:    [[TMP1:%.*]] = select i1 [[NOT_INNER_COND]], i1 [[INNER_SEL_TRUEVAL:%.*]], i1 false
368 ; CHECK-NEXT:    call void @use.i1(i1 [[TMP1]])
369 ; CHECK-NEXT:    [[NOT_ALT_COND:%.*]] = xor i1 [[ALT_COND:%.*]], true
370 ; CHECK-NEXT:    [[INNER_SEL:%.*]] = select i1 [[NOT_ALT_COND]], i1 true, i1 [[INNER_SEL_TRUEVAL]]
371 ; CHECK-NEXT:    [[NOT_INNER_COND1:%.*]] = xor i1 [[INNER_COND]], true
372 ; CHECK-NEXT:    [[OUTER_SEL:%.*]] = select i1 [[NOT_INNER_COND1]], i1 [[INNER_SEL]], i1 false
373 ; CHECK-NEXT:    ret i1 [[OUTER_SEL]]
375   %outer.cond = select i1 %inner.cond, i1 true, i1 %alt.cond ; or %inner.cond, %alt.cond
376   %not.inner.cond = xor i1 %inner.cond, -1
377   %inner.sel = select i1 %not.inner.cond, i1 %inner.sel.trueval, i1 false
378   call void @use.i1(i1 %inner.sel)
379   %not.outer.cond = xor i1 %outer.cond, -1
380   %outer.sel = select i1 %not.outer.cond, i1 true, i1 %inner.sel
381   ret i1 %outer.sel
384 ; In %outer.sel, %outer.cond is inverted
385 ; In %outer.cond, %inner.cond is inverted
386 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) {
387 ; CHECK-LABEL: @andcond.101.inv.outer.cond.inv.inner.cond.in.outer.cond(
388 ; CHECK-NEXT:    [[TMP1:%.*]] = select i1 [[INNER_COND:%.*]], i1 [[INNER_SEL_TRUEVAL:%.*]], i1 [[INNER_SEL_FALSEVAL:%.*]]
389 ; CHECK-NEXT:    call void @use.i1(i1 [[TMP1]])
390 ; CHECK-NEXT:    [[ALT_COND_NOT:%.*]] = xor i1 [[ALT_COND:%.*]], true
391 ; CHECK-NEXT:    [[INNER_SEL:%.*]] = select i1 [[ALT_COND_NOT]], i1 [[INNER_SEL_FALSEVAL]], i1 false
392 ; CHECK-NEXT:    [[OUTER_SEL:%.*]] = select i1 [[INNER_COND]], i1 [[INNER_SEL_TRUEVAL]], i1 [[INNER_SEL]]
393 ; CHECK-NEXT:    ret i1 [[OUTER_SEL]]
395   %not.inner.cond = xor i1 %inner.cond, -1
396   %outer.cond = select i1 %not.inner.cond, i1 %alt.cond, i1 false ; and %inner.cond, %alt.cond
397   %inner.sel = select i1 %inner.cond, i1 %inner.sel.trueval, i1 %inner.sel.falseval
398   call void @use.i1(i1 %inner.sel)
399   %not.outer.cond = xor i1 %outer.cond, -1
400   %outer.sel = select i1 %not.outer.cond, i1 %inner.sel, i1 false
401   ret i1 %outer.sel
403 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) {
404 ; CHECK-LABEL: @orcond.101.inv.outer.cond.inv.inner.cond.in.outer.cond(
405 ; CHECK-NEXT:    [[TMP1:%.*]] = select i1 [[INNER_COND:%.*]], i1 [[INNER_SEL_TRUEVAL:%.*]], i1 [[INNER_SEL_FALSEVAL:%.*]]
406 ; CHECK-NEXT:    call void @use.i1(i1 [[TMP1]])
407 ; CHECK-NEXT:    [[ALT_COND_NOT:%.*]] = xor i1 [[ALT_COND:%.*]], true
408 ; CHECK-NEXT:    [[INNER_SEL:%.*]] = select i1 [[ALT_COND_NOT]], i1 true, i1 [[INNER_SEL_TRUEVAL]]
409 ; CHECK-NEXT:    [[OUTER_SEL:%.*]] = select i1 [[INNER_COND]], i1 [[INNER_SEL]], i1 [[INNER_SEL_FALSEVAL]]
410 ; CHECK-NEXT:    ret i1 [[OUTER_SEL]]
412   %not.inner.cond = xor i1 %inner.cond, -1
413   %outer.cond = select i1 %not.inner.cond, i1 true, i1 %alt.cond ; or %inner.cond, %alt.cond
414   %inner.sel = select i1 %inner.cond, i1 %inner.sel.trueval, i1 %inner.sel.falseval
415   call void @use.i1(i1 %inner.sel)
416   %not.outer.cond = xor i1 %outer.cond, -1
417   %outer.sel = select i1 %not.outer.cond, i1 true, i1 %inner.sel
418   ret i1 %outer.sel
421 ; In %inner.sel, %inner.cond is inverted
422 ; In %outer.cond, %inner.cond is inverted
423 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) {
424 ; CHECK-LABEL: @andcond.110.inv.inner.cond.in.inner.sel.inv.inner.cond.in.outer.cond(
425 ; CHECK-NEXT:    [[NOT_INNER_COND_0:%.*]] = xor i1 [[INNER_COND:%.*]], true
426 ; CHECK-NEXT:    [[INNER_SEL:%.*]] = select i1 [[ALT_COND:%.*]], i1 [[OUTER_SEL_TRUEVAL:%.*]], i1 [[INNER_SEL_FALSEVAL:%.*]]
427 ; CHECK-NEXT:    [[OUTER_SEL:%.*]] = select i1 [[NOT_INNER_COND_0]], i1 [[INNER_SEL]], i1 false
428 ; CHECK-NEXT:    ret i1 [[OUTER_SEL]]
430   %not.inner.cond.0 = xor i1 %inner.cond, -1
431   %outer.cond = select i1 %not.inner.cond.0, i1 %alt.cond, i1 false ; and %inner.cond, %alt.cond
432   %not.inner.cond.1 = xor i1 %inner.cond, -1
433   %inner.sel = select i1 %not.inner.cond.1, i1 %inner.sel.falseval, i1 false
434   %outer.sel = select i1 %outer.cond, i1 %outer.sel.trueval, i1 %inner.sel
435   ret i1 %outer.sel
437 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) {
438 ; CHECK-LABEL: @orcond.110.inv.inner.cond.in.inner.sel.inv.inner.cond.in.outer.cond(
439 ; CHECK-NEXT:    [[NOT_INNER_COND_0:%.*]] = xor i1 [[INNER_COND:%.*]], true
440 ; CHECK-NEXT:    [[INNER_SEL:%.*]] = select i1 [[ALT_COND:%.*]], i1 [[INNER_SEL_TRUEVAL:%.*]], i1 [[OUTER_SEL_FALSEVAL:%.*]]
441 ; CHECK-NEXT:    [[OUTER_SEL:%.*]] = select i1 [[NOT_INNER_COND_0]], i1 true, i1 [[INNER_SEL]]
442 ; CHECK-NEXT:    ret i1 [[OUTER_SEL]]
444   %not.inner.cond.0 = xor i1 %inner.cond, -1
445   %outer.cond = select i1 %not.inner.cond.0, i1 true, i1 %alt.cond ; or %inner.cond, %alt.cond
446   %not.inner.cond.1 = xor i1 %inner.cond, -1
447   %inner.sel = select i1 %not.inner.cond.1, i1 true, i1 %inner.sel.trueval
448   %outer.sel = select i1 %outer.cond, i1 %inner.sel, i1 %outer.sel.falseval
449   ret i1 %outer.sel
452 ; In %outer.sel, %outer.cond is inverted
453 ; In %inner.sel, %inner.cond is inverted
454 ; In %outer.cond, %inner.cond is inverted
455 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) {
456 ; CHECK-LABEL: @andcond.111.inv.all.conds(
457 ; CHECK-NEXT:    [[NOT_INNER_COND_0:%.*]] = xor i1 [[INNER_COND:%.*]], true
458 ; CHECK-NEXT:    [[OUTER_COND:%.*]] = select i1 [[NOT_INNER_COND_0]], i1 [[ALT_COND:%.*]], i1 false
459 ; CHECK-NEXT:    call void @use.i1(i1 [[OUTER_COND]])
460 ; CHECK-NEXT:    [[NOT_INNER_COND_1:%.*]] = xor i1 [[INNER_COND]], true
461 ; CHECK-NEXT:    [[TMP1:%.*]] = select i1 [[NOT_INNER_COND_1]], i1 [[INNER_SEL_FALSEVAL:%.*]], i1 false
462 ; CHECK-NEXT:    call void @use.i1(i1 [[TMP1]])
463 ; CHECK-NEXT:    [[TMP2:%.*]] = select i1 [[INNER_COND]], i1 true, i1 [[ALT_COND]]
464 ; CHECK-NEXT:    [[TMP3:%.*]] = xor i1 [[TMP2]], true
465 ; CHECK-NEXT:    [[OUTER_SEL:%.*]] = select i1 [[TMP3]], i1 [[INNER_SEL_FALSEVAL]], i1 false
466 ; CHECK-NEXT:    ret i1 [[OUTER_SEL]]
468   %not.inner.cond.0 = xor i1 %inner.cond, -1
469   %outer.cond = select i1 %not.inner.cond.0, i1 %alt.cond, i1 false ; and %inner.cond, %alt.cond
470   call void @use.i1(i1 %outer.cond)
471   %not.inner.cond.1 = xor i1 %inner.cond, -1
472   %inner.sel = select i1 %not.inner.cond.1, i1 %inner.sel.falseval, i1 false
473   call void @use.i1(i1 %inner.sel)
474   %not.outer.cond = xor i1 %outer.cond, -1
475   %outer.sel = select i1 %not.outer.cond, i1 %inner.sel, i1 false
476   ret i1 %outer.sel
478 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) {
479 ; CHECK-LABEL: @orcond.111.inv.all.conds(
480 ; CHECK-NEXT:    [[NOT_INNER_COND_0:%.*]] = xor i1 [[INNER_COND:%.*]], true
481 ; CHECK-NEXT:    [[OUTER_COND:%.*]] = select i1 [[NOT_INNER_COND_0]], i1 true, i1 [[ALT_COND:%.*]]
482 ; CHECK-NEXT:    call void @use.i1(i1 [[OUTER_COND]])
483 ; CHECK-NEXT:    [[NOT_INNER_COND_1:%.*]] = xor i1 [[INNER_COND]], true
484 ; CHECK-NEXT:    [[TMP1:%.*]] = select i1 [[NOT_INNER_COND_1]], i1 true, i1 [[INNER_SEL_TRUEVAL:%.*]]
485 ; CHECK-NEXT:    call void @use.i1(i1 [[TMP1]])
486 ; CHECK-NEXT:    [[TMP2:%.*]] = select i1 [[INNER_COND]], i1 [[ALT_COND]], i1 false
487 ; CHECK-NEXT:    [[TMP3:%.*]] = xor i1 [[TMP2]], true
488 ; CHECK-NEXT:    [[OUTER_SEL:%.*]] = select i1 [[TMP3]], i1 true, i1 [[INNER_SEL_TRUEVAL]]
489 ; CHECK-NEXT:    ret i1 [[OUTER_SEL]]
491   %not.inner.cond.0 = xor i1 %inner.cond, -1
492   %outer.cond = select i1 %not.inner.cond.0, i1 true, i1 %alt.cond ; or %inner.cond, %alt.cond
493   call void @use.i1(i1 %outer.cond)
494   %not.inner.cond.1 = xor i1 %inner.cond, -1
495   %inner.sel = select i1 %not.inner.cond.1, i1 true, i1 %inner.sel.trueval
496   call void @use.i1(i1 %inner.sel)
497   %not.outer.cond = xor i1 %outer.cond, -1
498   %outer.sel = select i1 %not.outer.cond, i1 true, i1 %inner.sel
499   ret i1 %outer.sel
502 define i8 @test_implied_true(i8 %x) {
503 ; CHECK-LABEL: @test_implied_true(
504 ; CHECK-NEXT:    [[CMP2:%.*]] = icmp slt i8 [[X:%.*]], 0
505 ; CHECK-NEXT:    [[SEL2:%.*]] = select i1 [[CMP2]], i8 0, i8 20
506 ; CHECK-NEXT:    ret i8 [[SEL2]]
508   %cmp1 = icmp slt i8 %x, 10
509   %cmp2 = icmp slt i8 %x, 0
510   %sel1 = select i1 %cmp1, i8 0, i8 5
511   %sel2 = select i1 %cmp2, i8 %sel1, i8 20
512   ret i8 %sel2
515 define <2 x i8> @test_implied_true_vec(<2 x i8> %x) {
516 ; CHECK-LABEL: @test_implied_true_vec(
517 ; CHECK-NEXT:    [[CMP2:%.*]] = icmp slt <2 x i8> [[X:%.*]], zeroinitializer
518 ; CHECK-NEXT:    [[SEL2:%.*]] = select <2 x i1> [[CMP2]], <2 x i8> zeroinitializer, <2 x i8> splat (i8 20)
519 ; CHECK-NEXT:    ret <2 x i8> [[SEL2]]
521   %cmp1 = icmp slt <2 x i8> %x, <i8 10, i8 10>
522   %cmp2 = icmp slt <2 x i8> %x, zeroinitializer
523   %sel1 = select <2 x i1> %cmp1, <2 x i8> zeroinitializer, <2 x i8> <i8 5, i8 5>
524   %sel2 = select <2 x i1> %cmp2, <2 x i8> %sel1, <2 x i8> <i8 20, i8 20>
525   ret <2 x i8> %sel2
528 define i8 @test_implied_true_falseval(i8 %x) {
529 ; CHECK-LABEL: @test_implied_true_falseval(
530 ; CHECK-NEXT:    [[CMP2:%.*]] = icmp sgt i8 [[X:%.*]], 0
531 ; CHECK-NEXT:    [[SEL2:%.*]] = select i1 [[CMP2]], i8 20, i8 0
532 ; CHECK-NEXT:    ret i8 [[SEL2]]
534   %cmp1 = icmp slt i8 %x, 10
535   %cmp2 = icmp sgt i8 %x, 0
536   %sel1 = select i1 %cmp1, i8 0, i8 5
537   %sel2 = select i1 %cmp2, i8 20, i8 %sel1
538   ret i8 %sel2
541 define i8 @test_implied_false(i8 %x) {
542 ; CHECK-LABEL: @test_implied_false(
543 ; CHECK-NEXT:    [[CMP2:%.*]] = icmp slt i8 [[X:%.*]], 0
544 ; CHECK-NEXT:    [[SEL2:%.*]] = select i1 [[CMP2]], i8 5, i8 20
545 ; CHECK-NEXT:    ret i8 [[SEL2]]
547   %cmp1 = icmp sgt i8 %x, 10
548   %cmp2 = icmp slt i8 %x, 0
549   %sel1 = select i1 %cmp1, i8 0, i8 5
550   %sel2 = select i1 %cmp2, i8 %sel1, i8 20
551   ret i8 %sel2
554 ; Negative tests
556 define i8 @test_imply_fail(i8 %x) {
557 ; CHECK-LABEL: @test_imply_fail(
558 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i8 [[X:%.*]], -10
559 ; CHECK-NEXT:    [[CMP2:%.*]] = icmp slt i8 [[X]], 0
560 ; CHECK-NEXT:    [[SEL1:%.*]] = select i1 [[CMP1]], i8 0, i8 5
561 ; CHECK-NEXT:    [[SEL2:%.*]] = select i1 [[CMP2]], i8 [[SEL1]], i8 20
562 ; CHECK-NEXT:    ret i8 [[SEL2]]
564   %cmp1 = icmp slt i8 %x, -10
565   %cmp2 = icmp slt i8 %x, 0
566   %sel1 = select i1 %cmp1, i8 0, i8 5
567   %sel2 = select i1 %cmp2, i8 %sel1, i8 20
568   ret i8 %sel2
571 define <2 x i8> @test_imply_type_mismatch(<2 x i8> %x, i8 %y) {
572 ; CHECK-LABEL: @test_imply_type_mismatch(
573 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt <2 x i8> [[X:%.*]], splat (i8 10)
574 ; CHECK-NEXT:    [[CMP2:%.*]] = icmp slt i8 [[Y:%.*]], 0
575 ; CHECK-NEXT:    [[SEL1:%.*]] = select <2 x i1> [[CMP1]], <2 x i8> zeroinitializer, <2 x i8> splat (i8 5)
576 ; CHECK-NEXT:    [[SEL2:%.*]] = select i1 [[CMP2]], <2 x i8> [[SEL1]], <2 x i8> splat (i8 20)
577 ; CHECK-NEXT:    ret <2 x i8> [[SEL2]]
579   %cmp1 = icmp slt <2 x i8> %x, <i8 10, i8 10>
580   %cmp2 = icmp slt i8 %y, 0
581   %sel1 = select <2 x i1> %cmp1, <2 x i8> zeroinitializer, <2 x i8> <i8 5, i8 5>
582   %sel2 = select i1 %cmp2, <2 x i8> %sel1, <2 x i8> <i8 20, i8 20>
583   ret <2 x i8> %sel2
586 define <4 x i1> @test_dont_crash(i1 %cond, <4 x i1> %a, <4 x i1> %b) {
587 ; CHECK-LABEL: @test_dont_crash(
588 ; CHECK-NEXT:  entry:
589 ; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[COND:%.*]], <4 x i1> [[A:%.*]], <4 x i1> zeroinitializer
590 ; CHECK-NEXT:    [[AND:%.*]] = and <4 x i1> [[SEL]], [[B:%.*]]
591 ; CHECK-NEXT:    ret <4 x i1> [[AND]]
593 entry:
594   %sel = select i1 %cond, <4 x i1> %a, <4 x i1> zeroinitializer
595   %and = and <4 x i1> %sel, %b
596   ret <4 x i1> %and