Initial commit of morgans spilling algorithm (spill unused values that live through
[libfirm] / ir / be / beverify.c
1 /*
2  * Author:      Matthias Braun
3  * Date:                05.05.2006
4  * Copyright:   (c) Universitaet Karlsruhe
5  * License:     This file protected by GPL -  GNU GENERAL PUBLIC LICENSE.
6  *
7  */
8 #ifdef HAVE_CONFIG_H
9 #include "config.h"
10 #endif
11
12 #include "beverify.h"
13 #include "belive.h"
14 #include "besched.h"
15
16 #include "irnode.h"
17 #include "irgraph.h"
18 #include "irgwalk.h"
19 #include "irprintf.h"
20 #include "irdump_t.h"
21
22 typedef struct be_verify_register_pressure_env_t_ {
23         const arch_env_t *arch_env;
24         const arch_register_class_t *cls;
25         int registers_available;
26         int problem_found;
27 } be_verify_register_pressure_env_t;
28
29 static void verify_liveness_walker(ir_node *bl, void *data)
30 {
31         be_verify_register_pressure_env_t *env = (be_verify_register_pressure_env_t*) data;
32         int pressure;
33         pset *live_nodes = pset_new_ptr_default();
34         ir_node *irn;
35
36         // collect register pressure info
37         be_liveness_end_of_block(env->arch_env, env->cls, bl, live_nodes);
38         pressure = pset_count(live_nodes);
39         if(pressure > env->registers_available) {
40                 ir_printf("Verify Warning: Register pressure too high at end of block %+F (%d/%d).\n",
41                         bl, pressure, env->registers_available);
42                 env->problem_found = 1;
43         }
44         sched_foreach_reverse(bl, irn) {
45                 int pressure;
46
47                 if(is_Phi(irn))
48                         break;
49
50                 be_liveness_transfer(env->arch_env, env->cls, irn, live_nodes);
51                 pressure = pset_count(live_nodes);
52
53                 if(pressure > env->registers_available) {
54                         ir_printf("Verify Warning: Register pressure too high before %+F (in block %+F) (%d/%d).\n",
55                                 irn, bl, pressure, env->registers_available);
56                         env->problem_found = 1;
57                 }
58         }
59         del_pset(live_nodes);
60 }
61
62 void be_verify_register_pressure(const arch_env_t *arch_env, const arch_register_class_t *cls, ir_graph *irg)
63 {
64         be_verify_register_pressure_env_t env;
65
66         be_liveness(irg);
67
68         env.arch_env = arch_env;
69         env.cls = cls;
70         env.registers_available = arch_count_non_ignore_regs(arch_env, cls);
71         env.problem_found = 0;
72
73         irg_block_walk_graph(irg, verify_liveness_walker, NULL, &env);
74
75         assert(env.problem_found == 0);
76 }
77
78 typedef struct be_verify_schedule_env_t_ {
79         int problem_found;
80         ir_graph *irg;
81 } be_verify_schedule_env_t;
82
83 static void verify_schedule_walker(ir_node *bl, void *data)
84 {
85         be_verify_schedule_env_t *env = (be_verify_schedule_env_t*) data;
86         ir_node *irn;
87         int non_phi_found = 0;
88         int first_cfchange_found = 0;
89
90         /*
91          * Make sure that all phi nodes are scheduled at the beginning of the block, and that there
92          * are no nodes scheduled after a control flow changing node
93          */
94         sched_foreach(bl, irn) {
95                 if(is_Phi(irn)) {
96                         if(non_phi_found) {
97                                 ir_printf("Verify Warning: Phi node %+F scheduled after non-Phi nodes in block %+F (%s)\n",
98                                         irn, bl, get_irg_dump_name(env->irg));
99                                 env->problem_found = 1;
100                         }
101                         continue;
102                 }
103
104                 non_phi_found = 1;
105                 if(is_cfop(irn) && get_irn_opcode(irn) != iro_Start) {
106                         first_cfchange_found = 1;
107                 } else {
108                         if(first_cfchange_found) {
109                                 ir_printf("Verify Warning: Node %+F scheduled after control flow changing node in block %+F (%s)\n",
110                                         irn, bl, get_irg_dump_name(env->irg));
111                                 env->problem_found = 1;
112                         }
113                 }
114         }
115 }
116
117
118 void be_verify_schedule(ir_graph *irg)
119 {
120         be_verify_schedule_env_t env;
121
122         env.problem_found = 0;
123         env.irg = irg;
124
125         irg_block_walk_graph(irg, verify_schedule_walker, NULL, &env);
126
127         assert(env.problem_found == 0);
128 }