X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fopt%2Fldstopt.c;h=3667f26f6d95393eebe278dce0d9c187b651333c;hb=98beada6bb7ecbc2748b98f5e3b0ecfaa5a49144;hp=f7d8278b0ed113a75805aaf1222eec5d4464fead;hpb=f8cc15664f571aa7ef89d6f6bc8d5bd2b8ca7d53;p=libfirm diff --git a/ir/opt/ldstopt.c b/ir/opt/ldstopt.c index f7d8278b0..3667f26f6 100644 --- a/ir/opt/ldstopt.c +++ b/ir/opt/ldstopt.c @@ -43,14 +43,12 @@ #include "irhooks.h" #include "iredges.h" #include "irpass.h" -#include "opt_polymorphy.h" #include "irmemory.h" #include "irnodehashmap.h" #include "irgopt.h" #include "set.h" #include "be.h" #include "debug.h" -#include "opt_manage.h" /** The debug handle. */ DEBUG_ONLY(static firm_dbg_module_t *dbg;) @@ -339,170 +337,6 @@ static long get_Sel_array_index_long(ir_node *n, int dim) return get_tarval_long(get_Const_tarval(index)); } /* get_Sel_array_index_long */ -/** - * Returns the accessed component graph path for an - * node computing an address. - * - * @param ptr the node computing the address - * @param depth current depth in steps upward from the root - * of the address - */ -static compound_graph_path *rec_get_accessed_path(ir_node *ptr, size_t depth) -{ - compound_graph_path *res = NULL; - ir_entity *root, *field, *ent; - size_t path_len, pos, idx; - ir_tarval *tv; - ir_type *tp; - - 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 its length. - */ - assert(get_SymConst_kind(ptr) == symconst_addr_ent); - root = get_SymConst_entity(ptr); - res = (depth == 0) ? NULL : new_compound_graph_path(get_entity_type(root), depth); - } else if (is_Sel(ptr)) { - /* it's a Sel, go up until we find the root */ - res = rec_get_accessed_path(get_Sel_ptr(ptr), depth+1); - if (res == NULL) - return NULL; - - /* fill up the step in the path at the current position */ - field = get_Sel_entity(ptr); - path_len = get_compound_graph_path_length(res); - pos = path_len - depth - 1; - set_compound_graph_path_node(res, pos, field); - - if (is_Array_type(get_entity_owner(field))) { - assert(get_Sel_n_indexs(ptr) == 1 && "multi dim arrays not implemented"); - set_compound_graph_path_array_index(res, pos, get_Sel_array_index_long(ptr, 0)); - } - } else if (is_Add(ptr)) { - ir_mode *mode; - ir_tarval *tmp; - - { - ir_node *l = get_Add_left(ptr); - ir_node *r = get_Add_right(ptr); - if (is_Const(r) && get_irn_mode(l) == get_irn_mode(ptr)) { - ptr = l; - tv = get_Const_tarval(r); - } else { - ptr = r; - tv = get_Const_tarval(l); - } - } -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)) { - field = get_Sel_entity(ptr); - } else { - field = get_SymConst_entity(ptr); - } - idx = 0; - for (ent = field;;) { - unsigned size; - ir_tarval *sz, *tv_index, *tlower, *tupper; - ir_node *bound; - - tp = get_entity_type(ent); - if (! is_Array_type(tp)) - break; - ent = get_array_element_entity(tp); - size = get_type_size_bytes(get_entity_type(ent)); - sz = new_tarval_from_long(size, mode); - - tv_index = tarval_div(tmp, sz); - tmp = tarval_mod(tmp, sz); - - if (tv_index == tarval_bad || tmp == tarval_bad) - return NULL; - - assert(get_array_n_dimensions(tp) == 1 && "multiarrays not implemented"); - bound = get_array_lower_bound(tp, 0); - tlower = computed_value(bound); - bound = get_array_upper_bound(tp, 0); - tupper = computed_value(bound); - - if (tlower == tarval_bad || tupper == tarval_bad) - return NULL; - - if (tarval_cmp(tv_index, tlower) == ir_relation_less) - return NULL; - if (tarval_cmp(tupper, tv_index) == ir_relation_less) - return NULL; - - /* ok, bounds check finished */ - ++idx; - } - if (! tarval_is_null(tmp)) { - /* access to some struct/union member */ - return NULL; - } - - /* should be at least ONE array */ - if (idx == 0) - return NULL; - - res = rec_get_accessed_path(ptr, depth + idx); - if (res == NULL) - return NULL; - - path_len = get_compound_graph_path_length(res); - pos = path_len - depth - idx; - - for (ent = field;;) { - unsigned size; - ir_tarval *sz, *tv_index; - long index; - - tp = get_entity_type(ent); - if (! is_Array_type(tp)) - break; - ent = get_array_element_entity(tp); - set_compound_graph_path_node(res, pos, ent); - - 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); - - /* worked above, should work again */ - assert(tv_index != tarval_bad && tv != tarval_bad); - - /* bounds already checked above */ - index = get_tarval_long(tv_index); - set_compound_graph_path_array_index(res, pos, index); - ++pos; - } - } else if (is_Sub(ptr)) { - ir_node *l = get_Sub_left(ptr); - ir_node *r = get_Sub_right(ptr); - - ptr = l; - tv = get_Const_tarval(r); - tv = tarval_neg(tv); - goto ptr_arith; - } - return res; -} /* rec_get_accessed_path */ - -/** - * Returns an access path or NULL. The access path is only - * valid, if the graph is in phase_high and _no_ address computation is used. - */ -static compound_graph_path *get_accessed_path(ir_node *ptr) -{ - compound_graph_path *gr = rec_get_accessed_path(ptr, 0); - return gr; -} /* get_accessed_path */ - typedef struct path_entry { ir_entity *ent; struct path_entry *next; @@ -1142,61 +976,44 @@ static unsigned optimize_load(ir_node *load) return res | DF_CHANGED; } - /* Load from a constant polymorphic field, where we can resolve - polymorphism. */ - value = transform_polymorph_Load(load); - if (value == load) { - value = NULL; - /* check if we can determine the entity that will be loaded */ - ent = find_constant_entity(ptr); - if (ent != NULL - && get_entity_visibility(ent) != ir_visibility_external) { - /* 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]) { - ir_graph *irg = get_irn_irg(load); - exchange(info->projs[pn_Load_X_except], new_r_Bad(irg, mode_X)); - 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(get_nodes_block(load))); - info->projs[pn_Load_X_regular] = NULL; - res |= CF_CHANGED; - } - - if (get_entity_linkage(ent) & IR_LINKAGE_CONSTANT) { - if (has_entity_initializer(ent)) { - /* new style initializer */ - value = find_compound_ent_value(ptr); - } else if (entity_has_compound_ent_values(ent)) { - /* old style initializer */ - compound_graph_path *path = get_accessed_path(ptr); + value = NULL; + /* check if we can determine the entity that will be loaded */ + ent = find_constant_entity(ptr); + if (ent != NULL + && get_entity_visibility(ent) != ir_visibility_external) { + /* a static allocation that is not external: there should be NO + * exception when loading even if we cannot replace the load itself. + */ - if (path != NULL) { - assert(is_proper_compound_graph_path(path, get_compound_graph_path_length(path)-1)); + /* no exception, clear the info field as it might be checked later again */ + if (info->projs[pn_Load_X_except]) { + ir_graph *irg = get_irn_irg(load); + exchange(info->projs[pn_Load_X_except], new_r_Bad(irg, mode_X)); + 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(get_nodes_block(load))); + info->projs[pn_Load_X_regular] = NULL; + res |= CF_CHANGED; + } - 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) { - ir_graph *irg = get_irn_irg(load); - value = can_replace_load_by_const(load, value); - if (value != NULL && is_Sel(ptr) && - !is_irg_state(irg, IR_GRAPH_STATE_IMPLICIT_BITFIELD_MASKING)) { - /* frontend has inserted masking operations after bitfield accesses, - * so we might have to shift the const. */ - unsigned char bit_offset = get_entity_offset_bits_remainder(get_Sel_entity(ptr)); - ir_tarval *tv_old = get_Const_tarval(value); - ir_tarval *tv_offset = new_tarval_from_long(bit_offset, mode_Bu); - ir_tarval *tv_new = tarval_shl(tv_old, tv_offset); - value = new_r_Const(irg, tv_new); - } + if (get_entity_linkage(ent) & IR_LINKAGE_CONSTANT) { + if (has_entity_initializer(ent)) { + /* new style initializer */ + value = find_compound_ent_value(ptr); + } + if (value != NULL) { + ir_graph *irg = get_irn_irg(load); + value = can_replace_load_by_const(load, value); + if (value != NULL && is_Sel(ptr)) { + /* frontend has inserted masking operations after bitfield accesses, + * so we might have to shift the const. */ + unsigned char bit_offset = get_entity_offset_bits_remainder(get_Sel_entity(ptr)); + ir_tarval *tv_old = get_Const_tarval(value); + ir_tarval *tv_offset = new_tarval_from_long(bit_offset, mode_Bu); + ir_tarval *tv_new = tarval_shl(tv_old, tv_offset); + value = new_r_Const(irg, tv_new); } } } @@ -1821,7 +1638,7 @@ static int cmp_avail_entry(const void *elt, const void *key, size_t size) */ static unsigned hash_cache_entry(const avail_entry_t *entry) { - return get_irn_idx(entry->ptr) * 9 + HASH_PTR(entry->mode); + return get_irn_idx(entry->ptr) * 9 + hash_ptr(entry->mode); } /* hash_cache_entry */ /** @@ -1837,8 +1654,6 @@ static void move_loads_out_of_loops(scc *pscc, loop_env *env) phi_entry *phi_list = NULL; set *avail; - avail = new_set(cmp_avail_entry, 8); - /* collect all outer memories */ for (phi = pscc->head; phi != NULL; phi = next) { node_entry *ne = get_irn_ne(phi, env); @@ -1872,6 +1687,8 @@ static void move_loads_out_of_loops(scc *pscc, loop_env *env) if (phi_list->next != NULL) return; + avail = new_set(cmp_avail_entry, 8); + for (load = pscc->head; load; load = next) { ir_mode *load_mode; node_entry *ne = get_irn_ne(load, env); @@ -1923,13 +1740,13 @@ static void move_loads_out_of_loops(scc *pscc, loop_env *env) entry.ptr = ptr; entry.mode = load_mode; - res = (avail_entry_t*)set_find(avail, &entry, sizeof(entry), hash_cache_entry(&entry)); + res = set_find(avail_entry_t, avail, &entry, sizeof(entry), hash_cache_entry(&entry)); if (res != NULL) { irn = res->load; } else { irn = new_rd_Load(db, pred, get_Phi_pred(phi, pos), ptr, load_mode, cons_none); entry.load = irn; - set_insert(avail, &entry, sizeof(entry), hash_cache_entry(&entry)); + set_insert(avail_entry_t, avail, &entry, sizeof(entry), hash_cache_entry(&entry)); DB((dbg, LEVEL_1, " Created %+F in %+F\n", irn, pred)); } pe->load = irn; @@ -2148,7 +1965,7 @@ static void dfs(ir_node *irn, loop_env *env) node->low = MIN(o->DFSnum, node->low); } } else if (is_fragile_op(irn)) { - ir_node *pred = get_fragile_op_mem(irn); + ir_node *pred = get_memop_mem(irn); node_entry *o = get_irn_ne(pred, env); if (!irn_visited(pred)) { @@ -2215,7 +2032,7 @@ static void do_dfs(ir_graph *irg, loop_env *env) } else if (is_Raise(pred)) { dfs(get_Raise_mem(pred), env); } else if (is_fragile_op(pred)) { - dfs(get_fragile_op_mem(pred), env); + dfs(get_memop_mem(pred), env); } else if (is_Bad(pred)) { /* ignore non-optimized block predecessor */ } else { @@ -2263,10 +2080,16 @@ static int optimize_loops(ir_graph *irg) /* * do the load store optimization */ -static ir_graph_state_t do_loadstore_opt(ir_graph *irg) +void optimize_load_store(ir_graph *irg) { walk_env_t env; - ir_graph_state_t res = 0; + + assure_irg_properties(irg, + IR_GRAPH_PROPERTY_NO_UNREACHABLE_CODE + | IR_GRAPH_PROPERTY_CONSISTENT_OUT_EDGES + | IR_GRAPH_PROPERTY_NO_CRITICAL_EDGES + | IR_GRAPH_PROPERTY_CONSISTENT_DOMINANCE + | IR_GRAPH_PROPERTY_CONSISTENT_ENTITY_USAGE); FIRM_DBG_REGISTER(dbg, "firm.opt.ldstopt"); @@ -2292,31 +2115,15 @@ static ir_graph_state_t do_loadstore_opt(ir_graph *irg) obstack_free(&env.obst, NULL); - /* Handle graph state */ - if (env.changes) { - edges_deactivate(irg); - } - - if (!(env.changes & CF_CHANGED)) { - res |= IR_GRAPH_STATE_CONSISTENT_DOMINANCE | IR_GRAPH_STATE_NO_BADS; - } - - return res; -} - -static optdesc_t opt_loadstore = { - "load-store", - IR_GRAPH_STATE_NO_UNREACHABLE_CODE | IR_GRAPH_STATE_CONSISTENT_OUT_EDGES | IR_GRAPH_STATE_NO_CRITICAL_EDGES | IR_GRAPH_STATE_CONSISTENT_DOMINANCE | IR_GRAPH_STATE_CONSISTENT_ENTITY_USAGE, - do_loadstore_opt, -}; - -int optimize_load_store(ir_graph *irg) -{ - perform_irg_optimization(irg, &opt_loadstore); - return 1; + confirm_irg_properties(irg, + env.changes + ? env.changes & CF_CHANGED + ? IR_GRAPH_PROPERTIES_NONE + : IR_GRAPH_PROPERTIES_CONTROL_FLOW + : IR_GRAPH_PROPERTIES_ALL); } ir_graph_pass_t *optimize_load_store_pass(const char *name) { - return def_graph_pass_ret(name ? name : "ldst", optimize_load_store); + return def_graph_pass(name ? name : "ldst", optimize_load_store); } /* optimize_load_store_pass */