[TableGen] Fix validateOperandClass for non Phyical Reg (#118146)
[llvm-project.git] / llvm / test / Transforms / VectorCombine / X86 / extract-binop-inseltpoison.ll
blob3cf2940e86808eff10ecdacb22fc45df8dde5d3e
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 ; CHECK-LABEL: @ext13_ext13_mul(
55 ; CHECK-NEXT:    [[E0:%.*]] = extractelement <16 x i8> [[X:%.*]], i32 13
56 ; CHECK-NEXT:    [[E1:%.*]] = extractelement <16 x i8> [[Y:%.*]], i32 13
57 ; CHECK-NEXT:    [[R:%.*]] = mul i8 [[E0]], [[E1]]
58 ; CHECK-NEXT:    ret i8 [[R]]
60   %e0 = extractelement <16 x i8> %x, i32 13
61   %e1 = extractelement <16 x i8> %y, i32 13
62   %r = mul i8 %e0, %e1
63   ret i8 %r
66 ; Negative test - cost is irrelevant because sdiv has potential UB.
68 define i8 @ext0_ext0_sdiv(<16 x i8> %x, <16 x i8> %y) {
69 ; CHECK-LABEL: @ext0_ext0_sdiv(
70 ; CHECK-NEXT:    [[E0:%.*]] = extractelement <16 x i8> [[X:%.*]], i32 0
71 ; CHECK-NEXT:    [[E1:%.*]] = extractelement <16 x i8> [[Y:%.*]], i32 0
72 ; CHECK-NEXT:    [[R:%.*]] = sdiv i8 [[E0]], [[E1]]
73 ; CHECK-NEXT:    ret i8 [[R]]
75   %e0 = extractelement <16 x i8> %x, i32 0
76   %e1 = extractelement <16 x i8> %y, i32 0
77   %r = sdiv i8 %e0, %e1
78   ret i8 %r
81 ; Extracts are free and vector op has same cost as scalar, but we
82 ; speculatively transform to vector to create more optimization
83 ; opportunities..
85 define double @ext0_ext0_fadd(<2 x double> %x, <2 x double> %y) {
86 ; CHECK-LABEL: @ext0_ext0_fadd(
87 ; CHECK-NEXT:    [[TMP1:%.*]] = fadd <2 x double> [[X:%.*]], [[Y:%.*]]
88 ; CHECK-NEXT:    [[R:%.*]] = extractelement <2 x double> [[TMP1]], i32 0
89 ; CHECK-NEXT:    ret double [[R]]
91   %e0 = extractelement <2 x double> %x, i32 0
92   %e1 = extractelement <2 x double> %y, i32 0
93   %r = fadd double %e0, %e1
94   ret double %r
97 ; Eliminating extract is profitable. Flags propagate.
99 define double @ext1_ext1_fsub(<2 x double> %x, <2 x double> %y) {
100 ; CHECK-LABEL: @ext1_ext1_fsub(
101 ; CHECK-NEXT:    [[TMP1:%.*]] = fsub fast <2 x double> [[X:%.*]], [[Y:%.*]]
102 ; CHECK-NEXT:    [[R:%.*]] = extractelement <2 x double> [[TMP1]], i32 1
103 ; CHECK-NEXT:    ret double [[R]]
105   %e0 = extractelement <2 x double> %x, i32 1
106   %e1 = extractelement <2 x double> %y, i32 1
107   %r = fsub fast double %e0, %e1
108   ret double %r
111 ; Negative test - type mismatch.
113 define double @ext1_ext1_fadd_different_types(<2 x double> %x, <4 x double> %y) {
114 ; CHECK-LABEL: @ext1_ext1_fadd_different_types(
115 ; CHECK-NEXT:    [[E0:%.*]] = extractelement <2 x double> [[X:%.*]], i32 1
116 ; CHECK-NEXT:    [[E1:%.*]] = extractelement <4 x double> [[Y:%.*]], i32 1
117 ; CHECK-NEXT:    [[R:%.*]] = fadd fast double [[E0]], [[E1]]
118 ; CHECK-NEXT:    ret double [[R]]
120   %e0 = extractelement <2 x double> %x, i32 1
121   %e1 = extractelement <4 x double> %y, i32 1
122   %r = fadd fast double %e0, %e1
123   ret double %r
126 ; Disguised same vector operand; scalar code is not cheaper (with default
127 ; x86 target), so aggressively form vector binop.
129 define i32 @ext1_ext1_add_same_vec(<4 x i32> %x) {
130 ; CHECK-LABEL: @ext1_ext1_add_same_vec(
131 ; CHECK-NEXT:    [[TMP1:%.*]] = add <4 x i32> [[X:%.*]], [[X]]
132 ; CHECK-NEXT:    [[R:%.*]] = extractelement <4 x i32> [[TMP1]], i32 1
133 ; CHECK-NEXT:    ret i32 [[R]]
135   %e0 = extractelement <4 x i32> %x, i32 1
136   %e1 = extractelement <4 x i32> %x, i32 1
137   %r = add i32 %e0, %e1
138   ret i32 %r
141 ; Functionally equivalent to above test; should transform as above.
143 define i32 @ext1_ext1_add_same_vec_cse(<4 x i32> %x) {
144 ; CHECK-LABEL: @ext1_ext1_add_same_vec_cse(
145 ; CHECK-NEXT:    [[TMP1:%.*]] = add <4 x i32> [[X:%.*]], [[X]]
146 ; CHECK-NEXT:    [[R:%.*]] = extractelement <4 x i32> [[TMP1]], i32 1
147 ; CHECK-NEXT:    ret i32 [[R]]
149   %e0 = extractelement <4 x i32> %x, i32 1
150   %r = add i32 %e0, %e0
151   ret i32 %r
154 ; Don't assert if extract indices have different types.
156 define i32 @ext1_ext1_add_same_vec_diff_idx_ty(<4 x i32> %x) {
157 ; CHECK-LABEL: @ext1_ext1_add_same_vec_diff_idx_ty(
158 ; CHECK-NEXT:    [[TMP1:%.*]] = add <4 x i32> [[X:%.*]], [[X]]
159 ; CHECK-NEXT:    [[R:%.*]] = extractelement <4 x i32> [[TMP1]], i32 1
160 ; CHECK-NEXT:    ret i32 [[R]]
162   %e0 = extractelement <4 x i32> %x, i32 1
163   %e1 = extractelement <4 x i32> %x, i64 1
164   %r = add i32 %e0, %e1
165   ret i32 %r
168 ; Negative test - same vector operand; scalar code is cheaper than general case
169 ;                 and vector code would be more expensive still.
171 define i8 @ext1_ext1_add_same_vec_extra_use0(<16 x i8> %x) {
172 ; CHECK-LABEL: @ext1_ext1_add_same_vec_extra_use0(
173 ; CHECK-NEXT:    [[E0:%.*]] = extractelement <16 x i8> [[X:%.*]], i32 0
174 ; CHECK-NEXT:    call void @use_i8(i8 [[E0]])
175 ; CHECK-NEXT:    [[E1:%.*]] = extractelement <16 x i8> [[X]], i32 0
176 ; CHECK-NEXT:    [[R:%.*]] = add i8 [[E0]], [[E1]]
177 ; CHECK-NEXT:    ret i8 [[R]]
179   %e0 = extractelement <16 x i8> %x, i32 0
180   call void @use_i8(i8 %e0)
181   %e1 = extractelement <16 x i8> %x, i32 0
182   %r = add i8 %e0, %e1
183   ret i8 %r
186 ; Negative test - same vector operand; scalar code is cheaper than general case
187 ;                 and vector code would be more expensive still.
189 define i8 @ext1_ext1_add_same_vec_extra_use1(<16 x i8> %x) {
190 ; CHECK-LABEL: @ext1_ext1_add_same_vec_extra_use1(
191 ; CHECK-NEXT:    [[E0:%.*]] = extractelement <16 x i8> [[X:%.*]], i32 0
192 ; CHECK-NEXT:    [[E1:%.*]] = extractelement <16 x i8> [[X]], i32 0
193 ; CHECK-NEXT:    call void @use_i8(i8 [[E1]])
194 ; CHECK-NEXT:    [[R:%.*]] = add i8 [[E0]], [[E1]]
195 ; CHECK-NEXT:    ret i8 [[R]]
197   %e0 = extractelement <16 x i8> %x, i32 0
198   %e1 = extractelement <16 x i8> %x, i32 0
199   call void @use_i8(i8 %e1)
200   %r = add i8 %e0, %e1
201   ret i8 %r
204 ; Negative test - same vector operand; scalar code is cheaper than general case
205 ;                 and vector code would be more expensive still.
207 define i8 @ext1_ext1_add_same_vec_cse_extra_use(<16 x i8> %x) {
208 ; CHECK-LABEL: @ext1_ext1_add_same_vec_cse_extra_use(
209 ; CHECK-NEXT:    [[E:%.*]] = extractelement <16 x i8> [[X:%.*]], i32 0
210 ; CHECK-NEXT:    call void @use_i8(i8 [[E]])
211 ; CHECK-NEXT:    [[R:%.*]] = add i8 [[E]], [[E]]
212 ; CHECK-NEXT:    ret i8 [[R]]
214   %e = extractelement <16 x i8> %x, i32 0
215   call void @use_i8(i8 %e)
216   %r = add i8 %e, %e
217   ret i8 %r
220 ; Vector code costs the same as scalar, so aggressively form vector op.
222 define i8 @ext1_ext1_add_uses1(<16 x i8> %x, <16 x i8> %y) {
223 ; CHECK-LABEL: @ext1_ext1_add_uses1(
224 ; CHECK-NEXT:    [[E0:%.*]] = extractelement <16 x i8> [[X:%.*]], i32 0
225 ; CHECK-NEXT:    call void @use_i8(i8 [[E0]])
226 ; CHECK-NEXT:    [[TMP1:%.*]] = add <16 x i8> [[X]], [[Y:%.*]]
227 ; CHECK-NEXT:    [[R:%.*]] = extractelement <16 x i8> [[TMP1]], i32 0
228 ; CHECK-NEXT:    ret i8 [[R]]
230   %e0 = extractelement <16 x i8> %x, i32 0
231   call void @use_i8(i8 %e0)
232   %e1 = extractelement <16 x i8> %y, i32 0
233   %r = add i8 %e0, %e1
234   ret i8 %r
237 ; Vector code costs the same as scalar, so aggressively form vector op.
239 define i8 @ext1_ext1_add_uses2(<16 x i8> %x, <16 x i8> %y) {
240 ; CHECK-LABEL: @ext1_ext1_add_uses2(
241 ; CHECK-NEXT:    [[E1:%.*]] = extractelement <16 x i8> [[Y:%.*]], i32 0
242 ; CHECK-NEXT:    call void @use_i8(i8 [[E1]])
243 ; CHECK-NEXT:    [[TMP1:%.*]] = add <16 x i8> [[X:%.*]], [[Y]]
244 ; CHECK-NEXT:    [[R:%.*]] = extractelement <16 x i8> [[TMP1]], i32 0
245 ; CHECK-NEXT:    ret i8 [[R]]
247   %e0 = extractelement <16 x i8> %x, i32 0
248   %e1 = extractelement <16 x i8> %y, i32 0
249   call void @use_i8(i8 %e1)
250   %r = add i8 %e0, %e1
251   ret i8 %r
254 define i8 @ext0_ext1_add(<16 x i8> %x, <16 x i8> %y) {
255 ; SSE-LABEL: @ext0_ext1_add(
256 ; SSE-NEXT:    [[E0:%.*]] = extractelement <16 x i8> [[X:%.*]], i32 0
257 ; SSE-NEXT:    [[E1:%.*]] = extractelement <16 x i8> [[Y:%.*]], i32 1
258 ; SSE-NEXT:    [[R:%.*]] = add nuw i8 [[E0]], [[E1]]
259 ; SSE-NEXT:    ret i8 [[R]]
261 ; AVX-LABEL: @ext0_ext1_add(
262 ; 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>
263 ; AVX-NEXT:    [[TMP1:%.*]] = add nuw <16 x i8> [[X:%.*]], [[SHIFT]]
264 ; AVX-NEXT:    [[R:%.*]] = extractelement <16 x i8> [[TMP1]], i32 0
265 ; AVX-NEXT:    ret i8 [[R]]
267   %e0 = extractelement <16 x i8> %x, i32 0
268   %e1 = extractelement <16 x i8> %y, i32 1
269   %r = add nuw i8 %e0, %e1
270   ret i8 %r
273 define i8 @ext5_ext0_add(<16 x i8> %x, <16 x i8> %y) {
274 ; SSE-LABEL: @ext5_ext0_add(
275 ; SSE-NEXT:    [[E0:%.*]] = extractelement <16 x i8> [[X:%.*]], i32 5
276 ; SSE-NEXT:    [[E1:%.*]] = extractelement <16 x i8> [[Y:%.*]], i32 0
277 ; SSE-NEXT:    [[R:%.*]] = sub nsw i8 [[E0]], [[E1]]
278 ; SSE-NEXT:    ret i8 [[R]]
280 ; AVX-LABEL: @ext5_ext0_add(
281 ; 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>
282 ; AVX-NEXT:    [[TMP1:%.*]] = sub nsw <16 x i8> [[SHIFT]], [[Y:%.*]]
283 ; AVX-NEXT:    [[R:%.*]] = extractelement <16 x i8> [[TMP1]], i64 0
284 ; AVX-NEXT:    ret i8 [[R]]
286   %e0 = extractelement <16 x i8> %x, i32 5
287   %e1 = extractelement <16 x i8> %y, i32 0
288   %r = sub nsw i8 %e0, %e1
289   ret i8 %r
292 define i8 @ext1_ext6_add(<16 x i8> %x, <16 x i8> %y) {
293 ; SSE-LABEL: @ext1_ext6_add(
294 ; SSE-NEXT:    [[E0:%.*]] = extractelement <16 x i8> [[X:%.*]], i32 1
295 ; SSE-NEXT:    [[E1:%.*]] = extractelement <16 x i8> [[Y:%.*]], i32 6
296 ; SSE-NEXT:    [[R:%.*]] = and i8 [[E0]], [[E1]]
297 ; SSE-NEXT:    ret i8 [[R]]
299 ; AVX-LABEL: @ext1_ext6_add(
300 ; 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>
301 ; AVX-NEXT:    [[TMP1:%.*]] = and <16 x i8> [[X:%.*]], [[SHIFT]]
302 ; AVX-NEXT:    [[R:%.*]] = extractelement <16 x i8> [[TMP1]], i32 1
303 ; AVX-NEXT:    ret i8 [[R]]
305   %e0 = extractelement <16 x i8> %x, i32 1
306   %e1 = extractelement <16 x i8> %y, i32 6
307   %r = and i8 %e0, %e1
308   ret i8 %r
311 define float @ext1_ext0_fmul(<4 x float> %x) {
312 ; CHECK-LABEL: @ext1_ext0_fmul(
313 ; CHECK-NEXT:    [[SHIFT:%.*]] = shufflevector <4 x float> [[X:%.*]], <4 x float> poison, <4 x i32> <i32 1, i32 poison, i32 poison, i32 poison>
314 ; CHECK-NEXT:    [[TMP1:%.*]] = fmul <4 x float> [[SHIFT]], [[X]]
315 ; CHECK-NEXT:    [[R:%.*]] = extractelement <4 x float> [[TMP1]], i64 0
316 ; CHECK-NEXT:    ret float [[R]]
318   %e0 = extractelement <4 x float> %x, i32 1
319   %e1 = extractelement <4 x float> %x, i32 0
320   %r = fmul float %e0, %e1
321   ret float %r
324 define float @ext0_ext3_fmul_extra_use1(<4 x float> %x) {
325 ; CHECK-LABEL: @ext0_ext3_fmul_extra_use1(
326 ; CHECK-NEXT:    [[E0:%.*]] = extractelement <4 x float> [[X:%.*]], i32 0
327 ; CHECK-NEXT:    call void @use_f32(float [[E0]])
328 ; CHECK-NEXT:    [[SHIFT:%.*]] = shufflevector <4 x float> [[X]], <4 x float> poison, <4 x i32> <i32 3, i32 poison, i32 poison, i32 poison>
329 ; CHECK-NEXT:    [[TMP1:%.*]] = fmul nnan <4 x float> [[X]], [[SHIFT]]
330 ; CHECK-NEXT:    [[R:%.*]] = extractelement <4 x float> [[TMP1]], i32 0
331 ; CHECK-NEXT:    ret float [[R]]
333   %e0 = extractelement <4 x float> %x, i32 0
334   call void @use_f32(float %e0)
335   %e1 = extractelement <4 x float> %x, i32 3
336   %r = fmul nnan float %e0, %e1
337   ret float %r
340 define float @ext0_ext3_fmul_extra_use2(<4 x float> %x) {
341 ; CHECK-LABEL: @ext0_ext3_fmul_extra_use2(
342 ; CHECK-NEXT:    [[E0:%.*]] = extractelement <4 x float> [[X:%.*]], i32 0
343 ; CHECK-NEXT:    [[E1:%.*]] = extractelement <4 x float> [[X]], i32 3
344 ; CHECK-NEXT:    call void @use_f32(float [[E1]])
345 ; CHECK-NEXT:    [[R:%.*]] = fmul ninf nsz float [[E0]], [[E1]]
346 ; CHECK-NEXT:    ret float [[R]]
348   %e0 = extractelement <4 x float> %x, i32 0
349   %e1 = extractelement <4 x float> %x, i32 3
350   call void @use_f32(float %e1)
351   %r = fmul ninf nsz float %e0, %e1
352   ret float %r
355 define float @ext0_ext4_fmul_v8f32(<8 x float> %x) {
356 ; SSE-LABEL: @ext0_ext4_fmul_v8f32(
357 ; SSE-NEXT:    [[E0:%.*]] = extractelement <8 x float> [[X:%.*]], i32 0
358 ; SSE-NEXT:    [[E1:%.*]] = extractelement <8 x float> [[X]], i32 4
359 ; SSE-NEXT:    [[R:%.*]] = fadd float [[E0]], [[E1]]
360 ; SSE-NEXT:    ret float [[R]]
362 ; AVX-LABEL: @ext0_ext4_fmul_v8f32(
363 ; 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>
364 ; AVX-NEXT:    [[TMP1:%.*]] = fadd <8 x float> [[X]], [[SHIFT]]
365 ; AVX-NEXT:    [[R:%.*]] = extractelement <8 x float> [[TMP1]], i32 0
366 ; AVX-NEXT:    ret float [[R]]
368   %e0 = extractelement <8 x float> %x, i32 0
369   %e1 = extractelement <8 x float> %x, i32 4
370   %r = fadd float %e0, %e1
371   ret float %r
374 define float @ext7_ext4_fmul_v8f32(<8 x float> %x) {
375 ; SSE-LABEL: @ext7_ext4_fmul_v8f32(
376 ; SSE-NEXT:    [[E0:%.*]] = extractelement <8 x float> [[X:%.*]], i32 7
377 ; SSE-NEXT:    [[E1:%.*]] = extractelement <8 x float> [[X]], i32 4
378 ; SSE-NEXT:    [[R:%.*]] = fadd float [[E0]], [[E1]]
379 ; SSE-NEXT:    ret float [[R]]
381 ; AVX-LABEL: @ext7_ext4_fmul_v8f32(
382 ; 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>
383 ; AVX-NEXT:    [[TMP1:%.*]] = fadd <8 x float> [[SHIFT]], [[X]]
384 ; AVX-NEXT:    [[R:%.*]] = extractelement <8 x float> [[TMP1]], i64 4
385 ; AVX-NEXT:    ret float [[R]]
387   %e0 = extractelement <8 x float> %x, i32 7
388   %e1 = extractelement <8 x float> %x, i32 4
389   %r = fadd float %e0, %e1
390   ret float %r
393 define float @ext0_ext8_fmul_v16f32(<16 x float> %x) {
394 ; CHECK-LABEL: @ext0_ext8_fmul_v16f32(
395 ; CHECK-NEXT:    [[E0:%.*]] = extractelement <16 x float> [[X:%.*]], i32 0
396 ; CHECK-NEXT:    [[E1:%.*]] = extractelement <16 x float> [[X]], i32 8
397 ; CHECK-NEXT:    [[R:%.*]] = fadd float [[E0]], [[E1]]
398 ; CHECK-NEXT:    ret float [[R]]
400   %e0 = extractelement <16 x float> %x, i32 0
401   %e1 = extractelement <16 x float> %x, i32 8
402   %r = fadd float %e0, %e1
403   ret float %r
406 define float @ext14_ext15_fmul_v16f32(<16 x float> %x) {
407 ; SSE-LABEL: @ext14_ext15_fmul_v16f32(
408 ; SSE-NEXT:    [[E0:%.*]] = extractelement <16 x float> [[X:%.*]], i32 14
409 ; SSE-NEXT:    [[E1:%.*]] = extractelement <16 x float> [[X]], i32 15
410 ; SSE-NEXT:    [[R:%.*]] = fadd float [[E0]], [[E1]]
411 ; SSE-NEXT:    ret float [[R]]
413 ; AVX-LABEL: @ext14_ext15_fmul_v16f32(
414 ; AVX-NEXT:    [[SHIFT:%.*]] = shufflevector <16 x float> [[X:%.*]], <16 x float> poison, <16 x i32> <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 15, i32 poison>
415 ; AVX-NEXT:    [[TMP1:%.*]] = fadd <16 x float> [[X]], [[SHIFT]]
416 ; AVX-NEXT:    [[R:%.*]] = extractelement <16 x float> [[TMP1]], i32 14
417 ; AVX-NEXT:    ret float [[R]]
419   %e0 = extractelement <16 x float> %x, i32 14
420   %e1 = extractelement <16 x float> %x, i32 15
421   %r = fadd float %e0, %e1
422   ret float %r
425 define <4 x float> @ins_bo_ext_ext(<4 x float> %a, <4 x float> %b) {
426 ; CHECK-LABEL: @ins_bo_ext_ext(
427 ; CHECK-NEXT:    [[SHIFT:%.*]] = shufflevector <4 x float> [[A:%.*]], <4 x float> poison, <4 x i32> <i32 poison, i32 poison, i32 poison, i32 2>
428 ; CHECK-NEXT:    [[TMP1:%.*]] = fadd <4 x float> [[SHIFT]], [[A]]
429 ; CHECK-NEXT:    [[V3:%.*]] = shufflevector <4 x float> [[B:%.*]], <4 x float> [[TMP1]], <4 x i32> <i32 0, i32 1, i32 2, i32 7>
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 ; SSE-LABEL: @ins_bo_ext_ext_uses(
444 ; SSE-NEXT:    [[SHIFT:%.*]] = shufflevector <4 x float> [[A:%.*]], <4 x float> poison, <4 x i32> <i32 poison, i32 poison, i32 3, i32 poison>
445 ; SSE-NEXT:    [[TMP1:%.*]] = fadd <4 x float> [[A]], [[SHIFT]]
446 ; SSE-NEXT:    [[A23:%.*]] = extractelement <4 x float> [[TMP1]], i32 2
447 ; SSE-NEXT:    call void @use_f32(float [[A23]])
448 ; SSE-NEXT:    [[V3:%.*]] = shufflevector <4 x float> [[B:%.*]], <4 x float> [[TMP1]], <4 x i32> <i32 0, i32 1, i32 2, i32 6>
449 ; SSE-NEXT:    ret <4 x float> [[V3]]
451 ; AVX-LABEL: @ins_bo_ext_ext_uses(
452 ; AVX-NEXT:    [[SHIFT:%.*]] = shufflevector <4 x float> [[A:%.*]], <4 x float> poison, <4 x i32> <i32 poison, i32 poison, i32 3, i32 poison>
453 ; AVX-NEXT:    [[TMP1:%.*]] = fadd <4 x float> [[A]], [[SHIFT]]
454 ; AVX-NEXT:    [[A23:%.*]] = extractelement <4 x float> [[TMP1]], i32 2
455 ; AVX-NEXT:    call void @use_f32(float [[A23]])
456 ; AVX-NEXT:    [[V3:%.*]] = insertelement <4 x float> [[B:%.*]], float [[A23]], i32 3
457 ; AVX-NEXT:    ret <4 x float> [[V3]]
459   %a2 = extractelement <4 x float> %a, i32 2
460   %a3 = extractelement <4 x float> %a, i32 3
461   %a23 = fadd float %a2, %a3
462   call void @use_f32(float %a23)
463   %v3 = insertelement <4 x float> %b, float %a23, i32 3
464   ret <4 x float> %v3
467 define <4 x float> @PR34724(<4 x float> %a, <4 x float> %b) {
468 ; SSE-LABEL: @PR34724(
469 ; SSE-NEXT:    [[A0:%.*]] = extractelement <4 x float> [[A:%.*]], i32 0
470 ; SSE-NEXT:    [[A1:%.*]] = extractelement <4 x float> [[A]], i32 1
471 ; SSE-NEXT:    [[SHIFT:%.*]] = shufflevector <4 x float> [[A]], <4 x float> poison, <4 x i32> <i32 poison, i32 poison, i32 3, i32 poison>
472 ; SSE-NEXT:    [[TMP1:%.*]] = fadd <4 x float> [[A]], [[SHIFT]]
473 ; SSE-NEXT:    [[SHIFT1:%.*]] = shufflevector <4 x float> [[B:%.*]], <4 x float> poison, <4 x i32> <i32 1, i32 poison, i32 poison, i32 poison>
474 ; SSE-NEXT:    [[TMP2:%.*]] = fadd <4 x float> [[B]], [[SHIFT1]]
475 ; SSE-NEXT:    [[SHIFT2:%.*]] = shufflevector <4 x float> [[B]], <4 x float> poison, <4 x i32> <i32 poison, i32 poison, i32 poison, i32 2>
476 ; SSE-NEXT:    [[TMP3:%.*]] = fadd <4 x float> [[SHIFT2]], [[B]]
477 ; SSE-NEXT:    [[V1:%.*]] = shufflevector <4 x float> poison, <4 x float> [[TMP1]], <4 x i32> <i32 0, i32 6, i32 2, i32 3>
478 ; SSE-NEXT:    [[V2:%.*]] = shufflevector <4 x float> [[V1]], <4 x float> [[TMP2]], <4 x i32> <i32 0, i32 1, i32 4, i32 3>
479 ; SSE-NEXT:    [[V3:%.*]] = shufflevector <4 x float> [[V2]], <4 x float> [[TMP3]], <4 x i32> <i32 0, i32 1, i32 2, i32 7>
480 ; SSE-NEXT:    ret <4 x float> [[V3]]
482 ; AVX-LABEL: @PR34724(
483 ; AVX-NEXT:    [[A0:%.*]] = extractelement <4 x float> [[A:%.*]], i32 0
484 ; AVX-NEXT:    [[A1:%.*]] = extractelement <4 x float> [[A]], i32 1
485 ; AVX-NEXT:    [[SHIFT:%.*]] = shufflevector <4 x float> [[A]], <4 x float> poison, <4 x i32> <i32 poison, i32 poison, i32 3, i32 poison>
486 ; AVX-NEXT:    [[TMP1:%.*]] = fadd <4 x float> [[A]], [[SHIFT]]
487 ; AVX-NEXT:    [[SHIFT1:%.*]] = shufflevector <4 x float> [[B:%.*]], <4 x float> poison, <4 x i32> <i32 1, i32 poison, i32 poison, i32 poison>
488 ; AVX-NEXT:    [[TMP2:%.*]] = fadd <4 x float> [[B]], [[SHIFT1]]
489 ; AVX-NEXT:    [[B01:%.*]] = extractelement <4 x float> [[TMP2]], i32 0
490 ; AVX-NEXT:    [[SHIFT2:%.*]] = shufflevector <4 x float> [[B]], <4 x float> poison, <4 x i32> <i32 poison, i32 poison, i32 poison, i32 2>
491 ; AVX-NEXT:    [[TMP3:%.*]] = fadd <4 x float> [[SHIFT2]], [[B]]
492 ; AVX-NEXT:    [[V1:%.*]] = shufflevector <4 x float> poison, <4 x float> [[TMP1]], <4 x i32> <i32 0, i32 6, i32 2, i32 3>
493 ; AVX-NEXT:    [[V2:%.*]] = insertelement <4 x float> [[V1]], float [[B01]], i32 2
494 ; AVX-NEXT:    [[V3:%.*]] = shufflevector <4 x float> [[V2]], <4 x float> [[TMP3]], <4 x i32> <i32 0, i32 1, i32 2, i32 7>
495 ; AVX-NEXT:    ret <4 x float> [[V3]]
497   %a0 = extractelement <4 x float> %a, i32 0
498   %a1 = extractelement <4 x float> %a, i32 1
499   %a2 = extractelement <4 x float> %a, i32 2
500   %a3 = extractelement <4 x float> %a, i32 3
502   %b0 = extractelement <4 x float> %b, i32 0
503   %b1 = extractelement <4 x float> %b, i32 1
504   %b2 = extractelement <4 x float> %b, i32 2
505   %b3 = extractelement <4 x float> %b, i32 3
507   %a23 = fadd float %a2, %a3
508   %b01 = fadd float %b0, %b1
509   %b23 = fadd float %b2, %b3
511   %v1 = insertelement <4 x float> poison, float %a23, i32 1
512   %v2 = insertelement <4 x float> %v1, float %b01, i32 2
513   %v3 = insertelement <4 x float> %v2, float %b23, i32 3
514   ret <4 x float> %v3
517 define i32 @ext_ext_or_reduction_v4i32(<4 x i32> %x, <4 x i32> %y) {
518 ; CHECK-LABEL: @ext_ext_or_reduction_v4i32(
519 ; CHECK-NEXT:    [[Z:%.*]] = and <4 x i32> [[X:%.*]], [[Y:%.*]]
520 ; CHECK-NEXT:    [[SHIFT:%.*]] = shufflevector <4 x i32> [[Z]], <4 x i32> poison, <4 x i32> <i32 1, i32 poison, i32 poison, i32 poison>
521 ; CHECK-NEXT:    [[TMP1:%.*]] = or <4 x i32> [[Z]], [[SHIFT]]
522 ; CHECK-NEXT:    [[SHIFT1:%.*]] = shufflevector <4 x i32> [[Z]], <4 x i32> poison, <4 x i32> <i32 2, i32 poison, i32 poison, i32 poison>
523 ; CHECK-NEXT:    [[TMP2:%.*]] = or <4 x i32> [[TMP1]], [[SHIFT1]]
524 ; CHECK-NEXT:    [[SHIFT2:%.*]] = shufflevector <4 x i32> [[Z]], <4 x i32> poison, <4 x i32> <i32 3, i32 poison, i32 poison, i32 poison>
525 ; CHECK-NEXT:    [[TMP3:%.*]] = or <4 x i32> [[SHIFT2]], [[TMP2]]
526 ; CHECK-NEXT:    [[Z0123:%.*]] = extractelement <4 x i32> [[TMP3]], i64 0
527 ; CHECK-NEXT:    ret i32 [[Z0123]]
529   %z = and <4 x i32> %x, %y
530   %z0 = extractelement <4 x i32> %z, i32 0
531   %z1 = extractelement <4 x i32> %z, i32 1
532   %z01 = or i32 %z0, %z1
533   %z2 = extractelement <4 x i32> %z, i32 2
534   %z012 = or i32 %z01, %z2
535   %z3 = extractelement <4 x i32> %z, i32 3
536   %z0123 = or i32 %z3, %z012
537   ret i32 %z0123
540 define i32 @ext_ext_partial_add_reduction_v4i32(<4 x i32> %x) {
541 ; CHECK-LABEL: @ext_ext_partial_add_reduction_v4i32(
542 ; CHECK-NEXT:    [[SHIFT:%.*]] = shufflevector <4 x i32> [[X:%.*]], <4 x i32> poison, <4 x i32> <i32 1, i32 poison, i32 poison, i32 poison>
543 ; CHECK-NEXT:    [[TMP1:%.*]] = add <4 x i32> [[SHIFT]], [[X]]
544 ; CHECK-NEXT:    [[SHIFT1:%.*]] = shufflevector <4 x i32> [[X]], <4 x i32> poison, <4 x i32> <i32 2, i32 poison, i32 poison, i32 poison>
545 ; CHECK-NEXT:    [[TMP2:%.*]] = add <4 x i32> [[SHIFT1]], [[TMP1]]
546 ; CHECK-NEXT:    [[X210:%.*]] = extractelement <4 x i32> [[TMP2]], i64 0
547 ; CHECK-NEXT:    ret i32 [[X210]]
549   %x0 = extractelement <4 x i32> %x, i32 0
550   %x1 = extractelement <4 x i32> %x, i32 1
551   %x10 = add i32 %x1, %x0
552   %x2 = extractelement <4 x i32> %x, i32 2
553   %x210 = add i32 %x2, %x10
554   ret i32 %x210
557 define i32 @ext_ext_partial_add_reduction_and_extra_add_v4i32(<4 x i32> %x, <4 x i32> %y) {
558 ; CHECK-LABEL: @ext_ext_partial_add_reduction_and_extra_add_v4i32(
559 ; CHECK-NEXT:    [[SHIFT:%.*]] = shufflevector <4 x i32> [[Y:%.*]], <4 x i32> poison, <4 x i32> <i32 1, i32 poison, i32 poison, i32 poison>
560 ; CHECK-NEXT:    [[TMP1:%.*]] = add <4 x i32> [[SHIFT]], [[Y]]
561 ; CHECK-NEXT:    [[SHIFT1:%.*]] = shufflevector <4 x i32> [[Y]], <4 x i32> poison, <4 x i32> <i32 2, i32 poison, i32 poison, i32 poison>
562 ; CHECK-NEXT:    [[TMP2:%.*]] = add <4 x i32> [[SHIFT1]], [[TMP1]]
563 ; CHECK-NEXT:    [[SHIFT2:%.*]] = shufflevector <4 x i32> [[X:%.*]], <4 x i32> poison, <4 x i32> <i32 2, i32 poison, i32 poison, i32 poison>
564 ; CHECK-NEXT:    [[TMP3:%.*]] = add <4 x i32> [[SHIFT2]], [[TMP2]]
565 ; CHECK-NEXT:    [[X2Y210:%.*]] = extractelement <4 x i32> [[TMP3]], i64 0
566 ; CHECK-NEXT:    ret i32 [[X2Y210]]
568   %y0 = extractelement <4 x i32> %y, i32 0
569   %y1 = extractelement <4 x i32> %y, i32 1
570   %y10 = add i32 %y1, %y0
571   %y2 = extractelement <4 x i32> %y, i32 2
572   %y210 = add i32 %y2, %y10
573   %x2 = extractelement <4 x i32> %x, i32 2
574   %x2y210 = add i32 %x2, %y210
575   ret i32 %x2y210
578 define i32 @constant_fold_crash(<4 x i32> %x) {
579 ; CHECK-LABEL: @constant_fold_crash(
580 ; CHECK-NEXT:    [[A:%.*]] = extractelement <4 x i32> <i32 16, i32 17, i32 18, i32 19>, i32 1
581 ; CHECK-NEXT:    [[B:%.*]] = extractelement <4 x i32> [[X:%.*]], i32 0
582 ; CHECK-NEXT:    [[C:%.*]] = add i32 [[A]], [[B]]
583 ; CHECK-NEXT:    ret i32 [[C]]
585   %a = extractelement <4 x i32> <i32 16, i32 17, i32 18, i32 19>, i32 1
586   %b = extractelement <4 x i32> %x, i32 0
587   %c = add i32 %a, %b
588   ret i32 %c
591 define float @constant_fold_crash_commute(<4 x float> %x) {
592 ; CHECK-LABEL: @constant_fold_crash_commute(
593 ; 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
594 ; CHECK-NEXT:    [[B:%.*]] = extractelement <4 x float> [[X:%.*]], i32 1
595 ; CHECK-NEXT:    [[C:%.*]] = fadd float [[B]], [[A]]
596 ; CHECK-NEXT:    ret float [[C]]
598   %a = extractelement <4 x float> <float 16.0, float 17.0, float 18.0, float 19.0>, i32 3
599   %b = extractelement <4 x float> %x, i32 1
600   %c = fadd float %b, %a
601   ret float %c