about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2023-03-07 09:43:12 +0000
committerbors <bors@rust-lang.org>2023-03-07 09:43:12 +0000
commit0a3b557d528dd7c8a88ceca6f7dc0699b89a3ef4 (patch)
treead02b3e1690da2f936e346d44840d552b97f9f1e /compiler
parent8f9e09ac3ef3fa85d23ad6a0c920d49987144b13 (diff)
parent371d57084d7c2e2dd9b4ac6b5bb9fcc8b0dacd1e (diff)
downloadrust-0a3b557d528dd7c8a88ceca6f7dc0699b89a3ef4.tar.gz
rust-0a3b557d528dd7c8a88ceca6f7dc0699b89a3ef4.zip
Auto merge of #95317 - Jules-Bertholet:round_ties_to_even, r=pnkfelix,m-ou-se,scottmcm
Add `round_ties_even` to `f32` and `f64`

Tracking issue: #96710

Redux of #82273. See also #55107

Adds a new method, `round_ties_even`, to `f32` and `f64`, that rounds the float to the nearest integer , rounding halfway cases to the number with an even least significant bit. Uses the `roundeven` LLVM intrinsic to do this.

Of the five IEEE 754 rounding modes, this is the only one that doesn't already have a round-to-integer function exposed by Rust (others are `round`, `floor`, `ceil`, and `trunc`).  Ties-to-even is also the rounding mode used for int-to-float and float-to-float `as` casts, as well as float arithmentic operations. So not having an explicit rounding method for it seems like an oversight.

Bikeshed: this PR currently uses `round_ties_even` for the name of the method. But maybe `round_ties_to_even` is better, or `round_even`, or `round_to_even`?
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs4
-rw-r--r--compiler/rustc_codegen_gcc/src/intrinsic/mod.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/context.rs4
-rw-r--r--compiler/rustc_codegen_llvm/src/intrinsic.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/check/intrinsic.rs2
-rw-r--r--compiler/rustc_span/src/symbol.rs2
6 files changed, 16 insertions, 0 deletions
diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
index e74aabf2fcb..24f8d5e464e 100644
--- a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
+++ b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
@@ -281,8 +281,12 @@ fn codegen_float_intrinsic_call<'tcx>(
         sym::ceilf64 => ("ceil", 1, fx.tcx.types.f64),
         sym::truncf32 => ("truncf", 1, fx.tcx.types.f32),
         sym::truncf64 => ("trunc", 1, fx.tcx.types.f64),
+        sym::rintf32 => ("rintf", 1, fx.tcx.types.f32),
+        sym::rintf64 => ("rint", 1, fx.tcx.types.f64),
         sym::roundf32 => ("roundf", 1, fx.tcx.types.f32),
         sym::roundf64 => ("round", 1, fx.tcx.types.f64),
+        sym::roundevenf32 => ("roundevenf", 1, fx.tcx.types.f32),
+        sym::roundevenf64 => ("roundeven", 1, fx.tcx.types.f64),
         sym::sinf32 => ("sinf", 1, fx.tcx.types.f32),
         sym::sinf64 => ("sin", 1, fx.tcx.types.f64),
         sym::cosf32 => ("cosf", 1, fx.tcx.types.f32),
diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs
index 49be6c649e6..35e650c65a0 100644
--- a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs
+++ b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs
@@ -68,6 +68,8 @@ fn get_simple_intrinsic<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, name: Symbol) ->
         sym::nearbyintf64 => "nearbyint",
         sym::roundf32 => "roundf",
         sym::roundf64 => "round",
+        sym::roundevenf32 => "roundevenf",
+        sym::roundevenf64 => "roundeven",
         sym::abort => "abort",
         _ => return None,
     };
diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs
index 3d29968d5d6..f0d729d4779 100644
--- a/compiler/rustc_codegen_llvm/src/context.rs
+++ b/compiler/rustc_codegen_llvm/src/context.rs
@@ -735,9 +735,13 @@ impl<'ll> CodegenCx<'ll, '_> {
 
         ifn!("llvm.copysign.f32", fn(t_f32, t_f32) -> t_f32);
         ifn!("llvm.copysign.f64", fn(t_f64, t_f64) -> t_f64);
+
         ifn!("llvm.round.f32", fn(t_f32) -> t_f32);
         ifn!("llvm.round.f64", fn(t_f64) -> t_f64);
 
+        ifn!("llvm.roundeven.f32", fn(t_f32) -> t_f32);
+        ifn!("llvm.roundeven.f64", fn(t_f64) -> t_f64);
+
         ifn!("llvm.rint.f32", fn(t_f32) -> t_f32);
         ifn!("llvm.rint.f64", fn(t_f64) -> t_f64);
         ifn!("llvm.nearbyint.f32", fn(t_f32) -> t_f32);
diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs
index 39afb4af6f6..9c921989ca9 100644
--- a/compiler/rustc_codegen_llvm/src/intrinsic.rs
+++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs
@@ -71,6 +71,8 @@ fn get_simple_intrinsic<'ll>(
         sym::roundf32 => "llvm.round.f32",
         sym::roundf64 => "llvm.round.f64",
         sym::ptr_mask => "llvm.ptrmask",
+        sym::roundevenf32 => "llvm.roundeven.f32",
+        sym::roundevenf64 => "llvm.roundeven.f64",
         _ => return None,
     };
     Some(cx.get_intrinsic(llvm_name))
diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
index 054284cced5..20b6561f8b2 100644
--- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs
+++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
@@ -300,6 +300,8 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
             sym::nearbyintf64 => (0, vec![tcx.types.f64], tcx.types.f64),
             sym::roundf32 => (0, vec![tcx.types.f32], tcx.types.f32),
             sym::roundf64 => (0, vec![tcx.types.f64], tcx.types.f64),
+            sym::roundevenf32 => (0, vec![tcx.types.f32], tcx.types.f32),
+            sym::roundevenf64 => (0, vec![tcx.types.f64], tcx.types.f64),
 
             sym::volatile_load | sym::unaligned_volatile_load => {
                 (1, vec![tcx.mk_imm_ptr(param(0))], param(0))
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 6272bf7f25e..4e626fd9f30 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -1197,6 +1197,8 @@ symbols! {
         rlib,
         rotate_left,
         rotate_right,
+        roundevenf32,
+        roundevenf64,
         roundf32,
         roundf64,
         rt,