X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fbe%2Fbeschednormal.c;h=e642435cf492e492662af3a9d741fcdd796cdd32;hb=661e8c55444874a4b35d9802b02728576b98fb91;hp=df84887a5c54f2f667c1bba7452718934f186777;hpb=81d4cf5aeab4d0c0bc2a5e7c461d58ee7a7522d6;p=libfirm diff --git a/ir/be/beschednormal.c b/ir/be/beschednormal.c index df84887a5..e642435cf 100644 --- a/ir/be/beschednormal.c +++ b/ir/be/beschednormal.c @@ -22,9 +22,7 @@ * @author Christoph Mallon * @version $Id$ */ -#ifdef HAVE_CONFIG_H #include "config.h" -#endif #include @@ -42,6 +40,11 @@ //#define NORMAL_DBG #include "irprintf.h" +/** An instance of the normal scheduler. */ +typedef struct instance_t { + ir_graph* irg; /**< the IR graph of this instance */ + struct obstack obst; /**< obstack for temporary data */ +} instance_t; static int must_be_scheduled(const ir_node* const irn) { @@ -49,9 +52,6 @@ static int must_be_scheduled(const ir_node* const irn) } -static const arch_env_t *cur_arch_env; - - static ir_node *normal_select(void *block_env, ir_nodeset_t *ready_set, ir_nodeset_t *live_set) { @@ -72,7 +72,7 @@ static ir_node *normal_select(void *block_env, ir_nodeset_t *ready_set, for (; sched_count-- != 0; ++sched) { ir_node* irn = *sched; if (ir_nodeset_contains(ready_set, irn) && - !arch_irn_class_is(cur_arch_env, irn, branch)) { + !arch_irn_class_is(irn, branch)) { #if defined NORMAL_DBG ir_fprintf(stderr, "scheduling %+F\n", irn); #endif @@ -89,7 +89,6 @@ typedef struct irn_cost_pair { int cost; } irn_cost_pair; - static int cost_cmp(const void* a, const void* b) { const irn_cost_pair* const a1 = a; @@ -109,26 +108,31 @@ typedef struct flag_and_cost { irn_cost_pair costs[]; } flag_and_cost; +#define get_irn_fc(irn) ((flag_and_cost*)get_irn_link(irn)) +#define set_irn_fc(irn, fc) set_irn_link(irn, fc) + static int count_result(const ir_node* irn) { const ir_mode* mode = get_irn_mode(irn); - return - mode != mode_M && - mode != mode_X && - !arch_irn_is(cur_arch_env, irn, ignore); + + if (mode == mode_M || mode == mode_X) + return 0; + + if (arch_get_register_req_out(irn)->type & arch_register_req_type_ignore) + return 0; + + return 1; } /* TODO high cost for store trees */ - -static int normal_tree_cost(ir_node* irn) +static int normal_tree_cost(ir_node* irn, instance_t *inst) { - flag_and_cost* fc = get_irn_link(irn); - ir_node* block = get_nodes_block(irn); - int arity = get_irn_arity(irn); + flag_and_cost* fc; + int arity; ir_node* last; int n_res; int cost; @@ -139,14 +143,18 @@ static int normal_tree_cost(ir_node* irn) return 0; if (is_Proj(irn)) { - return normal_tree_cost(get_Proj_pred(irn)); + return normal_tree_cost(get_Proj_pred(irn), inst); } + arity = get_irn_arity(irn); + fc = get_irn_fc(irn); + if (fc == NULL) { irn_cost_pair* costs; int i; + ir_node* block = get_nodes_block(irn); - fc = malloc(sizeof(*fc) + sizeof(*fc->costs) * arity); + fc = obstack_alloc(&inst->obst, sizeof(*fc) + sizeof(*fc->costs) * arity); fc->no_root = 0; costs = fc->costs; @@ -162,11 +170,11 @@ static int normal_tree_cost(ir_node* irn) flag_and_cost* pred_fc; ir_node* real_pred; - cost = normal_tree_cost(pred); + cost = normal_tree_cost(pred, inst); if (be_is_Barrier(pred)) cost = 1; // XXX hack: the barrier causes all users to have a reguse of #regs - if (!arch_irn_is(cur_arch_env, pred, ignore)) { + if (!arch_irn_is_ignore(pred)) { real_pred = (is_Proj(pred) ? get_Proj_pred(pred) : pred); - pred_fc = get_irn_link(real_pred); + pred_fc = get_irn_fc(real_pred); pred_fc->no_root = 1; #if defined NORMAL_DBG ir_fprintf(stderr, "%+F says that %+F is no root\n", irn, real_pred); @@ -186,9 +194,9 @@ static int normal_tree_cost(ir_node* irn) last = 0; for (i = 0; i < arity; ++i) { ir_node* op = fc->costs[i].irn; - if (op == last) continue; - if (get_irn_mode(op) == mode_M) continue; - if (arch_irn_is(cur_arch_env, op, ignore)) continue; + if (op == last) continue; + if (get_irn_mode(op) == mode_M) continue; + if (arch_irn_is_ignore(op)) continue; cost = MAX(fc->costs[i].cost + n_op_res, cost); last = op; ++n_op_res; @@ -206,14 +214,14 @@ static int normal_tree_cost(ir_node* irn) static void normal_cost_walker(ir_node* irn, void* env) { - (void)env; + instance_t *inst = env; #if defined NORMAL_DBG ir_fprintf(stderr, "cost walking node %+F\n", irn); #endif if (is_Block(irn)) return; if (!must_be_scheduled(irn)) return; - normal_tree_cost(irn); + normal_tree_cost(irn, inst); } @@ -226,7 +234,7 @@ static void collect_roots(ir_node* irn, void* env) if (is_Block(irn)) return; if (!must_be_scheduled(irn)) return; - is_root = be_is_Keep(irn) || !((flag_and_cost*)get_irn_link(irn))->no_root; + is_root = be_is_Keep(irn) || !get_irn_fc(irn)->no_root; #if defined NORMAL_DBG ir_fprintf(stderr, "%+F is %sroot\n", irn, is_root ? "" : "no "); @@ -246,16 +254,16 @@ static void collect_roots(ir_node* irn, void* env) static ir_node** sched_node(ir_node** sched, ir_node* irn) { - ir_node* block = get_nodes_block(irn); - flag_and_cost* fc = get_irn_link(irn); - irn_cost_pair* irns = fc->costs; - int arity = get_irn_arity(irn); - int i; - - if (irn_visited(irn)) return sched; - if (is_End(irn)) return sched; + if (irn_visited_else_mark(irn)) return sched; + if (is_End(irn)) return sched; if (!is_Phi(irn) && !be_is_Keep(irn)) { + ir_node* block = get_nodes_block(irn); + int arity = get_irn_arity(irn); + flag_and_cost* fc = get_irn_fc(irn); + irn_cost_pair* irns = fc->costs; + int i; + for (i = 0; i < arity; ++i) { ir_node* pred = irns[i].irn; if (get_nodes_block(pred) != block) continue; @@ -265,7 +273,6 @@ static ir_node** sched_node(ir_node** sched, ir_node* irn) } } - mark_irn_visited(irn); ARR_APP1(ir_node*, sched, irn); return sched; } @@ -364,25 +371,30 @@ static void normal_sched_block(ir_node* block, void* env) static void *normal_init_graph(const list_sched_selector_t *vtab, const be_irg_t *birg) { - ir_graph *irg = be_get_birg_irg(birg); - heights_t *heights; + instance_t *inst = XMALLOC(instance_t); + ir_graph *irg = be_get_birg_irg(birg); + heights_t *heights; (void)vtab; - cur_arch_env = be_get_birg_arch_env(birg); + inst->irg = irg; + obstack_init(&inst->obst); be_clear_links(irg); heights = heights_new(irg); - irg_walk_graph(irg, normal_cost_walker, NULL, NULL); + ir_reserve_resources(irg, IR_RESOURCE_IRN_LINK); + irg_walk_graph(irg, normal_cost_walker, NULL, inst); irg_walk_graph(irg, collect_roots, NULL, NULL); inc_irg_visited(irg); + ir_reserve_resources(irg, IR_RESOURCE_IRN_VISITED); irg_block_walk_graph(irg, normal_sched_block, NULL, heights); + ir_free_resources(irg, IR_RESOURCE_IRN_VISITED); heights_free(heights); - return NULL; + return inst; } @@ -394,6 +406,15 @@ static void *normal_init_block(void *graph_env, ir_node *block) return NULL; } +void normal_finish_graph(void *env) +{ + instance_t *inst = env; + + /* block uses the link field to store the schedule */ + ir_free_resources(inst->irg, IR_RESOURCE_IRN_LINK); + obstack_free(&inst->obst, NULL); + xfree(inst); +} const list_sched_selector_t normal_selector = { normal_init_graph, @@ -405,5 +426,5 @@ const list_sched_selector_t normal_selector = { NULL, /* exectime */ NULL, /* latency */ NULL, /* finish_block */ - NULL /* finish_graph */ + normal_finish_graph };