X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fana%2Firextbb.c;h=2d5ee83e40b9cd3d74806c3a6073dfe9d643ed04;hb=5afaf595a454bb6b87899b317f2ae99ed03bf62e;hp=b26208945c5c5658d13bffb60181b78fd03db753;hpb=a97b92c4dcc62fc145d7adf6945a13c1ae0f47ee;p=libfirm diff --git a/ir/ana/irextbb.c b/ir/ana/irextbb.c index b26208945..2d5ee83e4 100644 --- a/ir/ana/irextbb.c +++ b/ir/ana/irextbb.c @@ -62,26 +62,22 @@ static void addto_extblk(ir_extblk *extblk, ir_node *block) /** * Pre block-walker. Calculates the extended block info. - * Currently, we use the (free) block input of all basis blocks - * to point to the leader block. */ static void pre_walk_calc_extbb(ir_node *block, void *ctx) { int n = get_Block_n_cfgpreds(block); env_t *env = ctx; - if (n > 1 || block == get_irg_start_block(current_ir_graph)) { + if (n <= 0 || n > 1 || block == get_irg_start_block(current_ir_graph)) { /* - * block is a JOIN-node ie he control flow from + * block is a JOIN-node ie the control flow from * many other blocks joins here. block is a leader. + * Note that we handle unreachable blocks (n <= 0) here too. */ allocate_extblk(block, env); } - else { - ir_node *add_to = get_Block_cfgpred(block, 0); - - if (! is_Bad(add_to)) - add_to = get_nodes_block(add_to); + else { /* we have only one control flow predecessor */ + ir_node *add_to = get_Block_cfgpred_block(block, 0); /* blocks with only one BAD predecessors are leaders too */ if (is_Bad(add_to)) { @@ -89,7 +85,7 @@ static void pre_walk_calc_extbb(ir_node *block, void *ctx) } else { /* - * Only on control flow predecessor. This block belongs + * Only one control flow predecessor. This block belongs * to the same extended basic block as its predecessor. */ set_Block_extbb(block, NULL); @@ -97,25 +93,52 @@ static void pre_walk_calc_extbb(ir_node *block, void *ctx) } } +static int _sentinel; + /** * Post block-walker. Calculates the extended block info. * During construction, we use the (free) block input of all basic blocks * to point to there previous block. */ -static void post_walk_calc_extbb(ir_node *block, void *env) +static void post_walk_calc_extbb(ir_node *block, void *ctx) { ir_extblk *extbb = get_Block_extbb(block); + env_t *env = ctx; + ir_extblk *sentinel = (ir_extblk *)&_sentinel; if (! extbb) { - ir_node *prev = block; + ir_node *curr, *prev; - /* search the leader */ - do { - prev = get_nodes_block(get_Block_cfgpred(prev, 0)); + /* + * Search the leader. It can happen, that we fall into an endless + * loop, because we enter an unreachable loop that is not yet detected. + * We break the loop using a sentinel. + */ + for (curr = block; !extbb; curr = prev) { + prev = get_Block_cfgpred_block(curr, 0); extbb = get_Block_extbb(prev); - } while (! extbb); + set_Block_extbb(curr, sentinel); + } + + if (extbb == sentinel) { + /* We detect a dead loop. We fix this by allocating an + * special Extended block + */ + ir_printf("Dead loop detected starting with %+F::%+F\n", get_irg_entity(current_ir_graph), block); - addto_extblk(extbb, block); + allocate_extblk(block, env); + extbb = get_Block_extbb(block); + set_Block_extbb(block, sentinel); + } + + /* replace all sentinels by the extbb info */ + prev = block; + while (1) { + if (get_Block_extbb(prev) != sentinel) + break; + set_Block_extbb(prev, extbb); + prev = get_Block_cfgpred_block(prev, 0); + } } } @@ -156,7 +179,8 @@ void compute_extbb(ir_graph *irg) { for (block = extbb->link, i = 0; i < len; ++i) { ir_node *nblock = get_irn_link(block); - extbb->blks[i] = block; + /* ensure that the leader is the first one */ + extbb->blks[len - 1 - i] = block; set_irn_link(block, NULL); block = nblock; } @@ -180,7 +204,7 @@ void free_extbb(ir_graph *irg) { /* Return the extended block of a node. */ ir_extblk *get_nodes_extbb(ir_node *node) { - ir_node *block = is_Block(node) ? node : get_nodes_block(node); + ir_node *block = is_Block(node) ? node : get_irn_n(node, -1); return get_Block_extbb(block); } @@ -219,12 +243,22 @@ void (set_extbb_link)(ir_extblk *blk, void *link) { _set_extbb_link(blk, link); } -/* Return the number of basis blocks of an extended block */ +/* Return the number of basic blocks of an extended block */ int (get_extbb_n_blocks)(const ir_extblk *blk) { return _get_extbb_n_blocks(blk); } -/* Return the i'th basis block of an extended block */ +/* Return the i'th basic block of an extended block */ ir_node *(get_extbb_block)(ir_extblk *blk, int pos) { return _get_extbb_block(blk, pos); } + +/* Return the leader basis block of an extended block. */ +ir_node *(get_extbb_leader)(ir_extblk *blk) { + return _get_extbb_leader(blk); +} + +/* Return the node number of an extended block. */ +long get_extbb_node_nr(ir_extblk *blk) { + return get_irn_node_nr(get_extbb_leader(blk)); +}