This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH, d] Fix IdentityExp comparison for complex floats


Currently all identity comparisons for complex types (c1 is c2) return
true. This is caused by the rrent implementation being only correct for
real types, so this adds new code for the complex type cases.

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

Tested on x86_64-linux-gnu and on the GDC CI
(https://github.com/D-Programming-GDC/GDC/pull/768)
--
Johannes


---
gcc/d/ChangeLog:

2018-11-24  Johannes Pfau  <johannespfau@gmail.com>

	* expr.cc (ExprVisitor::visit(IdentityExp)): Add support for complex types.
	(ExprVisitor::build_float_identity): New function. 

gcc/testsuite/ChangeLog:

2018-11-24  Johannes Pfau  <johannespfau@gmail.com>

	* gdc.dg/runnable.d: Test IdentityExp for complex types.


 gcc/d/expr.cc                   | 44 +++++++++++++++++++++++++--------
 gcc/testsuite/gdc.dg/runnable.d | 22 +++++++++++++++++
 2 files changed, 56 insertions(+), 10 deletions(-)

diff --git a/gcc/d/expr.cc b/gcc/d/expr.cc
index 9a1aad42d..7eef00ac0 100644
--- a/gcc/d/expr.cc
+++ b/gcc/d/expr.cc
@@ -255,6 +255,21 @@ public:
     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 t1, tree t2)
+  {
+    /* For floating-point values, identity is defined as the bits in the
+       operands being identical.  */
+    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.  */
@@ -275,19 +290,28 @@ public:
 	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 = d_save_expr (build_expr (e->e1));
+	tree e2 = d_save_expr (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)
+      {
+	tree e1 = d_save_expr (build_expr (e->e1));
+	tree e2 = d_save_expr (build_expr (e->e2));
+	this->result_ = build_float_identity (code, e1, e2);
       }
     else if (tb1->ty == Tstruct)
       {
diff --git a/gcc/testsuite/gdc.dg/runnable.d b/gcc/testsuite/gdc.dg/runnable.d
index 4f1ef76e4..2d33d7d10 100644
--- a/gcc/testsuite/gdc.dg/runnable.d
+++ b/gcc/testsuite/gdc.dg/runnable.d
@@ -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()
@@ -1570,6 +1591,7 @@ void main()
     test273();
     test285();
     test286();
+    test309();
 
     printf("Success!\n");
 }
-- 
2.19.1


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]