Repository: rust
Issue: Floating point autovectorization pessimized without the use of black_box
Labels: A-LLVM,I-slow,T-compiler,C-optimization

I have the following routine to sum 128 `f32` numbers:

```rust
pub fn sum128(f: &[f32; 128]) -> f32 {
    let mut vsum: [f32; 16] = [0.0; 16];
    for chunk in f.chunks_exact(16) {
        for j in 0..16 {
            vsum[j] += chunk[j];
        }
    }

    // Without this silly statement the optimizer loses its mind trying
    // to combine the above loop with the below reduction.
    std::hint::black_box(vsum);

    let mut width = 16;
    while width > 4 {
        let half = width / 2;
        for j in 0..half {
            vsum[j] += vsum[half + j];
        }
        width = half;
    }
    
    (vsum[0] + vsum[2]) + (vsum[1] + vsum[3])
}
```

It consists of one loop to reduce the array into a `[f32; 16]`, and a second loop plus final sum to reduce that into a single `f32`. With the `std::hint::black_box` the generated assembly with `-C opt-level=3 -C target-cpu=skylake` is reasonable:

```asm
sum128:
        vxorps  xmm0, xmm0, xmm0
        vaddps  ymm1, ymm0, ymmword ptr [rdi]
        vaddps  ymm0, ymm0, ymmword ptr [rdi + 32]
        vaddps  ymm1, ymm1, ymmword ptr [rdi + 64]
        vaddps  ymm0, ymm0, ymmword ptr [rdi + 96]
        vaddps  ymm1, ymm1, ymmword ptr [rdi + 128]
        vaddps  ymm0, ymm0, ymmword ptr [rdi + 160]
        vaddps  ymm1, ymm1, ymmword ptr [rdi + 192]
        vaddps  ymm0, ymm0, ymmword ptr [rdi + 224]
        vaddps  ymm1, ymm1, ymmword ptr [rdi + 256]
        vaddps  ymm0, ymm0, ymmword ptr [rdi + 288]
        vaddps  ymm1, ymm1, ymmword ptr [rdi + 320]
        vaddps  ymm0, ymm0, ymmword ptr [rdi + 352]
        vaddps  ymm1, ymm1, ymmword ptr [rdi + 384]
        vaddps  ymm0, ymm0, ymmword ptr [rdi + 416]
        vaddps  ymm1, ymm1, ymmword ptr [rdi + 448]
        vaddps  ymm0, ymm0, ymmword ptr [rdi + 480]
        vmovups ymmword ptr [rsp - 64], ymm1  ; useless, black box
        vmovups ymmword ptr [rsp - 32], ymm0  ; useless, black box
        lea     rax, [rsp - 64]               ; useless, black box
        vaddps  ymm0, ymm0, ymm1
        vextractf128    xmm1, ymm0, 1
        vaddps  xmm0, xmm1, xmm0
        vshufpd xmm1, xmm0, xmm0, 1
        vaddps  xmm0, xmm0, xmm1
        vmovshdup       xmm1, xmm0
        vaddss  xmm0, xmm0, xmm1
        vzeroupper
        ret
```

29 instructions, 3 of which are useless due to `black_box`. If one were to remove the `black_box` though, the compiler completely loses it trying to interleave the two loops, creating a huge pessimization of the generated code:

