1; RUN: llc < %s -march=x86-64 -mattr=ssse3 | FileCheck %s -check-prefix=CHECK -check-prefix=SSE 2; RUN: llc < %s -march=x86-64 -mattr=avx | FileCheck %s -check-prefix=CHECK -check-prefix=AVX 3; RUN: llc < %s -march=x86-64 -mattr=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 7define <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 29define <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 51define <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 73define <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 85define <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 97define <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 115define <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 133define <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 149define <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 164define <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 182define <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 199define <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 217define <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 244define <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. 265define <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 282define <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 300define <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