Skip to content

Commit 8bb356c

Browse files
committed
Auto merge of #3977 - eduardosm:f16-f128, r=RalfJung
miri: improve support for `f16` and `f128` Rounding intrinsics are now implemented for `f16` and `f128` and tests for `is_infinite`, NaN, `abs`, `copysign`, `min`, `max`, rounding, `*_fast` and `*_algebraic` have been added.
2 parents f7ccac9 + d7e91ba commit 8bb356c

2 files changed

Lines changed: 181 additions & 9 deletions

File tree

‎src/tools/miri/src/intrinsics/mod.rs‎

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,21 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
145145
this.write_scalar(Scalar::from_bool(branch), dest)?;
146146
}
147147

148+
"floorf16" | "ceilf16" | "truncf16" | "roundf16" | "rintf16" => {
149+
let[f] = check_arg_count(args)?;
150+
let f = this.read_scalar(f)?.to_f16()?;
151+
let mode = match intrinsic_name {
152+
"floorf16" => Round::TowardNegative,
153+
"ceilf16" => Round::TowardPositive,
154+
"truncf16" => Round::TowardZero,
155+
"roundf16" => Round::NearestTiesToAway,
156+
"rintf16" => Round::NearestTiesToEven,
157+
_ => bug!(),
158+
};
159+
let res = f.round_to_integral(mode).value;
160+
let res = this.adjust_nan(res,&[f]);
161+
this.write_scalar(res, dest)?;
162+
}
148163
"floorf32" | "ceilf32" | "truncf32" | "roundf32" | "rintf32" => {
149164
let[f] = check_arg_count(args)?;
150165
let f = this.read_scalar(f)?.to_f32()?;
@@ -175,6 +190,21 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
175190
let res = this.adjust_nan(res,&[f]);
176191
this.write_scalar(res, dest)?;
177192
}
193+
"floorf128" | "ceilf128" | "truncf128" | "roundf128" | "rintf128" => {
194+
let[f] = check_arg_count(args)?;
195+
let f = this.read_scalar(f)?.to_f128()?;
196+
let mode = match intrinsic_name {
197+
"floorf128" => Round::TowardNegative,
198+
"ceilf128" => Round::TowardPositive,
199+
"truncf128" => Round::TowardZero,
200+
"roundf128" => Round::NearestTiesToAway,
201+
"rintf128" => Round::NearestTiesToEven,
202+
_ => bug!(),
203+
};
204+
let res = f.round_to_integral(mode).value;
205+
let res = this.adjust_nan(res,&[f]);
206+
this.write_scalar(res, dest)?;
207+
}
178208

179209
#[rustfmt::skip]
180210
| "sinf32"

‎src/tools/miri/tests/pass/float.rs‎

