/**
* 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)) {
}
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);
}
}
+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);
+ }
}
}
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;
}
/* 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);
}
_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));
+}