Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .circleci/run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

set -uexo pipefail

HOST_DMD_VER=2.072.2 # same as in dmd/src/posix.mak
HOST_DMD_VER=2.074.1 # same as in dmd/src/posix.mak
CURL_USER_AGENT="CirleCI $(curl --version | head -n 1)"
N=4
CIRCLE_NODE_INDEX=${CIRCLE_NODE_INDEX:-0}
Expand Down
9 changes: 5 additions & 4 deletions src/dmd/backend/cod2.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <time.h>
#include "cc.h"
#include "oper.h"
Expand All @@ -32,8 +33,8 @@ int cdcmp_flag;
extern signed char regtorm[8];

// from divcoeff.c
extern bool choose_multiplier(int N, targ_ullong d, int prec, targ_ullong *pm, int *pshpost);
extern bool udiv_coefficients(int N, targ_ullong d, int *pshpre, targ_ullong *pm, int *pshpost);
extern bool choose_multiplier(int N, uint64_t d, int prec, uint64_t *pm, int *pshpost);
extern bool udiv_coefficients(int N, uint64_t d, int *pshpre, uint64_t *pm, int *pshpost);


/*******************************
Expand Down Expand Up @@ -1090,7 +1091,7 @@ void cdmul(CodeBuilder& cdb,elem *e,regm_t *pretregs)

unsigned r3;

targ_ullong m;
uint64_t m;
int shpost;
int N = sz * 8;
bool mhighbit = choose_multiplier(N, d, N - 1, &m, &shpost);
Expand Down Expand Up @@ -1191,7 +1192,7 @@ void cdmul(CodeBuilder& cdb,elem *e,regm_t *pretregs)
unsigned r3;
regm_t regm;
unsigned reg;
targ_ullong m;
uint64_t m;
int shpre;
int shpost;
if (udiv_coefficients(sz * 8, e2factor, &shpre, &m, &shpost))
Expand Down
143 changes: 72 additions & 71 deletions src/dmd/backend/divcoeff.c → src/dmd/backend/divcoeff.d
Original file line number Diff line number Diff line change
Expand Up @@ -2,38 +2,47 @@
* Compiler implementation of the
* $(LINK2 http://www.dlang.org, D programming language).
*
* Copyright: Copyright (C) 2013-2018 by The D Language Foundation, All Rights Reserved
* Copyright: Copyright (c) 2013-2018 by The D Language Foundation, All Rights Reserved
* Authors: $(LINK2 http://www.digitalmars.com, Walter Bright)
* License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
* Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/backend/divcoeff.c, backend/divcoeff.c)
* Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/backend/divcoeff.d, backend/divcoeff.d)
*/

/***************************************************
* Algorithms from "Division by Invariant Integers using Multiplication"
* by Torbjoern Granlund and Peter L. Montgomery
*/

#include <stdio.h>
#include <assert.h>
import core.stdc.stdio;

// This MUST MATCH typedef targ_ullong in cdef.h.
#if defined(__UINT64_TYPE__) && !defined(__APPLE__)
typedef __UINT64_TYPE__ ullong;
#elif defined(__UINTMAX_TYPE__)
typedef __UINTMAX_TYPE__ ullong;
#else
typedef unsigned long long ullong;
#endif
extern (C++):

void test_udiv_coefficients();
alias ullong = ulong;

/* unsigned 128 bit math
*/

#define SIGN64(x) ((long long)(x) < 0)
#define SHL128(dh,dl, xh,xl) ((dh = (xh << 1) | SIGN64(xl)), (dl = xl << 1))
#define SHR128(dh,dl, xh,xl) ((dl = (xl >> 1) | ((xh & 1) << 63)),(dh = xh >> 1))
#define XltY128(xh,xl,yh,yl) (xh < yh || (xh == yh && xl < yl))
bool SIGN64(ullong x)
{
return cast(long)x < 0;
}

void SHL128(out ullong dh, out ullong dl, ullong xh,ullong xl)
{
dh = (xh << 1) | SIGN64(xl);
dl = xl << 1;
}

void SHR128(out ullong dh, out ullong dl, ullong xh,ullong xl)
{
dl = (xl >> 1) | ((xh & 1) << 63);
dh = xh >> 1;
}

bool XltY128(ullong xh, ullong xl, ullong yh, ullong yl)
{
return xh < yh || (xh == yh && xl < yl);
}

