X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fbe%2Fbeschedtrace.c;h=52af5141136b6cf15d17ace68efe106cf6c950b9;hb=7a6efcac0fd46869f31d992d022dd909db4b4c29;hp=c95777e7f75a3bf7508b0b7359f45762e4f866d0;hpb=08bb312485d8a28679504d97402b70fde8073a66;p=libfirm diff --git a/ir/be/beschedtrace.c b/ir/be/beschedtrace.c index c95777e7f..52af51411 100644 --- a/ir/be/beschedtrace.c +++ b/ir/be/beschedtrace.c @@ -1,10 +1,32 @@ +/* + * Copyright (C) 1995-2007 University of Karlsruhe. All right reserved. + * + * This file is part of libFirm. + * + * This file may be distributed and/or modified under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation and appearing in the file LICENSE.GPL included in the + * packaging of this file. + * + * Licensees holding valid libFirm Professional Edition licenses may use + * this file in accordance with the libFirm Commercial License. + * Agreement provided with the Software. + * + * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE + * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE. + */ + /** - * Implements a trace scheduler as presented in Muchnik[TM]. - * Originally implemented by Michael Beck. - * @author Christian Wuerdig - * @date 28.08.2006 - * @cvs-id $Id$ + * @file + * @brief Implements a trace scheduler as presented in Muchnik[TM]. + * @author Michael Beck + * @date 28.08.2006 + * @version $Id$ */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif #include @@ -34,9 +56,21 @@ typedef struct _trace_env { 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; +/** + * Returns a random node from a nodeset + */ +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); +} + /** * Returns non-zero if the node is a root node */ @@ -248,6 +282,12 @@ 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 */ + return -5; + } if (get_irn_mode(irn) == mode_T) { /* mode_T nodes: num out regs == num Projs with mode datab */ @@ -264,7 +304,10 @@ static int get_reg_difference(trace_env_t *env, ir_node *irn) { /* num in regs: number of ins with mode datab and not ignore */ 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)) && ! arch_irn_is(env->arch_env, in, ignore)) + + if (! be_is_live_end(env->liveness, block, in) && /* if the value lives outside of block: do not count */ + mode_is_datab(get_irn_mode(in)) && /* must be data node */ + ! arch_irn_is(env->arch_env, in, ignore)) /* ignore "ignore" nodes :) */ num_in++; } @@ -282,12 +325,18 @@ static void descent(ir_node *root, ir_node *block, ir_node **list, trace_env_t * if (get_irn_critical_path_len(env, root) < path_len) { set_irn_critical_path_len(env, root, path_len); } + /* calculate number of users (needed for heuristic) */ + set_irn_num_user(env, root, get_num_successors(root)); + + /* calculate register difference (needed for heuristic) */ + set_irn_reg_diff(env, root, get_reg_difference(env, root)); /* Phi nodes always leave the block */ for (i = get_irn_arity(root) - 1; i >= 0; --i) { ir_node *pred = get_irn_n(root, i); DBG((env->dbg, LEVEL_3, " node %+F\n", pred)); + /* Blocks may happen as predecessors of End nodes */ if (is_Block(pred)) continue; @@ -300,12 +349,6 @@ static void descent(ir_node *root, ir_node *block, ir_node **list, trace_env_t * if (get_nodes_block(pred) != block) continue; - /* calculate number of users (needed for heuristic) */ - set_irn_num_user(env, root, get_num_successors(root)); - - /* calculate register difference (needed for heuristic) */ - set_irn_reg_diff(env, root, get_reg_difference(env, root)); - set_irn_link(pred, NULL); descent(pred, block, list, env, path_len); @@ -348,6 +391,8 @@ 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)) + continue; if (is_root(succ, block)) { mark_root_node(env, succ); set_irn_link(succ, root); @@ -406,7 +451,8 @@ 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(trace_env_t *env, ir_node *irn, ir_node *pred) { +static void trace_node_ready(void *data, ir_node *irn, ir_node *pred) { + trace_env_t *env = data; sched_timestep_t etime_p, etime; etime = env->curr_time; @@ -423,7 +469,8 @@ static void trace_node_ready(trace_env_t *env, ir_node *irn, ir_node *pred) { /** * Update the current time after irn has been selected. */ -static void trace_update_time(trace_env_t *env, ir_node *irn) { +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) { env->curr_time += get_irn_etime(env, irn); } @@ -437,15 +484,18 @@ static void trace_update_time(trace_env_t *env, ir_node *irn) { * @param birg The backend irg object * @return The environment */ -static trace_env_t *trace_init(const arch_env_t *arch_env, ir_graph *irg) { +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); int nn = get_irg_last_idx(irg); - env->arch_env = arch_env; + 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); 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))); return env; @@ -455,7 +505,9 @@ static trace_env_t *trace_init(const arch_env_t *arch_env, ir_graph *irg) { * Frees all memory allocated for trace scheduling environment. * @param env The environment */ -static void trace_free(trace_env_t *env) { +static void trace_free(void *data) { + trace_env_t *env = data; + be_liveness_free(env->liveness); DEL_ARR_F(env->sched_info); free(env); } @@ -463,20 +515,19 @@ static void trace_free(trace_env_t *env) { /** * Simple selector. Just assure that jumps are scheduled last. */ -static ir_node *basic_selection(const arch_env_t *arch_env, nodeset *ready_set) { +static ir_node *basic_selection(const arch_env_t *arch_env, ir_nodeset_t *ready_set) { ir_node *irn = NULL; + ir_nodeset_iterator_t iter; /* assure that branches and constants are executed last */ - for (irn = nodeset_first(ready_set); irn; irn = nodeset_next(ready_set)) { + foreach_ir_nodeset(ready_set, irn, iter) { if (! arch_irn_class_is(arch_env, irn, branch)) { - nodeset_break(ready_set); return irn; } } /* at last: schedule branches */ - irn = nodeset_first(ready_set); - nodeset_break(ready_set); + irn = get_nodeset_node(ready_set); return irn; } @@ -484,41 +535,43 @@ static ir_node *basic_selection(const arch_env_t *arch_env, nodeset *ready_set) /** * The muchnik selector. */ -static ir_node *muchnik_select(void *block_env, nodeset *ready_set, nodeset *live_set) +static ir_node *muchnik_select(void *block_env, ir_nodeset_t *ready_set, ir_nodeset_t *live_set) { trace_env_t *env = block_env; - nodeset *mcands, *ecands; + 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_nodeset(ready_set, irn) { + foreach_ir_nodeset(ready_set, irn, iter) { sched_timestep_t d = get_irn_delay(env, irn); max_delay = d > max_delay ? d : max_delay; } - mcands = new_nodeset(8); - ecands = new_nodeset(8); + ir_nodeset_init_size(&mcands, 8); + ir_nodeset_init_size(&ecands, 8); /* build mcands and ecands */ - foreach_nodeset(ready_set, irn) { + foreach_ir_nodeset(ready_set, irn, iter) { if (get_irn_delay(env, irn) == max_delay) { - nodeset_insert(mcands, irn); + ir_nodeset_insert(&mcands, irn); if (get_irn_etime(env, irn) <= env->curr_time) - nodeset_insert(ecands, irn); + ir_nodeset_insert(&ecands, irn); } } /* select a node */ - if (nodeset_count(mcands) == 1) { - irn = nodeset_first(mcands); + 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 = nodeset_count(ecands); + int cnt = ir_nodeset_size(&ecands); if (cnt == 1) { - irn = nodeset_first(ecands); + irn = get_nodeset_node(&ecands); if (arch_irn_class_is(env->arch_env, irn, branch)) { /* BEWARE: don't select a JUMP if others are still possible */ @@ -528,23 +581,23 @@ static ir_node *muchnik_select(void *block_env, nodeset *ready_set, nodeset *liv } 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); + irn = basic_selection(env->arch_env, &ecands); } else { force_mcands: - DB((env->dbg, LEVEL_3, "\tmcand = %d\n", nodeset_count(mcands))); - irn = basic_selection(env->arch_env, mcands); + DB((env->dbg, LEVEL_3, "\tmcand = %d\n", ir_nodeset_size(&mcands))); + irn = basic_selection(env->arch_env, &mcands); } } return irn; } -static void *muchnik_init_graph(const list_sched_selector_t *vtab, const arch_env_t *arch_env, ir_graph *irg) +static void *muchnik_init_graph(const list_sched_selector_t *vtab, const be_irg_t *birg) { - trace_env_t *env = trace_init(arch_env, irg); + trace_env_t *env = trace_init(birg); env->selector = vtab; - env->selector_env = env; + env->selector_env = (void*) be_get_birg_arch_env(birg); return (void *)env; } @@ -554,7 +607,7 @@ static void *muchnik_init_block(void *graph_env, ir_node *bl) return graph_env; } -static const list_sched_selector_t muchnik_selector_struct = { +const list_sched_selector_t muchnik_selector = { muchnik_init_graph, muchnik_init_block, muchnik_select, @@ -567,22 +620,21 @@ static const list_sched_selector_t muchnik_selector_struct = { trace_free /* finish_graph */ }; -const list_sched_selector_t *muchnik_selector = &muchnik_selector_struct; - /** * Execute the heuristic function. */ -static ir_node *heuristic_select(void *block_env, nodeset *ns, nodeset *lv) +static ir_node *heuristic_select(void *block_env, ir_nodeset_t *ns, ir_nodeset_t *lv) { trace_env_t *trace_env = block_env; ir_node *irn, *cand = NULL; int max_prio = INT_MIN; int cur_prio = INT_MIN; - int cur_pressure = nodeset_count(lv); + int cur_pressure = ir_nodeset_size(lv); int reg_fact, cand_reg_fact; + ir_nodeset_iterator_t iter; /* prefer instructions which can be scheduled early */ -#define PRIO_TIME 16 +#define PRIO_TIME 3 /* prefer instructions with lots of successors */ #define PRIO_NUMSUCCS 8 /* prefer instructions with long critical path */ @@ -595,14 +647,15 @@ static ir_node *heuristic_select(void *block_env, nodeset *ns, nodeset *lv) #define PRIO_CHG_PRESS 8 /* priority based selection, heuristic inspired by mueller diss */ - foreach_nodeset(ns, irn) { + foreach_ir_nodeset(ns, irn, iter) { /* make sure that branches are scheduled last */ if (! arch_irn_class_is(trace_env->arch_env, irn, branch)) { 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; */ + reg_fact = chg * cur_pressure; if (reg_fact < chg) reg_fact = INT_MAX - 2; reg_fact = sign ? -reg_fact : reg_fact; @@ -627,7 +680,7 @@ static ir_node *heuristic_select(void *block_env, nodeset *ns, nodeset *lv) DBG((trace_env->dbg, LEVEL_4, "\t#user: %d (%d)\n", get_irn_num_user(trace_env, irn), get_irn_num_user(trace_env, irn) << PRIO_NUMSUCCS)); DBG((trace_env->dbg, LEVEL_4, "\tetime: %d (%d)\n", get_irn_etime(trace_env, irn), 0 - (get_irn_etime(trace_env, irn) << PRIO_TIME))); DBG((trace_env->dbg, LEVEL_4, "\tpreorder: %d (%d)\n", get_irn_preorder(trace_env, irn), get_irn_preorder(trace_env, irn) << PRIO_PREORD)); - DBG((trace_env->dbg, LEVEL_4, "\treg diff: %d (%d)\n", get_irn_reg_diff(trace_env, irn), 0 - cand_reg_fact)); + DBG((trace_env->dbg, LEVEL_4, "\treg diff: %d (%d)\n", get_irn_reg_diff(trace_env, irn), 0 - reg_fact)); DBG((trace_env->dbg, LEVEL_4, "\tpressure: %d\n", cur_pressure)); } } @@ -642,7 +695,7 @@ static ir_node *heuristic_select(void *block_env, nodeset *ns, nodeset *lv) return cand; } -static const list_sched_selector_t heuristic_selector_struct = { +const list_sched_selector_t heuristic_selector = { muchnik_init_graph, muchnik_init_block, heuristic_select, @@ -654,5 +707,3 @@ static const list_sched_selector_t heuristic_selector_struct = { NULL, /* finish_block */ trace_free /* finish_graph */ }; - -const list_sched_selector_t *heuristic_selector = &heuristic_selector_struct;