X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;ds=sidebyside;f=ir%2Fbe%2Fbelistsched.c;h=7111443c7eca7535ecc87040dc9867eda9ac31f1;hb=77f1eeaeb90f2d231b0ccc2fcbe071a9b457e6c3;hp=d898439b99542553350fe5a1b45f81f84d2be3a5;hpb=d26125ca5720072a4975d37c0a17f7ad6c18de2d;p=libfirm diff --git a/ir/be/belistsched.c b/ir/be/belistsched.c index d898439b9..7111443c7 100644 --- a/ir/be/belistsched.c +++ b/ir/be/belistsched.c @@ -4,6 +4,9 @@ * @date 20.10.2004 * @author Sebastian Hack */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif #include #include @@ -19,6 +22,7 @@ #include "iterator.h" #include "irdump.h" #include "irprintf_t.h" +#include "debug.h" #include "besched_t.h" #include "beutil.h" @@ -28,42 +32,55 @@ * Scheduling environment for the whole graph. */ typedef struct _sched_env_t { - const ir_graph *irg; /**< The graph to schedule. */ - list_sched_selector_t *select; /**< The node selector. */ - void *select_env; /**< A pointer to give to the selector. */ + const ir_graph *irg; /**< The graph to schedule. */ + const list_sched_selector_t *selector; /**< The node selector. */ + void *selector_env; /**< A pointer to give to the selector. */ } sched_env_t; -ir_node *trivial_selector(void *env, ir_node *block, int curr_time, - pset *already_scheduled, pset *ready_list) +static ir_node *trivial_select(void *env, void *block_env, const struct list_head *sched_head, + int curr_time, pset *ready_set) { - ir_node *res = pset_first(ready_list); - pset_break(ready_list); - return res; + ir_node *res = pset_first(ready_set); + pset_break(ready_set); + return res; } +static const list_sched_selector_t trivial_selector_struct = { + NULL, + NULL, + trivial_select, + NULL, + NULL +}; + +const list_sched_selector_t *trivial_selector = &trivial_selector_struct; + static void list_sched_block(ir_node *block, void *env_ptr); -void list_sched(ir_graph *irg, list_sched_selector_t *selector, void *select_env) +void list_sched(ir_graph *irg, const list_sched_selector_t *selector) { - sched_env_t env; + sched_env_t env; + + memset(&env, 0, sizeof(env)); + env.selector = selector; + env.selector_env = selector->init_graph ? selector->init_graph(irg) : NULL; + env.irg = irg; - memset(&env, 0, sizeof(env)); - env.select = selector; - env.select_env = select_env; - env.irg = irg; + /* Normalize proj nodes. */ + normalize_proj_nodes(irg); - /* Normalize proj nodes. */ - normalize_proj_nodes(irg); + /* Compute the outs */ + if(get_irg_outs_state(irg) != outs_consistent) + compute_outs(irg); - /* Compute the outs */ - if(get_irg_outs_state(irg) != outs_consistent) - compute_outs(irg); + /* Dump the graph. */ + //dump_ir_block_graph(irg, "-before-sched"); - /* Dump the graph. */ - dump_ir_block_graph(irg, "-before-sched"); + /* Schedule each single block. */ + irg_block_walk_graph(irg, list_sched_block, NULL, &env); - /* Schedule each single block. */ - irg_block_walk_graph(irg, list_sched_block, NULL, &env); + if(selector->finish_graph) + selector->finish_graph(env.selector_env, irg); } @@ -71,10 +88,11 @@ void list_sched(ir_graph *irg, list_sched_selector_t *selector, void *select_env * Environment for a block scheduler. */ typedef struct _block_sched_env_t { - int curr_time; - pset *ready_set; - pset *already_scheduled; - ir_node *block; + int curr_time; + pset *ready_set; + pset *already_scheduled; + ir_node *block; + firm_dbg_module_t *dbg; } block_sched_env_t; @@ -87,15 +105,15 @@ typedef struct _block_sched_env_t { */ static INLINE int to_appear_in_schedule(ir_node *irn) { - int i, n; + int i, n; - for(i = 0, n = get_irn_arity(irn); i < n; ++i) { - ir_node *op = get_irn_n(irn, i); - if(mode_is_datab(get_irn_mode(op))) - return 1; - } + for(i = 0, n = get_irn_arity(irn); i < n; ++i) { + ir_node *op = get_irn_n(irn, i); + if(mode_is_datab(get_irn_mode(op))) + return 1; + } - return mode_is_datab(get_irn_mode(irn)); + return mode_is_datab(get_irn_mode(irn)); } @@ -107,32 +125,32 @@ static INLINE int to_appear_in_schedule(ir_node *irn) */ static INLINE int make_ready(block_sched_env_t *env, ir_node *irn) { - int i, n; - - /* Blocks cannot be scheduled. */ - if(is_Block(irn)) - return 0; - - /* - * Check, if the given ir node is in a different block as the - * currently scheduled one. If that is so, don't make the node ready. - */ - if(env->block != get_nodes_block(irn)) - return 0; - - for(i = 0, n = get_irn_arity(irn); i < n; ++i) { - ir_node *op = get_irn_n(irn, i); - - /* If the operand is local to the scheduled block and not yet - * scheduled, this nodes cannot be made ready, so exit. */ - if(!pset_find_ptr(env->already_scheduled, op) && get_nodes_block(op) == env->block) - return 0; - } + int i, n; + + /* Blocks cannot be scheduled. */ + if(is_Block(irn)) + return 0; - ir_debugf("\tmaking ready: %n\n", irn); - pset_insert_ptr(env->ready_set, irn); + /* + * Check, if the given ir node is in a different block as the + * currently scheduled one. If that is so, don't make the node ready. + */ + if(env->block != get_nodes_block(irn)) + return 0; - return 1; + for(i = 0, n = get_irn_arity(irn); i < n; ++i) { + ir_node *op = get_irn_n(irn, i); + + /* If the operand is local to the scheduled block and not yet + * scheduled, this nodes cannot be made ready, so exit. */ + if(!pset_find_ptr(env->already_scheduled, op) && get_nodes_block(op) == env->block) + return 0; + } + + DBG((env->dbg, LEVEL_2, "\tmaking ready: %n\n", irn)); + pset_insert_ptr(env->ready_set, irn); + + return 1; } /** @@ -162,12 +180,13 @@ static INLINE int make_ready(block_sched_env_t *env, ir_node *irn) */ static INLINE void make_users_ready(block_sched_env_t *env, ir_node *irn) { - int i, n; + int i, n; - for(i = 0, n = get_irn_n_outs(irn); i < n; ++i) { - ir_node *user = get_irn_out(irn, i); - make_ready(env, user); - } + for(i = 0, n = get_irn_n_outs(irn); i < n; ++i) { + ir_node *user = get_irn_out(irn, i); + if(!is_Phi(user)) + make_ready(env, user); + } } /** @@ -178,7 +197,7 @@ static INLINE void make_users_ready(block_sched_env_t *env, ir_node *irn) */ static int node_cmp_func(const void *p1, const void *p2) { - return p1 != p2; + return p1 != p2; } /** @@ -189,24 +208,25 @@ static int node_cmp_func(const void *p1, const void *p2) */ static ir_node *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(to_appear_in_schedule(irn)) { - sched_info_t *info = get_irn_sched_info(irn); - INIT_LIST_HEAD(&info->list); - sched_add(env->block, irn); - - ir_debugf("\tadding %n\n", irn); - } + /* If the node consumes/produces data, it is appended to the schedule + * list, otherwise, it is not put into the list */ + if(to_appear_in_schedule(irn)) { + sched_info_t *info = get_irn_sched_info(irn); + INIT_LIST_HEAD(&info->list); + info->time_step = env->curr_time; + sched_add(env->block, irn); - /* Insert the node in the set of all already scheduled nodes. */ - pset_insert_ptr(env->already_scheduled, irn); + DBG((env->dbg, LEVEL_2, "\tadding %n\n", irn)); + } - /* Remove the node from the ready set */ - if(pset_find_ptr(env->ready_set, irn)) - pset_remove_ptr(env->ready_set, irn); + /* Insert the node in the set of all already scheduled nodes. */ + pset_insert_ptr(env->already_scheduled, irn); - return irn; + /* Remove the node from the ready set */ + if(pset_find_ptr(env->ready_set, irn)) + pset_remove_ptr(env->ready_set, irn); + + return irn; } @@ -230,21 +250,21 @@ static ir_node *add_to_sched(block_sched_env_t *env, ir_node *irn) */ static void add_tuple_projs(block_sched_env_t *env, ir_node *irn) { - int i, n; - assert(get_irn_mode(irn) == mode_T && "Mode of node must be tuple"); + int i, n; + assert(get_irn_mode(irn) == mode_T && "Mode of node must be tuple"); - for(i = 0, n = get_irn_n_outs(irn); i < n; ++i) { - ir_node *out = get_irn_out(irn, i); + for(i = 0, n = get_irn_n_outs(irn); i < n; ++i) { + ir_node *out = get_irn_out(irn, i); - assert(is_Proj(out) && "successor of a modeT node must be a proj"); + 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); - } - } + if(get_irn_mode(out) == mode_T) + add_tuple_projs(env, out); + else { + add_to_sched(env, out); + make_users_ready(env, out); + } + } } /** @@ -260,11 +280,13 @@ static void add_tuple_projs(block_sched_env_t *env, ir_node *irn) */ static void list_sched_block(ir_node *block, void *env_ptr) { + void *block_env = NULL; sched_env_t *env = env_ptr; block_sched_env_t be; + const list_sched_selector_t *selector = env->selector; ir_node *irn; - int j, m; + int i, n, j, m; int phi_seen = 0; sched_info_t *info = get_irn_sched_info(block); @@ -272,17 +294,25 @@ static void list_sched_block(ir_node *block, void *env_ptr) INIT_LIST_HEAD(&info->list); /* Initialize the block scheduling environment */ + be.dbg = firm_dbg_register("firm.be.sched"); be.block = block; be.curr_time = 0; be.ready_set = new_pset(node_cmp_func, get_irn_n_outs(block)); be.already_scheduled = new_pset(node_cmp_func, get_irn_n_outs(block)); - ir_debugf("scheduling %n\n", block); + if(selector->init_block) + block_env = selector->init_block(env->selector_env, block); + + DBG((be.dbg, LEVEL_1, "scheduling %n\n", block)); /* Then one can add all nodes are ready to the set. */ - for(int i = 0, n = get_irn_n_outs(block); i < n; ++i) { + for(i = 0, n = get_irn_n_outs(block); i < n; ++i) { ir_node *irn = get_irn_out(block, i); + /* Skip the end node because of keepalive edges. */ + if(get_irn_opcode(irn) == iro_End) + continue; + /* Phi functions are scheduled immediately, since they only transfer * data flow from the predecessors to this block. */ if(is_Phi(irn)) { @@ -308,7 +338,7 @@ static void list_sched_block(ir_node *block, void *env_ptr) /* Make the node ready, if all operands live in a foreign block */ if(ready) { - ir_debugf("\timmediately ready: %n\n", irn); + DBG((be.dbg, LEVEL_2, "\timmediately ready: %n\n", irn)); make_ready(&be, irn); } } @@ -318,14 +348,12 @@ static void list_sched_block(ir_node *block, void *env_ptr) be.curr_time += phi_seen; while(pset_count(be.ready_set) > 0) { - ir_debugf("\tready set: %*n\n", pset_iterator, be.ready_set); - // pset_print(stdout, be.ready_set, irn_printer); + DBG((be.dbg, LEVEL_2, "\tready set: %*n\n", pset_iterator, be.ready_set)); /* select a node to be scheduled and check if it was ready */ - irn = env->select(env->select_env, block, be.curr_time, - be.already_scheduled, be.ready_set); + irn = selector->select(env->selector_env, block_env, &info->list, be.curr_time, be.ready_set); - ir_debugf("\tpicked node %n\n", irn); + DBG((be.dbg, LEVEL_3, "\tpicked node %n\n", irn)); /* Add the node to the schedule. */ add_to_sched(&be, irn); @@ -343,14 +371,9 @@ static void list_sched_block(ir_node *block, void *env_ptr) pset_remove_ptr(be.ready_set, irn); } + if(selector->finish_block) + selector->finish_block(env->selector_env, block_env, block); + del_pset(be.ready_set); del_pset(be.already_scheduled); - - { - sched_info_t *inf; - list_for_each_entry(sched_info_t, inf, &info->list, list) { - ir_node *irn = get_sched_info_irn(inf); - ir_debugf("node: %n, pos: %d\n", irn, inf->time_step); - } - } }