Rollup merge of #122470 - tgross35:f16-f128-step4-libs-min, r=Amanieu

`f16` and `f128` step 4: basic library support

This is the next step after https://github.com/rust-lang/rust/pull/121926, another portion of https://github.com/rust-lang/rust/pull/114607

Tracking issue: https://github.com/rust-lang/rust/issues/116909

This PR adds the most basic operations to `f16` and `f128` that get lowered as LLVM intrinsics. This is a very small step but it seemed reasonable enough to add unopinionated basic operations before the larger modules that are built on top of them.

r? ```@Amanieu``` since you were pretty involved in the RFC
cc ```@compiler-errors```
```@rustbot``` label +T-libs-api +S-blocked +F-f16_and_f128
This commit is contained in:
León Orell Valerian Liehr 2024-04-11 01:56:23 +02:00 committed by GitHub
commit aac3f24054
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
20 changed files with 482 additions and 50 deletions

View File

@ -227,13 +227,10 @@ mod impls {
impl_clone! {
usize u8 u16 u32 u64 u128
isize i8 i16 i32 i64 i128
f32 f64
f16 f32 f64 f128
bool char
}
#[cfg(not(bootstrap))]
impl_clone! { f16 f128 }
#[unstable(feature = "never_type", issue = "35121")]
impl Clone for ! {
#[inline]

View File

@ -1497,12 +1497,9 @@ mod impls {
}
partial_eq_impl! {
bool char usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64
bool char usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f16 f32 f64 f128
}
#[cfg(not(bootstrap))]
partial_eq_impl! { f16 f128 }
macro_rules! eq_impl {
($($t:ty)*) => ($(
#[stable(feature = "rust1", since = "1.0.0")]
@ -1553,10 +1550,7 @@ mod impls {
}
}
partial_ord_impl! { f32 f64 }
#[cfg(not(bootstrap))]
partial_ord_impl! { f16 f128 }
partial_ord_impl! { f16 f32 f64 f128 }
macro_rules! ord_impl {
($($t:ty)*) => ($(

View File

@ -34,8 +34,10 @@ macro_rules! impl_float_to_int {
}
}
impl_float_to_int!(f16 => u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize);
impl_float_to_int!(f32 => u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize);
impl_float_to_int!(f64 => u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize);
impl_float_to_int!(f128 => u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize);
// Conversion traits for primitive integer and float types
// Conversions T -> T are covered by a blanket impl and therefore excluded
@ -163,7 +165,12 @@ impl_from!(u16 => f64, #[stable(feature = "lossless_float_conv", since = "1.6.0"
impl_from!(u32 => f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")]);
// float -> float
impl_from!(f16 => f32, #[stable(feature = "lossless_float_conv", since = "1.6.0")]);
impl_from!(f16 => f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")]);
impl_from!(f16 => f128, #[stable(feature = "lossless_float_conv", since = "1.6.0")]);
impl_from!(f32 => f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")]);
impl_from!(f32 => f128, #[stable(feature = "lossless_float_conv", since = "1.6.0")]);
impl_from!(f64 => f128, #[stable(feature = "lossless_float_conv", since = "1.6.0")]);
macro_rules! impl_float_from_bool {
($float:ty) => {

View File

@ -11,5 +11,7 @@ macro_rules! floating {
};
}
floating! { f16 }
floating! { f32 }
floating! { f64 }
floating! { f128 }

View File

@ -200,8 +200,6 @@
//
// Language features:
// tidy-alphabetical-start
#![cfg_attr(not(bootstrap), feature(f128))]
#![cfg_attr(not(bootstrap), feature(f16))]
#![feature(abi_unadjusted)]
#![feature(adt_const_params)]
#![feature(allow_internal_unsafe)]
@ -226,6 +224,8 @@
#![feature(doc_notable_trait)]
#![feature(effects)]
#![feature(extern_types)]
#![feature(f128)]
#![feature(f16)]
#![feature(freeze_impls)]
#![feature(fundamental)]
#![feature(generic_arg_infer)]
@ -347,6 +347,10 @@ pub mod u8;
#[path = "num/shells/usize.rs"]
pub mod usize;
#[path = "num/f128.rs"]
pub mod f128;
#[path = "num/f16.rs"]
pub mod f16;
#[path = "num/f32.rs"]
pub mod f32;
#[path = "num/f64.rs"]

View File

@ -422,17 +422,11 @@ marker_impls! {
Copy for
usize, u8, u16, u32, u64, u128,
isize, i8, i16, i32, i64, i128,
f32, f64,
f16, f32, f64, f128,
bool, char,
{T: ?Sized} *const T,
{T: ?Sized} *mut T,
}
#[cfg(not(bootstrap))]
marker_impls! {
#[stable(feature = "rust1", since = "1.0.0")]
Copy for
f16, f128,
}
#[unstable(feature = "never_type", issue = "35121")]

View File

@ -0,0 +1,16 @@
//! Constants for the `f128` quadruple-precision floating point type.
//!
//! *[See also the `f128` primitive type][f128].*
//!
//! Mathematically significant numbers are provided in the `consts` sub-module.
//!
//! For the constants defined directly in this module
//! (as distinct from those defined in the `consts` sub-module),
//! new code should instead use the associated constants
//! defined directly on the `f128` type.
#![unstable(feature = "f128", issue = "116909")]
/// Basic mathematical constants.
#[unstable(feature = "f128", issue = "116909")]
pub mod consts {}

View File

@ -0,0 +1,16 @@
//! Constants for the `f16` half-precision floating point type.
//!
//! *[See also the `f16` primitive type][f16].*
//!
//! Mathematically significant numbers are provided in the `consts` sub-module.
//!
//! For the constants defined directly in this module
//! (as distinct from those defined in the `consts` sub-module),
//! new code should instead use the associated constants
//! defined directly on the `f16` type.
#![unstable(feature = "f16", issue = "116909")]
/// Basic mathematical constants.
#[unstable(feature = "f16", issue = "116909")]
pub mod consts {}

View File

@ -109,7 +109,7 @@ macro_rules! add_impl {
)*)
}
add_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
add_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f16 f32 f64 f128 }
/// The subtraction operator `-`.
///
@ -218,7 +218,7 @@ macro_rules! sub_impl {
)*)
}
sub_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
sub_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f16 f32 f64 f128 }
/// The multiplication operator `*`.
///
@ -348,7 +348,7 @@ macro_rules! mul_impl {
)*)
}
mul_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
mul_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f16 f32 f64 f128 }
/// The division operator `/`.
///
@ -506,7 +506,7 @@ macro_rules! div_impl_float {
)*)
}
div_impl_float! { f32 f64 }
div_impl_float! { f16 f32 f64 f128 }
/// The remainder operator `%`.
///
@ -623,7 +623,7 @@ macro_rules! rem_impl_float {
)*)
}
rem_impl_float! { f32 f64 }
rem_impl_float! { f16 f32 f64 f128 }
/// The unary negation operator `-`.
///
@ -698,7 +698,7 @@ macro_rules! neg_impl {
)*)
}
neg_impl! { isize i8 i16 i32 i64 i128 f32 f64 }
neg_impl! { isize i8 i16 i32 i64 i128 f16 f32 f64 f128 }
/// The addition assignment operator `+=`.
///
@ -765,7 +765,7 @@ macro_rules! add_assign_impl {
)+)
}
add_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
add_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f16 f32 f64 f128 }
/// The subtraction assignment operator `-=`.
///
@ -832,7 +832,7 @@ macro_rules! sub_assign_impl {
)+)
}
sub_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
sub_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f16 f32 f64 f128 }
/// The multiplication assignment operator `*=`.
///
@ -890,7 +890,7 @@ macro_rules! mul_assign_impl {
)+)
}
mul_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
mul_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f16 f32 f64 f128 }
/// The division assignment operator `/=`.
///
@ -947,7 +947,7 @@ macro_rules! div_assign_impl {
)+)
}
div_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
div_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f16 f32 f64 f128 }
/// The remainder assignment operator `%=`.
///
@ -1008,4 +1008,4 @@ macro_rules! rem_assign_impl {
)+)
}
rem_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
rem_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f16 f32 f64 f128 }

