From 637548dc5e5b11748b901b39738d8084b948ba1a Mon Sep 17 00:00:00 2001 From: Michael Beck Date: Thu, 5 Jun 2008 19:41:37 +0000 Subject: [PATCH] - BugFix: do NOT do the copy-return optimization if there might be access to the destination. This fixed fehler110.c [r19988] --- ir/lower/lower_calls.c | 83 ++++++++++++++++++++++++++---------------- 1 file changed, 51 insertions(+), 32 deletions(-) diff --git a/ir/lower/lower_calls.c b/ir/lower/lower_calls.c index 6b4d41052..c1ec226b5 100644 --- a/ir/lower/lower_calls.c +++ b/ir/lower/lower_calls.c @@ -201,14 +201,15 @@ struct cl_entry { * Walker environment for fix_args_and_collect_calls(). */ typedef struct _wlk_env_t { - int arg_shift; /**< The Argument index shift for parameters. */ - int first_hidden; /**< The index of the first hidden argument. */ - struct obstack obst; /**< An obstack to allocate the data on. */ - cl_entry *cl_list; /**< The call list. */ - pmap *dummy_map; /**< A map for finding the dummy arguments. */ - unsigned dnr; /**< The dummy index number. */ - const lower_params_t *params; /**< lowering parameters */ - int changed; /**< set if the current graph was changed */ + int arg_shift; /**< The Argument index shift for parameters. */ + int first_hidden; /**< The index of the first hidden argument. */ + struct obstack obst; /**< An obstack to allocate the data on. */ + cl_entry *cl_list; /**< The call list. */ + pmap *dummy_map; /**< A map for finding the dummy arguments. */ + unsigned dnr; /**< The dummy index number. */ + const lower_params_t *params; /**< Lowering parameters. */ + unsigned non_local_mem:1; /**< Set if non-local memory access was found. */ + unsigned changed:1; /**< Set if the current graph was changed. */ } wlk_env; /** @@ -240,9 +241,16 @@ static void fix_args_and_collect_calls(ir_node *n, void *ctx) { wlk_env *env = ctx; int i; ir_type *ctp; - ir_op *op = get_irn_op(n); + ir_opcode code = get_irn_opcode(n); - if (env->arg_shift > 0 && op == op_Proj) { + if (code == iro_Load || code == iro_Store) { + ir_node *ptr = get_irn_n(n, 1); + + if (! is_Sel(ptr)) + env->non_local_mem = 1; + else if (get_Sel_ptr(ptr) != get_irg_frame(current_ir_graph)) + env->non_local_mem = 1; + } else if (env->arg_shift > 0 && code == iro_Proj) { ir_node *pred = get_Proj_pred(n); /* Fix the argument numbers */ @@ -251,7 +259,7 @@ static void fix_args_and_collect_calls(ir_node *n, void *ctx) { set_Proj_proj(n, pnr + env->arg_shift); env->changed = 1; } - } else if (op == op_Call) { + } else if (code == iro_Call) { ctp = get_Call_type(n); if (env->params->flags & LF_COMPOUND_RETURN) { /* check for compound returns */ @@ -266,7 +274,7 @@ static void fix_args_and_collect_calls(ir_node *n, void *ctx) { } } } - } else if (op == op_CopyB && env->params->flags & LF_COMPOUND_RETURN) { + } else if (code == iro_CopyB && env->params->flags & LF_COMPOUND_RETURN) { /* check for compound returns */ ir_node *src = get_CopyB_src(n); /* older scheme using value_res_ent */ @@ -281,7 +289,7 @@ static void fix_args_and_collect_calls(ir_node *n, void *ctx) { e->copyb = n; } } - } else + } else { /* new scheme: compound results are determined by the call type only */ if (is_Proj(src)) { ir_node *proj = get_Proj_pred(src); @@ -298,6 +306,7 @@ static void fix_args_and_collect_calls(ir_node *n, void *ctx) { } } } + } } } @@ -423,11 +432,10 @@ static void add_hidden_param(ir_graph *irg, int n_com, ir_node **ins, cl_entry * if (get_struct_member(owner, idx) == ent) break; assert(idx < get_struct_n_members(owner)); - } - else - + } else { /* new scheme: compound returns are determined by the call type and are Proj's */ idx = get_Proj_proj(src); + } ins[idx] = get_CopyB_dst(p); mem = get_CopyB_mem(p); @@ -526,14 +534,17 @@ static void fix_call_list(ir_graph *irg, wlk_env *env) { */ static void transform_irg(const lower_params_t *lp, ir_graph *irg) { - ir_entity *ent = get_irg_entity(irg); - ir_type *mtp, *lowered_mtp, *tp, *ft; - int i, j, k, n_ress = 0, n_ret_com = 0, n_cr_opt; - ir_node **new_in, *ret, *endbl, *bl, *mem, *copy; - cr_pair *cr_opt; - wlk_env env; + ir_graph * rem = current_ir_graph; + ir_entity *ent = get_irg_entity(irg); + ir_type *mtp, *lowered_mtp, *tp, *ft; + int i, j, k, n_ress = 0, n_ret_com = 0, n_cr_opt; + ir_node **new_in, *ret, *endbl, *bl, *mem, *copy; + cr_pair *cr_opt; + wlk_env env; add_hidden hidden_params; + current_ir_graph = irg; + assert(ent && "Cannot transform graph without an entity"); assert(get_irg_phase_state(irg) == phase_high && "call lowering must be done in phase high"); @@ -567,8 +578,7 @@ static void transform_irg(const lower_params_t *lp, ir_graph *irg) /* hidden arguments are added first */ env.arg_shift = n_ret_com; env.first_hidden = 0; - } - else { + } else { /* hidden arguments are added last */ env.arg_shift = 0; env.first_hidden = get_method_n_params(mtp); @@ -578,11 +588,12 @@ static void transform_irg(const lower_params_t *lp, ir_graph *irg) env.arg_shift = 0; } obstack_init(&env.obst); - env.cl_list = NULL; - env.dummy_map = pmap_create_ex(8); - env.dnr = 0; - env.params = lp; - env.changed = 0; + env.cl_list = NULL; + env.dummy_map = pmap_create_ex(8); + env.dnr = 0; + env.params = lp; + env.non_local_mem = 0; + env.changed = 0; /* scan the code, fix argument numbers and collect calls. */ irg_walk_graph(irg, firm_clear_link, fix_args_and_collect_calls, &env); @@ -595,8 +606,8 @@ static void transform_irg(const lower_params_t *lp, ir_graph *irg) if (n_ret_com) { /* - * Now fix the Return node of the current graph. - */ + * Now fix the Return node of the current graph. + */ env.changed = 1; /* STEP 1: find the return. This is simple, we have normalized the graph. */ @@ -638,7 +649,14 @@ static void transform_irg(const lower_params_t *lp, ir_graph *irg) /* The Return(Unknown) is the Firm construct for a missing return. Do nothing. */ } else { - if (is_compound_address(ft, pred)) { + /** + * Sorrily detecting that copy-return is possible isn't that simple. + * We must check, that the hidden address is alias free during the whole + * function. + * A simple heuristic: all Loads/Stores inside + * the function access only local frame. + */ + if (!env.non_local_mem && is_compound_address(ft, pred)) { /* we can do the copy-return optimization here */ cr_opt[n_cr_opt].ent = get_Sel_entity(pred); cr_opt[n_cr_opt].arg = arg; @@ -684,6 +702,7 @@ static void transform_irg(const lower_params_t *lp, ir_graph *irg) set_irg_outs_inconsistent(irg); set_irg_loopinfo_state(irg, loopinfo_inconsistent); } + current_ir_graph = rem; } /** -- 2.20.1