/** * Check, whether a Return can be moved on block upwards. * * In a block with a Return, all live nodes must be linked * with the Return, otherwise they are dead (because the Return leaves * the graph, so no more users of the other nodes can exists. * * We can move a Return, if its predecessors are Phi nodes or * comes from another block. In the later case, it is always possible * to move the Return one block up, because the predecessor block must * dominate the Return block (SSA) and then it dominates the predecessor * block of the Return block as well. * * All predecessors of the Return block must be Jmp's of course, or we * cannot move it up, so we add blocks if needed. */ static bool can_move_ret(ir_node *ret) { ir_node *retbl = get_nodes_block(ret); int i, n = get_irn_arity(ret); for (i = 0; i < n; ++i) { ir_node *pred = get_irn_n(ret, i); if (! is_Phi(pred) && retbl == get_nodes_block(pred)) { /* first condition failed, found a non-Phi predecessor * then is in the Return block */ return false; } } /* check, that predecessors are Jmps */ n = get_Block_n_cfgpreds(retbl); /* we cannot move above a labeled block, as this might kill the block */ if (n <= 1 || get_Block_entity(retbl) != NULL) return false; for (i = 0; i < n; ++i) { ir_node *pred = get_Block_cfgpred(retbl, i); pred = skip_Tuple(pred); if (! is_Jmp(pred) && !is_Bad(pred)) { /* simply place a new block here */ ir_graph *irg = get_irn_irg(retbl); ir_node *block = new_r_Block(irg, 1, &pred); ir_node *jmp = new_r_Jmp(block); set_Block_cfgpred(retbl, i, jmp); } } return true; }
/* Walks back from n until it finds a real cf op. */ static ir_node *get_cf_op(ir_node *n) { while (!is_cfop(n) && !is_fragile_op(n) && !is_Bad(n)) { n = skip_Tuple(n); n = skip_Proj(n); } return n; }