Skip to content

Commit 20c567c

Browse files
committed
replace old soft division code with new functions
1 parent 6c6304d commit 20c567c

File tree

2 files changed

+40
-76
lines changed

2 files changed

+40
-76
lines changed

src/int/sdiv.rs

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -57,55 +57,63 @@ trait Divmod: Int {
5757

5858
impl Divmod for i32 {}
5959
impl Divmod for i64 {}
60+
// NOTE: there are aborts inside the specialized_div_rem functions if division by 0
61+
// is encountered, however these should be unreachable and optimized away unless
62+
// uses of `std/core::intrinsics::unchecked_div/rem` do not have a 0 check in front
63+
// of them.
6064

6165
intrinsics! {
6266
#[maybe_use_optimized_c_shim]
6367
#[arm_aeabi_alias = __aeabi_idiv]
6468
/// Returns `n / d`
6569
pub extern "C" fn __divsi3(a: i32, b: i32) -> i32 {
66-
a.div(b)
70+
i32_div_rem(a, b).0
6771
}
6872

6973
#[maybe_use_optimized_c_shim]
7074
/// Returns `n % d`
7175
pub extern "C" fn __modsi3(a: i32, b: i32) -> i32 {
72-
a.mod_(b)
76+
i32_div_rem(a, b).1
7377
}
74-
78+
7579
#[maybe_use_optimized_c_shim]
7680
/// Returns `n / d` and sets `*rem = n % d`
7781
pub extern "C" fn __divmodsi4(a: i32, b: i32, rem: &mut i32) -> i32 {
78-
a.divmod(b, rem, |a, b| __divsi3(a, b))
82+
let quo_rem = i32_div_rem(a, b);
83+
*rem = quo_rem.1;
84+
quo_rem.0
7985
}
8086

8187
#[maybe_use_optimized_c_shim]
8288
/// Returns `n / d`
8389
pub extern "C" fn __divdi3(a: i64, b: i64) -> i64 {
84-
a.div(b)
90+
i64_div_rem(a, b).0
8591
}
8692

8793
#[maybe_use_optimized_c_shim]
8894
/// Returns `n % d`
8995
pub extern "C" fn __moddi3(a: i64, b: i64) -> i64 {
90-
a.mod_(b)
96+
i64_div_rem(a, b).1
9197
}
9298

9399
#[aapcs_on_arm]
94100
/// Returns `n / d` and sets `*rem = n % d`
95101
pub extern "C" fn __divmoddi4(a: i64, b: i64, rem: &mut i64) -> i64 {
96-
a.divmod(b, rem, |a, b| __divdi3(a, b))
102+
let quo_rem = i64_div_rem(a, b);
103+
*rem = quo_rem.1;
104+
quo_rem.0
97105
}
98106

99107
#[win64_128bit_abi_hack]
100108
/// Returns `n / d`
101109
pub extern "C" fn __divti3(a: i128, b: i128) -> i128 {
102-
a.div(b)
110+
i128_div_rem(a, b).0
103111
}
104112

105113
#[win64_128bit_abi_hack]
106114
/// Returns `n % d`
107115
pub extern "C" fn __modti3(a: i128, b: i128) -> i128 {
108-
a.mod_(b)
116+
i128_div_rem(a, b).1
109117
}
110118

111119
// there is no `__divmodti4`

src/int/udiv.rs

Lines changed: 23 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -151,119 +151,75 @@ macro_rules! udivmod_inner {
151151
(q << 1) | carry as $ty
152152
}}
153153
}
154+
// NOTE: there are aborts inside the specialized_div_rem functions if division by 0
155+
// is encountered, however these should be unreachable and optimized away unless
156+
// uses of `std/core::intrinsics::unchecked_div/rem` do not have a 0 check in front
157+
// of them.
154158