void u128Div(ullong xh, ullong xl, ullong yh, ullong yl, ullong *pqh, ullong *pql)
{
Expand All @@ -46,7 +55,7 @@ void u128Div(ullong xh, ullong xl, ullong yh, ullong yl, ullong *pqh, ullong *pq
assert(yh || yl); // no div-by-0 bugs

// left justify y
unsigned shiftcount = 1;
uint shiftcount = 1;
if (!yh)
{ yh = yl;
yl = 0;
Expand Down Expand Up @@ -85,22 +94,23 @@ void u128Div(ullong xh, ullong xl, ullong yh, ullong yl, ullong *pqh, ullong *pq

// Remainder is xh,xl

#if 0
printf("%016llx_%016llx / %016llx_%016llx = %016llx_%016llx\n", xxh,xxl,yyh,yyl,qh,ql);
if (xxh == 0 && yyh == 0)
printf("should be %llx\n", xxl / yyl);
#endif
version (none)
{
printf("%016llx_%016llx / %016llx_%016llx = %016llx_%016llx\n", xxh,xxl,yyh,yyl,qh,ql);
if (xxh == 0 && yyh == 0)
printf("should be %llx\n", xxl / yyl);
}
}

/************************************
* Implement Algorithm 6.2: Selection of multiplier and shift count
* Input:
* N 32 or 64
* d divisor (must not be 0 or a power of 2)
* prec bits of precision desired
* Params:
* N = 32 or 64
* d = divisor (must not be 0 or a power of 2)
* prec = bits of precision desired
* Output:
* *pm factor
* *pshpost post shift
* *pm = factor
* *pshpost = post shift
* Returns:
* true m >= 2**N
*/
Expand All @@ -127,10 +137,10 @@ bool choose_multiplier(int N, ullong d, int prec, ullong *pm, int *pshpost)
if (N == 32)
{
// mlow = (2**(N + b)) / d
ullong mlow = (1ULL << (N + b)) / d;
ullong mlow = (1UL << (N + b)) / d;

// uhigh = (2**(N + b) + 2**(N + b - prec)) / d
ullong mhigh = ((1ULL << (N + b)) + (1ULL << (N + b - prec))) / d;
ullong mhigh = ((1UL << (N + b)) + (1UL << (N + b - prec))) / d;

while (mlow/2 < mhigh/2 && shpost)
{
Expand All @@ -140,27 +150,27 @@ bool choose_multiplier(int N, ullong d, int prec, ullong *pm, int *pshpost)
}

*pm = mhigh & 0xFFFFFFFF;
mhighbit = mhigh >> N;
mhighbit = (mhigh >> N) != 0;
}
else if (N == 64)
{
// Same as for N==32, but use 128 bit unsigned arithmetic

// mlow = (2**(N + b)) / d
ullong mlowl = 0;
ullong mlowh = 1ULL << b;
ullong mlowh = 1UL << b;

// mlow /= d
u128Div(mlowh, mlowl, 0, d, &mlowh, &mlowl);

// mhigh = (2**(N + b) + 2**(N + b - prec)) / d
ullong mhighl = 0;
ullong mhighh = 1ULL << b;
ullong mhighh = 1UL << b;
int e = N + b - prec;
if (e < 64)
mhighl = 1ULL << e;
mhighl = 1UL << e;
else
mhighh |= 1ULL << (e - 64);
mhighh |= 1UL << (e - 64);

// mhigh /= d
u128Div(mhighh, mhighl, 0, d, &mhighh, &mhighl);
Expand Down Expand Up @@ -223,10 +233,6 @@ bool choose_multiplier(int N, ullong d, int prec, ullong *pm, int *pshpost)

bool udiv_coefficients(int N, ullong d, int *pshpre, ullong *pm, int *pshpost)
{
#ifdef DEBUG
test_udiv_coefficients();
#endif

bool mhighbit = choose_multiplier(N, d, N, pm, pshpost);
if (mhighbit && (d & 1) == 0)
{
Expand All @@ -244,14 +250,8 @@ bool udiv_coefficients(int N, ullong d, int *pshpre, ullong *pm, int *pshpost)
return mhighbit;
}

#ifdef DEBUG
void test_udiv_coefficients()
unittest
{
static bool tested = false;
if (tested)
return;
tested = true;

struct S
{
int N;
Expand All @@ -260,10 +260,10 @@ void test_udiv_coefficients()
int highbit;
ullong m;
int shpost;
};
}

static S table[] =
{
static immutable S[14] table =
[
{ 32, 10, 0, 0, 0xCCCCCCCD, 3 },
{ 32, 13, 0, 0, 0x4EC4EC4F, 2 },
{ 32, 14, 1, 0, 0x92492493, 2 },
Expand All @@ -279,39 +279,40 @@ void test_udiv_coefficients()
{ 64, 17, 0, 0, 0xF0F0F0F0F0F0F0F1, 4 },
{ 64, 100, 2, 0, 0x28F5C28F5C28F5C3, 2 },
{ 64, 14007, 0, 1, 0x2B71840C5ADF02C3, 14 },
};
];

for (int i = 0; i < sizeof(table)/sizeof(table[0]); i++)
{ S *ps = &table[i];
for (int i = 0; i < table.length; i++)
{ const ps = &table[i];

ullong m;
int shpre;
int shpost;
bool mhighbit = udiv_coefficients(ps->N, ps->d, &shpre, &m, &shpost);
bool mhighbit = udiv_coefficients(ps.N, ps.d, &shpre, &m, &shpost);

//printf("[%d] %d %d %llx %d\n", i, shpre, mhighbit, m, shpost);
assert(shpre == ps->shpre);
assert(mhighbit == (bool)ps->highbit);
assert(m == ps->m);
assert(shpost == ps->shpost);
assert(shpre == ps.shpre);
assert(mhighbit == ps.highbit);
assert(m == ps.m);
assert(shpost == ps.shpost);
}
}
#endif

#if 0
#include <stdlib.h>

void main(int argc, char **argv)
version (none)
{
if (argc == 2)
import core.stdc.stdlib;

extern (D) int main(string[] args)
{
ullong d = atoi(argv[1]);
ullong m;
int shpre;
int shpost;
bool mhighbit = udiv_coefficients(64, d, &shpre, &m, &shpost);
if (args.length == 2)
{
ullong d = atoi(args[1].ptr);
ullong m;
int shpre;
int shpost;
bool mhighbit = udiv_coefficients(64, d, &shpre, &m, &shpost);

printf("%d %d %llx, %d\n", shpre, mhighbit, m, shpost);
printf("%d %d %llx, %d\n", shpre, mhighbit, m, shpost);
}
return 0;
}
}
#endif
Loading