[DAGCombiner] Add target hook function to decide folding (mul (add x, c1), c2)
[llvm-project.git] / llvm / test / Transforms / InstCombine / extractelement-inseltpoison.ll
blob82d805310489fcada4ed3bfd2bc2c17e0bb4a823
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
5 define i32 @extractelement_out_of_range(<2 x i32> %x) {
6 ; ANY-LABEL: @extractelement_out_of_range(
7 ; ANY-NEXT:    ret i32 poison
9   %E1 = extractelement <2 x i32> %x, i8 16
10   ret i32 %E1
13 define 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]]
18   %E1 = extractelement <2 x i32> %x, i128 0
19   ret i32 %E1
22 define 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]]
27   %vf = insertelement <4 x float> poison, 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
33 define i64 @test2(i64 %in) {
34 ; ANY-LABEL: @test2(
35 ; ANY-NEXT:    ret i64 [[IN:%.*]]
37   %vec = insertelement <8 x i64> poison, i64 %in, i32 0
38   %splat = shufflevector <8 x i64> %vec, <8 x i64> poison, <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
44 define 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]]
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]]
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
60 define 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]]
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]]
70   %i = insertelement <2 x i64> poison, 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
76 define 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]]
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]]
86   %i = insertelement <2 x i64> poison, 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
92 define 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]]
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]]
103   %i = insertelement <2 x i32> poison, 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
109 define 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]]
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]]
120   %i = insertelement <3 x i15> poison, 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
126 ; Negative test for the above fold, but we can remove the insert here.
128 define 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]]
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
140 ; Partial negative test for the above fold, extra uses are not allowed if shift is needed.
142 declare void @use(<8 x i8>)
144 define i8 @bitcasted_inselt_wide_source_uses(i32 %x) {
145 ; LE-LABEL: @bitcasted_inselt_wide_source_uses(
146 ; LE-NEXT:    [[I:%.*]] = insertelement <2 x i32> poison, 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]]
152 ; BE-LABEL: @bitcasted_inselt_wide_source_uses(
153 ; BE-NEXT:    [[I:%.*]] = insertelement <2 x i32> poison, 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]]
159   %i = insertelement <2 x i32> poison, 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
166 define 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]]
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]]
178   %i = insertelement <2 x i64> poison, 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
184 declare void @use_v2i128(<2 x i128>)
185 declare void @use_v8f32(<8 x float>)
187 define float @bitcasted_inselt_to_FP_uses(i128 %x) {
188 ; ANY-LABEL: @bitcasted_inselt_to_FP_uses(
189 ; ANY-NEXT:    [[I:%.*]] = insertelement <2 x i128> poison, 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]]
195   %i = insertelement <2 x i128> poison, 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
202 define float @bitcasted_inselt_to_FP_uses2(i128 %x) {
203 ; ANY-LABEL: @bitcasted_inselt_to_FP_uses2(
204 ; ANY-NEXT:    [[I:%.*]] = insertelement <2 x i128> poison, 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]]
210   %i = insertelement <2 x i128> poison, 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
217 define 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]]
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]]
229   %i = insertelement <2 x double> poison, 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
235 declare void @use_v2f64(<2 x double>)
236 declare void @use_v8i16(<8 x i16>)
238 define i16 @bitcasted_inselt_from_FP_uses(double %x) {
239 ; ANY-LABEL: @bitcasted_inselt_from_FP_uses(
240 ; ANY-NEXT:    [[I:%.*]] = insertelement <2 x double> poison, 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]]
246   %i = insertelement <2 x double> poison, 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
253 define i16 @bitcasted_inselt_from_FP_uses2(double %x) {
254 ; ANY-LABEL: @bitcasted_inselt_from_FP_uses2(
255 ; ANY-NEXT:    [[I:%.*]] = insertelement <2 x double> poison, 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]]
261   %i = insertelement <2 x double> poison, 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
268 define 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> poison, 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]]
275   %i = insertelement <2 x double> poison, 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
281 define 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> poison, 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]]
289   %i = insertelement <2 x double> poison, 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
296 declare void @use_v4f32(<4 x float>)
298 define 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> poison, 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]]
306   %i = insertelement <2 x double> poison, 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
313 ; This would crash/assert because the logic for collectShuffleElements()
314 ; does not consider the possibility of invalid insert/extract operands.
316 define <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> poison, <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:    ret <4 x double> [[T4]]
324   %t3 = extractelement <2 x double> %a, i32 0
325   %t4 = insertelement <4 x double> %b, double %t3, i32 2
326   %e = extractelement <4 x double> %t4, i32 1
327   store double %e, double* %p
328   %e1 = extractelement <2 x double> %a, i32 4 ; invalid index
329   %r = insertelement <4 x double> %t4, double %e1, i64 0
330   ret <4 x double> %r