-
Notifications
You must be signed in to change notification settings - Fork 12.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
LLVM miscompiles consecutive half
operations by using too much precision on several backends
#97975
Comments
@llvm/issue-subscribers-backend-powerpc Author: None (beetrees)
Consider the following IR:
```llvm
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 However, it appears that on several backends LLVM will fail to round the intermediate result of consecutive 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):
I also noticed that 32-bit ARM has this problem in LLVM 18 but not on the |
@llvm/issue-subscribers-backend-hexagon Author: None (beetrees)
Consider the following IR:
```llvm
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 However, it appears that on several backends LLVM will fail to round the intermediate result of consecutive 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):
I also noticed that 32-bit ARM has this problem in LLVM 18 but not on the |
@llvm/issue-subscribers-backend-mips Author: None (beetrees)
Consider the following IR:
```llvm
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 However, it appears that on several backends LLVM will fail to round the intermediate result of consecutive 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):
I also noticed that 32-bit ARM has this problem in LLVM 18 but not on the |
@llvm/issue-subscribers-lld-wasm Author: None (beetrees)
Consider the following IR:
```llvm
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 However, it appears that on several backends LLVM will fail to round the intermediate result of consecutive 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):
I also noticed that 32-bit ARM has this problem in LLVM 18 but not on the |
@llvm/issue-subscribers-backend-m68k Author: None (beetrees)
Consider the following IR:
```llvm
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 However, it appears that on several backends LLVM will fail to round the intermediate result of consecutive 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):
I also noticed that 32-bit ARM has this problem in LLVM 18 but not on the |
@llvm/issue-subscribers-backend-msp430 Author: None (beetrees)
Consider the following IR:
```llvm
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 However, it appears that on several backends LLVM will fail to round the intermediate result of consecutive 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):
I also noticed that 32-bit ARM has this problem in LLVM 18 but not on the |
@llvm/issue-subscribers-backend-webassembly Author: None (beetrees)
Consider the following IR:
```llvm
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 However, it appears that on several backends LLVM will fail to round the intermediate result of consecutive 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):
I also noticed that 32-bit ARM has this problem in LLVM 18 but not on the |
half
operations with too much precision on several backendshalf
operations by using too much precision on several backends
I'm not sure that the
missed-optimization
label is correct: not truncating to |
In Julia we handle this by inserting manual conversion operations: https://github.com/JuliaLang/julia/blob/master/src/llvm-demote-float16.cpp While I am not a fan of this I think the current state is that this is a "frontend" problem, and not a backend issue. GCC and Clang only recently introduced |
Nice workaround! However I think it's fair to say that frontends shouldn't be required to insert custom passes late in the LLVM optimisation pipeline in order for LLVM to not miscompile basic floating point operations. As the comment at the top of the file mentions, it relies on some other optimisation passes (instcombine) not running after it that could undo all its hard work. LLVM IR requires that the basic floating point operations ( Given that this appears to have been fixed for 32-bit ARM in #80440, it seems that most of the fix will be changing |
@vchuravy I also notice the Julia pass also handles |
@maleadt might remember, I think our experience with |
LLVM IR semantics for the floating-point types are that, e.g., The emulation of |
That is indeed that patch. At the time, I couldn't afford to spend the time fixing every target so I didn't try. Thus the opt-in mechanism.
I don't think we use the broken Maybe I'll try changing the default for f16 for all targets and see what happens. |
Yeah, because of the uncertainty how LLVM would treat these operations we inserted the conversions to make sure the results can always be trusted (see JuliaLang/julia#51470 (comment) and the comments below). |
I have confirmed that the experimental C-SKY and Xtensa backends appear to also have this issue. |
Use softPromoteHalf legalization for fp16 rather than PromoteFloat. Fix llvm#97975.
Use softPromoteHalf legalization for fp16 rather than PromoteFloat. Fix llvm#97975.
Use softPromoteHalf legalization for fp16 rather than PromoteFloat. Fix llvm#97975.
Consider the following IR:
On backends without native
half
support, LLVM generally lowershalf
by converting tofloat
, performing the desired operation, and then converting back tohalf
. For this to be a valid lowering, a conversion back tof16
must occur after each operation, otherwise the excess precision offloat
will affect the result. For example65504.0 65504.0 -65504.0
equals infinity if each operation is done athalf
precision, but will result in65504.0
if the intermediate value is not rounded to ahalf
but instead kept as afloat
. 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 ofhalf
operations rather than a problem in any specific backend (for instance, AFAIK the only backend-specific code LoongArch has for handlinghalf
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-unknown-unknown
)csky-unknown-linux-gnuabiv2
)hexagon-unknown-linux-musl
)loongarch64-unknown-linux-gnu
): Fixed by [loongarch][DAG][FREEZE] Fix crash when FREEZE a half(f16) type on loongarch #107791m68k-unknown-linux-gnu
)mips64el-unknown-linux-gnuabi64
): Fixed by [MIPS] Use softPromoteHalf legalization for fp16 rather than PromoteFloat #110199msp430-none-elf
)powerpc64le-unknown-linux-gnu
)sparc64-unknown-linux-gnu
)wasm32-unknown-wasi
): Already reported in Onwasm32
,half
operation results aren't correctly rounded between each operation #96437xtensa-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.
The text was updated successfully, but these errors were encountered: