X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fbe%2Fbeverify.c;h=7dc4e587b2e4aa1c7a0552d8a5eaf1c07344ea6a;hb=48f0393daa5d5a14ed7e3e32ee2b090759c9371e;hp=f59ebb1b54242b16c9d97adf46ed164dbd4062e2;hpb=d768cb66475e3868809f13d8dffee32ab136095c;p=libfirm diff --git a/ir/be/beverify.c b/ir/be/beverify.c index f59ebb1b5..7dc4e587b 100644 --- a/ir/be/beverify.c +++ b/ir/be/beverify.c @@ -90,14 +90,14 @@ static void verify_liveness_walker(ir_node *block, void *data) { /** * Start a walk over the irg and check the register pressure. */ -int 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 be_irg_t *birg, const arch_register_class_t *cls, ir_graph *irg) { be_verify_register_pressure_env_t env; env.lv = be_liveness(irg); env.irg = irg; - env.arch_env = arch_env; + env.arch_env = birg->main_env->arch_env; env.cls = cls; - env.registers_available = arch_count_non_ignore_regs(arch_env, cls); + env.registers_available = env.cls->n_regs - be_put_ignore_regs(birg, env.cls, NULL); env.problem_found = 0; irg_block_walk_graph(irg, verify_liveness_walker, NULL, &env); @@ -121,7 +121,6 @@ static void verify_schedule_walker(ir_node *block, void *data) { int cfchange_found = 0; // TODO ask arch about delay branches int delay_branches = 0; - pset *uses = pset_new_ptr_default(); /* * Tests for the following things: @@ -167,18 +166,29 @@ static void verify_schedule_walker(ir_node *block, void *data) { } // 3. Check for uses - if(pset_find_ptr(uses, node)) { - ir_fprintf(stderr, "Verify Warning: Value %+F used before it was defined in block %+F (%s)\n", - node, block, get_irg_dump_name(env->irg)); - env->problem_found = 1; - } if(!is_Phi(node)) { + int nodetime = sched_get_time_step(node); for(i = 0, arity = get_irn_arity(node); i < arity; ++i) { - pset_insert_ptr(uses, get_irn_n(node, i)); + ir_node *arg = get_irn_n(node, i); + if(get_nodes_block(arg) != block + || !sched_is_scheduled(arg)) + continue; + + if(sched_get_time_step(arg) >= nodetime) { + ir_fprintf(stderr, "Verify Warning: Value %+F used by %+F before it was defined in block %+F (%s)\n", + arg, node, block, get_irg_dump_name(env->irg)); + env->problem_found = 1; + } } } + + // 4. check for dead nodes + if(get_irn_n_edges(node) == 0) { + ir_fprintf(stderr, "Verify warning: Node %+F is dead but scheduled in block %+F (%s)\n", + node, block, get_irg_dump_name(env->irg)); + env->problem_found = 1; + } } - del_pset(uses); /* check that all delay branches are filled (at least with NOPs) */ if (cfchange_found && delay_branches != 0) { @@ -195,7 +205,7 @@ static int should_be_scheduled(ir_node *node) { if(get_irn_mode(node) == mode_M) { if(is_Proj(node)) return -1; - if(is_Phi(node) || is_Sync(node) || get_irn_opcode(node) == iro_Pin) + if(is_Phi(node) || is_Sync(node) || is_Pin(node)) return 0; } if(is_Proj(node) && get_irn_mode(node) == mode_X) @@ -586,11 +596,61 @@ typedef struct _be_verify_register_allocation_env_t { int problem_found; } be_verify_register_allocation_env_t; +static void check_register_constraints(ir_node *node, be_verify_register_allocation_env_t *env) { + const arch_env_t *arch_env = env->arch_env; + const arch_register_t *reg; + int i, arity; + + /* verify output register */ + if (arch_get_irn_reg_class(arch_env, node, -1) != NULL) { + reg = arch_get_irn_register(arch_env, node); + if (reg == NULL) { + ir_fprintf(stderr, "Verify warning: Node %+F in block %+F(%s) should have a register assigned\n", + node, get_nodes_block(node), get_irg_dump_name(env->irg)); + env->problem_found = 1; + } + else if (! arch_register_type_is(reg, joker) && !arch_reg_is_allocatable(arch_env, node, -1, reg)) { + ir_fprintf(stderr, "Verify warning: Register %s assigned as output of %+F not allowed (register constraint) in block %+F(%s)\n", + reg->name, node, get_nodes_block(node), get_irg_dump_name(env->irg)); + env->problem_found = 1; + } + } + + /* verify input register */ + arity = get_irn_arity(node); + for (i = 0; i < arity; ++i) { + ir_node *pred = get_irn_n(node, i); + + if (is_Bad(pred)) { + ir_fprintf(stderr, "Verify warning: %+F in block %+F(%s) has Bad as input %d\n", + node, get_nodes_block(node), get_irg_dump_name(env->irg), i); + env->problem_found = 1; + continue; + } + + if (arch_get_irn_reg_class(arch_env, node, i) == NULL) + continue; + + reg = arch_get_irn_register(arch_env, pred); + if (reg == NULL) { + ir_fprintf(stderr, "Verify warning: Node %+F in block %+F(%s) should have a register assigned\n", + pred, get_nodes_block(pred), get_irg_dump_name(env->irg)); + env->problem_found = 1; + continue; + } + else if (! arch_register_type_is(reg, joker) && ! arch_reg_is_allocatable(arch_env, node, i, reg)) { + ir_fprintf(stderr, "Verify warning: Register %s as input %d of %+F not allowed (register constraint) in block %+F(%s)\n", + reg->name, i, node, get_nodes_block(node), get_irg_dump_name(env->irg)); + env->problem_found = 1; + } + } +} + static void check_register_allocation(be_verify_register_allocation_env_t *env, const arch_register_class_t *regclass, pset *nodes) { const arch_env_t *arch_env = env->arch_env; ir_node *node; - const arch_register_t *reg; + const arch_register_t *reg = NULL; int fail = 0; bitset_t *registers = bitset_alloca(arch_register_class_n_regs(regclass)); @@ -600,12 +660,6 @@ static void check_register_allocation(be_verify_register_allocation_env_t *env, continue; reg = arch_get_irn_register(arch_env, node); - if(reg == NULL) { - ir_fprintf(stderr, "Verify warning: Node %+F in block %+F(%s) should have a register assigned\n", - node, get_nodes_block(node), get_irg_dump_name(env->irg)); - env->problem_found = 1; - continue; - } if(bitset_is_set(registers, reg->index)) { pset_break(nodes); fail = 1; @@ -647,6 +701,7 @@ static void verify_block_register_allocation(ir_node *block, void *data) { be_liveness_transfer(env->arch_env, regclass, node, live_nodes); check_register_allocation(env, regclass, live_nodes); + check_register_constraints(node, env); } del_pset(live_nodes); @@ -667,3 +722,55 @@ int be_verify_register_allocation(const arch_env_t *arch_env, ir_graph *irg) { return !env.problem_found; } + + + +//--------------------------------------------------------------------------- + + + +typedef struct _verify_out_dead_nodes_env { + ir_graph *irg; + bitset_t *reachable; + bitset_t *visited; + int problem_found; +} verify_out_dead_nodes_env; + +static void check_out_edges(ir_node *node, verify_out_dead_nodes_env *env) { + const ir_edge_t* edge; + + foreach_out_edge(node, edge) { + ir_node* src = get_edge_src_irn(edge); + + if(!bitset_is_set(env->reachable, get_irn_idx(src))) { + ir_fprintf(stderr, "Verify warning: Node %+F in block %+F(%s) only reachable through out edges from %+F\n", + src, get_nodes_block(src), get_irg_dump_name(env->irg), node); + env->problem_found = 1; + } + + if(!bitset_is_set(env->visited, get_irn_idx(src))) { + bitset_set(env->visited, get_irn_idx(src)); + if(!is_Block(src)) + check_out_edges(src, env); + } + } +} + +static void set_reachable(ir_node *node, void* data) +{ + bitset_t* reachable = data; + bitset_set(reachable, get_irn_idx(node)); +} + +int be_verify_out_edges(ir_graph *irg) { + verify_out_dead_nodes_env env; + env.irg = irg; + env.reachable = bitset_alloca(get_irg_last_idx(irg)); + env.visited = bitset_alloca(get_irg_last_idx(irg)); + env.problem_found = 0; + + irg_walk_graph(irg, set_reachable, NULL, env.reachable); + check_out_edges(get_irg_start(irg), &env); + + return !env.problem_found; +}