2 * Author: Matthias Braun
4 * Copyright: (c) Universitaet Karlsruhe
5 * License: This file protected by GPL - GNU GENERAL PUBLIC LICENSE.
22 typedef struct be_verify_register_pressure_env_t_ {
23 ir_graph *irg; /**< the irg to verify */
24 const arch_env_t *arch_env; /**< an architecture environment */
25 const arch_register_class_t *cls; /**< the register class to check for */
26 int registers_available; /**< number of available registers */
27 int problem_found; /**< flag indicating if a problem was found */
28 } be_verify_register_pressure_env_t;
31 * Print all nodes of a pset into a file.
33 static void print_living_values(FILE *F, pset *live_nodes)
38 foreach_pset(live_nodes, node) {
39 ir_fprintf(F, "%+F ", node);
45 * Check if number of live nodes never exceeds the number of available registers.
47 static void verify_liveness_walker(ir_node *bl, void *data)
49 be_verify_register_pressure_env_t *env = (be_verify_register_pressure_env_t *)data;
50 pset *live_nodes = pset_new_ptr_default();
53 /* collect register pressure info, start with end of a block */
54 be_liveness_end_of_block(env->arch_env, env->cls, bl, live_nodes);
56 sched_foreach_reverse(bl, irn) {
57 int pressure = pset_count(live_nodes);
62 if(pressure > env->registers_available) {
63 ir_fprintf(stderr, "Verify Warning: Register pressure too high at end of block %+F(%s) (%d/%d):\n",
64 bl, get_irg_dump_name(env->irg), pressure, env->registers_available);
65 print_living_values(stderr, live_nodes);
66 env->problem_found = 1;
69 be_liveness_transfer(env->arch_env, env->cls, irn, live_nodes);
75 * Start a walk over the irg and check the register pressure.
77 int be_verify_register_pressure(const arch_env_t *arch_env, const arch_register_class_t *cls, ir_graph *irg)
79 be_verify_register_pressure_env_t env;
84 env.arch_env = arch_env;
86 env.registers_available = arch_count_non_ignore_regs(arch_env, cls);
87 env.problem_found = 0;
89 irg_block_walk_graph(irg, verify_liveness_walker, NULL, &env);
91 return ! env.problem_found;
94 typedef struct be_verify_schedule_env_t_ {
95 int problem_found; /**< flags indicating if there was a problem */
96 ir_graph *irg; /**< the irg to check */
97 } be_verify_schedule_env_t;
100 * Simple schedule checker.
102 static void verify_schedule_walker(ir_node *bl, void *data)
104 be_verify_schedule_env_t *env = (be_verify_schedule_env_t*) data;
106 int non_phi_found = 0;
107 int cfchange_found = 0;
108 // TODO ask ABI about delay branches
109 int delay_branches = 0;
112 * Make sure that all phi nodes are scheduled at the beginning of the block, and that there
113 * is 1 or no control flow changing node scheduled and exactly delay_branches operations after it.
115 sched_foreach(bl, irn) {
118 ir_fprintf(stderr, "Verify Warning: Phi node %+F scheduled after non-Phi nodes in block %+F (%s)\n",
119 irn, bl, get_irg_dump_name(env->irg));
120 env->problem_found = 1;
126 if (is_cfop(irn) && get_irn_opcode(irn) != iro_Start) {
127 /* check, that only one CF operation is scheduled */
128 if (cfchange_found == 1) {
129 ir_fprintf(stderr, "Verify Warning: More than 1 control flow changing node (%+F) scheduled in block %+F (%s)\n",
130 irn, bl, get_irg_dump_name(env->irg));
131 env->problem_found = 1;
134 } else if (cfchange_found) {
135 /* check for delay branches */
136 if (delay_branches == 0) {
137 ir_fprintf(stderr, "Verify Warning: Node %+F scheduled after control flow changing node (+delay branches) in block %+F (%s)\n",
138 irn, bl, get_irg_dump_name(env->irg));
139 env->problem_found = 1;
146 /* check that all delay branches are used (at least with NOPs) */
147 if (cfchange_found && delay_branches != 0) {
148 ir_fprintf(stderr, "Not all delay slots filled after jump (%d/%d) in block %+F (%s)\n",
149 bl, get_irg_dump_name(env->irg));
150 env->problem_found = 1;
155 * Start a walk over the irg and check schedule.
157 int be_verify_schedule(ir_graph *irg)
159 be_verify_schedule_env_t env;
161 env.problem_found = 0;
164 irg_block_walk_graph(irg, verify_schedule_walker, NULL, &env);
166 return ! env.problem_found;