1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -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]], <i64 15, 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_undef(<2 x i64> %a) {
53; CHECK-LABEL: @test1_vec_undef(
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 0>
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 undef>
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]], <i64 36, i64 36>
86; CHECK-NEXT:    [[D:%.*]] = ashr exact <2 x i64> [[D1]], <i64 36, 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 <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_undef(<2 x i64> %a) {
115; CHECK-LABEL: @test2_vec_undef(
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 undef>
118; CHECK-NEXT:    [[D:%.*]] = ashr <2 x i64> [[D1]], <i64 36, i64 undef>
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 undef>
124  %q = ashr <2 x i32> %c, <i32 4, i32 undef>
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 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:%.*]], <i32 8, i32 8>
233; CHECK-NEXT:    [[C:%.*]] = or <2 x i32> [[TMP1]], <i32 -8388608, 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 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 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]], <i64 32, i64 32>
276; CHECK-NEXT:    [[F:%.*]] = or <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 <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_undef(<2 x i32> %A, <2 x i32> %B) {
304; CHECK-LABEL: @test8_vec_undef(
305; CHECK-NEXT:    [[C:%.*]] = zext <2 x i32> [[A:%.*]] to <2 x i128>
306; CHECK-NEXT:    [[D:%.*]] = zext <2 x i32> [[B:%.*]] to <2 x i128>
307; CHECK-NEXT:    [[E:%.*]] = shl <2 x i128> [[D]], <i128 32, i128 undef>
308; CHECK-NEXT:    [[F:%.*]] = or <2 x i128> [[E]], [[C]]
309; CHECK-NEXT:    [[G:%.*]] = trunc <2 x i128> [[F]] to <2 x i64>
310; CHECK-NEXT:    ret <2 x i64> [[G]]
311;
312  %C = zext <2 x i32> %A to <2 x i128>
313  %D = zext <2 x i32> %B to <2 x i128>
314  %E = shl <2 x i128> %D, <i128 32, i128 undef>
315  %F = or <2 x i128> %E, %C
316  %G = trunc <2 x i128> %F to <2 x i64>
317  ret <2 x i64> %G
318}
319
320define i8 @test9(i32 %X) {
321; CHECK-LABEL: @test9(
322; CHECK-NEXT:    [[TMP1:%.*]] = trunc i32 [[X:%.*]] to i8
323; CHECK-NEXT:    [[Z:%.*]] = and i8 [[TMP1]], 42
324; CHECK-NEXT:    ret i8 [[Z]]
325;
326  %Y = and i32 %X, 42
327  %Z = trunc i32 %Y to i8
328  ret i8 %Z
329}
330
331; rdar://8808586
332define i8 @test10(i32 %X) {
333; CHECK-LABEL: @test10(
334; CHECK-NEXT:    [[Y:%.*]] = trunc i32 [[X:%.*]] to i8
335; CHECK-NEXT:    [[Z:%.*]] = and i8 [[Y]], 42
336; CHECK-NEXT:    ret i8 [[Z]]
337;
338  %Y = trunc i32 %X to i8
339  %Z = and i8 %Y, 42
340  ret i8 %Z
341}
342
343define i64 @test11(i32 %A, i32 %B) {
344; CHECK-LABEL: @test11(
345; CHECK-NEXT:    [[C:%.*]] = zext i32 [[A:%.*]] to i64
346; CHECK-NEXT:    [[TMP1:%.*]] = and i32 [[B:%.*]], 31
347; CHECK-NEXT:    [[E:%.*]] = zext i32 [[TMP1]] to i64
348; CHECK-NEXT:    [[F:%.*]] = shl i64 [[C]], [[E]]
349; CHECK-NEXT:    ret i64 [[F]]
350;
351  %C = zext i32 %A to i128
352  %D = zext i32 %B to i128
353  %E = and i128 %D, 31
354  %F = shl i128 %C, %E
355  %G = trunc i128 %F to i64
356  ret i64 %G
357}
358
359define <2 x i64> @test11_vec(<2 x i32> %A, <2 x i32> %B) {
360; CHECK-LABEL: @test11_vec(
361; CHECK-NEXT:    [[C:%.*]] = zext <2 x i32> [[A:%.*]] to <2 x i64>
362; CHECK-NEXT:    [[TMP1:%.*]] = and <2 x i32> [[B:%.*]], <i32 31, i32 31>
363; CHECK-NEXT:    [[E:%.*]] = zext <2 x i32> [[TMP1]] to <2 x i64>
364; CHECK-NEXT:    [[F:%.*]] = shl <2 x i64> [[C]], [[E]]
365; CHECK-NEXT:    ret <2 x i64> [[F]]
366;
367  %C = zext <2 x i32> %A to <2 x i128>
368  %D = zext <2 x i32> %B to <2 x i128>
369  %E = and <2 x i128> %D, <i128 31, i128 31>
370  %F = shl <2 x i128> %C, %E
371  %G = trunc <2 x i128> %F to <2 x i64>
372  ret <2 x i64> %G
373}
374
375define <2 x i64> @test11_vec_nonuniform(<2 x i32> %A, <2 x i32> %B) {
376; CHECK-LABEL: @test11_vec_nonuniform(
377; CHECK-NEXT:    [[C:%.*]] = zext <2 x i32> [[A:%.*]] to <2 x i64>
378; CHECK-NEXT:    [[TMP1:%.*]] = and <2 x i32> [[B:%.*]], <i32 31, i32 15>
379; CHECK-NEXT:    [[E:%.*]] = zext <2 x i32> [[TMP1]] to <2 x i64>
380; CHECK-NEXT:    [[F:%.*]] = shl <2 x i64> [[C]], [[E]]
381; CHECK-NEXT:    ret <2 x i64> [[F]]
382;
383  %C = zext <2 x i32> %A to <2 x i128>
384  %D = zext <2 x i32> %B to <2 x i128>
385  %E = and <2 x i128> %D, <i128 31, i128 15>
386  %F = shl <2 x i128> %C, %E
387  %G = trunc <2 x i128> %F to <2 x i64>
388  ret <2 x i64> %G
389}
390
391define <2 x i64> @test11_vec_undef(<2 x i32> %A, <2 x i32> %B) {
392; CHECK-LABEL: @test11_vec_undef(
393; CHECK-NEXT:    [[C:%.*]] = zext <2 x i32> [[A:%.*]] to <2 x i128>
394; CHECK-NEXT:    [[D:%.*]] = zext <2 x i32> [[B:%.*]] to <2 x i128>
395; CHECK-NEXT:    [[E:%.*]] = and <2 x i128> [[D]], <i128 31, i128 undef>
396; CHECK-NEXT:    [[F:%.*]] = shl <2 x i128> [[C]], [[E]]
397; CHECK-NEXT:    [[G:%.*]] = trunc <2 x i128> [[F]] to <2 x i64>
398; CHECK-NEXT:    ret <2 x i64> [[G]]
399;
400  %C = zext <2 x i32> %A to <2 x i128>
401  %D = zext <2 x i32> %B to <2 x i128>
402  %E = and <2 x i128> %D, <i128 31, i128 undef>
403  %F = shl <2 x i128> %C, %E
404  %G = trunc <2 x i128> %F to <2 x i64>
405  ret <2 x i64> %G
406}
407
408define i64 @test12(i32 %A, i32 %B) {
409; CHECK-LABEL: @test12(
410; CHECK-NEXT:    [[C:%.*]] = zext i32 [[A:%.*]] to i64
411; CHECK-NEXT:    [[TMP1:%.*]] = and i32 [[B:%.*]], 31
412; CHECK-NEXT:    [[E:%.*]] = zext i32 [[TMP1]] to i64
413; CHECK-NEXT:    [[F:%.*]] = lshr i64 [[C]], [[E]]
414; CHECK-NEXT:    ret i64 [[F]]
415;
416  %C = zext i32 %A to i128
417  %D = zext i32 %B to i128
418  %E = and i128 %D, 31
419  %F = lshr i128 %C, %E
420  %G = trunc i128 %F to i64
421  ret i64 %G
422}
423
424define <2 x i64> @test12_vec(<2 x i32> %A, <2 x i32> %B) {
425; CHECK-LABEL: @test12_vec(
426; CHECK-NEXT:    [[C:%.*]] = zext <2 x i32> [[A:%.*]] to <2 x i64>
427; CHECK-NEXT:    [[TMP1:%.*]] = and <2 x i32> [[B:%.*]], <i32 31, i32 31>
428; CHECK-NEXT:    [[E:%.*]] = zext <2 x i32> [[TMP1]] to <2 x i64>
429; CHECK-NEXT:    [[F:%.*]] = lshr <2 x i64> [[C]], [[E]]
430; CHECK-NEXT:    ret <2 x i64> [[F]]
431;
432  %C = zext <2 x i32> %A to <2 x i128>
433  %D = zext <2 x i32> %B to <2 x i128>
434  %E = and <2 x i128> %D, <i128 31, i128 31>
435  %F = lshr <2 x i128> %C, %E
436  %G = trunc <2 x i128> %F to <2 x i64>
437  ret <2 x i64> %G
438}
439
440define <2 x i64> @test12_vec_nonuniform(<2 x i32> %A, <2 x i32> %B) {
441; CHECK-LABEL: @test12_vec_nonuniform(
442; CHECK-NEXT:    [[C:%.*]] = zext <2 x i32> [[A:%.*]] to <2 x i64>
443; CHECK-NEXT:    [[TMP1:%.*]] = and <2 x i32> [[B:%.*]], <i32 31, i32 15>
444; CHECK-NEXT:    [[E:%.*]] = zext <2 x i32> [[TMP1]] to <2 x i64>
445; CHECK-NEXT:    [[F:%.*]] = lshr <2 x i64> [[C]], [[E]]
446; CHECK-NEXT:    ret <2 x i64> [[F]]
447;
448  %C = zext <2 x i32> %A to <2 x i128>
449  %D = zext <2 x i32> %B to <2 x i128>
450  %E = and <2 x i128> %D, <i128 31, i128 15>
451  %F = lshr <2 x i128> %C, %E
452  %G = trunc <2 x i128> %F to <2 x i64>
453  ret <2 x i64> %G
454}
455
456define <2 x i64> @test12_vec_undef(<2 x i32> %A, <2 x i32> %B) {
457; CHECK-LABEL: @test12_vec_undef(
458; CHECK-NEXT:    [[C:%.*]] = zext <2 x i32> [[A:%.*]] to <2 x i128>
459; CHECK-NEXT:    [[D:%.*]] = zext <2 x i32> [[B:%.*]] to <2 x i128>
460; CHECK-NEXT:    [[E:%.*]] = and <2 x i128> [[D]], <i128 31, i128 undef>
461; CHECK-NEXT:    [[F:%.*]] = lshr <2 x i128> [[C]], [[E]]
462; CHECK-NEXT:    [[G:%.*]] = trunc <2 x i128> [[F]] to <2 x i64>
463; CHECK-NEXT:    ret <2 x i64> [[G]]
464;
465  %C = zext <2 x i32> %A to <2 x i128>
466  %D = zext <2 x i32> %B to <2 x i128>
467  %E = and <2 x i128> %D, <i128 31, i128 undef>
468  %F = lshr <2 x i128> %C, %E
469  %G = trunc <2 x i128> %F to <2 x i64>
470  ret <2 x i64> %G
471}
472
473define i64 @test13(i32 %A, i32 %B) {
474; CHECK-LABEL: @test13(
475; CHECK-NEXT:    [[C:%.*]] = sext i32 [[A:%.*]] to i64
476; CHECK-NEXT:    [[TMP1:%.*]] = and i32 [[B:%.*]], 31
477; CHECK-NEXT:    [[E:%.*]] = zext i32 [[TMP1]] to i64
478; CHECK-NEXT:    [[F:%.*]] = ashr i64 [[C]], [[E]]
479; CHECK-NEXT:    ret i64 [[F]]
480;
481  %C = sext i32 %A to i128
482  %D = zext i32 %B to i128
483  %E = and i128 %D, 31
484  %F = ashr i128 %C, %E
485  %G = trunc i128 %F to i64
486  ret i64 %G
487}
488
489define <2 x i64> @test13_vec(<2 x i32> %A, <2 x i32> %B) {
490; CHECK-LABEL: @test13_vec(
491; CHECK-NEXT:    [[C:%.*]] = sext <2 x i32> [[A:%.*]] to <2 x i64>
492; CHECK-NEXT:    [[TMP1:%.*]] = and <2 x i32> [[B:%.*]], <i32 31, i32 31>
493; CHECK-NEXT:    [[E:%.*]] = zext <2 x i32> [[TMP1]] to <2 x i64>
494; CHECK-NEXT:    [[F:%.*]] = ashr <2 x i64> [[C]], [[E]]
495; CHECK-NEXT:    ret <2 x i64> [[F]]
496;
497  %C = sext <2 x i32> %A to <2 x i128>
498  %D = zext <2 x i32> %B to <2 x i128>
499  %E = and <2 x i128> %D, <i128 31, i128 31>
500  %F = ashr <2 x i128> %C, %E
501  %G = trunc <2 x i128> %F to <2 x i64>
502  ret <2 x i64> %G
503}
504
505define <2 x i64> @test13_vec_nonuniform(<2 x i32> %A, <2 x i32> %B) {
506; CHECK-LABEL: @test13_vec_nonuniform(
507; CHECK-NEXT:    [[C:%.*]] = sext <2 x i32> [[A:%.*]] to <2 x i64>
508; CHECK-NEXT:    [[TMP1:%.*]] = and <2 x i32> [[B:%.*]], <i32 31, i32 15>
509; CHECK-NEXT:    [[E:%.*]] = zext <2 x i32> [[TMP1]] to <2 x i64>
510; CHECK-NEXT:    [[F:%.*]] = ashr <2 x i64> [[C]], [[E]]
511; CHECK-NEXT:    ret <2 x i64> [[F]]
512;
513  %C = sext <2 x i32> %A to <2 x i128>
514  %D = zext <2 x i32> %B to <2 x i128>
515  %E = and <2 x i128> %D, <i128 31, i128 15>
516  %F = ashr <2 x i128> %C, %E
517  %G = trunc <2 x i128> %F to <2 x i64>
518  ret <2 x i64> %G
519}
520
521define <2 x i64> @test13_vec_undef(<2 x i32> %A, <2 x i32> %B) {
522; CHECK-LABEL: @test13_vec_undef(
523; CHECK-NEXT:    [[C:%.*]] = sext <2 x i32> [[A:%.*]] to <2 x i128>
524; CHECK-NEXT:    [[D:%.*]] = zext <2 x i32> [[B:%.*]] to <2 x i128>
525; CHECK-NEXT:    [[E:%.*]] = and <2 x i128> [[D]], <i128 31, i128 undef>
526; CHECK-NEXT:    [[F:%.*]] = ashr <2 x i128> [[C]], [[E]]
527; CHECK-NEXT:    [[G:%.*]] = trunc <2 x i128> [[F]] to <2 x i64>
528; CHECK-NEXT:    ret <2 x i64> [[G]]
529;
530  %C = sext <2 x i32> %A to <2 x i128>
531  %D = zext <2 x i32> %B to <2 x i128>
532  %E = and <2 x i128> %D, <i128 31, i128 undef>
533  %F = ashr <2 x i128> %C, %E
534  %G = trunc <2 x i128> %F to <2 x i64>
535  ret <2 x i64> %G
536}
537
538; PR25543
539; https://llvm.org/bugs/show_bug.cgi?id=25543
540; This is an extractelement.
541
542define i32 @trunc_bitcast1(<4 x i32> %v) {
543; CHECK-LABEL: @trunc_bitcast1(
544; CHECK-NEXT:    [[EXT:%.*]] = extractelement <4 x i32> [[V:%.*]], i32 1
545; CHECK-NEXT:    ret i32 [[EXT]]
546;
547  %bc = bitcast <4 x i32> %v to i128
548  %shr = lshr i128 %bc, 32
549  %ext = trunc i128 %shr to i32
550  ret i32 %ext
551}
552
553; A bitcast may still be required.
554
555define i32 @trunc_bitcast2(<2 x i64> %v) {
556; CHECK-LABEL: @trunc_bitcast2(
557; CHECK-NEXT:    [[BC1:%.*]] = bitcast <2 x i64> [[V:%.*]] to <4 x i32>
558; CHECK-NEXT:    [[EXT:%.*]] = extractelement <4 x i32> [[BC1]], i32 2
559; CHECK-NEXT:    ret i32 [[EXT]]
560;
561  %bc = bitcast <2 x i64> %v to i128
562  %shr = lshr i128 %bc, 64
563  %ext = trunc i128 %shr to i32
564  ret i32 %ext
565}
566
567; The right shift is optional.
568
569define i32 @trunc_bitcast3(<4 x i32> %v) {
570; CHECK-LABEL: @trunc_bitcast3(
571; CHECK-NEXT:    [[EXT:%.*]] = extractelement <4 x i32> [[V:%.*]], i32 0
572; CHECK-NEXT:    ret i32 [[EXT]]
573;
574  %bc = bitcast <4 x i32> %v to i128
575  %ext = trunc i128 %bc to i32
576  ret i32 %ext
577}
578
579define i32 @trunc_shl_31_i32_i64(i64 %val) {
580; CHECK-LABEL: @trunc_shl_31_i32_i64(
581; CHECK-NEXT:    [[VAL_TR:%.*]] = trunc i64 [[VAL:%.*]] to i32
582; CHECK-NEXT:    [[TRUNC:%.*]] = shl i32 [[VAL_TR]], 31
583; CHECK-NEXT:    ret i32 [[TRUNC]]
584;
585  %shl = shl i64 %val, 31
586  %trunc = trunc i64 %shl to i32
587  ret i32 %trunc
588}
589
590define i32 @trunc_shl_nsw_31_i32_i64(i64 %val) {
591; CHECK-LABEL: @trunc_shl_nsw_31_i32_i64(
592; CHECK-NEXT:    [[VAL_TR:%.*]] = trunc i64 [[VAL:%.*]] to i32
593; CHECK-NEXT:    [[TRUNC:%.*]] = shl i32 [[VAL_TR]], 31
594; CHECK-NEXT:    ret i32 [[TRUNC]]
595;
596  %shl = shl nsw i64 %val, 31
597  %trunc = trunc i64 %shl to i32
598  ret i32 %trunc
599}
600
601define i32 @trunc_shl_nuw_31_i32_i64(i64 %val) {
602; CHECK-LABEL: @trunc_shl_nuw_31_i32_i64(
603; CHECK-NEXT:    [[VAL_TR:%.*]] = trunc i64 [[VAL:%.*]] to i32
604; CHECK-NEXT:    [[TRUNC:%.*]] = shl i32 [[VAL_TR]], 31
605; CHECK-NEXT:    ret i32 [[TRUNC]]
606;
607  %shl = shl nuw i64 %val, 31
608  %trunc = trunc i64 %shl to i32
609  ret i32 %trunc
610}
611
612define i32 @trunc_shl_nsw_nuw_31_i32_i64(i64 %val) {
613; CHECK-LABEL: @trunc_shl_nsw_nuw_31_i32_i64(
614; CHECK-NEXT:    [[VAL_TR:%.*]] = trunc i64 [[VAL:%.*]] to i32
615; CHECK-NEXT:    [[TRUNC:%.*]] = shl i32 [[VAL_TR]], 31
616; CHECK-NEXT:    ret i32 [[TRUNC]]
617;
618  %shl = shl nsw nuw i64 %val, 31
619  %trunc = trunc i64 %shl to i32
620  ret i32 %trunc
621}
622
623define i16 @trunc_shl_15_i16_i64(i64 %val) {
624; CHECK-LABEL: @trunc_shl_15_i16_i64(
625; CHECK-NEXT:    [[VAL_TR:%.*]] = trunc i64 [[VAL:%.*]] to i16
626; CHECK-NEXT:    [[TRUNC:%.*]] = shl i16 [[VAL_TR]], 15
627; CHECK-NEXT:    ret i16 [[TRUNC]]
628;
629  %shl = shl i64 %val, 15
630  %trunc = trunc i64 %shl to i16
631  ret i16 %trunc
632}
633
634define i16 @trunc_shl_15_i16_i32(i32 %val) {
635; CHECK-LABEL: @trunc_shl_15_i16_i32(
636; CHECK-NEXT:    [[VAL_TR:%.*]] = trunc i32 [[VAL:%.*]] to i16
637; CHECK-NEXT:    [[TRUNC:%.*]] = shl i16 [[VAL_TR]], 15
638; CHECK-NEXT:    ret i16 [[TRUNC]]
639;
640  %shl = shl i32 %val, 15
641  %trunc = trunc i32 %shl to i16
642  ret i16 %trunc
643}
644
645define i8 @trunc_shl_7_i8_i64(i64 %val) {
646; CHECK-LABEL: @trunc_shl_7_i8_i64(
647; CHECK-NEXT:    [[VAL_TR:%.*]] = trunc i64 [[VAL:%.*]] to i8
648; CHECK-NEXT:    [[TRUNC:%.*]] = shl i8 [[VAL_TR]], 7
649; CHECK-NEXT:    ret i8 [[TRUNC]]
650;
651  %shl = shl i64 %val, 7
652  %trunc = trunc i64 %shl to i8
653  ret i8 %trunc
654}
655
656define i2 @trunc_shl_1_i2_i64(i64 %val) {
657; CHECK-LABEL: @trunc_shl_1_i2_i64(
658; CHECK-NEXT:    [[SHL:%.*]] = shl i64 [[VAL:%.*]], 1
659; CHECK-NEXT:    [[TRUNC:%.*]] = trunc i64 [[SHL]] to i2
660; CHECK-NEXT:    ret i2 [[TRUNC]]
661;
662  %shl = shl i64 %val, 1
663  %trunc = trunc i64 %shl to i2
664  ret i2 %trunc
665}
666
667define i32 @trunc_shl_1_i32_i64(i64 %val) {
668; CHECK-LABEL: @trunc_shl_1_i32_i64(
669; CHECK-NEXT:    [[VAL_TR:%.*]] = trunc i64 [[VAL:%.*]] to i32
670; CHECK-NEXT:    [[TRUNC:%.*]] = shl i32 [[VAL_TR]], 1
671; CHECK-NEXT:    ret i32 [[TRUNC]]
672;
673  %shl = shl i64 %val, 1
674  %trunc = trunc i64 %shl to i32
675  ret i32 %trunc
676}
677
678define i32 @trunc_shl_16_i32_i64(i64 %val) {
679; CHECK-LABEL: @trunc_shl_16_i32_i64(
680; CHECK-NEXT:    [[VAL_TR:%.*]] = trunc i64 [[VAL:%.*]] to i32
681; CHECK-NEXT:    [[TRUNC:%.*]] = shl i32 [[VAL_TR]], 16
682; CHECK-NEXT:    ret i32 [[TRUNC]]
683;
684  %shl = shl i64 %val, 16
685  %trunc = trunc i64 %shl to i32
686  ret i32 %trunc
687}
688
689define i32 @trunc_shl_33_i32_i64(i64 %val) {
690; CHECK-LABEL: @trunc_shl_33_i32_i64(
691; CHECK-NEXT:    ret i32 0
692;
693  %shl = shl i64 %val, 33
694  %trunc = trunc i64 %shl to i32
695  ret i32 %trunc
696}
697
698define i32 @trunc_shl_32_i32_i64(i64 %val) {
699; CHECK-LABEL: @trunc_shl_32_i32_i64(
700; CHECK-NEXT:    ret i32 0
701;
702  %shl = shl i64 %val, 32
703  %trunc = trunc i64 %shl to i32
704  ret i32 %trunc
705}
706
707; Should be able to handle vectors
708define <2 x i32> @trunc_shl_16_v2i32_v2i64(<2 x i64> %val) {
709; CHECK-LABEL: @trunc_shl_16_v2i32_v2i64(
710; CHECK-NEXT:    [[VAL_TR:%.*]] = trunc <2 x i64> [[VAL:%.*]] to <2 x i32>
711; CHECK-NEXT:    [[TRUNC:%.*]] = shl <2 x i32> [[VAL_TR]], <i32 16, i32 16>
712; CHECK-NEXT:    ret <2 x i32> [[TRUNC]]
713;
714  %shl = shl <2 x i64> %val, <i64 16, i64 16>
715  %trunc = trunc <2 x i64> %shl to <2 x i32>
716  ret <2 x i32> %trunc
717}
718
719define <2 x i32> @trunc_shl_nosplat_v2i32_v2i64(<2 x i64> %val) {
720; CHECK-LABEL: @trunc_shl_nosplat_v2i32_v2i64(
721; CHECK-NEXT:    [[VAL_TR:%.*]] = trunc <2 x i64> [[VAL:%.*]] to <2 x i32>
722; CHECK-NEXT:    [[TRUNC:%.*]] = shl <2 x i32> [[VAL_TR]], <i32 15, i32 16>
723; CHECK-NEXT:    ret <2 x i32> [[TRUNC]]
724;
725  %shl = shl <2 x i64> %val, <i64 15, i64 16>
726  %trunc = trunc <2 x i64> %shl to <2 x i32>
727  ret <2 x i32> %trunc
728}
729
730define void @trunc_shl_31_i32_i64_multi_use(i64 %val, i32 addrspace(1)* %ptr0, i64 addrspace(1)* %ptr1) {
731; CHECK-LABEL: @trunc_shl_31_i32_i64_multi_use(
732; CHECK-NEXT:    [[SHL:%.*]] = shl i64 [[VAL:%.*]], 31
733; CHECK-NEXT:    [[TRUNC:%.*]] = trunc i64 [[SHL]] to i32
734; CHECK-NEXT:    store volatile i32 [[TRUNC]], i32 addrspace(1)* [[PTR0:%.*]], align 4
735; CHECK-NEXT:    store volatile i64 [[SHL]], i64 addrspace(1)* [[PTR1:%.*]], align 8
736; CHECK-NEXT:    ret void
737;
738  %shl = shl i64 %val, 31
739  %trunc = trunc i64 %shl to i32
740  store volatile i32 %trunc, i32 addrspace(1)* %ptr0
741  store volatile i64 %shl, i64 addrspace(1)* %ptr1
742  ret void
743}
744
745define i32 @trunc_shl_lshr_infloop(i64 %arg) {
746; CHECK-LABEL: @trunc_shl_lshr_infloop(
747; CHECK-NEXT:    [[ARG_TR:%.*]] = trunc i64 [[ARG:%.*]] to i32
748; CHECK-NEXT:    [[TMP1:%.*]] = shl i32 [[ARG_TR]], 1
749; CHECK-NEXT:    [[C:%.*]] = and i32 [[TMP1]], -4
750; CHECK-NEXT:    ret i32 [[C]]
751;
752  %A = lshr i64 %arg, 1
753  %B = shl i64 %A, 2
754  %C = trunc i64 %B to i32
755  ret i32 %C
756}
757
758define <2 x i32> @trunc_shl_v2i32_v2i64_uniform(<2 x i64> %val) {
759; CHECK-LABEL: @trunc_shl_v2i32_v2i64_uniform(
760; CHECK-NEXT:    [[VAL_TR:%.*]] = trunc <2 x i64> [[VAL:%.*]] to <2 x i32>
761; CHECK-NEXT:    [[TRUNC:%.*]] = shl <2 x i32> [[VAL_TR]], <i32 31, i32 31>
762; CHECK-NEXT:    ret <2 x i32> [[TRUNC]]
763;
764  %shl = shl <2 x i64> %val, <i64 31, i64 31>
765  %trunc = trunc <2 x i64> %shl to <2 x i32>
766  ret <2 x i32> %trunc
767}
768
769define <2 x i32> @trunc_shl_v2i32_v2i64_undef(<2 x i64> %val) {
770; CHECK-LABEL: @trunc_shl_v2i32_v2i64_undef(
771; CHECK-NEXT:    [[VAL_TR:%.*]] = trunc <2 x i64> [[VAL:%.*]] to <2 x i32>
772; CHECK-NEXT:    [[TRUNC:%.*]] = shl <2 x i32> [[VAL_TR]], <i32 31, i32 undef>
773; CHECK-NEXT:    ret <2 x i32> [[TRUNC]]
774;
775  %shl = shl <2 x i64> %val, <i64 31, i64 undef>
776  %trunc = trunc <2 x i64> %shl to <2 x i32>
777  ret <2 x i32> %trunc
778}
779
780define <2 x i32> @trunc_shl_v2i32_v2i64_nonuniform(<2 x i64> %val) {
781; CHECK-LABEL: @trunc_shl_v2i32_v2i64_nonuniform(
782; CHECK-NEXT:    [[VAL_TR:%.*]] = trunc <2 x i64> [[VAL:%.*]] to <2 x i32>
783; CHECK-NEXT:    [[TRUNC:%.*]] = shl <2 x i32> [[VAL_TR]], <i32 31, i32 12>
784; CHECK-NEXT:    ret <2 x i32> [[TRUNC]]
785;
786  %shl = shl <2 x i64> %val, <i64 31, i64 12>
787  %trunc = trunc <2 x i64> %shl to <2 x i32>
788  ret <2 x i32> %trunc
789}
790
791define <2 x i32> @trunc_shl_v2i32_v2i64_outofrange(<2 x i64> %val) {
792; CHECK-LABEL: @trunc_shl_v2i32_v2i64_outofrange(
793; CHECK-NEXT:    [[SHL:%.*]] = shl <2 x i64> [[VAL:%.*]], <i64 31, i64 33>
794; CHECK-NEXT:    [[TRUNC:%.*]] = trunc <2 x i64> [[SHL]] to <2 x i32>
795; CHECK-NEXT:    ret <2 x i32> [[TRUNC]]
796;
797  %shl = shl <2 x i64> %val, <i64 31, i64 33>
798  %trunc = trunc <2 x i64> %shl to <2 x i32>
799  ret <2 x i32> %trunc
800}
801
802define i32 @trunc_shl_ashr_infloop(i64 %arg) {
803; CHECK-LABEL: @trunc_shl_ashr_infloop(
804; CHECK-NEXT:    [[TMP1:%.*]] = lshr i64 [[ARG:%.*]], 1
805; CHECK-NEXT:    [[TMP2:%.*]] = trunc i64 [[TMP1]] to i32
806; CHECK-NEXT:    [[C:%.*]] = and i32 [[TMP2]], -4
807; CHECK-NEXT:    ret i32 [[C]]
808;
809  %A = ashr i64 %arg, 3
810  %B = shl i64 %A, 2
811  %C = trunc i64 %B to i32
812  ret i32 %C
813}
814
815define i32 @trunc_shl_shl_infloop(i64 %arg) {
816; CHECK-LABEL: @trunc_shl_shl_infloop(
817; CHECK-NEXT:    [[ARG_TR:%.*]] = trunc i64 [[ARG:%.*]] to i32
818; CHECK-NEXT:    [[C:%.*]] = shl i32 [[ARG_TR]], 3
819; CHECK-NEXT:    ret i32 [[C]]
820;
821  %A = shl i64 %arg, 1
822  %B = shl i64 %A, 2
823  %C = trunc i64 %B to i32
824  ret i32 %C
825}
826
827define i32 @trunc_shl_lshr_var(i64 %arg, i64 %val) {
828; CHECK-LABEL: @trunc_shl_lshr_var(
829; CHECK-NEXT:    [[A:%.*]] = lshr i64 [[ARG:%.*]], [[VAL:%.*]]
830; CHECK-NEXT:    [[A_TR:%.*]] = trunc i64 [[A]] to i32
831; CHECK-NEXT:    [[C:%.*]] = shl i32 [[A_TR]], 2
832; CHECK-NEXT:    ret i32 [[C]]
833;
834  %A = lshr i64 %arg, %val
835  %B = shl i64 %A, 2
836  %C = trunc i64 %B to i32
837  ret i32 %C
838}
839
840define i32 @trunc_shl_ashr_var(i64 %arg, i64 %val) {
841; CHECK-LABEL: @trunc_shl_ashr_var(
842; CHECK-NEXT:    [[A:%.*]] = ashr i64 [[ARG:%.*]], [[VAL:%.*]]
843; CHECK-NEXT:    [[A_TR:%.*]] = trunc i64 [[A]] to i32
844; CHECK-NEXT:    [[C:%.*]] = shl i32 [[A_TR]], 2
845; CHECK-NEXT:    ret i32 [[C]]
846;
847  %A = ashr i64 %arg, %val
848  %B = shl i64 %A, 2
849  %C = trunc i64 %B to i32
850  ret i32 %C
851}
852
853define i32 @trunc_shl_shl_var(i64 %arg, i64 %val) {
854; CHECK-LABEL: @trunc_shl_shl_var(
855; CHECK-NEXT:    [[A:%.*]] = shl i64 [[ARG:%.*]], [[VAL:%.*]]
856; CHECK-NEXT:    [[A_TR:%.*]] = trunc i64 [[A]] to i32
857; CHECK-NEXT:    [[C:%.*]] = shl i32 [[A_TR]], 2
858; CHECK-NEXT:    ret i32 [[C]]
859;
860  %A = shl i64 %arg, %val
861  %B = shl i64 %A, 2
862  %C = trunc i64 %B to i32
863  ret i32 %C
864}
865
866define <8 x i16> @trunc_shl_v8i15_v8i32_15(<8 x i32> %a) {
867; CHECK-LABEL: @trunc_shl_v8i15_v8i32_15(
868; CHECK-NEXT:    [[A_TR:%.*]] = trunc <8 x i32> [[A:%.*]] to <8 x i16>
869; CHECK-NEXT:    [[CONV:%.*]] = shl <8 x i16> [[A_TR]], <i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15>
870; CHECK-NEXT:    ret <8 x i16> [[CONV]]
871;
872  %shl = shl <8 x i32> %a, <i32 15, i32 15, i32 15, i32 15, i32 15, i32 15, i32 15, i32 15>
873  %conv = trunc <8 x i32> %shl to <8 x i16>
874  ret <8 x i16> %conv
875}
876
877define <8 x i16> @trunc_shl_v8i16_v8i32_16(<8 x i32> %a) {
878; CHECK-LABEL: @trunc_shl_v8i16_v8i32_16(
879; CHECK-NEXT:    ret <8 x i16> zeroinitializer
880;
881  %shl = shl <8 x i32> %a, <i32 16, i32 16, i32 16, i32 16, i32 16, i32 16, i32 16, i32 16>
882  %conv = trunc <8 x i32> %shl to <8 x i16>
883  ret <8 x i16> %conv
884}
885
886define <8 x i16> @trunc_shl_v8i16_v8i32_17(<8 x i32> %a) {
887; CHECK-LABEL: @trunc_shl_v8i16_v8i32_17(
888; CHECK-NEXT:    ret <8 x i16> zeroinitializer
889;
890  %shl = shl <8 x i32> %a, <i32 17, i32 17, i32 17, i32 17, i32 17, i32 17, i32 17, i32 17>
891  %conv = trunc <8 x i32> %shl to <8 x i16>
892  ret <8 x i16> %conv
893}
894
895define <8 x i16> @trunc_shl_v8i16_v8i32_4(<8 x i32> %a) {
896; CHECK-LABEL: @trunc_shl_v8i16_v8i32_4(
897; CHECK-NEXT:    [[A_TR:%.*]] = trunc <8 x i32> [[A:%.*]] to <8 x i16>
898; CHECK-NEXT:    [[CONV:%.*]] = shl <8 x i16> [[A_TR]], <i16 4, i16 4, i16 4, i16 4, i16 4, i16 4, i16 4, i16 4>
899; CHECK-NEXT:    ret <8 x i16> [[CONV]]
900;
901  %shl = shl <8 x i32> %a, <i32 4, i32 4, i32 4, i32 4, i32 4, i32 4, i32 4, i32 4>
902  %conv = trunc <8 x i32> %shl to <8 x i16>
903  ret <8 x i16> %conv
904}
905
906; Although the mask is the same value, we don't create a shuffle for types that the backend may not be able to handle:
907; trunc (shuffle X, C, Mask) --> shuffle (trunc X), C', Mask
908
909define <4 x i8> @wide_shuf(<4 x i32> %x) {
910; CHECK-LABEL: @wide_shuf(
911; CHECK-NEXT:    [[SHUF:%.*]] = shufflevector <4 x i32> [[X:%.*]], <4 x i32> <i32 undef, i32 3634, i32 90, i32 undef>, <4 x i32> <i32 1, i32 5, i32 6, i32 2>
912; CHECK-NEXT:    [[TRUNC:%.*]] = trunc <4 x i32> [[SHUF]] to <4 x i8>
913; CHECK-NEXT:    ret <4 x i8> [[TRUNC]]
914;
915  %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>
916  %trunc = trunc <4 x i32> %shuf to <4 x i8>
917  ret <4 x i8> %trunc
918}
919
920; trunc (shuffle X, undef, SplatMask) --> shuffle (trunc X), undef, SplatMask
921
922define <4 x i8> @wide_splat1(<4 x i32> %x) {
923; CHECK-LABEL: @wide_splat1(
924; CHECK-NEXT:    [[TMP1:%.*]] = trunc <4 x i32> [[X:%.*]] to <4 x i8>
925; CHECK-NEXT:    [[TRUNC:%.*]] = shufflevector <4 x i8> [[TMP1]], <4 x i8> undef, <4 x i32> <i32 2, i32 2, i32 2, i32 2>
926; CHECK-NEXT:    ret <4 x i8> [[TRUNC]]
927;
928  %shuf = shufflevector <4 x i32> %x, <4 x i32> undef, <4 x i32> <i32 2, i32 2, i32 2, i32 2>
929  %trunc = trunc <4 x i32> %shuf to <4 x i8>
930  ret <4 x i8> %trunc
931}
932
933; Test weird types.
934; trunc (shuffle X, undef, SplatMask) --> shuffle (trunc X), undef, SplatMask
935
936define <3 x i31> @wide_splat2(<3 x i33> %x) {
937; CHECK-LABEL: @wide_splat2(
938; CHECK-NEXT:    [[TMP1:%.*]] = trunc <3 x i33> [[X:%.*]] to <3 x i31>
939; CHECK-NEXT:    [[TRUNC:%.*]] = shufflevector <3 x i31> [[TMP1]], <3 x i31> undef, <3 x i32> <i32 1, i32 1, i32 1>
940; CHECK-NEXT:    ret <3 x i31> [[TRUNC]]
941;
942  %shuf = shufflevector <3 x i33> %x, <3 x i33> undef, <3 x i32> <i32 1, i32 1, i32 1>
943  %trunc = trunc <3 x i33> %shuf to <3 x i31>
944  ret <3 x i31> %trunc
945}
946
947; FIXME:
948; trunc (shuffle X, undef, SplatMask) --> shuffle (trunc X), undef, SplatMask
949; A mask with undef elements should still be considered a splat mask.
950
951define <3 x i31> @wide_splat3(<3 x i33> %x) {
952; CHECK-LABEL: @wide_splat3(
953; CHECK-NEXT:    [[SHUF:%.*]] = shufflevector <3 x i33> [[X:%.*]], <3 x i33> undef, <3 x i32> <i32 undef, i32 1, i32 1>
954; CHECK-NEXT:    [[TRUNC:%.*]] = trunc <3 x i33> [[SHUF]] to <3 x i31>
955; CHECK-NEXT:    ret <3 x i31> [[TRUNC]]
956;
957  %shuf = shufflevector <3 x i33> %x, <3 x i33> undef, <3 x i32> <i32 undef, i32 1, i32 1>
958  %trunc = trunc <3 x i33> %shuf to <3 x i31>
959  ret <3 x i31> %trunc
960}
961
962; TODO: The shuffle extends the length of the input vector. Should we shrink this?
963
964define <8 x i8> @wide_lengthening_splat(<4 x i16> %v) {
965; CHECK-LABEL: @wide_lengthening_splat(
966; CHECK-NEXT:    [[SHUF:%.*]] = shufflevector <4 x i16> [[V:%.*]], <4 x i16> undef, <8 x i32> zeroinitializer
967; CHECK-NEXT:    [[TR:%.*]] = trunc <8 x i16> [[SHUF]] to <8 x i8>
968; CHECK-NEXT:    ret <8 x i8> [[TR]]
969;
970  %shuf = shufflevector <4 x i16> %v, <4 x i16> %v, <8 x i32> zeroinitializer
971  %tr = trunc <8 x i16> %shuf to <8 x i8>
972  ret <8 x i8> %tr
973}
974
975define <2 x i8> @narrow_add_vec_constant(<2 x i32> %x) {
976; CHECK-LABEL: @narrow_add_vec_constant(
977; CHECK-NEXT:    [[TMP1:%.*]] = trunc <2 x i32> [[X:%.*]] to <2 x i8>
978; CHECK-NEXT:    [[TR:%.*]] = add <2 x i8> [[TMP1]], <i8 0, i8 127>
979; CHECK-NEXT:    ret <2 x i8> [[TR]]
980;
981  %add = add <2 x i32> %x, <i32 256, i32 -129>
982  %tr = trunc <2 x i32> %add to <2 x i8>
983  ret <2 x i8> %tr
984}
985
986define <2 x i8> @narrow_mul_vec_constant(<2 x i32> %x) {
987; CHECK-LABEL: @narrow_mul_vec_constant(
988; CHECK-NEXT:    [[TMP1:%.*]] = trunc <2 x i32> [[X:%.*]] to <2 x i8>
989; CHECK-NEXT:    [[TR:%.*]] = mul <2 x i8> [[TMP1]], <i8 0, i8 127>
990; CHECK-NEXT:    ret <2 x i8> [[TR]]
991;
992  %add = mul <2 x i32> %x, <i32 256, i32 -129>
993  %tr = trunc <2 x i32> %add to <2 x i8>
994  ret <2 x i8> %tr
995}
996
997define <2 x i8> @narrow_sub_vec_constant(<2 x i32> %x) {
998; CHECK-LABEL: @narrow_sub_vec_constant(
999; CHECK-NEXT:    [[TMP1:%.*]] = trunc <2 x i32> [[X:%.*]] to <2 x i8>
1000; CHECK-NEXT:    [[TR:%.*]] = sub <2 x i8> <i8 0, i8 127>, [[TMP1]]
1001; CHECK-NEXT:    ret <2 x i8> [[TR]]
1002;
1003  %sub = sub <2 x i32> <i32 256, i32 -129>, %x
1004  %tr = trunc <2 x i32> %sub to <2 x i8>
1005  ret <2 x i8> %tr
1006}
1007
1008; If the select is narrowed based on the target's datalayout, we allow more optimizations.
1009
1010define i16 @PR44545(i32 %t0, i32 %data) {
1011; CHECK-LABEL: @PR44545(
1012; CHECK-NEXT:    [[ISZERO:%.*]] = icmp eq i32 [[DATA:%.*]], 0
1013; CHECK-NEXT:    [[TMP1:%.*]] = trunc i32 [[T0:%.*]] to i16
1014; CHECK-NEXT:    [[SUB:%.*]] = select i1 [[ISZERO]], i16 -1, i16 [[TMP1]]
1015; CHECK-NEXT:    ret i16 [[SUB]]
1016;
1017  %t1 = add nuw nsw i32 %t0, 1
1018  %iszero = icmp eq i32 %data, 0
1019  %ffs = select i1 %iszero, i32 0, i32 %t1
1020  %cast = trunc i32 %ffs to i16
1021  %sub = add nsw i16 %cast, -1
1022  ret i16 %sub
1023}
1024