Lines changed: 151 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -157,13 +157,18 @@ fn basic() {
157157
assert_eq(-{5.0_f128}, -5.0_f128);
158158

159159
// infinities, NaN
160-
// FIXME(f16_f128): add when constants and `is_infinite` are available
160+
assert!((5.0_f16 / 0.0).is_infinite());
161+
assert_ne!({5.0_f16 / 0.0},{ -5.0_f16 / 0.0});
161162
assert!((5.0_f32 / 0.0).is_infinite());
162163
assert_ne!({5.0_f32 / 0.0},{ -5.0_f32 / 0.0});
163164
assert!((5.0_f64 / 0.0).is_infinite());
164165
assert_ne!({5.0_f64 / 0.0},{5.0_f64 / -0.0});
166+
assert!((5.0_f128 / 0.0).is_infinite());
167+
assert_ne!({5.0_f128 / 0.0},{5.0_f128 / -0.0});
168+
assert_ne!(f16::NAN, f16::NAN);
165169
assert_ne!(f32::NAN,f32::NAN);
166170
assert_ne!(f64::NAN,f64::NAN);
171+
assert_ne!(f128::NAN, f128::NAN);
167172

168173
// negative zero
169174
let posz = 0.0f16;
@@ -215,9 +220,14 @@ fn basic() {
215220
assert!((black_box(-1.0f128) % 1.0).is_sign_negative());
216221
assert!((black_box(-1.0f128) % -1.0).is_sign_negative());
217222

218-
// FIXME(f16_f128): add when `abs` is available
223+
assert_eq!((-1.0f16).abs(),1.0f16);
224+
assert_eq!(34.2f16.abs(),34.2f16);
219225
assert_eq!((-1.0f32).abs(),1.0f32);
226+
assert_eq!(34.2f32.abs(),34.2f32);
227+
assert_eq!((-1.0f64).abs(),1.0f64);
220228
assert_eq!(34.2f64.abs(),34.2f64);
229+
assert_eq!((-1.0f128).abs(),1.0f128);
230+
assert_eq!(34.2f128.abs(),34.2f128);
221231
}
222232

223233
/// Test casts from floats to ints and back
@@ -654,6 +664,14 @@ fn casts() {
654664
}
655665

656666
fnops(){
667+
// f16 min/max
668+
assert_eq((1.0_f16).max(-1.0),1.0);
669+
assert_eq((1.0_f16).min(-1.0), -1.0);
670+
assert_eq(f16::NAN.min(9.0),9.0);
671+
assert_eq(f16::NAN.max(-9.0), -9.0);
672+
assert_eq((9.0_f16).min(f16::NAN),9.0);
673+
assert_eq((-9.0_f16).max(f16::NAN), -9.0);
674+
657675
// f32 min/max
658676
assert_eq((1.0asf32).max(-1.0),1.0);
659677
assert_eq((1.0asf32).min(-1.0), -1.0);
@@ -670,6 +688,21 @@ fn ops() {
670688
assert_eq((9.0asf64).min(f64::NAN),9.0);
671689
assert_eq((-9.0asf64).max(f64::NAN), -9.0);
672690

691+
// f128 min/max
692+
assert_eq((1.0_f128).max(-1.0),1.0);
693+
assert_eq((1.0_f128).min(-1.0), -1.0);
694+
assert_eq(f128::NAN.min(9.0),9.0);
695+
assert_eq(f128::NAN.max(-9.0), -9.0);
696+
assert_eq((9.0_f128).min(f128::NAN),9.0);
697+
assert_eq((-9.0_f128).max(f128::NAN), -9.0);
698+
699+
// f16 copysign
700+
assert_eq(3.5_f16.copysign(0.42),3.5_f16);
701+
assert_eq(3.5_f16.copysign(-0.42), -3.5_f16);
702+
assert_eq((-3.5_f16).copysign(0.42),3.5_f16);
703+
assert_eq((-3.5_f16).copysign(-0.42), -3.5_f16);
704+
assert!(f16::NAN.copysign(1.0).is_nan());
705+
673706
// f32 copysign
674707
assert_eq(3.5_f32.copysign(0.42),3.5_f32);
675708
assert_eq(3.5_f32.copysign(-0.42), -3.5_f32);
@@ -683,6 +716,13 @@ fn ops() {
683716
assert_eq((-3.5_f64).copysign(0.42),3.5_f64);
684717
assert_eq((-3.5_f64).copysign(-0.42), -3.5_f64);
685718
assert!(f64::NAN.copysign(1.0).is_nan());
719+
720+
// f128 copysign
721+
assert_eq(3.5_f128.copysign(0.42),3.5_f128);
722+
assert_eq(3.5_f128.copysign(-0.42), -3.5_f128);
723+
assert_eq((-3.5_f128).copysign(0.42),3.5_f128);
724+
assert_eq((-3.5_f128).copysign(-0.42), -3.5_f128);
725+
assert!(f128::NAN.copysign(1.0).is_nan());
686726
}
687727

688728
/// Tests taken from rustc test suite.
@@ -807,6 +847,18 @@ fn nan_casts() {
807847

808848
fnrounding(){
809849
// Test cases taken from the library's tests for this feature
850+
// f16
851+
assert_eq(2.5f16.round_ties_even(),2.0f16);
852+
assert_eq(1.0f16.round_ties_even(),1.0f16);
853+
assert_eq(1.3f16.round_ties_even(),1.0f16);
854+
assert_eq(1.5f16.round_ties_even(),2.0f16);
855+
assert_eq(1.7f16.round_ties_even(),2.0f16);
856+
assert_eq(0.0f16.round_ties_even(),0.0f16);
857+
assert_eq((-0.0f16).round_ties_even(), -0.0f16);
858+
assert_eq((-1.0f16).round_ties_even(), -1.0f16);
859+
assert_eq((-1.3f16).round_ties_even(), -1.0f16);
860+
assert_eq((-1.5f16).round_ties_even(), -2.0f16);
861+
assert_eq((-1.7f16).round_ties_even(), -2.0f16);
810862
// f32
811863
assert_eq(2.5f32.round_ties_even(),2.0f32);
812864
assert_eq(1.0f32.round_ties_even(),1.0f32);
@@ -831,23 +883,59 @@ fn rounding() {
831883
assert_eq((-1.3f64).round_ties_even(), -1.0f64);
832884
assert_eq((-1.5f64).round_ties_even(), -2.0f64);
833885
assert_eq((-1.7f64).round_ties_even(), -2.0f64);
834-
886+
// f128
887+
assert_eq(2.5f128.round_ties_even(),2.0f128);
888+
assert_eq(1.0f128.round_ties_even(),1.0f128);
889+
assert_eq(1.3f128.round_ties_even(),1.0f128);
890+
assert_eq(1.5f128.round_ties_even(),2.0f128);
891+
assert_eq(1.7f128.round_ties_even(),2.0f128);
892+
assert_eq(0.0f128.round_ties_even(),0.0f128);
893+
assert_eq((-0.0f128).round_ties_even(), -0.0f128);
894+
assert_eq((-1.0f128).round_ties_even(), -1.0f128);
895+
assert_eq((-1.3f128).round_ties_even(), -1.0f128);
896+
assert_eq((-1.5f128).round_ties_even(), -2.0f128);
897+
assert_eq((-1.7f128).round_ties_even(), -2.0f128);
898+
899+
assert_eq!(3.8f16.floor(),3.0f16);
900+
assert_eq!((-1.1f16).floor(), -2.0f16);
835901
assert_eq!(3.8f32.floor(),3.0f32);
902+
assert_eq!((-1.1f32).floor(), -2.0f32);
903+
assert_eq!(3.8f64.floor(),3.0f64);
836904
assert_eq!((-1.1f64).floor(), -2.0f64);
905+
assert_eq!(3.8f128.floor(),3.0f128);
906+
assert_eq!((-1.1f128).floor(), -2.0f128);
837907

908+
assert_eq!(3.8f16.ceil(),4.0f16);
909+
assert_eq!((-2.3f16).ceil(), -2.0f16);
910+
assert_eq!(3.8f32.ceil(),4.0f32);
838911
assert_eq!((-2.3f32).ceil(), -2.0f32);
839912
assert_eq!(3.8f64.ceil(),4.0f64);
913+
assert_eq!((-2.3f64).ceil(), -2.0f64);
914+
assert_eq!(3.8f128.ceil(),4.0f128);
915+
assert_eq!((-2.3f128).ceil(), -2.0f128);
840916

917+
assert_eq!(0.1f16.trunc(),0.0f16);
918+
assert_eq!((-0.1f16).trunc(),0.0f16);
841919
assert_eq!(0.1f32.trunc(),0.0f32);
920+
assert_eq!((-0.1f32).trunc(),0.0f32);
921+
assert_eq!(0.1f64.trunc(),0.0f64);
842922
assert_eq!((-0.1f64).trunc(),0.0f64);
923+
assert_eq!(0.1f128.trunc(),0.0f128);
924+
assert_eq!((-0.1f128).trunc(),0.0f128);
843925

926+
assert_eq!(3.3_f16.round(),3.0);
927+
assert_eq!(2.5_f16.round(),3.0);
844928
assert_eq!(3.3_f32.round(),3.0);
845929
assert_eq!(2.5_f32.round(),3.0);
846930
assert_eq!(3.9_f64.round(),4.0);
847931
assert_eq!(2.5_f64.round(),3.0);
932+
assert_eq!(3.9_f128.round(),4.0);
933+
assert_eq!(2.5_f128.round(),3.0);
848934
}
849935

850936
fnmul_add(){
937+
// FIXME(f16_f128): add when supported
938+
851939
assert_eq!(3.0f32.mul_add(2.0f32,5.0f32),11.0);
852940
assert_eq!(0.0f32.mul_add(-2.0,f32::consts::E),f32::consts::E);
853941
assert_eq!(3.0f64.mul_add(2.0,5.0),11.0);
@@ -983,7 +1071,7 @@ fn test_fast() {
9831071
use std::intrinsics::{fadd_fast, fdiv_fast, fmul_fast, frem_fast, fsub_fast};
9841072

9851073
#[inline(never)]
986-
pubfntest_operations_f64(a:f64,b:f64){
1074+
pubfntest_operations_f16(a:f16,b:f16){
9871075
// make sure they all map to the correct operation
9881076
unsafe{
9891077
assert_eq!(fadd_fast(a, b), a + b);
@@ -1006,10 +1094,38 @@ fn test_fast() {
10061094
}
10071095
}
10081096

1009-
test_operations_f64(1.,2.);
1010-
test_operations_f64(10.,5.);
1097+
#[inline(never)]
1098+
pubfntest_operations_f64(a:f64,b:f64){
1099+
// make sure they all map to the correct operation
1100+
unsafe{
1101+
assert_eq!(fadd_fast(a, b), a + b);
1102+
assert_eq!(fsub_fast(a, b), a - b);
1103+
assert_eq!(fmul_fast(a, b), a * b);
1104+
assert_eq!(fdiv_fast(a, b), a / b);
1105+
assert_eq!(frem_fast(a, b), a % b);
1106+
}
1107+
}
1108+
1109+
#[inline(never)]
1110+
pubfntest_operations_f128(a:f128,b:f128){
1111+
// make sure they all map to the correct operation
1112+
unsafe{
1113+
assert_eq!(fadd_fast(a, b), a + b);
1114+
assert_eq!(fsub_fast(a, b), a - b);
1115+
assert_eq!(fmul_fast(a, b), a * b);
1116+
assert_eq!(fdiv_fast(a, b), a / b);
1117+
assert_eq!(frem_fast(a, b), a % b);
1118+
}
1119+
}
1120+
1121+
test_operations_f16(11.,2.);
1122+
test_operations_f16(10.,15.);
10111123
test_operations_f32(11.,2.);
10121124
test_operations_f32(10.,15.);
1125+
test_operations_f64(1.,2.);
1126+
test_operations_f64(10.,5.);
1127+
test_operations_f128(1.,2.);
1128+
test_operations_f128(10.,5.);
10131129
}
10141130

10151131
fntest_algebraic(){
@@ -1018,7 +1134,7 @@ fn test_algebraic() {
10181134
};
10191135

10201136
#[inline(never)]
1021-
pubfntest_operations_f64(a:f64,b:f64){
1137+
pubfntest_operations_f16(a:f16,b:f16){
10221138
// make sure they all map to the correct operation
10231139
assert_eq!(fadd_algebraic(a, b), a + b);
10241140
assert_eq!(fsub_algebraic(a, b), a - b);
@@ -1037,15 +1153,41 @@ fn test_algebraic() {
10371153
assert_eq!(frem_algebraic(a, b), a % b);
10381154
}
10391155

1040-
test_operations_f64(1.,2.);
1041-
test_operations_f64(10.,5.);
1156+
#[inline(never)]
1157+
pubfntest_operations_f64(a:f64,b:f64){
1158+
// make sure they all map to the correct operation
1159+
assert_eq!(fadd_algebraic(a, b), a + b);
1160+
assert_eq!(fsub_algebraic(a, b), a - b);
1161+
assert_eq!(fmul_algebraic(a, b), a * b);
1162+
assert_eq!(fdiv_algebraic(a, b), a / b);
1163+
assert_eq!(frem_algebraic(a, b), a % b);
1164+
}
1165+
1166+
#[inline(never)]
1167+
pubfntest_operations_f128(a:f128,b:f128){
1168+
// make sure they all map to the correct operation
1169+
assert_eq!(fadd_algebraic(a, b), a + b);
1170+
assert_eq!(fsub_algebraic(a, b), a - b);
1171+
assert_eq!(fmul_algebraic(a, b), a * b);
1172+
assert_eq!(fdiv_algebraic(a, b), a / b);
1173+
assert_eq!(frem_algebraic(a, b), a % b);
1174+
}
1175+
1176+
test_operations_f16(11.,2.);
1177+
test_operations_f16(10.,15.);
10421178
test_operations_f32(11.,2.);
10431179
test_operations_f32(10.,15.);
1180+
test_operations_f64(1.,2.);
1181+
test_operations_f64(10.,5.);
1182+
test_operations_f128(1.,2.);
1183+
test_operations_f128(10.,5.);
10441184
}
10451185

10461186
fntest_fmuladd(){
10471187
use std::intrinsics::{fmuladdf32, fmuladdf64};
10481188

1189+
// FIXME(f16_f128): add when supported
1190+
10491191
#[inline(never)]
10501192
pubfntest_operations_f32(a:f32,b:f32,c:f32){
10511193
assert_approx_eq!(unsafe{ fmuladdf32(a, b, c)}, a * b + c);

0 commit comments

Comments
 (0)