X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;ds=sidebyside;f=ir%2Fbe%2Fbeschednormal.c;h=dacc5a6750a40aaabd493df161cfa11e81791659;hb=2669742071b00949c6a5102f39b7df7fd7d3e3fb;hp=c13498782f36f8bc2ae66dc2c9196c14e05d6653;hpb=d0bf4325a38cd93458f136cc39a08fb4ba8e74b8;p=libfirm diff --git a/ir/be/beschednormal.c b/ir/be/beschednormal.c index c13498782..dacc5a675 100644 --- a/ir/be/beschednormal.c +++ b/ir/be/beschednormal.c @@ -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. * @@ -20,7 +20,7 @@ /** * @brief Use the strong normal form theorem (though it does not hold) * @author Christoph Mallon - * @version $Id: beschedrand.c 14604 2007-06-18 14:07:07Z matze $ + * @version $Id$ */ #ifdef HAVE_CONFIG_H #include "config.h" @@ -32,12 +32,21 @@ #include "belistsched.h" #include "belive_t.h" #include "beutil.h" +#include "height.h" #include "irtools.h" #include "irgwalk.h" +#include "benode_t.h" // XXX there is no one time init for schedulers //#define NORMAL_DBG +#include "irprintf.h" + + +static int must_be_scheduled(const ir_node* const irn) +{ + return !is_Proj(irn) && !is_Sync(irn); +} static const arch_env_t *cur_arch_env; @@ -83,9 +92,13 @@ typedef struct irn_cost_pair { static int cost_cmp(const void* a, const void* b) { - const irn_cost_pair* a1 = a; - const irn_cost_pair* b1 = b; - return b1->cost - a1->cost; + const irn_cost_pair* const a1 = a; + const irn_cost_pair* const b1 = b; + int ret = b1->cost - a1->cost; +#if defined NORMAL_DBG + ir_fprintf(stderr, "%+F %s %+F\n", a1->irn, ret < 0 ? "<" : ret > 0 ? ">" : "=", b1->irn); +#endif + return ret; } @@ -105,15 +118,26 @@ static int count_result(const ir_node* irn) } +/* TODO high cost for store trees + */ + + static int normal_tree_cost(ir_node* irn) { flag_and_cost* fc = get_irn_link(irn); ir_node* block = get_nodes_block(irn); int arity = get_irn_arity(irn); - int cost_max = 0; - int count_max = 0; int n_res; int cost; + int n_op_res = 0; + int i; + + if (be_is_Keep(irn)) + return 0; + + if (is_Proj(irn)) { + return normal_tree_cost(get_Proj_pred(irn)); + } if (fc == NULL) { irn_cost_pair* costs; @@ -127,54 +151,43 @@ static int normal_tree_cost(ir_node* irn) ir_node* pred = get_irn_n(irn, i); int cost; - if (is_Phi(irn) || get_irn_mode(pred) == mode_M) { + if (is_Phi(irn) || get_irn_mode(pred) == mode_M || is_Block(pred)) { cost = 0; } else if (get_nodes_block(pred) != block) { cost = 1; } else { flag_and_cost* pred_fc; + ir_node* real_pred; cost = normal_tree_cost(pred); - pred_fc = get_irn_link(pred); - pred_fc->no_root = 1; + 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)) { + real_pred = (is_Proj(pred) ? get_Proj_pred(pred) : pred); + pred_fc = get_irn_link(real_pred); + pred_fc->no_root = 1; #if defined NORMAL_DBG - ir_fprintf(stderr, "%+F says that %+F is no root\n", irn, pred); + ir_fprintf(stderr, "%+F says that %+F is no root\n", irn, real_pred); #endif + } } costs[i].irn = pred; costs[i].cost = cost; - - if (cost > cost_max) { - cost_max = cost; - count_max = 1; - } else if (cost == cost_max) { - ++count_max; - } } qsort(costs, arity, sizeof(*costs), cost_cmp); set_irn_link(irn, fc); - } else { - irn_cost_pair* costs = fc->costs; - int i; - - if (arity > 0) { - cost_max = costs[0].cost; - - for (i = 0; i < arity; ++i) { - if (costs[i].cost < cost_max) break; - ++count_max; - } - } } - n_res = count_result(irn); - if (cost_max == 0) { - cost = n_res; - } else { - cost = MAX(n_res, cost_max + count_max - 1); + cost = 0; + for (i = 0; i < arity; ++i) { + if (get_irn_mode(fc->costs[i].irn) == mode_M) continue; + if (arch_irn_is(cur_arch_env, fc->costs[i].irn, ignore)) continue; + cost = MAX(fc->costs[i].cost + n_op_res, cost); + ++n_op_res; } + n_res = count_result(irn); + cost = MAX(n_res, cost); #if defined NORMAL_DBG ir_fprintf(stderr, "reguse of %+F is %d\n", irn, cost); @@ -184,38 +197,6 @@ static int normal_tree_cost(ir_node* irn) } -static void normal_tree_sched(ir_node* irn) -{ - irn_cost_pair* irns = get_irn_link(irn); - int arity = get_irn_arity(irn); - int i; - - if (irns == NULL) return; - - for (i = 0; i < arity; ++i) { - normal_tree_sched(irns[i].irn); - } - - if (1) { // TODO check if node needs to be scheduled - ir_node* block = get_nodes_block(irn); - ir_node** sched = get_irn_link(block); - -#if defined NORMAL_DBG - ir_fprintf(stderr, "scheduling %+F in array %p\n", irn, sched); -#endif - - if (sched == NULL) { - sched = NEW_ARR_F(ir_node*, 0); - } - ARR_APP1(ir_node*, sched, irn); - set_irn_link(block, sched); - } - - free(irns); - set_irn_link(irn, NULL); -} - - static void normal_cost_walker(ir_node* irn, void* env) { (void)env; @@ -224,25 +205,27 @@ static void normal_cost_walker(ir_node* irn, void* env) 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); } static void collect_roots(ir_node* irn, void* env) { - flag_and_cost* fc; + int is_root; (void)env; if (is_Block(irn)) return; + if (!must_be_scheduled(irn)) return; - fc = get_irn_link(irn); + is_root = be_is_Keep(irn) || !((flag_and_cost*)get_irn_link(irn))->no_root; #if defined NORMAL_DBG - ir_fprintf(stderr, "%+F is %sroot\n", irn, fc->no_root ? "no " : ""); + ir_fprintf(stderr, "%+F is %sroot\n", irn, is_root ? "" : "no "); #endif - if (!fc->no_root) { + if (is_root) { ir_node* block = get_nodes_block(irn); ir_node** roots = get_irn_link(block); if (roots == NULL) { @@ -256,16 +239,21 @@ 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); - int arity = get_irn_arity(irn); - int i; + 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 (!is_Phi(irn)) { + if (!is_Phi(irn) && !be_is_Keep(irn)) { for (i = 0; i < arity; ++i) { - ir_node* pred = get_irn_n(irn, i); + ir_node* pred = irns[i].irn; if (get_nodes_block(pred) != block) continue; + if (get_irn_mode(pred) == mode_M) continue; + if (is_Proj(pred)) pred = get_Proj_pred(pred); sched = sched_node(sched, pred); } } @@ -276,16 +264,38 @@ static ir_node** sched_node(ir_node** sched, ir_node* irn) } +static int root_cmp(const void* a, const void* b) +{ + const irn_cost_pair* const a1 = a; + const irn_cost_pair* const b1 = b; + int ret; + if (is_irn_forking(a1->irn)) { + ret = 1; + } else if (is_irn_forking(b1->irn)) { + ret = -1; + } else { + ret = b1->cost - a1->cost; + if (ret == 0) { + /* place live-out nodes later */ + ret = (count_result(a1->irn) != 0) - (count_result(b1->irn) != 0); + } + } +#if defined NORMAL_DBG + ir_fprintf(stderr, "%+F %s %+F\n", a1->irn, ret < 0 ? "<" : ret > 0 ? ">" : "=", b1->irn); +#endif + return ret; +} + + static void normal_sched_block(ir_node* block, void* env) { - ir_node** roots = get_irn_link(block); + heights_t* heights = env; + ir_node** roots = get_irn_link(block); int root_count; irn_cost_pair* root_costs; int i; ir_node** sched; - (void)env; - #if defined NORMAL_DBG ir_fprintf(stderr, "sched walking block %+F\n", block); #endif @@ -301,13 +311,29 @@ static void normal_sched_block(ir_node* block, void* env) NEW_ARR_A(irn_cost_pair, root_costs, root_count); for (i = 0; i < root_count; ++i) { root_costs[i].irn = roots[i]; - root_costs[i].cost = normal_tree_cost(roots[i]); + root_costs[i].cost = get_irn_height(heights, roots[i]); +#if defined NORMAL_DBG + ir_fprintf(stderr, "height of %+F is %u\n", roots[i], root_costs[i].cost); +#endif + } + qsort(root_costs, root_count, sizeof(*root_costs), root_cmp); +#if defined NORMAL_DBG + { + int n = root_count; + int i; + + ir_fprintf(stderr, "Root Scheduling of %+F:\n", block); + for (i = 0; i < n; ++i) { + ir_fprintf(stderr, " %+F\n", root_costs[i].irn); + } + fprintf(stderr, "\n"); } - qsort(root_costs, root_count, sizeof(*root_costs), cost_cmp); +#endif sched = NEW_ARR_F(ir_node*, 0); for (i = 0; i < root_count; ++i) { ir_node* irn = root_costs[i].irn; + assert(must_be_scheduled(irn)); sched = sched_node(sched, irn); } set_irn_link(block, sched); @@ -320,12 +346,7 @@ static void normal_sched_block(ir_node* block, void* env) ir_fprintf(stderr, "Scheduling of %+F:\n", block); for (i = 0; i < n; ++i) { - int j; - for (j = 0; j < i; ++j) { - if (sched[i] == sched[j]) goto skip; - } ir_fprintf(stderr, " %+F\n", sched[i]); -skip:; } fprintf(stderr, "\n"); } @@ -336,7 +357,8 @@ skip:; static void *normal_init_graph(const list_sched_selector_t *vtab, const be_irg_t *birg) { - ir_graph* irg = be_get_birg_irg(birg); + ir_graph *irg = be_get_birg_irg(birg); + heights_t *heights; (void)vtab; @@ -344,10 +366,14 @@ static void *normal_init_graph(const list_sched_selector_t *vtab, be_clear_links(irg); + heights = heights_new(irg); + irg_walk_graph(irg, normal_cost_walker, NULL, NULL); irg_walk_graph(irg, collect_roots, NULL, NULL); inc_irg_visited(irg); - irg_block_walk_graph(irg, normal_sched_block, NULL, NULL); + irg_block_walk_graph(irg, normal_sched_block, NULL, heights); + + heights_free(heights); return NULL; }