View File

@ -1074,7 +1074,22 @@ mod prim_tuple {}
#[doc(hidden)]
impl<T> (T,) {}
#[rustc_doc_primitive = "f16"]
#[doc(alias = "half")]
/// A 16-bit floating point type (specifically, the "binary16" type defined in IEEE 754-2008).
///
/// This type is very similar to [`prim@f32`] but has decreased precision because it uses half as many
/// bits. Please see [the documentation for [`prim@f32`] or [Wikipedia on
/// half-precision values][wikipedia] for more information.
///
/// *[See also the `std::f16::consts` module](crate::f16::consts).*
///
/// [wikipedia]: https://en.wikipedia.org/wiki/Half-precision_floating-point_format
#[unstable(feature = "f16", issue = "116909")]
mod prim_f16 {}
#[rustc_doc_primitive = "f32"]
#[doc(alias = "single")]
/// A 32-bit floating point type (specifically, the "binary32" type defined in IEEE 754-2008).
///
/// This type can represent a wide range of decimal numbers, like `3.5`, `27`,
@ -1143,6 +1158,7 @@ impl<T> (T,) {}
mod prim_f32 {}
#[rustc_doc_primitive = "f64"]
#[doc(alias = "double")]
/// A 64-bit floating point type (specifically, the "binary64" type defined in IEEE 754-2008).
///
/// This type is very similar to [`f32`], but has increased
@ -1157,6 +1173,20 @@ mod prim_f32 {}
#[stable(feature = "rust1", since = "1.0.0")]
mod prim_f64 {}
#[rustc_doc_primitive = "f128"]
#[doc(alias = "quad")]
/// A 128-bit floating point type (specifically, the "binary128" type defined in IEEE 754-2008).
///
/// This type is very similar to [`prim@f32`] and [`prim@f64`], but has increased precision by using twice
/// as many bits as `f64`. Please see [the documentation for [`prim@f32`] or [Wikipedia on
/// quad-precision values][wikipedia] for more information.
///
/// *[See also the `std::f128::consts` module](crate::f128::consts).*
///
/// [wikipedia]: https://en.wikipedia.org/wiki/Quadruple-precision_floating-point_format
#[unstable(feature = "f128", issue = "116909")]
mod prim_f128 {}
#[rustc_doc_primitive = "i8"]
//
/// The 8-bit signed integer type.

