X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fbe%2Fbeschedtrace.c;h=8c84bfb9bbe28a7cd65c229b687c1478887a7466;hb=2cb67d89aafac7737bece78b5837d3d48fb528bc;hp=96d534f27c6b32657fcd14c002f958bbcc2b4a63;hpb=0860cafaff791b93c568c77739bd7d9c7240ee2f;p=libfirm diff --git a/ir/be/beschedtrace.c b/ir/be/beschedtrace.c index 96d534f27..8c84bfb9b 100644 --- a/ir/be/beschedtrace.c +++ b/ir/be/beschedtrace.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1995-2008 University of Karlsruhe. All right reserved. + * Copyright (C) 1995-2011 University of Karlsruhe. All right reserved. * * This file is part of libFirm. * @@ -22,24 +22,24 @@ * @brief Implements a trace scheduler as presented in Muchnik[TM]. * @author Michael Beck * @date 28.08.2006 - * @version $Id$ */ #include "config.h" #include #include "iredges_t.h" - +#include "beirg.h" #include "besched.h" #include "belistsched.h" -#include "benode_t.h" +#include "benode.h" #include "belive.h" +#include "bemodule.h" /* we need a special mark */ static char _mark; #define MARK &_mark -typedef struct _trace_irn { +typedef struct trace_irn { sched_timestep_t delay; /**< The delay for this node if already calculated, else 0. */ sched_timestep_t etime; /**< The earliest time of this node. */ unsigned num_user; /**< The number real users (mode datab) of this node */ @@ -49,11 +49,9 @@ typedef struct _trace_irn { unsigned is_root : 1; /**< is a root node of a block */ } trace_irn_t; -typedef struct _trace_env { +typedef struct trace_env { trace_irn_t *sched_info; /**< trace scheduling information about the nodes */ sched_timestep_t curr_time; /**< current time of the scheduler */ - void *selector_env; /**< the backend selector environment */ - const list_sched_selector_t *selector; /**< the actual backend selector */ be_lv_t *liveness; /**< The liveness for the irg */ DEBUG_ONLY(firm_dbg_module_t *dbg;) } trace_env_t; @@ -63,10 +61,7 @@ typedef struct _trace_env { */ static ir_node *get_nodeset_node(const ir_nodeset_t *nodeset) { - ir_nodeset_iterator_t iter; - - ir_nodeset_iterator_init(&iter, nodeset); - return ir_nodeset_iterator_next(&iter); + return ir_nodeset_first(nodeset); } /** @@ -74,7 +69,7 @@ static ir_node *get_nodeset_node(const ir_nodeset_t *nodeset) */ static inline unsigned is_root_node(trace_env_t *env, ir_node *n) { - int idx = get_irn_idx(n); + unsigned const idx = get_irn_idx(n); assert(idx < ARR_LEN(env->sched_info)); return env->sched_info[idx].is_root; @@ -85,7 +80,7 @@ static inline unsigned is_root_node(trace_env_t *env, ir_node *n) */ static inline void mark_root_node(trace_env_t *env, ir_node *n) { - int idx = get_irn_idx(n); + unsigned const idx = get_irn_idx(n); assert(idx < ARR_LEN(env->sched_info)); env->sched_info[idx].is_root = 1; @@ -94,8 +89,9 @@ static inline void mark_root_node(trace_env_t *env, ir_node *n) /** * Get the current delay. */ -static inline sched_timestep_t get_irn_delay(trace_env_t *env, ir_node *n) { - int idx = get_irn_idx(n); +static inline sched_timestep_t get_irn_delay(trace_env_t *env, ir_node *n) +{ + unsigned const idx = get_irn_idx(n); assert(idx < ARR_LEN(env->sched_info)); return env->sched_info[idx].delay; @@ -104,8 +100,9 @@ static inline sched_timestep_t get_irn_delay(trace_env_t *env, ir_node *n) { /** * Set the current delay. */ -static inline void set_irn_delay(trace_env_t *env, ir_node *n, sched_timestep_t delay) { - int idx = get_irn_idx(n); +static inline void set_irn_delay(trace_env_t *env, ir_node *n, sched_timestep_t delay) +{ + unsigned const idx = get_irn_idx(n); assert(idx < ARR_LEN(env->sched_info)); env->sched_info[idx].delay = delay; @@ -114,8 +111,9 @@ static inline void set_irn_delay(trace_env_t *env, ir_node *n, sched_timestep_t /** * Get the current etime. */ -static inline sched_timestep_t get_irn_etime(trace_env_t *env, ir_node *n) { - int idx = get_irn_idx(n); +static inline sched_timestep_t get_irn_etime(trace_env_t *env, ir_node *n) +{ + unsigned const idx = get_irn_idx(n); assert(idx < ARR_LEN(env->sched_info)); return env->sched_info[idx].etime; @@ -124,8 +122,9 @@ static inline sched_timestep_t get_irn_etime(trace_env_t *env, ir_node *n) { /** * Set the current etime. */ -static inline void set_irn_etime(trace_env_t *env, ir_node *n, sched_timestep_t etime) { - int idx = get_irn_idx(n); +static inline void set_irn_etime(trace_env_t *env, ir_node *n, sched_timestep_t etime) +{ + unsigned const idx = get_irn_idx(n); assert(idx < ARR_LEN(env->sched_info)); env->sched_info[idx].etime = etime; @@ -134,8 +133,9 @@ static inline void set_irn_etime(trace_env_t *env, ir_node *n, sched_timestep_t /** * Get the number of users. */ -static inline unsigned get_irn_num_user(trace_env_t *env, ir_node *n) { - int idx = get_irn_idx(n); +static inline unsigned get_irn_num_user(trace_env_t *env, ir_node *n) +{ + unsigned const idx = get_irn_idx(n); assert(idx < ARR_LEN(env->sched_info)); return env->sched_info[idx].num_user; @@ -144,8 +144,9 @@ static inline unsigned get_irn_num_user(trace_env_t *env, ir_node *n) { /** * Set the number of users. */ -static inline void set_irn_num_user(trace_env_t *env, ir_node *n, unsigned num_user) { - int idx = get_irn_idx(n); +static inline void set_irn_num_user(trace_env_t *env, ir_node *n, unsigned num_user) +{ + unsigned const idx = get_irn_idx(n); assert(idx < ARR_LEN(env->sched_info)); env->sched_info[idx].num_user = num_user; @@ -154,8 +155,9 @@ static inline void set_irn_num_user(trace_env_t *env, ir_node *n, unsigned num_u /** * Get the register difference. */ -static inline int get_irn_reg_diff(trace_env_t *env, ir_node *n) { - int idx = get_irn_idx(n); +static inline int get_irn_reg_diff(trace_env_t *env, ir_node *n) +{ + unsigned const idx = get_irn_idx(n); assert(idx < ARR_LEN(env->sched_info)); return env->sched_info[idx].reg_diff; @@ -164,8 +166,9 @@ static inline int get_irn_reg_diff(trace_env_t *env, ir_node *n) { /** * Set the register difference. */ -static inline void set_irn_reg_diff(trace_env_t *env, ir_node *n, int reg_diff) { - int idx = get_irn_idx(n); +static inline void set_irn_reg_diff(trace_env_t *env, ir_node *n, int reg_diff) +{ + unsigned const idx = get_irn_idx(n); assert(idx < ARR_LEN(env->sched_info)); env->sched_info[idx].reg_diff = reg_diff; @@ -174,8 +177,9 @@ static inline void set_irn_reg_diff(trace_env_t *env, ir_node *n, int reg_diff) /** * Get the pre-order position. */ -static inline int get_irn_preorder(trace_env_t *env, ir_node *n) { - int idx = get_irn_idx(n); +static inline int get_irn_preorder(trace_env_t *env, ir_node *n) +{ + unsigned const idx = get_irn_idx(n); assert(idx < ARR_LEN(env->sched_info)); return env->sched_info[idx].preorder; @@ -184,8 +188,9 @@ static inline int get_irn_preorder(trace_env_t *env, ir_node *n) { /** * Set the pre-order position. */ -static inline void set_irn_preorder(trace_env_t *env, ir_node *n, int pos) { - int idx = get_irn_idx(n); +static inline void set_irn_preorder(trace_env_t *env, ir_node *n, int pos) +{ + unsigned const idx = get_irn_idx(n); assert(idx < ARR_LEN(env->sched_info)); env->sched_info[idx].preorder = pos; @@ -194,8 +199,9 @@ static inline void set_irn_preorder(trace_env_t *env, ir_node *n, int pos) { /** * Get the pre-order position. */ -static inline unsigned get_irn_critical_path_len(trace_env_t *env, ir_node *n) { - int idx = get_irn_idx(n); +static inline unsigned get_irn_critical_path_len(trace_env_t *env, ir_node *n) +{ + unsigned const idx = get_irn_idx(n); assert(idx < ARR_LEN(env->sched_info)); return env->sched_info[idx].critical_path_len; @@ -204,8 +210,9 @@ static inline unsigned get_irn_critical_path_len(trace_env_t *env, ir_node *n) { /** * Set the pre-order position. */ -static inline void set_irn_critical_path_len(trace_env_t *env, ir_node *n, unsigned len) { - int idx = get_irn_idx(n); +static inline void set_irn_critical_path_len(trace_env_t *env, ir_node *n, unsigned len) +{ + unsigned const idx = get_irn_idx(n); assert(idx < ARR_LEN(env->sched_info)); env->sched_info[idx].critical_path_len = len; @@ -214,18 +221,25 @@ static inline void set_irn_critical_path_len(trace_env_t *env, ir_node *n, unsig /** * returns the exec-time for node n. */ -static sched_timestep_t exectime(trace_env_t *env, ir_node *n) { +static sched_timestep_t exectime(trace_env_t *env, ir_node *n) +{ + (void) env; if (be_is_Keep(n) || is_Proj(n)) return 0; +#if 0 if (env->selector->exectime) return env->selector->exectime(env->selector_env, n); +#endif return 1; } /** * Calculates the latency for between two ops */ -static sched_timestep_t latency(trace_env_t *env, ir_node *pred, int pred_cycle, ir_node *curr, int curr_cycle) { +static sched_timestep_t latency(trace_env_t *env, ir_node *pred, int pred_cycle, ir_node *curr, int curr_cycle) +{ + (void) pred_cycle; + (void) curr_cycle; /* a Keep hides a root */ if (be_is_Keep(curr)) return exectime(env, pred); @@ -234,21 +248,24 @@ static sched_timestep_t latency(trace_env_t *env, ir_node *pred, int pred_cycle, if (is_Proj(curr)) return 0; +#if 0 /* predecessors Proj's must be skipped */ if (is_Proj(pred)) pred = get_Proj_pred(pred); if (env->selector->latency) return env->selector->latency(env->selector_env, pred, pred_cycle, curr, curr_cycle); +#endif + return 1; } /** * Returns the number of users of a node having mode datab. */ -static int get_num_successors(ir_node *irn) { +static int get_num_successors(ir_node *irn) +{ int sum = 0; - const ir_edge_t *edge; if (get_irn_mode(irn) == mode_T) { /* for mode_T nodes: count the users of all Projs */ @@ -276,7 +293,8 @@ static int get_num_successors(ir_node *irn) { /** * Returns the difference of regs_output - regs_input; */ -static int get_reg_difference(trace_env_t *env, ir_node *irn) { +static int get_reg_difference(trace_env_t *env, ir_node *irn) +{ int num_out = 0; int num_in = 0; int i; @@ -289,7 +307,6 @@ static int get_reg_difference(trace_env_t *env, ir_node *irn) { if (get_irn_mode(irn) == mode_T) { /* mode_T nodes: num out regs == num Projs with mode datab */ - const ir_edge_t *edge; foreach_out_edge(irn, edge) { ir_node *proj = get_edge_src_irn(edge); if (mode_is_datab(get_irn_mode(proj))) @@ -321,7 +338,8 @@ static int get_reg_difference(trace_env_t *env, ir_node *irn) { /** * descent into a dag and create a pre-order list. */ -static void descent(ir_node *root, ir_node *block, ir_node **list, trace_env_t *env, unsigned path_len) { +static void descent(ir_node *root, ir_node *block, ir_node **list, trace_env_t *env, unsigned path_len) +{ int i; if (! is_Phi(root)) { @@ -365,9 +383,8 @@ static void descent(ir_node *root, ir_node *block, ir_node **list, trace_env_t * /** * Returns non-zero if root is a root in the block block. */ -static int is_root(ir_node *root, ir_node *block) { - const ir_edge_t *edge; - +static int is_root(ir_node *root, ir_node *block) +{ foreach_out_edge(root, edge) { ir_node *succ = get_edge_src_irn(edge); @@ -385,22 +402,16 @@ static int is_root(ir_node *root, ir_node *block) { /** * Performs initial block calculations for trace scheduling. */ -static void trace_preprocess_block(trace_env_t *env, ir_node *block) { +static void trace_preprocess_block(trace_env_t *env, ir_node *block) +{ ir_node *root = NULL, *preord = NULL; ir_node *curr, *irn; int cur_pos; - const ir_edge_t *edge; /* First step: Find the root set. */ foreach_out_edge(block, edge) { ir_node *succ = get_edge_src_irn(edge); - if (is_Block(succ)) { - /* A Block-Block edge. This should be the MacroBlock - * edge, ignore it. */ - assert(get_Block_MacroBlock(succ) == block && "Block-Block edge found"); - continue; - } if (is_Anchor(succ)) { /* ignore a keep alive edge */ continue; @@ -417,7 +428,7 @@ static void trace_preprocess_block(trace_env_t *env, ir_node *block) { /* Second step: calculate the pre-order list. */ preord = NULL; for (curr = root; curr; curr = irn) { - irn = get_irn_link(curr); + irn = (ir_node*)get_irn_link(curr); DBG((env->dbg, LEVEL_2, " DAG root %+F\n", curr)); descent(curr, block, &preord, env, 0); } @@ -426,7 +437,7 @@ static void trace_preprocess_block(trace_env_t *env, ir_node *block) { /* Third step: calculate the Delay. Note that our * list is now in pre-order, starting at root */ - for (cur_pos = 0, curr = root; curr; curr = get_irn_link(curr), cur_pos++) { + for (cur_pos = 0, curr = root; curr; curr = (ir_node*)get_irn_link(curr), cur_pos++) { sched_timestep_t d; if (is_cfop(curr)) { @@ -463,8 +474,9 @@ static void trace_preprocess_block(trace_env_t *env, ir_node *block) { /** * This functions gets called after a node finally has been made ready. */ -static void trace_node_ready(void *data, ir_node *irn, ir_node *pred) { - trace_env_t *env = data; +static void trace_node_ready(void *data, ir_node *irn, ir_node *pred) +{ + trace_env_t *env = (trace_env_t*)data; sched_timestep_t etime_p, etime; etime = env->curr_time; @@ -481,9 +493,10 @@ static void trace_node_ready(void *data, ir_node *irn, ir_node *pred) { /** * Update the current time after irn has been selected. */ -static void trace_update_time(void *data, ir_node *irn) { - trace_env_t *env = data; - if (is_Phi(irn) || get_irn_opcode(irn) == iro_Start) { +static void trace_update_time(void *data, ir_node *irn) +{ + trace_env_t *env = (trace_env_t*)data; + if (is_Phi(irn) || get_irn_opcode(irn) == beo_Start) { env->curr_time += get_irn_etime(env, irn); } else { @@ -493,21 +506,20 @@ static void trace_update_time(void *data, ir_node *irn) { /** * Allocates memory and initializes trace scheduling environment. - * @param birg The backend irg object + * @param irg The backend irg object * @return The environment */ -static trace_env_t *trace_init(const be_irg_t *birg) { +static trace_env_t *trace_init(ir_graph *irg) +{ trace_env_t *env = XMALLOCZ(trace_env_t); - ir_graph *irg = be_get_birg_irg(birg); int nn = get_irg_last_idx(irg); env->curr_time = 0; - env->sched_info = NEW_ARR_F(trace_irn_t, nn); - env->liveness = be_liveness(irg); + env->sched_info = NEW_ARR_FZ(trace_irn_t, nn); + env->liveness = be_get_irg_liveness(irg); FIRM_DBG_REGISTER(env->dbg, "firm.be.sched.trace"); - be_liveness_assure_chk(env->liveness); - memset(env->sched_info, 0, nn * sizeof(*(env->sched_info))); + be_assure_live_chk(irg); return env; } @@ -516,9 +528,9 @@ static trace_env_t *trace_init(const be_irg_t *birg) { * Frees all memory allocated for trace scheduling environment. * @param env The environment */ -static void trace_free(void *data) { - trace_env_t *env = data; - be_liveness_free(env->liveness); +static void trace_free(void *data) +{ + trace_env_t *env = (trace_env_t*)data; DEL_ARR_F(env->sched_info); free(env); } @@ -528,9 +540,6 @@ static void trace_free(void *data) { */ static ir_node *basic_selection(ir_nodeset_t *ready_set) { - ir_node *irn = NULL; - ir_nodeset_iterator_t iter; - /* assure that branches and constants are executed last */ foreach_ir_nodeset(ready_set, irn, iter) { if (!is_cfop(irn)) { @@ -539,22 +548,17 @@ static ir_node *basic_selection(ir_nodeset_t *ready_set) } /* at last: schedule branches */ - irn = get_nodeset_node(ready_set); - - return irn; + return get_nodeset_node(ready_set); } /** * The muchnik selector. */ -static ir_node *muchnik_select(void *block_env, ir_nodeset_t *ready_set, ir_nodeset_t *live_set) +static ir_node *muchnik_select(void *block_env, ir_nodeset_t *ready_set) { - trace_env_t *env = block_env; + trace_env_t *env = (trace_env_t*)block_env; ir_nodeset_t mcands, ecands; - ir_nodeset_iterator_t iter; sched_timestep_t max_delay = 0; - ir_node *irn; - (void) live_set; /* calculate the max delay of all candidates */ foreach_ir_nodeset(ready_set, irn, iter) { @@ -576,12 +580,13 @@ static ir_node *muchnik_select(void *block_env, ir_nodeset_t *ready_set, ir_node } /* select a node */ + ir_node *irn; if (ir_nodeset_size(&mcands) == 1) { irn = get_nodeset_node(&mcands); DB((env->dbg, LEVEL_3, "\tirn = %+F, mcand = 1, max_delay = %u\n", irn, max_delay)); } else { - int cnt = ir_nodeset_size(&ecands); + size_t cnt = ir_nodeset_size(&ecands); if (cnt == 1) { irn = get_nodeset_node(&ecands); @@ -592,12 +597,12 @@ static ir_node *muchnik_select(void *block_env, ir_nodeset_t *ready_set, ir_node DB((env->dbg, LEVEL_3, "\tirn = %+F, ecand = 1, max_delay = %u\n", irn, max_delay)); } else if (cnt > 1) { - DB((env->dbg, LEVEL_3, "\tecand = %d, max_delay = %u\n", cnt, max_delay)); + DB((env->dbg, LEVEL_3, "\tecand = %zu, max_delay = %u\n", cnt, max_delay)); irn = basic_selection(&ecands); } else { force_mcands: - DB((env->dbg, LEVEL_3, "\tmcand = %d\n", ir_nodeset_size(&mcands))); + DB((env->dbg, LEVEL_3, "\tmcand = %zu\n", ir_nodeset_size(&mcands))); irn = basic_selection(&mcands); } } @@ -605,45 +610,47 @@ force_mcands: return irn; } -static void *muchnik_init_graph(const list_sched_selector_t *vtab, const be_irg_t *birg) +static void *muchnik_init_graph(ir_graph *irg) { - trace_env_t *env = trace_init(birg); - env->selector = vtab; - env->selector_env = (void*) be_get_birg_arch_env(birg); + trace_env_t *env = trace_init(irg); return (void *)env; } static void *muchnik_init_block(void *graph_env, ir_node *bl) { - trace_preprocess_block(graph_env, bl); + trace_env_t *env = (trace_env_t*) graph_env; + trace_preprocess_block(env, bl); return graph_env; } -const list_sched_selector_t muchnik_selector = { - muchnik_init_graph, - muchnik_init_block, - muchnik_select, - NULL, /* to_appear_in_schedule */ - trace_node_ready, /* node_ready */ - trace_update_time, /* node_selected */ - NULL, /* exectime */ - NULL, /* latency */ - NULL, /* finish_block */ - trace_free /* finish_graph */ -}; +static void sched_muchnik(ir_graph *irg) +{ + static const list_sched_selector_t muchnik_selector = { + muchnik_init_graph, + muchnik_init_block, + muchnik_select, + trace_node_ready, /* node_ready */ + trace_update_time, /* node_selected */ + NULL, /* finish_block */ + trace_free /* finish_graph */ + }; + be_list_sched_graph(irg, &muchnik_selector); +} /** * Execute the heuristic function. */ -static ir_node *heuristic_select(void *block_env, ir_nodeset_t *ns, ir_nodeset_t *lv) +static ir_node *heuristic_select(void *block_env, ir_nodeset_t *ns) { - trace_env_t *trace_env = block_env; - ir_node *irn, *cand = NULL; + trace_env_t *trace_env = (trace_env_t*)block_env; + ir_node *cand = NULL; int max_prio = INT_MIN; int cur_prio = INT_MIN; - int cur_pressure = ir_nodeset_size(lv); - int reg_fact, cand_reg_fact; - ir_nodeset_iterator_t iter; + int reg_fact; + /* Note: register pressure calculation needs an overhaul, you need correct + * tracking for each register class indidually and weight by each class + int cur_pressure = ir_nodeset_size(lv); */ + int cur_pressure = 1; /* prefer instructions which can be scheduled early */ #define PRIO_TIME 3 @@ -666,7 +673,6 @@ static ir_node *heuristic_select(void *block_env, ir_nodeset_t *ns, ir_nodeset_t int sign = rdiff < 0; int chg = (rdiff < 0 ? -rdiff : rdiff) << PRIO_CHG_PRESS; - /* reg_fact = chg << cur_pressure; */ reg_fact = chg * cur_pressure; if (reg_fact < chg) reg_fact = INT_MAX - 2; @@ -682,7 +688,6 @@ static ir_node *heuristic_select(void *block_env, ir_nodeset_t *ns, ir_nodeset_t if (cur_prio > max_prio) { cand = irn; max_prio = cur_prio; - cand_reg_fact = reg_fact; } DBG((trace_env->dbg, LEVEL_4, "checked NODE %+F\n", irn)); @@ -707,15 +712,23 @@ static ir_node *heuristic_select(void *block_env, ir_nodeset_t *ns, ir_nodeset_t return cand; } -const list_sched_selector_t heuristic_selector = { - muchnik_init_graph, - muchnik_init_block, - heuristic_select, - NULL, /* to_appear_in_schedule */ - trace_node_ready, /* node_ready */ - trace_update_time, /* node_selected */ - NULL, /* exectime */ - NULL, /* latency */ - NULL, /* finish_block */ - trace_free /* finish_graph */ -}; +static void sched_heuristic(ir_graph *irg) +{ + static const list_sched_selector_t heuristic_selector = { + muchnik_init_graph, + muchnik_init_block, + heuristic_select, + trace_node_ready, /* node_ready */ + trace_update_time, /* node_selected */ + NULL, /* finish_block */ + trace_free /* finish_graph */ + }; + be_list_sched_graph(irg, &heuristic_selector); +} + +BE_REGISTER_MODULE_CONSTRUCTOR(be_init_sched_trace) +void be_init_sched_trace(void) +{ + be_register_scheduler("heur", sched_heuristic); + be_register_scheduler("muchnik", sched_muchnik); +}