Skip to content

Commit 454de78

Browse files
committed
Add basic library support for f16 and f128
Implement basic operation traits that get lowered to intrinsics. This includes codegen tests for implemented operations.
1 parent 88bcc79 commit 454de78

File tree

8 files changed

+296
-29
lines changed

8 files changed

+296
-29
lines changed

library/core/src/convert/num.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,10 @@ macro_rules! impl_float_to_int {
3434
}
3535
}
3636

37+
impl_float_to_int!(f16 => u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize);
3738
impl_float_to_int!(f32 => u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize);
3839
impl_float_to_int!(f64 => u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize);
40+
impl_float_to_int!(f128 => u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize);
3941

4042
// Conversion traits for primitive integer and float types
4143
// 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"
163165
impl_from!(u32 => f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")]);
164166

165167
// float -> float
168+
impl_from!(f16 => f32, #[stable(feature = "lossless_float_conv", since = "1.6.0")]);
169+
impl_from!(f16 => f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")]);
170+
impl_from!(f16 => f128, #[stable(feature = "lossless_float_conv", since = "1.6.0")]);
166171
impl_from!(f32 => f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")]);
172+
impl_from!(f32 => f128, #[stable(feature = "lossless_float_conv", since = "1.6.0")]);
173+
impl_from!(f64 => f128, #[stable(feature = "lossless_float_conv", since = "1.6.0")]);
167174

168175
macro_rules! impl_float_from_bool {
169176
($float:ty) => {

library/core/src/fmt/nofloat.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,7 @@ macro_rules! floating {
1111
};
1212
}
1313

14+
floating! { f16 }
1415
floating! { f32 }
1516
floating! { f64 }
17+
floating! { f128 }

library/core/src/ops/arith.rs

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ macro_rules! add_impl {
109109
)*)
110110
}
111111

112-
add_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
112+
add_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f16 f32 f64 f128 }
113113

114114
/// The subtraction operator `-`.
115115
///
@@ -218,7 +218,7 @@ macro_rules! sub_impl {
218218
)*)
219219
}
220220

221-
sub_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
221+
sub_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f16 f32 f64 f128 }
222222

223223
/// The multiplication operator `*`.
224224
///
@@ -348,7 +348,7 @@ macro_rules! mul_impl {
348348
)*)
349349
}
350350

351-
mul_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
351+
mul_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f16 f32 f64 f128 }
352352

353353
/// The division operator `/`.
354354
///
@@ -506,7 +506,7 @@ macro_rules! div_impl_float {
506506
)*)
507507
}
508508

509-
div_impl_float! { f32 f64 }
509+
div_impl_float! { f16 f32 f64 f128 }
510510

511511
/// The remainder operator `%`.
512512
///
@@ -623,7 +623,7 @@ macro_rules! rem_impl_float {
623623
)*)
624624
}
625625

626-
rem_impl_float! { f32 f64 }
626+
rem_impl_float! { f16 f32 f64 f128 }
627627

628628
/// The unary negation operator `-`.
629629
///
@@ -698,7 +698,7 @@ macro_rules! neg_impl {
698698
)*)
699699
}
700700

701-
neg_impl! { isize i8 i16 i32 i64 i128 f32 f64 }
701+
neg_impl! { isize i8 i16 i32 i64 i128 f16 f32 f64 f128 }
702702

703703
/// The addition assignment operator `+=`.
704704
///
@@ -765,7 +765,7 @@ macro_rules! add_assign_impl {
765765
)+)
766766
}
767767

768-
add_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
768+
add_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f16 f32 f64 f128 }
769769

770770
/// The subtraction assignment operator `-=`.
771771
///
@@ -832,7 +832,7 @@ macro_rules! sub_assign_impl {
832832
)+)
833833
}
834834

835-
sub_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
835+
sub_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f16 f32 f64 f128 }
836836