11
library/std/src/f128.rs Normal file
View File

@ -0,0 +1,11 @@
//! Constants for the `f128` double-precision floating point type.
//!
//! *[See also the `f128` primitive type](primitive@f128).*
//!
//! Mathematically significant numbers are provided in the `consts` sub-module.
#[cfg(test)]
mod tests;
#[unstable(feature = "f128", issue = "116909")]
pub use core::f128::consts;

View File

@ -0,0 +1,40 @@
#![allow(dead_code)] // FIXME(f16_f128): remove once constants are used
/// Smallest number
const TINY_BITS: u128 = 0x1;
/// Next smallest number
const TINY_UP_BITS: u128 = 0x2;
/// Exponent = 0b11...10, Sifnificand 0b1111..10. Min val > 0
const MAX_DOWN_BITS: u128 = 0x7ffeffffffffffffffffffffffffffff;
/// Zeroed exponent, full significant
const LARGEST_SUBNORMAL_BITS: u128 = 0x0000ffffffffffffffffffffffffffff;
/// Exponent = 0b1, zeroed significand
const SMALLEST_NORMAL_BITS: u128 = 0x00010000000000000000000000000000;
/// First pattern over the mantissa
const NAN_MASK1: u128 = 0x0000aaaaaaaaaaaaaaaaaaaaaaaaaaaa;
/// Second pattern over the mantissa
const NAN_MASK2: u128 = 0x00005555555555555555555555555555;
/// Compare by value
#[allow(unused_macros)]
macro_rules! assert_f128_eq {
($a:expr, $b:expr) => {
let (l, r): (&f128, &f128) = (&$a, &$b);
assert_eq!(*l, *r, "\na: {:#0130x}\nb: {:#0130x}", l.to_bits(), r.to_bits())
};
}
/// Compare by representation
#[allow(unused_macros)]
macro_rules! assert_f128_biteq {
($a:expr, $b:expr) => {
let (l, r): (&f128, &f128) = (&$a, &$b);
let lb = l.to_bits();
let rb = r.to_bits();
assert_eq!(
lb, rb,
"float {:?} is not bitequal to {:?}.\na: {:#0130x}\nb: {:#0130x}",
*l, *r, lb, rb
);
};
}

