Skip to content
Merged
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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI: auto-tester needs to be bumped too, see the discussion on the previous PR and the NG discussion - especially Martin's reply.

CURL_USER_AGENT="CirleCI $(curl --version | head -n 1)"
N=4
CIRCLE_NODE_INDEX=${CIRCLE_NODE_INDEX:-0}
Expand Down
13 changes: 8 additions & 5 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,9 +33,11 @@ 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 "C"
{
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);
}

/*******************************
* Swap two integers.
Expand Down Expand Up @@ -1090,7 +1093,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 +1194,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
161 changes: 81 additions & 80 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 @@ -43,10 +52,10 @@ void u128Div(ullong xh, ullong xl, ullong yh, ullong yl, ullong *pqh, ullong *pq

//ullong xxh = xh, xxl = xl, yyh = yh, yyl = yl;

assert(yh || yl); // no div-by-0 bugs
// assert(yh || yl); // no div-by-0 bugs
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not use the dassert workaround for DAutoTest I proposed here?
#7714 (comment)
If the body is version(assert) it should behave like built-in assert? Alternatively it's really just 2.067 that needs special casing.

Or maybe @CyberShadow can update DAutoTest to use 2.068.2 as initial bootstrap compiler?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't want to redo the asserts, as that doesn't scale to the rest of the back end. What's needed is to upgrade the boot compiler to 2.074. But that's for after this PR.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

as that doesn't scale to the rest of the back end.

Well, I thought it helps porting when the assert's are still enabled, but yeah this can be done in another PR


// left justify y
unsigned shiftcount = 1;
uint shiftcount = 1;
if (!yh)
{ yh = yl;
yl = 0;
Expand Down Expand Up @@ -85,31 +94,32 @@ 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
*/

bool choose_multiplier(int N, ullong d, int prec, ullong *pm, int *pshpost)
extern (C) bool choose_multiplier(int N, ullong d, int prec, ullong *pm, int *pshpost)
{
assert(N == 32 || N == 64);
assert(prec <= N);
assert(d > 1 && (d & (d - 1)));
// assert(N == 32 || N == 64);
// assert(prec <= N);
// assert(d > 1 && (d & (d - 1)));

// Compute b such that 2**(b-1) < d <= 2**b
// which is the number of significant bits in d
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 @@ -195,8 +205,8 @@ bool choose_multiplier(int N, ullong d, int prec, ullong *pm, int *pshpost)
*pm = mhighl;
mhighbit = mhighh & 1;
}
else
assert(0);
// else
// assert(0);

*pshpost = shpost;
return mhighbit;
Expand All @@ -221,12 +231,8 @@ bool choose_multiplier(int N, ullong d, int prec, ullong *pm, int *pshpost)
* q = SRL(MULUH(m, SRL(n, shpre)), shpost)
*/

bool udiv_coefficients(int N, ullong d, int *pshpre, ullong *pm, int *pshpost)
extern (C) 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 @@ -237,21 +243,15 @@ bool udiv_coefficients(int N, ullong d, int *pshpre, ullong *pm, int *pshpost)
}
*pshpre = e;
mhighbit = choose_multiplier(N, d, N - e, pm, pshpost);
assert(mhighbit == false);
// assert(mhighbit == false);
}
else
*pshpre = 0;
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