Skip to content

Use the compiler to determine whether or not to enable f16 and f128 #963

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

Merged
merged 1 commit into from
Jul 2, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion builtins-test-intrinsics/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,5 @@ fn main() {
println!("cargo::rerun-if-changed=../configure.rs");

let target = builtins_configure::Target::from_env();
builtins_configure::configure_f16_f128(&target);
builtins_configure::configure_aliases(&target);
}
2 changes: 2 additions & 0 deletions builtins-test/benches/float_cmp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@ float_bench! {
],
}

#[cfg(f128_enabled)]
float_bench! {
name: cmp_f128_gt,
sig: (a: f128, b: f128) -> CmpResult,
Expand All @@ -189,6 +190,7 @@ float_bench! {
asm: []
}

#[cfg(f128_enabled)]
float_bench! {
name: cmp_f128_unord,
sig: (a: f128, b: f128) -> CmpResult,
Expand Down
1 change: 0 additions & 1 deletion builtins-test/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,5 +116,4 @@ fn main() {
}

builtins_configure::configure_aliases(&target);
builtins_configure::configure_f16_f128(&target);
}
4 changes: 2 additions & 2 deletions builtins-test/tests/conv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ mod i_to_f {
i128, __floattidf;
}

#[cfg(not(feature = "no-f16-f128"))]
#[cfg(f128_enabled)]
#[cfg(not(any(target_arch = "powerpc", target_arch = "powerpc64")))]
i_to_f! { f128, Quad, not(feature = "no-sys-f128-int-convert"),
u32, __floatunsitf;
Expand All @@ -129,7 +129,7 @@ mod i_to_f {
i128, __floattitf;
}

#[cfg(not(feature = "no-f16-f128"))]
#[cfg(f128_enabled)]
#[cfg(any(target_arch = "powerpc", target_arch = "powerpc64"))]
i_to_f! { f128, Quad, not(feature = "no-sys-f128-int-convert"),
u32, __floatunsikf;
Expand Down
4 changes: 2 additions & 2 deletions builtins-test/tests/div_rem.rs
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ mod float_div {
f64, __divdf3, Double, all();
}

#[cfg(not(feature = "no-f16-f128"))]
#[cfg(f128_enabled)]
#[cfg(not(any(target_arch = "powerpc", target_arch = "powerpc64")))]
float! {
f128, __divtf3, Quad,
Expand All @@ -156,7 +156,7 @@ mod float_div {
not(any(feature = "no-sys-f128", all(target_arch = "aarch64", target_os = "linux")));
}

#[cfg(not(feature = "no-f16-f128"))]
#[cfg(f128_enabled)]
#[cfg(any(target_arch = "powerpc", target_arch = "powerpc64"))]
float! {
f128, __divkf3, Quad, not(feature = "no-sys-f128");
Expand Down
3 changes: 1 addition & 2 deletions compiler-builtins/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ mod configure;

use std::env;

use configure::{Target, configure_aliases, configure_f16_f128};
use configure::{Target, configure_aliases};

fn main() {
println!("cargo::rerun-if-changed=build.rs");
Expand All @@ -12,7 +12,6 @@ fn main() {
let cwd = env::current_dir().unwrap();

configure_check_cfg();
configure_f16_f128(&target);
configure_aliases(&target);

configure_libm(&target);
Expand Down
81 changes: 30 additions & 51 deletions compiler-builtins/configure.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Configuration that is shared between `compiler_builtins` and `builtins_test`.

use std::env;
use std::process::{Command, Stdio};
use std::{env, str};

#[derive(Debug)]
#[allow(dead_code)]
Expand All @@ -16,6 +17,8 @@ pub struct Target {
pub pointer_width: u8,
pub little_endian: bool,
pub features: Vec<String>,
pub reliable_f128: bool,
pub reliable_f16: bool,
}

impl Target {
Expand All @@ -32,6 +35,19 @@ impl Target {
.map(|s| s.to_lowercase().replace("_", "-"))
.collect();

// Query rustc for options that Cargo does not provide env for. The bootstrap hack is used
// to get consistent output regardless of channel (`f16`/`f128` config options are hidden
// on stable otherwise).
let mut cmd = Command::new(env::var("RUSTC").unwrap());
cmd.args(["--print=cfg", "--target", &triple])
.env("RUSTC_BOOTSTRAP", "1")
.stderr(Stdio::inherit());
let out = cmd
.output()
.unwrap_or_else(|e| panic!("failed to run `{cmd:?}`: {e}"));
assert!(out.status.success(), "failed to run `{cmd:?}`");
let rustc_cfg = str::from_utf8(&out.stdout).unwrap();

Self {
triple,
triple_split,
Expand All @@ -51,6 +67,8 @@ impl Target {
.split(",")
.map(ToOwned::to_owned)
.collect(),
reliable_f128: rustc_cfg.lines().any(|l| l == "target_has_reliable_f128"),
reliable_f16: rustc_cfg.lines().any(|l| l == "target_has_reliable_f16"),
}
}

Expand All @@ -74,63 +92,24 @@ pub fn configure_aliases(target: &Target) {
if target.triple_split[0] == "thumbv6m" || target.triple_split[0] == "thumbv8m.base" {
println!("cargo:rustc-cfg=thumb_1")
}
}

/// Configure whether or not `f16` and `f128` support should be enabled.
pub fn configure_f16_f128(target: &Target) {
// Set whether or not `f16` and `f128` are supported at a basic level by LLVM. This only means
// that the backend will not crash when using these types and generates code that can be called
// without crashing (no infinite recursion). This does not mean that the platform doesn't have
// ABI or other bugs.
//
// We do this here rather than in `rust-lang/rust` because configuring via cargo features is
// not straightforward.
//
// Original source of this list:
// <https://github.com/rust-lang/compiler-builtins/pull/652#issuecomment-2266151350>
let f16_enabled = match target.arch.as_str() {
// Unsupported <https://github.com/llvm/llvm-project/issues/94434>
"arm64ec" => false,
// Selection failure <https://github.com/llvm/llvm-project/issues/50374>
"s390x" => false,
// Infinite recursion <https://github.com/llvm/llvm-project/issues/97981>
"csky" => false,
"hexagon" => false,
"powerpc" | "powerpc64" => false,
"sparc" | "sparc64" => false,
"wasm32" | "wasm64" => false,
// Most everything else works as of LLVM 19
_ => true,
};

let f128_enabled = match target.arch.as_str() {
// Unsupported (libcall is not supported) <https://github.com/llvm/llvm-project/issues/121122>
"amdgpu" => false,
// Unsupported <https://github.com/llvm/llvm-project/issues/94434>
"arm64ec" => false,
// FIXME(llvm20): fixed by <https://github.com/llvm/llvm-project/pull/117525>
"mips64" | "mips64r6" => false,
// Selection failure <https://github.com/llvm/llvm-project/issues/95471>
"nvptx64" => false,
// Selection failure <https://github.com/llvm/llvm-project/issues/101545>
"powerpc64" if &target.os == "aix" => false,
// Selection failure <https://github.com/llvm/llvm-project/issues/41838>
"sparc" => false,
// Most everything else works as of LLVM 19
_ => true,
};
/* Not all backends support `f16` and `f128` to the same level on all architectures, so we
* need to disable things if the compiler may crash. See configuration at:
* * https://github.com/rust-lang/rust/blob/c65dccabacdfd6c8a7f7439eba13422fdd89b91e/compiler/rustc_codegen_llvm/src/llvm_util.rs#L367-L432
* * https://github.com/rust-lang/rustc_codegen_gcc/blob/4b5c44b14166083eef8d71f15f5ea1f53fc976a0/src/lib.rs#L496-L507
* * https://github.com/rust-lang/rustc_codegen_cranelift/blob/c713ffab3c6e28ab4b4dd4e392330f786ea657ad/src/lib.rs#L196-L226
*/

// If the feature is set, disable these types.
let disable_both = env::var_os("CARGO_FEATURE_NO_F16_F128").is_some();
// If the feature is set, disable both of these types.
let no_f16_f128 = target.cargo_features.iter().any(|s| s == "no-f16-f128");

println!("cargo::rustc-check-cfg=cfg(f16_enabled)");
println!("cargo::rustc-check-cfg=cfg(f128_enabled)");

if f16_enabled && !disable_both {
if target.reliable_f16 && !no_f16_f128 {
println!("cargo::rustc-cfg=f16_enabled");
}

if f128_enabled && !disable_both {
println!("cargo::rustc-check-cfg=cfg(f128_enabled)");
if target.reliable_f128 && !no_f16_f128 {
println!("cargo::rustc-cfg=f128_enabled");
}
}
81 changes: 29 additions & 52 deletions libm/configure.rs
Original file line number Diff line number Diff line change
@@ -1,25 +1,30 @@
// Configuration shared with both libm and libm-test

use std::env;
use std::path::PathBuf;
use std::process::{Command, Stdio};
use std::{env, str};

#[allow(dead_code)]
pub struct Config {
pub manifest_dir: PathBuf,
pub out_dir: PathBuf,
pub opt_level: String,
pub cargo_features: Vec<String>,
pub target_triple: String,
pub target_arch: String,
pub target_env: String,
pub target_family: Option<String>,
pub target_os: String,
pub target_string: String,
pub target_vendor: String,
pub target_features: Vec<String>,
pub reliable_f128: bool,
pub reliable_f16: bool,
}

impl Config {
pub fn from_env() -> Self {
let target_triple = env::var("TARGET").unwrap();
let target_features = env::var("CARGO_CFG_TARGET_FEATURE")
.map(|feats| feats.split(',').map(ToOwned::to_owned).collect())
.unwrap_or_default();
Expand All @@ -28,7 +33,21 @@ impl Config {
.map(|s| s.to_lowercase().replace("_", "-"))
.collect();

// Query rustc for options that Cargo does not provide env for. The bootstrap hack is used
// to get consistent output regardless of channel (`f16`/`f128` config options are hidden
// on stable otherwise).
let mut cmd = Command::new(env::var("RUSTC").unwrap());
cmd.args(["--print=cfg", "--target", &target_triple])
.env("RUSTC_BOOTSTRAP", "1")
.stderr(Stdio::inherit());
let out = cmd
.output()
.unwrap_or_else(|e| panic!("failed to run `{cmd:?}`: {e}"));
assert!(out.status.success(), "failed to run `{cmd:?}`");
let rustc_cfg = str::from_utf8(&out.stdout).unwrap();

Self {
target_triple,
manifest_dir: PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap()),
out_dir: PathBuf::from(env::var("OUT_DIR").unwrap()),
opt_level: env::var("OPT_LEVEL").unwrap(),
Expand All @@ -40,6 +59,8 @@ impl Config {
target_string: env::var("TARGET").unwrap(),
target_vendor: env::var("CARGO_CFG_TARGET_VENDOR").unwrap(),
target_features,
reliable_f128: rustc_cfg.lines().any(|l| l == "target_has_reliable_f128"),
reliable_f16: rustc_cfg.lines().any(|l| l == "target_has_reliable_f16"),
}
}
}
Expand Down Expand Up @@ -128,62 +149,18 @@ fn emit_f16_f128_cfg(cfg: &Config) {
return;
}

// Set whether or not `f16` and `f128` are supported at a basic level by LLVM. This only means
// that the backend will not crash when using these types and generates code that can be called
// without crashing (no infinite recursion). This does not mean that the platform doesn't have
// ABI or other bugs.
//
// We do this here rather than in `rust-lang/rust` because configuring via cargo features is
// not straightforward.
//
// Original source of this list:
// <https://github.com/rust-lang/compiler-builtins/pull/652#issuecomment-2266151350>
let f16_enabled = match cfg.target_arch.as_str() {
// Unsupported <https://github.com/llvm/llvm-project/issues/94434>
"arm64ec" => false,
// Selection failure <https://github.com/llvm/llvm-project/issues/50374>
"s390x" => false,
// Infinite recursion <https://github.com/llvm/llvm-project/issues/97981>
// FIXME(llvm): loongarch fixed by <https://github.com/llvm/llvm-project/pull/107791>
"csky" => false,
"hexagon" => false,
"loongarch64" => false,
"mips" | "mips64" | "mips32r6" | "mips64r6" => false,
"powerpc" | "powerpc64" => false,
"sparc" | "sparc64" => false,
"wasm32" | "wasm64" => false,
// Most everything else works as of LLVM 19
_ => true,
};

let f128_enabled = match cfg.target_arch.as_str() {
// Unsupported (libcall is not supported) <https://github.com/llvm/llvm-project/issues/121122>
"amdgpu" => false,
// Unsupported <https://github.com/llvm/llvm-project/issues/94434>
"arm64ec" => false,
// Selection failure <https://github.com/llvm/llvm-project/issues/96432>
"mips64" | "mips64r6" => false,
// Selection failure <https://github.com/llvm/llvm-project/issues/95471>
"nvptx64" => false,
// Selection failure <https://github.com/llvm/llvm-project/issues/101545>
"powerpc64" if &cfg.target_os == "aix" => false,
// Selection failure <https://github.com/llvm/llvm-project/issues/41838>
"sparc" => false,
// Most everything else works as of LLVM 19
_ => true,
};

// If the feature is set, disable these types.
let disable_both = env::var_os("CARGO_FEATURE_NO_F16_F128").is_some();
/* See the compiler-builtins configure file for info about the meaning of these options */

println!("cargo:rustc-check-cfg=cfg(f16_enabled)");
println!("cargo:rustc-check-cfg=cfg(f128_enabled)");
// If the feature is set, disable both of these types.
let no_f16_f128 = cfg.cargo_features.iter().any(|s| s == "no-f16-f128");

if f16_enabled && !disable_both {
println!("cargo:rustc-check-cfg=cfg(f16_enabled)");
if cfg.reliable_f16 && !no_f16_f128 {
println!("cargo:rustc-cfg=f16_enabled");
}

if f128_enabled && !disable_both {
println!("cargo:rustc-check-cfg=cfg(f128_enabled)");
if cfg.reliable_f128 && !no_f16_f128 {
println!("cargo:rustc-cfg=f128_enabled");
}
}
Loading