llvm / llvm/llvm-project

[RISCV] Loop-carried WAR hazard on RISC-V vector registers

Open
#221,163 5 comments 0 reactions 1 assignee Claimed by @wangpc-pp View on GitHub
backend:RISC-V missed-optimization
Dominant language
LLVM
Stars
40.5k
Forks
18.7k
PR merge metrics
PR metrics pending

Description

Consider a typical vector add kernel:

```c
for (int i = 0; i < n; i += vl) {
vl = __riscv_vsetvl_e32m8(n - i);
vfloat32m8_t a = __riscv_vle32_v_f32m8(in1 + i, vl);
vfloat32m8_t b = __riscv_vle32_v_f32m8(in2 + i, vl);
vfloat32m8_t c = __riscv_vfadd_vv_f32m8(a, b, vl);
__riscv_vse32_v_f32m8(out + i, c, vl);
}
```

the post-RA code for the single-block loop body is:

```asm
.LBB0_1: # %for.body (inner loop)
vsetvli a4, a3, e32, m8, ta, ma
vle32.v v8, (a1) # load -> v8
vle32.v v16, (a2) # load -> v16
vfadd.vv v8, v8, v16 # v8 = v8 + v16
vse32.v v8, (a0) # store <- v8 <- same register as the load
add a1, a1, a4
add a0, a0, a5
bgtz a3, .LBB0_1
```

The register allocator placed both the load destination and the store source on v8. From the loop's perspective this is a perfectly tight allocation (within one iteration, v8 is reused end-to-end). But across iterations it creates a WAR.

I tried writing a pass to rename the registers to solve this problem. Can you suggest a better solution?

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.