From: Christian Helmer Date: Tue, 15 Dec 2009 17:41:52 +0000 (+0000) Subject: Loop peeling and inversion functional but with errors in combination. X-Git-Url: http://nsz.repo.hu/git/?a=commitdiff_plain;h=24a5c9dd081da94e603f22cc3691f2d92e1f64e4;p=libfirm Loop peeling and inversion functional but with errors in combination. [r26794] --- diff --git a/ir/opt/loop.c b/ir/opt/loop.c index c130a9f45..e973bd4a1 100644 --- a/ir/opt/loop.c +++ b/ir/opt/loop.c @@ -37,6 +37,7 @@ #include "irtools.h" #include "array_t.h" /* automatic array */ #include "beutil.h" /* get_block */ +#include "irloop_t.h" /* set_irn_loop */ // TODO during DBG //#include "irnode_t.h" @@ -107,7 +108,7 @@ static out_edges *cond_chain_entries; static unsigned head_inversion_node_count; static unsigned head_inversion_node_limit; -//static unsigned head_inversion_block_count; +static unsigned head_inversion_block_count; /** * @@ -195,7 +196,8 @@ static unsigned is_alien_edge(ir_node *n, int i) static void unmark_block(ir_node *node, void * env) { (void) env; -// DB((dbg, LEVEL_1, "UNMARK %ld\n", node->node_nr)); + DB((dbg, LEVEL_4, "UNMARK ...")); + DB((dbg, LEVEL_4, " UNMARK %ld\n", get_irn_node_nr(node))); if(is_Block(node)) set_Block_mark(node, 0); } @@ -205,6 +207,20 @@ static unsigned is_nodesblock_marked(ir_node* node) return (get_Block_mark(get_block(node))); } +/* Returns the number of blocks in a loop. */ +int get_loop_n_blocks(ir_loop *loop) { + int elements, e; + int blocks = 0; + elements = get_loop_n_elements(loop); + + for(e=0; e= 0; --i) { - ir_node *pred = get_irn_n(node, i); - if (get_irn_visited(pred) < get_irg_visited(irg)) { - stop = loop_walker_rec(pred, pre, post, env); - if (stop) - return stop; - } - } - - if (post) - return post(node, env); - return 0; -} - -/** - * Walks through loop nodes. - * The entries of the loop (all edges pointing into the loop) have to be given. - */ -static unsigned loop_walker(out_edges *entries, - irg_walk_func_abortable *pre, irg_walk_func_abortable *post, void * env) -{ - int i; - int stop = 0; - - for (i=0; !stop && ilink; - DB((dbg, LEVEL_5, "ssa already visited: use linked %ld\n", get_irn_node_nr(value))); + DB((dbg, LEVEL_4, "ssa already visited: use linked %ld\n", get_irn_node_nr(value))); return value; } @@ -457,7 +405,7 @@ static ir_node *search_def_and_create_phis(ir_node *block, ir_mode *mode) ir_node *pred_block = get_Block_cfgpred_block(block, 0); ir_node *value; - DB((dbg, LEVEL_5, "ssa 1 pred: walk pred %ld\n", get_irn_node_nr(pred_block))); + DB((dbg, LEVEL_4, "ssa 1 pred: walk pred %ld\n", get_irn_node_nr(pred_block))); value = search_def_and_create_phis(pred_block, mode); get_node_info(block)->link = value; @@ -478,7 +426,7 @@ static ir_node *search_def_and_create_phis(ir_node *block, ir_mode *mode) /* EVERY node is assumed to have a node_info linked. */ alloc_node_info(phi, NULL); - DB((dbg, LEVEL_5, "ssa phi creation: link new phi %ld to block %ld\n", get_irn_node_nr(phi), get_irn_node_nr(block))); + DB((dbg, LEVEL_4, "ssa phi creation: link new phi %ld to block %ld\n", get_irn_node_nr(phi), get_irn_node_nr(block))); get_node_info(block)->link = phi; mark_irn_visited(block); @@ -487,7 +435,7 @@ static ir_node *search_def_and_create_phis(ir_node *block, ir_mode *mode) for(i = 0; i < n_cfgpreds; ++i) { ir_node *pred_block = get_Block_cfgpred_block(block, i); ir_node *pred_val = search_def_and_create_phis(pred_block, mode); - DB((dbg, LEVEL_5, "ssa phi pred:phi %ld, pred %ld\n", get_irn_node_nr(phi), get_irn_node_nr(pred_val))); + DB((dbg, LEVEL_4, "ssa phi pred:phi %ld, pred %ld\n", get_irn_node_nr(phi), get_irn_node_nr(pred_val))); set_irn_n(phi, i, pred_val); } @@ -537,7 +485,7 @@ static void construct_ssa(ir_node *orig_block, ir_node *orig_val, if (is_End(user)) continue; - DB((dbg, LEVEL_5, "original user %ld\n", get_irn_node_nr(user))); + DB((dbg, LEVEL_4, "original user %ld\n", get_irn_node_nr(user))); if (is_Phi(user)) { ir_node *pred_block = get_Block_cfgpred_block(user_block, j); @@ -764,15 +712,15 @@ static void copy_walk(ir_node *node, walker_condition *walk_condition) */ if (get_irn_visited(node) >= get_irg_visited(irg)) { /* Here we rely on nodestate's copy being initialized with NULL */ - DB((dbg, LEVEL_5, "copy_walk: We have already visited %ld\n", get_irn_node_nr(node))); + DB((dbg, LEVEL_4, "copy_walk: We have already visited %ld\n", get_irn_node_nr(node))); if (node_info->copy == NULL) { - if (!is_Const(node) && !is_SymConst(node)) { +// if (!is_Const(node) && !is_SymConst(node)) { cp = rawcopy_node(node); - } else { - cp = node; - node_info->copy = cp; - } - DB((dbg, LEVEL_5, "The TEMP copy of %ld is created %ld\n", get_irn_node_nr(node), get_irn_node_nr(cp))); +// } else { +// cp = node; +// node_info->copy = cp; +// } + DB((dbg, LEVEL_4, "The TEMP copy of %ld is created %ld\n", get_irn_node_nr(node), get_irn_node_nr(cp))); } return; } @@ -785,7 +733,7 @@ static void copy_walk(ir_node *node, walker_condition *walk_condition) if (!is_Block(node)) { ir_node *pred = get_nodes_block(node); if (walk_condition(pred)) - DB((dbg, LEVEL_5, "walk block %ld\n", get_irn_node_nr(pred))); + DB((dbg, LEVEL_4, "walk block %ld\n", get_irn_node_nr(pred))); copy_walk( pred, walk_condition ); } @@ -797,10 +745,10 @@ static void copy_walk(ir_node *node, walker_condition *walk_condition) ir_node *pred = get_irn_n(node, i); if (walk_condition(pred)) { - DB((dbg, LEVEL_5, "walk node %ld\n", get_irn_node_nr(pred))); + DB((dbg, LEVEL_4, "walk node %ld\n", get_irn_node_nr(pred))); copy_walk( pred, walk_condition ); cpin[i] = get_copy(pred); - DB((dbg, LEVEL_5, "copy of %ld gets new in %ld which is copy of %ld\n", + DB((dbg, LEVEL_4, "copy of %ld gets new in %ld which is copy of %ld\n", get_irn_node_nr(node), get_irn_node_nr(get_copy(pred)), get_irn_node_nr(pred))); } else { cpin[i] = pred; @@ -812,17 +760,17 @@ static void copy_walk(ir_node *node, walker_condition *walk_condition) /* No temporary copy existent */ /* Do not copy constants TODO right? */ - if (!is_Const(node) && !is_SymConst(node)) { +// if (!is_Const(node) && !is_SymConst(node)) { cp = rawcopy_node(node); - } else { - cp = node; - node_info->copy = cp; - } - DB((dbg, LEVEL_5, "The FINAL copy of %ld is CREATED %ld\n", get_irn_node_nr(node), get_irn_node_nr(cp))); +// } else { +// cp = node; +// node_info->copy = cp; +// } + DB((dbg, LEVEL_4, "The FINAL copy of %ld is CREATED %ld\n", get_irn_node_nr(node), get_irn_node_nr(cp))); } else { /* temporary copy is existent but without correct ins */ cp = get_copy(node); - DB((dbg, LEVEL_5, "The FINAL copy of %ld is EXISTENT %ld\n", get_irn_node_nr(node), get_irn_node_nr(cp))); + DB((dbg, LEVEL_4, "The FINAL copy of %ld is EXISTENT %ld\n", get_irn_node_nr(node), get_irn_node_nr(cp))); } if (!is_Block(node)) { @@ -837,6 +785,8 @@ static void copy_walk(ir_node *node, walker_condition *walk_condition) set_Block_MacroBlock(cp, cp); } + //TODO do? + //set_irn_loop(cp, cur_loop); set_irn_in(cp, ARR_LEN(cpin), cpin); } @@ -906,14 +856,19 @@ static void get_head_entries(ir_node *node, void *env) int arity = get_irn_arity(node); (void) env; + DB((dbg, LEVEL_5, "get head entries \n")); + for(i = 0; i < arity; ++i) { /* node is not in the head, but the predecessor is. * (head or loop chain nodes are marked) */ + DB((dbg, LEVEL_5, "... ")); + DB((dbg, LEVEL_5, "node %ld marked %d (0) pred %d marked %d (1) \n", + node->node_nr, is_nodesblock_marked(node),i, is_nodesblock_marked(get_irn_n(node, i)))); if (!is_nodesblock_marked(node) && is_nodesblock_marked(get_irn_n(node, i))) { out_edges entry; entry.node = node; entry.pred_irn_n = i; - DB((dbg, LEVEL_5, + DB((dbg, LEVEL_4, "Found head chain entry %ld @%d because !inloop %ld and inloop %ld\n", node->node_nr, i, node->node_nr, get_irn_n(node, i)->node_nr)); ARR_APP1(out_edges, cur_head_outs, entry); @@ -930,32 +885,39 @@ static void get_head_entries(ir_node *node, void *env) static unsigned condition_chains(ir_node *block) { const ir_edge_t *edge; unsigned mark = 0; - //unsigned over_limit = 0; - int nodes_n = 0; + printf("cd %ld\n", block->node_nr); + /* we need all outs, including keeps (TODO firm function for that??) */ foreach_out_edge_kind(block, edge, EDGE_KIND_NORMAL) { ++nodes_n; } - /* We do not want to collect more nodes from condition chains, than the limit allows us to. */ - if (head_inversion_node_count + nodes_n > head_inversion_node_limit) { - //over_limit = 1; + /* We do not want to collect more nodes from condition chains, than the limit allows us to. + * Also, leave at least one block as body. */ + if (head_inversion_node_count + nodes_n > head_inversion_node_limit + || loop_info.blocks == head_inversion_block_count + 1) { set_Block_mark(block, 0); -// printf(" %ld over limit\n", block->node_nr); + printf(" %ld over limit\n", block->node_nr); return 0; } - ++loop_info.blocks; + printf("blocks ++ %ld\n", block->node_nr); +// ++loop_info.blocks; /* First: check our successors, and add all succs that are outside of the loop to the list */ foreach_block_succ(block, edge) { ir_node *src = get_edge_src_irn( edge ); int pos = get_edge_src_pos( edge ); + printf("check %ld\n", src->node_nr); + + if (src->loop) + printf(" src %ld in loop %ld curlooop %ld \n", src->node_nr, src->loop->loop_nr, cur_loop->loop_nr); if (!is_in_loop(src)) { - //printf(" src %ld @ %d into block %ld \n", src->node_nr, pos, block->node_nr); + printf(" src %ld @ %d into block %ld \n", src->node_nr, pos, block->node_nr); + mark = 1; out_edges entry; entry.node = src; @@ -968,11 +930,14 @@ static unsigned condition_chains(ir_node *block) { /* this block is not part of the chain, * because the chain would become too big or we have no succ outside of the loop */ if (mark == 0) { + printf("mark is 0 %ld\n", block->node_nr); set_Block_mark(block, 0); return 0; } else { + printf("mark is 1 %ld\n", block->node_nr); set_Block_mark(block, 1); - DB((dbg, LEVEL_5, "block %ld is part of condition chain\n", get_irn_node_nr(block))); + ++head_inversion_block_count; + DB((dbg, LEVEL_4, "block %ld is part of condition chain\n", get_irn_node_nr(block))); head_inversion_node_count += nodes_n; } @@ -983,11 +948,13 @@ static unsigned condition_chains(ir_node *block) { int pos = get_edge_src_pos( edge ); /* already done cases */ - if (!is_in_loop( src ) || (get_irn_visited(src) >= get_irg_visited(current_ir_graph))) + if (!is_in_loop( src ) || (get_irn_visited(src) >= get_irg_visited(current_ir_graph))) { +// printf("!inloop || visited %ld\n", block->node_nr); continue; + } mark_irn_visited(src); - + DB((dbg, LEVEL_4, "condition chain walk %ld\n", get_irn_node_nr(src))); inchain = condition_chains( src ); /* if successor is not part of chain we need to collect its outs */ @@ -1039,7 +1006,7 @@ static void inversion_fix_heads(void) * Rewire the head blocks ins and their phi ins. * Requires phi list per block. */ - if ( is_backedge(loophead, i) ) { + if ( is_backedge(loophead, i) && !is_alien_edge(loophead, i) ) { invheadnins[iheadin_c] = pred; for_each_phi(invhead, phi) { get_node_info( phi )->ins[iheadin_c] = get_irn_n( phi, i) ; @@ -1107,11 +1074,11 @@ static void loop_inversion_walk(out_edges *head_entries) // add_End_keepalive(get_irg_end(current_ir_graph), pred); if (is_Block(node)) { - DB((dbg, LEVEL_5, "\nINIT walk block %ld\n", get_irn_node_nr(pred))); + DB((dbg, LEVEL_4, "\nINIT walk block %ld\n", get_irn_node_nr(pred))); copy_walk(pred, is_nodesblock_marked); duplicate_preds(node, entry.pred_irn_n, get_copy(pred) ); } else { - DB((dbg, LEVEL_5, "\nInit walk node %ld\n", get_irn_node_nr(pred))); + DB((dbg, LEVEL_4, "\nInit walk node %ld\n", get_irn_node_nr(pred))); copy_walk( pred, is_nodesblock_marked ); /* ignore keepalives */ @@ -1126,8 +1093,6 @@ static void loop_inversion_walk(out_edges *head_entries) inversion_fix_heads(); - DEBUG_ONLY(dump_ir_block_graph(current_ir_graph, "-headsfixed")); - /* Generate phis for users of values assigned in the condition chain and read in the loops body */ for(i = 0; i < entry_c; i++) { ir_node *cppred, *block, *cpblock, *pred; @@ -1140,7 +1105,7 @@ static void loop_inversion_walk(out_edges *head_entries) cppred = get_copy(pred); block = get_nodes_block(pred); cpblock = get_nodes_block(cppred); - DB((dbg, LEVEL_5, + DB((dbg, LEVEL_4, "construct_ssa (loop out value) original %ld and clone %ld\n", get_irn_node_nr(pred), get_irn_node_nr(cppred))); construct_ssa(block, pred, cpblock, cppred); @@ -1165,7 +1130,7 @@ static void loop_inversion_walk(out_edges *head_entries) inv_inhead_phi_def = get_copy(inhead_phi_def); def_block = get_nodes_block(inhead_phi_def); inv_def_block = get_nodes_block(inv_inhead_phi_def); - DB((dbg, LEVEL_5, + DB((dbg, LEVEL_4, "construct_ssa (condition chain out values) original %ld and clone %ld\n", get_irn_node_nr(inv_inhead_phi_def), get_irn_node_nr(inhead_phi_def))); construct_ssa(inv_def_block, inv_inhead_phi_def, def_block, inhead_phi_def); @@ -1182,7 +1147,7 @@ static void decision_maker(void) unsigned do_peel = 0; unsigned do_inversion = 1; - unsigned max_loop_opnodes = 200000; + unsigned max_loop_opnodes = 2000000; head_inversion_node_limit = 99910; @@ -1240,28 +1205,39 @@ static void decision_maker(void) ir_reserve_resources(current_ir_graph, IR_RESOURCE_BLOCK_MARK); irg_walk_graph(current_ir_graph, unmark_block, NULL, NULL); + loop_info.blocks = get_loop_n_blocks(cur_loop); cond_chain_entries = NEW_ARR_F(out_edges, 0); head_inversion_node_count = 0; + head_inversion_block_count = 0; inc_irg_visited(current_ir_graph); set_Block_mark(loop_cf_head, 1); mark_irn_visited(loop_cf_head); /* find condition chains */ condition_chains(loop_cf_head); - // TODO assume number of phis to be created. prevent inversion... + DEBUG_ONLY(dump_ir_block_graph(current_ir_graph, "-pre_inversion")); + + // TODO assume number of phis to be created. prevent inversion in case ... /* Loop inversion */ + /* We catch endless loops here too, + * because they do not have a condition chain and a maximum of 1 block. */ if (loop_info.blocks < 2) { do_inversion = 0; - DB((dbg, LEVEL_2, "Loop contains %d (less than 2) blocks => No Inversion done.\n", loop_info.blocks)); + DB((dbg, LEVEL_1, "Loop contains %d (less than 2) blocks => No Inversion done.\n", loop_info.blocks)); } + if (head_inversion_block_count < 1) { + do_inversion = 0; + DB((dbg, LEVEL_1, "Loop contains %d (less than 1) invertible blocks => No Inversion done.\n", head_inversion_block_count)); + } + + if (do_inversion) { cur_head_outs = NEW_ARR_F(out_edges, 0); /* get all edges pointing into the head or condition chain */ irg_walk_graph(current_ir_graph, get_head_entries, NULL, NULL); - loop_inversion_walk(cur_head_outs); DEL_ARR_F(cur_head_outs); @@ -1323,6 +1299,9 @@ void loop_optimization(ir_graph *irg) ir_loop *loop; int sons, nr; + FIRM_DBG_REGISTER(dbg, "firm.opt.loop"); + firm_dbg_set_mask(dbg, -1); + DB((dbg, LEVEL_1, " >>> loop optimization (Startnode %ld) <<<\n", get_irn_node_nr(get_irg_start(irg)))); /* Init */ @@ -1351,7 +1330,7 @@ void loop_optimization(ir_graph *irg) free_node_info(); ir_free_resources(irg, IR_RESOURCE_PHI_LIST|IR_RESOURCE_IRN_LINK); - DB((dbg, LEVEL_1, " >>> loop optimization done (Startnode %ld)<<<\n", get_irn_node_nr(get_irg_start(irg)))); + DB((dbg, LEVEL_1, " >>> loop optimization done (Startnode %ld) <<<\n", get_irn_node_nr(get_irg_start(irg)))); } void firm_init_loop(void) {