d: Use memset to fill alignment holes with zeroes.
authorIain Buclaw <ibuclaw@gdcproject.org>
Tue, 31 Mar 2020 16:18:32 +0000 (18:18 +0200)
committerIain Buclaw <ibuclaw@gdcproject.org>
Tue, 31 Mar 2020 17:03:04 +0000 (19:03 +0200)
This patch removes the manual insertion of padding for fields in
constructed struct literals, and instead uses memset() on the
declaration being initialized.

When compiling optimized builds, the intent is usually missed, and
alignment holes end up with non-zero values in them anyway.

gcc/d/ChangeLog:

PR d/94424
* d-codegen.cc (build_alignment_field): Remove.
(build_struct_literal): Don't insert alignment padding.
* expr.cc (ExprVisitor::visit (AssignExp *)): Call memset before
assigning struct literals.

gcc/testsuite/ChangeLog:

PR d/94424
* gdc.dg/pr94424.d: New test.

gcc/d/ChangeLog
gcc/d/d-codegen.cc
gcc/d/expr.cc
gcc/testsuite/ChangeLog
gcc/testsuite/gdc.dg/pr94424.d [new file with mode: 0644]

index ea1d7d5c896fa942fbf7f4ee8d0ca167a24755c1..9a3fbfa7c561ba06a6791d099328a5e6fa25707f 100644 (file)
@@ -1,3 +1,11 @@
+2020-03-31  Iain Buclaw  <ibuclaw@gdcproject.org>
+
+       PR d/94424
+       * d-codegen.cc (build_alignment_field): Remove.
+       (build_struct_literal): Don't insert alignment padding.
+       * expr.cc (ExprVisitor::visit (AssignExp *)): Call memset before
+       assigning struct literals.
+
 2020-03-31  Iain Buclaw  <ibuclaw@gdcproject.org>
 
        * typeinfo.cc (TypeInfoVisitor::internal_reference): Call
index 3895a59c224e1f84d84185d104a94ab2000d4e2b..66af2b4da308a59da95768f28a97ff15a7952674 100644 (file)
@@ -1076,26 +1076,6 @@ build_array_struct_comparison (tree_code code, StructDeclaration *sd,
   return compound_expr (body, result);
 }
 
