[RISCV] Loop-carried WAR hazard on RISC-V vector registers
- 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
Assessment
This issue has not been assessed yet.