11
library/std/src/f16.rs Normal file
View File

@ -0,0 +1,11 @@
//! Constants for the `f16` double-precision floating point type.
//!
//! *[See also the `f16` primitive type](primitive@f16).*
//!
//! Mathematically significant numbers are provided in the `consts` sub-module.
#[cfg(test)]
mod tests;
#[unstable(feature = "f16", issue = "116909")]
pub use core::f16::consts;

View File

@ -0,0 +1,46 @@
#![allow(dead_code)] // FIXME(f16_f128): remove once constants are used
// We run out of precision pretty quickly with f16
const F16_APPROX_L1: f16 = 0.001;
const F16_APPROX_L2: f16 = 0.01;
const F16_APPROX_L3: f16 = 0.1;
const F16_APPROX_L4: f16 = 0.5;
/// Smallest number
const TINY_BITS: u16 = 0x1;
/// Next smallest number
const TINY_UP_BITS: u16 = 0x2;
/// Exponent = 0b11...10, Sifnificand 0b1111..10. Min val > 0
const MAX_DOWN_BITS: u16 = 0x7bfe;
/// Zeroed exponent, full significant
const LARGEST_SUBNORMAL_BITS: u16 = 0x03ff;
/// Exponent = 0b1, zeroed significand
const SMALLEST_NORMAL_BITS: u16 = 0x0400;
/// First pattern over the mantissa
const NAN_MASK1: u16 = 0x02aa;
/// Second pattern over the mantissa
const NAN_MASK2: u16 = 0x0155;
/// Compare by value
#[allow(unused_macros)]
macro_rules! assert_f16_eq {
($a:expr, $b:expr) => {
let (l, r): (&f16, &f16) = (&$a, &$b);
assert_eq!(*l, *r, "\na: {:#018x}\nb: {:#018x}", l.to_bits(), r.to_bits())
};
}
/// Compare by representation
#[allow(unused_macros)]
macro_rules! assert_f16_biteq {
($a:expr, $b:expr) => {
let (l, r): (&f16, &f16) = (&$a, &$b);
let lb = l.to_bits();
let rb = r.to_bits();
assert_eq!(
lb, rb,
"float {:?} is not bitequal to {:?}.\na: {:#018x}\nb: {:#018x}",
*l, *r, lb, rb
);
};
}

View File

@ -283,6 +283,8 @@
#![feature(doc_masked)]
#![feature(doc_notable_trait)]
#![feature(dropck_eyepatch)]
#![feature(f128)]
#![feature(f16)]
#![feature(if_let_guard)]
#![feature(intra_doc_pointers)]
#![feature(lang_items)]
@ -558,6 +560,10 @@ pub use core::u8;
#[allow(deprecated, deprecated_in_future)]
pub use core::usize;
#[unstable(feature = "f128", issue = "116909")]
pub mod f128;
#[unstable(feature = "f16", issue = "116909")]
pub mod f16;
pub mod f32;
pub mod f64;

129
tests/codegen/float/f128.rs Normal file
View File

