xref: /llvm-project/llvm/test/Transforms/InstCombine/nested-select.ll (revision 38fffa630ee80163dc65e759392ad29798905679)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt -passes=instcombine -S < %s | FileCheck %s
3
4declare void @use.i1(i1)
5declare void @use.i8(i8)
6
7; Basic test
8
9define 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]]
14;
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
19}
20define 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]]
25;
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
30}
31
32; Extra use tests (basic test, no inversions)
33
34define 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]]
41;
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
47}
48define 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]]
55;
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
61}
62
63define 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]]
70;
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
76}
77define 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]]
84;
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
90}
91
92define 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]]
100;
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
107}
108define 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]]
116;
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
123}
124
125; Mismatched 'common' cond
126
127define 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]]
133;
134
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
139}
140define 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]]
146;
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
151}
152
153define 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]]
161;
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
168}
169define 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]]
177;
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
184}
185
186define 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]]
193;
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
199}
200define 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]]
207;
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
213}
214
215define 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]]
222;
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
228}
229define 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]]
236;
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
242}
243
244; Not an inversion
245; Based on reproduced from https://reviews.llvm.org/D139275#4001580
246define 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]]
253;
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
259}
260
261; Tests with intervening inversions
262
263; In %outer.sel, %outer.cond is inverted
264define 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]]
270;
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
276}
277define 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]]
283;
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
289}
290
291; In %inner.sel, %inner.cond is inverted
292define 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]]
297;
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
303}
304define 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]]
309;
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
315}
316
317; In %outer.cond, %inner.cond is inverted
318define 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]]
323;
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
329}
330define 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]]
335;
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
341}
342
343; In %outer.sel, %outer.cond is inverted
344; In %inner.sel, %inner.cond is inverted
345define 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]]
355;
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
363}
364define 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]]
374;
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
382}
383
384; In %outer.sel, %outer.cond is inverted
385; In %outer.cond, %inner.cond is inverted
386define 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]]
394;
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
402}
403define 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]]
411;
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
419}
420
421; In %inner.sel, %inner.cond is inverted
422; In %outer.cond, %inner.cond is inverted
423define 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]]
429;
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
436}
437define 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]]
443;
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
450}
451
452; In %outer.sel, %outer.cond is inverted
453; In %inner.sel, %inner.cond is inverted
454; In %outer.cond, %inner.cond is inverted
455define 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]]
467;
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
477}
478define 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]]
490;
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
500}
501
502define 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]]
507;
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
513}
514
515define <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]]
520;
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
526}
527
528define 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]]
533;
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
539}
540
541define 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]]
546;
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
552}
553
554; Negative tests
555
556define 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]]
563;
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
569}
570
571define <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]]
578;
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
584}
585
586define <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]]
592;
593entry:
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
597}
598