837837
/// The multiplication assignment operator `*=`.
838838
///
@@ -890,7 +890,7 @@ macro_rules! mul_assign_impl {
890890
)+)
891891
}
892892

893-
mul_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
893+
mul_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f16 f32 f64 f128 }
894894

895895
/// The division assignment operator `/=`.
896896
///
@@ -947,7 +947,7 @@ macro_rules! div_assign_impl {
947947
)+)
948948
}
949949

950-
div_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
950+
div_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f16 f32 f64 f128 }
951951

952952
/// The remainder assignment operator `%=`.
953953
///
@@ -1008,4 +1008,4 @@ macro_rules! rem_assign_impl {
10081008
)+)
10091009
}
10101010

1011-
rem_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
1011+
rem_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f16 f32 f64 f128 }

tests/codegen/float/f128.rs

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
// Verify that our intrinsics generate the correct LLVM calls for f128
2+
3+
#![crate_type = "lib"]
4+
#![feature(f128)]
5+
#![feature(core_intrinsics)]
6+
7+
// CHECK-LABEL: i1 @f128_eq(
8+
#[no_mangle]
9+
pub fn f128_eq(a: f128, b: f128) -> bool {
10+
// CHECK: fcmp oeq fp128 %{{.+}}, %{{.+}}
11+
a == b
12+
}
13+
14+
// CHECK-LABEL: i1 @f128_ne(
15+
#[no_mangle]
16+
pub fn f128_ne(a: f128, b: f128) -> bool {
17+
// CHECK: fcmp une fp128 %{{.+}}, %{{.+}}
18+
a != b
19+
}
20+
21+
// CHECK-LABEL: i1 @f128_gt(
22+
#[no_mangle]
23+
pub fn f128_gt(a: f128, b: f128) -> bool {
24+
// CHECK: fcmp ogt fp128 %{{.+}}, %{{.+}}
25+
a > b
26+
}
27+
28+
// CHECK-LABEL: i1 @f128_ge(
29+
#[no_mangle]
30+
pub fn f128_ge(a: f128, b: f128) -> bool {
31+
// CHECK: fcmp oge fp128 %{{.+}}, %{{.+}}
32+
a >= b
33+
}
34+
35+
// CHECK-LABEL: i1 @f128_lt(
36+
#[no_mangle]
37+
pub fn f128_lt(a: f128, b: f128) -> bool {
38+
// CHECK: fcmp olt fp128 %{{.+}}, %{{.+}}
39+
a < b
40+
}
41+
42+
// CHECK-LABEL: i1 @f128_le(
43+
#[no_mangle]
44+
pub fn f128_le(a: f128, b: f128) -> bool {
45+
// CHECK: fcmp ole fp128 %{{.+}}, %{{.+}}
46+
a <= b
47+
}
48+
49+
// CHECK-LABEL: fp128 @f128_neg(
50+
#[no_mangle]
51+
pub fn f128_neg(a: f128) -> f128 {
52+
// CHECK: fneg fp128
53+
-a
54+
}
55+
56+
// CHECK-LABEL: fp128 @f128_add(
57+
#[no_mangle]
58+
pub fn f128_add(a: f128, b: f128) -> f128 {
59+
// CHECK: fadd fp128 %{{.+}}, %{{.+}}
60+
a + b
61+
}
62+
63+
// CHECK-LABEL: fp128 @f128_sub(
64+
#[no_mangle]
65+
pub fn f128_sub(a: f128, b: f128) -> f128 {
66+
// CHECK: fsub fp128 %{{.+}}, %{{.+}}
67+
a - b
68+
}
69+
70+
// CHECK-LABEL: fp128 @f128_mul(
71+
#[no_mangle]
72+
pub fn f128_mul(a: f128, b: f128) -> f128 {
73+
// CHECK: fmul fp128 %{{.+}}, %{{.+}}
74+
a * b
75+
}
76+
77+
// CHECK-LABEL: fp128 @f128_div(
78+
#[no_mangle]
79+
pub fn f128_div(a: f128, b: f128) -> f128 {
80+
// CHECK: fdiv fp128 %{{.+}}, %{{.+}}
81+
a / b
82+
}
83+
84+
// CHECK-LABEL: fp128 @f128_rem(
85+
#[no_mangle]
86+
pub fn f128_rem(a: f128, b: f128) -> f128 {
87+
// CHECK: frem fp128 %{{.+}}, %{{.+}}
88+
a % b
89+
}
90+
91+
// CHECK-LABEL: void @f128_add_assign(
92+
#[no_mangle]
93+
pub fn f128_add_assign(a: &mut f128, b: f128) {
94+
// CHECK: fadd fp128 %{{.+}}, %{{.+}}
95+
// CHECK-NEXT: store fp128 %{{.+}}, ptr %{{.+}}
96+
*a += b;
97+
}
98+
99+
// CHECK-LABEL: void @f128_sub_assign(
100+
#[no_mangle]
101+
pub fn f128_sub_assign(a: &mut f128, b: f128) {
102+
// CHECK: fsub fp128 %{{.+}}, %{{.+}}
103+
// CHECK-NEXT: store fp128 %{{.+}}, ptr %{{.+}}
104+
*a -= b;
105+
}
106+
107+
// CHECK-LABEL: void @f128_mul_assign(
108+
#[no_mangle]
109+
pub fn f128_mul_assign(a: &mut f128, b: f128) {
110+
// CHECK: fmul fp128 %{{.+}}, %{{.+}}
111+
// CHECK-NEXT: store fp128 %{{.+}}, ptr %{{.+}}
112+
*a *= b
113+
}
114+
115+
// CHECK-LABEL: void @f128_div_assign(
116+
#[no_mangle]
117+
pub fn f128_div_assign(a: &mut f128, b: f128) {
118+
// CHECK: fdiv fp128 %{{.+}}, %{{.+}}
119+
// CHECK-NEXT: store fp128 %{{.+}}, ptr %{{.+}}
120+
*a /= b
121+
}
122+
123+
// CHECK-LABEL: void @f128_rem_assign(
124+
#[no_mangle]
125+
pub fn f128_rem_assign(a: &mut f128, b: f128) {
126+
// CHECK: frem fp128 %{{.+}}, %{{.+}}
127+
// CHECK-NEXT: store fp128 %{{.+}}, ptr %{{.+}}
128+
*a %= b
129+
}

