#include "beverify.h"
#include "belive.h"
-#include "besched_t.h"
-#include "benode_t.h"
-#include "beirg_t.h"
+#include "besched.h"
+#include "benode.h"
+#include "beirg.h"
#include "beintlive_t.h"
static int my_values_interfere(const ir_node *a, const ir_node *b);
ir_graph *irg) {
be_verify_register_pressure_env_t env;
- env.lv = be_liveness(birg);
+ env.lv = be_liveness(irg);
env.irg = irg;
env.cls = cls;
env.registers_available = env.cls->n_regs - be_put_ignore_regs(birg, env.cls, NULL);
env->problem_found = 1;
}
- if(be_is_Keep(node)) {
+ if(be_is_Keep(node) || be_is_CopyKeep(node)) {
/* at least 1 of the keep arguments has to be it schedule
* predecessor */
int arity = get_irn_arity(node);
int problem = 1;
ir_node *prev = sched_prev(node);
- while(be_is_Keep(prev))
+ while(be_is_Keep(prev) || be_is_CopyKeep(prev))
prev = sched_prev(prev);
for(i = 0; i < arity; ++i) {
static int should_be_scheduled(ir_node *node)
{
- if(is_Block(node))
- return -1;
-
- if(is_Proj(node))
- return 0;
-
- if(get_irn_mode(node) == mode_M) {
- if(is_Phi(node) || is_Sync(node) || is_Pin(node))
- return 0;
- }
- if(be_is_Keep(node) && get_irn_opcode(get_nodes_block(node)) == iro_Bad)
- return 0;
-
switch(get_irn_opcode(node)) {
+ case iro_Bad:
+ case iro_Block:
case iro_End:
case iro_NoMem:
- case iro_Bad:
+ case iro_Pin:
+ case iro_Proj:
+ case iro_Sync:
case iro_Unknown:
return 0;
+ case iro_Phi:
+ if (get_irn_mode(node) == mode_M)
+ return 0;
+ break;
+ case iro_Start:
+ case iro_Jmp:
+ case beo_Return:
+ return 1;
default:
break;
}
- if (arch_irn_get_flags(node) & arch_irn_flags_ignore)
- return -1;
+ if (get_irn_mode(node) != mode_T) {
+ if (arch_irn_is_ignore(node))
+ return -1;
+ }
return 1;
}
}
}
-static void check_spillslot_interference(be_verify_spillslots_env_t *env) {
- int spillcount = set_count(env->spills);
- spill_t **spills = alloca(spillcount * sizeof(spills[0]));
- spill_t *spill;
- int i;
+static void check_spillslot_interference(be_verify_spillslots_env_t *env)
+{
+ int spillcount = set_count(env->spills);
+ spill_t **spills = ALLOCAN(spill_t*, spillcount);
+ spill_t *spill;
+ int i;
for(spill = set_first(env->spills), i = 0; spill != NULL; spill = set_next(env->spills), ++i) {
spills[i] = spill;
static const arch_register_class_t *regclass;
static ir_node **registers;
-static void check_register_constraints(ir_node *node)
+static void check_output_constraints(ir_node *node)
{
- const arch_register_t *reg;
- int i, arity;
-
/* verify output register */
- if (arch_get_irn_reg_class_out(node) != NULL) {
- reg = arch_get_irn_register(node);
+ if (arch_get_irn_reg_class_out(node) == regclass) {
+ const arch_register_t *reg = arch_get_irn_register(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(irg));
problem_found = 1;
}
}
+}
+
+static void check_input_constraints(ir_node *node)
+{
+ const arch_register_t *reg;
+ int i, arity;
/* verify input register */
arity = get_irn_arity(node);
const arch_register_t *pred_reg = arch_get_irn_register(pred);
if (reg != pred_reg && !arch_register_type_is(pred_reg, joker)) {
+ const char *pred_name = pred_reg != NULL ? pred_reg->name : "(null)";
+ const char *reg_name = reg != NULL ? reg->name : "(null)";
ir_fprintf(stderr, "Verify warning: Input %d of %+F in block %+F(%s) uses register %s instead of %s\n",
- i, node, get_nodes_block(node), get_irg_dump_name(irg), pred_reg->name, reg->name);
+ i, node, get_nodes_block(node),
+ get_irg_dump_name(irg), pred_name, reg_name);
problem_found = 1;
}
}
}
}
-static void value_used(ir_node *node) {
+static void value_used(ir_node *block, ir_node *node) {
const arch_register_t *reg;
ir_node *reg_node;
return;
reg = arch_get_irn_register(node);
- if (reg->type & arch_register_type_virtual)
+ if (reg == NULL || reg->type & arch_register_type_virtual)
return;
reg_node = registers[reg->index];
if (reg_node != NULL && reg_node != node) {
ir_fprintf(stderr, "Verify warning: Register %s assigned more than once in block %+F(%s) (nodes %+F %+F)\n",
- reg->name, get_nodes_block(node), get_irg_dump_name(irg),
+ reg->name, block, get_irg_dump_name(irg),
node, reg_node);
problem_found = 1;
}
return;
reg = arch_get_irn_register(node);
- if (reg->type & arch_register_type_virtual)
+ if (reg == NULL || reg->type & arch_register_type_virtual)
return;
reg_node = registers[reg->index];
nregclasses = arch_env_get_n_reg_class(arch_env);
for (i = 0; i < nregclasses; ++i) {
- ir_node *node;
- int idx, i2, n_regs;
+ ir_node *node;
+ int idx, i2, n_regs;
regclass = arch_env_get_reg_class(arch_env, i);
assert(lv->nodes && "live sets must be computed");
n_regs = arch_register_class_n_regs(regclass);
- registers = alloca(n_regs * sizeof(registers[0]));
- memset(registers, 0, n_regs * sizeof(registers[0]));
+ registers = ALLOCANZ(ir_node*, n_regs);
be_lv_foreach(lv, block, be_lv_state_end, idx) {
ir_node *node = be_lv_get_irn(lv, block, idx);
- value_used(node);
+ value_used(block, node);
}
sched_foreach_reverse(block, node) {
foreach_out_edge(node, edge) {
ir_node *def = get_edge_src_irn(edge);
value_def(def);
+ check_output_constraints(def);
}
} else {
value_def(node);
+ check_output_constraints(node);
}
- check_register_constraints(node);
- if (is_Phi(node))
- continue;
+ check_input_constraints(node);
- arity = get_irn_arity(node);
- for (i2 = 0; i2 < arity; ++i2) {
- ir_node *use = get_irn_n(node, i2);
- value_used(use);
+ /* process uses. (Phi inputs are no real uses) */
+ if (!is_Phi(node)) {
+ arity = get_irn_arity(node);
+ for (i2 = 0; i2 < arity; ++i2) {
+ ir_node *use = get_irn_n(node, i2);
+ value_used(block, use);
+ }
}
}
int be_verify_register_allocation(const be_irg_t *birg) {
arch_env = be_get_birg_arch_env(birg);
irg = be_get_birg_irg(birg);
- lv = be_liveness(birg);
+ lv = be_liveness(irg);
problem_found = 0;
be_liveness_assure_sets(lv);
int be_verify_out_edges(ir_graph *irg) {
verify_out_dead_nodes_env env;
+return 1;
env.irg = irg;
env.reachable = bitset_alloca(get_irg_last_idx(irg));
env.problem_found = edges_verify(irg);