From ee44e33167b44432066f2ca6c7e413daa1949280 Mon Sep 17 00:00:00 2001 From: Michael Beck Date: Tue, 20 Jan 2009 01:20:48 +0000 Subject: [PATCH] - fixed handling of outer frame access [r25277] --- ir/ana/analyze_irg_args.c | 108 +++++++++++++++++++++++++++++++++++++- ir/be/beabi.c | 88 ++++++++++++++++++++++++------- ir/opt/gvn_pre.c | 7 +-- 3 files changed, 180 insertions(+), 23 deletions(-) diff --git a/ir/ana/analyze_irg_args.c b/ir/ana/analyze_irg_args.c index 305475641..a40cc6ab2 100644 --- a/ir/ana/analyze_irg_args.c +++ b/ir/ana/analyze_irg_args.c @@ -20,19 +20,21 @@ /** * @file * @brief read/write analyze of graph argument, which have mode reference. - * @author Beyhan Veliev + * @author Beyhan Veliev, Michael Beck * @version $Id$ */ #include "config.h" #include +#include "adt/raw_bitset.h" #include "irouts.h" #include "irnode_t.h" #include "irmode_t.h" #include "array_t.h" #include "irprog.h" #include "entity_t.h" +#include "irgwalk.h" #include "analyze_irg_args.h" @@ -493,6 +495,110 @@ unsigned get_method_param_weight(ir_entity *ent, int pos) return null_weight; } +typedef struct walk_env { + unsigned *marks; /**< raw bitset for nodes that could be analysed */ + unsigned *param_mask; /**< raw bitset of constant parameters */ + unsigned mask_len; /**< length of the parameter bitmask */ + unsigned weight; /**< the accumulated weight */ +} walk_env; + +/** + * Walker, evaluates possible constant folding + */ +static void evaluate_weight(ir_node *irn, void *ctx) { + walk_env *env = ctx; + int i, n; + ir_node *ptr; + + if (is_arg_Proj(irn)) { + unsigned argnum = (unsigned)get_Proj_proj(irn); + + if (argnum < env->mask_len) { + if (rbitset_is_set(env->param_mask, argnum)) { + /* is a constant parameter */ + rbitset_set(env->marks, get_irn_idx(irn)); + } + } + return; + } + if (is_irn_constlike(irn)) { + /* is a constant by itself */ + rbitset_set(env->marks, get_irn_idx(irn)); + return; + } + + if (is_Block(irn)) + return; + + /* handle some special cases */ + switch (get_irn_opcode(irn)) { + case iro_Div: + case iro_Quot: + case iro_Mod: + case iro_DivMod: + /* skip the memory input of these nodes */ + assert(pn_Generic_M_regular == 0); + n = 1; + break; + case iro_Call: + ptr = get_Call_ptr(irn); + if (! is_SymConst(ptr) && rbitset_is_set(env->marks, get_irn_idx(ptr))) { + /* the arguments is used as an pointer input for a call, + we can probably change an indirect Call into a direct one. */ + env->weight += indirect_call_weight; + } + n = 2; + break; + default: + n = 0; + break; + } + for (i = get_irn_arity(irn) - 1; i >= n; --i) { + ir_node *pred = get_irn_n(irn, i); + + if (! rbitset_is_set(env->marks, get_irn_idx(pred))) { + /* not constant predecessor ... */ + return; + } + } + + /* all predecessors are constant, we probably can fold this node */ + rbitset_set(env->marks, get_irn_idx(irn)); + + if (is_binop(irn)) { + env->weight += const_binop_weight; + } else if (is_unop(irn)) { + env->weight += const_binop_weight; + } else if (is_Proj(irn)) { + ir_node *pred = get_Proj_pred(irn); + if (is_Cmp(pred)) { + env->weight += const_cmp_weight; + } else if (is_Cond(pred)) { + /* the argument is used for a SwitchCond, a big win */ + env->weight += const_cmp_weight; + } + } +} + +/** + * + */ +unsigned analyze_irg_param_weights(ir_graph *irg, unsigned *bitmask, unsigned len) { + unsigned nodes = get_irg_last_idx(irg); + unsigned *marks = rbitset_malloc(nodes); + walk_env env; + + env.marks = marks; + env.param_mask = bitmask; + env.mask_len = len; + env.weight = null_weight; + + irg_walk_graph(irg, NULL, evaluate_weight, &env); + + xfree(marks); + return env.weight; +} + /** * Analyze argument's weight of a given * ir graph. diff --git a/ir/be/beabi.c b/ir/be/beabi.c index e9ee9d66d..3c0125607 100644 --- a/ir/be/beabi.c +++ b/ir/be/beabi.c @@ -1741,9 +1741,12 @@ static void fix_start_block(ir_graph *irg) panic("Initial exec has no follow block in %+F", irg); } -static void lower_outer_frame_sels(ir_node *irn, void *env) { +/** + * Update the entity of Sels to the outer value parameters. + */ +static void update_outer_frame_sels(ir_node *irn, void *env) { lower_frame_sels_env_t *ctx = env; - ir_node *ptr, *bl, *nw; + ir_node *ptr; ir_entity *ent; int pos = 0; @@ -1760,21 +1763,19 @@ static void lower_outer_frame_sels(ir_node *irn, void *env) { /* replace by its copy from the argument type */ pos = get_struct_member_index(ctx->value_tp, ent); ent = get_argument_entity(ent, ctx); - } - bl = get_nodes_block(irn); - nw = be_new_FrameAddr(ctx->link_class, current_ir_graph, bl, ptr, ent); - exchange(irn, nw); - - /* check, if it's a param sel and if have not seen this entity before */ - if (get_entity_owner(ent) == ctx->value_tp && get_entity_link(ent) == NULL) { - ent_pos_pair pair; - - pair.ent = ent; - pair.pos = pos; - pair.next = NULL; - ARR_APP1(ent_pos_pair, ctx->value_param_list, pair); - /* just a mark */ - set_entity_link(ent, ctx->value_param_list); + set_Sel_entity(irn, ent); + + /* check, if we have not seen this entity before */ + if (get_entity_link(ent) == NULL) { + ent_pos_pair pair; + + pair.ent = ent; + pair.pos = pos; + pair.next = NULL; + ARR_APP1(ent_pos_pair, ctx->value_param_list, pair); + /* just a mark */ + set_entity_link(ent, ctx->value_param_list); + } } } @@ -1799,7 +1800,7 @@ static void fix_outer_variable_access(be_abi_irg_t *env, lower_frame_sels_env_t ctx->static_link_pos = 0; irg = get_entity_irg(ent); - irg_walk_graph(irg, NULL, lower_outer_frame_sels, ctx); + irg_walk_graph(irg, NULL, update_outer_frame_sels, ctx); } } @@ -2598,9 +2599,45 @@ static void stack_bias_walker(ir_node *bl, void *data) } } +/** + * Walker: finally lower all Sels of outer frame or parameter + * entities. + */ +static void lower_outer_frame_sels(ir_node *sel, void *ctx) { + be_abi_irg_t *env = ctx; + ir_node *ptr; + ir_entity *ent; + ir_type *owner; + + if (! is_Sel(sel)) + return; + + ent = get_Sel_entity(sel); + owner = get_entity_owner(ent); + ptr = get_Sel_ptr(sel); + + if (owner == env->frame.frame_type || owner == env->frame.arg_type) { + /* found access to outer frame or arguments */ + int offset = get_stack_entity_offset(&env->frame, ent, 0); + + if (offset != 0) { + ir_node *bl = get_nodes_block(sel); + dbg_info *dbgi = get_irn_dbg_info(sel); + ir_mode *mode = get_irn_mode(sel); + ir_mode *mode_UInt = get_reference_mode_unsigned_eq(mode); + ir_node *cnst = new_r_Const_long(current_ir_graph, mode_UInt, offset); + + ptr = new_rd_Add(dbgi, current_ir_graph, bl, ptr, cnst, mode); + } + exchange(sel, ptr); + } +} + void be_abi_fix_stack_bias(be_abi_irg_t *env) { - ir_graph *irg = env->birg->irg; + ir_graph *irg = env->birg->irg; + ir_type *frame_tp; + int i; struct bias_walk bw; stack_frame_compute_initial_offset(&env->frame); @@ -2614,6 +2651,19 @@ void be_abi_fix_stack_bias(be_abi_irg_t *env) bw.env = env; bw.start_block = get_irg_start_block(irg); irg_block_walk_graph(irg, stack_bias_walker, NULL, &bw); + + /* fix now inner functions: these still have Sel node to outer + frame and parameter entities */ + frame_tp = get_irg_frame_type(irg); + for (i = get_class_n_members(frame_tp) - 1; i >= 0; --i) { + ir_entity *ent = get_class_member(frame_tp, i); + + if (is_method_entity(ent)) { + ir_graph *irg = get_entity_irg(ent); + + irg_walk_graph(irg, NULL, lower_outer_frame_sels, env); + } + } } ir_node *be_abi_get_callee_save_irn(be_abi_irg_t *abi, const arch_register_t *reg) diff --git a/ir/opt/gvn_pre.c b/ir/opt/gvn_pre.c index 798aa36e5..9243bbe79 100644 --- a/ir/opt/gvn_pre.c +++ b/ir/opt/gvn_pre.c @@ -407,9 +407,10 @@ static ir_node *phi_translate(ir_node *node, ir_node *block, int pos, ir_valuese if (trans == NULL) trans = leader; - if (is_Phi(trans) && get_nodes_block(trans) == block) - set_irn_n(nn, i, get_Phi_pred(trans, pos)); - else + if (is_Phi(trans) && get_nodes_block(trans) == block) { + ir_node *trans_pred = get_Phi_pred(trans, pos); + set_irn_n(nn, i, trans_pred); + } else set_irn_n(nn, i, trans); } nn = optimize_node(nn); -- 2.20.1