Commit f712b4e8 authored by Matthias Braun's avatar Matthias Braun
Browse files

* changed verfier to handle delay_slots (theoretically...)

* verify functions don"t assert anymore but return int
parent 7efb6059
......@@ -301,8 +301,8 @@ static void be_ra_chordal_main(const be_irg_t *bi)
dump(BE_CH_DUMP_SPILL, irg, chordal_env.cls, "-spill", dump_ir_block_graph_sched);
be_abi_fix_stack_nodes(bi->abi);
DEBUG_ONLY(be_verify_schedule(irg);)
DEBUG_ONLY(be_verify_register_pressure(chordal_env.birg->main_env->arch_env, chordal_env.cls, irg);)
assert(be_verify_schedule(irg));
assert(be_verify_register_pressure(chordal_env.birg->main_env->arch_env, chordal_env.cls, irg));
/* Color the graph. */
be_liveness(irg);
......
......@@ -365,7 +365,7 @@ static void be_main_loop(FILE *file_handle)
list_sched(&birg, be_disable_mris);
dump(DUMP_SCHED, irg, "-sched", dump_ir_block_graph_sched);
DEBUG_ONLY(be_verify_schedule(birg.irg);)
assert(be_verify_schedule(birg.irg));
be_do_stat_nodes(irg, "04 Schedule");
......@@ -402,7 +402,7 @@ static void be_main_loop(FILE *file_handle)
arch_code_generator_after_ra(birg.cg);
be_abi_fix_stack_bias(birg.abi);
DEBUG_ONLY(be_verify_schedule(birg.irg);)
assert(be_verify_schedule(birg.irg));
arch_code_generator_done(birg.cg);
dump(DUMP_FINAL, irg, "-end", dump_ir_extblock_graph_sched);
......
......@@ -445,6 +445,7 @@ static block_info_t *compute_block_start_info(ir_node *blk, void *env) {
ir_node *cpy = be_new_Copy(bel->cls, irg, pred_block, arg);
pset_insert_ptr(bel->copies, cpy);
DBG((dbg, DBG_START, " place a %+F of %+F in %+F\n", cpy, arg, pred_block));
/* TODO: Place copies before jumps! */
sched_add_before(sched_last(pred_block), cpy);
set_irn_n(irn, o, cpy);
}
......@@ -584,6 +585,8 @@ next_value:
static void remove_copies(belady_env_t *bel) {
ir_node *irn;
edges_deactivate(current_ir_graph);
edges_activate(current_ir_graph);
foreach_pset(bel->copies, irn) {
ir_node *src;
const ir_edge_t *edge;
......@@ -592,12 +595,14 @@ static void remove_copies(belady_env_t *bel) {
src = be_get_Copy_op(irn);
foreach_out_edge(irn, edge) {
ir_node* user = get_edge_src_irn(edge);
ir_node *user = get_edge_src_irn(edge);
int user_pos = get_edge_src_pos(edge);
#if 0
// is this normal?
if(user == NULL)
break;
#endif
set_irn_n(user, user_pos, src);
}
}
......
......@@ -443,90 +443,10 @@ static void *init_phase_data(phase_t *phase, ir_node *irn, void *old) {
return old;
}
typedef struct _liveness_dump_env_t {
const be_chordal_env_t *chordal_env;
FILE *f;
} liveness_dump_env_t;
#if 0
/**
* Pre-walker: dump liveness data to a file
*/
static void dump_liveness_walker(ir_node *bl, void *data)
{
liveness_dump_env_t *env = (liveness_dump_env_t*) data;
FILE *f = env->f;
const irn_live_t *li;
ir_node* irn;
int in = 0, end = 0, out = 0;
int max_pressure = 0;
pset *live_nodes;
// collect some statistics
live_foreach(bl, li) {
const ir_node* irn = li->irn;
if(!arch_irn_consider_in_reg_alloc(env->chordal_env->birg->main_env->arch_env, env->chordal_env->cls, irn))
continue;
if(live_is_in(li))
in++;
if(live_is_end(li))
end++;
if(live_is_out(li))
out++;
}
// collect register pressure info
live_nodes = pset_new_ptr_default();
be_liveness_end_of_block(env->chordal_env->birg->main_env->arch_env, env->chordal_env->cls, bl, live_nodes);
max_pressure = pset_count(live_nodes);
sched_foreach_reverse(bl, irn) {
int pressure;
if(is_Phi(irn))
break;
be_liveness_transfer(env->chordal_env->birg->main_env->arch_env, env->chordal_env->cls, irn, live_nodes);
pressure = pset_count(live_nodes);
if(pressure > max_pressure)
max_pressure = pressure;
}
del_pset(live_nodes);
ir_fprintf(f, "%+20F (%d in) (%d end) (%d out) (max_pressure %d)\n", bl, in, end, out, max_pressure);
live_foreach(bl, li) {
const ir_node* irn = li->irn;
if(!arch_irn_consider_in_reg_alloc(env->chordal_env->birg->main_env->arch_env, env->chordal_env->cls, irn))
continue;
ir_fprintf(f, "\t%+30F %4s %4s %4s\n",
irn,
live_is_in(li) ? "in" : "",
live_is_end(li) ? "end" : "",
live_is_out(li) ? "out" : "");
}
}
static void dump_liveness_info(const be_chordal_env_t *chordal_env, const char* name) {
char buf[128];
liveness_dump_env_t env;
env.chordal_env = chordal_env;
ir_snprintf(buf, sizeof(buf), "%F_%s_%s-live.txt", chordal_env->irg, chordal_env->cls->name, name);
env.f = fopen(buf, "wt");
if(env.f == NULL)
return;
irg_block_walk_graph(chordal_env->irg, dump_liveness_walker, NULL, &env);
fclose(env.f);
}
#endif
void be_spill_morgan(const be_chordal_env_t *chordal_env) {
morgan_env_t env;
FIRM_DBG_REGISTER(dbg, "ir.be.spillmorgan");
//firm_dbg_set_mask(dbg, DBG_LIVE | DBG_PRESSURE);
env.arch = chordal_env->birg->main_env->arch_env;
env.irg = chordal_env->irg;
......@@ -544,7 +464,6 @@ void be_spill_morgan(const be_chordal_env_t *chordal_env) {
env.loop_attr_set = new_set(loop_attr_cmp, 5);
env.block_attr_set = new_set(block_attr_cmp, 20);
/*-- Part1: Analysis --*/
be_liveness(env.irg);
......@@ -561,7 +480,7 @@ void be_spill_morgan(const be_chordal_env_t *chordal_env) {
reduce_register_pressure_in_loop(&env, get_irg_loop(env.irg), 0);
be_insert_spills_reloads(env.senv);
DEBUG_ONLY(be_verify_schedule(env.irg);)
assert(be_verify_schedule(env.irg));
// cleanup
be_end_uses(env.uses);
......@@ -570,6 +489,7 @@ void be_spill_morgan(const be_chordal_env_t *chordal_env) {
del_set(env.block_attr_set);
// fix the remaining places with too high register pressure with beladies algorithm
be_remove_dead_nodes_from_schedule(env.irg);
be_liveness(env.irg);
be_spill_belady_spill_env(chordal_env, env.senv);
......
......@@ -20,6 +20,7 @@
#include "irdump_t.h"
typedef struct be_verify_register_pressure_env_t_ {
ir_graph *irg;
const arch_env_t *arch_env;
const arch_register_class_t *cls;
int registers_available;
......@@ -48,8 +49,8 @@ static void verify_liveness_walker(ir_node *bl, void *data)
be_liveness_end_of_block(env->arch_env, env->cls, bl, live_nodes);
pressure = pset_count(live_nodes);
if(pressure > env->registers_available) {
ir_printf("Verify Warning: Register pressure too high at end of block %+F (%d/%d):\n",
bl, pressure, env->registers_available);
ir_printf("Verify Warning: Register pressure too high at end of block %+F(%s) (%d/%d):\n",
bl, get_irg_dump_name(env->irg), pressure, env->registers_available);
print_living_values(live_nodes);
env->problem_found = 1;
}
......@@ -63,8 +64,8 @@ static void verify_liveness_walker(ir_node *bl, void *data)
pressure = pset_count(live_nodes);
if(pressure > env->registers_available) {
ir_printf("Verify Warning: Register pressure too high before %+F (in block %+F) (%d/%d).\n",
irn, bl, pressure, env->registers_available);
ir_printf("Verify Warning: Register pressure too high before %+F (in block %+F(%s) (%d/%d).\n",
irn, bl, get_irg_dump_name(env->irg), pressure, env->registers_available);
print_living_values(live_nodes);
env->problem_found = 1;
}
......@@ -72,20 +73,19 @@ static void verify_liveness_walker(ir_node *bl, void *data)
del_pset(live_nodes);
}
void be_verify_register_pressure(const arch_env_t *arch_env, const arch_register_class_t *cls, ir_graph *irg)
int be_verify_register_pressure(const arch_env_t *arch_env, const arch_register_class_t *cls, ir_graph *irg)
{
be_verify_register_pressure_env_t env;
be_liveness(irg);
env.irg = irg;
env.arch_env = arch_env;
env.cls = cls;
env.registers_available = arch_count_non_ignore_regs(arch_env, cls);
env.problem_found = 0;
irg_block_walk_graph(irg, verify_liveness_walker, NULL, &env);
assert(env.problem_found == 0);
return !env.problem_found;
}
typedef struct be_verify_schedule_env_t_ {
......@@ -98,11 +98,13 @@ static void verify_schedule_walker(ir_node *bl, void *data)
be_verify_schedule_env_t *env = (be_verify_schedule_env_t*) data;
ir_node *irn;
int non_phi_found = 0;
int first_cfchange_found = 0;
int cfchange_found = 0;
// TODO ask ABI about delay branches
int delay_branches = 0;
/*
* Make sure that all phi nodes are scheduled at the beginning of the block, and that there
* are no nodes scheduled after a control flow changing node
* is 1 or no control flow changing node scheduled as last operation
*/
sched_foreach(bl, irn) {
if(is_Phi(irn)) {
......@@ -113,22 +115,34 @@ static void verify_schedule_walker(ir_node *bl, void *data)
}
continue;
}
non_phi_found = 1;
if(is_cfop(irn) && get_irn_opcode(irn) != iro_Start) {
first_cfchange_found = 1;
} else {
if(first_cfchange_found) {
ir_printf("Verify Warning: Node %+F scheduled after control flow changing node in block %+F (%s)\n",
if(cfchange_found == 1) {
ir_printf("Verify Warning: More than 1 control flow changing node (%+F) scheduled in block %+F (%s)\n",
irn, bl, get_irg_dump_name(env->irg));
env->problem_found = 1;
}
cfchange_found = 1;
} else if(cfchange_found) {
if(delay_branches == 0) {
ir_printf("Verify Warning: Node %+F scheduled after control flow changing node (+delay branches) in block %+F (%s)\n",
irn, bl, get_irg_dump_name(env->irg));
env->problem_found = 1;
} else {
delay_branches--;
}
}
}
}
if(cfchange_found && delay_branches != 0) {
ir_printf("Not all delay slots filled after jump (%d/%d) in block %+F (%s)\n",
bl, get_irg_dump_name(env->irg));
env->problem_found = 1;
}
}
void be_verify_schedule(ir_graph *irg)
int be_verify_schedule(ir_graph *irg)
{
be_verify_schedule_env_t env;
......@@ -137,5 +151,5 @@ void be_verify_schedule(ir_graph *irg)
irg_block_walk_graph(irg, verify_schedule_walker, NULL, &env);
assert(env.problem_found == 0);
return !env.problem_found;
}
......@@ -21,11 +21,11 @@
* Verifies, that the register pressure for a given register class doesn't exceed the limit
* of available registers.
*/
void be_verify_register_pressure(const arch_env_t *arch_env, const arch_register_class_t* cls, ir_graph *irg);
int be_verify_register_pressure(const arch_env_t *arch_env, const arch_register_class_t* cls, ir_graph *irg);
/**
* Does some sanity checks on the schedule
*/
void be_verify_schedule(ir_graph *irg);
int be_verify_schedule(ir_graph *irg);
#endif
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment