#include "firmstat.h"
#include "cfopt.h"
+#include "iropt_dbg.h"
/*------------------------------------------------------------------*/
/* Control flow optimization. */
* Replace binary Conds that jumps twice into the same block
* by a simple Jmp.
* E.g.
- * @code
+ * @verbatim
* Cond Jmp Bad
* / \ | /
* ProjX True ProjX False ==> | /
* \ / | /
* Block Block
- * @endcode
+ * @endverbatim
*
* Such pattern are the result of if-conversion.
*
*/
static void remove_senseless_conds(ir_node *bl, void *data)
{
- int i, j;
- int n = get_Block_n_cfgpreds(bl);
+ int i, j;
+ int n = get_Block_n_cfgpreds(bl);
- assert(is_Block(bl));
+ assert(is_Block(bl));
- for (i = 0; i < n; ++i) {
- ir_node *pred_i = get_Block_cfgpred(bl, i);
- ir_node *cond_i = skip_Proj(pred_i);
+ for (i = 0; i < n; ++i) {
+ ir_node *pred_i = get_Block_cfgpred(bl, i);
+ ir_node *cond_i = skip_Proj(pred_i);
- for (j = i + 1; j < n; ++j) {
- ir_node *pred_j = get_Block_cfgpred(bl, j);
- ir_node *cond_j = skip_Proj(pred_j);
+ for (j = i + 1; j < n; ++j) {
+ ir_node *pred_j = get_Block_cfgpred(bl, j);
+ ir_node *cond_j = skip_Proj(pred_j);
- if (cond_j == cond_i
- && get_irn_op(cond_i) == op_Cond
- && get_irn_mode(get_Cond_selector(cond_i)) == mode_b) {
+ if (cond_j == cond_i
+ && get_irn_op(cond_i) == op_Cond
+ && get_irn_mode(get_Cond_selector(cond_i)) == mode_b) {
- ir_node *jmp = new_r_Jmp(current_ir_graph, get_nodes_block(cond_i));
- set_irn_n(bl, i, jmp);
- set_irn_n(bl, j, new_Bad());
+ ir_node *jmp = new_r_Jmp(current_ir_graph, get_nodes_block(cond_i));
+ set_irn_n(bl, i, jmp);
+ set_irn_n(bl, j, new_Bad());
DBG_OPT_IFSIM2(cond_i, jmp);
- break;
- }
- }
- }
+ break;
+ }
+ }
+ }
}
/* see below */
new_block = equivalent_node(n);
- if (new_block != n && ! is_Bad(new_block))
+ if (new_block != n && ! is_Block_dead(new_block))
exchange (n, new_block);
} else if (get_opt_optimize() && (get_irn_mode(n) == mode_X)) {
/* We will soon visit a block. Optimize it before visiting! */
ir_node *b = get_nodes_block(skip_Proj(n));
- if (!is_Bad(b)) {
+ if (!is_Block_dead(b)) {
new_block = equivalent_node(b);
- while (irn_not_visited(b) && (!is_Bad(new_block)) && (new_block != b)) {
+ while (irn_not_visited(b) && (!is_Block_dead(new_block)) && (new_block != b)) {
/* We would have to run gigo() if new is bad, so we
promote it directly below. Nevertheless, we sometimes reach a block
the first time through a dataflow node. In this case we optimized the
/* normally, we would create a Bad block here, but this must be
* prevented, so just set it's cf to Bad.
*/
- if (is_Bad(new_block))
+ if (is_Block_dead(new_block))
exchange(n, new_Bad());
}
}
if (! is_Bad(pred_X)) {
ir_node *pred_bl = get_nodes_block(skip_Proj(pred_X));
- if (is_Bad(pred_bl) || (get_Block_dom_depth(pred_bl) == -1))
+ if (is_Block_dead(pred_bl) || (get_Block_dom_depth(pred_bl) < 0))
exchange (pred_X, new_Bad());
}
}
* The test is rather tricky.
*
* The situation is something like the following:
- *
+ * @verbatim
* if-block
* / \
* then-b else-b
* \ /
* b
+ * @endverbatim
*
- * b merges the control flow of an if-then-else. We may not remove
- * the 'then' _and_ the 'else' block of an 'if' if there is a Phi
- * node in b, even if both are empty. The destruction of this Phi
- * requires that a copy is added before the merge. We have to
- * keep one of the case blocks to place the copies in.
+ * b merges the control flow of an if-then-else. We may not remove
+ * the 'then' _and_ the 'else' block of an 'if' if there is a Phi
+ * node in b, even if both are empty. The destruction of this Phi
+ * requires that a copy is added before the merge. We have to
+ * keep one of the case blocks to place the copies in.
*
- * To perform the test for pos, we must regard predecessors before pos
- * as already removed.
+ * To perform the test for pos, we must regard predecessors before pos
+ * as already removed.
**/
static int test_whether_dispensable(ir_node *b, int pos) {
int i, j, n_preds = 1;
* for all nodes, not regarding whether there is a possibility for optimization.
*
* For each predecessor p of a Block b there are three cases:
- * 1. The predecessor p is a Bad node: just skip it. The in array of b shrinks by one.
- * 2. The predecessor p is empty. Remove p. All predecessors of p are now
- * predecessors of b.
- * 3. The predecessor p is a block containing useful code. Just keep p as is.
+ * -#. The predecessor p is a Bad node: just skip it. The in array of b shrinks by one.
+ * -#. The predecessor p is empty. Remove p. All predecessors of p are now
+ * predecessors of b.
+ * -#. The predecessor p is a block containing useful code. Just keep p as is.
*
* For Phi nodes f we have to check the conditions at the Block of f.
* For cases 1 and 3 we proceed as for Blocks. For case 2 we can have two
* cases:
- * 2a: The old predecessor of the Phi f is a Phi pred_f IN THE BLOCK REMOVED. In this
+ * -2a: The old predecessor of the Phi f is a Phi pred_f IN THE BLOCK REMOVED. In this
* case we proceed as for blocks. We remove pred_f. All
* predecessors of pred_f now are predecessors of f.
- * 2b: The old predecessor of f is NOT in the block removed. It might be a Phi, too.
+ * -2b: The old predecessor of f is NOT in the block removed. It might be a Phi, too.
* We have to replicate f for each predecessor of the removed block. Or, with
* other words, the removed predecessor block has exactly one predecessor.
*
* Further there is a special case for self referencing blocks:
+ * @verbatim
*
* then_b else_b then_b else_b
* \ / \ /
* | | | | | |
* | |____| | |____|
* | |
+ * @endverbatim
*
* If there is a Phi in pred_b, but we remove pred_b, we have to generate a
* Phi in loop_b, that has the ins of the Phi in pred_b and a self referencing
irg_dom_state dom_state = get_irg_dom_state(current_ir_graph);
current_ir_graph = irg;
+ /* if the graph is not pinned, we cannot determine empty blocks */
+ assert(get_irg_pinned(irg) != op_pin_state_floats &&
+ "Control flow optimization need a pinned graph");
+
/* Handle graph state */
assert(get_irg_phase_state(irg) != phase_building);
if (get_irg_outs_state(current_ir_graph) == outs_consistent)
for (i = 0, n = get_End_n_keepalives(end); i < n; ++i) {
ir_node *ka = get_End_keepalive(end, i);
- if (is_Block(ka) && (get_Block_dom_depth(ka) == -1))
- set_End_keepalive(end, i, new_Bad());
- if (is_Phi(ka) && (get_Block_dom_depth(get_nodes_block(ka)) == -1))
+ if (is_Block(ka)) {
+ if (get_Block_dom_depth(ka) == -1)
+ set_End_keepalive(end, i, new_Bad());
+ }
+ else if (get_Block_dom_depth(get_nodes_block(ka)) == -1)
set_End_keepalive(end, i, new_Bad());
}
}
} else if (get_irn_op(ka) == op_Phi) {
mark_irn_visited(ka);
ARR_APP1 (ir_node *, in, ka);
+ } else if (get_irn_op(ka) == op_IJmp) {
+ mark_irn_visited(ka);
+ ARR_APP1 (ir_node *, in, ka);
}
}
}