@ -0,0 +1,129 @@
// Verify that our intrinsics generate the correct LLVM calls for f128
#![crate_type = "lib"]
#![feature(f128)]
#![feature(core_intrinsics)]
// CHECK-LABEL: i1 @f128_eq(
#[no_mangle]
pub fn f128_eq(a: f128, b: f128) -> bool {
// CHECK: fcmp oeq fp128 %{{.+}}, %{{.+}}
a == b
}
// CHECK-LABEL: i1 @f128_ne(
#[no_mangle]
pub fn f128_ne(a: f128, b: f128) -> bool {
// CHECK: fcmp une fp128 %{{.+}}, %{{.+}}
a != b
}
// CHECK-LABEL: i1 @f128_gt(
#[no_mangle]
pub fn f128_gt(a: f128, b: f128) -> bool {
// CHECK: fcmp ogt fp128 %{{.+}}, %{{.+}}
a > b
}
// CHECK-LABEL: i1 @f128_ge(
#[no_mangle]
pub fn f128_ge(a: f128, b: f128) -> bool {
// CHECK: fcmp oge fp128 %{{.+}}, %{{.+}}
a >= b
}
// CHECK-LABEL: i1 @f128_lt(
#[no_mangle]
pub fn f128_lt(a: f128, b: f128) -> bool {
// CHECK: fcmp olt fp128 %{{.+}}, %{{.+}}
a < b
}
// CHECK-LABEL: i1 @f128_le(
#[no_mangle]
pub fn f128_le(a: f128, b: f128) -> bool {
// CHECK: fcmp ole fp128 %{{.+}}, %{{.+}}
a <= b
}
// CHECK-LABEL: fp128 @f128_neg(
#[no_mangle]
pub fn f128_neg(a: f128) -> f128 {
// CHECK: fneg fp128
-a
}
// CHECK-LABEL: fp128 @f128_add(
#[no_mangle]
pub fn f128_add(a: f128, b: f128) -> f128 {
// CHECK: fadd fp128 %{{.+}}, %{{.+}}
a + b
}
// CHECK-LABEL: fp128 @f128_sub(
#[no_mangle]
pub fn f128_sub(a: f128, b: f128) -> f128 {
// CHECK: fsub fp128 %{{.+}}, %{{.+}}
a - b
}
// CHECK-LABEL: fp128 @f128_mul(
#[no_mangle]
pub fn f128_mul(a: f128, b: f128) -> f128 {
// CHECK: fmul fp128 %{{.+}}, %{{.+}}
a * b
}
// CHECK-LABEL: fp128 @f128_div(
#[no_mangle]
pub fn f128_div(a: f128, b: f128) -> f128 {
// CHECK: fdiv fp128 %{{.+}}, %{{.+}}
a / b
}
// CHECK-LABEL: fp128 @f128_rem(
#[no_mangle]
pub fn f128_rem(a: f128, b: f128) -> f128 {
// CHECK: frem fp128 %{{.+}}, %{{.+}}
a % b
}
// CHECK-LABEL: void @f128_add_assign(
#[no_mangle]
pub fn f128_add_assign(a: &mut f128, b: f128) {
// CHECK: fadd fp128 %{{.+}}, %{{.+}}
// CHECK-NEXT: store fp128 %{{.+}}, ptr %{{.+}}
*a += b;
}
// CHECK-LABEL: void @f128_sub_assign(
#[no_mangle]
pub fn f128_sub_assign(a: &mut f128, b: f128) {
// CHECK: fsub fp128 %{{.+}}, %{{.+}}
// CHECK-NEXT: store fp128 %{{.+}}, ptr %{{.+}}
*a -= b;
}
// CHECK-LABEL: void @f128_mul_assign(
#[no_mangle]
pub fn f128_mul_assign(a: &mut f128, b: f128) {
// CHECK: fmul fp128 %{{.+}}, %{{.+}}
// CHECK-NEXT: store fp128 %{{.+}}, ptr %{{.+}}
*a *= b
}
// CHECK-LABEL: void @f128_div_assign(
#[no_mangle]
pub fn f128_div_assign(a: &mut f128, b: f128) {
// CHECK: fdiv fp128 %{{.+}}, %{{.+}}
// CHECK-NEXT: store fp128 %{{.+}}, ptr %{{.+}}
*a /= b
}
// CHECK-LABEL: void @f128_rem_assign(
#[no_mangle]
pub fn f128_rem_assign(a: &mut f128, b: f128) {
// CHECK: frem fp128 %{{.+}}, %{{.+}}
// CHECK-NEXT: store fp128 %{{.+}}, ptr %{{.+}}
*a %= b
}

129
tests/codegen/float/f16.rs Normal file
View File

