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. Bootstrapped and tested on x86_64-unknown-linux-gnu for all languages. OK? Thanks, Richard. 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. * gcc.target/avr/pr112830.c: New testcase. * gcc.target/i386/pr112830.c: Likewise. --- 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(-) create mode 100644 gcc/testsuite/gcc.target/avr/pr112830.c create mode 100644 gcc/testsuite/gcc.target/i386/pr112830.c 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) -- 2.35.3