Home | History | Annotate | Download | only in X86
      1 ; RUN: llc < %s -march=x86-64 -mattr=+sse2,+sse3 | FileCheck %s -check-prefix=CHECK -check-prefix=SSE3
      2 ; RUN: llc < %s -march=x86-64 -mattr=+sse2,+sse3,+ssse3 | FileCheck %s -check-prefix=CHECK -check-prefix=SSSE3
      3 ; RUN: llc < %s -march=x86-64 -mattr=+avx | FileCheck %s -check-prefix=CHECK -check-prefix=AVX
      4 ; RUN: llc < %s -march=x86-64 -mattr=+avx2 | FileCheck %s -check-prefix=CHECK -check-prefix=AVX2
      5 
      6 
      7 
      8 define <4 x float> @hadd_ps_test1(<4 x float> %A, <4 x float> %B) {
      9   %vecext = extractelement <4 x float> %A, i32 0
     10   %vecext1 = extractelement <4 x float> %A, i32 1
     11   %add = fadd float %vecext, %vecext1
     12   %vecinit = insertelement <4 x float> undef, float %add, i32 0
     13   %vecext2 = extractelement <4 x float> %A, i32 2
     14   %vecext3 = extractelement <4 x float> %A, i32 3
     15   %add4 = fadd float %vecext2, %vecext3
     16   %vecinit5 = insertelement <4 x float> %vecinit, float %add4, i32 1
     17   %vecext6 = extractelement <4 x float> %B, i32 0
     18   %vecext7 = extractelement <4 x float> %B, i32 1
     19   %add8 = fadd float %vecext6, %vecext7
     20   %vecinit9 = insertelement <4 x float> %vecinit5, float %add8, i32 2
     21   %vecext10 = extractelement <4 x float> %B, i32 2
     22   %vecext11 = extractelement <4 x float> %B, i32 3
     23   %add12 = fadd float %vecext10, %vecext11
     24   %vecinit13 = insertelement <4 x float> %vecinit9, float %add12, i32 3
     25   ret <4 x float> %vecinit13
     26 }
     27 ; CHECK-LABEL: hadd_ps_test1
     28 ; CHECK: haddps
     29 ; CHECK-NEXT: ret
     30 
     31 
     32 define <4 x float> @hadd_ps_test2(<4 x float> %A, <4 x float> %B) {
     33   %vecext = extractelement <4 x float> %A, i32 2
     34   %vecext1 = extractelement <4 x float> %A, i32 3
     35   %add = fadd float %vecext, %vecext1
     36   %vecinit = insertelement <4 x float> undef, float %add, i32 1
     37   %vecext2 = extractelement <4 x float> %A, i32 0
     38   %vecext3 = extractelement <4 x float> %A, i32 1
     39   %add4 = fadd float %vecext2, %vecext3
     40   %vecinit5 = insertelement <4 x float> %vecinit, float %add4, i32 0
     41   %vecext6 = extractelement <4 x float> %B, i32 2
     42   %vecext7 = extractelement <4 x float> %B, i32 3
     43   %add8 = fadd float %vecext6, %vecext7
     44   %vecinit9 = insertelement <4 x float> %vecinit5, float %add8, i32 3
     45   %vecext10 = extractelement <4 x float> %B, i32 0
     46   %vecext11 = extractelement <4 x float> %B, i32 1
     47   %add12 = fadd float %vecext10, %vecext11
     48   %vecinit13 = insertelement <4 x float> %vecinit9, float %add12, i32 2
     49   ret <4 x float> %vecinit13
     50 }
     51 ; CHECK-LABEL: hadd_ps_test2
     52 ; CHECK: haddps
     53 ; CHECK-NEXT: ret
     54 
     55 
     56 define <4 x float> @hsub_ps_test1(<4 x float> %A, <4 x float> %B) {
     57   %vecext = extractelement <4 x float> %A, i32 0
     58   %vecext1 = extractelement <4 x float> %A, i32 1
     59   %sub = fsub float %vecext, %vecext1
     60   %vecinit = insertelement <4 x float> undef, float %sub, i32 0
     61   %vecext2 = extractelement <4 x float> %A, i32 2
     62   %vecext3 = extractelement <4 x float> %A, i32 3
     63   %sub4 = fsub float %vecext2, %vecext3
     64   %vecinit5 = insertelement <4 x float> %vecinit, float %sub4, i32 1
     65   %vecext6 = extractelement <4 x float> %B, i32 0
     66   %vecext7 = extractelement <4 x float> %B, i32 1
     67   %sub8 = fsub float %vecext6, %vecext7
     68   %vecinit9 = insertelement <4 x float> %vecinit5, float %sub8, i32 2
     69   %vecext10 = extractelement <4 x float> %B, i32 2
     70   %vecext11 = extractelement <4 x float> %B, i32 3
     71   %sub12 = fsub float %vecext10, %vecext11
     72   %vecinit13 = insertelement <4 x float> %vecinit9, float %sub12, i32 3
     73   ret <4 x float> %vecinit13
     74 }
     75 ; CHECK-LABEL: hsub_ps_test1
     76 ; CHECK: hsubps
     77 ; CHECK-NEXT: ret
     78 
     79 
     80 define <4 x float> @hsub_ps_test2(<4 x float> %A, <4 x float> %B) {
     81   %vecext = extractelement <4 x float> %A, i32 2
     82   %vecext1 = extractelement <4 x float> %A, i32 3
     83   %sub = fsub float %vecext, %vecext1
     84   %vecinit = insertelement <4 x float> undef, float %sub, i32 1
     85   %vecext2 = extractelement <4 x float> %A, i32 0
     86   %vecext3 = extractelement <4 x float> %A, i32 1
     87   %sub4 = fsub float %vecext2, %vecext3
     88   %vecinit5 = insertelement <4 x float> %vecinit, float %sub4, i32 0
     89   %vecext6 = extractelement <4 x float> %B, i32 2
     90   %vecext7 = extractelement <4 x float> %B, i32 3
     91   %sub8 = fsub float %vecext6, %vecext7
     92   %vecinit9 = insertelement <4 x float> %vecinit5, float %sub8, i32 3
     93   %vecext10 = extractelement <4 x float> %B, i32 0
     94   %vecext11 = extractelement <4 x float> %B, i32 1
     95   %sub12 = fsub float %vecext10, %vecext11
     96   %vecinit13 = insertelement <4 x float> %vecinit9, float %sub12, i32 2
     97   ret <4 x float> %vecinit13
     98 }
     99 ; CHECK-LABEL: hsub_ps_test2
    100 ; CHECK: hsubps
    101 ; CHECK-NEXT: ret
    102 
    103 
    104 define <4 x i32> @phadd_d_test1(<4 x i32> %A, <4 x i32> %B) {
    105   %vecext = extractelement <4 x i32> %A, i32 0
    106   %vecext1 = extractelement <4 x i32> %A, i32 1
    107   %add = add i32 %vecext, %vecext1
    108   %vecinit = insertelement <4 x i32> undef, i32 %add, i32 0
    109   %vecext2 = extractelement <4 x i32> %A, i32 2
    110   %vecext3 = extractelement <4 x i32> %A, i32 3
    111   %add4 = add i32 %vecext2, %vecext3
    112   %vecinit5 = insertelement <4 x i32> %vecinit, i32 %add4, i32 1
    113   %vecext6 = extractelement <4 x i32> %B, i32 0
    114   %vecext7 = extractelement <4 x i32> %B, i32 1
    115   %add8 = add i32 %vecext6, %vecext7
    116   %vecinit9 = insertelement <4 x i32> %vecinit5, i32 %add8, i32 2
    117   %vecext10 = extractelement <4 x i32> %B, i32 2
    118   %vecext11 = extractelement <4 x i32> %B, i32 3
    119   %add12 = add i32 %vecext10, %vecext11
    120   %vecinit13 = insertelement <4 x i32> %vecinit9, i32 %add12, i32 3
    121   ret <4 x i32> %vecinit13
    122 }
    123 ; CHECK-LABEL: phadd_d_test1
    124 ; SSE3-NOT: phaddd
    125 ; SSSE3: phaddd
    126 ; AVX: vphaddd
    127 ; AVX2 vphaddd
    128 ; CHECK: ret
    129 
    130 
    131 define <4 x i32> @phadd_d_test2(<4 x i32> %A, <4 x i32> %B) {
    132   %vecext = extractelement <4 x i32> %A, i32 2
    133   %vecext1 = extractelement <4 x i32> %A, i32 3
    134   %add = add i32 %vecext, %vecext1
    135   %vecinit = insertelement <4 x i32> undef, i32 %add, i32 1
    136   %vecext2 = extractelement <4 x i32> %A, i32 0
    137   %vecext3 = extractelement <4 x i32> %A, i32 1
    138   %add4 = add i32 %vecext2, %vecext3
    139   %vecinit5 = insertelement <4 x i32> %vecinit, i32 %add4, i32 0
    140   %vecext6 = extractelement <4 x i32> %B, i32 3
    141   %vecext7 = extractelement <4 x i32> %B, i32 2
    142   %add8 = add i32 %vecext6, %vecext7
    143   %vecinit9 = insertelement <4 x i32> %vecinit5, i32 %add8, i32 3
    144   %vecext10 = extractelement <4 x i32> %B, i32 1
    145   %vecext11 = extractelement <4 x i32> %B, i32 0
    146   %add12 = add i32 %vecext10, %vecext11
    147   %vecinit13 = insertelement <4 x i32> %vecinit9, i32 %add12, i32 2
    148   ret <4 x i32> %vecinit13
    149 }
    150 ; CHECK-LABEL: phadd_d_test2
    151 ; SSE3-NOT: phaddd
    152 ; SSSE3: phaddd
    153 ; AVX: vphaddd
    154 ; AVX2 vphaddd
    155 ; CHECK: ret
    156 
    157 
    158 define <4 x i32> @phsub_d_test1(<4 x i32> %A, <4 x i32> %B) {
    159   %vecext = extractelement <4 x i32> %A, i32 0
    160   %vecext1 = extractelement <4 x i32> %A, i32 1
    161   %sub = sub i32 %vecext, %vecext1
    162   %vecinit = insertelement <4 x i32> undef, i32 %sub, i32 0
    163   %vecext2 = extractelement <4 x i32> %A, i32 2
    164   %vecext3 = extractelement <4 x i32> %A, i32 3
    165   %sub4 = sub i32 %vecext2, %vecext3
    166   %vecinit5 = insertelement <4 x i32> %vecinit, i32 %sub4, i32 1
    167   %vecext6 = extractelement <4 x i32> %B, i32 0
    168   %vecext7 = extractelement <4 x i32> %B, i32 1
    169   %sub8 = sub i32 %vecext6, %vecext7
    170   %vecinit9 = insertelement <4 x i32> %vecinit5, i32 %sub8, i32 2
    171   %vecext10 = extractelement <4 x i32> %B, i32 2
    172   %vecext11 = extractelement <4 x i32> %B, i32 3
    173   %sub12 = sub i32 %vecext10, %vecext11
    174   %vecinit13 = insertelement <4 x i32> %vecinit9, i32 %sub12, i32 3
    175   ret <4 x i32> %vecinit13
    176 }
    177 ; CHECK-LABEL: phsub_d_test1
    178 ; SSE3-NOT: phsubd
    179 ; SSSE3: phsubd
    180 ; AVX: vphsubd
    181 ; AVX2 vphsubd
    182 ; CHECK: ret
    183 
    184 
    185 define <4 x i32> @phsub_d_test2(<4 x i32> %A, <4 x i32> %B) {
    186   %vecext = extractelement <4 x i32> %A, i32 2
    187   %vecext1 = extractelement <4 x i32> %A, i32 3
    188   %sub = sub i32 %vecext, %vecext1
    189   %vecinit = insertelement <4 x i32> undef, i32 %sub, i32 1
    190   %vecext2 = extractelement <4 x i32> %A, i32 0
    191   %vecext3 = extractelement <4 x i32> %A, i32 1
    192   %sub4 = sub i32 %vecext2, %vecext3
    193   %vecinit5 = insertelement <4 x i32> %vecinit, i32 %sub4, i32 0
    194   %vecext6 = extractelement <4 x i32> %B, i32 2
    195   %vecext7 = extractelement <4 x i32> %B, i32 3
    196   %sub8 = sub i32 %vecext6, %vecext7
    197   %vecinit9 = insertelement <4 x i32> %vecinit5, i32 %sub8, i32 3
    198   %vecext10 = extractelement <4 x i32> %B, i32 0
    199   %vecext11 = extractelement <4 x i32> %B, i32 1
    200   %sub12 = sub i32 %vecext10, %vecext11
    201   %vecinit13 = insertelement <4 x i32> %vecinit9, i32 %sub12, i32 2
    202   ret <4 x i32> %vecinit13
    203 }
    204 ; CHECK-LABEL: phsub_d_test2
    205 ; SSE3-NOT: phsubd
    206 ; SSSE3: phsubd
    207 ; AVX: vphsubd
    208 ; AVX2 vphsubd
    209 ; CHECK: ret
    210 
    211 
    212 define <2 x double> @hadd_pd_test1(<2 x double> %A, <2 x double> %B) {
    213   %vecext = extractelement <2 x double> %A, i32 0
    214   %vecext1 = extractelement <2 x double> %A, i32 1
    215   %add = fadd double %vecext, %vecext1
    216   %vecinit = insertelement <2 x double> undef, double %add, i32 0
    217   %vecext2 = extractelement <2 x double> %B, i32 0
    218   %vecext3 = extractelement <2 x double> %B, i32 1
    219   %add2 = fadd double %vecext2, %vecext3
    220   %vecinit2 = insertelement <2 x double> %vecinit, double %add2, i32 1
    221   ret <2 x double> %vecinit2
    222 }
    223 ; CHECK-LABEL: hadd_pd_test1
    224 ; CHECK: haddpd
    225 ; CHECK-NEXT: ret
    226 
    227 
    228 define <2 x double> @hadd_pd_test2(<2 x double> %A, <2 x double> %B) {
    229   %vecext = extractelement <2 x double> %A, i32 1
    230   %vecext1 = extractelement <2 x double> %A, i32 0
    231   %add = fadd double %vecext, %vecext1
    232   %vecinit = insertelement <2 x double> undef, double %add, i32 0
    233   %vecext2 = extractelement <2 x double> %B, i32 1
    234   %vecext3 = extractelement <2 x double> %B, i32 0
    235   %add2 = fadd double %vecext2, %vecext3
    236   %vecinit2 = insertelement <2 x double> %vecinit, double %add2, i32 1
    237   ret <2 x double> %vecinit2
    238 }
    239 ; CHECK-LABEL: hadd_pd_test2
    240 ; CHECK: haddpd
    241 ; CHECK-NEXT: ret
    242 
    243 
    244 define <2 x double> @hsub_pd_test1(<2 x double> %A, <2 x double> %B) {
    245   %vecext = extractelement <2 x double> %A, i32 0
    246   %vecext1 = extractelement <2 x double> %A, i32 1
    247   %sub = fsub double %vecext, %vecext1
    248   %vecinit = insertelement <2 x double> undef, double %sub, i32 0
    249   %vecext2 = extractelement <2 x double> %B, i32 0
    250   %vecext3 = extractelement <2 x double> %B, i32 1
    251   %sub2 = fsub double %vecext2, %vecext3
    252   %vecinit2 = insertelement <2 x double> %vecinit, double %sub2, i32 1
    253   ret <2 x double> %vecinit2
    254 }
    255 ; CHECK-LABEL: hsub_pd_test1
    256 ; CHECK: hsubpd
    257 ; CHECK-NEXT: ret
    258 
    259 
    260 define <2 x double> @hsub_pd_test2(<2 x double> %A, <2 x double> %B) {
    261   %vecext = extractelement <2 x double> %B, i32 0
    262   %vecext1 = extractelement <2 x double> %B, i32 1
    263   %sub = fsub double %vecext, %vecext1
    264   %vecinit = insertelement <2 x double> undef, double %sub, i32 1
    265   %vecext2 = extractelement <2 x double> %A, i32 0
    266   %vecext3 = extractelement <2 x double> %A, i32 1
    267   %sub2 = fsub double %vecext2, %vecext3
    268   %vecinit2 = insertelement <2 x double> %vecinit, double %sub2, i32 0
    269   ret <2 x double> %vecinit2
    270 }
    271 ; CHECK-LABEL: hsub_pd_test2
    272 ; CHECK: hsubpd
    273 ; CHECK-NEXT: ret
    274 
    275 
    276 define <4 x double> @avx_vhadd_pd_test(<4 x double> %A, <4 x double> %B) {
    277   %vecext = extractelement <4 x double> %A, i32 0
    278   %vecext1 = extractelement <4 x double> %A, i32 1
    279   %add = fadd double %vecext, %vecext1
    280   %vecinit = insertelement <4 x double> undef, double %add, i32 0
    281   %vecext2 = extractelement <4 x double> %A, i32 2
    282   %vecext3 = extractelement <4 x double> %A, i32 3
    283   %add4 = fadd double %vecext2, %vecext3
    284   %vecinit5 = insertelement <4 x double> %vecinit, double %add4, i32 1
    285   %vecext6 = extractelement <4 x double> %B, i32 0
    286   %vecext7 = extractelement <4 x double> %B, i32 1
    287   %add8 = fadd double %vecext6, %vecext7
    288   %vecinit9 = insertelement <4 x double> %vecinit5, double %add8, i32 2
    289   %vecext10 = extractelement <4 x double> %B, i32 2
    290   %vecext11 = extractelement <4 x double> %B, i32 3
    291   %add12 = fadd double %vecext10, %vecext11
    292   %vecinit13 = insertelement <4 x double> %vecinit9, double %add12, i32 3
    293   ret <4 x double> %vecinit13
    294 }
    295 ; CHECK-LABEL: avx_vhadd_pd_test
    296 ; SSE3: haddpd
    297 ; SSE3-NEXT: haddpd
    298 ; SSSE3: haddpd
    299 ; SSSE3: haddpd
    300 ; AVX: vhaddpd
    301 ; AVX: vhaddpd
    302 ; AVX2: vhaddpd
    303 ; AVX2: vhaddpd
    304 ; CHECK: ret
    305 
    306 
    307 define <4 x double> @avx_vhsub_pd_test(<4 x double> %A, <4 x double> %B) {
    308   %vecext = extractelement <4 x double> %A, i32 0
    309   %vecext1 = extractelement <4 x double> %A, i32 1
    310   %sub = fsub double %vecext, %vecext1
    311   %vecinit = insertelement <4 x double> undef, double %sub, i32 0
    312   %vecext2 = extractelement <4 x double> %A, i32 2
    313   %vecext3 = extractelement <4 x double> %A, i32 3
    314   %sub4 = fsub double %vecext2, %vecext3
    315   %vecinit5 = insertelement <4 x double> %vecinit, double %sub4, i32 1
    316   %vecext6 = extractelement <4 x double> %B, i32 0
    317   %vecext7 = extractelement <4 x double> %B, i32 1
    318   %sub8 = fsub double %vecext6, %vecext7
    319   %vecinit9 = insertelement <4 x double> %vecinit5, double %sub8, i32 2
    320   %vecext10 = extractelement <4 x double> %B, i32 2
    321   %vecext11 = extractelement <4 x double> %B, i32 3
    322   %sub12 = fsub double %vecext10, %vecext11
    323   %vecinit13 = insertelement <4 x double> %vecinit9, double %sub12, i32 3
    324   ret <4 x double> %vecinit13
    325 }
    326 ; CHECK-LABEL: avx_vhsub_pd_test
    327 ; SSE3: hsubpd
    328 ; SSE3-NEXT: hsubpd
    329 ; SSSE3: hsubpd
    330 ; SSSE3-NEXT: hsubpd
    331 ; AVX: vhsubpd
    332 ; AVX: vhsubpd
    333 ; AVX2: vhsubpd
    334 ; AVX2: vhsubpd
    335 ; CHECK: ret
    336 
    337 
    338 define <8 x i32> @avx2_vphadd_d_test(<8 x i32> %A, <8 x i32> %B) {
    339   %vecext = extractelement <8 x i32> %A, i32 0
    340   %vecext1 = extractelement <8 x i32> %A, i32 1
    341   %add = add i32 %vecext, %vecext1
    342   %vecinit = insertelement <8 x i32> undef, i32 %add, i32 0
    343   %vecext2 = extractelement <8 x i32> %A, i32 2
    344   %vecext3 = extractelement <8 x i32> %A, i32 3
    345   %add4 = add i32 %vecext2, %vecext3
    346   %vecinit5 = insertelement <8 x i32> %vecinit, i32 %add4, i32 1
    347   %vecext6 = extractelement <8 x i32> %A, i32 4
    348   %vecext7 = extractelement <8 x i32> %A, i32 5
    349   %add8 = add i32 %vecext6, %vecext7
    350   %vecinit9 = insertelement <8 x i32> %vecinit5, i32 %add8, i32 2
    351   %vecext10 = extractelement <8 x i32> %A, i32 6
    352   %vecext11 = extractelement <8 x i32> %A, i32 7
    353   %add12 = add i32 %vecext10, %vecext11
    354   %vecinit13 = insertelement <8 x i32> %vecinit9, i32 %add12, i32 3
    355   %vecext14 = extractelement <8 x i32> %B, i32 0
    356   %vecext15 = extractelement <8 x i32> %B, i32 1
    357   %add16 = add i32 %vecext14, %vecext15
    358   %vecinit17 = insertelement <8 x i32> %vecinit13, i32 %add16, i32 4
    359   %vecext18 = extractelement <8 x i32> %B, i32 2
    360   %vecext19 = extractelement <8 x i32> %B, i32 3
    361   %add20 = add i32 %vecext18, %vecext19
    362   %vecinit21 = insertelement <8 x i32> %vecinit17, i32 %add20, i32 5
    363   %vecext22 = extractelement <8 x i32> %B, i32 4
    364   %vecext23 = extractelement <8 x i32> %B, i32 5
    365   %add24 = add i32 %vecext22, %vecext23
    366   %vecinit25 = insertelement <8 x i32> %vecinit21, i32 %add24, i32 6
    367   %vecext26 = extractelement <8 x i32> %B, i32 6
    368   %vecext27 = extractelement <8 x i32> %B, i32 7
    369   %add28 = add i32 %vecext26, %vecext27
    370   %vecinit29 = insertelement <8 x i32> %vecinit25, i32 %add28, i32 7
    371   ret <8 x i32> %vecinit29
    372 }
    373 ; CHECK-LABEL: avx2_vphadd_d_test
    374 ; SSE3-NOT: phaddd
    375 ; SSSE3: phaddd
    376 ; SSSE3-NEXT: phaddd
    377 ; AVX: vphaddd
    378 ; AVX: vphaddd
    379 ; AVX2: vphaddd
    380 ; AVX2: vphaddd
    381 ; CHECK: ret
    382 
    383 define <16 x i16> @avx2_vphadd_w_test(<16 x i16> %a, <16 x i16> %b) {
    384   %vecext = extractelement <16 x i16> %a, i32 0
    385   %vecext1 = extractelement <16 x i16> %a, i32 1
    386   %add = add i16 %vecext, %vecext1
    387   %vecinit = insertelement <16 x i16> undef, i16 %add, i32 0
    388   %vecext4 = extractelement <16 x i16> %a, i32 2
    389   %vecext6 = extractelement <16 x i16> %a, i32 3
    390   %add8 = add i16 %vecext4, %vecext6
    391   %vecinit10 = insertelement <16 x i16> %vecinit, i16 %add8, i32 1
    392   %vecext11 = extractelement <16 x i16> %a, i32 4
    393   %vecext13 = extractelement <16 x i16> %a, i32 5
    394   %add15 = add i16 %vecext11, %vecext13
    395   %vecinit17 = insertelement <16 x i16> %vecinit10, i16 %add15, i32 2
    396   %vecext18 = extractelement <16 x i16> %a, i32 6
    397   %vecext20 = extractelement <16 x i16> %a, i32 7
    398   %add22 = add i16 %vecext18, %vecext20
    399   %vecinit24 = insertelement <16 x i16> %vecinit17, i16 %add22, i32 3
    400   %vecext25 = extractelement <16 x i16> %a, i32 8
    401   %vecext27 = extractelement <16 x i16> %a, i32 9
    402   %add29 = add i16 %vecext25, %vecext27
    403   %vecinit31 = insertelement <16 x i16> %vecinit24, i16 %add29, i32 4
    404   %vecext32 = extractelement <16 x i16> %a, i32 10
    405   %vecext34 = extractelement <16 x i16> %a, i32 11
    406   %add36 = add i16 %vecext32, %vecext34
    407   %vecinit38 = insertelement <16 x i16> %vecinit31, i16 %add36, i32 5
    408   %vecext39 = extractelement <16 x i16> %a, i32 12
    409   %vecext41 = extractelement <16 x i16> %a, i32 13
    410   %add43 = add i16 %vecext39, %vecext41
    411   %vecinit45 = insertelement <16 x i16> %vecinit38, i16 %add43, i32 6
    412   %vecext46 = extractelement <16 x i16> %a, i32 14
    413   %vecext48 = extractelement <16 x i16> %a, i32 15
    414   %add50 = add i16 %vecext46, %vecext48
    415   %vecinit52 = insertelement <16 x i16> %vecinit45, i16 %add50, i32 7
    416   %vecext53 = extractelement <16 x i16> %b, i32 0
    417   %vecext55 = extractelement <16 x i16> %b, i32 1
    418   %add57 = add i16 %vecext53, %vecext55
    419   %vecinit59 = insertelement <16 x i16> %vecinit52, i16 %add57, i32 8
    420   %vecext60 = extractelement <16 x i16> %b, i32 2
    421   %vecext62 = extractelement <16 x i16> %b, i32 3
    422   %add64 = add i16 %vecext60, %vecext62
    423   %vecinit66 = insertelement <16 x i16> %vecinit59, i16 %add64, i32 9
    424   %vecext67 = extractelement <16 x i16> %b, i32 4
    425   %vecext69 = extractelement <16 x i16> %b, i32 5
    426   %add71 = add i16 %vecext67, %vecext69
    427   %vecinit73 = insertelement <16 x i16> %vecinit66, i16 %add71, i32 10
    428   %vecext74 = extractelement <16 x i16> %b, i32 6
    429   %vecext76 = extractelement <16 x i16> %b, i32 7
    430   %add78 = add i16 %vecext74, %vecext76
    431   %vecinit80 = insertelement <16 x i16> %vecinit73, i16 %add78, i32 11
    432   %vecext81 = extractelement <16 x i16> %b, i32 8
    433   %vecext83 = extractelement <16 x i16> %b, i32 9
    434   %add85 = add i16 %vecext81, %vecext83
    435   %vecinit87 = insertelement <16 x i16> %vecinit80, i16 %add85, i32 12
    436   %vecext88 = extractelement <16 x i16> %b, i32 10
    437   %vecext90 = extractelement <16 x i16> %b, i32 11
    438   %add92 = add i16 %vecext88, %vecext90
    439   %vecinit94 = insertelement <16 x i16> %vecinit87, i16 %add92, i32 13
    440   %vecext95 = extractelement <16 x i16> %b, i32 12
    441   %vecext97 = extractelement <16 x i16> %b, i32 13
    442   %add99 = add i16 %vecext95, %vecext97
    443   %vecinit101 = insertelement <16 x i16> %vecinit94, i16 %add99, i32 14
    444   %vecext102 = extractelement <16 x i16> %b, i32 14
    445   %vecext104 = extractelement <16 x i16> %b, i32 15
    446   %add106 = add i16 %vecext102, %vecext104
    447   %vecinit108 = insertelement <16 x i16> %vecinit101, i16 %add106, i32 15
    448   ret <16 x i16> %vecinit108
    449 }
    450 ; CHECK-LABEL: avx2_vphadd_w_test
    451 ; SSE3-NOT: phaddw
    452 ; SSSE3: phaddw
    453 ; SSSE3-NEXT: phaddw
    454 ; AVX: vphaddw
    455 ; AVX: vphaddw
    456 ; AVX2: vphaddw
    457 ; AVX2: vphaddw
    458 ; CHECK: ret
    459 
    460 
    461 ; Verify that we don't select horizontal subs in the following functions.
    462 
    463 define <4 x i32> @not_a_hsub_1(<4 x i32> %A, <4 x i32> %B) {
    464   %vecext = extractelement <4 x i32> %A, i32 0
    465   %vecext1 = extractelement <4 x i32> %A, i32 1
    466   %sub = sub i32 %vecext, %vecext1
    467   %vecinit = insertelement <4 x i32> undef, i32 %sub, i32 0
    468   %vecext2 = extractelement <4 x i32> %A, i32 2
    469   %vecext3 = extractelement <4 x i32> %A, i32 3
    470   %sub4 = sub i32 %vecext2, %vecext3
    471   %vecinit5 = insertelement <4 x i32> %vecinit, i32 %sub4, i32 1
    472   %vecext6 = extractelement <4 x i32> %B, i32 1
    473   %vecext7 = extractelement <4 x i32> %B, i32 0
    474   %sub8 = sub i32 %vecext6, %vecext7
    475   %vecinit9 = insertelement <4 x i32> %vecinit5, i32 %sub8, i32 2
    476   %vecext10 = extractelement <4 x i32> %B, i32 3
    477   %vecext11 = extractelement <4 x i32> %B, i32 2
    478   %sub12 = sub i32 %vecext10, %vecext11
    479   %vecinit13 = insertelement <4 x i32> %vecinit9, i32 %sub12, i32 3
    480   ret <4 x i32> %vecinit13
    481 }
    482 ; CHECK-LABEL: not_a_hsub_1
    483 ; CHECK-NOT: phsubd
    484 ; CHECK: ret
    485 
    486 
    487 define <4 x float> @not_a_hsub_2(<4 x float> %A, <4 x float> %B) {
    488   %vecext = extractelement <4 x float> %A, i32 2
    489   %vecext1 = extractelement <4 x float> %A, i32 3
    490   %sub = fsub float %vecext, %vecext1
    491   %vecinit = insertelement <4 x float> undef, float %sub, i32 1
    492   %vecext2 = extractelement <4 x float> %A, i32 0
    493   %vecext3 = extractelement <4 x float> %A, i32 1
    494   %sub4 = fsub float %vecext2, %vecext3
    495   %vecinit5 = insertelement <4 x float> %vecinit, float %sub4, i32 0
    496   %vecext6 = extractelement <4 x float> %B, i32 3
    497   %vecext7 = extractelement <4 x float> %B, i32 2
    498   %sub8 = fsub float %vecext6, %vecext7
    499   %vecinit9 = insertelement <4 x float> %vecinit5, float %sub8, i32 3
    500   %vecext10 = extractelement <4 x float> %B, i32 0
    501   %vecext11 = extractelement <4 x float> %B, i32 1
    502   %sub12 = fsub float %vecext10, %vecext11
    503   %vecinit13 = insertelement <4 x float> %vecinit9, float %sub12, i32 2
    504   ret <4 x float> %vecinit13
    505 }
    506 ; CHECK-LABEL: not_a_hsub_2
    507 ; CHECK-NOT: hsubps
    508 ; CHECK: ret
    509 
    510 
    511 define <2 x double> @not_a_hsub_3(<2 x double> %A, <2 x double> %B) {
    512   %vecext = extractelement <2 x double> %B, i32 0
    513   %vecext1 = extractelement <2 x double> %B, i32 1
    514   %sub = fsub double %vecext, %vecext1
    515   %vecinit = insertelement <2 x double> undef, double %sub, i32 1
    516   %vecext2 = extractelement <2 x double> %A, i32 1
    517   %vecext3 = extractelement <2 x double> %A, i32 0
    518   %sub2 = fsub double %vecext2, %vecext3
    519   %vecinit2 = insertelement <2 x double> %vecinit, double %sub2, i32 0
    520   ret <2 x double> %vecinit2
    521 }
    522 ; CHECK-LABEL: not_a_hsub_3
    523 ; CHECK-NOT: hsubpd
    524 ; CHECK: ret
    525 
    526 
    527 ; Test AVX horizontal add/sub of packed single/double precision
    528 ; floating point values from 256-bit vectors.
    529 
    530 define <8 x float> @avx_vhadd_ps(<8 x float> %a, <8 x float> %b) {
    531   %vecext = extractelement <8 x float> %a, i32 0
    532   %vecext1 = extractelement <8 x float> %a, i32 1
    533   %add = fadd float %vecext, %vecext1
    534   %vecinit = insertelement <8 x float> undef, float %add, i32 0
    535   %vecext2 = extractelement <8 x float> %a, i32 2
    536   %vecext3 = extractelement <8 x float> %a, i32 3
    537   %add4 = fadd float %vecext2, %vecext3
    538   %vecinit5 = insertelement <8 x float> %vecinit, float %add4, i32 1
    539   %vecext6 = extractelement <8 x float> %b, i32 0
    540   %vecext7 = extractelement <8 x float> %b, i32 1
    541   %add8 = fadd float %vecext6, %vecext7
    542   %vecinit9 = insertelement <8 x float> %vecinit5, float %add8, i32 2
    543   %vecext10 = extractelement <8 x float> %b, i32 2
    544   %vecext11 = extractelement <8 x float> %b, i32 3
    545   %add12 = fadd float %vecext10, %vecext11
    546   %vecinit13 = insertelement <8 x float> %vecinit9, float %add12, i32 3
    547   %vecext14 = extractelement <8 x float> %a, i32 4
    548   %vecext15 = extractelement <8 x float> %a, i32 5
    549   %add16 = fadd float %vecext14, %vecext15
    550   %vecinit17 = insertelement <8 x float> %vecinit13, float %add16, i32 4
    551   %vecext18 = extractelement <8 x float> %a, i32 6
    552   %vecext19 = extractelement <8 x float> %a, i32 7
    553   %add20 = fadd float %vecext18, %vecext19
    554   %vecinit21 = insertelement <8 x float> %vecinit17, float %add20, i32 5
    555   %vecext22 = extractelement <8 x float> %b, i32 4
    556   %vecext23 = extractelement <8 x float> %b, i32 5
    557   %add24 = fadd float %vecext22, %vecext23
    558   %vecinit25 = insertelement <8 x float> %vecinit21, float %add24, i32 6
    559   %vecext26 = extractelement <8 x float> %b, i32 6
    560   %vecext27 = extractelement <8 x float> %b, i32 7
    561   %add28 = fadd float %vecext26, %vecext27
    562   %vecinit29 = insertelement <8 x float> %vecinit25, float %add28, i32 7
    563   ret <8 x float> %vecinit29
    564 }
    565 ; CHECK-LABEL: avx_vhadd_ps
    566 ; SSE3: haddps
    567 ; SSE3-NEXT: haddps
    568 ; SSSE3: haddps
    569 ; SSSE3-NEXT: haddps
    570 ; AVX: vhaddps
    571 ; AVX2: vhaddps
    572 ; CHECK: ret
    573 
    574 
    575 define <8 x float> @avx_vhsub_ps(<8 x float> %a, <8 x float> %b) {
    576   %vecext = extractelement <8 x float> %a, i32 0
    577   %vecext1 = extractelement <8 x float> %a, i32 1
    578   %sub = fsub float %vecext, %vecext1
    579   %vecinit = insertelement <8 x float> undef, float %sub, i32 0
    580   %vecext2 = extractelement <8 x float> %a, i32 2
    581   %vecext3 = extractelement <8 x float> %a, i32 3
    582   %sub4 = fsub float %vecext2, %vecext3
    583   %vecinit5 = insertelement <8 x float> %vecinit, float %sub4, i32 1
    584   %vecext6 = extractelement <8 x float> %b, i32 0
    585   %vecext7 = extractelement <8 x float> %b, i32 1
    586   %sub8 = fsub float %vecext6, %vecext7
    587   %vecinit9 = insertelement <8 x float> %vecinit5, float %sub8, i32 2
    588   %vecext10 = extractelement <8 x float> %b, i32 2
    589   %vecext11 = extractelement <8 x float> %b, i32 3
    590   %sub12 = fsub float %vecext10, %vecext11
    591   %vecinit13 = insertelement <8 x float> %vecinit9, float %sub12, i32 3
    592   %vecext14 = extractelement <8 x float> %a, i32 4
    593   %vecext15 = extractelement <8 x float> %a, i32 5
    594   %sub16 = fsub float %vecext14, %vecext15
    595   %vecinit17 = insertelement <8 x float> %vecinit13, float %sub16, i32 4
    596   %vecext18 = extractelement <8 x float> %a, i32 6
    597   %vecext19 = extractelement <8 x float> %a, i32 7
    598   %sub20 = fsub float %vecext18, %vecext19
    599   %vecinit21 = insertelement <8 x float> %vecinit17, float %sub20, i32 5
    600   %vecext22 = extractelement <8 x float> %b, i32 4
    601   %vecext23 = extractelement <8 x float> %b, i32 5
    602   %sub24 = fsub float %vecext22, %vecext23
    603   %vecinit25 = insertelement <8 x float> %vecinit21, float %sub24, i32 6
    604   %vecext26 = extractelement <8 x float> %b, i32 6
    605   %vecext27 = extractelement <8 x float> %b, i32 7
    606   %sub28 = fsub float %vecext26, %vecext27
    607   %vecinit29 = insertelement <8 x float> %vecinit25, float %sub28, i32 7
    608   ret <8 x float> %vecinit29
    609 }
    610 ; CHECK-LABEL: avx_vhsub_ps
    611 ; SSE3: hsubps
    612 ; SSE3-NEXT: hsubps
    613 ; SSSE3: hsubps
    614 ; SSSE3-NEXT: hsubps
    615 ; AVX: vhsubps
    616 ; AVX2: vhsubps
    617 ; CHECK: ret
    618 
    619 
    620 define <4 x double> @avx_hadd_pd(<4 x double> %a, <4 x double> %b) {
    621   %vecext = extractelement <4 x double> %a, i32 0
    622   %vecext1 = extractelement <4 x double> %a, i32 1
    623   %add = fadd double %vecext, %vecext1
    624   %vecinit = insertelement <4 x double> undef, double %add, i32 0
    625   %vecext2 = extractelement <4 x double> %b, i32 0
    626   %vecext3 = extractelement <4 x double> %b, i32 1
    627   %add4 = fadd double %vecext2, %vecext3
    628   %vecinit5 = insertelement <4 x double> %vecinit, double %add4, i32 1
    629   %vecext6 = extractelement <4 x double> %a, i32 2
    630   %vecext7 = extractelement <4 x double> %a, i32 3
    631   %add8 = fadd double %vecext6, %vecext7
    632   %vecinit9 = insertelement <4 x double> %vecinit5, double %add8, i32 2
    633   %vecext10 = extractelement <4 x double> %b, i32 2
    634   %vecext11 = extractelement <4 x double> %b, i32 3
    635   %add12 = fadd double %vecext10, %vecext11
    636   %vecinit13 = insertelement <4 x double> %vecinit9, double %add12, i32 3
    637   ret <4 x double> %vecinit13
    638 }
    639 ; CHECK-LABEL: avx_hadd_pd
    640 ; SSE3: haddpd
    641 ; SSE3-NEXT: haddpd
    642 ; SSSE3: haddpd
    643 ; SSSE3-NEXT: haddpd
    644 ; AVX: vhaddpd
    645 ; AVX2: vhaddpd
    646 ; CHECK: ret
    647 
    648 
    649 define <4 x double> @avx_hsub_pd(<4 x double> %a, <4 x double> %b) {
    650   %vecext = extractelement <4 x double> %a, i32 0
    651   %vecext1 = extractelement <4 x double> %a, i32 1
    652   %sub = fsub double %vecext, %vecext1
    653   %vecinit = insertelement <4 x double> undef, double %sub, i32 0
    654   %vecext2 = extractelement <4 x double> %b, i32 0
    655   %vecext3 = extractelement <4 x double> %b, i32 1
    656   %sub4 = fsub double %vecext2, %vecext3
    657   %vecinit5 = insertelement <4 x double> %vecinit, double %sub4, i32 1
    658   %vecext6 = extractelement <4 x double> %a, i32 2
    659   %vecext7 = extractelement <4 x double> %a, i32 3
    660   %sub8 = fsub double %vecext6, %vecext7
    661   %vecinit9 = insertelement <4 x double> %vecinit5, double %sub8, i32 2
    662   %vecext10 = extractelement <4 x double> %b, i32 2
    663   %vecext11 = extractelement <4 x double> %b, i32 3
    664   %sub12 = fsub double %vecext10, %vecext11
    665   %vecinit13 = insertelement <4 x double> %vecinit9, double %sub12, i32 3
    666   ret <4 x double> %vecinit13
    667 }
    668 ; CHECK-LABEL: avx_hsub_pd
    669 ; SSE3: hsubpd
    670 ; SSE3-NEXT: hsubpd
    671 ; SSSE3: hsubpd
    672 ; SSSE3-NEXT: hsubpd
    673 ; AVX: vhsubpd
    674 ; AVX2: vhsubpd
    675 ; CHECK: ret
    676 
    677 
    678 ; Test AVX2 horizontal add of packed integer values from 256-bit vectors.
    679 
    680 define <8 x i32> @avx2_hadd_d(<8 x i32> %a, <8 x i32> %b) {
    681   %vecext = extractelement <8 x i32> %a, i32 0
    682   %vecext1 = extractelement <8 x i32> %a, i32 1
    683   %add = add i32 %vecext, %vecext1
    684   %vecinit = insertelement <8 x i32> undef, i32 %add, i32 0
    685   %vecext2 = extractelement <8 x i32> %a, i32 2
    686   %vecext3 = extractelement <8 x i32> %a, i32 3
    687   %add4 = add i32 %vecext2, %vecext3
    688   %vecinit5 = insertelement <8 x i32> %vecinit, i32 %add4, i32 1
    689   %vecext6 = extractelement <8 x i32> %b, i32 0
    690   %vecext7 = extractelement <8 x i32> %b, i32 1
    691   %add8 = add i32 %vecext6, %vecext7
    692   %vecinit9 = insertelement <8 x i32> %vecinit5, i32 %add8, i32 2
    693   %vecext10 = extractelement <8 x i32> %b, i32 2
    694   %vecext11 = extractelement <8 x i32> %b, i32 3
    695   %add12 = add i32 %vecext10, %vecext11
    696   %vecinit13 = insertelement <8 x i32> %vecinit9, i32 %add12, i32 3
    697   %vecext14 = extractelement <8 x i32> %a, i32 4
    698   %vecext15 = extractelement <8 x i32> %a, i32 5
    699   %add16 = add i32 %vecext14, %vecext15
    700   %vecinit17 = insertelement <8 x i32> %vecinit13, i32 %add16, i32 4
    701   %vecext18 = extractelement <8 x i32> %a, i32 6
    702   %vecext19 = extractelement <8 x i32> %a, i32 7
    703   %add20 = add i32 %vecext18, %vecext19
    704   %vecinit21 = insertelement <8 x i32> %vecinit17, i32 %add20, i32 5
    705   %vecext22 = extractelement <8 x i32> %b, i32 4
    706   %vecext23 = extractelement <8 x i32> %b, i32 5
    707   %add24 = add i32 %vecext22, %vecext23
    708   %vecinit25 = insertelement <8 x i32> %vecinit21, i32 %add24, i32 6
    709   %vecext26 = extractelement <8 x i32> %b, i32 6
    710   %vecext27 = extractelement <8 x i32> %b, i32 7
    711   %add28 = add i32 %vecext26, %vecext27
    712   %vecinit29 = insertelement <8 x i32> %vecinit25, i32 %add28, i32 7
    713   ret <8 x i32> %vecinit29
    714 }
    715 ; CHECK-LABEL: avx2_hadd_d
    716 ; SSE3-NOT: phaddd
    717 ; SSSE3: phaddd
    718 ; SSSE3-NEXT: phaddd
    719 ; AVX: vphaddd
    720 ; AVX: vphaddd
    721 ; AVX2: vphaddd
    722 ; AVX2-NOT: vphaddd
    723 ; CHECK: ret
    724 
    725 
    726 define <16 x i16> @avx2_hadd_w(<16 x i16> %a, <16 x i16> %b) {
    727   %vecext = extractelement <16 x i16> %a, i32 0
    728   %vecext1 = extractelement <16 x i16> %a, i32 1
    729   %add = add i16 %vecext, %vecext1
    730   %vecinit = insertelement <16 x i16> undef, i16 %add, i32 0
    731   %vecext4 = extractelement <16 x i16> %a, i32 2
    732   %vecext6 = extractelement <16 x i16> %a, i32 3
    733   %add8 = add i16 %vecext4, %vecext6
    734   %vecinit10 = insertelement <16 x i16> %vecinit, i16 %add8, i32 1
    735   %vecext11 = extractelement <16 x i16> %a, i32 4
    736   %vecext13 = extractelement <16 x i16> %a, i32 5
    737   %add15 = add i16 %vecext11, %vecext13
    738   %vecinit17 = insertelement <16 x i16> %vecinit10, i16 %add15, i32 2
    739   %vecext18 = extractelement <16 x i16> %a, i32 6
    740   %vecext20 = extractelement <16 x i16> %a, i32 7
    741   %add22 = add i16 %vecext18, %vecext20
    742   %vecinit24 = insertelement <16 x i16> %vecinit17, i16 %add22, i32 3
    743   %vecext25 = extractelement <16 x i16> %a, i32 8
    744   %vecext27 = extractelement <16 x i16> %a, i32 9
    745   %add29 = add i16 %vecext25, %vecext27
    746   %vecinit31 = insertelement <16 x i16> %vecinit24, i16 %add29, i32 8
    747   %vecext32 = extractelement <16 x i16> %a, i32 10
    748   %vecext34 = extractelement <16 x i16> %a, i32 11
    749   %add36 = add i16 %vecext32, %vecext34
    750   %vecinit38 = insertelement <16 x i16> %vecinit31, i16 %add36, i32 9
    751   %vecext39 = extractelement <16 x i16> %a, i32 12
    752   %vecext41 = extractelement <16 x i16> %a, i32 13
    753   %add43 = add i16 %vecext39, %vecext41
    754   %vecinit45 = insertelement <16 x i16> %vecinit38, i16 %add43, i32 10
    755   %vecext46 = extractelement <16 x i16> %a, i32 14
    756   %vecext48 = extractelement <16 x i16> %a, i32 15
    757   %add50 = add i16 %vecext46, %vecext48
    758   %vecinit52 = insertelement <16 x i16> %vecinit45, i16 %add50, i32 11
    759   %vecext53 = extractelement <16 x i16> %b, i32 0
    760   %vecext55 = extractelement <16 x i16> %b, i32 1
    761   %add57 = add i16 %vecext53, %vecext55
    762   %vecinit59 = insertelement <16 x i16> %vecinit52, i16 %add57, i32 4
    763   %vecext60 = extractelement <16 x i16> %b, i32 2
    764   %vecext62 = extractelement <16 x i16> %b, i32 3
    765   %add64 = add i16 %vecext60, %vecext62
    766   %vecinit66 = insertelement <16 x i16> %vecinit59, i16 %add64, i32 5
    767   %vecext67 = extractelement <16 x i16> %b, i32 4
    768   %vecext69 = extractelement <16 x i16> %b, i32 5
    769   %add71 = add i16 %vecext67, %vecext69
    770   %vecinit73 = insertelement <16 x i16> %vecinit66, i16 %add71, i32 6
    771   %vecext74 = extractelement <16 x i16> %b, i32 6
    772   %vecext76 = extractelement <16 x i16> %b, i32 7
    773   %add78 = add i16 %vecext74, %vecext76
    774   %vecinit80 = insertelement <16 x i16> %vecinit73, i16 %add78, i32 7
    775   %vecext81 = extractelement <16 x i16> %b, i32 8
    776   %vecext83 = extractelement <16 x i16> %b, i32 9
    777   %add85 = add i16 %vecext81, %vecext83
    778   %vecinit87 = insertelement <16 x i16> %vecinit80, i16 %add85, i32 12
    779   %vecext88 = extractelement <16 x i16> %b, i32 10
    780   %vecext90 = extractelement <16 x i16> %b, i32 11
    781   %add92 = add i16 %vecext88, %vecext90
    782   %vecinit94 = insertelement <16 x i16> %vecinit87, i16 %add92, i32 13
    783   %vecext95 = extractelement <16 x i16> %b, i32 12
    784   %vecext97 = extractelement <16 x i16> %b, i32 13
    785   %add99 = add i16 %vecext95, %vecext97
    786   %vecinit101 = insertelement <16 x i16> %vecinit94, i16 %add99, i32 14
    787   %vecext102 = extractelement <16 x i16> %b, i32 14
    788   %vecext104 = extractelement <16 x i16> %b, i32 15
    789   %add106 = add i16 %vecext102, %vecext104
    790   %vecinit108 = insertelement <16 x i16> %vecinit101, i16 %add106, i32 15
    791   ret <16 x i16> %vecinit108
    792 }
    793 ; CHECK-LABEL: avx2_hadd_w
    794 ; SSE3-NOT: phaddw
    795 ; SSSE3: phaddw
    796 ; SSSE3-NEXT: phaddw
    797 ; AVX: vphaddw
    798 ; AVX: vphaddw
    799 ; AVX2: vphaddw
    800 ; AVX2-NOT: vphaddw
    801 ; CHECK: ret
    802 
    803