1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -slp-vectorizer -mtriple=x86_64--                 -S | FileCheck %s --check-prefixes=CHECK,SSE
3; RUN: opt < %s -slp-vectorizer -mtriple=x86_64-- -mattr=avx512vl -S | FileCheck %s --check-prefixes=CHECK,AVX
4
5declare void @use1(i1)
6
7define i1 @logical_and_icmp(<4 x i32> %x) {
8; CHECK-LABEL: @logical_and_icmp(
9; CHECK-NEXT:    [[TMP1:%.*]] = icmp slt <4 x i32> [[X:%.*]], zeroinitializer
10; CHECK-NEXT:    [[TMP2:%.*]] = freeze <4 x i1> [[TMP1]]
11; CHECK-NEXT:    [[TMP3:%.*]] = call i1 @llvm.vector.reduce.and.v4i1(<4 x i1> [[TMP2]])
12; CHECK-NEXT:    ret i1 [[TMP3]]
13;
14  %x0 = extractelement <4 x i32> %x, i32 0
15  %x1 = extractelement <4 x i32> %x, i32 1
16  %x2 = extractelement <4 x i32> %x, i32 2
17  %x3 = extractelement <4 x i32> %x, i32 3
18  %c0 = icmp slt i32 %x0, 0
19  %c1 = icmp slt i32 %x1, 0
20  %c2 = icmp slt i32 %x2, 0
21  %c3 = icmp slt i32 %x3, 0
22  %s1 = select i1 %c0, i1 %c1, i1 false
23  %s2 = select i1 %s1, i1 %c2, i1 false
24  %s3 = select i1 %s2, i1 %c3, i1 false
25  ret i1 %s3
26}
27
28define i1 @logical_or_icmp(<4 x i32> %x, <4 x i32> %y) {
29; CHECK-LABEL: @logical_or_icmp(
30; CHECK-NEXT:    [[TMP1:%.*]] = icmp slt <4 x i32> [[X:%.*]], [[Y:%.*]]
31; CHECK-NEXT:    [[TMP2:%.*]] = freeze <4 x i1> [[TMP1]]
32; CHECK-NEXT:    [[TMP3:%.*]] = call i1 @llvm.vector.reduce.or.v4i1(<4 x i1> [[TMP2]])
33; CHECK-NEXT:    ret i1 [[TMP3]]
34;
35  %x0 = extractelement <4 x i32> %x, i32 0
36  %x1 = extractelement <4 x i32> %x, i32 1
37  %x2 = extractelement <4 x i32> %x, i32 2
38  %x3 = extractelement <4 x i32> %x, i32 3
39  %y0 = extractelement <4 x i32> %y, i32 0
40  %y1 = extractelement <4 x i32> %y, i32 1
41  %y2 = extractelement <4 x i32> %y, i32 2
42  %y3 = extractelement <4 x i32> %y, i32 3
43  %c0 = icmp slt i32 %x0, %y0
44  %c1 = icmp slt i32 %x1, %y1
45  %c2 = icmp slt i32 %x2, %y2
46  %c3 = icmp slt i32 %x3, %y3
47  %s1 = select i1 %c0, i1 true, i1 %c1
48  %s2 = select i1 %s1, i1 true, i1 %c2
49  %s3 = select i1 %s2, i1 true, i1 %c3
50  ret i1 %s3
51}
52
53define i1 @logical_and_fcmp(<4 x float> %x) {
54; CHECK-LABEL: @logical_and_fcmp(
55; CHECK-NEXT:    [[TMP1:%.*]] = fcmp olt <4 x float> [[X:%.*]], zeroinitializer
56; CHECK-NEXT:    [[TMP2:%.*]] = freeze <4 x i1> [[TMP1]]
57; CHECK-NEXT:    [[TMP3:%.*]] = call i1 @llvm.vector.reduce.and.v4i1(<4 x i1> [[TMP2]])
58; CHECK-NEXT:    ret i1 [[TMP3]]
59;
60  %x0 = extractelement <4 x float> %x, i32 0
61  %x1 = extractelement <4 x float> %x, i32 1
62  %x2 = extractelement <4 x float> %x, i32 2
63  %x3 = extractelement <4 x float> %x, i32 3
64  %c0 = fcmp olt float %x0, 0.0
65  %c1 = fcmp olt float %x1, 0.0
66  %c2 = fcmp olt float %x2, 0.0
67  %c3 = fcmp olt float %x3, 0.0
68  %s1 = select i1 %c0, i1 %c1, i1 false
69  %s2 = select i1 %s1, i1 %c2, i1 false
70  %s3 = select i1 %s2, i1 %c3, i1 false
71  ret i1 %s3
72}
73
74define i1 @logical_or_fcmp(<4 x float> %x) {
75; CHECK-LABEL: @logical_or_fcmp(
76; CHECK-NEXT:    [[TMP1:%.*]] = fcmp olt <4 x float> [[X:%.*]], zeroinitializer
77; CHECK-NEXT:    [[TMP2:%.*]] = freeze <4 x i1> [[TMP1]]
78; CHECK-NEXT:    [[TMP3:%.*]] = call i1 @llvm.vector.reduce.or.v4i1(<4 x i1> [[TMP2]])
79; CHECK-NEXT:    ret i1 [[TMP3]]
80;
81  %x0 = extractelement <4 x float> %x, i32 0
82  %x1 = extractelement <4 x float> %x, i32 1
83  %x2 = extractelement <4 x float> %x, i32 2
84  %x3 = extractelement <4 x float> %x, i32 3
85  %c0 = fcmp olt float %x0, 0.0
86  %c1 = fcmp olt float %x1, 0.0
87  %c2 = fcmp olt float %x2, 0.0
88  %c3 = fcmp olt float %x3, 0.0
89  %s1 = select i1 %c0, i1 true, i1 %c1
90  %s2 = select i1 %s1, i1 true, i1 %c2
91  %s3 = select i1 %s2, i1 true, i1 %c3
92  ret i1 %s3
93}
94
95define i1 @logical_and_icmp_diff_preds(<4 x i32> %x) {
96; SSE-LABEL: @logical_and_icmp_diff_preds(
97; SSE-NEXT:    [[X0:%.*]] = extractelement <4 x i32> [[X:%.*]], i32 0
98; SSE-NEXT:    [[X1:%.*]] = extractelement <4 x i32> [[X]], i32 1
99; SSE-NEXT:    [[X2:%.*]] = extractelement <4 x i32> [[X]], i32 2
100; SSE-NEXT:    [[X3:%.*]] = extractelement <4 x i32> [[X]], i32 3
101; SSE-NEXT:    [[C0:%.*]] = icmp ult i32 [[X0]], 0
102; SSE-NEXT:    [[C2:%.*]] = icmp sgt i32 [[X2]], 0
103; SSE-NEXT:    [[TMP1:%.*]] = insertelement <2 x i32> poison, i32 [[X3]], i32 0
104; SSE-NEXT:    [[TMP2:%.*]] = insertelement <2 x i32> [[TMP1]], i32 [[X1]], i32 1
105; SSE-NEXT:    [[TMP3:%.*]] = icmp slt <2 x i32> [[TMP2]], zeroinitializer
106; SSE-NEXT:    [[TMP4:%.*]] = extractelement <2 x i1> [[TMP3]], i32 1
107; SSE-NEXT:    [[S1:%.*]] = select i1 [[C0]], i1 [[TMP4]], i1 false
108; SSE-NEXT:    [[S2:%.*]] = select i1 [[S1]], i1 [[C2]], i1 false
109; SSE-NEXT:    [[TMP5:%.*]] = extractelement <2 x i1> [[TMP3]], i32 0
110; SSE-NEXT:    [[S3:%.*]] = select i1 [[S2]], i1 [[TMP5]], i1 false
111; SSE-NEXT:    ret i1 [[S3]]
112;
113; AVX-LABEL: @logical_and_icmp_diff_preds(
114; AVX-NEXT:    [[X0:%.*]] = extractelement <4 x i32> [[X:%.*]], i32 0
115; AVX-NEXT:    [[X1:%.*]] = extractelement <4 x i32> [[X]], i32 1
116; AVX-NEXT:    [[X2:%.*]] = extractelement <4 x i32> [[X]], i32 2
117; AVX-NEXT:    [[X3:%.*]] = extractelement <4 x i32> [[X]], i32 3
118; AVX-NEXT:    [[C0:%.*]] = icmp ult i32 [[X0]], 0
119; AVX-NEXT:    [[C1:%.*]] = icmp slt i32 [[X1]], 0
120; AVX-NEXT:    [[C2:%.*]] = icmp sgt i32 [[X2]], 0
121; AVX-NEXT:    [[C3:%.*]] = icmp slt i32 [[X3]], 0
122; AVX-NEXT:    [[S1:%.*]] = select i1 [[C0]], i1 [[C1]], i1 false
123; AVX-NEXT:    [[S2:%.*]] = select i1 [[S1]], i1 [[C2]], i1 false
124; AVX-NEXT:    [[S3:%.*]] = select i1 [[S2]], i1 [[C3]], i1 false
125; AVX-NEXT:    ret i1 [[S3]]
126;
127  %x0 = extractelement <4 x i32> %x, i32 0
128  %x1 = extractelement <4 x i32> %x, i32 1
129  %x2 = extractelement <4 x i32> %x, i32 2
130  %x3 = extractelement <4 x i32> %x, i32 3
131  %c0 = icmp ult i32 %x0, 0
132  %c1 = icmp slt i32 %x1, 0
133  %c2 = icmp sgt i32 %x2, 0
134  %c3 = icmp slt i32 %x3, 0
135  %s1 = select i1 %c0, i1 %c1, i1 false
136  %s2 = select i1 %s1, i1 %c2, i1 false
137  %s3 = select i1 %s2, i1 %c3, i1 false
138  ret i1 %s3
139}
140
141define i1 @logical_and_icmp_diff_const(<4 x i32> %x) {
142; CHECK-LABEL: @logical_and_icmp_diff_const(
143; CHECK-NEXT:    [[TMP1:%.*]] = icmp sgt <4 x i32> [[X:%.*]], <i32 0, i32 1, i32 2, i32 3>
144; CHECK-NEXT:    [[TMP2:%.*]] = freeze <4 x i1> [[TMP1]]
145; CHECK-NEXT:    [[TMP3:%.*]] = call i1 @llvm.vector.reduce.and.v4i1(<4 x i1> [[TMP2]])
146; CHECK-NEXT:    ret i1 [[TMP3]]
147;
148  %x0 = extractelement <4 x i32> %x, i32 0
149  %x1 = extractelement <4 x i32> %x, i32 1
150  %x2 = extractelement <4 x i32> %x, i32 2
151  %x3 = extractelement <4 x i32> %x, i32 3
152  %c0 = icmp sgt i32 %x0, 0
153  %c1 = icmp sgt i32 %x1, 1
154  %c2 = icmp sgt i32 %x2, 2
155  %c3 = icmp sgt i32 %x3, 3
156  %s1 = select i1 %c0, i1 %c1, i1 false
157  %s2 = select i1 %s1, i1 %c2, i1 false
158  %s3 = select i1 %s2, i1 %c3, i1 false
159  ret i1 %s3
160}
161
162define i1 @mixed_logical_icmp(<4 x i32> %x) {
163; CHECK-LABEL: @mixed_logical_icmp(
164; CHECK-NEXT:    [[TMP1:%.*]] = icmp sgt <4 x i32> [[X:%.*]], zeroinitializer
165; CHECK-NEXT:    [[TMP2:%.*]] = extractelement <4 x i1> [[TMP1]], i32 0
166; CHECK-NEXT:    [[TMP3:%.*]] = extractelement <4 x i1> [[TMP1]], i32 1
167; CHECK-NEXT:    [[S1:%.*]] = select i1 [[TMP2]], i1 [[TMP3]], i1 false
168; CHECK-NEXT:    [[TMP4:%.*]] = extractelement <4 x i1> [[TMP1]], i32 2
169; CHECK-NEXT:    [[S2:%.*]] = select i1 [[S1]], i1 true, i1 [[TMP4]]
170; CHECK-NEXT:    [[TMP5:%.*]] = extractelement <4 x i1> [[TMP1]], i32 3
171; CHECK-NEXT:    [[S3:%.*]] = select i1 [[S2]], i1 [[TMP5]], i1 false
172; CHECK-NEXT:    ret i1 [[S3]]
173;
174  %x0 = extractelement <4 x i32> %x, i32 0
175  %x1 = extractelement <4 x i32> %x, i32 1
176  %x2 = extractelement <4 x i32> %x, i32 2
177  %x3 = extractelement <4 x i32> %x, i32 3
178  %c0 = icmp sgt i32 %x0, 0
179  %c1 = icmp sgt i32 %x1, 0
180  %c2 = icmp sgt i32 %x2, 0
181  %c3 = icmp sgt i32 %x3, 0
182  %s1 = select i1 %c0, i1 %c1, i1 false
183  %s2 = select i1 %s1, i1 true, i1 %c2
184  %s3 = select i1 %s2, i1 %c3, i1 false
185  ret i1 %s3
186}
187
188define i1 @logical_and_icmp_subvec(<4 x i32> %x) {
189; SSE-LABEL: @logical_and_icmp_subvec(
190; SSE-NEXT:    [[X0:%.*]] = extractelement <4 x i32> [[X:%.*]], i32 0
191; SSE-NEXT:    [[X1:%.*]] = extractelement <4 x i32> [[X]], i32 1
192; SSE-NEXT:    [[X2:%.*]] = extractelement <4 x i32> [[X]], i32 2
193; SSE-NEXT:    [[TMP1:%.*]] = insertelement <2 x i32> poison, i32 [[X1]], i32 0
194; SSE-NEXT:    [[TMP2:%.*]] = insertelement <2 x i32> [[TMP1]], i32 [[X0]], i32 1
195; SSE-NEXT:    [[TMP3:%.*]] = icmp slt <2 x i32> [[TMP2]], zeroinitializer
196; SSE-NEXT:    [[C2:%.*]] = icmp slt i32 [[X2]], 0
197; SSE-NEXT:    [[TMP4:%.*]] = extractelement <2 x i1> [[TMP3]], i32 0
198; SSE-NEXT:    [[TMP5:%.*]] = extractelement <2 x i1> [[TMP3]], i32 1
199; SSE-NEXT:    [[S1:%.*]] = select i1 [[TMP5]], i1 [[TMP4]], i1 false
200; SSE-NEXT:    [[S2:%.*]] = select i1 [[S1]], i1 [[C2]], i1 false
201; SSE-NEXT:    ret i1 [[S2]]
202;
203; AVX-LABEL: @logical_and_icmp_subvec(
204; AVX-NEXT:    [[X0:%.*]] = extractelement <4 x i32> [[X:%.*]], i32 0
205; AVX-NEXT:    [[X1:%.*]] = extractelement <4 x i32> [[X]], i32 1
206; AVX-NEXT:    [[X2:%.*]] = extractelement <4 x i32> [[X]], i32 2
207; AVX-NEXT:    [[C0:%.*]] = icmp slt i32 [[X0]], 0
208; AVX-NEXT:    [[C1:%.*]] = icmp slt i32 [[X1]], 0
209; AVX-NEXT:    [[C2:%.*]] = icmp slt i32 [[X2]], 0
210; AVX-NEXT:    [[S1:%.*]] = select i1 [[C0]], i1 [[C1]], i1 false
211; AVX-NEXT:    [[S2:%.*]] = select i1 [[S1]], i1 [[C2]], i1 false
212; AVX-NEXT:    ret i1 [[S2]]
213;
214  %x0 = extractelement <4 x i32> %x, i32 0
215  %x1 = extractelement <4 x i32> %x, i32 1
216  %x2 = extractelement <4 x i32> %x, i32 2
217  %c0 = icmp slt i32 %x0, 0
218  %c1 = icmp slt i32 %x1, 0
219  %c2 = icmp slt i32 %x2, 0
220  %s1 = select i1 %c0, i1 %c1, i1 false
221  %s2 = select i1 %s1, i1 %c2, i1 false
222  ret i1 %s2
223}
224
225; TODO: This is better than all-scalar and still safe,
226;       but we want this to be 2 reductions with glue
227;       logic...or a wide reduction?
228
229define i1 @logical_and_icmp_clamp(<4 x i32> %x) {
230; CHECK-LABEL: @logical_and_icmp_clamp(
231; CHECK-NEXT:    [[TMP1:%.*]] = icmp slt <4 x i32> [[X:%.*]], <i32 42, i32 42, i32 42, i32 42>
232; CHECK-NEXT:    [[TMP2:%.*]] = icmp sgt <4 x i32> [[X]], <i32 17, i32 17, i32 17, i32 17>
233; CHECK-NEXT:    [[TMP3:%.*]] = freeze <4 x i1> [[TMP2]]
234; CHECK-NEXT:    [[TMP4:%.*]] = call i1 @llvm.vector.reduce.and.v4i1(<4 x i1> [[TMP3]])
235; CHECK-NEXT:    [[TMP5:%.*]] = freeze <4 x i1> [[TMP1]]
236; CHECK-NEXT:    [[TMP6:%.*]] = call i1 @llvm.vector.reduce.and.v4i1(<4 x i1> [[TMP5]])
237; CHECK-NEXT:    [[OP_RDX:%.*]] = select i1 [[TMP4]], i1 [[TMP6]], i1 false
238; CHECK-NEXT:    ret i1 [[OP_RDX]]
239;
240  %x0 = extractelement <4 x i32> %x, i32 0
241  %x1 = extractelement <4 x i32> %x, i32 1
242  %x2 = extractelement <4 x i32> %x, i32 2
243  %x3 = extractelement <4 x i32> %x, i32 3
244  %c0 = icmp slt i32 %x0, 42
245  %c1 = icmp slt i32 %x1, 42
246  %c2 = icmp slt i32 %x2, 42
247  %c3 = icmp slt i32 %x3, 42
248  %d0 = icmp sgt i32 %x0, 17
249  %d1 = icmp sgt i32 %x1, 17
250  %d2 = icmp sgt i32 %x2, 17
251  %d3 = icmp sgt i32 %x3, 17
252  %s1 = select i1 %c0, i1 %c1, i1 false
253  %s2 = select i1 %s1, i1 %c2, i1 false
254  %s3 = select i1 %s2, i1 %c3, i1 false
255  %s4 = select i1 %s3, i1 %d0, i1 false
256  %s5 = select i1 %s4, i1 %d1, i1 false
257  %s6 = select i1 %s5, i1 %d2, i1 false
258  %s7 = select i1 %s6, i1 %d3, i1 false
259  ret i1 %s7
260}
261
262define i1 @logical_and_icmp_clamp_extra_use_cmp(<4 x i32> %x) {
263; CHECK-LABEL: @logical_and_icmp_clamp_extra_use_cmp(
264; CHECK-NEXT:    [[TMP1:%.*]] = icmp slt <4 x i32> [[X:%.*]], <i32 42, i32 42, i32 42, i32 42>
265; CHECK-NEXT:    [[TMP2:%.*]] = extractelement <4 x i1> [[TMP1]], i32 2
266; CHECK-NEXT:    call void @use1(i1 [[TMP2]])
267; CHECK-NEXT:    [[TMP3:%.*]] = icmp sgt <4 x i32> [[X]], <i32 17, i32 17, i32 17, i32 17>
268; CHECK-NEXT:    [[TMP4:%.*]] = freeze <4 x i1> [[TMP3]]
269; CHECK-NEXT:    [[TMP5:%.*]] = call i1 @llvm.vector.reduce.and.v4i1(<4 x i1> [[TMP4]])
270; CHECK-NEXT:    [[TMP6:%.*]] = freeze <4 x i1> [[TMP1]]
271; CHECK-NEXT:    [[TMP7:%.*]] = call i1 @llvm.vector.reduce.and.v4i1(<4 x i1> [[TMP6]])
272; CHECK-NEXT:    [[OP_RDX:%.*]] = select i1 [[TMP5]], i1 [[TMP7]], i1 false
273; CHECK-NEXT:    ret i1 [[OP_RDX]]
274;
275  %x0 = extractelement <4 x i32> %x, i32 0
276  %x1 = extractelement <4 x i32> %x, i32 1
277  %x2 = extractelement <4 x i32> %x, i32 2
278  %x3 = extractelement <4 x i32> %x, i32 3
279  %c0 = icmp slt i32 %x0, 42
280  %c1 = icmp slt i32 %x1, 42
281  %c2 = icmp slt i32 %x2, 42
282  call void @use1(i1 %c2)
283  %c3 = icmp slt i32 %x3, 42
284  %d0 = icmp sgt i32 %x0, 17
285  %d1 = icmp sgt i32 %x1, 17
286  %d2 = icmp sgt i32 %x2, 17
287  %d3 = icmp sgt i32 %x3, 17
288  %s1 = select i1 %c0, i1 %c1, i1 false
289  %s2 = select i1 %s1, i1 %c2, i1 false
290  %s3 = select i1 %s2, i1 %c3, i1 false
291  %s4 = select i1 %s3, i1 %d0, i1 false
292  %s5 = select i1 %s4, i1 %d1, i1 false
293  %s6 = select i1 %s5, i1 %d2, i1 false
294  %s7 = select i1 %s6, i1 %d3, i1 false
295  ret i1 %s7
296}
297
298define i1 @logical_and_icmp_clamp_extra_use_select(<4 x i32> %x) {
299; CHECK-LABEL: @logical_and_icmp_clamp_extra_use_select(
300; CHECK-NEXT:    [[TMP1:%.*]] = icmp slt <4 x i32> [[X:%.*]], <i32 42, i32 42, i32 42, i32 42>
301; CHECK-NEXT:    [[TMP2:%.*]] = icmp sgt <4 x i32> [[X]], <i32 17, i32 17, i32 17, i32 17>
302; CHECK-NEXT:    [[TMP3:%.*]] = extractelement <4 x i1> [[TMP1]], i32 0
303; CHECK-NEXT:    [[TMP4:%.*]] = extractelement <4 x i1> [[TMP1]], i32 1
304; CHECK-NEXT:    [[S1:%.*]] = select i1 [[TMP3]], i1 [[TMP4]], i1 false
305; CHECK-NEXT:    [[TMP5:%.*]] = extractelement <4 x i1> [[TMP1]], i32 2
306; CHECK-NEXT:    [[S2:%.*]] = select i1 [[S1]], i1 [[TMP5]], i1 false
307; CHECK-NEXT:    call void @use1(i1 [[S2]])
308; CHECK-NEXT:    [[TMP6:%.*]] = freeze <4 x i1> [[TMP2]]
309; CHECK-NEXT:    [[TMP7:%.*]] = call i1 @llvm.vector.reduce.and.v4i1(<4 x i1> [[TMP6]])
310; CHECK-NEXT:    [[TMP8:%.*]] = extractelement <4 x i1> [[TMP1]], i32 3
311; CHECK-NEXT:    [[OP_RDX:%.*]] = select i1 [[TMP7]], i1 [[TMP8]], i1 false
312; CHECK-NEXT:    [[OP_RDX1:%.*]] = select i1 [[OP_RDX]], i1 [[S2]], i1 false
313; CHECK-NEXT:    ret i1 [[OP_RDX1]]
314;
315  %x0 = extractelement <4 x i32> %x, i32 0
316  %x1 = extractelement <4 x i32> %x, i32 1
317  %x2 = extractelement <4 x i32> %x, i32 2
318  %x3 = extractelement <4 x i32> %x, i32 3
319  %c0 = icmp slt i32 %x0, 42
320  %c1 = icmp slt i32 %x1, 42
321  %c2 = icmp slt i32 %x2, 42
322  %c3 = icmp slt i32 %x3, 42
323  %d0 = icmp sgt i32 %x0, 17
324  %d1 = icmp sgt i32 %x1, 17
325  %d2 = icmp sgt i32 %x2, 17
326  %d3 = icmp sgt i32 %x3, 17
327  %s1 = select i1 %c0, i1 %c1, i1 false
328  %s2 = select i1 %s1, i1 %c2, i1 false
329  call void @use1(i1 %s2)
330  %s3 = select i1 %s2, i1 %c3, i1 false
331  %s4 = select i1 %s3, i1 %d0, i1 false
332  %s5 = select i1 %s4, i1 %d1, i1 false
333  %s6 = select i1 %s5, i1 %d2, i1 false
334  %s7 = select i1 %s6, i1 %d3, i1 false
335  ret i1 %s7
336}
337
338define i1 @logical_and_icmp_clamp_v8i32(<8 x i32> %x, <8 x i32> %y) {
339; CHECK-LABEL: @logical_and_icmp_clamp_v8i32(
340; CHECK-NEXT:    [[X0:%.*]] = extractelement <8 x i32> [[X:%.*]], i32 0
341; CHECK-NEXT:    [[X1:%.*]] = extractelement <8 x i32> [[X]], i32 1
342; CHECK-NEXT:    [[X2:%.*]] = extractelement <8 x i32> [[X]], i32 2
343; CHECK-NEXT:    [[X3:%.*]] = extractelement <8 x i32> [[X]], i32 3
344; CHECK-NEXT:    [[Y0:%.*]] = extractelement <8 x i32> [[Y:%.*]], i32 0
345; CHECK-NEXT:    [[Y1:%.*]] = extractelement <8 x i32> [[Y]], i32 1
346; CHECK-NEXT:    [[Y2:%.*]] = extractelement <8 x i32> [[Y]], i32 2
347; CHECK-NEXT:    [[Y3:%.*]] = extractelement <8 x i32> [[Y]], i32 3
348; CHECK-NEXT:    [[TMP1:%.*]] = insertelement <8 x i32> poison, i32 [[X1]], i32 0
349; CHECK-NEXT:    [[TMP2:%.*]] = insertelement <8 x i32> [[TMP1]], i32 [[X0]], i32 1
350; CHECK-NEXT:    [[TMP3:%.*]] = insertelement <8 x i32> [[TMP2]], i32 [[X2]], i32 2
351; CHECK-NEXT:    [[TMP4:%.*]] = insertelement <8 x i32> [[TMP3]], i32 [[X3]], i32 3
352; CHECK-NEXT:    [[SHUFFLE:%.*]] = shufflevector <8 x i32> [[TMP4]], <8 x i32> poison, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 1, i32 0, i32 2, i32 3>
353; CHECK-NEXT:    [[TMP5:%.*]] = insertelement <8 x i32> <i32 42, i32 42, i32 42, i32 42, i32 poison, i32 poison, i32 poison, i32 poison>, i32 [[Y0]], i32 4
354; CHECK-NEXT:    [[TMP6:%.*]] = insertelement <8 x i32> [[TMP5]], i32 [[Y1]], i32 5
355; CHECK-NEXT:    [[TMP7:%.*]] = insertelement <8 x i32> [[TMP6]], i32 [[Y2]], i32 6
356; CHECK-NEXT:    [[TMP8:%.*]] = insertelement <8 x i32> [[TMP7]], i32 [[Y3]], i32 7
357; CHECK-NEXT:    [[TMP9:%.*]] = icmp slt <8 x i32> [[SHUFFLE]], [[TMP8]]
358; CHECK-NEXT:    [[TMP10:%.*]] = freeze <8 x i1> [[TMP9]]
359; CHECK-NEXT:    [[TMP11:%.*]] = call i1 @llvm.vector.reduce.and.v8i1(<8 x i1> [[TMP10]])
360; CHECK-NEXT:    ret i1 [[TMP11]]
361;
362  %x0 = extractelement <8 x i32> %x, i32 0
363  %x1 = extractelement <8 x i32> %x, i32 1
364  %x2 = extractelement <8 x i32> %x, i32 2
365  %x3 = extractelement <8 x i32> %x, i32 3
366  %y0 = extractelement <8 x i32> %y, i32 0
367  %y1 = extractelement <8 x i32> %y, i32 1
368  %y2 = extractelement <8 x i32> %y, i32 2
369  %y3 = extractelement <8 x i32> %y, i32 3
370  %c0 = icmp slt i32 %x0, 42
371  %c1 = icmp slt i32 %x1, 42
372  %c2 = icmp slt i32 %x2, 42
373  %c3 = icmp slt i32 %x3, 42
374  %d0 = icmp slt i32 %x0, %y0
375  %d1 = icmp slt i32 %x1, %y1
376  %d2 = icmp slt i32 %x2, %y2
377  %d3 = icmp slt i32 %x3, %y3
378  %s1 = select i1 %c0, i1 %c1, i1 false
379  %s2 = select i1 %s1, i1 %c2, i1 false
380  %s3 = select i1 %s2, i1 %c3, i1 false
381  %s4 = select i1 %s3, i1 %d0, i1 false
382  %s5 = select i1 %s4, i1 %d1, i1 false
383  %s6 = select i1 %s5, i1 %d2, i1 false
384  %s7 = select i1 %s6, i1 %d3, i1 false
385  ret i1 %s7
386}
387
388define i1 @logical_and_icmp_clamp_partial(<4 x i32> %x) {
389; SSE-LABEL: @logical_and_icmp_clamp_partial(
390; SSE-NEXT:    [[TMP1:%.*]] = extractelement <4 x i32> [[X:%.*]], i32 2
391; SSE-NEXT:    [[TMP2:%.*]] = extractelement <4 x i32> [[X]], i32 1
392; SSE-NEXT:    [[TMP3:%.*]] = extractelement <4 x i32> [[X]], i32 0
393; SSE-NEXT:    [[TMP4:%.*]] = insertelement <2 x i32> poison, i32 [[TMP2]], i32 0
394; SSE-NEXT:    [[TMP5:%.*]] = insertelement <2 x i32> [[TMP4]], i32 [[TMP3]], i32 1
395; SSE-NEXT:    [[TMP6:%.*]] = icmp slt <2 x i32> [[TMP5]], <i32 42, i32 42>
396; SSE-NEXT:    [[C2:%.*]] = icmp slt i32 [[TMP1]], 42
397; SSE-NEXT:    [[TMP7:%.*]] = icmp sgt <4 x i32> [[X]], <i32 17, i32 17, i32 17, i32 17>
398; SSE-NEXT:    [[TMP8:%.*]] = freeze <4 x i1> [[TMP7]]
399; SSE-NEXT:    [[TMP9:%.*]] = call i1 @llvm.vector.reduce.and.v4i1(<4 x i1> [[TMP8]])
400; SSE-NEXT:    [[TMP10:%.*]] = extractelement <2 x i1> [[TMP6]], i32 0
401; SSE-NEXT:    [[OP_RDX:%.*]] = select i1 [[TMP9]], i1 [[TMP10]], i1 false
402; SSE-NEXT:    [[TMP11:%.*]] = extractelement <2 x i1> [[TMP6]], i32 1
403; SSE-NEXT:    [[OP_RDX1:%.*]] = select i1 [[OP_RDX]], i1 [[TMP11]], i1 false
404; SSE-NEXT:    [[OP_RDX2:%.*]] = select i1 [[OP_RDX1]], i1 [[C2]], i1 false
405; SSE-NEXT:    ret i1 [[OP_RDX2]]
406;
407; AVX-LABEL: @logical_and_icmp_clamp_partial(
408; AVX-NEXT:    [[TMP1:%.*]] = extractelement <4 x i32> [[X:%.*]], i32 2
409; AVX-NEXT:    [[TMP2:%.*]] = extractelement <4 x i32> [[X]], i32 1
410; AVX-NEXT:    [[TMP3:%.*]] = extractelement <4 x i32> [[X]], i32 0
411; AVX-NEXT:    [[C0:%.*]] = icmp slt i32 [[TMP3]], 42
412; AVX-NEXT:    [[C1:%.*]] = icmp slt i32 [[TMP2]], 42
413; AVX-NEXT:    [[C2:%.*]] = icmp slt i32 [[TMP1]], 42
414; AVX-NEXT:    [[TMP4:%.*]] = icmp sgt <4 x i32> [[X]], <i32 17, i32 17, i32 17, i32 17>
415; AVX-NEXT:    [[TMP5:%.*]] = freeze <4 x i1> [[TMP4]]
416; AVX-NEXT:    [[TMP6:%.*]] = call i1 @llvm.vector.reduce.and.v4i1(<4 x i1> [[TMP5]])
417; AVX-NEXT:    [[OP_RDX:%.*]] = select i1 [[TMP6]], i1 [[C1]], i1 false
418; AVX-NEXT:    [[OP_RDX1:%.*]] = select i1 [[OP_RDX]], i1 [[C0]], i1 false
419; AVX-NEXT:    [[OP_RDX2:%.*]] = select i1 [[OP_RDX1]], i1 [[C2]], i1 false
420; AVX-NEXT:    ret i1 [[OP_RDX2]]
421;
422  %x0 = extractelement <4 x i32> %x, i32 0
423  %x1 = extractelement <4 x i32> %x, i32 1
424  %x2 = extractelement <4 x i32> %x, i32 2
425  %x3 = extractelement <4 x i32> %x, i32 3
426  %c0 = icmp slt i32 %x0, 42
427  %c1 = icmp slt i32 %x1, 42
428  %c2 = icmp slt i32 %x2, 42
429  ; remove an element from the previous test
430  %d0 = icmp sgt i32 %x0, 17
431  %d1 = icmp sgt i32 %x1, 17
432  %d2 = icmp sgt i32 %x2, 17
433  %d3 = icmp sgt i32 %x3, 17
434  %s1 = select i1 %c0, i1 %c1, i1 false
435  %s2 = select i1 %s1, i1 %c2, i1 false
436  ; remove an element from the previous test
437  %s4 = select i1 %s2, i1 %d0, i1 false
438  %s5 = select i1 %s4, i1 %d1, i1 false
439  %s6 = select i1 %s5, i1 %d2, i1 false
440  %s7 = select i1 %s6, i1 %d3, i1 false
441  ret i1 %s7
442}
443
444define i1 @logical_and_icmp_clamp_pred_diff(<4 x i32> %x) {
445; CHECK-LABEL: @logical_and_icmp_clamp_pred_diff(
446; CHECK-NEXT:    [[TMP1:%.*]] = icmp slt <4 x i32> [[X:%.*]], <i32 42, i32 42, i32 42, i32 42>
447; CHECK-NEXT:    [[TMP2:%.*]] = icmp ult <4 x i32> [[X]], <i32 42, i32 42, i32 42, i32 42>
448; CHECK-NEXT:    [[TMP3:%.*]] = shufflevector <4 x i1> [[TMP1]], <4 x i1> [[TMP2]], <4 x i32> <i32 0, i32 1, i32 2, i32 7>
449; CHECK-NEXT:    [[TMP4:%.*]] = icmp sgt <4 x i32> [[X]], <i32 17, i32 17, i32 17, i32 17>
450; CHECK-NEXT:    [[TMP5:%.*]] = freeze <4 x i1> [[TMP4]]
451; CHECK-NEXT:    [[TMP6:%.*]] = call i1 @llvm.vector.reduce.and.v4i1(<4 x i1> [[TMP5]])
452; CHECK-NEXT:    [[TMP7:%.*]] = freeze <4 x i1> [[TMP3]]
453; CHECK-NEXT:    [[TMP8:%.*]] = call i1 @llvm.vector.reduce.and.v4i1(<4 x i1> [[TMP7]])
454; CHECK-NEXT:    [[OP_RDX:%.*]] = select i1 [[TMP6]], i1 [[TMP8]], i1 false
455; CHECK-NEXT:    ret i1 [[OP_RDX]]
456;
457  %x0 = extractelement <4 x i32> %x, i32 0
458  %x1 = extractelement <4 x i32> %x, i32 1
459  %x2 = extractelement <4 x i32> %x, i32 2
460  %x3 = extractelement <4 x i32> %x, i32 3
461  %c0 = icmp slt i32 %x0, 42
462  %c1 = icmp slt i32 %x1, 42
463  %c2 = icmp slt i32 %x2, 42
464  %c3 = icmp ult i32 %x3, 42 ; predicate changed
465  %d0 = icmp sgt i32 %x0, 17
466  %d1 = icmp sgt i32 %x1, 17
467  %d2 = icmp sgt i32 %x2, 17
468  %d3 = icmp sgt i32 %x3, 17
469  %s1 = select i1 %c0, i1 %c1, i1 false
470  %s2 = select i1 %s1, i1 %c2, i1 false
471  %s3 = select i1 %s2, i1 %c3, i1 false
472  %s4 = select i1 %s3, i1 %d0, i1 false
473  %s5 = select i1 %s4, i1 %d1, i1 false
474  %s6 = select i1 %s5, i1 %d2, i1 false
475  %s7 = select i1 %s6, i1 %d3, i1 false
476  ret i1 %s7
477}
478
479define i1 @logical_and_icmp_extra_op(<4 x i32> %x, <4 x i32> %y, i1 %c) {
480; CHECK-LABEL: @logical_and_icmp_extra_op(
481; CHECK-NEXT:    [[TMP1:%.*]] = icmp slt <4 x i32> [[X:%.*]], [[Y:%.*]]
482; CHECK-NEXT:    [[S3:%.*]] = select i1 [[C:%.*]], i1 [[C]], i1 false
483; CHECK-NEXT:    [[TMP2:%.*]] = freeze <4 x i1> [[TMP1]]
484; CHECK-NEXT:    [[TMP3:%.*]] = call i1 @llvm.vector.reduce.and.v4i1(<4 x i1> [[TMP2]])
485; CHECK-NEXT:    [[OP_RDX:%.*]] = select i1 [[TMP3]], i1 [[S3]], i1 false
486; CHECK-NEXT:    ret i1 [[OP_RDX]]
487;
488  %x0 = extractelement <4 x i32> %x, i32 0
489  %x1 = extractelement <4 x i32> %x, i32 1
490  %x2 = extractelement <4 x i32> %x, i32 2
491  %x3 = extractelement <4 x i32> %x, i32 3
492  %y0 = extractelement <4 x i32> %y, i32 0
493  %y1 = extractelement <4 x i32> %y, i32 1
494  %y2 = extractelement <4 x i32> %y, i32 2
495  %y3 = extractelement <4 x i32> %y, i32 3
496  %d0 = icmp slt i32 %x0, %y0
497  %d1 = icmp slt i32 %x1, %y1
498  %d2 = icmp slt i32 %x2, %y2
499  %d3 = icmp slt i32 %x3, %y3
500  %s3 = select i1 %c, i1 %c, i1 false
501  %s4 = select i1 %s3, i1 %d0, i1 false
502  %s5 = select i1 %s4, i1 %d1, i1 false
503  %s6 = select i1 %s5, i1 %d2, i1 false
504  %s7 = select i1 %s6, i1 %d3, i1 false
505  ret i1 %s7
506}
507
508define i1 @logical_or_icmp_extra_op(<4 x i32> %x, <4 x i32> %y, i1 %c) {
509; CHECK-LABEL: @logical_or_icmp_extra_op(
510; CHECK-NEXT:    [[TMP1:%.*]] = icmp slt <4 x i32> [[X:%.*]], [[Y:%.*]]
511; CHECK-NEXT:    [[S3:%.*]] = select i1 [[C:%.*]], i1 true, i1 [[C]]
512; CHECK-NEXT:    [[TMP2:%.*]] = freeze <4 x i1> [[TMP1]]
513; CHECK-NEXT:    [[TMP3:%.*]] = call i1 @llvm.vector.reduce.or.v4i1(<4 x i1> [[TMP2]])
514; CHECK-NEXT:    [[OP_RDX:%.*]] = select i1 [[TMP3]], i1 true, i1 [[S3]]
515; CHECK-NEXT:    ret i1 [[OP_RDX]]
516;
517  %x0 = extractelement <4 x i32> %x, i32 0
518  %x1 = extractelement <4 x i32> %x, i32 1
519  %x2 = extractelement <4 x i32> %x, i32 2
520  %x3 = extractelement <4 x i32> %x, i32 3
521  %y0 = extractelement <4 x i32> %y, i32 0
522  %y1 = extractelement <4 x i32> %y, i32 1
523  %y2 = extractelement <4 x i32> %y, i32 2
524  %y3 = extractelement <4 x i32> %y, i32 3
525  %d0 = icmp slt i32 %x0, %y0
526  %d1 = icmp slt i32 %x1, %y1
527  %d2 = icmp slt i32 %x2, %y2
528  %d3 = icmp slt i32 %x3, %y3
529  %s3 = select i1 %c, i1 true, i1 %c
530  %s4 = select i1 %s3, i1 true, i1 %d0
531  %s5 = select i1 %s4, i1 true, i1 %d1
532  %s6 = select i1 %s5, i1 true, i1 %d2
533  %s7 = select i1 %s6, i1 true, i1 %d3
534  ret i1 %s7
535}
536