xref: /llvm-project/llvm/test/Transforms/InstCombine/icmp-vec.ll (revision 56c091ea7106507b36015297ee9005c9d5fab0bf)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -passes=instcombine -S | FileCheck %s
3
4; Canonicalize vector ge/le comparisons with constants to gt/lt.
5
6; Normal types are ConstantDataVectors. Test the constant values adjacent to the
7; min/max values that we're not allowed to transform.
8
9target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
10
11define <2 x i1> @sge(<2 x i8> %x) {
12; CHECK-LABEL: @sge(
13; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt <2 x i8> [[X:%.*]], <i8 -128, i8 126>
14; CHECK-NEXT:    ret <2 x i1> [[CMP]]
15;
16  %cmp = icmp sge <2 x i8> %x, <i8 -127, i8 -129>
17  ret <2 x i1> %cmp
18}
19
20define <2 x i1> @uge(<2 x i8> %x) {
21; CHECK-LABEL: @uge(
22; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt <2 x i8> [[X:%.*]], <i8 -2, i8 0>
23; CHECK-NEXT:    ret <2 x i1> [[CMP]]
24;
25  %cmp = icmp uge <2 x i8> %x, <i8 -1, i8 1>
26  ret <2 x i1> %cmp
27}
28
29define <2 x i1> @sle(<2 x i8> %x) {
30; CHECK-LABEL: @sle(
31; CHECK-NEXT:    [[CMP:%.*]] = icmp slt <2 x i8> [[X:%.*]], <i8 127, i8 -127>
32; CHECK-NEXT:    ret <2 x i1> [[CMP]]
33;
34  %cmp = icmp sle <2 x i8> %x, <i8 126, i8 128>
35  ret <2 x i1> %cmp
36}
37
38define <2 x i1> @ule(<2 x i8> %x) {
39; CHECK-LABEL: @ule(
40; CHECK-NEXT:    [[CMP:%.*]] = icmp ult <2 x i8> [[X:%.*]], <i8 -1, i8 1>
41; CHECK-NEXT:    ret <2 x i1> [[CMP]]
42;
43  %cmp = icmp ule <2 x i8> %x, <i8 254, i8 0>
44  ret <2 x i1> %cmp
45}
46
47define <2 x i1> @ult_min_signed_value(<2 x i8> %x) {
48; CHECK-LABEL: @ult_min_signed_value(
49; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt <2 x i8> [[X:%.*]], splat (i8 -1)
50; CHECK-NEXT:    ret <2 x i1> [[CMP]]
51;
52  %cmp = icmp ult <2 x i8> %x, <i8 128, i8 128>
53  ret <2 x i1> %cmp
54}
55
56; Zeros are special: they're ConstantAggregateZero.
57
58define <2 x i1> @sge_zero(<2 x i8> %x) {
59; CHECK-LABEL: @sge_zero(
60; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt <2 x i8> [[X:%.*]], splat (i8 -1)
61; CHECK-NEXT:    ret <2 x i1> [[CMP]]
62;
63  %cmp = icmp sge <2 x i8> %x, <i8 0, i8 0>
64  ret <2 x i1> %cmp
65}
66
67define <2 x i1> @uge_zero(<2 x i8> %x) {
68; CHECK-LABEL: @uge_zero(
69; CHECK-NEXT:    ret <2 x i1> splat (i1 true)
70;
71  %cmp = icmp uge <2 x i8> %x, <i8 0, i8 0>
72  ret <2 x i1> %cmp
73}
74
75define <2 x i1> @sle_zero(<2 x i8> %x) {
76; CHECK-LABEL: @sle_zero(
77; CHECK-NEXT:    [[CMP:%.*]] = icmp slt <2 x i8> [[X:%.*]], splat (i8 1)
78; CHECK-NEXT:    ret <2 x i1> [[CMP]]
79;
80  %cmp = icmp sle <2 x i8> %x, <i8 0, i8 0>
81  ret <2 x i1> %cmp
82}
83
84define <2 x i1> @ule_zero(<2 x i8> %x) {
85; CHECK-LABEL: @ule_zero(
86; CHECK-NEXT:    [[CMP:%.*]] = icmp eq <2 x i8> [[X:%.*]], zeroinitializer
87; CHECK-NEXT:    ret <2 x i1> [[CMP]]
88;
89  %cmp = icmp ule <2 x i8> %x, <i8 0, i8 0>
90  ret <2 x i1> %cmp
91}
92
93; Weird types are ConstantVectors, not ConstantDataVectors. For an i3 type:
94; Signed min = -4
95; Unsigned min = 0
96; Signed max = 3
97; Unsigned max = 7
98
99define <3 x i1> @sge_weird(<3 x i3> %x) {
100; CHECK-LABEL: @sge_weird(
101; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt <3 x i3> [[X:%.*]], <i3 -4, i3 2, i3 -1>
102; CHECK-NEXT:    ret <3 x i1> [[CMP]]
103;
104  %cmp = icmp sge <3 x i3> %x, <i3 -3, i3 -5, i3 0>
105  ret <3 x i1> %cmp
106}
107
108define <3 x i1> @uge_weird(<3 x i3> %x) {
109; CHECK-LABEL: @uge_weird(
110; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt <3 x i3> [[X:%.*]], <i3 -2, i3 0, i3 1>
111; CHECK-NEXT:    ret <3 x i1> [[CMP]]
112;
113  %cmp = icmp uge <3 x i3> %x, <i3 -1, i3 1, i3 2>
114  ret <3 x i1> %cmp
115}
116
117define <3 x i1> @sle_weird(<3 x i3> %x) {
118; CHECK-LABEL: @sle_weird(
119; CHECK-NEXT:    [[CMP:%.*]] = icmp slt <3 x i3> [[X:%.*]], <i3 3, i3 -3, i3 1>
120; CHECK-NEXT:    ret <3 x i1> [[CMP]]
121;
122  %cmp = icmp sle <3 x i3> %x, <i3 2, i3 4, i3 0>
123  ret <3 x i1> %cmp
124}
125
126define <3 x i1> @ule_weird(<3 x i3> %x) {
127; CHECK-LABEL: @ule_weird(
128; CHECK-NEXT:    [[CMP:%.*]] = icmp ult <3 x i3> [[X:%.*]], <i3 -1, i3 1, i3 2>
129; CHECK-NEXT:    ret <3 x i1> [[CMP]]
130;
131  %cmp = icmp ule <3 x i3> %x, <i3 6, i3 0, i3 1>
132  ret <3 x i1> %cmp
133}
134
135; We can't do the transform if any constants are already at the limits.
136
137define <2 x i1> @sge_min(<2 x i3> %x) {
138; CHECK-LABEL: @sge_min(
139; CHECK-NEXT:    [[CMP:%.*]] = icmp sge <2 x i3> [[X:%.*]], <i3 -4, i3 1>
140; CHECK-NEXT:    ret <2 x i1> [[CMP]]
141;
142  %cmp = icmp sge <2 x i3> %x, <i3 -4, i3 1>
143  ret <2 x i1> %cmp
144}
145
146define <2 x i1> @uge_min(<2 x i3> %x) {
147; CHECK-LABEL: @uge_min(
148; CHECK-NEXT:    [[CMP:%.*]] = icmp uge <2 x i3> [[X:%.*]], <i3 1, i3 0>
149; CHECK-NEXT:    ret <2 x i1> [[CMP]]
150;
151  %cmp = icmp uge <2 x i3> %x, <i3 1, i3 0>
152  ret <2 x i1> %cmp
153}
154
155define <2 x i1> @sle_max(<2 x i3> %x) {
156; CHECK-LABEL: @sle_max(
157; CHECK-NEXT:    [[CMP:%.*]] = icmp sle <2 x i3> [[X:%.*]], <i3 1, i3 3>
158; CHECK-NEXT:    ret <2 x i1> [[CMP]]
159;
160  %cmp = icmp sle <2 x i3> %x, <i3 1, i3 3>
161  ret <2 x i1> %cmp
162}
163
164define <2 x i1> @ule_max(<2 x i3> %x) {
165; CHECK-LABEL: @ule_max(
166; CHECK-NEXT:    [[CMP:%.*]] = icmp ule <2 x i3> [[X:%.*]], <i3 -1, i3 1>
167; CHECK-NEXT:    ret <2 x i1> [[CMP]]
168;
169  %cmp = icmp ule <2 x i3> %x, <i3 7, i3 1>
170  ret <2 x i1> %cmp
171}
172
173define <2 x i1> @PR27756_1(<2 x i8> %a) {
174; CHECK-LABEL: @PR27756_1(
175; CHECK-NEXT:    [[CMP:%.*]] = icmp slt <2 x i8> [[A:%.*]], <i8 34, i8 1>
176; CHECK-NEXT:    ret <2 x i1> [[CMP]]
177;
178  %cmp = icmp sle <2 x i8> %a, <i8 bitcast (<2 x i4> <i4 1, i4 2> to i8), i8 0>
179  ret <2 x i1> %cmp
180}
181
182; Undef elements don't prevent the transform of the comparison.
183
184define <3 x i1> @PR27756_2(<3 x i8> %a) {
185; CHECK-LABEL: @PR27756_2(
186; CHECK-NEXT:    [[CMP:%.*]] = icmp slt <3 x i8> [[A:%.*]], <i8 43, i8 43, i8 1>
187; CHECK-NEXT:    ret <3 x i1> [[CMP]]
188;
189  %cmp = icmp sle <3 x i8> %a, <i8 42, i8 poison, i8 0>
190  ret <3 x i1> %cmp
191}
192
193define <3 x i1> @PR27756_3(<3 x i8> %a) {
194; CHECK-LABEL: @PR27756_3(
195; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt <3 x i8> [[A:%.*]], <i8 0, i8 0, i8 41>
196; CHECK-NEXT:    ret <3 x i1> [[CMP]]
197;
198  %cmp = icmp sge <3 x i8> %a, <i8 poison, i8 1, i8 42>
199  ret <3 x i1> %cmp
200}
201
202@someglobal = global i32 0
203
204define <2 x i1> @PR27786(<2 x i8> %a) {
205; CHECK-LABEL: @PR27786(
206; CHECK-NEXT:    [[CMP:%.*]] = icmp sle <2 x i8> [[A:%.*]], bitcast (i16 ptrtoint (ptr @someglobal to i16) to <2 x i8>)
207; CHECK-NEXT:    ret <2 x i1> [[CMP]]
208;
209  %cmp = icmp sle <2 x i8> %a, bitcast (i16 ptrtoint (ptr @someglobal to i16) to <2 x i8>)
210  ret <2 x i1> %cmp
211}
212
213; This is similar to a transform for shuffled binops: compare first, shuffle after.
214
215define <4 x i1> @same_shuffle_inputs_icmp(<4 x i8> %x, <4 x i8> %y) {
216; CHECK-LABEL: @same_shuffle_inputs_icmp(
217; CHECK-NEXT:    [[TMP1:%.*]] = icmp sgt <4 x i8> [[X:%.*]], [[Y:%.*]]
218; CHECK-NEXT:    [[CMP:%.*]] = shufflevector <4 x i1> [[TMP1]], <4 x i1> poison, <4 x i32> <i32 3, i32 3, i32 2, i32 0>
219; CHECK-NEXT:    ret <4 x i1> [[CMP]]
220;
221  %shufx = shufflevector <4 x i8> %x, <4 x i8> poison, <4 x i32> < i32 3, i32 3, i32 2, i32 0 >
222  %shufy = shufflevector <4 x i8> %y, <4 x i8> poison, <4 x i32> < i32 3, i32 3, i32 2, i32 0 >
223  %cmp = icmp sgt <4 x i8> %shufx, %shufy
224  ret <4 x i1> %cmp
225}
226
227; fcmp and size-changing shuffles are ok too.
228
229define <5 x i1> @same_shuffle_inputs_fcmp(<4 x float> %x, <4 x float> %y) {
230; CHECK-LABEL: @same_shuffle_inputs_fcmp(
231; CHECK-NEXT:    [[TMP1:%.*]] = fcmp oeq <4 x float> [[X:%.*]], [[Y:%.*]]
232; CHECK-NEXT:    [[CMP:%.*]] = shufflevector <4 x i1> [[TMP1]], <4 x i1> poison, <5 x i32> <i32 0, i32 1, i32 3, i32 2, i32 0>
233; CHECK-NEXT:    ret <5 x i1> [[CMP]]
234;
235  %shufx = shufflevector <4 x float> %x, <4 x float> poison, <5 x i32> < i32 0, i32 1, i32 3, i32 2, i32 0 >
236  %shufy = shufflevector <4 x float> %y, <4 x float> poison, <5 x i32> < i32 0, i32 1, i32 3, i32 2, i32 0 >
237  %cmp = fcmp oeq <5 x float> %shufx, %shufy
238  ret <5 x i1> %cmp
239}
240
241declare void @use_v4i8(<4 x i8>)
242
243define <4 x i1> @same_shuffle_inputs_icmp_extra_use1(<4 x i8> %x, <4 x i8> %y) {
244; CHECK-LABEL: @same_shuffle_inputs_icmp_extra_use1(
245; CHECK-NEXT:    [[SHUFX:%.*]] = shufflevector <4 x i8> [[X:%.*]], <4 x i8> poison, <4 x i32> <i32 3, i32 3, i32 3, i32 3>
246; CHECK-NEXT:    [[TMP1:%.*]] = icmp ugt <4 x i8> [[X]], [[Y:%.*]]
247; CHECK-NEXT:    [[CMP:%.*]] = shufflevector <4 x i1> [[TMP1]], <4 x i1> poison, <4 x i32> <i32 3, i32 3, i32 3, i32 3>
248; CHECK-NEXT:    call void @use_v4i8(<4 x i8> [[SHUFX]])
249; CHECK-NEXT:    ret <4 x i1> [[CMP]]
250;
251  %shufx = shufflevector <4 x i8> %x, <4 x i8> poison, <4 x i32> < i32 3, i32 3, i32 3, i32 3 >
252  %shufy = shufflevector <4 x i8> %y, <4 x i8> poison, <4 x i32> < i32 3, i32 3, i32 3, i32 3 >
253  %cmp = icmp ugt <4 x i8> %shufx, %shufy
254  call void @use_v4i8(<4 x i8> %shufx)
255  ret <4 x i1> %cmp
256}
257
258declare void @use_v2i8(<2 x i8>)
259
260define <2 x i1> @same_shuffle_inputs_icmp_extra_use2(<4 x i8> %x, <4 x i8> %y) {
261; CHECK-LABEL: @same_shuffle_inputs_icmp_extra_use2(
262; CHECK-NEXT:    [[SHUFY:%.*]] = shufflevector <4 x i8> [[Y:%.*]], <4 x i8> poison, <2 x i32> <i32 3, i32 2>
263; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq <4 x i8> [[X:%.*]], [[Y]]
264; CHECK-NEXT:    [[CMP:%.*]] = shufflevector <4 x i1> [[TMP1]], <4 x i1> poison, <2 x i32> <i32 3, i32 2>
265; CHECK-NEXT:    call void @use_v2i8(<2 x i8> [[SHUFY]])
266; CHECK-NEXT:    ret <2 x i1> [[CMP]]
267;
268  %shufx = shufflevector <4 x i8> %x, <4 x i8> poison, <2 x i32> < i32 3, i32 2 >
269  %shufy = shufflevector <4 x i8> %y, <4 x i8> poison, <2 x i32> < i32 3, i32 2 >
270  %cmp = icmp eq <2 x i8> %shufx, %shufy
271  call void @use_v2i8(<2 x i8> %shufy)
272  ret <2 x i1> %cmp
273}
274
275; Negative test: if both shuffles have extra uses, don't transform because that would increase instruction count.
276
277define <2 x i1> @same_shuffle_inputs_icmp_extra_use3(<4 x i8> %x, <4 x i8> %y) {
278; CHECK-LABEL: @same_shuffle_inputs_icmp_extra_use3(
279; CHECK-NEXT:    [[SHUFX:%.*]] = shufflevector <4 x i8> [[X:%.*]], <4 x i8> poison, <2 x i32> zeroinitializer
280; CHECK-NEXT:    [[SHUFY:%.*]] = shufflevector <4 x i8> [[Y:%.*]], <4 x i8> poison, <2 x i32> zeroinitializer
281; CHECK-NEXT:    [[CMP:%.*]] = icmp eq <2 x i8> [[SHUFX]], [[SHUFY]]
282; CHECK-NEXT:    call void @use_v2i8(<2 x i8> [[SHUFX]])
283; CHECK-NEXT:    call void @use_v2i8(<2 x i8> [[SHUFY]])
284; CHECK-NEXT:    ret <2 x i1> [[CMP]]
285;
286  %shufx = shufflevector <4 x i8> %x, <4 x i8> poison, <2 x i32> < i32 0, i32 0 >
287  %shufy = shufflevector <4 x i8> %y, <4 x i8> poison, <2 x i32> < i32 0, i32 0 >
288  %cmp = icmp eq <2 x i8> %shufx, %shufy
289  call void @use_v2i8(<2 x i8> %shufx)
290  call void @use_v2i8(<2 x i8> %shufy)
291  ret <2 x i1> %cmp
292}
293
294define <4 x i1> @splat_icmp(<4 x i8> %x) {
295; CHECK-LABEL: @splat_icmp(
296; CHECK-NEXT:    [[TMP1:%.*]] = icmp sgt <4 x i8> [[X:%.*]], splat (i8 42)
297; CHECK-NEXT:    [[CMP:%.*]] = shufflevector <4 x i1> [[TMP1]], <4 x i1> poison, <4 x i32> <i32 3, i32 3, i32 3, i32 3>
298; CHECK-NEXT:    ret <4 x i1> [[CMP]]
299;
300  %splatx = shufflevector <4 x i8> %x, <4 x i8> poison, <4 x i32> <i32 3, i32 3, i32 3, i32 3>
301  %cmp = icmp sgt <4 x i8> %splatx, <i8 42, i8 42, i8 42, i8 42>
302  ret <4 x i1> %cmp
303}
304
305define <4 x i1> @splat_icmp_poison(<4 x i8> %x) {
306; CHECK-LABEL: @splat_icmp_poison(
307; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult <4 x i8> [[X:%.*]], splat (i8 42)
308; CHECK-NEXT:    [[CMP:%.*]] = shufflevector <4 x i1> [[TMP1]], <4 x i1> poison, <4 x i32> <i32 2, i32 2, i32 2, i32 2>
309; CHECK-NEXT:    ret <4 x i1> [[CMP]]
310;
311  %splatx = shufflevector <4 x i8> %x, <4 x i8> poison, <4 x i32> <i32 2, i32 poison, i32 poison, i32 2>
312  %cmp = icmp ult <4 x i8> %splatx, <i8 poison, i8 42, i8 poison, i8 42>
313  ret <4 x i1> %cmp
314}
315
316define <4 x i1> @splat_icmp_larger_size(<2 x i8> %x) {
317; CHECK-LABEL: @splat_icmp_larger_size(
318; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq <2 x i8> [[X:%.*]], splat (i8 42)
319; CHECK-NEXT:    [[CMP:%.*]] = shufflevector <2 x i1> [[TMP1]], <2 x i1> poison, <4 x i32> <i32 1, i32 1, i32 1, i32 1>
320; CHECK-NEXT:    ret <4 x i1> [[CMP]]
321;
322  %splatx = shufflevector <2 x i8> %x, <2 x i8> poison, <4 x i32> <i32 1, i32 poison, i32 1, i32 poison>
323  %cmp = icmp eq <4 x i8> %splatx, <i8 42, i8 42, i8 poison, i8 42>
324  ret <4 x i1> %cmp
325}
326
327define <4 x i1> @splat_fcmp_smaller_size(<5 x float> %x) {
328; CHECK-LABEL: @splat_fcmp_smaller_size(
329; CHECK-NEXT:    [[TMP1:%.*]] = fcmp oeq <5 x float> [[X:%.*]], splat (float 4.200000e+01)
330; CHECK-NEXT:    [[CMP:%.*]] = shufflevector <5 x i1> [[TMP1]], <5 x i1> poison, <4 x i32> <i32 1, i32 1, i32 1, i32 1>
331; CHECK-NEXT:    ret <4 x i1> [[CMP]]
332;
333  %splatx = shufflevector <5 x float> %x, <5 x float> poison, <4 x i32> <i32 1, i32 poison, i32 1, i32 poison>
334  %cmp = fcmp oeq <4 x float> %splatx, <float 42.0, float 42.0, float poison, float 42.0>
335  ret <4 x i1> %cmp
336}
337
338; Negative test
339
340define <4 x i1> @splat_icmp_extra_use(<4 x i8> %x) {
341; CHECK-LABEL: @splat_icmp_extra_use(
342; CHECK-NEXT:    [[SPLATX:%.*]] = shufflevector <4 x i8> [[X:%.*]], <4 x i8> poison, <4 x i32> <i32 3, i32 3, i32 3, i32 3>
343; CHECK-NEXT:    call void @use_v4i8(<4 x i8> [[SPLATX]])
344; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt <4 x i8> [[SPLATX]], splat (i8 42)
345; CHECK-NEXT:    ret <4 x i1> [[CMP]]
346;
347  %splatx = shufflevector <4 x i8> %x, <4 x i8> poison, <4 x i32> <i32 3, i32 3, i32 3, i32 3>
348  call void @use_v4i8(<4 x i8> %splatx)
349  %cmp = icmp sgt <4 x i8> %splatx, <i8 42, i8 42, i8 42, i8 42>
350  ret <4 x i1> %cmp
351}
352
353; Negative test
354
355define <4 x i1> @not_splat_icmp(<4 x i8> %x) {
356; CHECK-LABEL: @not_splat_icmp(
357; CHECK-NEXT:    [[SPLATX:%.*]] = shufflevector <4 x i8> [[X:%.*]], <4 x i8> poison, <4 x i32> <i32 3, i32 2, i32 3, i32 3>
358; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt <4 x i8> [[SPLATX]], splat (i8 42)
359; CHECK-NEXT:    ret <4 x i1> [[CMP]]
360;
361  %splatx = shufflevector <4 x i8> %x, <4 x i8> poison, <4 x i32> <i32 3, i32 2, i32 3, i32 3>
362  %cmp = icmp sgt <4 x i8> %splatx, <i8 42, i8 42, i8 42, i8 42>
363  ret <4 x i1> %cmp
364}
365
366; Negative test
367
368define <4 x i1> @not_splat_icmp2(<4 x i8> %x) {
369; CHECK-LABEL: @not_splat_icmp2(
370; CHECK-NEXT:    [[SPLATX:%.*]] = shufflevector <4 x i8> [[X:%.*]], <4 x i8> poison, <4 x i32> <i32 2, i32 2, i32 2, i32 2>
371; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt <4 x i8> [[SPLATX]], <i8 43, i8 42, i8 42, i8 42>
372; CHECK-NEXT:    ret <4 x i1> [[CMP]]
373;
374  %splatx = shufflevector <4 x i8> %x, <4 x i8> poison, <4 x i32> <i32 2, i32 2, i32 2, i32 2>
375  %cmp = icmp sgt <4 x i8> %splatx, <i8 43, i8 42, i8 42, i8 42>
376  ret <4 x i1> %cmp
377}
378
379; Check that we don't absorb the compare into the select, which is in the
380; canonical form of logical or.
381define <2 x i1> @icmp_logical_or_vec(<2 x i64> %x, <2 x i64> %y, <2 x i1> %falseval) {
382; CHECK-LABEL: @icmp_logical_or_vec(
383; CHECK-NEXT:    [[CMP_NE:%.*]] = icmp ne <2 x i64> [[X:%.*]], zeroinitializer
384; CHECK-NEXT:    [[SEL:%.*]] = select <2 x i1> [[CMP_NE]], <2 x i1> splat (i1 true), <2 x i1> [[FALSEVAL:%.*]]
385; CHECK-NEXT:    ret <2 x i1> [[SEL]]
386;
387  %cmp.ne = icmp ne <2 x i64> %x, zeroinitializer
388  %sel = select <2 x i1> %cmp.ne, <2 x i1> shufflevector (<2 x i1> insertelement (<2 x i1> poison, i1 true, i32 0), <2 x i1> poison, <2 x i32> zeroinitializer), <2 x i1> %falseval
389  ret <2 x i1> %sel
390}
391
392; The above, but for scalable vectors. Absorbing the compare into the select
393; and breaking the canonical form led to an infinite loop.
394define <vscale x 2 x i1> @icmp_logical_or_scalablevec(<vscale x 2 x i64> %x, <vscale x 2 x i64> %y, <vscale x 2 x i1> %falseval) {
395; CHECK-LABEL: @icmp_logical_or_scalablevec(
396; CHECK-NEXT:    [[CMP_NE:%.*]] = icmp ne <vscale x 2 x i64> [[X:%.*]], zeroinitializer
397; CHECK-NEXT:    [[SEL:%.*]] = select <vscale x 2 x i1> [[CMP_NE]], <vscale x 2 x i1> splat (i1 true), <vscale x 2 x i1> [[FALSEVAL:%.*]]
398; CHECK-NEXT:    ret <vscale x 2 x i1> [[SEL]]
399;
400  %cmp.ne = icmp ne <vscale x 2 x i64> %x, zeroinitializer
401  %sel = select <vscale x 2 x i1> %cmp.ne, <vscale x 2 x i1> splat (i1 true), <vscale x 2 x i1> %falseval
402  ret <vscale x 2 x i1> %sel
403}
404
405define i1 @eq_cast_eq-1(<2 x i4> %x, <2 x i4> %y) {
406; CHECK-LABEL: @eq_cast_eq-1(
407; CHECK-NEXT:    [[X_SCALAR:%.*]] = bitcast <2 x i4> [[X:%.*]] to i8
408; CHECK-NEXT:    [[Y_SCALAR:%.*]] = bitcast <2 x i4> [[Y:%.*]] to i8
409; CHECK-NEXT:    [[R:%.*]] = icmp eq i8 [[X_SCALAR]], [[Y_SCALAR]]
410; CHECK-NEXT:    ret i1 [[R]]
411;
412  %ic = icmp eq <2 x i4> %x, %y
413  %b = bitcast <2 x i1> %ic to i2
414  %r = icmp eq i2 %b, -1
415  ret i1 %r
416}
417
418define i1 @ne_cast_eq-1(<3 x i7> %x, <3 x i7> %y) {
419; CHECK-LABEL: @ne_cast_eq-1(
420; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq <3 x i7> [[X:%.*]], [[Y:%.*]]
421; CHECK-NEXT:    [[TMP2:%.*]] = bitcast <3 x i1> [[TMP1]] to i3
422; CHECK-NEXT:    [[R:%.*]] = icmp eq i3 [[TMP2]], 0
423; CHECK-NEXT:    ret i1 [[R]]
424;
425  %ic = icmp ne <3 x i7> %x, %y
426  %b = bitcast <3 x i1> %ic to i3
427  %r = icmp eq i3 %b, -1
428  ret i1 %r
429}
430
431define i1 @eq_cast_ne-1(<2 x i7> %x, <2 x i7> %y) {
432; CHECK-LABEL: @eq_cast_ne-1(
433; CHECK-NEXT:    [[TMP1:%.*]] = icmp ne <2 x i7> [[X:%.*]], [[Y:%.*]]
434; CHECK-NEXT:    [[TMP2:%.*]] = bitcast <2 x i1> [[TMP1]] to i2
435; CHECK-NEXT:    [[R:%.*]] = icmp ne i2 [[TMP2]], 0
436; CHECK-NEXT:    ret i1 [[R]]
437;
438  %ic = icmp eq <2 x i7> %x, %y
439  %b = bitcast <2 x i1> %ic to i2
440  %r = icmp ne i2 %b, -1
441  ret i1 %r
442}
443
444define i1 @eq_cast_ne-1-legal-scalar(<2 x i8> %x, <2 x i8> %y) {
445; CHECK-LABEL: @eq_cast_ne-1-legal-scalar(
446; CHECK-NEXT:    [[X_SCALAR:%.*]] = bitcast <2 x i8> [[X:%.*]] to i16
447; CHECK-NEXT:    [[Y_SCALAR:%.*]] = bitcast <2 x i8> [[Y:%.*]] to i16
448; CHECK-NEXT:    [[R:%.*]] = icmp ne i16 [[X_SCALAR]], [[Y_SCALAR]]
449; CHECK-NEXT:    ret i1 [[R]]
450;
451  %ic = icmp eq <2 x i8> %x, %y
452  %b = bitcast <2 x i1> %ic to i2
453  %r = icmp ne i2 %b, -1
454  ret i1 %r
455}
456
457define i1 @ne_cast_ne-1(<3 x i5> %x, <3 x i5> %y) {
458; CHECK-LABEL: @ne_cast_ne-1(
459; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq <3 x i5> [[X:%.*]], [[Y:%.*]]
460; CHECK-NEXT:    [[TMP2:%.*]] = bitcast <3 x i1> [[TMP1]] to i3
461; CHECK-NEXT:    [[R:%.*]] = icmp ne i3 [[TMP2]], 0
462; CHECK-NEXT:    ret i1 [[R]]
463;
464  %ic = icmp ne <3 x i5> %x, %y
465  %b = bitcast <3 x i1> %ic to i3
466  %r = icmp ne i3 %b, -1
467  ret i1 %r
468}
469
470define i1 @ugt_cast_eq-1(<2 x i4> %x, <2 x i4> %y) {
471; CHECK-LABEL: @ugt_cast_eq-1(
472; CHECK-NEXT:    [[TMP1:%.*]] = icmp ule <2 x i4> [[X:%.*]], [[Y:%.*]]
473; CHECK-NEXT:    [[TMP2:%.*]] = bitcast <2 x i1> [[TMP1]] to i2
474; CHECK-NEXT:    [[R:%.*]] = icmp eq i2 [[TMP2]], 0
475; CHECK-NEXT:    ret i1 [[R]]
476;
477  %ic = icmp ugt <2 x i4> %x, %y
478  %b = bitcast <2 x i1> %ic to i2
479  %r = icmp eq i2 %b, -1
480  ret i1 %r
481}
482
483define i1 @slt_cast_ne-1(<2 x i4> %x, <2 x i4> %y) {
484; CHECK-LABEL: @slt_cast_ne-1(
485; CHECK-NEXT:    [[TMP1:%.*]] = icmp sge <2 x i4> [[X:%.*]], [[Y:%.*]]
486; CHECK-NEXT:    [[TMP2:%.*]] = bitcast <2 x i1> [[TMP1]] to i2
487; CHECK-NEXT:    [[R:%.*]] = icmp ne i2 [[TMP2]], 0
488; CHECK-NEXT:    ret i1 [[R]]
489;
490  %ic = icmp slt <2 x i4> %x, %y
491  %b = bitcast <2 x i1> %ic to i2
492  %r = icmp ne i2 %b, -1
493  ret i1 %r
494}
495
496define i1 @ueq_cast_eq-1(<3 x float> %x, <3 x float> %y) {
497; CHECK-LABEL: @ueq_cast_eq-1(
498; CHECK-NEXT:    [[TMP1:%.*]] = fcmp one <3 x float> [[X:%.*]], [[Y:%.*]]
499; CHECK-NEXT:    [[TMP2:%.*]] = bitcast <3 x i1> [[TMP1]] to i3
500; CHECK-NEXT:    [[R:%.*]] = icmp eq i3 [[TMP2]], 0
501; CHECK-NEXT:    ret i1 [[R]]
502;
503  %fc = fcmp ueq <3 x float> %x, %y
504  %b = bitcast <3 x i1> %fc to i3
505  %r = icmp eq i3 %b, -1
506  ret i1 %r
507}
508
509define i1 @not_cast_ne-1(<3 x i1> %x) {
510; CHECK-LABEL: @not_cast_ne-1(
511; CHECK-NEXT:    [[TMP1:%.*]] = bitcast <3 x i1> [[X:%.*]] to i3
512; CHECK-NEXT:    [[R:%.*]] = icmp ne i3 [[TMP1]], 0
513; CHECK-NEXT:    ret i1 [[R]]
514;
515  %not = xor <3 x i1> %x, <i1 -1, i1 -1, i1 -1>
516  %b = bitcast <3 x i1> %not to i3
517  %r = icmp ne i3 %b, -1
518  ret i1 %r
519}
520
521define i1 @not_cast_ne-1_uses(<3 x i2> %x, ptr %p) {
522; CHECK-LABEL: @not_cast_ne-1_uses(
523; CHECK-NEXT:    [[NOT:%.*]] = xor <3 x i2> [[X:%.*]], splat (i2 -1)
524; CHECK-NEXT:    store <3 x i2> [[NOT]], ptr [[P:%.*]], align 1
525; CHECK-NEXT:    [[TMP1:%.*]] = bitcast <3 x i2> [[X]] to i6
526; CHECK-NEXT:    [[R:%.*]] = icmp ne i6 [[TMP1]], 0
527; CHECK-NEXT:    ret i1 [[R]]
528;
529  %not = xor <3 x i2> %x, <i2 -1, i2 -1, i2 -1>
530  store <3 x i2> %not, ptr %p
531  %b = bitcast <3 x i2> %not to i6
532  %r = icmp ne i6 %b, -1
533  ret i1 %r
534}
535
536; negative test - need equality pred on 2nd cmp
537
538define i1 @eq_cast_sgt-1(<3 x i4> %x, <3 x i4> %y) {
539; CHECK-LABEL: @eq_cast_sgt-1(
540; CHECK-NEXT:    [[IC:%.*]] = icmp eq <3 x i4> [[X:%.*]], [[Y:%.*]]
541; CHECK-NEXT:    [[B:%.*]] = bitcast <3 x i1> [[IC]] to i3
542; CHECK-NEXT:    [[R:%.*]] = icmp sgt i3 [[B]], -1
543; CHECK-NEXT:    ret i1 [[R]]
544;
545  %ic = icmp eq <3 x i4> %x, %y
546  %b = bitcast <3 x i1> %ic to i3
547  %r = icmp sgt i3 %b, -1
548  ret i1 %r
549}
550
551; negative test - need all-ones constant on 2nd cmp
552
553define i1 @eq_cast_eq1(<2 x i4> %x, <2 x i4> %y) {
554; CHECK-LABEL: @eq_cast_eq1(
555; CHECK-NEXT:    [[IC:%.*]] = icmp eq <2 x i4> [[X:%.*]], [[Y:%.*]]
556; CHECK-NEXT:    [[B:%.*]] = bitcast <2 x i1> [[IC]] to i2
557; CHECK-NEXT:    [[R:%.*]] = icmp eq i2 [[B]], 1
558; CHECK-NEXT:    ret i1 [[R]]
559;
560  %ic = icmp eq <2 x i4> %x, %y
561  %b = bitcast <2 x i1> %ic to i2
562  %r = icmp eq i2 %b, 1
563  ret i1 %r
564}
565
566; negative test - extra use
567
568define i1 @eq_cast_eq-1_use1(<2 x i4> %x, <2 x i4> %y, ptr %p) {
569; CHECK-LABEL: @eq_cast_eq-1_use1(
570; CHECK-NEXT:    [[IC:%.*]] = icmp sgt <2 x i4> [[X:%.*]], [[Y:%.*]]
571; CHECK-NEXT:    store <2 x i1> [[IC]], ptr [[P:%.*]], align 1
572; CHECK-NEXT:    [[B:%.*]] = bitcast <2 x i1> [[IC]] to i2
573; CHECK-NEXT:    [[R:%.*]] = icmp eq i2 [[B]], -1
574; CHECK-NEXT:    ret i1 [[R]]
575;
576  %ic = icmp sgt <2 x i4> %x, %y
577  store <2 x i1> %ic, ptr %p
578  %b = bitcast <2 x i1> %ic to i2
579  %r = icmp eq i2 %b, -1
580  ret i1 %r
581}
582
583; negative test - extra use
584
585define i1 @eq_cast_eq-1_use2(<2 x i4> %x, <2 x i4> %y, ptr %p) {
586; CHECK-LABEL: @eq_cast_eq-1_use2(
587; CHECK-NEXT:    [[IC:%.*]] = icmp sgt <2 x i4> [[X:%.*]], [[Y:%.*]]
588; CHECK-NEXT:    [[B:%.*]] = bitcast <2 x i1> [[IC]] to i2
589; CHECK-NEXT:    store <2 x i1> [[IC]], ptr [[P:%.*]], align 1
590; CHECK-NEXT:    [[R:%.*]] = icmp eq i2 [[B]], -1
591; CHECK-NEXT:    ret i1 [[R]]
592;
593  %ic = icmp sgt <2 x i4> %x, %y
594  %b = bitcast <2 x i1> %ic to i2
595  store i2 %b, ptr %p
596  %r = icmp eq i2 %b, -1
597  ret i1 %r
598}
599
600define i1 @ne_cast_sext(<3 x i1> %b) {
601; CHECK-LABEL: @ne_cast_sext(
602; CHECK-NEXT:    [[TMP1:%.*]] = bitcast <3 x i1> [[B:%.*]] to i3
603; CHECK-NEXT:    [[R:%.*]] = icmp ne i3 [[TMP1]], 0
604; CHECK-NEXT:    ret i1 [[R]]
605;
606  %e = sext <3 x i1> %b to <3 x i8>
607  %bc = bitcast <3 x i8> %e to i24
608  %r = icmp ne i24 %bc, 0
609  ret i1 %r
610}
611
612define i1 @eq_cast_sext(<8 x i3> %b) {
613; CHECK-LABEL: @eq_cast_sext(
614; CHECK-NEXT:    [[TMP1:%.*]] = bitcast <8 x i3> [[B:%.*]] to i24
615; CHECK-NEXT:    [[R:%.*]] = icmp eq i24 [[TMP1]], 0
616; CHECK-NEXT:    ret i1 [[R]]
617;
618  %e = sext <8 x i3> %b to <8 x i8>
619  %bc = bitcast <8 x i8> %e to i64
620  %r = icmp eq i64 %bc, 0
621  ret i1 %r
622}
623
624define i1 @ne_cast_zext(<4 x i1> %b) {
625; CHECK-LABEL: @ne_cast_zext(
626; CHECK-NEXT:    [[TMP1:%.*]] = bitcast <4 x i1> [[B:%.*]] to i4
627; CHECK-NEXT:    [[R:%.*]] = icmp ne i4 [[TMP1]], 0
628; CHECK-NEXT:    ret i1 [[R]]
629;
630  %e = zext <4 x i1> %b to <4 x i8>
631  %bc = bitcast <4 x i8> %e to i32
632  %r = icmp ne i32 %bc, 0
633  ret i1 %r
634}
635
636define i1 @eq_cast_zext(<5 x i3> %b) {
637; CHECK-LABEL: @eq_cast_zext(
638; CHECK-NEXT:    [[TMP1:%.*]] = bitcast <5 x i3> [[B:%.*]] to i15
639; CHECK-NEXT:    [[R:%.*]] = icmp eq i15 [[TMP1]], 0
640; CHECK-NEXT:    ret i1 [[R]]
641;
642  %e = zext <5 x i3> %b to <5 x i7>
643  %bc = bitcast <5 x i7> %e to i35
644  %r = icmp eq i35 %bc, 0
645  ret i1 %r
646}
647
648; negative test - valid for eq/ne only
649
650define i1 @sgt_cast_zext(<5 x i3> %b) {
651; CHECK-LABEL: @sgt_cast_zext(
652; CHECK-NEXT:    [[TMP1:%.*]] = bitcast <5 x i3> [[B:%.*]] to i15
653; CHECK-NEXT:    [[R:%.*]] = icmp ne i15 [[TMP1]], 0
654; CHECK-NEXT:    ret i1 [[R]]
655;
656  %e = zext <5 x i3> %b to <5 x i7>
657  %bc = bitcast <5 x i7> %e to i35
658  %r = icmp sgt i35 %bc, 0
659  ret i1 %r
660}
661
662; negative test - not valid with non-zero constants
663; TODO: We could handle some non-zero constants by checking for bit-loss after casts.
664
665define i1 @eq7_cast_sext(<5 x i3> %b) {
666; CHECK-LABEL: @eq7_cast_sext(
667; CHECK-NEXT:    [[E:%.*]] = sext <5 x i3> [[B:%.*]] to <5 x i7>
668; CHECK-NEXT:    [[BC:%.*]] = bitcast <5 x i7> [[E]] to i35
669; CHECK-NEXT:    [[R:%.*]] = icmp eq i35 [[BC]], 7
670; CHECK-NEXT:    ret i1 [[R]]
671;
672  %e = sext <5 x i3> %b to <5 x i7>
673  %bc = bitcast <5 x i7> %e to i35
674  %r = icmp eq i35 %bc, 7
675  ret i1 %r
676}
677
678; extra use of extend is ok
679
680define i1 @eq_cast_zext_use1(<5 x i3> %b, ptr %p) {
681; CHECK-LABEL: @eq_cast_zext_use1(
682; CHECK-NEXT:    [[E:%.*]] = zext <5 x i3> [[B:%.*]] to <5 x i7>
683; CHECK-NEXT:    store <5 x i7> [[E]], ptr [[P:%.*]], align 8
684; CHECK-NEXT:    [[TMP1:%.*]] = bitcast <5 x i3> [[B]] to i15
685; CHECK-NEXT:    [[R:%.*]] = icmp eq i15 [[TMP1]], 0
686; CHECK-NEXT:    ret i1 [[R]]
687;
688  %e = zext <5 x i3> %b to <5 x i7>
689  store <5 x i7> %e, ptr %p
690  %bc = bitcast <5 x i7> %e to i35
691  %r = icmp eq i35 %bc, 0
692  ret i1 %r
693}
694
695; negative test - don't create an extra cast
696
697declare void @use35(i35)
698
699define i1 @eq_cast_zext_use2(<5 x i3> %b) {
700; CHECK-LABEL: @eq_cast_zext_use2(
701; CHECK-NEXT:    [[E:%.*]] = zext <5 x i3> [[B:%.*]] to <5 x i7>
702; CHECK-NEXT:    [[BC:%.*]] = bitcast <5 x i7> [[E]] to i35
703; CHECK-NEXT:    call void @use35(i35 [[BC]])
704; CHECK-NEXT:    [[R:%.*]] = icmp eq i35 [[BC]], 0
705; CHECK-NEXT:    ret i1 [[R]]
706;
707  %e = zext <5 x i3> %b to <5 x i7>
708  %bc = bitcast <5 x i7> %e to i35
709  call void @use35(i35 %bc)
710  %r = icmp eq i35 %bc, 0
711  ret i1 %r
712}
713
714define i1 @eq_cast_eq_ptr-1(<2 x ptr> %x, <2 x ptr> %y) {
715; CHECK-LABEL: @eq_cast_eq_ptr-1(
716; CHECK-NEXT:    [[TMP1:%.*]] = icmp ne <2 x ptr> [[X:%.*]], [[Y:%.*]]
717; CHECK-NEXT:    [[TMP2:%.*]] = bitcast <2 x i1> [[TMP1]] to i2
718; CHECK-NEXT:    [[R:%.*]] = icmp eq i2 [[TMP2]], 0
719; CHECK-NEXT:    ret i1 [[R]]
720;
721  %ic = icmp eq <2 x ptr> %x, %y
722  %b = bitcast <2 x i1> %ic to i2
723  %r = icmp eq i2 %b, -1
724  ret i1 %r
725}
726
727define i1 @eq_cast_ne_ptr-1(<2 x ptr> %x, <2 x ptr> %y) {
728; CHECK-LABEL: @eq_cast_ne_ptr-1(
729; CHECK-NEXT:    [[TMP1:%.*]] = icmp ne <2 x ptr> [[X:%.*]], [[Y:%.*]]
730; CHECK-NEXT:    [[TMP2:%.*]] = bitcast <2 x i1> [[TMP1]] to i2
731; CHECK-NEXT:    [[R:%.*]] = icmp ne i2 [[TMP2]], 0
732; CHECK-NEXT:    ret i1 [[R]]
733;
734  %ic = icmp eq <2 x ptr> %x, %y
735  %b = bitcast <2 x i1> %ic to i2
736  %r = icmp ne i2 %b, -1
737  ret i1 %r
738}
739