Hi,

In an earlier change, a wrapper function was added to set
CONSTRUCTOR_ZERO_PADDING_BITS on all CONSTRUCTOR nodes. This removes all
the old generated calls to built-in memset and memcpy as zero padding is
now taken care of by the middle-end.

The remaining constructors that weren't getting zero padded was
ARRAY_TYPEs, so now `__builtin_clear_padding' is used to fill in all
alignment holes in constructed array literals where required.

Bootstrapped and regression tested on x86_64-linux-gnu/-m32, committed
to mainline.

Regards,
Iain.

---
        PR d/103044

gcc/d/ChangeLog:

        * d-tree.h (build_clear_padding_call): New prototype.
        * d-codegen.cc (build_clear_padding_call): New function.
        (build_memset_call): Remove generated call to __builtin_memcpy.
        (build_address): Replace generated call to __builtin_memset with
        __builtin_clear_padding.
        (build_array_from_exprs): Likewise.
        * expr.cc (ExprVisitor::visit (AssignExp *)): Remove generated call to
        __builtin_memset.
        (ExprVisitor::visit (ArrayLiteralExp *)): Likewise.  Insert call to
        __builtin_clear_padding after copying array into GC memory.
        (ExprVisitor::visit (StructLiteralExp *)): Remove generated call to
        __builtin_memset.
        * toir.cc (IRVisitor::visit (ReturnStatement *)): Likewise.
---
 gcc/d/d-codegen.cc | 41 ++++++++++++++++++++---------------
 gcc/d/d-tree.h     |  1 +
 gcc/d/expr.cc      | 53 +++++-----------------------------------------
 gcc/d/toir.cc      |  5 -----
 4 files changed, 30 insertions(+), 70 deletions(-)

diff --git a/gcc/d/d-codegen.cc b/gcc/d/d-codegen.cc
index 1a7575aac22..e35f75af584 100644
--- a/gcc/d/d-codegen.cc
+++ b/gcc/d/d-codegen.cc
@@ -717,10 +717,11 @@ build_address (tree exp)
       if (AGGREGATE_TYPE_P (TREE_TYPE (exp))
          && !aggregate_value_p (TREE_TYPE (exp), exp))
        {
-         tree tmp = build_local_temp (TREE_TYPE (exp));
-         init = compound_expr (init, build_memset_call (tmp));
-         init = compound_expr (init, modify_expr (tmp, exp));
-         exp = tmp;
+         tree target = force_target_expr (exp);
+         tree ptr = build_address (TARGET_EXPR_SLOT (target));
+         init = compound_expr (init, target);
+         init = compound_expr (init, build_clear_padding_call (ptr));
+         exp = TARGET_EXPR_SLOT (target);
        }
       else
        exp = force_target_expr (exp);
@@ -891,17 +892,13 @@ build_memset_call (tree ptr, tree num)
     }
 
   /* Use a zero constant to fill the destination if setting the entire object.
-     For CONSTRUCTORs, the memcpy() is lowered to a ref-all pointer assignment,
-     which can then be merged with other stores to the object.  */
+     For CONSTRUCTORs, also set CONSTRUCTOR_ZERO_PADDING_BITS.  */
   tree valtype = TREE_TYPE (TREE_TYPE (ptr));
   if (tree_int_cst_equal (TYPE_SIZE_UNIT (valtype), num))
     {
       tree cst = build_zero_cst (valtype);
       if (TREE_CODE (cst) == CONSTRUCTOR)
-       {
-         CONSTRUCTOR_ZERO_PADDING_BITS (cst) = 1;
-         return build_memcpy_call (ptr, build_address (cst), num);
-       }
+       CONSTRUCTOR_ZERO_PADDING_BITS (cst) = 1;
 
       return modify_expr (build_deref (ptr), cst);
     }
@@ -910,6 +907,18 @@ build_memset_call (tree ptr, tree num)
                          ptr, integer_zero_node, num);
 }
 
+/* Build a call to built-in clear_padding(),  clears padding bits inside of the
+   object representation of object pointed by PTR.  */
+
+tree
+build_clear_padding_call (tree ptr)
+{
+  gcc_assert (POINTER_TYPE_P (TREE_TYPE (ptr)));
+
+  return build_call_expr (builtin_decl_explicit (BUILT_IN_CLEAR_PADDING), 1,
+                         ptr);
+}
+
 /* Return TRUE if the struct SD is suitable for comparison using memcmp.
    This is because we don't guarantee that padding is zero-initialized for
    a stack variable, so we can't use memcmp to compare struct values.  */
@@ -1893,15 +1902,13 @@ build_array_from_exprs (Type *type, Expressions *exps, 
bool const_p)
   /* Create a new temporary to store the array.  */
   tree var = build_local_temp (satype);
 
-  /* Fill any alignment holes with zeroes.  */
-  TypeStruct *ts = etype->baseElemOf ()->isTypeStruct ();
-  tree init = NULL;
-  if (ts && (!identity_compare_p (ts->sym) || ts->sym->isUnionDeclaration ()))
-    init = build_memset_call (var);
-
   /* Initialize the temporary.  */
   tree assign = modify_expr (var, build_padded_constructor (satype, elms));
-  return compound_expr (compound_expr (init, assign), var);
+
+  /* Fill any alignment holes with zeroes.  */
+  tree clear_padding = build_clear_padding_call (build_address (var));
+
+  return compound_expr (compound_expr (assign, clear_padding), var);
 }
 
 
diff --git a/gcc/d/d-tree.h b/gcc/d/d-tree.h
index ebbbe715dac..9d576e2bd3b 100644
--- a/gcc/d/d-tree.h
+++ b/gcc/d/d-tree.h
@@ -568,6 +568,7 @@ extern tree d_mark_read (tree);
 extern tree build_memcmp_call (tree, tree, tree);
 extern tree build_memcpy_call (tree, tree, tree);
 extern tree build_memset_call (tree, tree = NULL_TREE);
+extern tree build_clear_padding_call (tree);
 extern bool identity_compare_p (StructDeclaration *);
 extern tree build_float_identity (tree_code, tree, tree);
 extern tree build_struct_comparison (tree_code, StructDeclaration *,
diff --git a/gcc/d/expr.cc b/gcc/d/expr.cc
index 1c1ecf2c6db..268a176eb7f 100644
--- a/gcc/d/expr.cc
+++ b/gcc/d/expr.cc
@@ -1026,7 +1026,6 @@ public:
     if (tb1->ty == TY::Tstruct)
       {
        tree t1 = build_expr (e->e1);
-       tree t2 = convert_for_assignment (e->e2, e->e1->type, true);
        StructDeclaration *sd = tb1->isTypeStruct ()->sym;
 
        /* Look for struct = 0.  */
@@ -1051,25 +1050,8 @@ public:
        else
          {
            /* Simple struct literal assignment.  */
-           tree init = NULL_TREE;
-
-           /* Fill any alignment holes in the struct using memset.  */
-           if ((e->op == EXP::construct
-                || (e->e2->op == EXP::structLiteral && e->op == EXP::blit))
-               && (sd->isUnionDeclaration () || !identity_compare_p (sd)))
-             {
-               t1 = stabilize_reference (t1);
-               init = build_memset_call (t1);
-             }
-
-           /* Elide generating assignment if init is all zeroes.  */
-           if (init != NULL_TREE && initializer_zerop (t2))
-             this->result_ = compound_expr (init, t1);
-           else
-             {
-               tree result = build_assign (modifycode, t1, t2);
-               this->result_ = compound_expr (init, result);
-             }
+           tree t2 = convert_for_assignment (e->e2, e->e1->type, true);
+           this->result_ = build_assign (modifycode, t1, t2);
          }
 
        return;
@@ -2685,22 +2667,6 @@ public:
        if (constant_p && initializer_constant_valid_p (ctor, TREE_TYPE (ctor)))
          TREE_STATIC (ctor) = 1;
 
-       /* Use memset to fill any alignment holes in the array.  */
-       if (!this->constp_ && !this->literalp_)
-         {
-           TypeStruct *ts = etype->baseElemOf ()->isTypeStruct ();
-
-           if (ts != NULL && (!identity_compare_p (ts->sym)
-                              || ts->sym->isUnionDeclaration ()))
-             {
-               tree var = build_local_temp (TREE_TYPE (ctor));
-               tree init = build_memset_call (var);
-               /* Evaluate memset() first, then any saved elements.  */
-               saved_elems = compound_expr (init, saved_elems);
-               ctor = compound_expr (modify_expr (var, ctor), var);
-             }
-         }
-
        this->result_ = compound_expr (saved_elems, d_convert (type, ctor));
       }
     else if (e->onstack)
@@ -2726,6 +2692,9 @@ public:
 
        tree result = build_memcpy_call (mem, build_address (ctor), size);
 
+       /* Fill any alignment holes in the array.  */
+       result = compound_expr (result, build_clear_padding_call (mem));
+
        /* Return the array pointed to by MEM.  */
        result = compound_expr (result, mem);
 
@@ -2899,18 +2868,6 @@ public:
        tree var = build_deref (e->sym);
        ctor = compound_expr (modify_expr (var, ctor), var);
       }
-    else if (!this->literalp_)
-      {
-       /* Use memset to fill any alignment holes in the object.  */
-       if (!identity_compare_p (e->sd) || e->sd->isUnionDeclaration ())
-         {
-           tree var = build_local_temp (TREE_TYPE (ctor));
-           tree init = build_memset_call (var);
-           /* Evaluate memset() first, then any saved element constructors.  */
-           saved_elems = compound_expr (init, saved_elems);
-           ctor = compound_expr (modify_expr (var, ctor), var);
-         }
-      }
 
     this->result_ = compound_expr (saved_elems, ctor);
   }
diff --git a/gcc/d/toir.cc b/gcc/d/toir.cc
index 427a662eeda..b70db7a0e50 100644
--- a/gcc/d/toir.cc
+++ b/gcc/d/toir.cc
@@ -1058,13 +1058,8 @@ public:
 
        if (sle != NULL)
          {
-           StructDeclaration *sd = type->baseElemOf ()->isTypeStruct ()->sym;
            sle->sym = build_address (this->func_->shidden);
            using_rvo_p = true;
-
-           /* Fill any alignment holes in the return slot using memset.  */
-           if (!identity_compare_p (sd) || sd->isUnionDeclaration ())
-             add_stmt (build_memset_call (this->func_->shidden));
          }
 
        if (using_rvo_p == true)
-- 
2.43.0

Reply via email to