}
-/**
- * Block-walker: searches for the following construct
- *
- * Const or Phi with constants
- * |
- * Cmp
- * |
- * Cond
- * /
- * ProjX
- * /
- * Block
- */
-static void cond_eval(ir_node* block, void* data)
+static int cond_eval_cmp(ir_node* proj_b, ir_node* block, ir_node* projx, ir_node* cond)
{
- condeval_env_t env;
- int *changed = data;
ir_graph *irg = current_ir_graph;
- ir_node *copy_block;
- ir_node *pred;
- ir_node *projx;
- ir_node *cond;
- ir_node *cmp;
- ir_node *left;
- ir_node *right;
- ir_node *cond_block;
- pn_Cmp pnc;
-
- if(get_Block_n_cfgpreds(block) != 1)
- return;
+ ir_node *cmp = get_Proj_pred(proj_b);
+ ir_node *left;
+ ir_node *right;
+ ir_node *cond_block;
+ ir_node *copy_block;
+ pn_Cmp pnc;
- projx = get_Block_cfgpred(block, 0);
- if (!is_Proj(projx))
- return;
- assert(get_irn_mode(projx) == mode_X);
-
- cond = get_Proj_pred(projx);
- if (!is_Cond(cond))
- return;
-
- pred = get_Cond_selector(cond);
- // TODO handle switches
- if (get_irn_mode(pred) != mode_b)
- return;
- if (!is_Proj(pred))
- return;
- pnc = get_Proj_proj(pred);
-
- cmp = get_Proj_pred(pred);
assert(is_Cmp(cmp));
left = get_Cmp_left(cmp);
right = get_Cmp_right(cmp);
assert(get_irn_mode(left) == get_irn_mode(right));
+ pnc = get_Proj_proj(proj_b);
/* we assume that the cond_block is the true case */
if (get_Proj_proj(projx) == pn_Cond_false) {
pnc = get_negated_pnc(pnc, get_irn_mode(left));
}
if(!is_Const(right))
- return;
+ return 0;
cond_block = get_nodes_block(cond);
pred = new_Bad();
}
set_Block_cfgpred(block, 0, pred);
- *changed = 1;
- set_irg_doms_inconsistent(irg);
- set_irg_extblk_inconsistent(irg);
- set_irg_loopinfo_inconsistent(irg);
} else {
+ condeval_env_t env;
+
if(get_nodes_block(left) != cond_block)
- return;
+ return 0;
// (recursively) look if a pred of a phi is a constant
env.true_block = block;
copy_block = find_phi_with_const(projx, left, &env);
- if(copy_block != NULL) {
- /* we have to remove the edge towards the pred as the pred now
- * jumps into the true_block. We also have to shorten phis
- * in our block because of this */
- const ir_edge_t *edge, *next;
- ir_node* bad = new_Bad();
- size_t cnst_pos = env.cnst_pos;
+ if (copy_block == NULL)
+ return 0;
- /* shorten phis */
- foreach_out_edge_safe(env.cnst_pred, edge, next) {
- ir_node *node = get_edge_src_irn(edge);
+ /* we have to remove the edge towards the pred as the pred now
+ * jumps into the true_block. We also have to shorten phis
+ * in our block because of this */
+ const ir_edge_t *edge, *next;
+ ir_node* bad = new_Bad();
+ size_t cnst_pos = env.cnst_pos;
- if(is_Phi(node))
- set_Phi_pred(node, cnst_pos, bad);
- }
+ /* shorten phis */
+ foreach_out_edge_safe(env.cnst_pred, edge, next) {
+ ir_node *node = get_edge_src_irn(edge);
- set_Block_cfgpred(env.cnst_pred, cnst_pos, bad);
-
- /* the graph is changed now */
- *changed = 1;
+ if(is_Phi(node))
+ set_Phi_pred(node, cnst_pos, bad);
}
+
+ set_Block_cfgpred(env.cnst_pred, cnst_pos, bad);
}
+ /* the graph is changed now */
+ return 1;
+}
+
+
+/**
+ * Block-walker: searches for the following construct
+ *
+ * Const or Phi with constants
+ * |
+ * Cmp
+ * |
+ * Cond
+ * /
+ * ProjX
+ * /
+ * Block
+ */
+static void cond_eval(ir_node* block, void* data)
+{
+ int *changed = data;
+ ir_node *pred;
+ ir_node *projx;
+ ir_node *cond;
+
+ if(get_Block_n_cfgpreds(block) != 1)
+ return;
+
+ projx = get_Block_cfgpred(block, 0);
+ if (!is_Proj(projx))
+ return;
+ assert(get_irn_mode(projx) == mode_X);
+
+ cond = get_Proj_pred(projx);
+ if (!is_Cond(cond))
+ return;
+
+ pred = get_Cond_selector(cond);
+ // TODO handle switches
+ if (get_irn_mode(pred) != mode_b)
+ return;
+ if (!is_Proj(pred))
+ return;
+
+ if (cond_eval_cmp(pred, block, projx, cond))
+ *changed = 1;
}
void opt_cond_eval(ir_graph* irg)