155159
intrinsics! {
156160
#[maybe_use_optimized_c_shim]
157161
#[arm_aeabi_alias = __aeabi_uidiv]
158162
/// Returns `n / d`
159163
pub extern "C" fn __udivsi3(n: u32, d: u32) -> u32 {
160-
// Special cases
161-
if d == 0 {
162-
// NOTE This should be unreachable in safe Rust because the program will panic before
163-
// this intrinsic is called
164-
::abort();
165-
}
166-
167-
if n == 0 {
168-
return 0;
169-
}
170-
171-
let mut sr = d.leading_zeros().wrapping_sub(n.leading_zeros());
172-
173-
// d > n
174-
if sr > u32::BITS - 1 {
175-
return 0;
176-
}
177-
178-
// d == 1
179-
if sr == u32::BITS - 1 {
180-
return n;
181-
}
182-
183-
sr += 1;
184-
185-
// 1 <= sr <= u32::BITS - 1
186-
let mut q = n << (u32::BITS - sr);
187-
let mut r = n >> sr;
188-
189-
let mut carry = 0;
190-
191-
// Don't use a range because they may generate references to memcpy in unoptimized code
192-
let mut i = 0;
193-
while i < sr {
194-
i += 1;
195-
196-
// r:q = ((r:q) << 1) | carry
197-
r = (r << 1) | (q >> (u32::BITS - 1));
198-
q = (q << 1) | carry;
199-
200-
// carry = 0;
201-
// if r > d {
202-
// r -= d;
203-
// carry = 1;
204-
// }
205-
206-
let s = (d.wrapping_sub(r).wrapping_sub(1)) as i32 >> (u32::BITS - 1);
207-
carry = (s & 1) as u32;
208-
r -= d & s as u32;
209-
}
210-
211-
(q << 1) | carry
164+
u32_div_rem(n, d).0
212165
}
213166

214167
#[maybe_use_optimized_c_shim]
215168
/// Returns `n % d`
216169
pub extern "C" fn __umodsi3(n: u32, d: u32) -> u32 {
217-
let q = __udivsi3(n, d);
218-
n - q * d
170+
u32_div_rem(n, d).1
219171
}
220172

221173
#[maybe_use_optimized_c_shim]
222174
/// Returns `n / d` and sets `*rem = n % d`
223175
pub extern "C" fn __udivmodsi4(n: u32, d: u32, rem: Option<&mut u32>) -> u32 {
224-
let q = __udivsi3(n, d);
176+
let quo_rem = u32_div_rem(n, d);
225177
if let Some(rem) = rem {
226-
*rem = n - (q * d);
178+
*rem = quo_rem.1;
227179
}
228-
q
180+
quo_rem.0
229181
}
230182

231183
#[maybe_use_optimized_c_shim]
232184
/// Returns `n / d`
233185
pub extern "C" fn __udivdi3(n: u64, d: u64) -> u64 {
234-
__udivmoddi4(n, d, None)
186+
u64_div_rem(n, d).0
235187
}
236188

237189
#[maybe_use_optimized_c_shim]
238190
/// Returns `n % d`
239191
pub extern "C" fn __umoddi3(n: u64, d: u64) -> u64 {
240-
let mut rem = 0;
241-
__udivmoddi4(n, d, Some(&mut rem));
242-
rem
192+
u64_div_rem(n, d).1
243193
}
244194

245195
/// Returns `n / d` and sets `*rem = n % d`
246196
pub extern "C" fn __udivmoddi4(n: u64, d: u64, rem: Option<&mut u64>) -> u64 {
247-
udivmod_inner!(n, d, rem, u64)
197+
let quo_rem = u64_div_rem(n, d);
198+
if let Some(rem) = rem {
199+
*rem = quo_rem.1;
200+
}
201+
quo_rem.0
248202
}
249203

250204
#[win64_128bit_abi_hack]
251205
/// Returns `n / d`
252206
pub extern "C" fn __udivti3(n: u128, d: u128) -> u128 {
253-
__udivmodti4(n, d, None)
207+
u128_div_rem(n, d).0
254208
}
255209

256210
#[win64_128bit_abi_hack]
257211
/// Returns `n % d`
258212
pub extern "C" fn __umodti3(n: u128, d: u128) -> u128 {
259-
let mut rem = 0;
260-
__udivmodti4(n, d, Some(&mut rem));
261-
rem
213+
u128_div_rem(n, d).1
262214
}
263215

264216
#[win64_128bit_abi_hack]
265217
/// Returns `n / d` and sets `*rem = n % d`
266218
pub extern "C" fn __udivmodti4(n: u128, d: u128, rem: Option<&mut u128>) -> u128 {
267-
udivmod_inner!(n, d, rem, u128)
219+
let quo_rem = u128_div_rem(n, d);
220+
if let Some(rem) = rem {
221+
*rem = quo_rem.1;
222+
}
223+
quo_rem.0
268224
}
269225
}

0 commit comments

Comments
 (0)