[PATCH][C++] Remove last use of can_trust_pointer_alignment

Richard Guenther rguenther@suse.de
Wed Aug 10 11:42:00 GMT 2011


Nothing in the middle-end happens conditional on 
can_trust_pointer_alignment anymore - we can always "trust" pointer
alignment, that function and its comment is somewhat gross.
In fact we can now track alignment properly via CCP and thus
the hack in cfgexpand.c:expand_call_stmt should not be neccessary
anymore.

Now, looking at the use of can_trust_pointer_alignment in build_over_call
and especially its comment:

          if (!can_trust_pointer_alignment ())
            {
              /* If we can't be sure about pointer alignment, a call
                 to __builtin_memcpy is expanded as a call to memcpy, which
                 is invalid with identical args.  Otherwise it is
                 expanded as a block move, which should be safe.  */
              arg0 = save_expr (arg0);
              arg1 = save_expr (arg1);
              test = build2 (EQ_EXPR, boolean_type_node, arg0, arg1);
            }

"Otherwise it is expanded as a block move" is certainly not true.
Whether it is expanded as block move depends on optimization setting,
target costs and, well, a way to do block moves (we fall back to
memcpy after all).

So the patch changes the above to if (!optimize), but I'd argue
we can as well either remove the conditional or emit it unconditional.
Dependent on whether we believe a memcpy implementation exists in
the wild that asserts that src != dst.

Independent of the can_trust_pointer_alignment issue nowadays the
case of !tree_int_cst_equal (TYPE_SIZE (type), TYPE_SIZE (as_base))
should use a MODIFY_EXPR with two MEM_REF operands and a proper
alias set, which would avoid the address-taking (and thus aliasing)
because of the memcpy and also would avoid forcing alias-set zero
because of the memcpy.

Thus (untested), something like

Index: gcc/cp/call.c
===================================================================
--- gcc/cp/call.c       (revision 177597)
+++ gcc/cp/call.c       (working copy)
@@ -6379,35 +6379,21 @@ build_over_call (struct z_candidate *can
        }
       else
        {
-         /* We must only copy the non-tail padding parts.
-            Use __builtin_memcpy for the bitwise copy.
-            FIXME fix 22488 so we can go back to using MODIFY_EXPR
-            instead of an explicit call to memcpy.  */
-
-         tree arg0, arg1, arg2, t;
+         /* We must only copy the non-tail padding parts.  */
+         tree arg0, arg2, t;
          tree test = NULL_TREE;
 
          arg2 = TYPE_SIZE_UNIT (as_base);
-         arg1 = arg;
          arg0 = cp_build_addr_expr (to, complain);
 
-         if (!can_trust_pointer_alignment ())
-           {
-             /* If we can't be sure about pointer alignment, a call
-                to __builtin_memcpy is expanded as a call to memcpy, 
which
-                is invalid with identical args.  Otherwise it is
-                expanded as a block move, which should be safe.  */
-             arg0 = save_expr (arg0);
-             arg1 = save_expr (arg1);
-             test = build2 (EQ_EXPR, boolean_type_node, arg0, arg1);
-           }
-         t = implicit_built_in_decls[BUILT_IN_MEMCPY];
-         t = build_call_n (t, 3, arg0, arg1, arg2);
-
-         t = convert (TREE_TYPE (arg0), t);
-         if (test)
-           t = build3 (COND_EXPR, TREE_TYPE (t), test, arg0, t);
-         val = cp_build_indirect_ref (t, RO_NULL, complain);
+         t = build_array_type (char_type_node, build_index_type (arg2));
+         t = build2 (MODIFY_EXPR, void_type_node,
+                     build2 (MEM_REF, t, to,
+                             build_int_cst (build_pointer_type (type), 
0)),
+                     build2 (MEM_REF, t, arg,
+                             build_int_cst (build_pointer_type (type), 
0)));
+         val = build2 (COMPOUND_EXPR, TREE_TYPE (to),
+                       t, to);
           TREE_NO_WARNING (val) = 1;
        }
 
which does a block copy of size arg2 (by using a char[arg2] array
a type for the mem-ref) using the alias-set of type (by
specifying the offset of the mem-ref with using a type of type *).

Well, but I'm bootstrapping and testing the following now, on
x86_64-unknown-linux-gnu (because I want to get rid of
that can_trust_pointer_alignment function).

Ok for trunk?

Thanks,
Richard.

2011-08-10  Richard Guenther  <rguenther@suse.de>

	cp/
	* call.c (build_over_call): Check for optimize instead of
	can_trust_pointer_alignment.  Adjust comment.

Index: gcc/cp/call.c
===================================================================
--- gcc/cp/call.c	(revision 177613)
+++ gcc/cp/call.c	(working copy)
@@ -6778,12 +6778,14 @@ build_over_call (struct z_candidate *can
 	  arg1 = arg;
 	  arg0 = cp_build_addr_expr (to, complain);
 
-	  if (!can_trust_pointer_alignment ())
+	  if (!optimize)
 	    {
-	      /* If we can't be sure about pointer alignment, a call
-		 to __builtin_memcpy is expanded as a call to memcpy, which
-		 is invalid with identical args.  Otherwise it is
-		 expanded as a block move, which should be safe.  */
+	      /* If we are not optimizing, a call to __builtin_memcpy is
+		 expanded as a call to memcpy, which is invalid with identical
+		 args.  Otherwise it is expanded as a block move, which should
+		 be safe.  */
+	      /* ???  It is of course only sometimes expanded as a block
+		 move.  */
 	      arg0 = save_expr (arg0);
 	      arg1 = save_expr (arg1);
 	      test = build2 (EQ_EXPR, boolean_type_node, arg0, arg1);



More information about the Gcc-patches mailing list