Skip to content

Add integer to f16 conversions#729

Open
tgross35 wants to merge 2 commits intorust-lang:mainfrom
tgross35:f16-int-conv
Open

Add integer to f16 conversions#729
tgross35 wants to merge 2 commits intorust-lang:mainfrom
tgross35:f16-int-conv

Conversation

@tgross35
Copy link
Contributor

@tgross35 tgross35 commented Nov 5, 2024

These are not present in LLVM's compiler-rt but LLVM does emit them in some cases 1.

@tgross35 tgross35 marked this pull request as draft November 5, 2024 00:34
@tgross35 tgross35 force-pushed the f16-int-conv branch 3 times, most recently from 7230b09 to d2d4f22 Compare November 5, 2024 07:50
tgross35 added a commit to tgross35/compiler-builtins that referenced this pull request Nov 5, 2024
CI in [1] seems to indicate that there are cases where the `f16`
infinite recursion bug ([2], [3]) can make its way into what gets called
during tests, even though this doesn't seem to be the usual case. In
order to make sure that we avoid these completely, just unset
`f16_enabled` on any platforms that have the recursion problem.

This also refactors the `match` statement to be more in line with
`library/std/build.rs`.

[1]: rust-lang#729
[2]: llvm/llvm-project#97981
[3]: rust-lang#651
@tgross35 tgross35 force-pushed the f16-int-conv branch 4 times, most recently from 1a86a8d to f6a5429 Compare November 5, 2024 09:07
@tgross35
Copy link
Contributor Author

tgross35 commented Nov 5, 2024

Includes #730 since PPC crashes without it.

tgross35 added a commit to tgross35/rust that referenced this pull request Jun 3, 2025
CI in [1] seems to indicate that there are cases where the `f16`
infinite recursion bug ([2], [3]) can make its way into what gets called
during tests, even though this doesn't seem to be the usual case. In
order to make sure that we avoid these completely, just unset
`f16_enabled` on any platforms that have the recursion problem.

This also refactors the `match` statement to be more in line with
`library/std/build.rs`.

[1]: rust-lang/compiler-builtins#729
[2]: llvm/llvm-project#97981
[3]: rust-lang/compiler-builtins#651
tautschnig pushed a commit to model-checking/verify-rust-std that referenced this pull request Jun 17, 2025
CI in [1] seems to indicate that there are cases where the `f16`
infinite recursion bug ([2], [3]) can make its way into what gets called
during tests, even though this doesn't seem to be the usual case. In
order to make sure that we avoid these completely, just unset
`f16_enabled` on any platforms that have the recursion problem.

This also refactors the `match` statement to be more in line with
`library/std/build.rs`.

[1]: rust-lang/compiler-builtins#729
[2]: llvm/llvm-project#97981
[3]: rust-lang/compiler-builtins#651
tgross35 added a commit that referenced this pull request Jan 31, 2026
CI in [1] seems to indicate that there are cases where the `f16`
infinite recursion bug ([2], [3]) can make its way into what gets called
during tests, even though this doesn't seem to be the usual case. In
order to make sure that we avoid these completely, just unset
`f16_enabled` on any platforms that have the recursion problem.

This also refactors the `match` statement to be more in line with
`library/std/build.rs`.

[1]: #729
[2]: llvm/llvm-project#97981
[3]: #651
These are not present in LLVM's `compiler-rt` but LLVM does emit them in
some cases [1].

[1]: rust-lang/rust#132614 (comment)
@tgross35 tgross35 marked this pull request as ready for review February 12, 2026 07:52
@tgross35
Copy link
Contributor Author

@quaternic would you mind double checking some of my logic here?

With this current implementation, we are getting errors like the following:

thread 'i_to_f::__floatunsihf' (15281862) panicked at builtins-test/tests/conv.rs:103:5:
incorrect rounding by __floatunsihf(2147483648): inf (0x7c00)
f->i bracket: (65504, 4294967295, 0)
errors: (2147418144, 2147483647, 2147483648)

Which is coming from the bit of code here https://github.com/tgross35/compiler-builtins/blob/c462b7b5aa56a2ff3cdbfaf7c19143bbdee17b00/builtins-test/tests/conv.rs#L44-L79. I think the implementation is correct, especially considering the tests against apfloat seem okay. So I think this is an error in the validation algorithm here, which only shows up for f16 because f16::MAX is way closer to 0 (NAN as i*) than to any iN::MAX for N >= 32 (all that we have algorithms for). And that isn't true for any other float type, even f32::MAX as u128 is > u128::MAX / 2.

As I'm typing it out that sounds pretty reasonable, just need to figure out how to patch this error algorithm.

@quaternic
Copy link
Contributor

I think the validation logic is broken in that the apfloat-results that overflowed to infinity are converted back to an integer, specifically the maximum for the type, which should be irrelevant for the casting from integer to float.

The overflow threshold is specifically when the exponent after rounding exceeds the maximum. But the rounding itself is done as if the exponent was unbounded. So for f16:

[src/main.rs:4:5] f16::MAX.next_down() as f32 = 65472.0
[src/main.rs:5:5] f16::MAX as f32 = 65504.0
[src/main.rs:6:5] 65519 as f16 as f32 = 65504.0
[src/main.rs:7:5] 65520 as f16 as f32 = inf

65520 as f16 overflows because it would round to 65536.0 if the exponent range allowed.

@tgross35
Copy link
Contributor Author

Isn't that represented correctly? The apfloat bit at https://github.com/tgross35/compiler-builtins/blob/c462b7b5aa56a2ff3cdbfaf7c19143bbdee17b00/builtins-test/tests/conv.rs#L29-L37 should be the same as this:

>> :dep rustc_apfloat
   Compiling rustc_apfloat v0.2.3+llvm-462a31f5a5ab
   Compiling smallvec v1.15.1
   Compiling bitflags v2.10.0
>> use rustc_apfloat::ieee::Half
>> use rustc_apfloat::Float;
>> Half::from_i128(65519)
StatusAnd { status: Status(INEXACT), value: 65504(Normal | +[2047] * 2^15) }
>> Half::from_i128(65519).value.to_bits()
31743
>> Half::from_i128(65520)
StatusAnd { status: Status(OVERFLOW | INEXACT), value: +Inf(Infinity | +[0] * 2^16) }
>> Half::from_i128(65520).value.to_bits()
31744

@quaternic
Copy link
Contributor

Lines 48-50 as-cast the f16 values back to integers, which saturates inf to u32::MAX, and NaN to 0, which is where you get the printed line

f->i bracket: (65504, 4294967295, 0)

@tgross35
Copy link
Contributor Author

Ah, by

the apfloat-results that overflowed to infinity

I thought you were referring to the test above that uses rustc_apfloat. It's probably fine to skip the error_plus < error part of the check if <$f_ty>::wrapping_add(f1.to_bits().wrapping_sub(1)) is infinite then, right?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants