X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fbe%2Fbeschedtrace.c;h=58e7604dc64c37f9a1d8e9863efc66d380285f0f;hb=1aae36757782e8c1d016d6bff9e5cdbaac1bc17d;hp=55a47ad5910d1366a9a9c5c9bf42fa6962ef53d4;hpb=ef6316dc389a9ecef0d5db9f3f3b3f52b85940aa;p=libfirm diff --git a/ir/be/beschedtrace.c b/ir/be/beschedtrace.c index 55a47ad59..58e7604dc 100644 --- a/ir/be/beschedtrace.c +++ b/ir/be/beschedtrace.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1995-2007 University of Karlsruhe. All right reserved. + * Copyright (C) 1995-2011 University of Karlsruhe. All right reserved. * * This file is part of libFirm. * @@ -24,23 +24,23 @@ * @date 28.08.2006 * @version $Id$ */ -#ifdef HAVE_CONFIG_H #include "config.h" -#endif #include #include "iredges_t.h" -#include "besched_t.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 */ @@ -50,12 +50,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 */ - const arch_env_t *arch_env; /**< the arch environment */ 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; @@ -74,9 +71,9 @@ static ir_node *get_nodeset_node(const ir_nodeset_t *nodeset) /** * Returns non-zero if the node is a root node */ -static INLINE unsigned is_root_node(trace_env_t *env, ir_node *n) +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,9 +82,9 @@ static INLINE unsigned is_root_node(trace_env_t *env, ir_node *n) /** * Mark a node as root node */ -static INLINE void mark_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; @@ -96,8 +93,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; @@ -106,8 +104,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; @@ -116,8 +115,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; @@ -126,8 +126,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; @@ -136,8 +137,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; @@ -146,8 +148,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; @@ -156,8 +159,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; @@ -166,8 +170,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; @@ -176,8 +181,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; @@ -186,8 +192,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; @@ -196,8 +203,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; @@ -206,8 +214,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; @@ -216,18 +225,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); @@ -240,15 +256,19 @@ static sched_timestep_t latency(trace_env_t *env, ir_node *pred, int pred_cycle, if (is_Proj(pred)) pred = get_Proj_pred(pred); +#if 0 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; @@ -278,14 +298,15 @@ 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; ir_node *block = get_nodes_block(irn); if (be_is_Call(irn)) { - /* we want calls prefered */ + /* we want calls preferred */ return -5; } @@ -305,13 +326,16 @@ static int get_reg_difference(trace_env_t *env, ir_node *irn) { for (i = get_irn_arity(irn) - 1; i >= 0; i--) { ir_node *in = get_irn_n(irn, i); - if (mode_is_datab(get_irn_mode(in)) && /* must be data node */ - ! arch_irn_is(env->arch_env, in, ignore) && /* ignore "ignore" nodes :) */ - ! be_is_live_end(env->liveness, block, in) /* if the value lives outside of block: do not count */ + if (!mode_is_datab(get_irn_mode(in))) + continue; + + if (arch_irn_is_ignore(in)) + continue; - ) { - num_in++; - } + if (be_is_live_end(env->liveness, block, in)) + continue; + + num_in++; } return num_out - num_in; @@ -320,7 +344,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)) { @@ -364,7 +389,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) { +static int is_root(ir_node *root, ir_node *block) +{ const ir_edge_t *edge; foreach_out_edge(root, edge) { @@ -384,7 +410,8 @@ 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; @@ -394,8 +421,10 @@ static void trace_preprocess_block(trace_env_t *env, ir_node *block) { foreach_out_edge(block, edge) { ir_node *succ = get_edge_src_irn(edge); - if (is_Anchor(succ)) + if (is_Anchor(succ)) { + /* ignore a keep alive edge */ continue; + } if (is_root(succ, block)) { mark_root_node(env, succ); set_irn_link(succ, root); @@ -408,7 +437,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); } @@ -417,10 +446,10 @@ 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 (arch_irn_class_is(env->arch_env, curr, branch)) { + if (is_cfop(curr)) { /* assure, that branches can be executed last */ d = 0; } @@ -454,8 +483,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; @@ -472,9 +502,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 { @@ -484,18 +515,17 @@ 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) { - trace_env_t *env = xcalloc(1, sizeof(*env)); - ir_graph *irg = be_get_birg_irg(birg); +static trace_env_t *trace_init(ir_graph *irg) +{ + trace_env_t *env = XMALLOCZ(trace_env_t); int nn = get_irg_last_idx(irg); - env->arch_env = be_get_birg_arch_env(birg); env->curr_time = 0; env->sched_info = NEW_ARR_F(trace_irn_t, nn); - env->liveness = be_liveness(birg); + env->liveness = be_liveness(irg); FIRM_DBG_REGISTER(env->dbg, "firm.be.sched.trace"); be_liveness_assure_chk(env->liveness); @@ -508,8 +538,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; +static void trace_free(void *data) +{ + trace_env_t *env = (trace_env_t*)data; be_liveness_free(env->liveness); DEL_ARR_F(env->sched_info); free(env); @@ -518,13 +549,14 @@ static void trace_free(void *data) { /** * Simple selector. Just assure that jumps are scheduled last. */ -static ir_node *basic_selection(const arch_env_t *arch_env, ir_nodeset_t *ready_set) { +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 (! arch_irn_class_is(arch_env, irn, branch)) { + if (!is_cfop(irn)) { return irn; } } @@ -538,14 +570,13 @@ static ir_node *basic_selection(const arch_env_t *arch_env, ir_nodeset_t *ready_ /** * 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) { @@ -572,69 +603,72 @@ static ir_node *muchnik_select(void *block_env, ir_nodeset_t *ready_set, ir_node 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); - if (arch_irn_class_is(env->arch_env, irn, branch)) { + if (is_cfop(irn)) { /* BEWARE: don't select a JUMP if others are still possible */ goto force_mcands; } 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)); - irn = basic_selection(env->arch_env, &ecands); + 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))); - irn = basic_selection(env->arch_env, &mcands); + DB((env->dbg, LEVEL_3, "\tmcand = %zu\n", ir_nodeset_size(&mcands))); + irn = basic_selection(&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; + trace_env_t *trace_env = (trace_env_t*)block_env; ir_node *irn, *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; + /* 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 @@ -652,12 +686,11 @@ static ir_node *heuristic_select(void *block_env, ir_nodeset_t *ns, ir_nodeset_t /* priority based selection, heuristic inspired by mueller diss */ foreach_ir_nodeset(ns, irn, iter) { /* make sure that branches are scheduled last */ - if (! arch_irn_class_is(trace_env->arch_env, irn, branch)) { + if (!is_cfop(irn)) { int rdiff = get_irn_reg_diff(trace_env, irn); 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; @@ -692,21 +725,29 @@ static ir_node *heuristic_select(void *block_env, ir_nodeset_t *ns, ir_nodeset_t DBG((trace_env->dbg, LEVEL_4, "heuristic selected %+F:\n", cand)); } else { - cand = basic_selection(trace_env->arch_env, ns); + cand = basic_selection(ns); } 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); +}