diff options
Diffstat (limited to 'gcc/gimplify.c')
-rw-r--r-- | gcc/gimplify.c | 22 |
1 files changed, 20 insertions, 2 deletions
diff --git a/gcc/gimplify.c b/gcc/gimplify.c index 2bf213c24e7..897c185c143 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -3314,6 +3314,21 @@ gimplify_init_constructor (tree *expr_p, tree *pre_p, } } + /* If the target is volatile and we have non-zero elements + initialize the target from a temporary. */ + if (TREE_THIS_VOLATILE (object) + && !TREE_ADDRESSABLE (type) + && num_nonzero_elements > 0) + { + tree temp = create_tmp_var (TYPE_MAIN_VARIANT (type), NULL); + TREE_OPERAND (*expr_p, 0) = temp; + *expr_p = build2 (COMPOUND_EXPR, TREE_TYPE (*expr_p), + *expr_p, + build2 (MODIFY_EXPR, void_type_node, + object, temp)); + return GS_OK; + } + if (notify_temp_creation) return GS_OK; @@ -3551,11 +3566,14 @@ gimplify_modify_expr_rhs (tree *expr_p, tree *from_p, tree *to_p, tree *pre_p, switch (TREE_CODE (*from_p)) { case VAR_DECL: - /* If we're assigning from a constant constructor, move the - constructor expression to the RHS of the MODIFY_EXPR. */ + /* If we're assigning from a read-only variable initialized with + a constructor, do the direct assignment from the constructor, + but only if neither source nor target are volatile since this + latter assignment might end up being done on a per-field basis. */ if (DECL_INITIAL (*from_p) && TREE_READONLY (*from_p) && !TREE_THIS_VOLATILE (*from_p) + && !TREE_THIS_VOLATILE (*to_p) && TREE_CODE (DECL_INITIAL (*from_p)) == CONSTRUCTOR) { tree old_from = *from_p; |