Skip to content

Tracking Issue for f16 and f128 float types #116909

Description

@traviscross

View all comments

This is a tracking issue for the RFC 3453 (rust-lang/rfcs#3453).

The feature gate for the issue is #![feature(f16)] and #![feature(f128)].

From the RFC:

This RFC proposes adding new IEEE-compliant floating point types f16 and f128 into the core language and standard library. We will provide a soft float implementation for all targets, and use hardware support where possible.

About tracking issues

Tracking issues are used to record the overall progress of implementation. They are also used as hubs connecting to other relevant issues, e.g., bugs or open design questions. A tracking issue is however not meant for large scale discussion, questions, or bug reports about a feature. Instead, open a dedicated issue for the specific matter and add the relevant feature gate label.

Steps

Unresolved questions

  • Do any new target features need to be marked as "forbidden" since they affect ABI? The logic here looks like that may be the case.
  • LLVM seems entirely unable to properly deal with the ABI for these operations, see e.g. this or this. It looks like fixing this will need some non-trivial LLVM changes to pick builtins with the right ABI, or else non-trivial Rust logic to reject e.g. * on f16 if LLVM would get the ABI wrong.
  • Clang rejects programs that try to use f16 on x86 without SSE. This means we have no template for what extern "C" should do, so maybe we should just reject code that tries to pass such values across extern "C"?

Implementation history and Future Steps

Note that // FIXME(f128)/// FIXME(f16)/// FIXME(f16,f128) and unimplemented!("f16_f128") are being used where relevant, to make the todo list easily greppable.

Nice to have changes:

Activity

  1. added
    C-tracking-issueCategory: An issue tracking the progress of sth. like the implementation of an RFC
    on Oct 18, 2023
  2. traviscross commented on Oct 18, 2023

    @traviscross
    Author
  3. traviscross commented on Oct 19, 2023

    @traviscross
    Author
  4. added
    B-RFC-approvedBlocker: Approved by a merged RFC but not yet implemented.
    on Oct 19, 2023
  5. tgross35 commented on Oct 19, 2023

    @tgross35
  6. gorentbarak commented on Oct 27, 2023

    @gorentbarak
  7. gorentbarak commented on Oct 27, 2023

    @gorentbarak
  8. gorentbarak commented on Oct 27, 2023

    @gorentbarak
  9. added
    I-prioritizeIssue needs a team member to assess the impact. Will be replaced by P-{low,medium,high,critical}
    on Oct 27, 2023
  10. gorentbarak commented on Oct 27, 2023

    @gorentbarak
  11. rustbot commented on Oct 27, 2023

    @rustbot
  12. gorentbarak commented on Oct 27, 2023

    @gorentbarak
  13. 132 remaining items

  14. added a commit that references this issue on Jan 22, 2026
  15. added a commit that references this issue on Jan 22, 2026
  16. pinskia commented on Jan 23, 2026

    @pinskia
  17. pinskia commented on Jan 23, 2026

    @pinskia

    We will provide a soft float implementation for all targets, and use hardware support where possible.

    This is bad form. The underyling target should decide if f16 and f128 are support rather than the language. This is how Fortran, C and many other languages are done.

  18. bjoernager commented on Jan 23, 2026

    @bjoernager
    Contributor

    Note I think the gate for f16 and f128 should be independent.
    That is have #![feature(f16)] and #![feature(f128)].

    They are already, and with the exact naming that you propose. ;)

    We will provide a soft float implementation for all targets, and use hardware support where possible.

    This is bad form. The underyling target should decide if f16 and f128 are support rather than the language.

    It seems that the consensus is to yield such optimisations to the programmer. But this statement also assumes that performance is more important than portability, which is not always the case for all software. Also, even just having the types for storage is useful.

    This is how Fortran, C and many other languages are done.

    Almost. It is not uncommon for compilers to provide soft floats on some embedded targets. But GCC and Clang, at least, do not seem do so on every target.

  19. programmerjake commented on Jan 23, 2026

    @programmerjake
    Member

    We will provide a soft float implementation for all targets, and use hardware support where possible.

    This is bad form. The underyling target should decide if f16 and f128 are support rather than the language. This is how Fortran, C and many other languages are done.

    I strongly disagree, any pure-computation API that Rust has should work anywhere, that allows code that needs those types to work anywhere even if a bit slowly instead of only wherever the target deigns to provide those types (not that many targets and IIRC some of them need very recent CPUs).

    That said, tracking issues aren't the place to have a long discussion, if you want to discuss it more, feel free to create a topic on https://internals.rust-lang.org/ and link it here.

  20. pinskia commented on Jan 23, 2026

    @pinskia
  21. bjoernager commented on Jan 23, 2026

    @bjoernager
  22. tgross35 commented on Jan 23, 2026

    @tgross35
    Member

    I assume you are coming here from the discussion on a GCC fallback?

    We eventually want these types available on all platforms because that shouldn't be the average programmer's concern. Of course the best case scenario is that the platform's ABI tells us exactly what to do, but it's not a good user experience if an otherwise functional library doesn't build on some platform just because they stopped updating their ABI a decade ago. Maybe the library could do something better on platforms that don't support f16/f128, but we'd like that to be a performance concern rather than a "does it work" concern. And then if they do eventually update the ABI, rust can adjust things as needed to match.

    I realize this is differs from the usual GCC path which e.g. doesn't support __int128 on i386 since it (despite my efforts) isn't specified there. But I think this is the perfect example where it would be nice if the compiler smoothed things over, because it is inconvenient and measurably bad for performance to roll your own __int128 to implement soft _Float128 ops (which is specified in i386. I'm aware _BitInt exists now.). And GCC also has some extensions.

    some targets don't have f16 (even in LLVM).

    AFAIK LLVM's half type now works on all targets since LLVM22, using i16 ABI and libcalls as a fallback. f128 still has some work to be done. For reference, we keep track of this at

    cfg.has_reliable_f16 = match (target_arch, target_os) {
    // LLVM crash without neon <https://github.com/llvm/llvm-project/issues/129394> (fixed in LLVM 20.1.1)
    (Arch::AArch64, _)
    if !cfg.target_features.iter().any(|f| f.as_str() == "neon")
    && version < (20, 1, 1) =>
    {
    false
    }
    // Unsupported <https://github.com/llvm/llvm-project/issues/94434> (fixed in llvm22)
    (Arch::Arm64EC, _) if major < 22 => false,
    // Selection failure <https://github.com/llvm/llvm-project/issues/50374> (fixed in llvm21)
    (Arch::S390x, _) if major < 21 => false,
    // MinGW ABI bugs <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115054>
    (Arch::X86_64, Os::Windows) if *target_env == Env::Gnu && *target_abi != Abi::Llvm => false,
    // Infinite recursion <https://github.com/llvm/llvm-project/issues/97981>
    (Arch::CSky, _) if major < 22 => false, // (fixed in llvm22)
    (Arch::Hexagon, _) if major < 21 => false, // (fixed in llvm21)
    (Arch::LoongArch32 | Arch::LoongArch64, _) if major < 21 => false, // (fixed in llvm21)
    (Arch::PowerPC | Arch::PowerPC64, _) if major < 22 => false, // (fixed in llvm22)
    (Arch::Sparc | Arch::Sparc64, _) if major < 22 => false, // (fixed in llvm22)
    (Arch::Wasm32 | Arch::Wasm64, _) if major < 22 => false, // (fixed in llvm22)
    // `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/121122
    (Arch::AmdGpu, _) => false,
    // Unsupported <https://github.com/llvm/llvm-project/issues/94434>
    (Arch::Arm64EC, _) => false,
    // Selection bug <https://github.com/llvm/llvm-project/issues/96432> (fixed in LLVM 20.1.0)
    (Arch::Mips64 | Arch::Mips64r6, _) if version < (20, 1, 0) => false,
    // Selection bug <https://github.com/llvm/llvm-project/issues/95471>. This issue is closed
    // but basic math still does not work.
    (Arch::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>)
    (Arch::PowerPC | Arch::PowerPC64, _) => false,
    // ABI unsupported <https://github.com/llvm/llvm-project/issues/41838>
    (Arch::Sparc, _) => false,
    // Stack alignment bug <https://github.com/llvm/llvm-project/issues/77401>. NB: tests may
    // not fail if our compiler-builtins is linked. (fixed in llvm21)
    (Arch::X86, _) if major < 21 => false,
    // MinGW ABI bugs <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115054>
    (Arch::X86_64, Os::Windows) if *target_env == Env::Gnu && *target_abi != 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).
    //
    // musl does not implement the symbols required for f128 math at all.
    _ if *target_env == Env::Musl => false,
    (Arch::X86_64, _) => false,
    (_, Os::Linux) if target_pointer_width == 64 => true,
    _ => false,
    } && cfg.has_reliable_f128;
    .

    Regarding where to discuss: the policy is absolutely not for the purpose of ignoring feedback. Things just get cluttered given the lack of threads on GH issues. Discussing on separate issues or at https://rust-lang.zulipchat.com is preferred for that reason, but I'd rather address this here than not at all.

  23. pinskia commented on Jan 23, 2026

    @pinskia
  24. tgross35 commented on Jan 23, 2026

    @tgross35
    Member

    Opened #151557 to continue this thread.

    Is there an email list instead? Email has a better interface than anything else?

    There is not, Zulip more or less took over the threaded discussion / public archive role.

  25. workingjubilee commented on Jan 25, 2026

    @workingjubilee
    Member

    While it seems that this discussion has been successfully channeled, I am locking this to discourage further reuse of this issue out-of-bounds of strictly "tracking" concerns, per rust-lang/compiler-team#739

    If you are not a team member and so cannot speak "over" the lock then you can create a new issue and ping back this one by linking to it. If it constitutes what should be an "unresolved question", "future step", or what-have-you, then a team member can edit that new issue into the tracking issue's initial post. Let all new comments from this point be of a similar procedural or "meta-level" nature.

  26. locked and limited conversation to collaborators on Jan 25, 2026
  27. ChrisDenton commented on Jul 1, 2026

    @ChrisDenton
    Member

    The maximum intrinsic is missing for wasm targets: #158673

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

Metadata

Metadata

Assignees

Labels

B-RFC-approvedBlocker: Approved by a merged RFC but not yet implemented.C-tracking-issueCategory: An issue tracking the progress of sth. like the implementation of an RFCF-f16_and_f128`#![feature(f16)]`, `#![feature(f128)]`T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.T-langRelevant to the language team

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions