fehler69: endless loop compiled program. maybe spill problem.
[libfirm] / ir / be / belistsched.c
index 300f920..21770ca 100644 (file)
@@ -123,7 +123,7 @@ static lc_opt_enum_int_var_t sched_prep_var = {
 static const lc_opt_table_entry_t list_sched_option_table[] = {
        LC_OPT_ENT_ENUM_PTR("prep",   "schedule preparation",   &sched_prep_var),
        LC_OPT_ENT_ENUM_PTR("select", "node selector",          &sched_select_var),
-       { NULL }
+       LC_OPT_LAST
 };
 
 /**
@@ -158,6 +158,24 @@ typedef struct _block_sched_env_t {
        void *selector_block_env;
 } block_sched_env_t;
 
+/**
+ * Returns non-zero if a node must be placed in the schedule.
+ */
+static INLINE int must_appear_in_schedule(const list_sched_selector_t *sel, void *block_env, const ir_node *irn)
+{
+       int res = -1;
+
+       /* if there are no uses, don't schedule */
+       if (get_irn_n_edges(irn) < 1)
+               return 0;
+
+       /* else ask the scheduler */
+       if (sel->to_appear_in_schedule)
+               res = sel->to_appear_in_schedule(block_env, irn);
+
+       return res >= 0 ? res : ((to_appear_in_schedule(irn) || BE_SCHED_NODE(irn)) && ! is_Unknown(irn));
+}
+
 /**
  * Returns non-zero if the node is already scheduled
  */
@@ -172,7 +190,7 @@ static INLINE int is_already_scheduled(block_sched_env_t *env, ir_node *n)
 /**
  * Mark a node as already scheduled
  */
-static INLINE void mark_already_scheduled(block_sched_env_t *env, ir_node *n)
+static INLINE void set_already_scheduled(block_sched_env_t *env, ir_node *n)
 {
        int idx = get_irn_idx(n);
 
@@ -180,6 +198,8 @@ static INLINE void mark_already_scheduled(block_sched_env_t *env, ir_node *n)
        env->sched_info[idx].already_sched = 1;
 }
 
+static void add_to_sched(block_sched_env_t *env, ir_node *irn);
+
 /**
  * Try to put a node in the ready set.
  * @param env   The block scheduler environment.
@@ -217,13 +237,18 @@ static INLINE int make_ready(block_sched_env_t *env, ir_node *pred, ir_node *irn
                        return 0;
        }
 
-       ir_nodeset_insert(&env->cands, irn);
+       if (! must_appear_in_schedule(env->selector, env, irn)) {
+               add_to_sched(env, irn);
+               DB((dbg, LEVEL_3, "\tmaking immediately available: %+F\n", irn));
+       } else {
+               ir_nodeset_insert(&env->cands, irn);
 
-       /* Notify selector about the ready node. */
-       if (env->selector->node_ready)
-               env->selector->node_ready(env->selector_block_env, irn, pred);
+               /* Notify selector about the ready node. */
+               if (env->selector->node_ready)
+                       env->selector->node_ready(env->selector_block_env, irn, pred);
 
-    DB((dbg, LEVEL_2, "\tmaking ready: %+F\n", irn));
+               DB((dbg, LEVEL_2, "\tmaking ready: %+F\n", irn));
+       }
 
     return 1;
 }
