X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fopt%2Fldstopt.c;h=ea3b1f181ac9ab2af41f097027636f2fb4a4989f;hb=f2c2e45eb4e677fef5bf6a8e418b2a22441172d5;hp=2ef7cece031d7a955f871a32d94d175298c67260;hpb=cd54f7ca7241d39efc69b33d103f91738641310a;p=libfirm diff --git a/ir/opt/ldstopt.c b/ir/opt/ldstopt.c index 2ef7cece0..ea3b1f181 100644 --- a/ir/opt/ldstopt.c +++ b/ir/opt/ldstopt.c @@ -23,9 +23,7 @@ * @author Michael Beck * @version $Id$ */ -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif +#include "config.h" #include @@ -48,9 +46,9 @@ #include "irtools.h" #include "opt_polymorphy.h" #include "irmemory.h" -#include "xmalloc.h" #include "irphase_t.h" #include "irgopt.h" +#include "set.h" #include "debug.h" /** The debug handle. */ @@ -707,7 +705,7 @@ static void handle_load_update(ir_node *load) { /* 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))); + exchange(info->projs[pn_Load_X_regular], new_r_Jmp(get_nodes_block(load))); kill_node(load); reduce_adr_usage(ptr); } @@ -856,29 +854,31 @@ static int try_load_after_store(ir_node *load, store_mode = get_irn_mode(get_Store_value(store)); store_mode_len = get_mode_size_bytes(store_mode); delta = load_offset - store_offset; - if (delta < 0 || delta + load_mode_len > store_mode_len) - return 0; + store_value = get_Store_value(store); - if (get_mode_arithmetic(store_mode) != irma_twos_complement || - get_mode_arithmetic(load_mode) != irma_twos_complement) - return 0; + if (delta != 0 || store_mode != load_mode) { + if (delta < 0 || delta + load_mode_len > store_mode_len) + return 0; - store_value = get_Store_value(store); + if (get_mode_arithmetic(store_mode) != irma_twos_complement || + get_mode_arithmetic(load_mode) != irma_twos_complement) + return 0; - /* produce a shift to adjust offset delta */ - if (delta > 0) { - ir_node *cnst; - /* FIXME: only true for little endian */ - cnst = new_Const_long(mode_Iu, delta * 8); - store_value = new_r_Shr(current_ir_graph, get_nodes_block(load), - store_value, cnst, store_mode); - } + /* produce a shift to adjust offset delta */ + if (delta > 0) { + ir_node *cnst; + + /* FIXME: only true for little endian */ + cnst = new_Const_long(mode_Iu, delta * 8); + store_value = new_r_Shr(get_nodes_block(load), + store_value, cnst, store_mode); + } - /* add an convert if needed */ - if (store_mode != load_mode) { - store_value = new_r_Conv(current_ir_graph, get_nodes_block(load), - store_value, load_mode); + /* add an convert if needed */ + if (store_mode != load_mode) { + store_value = new_r_Conv(get_nodes_block(load), store_value, load_mode); + } } DBG_OPT_RAW(load, store_value); @@ -894,7 +894,7 @@ static int try_load_after_store(ir_node *load, 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))); + exchange( info->projs[pn_Load_X_regular], new_r_Jmp(get_nodes_block(load))); res |= CF_CHANGED; } @@ -971,13 +971,13 @@ static unsigned follow_Mem_chain(ir_node *load, ir_node *curr) { if (info->projs[pn_Load_res]) { if (pred_info->projs[pn_Load_res] == NULL) { /* create a new Proj again */ - pred_info->projs[pn_Load_res] = new_r_Proj(current_ir_graph, get_nodes_block(pred), pred, get_Load_mode(pred), pn_Load_res); + pred_info->projs[pn_Load_res] = new_r_Proj(get_nodes_block(pred), pred, get_Load_mode(pred), pn_Load_res); } value = pred_info->projs[pn_Load_res]; /* add an convert if needed */ if (get_Load_mode(pred) != load_mode) { - value = new_r_Conv(current_ir_graph, get_nodes_block(load), value, load_mode); + value = new_r_Conv(get_nodes_block(load), value, load_mode); } exchange(info->projs[pn_Load_res], value); @@ -992,7 +992,7 @@ static unsigned follow_Mem_chain(ir_node *load, ir_node *curr) { 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))); + exchange( info->projs[pn_Load_X_regular], new_r_Jmp(get_nodes_block(load))); res |= CF_CHANGED; } @@ -1067,7 +1067,7 @@ ir_node *can_replace_load_by_const(const ir_node *load, ir_node *c) { /* copy the value from the const code irg and cast it */ res = copy_const_value(dbg, c); - res = new_rd_Conv(dbg, current_ir_graph, block, res, l_mode); + res = new_rd_Conv(dbg, block, res, l_mode); } } else { /* copy the value from the const code irg */ @@ -1118,7 +1118,7 @@ static unsigned optimize_load(ir_node *load) */ exchange(info->projs[pn_Load_X_except], new_Bad()); info->projs[pn_Load_X_except] = NULL; - exchange(info->projs[pn_Load_X_regular], new_r_Jmp(current_ir_graph, get_nodes_block(load))); + exchange(info->projs[pn_Load_X_regular], new_r_Jmp(get_nodes_block(load))); info->projs[pn_Load_X_regular] = NULL; res |= CF_CHANGED; } @@ -1133,7 +1133,7 @@ static unsigned optimize_load(ir_node *load) if (info->projs[pn_Load_X_regular]) { /* should not happen, but if it does, remove it */ - exchange(info->projs[pn_Load_X_regular], new_r_Jmp(current_ir_graph, get_nodes_block(load))); + exchange(info->projs[pn_Load_X_regular], new_r_Jmp(get_nodes_block(load))); res |= CF_CHANGED; } kill_node(load); @@ -1161,7 +1161,7 @@ static unsigned optimize_load(ir_node *load) 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))); + exchange(info->projs[pn_Load_X_regular], new_r_Jmp(get_nodes_block(load))); info->projs[pn_Load_X_regular] = NULL; res |= CF_CHANGED; } @@ -1201,7 +1201,7 @@ static unsigned optimize_load(ir_node *load) 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))); + exchange(info->projs[pn_Load_X_regular], new_r_Jmp(get_nodes_block(load))); info->projs[pn_Load_X_regular] = NULL; res |= CF_CHANGED; } @@ -1442,6 +1442,7 @@ static unsigned optimize_store(ir_node *store) { 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) { + DB((dbg, LEVEL_1, " Killing useless %+F to never read entity %+F\n", store, entity)); exchange(info->projs[pn_Store_M], get_Store_mem(store)); kill_node(store); reduce_adr_usage(ptr); @@ -1610,10 +1611,10 @@ static unsigned optimize_phi(ir_node *phi, walk_env_t *wenv) block = get_nodes_block(phi); /* second step: create a new memory Phi */ - phiM = new_rd_Phi(get_irn_dbg_info(phi), current_ir_graph, block, n, inM, mode_M); + phiM = new_rd_Phi(get_irn_dbg_info(phi), block, n, inM, mode_M); /* third step: create a new data Phi */ - phiD = new_rd_Phi(get_irn_dbg_info(phi), current_ir_graph, block, n, inD, mode); + phiD = new_rd_Phi(get_irn_dbg_info(phi), block, n, inD, mode); /* rewire memory and kill the node */ for (i = n - 1; i >= 0; --i) { @@ -1627,19 +1628,19 @@ static unsigned optimize_phi(ir_node *phi, walk_env_t *wenv) } /* fourth step: create the Store */ - store = new_rd_Store(db, current_ir_graph, block, phiM, ptr, phiD); + store = new_rd_Store(db, block, phiM, ptr, phiD, 0); #ifdef DO_CACHEOPT co_set_irn_name(store, co_get_irn_ident(old_store)); #endif - projM = new_rd_Proj(NULL, current_ir_graph, block, store, mode_M, pn_Store_M); + projM = new_rd_Proj(NULL, block, store, mode_M, pn_Store_M); info = get_ldst_info(store, &wenv->obst); info->projs[pn_Store_M] = projM; /* fifths step: repair exception flow */ if (exc) { - ir_node *projX = new_rd_Proj(NULL, current_ir_graph, block, store, mode_X, pn_Store_X_except); + ir_node *projX = new_rd_Proj(NULL, block, store, mode_X, pn_Store_X_except); info->projs[pn_Store_X_except] = projX; info->exc_block = exc; @@ -1696,7 +1697,6 @@ typedef struct scc { typedef struct node_entry { unsigned DFSnum; /**< the DFS number of this node */ unsigned low; /**< the low number of this node */ - ir_node *header; /**< the header of this node */ int in_stack; /**< flag, set if the node is on the stack */ ir_node *next; /**< link to the next node the the same scc */ scc *pscc; /**< the scc of this node */ @@ -1783,6 +1783,33 @@ struct phi_entry { phi_entry *next; }; +/** + * An entry in the avail set. + */ +typedef struct avail_entry_t { + ir_node *ptr; /**< the address pointer */ + ir_mode *mode; /**< the load mode */ + ir_node *load; /**< the associated Load */ +} avail_entry_t; + +/** + * Compare two avail entries. + */ +static int cmp_avail_entry(const void *elt, const void *key, size_t size) { + const avail_entry_t *a = elt; + const avail_entry_t *b = key; + (void) size; + + return a->ptr != b->ptr || a->mode != b->mode; +} /* cmp_avail_entry */ + +/** + * Calculate the hash value of an avail entry. + */ +static unsigned hash_cache_entry(const avail_entry_t *entry) { + return get_irn_idx(entry->ptr) * 9 + HASH_PTR(entry->mode); +} /* hash_cache_entry */ + /** * Move loops out of loops if possible. * @@ -1794,6 +1821,9 @@ static void move_loads_out_of_loops(scc *pscc, loop_env *env) { ir_entity *ent; int j; 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) { @@ -1804,7 +1834,7 @@ static void move_loads_out_of_loops(scc *pscc, loop_env *env) { if (! is_Phi(phi)) continue; - assert(get_irn_mode(phi) == mode_M && "DFS geturn non-memory Phi"); + assert(get_irn_mode(phi) == mode_M && "DFS return non-memory Phi"); for (j = get_irn_arity(phi) - 1; j >= 0; --j) { ir_node *pred = get_irn_n(phi, j); @@ -1824,6 +1854,10 @@ static void move_loads_out_of_loops(scc *pscc, loop_env *env) { /* no Phis no fun */ assert(phi_list != NULL && "DFS found a loop without Phi"); + /* for now, we cannot handle more than one input (only reducible cf) */ + if (phi_list->next != NULL) + return; + for (load = pscc->head; load; load = next) { ir_mode *load_mode; node_entry *ne = get_irn_ne(load, env); @@ -1837,10 +1871,10 @@ static void move_loads_out_of_loops(scc *pscc, loop_env *env) { if (info->projs[pn_Load_res] == NULL || info->projs[pn_Load_X_regular] != NULL || info->projs[pn_Load_X_except] != NULL) continue; - /* for now, we can only handle Load(Global) */ + /* for now, we can only move Load(Global) */ if (! is_Global(ptr)) continue; - ent = get_Global_entity(ptr); + ent = get_Global_entity(ptr); load_mode = get_Load_mode(load); for (other = pscc->head; other != NULL; other = next_other) { node_entry *ne = get_irn_ne(other, env); @@ -1856,17 +1890,13 @@ static void move_loads_out_of_loops(scc *pscc, loop_env *env) { if (rel != ir_no_alias) break; } - /* only pure Calls are allowed here, so ignore them */ + /* only Phis and pure Calls are allowed here, so ignore them */ } if (other == NULL) { ldst_info_t *ninfo; phi_entry *pe; dbg_info *db; - /* for now, we cannot handle more than one input */ - if (phi_list->next != NULL) - return; - /* yep, no aliasing Store found, Load can be moved */ DB((dbg, LEVEL_1, " Found a Load that could be moved: %+F\n", load)); @@ -1877,16 +1907,26 @@ static void move_loads_out_of_loops(scc *pscc, loop_env *env) { ir_node *blk = get_nodes_block(phi); ir_node *pred = get_Block_cfgpred_block(blk, pos); ir_node *irn, *mem; - - pe->load = irn = new_rd_Load(db, current_ir_graph, pred, get_Phi_pred(phi, pos), ptr, load_mode); + avail_entry_t entry, *res; + + entry.ptr = ptr; + entry.mode = load_mode; + res = set_find(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, 0); + entry.load = irn; + set_insert(avail, &entry, sizeof(entry), hash_cache_entry(&entry)); + DB((dbg, LEVEL_1, " Created %+F in %+F\n", irn, pred)); + } + pe->load = irn; ninfo = get_ldst_info(irn, phase_obst(&env->ph)); - ninfo->projs[pn_Load_M] = mem = new_r_Proj(current_ir_graph, pred, irn, mode_M, pn_Load_M); + ninfo->projs[pn_Load_M] = mem = new_r_Proj(pred, irn, mode_M, pn_Load_M); set_Phi_pred(phi, pos, mem); - ninfo->projs[pn_Load_res] = new_r_Proj(current_ir_graph, pred, irn, load_mode, pn_Load_res); - - DB((dbg, LEVEL_1, " Created %+F in %+F\n", irn, pred)); + ninfo->projs[pn_Load_res] = new_r_Proj(pred, irn, load_mode, pn_Load_res); } /* now kill the old Load */ @@ -1897,6 +1937,7 @@ static void move_loads_out_of_loops(scc *pscc, loop_env *env) { } } } + del_set(avail); } /* move_loads_out_of_loops */ /** @@ -1919,13 +1960,12 @@ static void process_loop(scc *pscc, loop_env *env) { next = e->next; b = get_irn_ne(block, env); - if (header) { + if (header != NULL) { if (h->POnum < b->POnum) { header = block; h = b; } - } - else { + } else { header = block; h = b; } @@ -1980,10 +2020,12 @@ static void process_loop(scc *pscc, loop_env *env) { /* not a memory loop */ goto fail; } - if (! out_rc) { + if (out_rc == NULL) { + /* first region constant */ out_rc = pred; ++num_outside; } else if (out_rc != pred) { + /* another region constant */ ++num_outside; } } @@ -2003,22 +2045,20 @@ static void process_loop(scc *pscc, loop_env *env) { for (irn = pscc->head; irn; irn = next) { node_entry *e = get_irn_ne(irn, env); next = e->next; - e->header = NULL; exchange(irn, out_rc); } env->changes |= DF_CHANGED; return; } - /* set the header for every node in this scc */ +#ifdef DEBUG_libfirm for (irn = pscc->head; irn; irn = next) { node_entry *e = get_irn_ne(irn, env); - e->header = header; next = e->next; DB((dbg, LEVEL_2, " %+F,", irn)); } DB((dbg, LEVEL_2, "\n")); - +#endif move_loads_out_of_loops(pscc, env); fail: @@ -2081,7 +2121,7 @@ static void dfs(ir_node *irn, loop_env *env) ir_node *pred = get_irn_n(irn, i); node_entry *o = get_irn_ne(pred, env); - if (irn_not_visited(pred)) { + if (!irn_visited(pred)) { dfs(pred, env); node->low = MIN(node->low, o->low); } @@ -2092,7 +2132,7 @@ static void dfs(ir_node *irn, loop_env *env) ir_node *pred = get_fragile_op_mem(irn); node_entry *o = get_irn_ne(pred, env); - if (irn_not_visited(pred)) { + if (!irn_visited(pred)) { dfs(pred, env); node->low = MIN(node->low, o->low); } @@ -2102,7 +2142,7 @@ static void dfs(ir_node *irn, loop_env *env) ir_node *pred = get_Proj_pred(irn); node_entry *o = get_irn_ne(pred, env); - if (irn_not_visited(pred)) { + if (!irn_visited(pred)) { dfs(pred, env); node->low = MIN(node->low, o->low); } @@ -2168,7 +2208,7 @@ static void do_dfs(ir_graph *irg, loop_env *env) { for (i = get_End_n_keepalives(end) - 1; i >= 0; --i) { ir_node *ka = get_End_keepalive(end, i); - if (is_Phi(ka) && irn_not_visited(ka)) + if (is_Phi(ka) && !irn_visited(ka)) dfs(ka, env); } current_ir_graph = rem; @@ -2258,5 +2298,5 @@ int optimize_load_store(ir_graph *irg) { have Bad() predecessors. */ set_irg_doms_inconsistent(irg); } - return (int) env.changes; + return env.changes != 0; } /* optimize_load_store */