xref: /llvm-project/llvm/test/Transforms/InstCombine/trunc-extractelement-inseltpoison.ll (revision 795c24c6fb4f9635c912f4084fa9339ea068c3d5)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -passes=instcombine -S -data-layout="e" | FileCheck %s --check-prefixes=ANY,LE
3; RUN: opt < %s -passes=instcombine -S -data-layout="E" | FileCheck %s --check-prefixes=ANY,BE
4
5define i32 @shrinkExtractElt_i64_to_i32_0(<3 x i64> %x) {
6; LE-LABEL: @shrinkExtractElt_i64_to_i32_0(
7; LE-NEXT:    [[TMP1:%.*]] = bitcast <3 x i64> [[X:%.*]] to <6 x i32>
8; LE-NEXT:    [[T:%.*]] = extractelement <6 x i32> [[TMP1]], i64 0
9; LE-NEXT:    ret i32 [[T]]
10;
11; BE-LABEL: @shrinkExtractElt_i64_to_i32_0(
12; BE-NEXT:    [[TMP1:%.*]] = bitcast <3 x i64> [[X:%.*]] to <6 x i32>
13; BE-NEXT:    [[T:%.*]] = extractelement <6 x i32> [[TMP1]], i64 1
14; BE-NEXT:    ret i32 [[T]]
15;
16  %e = extractelement <3 x i64> %x, i32 0
17  %t = trunc i64 %e to i32
18  ret i32 %t
19}
20
21define i32 @shrinkShiftExtractElt_i64_to_i32_0(<3 x i64> %x) {
22; LE-LABEL: @shrinkShiftExtractElt_i64_to_i32_0(
23; LE-NEXT:    [[TMP1:%.*]] = bitcast <3 x i64> [[X:%.*]] to <6 x i32>
24; LE-NEXT:    [[T:%.*]] = extractelement <6 x i32> [[TMP1]], i64 1
25; LE-NEXT:    ret i32 [[T]]
26;
27; BE-LABEL: @shrinkShiftExtractElt_i64_to_i32_0(
28; BE-NEXT:    [[TMP1:%.*]] = bitcast <3 x i64> [[X:%.*]] to <6 x i32>
29; BE-NEXT:    [[T:%.*]] = extractelement <6 x i32> [[TMP1]], i64 0
30; BE-NEXT:    ret i32 [[T]]
31;
32  %e = extractelement <3 x i64> %x, i32 0
33  %s = lshr i64 %e, 32
34  %t = trunc i64 %s to i32
35  ret i32 %t
36}
37
38define i32 @vscale_shrinkExtractElt_i64_to_i32_0(<vscale x 3 x i64> %x) {
39; LE-LABEL: @vscale_shrinkExtractElt_i64_to_i32_0(
40; LE-NEXT:    [[TMP1:%.*]] = bitcast <vscale x 3 x i64> [[X:%.*]] to <vscale x 6 x i32>
41; LE-NEXT:    [[T:%.*]] = extractelement <vscale x 6 x i32> [[TMP1]], i64 0
42; LE-NEXT:    ret i32 [[T]]
43;
44; BE-LABEL: @vscale_shrinkExtractElt_i64_to_i32_0(
45; BE-NEXT:    [[TMP1:%.*]] = bitcast <vscale x 3 x i64> [[X:%.*]] to <vscale x 6 x i32>
46; BE-NEXT:    [[T:%.*]] = extractelement <vscale x 6 x i32> [[TMP1]], i64 1
47; BE-NEXT:    ret i32 [[T]]
48;
49  %e = extractelement <vscale x 3 x i64> %x, i32 0
50  %t = trunc i64 %e to i32
51  ret i32 %t
52}
53
54define i32 @vscale_shrinkShiftExtractElt_i64_to_i32_0(<vscale x 3 x i64> %x) {
55; LE-LABEL: @vscale_shrinkShiftExtractElt_i64_to_i32_0(
56; LE-NEXT:    [[TMP1:%.*]] = bitcast <vscale x 3 x i64> [[X:%.*]] to <vscale x 6 x i32>
57; LE-NEXT:    [[T:%.*]] = extractelement <vscale x 6 x i32> [[TMP1]], i64 1
58; LE-NEXT:    ret i32 [[T]]
59;
60; BE-LABEL: @vscale_shrinkShiftExtractElt_i64_to_i32_0(
61; BE-NEXT:    [[TMP1:%.*]] = bitcast <vscale x 3 x i64> [[X:%.*]] to <vscale x 6 x i32>
62; BE-NEXT:    [[T:%.*]] = extractelement <vscale x 6 x i32> [[TMP1]], i64 0
63; BE-NEXT:    ret i32 [[T]]
64;
65  %e = extractelement <vscale x 3 x i64> %x, i32 0
66  %s = lshr i64 %e, 32
67  %t = trunc i64 %s to i32
68  ret i32 %t
69}
70
71define i32 @shrinkExtractElt_i64_to_i32_1(<3 x i64> %x) {
72; LE-LABEL: @shrinkExtractElt_i64_to_i32_1(
73; LE-NEXT:    [[TMP1:%.*]] = bitcast <3 x i64> [[X:%.*]] to <6 x i32>
74; LE-NEXT:    [[T:%.*]] = extractelement <6 x i32> [[TMP1]], i64 2
75; LE-NEXT:    ret i32 [[T]]
76;
77; BE-LABEL: @shrinkExtractElt_i64_to_i32_1(
78; BE-NEXT:    [[TMP1:%.*]] = bitcast <3 x i64> [[X:%.*]] to <6 x i32>
79; BE-NEXT:    [[T:%.*]] = extractelement <6 x i32> [[TMP1]], i64 3
80; BE-NEXT:    ret i32 [[T]]
81;
82  %e = extractelement <3 x i64> %x, i32 1
83  %t = trunc i64 %e to i32
84  ret i32 %t
85}
86
87define i32 @shrinkExtractElt_i64_to_i32_2(<3 x i64> %x) {
88; LE-LABEL: @shrinkExtractElt_i64_to_i32_2(
89; LE-NEXT:    [[TMP1:%.*]] = bitcast <3 x i64> [[X:%.*]] to <6 x i32>
90; LE-NEXT:    [[T:%.*]] = extractelement <6 x i32> [[TMP1]], i64 4
91; LE-NEXT:    ret i32 [[T]]
92;
93; BE-LABEL: @shrinkExtractElt_i64_to_i32_2(
94; BE-NEXT:    [[TMP1:%.*]] = bitcast <3 x i64> [[X:%.*]] to <6 x i32>
95; BE-NEXT:    [[T:%.*]] = extractelement <6 x i32> [[TMP1]], i64 5
96; BE-NEXT:    ret i32 [[T]]
97;
98  %e = extractelement <3 x i64> %x, i32 2
99  %t = trunc i64 %e to i32
100  ret i32 %t
101}
102
103define i16 @shrinkExtractElt_i64_to_i16_0(<3 x i64> %x) {
104; LE-LABEL: @shrinkExtractElt_i64_to_i16_0(
105; LE-NEXT:    [[TMP1:%.*]] = bitcast <3 x i64> [[X:%.*]] to <12 x i16>
106; LE-NEXT:    [[T:%.*]] = extractelement <12 x i16> [[TMP1]], i64 0
107; LE-NEXT:    ret i16 [[T]]
108;
109; BE-LABEL: @shrinkExtractElt_i64_to_i16_0(
110; BE-NEXT:    [[TMP1:%.*]] = bitcast <3 x i64> [[X:%.*]] to <12 x i16>
111; BE-NEXT:    [[T:%.*]] = extractelement <12 x i16> [[TMP1]], i64 3
112; BE-NEXT:    ret i16 [[T]]
113;
114  %e = extractelement <3 x i64> %x, i16 0
115  %t = trunc i64 %e to i16
116  ret i16 %t
117}
118
119define i16 @shrinkShiftExtractElt_i64_to_i16_0(<3 x i64> %x) {
120; LE-LABEL: @shrinkShiftExtractElt_i64_to_i16_0(
121; LE-NEXT:    [[TMP1:%.*]] = bitcast <3 x i64> [[X:%.*]] to <12 x i16>
122; LE-NEXT:    [[T:%.*]] = extractelement <12 x i16> [[TMP1]], i64 3
123; LE-NEXT:    ret i16 [[T]]
124;
125; BE-LABEL: @shrinkShiftExtractElt_i64_to_i16_0(
126; BE-NEXT:    [[TMP1:%.*]] = bitcast <3 x i64> [[X:%.*]] to <12 x i16>
127; BE-NEXT:    [[T:%.*]] = extractelement <12 x i16> [[TMP1]], i64 0
128; BE-NEXT:    ret i16 [[T]]
129;
130  %e = extractelement <3 x i64> %x, i16 0
131  %s = ashr i64 %e, 48
132  %t = trunc i64 %s to i16
133  ret i16 %t
134}
135
136define i16 @shrinkExtractElt_i64_to_i16_1(<3 x i64> %x) {
137; LE-LABEL: @shrinkExtractElt_i64_to_i16_1(
138; LE-NEXT:    [[TMP1:%.*]] = bitcast <3 x i64> [[X:%.*]] to <12 x i16>
139; LE-NEXT:    [[T:%.*]] = extractelement <12 x i16> [[TMP1]], i64 4
140; LE-NEXT:    ret i16 [[T]]
141;
142; BE-LABEL: @shrinkExtractElt_i64_to_i16_1(
143; BE-NEXT:    [[TMP1:%.*]] = bitcast <3 x i64> [[X:%.*]] to <12 x i16>
144; BE-NEXT:    [[T:%.*]] = extractelement <12 x i16> [[TMP1]], i64 7
145; BE-NEXT:    ret i16 [[T]]
146;
147  %e = extractelement <3 x i64> %x, i16 1
148  %t = trunc i64 %e to i16
149  ret i16 %t
150}
151
152define i16 @shrinkExtractElt_i64_to_i16_2(<3 x i64> %x) {
153; LE-LABEL: @shrinkExtractElt_i64_to_i16_2(
154; LE-NEXT:    [[TMP1:%.*]] = bitcast <3 x i64> [[X:%.*]] to <12 x i16>
155; LE-NEXT:    [[T:%.*]] = extractelement <12 x i16> [[TMP1]], i64 8
156; LE-NEXT:    ret i16 [[T]]
157;
158; BE-LABEL: @shrinkExtractElt_i64_to_i16_2(
159; BE-NEXT:    [[TMP1:%.*]] = bitcast <3 x i64> [[X:%.*]] to <12 x i16>
160; BE-NEXT:    [[T:%.*]] = extractelement <12 x i16> [[TMP1]], i64 11
161; BE-NEXT:    ret i16 [[T]]
162;
163  %e = extractelement <3 x i64> %x, i16 2
164  %t = trunc i64 %e to i16
165  ret i16 %t
166}
167
168; Crazy types may be ok.
169define i11 @shrinkExtractElt_i33_to_11_2(<3 x i33> %x) {
170; LE-LABEL: @shrinkExtractElt_i33_to_11_2(
171; LE-NEXT:    [[TMP1:%.*]] = bitcast <3 x i33> [[X:%.*]] to <9 x i11>
172; LE-NEXT:    [[T:%.*]] = extractelement <9 x i11> [[TMP1]], i64 6
173; LE-NEXT:    ret i11 [[T]]
174;
175; BE-LABEL: @shrinkExtractElt_i33_to_11_2(
176; BE-NEXT:    [[TMP1:%.*]] = bitcast <3 x i33> [[X:%.*]] to <9 x i11>
177; BE-NEXT:    [[T:%.*]] = extractelement <9 x i11> [[TMP1]], i64 8
178; BE-NEXT:    ret i11 [[T]]
179;
180  %e = extractelement <3 x i33> %x, i16 2
181  %t = trunc i33 %e to i11
182  ret i11 %t
183}
184
185; Do not optimize if it would result in an invalid bitcast instruction.
186define i13 @shrinkExtractElt_i67_to_i13_2(<3 x i67> %x) {
187; ANY-LABEL: @shrinkExtractElt_i67_to_i13_2(
188; ANY-NEXT:    [[E:%.*]] = extractelement <3 x i67> [[X:%.*]], i64 2
189; ANY-NEXT:    [[T:%.*]] = trunc i67 [[E]] to i13
190; ANY-NEXT:    ret i13 [[T]]
191;
192  %e = extractelement <3 x i67> %x, i459 2
193  %t = trunc i67 %e to i13
194  ret i13 %t
195}
196
197; Do not optimize if the bitcast instruction would be valid, but the
198; transform would be wrong.
199define i30 @shrinkExtractElt_i40_to_i30_1(<3 x i40> %x) {
200; ANY-LABEL: @shrinkExtractElt_i40_to_i30_1(
201; ANY-NEXT:    [[E:%.*]] = extractelement <3 x i40> [[X:%.*]], i64 1
202; ANY-NEXT:    [[T:%.*]] = trunc i40 [[E]] to i30
203; ANY-NEXT:    ret i30 [[T]]
204;
205  %e = extractelement <3 x i40> %x, i32 1
206  %t = trunc i40 %e to i30
207  ret i30 %t
208}
209
210; Do not optimize if the shift amount isn't a whole number of truncated bits.
211define i16 @shrinkShiftExtractElt_i64_to_i16_0_badshift(<3 x i64> %x) {
212; ANY-LABEL: @shrinkShiftExtractElt_i64_to_i16_0_badshift(
213; ANY-NEXT:    [[E:%.*]] = extractelement <3 x i64> [[X:%.*]], i64 0
214; ANY-NEXT:    [[S:%.*]] = lshr i64 [[E]], 31
215; ANY-NEXT:    [[T:%.*]] = trunc i64 [[S]] to i16
216; ANY-NEXT:    ret i16 [[T]]
217;
218  %e = extractelement <3 x i64> %x, i16 0
219  %s = lshr i64 %e, 31
220  %t = trunc i64 %s to i16
221  ret i16 %t
222}
223
224; Do not canonicalize if that would increase the instruction count.
225declare void @use(i64)
226define i16 @shrinkExtractElt_i64_to_i16_2_extra_use(<3 x i64> %x) {
227; ANY-LABEL: @shrinkExtractElt_i64_to_i16_2_extra_use(
228; ANY-NEXT:    [[E:%.*]] = extractelement <3 x i64> [[X:%.*]], i64 2
229; ANY-NEXT:    call void @use(i64 [[E]])
230; ANY-NEXT:    [[T:%.*]] = trunc i64 [[E]] to i16
231; ANY-NEXT:    ret i16 [[T]]
232;
233  %e = extractelement <3 x i64> %x, i64 2
234  call void @use(i64 %e)
235  %t = trunc i64 %e to i16
236  ret i16 %t
237}
238
239; Do not canonicalize if that would increase the instruction count.
240define i16 @shrinkShiftExtractElt_i64_to_i16_2_extra_shift_use(<3 x i64> %x) {
241; ANY-LABEL: @shrinkShiftExtractElt_i64_to_i16_2_extra_shift_use(
242; ANY-NEXT:    [[E:%.*]] = extractelement <3 x i64> [[X:%.*]], i64 2
243; ANY-NEXT:    [[S:%.*]] = lshr i64 [[E]], 48
244; ANY-NEXT:    call void @use(i64 [[S]])
245; ANY-NEXT:    [[T:%.*]] = trunc nuw i64 [[S]] to i16
246; ANY-NEXT:    ret i16 [[T]]
247;
248  %e = extractelement <3 x i64> %x, i64 2
249  %s = lshr i64 %e, 48
250  call void @use(i64 %s)
251  %t = trunc i64 %s to i16
252  ret i16 %t
253}
254
255; OK to reuse the extract if we remove the shift+trunc.
256define i16 @shrinkShiftExtractElt_i64_to_i16_2_extra_extract_use(<3 x i64> %x) {
257; LE-LABEL: @shrinkShiftExtractElt_i64_to_i16_2_extra_extract_use(
258; LE-NEXT:    [[E:%.*]] = extractelement <3 x i64> [[X:%.*]], i64 2
259; LE-NEXT:    call void @use(i64 [[E]])
260; LE-NEXT:    [[TMP1:%.*]] = bitcast <3 x i64> [[X]] to <12 x i16>
261; LE-NEXT:    [[T:%.*]] = extractelement <12 x i16> [[TMP1]], i64 11
262; LE-NEXT:    ret i16 [[T]]
263;
264; BE-LABEL: @shrinkShiftExtractElt_i64_to_i16_2_extra_extract_use(
265; BE-NEXT:    [[E:%.*]] = extractelement <3 x i64> [[X:%.*]], i64 2
266; BE-NEXT:    call void @use(i64 [[E]])
267; BE-NEXT:    [[TMP1:%.*]] = bitcast <3 x i64> [[X]] to <12 x i16>
268; BE-NEXT:    [[T:%.*]] = extractelement <12 x i16> [[TMP1]], i64 8
269; BE-NEXT:    ret i16 [[T]]
270;
271  %e = extractelement <3 x i64> %x, i64 2
272  call void @use(i64 %e)
273  %s = lshr i64 %e, 48
274  %t = trunc i64 %s to i16
275  ret i16 %t
276}
277
278; Check to ensure PR45314 remains fixed.
279define <4 x i64> @PR45314(<4 x i64> %x) {
280; LE-LABEL: @PR45314(
281; LE-NEXT:    [[TMP1:%.*]] = bitcast <4 x i64> [[X:%.*]] to <8 x i32>
282; LE-NEXT:    [[S:%.*]] = shufflevector <8 x i32> [[TMP1]], <8 x i32> poison, <8 x i32> zeroinitializer
283; LE-NEXT:    [[B:%.*]] = bitcast <8 x i32> [[S]] to <4 x i64>
284; LE-NEXT:    ret <4 x i64> [[B]]
285;
286; BE-LABEL: @PR45314(
287; BE-NEXT:    [[TMP1:%.*]] = bitcast <4 x i64> [[X:%.*]] to <8 x i32>
288; BE-NEXT:    [[S:%.*]] = shufflevector <8 x i32> [[TMP1]], <8 x i32> poison, <8 x i32> <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1>
289; BE-NEXT:    [[B:%.*]] = bitcast <8 x i32> [[S]] to <4 x i64>
290; BE-NEXT:    ret <4 x i64> [[B]]
291;
292  %e = extractelement <4 x i64> %x, i32 0
293  %t = trunc i64 %e to i32
294  %i = insertelement <8 x i32> poison, i32 %t, i32 0
295  %s = shufflevector <8 x i32> %i, <8 x i32> poison, <8 x i32> zeroinitializer
296  %b = bitcast <8 x i32> %s to <4 x i64>
297  ret <4 x i64> %b
298}
299