Skip to content

Commit 3ff194f

Browse files
committed
libm: Replace div! with unchecked_div_*
`div!` looks innocuous but is actually unsafe. Replace it with function calls that require us to actually use `unsafe`, and add the precondition notes. These can likely be removed completely in the near future. There is one case in `rem_pio2_large` and one in `exp2` where preconditions aren't as easy to define, but fortunately it seems like we are able to just use regular division there without affecting codegen.
1 parent 6015b65 commit 3ff194f

File tree

7 files changed

+44
-23
lines changed

7 files changed

+44
-23
lines changed

libm/src/math/exp2.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -380,7 +380,7 @@ pub fn exp2(mut x: f64) -> f64 {
380380
let mut i0 = ui as u32;
381381
i0 = i0.wrapping_add(TBLSIZE as u32 / 2);
382382
let ku = i0 / TBLSIZE as u32 * TBLSIZE as u32;
383-
let ki = div!(ku as i32, TBLSIZE as i32);
383+
let ki = (ku as i32) / TBLSIZE as i32;
384384
i0 %= TBLSIZE as u32;
385385
let uf = f64::from_bits(ui) - redux;
386386
let mut z = x - uf;

libm/src/math/lgamma_r.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@
7979
*/
8080

8181
use super::{floor, k_cos, k_sin, log};
82+
use crate::support::unchecked_div_i32;
8283

8384
const PI: f64 = 3.14159265358979311600e+00; /* 0x400921FB, 0x54442D18 */
8485
const A0: f64 = 7.72156649015328655494e-02; /* 0x3FB3C467, 0xE37DB0C8 */
@@ -152,7 +153,8 @@ fn sin_pi(mut x: f64) -> f64 {
152153
x = 2.0 * (x * 0.5 - floor(x * 0.5)); /* x mod 2.0 */
153154

154155
n = (x * 4.0) as i32;
155-
n = div!(n + 1, 2);
156+
// SAFETY: nonzero divisor, nonnegative dividend (`n < 8`).
157+
n = unsafe { unchecked_div_i32(n + 1, 2) };
156158
x -= (n as f64) * 0.5;
157159
x *= PI;
158160

libm/src/math/lgammaf_r.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
*/
1515

1616
use super::{floorf, k_cosf, k_sinf, logf};
17+
use crate::support::unchecked_div_isize;
1718

1819
const PI: f32 = 3.1415927410e+00; /* 0x40490fdb */
1920
const A0: f32 = 7.7215664089e-02; /* 0x3d9e233f */
@@ -88,7 +89,8 @@ fn sin_pi(mut x: f32) -> f32 {
8889
x = 2.0 * (x * 0.5 - floorf(x * 0.5)); /* x mod 2.0 */
8990

9091
n = (x * 4.0) as isize;
91-
n = div!(n + 1, 2);
92+
// SAFETY: nonzero divisor, nonnegative dividend (`n < 8`).
93+
n = unsafe { unchecked_div_isize(n + 1, 2) };
9294
y = (x as f64) - (n as f64) * 0.5;
9395
y *= 3.14159265358979323846;
9496
match n {

libm/src/math/mod.rs

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -58,24 +58,6 @@ macro_rules! i {
5858
};
5959
}
6060

61-
// Temporary macro to avoid panic codegen for division (in debug mode too). At
62-
// the time of this writing this is only used in a few places, and once
63-
// rust-lang/rust#72751 is fixed then this macro will no longer be necessary and
64-
// the native `/` operator can be used and panics won't be codegen'd.
65-
#[cfg(any(debug_assertions, not(intrinsics_enabled)))]
66-
macro_rules! div {
67-
($a:expr, $b:expr) => {
68-
$a / $b
69-
};
70-
}
71-
72-
#[cfg(all(not(debug_assertions), intrinsics_enabled))]
73-
macro_rules! div {
74-
($a:expr, $b:expr) => {
75-
unsafe { core::intrinsics::unchecked_div($a, $b) }
76-
};
77-
}
78-
7961
// `support` may be public for testing
8062
#[macro_use]
8163
#[cfg(feature = "unstable-public-internals")]

libm/src/math/rem_pio2_large.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,7 @@ pub(crate) fn rem_pio2_large(x: &[f64], y: &mut [f64], e0: i32, prec: usize) ->
255255

256256
/* determine jx,jv,q0, note that 3>q0 */
257257
let jx = nx - 1;
258-
let mut jv = div!(e0 - 3, 24);
258+
let mut jv = (e0 - 3) / 24;
259259
if jv < 0 {
260260
jv = 0;
261261
}

libm/src/math/support/mod.rs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,3 +37,36 @@ pub fn cold_path() {
3737
#[cfg(intrinsics_enabled)]
3838
core::hint::cold_path();
3939
}
40+
41+
/// # Safety
42+
///
43+
/// `y` must not be zero and the result must not overflow (`x > i32::MIN`).
44+
pub unsafe fn unchecked_div_i32(x: i32, y: i32) -> i32 {
45+
cfg_if! {
46+
if #[cfg(all(not(debug_assertions), intrinsics_enabled))] {
47+
// Temporary macro to avoid panic codegen for division (in debug mode too). At
48+
// the time of this writing this is only used in a few places, and once
49+
// rust-lang/rust#72751 is fixed then this macro will no longer be necessary and
50+
// the native `/` operator can be used and panics won't be codegen'd.
51+
//
52+
// Note: I am not sure whether the above comment is still up to date, we need
53+
// to double check whether panics are elided where we use this.
54+
unsafe { core::intrinsics::unchecked_div(x, y) }
55+
} else {
56+
x / y
57+
}
58+
}
59+
}
60+
61+
/// # Safety
62+
///
63+
/// `y` must not be zero and the result must not overflow (`x > isize::MIN`).
64+
pub unsafe fn unchecked_div_isize(x: isize, y: isize) -> isize {
65+
cfg_if! {
66+
if #[cfg(all(not(debug_assertions), intrinsics_enabled))] {
67+
unsafe { core::intrinsics::unchecked_div(x, y) }
68+
} else {
69+
x / y
70+
}
71+
}
72+
}

libm/src/math/tgamma.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ Gamma(x)*Gamma(-x) = -pi/(x sin(pi x))
2323
most ideas and constants are from boost and python
2424
*/
2525
use super::{exp, floor, k_cos, k_sin, pow};
26+
use crate::support::unchecked_div_isize;
2627

2728
const PI: f64 = 3.141592653589793238462643383279502884;
2829

@@ -37,7 +38,8 @@ fn sinpi(mut x: f64) -> f64 {
3738

3839
/* reduce x into [-.25,.25] */
3940
n = (4.0 * x) as isize;
40-
n = div!(n + 1, 2);
41+
// SAFETY: nonzero divisor, nonnegative dividend (`n < 8`).
42+
n = unsafe { unchecked_div_isize(n + 1, 2) };
4143
x -= (n as f64) * 0.5;
4244

4345
x *= PI;

0 commit comments

Comments
 (0)