-
Notifications
You must be signed in to change notification settings - Fork 14.6k
Description
Consider the following IR:
define half @to_half(i16 %bits) {
%f = bitcast i16 %bits to half
ret half %f
}
define i16 @from_half(half %f) {
%bits = bitcast half %f to i16
ret i16 %bits
}
As the only operation involved is a bitcast (in particular, there are no floating point type conversions in the LLVM IR), the values returned from to_half
and from_half
should be bit-for-bit identical to the value passed to them as their only argument (just a different type). However, several targets pass/return half
as a float
. On these targets, LLVM will use the default float conversion builtins (such as __gnu_h2f_ieee
and __gnu_f2h_ieee
) to convert between half
and float
. The issue is that these builtins silence signalling NaNs which changes the NaN payload, meaning that the roundtrip of half
-> float
-> half
is not lossless and causes the generated ASM to violate the semantics of LLVM IR. This miscompilation is similar to #66803.
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):
- C-SKY (
csky-unknown-linux-gnuabiv2
with-mcpu=ck860fv -mattr=+hard-float
)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 #130977LoongArch (loongarch64-unknown-linux-gnu
with-mattr=+f
): Fixed by [loongarch][DAG][FREEZE] Fix crash when FREEZE a half(f16) type on loongarch #107791MIPS (mips64el-unknown-linux-gnuabi64
): Fixed by [MIPS] Use softPromoteHalf legalization for fp16 rather than PromoteFloat #110199PowerPC (powerpc64le-unknown-linux-gnu
)SPARC (sparc64-unknown-linux-gnu
)WASM (wasm32-unknown-wasi
): Already reported inwasm32
queitenshalf
signalling NaNs in some situations when passing/returning them #96438To pick up a draggable item, press the space bar. While dragging, use the arrow keys to move the item. Press space again to drop the item in its new position, or press escape to cancel.
As none of these target's ABI specifications (that I've been able to find) specify how half
should be passed (nor does Clang support _Float16
on any of these targets), and given that these targets are a subset of those affected by #97975, I'm filing this as a single issue as the ABI has probably been selected as an automatic default by LLVM rather than a deliberate choice by the backends. Ultimately there are two possible solutions: either fix LLVM to codegen lossless conversions between half
and float
when needed for the ABI (one way to do this would be with a new pair of builtins that don't silence signalling NaNs), or change the ABIs to pass/return half
without converting it to float
(probably using the same ABI as i16
, but some targets might have better options).
Related to #97975.
Activity
llvmbot commentedon Jul 8, 2024
@llvm/issue-subscribers-backend-powerpc
Author: None (beetrees)
define i16 @from_half(half %f) {
%bits = bitcast half %f to i16
ret i16 %bits
}
llvmbot commentedon Jul 8, 2024
@llvm/issue-subscribers-backend-mips
Author: None (beetrees)
define i16 @from_half(half %f) {
%bits = bitcast half %f to i16
ret i16 %bits
}
llvmbot commentedon Jul 8, 2024
@llvm/issue-subscribers-backend-hexagon
Author: None (beetrees)
define i16 @from_half(half %f) {
%bits = bitcast half %f to i16
ret i16 %bits
}
llvmbot commentedon Jul 8, 2024
@llvm/issue-subscribers-backend-webassembly
Author: None (beetrees)
define i16 @from_half(half %f) {
%bits = bitcast half %f to i16
ret i16 %bits
}
f16
andf128
float types rust-lang/rust#116909vchuravy commentedon Jul 8, 2024
FYI: On PPC atleast you need to add
zext
I think. (On PPC i16 is being passed as i32 and that can cause issue)4 remaining items
beetrees commentedon Aug 3, 2024
I've confirmed that the experimental C-SKY backend also appears to experience this issue.
half
operations by using too much precision on several backends #97975beetrees commentedon Aug 22, 2024
The LoongArch backend also appears to have this issue.
f16
tests on loongarch rust-lang/rust#129384f16
tests on platforms that were missing conversion symbols rust-lang/rust#129385Disable `f16` on platforms that have recursion problems
f16
on platforms that have recursion problems rust-lang/compiler-builtins#730Disable `f16` on platforms that have recursion problems
Disable `f16` on platforms that have recursion problems