tests/codegen/float/f16.rs

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
// Verify that our intrinsics generate the correct LLVM calls for f16
2+
3+
#![crate_type = "lib"]
4+
#![feature(f16)]
5+
#![feature(core_intrinsics)]
6+
7+
// CHECK-LABEL: i1 @f16_eq(
8+
#[no_mangle]
9+
pub fn f16_eq(a: f16, b: f16) -> bool {
10+
// CHECK: fcmp oeq half %{{.+}}, %{{.+}}
11+
a == b
12+
}
13+
14+
// CHECK-LABEL: i1 @f16_ne(
15+
#[no_mangle]
16+
pub fn f16_ne(a: f16, b: f16) -> bool {
17+
// CHECK: fcmp une half %{{.+}}, %{{.+}}
18+
a != b
19+
}
20+
21+
// CHECK-LABEL: i1 @f16_gt(
22+
#[no_mangle]
23+
pub fn f16_gt(a: f16, b: f16) -> bool {
24+
// CHECK: fcmp ogt half %{{.+}}, %{{.+}}
25+
a > b
26+
}
27+
28+
// CHECK-LABEL: i1 @f16_ge(
29+
#[no_mangle]
30+
pub fn f16_ge(a: f16, b: f16) -> bool {
31+
// CHECK: fcmp oge half %{{.+}}, %{{.+}}
32+
a >= b
33+
}
34+
35+
// CHECK-LABEL: i1 @f16_lt(
36+
#[no_mangle]
37+
pub fn f16_lt(a: f16, b: f16) -> bool {
38+
// CHECK: fcmp olt half %{{.+}}, %{{.+}}
39+
a < b
40+
}
41+
42+
// CHECK-LABEL: i1 @f16_le(
43+
#[no_mangle]
44+
pub fn f16_le(a: f16, b: f16) -> bool {
45+
// CHECK: fcmp ole half %{{.+}}, %{{.+}}
46+
a <= b
47+
}
48+
49+
// CHECK-LABEL: half @f16_neg(
50+
#[no_mangle]
51+
pub fn f16_neg(a: f16) -> f16 {
52+
// CHECK: fneg half %{{.+}}
53+
-a
54+
}
55+
56+
// CHECK-LABEL: half @f16_add(
57+
#[no_mangle]
58+
pub fn f16_add(a: f16, b: f16) -> f16 {
59+
// CHECK: fadd half %{{.+}}, %{{.+}}
60+
a + b
61+
}
62+
63+
// CHECK-LABEL: half @f16_sub(
64+
#[no_mangle]
65+
pub fn f16_sub(a: f16, b: f16) -> f16 {
66+
// CHECK: fsub half %{{.+}}, %{{.+}}
67+
a - b
68+
}
69+
70+
// CHECK-LABEL: half @f16_mul(
71+
#[no_mangle]
72+
pub fn f16_mul(a: f16, b: f16) -> f16 {
73+
// CHECK: fmul half %{{.+}}, %{{.+}}
74+
a * b
75+
}
76+
77+
// CHECK-LABEL: half @f16_div(
78+
#[no_mangle]
79+
pub fn f16_div(a: f16, b: f16) -> f16 {
80+
// CHECK: fdiv half %{{.+}}, %{{.+}}
81+
a / b
82+
}
83+
84+
// CHECK-LABEL: half @f16_rem(
85+
#[no_mangle]
86+
pub fn f16_rem(a: f16, b: f16) -> f16 {
87+
// CHECK: frem half %{{.+}}, %{{.+}}
88+
a % b
89+
}
90+
91+
// CHECK-LABEL: void @f16_add_assign(
92+
#[no_mangle]
93+
pub fn f16_add_assign(a: &mut f16, b: f16) {
94+
// CHECK: fadd half %{{.+}}, %{{.+}}
95+
// CHECK-NEXT: store half %{{.+}}, ptr %{{.+}}
96+
*a += b;
97+
}
98+
99+
// CHECK-LABEL: void @f16_sub_assign(
100+
#[no_mangle]
101+
pub fn f16_sub_assign(a: &mut f16, b: f16) {
102+
// CHECK: fsub half %{{.+}}, %{{.+}}
103+
// CHECK-NEXT: store half %{{.+}}, ptr %{{.+}}
104+
*a -= b;
105+
}
106+
107+
// CHECK-LABEL: void @f16_mul_assign(
108+
#[no_mangle]
109+
pub fn f16_mul_assign(a: &mut f16, b: f16) {
110+
// CHECK: fmul half %{{.+}}, %{{.+}}
111+
// CHECK-NEXT: store half %{{.+}}, ptr %{{.+}}
112+
*a *= b
113+
}
114+
115+
// CHECK-LABEL: void @f16_div_assign(
116+
#[no_mangle]
117+
pub fn f16_div_assign(a: &mut f16, b: f16) {
118+
// CHECK: fdiv half %{{.+}}, %{{.+}}
119+
// CHECK-NEXT: store half %{{.+}}, ptr %{{.+}}
120+
*a /= b
121+
}
122+
123+
// CHECK-LABEL: void @f16_rem_assign(
124+
#[no_mangle]
125+
pub fn f16_rem_assign(a: &mut f16, b: f16) {
126+
// CHECK: frem half %{{.+}}, %{{.+}}
127+
// CHECK-NEXT: store half %{{.+}}, ptr %{{.+}}
128+
*a %= b
129+
}

0 commit comments

Comments
 (0)