fehler 21
[libfirm] / ir / be / belistsched.c
index 1fa744e..5edf3a4 100644 (file)
@@ -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);
        }
@@ -351,49 +380,37 @@ 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;
+       make_users_ready(env, irn);
 }
 
+#ifdef SCHEDULE_PROJS
 /**
  * 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
@@ -426,14 +443,14 @@ static void add_tuple_projs(block_sched_env_t *env, ir_node *irn)
 
                assert(is_Proj(out) && "successor of a modeT node must be a proj");
 
-               if (get_irn_mode(out) == mode_T)
+               if (get_irn_mode(out) == mode_T) {
                        add_tuple_projs(env, out);
-               else {
+               else {
                        add_to_sched(env, out);
-                       make_users_ready(env, out);
                }
        }
 }
+#endif
 
 /**
  * Perform list scheduling on a block.
@@ -490,12 +507,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
@@ -529,7 +547,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;
@@ -546,10 +564,10 @@ static void list_sched_block(ir_node *block, void *env_ptr)
                /* Add the node to the schedule. */
                add_to_sched(&be, irn);
 
+#ifdef SCHEDULE_PROJS
                if (get_irn_mode(irn) == mode_T)
                        add_tuple_projs(&be, irn);
-               else
-                       make_users_ready(&be, irn);
+#endif
 
                /* remove the scheduled node from the ready list. */
                ir_nodeset_remove(&be.cands, irn);
@@ -563,7 +581,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;