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