Skip to content

Use rounding instructions on aarch64 #903

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions etc/function-definitions.json
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@
},
"ceil": {
"sources": [
"libm/src/math/arch/aarch64.rs",
"libm/src/math/arch/i586.rs",
"libm/src/math/arch/wasm32.rs",
"libm/src/math/ceil.rs",
Expand All @@ -107,6 +108,7 @@
},
"ceilf": {
"sources": [
"libm/src/math/arch/aarch64.rs",
"libm/src/math/arch/wasm32.rs",
"libm/src/math/ceil.rs",
"libm/src/math/generic/ceil.rs"
Expand All @@ -122,6 +124,7 @@
},
"ceilf16": {
"sources": [
"libm/src/math/arch/aarch64.rs",
"libm/src/math/ceil.rs",
"libm/src/math/generic/ceil.rs"
],
Expand Down Expand Up @@ -311,6 +314,7 @@
},
"floor": {
"sources": [
"libm/src/math/arch/aarch64.rs",
"libm/src/math/arch/i586.rs",
"libm/src/math/arch/wasm32.rs",
"libm/src/math/floor.rs",
Expand All @@ -320,6 +324,7 @@
},
"floorf": {
"sources": [
"libm/src/math/arch/aarch64.rs",
"libm/src/math/arch/wasm32.rs",
"libm/src/math/floor.rs",
"libm/src/math/generic/floor.rs"
Expand All @@ -335,6 +340,7 @@
},
"floorf16": {
"sources": [
"libm/src/math/arch/aarch64.rs",
"libm/src/math/floor.rs",
"libm/src/math/generic/floor.rs"
],
Expand Down Expand Up @@ -815,19 +821,22 @@
},
"round": {
"sources": [
"libm/src/math/arch/aarch64.rs",
"libm/src/math/generic/round.rs",
"libm/src/math/round.rs"
],
"type": "f64"
},
"roundeven": {
"sources": [
"libm/src/math/arch/aarch64.rs",
"libm/src/math/roundeven.rs"
],
"type": "f64"
},
"roundevenf": {
"sources": [
"libm/src/math/arch/aarch64.rs",
"libm/src/math/roundeven.rs"
],
"type": "f32"
Expand All @@ -840,12 +849,14 @@
},
"roundevenf16": {
"sources": [
"libm/src/math/arch/aarch64.rs",
"libm/src/math/roundeven.rs"
],
"type": "f16"
},
"roundf": {
"sources": [
"libm/src/math/arch/aarch64.rs",
"libm/src/math/generic/round.rs",
"libm/src/math/round.rs"
],
Expand All @@ -860,6 +871,7 @@
},
"roundf16": {
"sources": [
"libm/src/math/arch/aarch64.rs",
"libm/src/math/generic/round.rs",
"libm/src/math/round.rs"
],
Expand Down Expand Up @@ -1002,6 +1014,7 @@
},
"trunc": {
"sources": [
"libm/src/math/arch/aarch64.rs",
"libm/src/math/arch/wasm32.rs",
"libm/src/math/generic/trunc.rs",
"libm/src/math/trunc.rs"
Expand All @@ -1010,6 +1023,7 @@
},
"truncf": {
"sources": [
"libm/src/math/arch/aarch64.rs",
"libm/src/math/arch/wasm32.rs",
"libm/src/math/generic/trunc.rs",
"libm/src/math/trunc.rs"
Expand All @@ -1025,6 +1039,7 @@
},
"truncf16": {
"sources": [
"libm/src/math/arch/aarch64.rs",
"libm/src/math/generic/trunc.rs",
"libm/src/math/trunc.rs"
],
Expand Down
198 changes: 187 additions & 11 deletions libm/src/math/arch/aarch64.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,156 @@ pub fn fmaf(mut x: f32, y: f32, z: f32) -> f32 {
x
}

pub fn ceil(mut x: f64) -> f64 {
// SAFETY: `frintp` is available with neon and has no side effects.
unsafe {
asm!(
"frintp {x:d}, {x:d}",
x = inout(vreg) x,
options(nomem, nostack, pure)
);
}
x
}

pub fn ceilf(mut x: f32) -> f32 {
// SAFETY: `frintp` is available with neon and has no side effects.
unsafe {
asm!(
"frintp {x:s}, {x:s}",
x = inout(vreg) x,
options(nomem, nostack, pure)
);
}
x
}

#[cfg(all(f16_enabled, target_feature = "fp16"))]
pub fn ceilf16(mut x: f16) -> f16 {
// SAFETY: `frintp` is available for `f16` with `fp16` (implies `neon`) and has no side effects.
unsafe {
asm!(
"frintp {x:h}, {x:h}",
x = inout(vreg) x,
options(nomem, nostack, pure)
);
}
x
}

pub fn floor(mut x: f64) -> f64 {
// SAFETY: `frintm` is available with neon and has no side effects.
unsafe {
asm!(
"frintm {x:d}, {x:d}",
x = inout(vreg) x,
options(nomem, nostack, pure)
);
}
x
}

pub fn floorf(mut x: f32) -> f32 {
// SAFETY: `frintm` is available with neon and has no side effects.
unsafe {
asm!(
"frintm {x:s}, {x:s}",
x = inout(vreg) x,
options(nomem, nostack, pure)
);
}
x
}

#[cfg(all(f16_enabled, target_feature = "fp16"))]
pub fn floorf16(mut x: f16) -> f16 {
// SAFETY: `frintm` is available for `f16` with `fp16` (implies `neon`) and has no side effects.
unsafe {
asm!(
"frintm {x:h}, {x:h}",
x = inout(vreg) x,
options(nomem, nostack, pure)
);
}
x
}

pub fn rint(mut x: f64) -> f64 {
// SAFETY: `frintx` is available with neon and has no side effects.
unsafe {
asm!(
"frintx {x:d}, {x:d}",
x = inout(vreg) x,
options(nomem, nostack, pure)
);
}
x
}

pub fn rintf(mut x: f32) -> f32 {
// SAFETY: `frintx` is available with neon and has no side effects.
unsafe {
asm!(
"frintx {x:s}, {x:s}",
x = inout(vreg) x,
options(nomem, nostack, pure)
);
}
x
}

#[cfg(all(f16_enabled, target_feature = "fp16"))]
pub fn rintf16(mut x: f16) -> f16 {
// SAFETY: `frintx` is available for `f16` with `fp16` (implies `neon`) and has no side effects.
unsafe {
asm!(
"frintx {x:h}, {x:h}",
x = inout(vreg) x,
options(nomem, nostack, pure)
);
}
x
}

pub fn round(mut x: f64) -> f64 {
// SAFETY: `frinta` is available with neon and has no side effects.
unsafe {
asm!(
"frinta {x:d}, {x:d}",
x = inout(vreg) x,
options(nomem, nostack, pure)
);
}
x
}

pub fn roundf(mut x: f32) -> f32 {
// SAFETY: `frinta` is available with neon and has no side effects.
unsafe {
asm!(
"frinta {x:s}, {x:s}",
x = inout(vreg) x,
options(nomem, nostack, pure)
);
}
x
}

#[cfg(all(f16_enabled, target_feature = "fp16"))]
pub fn roundf16(mut x: f16) -> f16 {
// SAFETY: `frinta` is available for `f16` with `fp16` (implies `neon`) and has no side effects.
unsafe {
asm!(
"frinta {x:h}, {x:h}",
x = inout(vreg) x,
options(nomem, nostack, pure)
);
}
x
}

pub fn roundeven(mut x: f64) -> f64 {
// SAFETY: `frintn` is available with neon and has no side effects.
//
// `frintn` is always round-to-nearest which does not match the C specification, but Rust does
// not support rounding modes.
unsafe {
asm!(
"frintn {x:d}, {x:d}",
Expand All @@ -45,11 +190,8 @@ pub fn rint(mut x: f64) -> f64 {
x
}

pub fn rintf(mut x: f32) -> f32 {
pub fn roundevenf(mut x: f32) -> f32 {
// SAFETY: `frintn` is available with neon and has no side effects.
//
// `frintn` is always round-to-nearest which does not match the C specification, but Rust does
// not support rounding modes.
unsafe {
asm!(
"frintn {x:s}, {x:s}",
Expand All @@ -61,11 +203,8 @@ pub fn rintf(mut x: f32) -> f32 {
}

#[cfg(all(f16_enabled, target_feature = "fp16"))]
pub fn rintf16(mut x: f16) -> f16 {
pub fn roundevenf16(mut x: f16) -> f16 {
// SAFETY: `frintn` is available for `f16` with `fp16` (implies `neon`) and has no side effects.
//
// `frintn` is always round-to-nearest which does not match the C specification, but Rust does
// not support rounding modes.
unsafe {
asm!(
"frintn {x:h}, {x:h}",
Expand All @@ -76,6 +215,43 @@ pub fn rintf16(mut x: f16) -> f16 {
x
}

pub fn trunc(mut x: f64) -> f64 {
// SAFETY: `frintz` is available with neon and has no side effects.
unsafe {
asm!(
"frintz {x:d}, {x:d}",
x = inout(vreg) x,
options(nomem, nostack, pure)
);
}
x
}

pub fn truncf(mut x: f32) -> f32 {
// SAFETY: `frintz` is available with neon and has no side effects.
unsafe {
asm!(
"frintz {x:s}, {x:s}",
x = inout(vreg) x,
options(nomem, nostack, pure)
);
}
x
}

#[cfg(all(f16_enabled, target_feature = "fp16"))]
pub fn truncf16(mut x: f16) -> f16 {
// SAFETY: `frintz` is available for `f16` with `fp16` (implies `neon`) and has no side effects.
unsafe {
asm!(
"frintz {x:h}, {x:h}",
x = inout(vreg) x,
options(nomem, nostack, pure)
);
}
x
}

pub fn sqrt(mut x: f64) -> f64 {
// SAFETY: `fsqrt` is available with neon and has no side effects.
unsafe {
Expand Down
15 changes: 15 additions & 0 deletions libm/src/math/arch/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,30 @@ cfg_if! {
pub use aarch64::{
fma,
fmaf,
ceil,
ceilf,
floor,
floorf,
round,
roundf,
rint,
rintf,
roundeven,
roundevenf,
trunc,
truncf,
sqrt,
sqrtf,
};

#[cfg(all(f16_enabled, target_feature = "fp16"))]
pub use aarch64::{
ceilf16,
floorf16,
roundf16,
rintf16,
roundevenf16,
truncf16,
sqrtf16,
};
}
Expand Down
Loading
Loading