DEBUG_ONLY(firm_dbg_module_t *dbg);
+/** allow every Psi to be created. */
+static int default_allow_ifconv(ir_node *sel, ir_node* phi_list, int i, int j)
+{
+ return 1;
+}
+
+/**
+ * Default options.
+ */
+static const opt_if_conv_info_t default_info = {
+ 0, /* doesn't matter for Psi */
+ default_allow_ifconv
+};
/**
* Additional block info.
ir_node* pred_block = get_nodes_block(pred);
if (pred_block == dependency) {
- assert(is_Proj(pred));
- assert(get_irn_mode(pred) == mode_X);
- return pred;
+ if (is_Proj(pred)) {
+ assert(get_irn_mode(pred) == mode_X);
+ return pred;
+ }
+ return NULL;
}
if (is_Proj(pred)) {
{
int arity;
int i;
+ opt_if_conv_info_t *opt_info = env;
/* Bail out, if there are no Phis at all */
if (get_block_blockinfo(block)->phi == NULL) return;
cond = get_Proj_pred(projx0);
if (get_irn_op(cond) != op_Cond) continue;
+
/* We only handle boolean decisions, no switches */
if (get_irn_mode(get_Cond_selector(cond)) != mode_b) continue;
for (j = i + 1; j < arity; ++j) {
ir_node* projx1;
- ir_node* conds[0];
+ ir_node* conds[1];
ir_node* vals[2];
- ir_node* psi;
+ ir_node* psi = NULL;
ir_node* psi_block;
ir_node* phi;
if (projx1 == NULL) continue;
+ phi = get_block_blockinfo(block)->phi;
+ if (!opt_info->allow_ifconv(get_Cond_selector(cond), phi, i, j)) continue;
+
DB((dbg, LEVEL_1, "Found Cond %+F with proj %+F and %+F\n",
cond, projx0, projx1
));
conds[0] = get_Cond_selector(cond);
psi_block = get_nodes_block(cond);
- phi = get_block_blockinfo(block)->phi;
do {
ir_node* val_i = get_irn_n(phi, i);
ir_node* val_j = get_irn_n(phi, j);
vals[0] = val_j;
vals[1] = val_i;
}
+
psi = new_r_Psi(
current_ir_graph, psi_block, 1, conds, vals, get_irn_mode(phi)
);
DB((dbg, LEVEL_2, "Generating %+F for %+F\n", psi, phi));
}
+ /* only exchange if we have a Psi */
if (arity == 2) {
exchange(phi, psi);
} else {
if (arity == 2) {
#if 1
DB((dbg, LEVEL_1, "Welding block %+F and %+F\n", block, psi_block));
- get_block_blockinfo(block)->has_pinned |= get_block_blockinfo(psi_block)->has_pinned;
+ /* copy the block-info from the Psi-block to the block before merging */
+ get_block_blockinfo(psi_block)->has_pinned |= get_block_blockinfo(block)->has_pinned;
+ set_irn_link(block, get_irn_link(psi_block));
+
set_irn_in(block, get_irn_arity(psi_block), get_irn_in(psi_block) + 1);
exchange_cdep(psi_block, block);
exchange(psi_block, block);
void opt_if_conv(ir_graph *irg, const opt_if_conv_info_t *params)
{
struct obstack obst;
+ opt_if_conv_info_t p;
- if (!get_opt_if_conversion())
+ if (! get_opt_if_conversion())
return;
+ /* get the parameters */
+ if (params)
+ memcpy(&p, params, sizeof(p));
+ else
+ memcpy(&p, &default_info, sizeof(p));
+
FIRM_DBG_REGISTER(dbg, "firm.opt.ifconv");
DB((dbg, LEVEL_1, "Running if-conversion on %+F\n", irg));
- dump_ir_block_graph(irg, "_00_pre");
-
normalize_one_return(irg);
remove_critical_cf_edges(irg);
- dump_ir_block_graph(irg, "_01_normal");
-
compute_cdep(irg);
assure_doms(irg);
obstack_init(&obst);
irg_block_walk_graph(irg, init_block_link, NULL, &obst);
irg_walk_graph(irg, collect_phis, NULL, NULL);
- irg_block_walk_graph(irg, NULL, if_conv_walker, NULL);
+ irg_block_walk_graph(irg, NULL, if_conv_walker, &p);
- dump_ir_block_graph(irg, "_02_ifconv");
local_optimize_graph(irg);
- dump_ir_block_graph(irg, "_03_postopt");
irg_walk_graph(irg, NULL, optimise_psis, NULL);
- dump_ir_block_graph(irg, "_04_postifconv");
-
obstack_free(&obst, NULL);
free_dom(irg);
DBG((dbg, LEVEL_1, "muxes made: %d\n", muxes_made));
obstack_free(&obst, NULL);
-
- dump_ir_block_graph(irg, "_ifconv_hack");
}
#endif