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 *block, 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();
54 /* collect register pressure info, start with end of a block */
55 be_liveness_end_of_block(env->arch_env, env->cls, block, live_nodes);
57 pressure = pset_count(live_nodes);
58 if(pressure > env->registers_available) {
59 ir_fprintf(stderr, "Verify Warning: Register pressure too high at end of block %+F(%s) (%d/%d):\n",
60 block, get_irg_dump_name(env->irg), pressure, env->registers_available);
61 print_living_values(stderr, live_nodes);
62 env->problem_found = 1;
65 sched_foreach_reverse(block, irn) {
69 be_liveness_transfer(env->arch_env, env->cls, irn, live_nodes);
71 pressure = pset_count(live_nodes);
73 if(pressure > env->registers_available) {
74 ir_fprintf(stderr, "Verify Warning: Register pressure too high before node %+F in %+F(%s) (%d/%d):\n",
75 irn, block, get_irg_dump_name(env->irg), pressure, env->registers_available);
76 print_living_values(stderr, live_nodes);
77 env->problem_found = 1;
84 * Start a walk over the irg and check the register pressure.
86 int be_verify_register_pressure(const arch_env_t *arch_env, const arch_register_class_t *cls, ir_graph *irg)
88 be_verify_register_pressure_env_t env;
93 env.arch_env = arch_env;
95 env.registers_available = arch_count_non_ignore_regs(arch_env, cls);
96 env.problem_found = 0;
98 irg_block_walk_graph(irg, verify_liveness_walker, NULL, &env);
100 return ! env.problem_found;
103 typedef struct be_verify_schedule_env_t_ {
104 int problem_found; /**< flags indicating if there was a problem */
105 ir_graph *irg; /**< the irg to check */
106 } be_verify_schedule_env_t;
109 * Simple schedule checker.
111 static void verify_schedule_walker(ir_node *block, void *data)
113 be_verify_schedule_env_t *env = (be_verify_schedule_env_t*) data;
115 int non_phi_found = 0;
116 int cfchange_found = 0;
117 // TODO ask arch about delay branches
118 int delay_branches = 0;
119 pset *uses = pset_new_ptr_default();
122 * Tests for the following things:
123 * 1. Make sure that all phi nodes are scheduled at the beginning of the block
124 * 2. There is 1 or no control flow changing node scheduled and exactly delay_branches operations after it.
125 * 3. No value is defined after it has been used
127 sched_foreach(block, node) {
133 ir_fprintf(stderr, "Verify Warning: Phi node %+F scheduled after non-Phi nodes in block %+F (%s)\n",
134 node, block, get_irg_dump_name(env->irg));
135 env->problem_found = 1;
141 // 2. Check for control flow changing nodes
142 if (is_cfop(node) && get_irn_opcode(node) != iro_Start) {
143 /* check, that only one CF operation is scheduled */
144 if (cfchange_found == 1) {
145 ir_fprintf(stderr, "Verify Warning: More than 1 control flow changing node (%+F) scheduled in block %+F (%s)\n",
146 node, block, get_irg_dump_name(env->irg));
147 env->problem_found = 1;
150 } else if (cfchange_found) {
151 /* check for delay branches */
152 if (delay_branches == 0) {
153 ir_fprintf(stderr, "Verify Warning: Node %+F scheduled after control flow changing node (+delay branches) in block %+F (%s)\n",
154 node, block, get_irg_dump_name(env->irg));
155 env->problem_found = 1;
162 if(pset_find_ptr(uses, node)) {
163 ir_fprintf(stderr, "Verify Warning: Value %+F used before it was defined in block %+F (%s)\n",
164 node, block, get_irg_dump_name(env->irg));
165 env->problem_found = 1;
167 for(i = 0, arity = get_irn_arity(node); i < arity; ++i) {
168 pset_insert_ptr(uses, get_irn_n(node, i));
173 /* check that all delay branches are filled (at least with NOPs) */
174 if (cfchange_found && delay_branches != 0) {
175 ir_fprintf(stderr, "Not all delay slots filled after jump (%d/%d) in block %+F (%s)\n",
176 block, get_irg_dump_name(env->irg));
177 env->problem_found = 1;
182 * Start a walk over the irg and check schedule.
184 int be_verify_schedule(ir_graph *irg)
186 be_verify_schedule_env_t env;
188 env.problem_found = 0;
191 irg_block_walk_graph(irg, verify_schedule_walker, NULL, &env);
193 return ! env.problem_found;