X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fopt%2Fldstopt.c;h=ac883ed29cce5d41b8275843f1d378e2a49a44de;hb=1c199e4bb4a8190e6d5b5e03928aa35129b6d371;hp=dd8e5a5304de22d61e9d4bddba89a21c770f53b5;hpb=e9acaaa06c895c2632071e8d42e8632253c3d9f8;p=libfirm diff --git a/ir/opt/ldstopt.c b/ir/opt/ldstopt.c index dd8e5a530..ac883ed29 100644 --- a/ir/opt/ldstopt.c +++ b/ir/opt/ldstopt.c @@ -257,10 +257,7 @@ static ir_entity *find_constant_entity(ir_node *ptr) { for (;;) { if (is_SymConst(ptr) && get_SymConst_kind(ptr) == symconst_addr_ent) { - ir_entity *ent = get_SymConst_entity(ptr); - if (variability_constant == get_entity_variability(ent)) - return ent; - return NULL; + return get_SymConst_entity(ptr); } else if (is_Sel(ptr)) { ir_entity *ent = get_Sel_entity(ptr); ir_type *tp = get_entity_owner(ent); @@ -364,7 +361,7 @@ static compound_graph_path *rec_get_accessed_path(ir_node *ptr, int depth) { if (is_SymConst(ptr)) { /* a SymConst. If the depth is 0, this is an access to a global * entity and we don't need a component path, else we know - * at least it's length. + * at least its length. */ assert(get_SymConst_kind(ptr) == symconst_addr_ent); root = get_SymConst_entity(ptr); @@ -386,11 +383,12 @@ static compound_graph_path *rec_get_accessed_path(ir_node *ptr, int depth) { set_compound_graph_path_array_index(res, pos, get_Sel_array_index_long(ptr, 0)); } } else if (is_Add(ptr)) { - ir_node *l = get_Add_left(ptr); - ir_node *r = get_Add_right(ptr); - ir_mode *mode; + ir_node *l = get_Add_left(ptr); + ir_node *r = get_Add_right(ptr); + ir_mode *mode = get_irn_mode(ptr); + tarval *tmp; - if (is_Const(r)) { + if (is_Const(r) && get_irn_mode(l) == mode) { ptr = l; tv = get_Const_tarval(r); } else { @@ -399,6 +397,7 @@ static compound_graph_path *rec_get_accessed_path(ir_node *ptr, int depth) { } ptr_arith: mode = get_tarval_mode(tv); + tmp = tv; /* ptr must be a Sel or a SymConst, this was checked in find_constant_entity() */ if (is_Sel(ptr)) { @@ -419,10 +418,10 @@ ptr_arith: size = get_type_size_bytes(get_entity_type(ent)); sz = new_tarval_from_long(size, mode); - tv_index = tarval_div(tv, sz); - tv = tarval_mod(tv, sz); + tv_index = tarval_div(tmp, sz); + tmp = tarval_mod(tmp, sz); - if (tv_index == tarval_bad || tv == tarval_bad) + if (tv_index == tarval_bad || tmp == tarval_bad) return NULL; assert(get_array_n_dimensions(tp) == 1 && "multiarrays not implemented"); @@ -442,7 +441,7 @@ ptr_arith: /* ok, bounds check finished */ ++idx; } - if (! tarval_is_null(tv)) { + if (! tarval_is_null(tmp)) { /* access to some struct/union member */ return NULL; } @@ -500,7 +499,8 @@ ptr_arith: * valid, if the graph is in phase_high and _no_ address computation is used. */ static compound_graph_path *get_accessed_path(ir_node *ptr) { - return rec_get_accessed_path(ptr, 0); + compound_graph_path *gr = rec_get_accessed_path(ptr, 0); + return gr; } /* get_accessed_path */ typedef struct path_entry { @@ -691,7 +691,7 @@ static ir_node *find_compound_ent_value(ir_node *ptr) { static void reduce_adr_usage(ir_node *ptr); /** - * Update a Load that may lost it's usage. + * Update a Load that may have lost its users. */ static void handle_load_update(ir_node *load) { ldst_info_t *info = get_irn_link(load); @@ -704,7 +704,7 @@ static void handle_load_update(ir_node *load) { ir_node *ptr = get_Load_ptr(load); ir_node *mem = get_Load_mem(load); - /* a Load which value is neither used nor exception checked, remove it */ + /* a Load whose value is neither used nor exception checked, remove it */ exchange(info->projs[pn_Load_M], mem); if (info->projs[pn_Load_X_regular]) exchange(info->projs[pn_Load_X_regular], new_r_Jmp(current_ir_graph, get_nodes_block(load))); @@ -714,7 +714,7 @@ static void handle_load_update(ir_node *load) { } /* handle_load_update */ /** - * A Use of an address node is vanished. Check if this was a Proj + * A use of an address node has vanished. Check if this was a Proj * node and update the counters. */ static void reduce_adr_usage(ir_node *ptr) { @@ -727,7 +727,7 @@ static void reduce_adr_usage(ir_node *ptr) { ldst_info_t *info = get_irn_link(pred); info->projs[get_Proj_proj(ptr)] = NULL; - /* this node lost it's result proj, handle that */ + /* this node lost its result proj, handle that */ handle_load_update(pred); } } @@ -1125,7 +1125,7 @@ static unsigned optimize_load(ir_node *load) } /* The mem of the Load. Must still be returned after optimization. */ - mem = get_Load_mem(load); + mem = get_Load_mem(load); if (! info->projs[pn_Load_res] && ! info->projs[pn_Load_X_except]) { /* a Load which value is neither used nor exception checked, remove it */ @@ -1148,53 +1148,48 @@ static unsigned optimize_load(ir_node *load) value = NULL; /* check if we can determine the entity that will be loaded */ ent = find_constant_entity(ptr); - if (ent != NULL) { - if ((allocation_static == get_entity_allocation(ent)) && - (visibility_external_allocated != get_entity_visibility(ent))) { - /* a static allocation that is not external: there should be NO exception - * when loading even if we cannot replace the load itself. */ - - /* no exception, clear the info field as it might be checked later again */ - if (info->projs[pn_Load_X_except]) { - exchange(info->projs[pn_Load_X_except], new_Bad()); - info->projs[pn_Load_X_except] = NULL; - res |= CF_CHANGED; - } - if (info->projs[pn_Load_X_regular]) { - exchange(info->projs[pn_Load_X_regular], new_r_Jmp(current_ir_graph, get_nodes_block(load))); - info->projs[pn_Load_X_regular] = NULL; - res |= CF_CHANGED; - } + if (ent != NULL && + allocation_static == get_entity_allocation(ent) && + visibility_external_allocated != get_entity_visibility(ent)) { + /* a static allocation that is not external: there should be NO exception + * when loading even if we cannot replace the load itself. */ + + /* no exception, clear the info field as it might be checked later again */ + if (info->projs[pn_Load_X_except]) { + exchange(info->projs[pn_Load_X_except], new_Bad()); + info->projs[pn_Load_X_except] = NULL; + res |= CF_CHANGED; + } + if (info->projs[pn_Load_X_regular]) { + exchange(info->projs[pn_Load_X_regular], new_r_Jmp(current_ir_graph, get_nodes_block(load))); + info->projs[pn_Load_X_regular] = NULL; + res |= CF_CHANGED; + } - if (variability_constant == get_entity_variability(ent)) { - if (is_atomic_entity(ent)) { - /* Might not be atomic after - lowering of Sels. In this - case we could also load, but - it's more complicated. */ - /* more simpler case: we load the content of a constant value: - * replace it by the constant itself - */ - value = get_atomic_ent_value(ent); - } else { - if (ent->has_initializer) { - /* new style initializer */ - value = find_compound_ent_value(ptr); - } else { - /* old style initializer */ - compound_graph_path *path = get_accessed_path(ptr); - - if (path != NULL) { - assert(is_proper_compound_graph_path(path, get_compound_graph_path_length(path)-1)); - - value = get_compound_ent_value_by_path(ent, path); - free_compound_graph_path(path); - } - } + if (variability_constant == get_entity_variability(ent)) { + if (is_atomic_entity(ent)) { + /* Might not be atomic after lowering of Sels. In this case we + * could also load, but it's more complicated. */ + /* more simpler case: we load the content of a constant value: + * replace it by the constant itself */ + value = get_atomic_ent_value(ent); + } else if (ent->has_initializer) { + /* new style initializer */ + value = find_compound_ent_value(ptr); + } else { + /* old style initializer */ + compound_graph_path *path = get_accessed_path(ptr); + + if (path != NULL) { + assert(is_proper_compound_graph_path(path, get_compound_graph_path_length(path)-1)); + + value = get_compound_ent_value_by_path(ent, path); + DB((dbg, LEVEL_1, " Constant access at %F%F resulted in %+F\n", ent, path, value)); + free_compound_graph_path(path); } - if (value != NULL) - value = can_replace_load_by_const(load, value); } + if (value != NULL) + value = can_replace_load_by_const(load, value); } } } @@ -1352,18 +1347,61 @@ static unsigned follow_Mem_chain_for_Store(ir_node *store, ir_node *curr) { return res; } /* follow_Mem_chain_for_Store */ +/** find entity used as base for an address calculation */ +static ir_entity *find_entity(ir_node *ptr) +{ + switch(get_irn_opcode(ptr)) { + case iro_SymConst: + return get_SymConst_entity(ptr); + case iro_Sel: { + ir_node *pred = get_Sel_ptr(ptr); + if (get_irg_frame(get_irn_irg(ptr)) == pred) + return get_Sel_entity(ptr); + + return find_entity(pred); + } + case iro_Sub: + case iro_Add: { + ir_node *left = get_binop_left(ptr); + ir_node *right; + if (mode_is_reference(get_irn_mode(left))) + return find_entity(left); + right = get_binop_right(ptr); + if (mode_is_reference(get_irn_mode(right))) + return find_entity(right); + return NULL; + } + default: + return NULL; + } +} + /** * optimize a Store * * @param store the Store node */ static unsigned optimize_store(ir_node *store) { - ir_node *ptr, *mem; + ir_node *ptr; + ir_node *mem; + ir_entity *entity; if (get_Store_volatility(store) == volatility_is_volatile) return 0; - ptr = get_Store_ptr(store); + ptr = get_Store_ptr(store); + entity = find_entity(ptr); + + /* a store to an entity which is never read is unnecessary */ + if (entity != NULL && !(get_entity_usage(entity) & ir_usage_read)) { + ldst_info_t *info = get_irn_link(store); + if (info->projs[pn_Store_X_except] == NULL) { + exchange(info->projs[pn_Store_M], get_Store_mem(store)); + kill_node(store); + reduce_adr_usage(ptr); + return DF_CHANGED; + } + } /* Check, if the address of this Store is used more than once. * If not, this Store cannot be removed in any case. */ @@ -2166,6 +2204,7 @@ void optimize_load_store(ir_graph *irg) { /* Handle graph state */ if (env.changes) { set_irg_outs_inconsistent(irg); + set_irg_entity_usage_state(irg, ir_entity_usage_not_computed); } if (env.changes & CF_CHANGED) {