```asm
sum128:
        vxorps  xmm0, xmm0, xmm0
        vmovsd  xmm1, qword ptr [rdi]
        vmovsd  xmm2, qword ptr [rdi + 8]
        vmovsd  xmm3, qword ptr [rdi + 16]
        vmovsd  xmm4, qword ptr [rdi + 24]
        vaddps  xmm1, xmm1, xmm0
        vaddps  xmm2, xmm2, xmm0
        vaddps  xmm3, xmm3, xmm0
        vaddps  xmm4, xmm4, xmm0
        vmovsd  xmm5, qword ptr [rdi + 32]
        vaddps  xmm5, xmm5, xmm0
        vmovsd  xmm6, qword ptr [rdi + 40]
        vaddps  xmm6, xmm6, xmm0
        vmovsd  xmm7, qword ptr [rdi + 48]
        vaddps  xmm7, xmm7, xmm0
        vmovsd  xmm8, qword ptr [rdi + 56]
        vaddps  xmm0, xmm8, xmm0
        vmovsd  xmm8, qword ptr [rdi + 64]
        vaddps  xmm1, xmm8, xmm1
        vmovsd  xmm8, qword ptr [rdi + 72]
        vaddps  xmm2, xmm8, xmm2
        vmovsd  xmm8, qword ptr [rdi + 80]
        vaddps  xmm3, xmm8, xmm3
        vmovsd  xmm8, qword ptr [rdi + 88]
        vaddps  xmm4, xmm8, xmm4
        vmovsd  xmm8, qword ptr [rdi + 96]
        vaddps  xmm5, xmm8, xmm5
        vmovsd  xmm8, qword ptr [rdi + 104]
        vaddps  xmm6, xmm8, xmm6
        vmovsd  xmm8, qword ptr [rdi + 112]
        vaddps  xmm7, xmm8, xmm7
        vmovsd  xmm8, qword ptr [rdi + 120]
        vaddps  xmm0, xmm8, xmm0
        vmovsd  xmm8, qword ptr [rdi + 128]
        vaddps  xmm1, xmm8, xmm1
        vmovsd  xmm8, qword ptr [rdi + 136]
        vaddps  xmm2, xmm8, xmm2
        vmovsd  xmm8, qword ptr [rdi + 144]
        vaddps  xmm3, xmm8, xmm3
        vmovsd  xmm8, qword ptr [rdi + 152]
        vaddps  xmm4, xmm8, xmm4
        vmovsd  xmm8, qword ptr [rdi + 160]
        vaddps  xmm5, xmm8, xmm5
        vmovsd  xmm8, qword ptr [rdi + 168]
        vaddps  xmm6, xmm8, xmm6
        vmovsd  xmm8, qword ptr [rdi + 176]
        vaddps  xmm7, xmm8, xmm7
        vmovsd  xmm8, qword ptr [rdi + 184]
        vaddps  xmm0, xmm8, xmm0
        vmovsd  xmm8, qword ptr [rdi + 192]
        vaddps  xmm1, xmm8, xmm1
        vmovsd  xmm8, qword ptr [rdi + 200]
        vaddps  xmm2, xmm8, xmm2
        vmovsd  xmm8, qword ptr [rdi + 208]
        vaddps  xmm3, xmm8, xmm3
        vmovsd  xmm8, qword ptr [rdi + 216]
        vaddps  xmm4, xmm8, xmm4
        vmovsd  xmm8, qword ptr [rdi + 224]
        vaddps  xmm5, xmm8, xmm5
        vmovsd  xmm8, qword ptr [rdi + 232]
        vaddps  xmm6, xmm8, xmm6
        vmovsd  xmm8, qword ptr [rdi + 240]
        vaddps  xmm7, xmm8, xmm7
        vmovsd  xmm8, qword ptr [rdi + 248]
        vaddps  xmm0, xmm8, xmm0
        vmovsd  xmm8, qword ptr [rdi + 256]
        vaddps  xmm1, xmm8, xmm1
        vmovsd  xmm8, qword ptr [rdi + 264]
        vaddps  xmm2, xmm8, xmm2
        vmovsd  xmm8, qword ptr [rdi + 272]
        vaddps  xmm3, xmm8, xmm3
        vmovsd  xmm8, qword ptr [rdi + 280]
        vaddps  xmm4, xmm8, xmm4
        vmovsd  xmm8, qword ptr [rdi + 288]
        vaddps  xmm5, xmm8, xmm5
        vmovsd  xmm8, qword ptr [rdi + 296]
        vaddps  xmm6, xmm8, xmm6
        vmovsd  xmm8, qword ptr [rdi + 304]
        vaddps  xmm7, xmm8, xmm7
        vmovsd  xmm8, qword ptr [rdi + 312]
        vaddps  xmm0, xmm8, xmm0
        vmovsd  xmm8, qword ptr [rdi + 320]
        vaddps  xmm1, xmm8, xmm1
        vmovsd  xmm8, qword ptr [rdi + 328]
        vaddps  xmm2, xmm8, xmm2
        vmovsd  xmm8, qword ptr [rdi + 336]
        vaddps  xmm3, xmm8, xmm3
        vmovsd  xmm8, qword ptr [rdi + 344]
        vaddps  xmm4, xmm8, xmm4
        vmovsd  xmm8, qword ptr [rdi + 352]
        vaddps  xmm5, xmm8, xmm5
        vmovsd  xmm8, qword ptr [rdi + 360]
        vaddps  xmm6, xmm8, xmm6
        vmovsd  xmm8, qword ptr [rdi + 368]
        vaddps  xmm7, xmm8, xmm7
        vmovsd  xmm8, qword ptr [rdi + 376]
        vaddps  xmm0, xmm8, xmm0
        vmovsd  xmm8, qword ptr [rdi + 384]
        vaddps  xmm1, xmm8, xmm1
        vmovsd  xmm8, qword ptr [rdi + 392]
        vaddps  xmm2, xmm8, xmm2
        vmovsd  xmm8, qword ptr [rdi + 400]
        vaddps  xmm3, xmm8, xmm3
        vmovsd  xmm8, qword ptr [rdi + 408]
        vaddps  xmm4, xmm8, xmm4
        vmovsd  xmm8, qword ptr [rdi + 416]
        vaddps  xmm5, xmm8, xmm5
        vmovsd  xmm8, qword ptr [rdi + 424]
        vaddps  xmm6, xmm8, xmm6
        vmovsd  xmm8, qword ptr [rdi + 432]
        vaddps  xmm7, xmm8, xmm7
        vmovsd  xmm8, qword ptr [rdi + 440]
        vaddps  xmm0, xmm8, xmm0
        vmovsd  xmm8, qword ptr [rdi + 448]
        vaddps  xmm1, xmm8, xmm1
        vmovsd  xmm8, qword ptr [rdi + 456]
        vaddps  xmm2, xmm8, xmm2
        vmovsd  xmm8, qword ptr [rdi + 464]
        vaddps  xmm3, xmm8, xmm3
        vmovsd  xmm8, qword ptr [rdi + 472]
        vaddps  xmm4, xmm8, xmm4
        vmovsd  xmm8, qword ptr [rdi + 480]
        vaddps  xmm5, xmm8, xmm5
        vaddps  xmm1, xmm5, xmm1
        vmovsd  xmm5, qword ptr [rdi + 488]
        vaddps  xmm5, xmm5, xmm6
        vaddps  xmm2, xmm5, xmm2
        vmovsd  xmm5, qword ptr [rdi + 496]
        vaddps  xmm5, xmm5, xmm7
        vaddps  xmm3, xmm5, xmm3
        vaddps  xmm1, xmm3, xmm1
        vmovsd  xmm3, qword ptr [rdi + 504]
        vaddps  xmm0, xmm3, xmm0
        vaddps  xmm0, xmm0, xmm4
        vaddps  xmm0, xmm0, xmm2
        vaddps  xmm0, xmm1, xmm0
        vmovshdup       xmm1, xmm0
        vaddss  xmm0, xmm0, xmm1
        ret
```

We went from 29 to 139 instructions!