X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fopt%2Fldstopt.c;h=ed8faf341bd3c813d649f7ff90c982b6ac2109e7;hb=288b414e4d82e0aa0d4b4348d8c387db02142cdb;hp=d43a0b56e75ca6ea42a59f66f2b3b7a510e2f9fd;hpb=31ef53136fdb86d4a98919c2148c95cadea4ea81;p=libfirm diff --git a/ir/opt/ldstopt.c b/ir/opt/ldstopt.c index d43a0b56e..ed8faf341 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 @@ -50,6 +48,7 @@ #include "irmemory.h" #include "irphase_t.h" #include "irgopt.h" +#include "set.h" #include "debug.h" /** The debug handle. */ @@ -1444,6 +1443,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); @@ -1629,7 +1629,7 @@ 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, current_ir_graph, block, phiM, ptr, phiD, 0); #ifdef DO_CACHEOPT co_set_irn_name(store, co_get_irn_ident(old_store)); #endif @@ -1698,7 +1698,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 */ @@ -1785,6 +1784,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. * @@ -1796,6 +1822,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) { @@ -1806,7 +1835,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); @@ -1826,6 +1855,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); @@ -1839,10 +1872,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); @@ -1858,17 +1891,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)); @@ -1879,16 +1908,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, current_ir_graph, 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); 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)); } /* now kill the old Load */ @@ -1899,6 +1938,7 @@ static void move_loads_out_of_loops(scc *pscc, loop_env *env) { } } } + del_set(avail); } /* move_loads_out_of_loops */ /** @@ -1921,13 +1961,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; } @@ -1982,10 +2021,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; } } @@ -2005,22 +2046,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: @@ -2260,5 +2299,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 */