From a70655507a5c4f0b9bf6aab0ea15cee2f87c2a12 Mon Sep 17 00:00:00 2001 From: James Barford-Evans Date: Thu, 20 Aug 2026 09:00:04 +0100 Subject: [PATCH 01/12] Create `f16b` struct and documentation --- compiler/rustc_attr_ir/src/lang_items.rs | 1 + compiler/rustc_feature/src/builtin_attrs.rs | 5 + compiler/rustc_feature/src/unstable.rs | 4 + .../rustc_hir_analysis/src/check/check.rs | 2 + compiler/rustc_interface/src/util.rs | 4 + compiler/rustc_middle/src/ty/layout.rs | 5 + compiler/rustc_span/src/symbol.rs | 4 + compiler/rustc_ty_utils/src/layout.rs | 10 +- library/core/Cargo.toml | 1 + library/core/src/num/f16b.rs | 181 ++++++++++++++++++ library/core/src/num/mod.rs | 4 + .../src/language-features/f16b.md | 11 ++ 12 files changed, 231 insertions(+), 1 deletion(-) create mode 100644 library/core/src/num/f16b.rs create mode 100644 src/doc/unstable-book/src/language-features/f16b.md diff --git a/compiler/rustc_attr_ir/src/lang_items.rs b/compiler/rustc_attr_ir/src/lang_items.rs index f2ad7abba755d..fa75978b27c9a 100644 --- a/compiler/rustc_attr_ir/src/lang_items.rs +++ b/compiler/rustc_attr_ir/src/lang_items.rs @@ -281,6 +281,7 @@ language_item_table! { PartialEq, sym::eq, eq_trait, Target::Trait, GenericRequirement::Exact(1); PartialOrd, sym::partial_ord, partial_ord_trait, Target::Trait, GenericRequirement::Exact(1); CVoid, sym::c_void, c_void, Target::Enum, GenericRequirement::None; + F16B, sym::f16b, f16b, Target::Struct, GenericRequirement::Exact(0); Type, sym::type_info, type_struct, Target::Struct, GenericRequirement::None; TypeGeneric, sym::type_info_generic, type_generic, Target::Enum, GenericRequirement::None; diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index f79a8e9ffc79c..abd07722619ae 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -40,6 +40,11 @@ const GATED_CFGS: &[GatedCfg] = &[ sym::cfg_target_has_reliable_f16_f128, Features::cfg_target_has_reliable_f16_f128, ), + ( + sym::target_has_reliable_f16b, + sym::cfg_target_has_reliable_f16b, + Features::cfg_target_has_reliable_f16b, + ), ( sym::target_has_reliable_f128, sym::cfg_target_has_reliable_f16_f128, diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index ca70389815141..f187c8f780cdc 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -227,6 +227,8 @@ declare_features! ( (unstable, anonymous_lifetime_in_impl_trait, "1.63.0", None), /// Allows checking whether or not the backend correctly supports unstable float types. (internal, cfg_target_has_reliable_f16_f128, "1.88.0", None), + /// Allows checking whether or not the backend correctly supports the unstable `f16b` type. + (internal, cfg_target_has_reliable_f16b, "CURRENT_RUSTC_VERSION", None), /// Allows checking whether or not the target might have thread support. (internal, cfg_target_has_threads, "1.99.0", None), /// Allows identifying the `compiler_builtins` crate. @@ -518,6 +520,8 @@ declare_features! ( (unstable, f128, "1.78.0", Some(116909)), /// Allow using 16-bit (half precision) floating point numbers. (unstable, f16, "1.78.0", Some(116909)), + /// Allow using bfloat16 floating point numbers. + (unstable, f16b, "CURRENT_RUSTC_VERSION", Some(160630)), /// Allows the use of `#[ffi_const]` on foreign functions. (unstable, ffi_const, "1.45.0", Some(58328)), /// Allows the use of `#[ffi_pure]` on foreign functions. diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index d5bc834b831c7..c1a4cf27cac5b 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -1585,6 +1585,8 @@ fn check_scalable_vector(tcx: TyCtxt<'_>, span: Span, def_id: LocalDefId, scalab // bools match element_ty.kind() { ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Bool => (), + // We need to treat a `bfloat` (`f16b`) as a primitive scalar + ty::Adt(def, _) if tcx.is_lang_item(def.did(), LangItem::F16B) => (), _ => { let mut err = tcx.dcx().struct_span_err( span, diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs index 5173f12d6fb66..9ff239cb1e017 100644 --- a/compiler/rustc_interface/src/util.rs +++ b/compiler/rustc_interface/src/util.rs @@ -74,6 +74,9 @@ pub(crate) fn add_configuration( if target_config.has_reliable_f16_math { cfg.insert((sym::target_has_reliable_f16_math, None)); } + if target_config.has_reliable_f16b { + cfg.insert((sym::target_has_reliable_f16b, None)); + } if target_config.has_reliable_f128 { cfg.insert((sym::target_has_reliable_f128, None)); } @@ -417,6 +420,7 @@ impl CodegenBackend for DummyCodegenBackend { internal_target_features, has_reliable_f16: true, has_reliable_f16_math: true, + has_reliable_f16b: true, has_reliable_f128: true, has_reliable_f128_math: true, } diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index c18bf81121377..4ca34e7f73c86 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -139,6 +139,11 @@ impl abi::Float { use abi::Float::*; match *self { F16 => tcx.types.f16, + F16B => Ty::new_adt( + tcx, + tcx.adt_def(tcx.require_lang_item(LangItem::F16B, DUMMY_SP)), + ty::List::empty(), + ), F32 => tcx.types.f32, F64 => tcx.types.f64, F128 => tcx.types.f128, diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 7665df4a4e5ae..3bb846368cead 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -522,6 +522,7 @@ symbols! { begin_panic, bench, bevy_ecs, + bfloat, bikeshed, bikeshed_guaranteed_no_drop, bin, @@ -600,6 +601,7 @@ symbols! { cfg_target_has_atomic, cfg_target_has_atomic_equal_alignment, cfg_target_has_reliable_f16_f128, + cfg_target_has_reliable_f16b, cfg_target_has_threads, cfg_target_object_format, cfg_target_thread_local, @@ -936,6 +938,7 @@ symbols! { external_doc, f16, f16_nan, + f16b, f16c_target_feature, f32, f32_nan, @@ -2093,6 +2096,7 @@ symbols! { target_has_atomic_primitive_alignment, target_has_reliable_f16, target_has_reliable_f16_math, + target_has_reliable_f16b, target_has_reliable_f128, target_has_reliable_f128_math, target_has_threads, diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index 37ff443c83980..0a68a8bb679b6 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -11,6 +11,7 @@ use rustc_abi::{ }; use rustc_hashes::Hash64; use rustc_hir as hir; +use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::find_attr; use rustc_index::{Idx as _, IndexVec}; use rustc_middle::bug; @@ -738,7 +739,7 @@ fn layout_of_uncached<'tcx>( .is_sized(tcx, typing_env) }); - let layout = cx + let mut layout = cx .calc .layout_of_struct_or_enum( &def.repr(), @@ -805,6 +806,13 @@ fn layout_of_uncached<'tcx>( } } + if tcx.is_lang_item(def.did(), LangItem::F16B) { + let bfloat = scalar_unit(Primitive::Float(abi::Float::F16B)); + assert_eq!(layout.size, abi::Float::F16B.size()); + layout.align = abi::Float::F16B.align(cx); + layout.backend_repr = BackendRepr::Scalar(bfloat); + } + tcx.mk_layout(layout) } diff --git a/library/core/Cargo.toml b/library/core/Cargo.toml index 3f5f9f454a99d..d8f4ec0528dee 100644 --- a/library/core/Cargo.toml +++ b/library/core/Cargo.toml @@ -36,6 +36,7 @@ check-cfg = [ # gate tests. 'cfg(target_has_reliable_f16)', 'cfg(target_has_reliable_f16_math)', + 'cfg(target_has_reliable_f16b)', 'cfg(target_has_reliable_f128)', 'cfg(target_has_reliable_f128_math)', # Prevents use of a static variable for providing platform specific RawOsError diff --git a/library/core/src/num/f16b.rs b/library/core/src/num/f16b.rs new file mode 100644 index 0000000000000..ea11c635ac0fa --- /dev/null +++ b/library/core/src/num/f16b.rs @@ -0,0 +1,181 @@ +//! The 16-bit brain floating-point type. + +#![unstable(feature = "f16b", issue = "160630")] + +use crate::{fmt, mem}; + +/// A 16-bit brain floating-point value. +/// +/// This type stores values using the bfloat16 encoding. It deliberately +/// exposes only raw-bit construction, comparison, formatting, and lossless +/// widening to [`f32`]. +/// +/// The 16-bit brain floating-point intends to preserve the dynamic range of +/// a 32-bit floating-point value while using half the storage. It does +/// this by using 8 bits for the exponent, the same as `f32`, but only +/// using 7 bits for the mantissa. See [Wikipedia on bfloat16][wikipedia] for +/// more information. +/// +/// [wikipedia]: https://en.wikipedia.org/wiki/Bfloat16_floating-point_format +#[lang = "f16b"] +#[doc(alias = "bf16")] // what hardware often names it +#[doc(alias = "bfloat")] // LLVM's name +#[doc(alias = "bfloat16")] // Wikipedia's name +#[doc(alias = "bfloat16_t")] // The C++ `stdfloat` name +#[allow(non_camel_case_types)] +#[repr(transparent)] +#[unstable(feature = "f16b", issue = "160630")] +pub struct f16b(u16); + +#[doc(test(attr( + feature(cfg_target_has_reliable_f16b), + allow(internal_features, unused_features) +)))] +impl f16b { + /// Raw transmutation from `u16`. + /// + /// This is currently identical to `transmute::(v)` on all platforms. + /// It turns out this is incredibly portable, for two reasons: + /// + /// * Floats and Ints have the same endianness on all supported platforms. + /// * IEEE 754 very precisely specifies the bit layout of floats. + /// + /// However there is one caveat: prior to the 2008 version of IEEE 754, how + /// to interpret the NaN signaling bit wasn't actually specified. Most platforms + /// (notably x86 and ARM) picked the interpretation that was ultimately + /// standardized in 2008, but some didn't (notably MIPS). As a result, all + /// signaling NaNs on MIPS are quiet NaNs on x86, and vice-versa. + /// + /// Rather than trying to preserve signaling-ness cross-platform, this + /// implementation favors preserving the exact bits. This means that + /// any payloads encoded in NaNs will be preserved even if the result of + /// this method is sent over the network from an x86 machine to a MIPS one. + /// + /// If the results of this method are only manipulated by the same + /// architecture that produced them, then there is no portability concern. + /// + /// If the input isn't NaN, then there is no portability concern. + /// + /// If you don't care about signalingness (very likely), then there is no + /// portability concern. + /// + /// Note that this function is distinct from `as` casting, which attempts to + /// preserve the *numeric* value, and not the bitwise value. + /// + /// ```no_run + /// #![feature(f16b)] + /// # #[cfg(target_has_reliable_f16b)] { + /// # use core::num::f16b; + /// + /// let v = f16b::from_bits(0x4148); + /// assert_eq!(f32::from(v), 12.5); + /// # } + /// ``` + #[inline] + #[must_use] + #[unstable(feature = "f16b", issue = "160630")] + pub const fn from_bits(bits: u16) -> Self { + // SAFETY: `f16b` and `u16` have the same size, and every bit pattern is valid. + unsafe { mem::transmute(bits) } + } + + /// Raw transmutation to `u16`. + /// + /// This is currently identical to `transmute::(self)` on all platforms. + /// + /// See [`from_bits`](#method.from_bits) for some discussion of the + /// portability of this operation (there are almost no issues). + /// + /// Note that this function is distinct from `as` casting, which attempts to + /// preserve the *numeric* value, and not the bitwise value. + /// + /// ```no_run + /// #![feature(f16b)] + /// # #[cfg(target_has_reliable_f16b)] { + /// # use core::num::f16b; + /// + /// assert_eq!(f16b::from_bits(0x4148).to_bits(), 0x4148); + /// # } + /// ``` + #[inline] + #[unstable(feature = "f16b", issue = "160630")] + #[must_use = "this returns the result of the operation, without modifying the original"] + pub const fn to_bits(self) -> u16 { + // SAFETY: `f16b` and `u16` have the same size, and every bit pattern is valid. + unsafe { mem::transmute(self) } + } +} + +#[inline] +const fn widen(value: f16b) -> f32 { + f32::from_bits((value.to_bits() as u32) << 16) +} + +#[unstable(feature = "f16b", issue = "160630")] +impl Copy for f16b {} + +#[unstable(feature = "f16b", issue = "160630")] +impl Clone for f16b { + #[inline] + fn clone(&self) -> Self { + *self + } +} + +#[unstable(feature = "f16b", issue = "160630")] +impl Default for f16b { + #[inline] + fn default() -> Self { + Self::from_bits(0) + } +} + +#[unstable(feature = "f16b", issue = "160630")] +impl PartialEq for f16b { + #[inline] + fn eq(&self, other: &Self) -> bool { + widen(*self).eq(&widen(*other)) + } +} + +#[unstable(feature = "f16b", issue = "160630")] +impl PartialOrd for f16b { + #[inline] + fn partial_cmp(&self, other: &Self) -> Option { + widen(*self).partial_cmp(&widen(*other)) + } +} + +#[unstable(feature = "f16b", issue = "160630")] +impl From for f32 { + #[inline] + fn from(value: f16b) -> Self { + widen(value) + } +} + +#[unstable(feature = "f16b", issue = "160630")] +impl fmt::Debug for f16b { + #[inline] + fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Debug::fmt(&widen(*self), formatter) + } +} + +#[cfg(not(no_fp_fmt_parse))] +#[unstable(feature = "f16b", issue = "160630")] +impl fmt::LowerExp for f16b { + #[inline] + fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::LowerExp::fmt(&widen(*self), formatter) + } +} + +#[cfg(not(no_fp_fmt_parse))] +#[unstable(feature = "f16b", issue = "160630")] +impl fmt::UpperExp for f16b { + #[inline] + fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::UpperExp::fmt(&widen(*self), formatter) + } +} diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs index db41d23770477..0e85abf017cc6 100644 --- a/library/core/src/num/mod.rs +++ b/library/core/src/num/mod.rs @@ -43,6 +43,8 @@ mod int_macros; // import int_impl! #[macro_use] mod uint_macros; // import uint_impl! +#[path = "f16b.rs"] +mod bfloat; mod complex; mod error; #[cfg(not(no_fp_fmt_parse))] @@ -56,6 +58,8 @@ mod wrapping; #[doc(hidden)] pub mod niche_types; +#[unstable(feature = "f16b", issue = "160630")] +pub use bfloat::f16b; #[unstable(feature = "complex_numbers", issue = "154023")] pub use complex::Complex; #[stable(feature = "int_error_matching", since = "1.55.0")] diff --git a/src/doc/unstable-book/src/language-features/f16b.md b/src/doc/unstable-book/src/language-features/f16b.md new file mode 100644 index 0000000000000..ada81e26c4f8a --- /dev/null +++ b/src/doc/unstable-book/src/language-features/f16b.md @@ -0,0 +1,11 @@ +# `f16b` + +The tracking issue for this feature is: [#160630] + +[#160630]: https://github.com/rust-lang/rust/issues/160630 + +--- + +Enable the `core::num::f16b` type for values stored in the bfloat16 format. + +`f16b` is a nominal library type, not a primitive floating-point type: it has no literal suffix, arithmetic operators, or numeric `as` casts. A compiler lang item connects its layout to the chosen backends representation. From 6c3742a6374eb635812c31fd845c5b8dad3833b0 Mon Sep 17 00:00:00 2001 From: James Barford-Evans Date: Thu, 20 Aug 2026 09:00:41 +0100 Subject: [PATCH 02/12] Add `F16B` to `Float` & wireup trivial matches --- compiler/rustc_abi/src/layout/ty.rs | 2 +- compiler/rustc_abi/src/lib.rs | 8 +++++++- compiler/rustc_codegen_llvm/src/va_arg.rs | 2 +- compiler/rustc_codegen_ssa/src/mir/naked_asm.rs | 1 + compiler/rustc_codegen_ssa/src/traits/type_.rs | 2 ++ compiler/rustc_public/src/abi.rs | 3 ++- compiler/rustc_public/src/unstable/convert/stable/abi.rs | 1 + compiler/rustc_target/src/callconv/mips64.rs | 2 ++ compiler/rustc_target/src/callconv/sparc64.rs | 1 + 9 files changed, 18 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_abi/src/layout/ty.rs b/compiler/rustc_abi/src/layout/ty.rs index 27ec34f519870..4d588054e0fe6 100644 --- a/compiler/rustc_abi/src/layout/ty.rs +++ b/compiler/rustc_abi/src/layout/ty.rs @@ -331,7 +331,7 @@ impl<'a, Ty> TyAndLayout<'a, Ty> { Primitive::Float(float @ (Float::F16 | Float::F32 | Float::F64 | Float::F128)) => { Some(Numeric::Float(float)) } - Primitive::Pointer(..) => None, + Primitive::Pointer(..) | Primitive::Float(Float::F16B) => None, } } diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index a306b494ceced..6c2b6388f7f5d 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -1410,6 +1410,10 @@ impl Integer { #[cfg_attr(feature = "nightly", derive(StableHash))] pub enum Float { F16, + /// `f16b`. This is not a builtin type in Rust (it is exposed as a lang item), + /// but it is a builtin type in LLVM so needs to be explicitly represented + /// in the backend. + F16B, F32, F64, F128, @@ -1421,6 +1425,7 @@ impl Float { match self { F16 => Size::from_bits(16), + F16B => Size::from_bits(16), F32 => Size::from_bits(32), F64 => Size::from_bits(64), F128 => Size::from_bits(128), @@ -1432,7 +1437,7 @@ impl Float { let dl = cx.data_layout(); AbiAlign::new(match self { - F16 => dl.f16_align, + F16 | F16B => dl.f16_align, F32 => dl.f32_align, F64 => dl.f64_align, F128 => dl.f128_align, @@ -1444,6 +1449,7 @@ impl Float { match self { F16 => "f16", + F16B => "f16b", F32 => "f32", F64 => "f64", F128 => "f128", diff --git a/compiler/rustc_codegen_llvm/src/va_arg.rs b/compiler/rustc_codegen_llvm/src/va_arg.rs index 8d2a504d4877b..b6c392d797a4b 100644 --- a/compiler/rustc_codegen_llvm/src/va_arg.rs +++ b/compiler/rustc_codegen_llvm/src/va_arg.rs @@ -95,7 +95,7 @@ fn get_param_type_alignment<'ll, 'tcx>( Integer::I128 => return Align::EIGHT, }, Primitive::Float(float) => match float { - Float::F16 | Float::F32 => unreachable!(), + Float::F16 | Float::F16B | Float::F32 => unreachable!(), Float::F64 => { /* fall through */ } Float::F128 => return Align::from_bytes(16).unwrap(), }, diff --git a/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs b/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs index 939e5395e4741..cbe7a3e058146 100644 --- a/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs +++ b/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs @@ -508,6 +508,7 @@ fn wasm_primitive(primitive: Primitive, ptr_type: &'static str) -> &'static str Integer::I128 => "i64, i64", }, Primitive::Float(float) => match float { + Float::F16B => bug!("`f16b` unsupported on wasm"), Float::F16 | Float::F32 => "f32", Float::F64 => "f64", Float::F128 => "i64, i64", diff --git a/compiler/rustc_codegen_ssa/src/traits/type_.rs b/compiler/rustc_codegen_ssa/src/traits/type_.rs index 707eb3a6ee85d..772330afa701b 100644 --- a/compiler/rustc_codegen_ssa/src/traits/type_.rs +++ b/compiler/rustc_codegen_ssa/src/traits/type_.rs @@ -18,6 +18,7 @@ pub trait BaseTypeCodegenMethods: BackendTypes { fn type_isize(&self) -> Self::Type; fn type_f16(&self) -> Self::Type; + fn type_f16b(&self) -> Self::Type; fn type_f32(&self) -> Self::Type; fn type_f64(&self) -> Self::Type; fn type_f128(&self) -> Self::Type; @@ -67,6 +68,7 @@ pub trait DerivedTypeCodegenMethods<'tcx>: use Float::*; match f { F16 => self.type_f16(), + F16B => self.type_f16b(), F32 => self.type_f32(), F64 => self.type_f64(), F128 => self.type_f128(), diff --git a/compiler/rustc_public/src/abi.rs b/compiler/rustc_public/src/abi.rs index 910f4a5745a7d..9036520072d8a 100644 --- a/compiler/rustc_public/src/abi.rs +++ b/compiler/rustc_public/src/abi.rs @@ -353,6 +353,7 @@ pub enum IntegerLength { #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Serialize)] pub enum FloatLength { F16, + F16B, F32, F64, F128, @@ -373,7 +374,7 @@ impl IntegerLength { impl FloatLength { pub fn bits(self) -> usize { match self { - FloatLength::F16 => 16, + FloatLength::F16 | FloatLength::F16B => 16, FloatLength::F32 => 32, FloatLength::F64 => 64, FloatLength::F128 => 128, diff --git a/compiler/rustc_public/src/unstable/convert/stable/abi.rs b/compiler/rustc_public/src/unstable/convert/stable/abi.rs index 4bb00b4c04394..adda66624af91 100644 --- a/compiler/rustc_public/src/unstable/convert/stable/abi.rs +++ b/compiler/rustc_public/src/unstable/convert/stable/abi.rs @@ -388,6 +388,7 @@ impl<'tcx> Stable<'tcx> for rustc_abi::Float { fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &CompilerCtxt<'_, BridgeTys>) -> Self::T { match self { rustc_abi::Float::F16 => FloatLength::F16, + rustc_abi::Float::F16B => FloatLength::F16B, rustc_abi::Float::F32 => FloatLength::F32, rustc_abi::Float::F64 => FloatLength::F64, rustc_abi::Float::F128 => FloatLength::F128, diff --git a/compiler/rustc_target/src/callconv/mips64.rs b/compiler/rustc_target/src/callconv/mips64.rs index 8002f98507ba8..f83be31bc82ce 100644 --- a/compiler/rustc_target/src/callconv/mips64.rs +++ b/compiler/rustc_target/src/callconv/mips64.rs @@ -31,6 +31,8 @@ where match float { // C does not have the f16 type Float::F16 => None, + // No `f16b` type + Float::F16B => panic!("`f16b` unsupported on mips64"), Float::F32 => Some(Reg::f32()), Float::F64 => Some(Reg::f64()), Float::F128 => Some(Reg::f128()), diff --git a/compiler/rustc_target/src/callconv/sparc64.rs b/compiler/rustc_target/src/callconv/sparc64.rs index bfaa3f3cb19c8..9c0c3a8b69530 100644 --- a/compiler/rustc_target/src/callconv/sparc64.rs +++ b/compiler/rustc_target/src/callconv/sparc64.rs @@ -58,6 +58,7 @@ fn classify<'a, Ty, C>( Float::F16 => { // Match LLVM by passing `f16` in integer registers. } + Float::F16B => panic!("`f16b` unsupported on sparc64"), } } else { /* pass unaligned floats in integer registers */ From 5d548ecc09310b5ec141894dc381e40e9d37afab Mon Sep 17 00:00:00 2001 From: James Barford-Evans Date: Thu, 20 Aug 2026 09:01:13 +0100 Subject: [PATCH 03/12] Use `cfg`'s in backends --- compiler/rustc_codegen_cranelift/src/lib.rs | 1 + compiler/rustc_codegen_gcc/src/base.rs | 2 ++ compiler/rustc_codegen_gcc/src/context.rs | 3 +++ compiler/rustc_codegen_gcc/src/lib.rs | 2 ++ compiler/rustc_codegen_llvm/src/llvm_util.rs | 16 ++++++++++++++++ compiler/rustc_codegen_ssa/src/lib.rs | 3 +++ compiler/rustc_codegen_ssa/src/traits/backend.rs | 1 + 7 files changed, 28 insertions(+) diff --git a/compiler/rustc_codegen_cranelift/src/lib.rs b/compiler/rustc_codegen_cranelift/src/lib.rs index 71fce9e28f120..f6d5501eace68 100644 --- a/compiler/rustc_codegen_cranelift/src/lib.rs +++ b/compiler/rustc_codegen_cranelift/src/lib.rs @@ -190,6 +190,7 @@ impl CodegenBackend for CraneliftCodegenBackend { // available in Cranelift. has_reliable_f16: has_reliable_f16_f128, has_reliable_f16_math: has_reliable_f16_f128, + has_reliable_f16b: false, has_reliable_f128: has_reliable_f16_f128, has_reliable_f128_math, } diff --git a/compiler/rustc_codegen_gcc/src/base.rs b/compiler/rustc_codegen_gcc/src/base.rs index 7a25fc46fd3fc..b9a65c817ea00 100644 --- a/compiler/rustc_codegen_gcc/src/base.rs +++ b/compiler/rustc_codegen_gcc/src/base.rs @@ -214,6 +214,7 @@ pub fn compile_codegen_unit( // -fsyntax-only), forbid the compilation when get_target_info() is called on a // context. let f16_type_supported = target_info.supports_target_dependent_type(CType::Float16); + let f16b_type_supported = target_info.supports_target_dependent_type(CType::BFloat16); let f32_type_supported = target_info.supports_target_dependent_type(CType::Float32); let f64_type_supported = target_info.supports_target_dependent_type(CType::Float64); let f128_type_supported = target_info.supports_target_dependent_type(CType::Float128); @@ -225,6 +226,7 @@ pub fn compile_codegen_unit( tcx, u128_type_supported, f16_type_supported, + f16b_type_supported, f32_type_supported, f64_type_supported, f128_type_supported, diff --git a/compiler/rustc_codegen_gcc/src/context.rs b/compiler/rustc_codegen_gcc/src/context.rs index 19fbe37c27b9e..3189df421452a 100644 --- a/compiler/rustc_codegen_gcc/src/context.rs +++ b/compiler/rustc_codegen_gcc/src/context.rs @@ -73,6 +73,7 @@ pub struct CodegenCx<'gcc, 'tcx> { pub supports_128bit_integers: bool, pub supports_f16_type: bool, + pub supports_f16b_type: bool, pub supports_f32_type: bool, pub supports_f64_type: bool, pub supports_f128_type: bool, @@ -141,6 +142,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { tcx: TyCtxt<'tcx>, supports_128bit_integers: bool, supports_f16_type: bool, + supports_f16b_type: bool, supports_f32_type: bool, supports_f64_type: bool, supports_f128_type: bool, @@ -277,6 +279,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { supports_128bit_integers, supports_f16_type, + supports_f16b_type, supports_f32_type, supports_f64_type, supports_f128_type, diff --git a/compiler/rustc_codegen_gcc/src/lib.rs b/compiler/rustc_codegen_gcc/src/lib.rs index cbc7db8e9e23f..85d14b51bfc82 100644 --- a/compiler/rustc_codegen_gcc/src/lib.rs +++ b/compiler/rustc_codegen_gcc/src/lib.rs @@ -553,6 +553,7 @@ fn target_config(sess: &Session, target_info: &LockedTargetInfo) -> TargetConfig ); let has_reliable_f16 = target_info.supports_target_dependent_type(CType::Float16); + let has_reliable_f16b = target_info.supports_target_dependent_type(CType::BFloat16); let has_reliable_f128 = target_info.supports_target_dependent_type(CType::Float128); TargetConfig { @@ -560,6 +561,7 @@ fn target_config(sess: &Session, target_info: &LockedTargetInfo) -> TargetConfig // There are no known bugs with GCC support for f16 or f128 has_reliable_f16, has_reliable_f16_math: has_reliable_f16, + has_reliable_f16b, has_reliable_f128, has_reliable_f128_math: has_reliable_f128, } diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index a5441b1ef1135..b25d4cb929d42 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -372,6 +372,7 @@ pub(crate) fn target_config(sess: &Session) -> TargetConfig { internal_target_features, has_reliable_f16: true, has_reliable_f16_math: true, + has_reliable_f16b: true, has_reliable_f128: true, has_reliable_f128_math: true, }; @@ -409,6 +410,21 @@ fn update_target_reliable_float_cfg(sess: &Session, cfg: &mut TargetConfig) { _ => true, }; + // The heuristic for evaluating to true is twofold, namely; + // + // 1. Can LLVM compile an IR snippet containing `fpext bfloat % to float` + // 2. Does the documentation indicate `bf16` support, can be seen in the + // tracking issue; + cfg.has_reliable_f16b = match (target_arch, target_os) { + // This is similar to , however + // does not work until LLVM 23 on Windows. + (Arch::Arm64EC, _) => major >= 23, + (Arch::AArch64, _) | (Arch::X86_64, _) | (Arch::RiscV64, _) | (Arch::LoongArch64, _) => { + major >= 21 + } + _ => false, + }; + cfg.has_reliable_f128 = match (target_arch, target_os) { // Unsupported https://github.com/llvm/llvm-project/issues/121122 (Arch::AmdGpu, _) => false, diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs index bf2ce74e38d84..3da9a475c1f5a 100644 --- a/compiler/rustc_codegen_ssa/src/lib.rs +++ b/compiler/rustc_codegen_ssa/src/lib.rs @@ -315,6 +315,9 @@ pub struct TargetConfig { pub has_reliable_f16: bool, /// Option for `cfg(target_has_reliable_f16_math)`, true if `f16` math calls work. pub has_reliable_f16_math: bool, + /// Option for `cfg(target_has_reliable_f16b)`, presently true if both the ABI + /// and LLVM version supports `f16b`. + pub has_reliable_f16b: bool, /// Option for `cfg(target_has_reliable_f128)`, true if `f128` basic arithmetic works. pub has_reliable_f128: bool, /// Option for `cfg(target_has_reliable_f128_math)`, true if `f128` math calls work. diff --git a/compiler/rustc_codegen_ssa/src/traits/backend.rs b/compiler/rustc_codegen_ssa/src/traits/backend.rs index 11878c1f5165d..508e9f7ebedc2 100644 --- a/compiler/rustc_codegen_ssa/src/traits/backend.rs +++ b/compiler/rustc_codegen_ssa/src/traits/backend.rs @@ -50,6 +50,7 @@ pub trait CodegenBackend { // support the float types, rather than accidentally quietly skipping all tests. has_reliable_f16: true, has_reliable_f16_math: true, + has_reliable_f16b: true, has_reliable_f128: true, has_reliable_f128_math: true, } From ac1c383e6a68aeda9d3fb64e66ce255b54684466 Mon Sep 17 00:00:00 2001 From: James Barford-Evans Date: Thu, 20 Aug 2026 09:01:39 +0100 Subject: [PATCH 04/12] Wire up backends --- compiler/rustc_codegen_cranelift/src/common.rs | 1 + compiler/rustc_codegen_gcc/src/type_.rs | 8 ++++++++ compiler/rustc_codegen_llvm/src/abi.rs | 1 + compiler/rustc_codegen_llvm/src/intrinsic.rs | 3 +++ compiler/rustc_codegen_llvm/src/type_.rs | 4 ++++ compiler/rustc_session/src/config/cfg.rs | 1 + src/tools/miri/src/bin/miri.rs | 1 + 7 files changed, 19 insertions(+) diff --git a/compiler/rustc_codegen_cranelift/src/common.rs b/compiler/rustc_codegen_cranelift/src/common.rs index 1bdb3efefa1aa..2a3fe11e9c820 100644 --- a/compiler/rustc_codegen_cranelift/src/common.rs +++ b/compiler/rustc_codegen_cranelift/src/common.rs @@ -34,6 +34,7 @@ pub(crate) fn scalar_to_clif_type(tcx: TyCtxt<'_>, scalar: Scalar) -> Type { }, Primitive::Float(float) => match float { Float::F16 => types::F16, + Float::F16B => bug!("f16b is not supported by the Cranelift codegen backend"), Float::F32 => types::F32, Float::F64 => types::F64, Float::F128 => types::F128, diff --git a/compiler/rustc_codegen_gcc/src/type_.rs b/compiler/rustc_codegen_gcc/src/type_.rs index 5252f93a92ebe..9e86d36d8aa17 100644 --- a/compiler/rustc_codegen_gcc/src/type_.rs +++ b/compiler/rustc_codegen_gcc/src/type_.rs @@ -156,6 +156,14 @@ impl<'gcc, 'tcx> BaseTypeCodegenMethods for CodegenCx<'gcc, 'tcx> { bug!("unsupported float width 16") } + fn type_f16b(&self) -> Type<'gcc> { + #[cfg(feature = "master")] + if self.supports_f16b_type { + return self.context.new_c_type(CType::BFloat16); + } + bug!("unsupported type bfloat16") + } + fn type_f32(&self) -> Type<'gcc> { #[cfg(feature = "master")] if self.supports_f32_type { diff --git a/compiler/rustc_codegen_llvm/src/abi.rs b/compiler/rustc_codegen_llvm/src/abi.rs index 2f2b6ba8ae97b..e96fea76cb586 100644 --- a/compiler/rustc_codegen_llvm/src/abi.rs +++ b/compiler/rustc_codegen_llvm/src/abi.rs @@ -158,6 +158,7 @@ impl LlvmType for Reg { }, Primitive::Float(float) => match float { Float::F16 => cx.type_f16(), + Float::F16B => cx.type_f16b(), Float::F32 => cx.type_f32(), Float::F64 => cx.type_f64(), Float::F128 => cx.type_f128(), diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index c4ff1eee56750..de3de96bd3e5c 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -337,6 +337,9 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { Primitive::Float(Float::F16) => { bug!("the va_arg intrinsic does not support `f16`") } + Primitive::Float(Float::F16B) => { + bug!("the va_arg intrinsic does not support `f16b`") + } Primitive::Float(Float::F32) => { // c_double is actually f32 on avr. if self.cx().sess().target.arch != Arch::Avr { diff --git a/compiler/rustc_codegen_llvm/src/type_.rs b/compiler/rustc_codegen_llvm/src/type_.rs index 22d43f22e24a4..7af0a0be1b2dc 100644 --- a/compiler/rustc_codegen_llvm/src/type_.rs +++ b/compiler/rustc_codegen_llvm/src/type_.rs @@ -214,6 +214,10 @@ impl<'ll, CX: Borrow>> BaseTypeCodegenMethods for GenericCx<'ll, CX> { unsafe { llvm::LLVMHalfTypeInContext(self.llcx()) } } + fn type_f16b(&self) -> &'ll Type { + unsafe { llvm::LLVMBFloatTypeInContext(self.llcx()) } + } + fn type_f32(&self) -> &'ll Type { unsafe { llvm::LLVMFloatTypeInContext(self.llcx()) } } diff --git a/compiler/rustc_session/src/config/cfg.rs b/compiler/rustc_session/src/config/cfg.rs index a6decd5898689..05e3c346cd767 100644 --- a/compiler/rustc_session/src/config/cfg.rs +++ b/compiler/rustc_session/src/config/cfg.rs @@ -154,6 +154,7 @@ pub(crate) fn disallow_cfgs(sess: &Session, user_cfgs: &Cfg) { | (sym::target_has_atomic_load_store, Some(_)) | (sym::target_has_reliable_f16, None | Some(_)) | (sym::target_has_reliable_f16_math, None | Some(_)) + | (sym::target_has_reliable_f16b, None | Some(_)) | (sym::target_has_reliable_f128, None | Some(_)) | (sym::target_has_reliable_f128_math, None | Some(_)) | (sym::target_thread_local, None) => disallow(cfg, "--target"), diff --git a/src/tools/miri/src/bin/miri.rs b/src/tools/miri/src/bin/miri.rs index 19d1f5d6f461c..dde41f901b8ba 100644 --- a/src/tools/miri/src/bin/miri.rs +++ b/src/tools/miri/src/bin/miri.rs @@ -221,6 +221,7 @@ impl CodegenBackend for MiriCodegenBackend { internal_target_features: native_target_config.internal_target_features, // The basic types and ABI always work. + has_reliable_f16b: true, has_reliable_f16: true, has_reliable_f128: true, // We always provide the f16 intrinsics, but some are provided via the host, From df1f7a07db5f92080ec2f49f7c26f3c7b35dcd4e Mon Sep 17 00:00:00 2001 From: James Barford-Evans Date: Thu, 20 Aug 2026 09:02:38 +0100 Subject: [PATCH 05/12] Create tests --- tests/assembly-llvm/f16b/aarch64.rs | 65 ++++++++++ tests/assembly-llvm/f16b/loongarch64.rs | 56 ++++++++ tests/assembly-llvm/f16b/riscv.rs | 57 +++++++++ tests/assembly-llvm/f16b/x86_64-linux.rs | 51 ++++++++ tests/assembly-llvm/f16b/x86_64-windows.rs | 55 ++++++++ tests/auxiliary/minicore.rs | 43 ++++++- tests/codegen-llvm/float/f16b.rs | 44 +++++++ .../scalable-vectors/bf16-intrinsic.rs | 31 +++++ ...ature-gate-cfg-target-has-reliable-f16b.rs | 8 ++ ...e-gate-cfg-target-has-reliable-f16b.stderr | 12 ++ tests/ui/feature-gates/feature-gate-f16b.rs | 32 +++++ .../ui/feature-gates/feature-gate-f16b.stderr | 121 ++++++++++++++++++ tests/ui/float/f16b-restrictions.rs | 23 ++++ tests/ui/float/f16b-restrictions.stderr | 43 +++++++ tests/ui/float/f16b.rs | 40 ++++++ tests/ui/parser/f16b.rs | 17 +++ tests/ui/parser/f16b.stderr | 10 ++ 17 files changed, 706 insertions(+), 2 deletions(-) create mode 100644 tests/assembly-llvm/f16b/aarch64.rs create mode 100644 tests/assembly-llvm/f16b/loongarch64.rs create mode 100644 tests/assembly-llvm/f16b/riscv.rs create mode 100644 tests/assembly-llvm/f16b/x86_64-linux.rs create mode 100644 tests/assembly-llvm/f16b/x86_64-windows.rs create mode 100644 tests/codegen-llvm/float/f16b.rs create mode 100644 tests/codegen-llvm/scalable-vectors/bf16-intrinsic.rs create mode 100644 tests/ui/feature-gates/feature-gate-cfg-target-has-reliable-f16b.rs create mode 100644 tests/ui/feature-gates/feature-gate-cfg-target-has-reliable-f16b.stderr create mode 100644 tests/ui/feature-gates/feature-gate-f16b.rs create mode 100644 tests/ui/feature-gates/feature-gate-f16b.stderr create mode 100644 tests/ui/float/f16b-restrictions.rs create mode 100644 tests/ui/float/f16b-restrictions.stderr create mode 100644 tests/ui/float/f16b.rs create mode 100644 tests/ui/parser/f16b.rs create mode 100644 tests/ui/parser/f16b.stderr diff --git a/tests/assembly-llvm/f16b/aarch64.rs b/tests/assembly-llvm/f16b/aarch64.rs new file mode 100644 index 0000000000000..d602a236899aa --- /dev/null +++ b/tests/assembly-llvm/f16b/aarch64.rs @@ -0,0 +1,65 @@ +//@ add-minicore +//@ assembly-output: emit-asm +// +//@ revisions: AARCH64_LINUX AARCH64_DARWIN AARCH64_BE AARCH64_MSVC ARM64EC_MSVC +//@ [AARCH64_LINUX] compile-flags: -Copt-level=3 --target aarch64-unknown-linux-gnu +//@ [AARCH64_LINUX] needs-llvm-components: aarch64 +//@ [AARCH64_BE] compile-flags: -Copt-level=3 --target aarch64_be-unknown-linux-gnu +//@ [AARCH64_BE] needs-llvm-components: aarch64 +//@ [AARCH64_DARWIN] compile-flags: -Copt-level=3 --target aarch64-apple-darwin +//@ [AARCH64_DARWIN] needs-llvm-components: aarch64 +//@ [AARCH64_MSVC] compile-flags: -Copt-level=3 --target aarch64-pc-windows-msvc +//@ [AARCH64_MSVC] needs-llvm-components: aarch64 +//@ [ARM64EC_MSVC] compile-flags: -Copt-level=3 --target arm64ec-pc-windows-msvc +//@ [ARM64EC_MSVC] needs-llvm-components: aarch64 +//@ [ARM64EC_MSVC] min-llvm-version: 23 + +#![feature(f16b, no_core)] +#![no_core] +#![crate_type = "lib"] +#![allow(improper_ctypes_definitions)] + +// Check that the assembly that rustc generates matches what clang emits. + +extern crate minicore; + +use minicore::From; +use minicore::num::f16b; + +// CHECK-LABEL: {{^"?[#_]?identity_f16b"?:}} +// CHECK: ret +#[unsafe(no_mangle)] +pub extern "C" fn identity_f16b(value: f16b) -> f16b { + value +} + +// CHECK-LABEL: {{^"?[#_]?f16b_to_bits"?:}} +// AARCH64_LINUX: fmov w0, s0 +// AARCH64_BE: fmov w0, s0 +// AARCH64_DARWIN: fmov w8, s0 +// AARCH64_DARWIN-NEXT: and w0, w8, #0xffff +// AARCH64_MSVC: fmov w0, s0 +// ARM64EC_MSVC: fmov w0, s0 +// CHECK-NEXT: ret +#[unsafe(no_mangle)] +pub extern "C" fn f16b_to_bits(value: f16b) -> u16 { + value.to_bits() +} + +// CHECK-LABEL: {{^"?[#_]?f16b_from_bits"?:}} +// CHECK: fmov s0, w0 +// CHECK-NEXT: ret +#[unsafe(no_mangle)] +pub extern "C" fn f16b_from_bits(bits: u16) -> f16b { + f16b::from_bits(bits) +} + +// CHECK-LABEL: {{^"?[#_]?widen_f16b"?:}} +// CHECK: fmov w8, s0 +// CHECK-NEXT: lsl w8, w8, #16 +// CHECK-NEXT: fmov s0, w8 +// CHECK-NEXT: ret +#[unsafe(no_mangle)] +pub extern "C" fn widen_f16b(value: f16b) -> f32 { + f32::from(value) +} diff --git a/tests/assembly-llvm/f16b/loongarch64.rs b/tests/assembly-llvm/f16b/loongarch64.rs new file mode 100644 index 0000000000000..966c2ebfafc89 --- /dev/null +++ b/tests/assembly-llvm/f16b/loongarch64.rs @@ -0,0 +1,56 @@ +//@ add-minicore +//@ assembly-output: emit-asm +//@ compile-flags: -Copt-level=3 --target loongarch64-unknown-linux-gnu +//@ needs-llvm-components: loongarch + +#![feature(f16b, no_core)] +#![no_core] +#![crate_type = "lib"] +#![allow(improper_ctypes_definitions)] + +// Check that the assembly that rustc generates matches what clang emits. + +extern crate minicore; + +use minicore::From; +use minicore::num::f16b; + +// CHECK-LABEL: identity_f16b: +// CHECK: movfr2gr.s $a0, $fa0 +// CHECK-NEXT: lu12i.w $a1, -16 +// CHECK-NEXT: or $a0, $a0, $a1 +// CHECK-NEXT: movgr2fr.w $fa0, $a0 +// CHECK-NEXT: ret +#[unsafe(no_mangle)] +pub extern "C" fn identity_f16b(value: f16b) -> f16b { + value +} + +// CHECK-LABEL: f16b_to_bits: +// CHECK: movfr2gr.s $a0, $fa0 +// CHECK-NEXT: bstrpick.d $a0, $a0, 15, 0 +// CHECK-NEXT: ret +#[unsafe(no_mangle)] +pub extern "C" fn f16b_to_bits(value: f16b) -> u16 { + value.to_bits() +} + +// CHECK-LABEL: f16b_from_bits: +// CHECK: lu12i.w $a1, -16 +// CHECK-NEXT: or $a0, $a0, $a1 +// CHECK-NEXT: movgr2fr.w $fa0, $a0 +// CHECK-NEXT: ret +#[unsafe(no_mangle)] +pub extern "C" fn f16b_from_bits(bits: u16) -> f16b { + f16b::from_bits(bits) +} + +// CHECK-LABEL: widen_f16b: +// CHECK: movfr2gr.s $a0, $fa0 +// CHECK-NEXT: slli.d $a0, $a0, 16 +// CHECK-NEXT: movgr2fr.w $fa0, $a0 +// CHECK-NEXT: ret +#[unsafe(no_mangle)] +pub extern "C" fn widen_f16b(value: f16b) -> f32 { + f32::from(value) +} diff --git a/tests/assembly-llvm/f16b/riscv.rs b/tests/assembly-llvm/f16b/riscv.rs new file mode 100644 index 0000000000000..8459148975c50 --- /dev/null +++ b/tests/assembly-llvm/f16b/riscv.rs @@ -0,0 +1,57 @@ +//@ add-minicore +//@ assembly-output: emit-asm +//@ compile-flags: -Copt-level=3 --target riscv64gc-unknown-linux-gnu +//@ needs-llvm-components: riscv + +#![feature(f16b, no_core)] +#![no_core] +#![crate_type = "lib"] +#![allow(improper_ctypes_definitions)] + +// Check that the assembly that rustc generates matches what clang emits. + +extern crate minicore; + +use minicore::From; +use minicore::num::f16b; + +// CHECK-LABEL: identity_f16b: +// CHECK: fmv.x.w a0, fa0 +// CHECK-NEXT: lui a1, 1048560 +// CHECK-NEXT: or a0, a0, a1 +// CHECK-NEXT: fmv.w.x fa0, a0 +// CHECK-NEXT: ret +#[unsafe(no_mangle)] +pub extern "C" fn identity_f16b(value: f16b) -> f16b { + value +} + +// CHECK-LABEL: f16b_to_bits: +// CHECK: fmv.x.w a0, fa0 +// CHECK-NEXT: slli a0, a0, 48 +// CHECK-NEXT: srli a0, a0, 48 +// CHECK-NEXT: ret +#[unsafe(no_mangle)] +pub extern "C" fn f16b_to_bits(value: f16b) -> u16 { + value.to_bits() +} + +// CHECK-LABEL: f16b_from_bits: +// CHECK: lui a1, 1048560 +// CHECK-NEXT: or a0, a0, a1 +// CHECK-NEXT: fmv.w.x fa0, a0 +// CHECK-NEXT: ret +#[unsafe(no_mangle)] +pub extern "C" fn f16b_from_bits(bits: u16) -> f16b { + f16b::from_bits(bits) +} + +// CHECK-LABEL: widen_f16b: +// CHECK: fmv.x.w a0, fa0 +// CHECK-NEXT: slli a0, a0, 16 +// CHECK-NEXT: fmv.w.x fa0, a0 +// CHECK-NEXT: ret +#[unsafe(no_mangle)] +pub extern "C" fn widen_f16b(value: f16b) -> f32 { + f32::from(value) +} diff --git a/tests/assembly-llvm/f16b/x86_64-linux.rs b/tests/assembly-llvm/f16b/x86_64-linux.rs new file mode 100644 index 0000000000000..c8fe49b11d911 --- /dev/null +++ b/tests/assembly-llvm/f16b/x86_64-linux.rs @@ -0,0 +1,51 @@ +//@ add-minicore +//@ assembly-output: emit-asm +// +//@ compile-flags: -Copt-level=3 -Cllvm-args=-x86-asm-syntax=intel +//@ compile-flags: --target x86_64-unknown-linux-gnu +//@ needs-llvm-components: x86 + +#![feature(f16b, no_core)] +#![no_core] +#![crate_type = "lib"] +#![allow(improper_ctypes_definitions)] + +// Check that the assembly that rustc generates matches what clang emits. + +extern crate minicore; + +use minicore::From; +use minicore::num::f16b; + +// CHECK-LABEL: identity_f16b: +// CHECK: ret +#[unsafe(no_mangle)] +pub extern "C" fn identity_f16b(value: f16b) -> f16b { + value +} + +// CHECK-LABEL: f16b_to_bits: +// CHECK: pextrw eax, xmm0, 0 +// CHECK-NEXT: ret +#[unsafe(no_mangle)] +pub extern "C" fn f16b_to_bits(value: f16b) -> u16 { + value.to_bits() +} + +// CHECK-LABEL: f16b_from_bits: +// CHECK: pinsrw xmm0, edi, 0 +// CHECK-NEXT: ret +#[unsafe(no_mangle)] +pub extern "C" fn f16b_from_bits(bits: u16) -> f16b { + f16b::from_bits(bits) +} + +// CHECK-LABEL: widen_f16b: +// CHECK: pextrw eax, xmm0, 0 +// CHECK-NEXT: shl eax, 16 +// CHECK-NEXT: movd xmm0, eax +// CHECK-NEXT: ret +#[unsafe(no_mangle)] +pub extern "C" fn widen_f16b(value: f16b) -> f32 { + f32::from(value) +} diff --git a/tests/assembly-llvm/f16b/x86_64-windows.rs b/tests/assembly-llvm/f16b/x86_64-windows.rs new file mode 100644 index 0000000000000..43af6c3a5f516 --- /dev/null +++ b/tests/assembly-llvm/f16b/x86_64-windows.rs @@ -0,0 +1,55 @@ +//@ add-minicore +//@ assembly-output: emit-asm +// +//@ revisions: WINDOWS_GNU WINDOWS_MSVC +//@ [WINDOWS_GNU] compile-flags: -Copt-level=3 -Cllvm-args=-x86-asm-syntax=intel +//@ [WINDOWS_GNU] compile-flags: --target x86_64-pc-windows-gnu +//@ [WINDOWS_GNU] needs-llvm-components: x86 +//@ [WINDOWS_MSVC] compile-flags: -Copt-level=3 -Cllvm-args=-x86-asm-syntax=intel +//@ [WINDOWS_MSVC] compile-flags: --target x86_64-pc-windows-msvc +//@ [WINDOWS_MSVC] needs-llvm-components: x86 + +#![feature(f16b, no_core)] +#![no_core] +#![crate_type = "lib"] +#![allow(improper_ctypes_definitions)] + +// Check that the assembly that rustc generates matches what clang emits. + +extern crate minicore; + +use minicore::From; +use minicore::num::f16b; + +// CHECK-LABEL: identity_f16b: +// CHECK: ret +#[unsafe(no_mangle)] +pub extern "C" fn identity_f16b(value: f16b) -> f16b { + value +} + +// CHECK-LABEL: f16b_to_bits: +// CHECK: pextrw eax, xmm0, 0 +// CHECK-NEXT: ret +#[unsafe(no_mangle)] +pub extern "C" fn f16b_to_bits(value: f16b) -> u16 { + value.to_bits() +} + +// CHECK-LABEL: f16b_from_bits: +// CHECK: pinsrw xmm0, ecx, 0 +// CHECK-NEXT: ret +#[unsafe(no_mangle)] +pub extern "C" fn f16b_from_bits(bits: u16) -> f16b { + f16b::from_bits(bits) +} + +// CHECK-LABEL: widen_f16b: +// CHECK: pextrw eax, xmm0, 0 +// CHECK-NEXT: shl eax, 16 +// CHECK-NEXT: movd xmm0, eax +// CHECK-NEXT: ret +#[unsafe(no_mangle)] +pub extern "C" fn widen_f16b(value: f16b) -> f32 { + f32::from(value) +} diff --git a/tests/auxiliary/minicore.rs b/tests/auxiliary/minicore.rs index 2b7eb0b9afbcf..f0ccc341a567d 100644 --- a/tests/auxiliary/minicore.rs +++ b/tests/auxiliary/minicore.rs @@ -29,6 +29,8 @@ rustc_attrs, decl_macro, f16, + f16b, + cfg_target_has_reliable_f16b, f128, repr_simd, transparent_unions, @@ -80,6 +82,10 @@ impl LegacyReceiver for &mut T {} #[lang = "copy"] pub trait Copy: Sized {} +pub trait From: Sized { + fn from(value: T) -> Self; +} + #[lang = "bikeshed_guaranteed_no_drop"] pub trait BikeshedGuaranteedNoDrop {} @@ -360,7 +366,7 @@ pub const unsafe fn copy_nonoverlapping(src: *const T, dst: *mut T, count: us pub mod mem { #[rustc_nounwind] #[rustc_intrinsic] - pub unsafe fn transmute(src: Src) -> Dst; + pub const unsafe fn transmute(src: Src) -> Dst; #[rustc_nounwind] #[rustc_intrinsic] @@ -392,7 +398,40 @@ pub mod hint { } pub mod num { - use super::Copy; + use super::{Copy, From, mem}; + + #[rustc_intrinsic] + const unsafe fn unchecked_shl(value: T, shift: U) -> T; + + #[cfg(target_has_reliable_f16b)] + #[allow(non_camel_case_types)] + #[lang = "f16b"] + #[repr(transparent)] + pub struct f16b(u16); + + #[cfg(target_has_reliable_f16b)] + impl f16b { + #[inline] + pub const fn from_bits(bits: u16) -> Self { + unsafe { mem::transmute(bits) } + } + + #[inline] + pub const fn to_bits(self) -> u16 { + unsafe { mem::transmute(self) } + } + } + + #[cfg(target_has_reliable_f16b)] + impl Copy for f16b {} + + #[cfg(target_has_reliable_f16b)] + impl From for f32 { + #[inline] + fn from(value: f16b) -> Self { + unsafe { mem::transmute(unchecked_shl(value.to_bits() as u32, 16u32)) } + } + } #[repr(C)] #[lang = "complex"] diff --git a/tests/codegen-llvm/float/f16b.rs b/tests/codegen-llvm/float/f16b.rs new file mode 100644 index 0000000000000..b7c16bcdf548b --- /dev/null +++ b/tests/codegen-llvm/float/f16b.rs @@ -0,0 +1,44 @@ +//@ compile-flags: -Copt-level=3 +//@ ignore-backends: gcc +//@ ignore-s390x +//@ ignore-wasm +//@ ignore-x86 + +#![crate_type = "lib"] +#![feature(f16b)] +#![allow(improper_ctypes_definitions)] + +extern crate core; + +use core::num::f16b; + +// CHECK-LABEL: define{{.*}} bfloat @identity_f16b(bfloat +#[no_mangle] +pub extern "C" fn identity_f16b(value: f16b) -> f16b { + // CHECK: ret bfloat + value +} + +// CHECK-LABEL: define{{.*}} i16 @f16b_to_bits(bfloat +#[no_mangle] +pub extern "C" fn f16b_to_bits(value: f16b) -> u16 { + // CHECK: bitcast bfloat %value to i16 + value.to_bits() +} + +// CHECK-LABEL: define{{.*}} bfloat @f16b_from_bits(i16 +#[no_mangle] +pub extern "C" fn f16b_from_bits(bits: u16) -> f16b { + // CHECK: bitcast i16 %bits to bfloat + f16b::from_bits(bits) +} + +// CHECK-LABEL: define{{.*}} float @widen_f16b(bfloat +#[no_mangle] +pub extern "C" fn widen_f16b(value: f16b) -> f32 { + // CHECK: bitcast bfloat %value to i16 + // CHECK: zext i16 + // CHECK: shl nuw i32 {{.*}}, 16 + // CHECK: bitcast i32 {{.*}} to float + f32::from(value) +} diff --git a/tests/codegen-llvm/scalable-vectors/bf16-intrinsic.rs b/tests/codegen-llvm/scalable-vectors/bf16-intrinsic.rs new file mode 100644 index 0000000000000..862306a9b796b --- /dev/null +++ b/tests/codegen-llvm/scalable-vectors/bf16-intrinsic.rs @@ -0,0 +1,31 @@ +//@ add-minicore +//@ compile-flags: --target aarch64-unknown-linux-gnu +//@ needs-llvm-components: aarch64 + +#![crate_type = "lib"] +#![feature(abi_unadjusted, f16b, link_llvm_intrinsics, no_core, simd_ffi)] +#![no_core] +#![allow(non_camel_case_types)] + +extern crate minicore; + +use minicore::num::f16b; +use minicore::simd::{Simd, f32x4}; + +type bfloat16x8_t = Simd; + +#[unsafe(no_mangle)] +#[target_feature(enable = "neon,bf16")] +// CHECK-LABEL: define <4 x float> @vbfmmlaq_f32( +// CHECK-SAME: <4 x float> %acc, <8 x bfloat> %lhs, <8 x bfloat> %rhs) +pub unsafe extern "C" fn vbfmmlaq_f32(acc: f32x4, lhs: bfloat16x8_t, rhs: bfloat16x8_t) -> f32x4 { + unsafe extern "unadjusted" { + #[link_name = "llvm.aarch64.neon.bfmmla"] + fn bfmmla(acc: f32x4, lhs: bfloat16x8_t, rhs: bfloat16x8_t) -> f32x4; + } + + // CHECK: [[RESULT:%.*]] = {{.*}}call <4 x float> @llvm.aarch64.neon.bfmmla( + // CHECK-SAME: <4 x float> %acc, <8 x bfloat> %lhs, <8 x bfloat> %rhs) + // CHECK: ret <4 x float> [[RESULT]] + unsafe { bfmmla(acc, lhs, rhs) } +} diff --git a/tests/ui/feature-gates/feature-gate-cfg-target-has-reliable-f16b.rs b/tests/ui/feature-gates/feature-gate-cfg-target-has-reliable-f16b.rs new file mode 100644 index 0000000000000..1ddc115519b7a --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-cfg-target-has-reliable-f16b.rs @@ -0,0 +1,8 @@ +//@ ignore-s390x +//@ ignore-wasm +//@ compile-flags: --check-cfg=cfg(target_has_reliable_f16b) + +fn main() { + cfg!(target_has_reliable_f16b); + //~^ ERROR `cfg(target_has_reliable_f16b)` is experimental and subject to change +} diff --git a/tests/ui/feature-gates/feature-gate-cfg-target-has-reliable-f16b.stderr b/tests/ui/feature-gates/feature-gate-cfg-target-has-reliable-f16b.stderr new file mode 100644 index 0000000000000..00cd88141cb59 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-cfg-target-has-reliable-f16b.stderr @@ -0,0 +1,12 @@ +error[E0658]: `cfg(target_has_reliable_f16b)` is experimental and subject to change + --> $DIR/feature-gate-cfg-target-has-reliable-f16b.rs:6:10 + | +LL | cfg!(target_has_reliable_f16b); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(cfg_target_has_reliable_f16b)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-f16b.rs b/tests/ui/feature-gates/feature-gate-f16b.rs new file mode 100644 index 0000000000000..3cae1aefd165f --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-f16b.rs @@ -0,0 +1,32 @@ +//@ ignore-s390x +//@ ignore-wasm +extern crate core; + +use core::num::f16b; +//~^ ERROR use of unstable library feature `f16b` + +fn main() { + let _ = f16b::from_bits(0); + //~^ ERROR use of unstable library feature `f16b` + //~| ERROR use of unstable library feature `f16b` + + let a = 0.0f16b; + //~^ ERROR invalid suffix `f16b` + + let _: f16b = 1.0; + //~^ ERROR use of unstable library feature `f16b` + //~| ERROR mismatched types + + let x = f16b::from_bits(0x3f80); + //~^ ERROR use of unstable library feature `f16b` + //~| ERROR use of unstable library feature `f16b` + let _ = x + x; + //~^ ERROR cannot add `f16b` to `f16b` + + let _ = 1u16 as f16b; + //~^ ERROR use of unstable library feature `f16b` + //~| ERROR non-primitive cast + + let _ = x as f32; + //~^ ERROR non-primitive cast +} diff --git a/tests/ui/feature-gates/feature-gate-f16b.stderr b/tests/ui/feature-gates/feature-gate-f16b.stderr new file mode 100644 index 0000000000000..21b537430c295 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-f16b.stderr @@ -0,0 +1,121 @@ +error: invalid suffix `f16b` for float literal + --> $DIR/feature-gate-f16b.rs:13:13 + | +LL | let a = 0.0f16b; + | ^^^^^^^ invalid suffix `f16b` + | + = help: valid suffixes are `f32` and `f64` + +error[E0658]: use of unstable library feature `f16b` + --> $DIR/feature-gate-f16b.rs:5:5 + | +LL | use core::num::f16b; + | ^^^^^^^^^^^^^^^ + | + = note: see issue #160630 for more information + = help: add `#![feature(f16b)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: use of unstable library feature `f16b` + --> $DIR/feature-gate-f16b.rs:9:13 + | +LL | let _ = f16b::from_bits(0); + | ^^^^ + | + = note: see issue #160630 for more information + = help: add `#![feature(f16b)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: use of unstable library feature `f16b` + --> $DIR/feature-gate-f16b.rs:16:12 + | +LL | let _: f16b = 1.0; + | ^^^^ + | + = note: see issue #160630 for more information + = help: add `#![feature(f16b)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: use of unstable library feature `f16b` + --> $DIR/feature-gate-f16b.rs:20:13 + | +LL | let x = f16b::from_bits(0x3f80); + | ^^^^ + | + = note: see issue #160630 for more information + = help: add `#![feature(f16b)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: use of unstable library feature `f16b` + --> $DIR/feature-gate-f16b.rs:26:21 + | +LL | let _ = 1u16 as f16b; + | ^^^^ + | + = note: see issue #160630 for more information + = help: add `#![feature(f16b)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: use of unstable library feature `f16b` + --> $DIR/feature-gate-f16b.rs:9:13 + | +LL | let _ = f16b::from_bits(0); + | ^^^^^^^^^^^^^^^ + | + = note: see issue #160630 for more information + = help: add `#![feature(f16b)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0308]: mismatched types + --> $DIR/feature-gate-f16b.rs:16:19 + | +LL | let _: f16b = 1.0; + | ---- ^^^ expected `f16b`, found floating-point number + | | + | expected due to this + +error[E0658]: use of unstable library feature `f16b` + --> $DIR/feature-gate-f16b.rs:20:13 + | +LL | let x = f16b::from_bits(0x3f80); + | ^^^^^^^^^^^^^^^ + | + = note: see issue #160630 for more information + = help: add `#![feature(f16b)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0369]: cannot add `f16b` to `f16b` + --> $DIR/feature-gate-f16b.rs:23:15 + | +LL | let _ = x + x; + | - ^ - f16b + | | + | f16b + | +note: `f16b` does not implement `Add` + --> $SRC_DIR/core/src/num/f16b.rs:LL:COL + | + = note: `f16b` is defined in another crate + +error[E0605]: non-primitive cast: `u16` as `f16b` + --> $DIR/feature-gate-f16b.rs:26:13 + | +LL | let _ = 1u16 as f16b; + | ^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object + +error[E0605]: non-primitive cast: `f16b` as `f32` + --> $DIR/feature-gate-f16b.rs:30:13 + | +LL | let _ = x as f32; + | ^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object + | +help: consider using the `From` trait instead + | +LL - let _ = x as f32; +LL + let _ = f32::from(x); + | + +error: aborting due to 12 previous errors + +Some errors have detailed explanations: E0308, E0369, E0605, E0658. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/float/f16b-restrictions.rs b/tests/ui/float/f16b-restrictions.rs new file mode 100644 index 0000000000000..7d9af6d6a7de3 --- /dev/null +++ b/tests/ui/float/f16b-restrictions.rs @@ -0,0 +1,23 @@ +//@ ignore-s390x +//@ ignore-wasm + +#![feature(f16b)] + +extern crate core; + +use core::num::f16b; + +fn main() { + let _: f16b = 1.0; + //~^ ERROR mismatched types + + let x = f16b::from_bits(0x3f80); + let _ = x + x; + //~^ ERROR cannot add `f16b` to `f16b` + + let _ = 1u16 as f16b; + //~^ ERROR non-primitive cast + + let _ = x as f32; + //~^ ERROR non-primitive cast +} diff --git a/tests/ui/float/f16b-restrictions.stderr b/tests/ui/float/f16b-restrictions.stderr new file mode 100644 index 0000000000000..e82605d65149e --- /dev/null +++ b/tests/ui/float/f16b-restrictions.stderr @@ -0,0 +1,43 @@ +error[E0308]: mismatched types + --> $DIR/f16b-restrictions.rs:11:19 + | +LL | let _: f16b = 1.0; + | ---- ^^^ expected `f16b`, found floating-point number + | | + | expected due to this + +error[E0369]: cannot add `f16b` to `f16b` + --> $DIR/f16b-restrictions.rs:15:15 + | +LL | let _ = x + x; + | - ^ - f16b + | | + | f16b + | +note: `f16b` does not implement `Add` + --> $SRC_DIR/core/src/num/f16b.rs:LL:COL + | + = note: `f16b` is defined in another crate + +error[E0605]: non-primitive cast: `u16` as `f16b` + --> $DIR/f16b-restrictions.rs:18:13 + | +LL | let _ = 1u16 as f16b; + | ^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object + +error[E0605]: non-primitive cast: `f16b` as `f32` + --> $DIR/f16b-restrictions.rs:21:13 + | +LL | let _ = x as f32; + | ^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object + | +help: consider using the `From` trait instead + | +LL - let _ = x as f32; +LL + let _ = f32::from(x); + | + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0308, E0369, E0605. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/float/f16b.rs b/tests/ui/float/f16b.rs new file mode 100644 index 0000000000000..f2cfc908cac22 --- /dev/null +++ b/tests/ui/float/f16b.rs @@ -0,0 +1,40 @@ +//@ ignore-s390x +//@ ignore-wasm +//@ ignore-backends: gcc +//@ run-pass + +#![feature(f16b)] + +extern crate core; + +use core::num::f16b; +use std::fmt::{Debug, LowerExp, UpperExp}; + +const ONE: f16b = f16b::from_bits(0x3f80); +const ONE_BITS: u16 = ONE.to_bits(); + +fn assert_traits() +where + T: Default + Copy + Clone + Debug + LowerExp + UpperExp + PartialEq + PartialOrd, +{ +} + +fn main() { + assert_traits::(); + + assert_eq!(size_of::(), 2); + assert_eq!(align_of::(), 2); + assert_eq!(f16b::default().to_bits(), 0); + assert_eq!(ONE_BITS, 0x3f80); + assert_eq!(f32::from(ONE).to_bits(), 0x3f80_0000); + + let two = f16b::from_bits(0x4000); + let negative_zero = f16b::from_bits(0x8000); + let nan = f16b::from_bits(0x7fc0); + assert!(ONE < two); + assert_eq!(f16b::from_bits(0), negative_zero); + assert!(nan != nan); + assert_eq!(format!("{ONE:?}"), "1.0"); + assert_eq!(format!("{ONE:e}"), "1e0"); + assert_eq!(format!("{ONE:E}"), "1E0"); +} diff --git a/tests/ui/parser/f16b.rs b/tests/ui/parser/f16b.rs new file mode 100644 index 0000000000000..ceb388dabf9bf --- /dev/null +++ b/tests/ui/parser/f16b.rs @@ -0,0 +1,17 @@ +//@ ignore-s390x +//@ ignore-wasm + +#![feature(f16b)] + +extern crate core; + +use core::num::f16b; + +// `f16b` is a nominal core type, not a floating-point literal type. +fn main() { + let value = f16b::from_bits(0x3f80); + let _: f16b = value; + + let _ = 0.0f16b; + //~^ ERROR invalid suffix `f16b` for float literal +} diff --git a/tests/ui/parser/f16b.stderr b/tests/ui/parser/f16b.stderr new file mode 100644 index 0000000000000..53ec412bbe232 --- /dev/null +++ b/tests/ui/parser/f16b.stderr @@ -0,0 +1,10 @@ +error: invalid suffix `f16b` for float literal + --> $DIR/f16b.rs:15:13 + | +LL | let _ = 0.0f16b; + | ^^^^^^^ invalid suffix `f16b` + | + = help: valid suffixes are `f32` and `f64` + +error: aborting due to 1 previous error + From d7f1871e60487d33749c89273871587c5222c3c8 Mon Sep 17 00:00:00 2001 From: James Barford-Evans Date: Thu, 20 Aug 2026 14:11:54 +0100 Subject: [PATCH 06/12] cfg test on `target_has_reliable_f16b` --- tests/ui/float/f16b.rs | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/tests/ui/float/f16b.rs b/tests/ui/float/f16b.rs index f2cfc908cac22..5682a82104f67 100644 --- a/tests/ui/float/f16b.rs +++ b/tests/ui/float/f16b.rs @@ -1,9 +1,7 @@ -//@ ignore-s390x -//@ ignore-wasm -//@ ignore-backends: gcc +//@ compile-flags: --check-cfg=cfg(target_has_reliable_f16b) //@ run-pass -#![feature(f16b)] +#![feature(f16b, cfg_target_has_reliable_f16b)] extern crate core; @@ -20,21 +18,23 @@ where } fn main() { - assert_traits::(); - - assert_eq!(size_of::(), 2); - assert_eq!(align_of::(), 2); - assert_eq!(f16b::default().to_bits(), 0); - assert_eq!(ONE_BITS, 0x3f80); - assert_eq!(f32::from(ONE).to_bits(), 0x3f80_0000); - - let two = f16b::from_bits(0x4000); - let negative_zero = f16b::from_bits(0x8000); - let nan = f16b::from_bits(0x7fc0); - assert!(ONE < two); - assert_eq!(f16b::from_bits(0), negative_zero); - assert!(nan != nan); - assert_eq!(format!("{ONE:?}"), "1.0"); - assert_eq!(format!("{ONE:e}"), "1e0"); - assert_eq!(format!("{ONE:E}"), "1E0"); + if cfg!(target_has_reliable_f16b) { + assert_traits::(); + + assert_eq!(size_of::(), 2); + assert_eq!(align_of::(), 2); + assert_eq!(f16b::default().to_bits(), 0); + assert_eq!(ONE_BITS, 0x3f80); + assert_eq!(f32::from(ONE).to_bits(), 0x3f80_0000); + + let two = f16b::from_bits(0x4000); + let negative_zero = f16b::from_bits(0x8000); + let nan = f16b::from_bits(0x7fc0); + assert!(ONE < two); + assert_eq!(f16b::from_bits(0), negative_zero); + assert!(nan != nan); + assert_eq!(format!("{ONE:?}"), "1.0"); + assert_eq!(format!("{ONE:e}"), "1e0"); + assert_eq!(format!("{ONE:E}"), "1E0"); + } } From 048da1fe5a16bf27ba5b9fbe479ef99f55b2c21c Mon Sep 17 00:00:00 2001 From: James Barford-Evans Date: Tue, 1 Sep 2026 15:53:07 +0100 Subject: [PATCH 07/12] Consolidate `assembly-llvm` tests into one, factor out `ignore`'s, update tests and remove major >= 21 check --- compiler/rustc_codegen_llvm/src/llvm_util.rs | 2 +- .../rustc_codegen_ssa/src/mir/naked_asm.rs | 2 + .../core/src/num/{f16b.rs => brain_float.rs} | 0 library/core/src/num/mod.rs | 5 +- .../src/language-features/f16b.md | 2 +- tests/assembly-llvm/f16b.rs | 124 ++++++++++++++++++ tests/assembly-llvm/f16b/aarch64.rs | 65 --------- tests/assembly-llvm/f16b/loongarch64.rs | 56 -------- tests/assembly-llvm/f16b/riscv.rs | 57 -------- tests/assembly-llvm/f16b/x86_64-linux.rs | 51 ------- tests/assembly-llvm/f16b/x86_64-windows.rs | 55 -------- tests/codegen-llvm/float/f16b.rs | 4 - .../scalable-vectors/bf16-intrinsic.rs | 4 +- ...ature-gate-cfg-target-has-reliable-f16b.rs | 2 - ...e-gate-cfg-target-has-reliable-f16b.stderr | 2 +- tests/ui/feature-gates/feature-gate-f16b.rs | 2 - .../ui/feature-gates/feature-gate-f16b.stderr | 26 ++-- tests/ui/float/f16b-restrictions.stderr | 2 +- tests/ui/float/f16b.rs | 5 +- tests/ui/parser/f16b.rs | 3 - tests/ui/parser/f16b.stderr | 2 +- 21 files changed, 151 insertions(+), 320 deletions(-) rename library/core/src/num/{f16b.rs => brain_float.rs} (100%) create mode 100644 tests/assembly-llvm/f16b.rs delete mode 100644 tests/assembly-llvm/f16b/aarch64.rs delete mode 100644 tests/assembly-llvm/f16b/loongarch64.rs delete mode 100644 tests/assembly-llvm/f16b/riscv.rs delete mode 100644 tests/assembly-llvm/f16b/x86_64-linux.rs delete mode 100644 tests/assembly-llvm/f16b/x86_64-windows.rs diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index b25d4cb929d42..8f5ecd93e0c79 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -420,7 +420,7 @@ fn update_target_reliable_float_cfg(sess: &Session, cfg: &mut TargetConfig) { // does not work until LLVM 23 on Windows. (Arch::Arm64EC, _) => major >= 23, (Arch::AArch64, _) | (Arch::X86_64, _) | (Arch::RiscV64, _) | (Arch::LoongArch64, _) => { - major >= 21 + true } _ => false, }; diff --git a/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs b/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs index cbe7a3e058146..86d8f2e47eb7a 100644 --- a/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs +++ b/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs @@ -508,6 +508,8 @@ fn wasm_primitive(primitive: Primitive, ptr_type: &'static str) -> &'static str Integer::I128 => "i64, i64", }, Primitive::Float(float) => match float { + // This could probably use an f32 for WASM however has not been + // verified so leaving as a `bug!(...)` for now. Float::F16B => bug!("`f16b` unsupported on wasm"), Float::F16 | Float::F32 => "f32", Float::F64 => "f64", diff --git a/library/core/src/num/f16b.rs b/library/core/src/num/brain_float.rs similarity index 100% rename from library/core/src/num/f16b.rs rename to library/core/src/num/brain_float.rs diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs index 0e85abf017cc6..5503de133ce86 100644 --- a/library/core/src/num/mod.rs +++ b/library/core/src/num/mod.rs @@ -43,8 +43,7 @@ mod int_macros; // import int_impl! #[macro_use] mod uint_macros; // import uint_impl! -#[path = "f16b.rs"] -mod bfloat; +mod brain_float; mod complex; mod error; #[cfg(not(no_fp_fmt_parse))] @@ -59,7 +58,7 @@ mod wrapping; pub mod niche_types; #[unstable(feature = "f16b", issue = "160630")] -pub use bfloat::f16b; +pub use brain_float::f16b; #[unstable(feature = "complex_numbers", issue = "154023")] pub use complex::Complex; #[stable(feature = "int_error_matching", since = "1.55.0")] diff --git a/src/doc/unstable-book/src/language-features/f16b.md b/src/doc/unstable-book/src/language-features/f16b.md index ada81e26c4f8a..c18289921e032 100644 --- a/src/doc/unstable-book/src/language-features/f16b.md +++ b/src/doc/unstable-book/src/language-features/f16b.md @@ -8,4 +8,4 @@ The tracking issue for this feature is: [#160630] Enable the `core::num::f16b` type for values stored in the bfloat16 format. -`f16b` is a nominal library type, not a primitive floating-point type: it has no literal suffix, arithmetic operators, or numeric `as` casts. A compiler lang item connects its layout to the chosen backends representation. +`f16b` is a nominal library type, not a primitive floating-point type: it has no literal suffix, arithmetic operators, or numeric `as` casts. A compiler lang item connects its layout to the chosen backend's representation. diff --git a/tests/assembly-llvm/f16b.rs b/tests/assembly-llvm/f16b.rs new file mode 100644 index 0000000000000..9d176a5026c27 --- /dev/null +++ b/tests/assembly-llvm/f16b.rs @@ -0,0 +1,124 @@ +//@ add-minicore +//@ assembly-output: emit-asm +// +//@ revisions: AARCH64_LINUX AARCH64_BE AARCH64_DARWIN AARCH64_MSVC ARM64EC_MSVC X64_LINUX X64_WINDOWS_GNU X64_WINDOWS_MSVC RISCV64 LOONGARCH64 +//@ [AARCH64_LINUX] compile-flags: -Copt-level=3 --target aarch64-unknown-linux-gnu +//@ [AARCH64_LINUX] needs-llvm-components: aarch64 +//@ [AARCH64_LINUX] filecheck-flags: --check-prefixes AARCH64,AARCH64-NOTAPPLE +//@ [AARCH64_BE] compile-flags: -Copt-level=3 --target aarch64_be-unknown-linux-gnu +//@ [AARCH64_BE] needs-llvm-components: aarch64 +//@ [AARCH64_BE] filecheck-flags: --check-prefixes AARCH64,AARCH64-NOTAPPLE +//@ [AARCH64_DARWIN] compile-flags: -Copt-level=3 --target aarch64-apple-darwin +//@ [AARCH64_DARWIN] needs-llvm-components: aarch64 +//@ [AARCH64_DARWIN] filecheck-flags: --check-prefixes AARCH64,AARCH64-APPLE +//@ [AARCH64_MSVC] compile-flags: -Copt-level=3 --target aarch64-pc-windows-msvc +//@ [AARCH64_MSVC] needs-llvm-components: aarch64 +//@ [AARCH64_MSVC] filecheck-flags: --check-prefixes AARCH64,AARCH64-NOTAPPLE +//@ [ARM64EC_MSVC] compile-flags: -Copt-level=3 --target arm64ec-pc-windows-msvc +//@ [ARM64EC_MSVC] needs-llvm-components: aarch64 +//@ [ARM64EC_MSVC] min-llvm-version: 23 +//@ [ARM64EC_MSVC] filecheck-flags: --check-prefixes AARCH64,AARCH64-NOTAPPLE +//@ [X64_LINUX] compile-flags: -Copt-level=3 -Cllvm-args=-x86-asm-syntax=intel --target x86_64-unknown-linux-gnu +//@ [X64_LINUX] needs-llvm-components: x86 +//@ [X64_LINUX] filecheck-flags: --check-prefixes X64,X64-LINUX +//@ [X64_WINDOWS_GNU] compile-flags: -Copt-level=3 -Cllvm-args=-x86-asm-syntax=intel --target x86_64-pc-windows-gnu +//@ [X64_WINDOWS_GNU] needs-llvm-components: x86 +//@ [X64_WINDOWS_GNU] filecheck-flags: --check-prefixes X64,X64-WINDOWS +//@ [X64_WINDOWS_MSVC] compile-flags: -Copt-level=3 -Cllvm-args=-x86-asm-syntax=intel --target x86_64-pc-windows-msvc +//@ [X64_WINDOWS_MSVC] needs-llvm-components: x86 +//@ [X64_WINDOWS_MSVC] filecheck-flags: --check-prefixes X64,X64-WINDOWS +//@ [RISCV64] compile-flags: -Copt-level=3 --target riscv64gc-unknown-linux-gnu +//@ [RISCV64] needs-llvm-components: riscv +//@ [LOONGARCH64] compile-flags: -Copt-level=3 --target loongarch64-unknown-linux-gnu +//@ [LOONGARCH64] needs-llvm-components: loongarch + +#![feature(f16b, no_core)] +#![no_core] +#![crate_type = "lib"] +#![allow(improper_ctypes_definitions)] + +// Check that the assembly that rustc generates matches what clang emits. + +extern crate minicore; + +use minicore::From; +use minicore::num::f16b; + +// CHECK-LABEL: {{^"?[#_]?identity_f16b"?:}} +// AARCH64: ret +// X64: ret +// RISCV64: fmv.x.w a0, fa0 +// RISCV64-NEXT: lui a1, 1048560 +// RISCV64-NEXT: or a0, a0, a1 +// RISCV64-NEXT: fmv.w.x fa0, a0 +// RISCV64-NEXT: ret +// LOONGARCH64: movfr2gr.s $a0, $fa0 +// LOONGARCH64-NEXT: lu12i.w $a1, -16 +// LOONGARCH64-NEXT: or $a0, $a0, $a1 +// LOONGARCH64-NEXT: movgr2fr.w $fa0, $a0 +// LOONGARCH64-NEXT: ret +#[unsafe(no_mangle)] +pub extern "C" fn identity_f16b(value: f16b) -> f16b { + value +} + +// CHECK-LABEL: {{^"?[#_]?f16b_to_bits"?:}} +// AARCH64-NOTAPPLE: fmov w0, s0 +// AARCH64-APPLE: fmov w8, s0 +// AARCH64-APPLE-NEXT: and w0, w8, #0xffff +// AARCH64-NEXT: ret +// X64: pextrw eax, xmm0, 0 +// X64-NEXT: ret +// RISCV64: fmv.x.w a0, fa0 +// RISCV64-NEXT: slli a0, a0, 48 +// RISCV64-NEXT: srli a0, a0, 48 +// RISCV64-NEXT: ret +// LOONGARCH64: movfr2gr.s $a0, $fa0 +// LOONGARCH64-NEXT: bstrpick.d $a0, $a0, 15, 0 +// LOONGARCH64-NEXT: ret +#[unsafe(no_mangle)] +pub extern "C" fn f16b_to_bits(value: f16b) -> u16 { + value.to_bits() +} + +// CHECK-LABEL: {{^"?[#_]?f16b_from_bits"?:}} +// AARCH64: fmov s0, w0 +// AARCH64-NEXT: ret +// X64-LINUX: pinsrw xmm0, edi, 0 +// X64-LINUX-NEXT: ret +// X64-WINDOWS: pinsrw xmm0, ecx, 0 +// X64-WINDOWS-NEXT: ret +// RISCV64: lui a1, 1048560 +// RISCV64-NEXT: or a0, a0, a1 +// RISCV64-NEXT: fmv.w.x fa0, a0 +// RISCV64-NEXT: ret +// LOONGARCH64: lu12i.w $a1, -16 +// LOONGARCH64-NEXT: or $a0, $a0, $a1 +// LOONGARCH64-NEXT: movgr2fr.w $fa0, $a0 +// LOONGARCH64-NEXT: ret +#[unsafe(no_mangle)] +pub extern "C" fn f16b_from_bits(bits: u16) -> f16b { + f16b::from_bits(bits) +} + +// CHECK-LABEL: {{^"?[#_]?widen_f16b"?:}} +// AARCH64: fmov w8, s0 +// AARCH64-NEXT: lsl w8, w8, #16 +// AARCH64-NEXT: fmov s0, w8 +// AARCH64-NEXT: ret +// X64: pextrw eax, xmm0, 0 +// X64-NEXT: shl eax, 16 +// X64-NEXT: movd xmm0, eax +// X64-NEXT: ret +// RISCV64: fmv.x.w a0, fa0 +// RISCV64-NEXT: slli a0, a0, 16 +// RISCV64-NEXT: fmv.w.x fa0, a0 +// RISCV64-NEXT: ret +// LOONGARCH64: movfr2gr.s $a0, $fa0 +// LOONGARCH64-NEXT: slli.d $a0, $a0, 16 +// LOONGARCH64-NEXT: movgr2fr.w $fa0, $a0 +// LOONGARCH64-NEXT: ret +#[unsafe(no_mangle)] +pub extern "C" fn widen_f16b(value: f16b) -> f32 { + f32::from(value) +} diff --git a/tests/assembly-llvm/f16b/aarch64.rs b/tests/assembly-llvm/f16b/aarch64.rs deleted file mode 100644 index d602a236899aa..0000000000000 --- a/tests/assembly-llvm/f16b/aarch64.rs +++ /dev/null @@ -1,65 +0,0 @@ -//@ add-minicore -//@ assembly-output: emit-asm -// -//@ revisions: AARCH64_LINUX AARCH64_DARWIN AARCH64_BE AARCH64_MSVC ARM64EC_MSVC -//@ [AARCH64_LINUX] compile-flags: -Copt-level=3 --target aarch64-unknown-linux-gnu -//@ [AARCH64_LINUX] needs-llvm-components: aarch64 -//@ [AARCH64_BE] compile-flags: -Copt-level=3 --target aarch64_be-unknown-linux-gnu -//@ [AARCH64_BE] needs-llvm-components: aarch64 -//@ [AARCH64_DARWIN] compile-flags: -Copt-level=3 --target aarch64-apple-darwin -//@ [AARCH64_DARWIN] needs-llvm-components: aarch64 -//@ [AARCH64_MSVC] compile-flags: -Copt-level=3 --target aarch64-pc-windows-msvc -//@ [AARCH64_MSVC] needs-llvm-components: aarch64 -//@ [ARM64EC_MSVC] compile-flags: -Copt-level=3 --target arm64ec-pc-windows-msvc -//@ [ARM64EC_MSVC] needs-llvm-components: aarch64 -//@ [ARM64EC_MSVC] min-llvm-version: 23 - -#![feature(f16b, no_core)] -#![no_core] -#![crate_type = "lib"] -#![allow(improper_ctypes_definitions)] - -// Check that the assembly that rustc generates matches what clang emits. - -extern crate minicore; - -use minicore::From; -use minicore::num::f16b; - -// CHECK-LABEL: {{^"?[#_]?identity_f16b"?:}} -// CHECK: ret -#[unsafe(no_mangle)] -pub extern "C" fn identity_f16b(value: f16b) -> f16b { - value -} - -// CHECK-LABEL: {{^"?[#_]?f16b_to_bits"?:}} -// AARCH64_LINUX: fmov w0, s0 -// AARCH64_BE: fmov w0, s0 -// AARCH64_DARWIN: fmov w8, s0 -// AARCH64_DARWIN-NEXT: and w0, w8, #0xffff -// AARCH64_MSVC: fmov w0, s0 -// ARM64EC_MSVC: fmov w0, s0 -// CHECK-NEXT: ret -#[unsafe(no_mangle)] -pub extern "C" fn f16b_to_bits(value: f16b) -> u16 { - value.to_bits() -} - -// CHECK-LABEL: {{^"?[#_]?f16b_from_bits"?:}} -// CHECK: fmov s0, w0 -// CHECK-NEXT: ret -#[unsafe(no_mangle)] -pub extern "C" fn f16b_from_bits(bits: u16) -> f16b { - f16b::from_bits(bits) -} - -// CHECK-LABEL: {{^"?[#_]?widen_f16b"?:}} -// CHECK: fmov w8, s0 -// CHECK-NEXT: lsl w8, w8, #16 -// CHECK-NEXT: fmov s0, w8 -// CHECK-NEXT: ret -#[unsafe(no_mangle)] -pub extern "C" fn widen_f16b(value: f16b) -> f32 { - f32::from(value) -} diff --git a/tests/assembly-llvm/f16b/loongarch64.rs b/tests/assembly-llvm/f16b/loongarch64.rs deleted file mode 100644 index 966c2ebfafc89..0000000000000 --- a/tests/assembly-llvm/f16b/loongarch64.rs +++ /dev/null @@ -1,56 +0,0 @@ -//@ add-minicore -//@ assembly-output: emit-asm -//@ compile-flags: -Copt-level=3 --target loongarch64-unknown-linux-gnu -//@ needs-llvm-components: loongarch - -#![feature(f16b, no_core)] -#![no_core] -#![crate_type = "lib"] -#![allow(improper_ctypes_definitions)] - -// Check that the assembly that rustc generates matches what clang emits. - -extern crate minicore; - -use minicore::From; -use minicore::num::f16b; - -// CHECK-LABEL: identity_f16b: -// CHECK: movfr2gr.s $a0, $fa0 -// CHECK-NEXT: lu12i.w $a1, -16 -// CHECK-NEXT: or $a0, $a0, $a1 -// CHECK-NEXT: movgr2fr.w $fa0, $a0 -// CHECK-NEXT: ret -#[unsafe(no_mangle)] -pub extern "C" fn identity_f16b(value: f16b) -> f16b { - value -} - -// CHECK-LABEL: f16b_to_bits: -// CHECK: movfr2gr.s $a0, $fa0 -// CHECK-NEXT: bstrpick.d $a0, $a0, 15, 0 -// CHECK-NEXT: ret -#[unsafe(no_mangle)] -pub extern "C" fn f16b_to_bits(value: f16b) -> u16 { - value.to_bits() -} - -// CHECK-LABEL: f16b_from_bits: -// CHECK: lu12i.w $a1, -16 -// CHECK-NEXT: or $a0, $a0, $a1 -// CHECK-NEXT: movgr2fr.w $fa0, $a0 -// CHECK-NEXT: ret -#[unsafe(no_mangle)] -pub extern "C" fn f16b_from_bits(bits: u16) -> f16b { - f16b::from_bits(bits) -} - -// CHECK-LABEL: widen_f16b: -// CHECK: movfr2gr.s $a0, $fa0 -// CHECK-NEXT: slli.d $a0, $a0, 16 -// CHECK-NEXT: movgr2fr.w $fa0, $a0 -// CHECK-NEXT: ret -#[unsafe(no_mangle)] -pub extern "C" fn widen_f16b(value: f16b) -> f32 { - f32::from(value) -} diff --git a/tests/assembly-llvm/f16b/riscv.rs b/tests/assembly-llvm/f16b/riscv.rs deleted file mode 100644 index 8459148975c50..0000000000000 --- a/tests/assembly-llvm/f16b/riscv.rs +++ /dev/null @@ -1,57 +0,0 @@ -//@ add-minicore -//@ assembly-output: emit-asm -//@ compile-flags: -Copt-level=3 --target riscv64gc-unknown-linux-gnu -//@ needs-llvm-components: riscv - -#![feature(f16b, no_core)] -#![no_core] -#![crate_type = "lib"] -#![allow(improper_ctypes_definitions)] - -// Check that the assembly that rustc generates matches what clang emits. - -extern crate minicore; - -use minicore::From; -use minicore::num::f16b; - -// CHECK-LABEL: identity_f16b: -// CHECK: fmv.x.w a0, fa0 -// CHECK-NEXT: lui a1, 1048560 -// CHECK-NEXT: or a0, a0, a1 -// CHECK-NEXT: fmv.w.x fa0, a0 -// CHECK-NEXT: ret -#[unsafe(no_mangle)] -pub extern "C" fn identity_f16b(value: f16b) -> f16b { - value -} - -// CHECK-LABEL: f16b_to_bits: -// CHECK: fmv.x.w a0, fa0 -// CHECK-NEXT: slli a0, a0, 48 -// CHECK-NEXT: srli a0, a0, 48 -// CHECK-NEXT: ret -#[unsafe(no_mangle)] -pub extern "C" fn f16b_to_bits(value: f16b) -> u16 { - value.to_bits() -} - -// CHECK-LABEL: f16b_from_bits: -// CHECK: lui a1, 1048560 -// CHECK-NEXT: or a0, a0, a1 -// CHECK-NEXT: fmv.w.x fa0, a0 -// CHECK-NEXT: ret -#[unsafe(no_mangle)] -pub extern "C" fn f16b_from_bits(bits: u16) -> f16b { - f16b::from_bits(bits) -} - -// CHECK-LABEL: widen_f16b: -// CHECK: fmv.x.w a0, fa0 -// CHECK-NEXT: slli a0, a0, 16 -// CHECK-NEXT: fmv.w.x fa0, a0 -// CHECK-NEXT: ret -#[unsafe(no_mangle)] -pub extern "C" fn widen_f16b(value: f16b) -> f32 { - f32::from(value) -} diff --git a/tests/assembly-llvm/f16b/x86_64-linux.rs b/tests/assembly-llvm/f16b/x86_64-linux.rs deleted file mode 100644 index c8fe49b11d911..0000000000000 --- a/tests/assembly-llvm/f16b/x86_64-linux.rs +++ /dev/null @@ -1,51 +0,0 @@ -//@ add-minicore -//@ assembly-output: emit-asm -// -//@ compile-flags: -Copt-level=3 -Cllvm-args=-x86-asm-syntax=intel -//@ compile-flags: --target x86_64-unknown-linux-gnu -//@ needs-llvm-components: x86 - -#![feature(f16b, no_core)] -#![no_core] -#![crate_type = "lib"] -#![allow(improper_ctypes_definitions)] - -// Check that the assembly that rustc generates matches what clang emits. - -extern crate minicore; - -use minicore::From; -use minicore::num::f16b; - -// CHECK-LABEL: identity_f16b: -// CHECK: ret -#[unsafe(no_mangle)] -pub extern "C" fn identity_f16b(value: f16b) -> f16b { - value -} - -// CHECK-LABEL: f16b_to_bits: -// CHECK: pextrw eax, xmm0, 0 -// CHECK-NEXT: ret -#[unsafe(no_mangle)] -pub extern "C" fn f16b_to_bits(value: f16b) -> u16 { - value.to_bits() -} - -// CHECK-LABEL: f16b_from_bits: -// CHECK: pinsrw xmm0, edi, 0 -// CHECK-NEXT: ret -#[unsafe(no_mangle)] -pub extern "C" fn f16b_from_bits(bits: u16) -> f16b { - f16b::from_bits(bits) -} - -// CHECK-LABEL: widen_f16b: -// CHECK: pextrw eax, xmm0, 0 -// CHECK-NEXT: shl eax, 16 -// CHECK-NEXT: movd xmm0, eax -// CHECK-NEXT: ret -#[unsafe(no_mangle)] -pub extern "C" fn widen_f16b(value: f16b) -> f32 { - f32::from(value) -} diff --git a/tests/assembly-llvm/f16b/x86_64-windows.rs b/tests/assembly-llvm/f16b/x86_64-windows.rs deleted file mode 100644 index 43af6c3a5f516..0000000000000 --- a/tests/assembly-llvm/f16b/x86_64-windows.rs +++ /dev/null @@ -1,55 +0,0 @@ -//@ add-minicore -//@ assembly-output: emit-asm -// -//@ revisions: WINDOWS_GNU WINDOWS_MSVC -//@ [WINDOWS_GNU] compile-flags: -Copt-level=3 -Cllvm-args=-x86-asm-syntax=intel -//@ [WINDOWS_GNU] compile-flags: --target x86_64-pc-windows-gnu -//@ [WINDOWS_GNU] needs-llvm-components: x86 -//@ [WINDOWS_MSVC] compile-flags: -Copt-level=3 -Cllvm-args=-x86-asm-syntax=intel -//@ [WINDOWS_MSVC] compile-flags: --target x86_64-pc-windows-msvc -//@ [WINDOWS_MSVC] needs-llvm-components: x86 - -#![feature(f16b, no_core)] -#![no_core] -#![crate_type = "lib"] -#![allow(improper_ctypes_definitions)] - -// Check that the assembly that rustc generates matches what clang emits. - -extern crate minicore; - -use minicore::From; -use minicore::num::f16b; - -// CHECK-LABEL: identity_f16b: -// CHECK: ret -#[unsafe(no_mangle)] -pub extern "C" fn identity_f16b(value: f16b) -> f16b { - value -} - -// CHECK-LABEL: f16b_to_bits: -// CHECK: pextrw eax, xmm0, 0 -// CHECK-NEXT: ret -#[unsafe(no_mangle)] -pub extern "C" fn f16b_to_bits(value: f16b) -> u16 { - value.to_bits() -} - -// CHECK-LABEL: f16b_from_bits: -// CHECK: pinsrw xmm0, ecx, 0 -// CHECK-NEXT: ret -#[unsafe(no_mangle)] -pub extern "C" fn f16b_from_bits(bits: u16) -> f16b { - f16b::from_bits(bits) -} - -// CHECK-LABEL: widen_f16b: -// CHECK: pextrw eax, xmm0, 0 -// CHECK-NEXT: shl eax, 16 -// CHECK-NEXT: movd xmm0, eax -// CHECK-NEXT: ret -#[unsafe(no_mangle)] -pub extern "C" fn widen_f16b(value: f16b) -> f32 { - f32::from(value) -} diff --git a/tests/codegen-llvm/float/f16b.rs b/tests/codegen-llvm/float/f16b.rs index b7c16bcdf548b..7de6a776190c9 100644 --- a/tests/codegen-llvm/float/f16b.rs +++ b/tests/codegen-llvm/float/f16b.rs @@ -1,8 +1,4 @@ //@ compile-flags: -Copt-level=3 -//@ ignore-backends: gcc -//@ ignore-s390x -//@ ignore-wasm -//@ ignore-x86 #![crate_type = "lib"] #![feature(f16b)] diff --git a/tests/codegen-llvm/scalable-vectors/bf16-intrinsic.rs b/tests/codegen-llvm/scalable-vectors/bf16-intrinsic.rs index 862306a9b796b..78b302df76261 100644 --- a/tests/codegen-llvm/scalable-vectors/bf16-intrinsic.rs +++ b/tests/codegen-llvm/scalable-vectors/bf16-intrinsic.rs @@ -3,7 +3,7 @@ //@ needs-llvm-components: aarch64 #![crate_type = "lib"] -#![feature(abi_unadjusted, f16b, link_llvm_intrinsics, no_core, simd_ffi)] +#![feature(f16b, link_llvm_intrinsics, no_core, simd_ffi)] #![no_core] #![allow(non_camel_case_types)] @@ -19,7 +19,7 @@ type bfloat16x8_t = Simd; // CHECK-LABEL: define <4 x float> @vbfmmlaq_f32( // CHECK-SAME: <4 x float> %acc, <8 x bfloat> %lhs, <8 x bfloat> %rhs) pub unsafe extern "C" fn vbfmmlaq_f32(acc: f32x4, lhs: bfloat16x8_t, rhs: bfloat16x8_t) -> f32x4 { - unsafe extern "unadjusted" { + unsafe extern "llvm-intrinsic" { #[link_name = "llvm.aarch64.neon.bfmmla"] fn bfmmla(acc: f32x4, lhs: bfloat16x8_t, rhs: bfloat16x8_t) -> f32x4; } diff --git a/tests/ui/feature-gates/feature-gate-cfg-target-has-reliable-f16b.rs b/tests/ui/feature-gates/feature-gate-cfg-target-has-reliable-f16b.rs index 1ddc115519b7a..a1c2f22782c4c 100644 --- a/tests/ui/feature-gates/feature-gate-cfg-target-has-reliable-f16b.rs +++ b/tests/ui/feature-gates/feature-gate-cfg-target-has-reliable-f16b.rs @@ -1,5 +1,3 @@ -//@ ignore-s390x -//@ ignore-wasm //@ compile-flags: --check-cfg=cfg(target_has_reliable_f16b) fn main() { diff --git a/tests/ui/feature-gates/feature-gate-cfg-target-has-reliable-f16b.stderr b/tests/ui/feature-gates/feature-gate-cfg-target-has-reliable-f16b.stderr index 00cd88141cb59..46106f61ad3ae 100644 --- a/tests/ui/feature-gates/feature-gate-cfg-target-has-reliable-f16b.stderr +++ b/tests/ui/feature-gates/feature-gate-cfg-target-has-reliable-f16b.stderr @@ -1,5 +1,5 @@ error[E0658]: `cfg(target_has_reliable_f16b)` is experimental and subject to change - --> $DIR/feature-gate-cfg-target-has-reliable-f16b.rs:6:10 + --> $DIR/feature-gate-cfg-target-has-reliable-f16b.rs:4:10 | LL | cfg!(target_has_reliable_f16b); | ^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/feature-gates/feature-gate-f16b.rs b/tests/ui/feature-gates/feature-gate-f16b.rs index 3cae1aefd165f..fc531c19ba5b1 100644 --- a/tests/ui/feature-gates/feature-gate-f16b.rs +++ b/tests/ui/feature-gates/feature-gate-f16b.rs @@ -1,5 +1,3 @@ -//@ ignore-s390x -//@ ignore-wasm extern crate core; use core::num::f16b; diff --git a/tests/ui/feature-gates/feature-gate-f16b.stderr b/tests/ui/feature-gates/feature-gate-f16b.stderr index 21b537430c295..f0314f8dd5469 100644 --- a/tests/ui/feature-gates/feature-gate-f16b.stderr +++ b/tests/ui/feature-gates/feature-gate-f16b.stderr @@ -1,5 +1,5 @@ error: invalid suffix `f16b` for float literal - --> $DIR/feature-gate-f16b.rs:13:13 + --> $DIR/feature-gate-f16b.rs:11:13 | LL | let a = 0.0f16b; | ^^^^^^^ invalid suffix `f16b` @@ -7,7 +7,7 @@ LL | let a = 0.0f16b; = help: valid suffixes are `f32` and `f64` error[E0658]: use of unstable library feature `f16b` - --> $DIR/feature-gate-f16b.rs:5:5 + --> $DIR/feature-gate-f16b.rs:3:5 | LL | use core::num::f16b; | ^^^^^^^^^^^^^^^ @@ -17,7 +17,7 @@ LL | use core::num::f16b; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: use of unstable library feature `f16b` - --> $DIR/feature-gate-f16b.rs:9:13 + --> $DIR/feature-gate-f16b.rs:7:13 | LL | let _ = f16b::from_bits(0); | ^^^^ @@ -27,7 +27,7 @@ LL | let _ = f16b::from_bits(0); = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: use of unstable library feature `f16b` - --> $DIR/feature-gate-f16b.rs:16:12 + --> $DIR/feature-gate-f16b.rs:14:12 | LL | let _: f16b = 1.0; | ^^^^ @@ -37,7 +37,7 @@ LL | let _: f16b = 1.0; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: use of unstable library feature `f16b` - --> $DIR/feature-gate-f16b.rs:20:13 + --> $DIR/feature-gate-f16b.rs:18:13 | LL | let x = f16b::from_bits(0x3f80); | ^^^^ @@ -47,7 +47,7 @@ LL | let x = f16b::from_bits(0x3f80); = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: use of unstable library feature `f16b` - --> $DIR/feature-gate-f16b.rs:26:21 + --> $DIR/feature-gate-f16b.rs:24:21 | LL | let _ = 1u16 as f16b; | ^^^^ @@ -57,7 +57,7 @@ LL | let _ = 1u16 as f16b; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: use of unstable library feature `f16b` - --> $DIR/feature-gate-f16b.rs:9:13 + --> $DIR/feature-gate-f16b.rs:7:13 | LL | let _ = f16b::from_bits(0); | ^^^^^^^^^^^^^^^ @@ -67,7 +67,7 @@ LL | let _ = f16b::from_bits(0); = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0308]: mismatched types - --> $DIR/feature-gate-f16b.rs:16:19 + --> $DIR/feature-gate-f16b.rs:14:19 | LL | let _: f16b = 1.0; | ---- ^^^ expected `f16b`, found floating-point number @@ -75,7 +75,7 @@ LL | let _: f16b = 1.0; | expected due to this error[E0658]: use of unstable library feature `f16b` - --> $DIR/feature-gate-f16b.rs:20:13 + --> $DIR/feature-gate-f16b.rs:18:13 | LL | let x = f16b::from_bits(0x3f80); | ^^^^^^^^^^^^^^^ @@ -85,7 +85,7 @@ LL | let x = f16b::from_bits(0x3f80); = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0369]: cannot add `f16b` to `f16b` - --> $DIR/feature-gate-f16b.rs:23:15 + --> $DIR/feature-gate-f16b.rs:21:15 | LL | let _ = x + x; | - ^ - f16b @@ -93,18 +93,18 @@ LL | let _ = x + x; | f16b | note: `f16b` does not implement `Add` - --> $SRC_DIR/core/src/num/f16b.rs:LL:COL + --> $SRC_DIR/core/src/num/brain_float.rs:LL:COL | = note: `f16b` is defined in another crate error[E0605]: non-primitive cast: `u16` as `f16b` - --> $DIR/feature-gate-f16b.rs:26:13 + --> $DIR/feature-gate-f16b.rs:24:13 | LL | let _ = 1u16 as f16b; | ^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object error[E0605]: non-primitive cast: `f16b` as `f32` - --> $DIR/feature-gate-f16b.rs:30:13 + --> $DIR/feature-gate-f16b.rs:28:13 | LL | let _ = x as f32; | ^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object diff --git a/tests/ui/float/f16b-restrictions.stderr b/tests/ui/float/f16b-restrictions.stderr index e82605d65149e..55626b173b2a6 100644 --- a/tests/ui/float/f16b-restrictions.stderr +++ b/tests/ui/float/f16b-restrictions.stderr @@ -15,7 +15,7 @@ LL | let _ = x + x; | f16b | note: `f16b` does not implement `Add` - --> $SRC_DIR/core/src/num/f16b.rs:LL:COL + --> $SRC_DIR/core/src/num/brain_float.rs:LL:COL | = note: `f16b` is defined in another crate diff --git a/tests/ui/float/f16b.rs b/tests/ui/float/f16b.rs index 5682a82104f67..757fbfe175f15 100644 --- a/tests/ui/float/f16b.rs +++ b/tests/ui/float/f16b.rs @@ -18,11 +18,12 @@ where } fn main() { + assert_eq!(size_of::(), 2); + assert_eq!(align_of::(), 2); + if cfg!(target_has_reliable_f16b) { assert_traits::(); - assert_eq!(size_of::(), 2); - assert_eq!(align_of::(), 2); assert_eq!(f16b::default().to_bits(), 0); assert_eq!(ONE_BITS, 0x3f80); assert_eq!(f32::from(ONE).to_bits(), 0x3f80_0000); diff --git a/tests/ui/parser/f16b.rs b/tests/ui/parser/f16b.rs index ceb388dabf9bf..bb6f3737a33d5 100644 --- a/tests/ui/parser/f16b.rs +++ b/tests/ui/parser/f16b.rs @@ -1,6 +1,3 @@ -//@ ignore-s390x -//@ ignore-wasm - #![feature(f16b)] extern crate core; diff --git a/tests/ui/parser/f16b.stderr b/tests/ui/parser/f16b.stderr index 53ec412bbe232..2d89bbe4d8776 100644 --- a/tests/ui/parser/f16b.stderr +++ b/tests/ui/parser/f16b.stderr @@ -1,5 +1,5 @@ error: invalid suffix `f16b` for float literal - --> $DIR/f16b.rs:15:13 + --> $DIR/f16b.rs:12:13 | LL | let _ = 0.0f16b; | ^^^^^^^ invalid suffix `f16b` From 256ab0ac171a3c230271588de3c6ad17b48be0bd Mon Sep 17 00:00:00 2001 From: James Barford-Evans Date: Wed, 2 Sep 2026 09:33:40 +0100 Subject: [PATCH 08/12] Test changes for `Tidy`, hard cfg check and include the `use core...` in the documentation --- library/core/src/num/brain_float.rs | 4 +- src/tools/tidy/src/style.rs | 1 + tests/assembly-llvm/f16b.rs | 58 ++++++++++++------------- tests/ui/float/f16b-restrictions.rs | 3 -- tests/ui/float/f16b-restrictions.stderr | 8 ++-- tests/ui/float/f16b.rs | 8 +++- 6 files changed, 43 insertions(+), 39 deletions(-) diff --git a/library/core/src/num/brain_float.rs b/library/core/src/num/brain_float.rs index ea11c635ac0fa..893b1c5a5cd3e 100644 --- a/library/core/src/num/brain_float.rs +++ b/library/core/src/num/brain_float.rs @@ -65,7 +65,7 @@ impl f16b { /// ```no_run /// #![feature(f16b)] /// # #[cfg(target_has_reliable_f16b)] { - /// # use core::num::f16b; + /// use core::num::f16b; /// /// let v = f16b::from_bits(0x4148); /// assert_eq!(f32::from(v), 12.5); @@ -92,7 +92,7 @@ impl f16b { /// ```no_run /// #![feature(f16b)] /// # #[cfg(target_has_reliable_f16b)] { - /// # use core::num::f16b; + /// use core::num::f16b; /// /// assert_eq!(f16b::from_bits(0x4148).to_bits(), 0x4148); /// # } diff --git a/src/tools/tidy/src/style.rs b/src/tools/tidy/src/style.rs index 0f0930ca6efae..a3085f8ba27c0 100644 --- a/src/tools/tidy/src/style.rs +++ b/src/tools/tidy/src/style.rs @@ -74,6 +74,7 @@ const ANNOTATIONS_TO_IGNORE: &[&str] = &[ "//@ lldb", "//@ cdb", "//@ normalize-stderr", + "//@ revisions", ]; fn generate_problems<'a>( diff --git a/tests/assembly-llvm/f16b.rs b/tests/assembly-llvm/f16b.rs index 9d176a5026c27..cb762d21eef12 100644 --- a/tests/assembly-llvm/f16b.rs +++ b/tests/assembly-llvm/f16b.rs @@ -2,35 +2,35 @@ //@ assembly-output: emit-asm // //@ revisions: AARCH64_LINUX AARCH64_BE AARCH64_DARWIN AARCH64_MSVC ARM64EC_MSVC X64_LINUX X64_WINDOWS_GNU X64_WINDOWS_MSVC RISCV64 LOONGARCH64 -//@ [AARCH64_LINUX] compile-flags: -Copt-level=3 --target aarch64-unknown-linux-gnu -//@ [AARCH64_LINUX] needs-llvm-components: aarch64 -//@ [AARCH64_LINUX] filecheck-flags: --check-prefixes AARCH64,AARCH64-NOTAPPLE -//@ [AARCH64_BE] compile-flags: -Copt-level=3 --target aarch64_be-unknown-linux-gnu -//@ [AARCH64_BE] needs-llvm-components: aarch64 -//@ [AARCH64_BE] filecheck-flags: --check-prefixes AARCH64,AARCH64-NOTAPPLE -//@ [AARCH64_DARWIN] compile-flags: -Copt-level=3 --target aarch64-apple-darwin -//@ [AARCH64_DARWIN] needs-llvm-components: aarch64 -//@ [AARCH64_DARWIN] filecheck-flags: --check-prefixes AARCH64,AARCH64-APPLE -//@ [AARCH64_MSVC] compile-flags: -Copt-level=3 --target aarch64-pc-windows-msvc -//@ [AARCH64_MSVC] needs-llvm-components: aarch64 -//@ [AARCH64_MSVC] filecheck-flags: --check-prefixes AARCH64,AARCH64-NOTAPPLE -//@ [ARM64EC_MSVC] compile-flags: -Copt-level=3 --target arm64ec-pc-windows-msvc -//@ [ARM64EC_MSVC] needs-llvm-components: aarch64 -//@ [ARM64EC_MSVC] min-llvm-version: 23 -//@ [ARM64EC_MSVC] filecheck-flags: --check-prefixes AARCH64,AARCH64-NOTAPPLE -//@ [X64_LINUX] compile-flags: -Copt-level=3 -Cllvm-args=-x86-asm-syntax=intel --target x86_64-unknown-linux-gnu -//@ [X64_LINUX] needs-llvm-components: x86 -//@ [X64_LINUX] filecheck-flags: --check-prefixes X64,X64-LINUX -//@ [X64_WINDOWS_GNU] compile-flags: -Copt-level=3 -Cllvm-args=-x86-asm-syntax=intel --target x86_64-pc-windows-gnu -//@ [X64_WINDOWS_GNU] needs-llvm-components: x86 -//@ [X64_WINDOWS_GNU] filecheck-flags: --check-prefixes X64,X64-WINDOWS -//@ [X64_WINDOWS_MSVC] compile-flags: -Copt-level=3 -Cllvm-args=-x86-asm-syntax=intel --target x86_64-pc-windows-msvc -//@ [X64_WINDOWS_MSVC] needs-llvm-components: x86 -//@ [X64_WINDOWS_MSVC] filecheck-flags: --check-prefixes X64,X64-WINDOWS -//@ [RISCV64] compile-flags: -Copt-level=3 --target riscv64gc-unknown-linux-gnu -//@ [RISCV64] needs-llvm-components: riscv -//@ [LOONGARCH64] compile-flags: -Copt-level=3 --target loongarch64-unknown-linux-gnu -//@ [LOONGARCH64] needs-llvm-components: loongarch +//@[AARCH64_LINUX] compile-flags: -Copt-level=3 --target aarch64-unknown-linux-gnu +//@[AARCH64_LINUX] needs-llvm-components: aarch64 +//@[AARCH64_LINUX] filecheck-flags: --check-prefixes AARCH64,AARCH64-NOTAPPLE +//@[AARCH64_BE] compile-flags: -Copt-level=3 --target aarch64_be-unknown-linux-gnu +//@[AARCH64_BE] needs-llvm-components: aarch64 +//@[AARCH64_BE] filecheck-flags: --check-prefixes AARCH64,AARCH64-NOTAPPLE +//@[AARCH64_DARWIN] compile-flags: -Copt-level=3 --target aarch64-apple-darwin +//@[AARCH64_DARWIN] needs-llvm-components: aarch64 +//@[AARCH64_DARWIN] filecheck-flags: --check-prefixes AARCH64,AARCH64-APPLE +//@[AARCH64_MSVC] compile-flags: -Copt-level=3 --target aarch64-pc-windows-msvc +//@[AARCH64_MSVC] needs-llvm-components: aarch64 +//@[AARCH64_MSVC] filecheck-flags: --check-prefixes AARCH64,AARCH64-NOTAPPLE +//@[ARM64EC_MSVC] compile-flags: -Copt-level=3 --target arm64ec-pc-windows-msvc +//@[ARM64EC_MSVC] needs-llvm-components: aarch64 +//@[ARM64EC_MSVC] min-llvm-version: 23 +//@[ARM64EC_MSVC] filecheck-flags: --check-prefixes AARCH64,AARCH64-NOTAPPLE +//@[X64_LINUX] compile-flags: -Copt-level=3 -Cllvm-args=-x86-asm-syntax=intel --target x86_64-unknown-linux-gnu +//@[X64_LINUX] needs-llvm-components: x86 +//@[X64_LINUX] filecheck-flags: --check-prefixes X64,X64-LINUX +//@[X64_WINDOWS_GNU] compile-flags: -Copt-level=3 -Cllvm-args=-x86-asm-syntax=intel --target x86_64-pc-windows-gnu +//@[X64_WINDOWS_GNU] needs-llvm-components: x86 +//@[X64_WINDOWS_GNU] filecheck-flags: --check-prefixes X64,X64-WINDOWS +//@[X64_WINDOWS_MSVC] compile-flags: -Copt-level=3 -Cllvm-args=-x86-asm-syntax=intel --target x86_64-pc-windows-msvc +//@[X64_WINDOWS_MSVC] needs-llvm-components: x86 +//@[X64_WINDOWS_MSVC] filecheck-flags: --check-prefixes X64,X64-WINDOWS +//@[RISCV64] compile-flags: -Copt-level=3 --target riscv64gc-unknown-linux-gnu +//@[RISCV64] needs-llvm-components: riscv +//@[LOONGARCH64] compile-flags: -Copt-level=3 --target loongarch64-unknown-linux-gnu +//@[LOONGARCH64] needs-llvm-components: loongarch #![feature(f16b, no_core)] #![no_core] diff --git a/tests/ui/float/f16b-restrictions.rs b/tests/ui/float/f16b-restrictions.rs index 7d9af6d6a7de3..b2dbf1a734be3 100644 --- a/tests/ui/float/f16b-restrictions.rs +++ b/tests/ui/float/f16b-restrictions.rs @@ -1,6 +1,3 @@ -//@ ignore-s390x -//@ ignore-wasm - #![feature(f16b)] extern crate core; diff --git a/tests/ui/float/f16b-restrictions.stderr b/tests/ui/float/f16b-restrictions.stderr index 55626b173b2a6..c2fea6cefca5c 100644 --- a/tests/ui/float/f16b-restrictions.stderr +++ b/tests/ui/float/f16b-restrictions.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/f16b-restrictions.rs:11:19 + --> $DIR/f16b-restrictions.rs:8:19 | LL | let _: f16b = 1.0; | ---- ^^^ expected `f16b`, found floating-point number @@ -7,7 +7,7 @@ LL | let _: f16b = 1.0; | expected due to this error[E0369]: cannot add `f16b` to `f16b` - --> $DIR/f16b-restrictions.rs:15:15 + --> $DIR/f16b-restrictions.rs:12:15 | LL | let _ = x + x; | - ^ - f16b @@ -20,13 +20,13 @@ note: `f16b` does not implement `Add` = note: `f16b` is defined in another crate error[E0605]: non-primitive cast: `u16` as `f16b` - --> $DIR/f16b-restrictions.rs:18:13 + --> $DIR/f16b-restrictions.rs:15:13 | LL | let _ = 1u16 as f16b; | ^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object error[E0605]: non-primitive cast: `f16b` as `f32` - --> $DIR/f16b-restrictions.rs:21:13 + --> $DIR/f16b-restrictions.rs:18:13 | LL | let _ = x as f32; | ^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object diff --git a/tests/ui/float/f16b.rs b/tests/ui/float/f16b.rs index 757fbfe175f15..7406fdc538dd8 100644 --- a/tests/ui/float/f16b.rs +++ b/tests/ui/float/f16b.rs @@ -6,11 +6,16 @@ extern crate core; use core::num::f16b; +#[cfg(target_has_reliable_f16b)] use std::fmt::{Debug, LowerExp, UpperExp}; +#[cfg(target_has_reliable_f16b)] const ONE: f16b = f16b::from_bits(0x3f80); + +#[cfg(target_has_reliable_f16b)] const ONE_BITS: u16 = ONE.to_bits(); +#[cfg(target_has_reliable_f16b)] fn assert_traits() where T: Default + Copy + Clone + Debug + LowerExp + UpperExp + PartialEq + PartialOrd, @@ -21,7 +26,8 @@ fn main() { assert_eq!(size_of::(), 2); assert_eq!(align_of::(), 2); - if cfg!(target_has_reliable_f16b) { + #[cfg(target_has_reliable_f16b)] + { assert_traits::(); assert_eq!(f16b::default().to_bits(), 0); From 96b2e5497af33343815dd951d275dd4bce3aa666 Mon Sep 17 00:00:00 2001 From: James Barford-Evans Date: Wed, 2 Sep 2026 13:38:34 +0100 Subject: [PATCH 09/12] add optimisation revisions for `scalable-vectors/bf16-intrinsic.rs` test --- tests/codegen-llvm/scalable-vectors/bf16-intrinsic.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/codegen-llvm/scalable-vectors/bf16-intrinsic.rs b/tests/codegen-llvm/scalable-vectors/bf16-intrinsic.rs index 78b302df76261..a080b36382389 100644 --- a/tests/codegen-llvm/scalable-vectors/bf16-intrinsic.rs +++ b/tests/codegen-llvm/scalable-vectors/bf16-intrinsic.rs @@ -1,4 +1,7 @@ //@ add-minicore +//@ revisions: OPT-0 OPT-3 +//@[OPT-0] compile-flags: -Copt-level=0 +//@[OPT-3] compile-flags: -Copt-level=3 //@ compile-flags: --target aarch64-unknown-linux-gnu //@ needs-llvm-components: aarch64 From 1881b6e55d9f4d877ba78e6f4f230e66f4fb0c86 Mon Sep 17 00:00:00 2001 From: James Barford-Evans Date: Wed, 2 Sep 2026 14:46:59 +0100 Subject: [PATCH 10/12] rename `brain_float` `bfloat` --- library/core/src/num/{brain_float.rs => bfloat.rs} | 0 library/core/src/num/mod.rs | 4 ++-- tests/ui/feature-gates/feature-gate-f16b.stderr | 2 +- tests/ui/float/f16b-restrictions.stderr | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) rename library/core/src/num/{brain_float.rs => bfloat.rs} (100%) diff --git a/library/core/src/num/brain_float.rs b/library/core/src/num/bfloat.rs similarity index 100% rename from library/core/src/num/brain_float.rs rename to library/core/src/num/bfloat.rs diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs index 5503de133ce86..f5c7c853ef590 100644 --- a/library/core/src/num/mod.rs +++ b/library/core/src/num/mod.rs @@ -43,7 +43,7 @@ mod int_macros; // import int_impl! #[macro_use] mod uint_macros; // import uint_impl! -mod brain_float; +mod bfloat; mod complex; mod error; #[cfg(not(no_fp_fmt_parse))] @@ -58,7 +58,7 @@ mod wrapping; pub mod niche_types; #[unstable(feature = "f16b", issue = "160630")] -pub use brain_float::f16b; +pub use bfloat::f16b; #[unstable(feature = "complex_numbers", issue = "154023")] pub use complex::Complex; #[stable(feature = "int_error_matching", since = "1.55.0")] diff --git a/tests/ui/feature-gates/feature-gate-f16b.stderr b/tests/ui/feature-gates/feature-gate-f16b.stderr index f0314f8dd5469..3ba9299485276 100644 --- a/tests/ui/feature-gates/feature-gate-f16b.stderr +++ b/tests/ui/feature-gates/feature-gate-f16b.stderr @@ -93,7 +93,7 @@ LL | let _ = x + x; | f16b | note: `f16b` does not implement `Add` - --> $SRC_DIR/core/src/num/brain_float.rs:LL:COL + --> $SRC_DIR/core/src/num/bfloat.rs:LL:COL | = note: `f16b` is defined in another crate diff --git a/tests/ui/float/f16b-restrictions.stderr b/tests/ui/float/f16b-restrictions.stderr index c2fea6cefca5c..540e92d26b384 100644 --- a/tests/ui/float/f16b-restrictions.stderr +++ b/tests/ui/float/f16b-restrictions.stderr @@ -15,7 +15,7 @@ LL | let _ = x + x; | f16b | note: `f16b` does not implement `Add` - --> $SRC_DIR/core/src/num/brain_float.rs:LL:COL + --> $SRC_DIR/core/src/num/bfloat.rs:LL:COL | = note: `f16b` is defined in another crate From 0a2cc1cdb45bea383639e150404e72863833ff7f Mon Sep 17 00:00:00 2001 From: James Barford-Evans Date: Mon, 7 Sep 2026 08:56:18 +0100 Subject: [PATCH 11/12] Apply nits --- compiler/rustc_target/src/callconv/mips64.rs | 2 +- compiler/rustc_target/src/callconv/sparc64.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_target/src/callconv/mips64.rs b/compiler/rustc_target/src/callconv/mips64.rs index f83be31bc82ce..0a2316618284d 100644 --- a/compiler/rustc_target/src/callconv/mips64.rs +++ b/compiler/rustc_target/src/callconv/mips64.rs @@ -32,7 +32,7 @@ where // C does not have the f16 type Float::F16 => None, // No `f16b` type - Float::F16B => panic!("`f16b` unsupported on mips64"), + Float::F16B => unreachable!("`f16b` unsupported on mips64"), Float::F32 => Some(Reg::f32()), Float::F64 => Some(Reg::f64()), Float::F128 => Some(Reg::f128()), diff --git a/compiler/rustc_target/src/callconv/sparc64.rs b/compiler/rustc_target/src/callconv/sparc64.rs index 9c0c3a8b69530..abef388ef2e12 100644 --- a/compiler/rustc_target/src/callconv/sparc64.rs +++ b/compiler/rustc_target/src/callconv/sparc64.rs @@ -58,7 +58,7 @@ fn classify<'a, Ty, C>( Float::F16 => { // Match LLVM by passing `f16` in integer registers. } - Float::F16B => panic!("`f16b` unsupported on sparc64"), + Float::F16B => unreachable!("`f16b` unsupported on sparc64"), } } else { /* pass unaligned floats in integer registers */ From 2f22e8212f135c834372abb73770d80308b4b6a3 Mon Sep 17 00:00:00 2001 From: James Barford-Evans Date: Mon, 7 Sep 2026 11:53:01 +0100 Subject: [PATCH 12/12] Update hygine test by removing `$f` --- tests/ui/hygiene/unpretty-debug-lifetimes.rs | 6 +++--- tests/ui/hygiene/unpretty-debug-lifetimes.stdout | 7 +++---- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/tests/ui/hygiene/unpretty-debug-lifetimes.rs b/tests/ui/hygiene/unpretty-debug-lifetimes.rs index ee8be21b60d01..1b9dfe1fd23dd 100644 --- a/tests/ui/hygiene/unpretty-debug-lifetimes.rs +++ b/tests/ui/hygiene/unpretty-debug-lifetimes.rs @@ -11,8 +11,8 @@ #![feature(no_core)] #![no_core] -macro lifetime_hygiene($f:ident<$a:lifetime>) { - fn $f<$a, 'a>() {} +macro lifetime_hygiene($a:lifetime) { + fn f<$a, 'a>() {} } -lifetime_hygiene!(f<'a>); +lifetime_hygiene!('a); diff --git a/tests/ui/hygiene/unpretty-debug-lifetimes.stdout b/tests/ui/hygiene/unpretty-debug-lifetimes.stdout index 689453326c0b5..afe7afa89ff94 100644 --- a/tests/ui/hygiene/unpretty-debug-lifetimes.stdout +++ b/tests/ui/hygiene/unpretty-debug-lifetimes.stdout @@ -15,11 +15,10 @@ macro lifetime_hygiene /* 0#0 */ { - ($f /* 0#0 */:ident /* 0#0 */<$a /* 0#0 */:lifetime /* 0#0 */>) - => - { fn /* 0#0 */ $f /* 0#0 */<$a /* 0#0 */, 'a /* 0#0 */>() {} } + ($a /* 0#0 */:lifetime /* 0#0 */) => + { fn /* 0#0 */ f /* 0#0 */<$a /* 0#0 */, 'a /* 0#0 */>() {} } } -fn f /* 0#0 */<'a /* 0#0 */, 'a /* 0#1 */>() {} +fn f /* 0#1 */<'a /* 0#0 */, 'a /* 0#1 */>() {} /*