about summary refs log tree commit diff
diff options
context:
space:
mode:
authorTrevor Gross <tmgross@umich.edu>2024-03-06 05:40:29 -0600
committerTrevor Gross <tmgross@umich.edu>2024-04-10 13:50:27 -0400
commit454de78ea3073a284a7a8a41184789f9afa066a3 (patch)
tree7af8eeaa73c3aa2833cf0f1b313242f160fa8186
parent88bcc79f316b342c9413c5760bc2f6d5ac69e4fe (diff)
Add basic library support for `f16` and `f128`
Implement basic operation traits that get lowered to intrinsics. This
includes codegen tests for implemented operations.
-rw-r--r--library/core/src/convert/num.rs7
-rw-r--r--library/core/src/fmt/nofloat.rs2
-rw-r--r--library/core/src/ops/arith.rs22
-rw-r--r--tests/codegen/float/f128.rs129
-rw-r--r--tests/codegen/float/f16.rs129
-rw-r--r--tests/ui/issues/issue-11771.stderr12
-rw-r--r--tests/ui/issues/issue-50582.stderr6
-rw-r--r--tests/ui/mismatched_types/binops.stderr18
8 files changed, 296 insertions, 29 deletions
diff --git a/library/core/src/convert/num.rs b/library/core/src/convert/num.rs
index 0167d04c413..1737c631f0b 100644
--- a/library/core/src/convert/num.rs
+++ b/library/core/src/convert/num.rs
@@ -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) => {
diff --git a/library/core/src/fmt/nofloat.rs b/library/core/src/fmt/nofloat.rs
index cfb94cd9de5..a36e7efcd95 100644
--- a/library/core/src/fmt/nofloat.rs
+++ b/library/core/src/fmt/nofloat.rs
@@ -11,5 +11,7 @@ macro_rules! floating {
     };
 }
 
+floating! { f16 }
 floating! { f32 }
 floating! { f64 }
+floating! { f128 }
diff --git a/library/core/src/ops/arith.rs b/library/core/src/ops/arith.rs
index fd50f804748..5e77788d8ea 100644
--- a/library/core/src/ops/arith.rs
+++ b/library/core/src/ops/arith.rs
@@ -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 }
diff --git a/tests/codegen/float/f128.rs b/tests/codegen/float/f128.rs
new file mode 100644
index 00000000000..97d545e0283
--- /dev/null
+++ b/tests/codegen/float/f128.rs
@@ -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
+}
diff --git a/tests/codegen/float/f16.rs b/tests/codegen/float/f16.rs
new file mode 100644
index 00000000000..d1f75cc3b68
--- /dev/null
+++ b/tests/codegen/float/f16.rs
@@ -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
+}
diff --git a/tests/ui/issues/issue-11771.stderr b/tests/ui/issues/issue-11771.stderr
index 161fce4b031..d4a4647f6a1 100644
--- a/tests/ui/issues/issue-11771.stderr
+++ b/tests/ui/issues/issue-11771.stderr
@@ -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
 
diff --git a/tests/ui/issues/issue-50582.stderr b/tests/ui/issues/issue-50582.stderr
index 1967b51128f..b765d2f087d 100644
--- a/tests/ui/issues/issue-50582.stderr
+++ b/tests/ui/issues/issue-50582.stderr
@@ -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
 
diff --git a/tests/ui/mismatched_types/binops.stderr b/tests/ui/mismatched_types/binops.stderr
index f8047c8e2d4..099c580a056 100644
--- a/tests/ui/mismatched_types/binops.stderr
+++ b/tests/ui/mismatched_types/binops.stderr
@@ -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