add an is_Quot function
[libfirm] / ir / opt / ifconv.c
index ff4764f..58f9034 100644 (file)
 
 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.
@@ -78,9 +91,11 @@ static ir_node* walk_to_projx(ir_node* start, const ir_node* dependency)
                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)) {
@@ -236,6 +251,7 @@ static void if_conv_walker(ir_node* block, void* env)
 {
        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;
@@ -257,14 +273,15 @@ restart:
 
                        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;
 
@@ -276,6 +293,9 @@ restart:
 
                                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
                                ));
@@ -287,7 +307,6 @@ restart:
                                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);
@@ -307,12 +326,14 @@ restart:
                                                        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 {
@@ -328,7 +349,10 @@ restart:
                                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);
@@ -599,37 +623,36 @@ static void optimise_psis(ir_node* node, void* env)
 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);
@@ -1621,8 +1644,6 @@ void opt_if_conv(ir_graph *irg, const opt_if_conv_info_t *params)
   DBG((dbg, LEVEL_1, "muxes made: %d\n", muxes_made));
 
   obstack_free(&obst, NULL);
-
-       dump_ir_block_graph(irg, "_ifconv_hack");
 }
 
 #endif