X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fopt%2Fldstopt.c;h=a74aae4d9420e302cc783fba5a522f05a40da7a4;hb=be375dcbb1195db1ed6a7ea7e4787456fb1d7b4f;hp=8664a7649e78537d8a9a9da35b60ae651e91ae2e;hpb=5fc55389c848cf1db10514a6de5b1ec8835e4fdc;p=libfirm diff --git a/ir/opt/ldstopt.c b/ir/opt/ldstopt.c index 8664a7649..a74aae4d9 100644 --- a/ir/opt/ldstopt.c +++ b/ir/opt/ldstopt.c @@ -36,6 +36,7 @@ #include "irflag_t.h" #include "array.h" #include "irhooks.h" +#include "iredges.h" #include "irtools.h" #include "opt_polymorphy.h" @@ -169,9 +170,7 @@ static unsigned update_exc(ldst_info_t *info, ir_node *block, int pos) } /** Return the number of uses of an address node */ -#define get_irn_n_uses(adr) (unsigned)PTR_TO_INT(get_irn_link(adr)) -/** Sets the number of uses of an address node */ -#define set_irn_n_uses(adr, n) set_irn_link(adr, INT_TO_PTR(n)) +#define get_irn_n_uses(adr) get_irn_n_edges(adr) /** * walker, collects all Load/Store/Proj nodes @@ -199,8 +198,6 @@ static void collect_nodes(ir_node *node, void *env) if ((ldst_info->flags & LDST_VISITED) == 0) { adr = get_Load_ptr(pred); - set_irn_n_uses(adr, get_irn_n_uses(adr) + 1); - ldst_info->flags |= LDST_VISITED; } @@ -224,8 +221,6 @@ static void collect_nodes(ir_node *node, void *env) if ((ldst_info->flags & LDST_VISITED) == 0) { adr = get_Store_ptr(pred); - set_irn_n_uses(adr, get_irn_n_uses(adr) + 1); - ldst_info->flags |= LDST_VISITED; } @@ -243,7 +238,7 @@ static void collect_nodes(ir_node *node, void *env) } } } - else if (op == op_Block) { /* check, if it's an exception block */ + else if (op == op_Block) { int i; for (i = get_Block_n_cfgpreds(node) - 1; i >= 0; --i) { @@ -260,7 +255,7 @@ static void collect_nodes(ir_node *node, void *env) bl_info = get_block_info(pred_block, wenv); if (is_fragile_op(pred)) - bl_info->flags |= BLOCK_HAS_EXC; + bl_info->flags |= BLOCK_HAS_EXC; else if (is_irn_forking(pred)) bl_info->flags |= BLOCK_HAS_COND; @@ -276,7 +271,7 @@ static void collect_nodes(ir_node *node, void *env) /** * Returns an entity if the address ptr points to a constant one. */ -static entity *find_constant_entity(ir_node *ptr) +static ir_entity *find_constant_entity(ir_node *ptr) { for (;;) { ir_op *op = get_irn_op(ptr); @@ -285,8 +280,8 @@ static entity *find_constant_entity(ir_node *ptr) return get_SymConst_entity(ptr); } else if (op == op_Sel) { - entity *ent = get_Sel_entity(ptr); - ir_type *tp = get_entity_owner(ent); + ir_entity *ent = get_Sel_entity(ptr); + ir_type *tp = get_entity_owner(ent); /* Do not fiddle with polymorphism. */ if (is_Class_type(get_entity_owner(ent)) && @@ -355,7 +350,7 @@ static long get_Sel_array_index_long(ir_node *n, int dim) { */ static compound_graph_path *rec_get_accessed_path(ir_node *ptr, int depth) { compound_graph_path *res = NULL; - entity *root, *field; + ir_entity *root, *field; int path_len, pos; if (get_irn_op(ptr) == op_SymConst) { @@ -412,6 +407,7 @@ static void handle_load_update(ir_node *load) { /* a Load which value is neither used nor exception checked, remove it */ exchange(info->projs[pn_Load_M], mem); + exchange(load, new_Bad()); reduce_adr_usage(ptr); } } @@ -421,14 +417,9 @@ static void handle_load_update(ir_node *load) { * node and update the counters. */ static void reduce_adr_usage(ir_node *ptr) { - int use_count = get_irn_n_uses(ptr); - --use_count; - assert(use_count >= 0); - set_irn_n_uses(ptr, use_count); - if (is_Proj(ptr)) { - if (use_count <= 0) { - /* this Proj is now dead, update the Load/Store info */ + if (get_irn_n_edges(ptr) <= 0) { + /* this Proj is dead now */ ir_node *pred = get_Proj_pred(ptr); opcode code = get_irn_opcode(pred); @@ -501,6 +492,7 @@ static unsigned follow_Load_chain(ir_node *load, ir_node *curr) { if (info->projs[pn_Load_res]) exchange(info->projs[pn_Load_res], value); + exchange(load, new_Bad()); reduce_adr_usage(ptr); return res | DF_CHANGED; } @@ -546,6 +538,7 @@ static unsigned follow_Load_chain(ir_node *load, ir_node *curr) { res |= CF_CHANGED; } + exchange(load, new_Bad()); reduce_adr_usage(ptr); return res |= DF_CHANGED; } @@ -581,9 +574,8 @@ static unsigned follow_Load_chain(ir_node *load, ir_node *curr) { static unsigned optimize_load(ir_node *load) { ldst_info_t *info = get_irn_link(load); - ir_mode *load_mode = get_Load_mode(load); ir_node *mem, *ptr, *new_node; - entity *ent; + ir_entity *ent; unsigned res = 0; /* do NOT touch volatile loads for now */ @@ -607,9 +599,9 @@ static unsigned optimize_load(ir_node *load) if (get_irn_op(skip_Proj(mem)) == op_Alloc) { /* ok, check the types */ - entity *ent = get_Sel_entity(ptr); - ir_type *s_type = get_entity_type(ent); - ir_type *a_type = get_Alloc_type(mem); + ir_entity *ent = get_Sel_entity(ptr); + ir_type *s_type = get_entity_type(ent); + ir_type *a_type = get_Alloc_type(mem); if (is_SubClass_of(s_type, a_type)) { /* ok, condition met: there can't be an exception because @@ -641,6 +633,7 @@ static unsigned optimize_load(ir_node *load) /* a Load which value is neither used nor exception checked, remove it */ exchange(info->projs[pn_Load_M], mem); + exchange(load, new_Bad()); reduce_adr_usage(ptr); return res | DF_CHANGED; } @@ -660,6 +653,7 @@ static unsigned optimize_load(ir_node *load) if (info->projs[pn_Load_res]) exchange(info->projs[pn_Load_res], new_node); + exchange(load, new_Bad()); reduce_adr_usage(ptr); return res | DF_CHANGED; } @@ -704,6 +698,7 @@ static unsigned optimize_load(ir_node *load) res |= DF_CHANGED; } } + exchange(load, new_Bad()); reduce_adr_usage(ptr); return res; } @@ -718,7 +713,7 @@ static unsigned optimize_load(ir_node *load) { int j; for (j = 0; j < get_compound_graph_path_length(path); ++j) { - entity *node = get_compound_graph_path_node(path, j); + ir_entity *node = get_compound_graph_path_node(path, j); fprintf(stdout, ".%s", get_entity_name(node)); if (is_Array_type(get_entity_owner(node))) fprintf(stdout, "[%d]", get_compound_graph_path_array_index(path, j)); @@ -740,6 +735,7 @@ static unsigned optimize_load(ir_node *load) exchange(info->projs[pn_Load_res], copy_const_value(get_irn_dbg_info(load), c)); res |= DF_CHANGED; } + exchange(load, new_Bad()); reduce_adr_usage(ptr); return res; } @@ -809,6 +805,7 @@ static unsigned follow_Load_chain_for_Store(ir_node *store, ir_node *curr) { if (get_Store_volatility(pred) != volatility_is_volatile && !pred_info->projs[pn_Store_X_except]) { DBG_OPT_WAW(pred, store); exchange( pred_info->projs[pn_Store_M], get_Store_mem(pred) ); + exchange(pred, new_Bad()); reduce_adr_usage(ptr); return DF_CHANGED; } @@ -822,6 +819,7 @@ static unsigned follow_Load_chain_for_Store(ir_node *store, ir_node *curr) { if (! info->projs[pn_Store_X_except]) { DBG_OPT_WAR(store, pred); exchange( info->projs[pn_Store_M], mem ); + exchange(store, new_Bad()); reduce_adr_usage(ptr); return DF_CHANGED; } @@ -855,7 +853,6 @@ static unsigned follow_Load_chain_for_Store(ir_node *store, ir_node *curr) { */ static unsigned optimize_store(ir_node *store) { - ldst_info_t *info = get_irn_link(store); ir_node *ptr, *mem; if (get_Store_volatility(store) == volatility_is_volatile) @@ -882,10 +879,10 @@ static unsigned optimize_store(ir_node *store) * * val1 val2 val3 val1 val2 val3 * | | | \ | / - * Str Str Str \ | / + * Store Store Store \ | / * \ | / PhiData * \ | / | - * \ | / Str + * \ | / Store * PhiM * * @endverbatim @@ -897,9 +894,9 @@ static unsigned optimize_store(ir_node *store) static unsigned optimize_phi(ir_node *phi, walk_env_t *wenv) { int i, n; - ir_node *store, *old_store, *ptr, *block, *phiM, *phiD, *exc, *projM; + ir_node *store, *old_store, *ptr, *block, *phi_block, *phiM, *phiD, *exc, *projM; ir_mode *mode; - ir_node **inM, **inD; + ir_node **inM, **inD, **stores; int *idx; dbg_info *db = NULL; ldst_info_t *info; @@ -919,13 +916,20 @@ static unsigned optimize_phi(ir_node *phi, walk_env_t *wenv) if (get_irn_op(store) != op_Store) return 0; + block = get_nodes_block(store); + /* abort on dead blocks */ - if (is_Block_dead(get_nodes_block(store))) + if (is_Block_dead(block)) return 0; - /* check if the block has only one successor */ - bl_info = get_irn_link(get_nodes_block(store)); - if (bl_info->flags) + /* check if the block is post dominated by Phi-block + and has no exception exit */ + bl_info = get_irn_link(block); + if (bl_info->flags & BLOCK_HAS_EXC) + return 0; + + phi_block = get_nodes_block(phi); + if (! block_postdominates(phi_block, block)) return 0; /* this is the address of the store */ @@ -950,12 +954,18 @@ static unsigned optimize_phi(ir_node *phi, walk_env_t *wenv) return 0; /* abort on dead blocks */ - if (is_Block_dead(get_nodes_block(store))) + block = get_nodes_block(pred); + if (is_Block_dead(block)) return 0; - /* check if the block has only one successor */ - bl_info = get_irn_link(get_nodes_block(store)); - if (bl_info->flags) + /* check if the block is post dominated by Phi-block + and has no exception exit. Note that block must be different from + Phi-block, else we would move a Store from end End of a block to its + Start... */ + bl_info = get_irn_link(block); + if (bl_info->flags & BLOCK_HAS_EXC) + return 0; + if (block == phi_block || ! block_postdominates(phi_block, block)) return 0; } @@ -976,24 +986,42 @@ static unsigned optimize_phi(ir_node *phi, walk_env_t *wenv) * Is only allowed if the predecessor blocks have only one successor. */ - /* first step: collect all inputs */ + NEW_ARR_A(ir_node *, stores, n); NEW_ARR_A(ir_node *, inM, n); NEW_ARR_A(ir_node *, inD, n); NEW_ARR_A(int, idx, n); + /* Prepare: Collect all Store nodes. We must do this + first because we otherwise may loose a store when exchanging its + memory Proj. + */ + for (i = 0; i < n; ++i) + stores[i] = skip_Proj(get_Phi_pred(phi, i)); + + /* Prepare: Skip the memory Proj: we need this in the case some stores + are cascaded. + Beware: One Store might be included more than once in the stores[] + list, so we must prevent to do the exchange more than once. + */ for (i = 0; i < n; ++i) { - ir_node *pred = skip_Proj(get_Phi_pred(phi, i)); - info = get_irn_link(pred); + ir_node *store = stores[i]; + ir_node *proj_m; - inM[i] = get_Store_mem(pred); - inD[i] = get_Store_value(pred); - idx[i] = info->exc_idx; + info = get_irn_link(store); + proj_m = info->projs[pn_Store_M]; - /* Should we here replace the Proj after the Store by - * the Store's memory? Would be save but should not be needed, - * because we checked that all pred blocks have only one - * control flow successor. - */ + if (is_Proj(proj_m) && get_Proj_pred(proj_m) == store) + exchange(proj_m, get_Store_mem(store)); + } + + /* first step: collect all inputs */ + for (i = 0; i < n; ++i) { + ir_node *store = stores[i]; + info = get_irn_link(store); + + inM[i] = get_Store_mem(store); + inD[i] = get_Store_value(store); + idx[i] = info->exc_idx; } block = get_nodes_block(phi); @@ -1008,8 +1036,6 @@ static unsigned optimize_phi(ir_node *phi, walk_env_t *wenv) #ifdef DO_CACHEOPT co_set_irn_name(store, co_get_irn_ident(old_store)); #endif - /* we replaced n uses by 1 */ - set_irn_n_uses(ptr, get_irn_n_uses(ptr) - n + 1); projM = new_rd_Proj(NULL, current_ir_graph, block, store, mode_M, pn_Store_M); @@ -1080,6 +1106,11 @@ void optimize_load_store(ir_graph *irg) if (! get_opt_redundant_loadstore()) return; + edges_assure(irg); + + /* for Phi optimization post-dominators are needed ... */ + assure_postdoms(irg); + obstack_init(&env.obst); env.changes = 0;