Skip to content

Add f16 formatting and parsing #127013

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

Open
wants to merge 4 commits into
base: master
Choose a base branch
from

Conversation

tgross35
Copy link
Contributor

@tgross35 tgross35 commented Jun 27, 2024

Use the same algorithms as for f32 and f64 to implement f16 parsing and printing.

try-job: aarch64-gnu

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-libs Relevant to the library team, which will review and decide on the PR/issue. labels Jun 27, 2024
@rust-log-analyzer

This comment has been minimized.

@tgross35
Copy link
Contributor Author

@rustbot label +rla-silenced

@rustbot rustbot added the rla-silenced Silences rust-log-analyzer postings to the PR it's added on. label Jun 27, 2024
@tgross35
Copy link
Contributor Author

@rustbot label +F-f16_and_f128

@rustbot rustbot added the F-f16_and_f128 `#![feature(f16)]`, `#![feature(f128)]` label Jun 27, 2024
@tgross35
Copy link
Contributor Author

tgross35 commented Jul 9, 2024

This will need #127510

@bors
Copy link
Collaborator

bors commented Jul 15, 2024

☔ The latest upstream changes (presumably #127020) made this pull request unmergeable. Please resolve the merge conflicts.

@tgross35 tgross35 force-pushed the f16-format-parse branch 2 times, most recently from 7c3f9c1 to f3ebeb3 Compare July 23, 2024 09:52
@tgross35
Copy link
Contributor Author

Update: I'm really just waiting on #128083 to bump stage0, managing #[cfg(not(bootstrap))] and always building stage1 got too painful.

@bors
Copy link
Collaborator

bors commented Jul 30, 2024

☔ The latest upstream changes (presumably #128360) made this pull request unmergeable. Please resolve the merge conflicts.

@Dylan-DPC Dylan-DPC added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Aug 20, 2024
@tgross35 tgross35 force-pushed the f16-format-parse branch 6 times, most recently from 21ffabc to 2098f01 Compare August 25, 2024 07:53
@rustbot rustbot added the T-bootstrap Relevant to the bootstrap subteam: Rust's build system (x.py and src/bootstrap) label Aug 25, 2024
@tgross35 tgross35 force-pushed the f16-format-parse branch 5 times, most recently from 404089f to 3636530 Compare August 30, 2024 09:04
@bors

This comment was marked as outdated.

bors added a commit to rust-lang-ci/rust that referenced this pull request Apr 29, 2025
Add `f16` formatting and parsing

Use the same algorithms as for `f32` and `f64` to implement `f16` parsing and printing.

try-job: aarch64-gnu
@bors

This comment was marked as outdated.

@bors bors added the S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. label Apr 29, 2025
@tgross35
Copy link
Contributor Author

@bors try

@bors
Copy link
Collaborator

bors commented Apr 29, 2025

⌛ Trying commit c5f4a2a with merge a94056d...

bors added a commit to rust-lang-ci/rust that referenced this pull request Apr 29, 2025
Add `f16` formatting and parsing

Use the same algorithms as for `f32` and `f64` to implement `f16` parsing and printing.

try-job: aarch64-gnu
tgross35 and others added 2 commits April 29, 2025 16:23
Extend the existing tests for `f32` and `f64` with versions that include
`f16`'s new printing and parsing implementations.

Co-authored-by: Speedy_Lex <alex.ciocildau@gmail.com>
This requires a fix to the subnormal test to cap the maximum allowed
value within the maximum mantissa.
@tgross35
Copy link
Contributor Author

@bors try

@bors
Copy link
Collaborator

bors commented Apr 29, 2025

⌛ Trying commit 5b2b504 with merge 5a35f4b...

bors added a commit to rust-lang-ci/rust that referenced this pull request Apr 29, 2025
Add `f16` formatting and parsing

Use the same algorithms as for `f32` and `f64` to implement `f16` parsing and printing.

try-job: aarch64-gnu
@rust-log-analyzer

This comment was marked as outdated.

@rust-log-analyzer

This comment has been minimized.

@bors
Copy link
Collaborator

bors commented Apr 29, 2025

💔 Test failed - checks-actions

@tgross35 tgross35 force-pushed the f16-format-parse branch 5 times, most recently from cfaf322 to e3826ce Compare May 3, 2025 05:54
In order to avoid crashes when compiling with Cranelift or on targets
where f16 is not well supported, choose to use a fallback based on
`target_has_reliable_f16`.
@tgross35 tgross35 force-pushed the f16-format-parse branch from e3826ce to f9243ad Compare May 3, 2025 06:41
@tgross35
Copy link
Contributor Author

tgross35 commented May 4, 2025

test-float-parse runs with stage0 so it can't use target_has_reliable_f16 until the next bootstrap bump happens. That's in ~1week so I'm just going to wait that out rather than trying to work around it.

Cc @bjorn3, the fourth patch uses cfg(target_has_reliable_f16) to select between the real implementations and a fallback. I really wasn't planning on using these in core/std but I can't think of a better way to add the implementations but keep things working with Cranelift (outside of aggressive inlining which likely wouldn't be great here).

@tgross35 tgross35 removed the S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. label May 4, 2025
@speedy-lex
Copy link
Contributor

speedy-lex commented May 6, 2025

@tgross35, what exactly is the problem of using the "is f16 supported" cfg in core/std? Weren't we using a huge target arch selector with a bunch of boolean stuff with x86, aarch64 and neon? Isn't the new cfg cleaner?

@tgross35
Copy link
Contributor Author

tgross35 commented May 6, 2025

Previously the build.rs config was only used in testing. Bjorn mentioned on Zulip that using it in std that we have to be a bit careful because there are cases where std built with target_has_reliable_f16 will be combined with crates that don't have that set, such as LLVM-built std and cranelift-built user crates.

I don't think this is a problem here since the API is the same and the config only determines whether or not a fallback is used, but it's worth somebody double checking my logic.

@tgross35
Copy link
Contributor Author

tgross35 commented May 6, 2025

Weren't we using a huge target arch selector with a bunch of boolean stuff with x86, aarch64 and neon? Isn't the new cfg cleaner?

Also to be clear this mess unfortunately still exists, it just moved to

fn update_target_reliable_float_cfg(sess: &Session, cfg: &mut TargetConfig) {
let target_arch = sess.target.arch.as_ref();
let target_os = sess.target.options.os.as_ref();
let target_env = sess.target.options.env.as_ref();
let target_abi = sess.target.options.abi.as_ref();
let target_pointer_width = sess.target.pointer_width;
cfg.has_reliable_f16 = match (target_arch, target_os) {
// Selection failure <https://github.com/llvm/llvm-project/issues/50374>
("s390x", _) => false,
// Unsupported <https://github.com/llvm/llvm-project/issues/94434>
("arm64ec", _) => false,
// MinGW ABI bugs <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115054>
("x86_64", "windows") if target_env == "gnu" && target_abi != "llvm" => false,
// Infinite recursion <https://github.com/llvm/llvm-project/issues/97981>
("csky", _) => false,
("hexagon", _) => false,
("powerpc" | "powerpc64", _) => false,
("sparc" | "sparc64", _) => false,
("wasm32" | "wasm64", _) => false,
// `f16` support only requires that symbols converting to and from `f32` are available. We
// provide these in `compiler-builtins`, so `f16` should be available on all platforms that
// do not have other ABI issues or LLVM crashes.
_ => true,
};
cfg.has_reliable_f128 = match (target_arch, target_os) {
// Unsupported <https://github.com/llvm/llvm-project/issues/94434>
("arm64ec", _) => false,
// Selection bug <https://github.com/llvm/llvm-project/issues/96432>
("mips64" | "mips64r6", _) => false,
// Selection bug <https://github.com/llvm/llvm-project/issues/95471>
("nvptx64", _) => false,
// ABI bugs <https://github.com/rust-lang/rust/issues/125109> et al. (full
// list at <https://github.com/rust-lang/rust/issues/116909>)
("powerpc" | "powerpc64", _) => false,
// ABI unsupported <https://github.com/llvm/llvm-project/issues/41838>
("sparc", _) => false,
// Stack alignment bug <https://github.com/llvm/llvm-project/issues/77401>. NB: tests may
// not fail if our compiler-builtins is linked.
("x86", _) => false,
// MinGW ABI bugs <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115054>
("x86_64", "windows") if target_env == "gnu" && target_abi != "llvm" => false,
// There are no known problems on other platforms, so the only requirement is that symbols
// are available. `compiler-builtins` provides all symbols required for core `f128`
// support, so this should work for everything else.
_ => true,
};
// Assume that working `f16` means working `f16` math for most platforms, since
// operations just go through `f32`.
cfg.has_reliable_f16_math = cfg.has_reliable_f16;
cfg.has_reliable_f128_math = match (target_arch, target_os) {
// LLVM lowers `fp128` math to `long double` symbols even on platforms where
// `long double` is not IEEE binary128. See
// <https://github.com/llvm/llvm-project/issues/44744>.
//
// This rules out anything that doesn't have `long double` = `binary128`; <= 32 bits
// (ld is `f64`), anything other than Linux (Windows and MacOS use `f64`), and `x86`
// (ld is 80-bit extended precision).
("x86_64", _) => false,
(_, "linux") if target_pointer_width == 64 => true,
_ => false,
} && cfg.has_reliable_f128;
}
:)

@speedy-lex
Copy link
Contributor

I don't think this is a problem here since the API is the same and the config only determines whether or not a fallback is used, but it's worth somebody double checking my logic.

@tgross35, This may be a problem. The cfg does select between implementations but it's selected at compile time as with all cfg's. This means LLVM will remove one of the implementations since it would be dead code. I don't think this is a major problem since f16 hardware impl should be reflected by the target arch. Something like this is what can be used to check and select features at runtime but I think something better would be:

  • Target triple has guaranteed f16 support -> use hardware support
  • Target triple might have f16 support -> use software impl
  • Target triple doesn't support f16 -> use software impl
    This way, we can be sure that f16 will work even if redistributing binaries.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-testsuite Area: The testsuite used to check the correctness of rustc F-f16_and_f128 `#![feature(f16)]`, `#![feature(f128)]` rla-silenced Silences rust-log-analyzer postings to the PR it's added on. S-blocked Status: Blocked on something else such as an RFC or other implementation work. T-bootstrap Relevant to the bootstrap subteam: Rust's build system (x.py and src/bootstrap) T-libs Relevant to the library team, which will review and decide on the PR/issue.
10 participants