From 221288789d47216dbf35415ed91ab3416cff4ff9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCnther=20Brammer?= Date: Mon, 28 Aug 2023 00:44:00 +0200 Subject: [PATCH] Return f32 and f64 in XMM0 instead of FP0 on i686 Rust calling convention i686 already uses SSE to do calculations with f32 and f64, but the C calling convention uses the x87 stack to return values. The Rust calling convention does not need to do this, and LLVM makes it easy to use XMM0 instead, which saves move instructions and fixes problems with NaN values. --- compiler/rustc_ty_utils/src/abi.rs | 5 +++++ library/std/src/f32/tests.rs | 7 ------- library/std/src/f64/tests.rs | 7 ------- 3 files changed, 5 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs index 16183403d67aa..6806baf4a1d26 100644 --- a/compiler/rustc_ty_utils/src/abi.rs +++ b/compiler/rustc_ty_utils/src/abi.rs @@ -371,6 +371,7 @@ fn fn_abi_new_uncached<'tcx>( let target = &cx.tcx.sess.target; let target_env_gnu_like = matches!(&target.env[..], "gnu" | "musl" | "uclibc"); let win_x64_gnu = target.os == "windows" && target.arch == "x86_64" && target.env == "gnu"; + let x86_32 = target.arch == "x86"; let linux_s390x_gnu_like = target.os == "linux" && target.arch == "s390x" && target_env_gnu_like; let linux_sparc64_gnu_like = @@ -415,6 +416,10 @@ fn fn_abi_new_uncached<'tcx>( is_return, drop_target_pointee, ); + // Use SSE instead of x87 registers for return values when available + if x86_32 && rust_abi && is_return && matches!(scalar.primitive(), F32 | F64) { + attrs.set(ArgAttribute::InReg); + } attrs }); diff --git a/library/std/src/f32/tests.rs b/library/std/src/f32/tests.rs index 9ca4e8f2f45fe..cf6ea80eab719 100644 --- a/library/std/src/f32/tests.rs +++ b/library/std/src/f32/tests.rs @@ -315,7 +315,6 @@ fn test_is_sign_negative() { assert!((-f32::NAN).is_sign_negative()); } -#[allow(unused_macros)] macro_rules! assert_f32_biteq { ($left : expr, $right : expr) => { let l: &f32 = &$left; @@ -326,9 +325,6 @@ macro_rules! assert_f32_biteq { }; } -// Ignore test on x87 floating point, these platforms do not guarantee NaN -// payloads are preserved and flush denormals to zero, failing the tests. -#[cfg(not(target_arch = "x86"))] #[test] fn test_next_up() { let tiny = f32::from_bits(1); @@ -359,9 +355,6 @@ fn test_next_up() { assert_f32_biteq!(nan2.next_up(), nan2); } -// Ignore test on x87 floating point, these platforms do not guarantee NaN -// payloads are preserved and flush denormals to zero, failing the tests. -#[cfg(not(target_arch = "x86"))] #[test] fn test_next_down() { let tiny = f32::from_bits(1); diff --git a/library/std/src/f64/tests.rs b/library/std/src/f64/tests.rs index f88d01593b5e4..6c86df1637acd 100644 --- a/library/std/src/f64/tests.rs +++ b/library/std/src/f64/tests.rs @@ -305,7 +305,6 @@ fn test_is_sign_negative() { assert!((-f64::NAN).is_sign_negative()); } -#[allow(unused_macros)] macro_rules! assert_f64_biteq { ($left : expr, $right : expr) => { let l: &f64 = &$left; @@ -316,9 +315,6 @@ macro_rules! assert_f64_biteq { }; } -// Ignore test on x87 floating point, these platforms do not guarantee NaN -// payloads are preserved and flush denormals to zero, failing the tests. -#[cfg(not(target_arch = "x86"))] #[test] fn test_next_up() { let tiny = f64::from_bits(1); @@ -348,9 +344,6 @@ fn test_next_up() { assert_f64_biteq!(nan2.next_up(), nan2); } -// Ignore test on x87 floating point, these platforms do not guarantee NaN -// payloads are preserved and flush denormals to zero, failing the tests. -#[cfg(not(target_arch = "x86"))] #[test] fn test_next_down() { let tiny = f64::from_bits(1);