@ -0,0 +1,129 @@
// Verify that our intrinsics generate the correct LLVM calls for f16
#![crate_type = "lib"]
#![feature(f16)]
#![feature(core_intrinsics)]
// CHECK-LABEL: i1 @f16_eq(
#[no_mangle]
pub fn f16_eq(a: f16, b: f16) -> bool {
// CHECK: fcmp oeq half %{{.+}}, %{{.+}}
a == b
}
// CHECK-LABEL: i1 @f16_ne(
#[no_mangle]
pub fn f16_ne(a: f16, b: f16) -> bool {
// CHECK: fcmp une half %{{.+}}, %{{.+}}
a != b
}
// CHECK-LABEL: i1 @f16_gt(
#[no_mangle]
pub fn f16_gt(a: f16, b: f16) -> bool {
// CHECK: fcmp ogt half %{{.+}}, %{{.+}}
a > b
}
// CHECK-LABEL: i1 @f16_ge(
#[no_mangle]
pub fn f16_ge(a: f16, b: f16) -> bool {
// CHECK: fcmp oge half %{{.+}}, %{{.+}}
a >= b
}
// CHECK-LABEL: i1 @f16_lt(
#[no_mangle]
pub fn f16_lt(a: f16, b: f16) -> bool {
// CHECK: fcmp olt half %{{.+}}, %{{.+}}
a < b
}
// CHECK-LABEL: i1 @f16_le(
#[no_mangle]
pub fn f16_le(a: f16, b: f16) -> bool {
// CHECK: fcmp ole half %{{.+}}, %{{.+}}
a <= b
}
// CHECK-LABEL: half @f16_neg(
#[no_mangle]
pub fn f16_neg(a: f16) -> f16 {
// CHECK: fneg half %{{.+}}
-a
}
// CHECK-LABEL: half @f16_add(
#[no_mangle]
pub fn f16_add(a: f16, b: f16) -> f16 {
// CHECK: fadd half %{{.+}}, %{{.+}}
a + b
}
// CHECK-LABEL: half @f16_sub(
#[no_mangle]
pub fn f16_sub(a: f16, b: f16) -> f16 {
// CHECK: fsub half %{{.+}}, %{{.+}}
a - b
}
// CHECK-LABEL: half @f16_mul(
#[no_mangle]
pub fn f16_mul(a: f16, b: f16) -> f16 {
// CHECK: fmul half %{{.+}}, %{{.+}}
a * b
}
// CHECK-LABEL: half @f16_div(
#[no_mangle]
pub fn f16_div(a: f16, b: f16) -> f16 {
// CHECK: fdiv half %{{.+}}, %{{.+}}
a / b
}
// CHECK-LABEL: half @f16_rem(
#[no_mangle]
pub fn f16_rem(a: f16, b: f16) -> f16 {
// CHECK: frem half %{{.+}}, %{{.+}}
a % b
}
// CHECK-LABEL: void @f16_add_assign(
#[no_mangle]
pub fn f16_add_assign(a: &mut f16, b: f16) {
// CHECK: fadd half %{{.+}}, %{{.+}}
// CHECK-NEXT: store half %{{.+}}, ptr %{{.+}}
*a += b;
}
// CHECK-LABEL: void @f16_sub_assign(
#[no_mangle]
pub fn f16_sub_assign(a: &mut f16, b: f16) {
// CHECK: fsub half %{{.+}}, %{{.+}}
// CHECK-NEXT: store half %{{.+}}, ptr %{{.+}}
*a -= b;
}
// CHECK-LABEL: void @f16_mul_assign(
#[no_mangle]
pub fn f16_mul_assign(a: &mut f16, b: f16) {
// CHECK: fmul half %{{.+}}, %{{.+}}
// CHECK-NEXT: store half %{{.+}}, ptr %{{.+}}
*a *= b
}
// CHECK-LABEL: void @f16_div_assign(
#[no_mangle]
pub fn f16_div_assign(a: &mut f16, b: f16) {
// CHECK: fdiv half %{{.+}}, %{{.+}}
// CHECK-NEXT: store half %{{.+}}, ptr %{{.+}}
*a /= b
}
// CHECK-LABEL: void @f16_rem_assign(
#[no_mangle]
pub fn f16_rem_assign(a: &mut f16, b: f16) {
// CHECK: frem half %{{.+}}, %{{.+}}
// CHECK-NEXT: store half %{{.+}}, ptr %{{.+}}
*a %= b
}

View File

