static unsigned int execute_return_slot_opt (void) { basic_block bb; FOR_EACH_BB (bb) { block_stmt_iterator i; for (i = bsi_start (bb); !bsi_end_p (i); bsi_next (&i)) { tree stmt = bsi_stmt (i); tree call; if (TREE_CODE (stmt) == MODIFY_EXPR && (call = TREE_OPERAND (stmt, 1), TREE_CODE (call) == CALL_EXPR) && !CALL_EXPR_RETURN_SLOT_OPT (call) && aggregate_value_p (call, call)) /* Check if the location being assigned to is call-clobbered. */ CALL_EXPR_RETURN_SLOT_OPT (call) = dest_safe_for_nrv_p (TREE_OPERAND (stmt, 0)) ? 1 : 0; } } return 0; }
static unsigned int execute_return_slot_opt (void) { basic_block bb; FOR_EACH_BB_FN (bb, cfun) { gimple_stmt_iterator gsi; for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) { gimple stmt = gsi_stmt (gsi); bool slot_opt_p; if (is_gimple_call (stmt) && gimple_call_lhs (stmt) && !gimple_call_return_slot_opt_p (stmt) && aggregate_value_p (TREE_TYPE (gimple_call_lhs (stmt)), gimple_call_fndecl (stmt))) { /* Check if the location being assigned to is clobbered by the call. */ slot_opt_p = dest_safe_for_nrv_p (stmt); gimple_call_set_return_slot_opt (stmt, slot_opt_p); } } }
static bool dest_safe_for_nrv_p (tree dest) { switch (TREE_CODE (dest)) { case VAR_DECL: { subvar_t subvar; if (is_call_clobbered (dest)) return false; for (subvar = get_subvars_for_var (dest); subvar; subvar = subvar->next) if (is_call_clobbered (subvar->var)) return false; return true; } case ARRAY_REF: case COMPONENT_REF: return dest_safe_for_nrv_p (TREE_OPERAND (dest, 0)); default: return false; } }