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