[gcc r14-6182] middle-end/112830 - avoid gimplifying non-default addr-space assign to memcpy

Richard Biener rguenth@gcc.gnu.org
Tue Dec 5 13:55:48 GMT 2023


https://gcc.gnu.org/g:68d32d02035fc081384ec6d6fd275e49ffa5d016

commit r14-6182-g68d32d02035fc081384ec6d6fd275e49ffa5d016
Author: Richard Biener <rguenther@suse.de>
Date:   Mon Dec 4 10:35:38 2023 +0100

    middle-end/112830 - avoid gimplifying non-default addr-space assign to memcpy
    
    The following avoids turning aggregate copy involving non-default
    address-spaces to memcpy since that is not prepared for that.
    
    GIMPLE verification no longer accepts WITH_SIZE_EXPR in aggregate
    copies, the following re-allows that for the RHS.  I also needed
    to adjust one assert in DCE.
    
    get_memory_address is used for string builtin expansion, so instead
    of fixing that up for non-generic address-spaces I've put an assert
    there.
    
    I'll note that the same issue exists for initialization from an
    empty CTOR which we gimplify to a memset call but since we are
    not prepared to handle RTL expansion of the original VLA init and
    I failed to provide test coverage (without extending the GNU C
    extension for VLA structs) and the Ada frontend (or other frontends)
    to not have address-space support the patch instead asserts we only
    see generic address-spaces there.
    
            PR middle-end/112830
            * gimplify.cc (gimplify_modify_expr): Avoid turning aggregate
            copy of non-generic address-spaces to memcpy.
            (gimplify_modify_expr_to_memcpy): Assert we are dealing with
            a copy inside the generic address-space.
            (gimplify_modify_expr_to_memset): Likewise.
            * tree-cfg.cc (verify_gimple_assign_single): Allow
            WITH_SIZE_EXPR as part of the RHS of an assignment.
            * builtins.cc (get_memory_address): Assert we are dealing
            with the generic address-space.
            * tree-ssa-dce.cc (ref_may_be_aliased): Handle WITH_SIZE_EXPR.
    
            * gcc.target/avr/pr112830.c: New testcase.
            * gcc.target/i386/pr112830.c: Likewise.

Diff:
---
 gcc/builtins.cc                          |  3 +++
 gcc/gimplify.cc                          |  8 ++++++--
 gcc/testsuite/gcc.target/avr/pr112830.c  | 12 ++++++++++++
 gcc/testsuite/gcc.target/i386/pr112830.c |  9 +++++++++
 gcc/tree-cfg.cc                          | 16 ++++++++++------
 gcc/tree-ssa-dce.cc                      |  3 ++-
 6 files changed, 42 insertions(+), 9 deletions(-)

diff --git a/gcc/builtins.cc b/gcc/builtins.cc
index 4fc58a0bda9..aa86ac1545d 100644
--- a/gcc/builtins.cc
+++ b/gcc/builtins.cc
@@ -1347,6 +1347,9 @@ get_memory_rtx (tree exp, tree len)
   tree orig_exp = exp, base;
   rtx addr, mem;
 
+  gcc_checking_assert
+    (ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (exp)))));
+
   /* When EXP is not resolved SAVE_EXPR, MEM_ATTRS can be still derived
      from its expression, for expr->a.b only <variable>.a.b is recorded.  */
   if (TREE_CODE (exp) == SAVE_EXPR && !SAVE_EXPR_RESOLVED_P (exp))
diff --git a/gcc/gimplify.cc b/gcc/gimplify.cc
index 02f85e7109b..342e43a7f25 100644
--- a/gcc/gimplify.cc
+++ b/gcc/gimplify.cc
@@ -4887,6 +4887,8 @@ gimplify_modify_expr_to_memcpy (tree *expr_p, tree size, bool want_value,
 
   to = TREE_OPERAND (*expr_p, 0);
   from = TREE_OPERAND (*expr_p, 1);
+  gcc_assert (ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (TREE_TYPE (to)))
+	      && ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (TREE_TYPE (from))));
 
   /* Mark the RHS addressable.  Beware that it may not be possible to do so
      directly if a temporary has been created by the gimplification.  */
