Skip to content
This repository has been archived by the owner on Jun 20, 2019. It is now read-only.

Commit

Permalink
Fix IdentityExp comparison for complex floats
Browse files Browse the repository at this point in the history
  • Loading branch information
jpf91 committed Nov 18, 2018
1 parent 8e9a539 commit 6a30937
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 10 deletions.
46 changes: 36 additions & 10 deletions gcc/d/expr.cc
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,24 @@ class ExprVisitor : public Visitor
this->result_ = build_condition (build_ctype (e->type), cond, t1, t2);
}

/* Helper function for floating point identity comparison. Compare
only well-defined bits, ignore padding (e.g. for X86 80bit real). */

static tree build_float_identity (tree_code code, tree e1, tree e2)
{
/* For floating-point values, identity is defined as the bits in the
operands being identical. */
tree t1 = d_save_expr (e1);
tree t2 = d_save_expr (e2);

tree tmemcmp = builtin_decl_explicit (BUILT_IN_MEMCMP);
tree size = size_int (TYPE_PRECISION (TREE_TYPE (t1)) / BITS_PER_UNIT);

tree result = build_call_expr (tmemcmp, 3, build_address (t1),
build_address (t2), size);
return build_boolop (code, result, integer_zero_node);
}

/* Build an identity comparison expression. Operands go through the
usual conversions to bring them to a common type before comparison.
The result type is bool. */
Expand All @@ -275,19 +293,27 @@ class ExprVisitor : public Visitor
this->result_ = d_convert (build_ctype (e->type),
build_boolop (code, t1, t2));
}
else if (tb1->isfloating () && tb1->ty != Tvector)
else if (tb1->iscomplex () && tb1->ty != Tvector)
{
/* For floating-point values, identity is defined as the bits in the
operands being identical. */
tree t1 = d_save_expr (build_expr (e->e1));
tree t2 = d_save_expr (build_expr (e->e2));
tree e1 = build_expr (e->e1);
tree e2 = build_expr (e->e2);
tree re1 = real_part (e1);
tree im1 = imaginary_part (e1);
tree re2 = real_part (e2);
tree im2 = imaginary_part (e2);

tree tmemcmp = builtin_decl_explicit (BUILT_IN_MEMCMP);
tree size = size_int (TYPE_PRECISION (TREE_TYPE (t1)) / BITS_PER_UNIT);
tree req = build_float_identity (code, re1, re2);
tree ieq = build_float_identity (code, im1, im2);

tree result = build_call_expr (tmemcmp, 3, build_address (t1),
build_address (t2), size);
this->result_ = build_boolop (code, result, integer_zero_node);
if (code == EQ_EXPR)
this->result_ = build_boolop (TRUTH_ANDIF_EXPR, req, ieq);
else
this->result_ = build_boolop (TRUTH_ORIF_EXPR, req, ieq);
}
else if (tb1->isfloating () && tb1->ty != Tvector)
{
this->result_ = build_float_identity (code, build_expr (e->e1),
build_expr (e->e2));
}
else if (tb1->ty == Tstruct)
{
Expand Down
22 changes: 22 additions & 0 deletions gcc/testsuite/gdc.dg/runnable.d
Original file line number Diff line number Diff line change
Expand Up @@ -1533,6 +1533,27 @@ void test286()
assert(0);
}

/******************************************/
// https://bugzilla.gdcproject.org/show_bug.cgi?id=309

void test309()
{
creal f1 = +0.0 + 0.0i;
creal f2 = +0.0 - 0.0i;
creal f3 = -0.0 + 0.0i;
creal f4 = +0.0 + 0.0i;

assert(f1 !is f2);
assert(f1 !is f3);
assert(f2 !is f3);
assert(f1 is f4);

assert(!(f1 is f2));
assert(!(f1 is f3));
assert(!(f2 is f3));
assert(!(f1 !is f4));
}

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

void main()
Expand Down Expand Up @@ -1570,6 +1591,7 @@ void main()
test273();
test285();
test286();
test309();

printf("Success!\n");
}

0 comments on commit 6a30937

Please sign in to comment.