d: Refactor use of built-in memcmp/memcpy/memset into helper functions.
authorIain Buclaw <ibuclaw@gdcproject.org>
Fri, 17 Jul 2020 15:20:02 +0000 (17:20 +0200)
committerIain Buclaw <ibuclaw@gdcproject.org>
Thu, 30 Jul 2020 16:01:33 +0000 (18:01 +0200)
Generating calls to memset, memcpy, and memcmp is frequent enough that
it becomes beneficial to put them into their own routine.  All parts of
the front-end have been updated to call the new helper functions instead
of doing it themselves.

gcc/d/ChangeLog:

* d-codegen.cc (build_memcmp_call): New function.
(build_memcpy_call): New function.
(build_memset_call): New function.
(build_float_identity): Call build_memcmp_call.
(lower_struct_comparison): Likewise.
(build_struct_comparison): Likewise.
* d-tree.h (build_memcmp_call): Declare.
(build_memcpy_call): Declare.
(build_memset_call): Declare.
* expr.cc (ExprVisitor::visit (EqualExp *)): Call build_memcmp_call.
(ExprVisitor::visit (AssignExp *)): Call build_memset_call.
(ExprVisitor::visit (ArrayLiteralExp *)): Call build_memcpy_call.
(ExprVisitor::visit (StructLiteralExp *)): Call build_memset_call.

gcc/d/d-codegen.cc
gcc/d/d-tree.h
gcc/d/expr.cc

index cea47315d0e0387abe957b74c1351d8bc4524acf..a38aa6c55e036bc326cf8cd20dc370d391d8e19c 100644 (file)
@@ -794,6 +794,41 @@ d_mark_read (tree exp)
   return exp;
 }
 
+/* Build a call to memcmp(), compares the first NUM bytes of PTR1 with PTR2.  */
+
+tree
+build_memcmp_call (tree ptr1, tree ptr2, tree num)
+{
+  return build_call_expr (builtin_decl_explicit (BUILT_IN_MEMCMP), 3,
+                         ptr1, ptr2, num);
+}
+
+/* Build a call to memcpy(), copies the first NUM bytes of SRC into DST.  */
+
+tree
+build_memcpy_call (tree dst, tree src, tree num)
+{
+  return build_call_expr (builtin_decl_explicit (BUILT_IN_MEMCPY), 3,
+                         dst, src, num);
+}
+
+/* Build a call to memset(), fills the first NUM bytes of PTR with zeros.
+   If NUM is NULL, then we expect PTR to be object that requires filling.  */
+
+tree
+build_memset_call (tree ptr, tree num)
+{
+  if (num == NULL_TREE)
+    {
+      gcc_assert (TREE_CODE (ptr) != ADDR_EXPR);
+      num = TYPE_SIZE_UNIT (TREE_TYPE (ptr));
+      ptr = build_address (ptr);
+    }
+
+  return build_call_expr (builtin_decl_explicit (BUILT_IN_MEMSET), 3,
+                         ptr, integer_zero_node, num);
+}
+
 /* 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.  */
@@ -846,11 +881,9 @@ identity_compare_p (StructDeclaration *sd)
 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);
+  tree result = build_memcmp_call (build_address (t1),
+                                  build_address (t2), size);
   return build_boolop (code, result, integer_zero_node);
 }
 
