Home | History | Annotate | Download | only in X86
      1 ; RUN: llc < %s -march=x86-64 -mcpu=corei7 -mattr=+ssse3 | FileCheck %s -check-prefix=CHECK -check-prefix=SSE
      2 ; RUN: llc < %s -march=x86-64 -mcpu=corei7-avx | FileCheck %s -check-prefix=CHECK -check-prefix=AVX
      3 ; RUN: llc < %s -march=x86-64 -mcpu=core-avx2 | FileCheck %s -check-prefix=CHECK -check-prefix=AVX2
      4 
      5 ; Verify that we correctly fold horizontal binop even in the presence of UNDEFs.
      6 
      7 define <4 x float> @test1_undef(<4 x float> %a, <4 x float> %b) {
      8   %vecext = extractelement <4 x float> %a, i32 0
      9   %vecext1 = extractelement <4 x float> %a, i32 1
     10   %add = fadd float %vecext, %vecext1
     11   %vecinit = insertelement <4 x float> undef, float %add, i32 0
     12   %vecext2 = extractelement <4 x float> %a, i32 2
     13   %vecext3 = extractelement <4 x float> %a, i32 3
     14   %add4 = fadd float %vecext2, %vecext3
     15   %vecinit5 = insertelement <4 x float> %vecinit, float %add4, i32 1
     16   %vecext10 = extractelement <4 x float> %b, i32 2
     17   %vecext11 = extractelement <4 x float> %b, i32 3
     18   %add12 = fadd float %vecext10, %vecext11
     19   %vecinit13 = insertelement <4 x float> %vecinit5, float %add12, i32 3
     20   ret <4 x float> %vecinit13
     21 }
     22 ; CHECK-LABEL: test1_undef
     23 ; SSE: haddps
     24 ; AVX: vhaddps
     25 ; AVX2: vhaddps
     26 ; CHECK-NEXT: ret
     27 
     28 
     29 define <4 x float> @test2_undef(<4 x float> %a, <4 x float> %b) {
     30   %vecext = extractelement <4 x float> %a, i32 0
     31   %vecext1 = extractelement <4 x float> %a, i32 1
     32   %add = fadd float %vecext, %vecext1
     33   %vecinit = insertelement <4 x float> undef, float %add, i32 0
     34   %vecext6 = extractelement <4 x float> %b, i32 0
     35   %vecext7 = extractelement <4 x float> %b, i32 1
     36   %add8 = fadd float %vecext6, %vecext7
     37   %vecinit9 = insertelement <4 x float> %vecinit, float %add8, i32 2
     38   %vecext10 = extractelement <4 x float> %b, i32 2
     39   %vecext11 = extractelement <4 x float> %b, i32 3
     40   %add12 = fadd float %vecext10, %vecext11
     41   %vecinit13 = insertelement <4 x float> %vecinit9, float %add12, i32 3
     42   ret <4 x float> %vecinit13
     43 }
     44 ; CHECK-LABEL: test2_undef
     45 ; SSE: haddps
     46 ; AVX: vhaddps
     47 ; AVX2: vhaddps
     48 ; CHECK-NEXT: ret
     49 
     50 
     51 define <4 x float> @test3_undef(<4 x float> %a, <4 x float> %b) {
     52   %vecext = extractelement <4 x float> %a, i32 0
     53   %vecext1 = extractelement <4 x float> %a, i32 1
     54   %add = fadd float %vecext, %vecext1
     55   %vecinit = insertelement <4 x float> undef, float %add, i32 0
     56   %vecext2 = extractelement <4 x float> %a, i32 2
     57   %vecext3 = extractelement <4 x float> %a, i32 3
     58   %add4 = fadd float %vecext2, %vecext3
     59   %vecinit5 = insertelement <4 x float> %vecinit, float %add4, i32 1
     60   %vecext6 = extractelement <4 x float> %b, i32 0
     61   %vecext7 = extractelement <4 x float> %b, i32 1
     62   %add8 = fadd float %vecext6, %vecext7
     63   %vecinit9 = insertelement <4 x float> %vecinit5, float %add8, i32 2
     64   ret <4 x float> %vecinit9
     65 }
     66 ; CHECK-LABEL: test3_undef
     67 ; SSE: haddps
     68 ; AVX: vhaddps
     69 ; AVX2: vhaddps
     70 ; CHECK-NEXT: ret
     71 
     72 
     73 define <4 x float> @test4_undef(<4 x float> %a, <4 x float> %b) {
     74   %vecext = extractelement <4 x float> %a, i32 0
     75   %vecext1 = extractelement <4 x float> %a, i32 1
     76   %add = fadd float %vecext, %vecext1
     77   %vecinit = insertelement <4 x float> undef, float %add, i32 0
     78   ret <4 x float> %vecinit
     79 }
     80 ; CHECK-LABEL: test4_undef
     81 ; CHECK-NOT: haddps
     82 ; CHECK: ret
     83 
     84 
     85 define <2 x double> @test5_undef(<2 x double> %a, <2 x double> %b) {
     86   %vecext = extractelement <2 x double> %a, i32 0
     87   %vecext1 = extractelement <2 x double> %a, i32 1
     88   %add = fadd double %vecext, %vecext1
     89   %vecinit = insertelement <2 x double> undef, double %add, i32 0
     90   ret <2 x double> %vecinit
     91 }
     92 ; CHECK-LABEL: test5_undef
     93 ; CHECK-NOT: haddpd
     94 ; CHECK: ret
     95 
     96 
     97 define <4 x float> @test6_undef(<4 x float> %a, <4 x float> %b) {
     98   %vecext = extractelement <4 x float> %a, i32 0
     99   %vecext1 = extractelement <4 x float> %a, i32 1
    100   %add = fadd float %vecext, %vecext1
    101   %vecinit = insertelement <4 x float> undef, float %add, i32 0
    102   %vecext2 = extractelement <4 x float> %a, i32 2
    103   %vecext3 = extractelement <4 x float> %a, i32 3
    104   %add4 = fadd float %vecext2, %vecext3
    105   %vecinit5 = insertelement <4 x float> %vecinit, float %add4, i32 1
    106   ret <4 x float> %vecinit5
    107 }
    108 ; CHECK-LABEL: test6_undef
    109 ; SSE: haddps
    110 ; AVX: vhaddps
    111 ; AVX2: vhaddps
    112 ; CHECK-NEXT: ret
    113 
    114 
    115 define <4 x float> @test7_undef(<4 x float> %a, <4 x float> %b) {
    116   %vecext = extractelement <4 x float> %b, i32 0
    117   %vecext1 = extractelement <4 x float> %b, i32 1
    118   %add = fadd float %vecext, %vecext1
    119   %vecinit = insertelement <4 x float> undef, float %add, i32 2
    120   %vecext2 = extractelement <4 x float> %b, i32 2
    121   %vecext3 = extractelement <4 x float> %b, i32 3
    122   %add4 = fadd float %vecext2, %vecext3
    123   %vecinit5 = insertelement <4 x float> %vecinit, float %add4, i32 3
    124   ret <4 x float> %vecinit5
    125 }
    126 ; CHECK-LABEL: test7_undef
    127 ; SSE: haddps
    128 ; AVX: vhaddps
    129 ; AVX2: vhaddps
    130 ; CHECK-NEXT: ret
    131 
    132 
    133 define <4 x float> @test8_undef(<4 x float> %a, <4 x float> %b) {
    134   %vecext = extractelement <4 x float> %a, i32 0
    135   %vecext1 = extractelement <4 x float> %a, i32 1
    136   %add = fadd float %vecext, %vecext1
    137   %vecinit = insertelement <4 x float> undef, float %add, i32 0
    138   %vecext2 = extractelement <4 x float> %a, i32 2
    139   %vecext3 = extractelement <4 x float> %a, i32 3
    140   %add4 = fadd float %vecext2, %vecext3
    141   %vecinit5 = insertelement <4 x float> %vecinit, float %add4, i32 2
    142   ret <4 x float> %vecinit5
    143 }
    144 ; CHECK-LABEL: test8_undef
    145 ; CHECK-NOT: haddps
    146 ; CHECK: ret
    147 
    148 
    149 define <4 x float> @test9_undef(<4 x float> %a, <4 x float> %b) {
    150   %vecext = extractelement <4 x float> %a, i32 0
    151   %vecext1 = extractelement <4 x float> %a, i32 1
    152   %add = fadd float %vecext, %vecext1
    153   %vecinit = insertelement <4 x float> undef, float %add, i32 0
    154   %vecext2 = extractelement <4 x float> %b, i32 2
    155   %vecext3 = extractelement <4 x float> %b, i32 3
    156   %add4 = fadd float %vecext2, %vecext3
    157   %vecinit5 = insertelement <4 x float> %vecinit, float %add4, i32 3
    158   ret <4 x float> %vecinit5
    159 }
    160 ; CHECK-LABEL: test9_undef
    161 ; CHECK: haddps
    162 ; CHECK-NEXT: ret
    163 
    164 define <8 x float> @test10_undef(<8 x float> %a, <8 x float> %b) {
    165   %vecext = extractelement <8 x float> %a, i32 0
    166   %vecext1 = extractelement <8 x float> %a, i32 1
    167   %add = fadd float %vecext, %vecext1
    168   %vecinit = insertelement <8 x float> undef, float %add, i32 0
    169   %vecext2 = extractelement <8 x float> %b, i32 2
    170   %vecext3 = extractelement <8 x float> %b, i32 3
    171   %add4 = fadd float %vecext2, %vecext3
    172   %vecinit5 = insertelement <8 x float> %vecinit, float %add4, i32 3
    173   ret <8 x float> %vecinit5
    174 }
    175 ; CHECK-LABEL: test10_undef
    176 ; SSE: haddps
    177 ; AVX: vhaddps
    178 ; AVX2: vhaddps
    179 ; CHECK-NOT: haddps
    180 ; CHECK: ret
    181 
    182 define <8 x float> @test11_undef(<8 x float> %a, <8 x float> %b) {
    183   %vecext = extractelement <8 x float> %a, i32 0
    184   %vecext1 = extractelement <8 x float> %a, i32 1
    185   %add = fadd float %vecext, %vecext1
    186   %vecinit = insertelement <8 x float> undef, float %add, i32 0
    187   %vecext2 = extractelement <8 x float> %b, i32 4
    188   %vecext3 = extractelement <8 x float> %b, i32 5
    189   %add4 = fadd float %vecext2, %vecext3
    190   %vecinit5 = insertelement <8 x float> %vecinit, float %add4, i32 6
    191   ret <8 x float> %vecinit5
    192 }
    193 ; CHECK-LABEL: test11_undef
    194 ; SSE-NOT: haddps
    195 ; AVX: vhaddps
    196 ; AVX2: vhaddps
    197 ; CHECK: ret
    198 
    199 define <8 x float> @test12_undef(<8 x float> %a, <8 x float> %b) {
    200   %vecext = extractelement <8 x float> %a, i32 0
    201   %vecext1 = extractelement <8 x float> %a, i32 1
    202   %add = fadd float %vecext, %vecext1
    203   %vecinit = insertelement <8 x float> undef, float %add, i32 0
    204   %vecext2 = extractelement <8 x float> %a, i32 2
    205   %vecext3 = extractelement <8 x float> %a, i32 3
    206   %add4 = fadd float %vecext2, %vecext3
    207   %vecinit5 = insertelement <8 x float> %vecinit, float %add4, i32 1
    208   ret <8 x float> %vecinit5
    209 }
    210 ; CHECK-LABEL: test12_undef
    211 ; SSE: haddps
    212 ; AVX: vhaddps
    213 ; AVX2: vhaddps
    214 ; CHECK-NOT: haddps
    215 ; CHECK: ret
    216 
    217 define <8 x float> @test13_undef(<8 x float> %a, <8 x float> %b) {
    218   %vecext = extractelement <8 x float> %a, i32 0
    219   %vecext1 = extractelement <8 x float> %a, i32 1
    220   %add1 = fadd float %vecext, %vecext1
    221   %vecinit1 = insertelement <8 x float> undef, float %add1, i32 0
    222   %vecext2 = extractelement <8 x float> %a, i32 2
    223   %vecext3 = extractelement <8 x float> %a, i32 3
    224   %add2 = fadd float %vecext2, %vecext3
    225   %vecinit2 = insertelement <8 x float> %vecinit1, float %add2, i32 1
    226   %vecext4 = extractelement <8 x float> %a, i32 4
    227   %vecext5 = extractelement <8 x float> %a, i32 5
    228   %add3 = fadd float %vecext4, %vecext5
    229   %vecinit3 = insertelement <8 x float> %vecinit2, float %add3, i32 2
    230   %vecext6 = extractelement <8 x float> %a, i32 6
    231   %vecext7 = extractelement <8 x float> %a, i32 7
    232   %add4 = fadd float %vecext6, %vecext7
    233   %vecinit4 = insertelement <8 x float> %vecinit3, float %add4, i32 3
    234   ret <8 x float> %vecinit4
    235 }
    236 ; CHECK-LABEL: test13_undef
    237 ; SSE: haddps
    238 ; SSE-NOT: haddps
    239 ; AVX: vhaddps
    240 ; AVX2: vhaddps
    241 ; CHECK-NOT: haddps
    242 ; CHECK: ret
    243 
    244 define <8 x i32> @test14_undef(<8 x i32> %a, <8 x i32> %b) {
    245   %vecext = extractelement <8 x i32> %a, i32 0
    246   %vecext1 = extractelement <8 x i32> %a, i32 1
    247   %add = add i32 %vecext, %vecext1
    248   %vecinit = insertelement <8 x i32> undef, i32 %add, i32 0
    249   %vecext2 = extractelement <8 x i32> %b, i32 2
    250   %vecext3 = extractelement <8 x i32> %b, i32 3
    251   %add4 = add i32 %vecext2, %vecext3
    252   %vecinit5 = insertelement <8 x i32> %vecinit, i32 %add4, i32 3
    253   ret <8 x i32> %vecinit5
    254 }
    255 ; CHECK-LABEL: test14_undef
    256 ; SSE: phaddd
    257 ; AVX: vphaddd
    258 ; AVX2: vphaddd
    259 ; CHECK-NOT: phaddd
    260 ; CHECK: ret
    261 
    262 ; On AVX2, the following sequence can be folded into a single horizontal add.
    263 ; If the Subtarget doesn't support AVX2, then we avoid emitting two packed 
    264 ; integer horizontal adds instead of two scalar adds followed by vector inserts.
    265 define <8 x i32> @test15_undef(<8 x i32> %a, <8 x i32> %b) {
    266   %vecext = extractelement <8 x i32> %a, i32 0
    267   %vecext1 = extractelement <8 x i32> %a, i32 1
    268   %add = add i32 %vecext, %vecext1
    269   %vecinit = insertelement <8 x i32> undef, i32 %add, i32 0
    270   %vecext2 = extractelement <8 x i32> %b, i32 4
    271   %vecext3 = extractelement <8 x i32> %b, i32 5
    272   %add4 = add i32 %vecext2, %vecext3
    273   %vecinit5 = insertelement <8 x i32> %vecinit, i32 %add4, i32 6
    274   ret <8 x i32> %vecinit5
    275 }
    276 ; CHECK-LABEL: test15_undef
    277 ; SSE-NOT: phaddd
    278 ; AVX-NOT: vphaddd
    279 ; AVX2: vphaddd
    280 ; CHECK: ret
    281 
    282 define <8 x i32> @test16_undef(<8 x i32> %a, <8 x i32> %b) {
    283   %vecext = extractelement <8 x i32> %a, i32 0
    284   %vecext1 = extractelement <8 x i32> %a, i32 1
    285   %add = add i32 %vecext, %vecext1
    286   %vecinit = insertelement <8 x i32> undef, i32 %add, i32 0
    287   %vecext2 = extractelement <8 x i32> %a, i32 2
    288   %vecext3 = extractelement <8 x i32> %a, i32 3
    289   %add4 = add i32 %vecext2, %vecext3
    290   %vecinit5 = insertelement <8 x i32> %vecinit, i32 %add4, i32 1
    291   ret <8 x i32> %vecinit5
    292 }
    293 ; CHECK-LABEL: test16_undef
    294 ; SSE: phaddd
    295 ; AVX: vphaddd
    296 ; AVX2: vphaddd
    297 ; CHECK-NOT: haddps
    298 ; CHECK: ret
    299 
    300 define <8 x i32> @test17_undef(<8 x i32> %a, <8 x i32> %b) {
    301   %vecext = extractelement <8 x i32> %a, i32 0
    302   %vecext1 = extractelement <8 x i32> %a, i32 1
    303   %add1 = add i32 %vecext, %vecext1
    304   %vecinit1 = insertelement <8 x i32> undef, i32 %add1, i32 0
    305   %vecext2 = extractelement <8 x i32> %a, i32 2
    306   %vecext3 = extractelement <8 x i32> %a, i32 3
    307   %add2 = add i32 %vecext2, %vecext3
    308   %vecinit2 = insertelement <8 x i32> %vecinit1, i32 %add2, i32 1
    309   %vecext4 = extractelement <8 x i32> %a, i32 4
    310   %vecext5 = extractelement <8 x i32> %a, i32 5
    311   %add3 = add i32 %vecext4, %vecext5
    312   %vecinit3 = insertelement <8 x i32> %vecinit2, i32 %add3, i32 2
    313   %vecext6 = extractelement <8 x i32> %a, i32 6
    314   %vecext7 = extractelement <8 x i32> %a, i32 7
    315   %add4 = add i32 %vecext6, %vecext7
    316   %vecinit4 = insertelement <8 x i32> %vecinit3, i32 %add4, i32 3
    317   ret <8 x i32> %vecinit4
    318 }
    319 ; CHECK-LABEL: test17_undef
    320 ; SSE: phaddd
    321 ; AVX: vphaddd
    322 ; AVX2: vphaddd
    323 ; CHECK-NOT: haddps
    324 ; CHECK: ret
    325 
    326