Skip to content

Commit

Permalink
Use inline assembly
Browse files Browse the repository at this point in the history
  • Loading branch information
tustvold committed Aug 9, 2023
1 parent 5c978a3 commit a37aee3
Showing 1 changed file with 25 additions and 5 deletions.
30 changes: 25 additions & 5 deletions arrow-buffer/src/bigint/div.rs
Original file line number Diff line number Diff line change
Expand Up @@ -139,11 +139,31 @@ fn div_rem_knuth<const N: usize>(
}

/// Divide a u128 by a u64 divisor, returning the quotient and remainder
fn div_rem_word(hi: u64, lo: u64, y: u64) -> (u64, u64) {
debug_assert!(hi < y);
let x = (u128::from(hi) << 64) + u128::from(lo);
let y = u128::from(y);
((x / y) as u64, (x % y) as u64)
fn div_rem_word(hi: u64, lo: u64, divisor: u64) -> (u64, u64) {
debug_assert!(hi < divisor);
debug_assert_ne!(divisor, 0);

// LLVM fails to use the div instruction as it is not able to prove
// that hi < divisor, and therefore the result will fit into 64-bits
#[cfg(target_arch = "x86_64")]
unsafe {
let mut quot = lo;
let mut rem = hi;
std::arch::asm!(
"div {divisor}",
divisor = in(reg) divisor,
inout("rax") quot,
inout("rdx") rem,
options(pure, nomem, nostack)
);
(quot, rem)
}
#[cfg(not(target_arch = "x86_64"))]
{
let x = (u128::from(hi) << 64) + u128::from(lo);
let y = u128::from(y);
((x / y) as u64, (x % y) as u64)
}
}

/// Perform `a += b`
Expand Down

0 comments on commit a37aee3

Please sign in to comment.