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

Reply via email to