| Issue |
208549
|
| Summary |
RISC-V RV64 missed optimization? Narrow `trunc(load i64)` to `lbu`
|
| Labels |
new issue
|
| Assignees |
|
| Reporter |
ParkHanbum
|
## Summary
For a non-volatile, non-atomic `load i64, align 1` whose only demanded result
is `trunc ... to i8`, RV64 lowering reconstructs the entire unaligned i64 from
eight byte loads and shift/or operations. On little-endian RV64, the requested
result is simply the first byte, so it appears that the backend could emit one
`lbu` instead.
This report asks whether the RV64 behavior is an intended fault/legality
constraint or a missed RISC-V backend combine. It does not claim a correctness
bug.
## Reduced IR
```llvm
target triple = "riscv64-unknown-linux-gnu"
define i8 @decode(ptr %p) {
entry:
%w = load i64, ptr %p, align 1
%r = trunc i64 %w to i8
ret i8 %r
}
```
## Observed RV64 Assembly
`rocket-rv64` emits eight `lbu` instructions and reconstructs the complete
i64 with shifts and ors before returning it. The reduced output is 23
instructions including `ret`.
```asm
lbu a1, 0(a0)
lbu a2, 1(a0)
lbu a3, 2(a0)
lbu a4, 3(a0)
... # remaining bytes and reconstruction
ret
```
It lowers to:
```asm
lbu a0, 0(a0)
ret
```
## Cross-Target Evidence
- x86-64 lowers the current O2 IR to one `movzbl` load.
- AArch64 lowers it to one `ldrb` load.
- RISC-V RV32 also lowers the same current O2 IR to one `lbu` load.
- Only RV64 `rocket-rv64` expands the current form into the bytewise i64
reconstruction.
## Cost Evidence
`llvm-mca --iterations=100` for `rocket-rv64` reports:
| Form | Instructions | Total cycles | Total uOps | Block RThroughput |
|---|---:|---:|---:|---:|
| Current RV64 output | 2300 | 2501 | 2300 | 23.0 |
| Equivalent `load i8` form | 200 | 301 | 200 | 2.0 |
## Question
Is the RV64 expansion required by an intended RISC-V lowering or fault-semantics
constraint? If not, could RV64 recognize the demanded low byte before
legalizing/splitting the unaligned i64 load, analogous to the code generated
for RV32 and the other tested targets?
this pattern appeared so many project. for example, ffmpeg hevc.ll
```llvm
%36 = and i8 %35, 63
%37 = load i32, ptr %19, align 1, !tbaa !11
%38 = call i32 @llvm.bswap.i32(i32 %37)
%39 = lshr i32 %38, 19
%40 = call i32 @llvm.umin.i32(i32 %26, i32 13)
%41 = trunc i32 %39 to i8
```
_______________________________________________
llvm-bugs mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs