• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -instcombine -S -data-layout="e" | FileCheck %s --check-prefixes=ANY,LE
3; RUN: opt < %s -instcombine -S -data-layout="E" | FileCheck %s --check-prefixes=ANY,BE
4
5define i32 @extractelement_out_of_range(<2 x i32> %x) {
6; ANY-LABEL: @extractelement_out_of_range(
7; ANY-NEXT:    ret i32 undef
8;
9  %E1 = extractelement <2 x i32> %x, i8 16
10  ret i32 %E1
11}
12
13define i32 @extractelement_type_out_of_range(<2 x i32> %x) {
14; ANY-LABEL: @extractelement_type_out_of_range(
15; ANY-NEXT:    [[E1:%.*]] = extractelement <2 x i32> [[X:%.*]], i128 0
16; ANY-NEXT:    ret i32 [[E1]]
17;
18  %E1 = extractelement <2 x i32> %x, i128 0
19  ret i32 %E1
20}
21
22define i32 @bitcasted_inselt_equal_num_elts(float %f) {
23; ANY-LABEL: @bitcasted_inselt_equal_num_elts(
24; ANY-NEXT:    [[R:%.*]] = bitcast float [[F:%.*]] to i32
25; ANY-NEXT:    ret i32 [[R]]
26;
27  %vf = insertelement <4 x float> undef, float %f, i32 0
28  %vi = bitcast <4 x float> %vf to <4 x i32>
29  %r = extractelement <4 x i32> %vi, i32 0
30  ret i32 %r
31}
32
33define i64 @test2(i64 %in) {
34; ANY-LABEL: @test2(
35; ANY-NEXT:    ret i64 [[IN:%.*]]
36;
37  %vec = insertelement <8 x i64> undef, i64 %in, i32 0
38  %splat = shufflevector <8 x i64> %vec, <8 x i64> undef, <8 x i32> zeroinitializer
39  %add = add <8 x i64> %splat, <i64 0, i64 1, i64 2, i64 3, i64 4, i64 5, i64 6, i64 7>
40  %r = extractelement <8 x i64> %add, i32 0
41  ret i64 %r
42}
43
44define i32 @bitcasted_inselt_wide_source_zero_elt(i64 %x) {
45; LE-LABEL: @bitcasted_inselt_wide_source_zero_elt(
46; LE-NEXT:    [[R:%.*]] = trunc i64 [[X:%.*]] to i32
47; LE-NEXT:    ret i32 [[R]]
48;
49; BE-LABEL: @bitcasted_inselt_wide_source_zero_elt(
50; BE-NEXT:    [[TMP1:%.*]] = lshr i64 [[X:%.*]], 32
51; BE-NEXT:    [[R:%.*]] = trunc i64 [[TMP1]] to i32
52; BE-NEXT:    ret i32 [[R]]
53;
54  %i = insertelement <2 x i64> zeroinitializer, i64 %x, i32 0
55  %b = bitcast <2 x i64> %i to <4 x i32>
56  %r = extractelement <4 x i32> %b, i32 0
57  ret i32 %r
58}
59
60define i16 @bitcasted_inselt_wide_source_modulo_elt(i64 %x) {
61; LE-LABEL: @bitcasted_inselt_wide_source_modulo_elt(
62; LE-NEXT:    [[R:%.*]] = trunc i64 [[X:%.*]] to i16
63; LE-NEXT:    ret i16 [[R]]
64;
65; BE-LABEL: @bitcasted_inselt_wide_source_modulo_elt(
66; BE-NEXT:    [[TMP1:%.*]] = lshr i64 [[X:%.*]], 48
67; BE-NEXT:    [[R:%.*]] = trunc i64 [[TMP1]] to i16
68; BE-NEXT:    ret i16 [[R]]
69;
70  %i = insertelement <2 x i64> undef, i64 %x, i32 1
71  %b = bitcast <2 x i64> %i to <8 x i16>
72  %r = extractelement <8 x i16> %b, i32 4
73  ret i16 %r
74}
75
76define i32 @bitcasted_inselt_wide_source_not_modulo_elt(i64 %x) {
77; LE-LABEL: @bitcasted_inselt_wide_source_not_modulo_elt(
78; LE-NEXT:    [[TMP1:%.*]] = lshr i64 [[X:%.*]], 32
79; LE-NEXT:    [[R:%.*]] = trunc i64 [[TMP1]] to i32
80; LE-NEXT:    ret i32 [[R]]
81;
82; BE-LABEL: @bitcasted_inselt_wide_source_not_modulo_elt(
83; BE-NEXT:    [[R:%.*]] = trunc i64 [[X:%.*]] to i32
84; BE-NEXT:    ret i32 [[R]]
85;
86  %i = insertelement <2 x i64> undef, i64 %x, i32 0
87  %b = bitcast <2 x i64> %i to <4 x i32>
88  %r = extractelement <4 x i32> %b, i32 1
89  ret i32 %r
90}
91
92define i8 @bitcasted_inselt_wide_source_not_modulo_elt_not_half(i32 %x) {
93; LE-LABEL: @bitcasted_inselt_wide_source_not_modulo_elt_not_half(
94; LE-NEXT:    [[TMP1:%.*]] = lshr i32 [[X:%.*]], 16
95; LE-NEXT:    [[R:%.*]] = trunc i32 [[TMP1]] to i8
96; LE-NEXT:    ret i8 [[R]]
97;
98; BE-LABEL: @bitcasted_inselt_wide_source_not_modulo_elt_not_half(
99; BE-NEXT:    [[TMP1:%.*]] = lshr i32 [[X:%.*]], 8
100; BE-NEXT:    [[R:%.*]] = trunc i32 [[TMP1]] to i8
101; BE-NEXT:    ret i8 [[R]]
102;
103  %i = insertelement <2 x i32> undef, i32 %x, i32 0
104  %b = bitcast <2 x i32> %i to <8 x i8>
105  %r = extractelement <8 x i8> %b, i32 2
106  ret i8 %r
107}
108
109define i3 @bitcasted_inselt_wide_source_not_modulo_elt_not_half_weird_types(i15 %x) {
110; LE-LABEL: @bitcasted_inselt_wide_source_not_modulo_elt_not_half_weird_types(
111; LE-NEXT:    [[TMP1:%.*]] = lshr i15 [[X:%.*]], 3
112; LE-NEXT:    [[R:%.*]] = trunc i15 [[TMP1]] to i3
113; LE-NEXT:    ret i3 [[R]]
114;
115; BE-LABEL: @bitcasted_inselt_wide_source_not_modulo_elt_not_half_weird_types(
116; BE-NEXT:    [[TMP1:%.*]] = lshr i15 [[X:%.*]], 9
117; BE-NEXT:    [[R:%.*]] = trunc i15 [[TMP1]] to i3
118; BE-NEXT:    ret i3 [[R]]
119;
120  %i = insertelement <3 x i15> undef, i15 %x, i32 0
121  %b = bitcast <3 x i15> %i to <15 x i3>
122  %r = extractelement <15 x i3> %b, i32 1
123  ret i3 %r
124}
125
126; Negative test for the above fold, but we can remove the insert here.
127
128define i8 @bitcasted_inselt_wide_source_wrong_insert(<2 x i32> %v, i32 %x) {
129; ANY-LABEL: @bitcasted_inselt_wide_source_wrong_insert(
130; ANY-NEXT:    [[B:%.*]] = bitcast <2 x i32> [[V:%.*]] to <8 x i8>
131; ANY-NEXT:    [[R:%.*]] = extractelement <8 x i8> [[B]], i32 2
132; ANY-NEXT:    ret i8 [[R]]
133;
134  %i = insertelement <2 x i32> %v, i32 %x, i32 1
135  %b = bitcast <2 x i32> %i to <8 x i8>
136  %r = extractelement <8 x i8> %b, i32 2
137  ret i8 %r
138}
139
140; Partial negative test for the above fold, extra uses are not allowed if shift is needed.
141
142declare void @use(<8 x i8>)
143
144define i8 @bitcasted_inselt_wide_source_uses(i32 %x) {
145; LE-LABEL: @bitcasted_inselt_wide_source_uses(
146; LE-NEXT:    [[I:%.*]] = insertelement <2 x i32> undef, i32 [[X:%.*]], i32 0
147; LE-NEXT:    [[B:%.*]] = bitcast <2 x i32> [[I]] to <8 x i8>
148; LE-NEXT:    call void @use(<8 x i8> [[B]])
149; LE-NEXT:    [[R:%.*]] = extractelement <8 x i8> [[B]], i32 3
150; LE-NEXT:    ret i8 [[R]]
151;
152; BE-LABEL: @bitcasted_inselt_wide_source_uses(
153; BE-NEXT:    [[I:%.*]] = insertelement <2 x i32> undef, i32 [[X:%.*]], i32 0
154; BE-NEXT:    [[B:%.*]] = bitcast <2 x i32> [[I]] to <8 x i8>
155; BE-NEXT:    call void @use(<8 x i8> [[B]])
156; BE-NEXT:    [[R:%.*]] = trunc i32 [[X]] to i8
157; BE-NEXT:    ret i8 [[R]]
158;
159  %i = insertelement <2 x i32> undef, i32 %x, i32 0
160  %b = bitcast <2 x i32> %i to <8 x i8>
161  call void @use(<8 x i8> %b)
162  %r = extractelement <8 x i8> %b, i32 3
163  ret i8 %r
164}
165
166define float @bitcasted_inselt_to_FP(i64 %x) {
167; LE-LABEL: @bitcasted_inselt_to_FP(
168; LE-NEXT:    [[TMP1:%.*]] = lshr i64 [[X:%.*]], 32
169; LE-NEXT:    [[TMP2:%.*]] = trunc i64 [[TMP1]] to i32
170; LE-NEXT:    [[R:%.*]] = bitcast i32 [[TMP2]] to float
171; LE-NEXT:    ret float [[R]]
172;
173; BE-LABEL: @bitcasted_inselt_to_FP(
174; BE-NEXT:    [[TMP1:%.*]] = trunc i64 [[X:%.*]] to i32
175; BE-NEXT:    [[R:%.*]] = bitcast i32 [[TMP1]] to float
176; BE-NEXT:    ret float [[R]]
177;
178  %i = insertelement <2 x i64> undef, i64 %x, i32 0
179  %b = bitcast <2 x i64> %i to <4 x float>
180  %r = extractelement <4 x float> %b, i32 1
181  ret float %r
182}
183
184declare void @use_v2i128(<2 x i128>)
185declare void @use_v8f32(<8 x float>)
186
187define float @bitcasted_inselt_to_FP_uses(i128 %x) {
188; ANY-LABEL: @bitcasted_inselt_to_FP_uses(
189; ANY-NEXT:    [[I:%.*]] = insertelement <2 x i128> undef, i128 [[X:%.*]], i32 0
190; ANY-NEXT:    call void @use_v2i128(<2 x i128> [[I]])
191; ANY-NEXT:    [[B:%.*]] = bitcast <2 x i128> [[I]] to <8 x float>
192; ANY-NEXT:    [[R:%.*]] = extractelement <8 x float> [[B]], i32 1
193; ANY-NEXT:    ret float [[R]]
194;
195  %i = insertelement <2 x i128> undef, i128 %x, i32 0
196  call void @use_v2i128(<2 x i128> %i)
197  %b = bitcast <2 x i128> %i to <8 x float>
198  %r = extractelement <8 x float> %b, i32 1
199  ret float %r
200}
201
202define float @bitcasted_inselt_to_FP_uses2(i128 %x) {
203; ANY-LABEL: @bitcasted_inselt_to_FP_uses2(
204; ANY-NEXT:    [[I:%.*]] = insertelement <2 x i128> undef, i128 [[X:%.*]], i32 0
205; ANY-NEXT:    [[B:%.*]] = bitcast <2 x i128> [[I]] to <8 x float>
206; ANY-NEXT:    call void @use_v8f32(<8 x float> [[B]])
207; ANY-NEXT:    [[R:%.*]] = extractelement <8 x float> [[B]], i32 1
208; ANY-NEXT:    ret float [[R]]
209;
210  %i = insertelement <2 x i128> undef, i128 %x, i32 0
211  %b = bitcast <2 x i128> %i to <8 x float>
212  call void @use_v8f32(<8 x float> %b)
213  %r = extractelement <8 x float> %b, i32 1
214  ret float %r
215}
216
217define i32 @bitcasted_inselt_from_FP(double %x) {
218; LE-LABEL: @bitcasted_inselt_from_FP(
219; LE-NEXT:    [[TMP1:%.*]] = bitcast double [[X:%.*]] to i64
220; LE-NEXT:    [[TMP2:%.*]] = lshr i64 [[TMP1]], 32
221; LE-NEXT:    [[R:%.*]] = trunc i64 [[TMP2]] to i32
222; LE-NEXT:    ret i32 [[R]]
223;
224; BE-LABEL: @bitcasted_inselt_from_FP(
225; BE-NEXT:    [[TMP1:%.*]] = bitcast double [[X:%.*]] to i64
226; BE-NEXT:    [[R:%.*]] = trunc i64 [[TMP1]] to i32
227; BE-NEXT:    ret i32 [[R]]
228;
229  %i = insertelement <2 x double> undef, double %x, i32 0
230  %b = bitcast <2 x double> %i to <4 x i32>
231  %r = extractelement <4 x i32> %b, i32 1
232  ret i32 %r
233}
234
235declare void @use_v2f64(<2 x double>)
236declare void @use_v8i16(<8 x i16>)
237
238define i16 @bitcasted_inselt_from_FP_uses(double %x) {
239; ANY-LABEL: @bitcasted_inselt_from_FP_uses(
240; ANY-NEXT:    [[I:%.*]] = insertelement <2 x double> undef, double [[X:%.*]], i32 0
241; ANY-NEXT:    call void @use_v2f64(<2 x double> [[I]])
242; ANY-NEXT:    [[B:%.*]] = bitcast <2 x double> [[I]] to <8 x i16>
243; ANY-NEXT:    [[R:%.*]] = extractelement <8 x i16> [[B]], i32 1
244; ANY-NEXT:    ret i16 [[R]]
245;
246  %i = insertelement <2 x double> undef, double %x, i32 0
247  call void @use_v2f64(<2 x double> %i)
248  %b = bitcast <2 x double> %i to <8 x i16>
249  %r = extractelement <8 x i16> %b, i32 1
250  ret i16 %r
251}
252
253define i16 @bitcasted_inselt_from_FP_uses2(double %x) {
254; ANY-LABEL: @bitcasted_inselt_from_FP_uses2(
255; ANY-NEXT:    [[I:%.*]] = insertelement <2 x double> undef, double [[X:%.*]], i32 0
256; ANY-NEXT:    [[B:%.*]] = bitcast <2 x double> [[I]] to <8 x i16>
257; ANY-NEXT:    call void @use_v8i16(<8 x i16> [[B]])
258; ANY-NEXT:    [[R:%.*]] = extractelement <8 x i16> [[B]], i32 1
259; ANY-NEXT:    ret i16 [[R]]
260;
261  %i = insertelement <2 x double> undef, double %x, i32 0
262  %b = bitcast <2 x double> %i to <8 x i16>
263  call void @use_v8i16(<8 x i16> %b)
264  %r = extractelement <8 x i16> %b, i32 1
265  ret i16 %r
266}
267
268define float @bitcasted_inselt_to_and_from_FP(double %x) {
269; ANY-LABEL: @bitcasted_inselt_to_and_from_FP(
270; ANY-NEXT:    [[I:%.*]] = insertelement <2 x double> undef, double [[X:%.*]], i32 0
271; ANY-NEXT:    [[B:%.*]] = bitcast <2 x double> [[I]] to <4 x float>
272; ANY-NEXT:    [[R:%.*]] = extractelement <4 x float> [[B]], i32 1
273; ANY-NEXT:    ret float [[R]]
274;
275  %i = insertelement <2 x double> undef, double %x, i32 0
276  %b = bitcast <2 x double> %i to <4 x float>
277  %r = extractelement <4 x float> %b, i32 1
278  ret float %r
279}
280
281define float @bitcasted_inselt_to_and_from_FP_uses(double %x) {
282; ANY-LABEL: @bitcasted_inselt_to_and_from_FP_uses(
283; ANY-NEXT:    [[I:%.*]] = insertelement <2 x double> undef, double [[X:%.*]], i32 0
284; ANY-NEXT:    call void @use_v2f64(<2 x double> [[I]])
285; ANY-NEXT:    [[B:%.*]] = bitcast <2 x double> [[I]] to <4 x float>
286; ANY-NEXT:    [[R:%.*]] = extractelement <4 x float> [[B]], i32 1
287; ANY-NEXT:    ret float [[R]]
288;
289  %i = insertelement <2 x double> undef, double %x, i32 0
290  call void @use_v2f64(<2 x double> %i)
291  %b = bitcast <2 x double> %i to <4 x float>
292  %r = extractelement <4 x float> %b, i32 1
293  ret float %r
294}
295
296declare void @use_v4f32(<4 x float>)
297
298define float @bitcasted_inselt_to_and_from_FP_uses2(double %x) {
299; ANY-LABEL: @bitcasted_inselt_to_and_from_FP_uses2(
300; ANY-NEXT:    [[I:%.*]] = insertelement <2 x double> undef, double [[X:%.*]], i32 0
301; ANY-NEXT:    [[B:%.*]] = bitcast <2 x double> [[I]] to <4 x float>
302; ANY-NEXT:    call void @use_v4f32(<4 x float> [[B]])
303; ANY-NEXT:    [[R:%.*]] = extractelement <4 x float> [[B]], i32 1
304; ANY-NEXT:    ret float [[R]]
305;
306  %i = insertelement <2 x double> undef, double %x, i32 0
307  %b = bitcast <2 x double> %i to <4 x float>
308  call void @use_v4f32(<4 x float> %b)
309  %r = extractelement <4 x float> %b, i32 1
310  ret float %r
311}
312
313; This would crash/assert because the logic for collectShuffleElements()
314; does not consider the possibility of invalid insert/extract operands.
315
316define <4 x double> @invalid_extractelement(<2 x double> %a, <4 x double> %b, double* %p) {
317; ANY-LABEL: @invalid_extractelement(
318; ANY-NEXT:    [[TMP1:%.*]] = shufflevector <2 x double> [[A:%.*]], <2 x double> undef, <4 x i32> <i32 0, i32 undef, i32 undef, i32 undef>
319; ANY-NEXT:    [[T4:%.*]] = shufflevector <4 x double> [[B:%.*]], <4 x double> [[TMP1]], <4 x i32> <i32 undef, i32 1, i32 4, i32 3>
320; ANY-NEXT:    [[E:%.*]] = extractelement <4 x double> [[B]], i32 1
321; ANY-NEXT:    store double [[E]], double* [[P:%.*]], align 8
322; ANY-NEXT:    [[R:%.*]] = insertelement <4 x double> [[T4]], double undef, i64 0
323; ANY-NEXT:    ret <4 x double> [[R]]
324;
325  %t3 = extractelement <2 x double> %a, i32 0
326  %t4 = insertelement <4 x double> %b, double %t3, i32 2
327  %e = extractelement <4 x double> %t4, i32 1
328  store double %e, double* %p
329  %e1 = extractelement <2 x double> %a, i32 4 ; invalid index
330  %r = insertelement <4 x double> %t4, double %e1, i64 0
331  ret <4 x double> %r
332}
333