-
Notifications
You must be signed in to change notification settings - Fork 15k
Description
Consider the following IR:
define half @f(half %a, half %b, half %c) {
%d = fadd half %a, %b
%e = fadd half %d, %c
ret half %e
}On backends without native half support, LLVM generally lowers half by converting to float, performing the desired operation, and then converting back to half. For this to be a valid lowering, a conversion back to f16 must occur after each operation, otherwise the excess precision of float will affect the result. For example 65504.0 + 65504.0 + -65504.0 equals infinity if each operation is done at half precision, but will result in 65504.0 if the intermediate value is not rounded to a half but instead kept as a float. This excess runtime precision can lead to miscompilations similar to #89885.
However, it appears that on several backends LLVM will fail to round the intermediate result of consecutive half operations, leading to these kind of bugs. I'm filing this as a single issue rather than a separate issue for each backend as I believe this is an issue with LLVM's default handling of half operations rather than a problem in any specific backend (for instance, AFAIK the only backend-specific code LoongArch has for handling half was added in #94456).
By inspecting the assembly LLVM emits, I've discovered that at least the following backends appear to be affected (in brackets are a specific target triple that I've checked):
- AVR (
avr-unknown-unknown): Fixed by [AVR] Changehalfto usesoftPromoteHalfType#152783 - C-SKY (
csky-unknown-linux-gnuabiv2) - Hexagon (
hexagon-unknown-linux-musl): Fixed by [HEXAGON] Add support to lower "FREEZE a half(f16)" instruction on Hexagon and fix the isel-buildvector-v2f16.ll assertion #130977 - LoongArch (
loongarch64-unknown-linux-gnu): Fixed by [loongarch][DAG][FREEZE] Fix crash when FREEZE a half(f16) type on loongarch #107791 - M68k (
m68k-unknown-linux-gnu) - MIPS (
mips64el-unknown-linux-gnuabi64): Fixed by [MIPS] Use softPromoteHalf legalization for fp16 rather than PromoteFloat #110199 - MSP430 (
msp430-none-elf) - PowerPC (
powerpc64le-unknown-linux-gnu): Fixed by [PowerPC] Changehalfto use soft promotion rather thanPromoteFloat#152632 - SPARC (
sparc64-unknown-linux-gnu): Fixed by [SPARC] Changehalfto use soft promotion rather thanPromoteFloat#152727 - WASM (
wasm32-unknown-wasi): Already reported in Onwasm32,halfoperation results aren't correctly rounded between each operation #96437, fixed by [WebAssembly] Changehalfto use soft promotion rather thanPromoteFloat#152833 - Xtensa (
xtensa-none-elf)
I also noticed that 32-bit ARM has this problem in LLVM 18 but not on the main branch. Looking through the issue tracker, it seems it's likely that this was fixed by #80440.
Related to #97981.