X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fbe%2Fbeverify.c;h=d0ecd4cdf6f57bc682840ef2d3ff3304663c920a;hb=ff9b23893ba556b55fb18b0203a804179a4ea5d4;hp=e1264181abf8740f565cb1239eb56feff560fafc;hpb=ff4b945299a64fba36a700e117fd01db9300a5bc;p=libfirm diff --git a/ir/be/beverify.c b/ir/be/beverify.c index e1264181a..d0ecd4cdf 100644 --- a/ir/be/beverify.c +++ b/ir/be/beverify.c @@ -11,16 +11,18 @@ #include "beverify.h" #include "belive.h" -#include "besched.h" +#include "besched_t.h" #include "irnode.h" #include "irgraph.h" #include "irgwalk.h" #include "irprintf.h" #include "irdump_t.h" +#include "benode_t.h" typedef struct be_verify_register_pressure_env_t_ { ir_graph *irg; /**< the irg to verify */ + be_lv_t *lv; /**< Liveness information. */ const arch_env_t *arch_env; /**< an architecture environment */ const arch_register_class_t *cls; /**< the register class to check for */ int registers_available; /**< number of available registers */ @@ -44,29 +46,38 @@ static void print_living_values(FILE *F, pset *live_nodes) /** * Check if number of live nodes never exceeds the number of available registers. */ -static void verify_liveness_walker(ir_node *bl, void *data) +static void verify_liveness_walker(ir_node *block, void *data) { be_verify_register_pressure_env_t *env = (be_verify_register_pressure_env_t *)data; pset *live_nodes = pset_new_ptr_default(); ir_node *irn; + int pressure; /* collect register pressure info, start with end of a block */ - be_liveness_end_of_block(env->arch_env, env->cls, bl, live_nodes); + be_liveness_end_of_block(env->lv, env->arch_env, env->cls, block, live_nodes); - sched_foreach_reverse(bl, irn) { - int pressure = pset_count(live_nodes); + pressure = pset_count(live_nodes); + if(pressure > env->registers_available) { + ir_fprintf(stderr, "Verify Warning: Register pressure too high at end of block %+F(%s) (%d/%d):\n", + block, get_irg_dump_name(env->irg), pressure, env->registers_available); + print_living_values(stderr, live_nodes); + env->problem_found = 1; + } + sched_foreach_reverse(block, irn) { if (is_Phi(irn)) break; + be_liveness_transfer(env->arch_env, env->cls, irn, live_nodes); + + pressure = pset_count(live_nodes); + if(pressure > env->registers_available) { - ir_fprintf(stderr, "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); + ir_fprintf(stderr, "Verify Warning: Register pressure too high before node %+F in %+F(%s) (%d/%d):\n", + irn, block, get_irg_dump_name(env->irg), pressure, env->registers_available); print_living_values(stderr, live_nodes); env->problem_found = 1; } - - be_liveness_transfer(env->arch_env, env->cls, irn, live_nodes); } del_pset(live_nodes); } @@ -78,8 +89,7 @@ int be_verify_register_pressure(const arch_env_t *arch_env, const arch_register_ { be_verify_register_pressure_env_t env; - be_liveness(irg); - + env.lv = be_liveness(irg); env.irg = irg; env.arch_env = arch_env; env.cls = cls; @@ -87,6 +97,7 @@ int be_verify_register_pressure(const arch_env_t *arch_env, const arch_register_ env.problem_found = 0; irg_block_walk_graph(irg, verify_liveness_walker, NULL, &env); + be_liveness_free(env.lv); return ! env.problem_found; } @@ -99,54 +110,77 @@ typedef struct be_verify_schedule_env_t_ { /** * Simple schedule checker. */ -static void verify_schedule_walker(ir_node *bl, void *data) +static void verify_schedule_walker(ir_node *block, void *data) { be_verify_schedule_env_t *env = (be_verify_schedule_env_t*) data; - ir_node *irn; + ir_node *node; int non_phi_found = 0; int cfchange_found = 0; - // TODO ask ABI about delay branches + // TODO ask arch about delay branches int delay_branches = 0; + pset *uses = pset_new_ptr_default(); /* - * Make sure that all phi nodes are scheduled at the beginning of the block, and that there - * is 1 or no control flow changing node scheduled and exactly delay_branches operations after it. + * Tests for the following things: + * 1. Make sure that all phi nodes are scheduled at the beginning of the block + * 2. There is 1 or no control flow changing node scheduled and exactly delay_branches operations after it. + * 3. No value is defined after it has been used */ - sched_foreach(bl, irn) { - if (is_Phi(irn)) { + sched_foreach(block, node) { + int i, arity; + + // 1. Check for phis + if (is_Phi(node)) { if (non_phi_found) { ir_fprintf(stderr, "Verify Warning: Phi node %+F scheduled after non-Phi nodes in block %+F (%s)\n", - irn, bl, get_irg_dump_name(env->irg)); + node, block, get_irg_dump_name(env->irg)); env->problem_found = 1; } - continue; + } else { + non_phi_found = 1; } - non_phi_found = 1; - if (is_cfop(irn) && get_irn_opcode(irn) != iro_Start) { + // 2. Check for control flow changing nodes + if (is_cfop(node) && get_irn_opcode(node) != iro_Start) { /* check, that only one CF operation is scheduled */ if (cfchange_found == 1) { ir_fprintf(stderr, "Verify Warning: More than 1 control flow changing node (%+F) scheduled in block %+F (%s)\n", - irn, bl, get_irg_dump_name(env->irg)); + node, block, get_irg_dump_name(env->irg)); env->problem_found = 1; } cfchange_found = 1; } else if (cfchange_found) { - /* check for delay branches */ - if (delay_branches == 0) { - ir_fprintf(stderr, "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--; + // proj and keepany aren't real instructions... + if(!is_Proj(node) && !be_is_Keep(node)) { + /* check for delay branches */ + if (delay_branches == 0) { + ir_fprintf(stderr, "Verify Warning: Node %+F scheduled after control flow changing node (+delay branches) in block %+F (%s)\n", + node, block, get_irg_dump_name(env->irg)); + env->problem_found = 1; + } else { + delay_branches--; + } + } + } + + // 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)) { + for(i = 0, arity = get_irn_arity(node); i < arity; ++i) { + pset_insert_ptr(uses, get_irn_n(node, i)); } } } + del_pset(uses); - /* check that all delay branches are used (at least with NOPs) */ + /* check that all delay branches are filled (at least with NOPs) */ if (cfchange_found && delay_branches != 0) { ir_fprintf(stderr, "Not all delay slots filled after jump (%d/%d) in block %+F (%s)\n", - bl, get_irg_dump_name(env->irg)); + block, get_irg_dump_name(env->irg)); env->problem_found = 1; } } @@ -165,3 +199,8 @@ int be_verify_schedule(ir_graph *irg) return ! env.problem_found; } + +/* Ideas for further verifiers: + * - make sure that each use is dominated by its definition (except phi arguments) + * - make sure that all spills attached to phims spill into the same slot... + */