@@ -235,18 +260,22 @@ static INLINE int make_ready(block_sched_env_t *env, ir_node *pred, ir_node *irn
  * @param env The block schedule environment.
  * @param irn The node, which usages (successors) are to be made ready.
  */
-static INLINE void make_users_ready(block_sched_env_t *env, ir_node *irn)
+static void make_users_ready(block_sched_env_t *env, ir_node *irn)
 {
        const ir_edge_t *edge;
 
+       /* make all data users ready */
        foreach_out_edge(irn, edge) {
                ir_node *user = get_edge_src_irn(edge);
+
                if (! is_Phi(user))
                        make_ready(env, irn, user);
        }
 
+       /* and the dependent nodes as well */
        foreach_out_edge_kind(irn, edge, EDGE_KIND_DEP) {
                ir_node *user = get_edge_src_irn(edge);
+
                if (! is_Phi(user))
                        make_ready(env, irn, user);
        }
@@ -296,10 +325,11 @@ static int get_num_successors(ir_node *irn) {
                        ir_node *proj = get_edge_src_irn(edge);
                        ir_mode *mode = get_irn_mode(proj);
 
-                       if (mode == mode_T)
+                       if (mode == mode_T) {
                                sum += get_num_successors(proj);
-                       else if (mode_is_datab(mode))
+                       } else if (mode_is_datab(mode)) {
                                sum += get_irn_n_edges(proj);
+                       }
                }
        }
        else {
@@ -315,7 +345,7 @@ static int get_num_successors(ir_node *irn) {
 
 /**
  * Adds irn to @p live, updates all inputs that this user is scheduled
- * and counts all of it's non scheduled users.
+ * and counts all of its non scheduled users.
  */
 static void update_sched_liveness(block_sched_env_t *env, ir_node *irn) {
        int i;
@@ -328,8 +358,7 @@ static void update_sched_liveness(block_sched_env_t *env, ir_node *irn) {
                ir_node *in = get_irn_in_or_dep(irn, i);
 
                /* if in is a proj: update predecessor */
-               while (is_Proj(in))
-                       in = get_Proj_pred(in);
+               in = skip_Proj(in);
 
                /* if in is still in the live set: reduce number of users by one */
                if (ir_nodeset_contains(&env->live, in)) {
@@ -351,88 +380,34 @@ static void update_sched_liveness(block_sched_env_t *env, ir_node *irn) {
        }
 }
 
-static INLINE int must_appear_in_schedule(const list_sched_selector_t *sel, void *block_env, const ir_node *irn)
-{
-       int res = -1;
-
-       if (get_irn_n_edges(irn) < 1)
-               return 0;
-
-       if (sel->to_appear_in_schedule)
-               res = sel->to_appear_in_schedule(block_env, irn);
-
-       return res >= 0 ? res : ((to_appear_in_schedule(irn) || BE_SCHED_NODE(irn)) && ! is_Unknown(irn));
-}
-
 /**
  * Append an instruction to a schedule.
  * @param env The block scheduling environment.
  * @param irn The node to add to the schedule.
  * @return    The given node.
  */
-static ir_node *add_to_sched(block_sched_env_t *env, ir_node *irn)
+static void add_to_sched(block_sched_env_t *env, ir_node *irn)
 {
     /* If the node consumes/produces data, it is appended to the schedule
      * list, otherwise, it is not put into the list */
     if (must_appear_in_schedule(env->selector, env->selector_block_env, irn)) {
                update_sched_liveness(env, irn);
-        sched_add_before(env->block, irn);
+               sched_add_before(env->block, irn);
 
-        DBG((dbg, LEVEL_2, "\tadding %+F\n", irn));
+               DBG((dbg, LEVEL_2, "\tadding %+F\n", irn));
+
+               /* Remove the node from the ready set */
+               ir_nodeset_remove(&env->cands, irn);
     }
 
        /* notify the selector about the finally selected node. */
        if (env->selector->node_selected)
                env->selector->node_selected(env->selector_block_env, irn);
 
-    /* Insert the node in the set of all already scheduled nodes. */
-    mark_already_scheduled(env, irn);
-
-    /* Remove the node from the ready set */
-       ir_nodeset_remove(&env->cands, irn);
+    /* Insert the node in the set of all available scheduled nodes. */
+    set_already_scheduled(env, irn);
 
-    return irn;
-}
-
-/**
- * Add the proj nodes of a tuple-mode irn to the schedule immediately
- * after the tuple-moded irn. By pinning the projs after the irn, no
- * other nodes can create a new lifetime between the tuple-moded irn and
- * one of its projs. This should render a realistic image of a
- * tuple-moded irn, which in fact models a node which defines multiple
- * values.
- *
- * @param irn The tuple-moded irn.
- */
-static void add_tuple_projs(block_sched_env_t *env, ir_node *irn)
-{
-       const ir_edge_t *edge;
-
-       assert(get_irn_mode(irn) == mode_T && "Mode of node must be tuple");
-
-       if (is_Bad(irn))
-               return;
-
-
-       /* non-proj nodes can have dependency edges to tuple nodes. */
-       foreach_out_edge_kind(irn, edge, EDGE_KIND_DEP) {
-               ir_node *out = get_edge_src_irn(edge);
-               make_ready(env, irn, out);
-       }
-
-       /* schedule the normal projs */
-       foreach_out_edge(irn, edge) {
-               ir_node *out = get_edge_src_irn(edge);
-
-               assert(is_Proj(out) && "successor of a modeT node must be a proj");
-
-               if (get_irn_mode(out) == mode_T)
-                       add_tuple_projs(env, out);
-               else {
-                       add_to_sched(env, out);
-                       make_users_ready(env, out);
-               }
-       }
+       make_users_ready(env, irn);
 }
 
 /**
@@ -490,12 +465,13 @@ static void list_sched_block(ir_node *block, void *env_ptr)
                                transfer data flow from the predecessors to this block.
                        */
                        add_to_sched(&be, irn);
-                       make_users_ready(&be, irn);
                }
                else if (irn == start_node) {
                        /* The start block will be scheduled as the first node */
                        add_to_sched(&be, irn);
+#ifdef SCHEDULE_PROJS
                        add_tuple_projs(&be, irn);
+#endif
                }
                else {
                        /* Other nodes must have all operands in other blocks to be made
@@ -509,10 +485,9 @@ static void list_sched_block(ir_node *block, void *env_ptr)
                                if (get_nodes_block(operand) == block) {
                                        ready = 0;
                                        break;
-                               }
-                               else {
+                               } else {
                                        /* live in values increase register pressure */
-                                       update_sched_liveness(&be, operand);
+                                       ir_nodeset_insert(&be.live, operand);
                                }
                        }
 
@@ -530,7 +505,7 @@ static void list_sched_block(ir_node *block, void *env_ptr)
                /* collect statistics about amount of ready nodes */
                be_do_stat_sched_ready(block, &be.cands);
 
-               /* Keeps must be scheduled immediatly */
+               /* Keeps must be scheduled immediately */
                foreach_ir_nodeset(&be.cands, irn, iter) {
                        if (be_is_Keep(irn) || be_is_CopyKeep(irn) || is_Sync(irn)) {
                                break;
@@ -547,11 +522,6 @@ static void list_sched_block(ir_node *block, void *env_ptr)
                /* Add the node to the schedule. */
                add_to_sched(&be, irn);
 
-               if (get_irn_mode(irn) == mode_T)
-                       add_tuple_projs(&be, irn);
-               else
-                       make_users_ready(&be, irn);
-
                /* remove the scheduled node from the ready list. */
                ir_nodeset_remove(&be.cands, irn);
        }
@@ -564,7 +534,7 @@ static void list_sched_block(ir_node *block, void *env_ptr)
 }
 
 /* List schedule a graph. */
-void list_sched(const be_irg_t *birg, be_options_t *be_opts)
+void list_sched(be_irg_t *birg, be_options_t *be_opts)
 {
        const arch_env_t *arch_env = birg->main_env->arch_env;
        ir_graph         *irg      = birg->irg;
@@ -574,6 +544,8 @@ void list_sched(const be_irg_t *birg, be_options_t *be_opts)
        mris_env_t *mris = NULL;
        list_sched_selector_t sel;
 
+       (void)be_opts;
+
        /* Select a scheduler based on backend options */
        switch (list_sched_options.select) {
                case BE_SCHED_SELECT_TRIVIAL:
@@ -645,7 +617,8 @@ void list_sched(const be_irg_t *birg, be_options_t *be_opts)
 }
 
 /* List schedule a block. */
-void list_sched_single_block(const be_irg_t *birg, ir_node *block, be_options_t *be_opts)
+void list_sched_single_block(const be_irg_t *birg, ir_node *block,
+                             be_options_t *be_opts)
 {
        const arch_env_t *arch_env = birg->main_env->arch_env;
        ir_graph         *irg      = birg->irg;
@@ -654,6 +627,8 @@ void list_sched_single_block(const be_irg_t *birg, ir_node *block, be_options_t
        sched_env_t env;
        list_sched_selector_t sel;
 
+       (void)be_opts;
+
        /* Select a scheduler based on backend options */
        switch (list_sched_options.select) {
                case BE_SCHED_SELECT_TRIVIAL: