mirror of
https://github.com/dlang/dmd.git
synced 2025-04-26 13:10:12 +03:00
[druntime] core.int128: Optimize new udivmod overload via inline asm on x86_64
This commit is contained in:
parent
3a661c1f8c
commit
6b7bbdd330
1 changed files with 39 additions and 1 deletions
|
@ -562,6 +562,12 @@ Cent udivmod(Cent c1, Cent c2, out Cent modulus)
|
||||||
return quotient;
|
return quotient;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
version (X86_64)
|
||||||
|
{
|
||||||
|
version (GNU) version = GNU_OR_LDC_X86_64;
|
||||||
|
version (LDC) version = GNU_OR_LDC_X86_64;
|
||||||
|
}
|
||||||
|
|
||||||
/****************************
|
/****************************
|
||||||
* Unsigned divide 128-bit c1 / 64-bit c2. The result must fit in 64 bits.
|
* Unsigned divide 128-bit c1 / 64-bit c2. The result must fit in 64 bits.
|
||||||
* The remainder after division is stored to modulus.
|
* The remainder after division is stored to modulus.
|
||||||
|
@ -577,6 +583,39 @@ U udivmod(Cent c1, U c2, out U modulus)
|
||||||
{
|
{
|
||||||
import core.bitop;
|
import core.bitop;
|
||||||
|
|
||||||
|
if (!__ctfe)
|
||||||
|
{
|
||||||
|
version (GNU_OR_LDC_X86_64)
|
||||||
|
{
|
||||||
|
U ret = void;
|
||||||
|
asm pure @trusted nothrow @nogc
|
||||||
|
{
|
||||||
|
"divq %4"
|
||||||
|
: "=a"(ret), "=d"(modulus)
|
||||||
|
: "a"(c1.lo), "d"(c1.hi), "r"(c2)
|
||||||
|
: "cc";
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
else version (D_InlineAsm_X86_64)
|
||||||
|
{
|
||||||
|
const lo = c1.lo;
|
||||||
|
const hi = c1.hi;
|
||||||
|
U mod = void;
|
||||||
|
U ret = void;
|
||||||
|
asm pure @trusted nothrow @nogc
|
||||||
|
{
|
||||||
|
mov RAX, lo;
|
||||||
|
mov RDX, hi;
|
||||||
|
div c2;
|
||||||
|
mov mod, RDX; // DMD bug: cannot use modulus directly
|
||||||
|
mov ret, RAX;
|
||||||
|
}
|
||||||
|
modulus = mod;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// We work in base 2^^32
|
// We work in base 2^^32
|
||||||
enum base = 1UL << 32;
|
enum base = 1UL << 32;
|
||||||
enum divmask = (1UL << (Ubits / 2)) - 1;
|
enum divmask = (1UL << (Ubits / 2)) - 1;
|
||||||
|
@ -918,7 +957,6 @@ unittest
|
||||||
assert(udiv(C10,C2) == C5);
|
assert(udiv(C10,C2) == C5);
|
||||||
assert(udivmod(C10,C2, modulus) == C5); assert(modulus == C0);
|
assert(udivmod(C10,C2, modulus) == C5); assert(modulus == C0);
|
||||||
assert(udivmod(C10,C3, modulus) == C3); assert(modulus == C1);
|
assert(udivmod(C10,C3, modulus) == C3); assert(modulus == C1);
|
||||||
assert(udivmod(C10,C0, modulus) == Cm1); assert(modulus == C0);
|
|
||||||
assert(udivmod(C2,C90_30, modulus) == C0); assert(modulus == C2);
|
assert(udivmod(C2,C90_30, modulus) == C0); assert(modulus == C2);
|
||||||
assert(udiv(mul(C90_30, C2), C2) == C90_30);
|
assert(udiv(mul(C90_30, C2), C2) == C90_30);
|
||||||
assert(udiv(mul(C90_30, C2), C90_30) == C2);
|
assert(udiv(mul(C90_30, C2), C90_30) == C2);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue