Skip to content

Commit

Permalink
Reintroduce the fix for issue 3632, without the dependency on fixing …
Browse files Browse the repository at this point in the history
…issue 1824.

Revert the parts in clone.c that were commented out, so pull #387 can merge cleanly.
  • Loading branch information
yebblies committed Apr 14, 2012
1 parent fb8f467 commit f9c21c2
Show file tree
Hide file tree
Showing 5 changed files with 158 additions and 39 deletions.
14 changes: 0 additions & 14 deletions src/clone.c
Expand Up @@ -204,11 +204,6 @@ int StructDeclaration::needOpEquals()
if (hasIdentityEquals)
goto Lneed;

#if 0
if (isUnionDeclaration())
goto Ldontneed;
#endif

/* If any of the fields has an opEquals, then we
* need it too.
*/
Expand All @@ -220,14 +215,6 @@ int StructDeclaration::needOpEquals()
if (v->storage_class & STCref)
continue;
Type *tv = v->type->toBasetype();
#if 0
if (tv->isfloating())
goto Lneed;
if (tv->ty == Tarray)
goto Lneed;
if (tv->ty == Tclass)
goto Lneed;
#endif
while (tv->ty == Tsarray)
{ TypeSArray *ta = (TypeSArray *)tv;
tv = tv->nextOf()->toBasetype();
Expand All @@ -239,7 +226,6 @@ int StructDeclaration::needOpEquals()
goto Lneed;
}
}
Ldontneed:
if (X) printf("\tdontneed\n");
return 0;

Expand Down
62 changes: 44 additions & 18 deletions src/constfold.c
Expand Up @@ -969,26 +969,52 @@ Expression *Identity(enum TOK op, Type *type, Expression *e1, Expression *e2)

cmp = (es1->var == es2->var && es1->offset == es2->offset);
}
else if (e1->op == TOKstructliteral && e2->op == TOKstructliteral)
{ StructLiteralExp *es1 = (StructLiteralExp *)e1;
StructLiteralExp *es2 = (StructLiteralExp *)e2;

if (es1->sd != es2->sd)
cmp = 0;
else if ((!es1->elements || !es1->elements->dim) &&
(!es2->elements || !es2->elements->dim))
cmp = 1; // both arrays are empty
else if (!es1->elements || !es2->elements)
cmp = 0;
else if (es1->elements->dim != es2->elements->dim)
cmp = 0;
else
{
cmp = 1;
for (size_t i = 0; i < es1->elements->dim; i++)
{ Expression *ee1 = (*es1->elements)[i];
Expression *ee2 = (*es2->elements)[i];

if (ee1 == ee2)
continue;
if (!ee1 || !ee2)
{ cmp = 0;
break;
}
Expression *v = Identity(TOKequal, Type::tint32, ee1, ee2);
if (v == EXP_CANT_INTERPRET)
return EXP_CANT_INTERPRET;
cmp = v->toInteger();
if (cmp == 0)
break;
}
}
}
else if (e1->type->isfloating() && e2->type->isfloating())
{
complex_t v1 = e1->toComplex();
complex_t v2 = e2->toComplex();
cmp = RealEquals(creall(v1), creall(v2)) &&
RealEquals(cimagl(v1), cimagl(v2));
}
else
{
if (e1->type->isreal())
{
cmp = RealEquals(e1->toReal(), e2->toReal());
}
else if (e1->type->isimaginary())
{
cmp = RealEquals(e1->toImaginary(), e2->toImaginary());
}
else if (e1->type->iscomplex())
{
complex_t v1 = e1->toComplex();
complex_t v2 = e2->toComplex();
cmp = RealEquals(creall(v1), creall(v2)) &&
RealEquals(cimagl(v1), cimagl(v1));
}
else
return Equal((op == TOKidentity) ? TOKequal : TOKnotequal,
type, e1, e2);
return Equal((op == TOKidentity) ? TOKequal : TOKnotequal,
type, e1, e2);
}
if (op == TOKnotidentity)
cmp ^= 1;
Expand Down
37 changes: 35 additions & 2 deletions src/e2ir.c
Expand Up @@ -2454,7 +2454,37 @@ elem *IdentityExp::toElem(IRState *irs)

//printf("IdentityExp::toElem() %s\n", toChars());

if (t1->ty == Tstruct || t1->isfloating())
if (t1->ty == Tcomplex80 && REALPAD != 0)
{
/* creal has padding in the middle on some platforms,
* so do identity comparison on real and imaginary parts
* separately.
*/
symbol *s1 = symbol_genauto(t1->toCtype());
symbol *s2 = symbol_genauto(t2->toCtype());
elem *el1 = e1->toElem(irs);
elem *el2 = e2->toElem(irs);
elem *ed1 = el_bin(OPeq, TYcldouble, el_var(s1), el1);
elem *ed2 = el_bin(OPeq, TYcldouble, el_var(s2), el2);

elem *e1a = addressElem(ed1, Type::tcomplex80);
elem *e2a = addressElem(ed2, Type::tcomplex80);
elem *ecount1 = el_long(TYsize_t, REALSIZE - REALPAD);
elem *ec1 = el_bin(OPmemcmp, TYint, el_param(e1a, e2a), ecount1);
ec1 = el_bin(eop, TYint, ec1, el_long(TYint, 0));

e1a = el_bin(OPadd, e1a->Ety, addressElem(el_var(s1), Type::tcomplex80), el_long(TYsize_t, REALSIZE));
e2a = el_bin(OPadd, e2a->Ety, addressElem(el_var(s2), Type::tcomplex80), el_long(TYsize_t, REALSIZE));
elem *ecount2 = el_long(TYsize_t, REALSIZE - REALPAD);
elem *ec2 = el_bin(OPmemcmp, TYint, el_param(e1a, e2a ), ecount2);
ec2 = el_bin(eop, TYint, ec2, el_long(TYint, 0));

enum OPER xop = (op == TOKidentity) ? OPandand : OPoror;

e = el_bin(xop, TYint, ec1, ec2);
el_setLoc(e,loc);
}
else if (t1->ty == Tstruct || t1->isfloating())
{ // Do bit compare of struct's
elem *es1;
elem *es2;
Expand All @@ -2467,7 +2497,10 @@ elem *IdentityExp::toElem(IRState *irs)
es2 = addressElem(es2, e2->type);
//es2 = el_una(OPaddr, TYnptr, es2);
e = el_param(es1, es2);
ecount = el_long(TYsize_t, t1->size());
if (t1->ty == Tfloat80 || t1->ty == Timaginary80)
ecount = el_long(TYsize_t, t1->size() - REALPAD);
else
ecount = el_long(TYsize_t, t1->size());
e = el_bin(OPmemcmp, TYint, e, ecount);
e = el_bin(eop, TYint, e, el_long(TYint, 0));
el_setLoc(e,loc);
Expand Down
9 changes: 4 additions & 5 deletions src/expression.c
Expand Up @@ -2329,11 +2329,10 @@ complex_t RealExp::toComplex()

int RealEquals(real_t x1, real_t x2)
{
return (Port::isNan(x1) && Port::isNan(x2)) ||
/* In some cases, the REALPAD bytes get garbage in them,
* so be sure and ignore them.
*/
memcmp(&x1, &x2, REALSIZE - REALPAD) == 0;
/* In some cases, the REALPAD bytes get garbage in them,
* so be sure and ignore them.
*/
return memcmp(&x1, &x2, REALSIZE - REALPAD) == 0;
}

int RealExp::equals(Object *o)
Expand Down
75 changes: 75 additions & 0 deletions test/runnable/xtest46.d
Expand Up @@ -435,6 +435,80 @@ void test21()

/***************************************************/

template TT3632(T...) { alias T TT3632; }

void test3632()
{
__gshared static int global;
if (!__ctfe)
{ // defeat optimizer/constfolding
asm { mov global, 1; }
}

int test(T)()
{
static struct W
{
T f;
this(T g) { if (__ctfe || global) f = g; }
}
auto nan = W(T.nan);
auto nan2 = W(T.nan);
auto init = W(T.init);
auto init2 = W(T.init);
auto zero = W(cast(T)0);
auto zero2 = W(cast(T)0);
auto nzero2 = W(-cast(T)0);

// requires fixing issue 3789
//assert(!(nan == nan2));
//assert(!(nan == init2));
//assert(!(init == init2));
//assert( (zero == zero2));
//assert( (zero == nzero2));

assert(!(nan.f == nan2.f));
assert(!(nan.f == init2.f));
assert(!(init.f == init2.f));
assert( (zero.f == zero2.f));
assert( (zero.f == nzero2.f));

assert( (nan is nan2));
assert(!(nan is init2));
assert( (init is init2));
assert( (zero is zero2));
assert(!(zero is nzero2));

assert( (nan.f is nan2.f));
assert(!(nan.f is init2.f));
assert( (init.f is init2.f));
assert( (zero.f is zero2.f));
assert(!(zero.f is nzero2.f));

assert(!(nan !is nan2));
assert( (nan !is init2));
assert(!(init !is init2));
assert(!(zero !is zero2));
assert( (zero !is nzero2));

assert(!(nan.f !is nan2.f));
assert( (nan.f !is init2.f));
assert(!(init.f !is init2.f));
assert(!(zero.f !is zero2.f));
assert( (zero.f !is nzero2.f));

return 1;
}

foreach(T; TT3632!(float, double, real, ifloat, idouble, ireal, cfloat, cdouble, creal))
{
auto x = test!T();
enum y = test!T();
}
}

/***************************************************/

void test22()
{
immutable uint x, y;
Expand Down Expand Up @@ -5112,6 +5186,7 @@ int main()
test129();
test130();
test131();
test3632();
test132();
test133();
test134();
Expand Down

0 comments on commit f9c21c2

Please sign in to comment.