Module compiler_builtins::int::specialized_div_rem
source · Expand description
This specialized_div_rem
module is originally from version 1.0.0 of the
specialized-div-rem
crate. Note that for
loops with ranges are not used in this
module, since unoptimized compilation may generate references to memcpy
.
The purpose of these macros is to easily change the both the division algorithm used for a given integer size and the half division used by that algorithm. The way functions call each other is also constructed such that linkers will find the chain of software and hardware divisions needed for every size of signed and unsigned division. For example, most target compilations do the following:
- Many 128 bit division functions like
u128::wrapping_div
usestd::intrinsics::unchecked_div
, which gets replaced by__udivti3
because there is not a 128 bit by 128 bit hardware division function in most architectures.__udivti3
usesu128_div_rem
(this extra level of function calls exists because__umodti3
and__udivmodti4
also exist, andspecialized_div_rem
supplies just one function to calculate both the quotient and remainder. If configuration flags enable it,impl_trifecta!
definesu128_div_rem
to use the trifecta algorithm, which requires the half sized divisionu64_by_u64_div_rem
. If the architecture supplies a 64 bit hardware division instruction,u64_by_u64_div_rem
will be reduced to those instructions. Note that we do not specify the half size division directly to be__udivdi3
, because hardware division would never be introduced. - If the architecture does not supply a 64 bit hardware division instruction, u64
divisions will use functions such as
__udivdi3
. This will callu64_div_rem
which is defined byimpl_delegate!
. The half division for this algorithm isu32_by_u32_div_rem
which in turn becomes hardware division instructions or more software division algorithms. - If the architecture does not supply a 32 bit hardware instruction, linkers will
look for
__udivsi3
.impl_binary_long!
is used, but this algorithm uses no half division, so the chain of calls ends here.
On some architectures like x86_64, an asymmetrically sized division is supplied, in
which 128 bit numbers can be divided by 64 bit numbers. impl_asymmetric!
is used to
extend the 128 by 64 bit division to a full 128 by 128 bit division.
Modules
Constants
- USE_LZ 🔒
Functions
- Divides
duo
bydiv
and returns a tuple of the quotient and the remainder.checked_div
andchecked_rem
are used to avoid bringing in panic function dependencies. - Computes the quotient and remainder of
duo
divided bydiv
and returns them as a tuple. - Finds the shift left that the divisor
div
would need to be normalized for a binary long division step with the dividendduo
. NOTE: This function assumes that these edge cases have been handled before reaching it:if div == 0 { panic!("attempt to divide by zero") } if duo < div { return (0, duo) }
- Divides
duo
bydiv
and returns a tuple of the quotient and the remainder.checked_div
andchecked_rem
are used to avoid bringing in panic function dependencies. - Computes the quotient and remainder of
duo
divided bydiv
and returns them as a tuple. - Finds the shift left that the divisor
div
would need to be normalized for a binary long division step with the dividendduo
. NOTE: This function assumes that these edge cases have been handled before reaching it:if div == 0 { panic!("attempt to divide by zero") } if duo < div { return (0, duo) }
- Divides
duo
bydiv
and returns a tuple of the quotient and the remainder. - Computes the quotient and remainder of
duo
divided bydiv
and returns them as a tuple. - The behavior of all divisions by zero is controlled by this function. This function should be impossible to reach by Rust users, unless
compiler-builtins
public division functions orcore/std::unchecked_div/rem
are directly used without a zero check in front.