@@ -879,10 +912,8 @@ lower_struct_comparison (tree_code code, StructDeclaration *sd,
   /* Let back-end take care of union comparisons.  */
   if (sd->isUnionDeclaration ())
     {
-      tmemcmp = build_call_expr (builtin_decl_explicit (BUILT_IN_MEMCMP), 3,
-                                build_address (t1), build_address (t2),
-                                size_int (sd->structsize));
-
+      tmemcmp = build_memcmp_call (build_address (t1), build_address (t2),
+                                  size_int (sd->structsize));
       return build_boolop (code, tmemcmp, integer_zero_node);
     }
 
@@ -943,11 +974,9 @@ lower_struct_comparison (tree_code code, StructDeclaration *sd,
          else
            {
              /* Simple memcmp between types.  */
-             tcmp = build_call_expr (builtin_decl_explicit (BUILT_IN_MEMCMP),
-                                     3, build_address (t1ref),
-                                     build_address (t2ref),
-                                     TYPE_SIZE_UNIT (stype));
-
+             tcmp = build_memcmp_call (build_address (t1ref),
+                                       build_address (t2ref),
+                                       TYPE_SIZE_UNIT (stype));
              tcmp = build_boolop (code, tcmp, integer_zero_node);
            }
        }
@@ -995,11 +1024,8 @@ build_struct_comparison (tree_code code, StructDeclaration *sd,
   else
     {
       /* Do bit compare of structs.  */
-      tree size = size_int (sd->structsize);
-      tree tmemcmp = build_call_expr (builtin_decl_explicit (BUILT_IN_MEMCMP),
-                                     3, build_address (t1),
-                                     build_address (t2), size);
-
+      tree tmemcmp = build_memcmp_call (build_address (t1), build_address (t2),
+                                       size_int (sd->structsize));
       result = build_boolop (code, tmemcmp, integer_zero_node);
     }
 
index d92418a55c9cea3558046585302c154d6c41df1a..48c8ef09dd183c8fca427aa2ac9c77edd001bbb7 100644 (file)
@@ -530,6 +530,9 @@ extern tree build_address (tree);
 extern tree d_mark_addressable (tree);
 extern tree d_mark_used (tree);
 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 bool identity_compare_p (StructDeclaration *);
 extern tree build_float_identity (tree_code, tree, tree);
 extern tree build_struct_comparison (tree_code, StructDeclaration *,
index ac9a2820112af19b9b489bca829841c0fc585be1..58d4943ef2b74e9df479354a298ff3a2d948f5f9 100644 (file)
@@ -378,9 +378,8 @@ public:
                || identity_compare_p (t1elem->isTypeStruct ()->sym))
              {
                tree size = size_mult_expr (t1len, size_int (t1elem->size ()));
-               tree tmemcmp = builtin_decl_explicit (BUILT_IN_MEMCMP);
 
-               result = build_call_expr (tmemcmp, 3, t1ptr, t2ptr, size);
+               result = build_memcmp_call (t1ptr, t2ptr, size);
                result = build_boolop (code, result, integer_zero_node);
              }
            else
@@ -948,12 +947,9 @@ public:
 
            if (integer_zerop (t2))
              {
-               tree tmemset = builtin_decl_explicit (BUILT_IN_MEMSET);
                tree size = size_mult_expr (d_array_length (t1),
                                            size_int (etype->size ()));
-
-               result = build_call_expr (tmemset, 3, d_array_ptr (t1),
-                                         integer_zero_node, size);
+               result = build_memset_call (d_array_ptr (t1), size);
              }
            else
              result = build_array_set (d_array_ptr (t1),
@@ -970,12 +966,10 @@ public:
              {
                tree t1 = d_save_expr (d_array_convert (e->e1));
                tree t2 = d_array_convert (e->e2);
-               tree tmemcpy = builtin_decl_explicit (BUILT_IN_MEMCPY);
                tree size = size_mult_expr (d_array_length (t1),
                                            size_int (etype->size ()));
-
-               tree result = build_call_expr (tmemcpy, 3, d_array_ptr (t1),
-                                              d_array_ptr (t2), size);
+               tree result = build_memcpy_call (d_array_ptr (t1),
+                                                d_array_ptr (t2), size);
                this->result_ = compound_expr (result, t1);
              }
            else if ((postblit || destructor) && e->op != TOKblit)
@@ -1042,9 +1036,7 @@ public:
          {
            /* Use memset to fill struct.  */
            gcc_assert (e->op == TOKblit);
-           tree tmemset = builtin_decl_explicit (BUILT_IN_MEMSET);
-           tree result = build_call_expr (tmemset, 3, build_address (t1),
-                                          t2, size_int (sd->structsize));
+           tree result = build_memset_call (t1);
 
            /* Maybe set-up hidden pointer to outer scope context.  */
            if (sd->isNested ())
@@ -1065,12 +1057,7 @@ public:
 
            /* 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));
-             }
+             init = build_memset_call (t1);
 
            tree result = build_assign (modifycode, t1, t2);
            this->result_ = compound_expr (init, result);
@@ -1087,15 +1074,7 @@ public:
          {
            /* Use memset to fill the array.  */
            gcc_assert (e->op == TOKblit);
-
-           tree t1 = build_expr (e->e1);
-           tree t2 = convert_for_assignment (build_expr (e->e2),
-                                             e->e2->type, e->e1->type);
-           tree size = size_int (e->e1->type->size ());
-
-           tree tmemset = builtin_decl_explicit (BUILT_IN_MEMSET);
-           this->result_ = build_call_expr (tmemset, 3, build_address (t1),
-                                            t2, size);
+           this->result_ = build_memset_call (build_expr (e->e1));
            return;
          }
 
@@ -2753,12 +2732,10 @@ public:
        mem = d_save_expr (mem);
 
        /* Now copy the constructor into memory.  */
-       tree tmemcpy = builtin_decl_explicit (BUILT_IN_MEMCPY);
        tree size = size_mult_expr (size_int (e->elements->length),
                                    size_int (tb->nextOf ()->size ()));
 
-       tree result = build_call_expr (tmemcpy, 3, mem,
-                                      build_address (ctor), size);
+       tree result = build_memcpy_call (mem, build_address (ctor), size);
 
        /* Return the array pointed to by MEM.  */
        result = compound_expr (result, mem);
@@ -2935,10 +2912,7 @@ public:
       {
        /* For unions, use memset to fill holes in the object.  */
        tree var = build_local_temp (TREE_TYPE (ctor));
-       tree tmemset = builtin_decl_explicit (BUILT_IN_MEMSET);
-       tree init = build_call_expr (tmemset, 3, build_address (var),
-                                    size_zero_node,
-                                    size_int (e->sd->structsize));
+       tree init = build_memset_call (var);
 
        init = compound_expr (init, saved_elems);
        init = compound_expr (init, modify_expr (var, ctor));