Inefficient `half` and `bfloat` identify on targets that use NaN-boxing (RISC-V and loongarch)
- Dominant language
- LLVM
- Stars
- 40.5k
- Forks
- 18.7k
- PR merge metrics
- PR metrics pending
Description
Input
```llvm
define half @identity_f16(half) {
ret half %0
}
define bfloat @identity_bf16(bfloat) {
ret bfloat %0
}
; No issues
define float @identity_f32(float) {
ret float %0
}
```
Output on RV64:
```asm
identity_f16:
fmv.x.w a0, fa0
lui a1, 1048560
or a0, a0, a1
fmv.w.x fa0, a0
ret
identity_bf16:
fmv.x.w a0, fa0
lui a1, 1048560
or a0, a0, a1
fmv.w.x fa0, a0
ret
identity_f32:
ret
```
Output on loongarch64:
```asm
identity_f16:
movfr2gr.s $a0, $fa0
lu12i.w $a1, -16
or $a0, $a0, $a1
movgr2fr.w $fa0, $a0
ret
identity_bf16:
movfr2gr.s $a0, $fa0
lu12i.w $a1, -16
or $a0, $a0, $a1
movgr2fr.w $fa0, $a0
ret
identity_f32:
ret
```
The RISC-V and loongarch targets appear to be packing the f16/bf16 into a NaN by setting the high bits to 0xffff. This isn't necessary, however; because it can be assumed that the passed argument should is already in proper form, these functions can just be a `ret`.
More at https://llvm.godbolt.org/z/ThfWeMjYP, noticed as part of https://github.com/rust-lang/rust/pull/160859/changes#r4020261459.
Contributor guide
Research direction
Start by reproducing the LLVM IR example on RV64 and loongarch64, comparing the generated identity_f16, identity_bf16, and identity_f32 output. The issue names no source file or test; trace the target code responsible for the extra NaN-boxing moves. Done means the half and bfloat identity functions return directly on both targets without the unnecessary packing sequence.
Written by the indexing model from the issue text.
Assessment
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100