xref: /llvm-project/llvm/test/Transforms/InstCombine/trunc-inseltpoison.ll (revision 38fffa630ee80163dc65e759392ad29798905679)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -passes=instcombine -S | FileCheck %s
3target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
4
5; Instcombine should be able to eliminate all of these ext casts.
6
7declare void @use(i32)
8declare void @use_vec(<2 x i32>)
9
10define i64 @test1(i64 %a) {
11; CHECK-LABEL: @test1(
12; CHECK-NEXT:    [[B:%.*]] = trunc i64 [[A:%.*]] to i32
13; CHECK-NEXT:    [[C:%.*]] = and i64 [[A]], 15
14; CHECK-NEXT:    call void @use(i32 [[B]])
15; CHECK-NEXT:    ret i64 [[C]]
16;
17  %b = trunc i64 %a to i32
18  %c = and i32 %b, 15
19  %d = zext i32 %c to i64
20  call void @use(i32 %b)
21  ret i64 %d
22}
23
24define <2 x i64> @test1_vec(<2 x i64> %a) {
25; CHECK-LABEL: @test1_vec(
26; CHECK-NEXT:    [[B:%.*]] = trunc <2 x i64> [[A:%.*]] to <2 x i32>
27; CHECK-NEXT:    [[D:%.*]] = and <2 x i64> [[A]], splat (i64 15)
28; CHECK-NEXT:    call void @use_vec(<2 x i32> [[B]])
29; CHECK-NEXT:    ret <2 x i64> [[D]]
30;
31  %b = trunc <2 x i64> %a to <2 x i32>
32  %c = and <2 x i32> %b, <i32 15, i32 15>
33  %d = zext <2 x i32> %c to <2 x i64>
34  call void @use_vec(<2 x i32> %b)
35  ret <2 x i64> %d
36}
37
38define <2 x i64> @test1_vec_nonuniform(<2 x i64> %a) {
39; CHECK-LABEL: @test1_vec_nonuniform(
40; CHECK-NEXT:    [[B:%.*]] = trunc <2 x i64> [[A:%.*]] to <2 x i32>
41; CHECK-NEXT:    [[D:%.*]] = and <2 x i64> [[A]], <i64 15, i64 7>
42; CHECK-NEXT:    call void @use_vec(<2 x i32> [[B]])
43; CHECK-NEXT:    ret <2 x i64> [[D]]
44;
45  %b = trunc <2 x i64> %a to <2 x i32>
46  %c = and <2 x i32> %b, <i32 15, i32 7>
47  %d = zext <2 x i32> %c to <2 x i64>
48  call void @use_vec(<2 x i32> %b)
49  ret <2 x i64> %d
50}
51
52define <2 x i64> @test1_vec_poison(<2 x i64> %a) {
53; CHECK-LABEL: @test1_vec_poison(
54; CHECK-NEXT:    [[B:%.*]] = trunc <2 x i64> [[A:%.*]] to <2 x i32>
55; CHECK-NEXT:    [[D:%.*]] = and <2 x i64> [[A]], <i64 15, i64 poison>
56; CHECK-NEXT:    call void @use_vec(<2 x i32> [[B]])
57; CHECK-NEXT:    ret <2 x i64> [[D]]
58;
59  %b = trunc <2 x i64> %a to <2 x i32>
60  %c = and <2 x i32> %b, <i32 15, i32 poison>
61  %d = zext <2 x i32> %c to <2 x i64>
62  call void @use_vec(<2 x i32> %b)
63  ret <2 x i64> %d
64}
65
66define i64 @test2(i64 %a) {
67; CHECK-LABEL: @test2(
68; CHECK-NEXT:    [[B:%.*]] = trunc i64 [[A:%.*]] to i32
69; CHECK-NEXT:    [[D1:%.*]] = shl i64 [[A]], 36
70; CHECK-NEXT:    [[D:%.*]] = ashr exact i64 [[D1]], 36
71; CHECK-NEXT:    call void @use(i32 [[B]])
72; CHECK-NEXT:    ret i64 [[D]]
73;
74  %b = trunc i64 %a to i32
75  %c = shl i32 %b, 4
76  %q = ashr i32 %c, 4
77  %d = sext i32 %q to i64
78  call void @use(i32 %b)
79  ret i64 %d
80}
81
82define <2 x i64> @test2_vec(<2 x i64> %a) {
83; CHECK-LABEL: @test2_vec(
84; CHECK-NEXT:    [[B:%.*]] = trunc <2 x i64> [[A:%.*]] to <2 x i32>
85; CHECK-NEXT:    [[D1:%.*]] = shl <2 x i64> [[A]], splat (i64 36)
86; CHECK-NEXT:    [[D:%.*]] = ashr exact <2 x i64> [[D1]], splat (i64 36)
87; CHECK-NEXT:    call void @use_vec(<2 x i32> [[B]])
88; CHECK-NEXT:    ret <2 x i64> [[D]]
89;
90  %b = trunc <2 x i64> %a to <2 x i32>
91  %c = shl <2 x i32> %b, <i32 4, i32 4>
92  %q = ashr <2 x i32> %c, <i32 4, i32 4>
93  %d = sext <2 x i32> %q to <2 x i64>
94  call void @use_vec(<2 x i32> %b)
95  ret <2 x i64> %d
96}
97
98define <2 x i64> @test2_vec_nonuniform(<2 x i64> %a) {
99; CHECK-LABEL: @test2_vec_nonuniform(
100; CHECK-NEXT:    [[B:%.*]] = trunc <2 x i64> [[A:%.*]] to <2 x i32>
101; CHECK-NEXT:    [[D1:%.*]] = shl <2 x i64> [[A]], <i64 36, i64 37>
102; CHECK-NEXT:    [[D:%.*]] = ashr exact <2 x i64> [[D1]], <i64 36, i64 37>
103; CHECK-NEXT:    call void @use_vec(<2 x i32> [[B]])
104; CHECK-NEXT:    ret <2 x i64> [[D]]
105;
106  %b = trunc <2 x i64> %a to <2 x i32>
107  %c = shl <2 x i32> %b, <i32 4, i32 5>
108  %q = ashr <2 x i32> %c, <i32 4, i32 5>
109  %d = sext <2 x i32> %q to <2 x i64>
110  call void @use_vec(<2 x i32> %b)
111  ret <2 x i64> %d
112}
113
114define <2 x i64> @test2_vec_poison(<2 x i64> %a) {
115; CHECK-LABEL: @test2_vec_poison(
116; CHECK-NEXT:    [[B:%.*]] = trunc <2 x i64> [[A:%.*]] to <2 x i32>
117; CHECK-NEXT:    [[D1:%.*]] = shl <2 x i64> [[A]], <i64 36, i64 poison>
118; CHECK-NEXT:    [[D:%.*]] = ashr exact <2 x i64> [[D1]], <i64 36, i64 poison>
119; CHECK-NEXT:    call void @use_vec(<2 x i32> [[B]])
120; CHECK-NEXT:    ret <2 x i64> [[D]]
121;
122  %b = trunc <2 x i64> %a to <2 x i32>
123  %c = shl <2 x i32> %b, <i32 4, i32 poison>
124  %q = ashr <2 x i32> %c, <i32 4, i32 poison>
125  %d = sext <2 x i32> %q to <2 x i64>
126  call void @use_vec(<2 x i32> %b)
127  ret <2 x i64> %d
128}
129
130define i64 @test3(i64 %a) {
131; CHECK-LABEL: @test3(
132; CHECK-NEXT:    [[B:%.*]] = trunc i64 [[A:%.*]] to i32
133; CHECK-NEXT:    [[C:%.*]] = and i64 [[A]], 8
134; CHECK-NEXT:    call void @use(i32 [[B]])
135; CHECK-NEXT:    ret i64 [[C]]
136;
137  %b = trunc i64 %a to i32
138  %c = and i32 %b, 8
139  %d = zext i32 %c to i64
140  call void @use(i32 %b)
141  ret i64 %d
142}
143
144define i64 @test4(i64 %a) {
145; CHECK-LABEL: @test4(
146; CHECK-NEXT:    [[B:%.*]] = trunc i64 [[A:%.*]] to i32
147; CHECK-NEXT:    [[C:%.*]] = and i64 [[A]], 8
148; CHECK-NEXT:    [[X:%.*]] = xor i64 [[C]], 8
149; CHECK-NEXT:    call void @use(i32 [[B]])
150; CHECK-NEXT:    ret i64 [[X]]
151;
152  %b = trunc i64 %a to i32
153  %c = and i32 %b, 8
154  %x = xor i32 %c, 8
155  %d = zext i32 %x to i64
156  call void @use(i32 %b)
157  ret i64 %d
158}
159
160define i32 @test5(i32 %A) {
161; CHECK-LABEL: @test5(
162; CHECK-NEXT:    [[TMP1:%.*]] = lshr i32 [[A:%.*]], 16
163; CHECK-NEXT:    ret i32 [[TMP1]]
164;
165  %B = zext i32 %A to i128
166  %C = lshr i128 %B, 16
167  %D = trunc i128 %C to i32
168  ret i32 %D
169}
170
171define i32 @test6(i64 %A) {
172; CHECK-LABEL: @test6(
173; CHECK-NEXT:    [[TMP1:%.*]] = lshr i64 [[A:%.*]], 32
174; CHECK-NEXT:    [[D:%.*]] = trunc nuw i64 [[TMP1]] to i32
175; CHECK-NEXT:    ret i32 [[D]]
176;
177  %B = zext i64 %A to i128
178  %C = lshr i128 %B, 32
179  %D = trunc i128 %C to i32
180  ret i32 %D
181}
182
183; Test case where 'ashr' demanded bits does not contain any of the high bits,
184; but does contain sign bits, where the sign bit is not known to be zero.
185define i16 @ashr_mul_sign_bits(i8 %X, i8 %Y) {
186; CHECK-LABEL: @ashr_mul_sign_bits(
187; CHECK-NEXT:    [[A:%.*]] = sext i8 [[X:%.*]] to i16
188; CHECK-NEXT:    [[B:%.*]] = sext i8 [[Y:%.*]] to i16
189; CHECK-NEXT:    [[C:%.*]] = mul nsw i16 [[A]], [[B]]
190; CHECK-NEXT:    [[D:%.*]] = ashr i16 [[C]], 3
191; CHECK-NEXT:    ret i16 [[D]]
192;
193  %A = sext i8 %X to i32
194  %B = sext i8 %Y to i32
195  %C = mul i32 %A, %B
196  %D = ashr i32 %C, 3
197  %E = trunc i32 %D to i16
198  ret i16 %E
199}
200
201define i16 @ashr_mul(i8 %X, i8 %Y) {
202; CHECK-LABEL: @ashr_mul(
203; CHECK-NEXT:    [[A:%.*]] = sext i8 [[X:%.*]] to i16
204; CHECK-NEXT:    [[B:%.*]] = sext i8 [[Y:%.*]] to i16
205; CHECK-NEXT:    [[C:%.*]] = mul nsw i16 [[A]], [[B]]
206; CHECK-NEXT:    [[D:%.*]] = ashr i16 [[C]], 8
207; CHECK-NEXT:    ret i16 [[D]]
208;
209  %A = sext i8 %X to i20
210  %B = sext i8 %Y to i20
211  %C = mul i20 %A, %B
212  %D = ashr i20 %C, 8
213  %E = trunc i20 %D to i16
214  ret i16 %E
215}
216
217define i32 @trunc_ashr(i32 %X) {
218; CHECK-LABEL: @trunc_ashr(
219; CHECK-NEXT:    [[TMP1:%.*]] = lshr i32 [[X:%.*]], 8
220; CHECK-NEXT:    [[C:%.*]] = or i32 [[TMP1]], -8388608
221; CHECK-NEXT:    ret i32 [[C]]
222;
223  %A = zext i32 %X to i36
224  %B = or i36 %A, -2147483648 ; 0xF80000000
225  %C = ashr i36 %B, 8
226  %T = trunc i36 %C to i32
227  ret i32  %T
228}
229
230define <2 x i32> @trunc_ashr_vec(<2 x i32> %X) {
231; CHECK-LABEL: @trunc_ashr_vec(
232; CHECK-NEXT:    [[TMP1:%.*]] = lshr <2 x i32> [[X:%.*]], splat (i32 8)
233; CHECK-NEXT:    [[C:%.*]] = or <2 x i32> [[TMP1]], splat (i32 -8388608)
234; CHECK-NEXT:    ret <2 x i32> [[C]]
235;
236  %A = zext <2 x i32> %X to <2 x i36>
237  %B = or <2 x i36> %A, <i36 -2147483648, i36 -2147483648> ; 0xF80000000
238  %C = ashr <2 x i36> %B, <i36 8, i36 8>
239  %T = trunc <2 x i36> %C to <2 x i32>
240  ret <2 x i32>  %T
241}
242
243define i92 @test7(i64 %A) {
244; CHECK-LABEL: @test7(
245; CHECK-NEXT:    [[TMP1:%.*]] = lshr i64 [[A:%.*]], 32
246; CHECK-NEXT:    [[D:%.*]] = zext nneg i64 [[TMP1]] to i92
247; CHECK-NEXT:    ret i92 [[D]]
248;
249  %B = zext i64 %A to i128
250  %C = lshr i128 %B, 32
251  %D = trunc i128 %C to i92
252  ret i92 %D
253}
254
255define i64 @test8(i32 %A, i32 %B) {
256; CHECK-LABEL: @test8(
257; CHECK-NEXT:    [[C:%.*]] = zext i32 [[A:%.*]] to i64
258; CHECK-NEXT:    [[D:%.*]] = zext i32 [[B:%.*]] to i64
259; CHECK-NEXT:    [[E:%.*]] = shl nuw i64 [[D]], 32
260; CHECK-NEXT:    [[F:%.*]] = or disjoint i64 [[E]], [[C]]
261; CHECK-NEXT:    ret i64 [[F]]
262;
263  %C = zext i32 %A to i128
264  %D = zext i32 %B to i128
265  %E = shl i128 %D, 32
266  %F = or i128 %E, %C
267  %G = trunc i128 %F to i64
268  ret i64 %G
269}
270
271define <2 x i64> @test8_vec(<2 x i32> %A, <2 x i32> %B) {
272; CHECK-LABEL: @test8_vec(
273; CHECK-NEXT:    [[C:%.*]] = zext <2 x i32> [[A:%.*]] to <2 x i64>
274; CHECK-NEXT:    [[D:%.*]] = zext <2 x i32> [[B:%.*]] to <2 x i64>
275; CHECK-NEXT:    [[E:%.*]] = shl nuw <2 x i64> [[D]], splat (i64 32)
276; CHECK-NEXT:    [[F:%.*]] = or disjoint <2 x i64> [[E]], [[C]]
277; CHECK-NEXT:    ret <2 x i64> [[F]]
278;
279  %C = zext <2 x i32> %A to <2 x i128>
280  %D = zext <2 x i32> %B to <2 x i128>
281  %E = shl <2 x i128> %D, <i128 32, i128 32>
282  %F = or <2 x i128> %E, %C
283  %G = trunc <2 x i128> %F to <2 x i64>
284  ret <2 x i64> %G
285}
286
287define <2 x i64> @test8_vec_nonuniform(<2 x i32> %A, <2 x i32> %B) {
288; CHECK-LABEL: @test8_vec_nonuniform(
289; CHECK-NEXT:    [[C:%.*]] = zext <2 x i32> [[A:%.*]] to <2 x i64>
290; CHECK-NEXT:    [[D:%.*]] = zext <2 x i32> [[B:%.*]] to <2 x i64>
291; CHECK-NEXT:    [[E:%.*]] = shl <2 x i64> [[D]], <i64 32, i64 48>
292; CHECK-NEXT:    [[F:%.*]] = or disjoint <2 x i64> [[E]], [[C]]
293; CHECK-NEXT:    ret <2 x i64> [[F]]
294;
295  %C = zext <2 x i32> %A to <2 x i128>
296  %D = zext <2 x i32> %B to <2 x i128>
297  %E = shl <2 x i128> %D, <i128 32, i128 48>
298  %F = or <2 x i128> %E, %C
299  %G = trunc <2 x i128> %F to <2 x i64>
300  ret <2 x i64> %G
301}
302
303define <2 x i64> @test8_vec_poison(<2 x i32> %A, <2 x i32> %B) {
304; CHECK-LABEL: @test8_vec_poison(
305; CHECK-NEXT:    [[C:%.*]] = zext <2 x i32> [[A:%.*]] to <2 x i64>
306; CHECK-NEXT:    [[D:%.*]] = zext <2 x i32> [[B:%.*]] to <2 x i64>
307; CHECK-NEXT:    [[E:%.*]] = shl nuw <2 x i64> [[D]], <i64 32, i64 poison>
308; CHECK-NEXT:    [[G:%.*]] = or disjoint <2 x i64> [[E]], [[C]]
309; CHECK-NEXT:    ret <2 x i64> [[G]]
310;
311  %C = zext <2 x i32> %A to <2 x i128>
312  %D = zext <2 x i32> %B to <2 x i128>
313  %E = shl <2 x i128> %D, <i128 32, i128 poison>
314  %F = or <2 x i128> %E, %C
315  %G = trunc <2 x i128> %F to <2 x i64>
316  ret <2 x i64> %G
317}
318
319define i8 @test9(i32 %X) {
320; CHECK-LABEL: @test9(
321; CHECK-NEXT:    [[TMP1:%.*]] = trunc i32 [[X:%.*]] to i8
322; CHECK-NEXT:    [[Z:%.*]] = and i8 [[TMP1]], 42
323; CHECK-NEXT:    ret i8 [[Z]]
324;
325  %Y = and i32 %X, 42
326  %Z = trunc i32 %Y to i8
327  ret i8 %Z
328}
329
330; rdar://8808586
331define i8 @test10(i32 %X) {
332; CHECK-LABEL: @test10(
333; CHECK-NEXT:    [[Y:%.*]] = trunc i32 [[X:%.*]] to i8
334; CHECK-NEXT:    [[Z:%.*]] = and i8 [[Y]], 42
335; CHECK-NEXT:    ret i8 [[Z]]
336;
337  %Y = trunc i32 %X to i8
338  %Z = and i8 %Y, 42
339  ret i8 %Z
340}
341
342define i64 @test11(i32 %A, i32 %B) {
343; CHECK-LABEL: @test11(
344; CHECK-NEXT:    [[C:%.*]] = zext i32 [[A:%.*]] to i64
345; CHECK-NEXT:    [[TMP1:%.*]] = and i32 [[B:%.*]], 31
346; CHECK-NEXT:    [[E:%.*]] = zext nneg i32 [[TMP1]] to i64
347; CHECK-NEXT:    [[F:%.*]] = shl nuw nsw i64 [[C]], [[E]]
348; CHECK-NEXT:    ret i64 [[F]]
349;
350  %C = zext i32 %A to i128
351  %D = zext i32 %B to i128
352  %E = and i128 %D, 31
353  %F = shl i128 %C, %E
354  %G = trunc i128 %F to i64
355  ret i64 %G
356}
357
358define <2 x i64> @test11_vec(<2 x i32> %A, <2 x i32> %B) {
359; CHECK-LABEL: @test11_vec(
360; CHECK-NEXT:    [[C:%.*]] = zext <2 x i32> [[A:%.*]] to <2 x i64>
361; CHECK-NEXT:    [[TMP1:%.*]] = and <2 x i32> [[B:%.*]], splat (i32 31)
362; CHECK-NEXT:    [[E:%.*]] = zext nneg <2 x i32> [[TMP1]] to <2 x i64>
363; CHECK-NEXT:    [[F:%.*]] = shl nuw nsw <2 x i64> [[C]], [[E]]
364; CHECK-NEXT:    ret <2 x i64> [[F]]
365;
366  %C = zext <2 x i32> %A to <2 x i128>
367  %D = zext <2 x i32> %B to <2 x i128>
368  %E = and <2 x i128> %D, <i128 31, i128 31>
369  %F = shl <2 x i128> %C, %E
370  %G = trunc <2 x i128> %F to <2 x i64>
371  ret <2 x i64> %G
372}
373
374define <2 x i64> @test11_vec_nonuniform(<2 x i32> %A, <2 x i32> %B) {
375; CHECK-LABEL: @test11_vec_nonuniform(
376; CHECK-NEXT:    [[C:%.*]] = zext <2 x i32> [[A:%.*]] to <2 x i64>
377; CHECK-NEXT:    [[TMP1:%.*]] = and <2 x i32> [[B:%.*]], <i32 31, i32 15>
378; CHECK-NEXT:    [[E:%.*]] = zext nneg <2 x i32> [[TMP1]] to <2 x i64>
379; CHECK-NEXT:    [[F:%.*]] = shl nuw nsw <2 x i64> [[C]], [[E]]
380; CHECK-NEXT:    ret <2 x i64> [[F]]
381;
382  %C = zext <2 x i32> %A to <2 x i128>
383  %D = zext <2 x i32> %B to <2 x i128>
384  %E = and <2 x i128> %D, <i128 31, i128 15>
385  %F = shl <2 x i128> %C, %E
386  %G = trunc <2 x i128> %F to <2 x i64>
387  ret <2 x i64> %G
388}
389
390define <2 x i64> @test11_vec_poison(<2 x i32> %A, <2 x i32> %B) {
391; CHECK-LABEL: @test11_vec_poison(
392; CHECK-NEXT:    [[C:%.*]] = zext <2 x i32> [[A:%.*]] to <2 x i64>
393; CHECK-NEXT:    [[TMP1:%.*]] = and <2 x i32> [[B:%.*]], <i32 31, i32 poison>
394; CHECK-NEXT:    [[E:%.*]] = zext nneg <2 x i32> [[TMP1]] to <2 x i64>
395; CHECK-NEXT:    [[G:%.*]] = shl nuw nsw <2 x i64> [[C]], [[E]]
396; CHECK-NEXT:    ret <2 x i64> [[G]]
397;
398  %C = zext <2 x i32> %A to <2 x i128>
399  %D = zext <2 x i32> %B to <2 x i128>
400  %E = and <2 x i128> %D, <i128 31, i128 poison>
401  %F = shl <2 x i128> %C, %E
402  %G = trunc <2 x i128> %F to <2 x i64>
403  ret <2 x i64> %G
404}
405
406define i64 @test12(i32 %A, i32 %B) {
407; CHECK-LABEL: @test12(
408; CHECK-NEXT:    [[C:%.*]] = zext i32 [[A:%.*]] to i64
409; CHECK-NEXT:    [[TMP1:%.*]] = and i32 [[B:%.*]], 31
410; CHECK-NEXT:    [[E:%.*]] = zext nneg i32 [[TMP1]] to i64
411; CHECK-NEXT:    [[F:%.*]] = lshr i64 [[C]], [[E]]
412; CHECK-NEXT:    ret i64 [[F]]
413;
414  %C = zext i32 %A to i128
415  %D = zext i32 %B to i128
416  %E = and i128 %D, 31
417  %F = lshr i128 %C, %E
418  %G = trunc i128 %F to i64
419  ret i64 %G
420}
421
422define <2 x i64> @test12_vec(<2 x i32> %A, <2 x i32> %B) {
423; CHECK-LABEL: @test12_vec(
424; CHECK-NEXT:    [[C:%.*]] = zext <2 x i32> [[A:%.*]] to <2 x i64>
425; CHECK-NEXT:    [[TMP1:%.*]] = and <2 x i32> [[B:%.*]], splat (i32 31)
426; CHECK-NEXT:    [[E:%.*]] = zext nneg <2 x i32> [[TMP1]] to <2 x i64>
427; CHECK-NEXT:    [[F:%.*]] = lshr <2 x i64> [[C]], [[E]]
428; CHECK-NEXT:    ret <2 x i64> [[F]]
429;
430  %C = zext <2 x i32> %A to <2 x i128>
431  %D = zext <2 x i32> %B to <2 x i128>
432  %E = and <2 x i128> %D, <i128 31, i128 31>
433  %F = lshr <2 x i128> %C, %E
434  %G = trunc <2 x i128> %F to <2 x i64>
435  ret <2 x i64> %G
436}
437
438define <2 x i64> @test12_vec_nonuniform(<2 x i32> %A, <2 x i32> %B) {
439; CHECK-LABEL: @test12_vec_nonuniform(
440; CHECK-NEXT:    [[C:%.*]] = zext <2 x i32> [[A:%.*]] to <2 x i64>
441; CHECK-NEXT:    [[TMP1:%.*]] = and <2 x i32> [[B:%.*]], <i32 31, i32 15>
442; CHECK-NEXT:    [[E:%.*]] = zext nneg <2 x i32> [[TMP1]] to <2 x i64>
443; CHECK-NEXT:    [[F:%.*]] = lshr <2 x i64> [[C]], [[E]]
444; CHECK-NEXT:    ret <2 x i64> [[F]]
445;
446  %C = zext <2 x i32> %A to <2 x i128>
447  %D = zext <2 x i32> %B to <2 x i128>
448  %E = and <2 x i128> %D, <i128 31, i128 15>
449  %F = lshr <2 x i128> %C, %E
450  %G = trunc <2 x i128> %F to <2 x i64>
451  ret <2 x i64> %G
452}
453
454define <2 x i64> @test12_vec_poison(<2 x i32> %A, <2 x i32> %B) {
455; CHECK-LABEL: @test12_vec_poison(
456; CHECK-NEXT:    [[C:%.*]] = zext <2 x i32> [[A:%.*]] to <2 x i64>
457; CHECK-NEXT:    [[TMP1:%.*]] = and <2 x i32> [[B:%.*]], <i32 31, i32 poison>
458; CHECK-NEXT:    [[E:%.*]] = zext nneg <2 x i32> [[TMP1]] to <2 x i64>
459; CHECK-NEXT:    [[G:%.*]] = lshr <2 x i64> [[C]], [[E]]
460; CHECK-NEXT:    ret <2 x i64> [[G]]
461;
462  %C = zext <2 x i32> %A to <2 x i128>
463  %D = zext <2 x i32> %B to <2 x i128>
464  %E = and <2 x i128> %D, <i128 31, i128 poison>
465  %F = lshr <2 x i128> %C, %E
466  %G = trunc <2 x i128> %F to <2 x i64>
467  ret <2 x i64> %G
468}
469
470define i64 @test13(i32 %A, i32 %B) {
471; CHECK-LABEL: @test13(
472; CHECK-NEXT:    [[C:%.*]] = sext i32 [[A:%.*]] to i64
473; CHECK-NEXT:    [[TMP1:%.*]] = and i32 [[B:%.*]], 31
474; CHECK-NEXT:    [[E:%.*]] = zext nneg i32 [[TMP1]] to i64
475; CHECK-NEXT:    [[F:%.*]] = ashr i64 [[C]], [[E]]
476; CHECK-NEXT:    ret i64 [[F]]
477;
478  %C = sext i32 %A to i128
479  %D = zext i32 %B to i128
480  %E = and i128 %D, 31
481  %F = ashr i128 %C, %E
482  %G = trunc i128 %F to i64
483  ret i64 %G
484}
485
486define <2 x i64> @test13_vec(<2 x i32> %A, <2 x i32> %B) {
487; CHECK-LABEL: @test13_vec(
488; CHECK-NEXT:    [[C:%.*]] = sext <2 x i32> [[A:%.*]] to <2 x i64>
489; CHECK-NEXT:    [[TMP1:%.*]] = and <2 x i32> [[B:%.*]], splat (i32 31)
490; CHECK-NEXT:    [[E:%.*]] = zext nneg <2 x i32> [[TMP1]] to <2 x i64>
491; CHECK-NEXT:    [[F:%.*]] = ashr <2 x i64> [[C]], [[E]]
492; CHECK-NEXT:    ret <2 x i64> [[F]]
493;
494  %C = sext <2 x i32> %A to <2 x i128>
495  %D = zext <2 x i32> %B to <2 x i128>
496  %E = and <2 x i128> %D, <i128 31, i128 31>
497  %F = ashr <2 x i128> %C, %E
498  %G = trunc <2 x i128> %F to <2 x i64>
499  ret <2 x i64> %G
500}
501
502define <2 x i64> @test13_vec_nonuniform(<2 x i32> %A, <2 x i32> %B) {
503; CHECK-LABEL: @test13_vec_nonuniform(
504; CHECK-NEXT:    [[C:%.*]] = sext <2 x i32> [[A:%.*]] to <2 x i64>
505; CHECK-NEXT:    [[TMP1:%.*]] = and <2 x i32> [[B:%.*]], <i32 31, i32 15>
506; CHECK-NEXT:    [[E:%.*]] = zext nneg <2 x i32> [[TMP1]] to <2 x i64>
507; CHECK-NEXT:    [[F:%.*]] = ashr <2 x i64> [[C]], [[E]]
508; CHECK-NEXT:    ret <2 x i64> [[F]]
509;
510  %C = sext <2 x i32> %A to <2 x i128>
511  %D = zext <2 x i32> %B to <2 x i128>
512  %E = and <2 x i128> %D, <i128 31, i128 15>
513  %F = ashr <2 x i128> %C, %E
514  %G = trunc <2 x i128> %F to <2 x i64>
515  ret <2 x i64> %G
516}
517
518define <2 x i64> @test13_vec_poison(<2 x i32> %A, <2 x i32> %B) {
519; CHECK-LABEL: @test13_vec_poison(
520; CHECK-NEXT:    [[C:%.*]] = sext <2 x i32> [[A:%.*]] to <2 x i64>
521; CHECK-NEXT:    [[TMP1:%.*]] = and <2 x i32> [[B:%.*]], <i32 31, i32 poison>
522; CHECK-NEXT:    [[E:%.*]] = zext nneg <2 x i32> [[TMP1]] to <2 x i64>
523; CHECK-NEXT:    [[G:%.*]] = ashr <2 x i64> [[C]], [[E]]
524; CHECK-NEXT:    ret <2 x i64> [[G]]
525;
526  %C = sext <2 x i32> %A to <2 x i128>
527  %D = zext <2 x i32> %B to <2 x i128>
528  %E = and <2 x i128> %D, <i128 31, i128 poison>
529  %F = ashr <2 x i128> %C, %E
530  %G = trunc <2 x i128> %F to <2 x i64>
531  ret <2 x i64> %G
532}
533
534; PR25543
535; https://llvm.org/bugs/show_bug.cgi?id=25543
536; This is an extractelement.
537
538define i32 @trunc_bitcast1(<4 x i32> %v) {
539; CHECK-LABEL: @trunc_bitcast1(
540; CHECK-NEXT:    [[EXT:%.*]] = extractelement <4 x i32> [[V:%.*]], i64 1
541; CHECK-NEXT:    ret i32 [[EXT]]
542;
543  %bc = bitcast <4 x i32> %v to i128
544  %shr = lshr i128 %bc, 32
545  %ext = trunc i128 %shr to i32
546  ret i32 %ext
547}
548
549; A bitcast may still be required.
550
551define i32 @trunc_bitcast2(<2 x i64> %v) {
552; CHECK-LABEL: @trunc_bitcast2(
553; CHECK-NEXT:    [[BC1:%.*]] = bitcast <2 x i64> [[V:%.*]] to <4 x i32>
554; CHECK-NEXT:    [[EXT:%.*]] = extractelement <4 x i32> [[BC1]], i64 2
555; CHECK-NEXT:    ret i32 [[EXT]]
556;
557  %bc = bitcast <2 x i64> %v to i128
558  %shr = lshr i128 %bc, 64
559  %ext = trunc i128 %shr to i32
560  ret i32 %ext
561}
562
563; The right shift is optional.
564
565define i32 @trunc_bitcast3(<4 x i32> %v) {
566; CHECK-LABEL: @trunc_bitcast3(
567; CHECK-NEXT:    [[EXT:%.*]] = extractelement <4 x i32> [[V:%.*]], i64 0
568; CHECK-NEXT:    ret i32 [[EXT]]
569;
570  %bc = bitcast <4 x i32> %v to i128
571  %ext = trunc i128 %bc to i32
572  ret i32 %ext
573}
574
575define i32 @trunc_shl_31_i32_i64(i64 %val) {
576; CHECK-LABEL: @trunc_shl_31_i32_i64(
577; CHECK-NEXT:    [[VAL_TR:%.*]] = trunc i64 [[VAL:%.*]] to i32
578; CHECK-NEXT:    [[TRUNC:%.*]] = shl i32 [[VAL_TR]], 31
579; CHECK-NEXT:    ret i32 [[TRUNC]]
580;
581  %shl = shl i64 %val, 31
582  %trunc = trunc i64 %shl to i32
583  ret i32 %trunc
584}
585
586define i32 @trunc_shl_nsw_31_i32_i64(i64 %val) {
587; CHECK-LABEL: @trunc_shl_nsw_31_i32_i64(
588; CHECK-NEXT:    [[VAL_TR:%.*]] = trunc i64 [[VAL:%.*]] to i32
589; CHECK-NEXT:    [[TRUNC:%.*]] = shl i32 [[VAL_TR]], 31
590; CHECK-NEXT:    ret i32 [[TRUNC]]
591;
592  %shl = shl nsw i64 %val, 31
593  %trunc = trunc i64 %shl to i32
594  ret i32 %trunc
595}
596
597define i32 @trunc_shl_nuw_31_i32_i64(i64 %val) {
598; CHECK-LABEL: @trunc_shl_nuw_31_i32_i64(
599; CHECK-NEXT:    [[VAL_TR:%.*]] = trunc i64 [[VAL:%.*]] to i32
600; CHECK-NEXT:    [[TRUNC:%.*]] = shl i32 [[VAL_TR]], 31
601; CHECK-NEXT:    ret i32 [[TRUNC]]
602;
603  %shl = shl nuw i64 %val, 31
604  %trunc = trunc i64 %shl to i32
605  ret i32 %trunc
606}
607
608define i32 @trunc_shl_nsw_nuw_31_i32_i64(i64 %val) {
609; CHECK-LABEL: @trunc_shl_nsw_nuw_31_i32_i64(
610; CHECK-NEXT:    [[VAL_TR:%.*]] = trunc i64 [[VAL:%.*]] to i32
611; CHECK-NEXT:    [[TRUNC:%.*]] = shl i32 [[VAL_TR]], 31
612; CHECK-NEXT:    ret i32 [[TRUNC]]
613;
614  %shl = shl nsw nuw i64 %val, 31
615  %trunc = trunc i64 %shl to i32
616  ret i32 %trunc
617}
618
619define i16 @trunc_shl_15_i16_i64(i64 %val) {
620; CHECK-LABEL: @trunc_shl_15_i16_i64(
621; CHECK-NEXT:    [[VAL_TR:%.*]] = trunc i64 [[VAL:%.*]] to i16
622; CHECK-NEXT:    [[TRUNC:%.*]] = shl i16 [[VAL_TR]], 15
623; CHECK-NEXT:    ret i16 [[TRUNC]]
624;
625  %shl = shl i64 %val, 15
626  %trunc = trunc i64 %shl to i16
627  ret i16 %trunc
628}
629
630define i16 @trunc_shl_15_i16_i32(i32 %val) {
631; CHECK-LABEL: @trunc_shl_15_i16_i32(
632; CHECK-NEXT:    [[VAL_TR:%.*]] = trunc i32 [[VAL:%.*]] to i16
633; CHECK-NEXT:    [[TRUNC:%.*]] = shl i16 [[VAL_TR]], 15
634; CHECK-NEXT:    ret i16 [[TRUNC]]
635;
636  %shl = shl i32 %val, 15
637  %trunc = trunc i32 %shl to i16
638  ret i16 %trunc
639}
640
641define i8 @trunc_shl_7_i8_i64(i64 %val) {
642; CHECK-LABEL: @trunc_shl_7_i8_i64(
643; CHECK-NEXT:    [[VAL_TR:%.*]] = trunc i64 [[VAL:%.*]] to i8
644; CHECK-NEXT:    [[TRUNC:%.*]] = shl i8 [[VAL_TR]], 7
645; CHECK-NEXT:    ret i8 [[TRUNC]]
646;
647  %shl = shl i64 %val, 7
648  %trunc = trunc i64 %shl to i8
649  ret i8 %trunc
650}
651
652define i2 @trunc_shl_1_i2_i64(i64 %val) {
653; CHECK-LABEL: @trunc_shl_1_i2_i64(
654; CHECK-NEXT:    [[SHL:%.*]] = shl i64 [[VAL:%.*]], 1
655; CHECK-NEXT:    [[TRUNC:%.*]] = trunc i64 [[SHL]] to i2
656; CHECK-NEXT:    ret i2 [[TRUNC]]
657;
658  %shl = shl i64 %val, 1
659  %trunc = trunc i64 %shl to i2
660  ret i2 %trunc
661}
662
663define i32 @trunc_shl_1_i32_i64(i64 %val) {
664; CHECK-LABEL: @trunc_shl_1_i32_i64(
665; CHECK-NEXT:    [[VAL_TR:%.*]] = trunc i64 [[VAL:%.*]] to i32
666; CHECK-NEXT:    [[TRUNC:%.*]] = shl i32 [[VAL_TR]], 1
667; CHECK-NEXT:    ret i32 [[TRUNC]]
668;
669  %shl = shl i64 %val, 1
670  %trunc = trunc i64 %shl to i32
671  ret i32 %trunc
672}
673
674define i32 @trunc_shl_16_i32_i64(i64 %val) {
675; CHECK-LABEL: @trunc_shl_16_i32_i64(
676; CHECK-NEXT:    [[VAL_TR:%.*]] = trunc i64 [[VAL:%.*]] to i32
677; CHECK-NEXT:    [[TRUNC:%.*]] = shl i32 [[VAL_TR]], 16
678; CHECK-NEXT:    ret i32 [[TRUNC]]
679;
680  %shl = shl i64 %val, 16
681  %trunc = trunc i64 %shl to i32
682  ret i32 %trunc
683}
684
685define i32 @trunc_shl_33_i32_i64(i64 %val) {
686; CHECK-LABEL: @trunc_shl_33_i32_i64(
687; CHECK-NEXT:    ret i32 0
688;
689  %shl = shl i64 %val, 33
690  %trunc = trunc i64 %shl to i32
691  ret i32 %trunc
692}
693
694define i32 @trunc_shl_32_i32_i64(i64 %val) {
695; CHECK-LABEL: @trunc_shl_32_i32_i64(
696; CHECK-NEXT:    ret i32 0
697;
698  %shl = shl i64 %val, 32
699  %trunc = trunc i64 %shl to i32
700  ret i32 %trunc
701}
702
703; Should be able to handle vectors
704define <2 x i32> @trunc_shl_16_v2i32_v2i64(<2 x i64> %val) {
705; CHECK-LABEL: @trunc_shl_16_v2i32_v2i64(
706; CHECK-NEXT:    [[VAL_TR:%.*]] = trunc <2 x i64> [[VAL:%.*]] to <2 x i32>
707; CHECK-NEXT:    [[TRUNC:%.*]] = shl <2 x i32> [[VAL_TR]], splat (i32 16)
708; CHECK-NEXT:    ret <2 x i32> [[TRUNC]]
709;
710  %shl = shl <2 x i64> %val, <i64 16, i64 16>
711  %trunc = trunc <2 x i64> %shl to <2 x i32>
712  ret <2 x i32> %trunc
713}
714
715define <2 x i32> @trunc_shl_nosplat_v2i32_v2i64(<2 x i64> %val) {
716; CHECK-LABEL: @trunc_shl_nosplat_v2i32_v2i64(
717; CHECK-NEXT:    [[VAL_TR:%.*]] = trunc <2 x i64> [[VAL:%.*]] to <2 x i32>
718; CHECK-NEXT:    [[TRUNC:%.*]] = shl <2 x i32> [[VAL_TR]], <i32 15, i32 16>
719; CHECK-NEXT:    ret <2 x i32> [[TRUNC]]
720;
721  %shl = shl <2 x i64> %val, <i64 15, i64 16>
722  %trunc = trunc <2 x i64> %shl to <2 x i32>
723  ret <2 x i32> %trunc
724}
725
726define void @trunc_shl_31_i32_i64_multi_use(i64 %val, ptr addrspace(1) %ptr0, ptr addrspace(1) %ptr1) {
727; CHECK-LABEL: @trunc_shl_31_i32_i64_multi_use(
728; CHECK-NEXT:    [[SHL:%.*]] = shl i64 [[VAL:%.*]], 31
729; CHECK-NEXT:    [[TRUNC:%.*]] = trunc i64 [[SHL]] to i32
730; CHECK-NEXT:    store volatile i32 [[TRUNC]], ptr addrspace(1) [[PTR0:%.*]], align 4
731; CHECK-NEXT:    store volatile i64 [[SHL]], ptr addrspace(1) [[PTR1:%.*]], align 8
732; CHECK-NEXT:    ret void
733;
734  %shl = shl i64 %val, 31
735  %trunc = trunc i64 %shl to i32
736  store volatile i32 %trunc, ptr addrspace(1) %ptr0
737  store volatile i64 %shl, ptr addrspace(1) %ptr1
738  ret void
739}
740
741define i32 @trunc_shl_lshr_infloop(i64 %arg) {
742; CHECK-LABEL: @trunc_shl_lshr_infloop(
743; CHECK-NEXT:    [[ARG_TR:%.*]] = trunc i64 [[ARG:%.*]] to i32
744; CHECK-NEXT:    [[TMP1:%.*]] = shl i32 [[ARG_TR]], 1
745; CHECK-NEXT:    [[C:%.*]] = and i32 [[TMP1]], -4
746; CHECK-NEXT:    ret i32 [[C]]
747;
748  %A = lshr i64 %arg, 1
749  %B = shl i64 %A, 2
750  %C = trunc i64 %B to i32
751  ret i32 %C
752}
753
754define <2 x i32> @trunc_shl_v2i32_v2i64_uniform(<2 x i64> %val) {
755; CHECK-LABEL: @trunc_shl_v2i32_v2i64_uniform(
756; CHECK-NEXT:    [[VAL_TR:%.*]] = trunc <2 x i64> [[VAL:%.*]] to <2 x i32>
757; CHECK-NEXT:    [[TRUNC:%.*]] = shl <2 x i32> [[VAL_TR]], splat (i32 31)
758; CHECK-NEXT:    ret <2 x i32> [[TRUNC]]
759;
760  %shl = shl <2 x i64> %val, <i64 31, i64 31>
761  %trunc = trunc <2 x i64> %shl to <2 x i32>
762  ret <2 x i32> %trunc
763}
764
765define <2 x i32> @trunc_shl_v2i32_v2i64_poison(<2 x i64> %val) {
766; CHECK-LABEL: @trunc_shl_v2i32_v2i64_poison(
767; CHECK-NEXT:    [[VAL_TR:%.*]] = trunc <2 x i64> [[VAL:%.*]] to <2 x i32>
768; CHECK-NEXT:    [[TRUNC:%.*]] = shl <2 x i32> [[VAL_TR]], <i32 31, i32 poison>
769; CHECK-NEXT:    ret <2 x i32> [[TRUNC]]
770;
771  %shl = shl <2 x i64> %val, <i64 31, i64 poison>
772  %trunc = trunc <2 x i64> %shl to <2 x i32>
773  ret <2 x i32> %trunc
774}
775
776define <2 x i32> @trunc_shl_v2i32_v2i64_nonuniform(<2 x i64> %val) {
777; CHECK-LABEL: @trunc_shl_v2i32_v2i64_nonuniform(
778; CHECK-NEXT:    [[VAL_TR:%.*]] = trunc <2 x i64> [[VAL:%.*]] to <2 x i32>
779; CHECK-NEXT:    [[TRUNC:%.*]] = shl <2 x i32> [[VAL_TR]], <i32 31, i32 12>
780; CHECK-NEXT:    ret <2 x i32> [[TRUNC]]
781;
782  %shl = shl <2 x i64> %val, <i64 31, i64 12>
783  %trunc = trunc <2 x i64> %shl to <2 x i32>
784  ret <2 x i32> %trunc
785}
786
787define <2 x i32> @trunc_shl_v2i32_v2i64_outofrange(<2 x i64> %val) {
788; CHECK-LABEL: @trunc_shl_v2i32_v2i64_outofrange(
789; CHECK-NEXT:    [[SHL:%.*]] = shl <2 x i64> [[VAL:%.*]], <i64 31, i64 33>
790; CHECK-NEXT:    [[TRUNC:%.*]] = trunc <2 x i64> [[SHL]] to <2 x i32>
791; CHECK-NEXT:    ret <2 x i32> [[TRUNC]]
792;
793  %shl = shl <2 x i64> %val, <i64 31, i64 33>
794  %trunc = trunc <2 x i64> %shl to <2 x i32>
795  ret <2 x i32> %trunc
796}
797
798define i32 @trunc_shl_ashr_infloop(i64 %arg) {
799; CHECK-LABEL: @trunc_shl_ashr_infloop(
800; CHECK-NEXT:    [[TMP1:%.*]] = lshr i64 [[ARG:%.*]], 1
801; CHECK-NEXT:    [[TMP2:%.*]] = trunc i64 [[TMP1]] to i32
802; CHECK-NEXT:    [[C:%.*]] = and i32 [[TMP2]], -4
803; CHECK-NEXT:    ret i32 [[C]]
804;
805  %A = ashr i64 %arg, 3
806  %B = shl i64 %A, 2
807  %C = trunc i64 %B to i32
808  ret i32 %C
809}
810
811define i32 @trunc_shl_shl_infloop(i64 %arg) {
812; CHECK-LABEL: @trunc_shl_shl_infloop(
813; CHECK-NEXT:    [[ARG_TR:%.*]] = trunc i64 [[ARG:%.*]] to i32
814; CHECK-NEXT:    [[C:%.*]] = shl i32 [[ARG_TR]], 3
815; CHECK-NEXT:    ret i32 [[C]]
816;
817  %A = shl i64 %arg, 1
818  %B = shl i64 %A, 2
819  %C = trunc i64 %B to i32
820  ret i32 %C
821}
822
823define i32 @trunc_shl_lshr_var(i64 %arg, i64 %val) {
824; CHECK-LABEL: @trunc_shl_lshr_var(
825; CHECK-NEXT:    [[A:%.*]] = lshr i64 [[ARG:%.*]], [[VAL:%.*]]
826; CHECK-NEXT:    [[A_TR:%.*]] = trunc i64 [[A]] to i32
827; CHECK-NEXT:    [[C:%.*]] = shl i32 [[A_TR]], 2
828; CHECK-NEXT:    ret i32 [[C]]
829;
830  %A = lshr i64 %arg, %val
831  %B = shl i64 %A, 2
832  %C = trunc i64 %B to i32
833  ret i32 %C
834}
835
836define i32 @trunc_shl_ashr_var(i64 %arg, i64 %val) {
837; CHECK-LABEL: @trunc_shl_ashr_var(
838; CHECK-NEXT:    [[A:%.*]] = ashr i64 [[ARG:%.*]], [[VAL:%.*]]
839; CHECK-NEXT:    [[A_TR:%.*]] = trunc i64 [[A]] to i32
840; CHECK-NEXT:    [[C:%.*]] = shl i32 [[A_TR]], 2
841; CHECK-NEXT:    ret i32 [[C]]
842;
843  %A = ashr i64 %arg, %val
844  %B = shl i64 %A, 2
845  %C = trunc i64 %B to i32
846  ret i32 %C
847}
848
849define i32 @trunc_shl_shl_var(i64 %arg, i64 %val) {
850; CHECK-LABEL: @trunc_shl_shl_var(
851; CHECK-NEXT:    [[A:%.*]] = shl i64 [[ARG:%.*]], [[VAL:%.*]]
852; CHECK-NEXT:    [[A_TR:%.*]] = trunc i64 [[A]] to i32
853; CHECK-NEXT:    [[C:%.*]] = shl i32 [[A_TR]], 2
854; CHECK-NEXT:    ret i32 [[C]]
855;
856  %A = shl i64 %arg, %val
857  %B = shl i64 %A, 2
858  %C = trunc i64 %B to i32
859  ret i32 %C
860}
861
862define <8 x i16> @trunc_shl_v8i15_v8i32_15(<8 x i32> %a) {
863; CHECK-LABEL: @trunc_shl_v8i15_v8i32_15(
864; CHECK-NEXT:    [[A_TR:%.*]] = trunc <8 x i32> [[A:%.*]] to <8 x i16>
865; CHECK-NEXT:    [[CONV:%.*]] = shl <8 x i16> [[A_TR]], splat (i16 15)
866; CHECK-NEXT:    ret <8 x i16> [[CONV]]
867;
868  %shl = shl <8 x i32> %a, <i32 15, i32 15, i32 15, i32 15, i32 15, i32 15, i32 15, i32 15>
869  %conv = trunc <8 x i32> %shl to <8 x i16>
870  ret <8 x i16> %conv
871}
872
873define <8 x i16> @trunc_shl_v8i16_v8i32_16(<8 x i32> %a) {
874; CHECK-LABEL: @trunc_shl_v8i16_v8i32_16(
875; CHECK-NEXT:    ret <8 x i16> zeroinitializer
876;
877  %shl = shl <8 x i32> %a, <i32 16, i32 16, i32 16, i32 16, i32 16, i32 16, i32 16, i32 16>
878  %conv = trunc <8 x i32> %shl to <8 x i16>
879  ret <8 x i16> %conv
880}
881
882define <8 x i16> @trunc_shl_v8i16_v8i32_17(<8 x i32> %a) {
883; CHECK-LABEL: @trunc_shl_v8i16_v8i32_17(
884; CHECK-NEXT:    ret <8 x i16> zeroinitializer
885;
886  %shl = shl <8 x i32> %a, <i32 17, i32 17, i32 17, i32 17, i32 17, i32 17, i32 17, i32 17>
887  %conv = trunc <8 x i32> %shl to <8 x i16>
888  ret <8 x i16> %conv
889}
890
891define <8 x i16> @trunc_shl_v8i16_v8i32_4(<8 x i32> %a) {
892; CHECK-LABEL: @trunc_shl_v8i16_v8i32_4(
893; CHECK-NEXT:    [[A_TR:%.*]] = trunc <8 x i32> [[A:%.*]] to <8 x i16>
894; CHECK-NEXT:    [[CONV:%.*]] = shl <8 x i16> [[A_TR]], splat (i16 4)
895; CHECK-NEXT:    ret <8 x i16> [[CONV]]
896;
897  %shl = shl <8 x i32> %a, <i32 4, i32 4, i32 4, i32 4, i32 4, i32 4, i32 4, i32 4>
898  %conv = trunc <8 x i32> %shl to <8 x i16>
899  ret <8 x i16> %conv
900}
901
902; Although the mask is the same value, we don't create a shuffle for types that the backend may not be able to handle:
903; trunc (shuffle X, C, Mask) --> shuffle (trunc X), C', Mask
904
905define <4 x i8> @wide_shuf(<4 x i32> %x) {
906; CHECK-LABEL: @wide_shuf(
907; CHECK-NEXT:    [[SHUF:%.*]] = shufflevector <4 x i32> [[X:%.*]], <4 x i32> <i32 poison, i32 3634, i32 90, i32 poison>, <4 x i32> <i32 1, i32 5, i32 6, i32 2>
908; CHECK-NEXT:    [[TRUNC:%.*]] = trunc <4 x i32> [[SHUF]] to <4 x i8>
909; CHECK-NEXT:    ret <4 x i8> [[TRUNC]]
910;
911  %shuf = shufflevector <4 x i32> %x, <4 x i32> <i32 35, i32 3634, i32 90, i32 -1>, <4 x i32> <i32 1, i32 5, i32 6, i32 2>
912  %trunc = trunc <4 x i32> %shuf to <4 x i8>
913  ret <4 x i8> %trunc
914}
915
916; trunc (shuffle X, poison, SplatMask) --> shuffle (trunc X), poison, SplatMask
917
918define <4 x i8> @wide_splat1(<4 x i32> %x) {
919; CHECK-LABEL: @wide_splat1(
920; CHECK-NEXT:    [[TMP1:%.*]] = trunc <4 x i32> [[X:%.*]] to <4 x i8>
921; CHECK-NEXT:    [[TRUNC:%.*]] = shufflevector <4 x i8> [[TMP1]], <4 x i8> poison, <4 x i32> <i32 2, i32 2, i32 2, i32 2>
922; CHECK-NEXT:    ret <4 x i8> [[TRUNC]]
923;
924  %shuf = shufflevector <4 x i32> %x, <4 x i32> poison, <4 x i32> <i32 2, i32 2, i32 2, i32 2>
925  %trunc = trunc <4 x i32> %shuf to <4 x i8>
926  ret <4 x i8> %trunc
927}
928
929; Test weird types.
930; trunc (shuffle X, poison, SplatMask) --> shuffle (trunc X), poison, SplatMask
931
932define <3 x i31> @wide_splat2(<3 x i33> %x) {
933; CHECK-LABEL: @wide_splat2(
934; CHECK-NEXT:    [[TMP1:%.*]] = trunc <3 x i33> [[X:%.*]] to <3 x i31>
935; CHECK-NEXT:    [[TRUNC:%.*]] = shufflevector <3 x i31> [[TMP1]], <3 x i31> poison, <3 x i32> <i32 1, i32 1, i32 1>
936; CHECK-NEXT:    ret <3 x i31> [[TRUNC]]
937;
938  %shuf = shufflevector <3 x i33> %x, <3 x i33> poison, <3 x i32> <i32 1, i32 1, i32 1>
939  %trunc = trunc <3 x i33> %shuf to <3 x i31>
940  ret <3 x i31> %trunc
941}
942
943; FIXME:
944; trunc (shuffle X, poison, SplatMask) --> shuffle (trunc X), poison, SplatMask
945; A mask with poison elements should still be considered a splat mask.
946
947define <3 x i31> @wide_splat3(<3 x i33> %x) {
948; CHECK-LABEL: @wide_splat3(
949; CHECK-NEXT:    [[SHUF:%.*]] = shufflevector <3 x i33> [[X:%.*]], <3 x i33> poison, <3 x i32> <i32 poison, i32 1, i32 1>
950; CHECK-NEXT:    [[TRUNC:%.*]] = trunc <3 x i33> [[SHUF]] to <3 x i31>
951; CHECK-NEXT:    ret <3 x i31> [[TRUNC]]
952;
953  %shuf = shufflevector <3 x i33> %x, <3 x i33> poison, <3 x i32> <i32 poison, i32 1, i32 1>
954  %trunc = trunc <3 x i33> %shuf to <3 x i31>
955  ret <3 x i31> %trunc
956}
957
958; TODO: The shuffle extends the length of the input vector. Should we shrink this?
959
960define <8 x i8> @wide_lengthening_splat(<4 x i16> %v) {
961; CHECK-LABEL: @wide_lengthening_splat(
962; CHECK-NEXT:    [[SHUF:%.*]] = shufflevector <4 x i16> [[V:%.*]], <4 x i16> poison, <8 x i32> zeroinitializer
963; CHECK-NEXT:    [[TR:%.*]] = trunc <8 x i16> [[SHUF]] to <8 x i8>
964; CHECK-NEXT:    ret <8 x i8> [[TR]]
965;
966  %shuf = shufflevector <4 x i16> %v, <4 x i16> %v, <8 x i32> zeroinitializer
967  %tr = trunc <8 x i16> %shuf to <8 x i8>
968  ret <8 x i8> %tr
969}
970
971define <2 x i8> @narrow_add_vec_constant(<2 x i32> %x) {
972; CHECK-LABEL: @narrow_add_vec_constant(
973; CHECK-NEXT:    [[TMP1:%.*]] = trunc <2 x i32> [[X:%.*]] to <2 x i8>
974; CHECK-NEXT:    [[TR:%.*]] = add <2 x i8> [[TMP1]], <i8 0, i8 127>
975; CHECK-NEXT:    ret <2 x i8> [[TR]]
976;
977  %add = add <2 x i32> %x, <i32 256, i32 -129>
978  %tr = trunc <2 x i32> %add to <2 x i8>
979  ret <2 x i8> %tr
980}
981
982define <2 x i8> @narrow_mul_vec_constant(<2 x i32> %x) {
983; CHECK-LABEL: @narrow_mul_vec_constant(
984; CHECK-NEXT:    [[TMP1:%.*]] = trunc <2 x i32> [[X:%.*]] to <2 x i8>
985; CHECK-NEXT:    [[TR:%.*]] = mul <2 x i8> [[TMP1]], <i8 0, i8 127>
986; CHECK-NEXT:    ret <2 x i8> [[TR]]
987;
988  %add = mul <2 x i32> %x, <i32 256, i32 -129>
989  %tr = trunc <2 x i32> %add to <2 x i8>
990  ret <2 x i8> %tr
991}
992
993define <2 x i8> @narrow_sub_vec_constant(<2 x i32> %x) {
994; CHECK-LABEL: @narrow_sub_vec_constant(
995; CHECK-NEXT:    [[TMP1:%.*]] = trunc <2 x i32> [[X:%.*]] to <2 x i8>
996; CHECK-NEXT:    [[TR:%.*]] = sub <2 x i8> <i8 0, i8 127>, [[TMP1]]
997; CHECK-NEXT:    ret <2 x i8> [[TR]]
998;
999  %sub = sub <2 x i32> <i32 256, i32 -129>, %x
1000  %tr = trunc <2 x i32> %sub to <2 x i8>
1001  ret <2 x i8> %tr
1002}
1003
1004; If the select is narrowed based on the target's datalayout, we allow more optimizations.
1005
1006define i16 @PR44545(i32 %t0, i32 %data) {
1007; CHECK-LABEL: @PR44545(
1008; CHECK-NEXT:    [[ISZERO:%.*]] = icmp eq i32 [[DATA:%.*]], 0
1009; CHECK-NEXT:    [[TMP1:%.*]] = trunc i32 [[T0:%.*]] to i16
1010; CHECK-NEXT:    [[SUB:%.*]] = select i1 [[ISZERO]], i16 -1, i16 [[TMP1]]
1011; CHECK-NEXT:    ret i16 [[SUB]]
1012;
1013  %t1 = add nuw nsw i32 %t0, 1
1014  %iszero = icmp eq i32 %data, 0
1015  %ffs = select i1 %iszero, i32 0, i32 %t1
1016  %cast = trunc i32 %ffs to i16
1017  %sub = add nsw i16 %cast, -1
1018  ret i16 %sub
1019}
1020