-/* Create an anonymous field of type ubyte[T] at OFFSET to fill
-   the alignment hole between OFFSET and FIELDPOS.  */
-
-static tree
-build_alignment_field (tree type, HOST_WIDE_INT offset, HOST_WIDE_INT fieldpos)
-{
-  tree atype = make_array_type (Type::tuns8, fieldpos - offset);
-  tree field = create_field_decl (atype, NULL, 1, 1);
-
-  SET_DECL_OFFSET_ALIGN (field, TYPE_ALIGN (atype));
-  DECL_FIELD_OFFSET (field) = size_int (offset);
-  DECL_FIELD_BIT_OFFSET (field) = bitsize_zero_node;
-  DECL_FIELD_CONTEXT (field) = type;
-  DECL_PADDING_P (field) = 1;
-
-  layout_decl (field, 0);
-
-  return field;
-}
-
 /* Build a constructor for a variable of aggregate type TYPE using the
    initializer INIT, an ordered flat list of fields and values provided
    by the frontend.  The returned constructor should be a value that
@@ -1111,14 +1091,8 @@ build_struct_literal (tree type, vec<constructor_elt, va_gc> *init)
   vec<constructor_elt, va_gc> *ve = NULL;
   HOST_WIDE_INT offset = 0;
   bool constant_p = true;
-  bool fillholes = true;
   bool finished = false;
 
-  /* Filling alignment holes this only applies to structs.  */
-  if (TREE_CODE (type) != RECORD_TYPE
-      || CLASS_TYPE_P (type) || TYPE_PACKED (type))
-    fillholes = false;
-
   /* Walk through each field, matching our initializer list.  */
   for (tree field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
     {
@@ -1163,15 +1137,6 @@ build_struct_literal (tree type, vec<constructor_elt, va_gc> *init)
          HOST_WIDE_INT fieldpos = int_byte_position (field);
          gcc_assert (value != NULL_TREE);
 
-         /* Insert anonymous fields in the constructor for padding out
-            alignment holes in-place between fields.  */
-         if (fillholes && offset < fieldpos)
-           {
-             tree pfield = build_alignment_field (type, offset, fieldpos);
-             tree pvalue = build_zero_cst (TREE_TYPE (pfield));
-             CONSTRUCTOR_APPEND_ELT (ve, pfield, pvalue);
-           }
-
          /* Must not initialize fields that overlap.  */
          if (fieldpos < offset)
            {
@@ -1214,15 +1179,6 @@ build_struct_literal (tree type, vec<constructor_elt, va_gc> *init)
        break;
     }
 
-  /* Finally pad out the end of the record.  */
-  if (fillholes && offset < int_size_in_bytes (type))
-    {
-      tree pfield = build_alignment_field (type, offset,
-                                          int_size_in_bytes (type));
-      tree pvalue = build_zero_cst (TREE_TYPE (pfield));
-      CONSTRUCTOR_APPEND_ELT (ve, pfield, pvalue);
-    }
-
   /* Ensure that we have consumed all values.  */
   gcc_assert (vec_safe_is_empty (init) || ANON_AGGR_TYPE_P (type));
 
index fcf9bc5880af60892d4bac1b0c0ed80425cc816f..0ed50ee2d9e9120dfa8f991b290490a6240f3537 100644 (file)
@@ -1054,14 +1054,13 @@ public:
        tree t1 = build_expr (e->e1);
        tree t2 = convert_for_assignment (build_expr (e->e2),
                                          e->e2->type, e->e1->type);
+       StructDeclaration *sd = ((TypeStruct *) tb1)->sym;
 
        /* Look for struct = 0.  */
        if (e->e2->op == TOKint64)
          {
            /* Use memset to fill struct.  */
            gcc_assert (e->op == TOKblit);
-           StructDeclaration *sd = ((TypeStruct *) tb1)->sym;
-
            tree tmemset = builtin_decl_explicit (BUILT_IN_MEMSET);
            tree result = build_call_expr (tmemset, 3, build_address (t1),
                                           t2, size_int (sd->structsize));
@@ -1079,7 +1078,22 @@ public:
            this->result_ = compound_expr (result, t1);
          }
        else
-         this->result_ = build_assign (modifycode, t1, t2);
+         {
+           /* Simple struct literal assignment.  */
+           tree init = NULL_TREE;
+
+           /* Fill any alignment holes in the struct using memset.  */
+           if (e->op == TOKconstruct && !identity_compare_p (sd))
+             {
+               tree tmemset = builtin_decl_explicit (BUILT_IN_MEMSET);
+               init = build_call_expr (tmemset, 3, build_address (t1),
+                                       integer_zero_node,
+                                       size_int (sd->structsize));
+             }
+
+           tree result = build_assign (modifycode, t1, t2);
+           this->result_ = compound_expr (init, result);
+         }
 
        return;
       }
index 1d97d6b52199b80bc5fe8a7518c444c0ccf9643a..008acc6e231735117a54ae3b6806d26576498b11 100644 (file)
@@ -1,3 +1,8 @@
+2020-03-31  Iain Buclaw  <ibuclaw@gdcproject.org>
+
+       PR d/94424
+       * gdc.dg/pr94424.d: New test.
+
 2020-03-31  Felix Yang  <felix.yang@huawei.com>
 
        PR tree-optimization/94398
diff --git a/gcc/testsuite/gdc.dg/pr94424.d b/gcc/testsuite/gdc.dg/pr94424.d
new file mode 100644 (file)
index 0000000..b9f9fac
--- /dev/null
@@ -0,0 +1,19 @@
+// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94424
+// { dg-additional-options "-fmain -funittest" }
+// { dg-do run { target hw } }
+// { dg-skip-if "needs gcc/config.d" { ! d_runtime } }
+@safe unittest
+{
+    struct C
+    {
+        ubyte i;
+        this(ubyte i) { this.i = i; }
+    }
+
+    auto c1 = C(1);
+    auto c2 = C(2);
+
+    assert(__cmp([c1, c1][], [c2, c2][]) < 0);
+    assert(__cmp([c2, c2], [c1, c1]) > 0);
+    assert(__cmp([c2, c2], [c2, c1]) > 0);
+}