BugFix: equivalent_node_Bound() was too greedy, reduced to a safe minimum (now mostly...
[libfirm] / ir / ir / irgopt.c
index 26937a7..ad794eb 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 1995-2007 University of Karlsruhe.  All right reserved.
+ * Copyright (C) 1995-2008 University of Karlsruhe.  All right reserved.
  *
  * This file is part of libFirm.
  *
@@ -52,7 +52,7 @@
 #include "irbackedge_t.h"
 #include "cgana.h"
 #include "trouts.h"
-
+#include "error.h"
 
 #include "irflag_t.h"
 #include "irhooks.h"
@@ -182,15 +182,13 @@ static void opt_walker(ir_node *n, void *env) {
 /* Applies local optimizations to all nodes in the graph until fixpoint. */
 void optimize_graph_df(ir_graph *irg) {
        pdeq     *waitq = new_pdeq();
-       int      state = edges_activated(irg);
        ir_graph *rem = current_ir_graph;
        ir_node  *end;
-       int      i;
+       int      i, state;
 
        current_ir_graph = irg;
 
-       if (! state)
-               edges_activate(irg);
+       state = edges_assure(irg);
 
        if (get_opt_global_cse())
                set_irg_pinned(current_ir_graph, op_pin_state_floats);
@@ -312,6 +310,7 @@ static void copy_node(ir_node *n, void *env) {
        ir_node *nn, *block;
        int new_arity;
        ir_op *op = get_irn_op(n);
+       (void) env;
 
        /* The end node looses it's flexible in array.  This doesn't matter,
           as dead node elimination builds End by hand, inlineing doesn't use
@@ -340,9 +339,13 @@ static void copy_node(ir_node *n, void *env) {
                get_irn_mode(n),
                new_arity,
                get_irn_in(n) + 1);
-               /* Copy the attributes.  These might point to additional data.  If this
-               was allocated on the old obstack the pointers now are dangling.  This
-       frees e.g. the memory of the graph_arr allocated in new_immBlock. */
+       /* Copy the attributes.  These might point to additional data.  If this
+          was allocated on the old obstack the pointers now are dangling.  This
+          frees e.g. the memory of the graph_arr allocated in new_immBlock. */
+       if (op == op_Block) {
+               /* we cannot allow blocks WITHOUT macroblock input */
+               set_irn_n(nn, -1, get_irn_n(n, -1));
+       }
        copy_node_attr(n, nn);
 
 #ifdef DEBUG_libfirm
@@ -379,7 +382,9 @@ static void copy_preds(ir_node *n, void *env) {
                        set_irn_n(nn, -1, nn);
                } else {
                        /* get the macro block header */
-                       set_irn_n(nn, -1, get_new_node(mbh));
+                       ir_node *nmbh = get_new_node(mbh);
+                       assert(nmbh != NULL);
+                       set_irn_n(nn, -1, nmbh);
                }
 
                /* Don't copy Bad nodes. */
@@ -412,7 +417,7 @@ static void copy_preds(ir_node *n, void *env) {
                                exchange(nn, old);
                        }
                }
-       } else if (is_Phi(n)) {
+       } else if (is_Phi(n) && get_irn_arity(n) > 0) {
                /* Don't copy node if corresponding predecessor in block is Bad.
                   The Block itself should not be Bad. */
                block = get_nodes_block(n);
@@ -611,68 +616,65 @@ copy_graph_env(int copy_node_nr) {
  * Adds all new nodes to a new hash table for CSE.  Does not
  * perform CSE, so the hash table might contain common subexpressions.
  */
-void
-dead_node_elimination(ir_graph *irg) {
-       if (get_opt_optimize() && get_opt_dead_node_elimination()) {
-               ir_graph *rem;
+void dead_node_elimination(ir_graph *irg) {
+       ir_graph *rem;
 #ifdef INTERPROCEDURAL_VIEW
-               int rem_ipview = get_interprocedural_view();
+       int rem_ipview = get_interprocedural_view();
 #endif
-               struct obstack *graveyard_obst = NULL;
-               struct obstack *rebirth_obst   = NULL;
-               assert(! edges_activated(irg) && "dead node elimination requires disabled edges");
+       struct obstack *graveyard_obst = NULL;
+       struct obstack *rebirth_obst   = NULL;
+       assert(! edges_activated(irg) && "dead node elimination requires disabled edges");
 
-               /* inform statistics that we started a dead-node elimination run */
-               hook_dead_node_elim(irg, 1);
+       /* inform statistics that we started a dead-node elimination run */
+       hook_dead_node_elim(irg, 1);
 
-               /* Remember external state of current_ir_graph. */
-               rem = current_ir_graph;
-               current_ir_graph = irg;
+       /* Remember external state of current_ir_graph. */
+       rem = current_ir_graph;
+       current_ir_graph = irg;
 #ifdef INTERPROCEDURAL_VIEW
-               set_interprocedural_view(0);
+       set_interprocedural_view(0);
 #endif
 
-               assert(get_irg_phase_state(irg) != phase_building);
+       assert(get_irg_phase_state(irg) != phase_building);
 
-               /* Handle graph state */
-               free_callee_info(irg);
-               free_irg_outs(irg);
-               free_trouts();
+       /* Handle graph state */
+       free_callee_info(irg);
+       free_irg_outs(irg);
+       free_trouts();
 
-               /* @@@ so far we loose loops when copying */
-               free_loop_information(irg);
+       /* @@@ so far we loose loops when copying */
+       free_loop_information(irg);
 
-               set_irg_doms_inconsistent(irg);
+       set_irg_doms_inconsistent(irg);
 
-               /* A quiet place, where the old obstack can rest in peace,
-                  until it will be cremated. */
-               graveyard_obst = irg->obst;
+       /* A quiet place, where the old obstack can rest in peace,
+          until it will be cremated. */
+       graveyard_obst = irg->obst;
 
-               /* A new obstack, where the reachable nodes will be copied to. */
-               rebirth_obst = xmalloc(sizeof(*rebirth_obst));
-               irg->obst = rebirth_obst;
-               obstack_init(irg->obst);
-               irg->last_node_idx = 0;
+       /* A new obstack, where the reachable nodes will be copied to. */
+       rebirth_obst = xmalloc(sizeof(*rebirth_obst));
+       irg->obst = rebirth_obst;
+       obstack_init(irg->obst);
+       irg->last_node_idx = 0;
 
-               /* We also need a new value table for CSE */
-               del_identities(irg->value_table);
-               irg->value_table = new_identities();
+       /* We also need a new value table for CSE */
+       del_identities(irg->value_table);
+       irg->value_table = new_identities();
 
-               /* Copy the graph from the old to the new obstack */
-               copy_graph_env(/*copy_node_nr=*/1);
+       /* Copy the graph from the old to the new obstack */
+       copy_graph_env(/*copy_node_nr=*/1);
 
-               /* Free memory from old unoptimized obstack */
-               obstack_free(graveyard_obst, 0);  /* First empty the obstack ... */
-               xfree(graveyard_obst);            /* ... then free it.           */
+       /* Free memory from old unoptimized obstack */
+       obstack_free(graveyard_obst, 0);  /* First empty the obstack ... */
+       xfree(graveyard_obst);            /* ... then free it.           */
 
-               /* inform statistics that the run is over */
-               hook_dead_node_elim(irg, 0);
+       /* inform statistics that the run is over */
+       hook_dead_node_elim(irg, 0);
 
-               current_ir_graph = rem;
+       current_ir_graph = rem;
 #ifdef INTERPROCEDURAL_VIEW
-               set_interprocedural_view(rem_ipview);
+       set_interprocedural_view(rem_ipview);
 #endif
-       }
 }
 
 /**
@@ -775,6 +777,7 @@ static void relink_bad_predecessors(ir_node *n, void *env) {
  * changes).
  */
 void remove_bad_predecessors(ir_graph *irg) {
+       panic("Fix backedge handling first");
        irg_walk_graph(irg, firm_clear_link, relink_bad_predecessors, NULL);
 }
 
@@ -994,8 +997,8 @@ int inline_method(ir_node *call, ir_graph *called_graph) {
        ir_type *called_frame;
        irg_inline_property prop = get_irg_inline_property(called_graph);
 
-       if ( (prop < irg_inline_forced) &&
-            (!get_opt_optimize() || !get_opt_inline() || (prop == irg_inline_forbidden))) return 0;
+       if ( (prop < irg_inline_forced) || (prop == irg_inline_forbidden))
+               return 0;
 
        /* Do not inline variadic functions. */
        if (get_method_variadicity(get_entity_type(get_irg_entity(called_graph))) == variadicity_variadic)
@@ -1343,7 +1346,7 @@ static ir_graph *get_call_called_irg(ir_node *call) {
        ir_graph *called_irg = NULL;
 
        addr = get_Call_ptr(call);
-       if (is_SymConst(addr) && get_SymConst_kind(addr) == symconst_addr_ent) {
+       if (is_SymConst_addr_ent(addr)) {
                called_irg = get_entity_irg(get_SymConst_entity(addr));
        }
 
@@ -1387,8 +1390,6 @@ void inline_small_irgs(ir_graph *irg, int size) {
        call_entry *entry;
        DEBUG_ONLY(firm_dbg_module_t *dbg;)
 
-       if (!(get_opt_optimize() && get_opt_inline())) return;
-
        FIRM_DBG_REGISTER(dbg, "firm.opt.inline");
 
        current_ir_graph = irg;
@@ -1570,8 +1571,6 @@ void inline_leave_functions(int maxsize, int leavesize, int size, int ignore_run
        struct obstack   obst;
        DEBUG_ONLY(firm_dbg_module_t *dbg;)
 
-       if (!(get_opt_optimize() && get_opt_inline())) return;
-
        FIRM_DBG_REGISTER(dbg, "firm.opt.inline");
        rem = current_ir_graph;
        obstack_init(&obst);
@@ -1711,11 +1710,12 @@ void inline_leave_functions(int maxsize, int leavesize, int size, int ignore_run
                        optimize_graph_df(irg);
                        optimize_cf(irg);
                }
-               if (env->got_inline || (env->n_callers_orig != env->n_callers))
+               if (env->got_inline || (env->n_callers_orig != env->n_callers)) {
                        DB((dbg, SET_LEVEL_1, "Nodes:%3d ->%3d, calls:%3d ->%3d, callers:%3d ->%3d, -- %s\n",
                        env->n_nodes_orig, env->n_nodes, env->n_call_nodes_orig, env->n_call_nodes,
                        env->n_callers_orig, env->n_callers,
                        get_entity_name(get_irg_entity(irg))));
+               }
        }
 
        obstack_free(&obst, NULL);
@@ -2224,7 +2224,8 @@ void place_code(ir_graph *irg) {
 }
 
 typedef struct cf_env {
-       char changed;       /**< flag indicates that the cf graphs has changed. */
+       char ignore_exc_edges; /**< set if exception edges should be ignored. */
+       char changed;          /**< flag indicates that the cf graphs has changed. */
 } cf_env;
 
 /**
@@ -2252,14 +2253,18 @@ static void walk_critical_cf_edges(ir_node *n, void *env) {
                        const ir_op *cfop;
 
                        pre = get_irn_n(n, i);
-                       cfop = get_irn_op(skip_Proj(pre));
+                       /* don't count Bad's */
+                       if (is_Bad(pre))
+                               continue;
 
+                       cfop = get_irn_op(skip_Proj(pre));
                        if (is_op_fragile(cfop)) {
-                               if (cfop != op_Raise)
-                                       goto insert;
-                               continue;
+                               if (cenv->ignore_exc_edges && get_Proj_proj(pre) == pn_Generic_X_except)
+                                       continue;
+                               goto insert;
                        }
-                       if (is_op_forking(cfop)) {
+                       /* we don't want place nodes in the start block, so handle it like forking */
+                       if (is_op_forking(cfop) || cfop == op_Start) {
                                /* Predecessor has multiple successors. Insert new control flow edge edges. */
 insert:
                                /* set predecessor of new block */
@@ -2277,7 +2282,8 @@ insert:
 void remove_critical_cf_edges(ir_graph *irg) {
        cf_env env;
 
-       env.changed = 0;
+       env.ignore_exc_edges = 1;
+       env.changed          = 0;
 
        irg_block_walk_graph(irg, NULL, walk_critical_cf_edges, &env);
        if (env.changed) {