From 5bdebb51a649d04569324f4f1124d5e64a3cbff7 Mon Sep 17 00:00:00 2001 From: Iain Buclaw Date: Sun, 20 Jan 2019 12:55:38 +0000 Subject: [PATCH] [D] Fix identity comparison for structs with complex float fields. gcc/d/ChangeLog: 2019-01-20 Iain Buclaw * d-codegen.cc (identity_compare_p): Return false if seen built-in type with padding. (build_float_identity): Moved here from expr.cc. (lower_struct_comparison): Handle real and complex types. * d-tree.h (build_float_identity): New. * expr.cc (build_float_identity): Move to d-codegen.cc. gcc/testsuite/ChangeLog: 2019-01-20 Iain Buclaw * gdc.dg/runnable.d: Add more tests for comparing complex types. From-SVN: r268104 --- gcc/d/ChangeLog | 9 +++++ gcc/d/d-codegen.cc | 58 ++++++++++++++++++++++++++------- gcc/d/d-tree.h | 1 + gcc/d/expr.cc | 14 -------- gcc/testsuite/ChangeLog | 4 +++ gcc/testsuite/gdc.dg/runnable.d | 20 ++++++++++++ 6 files changed, 81 insertions(+), 25 deletions(-) diff --git a/gcc/d/ChangeLog b/gcc/d/ChangeLog index f062ff8f24f..aa3bb7f9041 100644 --- a/gcc/d/ChangeLog +++ b/gcc/d/ChangeLog @@ -1,3 +1,12 @@ +2019-01-20 Iain Buclaw + + * d-codegen.cc (identity_compare_p): Return false if seen built-in + type with padding. + (build_float_identity): Moved here from expr.cc. + (lower_struct_comparison): Handle real and complex types. + * d-tree.h (build_float_identity): New. + * expr.cc (build_float_identity): Move to d-codegen.cc. + 2019-01-20 Johannes Pfau * expr.cc (build_float_identity): New function. diff --git a/gcc/d/d-codegen.cc b/gcc/d/d-codegen.cc index 7ca0acffcc4..58c8257c63c 100644 --- a/gcc/d/d-codegen.cc +++ b/gcc/d/d-codegen.cc @@ -798,15 +798,21 @@ identity_compare_p (StructDeclaration *sd) for (size_t i = 0; i < sd->fields.dim; i++) { VarDeclaration *vd = sd->fields[i]; + Type *tb = vd->type->toBasetype (); /* Check inner data structures. */ - if (vd->type->ty == Tstruct) + if (tb->ty == Tstruct) { - TypeStruct *ts = (TypeStruct *) vd->type; + TypeStruct *ts = (TypeStruct *) tb; if (!identity_compare_p (ts->sym)) return false; } + /* Check for types that may have padding. */ + if ((tb->ty == Tcomplex80 || tb->ty == Tfloat80 || tb->ty == Timaginary80) + && Target::realpad != 0) + return false; + if (offset <= vd->offset) { /* There's a hole in the struct. */ @@ -824,6 +830,20 @@ identity_compare_p (StructDeclaration *sd) return true; } +/* Build a floating-point identity comparison between T1 and T2, ignoring any + excessive padding in the type. CODE is EQ_EXPR or NE_EXPR comparison. */ + +tree +build_float_identity (tree_code code, tree t1, tree t2) +{ + 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); +} + /* Lower a field-by-field equality expression between T1 and T2 of type SD. CODE is the EQ_EXPR or NE_EXPR comparison. */ @@ -859,29 +879,45 @@ lower_struct_comparison (tree_code code, StructDeclaration *sd, for (size_t i = 0; i < sd->fields.dim; i++) { VarDeclaration *vd = sd->fields[i]; + Type *type = vd->type->toBasetype (); tree sfield = get_symbol_decl (vd); tree t1ref = component_ref (t1, sfield); tree t2ref = component_ref (t2, sfield); tree tcmp; - if (vd->type->ty == Tstruct) + if (type->ty == Tstruct) { /* Compare inner data structures. */ - StructDeclaration *decl = ((TypeStruct *) vd->type)->sym; + StructDeclaration *decl = ((TypeStruct *) type)->sym; tcmp = lower_struct_comparison (code, decl, t1ref, t2ref); } + else if (type->ty != Tvector && type->isintegral ()) + { + /* Integer comparison, no special handling required. */ + tcmp = build_boolop (code, t1ref, t2ref); + } + else if (type->ty != Tvector && type->isfloating ()) + { + /* Floating-point comparison, don't compare padding in type. */ + if (!type->iscomplex ()) + tcmp = build_float_identity (code, t1ref, t2ref); + else + { + tree req = build_float_identity (code, real_part (t1ref), + real_part (t2ref)); + tree ieq = build_float_identity (code, imaginary_part (t1ref), + imaginary_part (t2ref)); + + tcmp = build_boolop (tcode, req, ieq); + } + } else { - tree stype = build_ctype (vd->type); + tree stype = build_ctype (type); opt_scalar_int_mode mode = int_mode_for_mode (TYPE_MODE (stype)); - if (vd->type->ty != Tvector && vd->type->isintegral ()) - { - /* Integer comparison, no special handling required. */ - tcmp = build_boolop (code, t1ref, t2ref); - } - else if (mode.exists ()) + if (mode.exists ()) { /* Compare field bits as their corresponding integer type. *((T*) &t1) == *((T*) &t2) */ diff --git a/gcc/d/d-tree.h b/gcc/d/d-tree.h index 6ffb0f32a1f..0b3c5eddedd 100644 --- a/gcc/d/d-tree.h +++ b/gcc/d/d-tree.h @@ -522,6 +522,7 @@ extern tree d_mark_addressable (tree); extern tree d_mark_used (tree); extern tree d_mark_read (tree); extern bool identity_compare_p (StructDeclaration *); +extern tree build_float_identity (tree_code, tree, tree); extern tree build_struct_comparison (tree_code, StructDeclaration *, tree, tree); extern tree build_array_struct_comparison (tree_code, StructDeclaration *, diff --git a/gcc/d/expr.cc b/gcc/d/expr.cc index a1f7c262dc8..4bfdde5a29a 100644 --- a/gcc/d/expr.cc +++ b/gcc/d/expr.cc @@ -43,20 +43,6 @@ along with GCC; see the file COPYING3. If not see #include "d-tree.h" -/* Build a floating-point identity comparison between T1 and T2, ignoring any - excessive padding in the type. CODE is EQ_EXPR or NE_EXPR comparison. */ - -static tree -build_float_identity (tree_code code, tree t1, tree t2) -{ - 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); -} - /* Implements the visitor interface to build the GCC trees of all Expression AST classes emitted from the D Front-end. All visit methods accept one parameter E, which holds the frontend AST diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index de3a3c428d2..853224023fd 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2019-01-20 Iain Buclaw + + * gdc.dg/runnable.d: Add more tests for comparing complex types. + 2019-01-20 Johannes Pfau * gdc.dg/runnable.d: Add tests for comparing complex types. diff --git a/gcc/testsuite/gdc.dg/runnable.d b/gcc/testsuite/gdc.dg/runnable.d index 65c71e86292..e36a2585027 100644 --- a/gcc/testsuite/gdc.dg/runnable.d +++ b/gcc/testsuite/gdc.dg/runnable.d @@ -1553,6 +1553,26 @@ void test309() assert(!(f1 is f3)); assert(!(f2 is f3)); assert(!(f1 !is f4)); + + struct CReal + { + creal value; + } + + CReal s1 = CReal(+0.0 + 0.0i); + CReal s2 = CReal(+0.0 - 0.0i); + CReal s3 = CReal(-0.0 + 0.0i); + CReal s4 = CReal(+0.0 + 0.0i); + + assert(s1 !is s2); + assert(s1 !is s3); + assert(s2 !is s3); + assert(s1 is s4); + + assert(!(s1 is s2)); + assert(!(s1 is s3)); + assert(!(s2 is s3)); + assert(!(s1 !is s4)); } /******************************************/ -- 2.30.2