Skip to content

Commit ed984e4

Browse files
committed
core: Add ARM64 FJCVTZS instruction optimization for f64 to i32
1 parent 7ab3548 commit ed984e4

File tree

1 file changed

+40
-0
lines changed

1 file changed

+40
-0
lines changed

core/src/ecma_conversions.rs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,49 @@ pub fn f64_to_wrapping_u32(n: f64) -> u32 {
4040
/// Converts an `f64` to an `i32` with ECMAScript `ToInt32` wrapping behavior.
4141
/// The value will be wrapped in the range [-2^31, 2^31).
4242
pub fn f64_to_wrapping_i32(n: f64) -> i32 {
43+
// TODO: use core intrinsic when https://github.com/rust-lang/rust/issues/147555 is stabilized.
44+
#[cfg(target_arch = "aarch64")]
45+
{
46+
#[cfg(target_feature = "jsconv")]
47+
unsafe {
48+
f64_to_wrapping_int32_aarch64(n)
49+
}
50+
#[cfg(not(target_feature = "jsconv"))]
51+
if std::arch::is_aarch64_feature_detected!("jsconv") {
52+
unsafe { f64_to_wrapping_int32_aarch64(n) }
53+
} else {
54+
f64_to_wrapping_i32_generic(n)
55+
}
56+
}
57+
#[cfg(not(target_arch = "aarch64"))]
58+
f64_to_wrapping_i32_generic(n)
59+
}
60+
61+
#[allow(unused)]
62+
fn f64_to_wrapping_i32_generic(n: f64) -> i32 {
4363
f64_to_wrapping_u32(n) as i32
4464
}
4565

66+
#[allow(unused)]
67+
#[cfg(target_arch = "aarch64")]
68+
#[target_feature(enable = "jsconv")]
69+
/// Converts an `f64` to an `i32` with ECMAScript `ToInt32` wrapping behavior.
70+
/// The value will be wrapped in the range [-2^31, 2^31).
71+
/// Optimized for aarch64 cpu with the fjcvtzs instruction.
72+
unsafe fn f64_to_wrapping_int32_aarch64(number: f64) -> i32 {
73+
let ret: i32;
74+
// SAFETY: fjcvtzs instruction is available under jsconv feature.
75+
unsafe {
76+
std::arch::asm!(
77+
"fjcvtzs {dst:w}, {src:d}",
78+
src = in(vreg) number,
79+
dst = out(reg) ret,
80+
options(nostack, nomem, pure)
81+
);
82+
}
83+
ret
84+
}
85+
4686
/// Implements the IEEE-754 "Round to nearest, ties to even" rounding rule.
4787
/// (e.g., both 1.5 and 2.5 will round to 2).
4888
/// This also clamps out-of-range values and NaN to `i32::MIN`.

0 commit comments

Comments
 (0)