Merge pull request #665 from kleisauke/wasm-f16-f128-feature

Configure `f16` and `f128` support for WebAssembly
This commit is contained in:
Trevor Gross 2024-08-12 11:41:46 -05:00 committed by GitHub
commit 9437d60d78
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
17 changed files with 261 additions and 180 deletions

View file

@ -1,44 +1,8 @@
use std::{collections::BTreeMap, env, path::PathBuf, sync::atomic::Ordering};
#[allow(dead_code)]
struct Target {
triple: String,
os: String,
arch: String,
vendor: String,
env: String,
pointer_width: u8,
little_endian: bool,
features: Vec<String>,
}
mod configure;
impl Target {
fn from_env() -> Self {
let little_endian = match env::var("CARGO_CFG_TARGET_ENDIAN").unwrap().as_str() {
"little" => true,
"big" => false,
x => panic!("unknown endian {x}"),
};
Self {
triple: env::var("TARGET").unwrap(),
os: env::var("CARGO_CFG_TARGET_OS").unwrap(),
arch: env::var("CARGO_CFG_TARGET_ARCH").unwrap(),
vendor: env::var("CARGO_CFG_TARGET_VENDOR").unwrap(),
env: env::var("CARGO_CFG_TARGET_ENV").unwrap(),
pointer_width: env::var("CARGO_CFG_TARGET_POINTER_WIDTH")
.unwrap()
.parse()
.unwrap(),
little_endian,
features: env::var("CARGO_CFG_TARGET_FEATURE")
.unwrap_or_default()
.split(",")
.map(ToOwned::to_owned)
.collect(),
}
}
}
use configure::{configure_f16_f128, Target};
fn main() {
println!("cargo:rerun-if-changed=build.rs");
@ -261,47 +225,6 @@ fn configure_check_cfg() {
println!("cargo::rustc-check-cfg=cfg(assert_no_panic)");
}
/// Configure whether or not `f16` and `f128` support should be enabled.
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. This does not mean that the
// backend does the right thing, or that the platform doesn't have ABI 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_ok, f128_ok) = match target.arch.as_str() {
// `f16` and `f128` both crash <https://github.com/llvm/llvm-project/issues/94434>
"arm64ec" => (false, false),
// `f16` crashes <https://github.com/llvm/llvm-project/issues/50374>
"s390x" => (false, true),
// `f128` crashes <https://github.com/llvm/llvm-project/issues/96432>
"mips64" | "mips64r6" => (true, false),
// `f128` crashes <https://github.com/llvm/llvm-project/issues/101545>
"powerpc64" if &target.os == "aix" => (true, false),
// `f128` crashes <https://github.com/llvm/llvm-project/issues/41838>
"sparc" | "sparcv9" => (true, false),
// Most everything else works as of LLVM 19
_ => (true, true),
};
// If the feature is set, disable these types.
let disable_both = env::var_os("CARGO_FEATURE_NO_F16_F128").is_some();
println!("cargo::rustc-check-cfg=cfg(f16_enabled)");
println!("cargo::rustc-check-cfg=cfg(f128_enabled)");
if f16_ok && !disable_both {
println!("cargo::rustc-cfg=f16_enabled");
}
if f128_ok && !disable_both {
println!("cargo::rustc-cfg=f128_enabled");
}
}
#[cfg(feature = "c")]
mod c {
use std::collections::{BTreeMap, HashSet};

View file

@ -0,0 +1,86 @@
// Configuration that is shared between `compiler_builtins` and `testcrate`.
use std::env;
#[allow(dead_code)]
pub struct Target {
pub triple: String,
pub os: String,
pub arch: String,
pub vendor: String,
pub env: String,
pub pointer_width: u8,
pub little_endian: bool,
pub features: Vec<String>,
}
impl Target {
pub fn from_env() -> Self {
let little_endian = match env::var("CARGO_CFG_TARGET_ENDIAN").unwrap().as_str() {
"little" => true,
"big" => false,
x => panic!("unknown endian {x}"),
};
Self {
triple: env::var("TARGET").unwrap(),
os: env::var("CARGO_CFG_TARGET_OS").unwrap(),
arch: env::var("CARGO_CFG_TARGET_ARCH").unwrap(),
vendor: env::var("CARGO_CFG_TARGET_VENDOR").unwrap(),
env: env::var("CARGO_CFG_TARGET_ENV").unwrap(),
pointer_width: env::var("CARGO_CFG_TARGET_POINTER_WIDTH")
.unwrap()
.parse()
.unwrap(),
little_endian,
features: env::var("CARGO_CFG_TARGET_FEATURE")
.unwrap_or_default()
.split(",")
.map(ToOwned::to_owned)
.collect(),
}
}
}
/// 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. This does not mean that the
// backend does the right thing, or that the platform doesn't have ABI 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_ok, f128_ok) = match target.arch.as_str() {
// `f16` and `f128` both crash <https://github.com/llvm/llvm-project/issues/94434>
"arm64ec" => (false, false),
// `f16` crashes <https://github.com/llvm/llvm-project/issues/50374>
"s390x" => (false, true),
// `f128` crashes <https://github.com/llvm/llvm-project/issues/96432>
"mips64" | "mips64r6" => (true, false),
// `f128` crashes <https://github.com/llvm/llvm-project/issues/101545>
"powerpc64" if &target.os == "aix" => (true, false),
// `f128` crashes <https://github.com/llvm/llvm-project/issues/41838>
"sparc" | "sparcv9" => (true, false),
// `f16` miscompiles <https://github.com/llvm/llvm-project/issues/96438>
"wasm32" | "wasm64" => (false, true),
// Most everything else works as of LLVM 19
_ => (true, true),
};
// If the feature is set, disable these types.
let disable_both = env::var_os("CARGO_FEATURE_NO_F16_F128").is_some();
println!("cargo::rustc-check-cfg=cfg(f16_enabled)");
println!("cargo::rustc-check-cfg=cfg(f128_enabled)");
if f16_ok && !disable_both {
println!("cargo::rustc-cfg=f16_enabled");
}
if f128_ok && !disable_both {
println!("cargo::rustc-cfg=f128_enabled");
}
}