@@ -4945,6 +4947,7 @@ gimplify_modify_expr_to_memset (tree *expr_p, tree size, bool want_value,
 
   /* Now proceed.  */
   to = TREE_OPERAND (*expr_p, 0);
+  gcc_assert (ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (TREE_TYPE (to))));
 
   to_ptr = build_fold_addr_expr_loc (loc, to);
   gimplify_arg (&to_ptr, seq_p, loc);
@@ -6466,8 +6469,9 @@ gimplify_modify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
 
       if (TREE_CODE (from) == CONSTRUCTOR)
 	return gimplify_modify_expr_to_memset (expr_p, size, want_value, pre_p);
-
-      if (is_gimple_addressable (from))
+      else if (is_gimple_addressable (from)
+	       && ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (TREE_TYPE (*to_p)))
+	       && ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (TREE_TYPE (from))))
 	{
 	  *from_p = from;
 	  return gimplify_modify_expr_to_memcpy (expr_p, size, want_value,
diff --git a/gcc/testsuite/gcc.target/avr/pr112830.c b/gcc/testsuite/gcc.target/avr/pr112830.c
new file mode 100644
index 00000000000..c305daed06c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/avr/pr112830.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "" } */
+
+typedef __SIZE_TYPE__ size_t;
+
+void copy_n (void *vdst, const __memx void *vsrc, size_t n)
+{
+  typedef struct { char a[n]; } T;
+  T *dst = (T*) vdst;
+  const __memx T *src = (const __memx T*) vsrc;
+  *dst = *src;
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr112830.c b/gcc/testsuite/gcc.target/i386/pr112830.c
new file mode 100644
index 00000000000..2ba610404bf
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr112830.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "" } */
+
+void
+foo (int n, __seg_fs void *p, __seg_gs void *q)
+{
+  typedef struct { char t[n]; } T;
+  *(__seg_fs T *)p = *(__seg_gs T *)q;
+}
diff --git a/gcc/tree-cfg.cc b/gcc/tree-cfg.cc
index 475ea5d99ef..5400805f51a 100644
--- a/gcc/tree-cfg.cc
+++ b/gcc/tree-cfg.cc
@@ -4673,6 +4673,16 @@ verify_gimple_assign_single (gassign *stmt)
       error ("%qs in gimple IL", code_name);
       return true;
 
+    case WITH_SIZE_EXPR:
+      if (!is_gimple_val (TREE_OPERAND (rhs1, 1)))
+	{
+	  error ("invalid %qs size argument in load", code_name);
+	  debug_generic_stmt (lhs);
+	  debug_generic_stmt (rhs1);
+	  return true;
+	}
+      rhs1 = TREE_OPERAND (rhs1, 0);
+      /* Fallthru.  */
     case COMPONENT_REF:
     case BIT_FIELD_REF:
     case ARRAY_REF:
@@ -4810,12 +4820,6 @@ verify_gimple_assign_single (gassign *stmt)
 	}
       return res;
 
-    case WITH_SIZE_EXPR:
-      error ("%qs RHS in assignment statement",
-	     get_tree_code_name (rhs_code));
-      debug_generic_expr (rhs1);
-      return true;
-
     case OBJ_TYPE_REF:
       /* FIXME.  */
       return res;
diff --git a/gcc/tree-ssa-dce.cc b/gcc/tree-ssa-dce.cc
index bbdf9312c9f..4e371b21a90 100644
--- a/gcc/tree-ssa-dce.cc
+++ b/gcc/tree-ssa-dce.cc
@@ -469,7 +469,8 @@ find_obviously_necessary_stmts (bool aggressive)
 static bool
 ref_may_be_aliased (tree ref)
 {
-  gcc_assert (TREE_CODE (ref) != WITH_SIZE_EXPR);
+  if (TREE_CODE (ref) == WITH_SIZE_EXPR)
+    ref = TREE_OPERAND (ref, 0);
   while (handled_component_p (ref))
     ref = TREE_OPERAND (ref, 0);
   if ((TREE_CODE (ref) == MEM_REF || TREE_CODE (ref) == TARGET_MEM_REF)


More information about the Gcc-cvs mailing list