@@ -2158,6 +2158,20 @@ expand_used_vars (bitmap forced_stack_vars)
frame_phase = off ? align - off : 0;
}
+ /* Mark VARs on returns. */
+ if (DECL_RESULT (current_function_decl))
+ {
+ edge_iterator ei;
+ edge e;
+ FOR_EACH_EDGE (e, ei, EXIT_BLOCK_PTR_FOR_FN (cfun)->preds)
+ if (greturn *ret = safe_dyn_cast<greturn *> (last_stmt (e->src)))
+ {
+ tree val = gimple_return_retval (ret);
+ if (val && VAR_P (val))
+ DECL_USEDBY_RETURN_P (val) = 1;
+ }
+ }
+
/* Set TREE_USED on all variables in the local_decls. */
FOR_EACH_LOCAL_DECL (cfun, i, var)
TREE_USED (var) = 1;
@@ -6115,6 +6115,19 @@ expand_assignment (tree to, tree from, bool nontemporal)
return;
}
+ /* If it is assigning to a struct var which will be returned, and the
+ function is returning via registers, it would be better to use the
+ register's mode to move sub-blocks for the assignment. */
+ if (VAR_P (to) && DECL_USEDBY_RETURN_P (to) && mode == BLKmode
+ && TREE_CODE (from) != CONSTRUCTOR
+ && GET_CODE (DECL_RTL (DECL_RESULT (current_function_decl))) == PARALLEL)
+ {
+ rtx ret = DECL_RTL (DECL_RESULT (current_function_decl));
+ machine_mode sub_mode = GET_MODE (XEXP (XVECEXP (ret, 0, 0), 0));
+ move_sub_blocks (to_rtx, from, sub_mode, nontemporal);
+ return;
+ }
+
/* Compute FROM and store the value in the rtx we got. */
push_temp_slots ();
@@ -1808,7 +1808,8 @@ struct GTY(()) tree_decl_common {
In VAR_DECL, PARM_DECL and RESULT_DECL, this is
DECL_HAS_VALUE_EXPR_P. */
unsigned decl_flag_2 : 1;
- /* In FIELD_DECL, this is DECL_PADDING_P. */
+ /* In FIELD_DECL, this is DECL_PADDING_P
+ In VAR_DECL, this is DECL_USEDBY_RETURN_P. */
unsigned decl_flag_3 : 1;
/* Logically, these two would go in a theoretical base shared by var and
parm decl. */
@@ -3007,6 +3007,10 @@ extern void decl_value_expr_insert (tree, tree);
#define DECL_PADDING_P(NODE) \
(FIELD_DECL_CHECK (NODE)->decl_common.decl_flag_3)
+/* Used in a VAR_DECL to indicate that it is used by a return stmt. */
+#define DECL_USEDBY_RETURN_P(NODE) \
+ (VAR_DECL_CHECK (NODE)->decl_common.decl_flag_3)
+
/* Used in a FIELD_DECL to indicate whether this field is not a flexible
array member. This is only valid for the last array type field of a
structure. */