@ -6,15 +6,15 @@ LL | 1 +
|
= help: the trait `Add<()>` is not implemented for `{integer}`
= help: the following other types implement trait `Add<Rhs>`:
<&'a f128 as Add<f128>>
<&'a f16 as Add<f16>>
<&'a f32 as Add<f32>>
<&'a f64 as Add<f64>>
<&'a i128 as Add<i128>>
<&'a i16 as Add<i16>>
<&'a i32 as Add<i32>>
<&'a i64 as Add<i64>>
<&'a i8 as Add<i8>>
<&'a isize as Add<isize>>
and 48 others
and 56 others
error[E0277]: cannot add `()` to `{integer}`
--> $DIR/issue-11771.rs:8:7
@ -24,15 +24,15 @@ LL | 1 +
|
= help: the trait `Add<()>` is not implemented for `{integer}`
= help: the following other types implement trait `Add<Rhs>`:
<&'a f128 as Add<f128>>
<&'a f16 as Add<f16>>
<&'a f32 as Add<f32>>
<&'a f64 as Add<f64>>
<&'a i128 as Add<i128>>
<&'a i16 as Add<i16>>
<&'a i32 as Add<i32>>
<&'a i64 as Add<i64>>
<&'a i8 as Add<i8>>
<&'a isize as Add<isize>>
and 48 others
and 56 others
error: aborting due to 2 previous errors

View File

@ -16,15 +16,15 @@ LL | Vec::<[(); 1 + for x in 0..1 {}]>::new();
|
= help: the trait `Add<()>` is not implemented for `{integer}`
= help: the following other types implement trait `Add<Rhs>`:
<&'a f128 as Add<f128>>
<&'a f16 as Add<f16>>
<&'a f32 as Add<f32>>
<&'a f64 as Add<f64>>
<&'a i128 as Add<i128>>
<&'a i16 as Add<i16>>
<&'a i32 as Add<i32>>
<&'a i64 as Add<i64>>
<&'a i8 as Add<i8>>
<&'a isize as Add<isize>>
and 48 others
and 56 others
error: aborting due to 2 previous errors

View File

@ -6,15 +6,15 @@ LL | 1 + Some(1);
|
= help: the trait `Add<Option<{integer}>>` is not implemented for `{integer}`
= help: the following other types implement trait `Add<Rhs>`:
<&'a f128 as Add<f128>>
<&'a f16 as Add<f16>>
<&'a f32 as Add<f32>>
<&'a f64 as Add<f64>>
<&'a i128 as Add<i128>>
<&'a i16 as Add<i16>>
<&'a i32 as Add<i32>>
<&'a i64 as Add<i64>>
<&'a i8 as Add<i8>>
<&'a isize as Add<isize>>
and 48 others
and 56 others
error[E0277]: cannot subtract `Option<{integer}>` from `usize`
--> $DIR/binops.rs:3:16
@ -37,15 +37,15 @@ LL | 3 * ();
|
= help: the trait `Mul<()>` is not implemented for `{integer}`
= help: the following other types implement trait `Mul<Rhs>`:
<&'a f128 as Mul<f128>>
<&'a f16 as Mul<f16>>
<&'a f32 as Mul<f32>>
<&'a f64 as Mul<f64>>
<&'a i128 as Mul<i128>>
<&'a i16 as Mul<i16>>
<&'a i32 as Mul<i32>>
<&'a i64 as Mul<i64>>
<&'a i8 as Mul<i8>>
<&'a isize as Mul<isize>>
and 49 others
and 57 others
error[E0277]: cannot divide `{integer}` by `&str`
--> $DIR/binops.rs:5:7
@ -55,15 +55,15 @@ LL | 4 / "";
|
= help: the trait `Div<&str>` is not implemented for `{integer}`
= help: the following other types implement trait `Div<Rhs>`:
<&'a f128 as Div<f128>>
<&'a f16 as Div<f16>>
<&'a f32 as Div<f32>>
<&'a f64 as Div<f64>>
<&'a i128 as Div<i128>>
<&'a i16 as Div<i16>>
<&'a i32 as Div<i32>>
<&'a i64 as Div<i64>>
<&'a i8 as Div<i8>>
<&'a isize as Div<isize>>
and 54 others
and 62 others
error[E0277]: can't compare `{integer}` with `String`
--> $DIR/binops.rs:6:7