View file

@ -1,7 +1,7 @@
#![feature(f128)]
#![cfg_attr(f128_enabled, feature(f128))]
use compiler_builtins::float::add;
use criterion::{criterion_group, criterion_main, Criterion};
use criterion::{criterion_main, Criterion};
use testcrate::float_bench;
float_bench! {
@ -66,6 +66,7 @@ float_bench! {
],
}
#[cfg(f128_enabled)]
float_bench! {
name: add_f128,
sig: (a: f128, b: f128) -> f128,
@ -77,5 +78,16 @@ float_bench! {
asm: []
}
criterion_group!(float_add, add_f32, add_f64, add_f128);
pub fn float_add() {
let mut criterion = Criterion::default().configure_from_args();
add_f32(&mut criterion);
add_f64(&mut criterion);
#[cfg(f128_enabled)]
{
add_f128(&mut criterion);
}
}
criterion_main!(float_add);

View file

@ -1,6 +1,6 @@
#![feature(f128)]
#![cfg_attr(f128_enabled, feature(f128))]
use criterion::{criterion_group, criterion_main, Criterion};
use criterion::{criterion_main, Criterion};
use testcrate::float_bench;
use compiler_builtins::float::cmp;
@ -190,13 +190,19 @@ float_bench! {
asm: []
}
criterion_group!(
float_cmp,
cmp_f32_gt,
cmp_f32_unord,
cmp_f64_gt,
cmp_f64_unord,
cmp_f128_gt,
cmp_f128_unord
);
pub fn float_cmp() {
let mut criterion = Criterion::default().configure_from_args();
cmp_f32_gt(&mut criterion);
cmp_f32_unord(&mut criterion);
cmp_f64_gt(&mut criterion);
cmp_f64_unord(&mut criterion);
#[cfg(f128_enabled)]
{
cmp_f128_gt(&mut criterion);
cmp_f128_unord(&mut criterion);
}
}
criterion_main!(float_cmp);

View file

@ -1,4 +1,3 @@
#![feature(f128)]
#![allow(improper_ctypes)]
use compiler_builtins::float::conv;

View file

@ -1,5 +1,3 @@
#![feature(f128)]
use compiler_builtins::float::div;
use criterion::{criterion_group, criterion_main, Criterion};
use testcrate::float_bench;

View file

@ -1,11 +1,12 @@
#![allow(unused_variables)] // "unused" f16 registers
#![feature(f128)]
#![feature(f16)]
#![cfg_attr(f128_enabled, feature(f128))]
#![cfg_attr(f16_enabled, feature(f16))]
use compiler_builtins::float::extend;
use criterion::{criterion_group, criterion_main, Criterion};
use criterion::{criterion_main, Criterion};
use testcrate::float_bench;
#[cfg(f16_enabled)]
float_bench! {
name: extend_f16_f32,
sig: (a: f16) -> f32,
@ -28,6 +29,7 @@ float_bench! {
],
}
#[cfg(all(f16_enabled, f128_enabled))]
float_bench! {
name: extend_f16_f128,
sig: (a: f16) -> f128,
@ -60,6 +62,7 @@ float_bench! {
],
}
#[cfg(f128_enabled)]
float_bench! {
name: extend_f32_f128,
sig: (a: f32) -> f128,
@ -71,6 +74,7 @@ float_bench! {
asm: [],
}
#[cfg(f128_enabled)]
float_bench! {
name: extend_f64_f128,
sig: (a: f64) -> f128,
@ -82,23 +86,28 @@ float_bench! {
asm: [],
}
#[cfg(not(any(target_arch = "powerpc", target_arch = "powerpc64")))]
criterion_group!(
float_extend,
extend_f16_f32,
extend_f16_f128,
extend_f32_f64,
extend_f32_f128,
extend_f64_f128,
);
pub fn float_extend() {
let mut criterion = Criterion::default().configure_from_args();
// FIXME(#655): `f16` tests disabled until we can bootstrap symbols
#[cfg(any(target_arch = "powerpc", target_arch = "powerpc64"))]
criterion_group!(
float_extend,
extend_f32_f64,
extend_f32_f128,
extend_f64_f128,
);
// FIXME(#655): `f16` tests disabled until we can bootstrap symbols
#[cfg(f16_enabled)]
#[cfg(not(any(target_arch = "powerpc", target_arch = "powerpc64")))]
{
extend_f16_f32(&mut criterion);
#[cfg(f128_enabled)]
{
extend_f16_f128(&mut criterion);
}
}
extend_f32_f64(&mut criterion);
#[cfg(f128_enabled)]
{
extend_f32_f128(&mut criterion);
extend_f64_f128(&mut criterion);
}
}
criterion_main!(float_extend);

View file

@ -1,7 +1,7 @@
#![feature(f128)]
#![cfg_attr(f128_enabled, feature(f128))]
use compiler_builtins::float::mul;
use criterion::{criterion_group, criterion_main, Criterion};
use criterion::{criterion_main, Criterion};
use testcrate::float_bench;
float_bench! {
@ -66,6 +66,7 @@ float_bench! {
],
}
#[cfg(f128_enabled)]
float_bench! {
name: mul_f128,
sig: (a: f128, b: f128) -> f128,
@ -77,5 +78,16 @@ float_bench! {
asm: []
}
criterion_group!(float_mul, mul_f32, mul_f64, mul_f128);
pub fn float_mul() {
let mut criterion = Criterion::default().configure_from_args();
mul_f32(&mut criterion);
mul_f64(&mut criterion);
#[cfg(f128_enabled)]
{
mul_f128(&mut criterion);
}
}
criterion_main!(float_mul);

View file

@ -1,7 +1,7 @@
#![feature(f128)]
#![cfg_attr(f128_enabled, feature(f128))]
use compiler_builtins::float::sub;
use criterion::{criterion_group, criterion_main, Criterion};
use criterion::{criterion_main, Criterion};
use testcrate::float_bench;
float_bench! {
@ -66,6 +66,7 @@ float_bench! {
],
}
#[cfg(f128_enabled)]
float_bench! {
name: sub_f128,
sig: (a: f128, b: f128) -> f128,
@ -77,5 +78,16 @@ float_bench! {
asm: []
}
criterion_group!(float_sub, sub_f32, sub_f64, sub_f128);
pub fn float_sub() {
let mut criterion = Criterion::default().configure_from_args();
sub_f32(&mut criterion);
sub_f64(&mut criterion);
#[cfg(f128_enabled)]
{
sub_f128(&mut criterion);
}
}
criterion_main!(float_sub);

View file

@ -1,10 +1,11 @@
#![feature(f128)]
#![feature(f16)]
#![cfg_attr(f128_enabled, feature(f128))]
#![cfg_attr(f16_enabled, feature(f16))]
use compiler_builtins::float::trunc;
use criterion::{criterion_group, criterion_main, Criterion};
use criterion::{criterion_main, Criterion};
use testcrate::float_bench;
#[cfg(f16_enabled)]
float_bench! {
name: trunc_f32_f16,
sig: (a: f32) -> f16,
@ -27,6 +28,7 @@ float_bench! {
],
}
#[cfg(f16_enabled)]
float_bench! {
name: trunc_f64_f16,
sig: (a: f64) -> f16,
@ -82,6 +84,7 @@ float_bench! {
],
}
#[cfg(all(f16_enabled, f128_enabled))]
float_bench! {
name: trunc_f128_f16,
sig: (a: f128) -> f16,
@ -93,6 +96,7 @@ float_bench! {
asm: [],
}
#[cfg(f128_enabled)]
float_bench! {
name: trunc_f128_f32,
sig: (a: f128) -> f32,
@ -104,6 +108,7 @@ float_bench! {
asm: [],
}
#[cfg(f128_enabled)]
float_bench! {
name: trunc_f128_f64,
sig: (a: f128) -> f64,
@ -115,19 +120,31 @@ float_bench! {
asm: [],
}
#[cfg(not(any(target_arch = "powerpc", target_arch = "powerpc64")))]
criterion_group!(
float_trunc,
trunc_f32_f16,
trunc_f64_f16,
trunc_f64_f32,
trunc_f128_f16,
trunc_f128_f32,
trunc_f128_f64,
);
pub fn float_trunc() {
let mut criterion = Criterion::default().configure_from_args();
// FIXME(#655): `f16` tests disabled until we can bootstrap symbols
#[cfg(any(target_arch = "powerpc", target_arch = "powerpc64"))]
criterion_group!(float_trunc, trunc_f64_f32, trunc_f128_f32, trunc_f128_f64,);
// FIXME(#655): `f16` tests disabled until we can bootstrap symbols
#[cfg(f16_enabled)]
#[cfg(not(any(target_arch = "powerpc", target_arch = "powerpc64")))]
{
trunc_f32_f16(&mut criterion);
trunc_f64_f16(&mut criterion);
}
trunc_f64_f32(&mut criterion);
#[cfg(f128_enabled)]
{
// FIXME(#655): `f16` tests disabled until we can bootstrap symbols
#[cfg(f16_enabled)]
#[cfg(not(any(target_arch = "powerpc", target_arch = "powerpc64")))]
{
trunc_f128_f16(&mut criterion);
}
trunc_f128_f32(&mut criterion);
trunc_f128_f64(&mut criterion);
}
}
criterion_main!(float_trunc);

View file

@ -1,4 +1,4 @@
use std::{collections::HashSet, env};
use std::collections::HashSet;
/// Features to enable
#[derive(Debug, PartialEq, Eq, Hash)]
@ -9,35 +9,39 @@ enum Feature {
NoSysF16F128Convert,
}
mod builtins_configure {
include!("../configure.rs");
}
fn main() {
let target = env::var("TARGET").unwrap();
let target = builtins_configure::Target::from_env();
let mut features = HashSet::new();
// These platforms do not have f128 symbols available in their system libraries, so
// skip related tests.
if target.starts_with("arm-")
|| target.contains("apple-darwin")
|| target.contains("windows-msvc")
if target.arch == "arm"
|| target.vendor == "apple"
|| target.env == "msvc"
// GCC and LLVM disagree on the ABI of `f16` and `f128` with MinGW. See
// <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115054>.
|| target.contains("windows-gnu")
|| (target.os == "windows" && target.env == "gnu")
// FIXME(llvm): There is an ABI incompatibility between GCC and Clang on 32-bit x86.
// See <https://github.com/llvm/llvm-project/issues/77401>.
|| target.starts_with("i686")
|| target.arch == "i686"
// 32-bit PowerPC and 64-bit LE gets code generated that Qemu cannot handle. See
// <https://github.com/rust-lang/compiler-builtins/pull/606#issuecomment-2105635926>.
|| target.starts_with("powerpc-")
|| target.starts_with("powerpc64le-")
|| target.arch == "powerpc"
|| target.arch == "powerpc64le"
// FIXME: We get different results from the builtin functions. See
// <https://github.com/rust-lang/compiler-builtins/pull/606#issuecomment-2105657287>.
|| target.starts_with("powerpc64-")
|| target.arch == "powerpc64"
{
features.insert(Feature::NoSysF128);
features.insert(Feature::NoSysF128IntConvert);
features.insert(Feature::NoSysF16F128Convert);
}
if target.starts_with("i586") || target.starts_with("i686") {
if target.arch == "i586" || target.arch == "i686" {
// 32-bit x86 does not have `__fixunstfti`/`__fixtfti` but does have everything else
features.insert(Feature::NoSysF128IntConvert);
// FIXME: 32-bit x86 has a bug in `f128 -> f16` system libraries
@ -46,16 +50,18 @@ fn main() {
// These platforms do not have f16 symbols available in their system libraries, so
// skip related tests. Most of these are missing `f16 <-> f32` conversion routines.
if (target.starts_with("aarch64-") && target.contains("linux"))
|| target.starts_with("arm")
|| target.starts_with("powerpc-")
|| target.starts_with("powerpc64-")
|| target.starts_with("powerpc64le-")
|| target.starts_with("i586-")
|| target.contains("windows-")
if (target.arch == "aarch64" && target.os == "linux")
|| target.arch.starts_with("arm")
|| target.arch == "powerpc"
|| target.arch == "powerpc64"
|| target.arch == "powerpc64le"
|| target.arch == "i586"
|| target.os == "windows"
// Linking says "error: function signature mismatch: __extendhfsf2" and seems to
// think the signature is either `(i32) -> f32` or `(f32) -> f32`
|| target.starts_with("wasm32-")
// think the signature is either `(i32) -> f32` or `(f32) -> f32`. See
// <https://github.com/llvm/llvm-project/issues/96438>.
|| target.arch == "wasm32"
|| target.arch == "wasm64"
{
features.insert(Feature::NoSysF16);
features.insert(Feature::NoSysF16F128Convert);
@ -77,4 +83,6 @@ fn main() {
println!("cargo:warning={warning}");
println!("cargo:rustc-cfg=feature=\"{name}\"");
}
builtins_configure::configure_f16_f128(&target);
}

View file

@ -350,9 +350,11 @@ macro_rules! impl_testio {
}
}
#[cfg(not(feature = "no-f16-f128"))]
impl_testio!(float f16, f128);
#[cfg(f16_enabled)]
impl_testio!(float f16);
impl_testio!(float f32, f64);
#[cfg(f128_enabled)]
impl_testio!(float f128);
impl_testio!(int i16, i32, i64, i128);
impl_testio!(int u16, u32, u64, u128);
impl_testio!((float, int)(f32, i32));

View file

@ -13,8 +13,8 @@
//! Some floating point tests are disabled for specific architectures, because they do not have
//! correct rounding.
#![no_std]
#![cfg_attr(not(feature = "no-f16-f128"), feature(f128))]
#![cfg_attr(not(feature = "no-f16-f128"), feature(f16))]
#![cfg_attr(f128_enabled, feature(f128))]
#![cfg_attr(f16_enabled, feature(f16))]
#![feature(isqrt)]
pub mod bench;

View file

@ -1,6 +1,5 @@
#![allow(unused_macros)]
#![feature(f128)]
#![feature(f16)]
#![cfg_attr(f128_enabled, feature(f128))]
use testcrate::*;
@ -120,7 +119,7 @@ mod float_addsub {
}
}
#[cfg(not(feature = "no-f16-f128"))]
#[cfg(f128_enabled)]
#[cfg(not(all(target_arch = "x86", not(target_feature = "sse"))))]
#[cfg(not(any(target_arch = "powerpc", target_arch = "powerpc64")))]
mod float_addsub_f128 {
@ -131,7 +130,7 @@ mod float_addsub_f128 {
}
}
#[cfg(not(feature = "no-f16-f128"))]
#[cfg(f128_enabled)]
#[cfg(any(target_arch = "powerpc", target_arch = "powerpc64"))]
mod float_addsub_f128_ppc {
use super::*;

View file

@ -1,7 +1,6 @@
#![allow(unused_macros)]
#![allow(unreachable_code)]
#![feature(f128)]
#![feature(f16)]
#![cfg_attr(f128_enabled, feature(f128))]
#[cfg(not(target_arch = "powerpc64"))]
use testcrate::*;
@ -94,7 +93,7 @@ mod float_comparisons {
}
#[test]
#[cfg(not(feature = "no-f16-f128"))]
#[cfg(f128_enabled)]
fn cmp_f128() {
#[cfg(any(target_arch = "powerpc", target_arch = "powerpc64"))]
use compiler_builtins::float::cmp::{

View file

@ -1,5 +1,5 @@
#![cfg_attr(not(feature = "no-f16-f128"), feature(f16))]
#![cfg_attr(not(feature = "no-f16-f128"), feature(f128))]
#![cfg_attr(f128_enabled, feature(f128))]
#![cfg_attr(f16_enabled, feature(f16))]
// makes configuration easier
#![allow(unused_macros)]
#![allow(unused_imports)]
@ -176,7 +176,7 @@ mod f_to_i {
}
#[test]
#[cfg(not(feature = "no-f16-f128"))]
#[cfg(f128_enabled)]
fn f128_to_int() {
#[cfg(any(target_arch = "powerpc", target_arch = "powerpc64"))]
use compiler_builtins::float::conv::{
@ -264,7 +264,7 @@ mod extend {
f32 => f64, Single => Double, __extendsfdf2vfp, all();
}
#[cfg(not(feature = "no-f16-f128"))]
#[cfg(all(f16_enabled, f128_enabled))]
#[cfg(not(any(target_arch = "powerpc", target_arch = "powerpc64")))]
f_to_f! {
extend,
@ -275,7 +275,7 @@ mod extend {
f64 => f128, Double => Quad, __extenddftf2, not(feature = "no-sys-f128");
}
#[cfg(not(feature = "no-f16-f128"))]
#[cfg(f128_enabled)]
#[cfg(any(target_arch = "powerpc", target_arch = "powerpc64"))]
f_to_f! {
extend,
@ -299,7 +299,7 @@ mod trunc {
f64 => f32, Double => Single, __truncdfsf2vfp, all();
}
#[cfg(not(feature = "no-f16-f128"))]
#[cfg(all(f16_enabled, f128_enabled))]
#[cfg(not(any(target_arch = "powerpc", target_arch = "powerpc64")))]
f_to_f! {
trunc,
@ -310,7 +310,7 @@ mod trunc {
f128 => f64, Quad => Double, __trunctfdf2, not(feature = "no-sys-f128");
}
#[cfg(not(feature = "no-f16-f128"))]
#[cfg(f128_enabled)]
#[cfg(any(target_arch = "powerpc", target_arch = "powerpc64"))]
f_to_f! {
trunc,

View file

@ -1,6 +1,5 @@
#![allow(unused_macros)]
#![feature(f128)]
#![feature(f16)]
#![cfg_attr(f128_enabled, feature(f128))]
use testcrate::*;
@ -131,7 +130,7 @@ mod float_mul {
}
}
#[cfg(not(feature = "no-f16-f128"))]
#[cfg(f128_enabled)]
#[cfg(not(all(target_arch = "x86", not(target_feature = "sse"))))]
#[cfg(not(any(target_arch = "powerpc", target_arch = "powerpc64")))]
mod float_mul_f128 {
@ -145,7 +144,7 @@ mod float_mul_f128 {
}
}
#[cfg(not(feature = "no-f16-f128"))]
#[cfg(f128_enabled)]
#[cfg(any(target_arch = "powerpc", target_arch = "powerpc64"))]
mod float_mul_f128_ppc {
use super::*;