[clang][modules] Don't prevent translation of FW_Private includes when explicitly...
[llvm-project.git] / llvm / test / Transforms / VectorCombine / X86 / extract-binop-inseltpoison.ll
blob97be7304bb0c87ea605c614015a92bbaa478c7d7
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -passes=vector-combine -S -mtriple=x86_64-- -mattr=SSE2 | FileCheck %s --check-prefixes=CHECK,SSE
3 ; RUN: opt < %s -passes=vector-combine -S -mtriple=x86_64-- -mattr=AVX2 | FileCheck %s --check-prefixes=CHECK,AVX
5 declare void @use_i8(i8)
6 declare void @use_f32(float)
8 ; Eliminating extract is profitable.
10 define i8 @ext0_ext0_add(<16 x i8> %x, <16 x i8> %y) {
11 ; CHECK-LABEL: @ext0_ext0_add(
12 ; CHECK-NEXT:    [[TMP1:%.*]] = add <16 x i8> [[X:%.*]], [[Y:%.*]]
13 ; CHECK-NEXT:    [[R:%.*]] = extractelement <16 x i8> [[TMP1]], i32 0
14 ; CHECK-NEXT:    ret i8 [[R]]
16   %e0 = extractelement <16 x i8> %x, i32 0
17   %e1 = extractelement <16 x i8> %y, i32 0
18   %r = add i8 %e0, %e1
19   ret i8 %r
22 ; Eliminating extract is still profitable. Flags propagate.
24 define i8 @ext1_ext1_add_flags(<16 x i8> %x, <16 x i8> %y) {
25 ; CHECK-LABEL: @ext1_ext1_add_flags(
26 ; CHECK-NEXT:    [[TMP1:%.*]] = add nuw nsw <16 x i8> [[X:%.*]], [[Y:%.*]]
27 ; CHECK-NEXT:    [[R:%.*]] = extractelement <16 x i8> [[TMP1]], i32 1
28 ; CHECK-NEXT:    ret i8 [[R]]
30   %e0 = extractelement <16 x i8> %x, i32 1
31   %e1 = extractelement <16 x i8> %y, i32 1
32   %r = add nsw nuw i8 %e0, %e1
33   ret i8 %r
36 ; Negative test - eliminating extract is profitable, but vector shift is expensive.
38 define i8 @ext1_ext1_shl(<16 x i8> %x, <16 x i8> %y) {
39 ; CHECK-LABEL: @ext1_ext1_shl(
40 ; CHECK-NEXT:    [[E0:%.*]] = extractelement <16 x i8> [[X:%.*]], i32 1
41 ; CHECK-NEXT:    [[E1:%.*]] = extractelement <16 x i8> [[Y:%.*]], i32 1
42 ; CHECK-NEXT:    [[R:%.*]] = shl i8 [[E0]], [[E1]]
43 ; CHECK-NEXT:    ret i8 [[R]]
45   %e0 = extractelement <16 x i8> %x, i32 1
46   %e1 = extractelement <16 x i8> %y, i32 1
47   %r = shl i8 %e0, %e1
48   ret i8 %r
51 ; Negative test - eliminating extract is profitable, but vector multiply is expensive.
53 define i8 @ext13_ext13_mul(<16 x i8> %x, <16 x i8> %y) {
54 ; SSE-LABEL: @ext13_ext13_mul(
55 ; SSE-NEXT:    [[TMP1:%.*]] = mul <16 x i8> [[X:%.*]], [[Y:%.*]]
56 ; SSE-NEXT:    [[R:%.*]] = extractelement <16 x i8> [[TMP1]], i32 13
57 ; SSE-NEXT:    ret i8 [[R]]
59 ; AVX-LABEL: @ext13_ext13_mul(
60 ; AVX-NEXT:    [[E0:%.*]] = extractelement <16 x i8> [[X:%.*]], i32 13
61 ; AVX-NEXT:    [[E1:%.*]] = extractelement <16 x i8> [[Y:%.*]], i32 13
62 ; AVX-NEXT:    [[R:%.*]] = mul i8 [[E0]], [[E1]]
63 ; AVX-NEXT:    ret i8 [[R]]
65   %e0 = extractelement <16 x i8> %x, i32 13
66   %e1 = extractelement <16 x i8> %y, i32 13
67   %r = mul i8 %e0, %e1
68   ret i8 %r
71 ; Negative test - cost is irrelevant because sdiv has potential UB.
73 define i8 @ext0_ext0_sdiv(<16 x i8> %x, <16 x i8> %y) {
74 ; CHECK-LABEL: @ext0_ext0_sdiv(
75 ; CHECK-NEXT:    [[E0:%.*]] = extractelement <16 x i8> [[X:%.*]], i32 0
76 ; CHECK-NEXT:    [[E1:%.*]] = extractelement <16 x i8> [[Y:%.*]], i32 0
77 ; CHECK-NEXT:    [[R:%.*]] = sdiv i8 [[E0]], [[E1]]
78 ; CHECK-NEXT:    ret i8 [[R]]
80   %e0 = extractelement <16 x i8> %x, i32 0
81   %e1 = extractelement <16 x i8> %y, i32 0
82   %r = sdiv i8 %e0, %e1
83   ret i8 %r
86 ; Extracts are free and vector op has same cost as scalar, but we
87 ; speculatively transform to vector to create more optimization
88 ; opportunities..
90 define double @ext0_ext0_fadd(<2 x double> %x, <2 x double> %y) {
91 ; CHECK-LABEL: @ext0_ext0_fadd(
92 ; CHECK-NEXT:    [[TMP1:%.*]] = fadd <2 x double> [[X:%.*]], [[Y:%.*]]
93 ; CHECK-NEXT:    [[R:%.*]] = extractelement <2 x double> [[TMP1]], i32 0
94 ; CHECK-NEXT:    ret double [[R]]
96   %e0 = extractelement <2 x double> %x, i32 0
97   %e1 = extractelement <2 x double> %y, i32 0
98   %r = fadd double %e0, %e1
99   ret double %r
102 ; Eliminating extract is profitable. Flags propagate.
104 define double @ext1_ext1_fsub(<2 x double> %x, <2 x double> %y) {
105 ; CHECK-LABEL: @ext1_ext1_fsub(
106 ; CHECK-NEXT:    [[TMP1:%.*]] = fsub fast <2 x double> [[X:%.*]], [[Y:%.*]]
107 ; CHECK-NEXT:    [[R:%.*]] = extractelement <2 x double> [[TMP1]], i32 1
108 ; CHECK-NEXT:    ret double [[R]]
110   %e0 = extractelement <2 x double> %x, i32 1
111   %e1 = extractelement <2 x double> %y, i32 1
112   %r = fsub fast double %e0, %e1
113   ret double %r
116 ; Negative test - type mismatch.
118 define double @ext1_ext1_fadd_different_types(<2 x double> %x, <4 x double> %y) {
119 ; CHECK-LABEL: @ext1_ext1_fadd_different_types(
120 ; CHECK-NEXT:    [[E0:%.*]] = extractelement <2 x double> [[X:%.*]], i32 1
121 ; CHECK-NEXT:    [[E1:%.*]] = extractelement <4 x double> [[Y:%.*]], i32 1
122 ; CHECK-NEXT:    [[R:%.*]] = fadd fast double [[E0]], [[E1]]
123 ; CHECK-NEXT:    ret double [[R]]
125   %e0 = extractelement <2 x double> %x, i32 1
126   %e1 = extractelement <4 x double> %y, i32 1
127   %r = fadd fast double %e0, %e1
128   ret double %r
131 ; Disguised same vector operand; scalar code is not cheaper (with default
132 ; x86 target), so aggressively form vector binop.
134 define i32 @ext1_ext1_add_same_vec(<4 x i32> %x) {
135 ; CHECK-LABEL: @ext1_ext1_add_same_vec(
136 ; CHECK-NEXT:    [[TMP1:%.*]] = add <4 x i32> [[X:%.*]], [[X]]
137 ; CHECK-NEXT:    [[R:%.*]] = extractelement <4 x i32> [[TMP1]], i32 1
138 ; CHECK-NEXT:    ret i32 [[R]]
140   %e0 = extractelement <4 x i32> %x, i32 1
141   %e1 = extractelement <4 x i32> %x, i32 1
142   %r = add i32 %e0, %e1
143   ret i32 %r
146 ; Functionally equivalent to above test; should transform as above.
148 define i32 @ext1_ext1_add_same_vec_cse(<4 x i32> %x) {
149 ; CHECK-LABEL: @ext1_ext1_add_same_vec_cse(
150 ; CHECK-NEXT:    [[TMP1:%.*]] = add <4 x i32> [[X:%.*]], [[X]]
151 ; CHECK-NEXT:    [[R:%.*]] = extractelement <4 x i32> [[TMP1]], i32 1
152 ; CHECK-NEXT:    ret i32 [[R]]
154   %e0 = extractelement <4 x i32> %x, i32 1
155   %r = add i32 %e0, %e0
156   ret i32 %r
159 ; Don't assert if extract indices have different types.
161 define i32 @ext1_ext1_add_same_vec_diff_idx_ty(<4 x i32> %x) {
162 ; CHECK-LABEL: @ext1_ext1_add_same_vec_diff_idx_ty(
163 ; CHECK-NEXT:    [[TMP1:%.*]] = add <4 x i32> [[X:%.*]], [[X]]
164 ; CHECK-NEXT:    [[R:%.*]] = extractelement <4 x i32> [[TMP1]], i32 1
165 ; CHECK-NEXT:    ret i32 [[R]]
167   %e0 = extractelement <4 x i32> %x, i32 1
168   %e1 = extractelement <4 x i32> %x, i64 1
169   %r = add i32 %e0, %e1
170   ret i32 %r
173 ; Negative test - same vector operand; scalar code is cheaper than general case
174 ;                 and vector code would be more expensive still.
176 define i8 @ext1_ext1_add_same_vec_extra_use0(<16 x i8> %x) {
177 ; CHECK-LABEL: @ext1_ext1_add_same_vec_extra_use0(
178 ; CHECK-NEXT:    [[E0:%.*]] = extractelement <16 x i8> [[X:%.*]], i32 0
179 ; CHECK-NEXT:    call void @use_i8(i8 [[E0]])
180 ; CHECK-NEXT:    [[E1:%.*]] = extractelement <16 x i8> [[X]], i32 0
181 ; CHECK-NEXT:    [[R:%.*]] = add i8 [[E0]], [[E1]]
182 ; CHECK-NEXT:    ret i8 [[R]]
184   %e0 = extractelement <16 x i8> %x, i32 0
185   call void @use_i8(i8 %e0)
186   %e1 = extractelement <16 x i8> %x, i32 0
187   %r = add i8 %e0, %e1
188   ret i8 %r
191 ; Negative test - same vector operand; scalar code is cheaper than general case
192 ;                 and vector code would be more expensive still.
194 define i8 @ext1_ext1_add_same_vec_extra_use1(<16 x i8> %x) {
195 ; CHECK-LABEL: @ext1_ext1_add_same_vec_extra_use1(
196 ; CHECK-NEXT:    [[E0:%.*]] = extractelement <16 x i8> [[X:%.*]], i32 0
197 ; CHECK-NEXT:    [[E1:%.*]] = extractelement <16 x i8> [[X]], i32 0
198 ; CHECK-NEXT:    call void @use_i8(i8 [[E1]])
199 ; CHECK-NEXT:    [[R:%.*]] = add i8 [[E0]], [[E1]]
200 ; CHECK-NEXT:    ret i8 [[R]]
202   %e0 = extractelement <16 x i8> %x, i32 0
203   %e1 = extractelement <16 x i8> %x, i32 0
204   call void @use_i8(i8 %e1)
205   %r = add i8 %e0, %e1
206   ret i8 %r
209 ; Negative test - same vector operand; scalar code is cheaper than general case
210 ;                 and vector code would be more expensive still.
212 define i8 @ext1_ext1_add_same_vec_cse_extra_use(<16 x i8> %x) {
213 ; CHECK-LABEL: @ext1_ext1_add_same_vec_cse_extra_use(
214 ; CHECK-NEXT:    [[E:%.*]] = extractelement <16 x i8> [[X:%.*]], i32 0
215 ; CHECK-NEXT:    call void @use_i8(i8 [[E]])
216 ; CHECK-NEXT:    [[R:%.*]] = add i8 [[E]], [[E]]
217 ; CHECK-NEXT:    ret i8 [[R]]
219   %e = extractelement <16 x i8> %x, i32 0
220   call void @use_i8(i8 %e)
221   %r = add i8 %e, %e
222   ret i8 %r
225 ; Vector code costs the same as scalar, so aggressively form vector op.
227 define i8 @ext1_ext1_add_uses1(<16 x i8> %x, <16 x i8> %y) {
228 ; CHECK-LABEL: @ext1_ext1_add_uses1(
229 ; CHECK-NEXT:    [[E0:%.*]] = extractelement <16 x i8> [[X:%.*]], i32 0
230 ; CHECK-NEXT:    call void @use_i8(i8 [[E0]])
231 ; CHECK-NEXT:    [[TMP1:%.*]] = add <16 x i8> [[X]], [[Y:%.*]]
232 ; CHECK-NEXT:    [[R:%.*]] = extractelement <16 x i8> [[TMP1]], i32 0
233 ; CHECK-NEXT:    ret i8 [[R]]
235   %e0 = extractelement <16 x i8> %x, i32 0
236   call void @use_i8(i8 %e0)
237   %e1 = extractelement <16 x i8> %y, i32 0
238   %r = add i8 %e0, %e1
239   ret i8 %r
242 ; Vector code costs the same as scalar, so aggressively form vector op.
244 define i8 @ext1_ext1_add_uses2(<16 x i8> %x, <16 x i8> %y) {
245 ; CHECK-LABEL: @ext1_ext1_add_uses2(
246 ; CHECK-NEXT:    [[E1:%.*]] = extractelement <16 x i8> [[Y:%.*]], i32 0
247 ; CHECK-NEXT:    call void @use_i8(i8 [[E1]])
248 ; CHECK-NEXT:    [[TMP1:%.*]] = add <16 x i8> [[X:%.*]], [[Y]]
249 ; CHECK-NEXT:    [[R:%.*]] = extractelement <16 x i8> [[TMP1]], i32 0
250 ; CHECK-NEXT:    ret i8 [[R]]
252   %e0 = extractelement <16 x i8> %x, i32 0
253   %e1 = extractelement <16 x i8> %y, i32 0
254   call void @use_i8(i8 %e1)
255   %r = add i8 %e0, %e1
256   ret i8 %r
259 define i8 @ext0_ext1_add(<16 x i8> %x, <16 x i8> %y) {
260 ; SSE-LABEL: @ext0_ext1_add(
261 ; SSE-NEXT:    [[E0:%.*]] = extractelement <16 x i8> [[X:%.*]], i32 0
262 ; SSE-NEXT:    [[E1:%.*]] = extractelement <16 x i8> [[Y:%.*]], i32 1
263 ; SSE-NEXT:    [[R:%.*]] = add nuw i8 [[E0]], [[E1]]
264 ; SSE-NEXT:    ret i8 [[R]]
266 ; AVX-LABEL: @ext0_ext1_add(
267 ; AVX-NEXT:    [[SHIFT:%.*]] = shufflevector <16 x i8> [[Y:%.*]], <16 x i8> poison, <16 x i32> <i32 1, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison>
268 ; AVX-NEXT:    [[TMP1:%.*]] = add nuw <16 x i8> [[X:%.*]], [[SHIFT]]
269 ; AVX-NEXT:    [[R:%.*]] = extractelement <16 x i8> [[TMP1]], i32 0
270 ; AVX-NEXT:    ret i8 [[R]]
272   %e0 = extractelement <16 x i8> %x, i32 0
273   %e1 = extractelement <16 x i8> %y, i32 1
274   %r = add nuw i8 %e0, %e1
275   ret i8 %r
278 define i8 @ext5_ext0_add(<16 x i8> %x, <16 x i8> %y) {
279 ; SSE-LABEL: @ext5_ext0_add(
280 ; SSE-NEXT:    [[E0:%.*]] = extractelement <16 x i8> [[X:%.*]], i32 5
281 ; SSE-NEXT:    [[E1:%.*]] = extractelement <16 x i8> [[Y:%.*]], i32 0
282 ; SSE-NEXT:    [[R:%.*]] = sub nsw i8 [[E0]], [[E1]]
283 ; SSE-NEXT:    ret i8 [[R]]
285 ; AVX-LABEL: @ext5_ext0_add(
286 ; AVX-NEXT:    [[SHIFT:%.*]] = shufflevector <16 x i8> [[X:%.*]], <16 x i8> poison, <16 x i32> <i32 5, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison>
287 ; AVX-NEXT:    [[TMP1:%.*]] = sub nsw <16 x i8> [[SHIFT]], [[Y:%.*]]
288 ; AVX-NEXT:    [[R:%.*]] = extractelement <16 x i8> [[TMP1]], i64 0
289 ; AVX-NEXT:    ret i8 [[R]]
291   %e0 = extractelement <16 x i8> %x, i32 5
292   %e1 = extractelement <16 x i8> %y, i32 0
293   %r = sub nsw i8 %e0, %e1
294   ret i8 %r
297 define i8 @ext1_ext6_add(<16 x i8> %x, <16 x i8> %y) {
298 ; SSE-LABEL: @ext1_ext6_add(
299 ; SSE-NEXT:    [[E0:%.*]] = extractelement <16 x i8> [[X:%.*]], i32 1
300 ; SSE-NEXT:    [[E1:%.*]] = extractelement <16 x i8> [[Y:%.*]], i32 6
301 ; SSE-NEXT:    [[R:%.*]] = and i8 [[E0]], [[E1]]
302 ; SSE-NEXT:    ret i8 [[R]]
304 ; AVX-LABEL: @ext1_ext6_add(
305 ; AVX-NEXT:    [[SHIFT:%.*]] = shufflevector <16 x i8> [[Y:%.*]], <16 x i8> poison, <16 x i32> <i32 poison, i32 6, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison>
306 ; AVX-NEXT:    [[TMP1:%.*]] = and <16 x i8> [[X:%.*]], [[SHIFT]]
307 ; AVX-NEXT:    [[R:%.*]] = extractelement <16 x i8> [[TMP1]], i32 1
308 ; AVX-NEXT:    ret i8 [[R]]
310   %e0 = extractelement <16 x i8> %x, i32 1
311   %e1 = extractelement <16 x i8> %y, i32 6
312   %r = and i8 %e0, %e1
313   ret i8 %r
316 define float @ext1_ext0_fmul(<4 x float> %x) {
317 ; CHECK-LABEL: @ext1_ext0_fmul(
318 ; CHECK-NEXT:    [[SHIFT:%.*]] = shufflevector <4 x float> [[X:%.*]], <4 x float> poison, <4 x i32> <i32 1, i32 poison, i32 poison, i32 poison>
319 ; CHECK-NEXT:    [[TMP1:%.*]] = fmul <4 x float> [[SHIFT]], [[X]]
320 ; CHECK-NEXT:    [[R:%.*]] = extractelement <4 x float> [[TMP1]], i64 0
321 ; CHECK-NEXT:    ret float [[R]]
323   %e0 = extractelement <4 x float> %x, i32 1
324   %e1 = extractelement <4 x float> %x, i32 0
325   %r = fmul float %e0, %e1
326   ret float %r
329 define float @ext0_ext3_fmul_extra_use1(<4 x float> %x) {
330 ; CHECK-LABEL: @ext0_ext3_fmul_extra_use1(
331 ; CHECK-NEXT:    [[E0:%.*]] = extractelement <4 x float> [[X:%.*]], i32 0
332 ; CHECK-NEXT:    call void @use_f32(float [[E0]])
333 ; CHECK-NEXT:    [[SHIFT:%.*]] = shufflevector <4 x float> [[X]], <4 x float> poison, <4 x i32> <i32 3, i32 poison, i32 poison, i32 poison>
334 ; CHECK-NEXT:    [[TMP1:%.*]] = fmul nnan <4 x float> [[X]], [[SHIFT]]
335 ; CHECK-NEXT:    [[R:%.*]] = extractelement <4 x float> [[TMP1]], i32 0
336 ; CHECK-NEXT:    ret float [[R]]
338   %e0 = extractelement <4 x float> %x, i32 0
339   call void @use_f32(float %e0)
340   %e1 = extractelement <4 x float> %x, i32 3
341   %r = fmul nnan float %e0, %e1
342   ret float %r
345 define float @ext0_ext3_fmul_extra_use2(<4 x float> %x) {
346 ; CHECK-LABEL: @ext0_ext3_fmul_extra_use2(
347 ; CHECK-NEXT:    [[E0:%.*]] = extractelement <4 x float> [[X:%.*]], i32 0
348 ; CHECK-NEXT:    [[E1:%.*]] = extractelement <4 x float> [[X]], i32 3
349 ; CHECK-NEXT:    call void @use_f32(float [[E1]])
350 ; CHECK-NEXT:    [[R:%.*]] = fmul ninf nsz float [[E0]], [[E1]]
351 ; CHECK-NEXT:    ret float [[R]]
353   %e0 = extractelement <4 x float> %x, i32 0
354   %e1 = extractelement <4 x float> %x, i32 3
355   call void @use_f32(float %e1)
356   %r = fmul ninf nsz float %e0, %e1
357   ret float %r
360 define float @ext0_ext4_fmul_v8f32(<8 x float> %x) {
361 ; SSE-LABEL: @ext0_ext4_fmul_v8f32(
362 ; SSE-NEXT:    [[E0:%.*]] = extractelement <8 x float> [[X:%.*]], i32 0
363 ; SSE-NEXT:    [[E1:%.*]] = extractelement <8 x float> [[X]], i32 4
364 ; SSE-NEXT:    [[R:%.*]] = fadd float [[E0]], [[E1]]
365 ; SSE-NEXT:    ret float [[R]]
367 ; AVX-LABEL: @ext0_ext4_fmul_v8f32(
368 ; AVX-NEXT:    [[SHIFT:%.*]] = shufflevector <8 x float> [[X:%.*]], <8 x float> poison, <8 x i32> <i32 4, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison>
369 ; AVX-NEXT:    [[TMP1:%.*]] = fadd <8 x float> [[X]], [[SHIFT]]
370 ; AVX-NEXT:    [[R:%.*]] = extractelement <8 x float> [[TMP1]], i32 0
371 ; AVX-NEXT:    ret float [[R]]
373   %e0 = extractelement <8 x float> %x, i32 0
374   %e1 = extractelement <8 x float> %x, i32 4
375   %r = fadd float %e0, %e1
376   ret float %r
379 define float @ext7_ext4_fmul_v8f32(<8 x float> %x) {
380 ; SSE-LABEL: @ext7_ext4_fmul_v8f32(
381 ; SSE-NEXT:    [[E0:%.*]] = extractelement <8 x float> [[X:%.*]], i32 7
382 ; SSE-NEXT:    [[E1:%.*]] = extractelement <8 x float> [[X]], i32 4
383 ; SSE-NEXT:    [[R:%.*]] = fadd float [[E0]], [[E1]]
384 ; SSE-NEXT:    ret float [[R]]
386 ; AVX-LABEL: @ext7_ext4_fmul_v8f32(
387 ; AVX-NEXT:    [[SHIFT:%.*]] = shufflevector <8 x float> [[X:%.*]], <8 x float> poison, <8 x i32> <i32 poison, i32 poison, i32 poison, i32 poison, i32 7, i32 poison, i32 poison, i32 poison>
388 ; AVX-NEXT:    [[TMP1:%.*]] = fadd <8 x float> [[SHIFT]], [[X]]
389 ; AVX-NEXT:    [[R:%.*]] = extractelement <8 x float> [[TMP1]], i64 4
390 ; AVX-NEXT:    ret float [[R]]
392   %e0 = extractelement <8 x float> %x, i32 7
393   %e1 = extractelement <8 x float> %x, i32 4
394   %r = fadd float %e0, %e1
395   ret float %r
398 define float @ext0_ext8_fmul_v16f32(<16 x float> %x) {
399 ; CHECK-LABEL: @ext0_ext8_fmul_v16f32(
400 ; CHECK-NEXT:    [[E0:%.*]] = extractelement <16 x float> [[X:%.*]], i32 0
401 ; CHECK-NEXT:    [[E1:%.*]] = extractelement <16 x float> [[X]], i32 8
402 ; CHECK-NEXT:    [[R:%.*]] = fadd float [[E0]], [[E1]]
403 ; CHECK-NEXT:    ret float [[R]]
405   %e0 = extractelement <16 x float> %x, i32 0
406   %e1 = extractelement <16 x float> %x, i32 8
407   %r = fadd float %e0, %e1
408   ret float %r
411 define float @ext14_ext15_fmul_v16f32(<16 x float> %x) {
412 ; CHECK-LABEL: @ext14_ext15_fmul_v16f32(
413 ; CHECK-NEXT:    [[E0:%.*]] = extractelement <16 x float> [[X:%.*]], i32 14
414 ; CHECK-NEXT:    [[E1:%.*]] = extractelement <16 x float> [[X]], i32 15
415 ; CHECK-NEXT:    [[R:%.*]] = fadd float [[E0]], [[E1]]
416 ; CHECK-NEXT:    ret float [[R]]
418   %e0 = extractelement <16 x float> %x, i32 14
419   %e1 = extractelement <16 x float> %x, i32 15
420   %r = fadd float %e0, %e1
421   ret float %r
424 define <4 x float> @ins_bo_ext_ext(<4 x float> %a, <4 x float> %b) {
425 ; CHECK-LABEL: @ins_bo_ext_ext(
426 ; CHECK-NEXT:    [[SHIFT:%.*]] = shufflevector <4 x float> [[A:%.*]], <4 x float> poison, <4 x i32> <i32 poison, i32 poison, i32 poison, i32 2>
427 ; CHECK-NEXT:    [[TMP1:%.*]] = fadd <4 x float> [[SHIFT]], [[A]]
428 ; CHECK-NEXT:    [[A23:%.*]] = extractelement <4 x float> [[TMP1]], i64 3
429 ; CHECK-NEXT:    [[V3:%.*]] = insertelement <4 x float> [[B:%.*]], float [[A23]], i32 3
430 ; CHECK-NEXT:    ret <4 x float> [[V3]]
432   %a2 = extractelement <4 x float> %a, i32 2
433   %a3 = extractelement <4 x float> %a, i32 3
434   %a23 = fadd float %a2, %a3
435   %v3 = insertelement <4 x float> %b, float %a23, i32 3
436   ret <4 x float> %v3
439 ; TODO: This is conservatively left to extract from the lower index value,
440 ;       but it is likely that extracting from index 3 is the better option.
442 define <4 x float> @ins_bo_ext_ext_uses(<4 x float> %a, <4 x float> %b) {
443 ; CHECK-LABEL: @ins_bo_ext_ext_uses(
444 ; CHECK-NEXT:    [[SHIFT:%.*]] = shufflevector <4 x float> [[A:%.*]], <4 x float> poison, <4 x i32> <i32 poison, i32 poison, i32 3, i32 poison>
445 ; CHECK-NEXT:    [[TMP1:%.*]] = fadd <4 x float> [[A]], [[SHIFT]]
446 ; CHECK-NEXT:    [[A23:%.*]] = extractelement <4 x float> [[TMP1]], i32 2
447 ; CHECK-NEXT:    call void @use_f32(float [[A23]])
448 ; CHECK-NEXT:    [[V3:%.*]] = insertelement <4 x float> [[B:%.*]], float [[A23]], i32 3
449 ; CHECK-NEXT:    ret <4 x float> [[V3]]
451   %a2 = extractelement <4 x float> %a, i32 2
452   %a3 = extractelement <4 x float> %a, i32 3
453   %a23 = fadd float %a2, %a3
454   call void @use_f32(float %a23)
455   %v3 = insertelement <4 x float> %b, float %a23, i32 3
456   ret <4 x float> %v3
459 define <4 x float> @PR34724(<4 x float> %a, <4 x float> %b) {
460 ; CHECK-LABEL: @PR34724(
461 ; CHECK-NEXT:    [[A0:%.*]] = extractelement <4 x float> [[A:%.*]], i32 0
462 ; CHECK-NEXT:    [[A1:%.*]] = extractelement <4 x float> [[A]], i32 1
463 ; CHECK-NEXT:    [[SHIFT:%.*]] = shufflevector <4 x float> [[A]], <4 x float> poison, <4 x i32> <i32 poison, i32 poison, i32 3, i32 poison>
464 ; CHECK-NEXT:    [[TMP1:%.*]] = fadd <4 x float> [[A]], [[SHIFT]]
465 ; CHECK-NEXT:    [[A23:%.*]] = extractelement <4 x float> [[TMP1]], i32 2
466 ; CHECK-NEXT:    [[SHIFT1:%.*]] = shufflevector <4 x float> [[B:%.*]], <4 x float> poison, <4 x i32> <i32 1, i32 poison, i32 poison, i32 poison>
467 ; CHECK-NEXT:    [[TMP2:%.*]] = fadd <4 x float> [[B]], [[SHIFT1]]
468 ; CHECK-NEXT:    [[B01:%.*]] = extractelement <4 x float> [[TMP2]], i32 0
469 ; CHECK-NEXT:    [[SHIFT2:%.*]] = shufflevector <4 x float> [[B]], <4 x float> poison, <4 x i32> <i32 poison, i32 poison, i32 poison, i32 2>
470 ; CHECK-NEXT:    [[TMP3:%.*]] = fadd <4 x float> [[SHIFT2]], [[B]]
471 ; CHECK-NEXT:    [[B23:%.*]] = extractelement <4 x float> [[TMP3]], i64 3
472 ; CHECK-NEXT:    [[V1:%.*]] = insertelement <4 x float> poison, float [[A23]], i32 1
473 ; CHECK-NEXT:    [[V2:%.*]] = insertelement <4 x float> [[V1]], float [[B01]], i32 2
474 ; CHECK-NEXT:    [[V3:%.*]] = insertelement <4 x float> [[V2]], float [[B23]], i32 3
475 ; CHECK-NEXT:    ret <4 x float> [[V3]]
477   %a0 = extractelement <4 x float> %a, i32 0
478   %a1 = extractelement <4 x float> %a, i32 1
479   %a2 = extractelement <4 x float> %a, i32 2
480   %a3 = extractelement <4 x float> %a, i32 3
482   %b0 = extractelement <4 x float> %b, i32 0
483   %b1 = extractelement <4 x float> %b, i32 1
484   %b2 = extractelement <4 x float> %b, i32 2
485   %b3 = extractelement <4 x float> %b, i32 3
487   %a23 = fadd float %a2, %a3
488   %b01 = fadd float %b0, %b1
489   %b23 = fadd float %b2, %b3
491   %v1 = insertelement <4 x float> poison, float %a23, i32 1
492   %v2 = insertelement <4 x float> %v1, float %b01, i32 2
493   %v3 = insertelement <4 x float> %v2, float %b23, i32 3
494   ret <4 x float> %v3
497 define i32 @ext_ext_or_reduction_v4i32(<4 x i32> %x, <4 x i32> %y) {
498 ; CHECK-LABEL: @ext_ext_or_reduction_v4i32(
499 ; CHECK-NEXT:    [[Z:%.*]] = and <4 x i32> [[X:%.*]], [[Y:%.*]]
500 ; CHECK-NEXT:    [[SHIFT:%.*]] = shufflevector <4 x i32> [[Z]], <4 x i32> poison, <4 x i32> <i32 1, i32 poison, i32 poison, i32 poison>
501 ; CHECK-NEXT:    [[TMP1:%.*]] = or <4 x i32> [[Z]], [[SHIFT]]
502 ; CHECK-NEXT:    [[SHIFT1:%.*]] = shufflevector <4 x i32> [[Z]], <4 x i32> poison, <4 x i32> <i32 2, i32 poison, i32 poison, i32 poison>
503 ; CHECK-NEXT:    [[TMP2:%.*]] = or <4 x i32> [[TMP1]], [[SHIFT1]]
504 ; CHECK-NEXT:    [[SHIFT2:%.*]] = shufflevector <4 x i32> [[Z]], <4 x i32> poison, <4 x i32> <i32 3, i32 poison, i32 poison, i32 poison>
505 ; CHECK-NEXT:    [[TMP3:%.*]] = or <4 x i32> [[SHIFT2]], [[TMP2]]
506 ; CHECK-NEXT:    [[Z0123:%.*]] = extractelement <4 x i32> [[TMP3]], i64 0
507 ; CHECK-NEXT:    ret i32 [[Z0123]]
509   %z = and <4 x i32> %x, %y
510   %z0 = extractelement <4 x i32> %z, i32 0
511   %z1 = extractelement <4 x i32> %z, i32 1
512   %z01 = or i32 %z0, %z1
513   %z2 = extractelement <4 x i32> %z, i32 2
514   %z012 = or i32 %z01, %z2
515   %z3 = extractelement <4 x i32> %z, i32 3
516   %z0123 = or i32 %z3, %z012
517   ret i32 %z0123
520 define i32 @ext_ext_partial_add_reduction_v4i32(<4 x i32> %x) {
521 ; CHECK-LABEL: @ext_ext_partial_add_reduction_v4i32(
522 ; CHECK-NEXT:    [[SHIFT:%.*]] = shufflevector <4 x i32> [[X:%.*]], <4 x i32> poison, <4 x i32> <i32 1, i32 poison, i32 poison, i32 poison>
523 ; CHECK-NEXT:    [[TMP1:%.*]] = add <4 x i32> [[SHIFT]], [[X]]
524 ; CHECK-NEXT:    [[SHIFT1:%.*]] = shufflevector <4 x i32> [[X]], <4 x i32> poison, <4 x i32> <i32 2, i32 poison, i32 poison, i32 poison>
525 ; CHECK-NEXT:    [[TMP2:%.*]] = add <4 x i32> [[SHIFT1]], [[TMP1]]
526 ; CHECK-NEXT:    [[X210:%.*]] = extractelement <4 x i32> [[TMP2]], i64 0
527 ; CHECK-NEXT:    ret i32 [[X210]]
529   %x0 = extractelement <4 x i32> %x, i32 0
530   %x1 = extractelement <4 x i32> %x, i32 1
531   %x10 = add i32 %x1, %x0
532   %x2 = extractelement <4 x i32> %x, i32 2
533   %x210 = add i32 %x2, %x10
534   ret i32 %x210
537 define i32 @ext_ext_partial_add_reduction_and_extra_add_v4i32(<4 x i32> %x, <4 x i32> %y) {
538 ; CHECK-LABEL: @ext_ext_partial_add_reduction_and_extra_add_v4i32(
539 ; CHECK-NEXT:    [[SHIFT:%.*]] = shufflevector <4 x i32> [[Y:%.*]], <4 x i32> poison, <4 x i32> <i32 1, i32 poison, i32 poison, i32 poison>
540 ; CHECK-NEXT:    [[TMP1:%.*]] = add <4 x i32> [[SHIFT]], [[Y]]
541 ; CHECK-NEXT:    [[SHIFT1:%.*]] = shufflevector <4 x i32> [[Y]], <4 x i32> poison, <4 x i32> <i32 2, i32 poison, i32 poison, i32 poison>
542 ; CHECK-NEXT:    [[TMP2:%.*]] = add <4 x i32> [[SHIFT1]], [[TMP1]]
543 ; CHECK-NEXT:    [[SHIFT2:%.*]] = shufflevector <4 x i32> [[X:%.*]], <4 x i32> poison, <4 x i32> <i32 2, i32 poison, i32 poison, i32 poison>
544 ; CHECK-NEXT:    [[TMP3:%.*]] = add <4 x i32> [[SHIFT2]], [[TMP2]]
545 ; CHECK-NEXT:    [[X2Y210:%.*]] = extractelement <4 x i32> [[TMP3]], i64 0
546 ; CHECK-NEXT:    ret i32 [[X2Y210]]
548   %y0 = extractelement <4 x i32> %y, i32 0
549   %y1 = extractelement <4 x i32> %y, i32 1
550   %y10 = add i32 %y1, %y0
551   %y2 = extractelement <4 x i32> %y, i32 2
552   %y210 = add i32 %y2, %y10
553   %x2 = extractelement <4 x i32> %x, i32 2
554   %x2y210 = add i32 %x2, %y210
555   ret i32 %x2y210
558 define i32 @constant_fold_crash(<4 x i32> %x) {
559 ; CHECK-LABEL: @constant_fold_crash(
560 ; CHECK-NEXT:    [[A:%.*]] = extractelement <4 x i32> <i32 16, i32 17, i32 18, i32 19>, i32 1
561 ; CHECK-NEXT:    [[B:%.*]] = extractelement <4 x i32> [[X:%.*]], i32 0
562 ; CHECK-NEXT:    [[C:%.*]] = add i32 [[A]], [[B]]
563 ; CHECK-NEXT:    ret i32 [[C]]
565   %a = extractelement <4 x i32> <i32 16, i32 17, i32 18, i32 19>, i32 1
566   %b = extractelement <4 x i32> %x, i32 0
567   %c = add i32 %a, %b
568   ret i32 %c
571 define float @constant_fold_crash_commute(<4 x float> %x) {
572 ; CHECK-LABEL: @constant_fold_crash_commute(
573 ; CHECK-NEXT:    [[A:%.*]] = extractelement <4 x float> <float 1.600000e+01, float 1.700000e+01, float 1.800000e+01, float 1.900000e+01>, i32 3
574 ; CHECK-NEXT:    [[B:%.*]] = extractelement <4 x float> [[X:%.*]], i32 1
575 ; CHECK-NEXT:    [[C:%.*]] = fadd float [[B]], [[A]]
576 ; CHECK-NEXT:    ret float [[C]]
578   %a = extractelement <4 x float> <float 16.0, float 17.0, float 18.0, float 19.0>, i32 3
579   %b = extractelement <4 x float> %x, i32 1
580   %c = fadd float %b, %a
581   ret float %c