unified mein file comments
[libfirm] / ir / be / beverify.c
1 /*
2  * Copyright (C) 1995-2007 University of Karlsruhe.  All right reserved.
3  *
4  * This file is part of libFirm.
5  *
6  * This file may be distributed and/or modified under the terms of the
7  * GNU General Public License version 2 as published by the Free Software
8  * Foundation and appearing in the file LICENSE.GPL included in the
9  * packaging of this file.
10  *
11  * Licensees holding valid libFirm Professional Edition licenses may use
12  * this file in accordance with the libFirm Commercial License.
13  * Agreement provided with the Software.
14  *
15  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
16  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE.
18  */
19
20 /**
21  * @file
22  * @brief       Various verify routines that check a scheduled graph for correctness.
23  * @author      Matthias Braun
24  * @date        05.05.2006
25  * @version     $Id$
26  */
27 #ifdef HAVE_CONFIG_H
28 #include "config.h"
29 #endif
30
31 #include <limits.h>
32
33 #include "bitset.h"
34 #include "set.h"
35 #include "array.h"
36
37 #include "irnode.h"
38 #include "irgraph.h"
39 #include "irgwalk.h"
40 #include "irprintf.h"
41 #include "irdump_t.h"
42 #include "iredges.h"
43
44 #include "beverify.h"
45 #include "belive.h"
46 #include "besched_t.h"
47 #include "benode_t.h"
48 #include "beirg_t.h"
49 #include "bera.h"
50
51 static int my_values_interfere(const ir_node *a, const ir_node *b);
52
53 typedef struct be_verify_register_pressure_env_t_ {
54         ir_graph                    *irg;                 /**< the irg to verify */
55          be_lv_t                    *lv;                  /**< Liveness information. */
56         const arch_env_t            *arch_env;            /**< an architecture environment */
57         const arch_register_class_t *cls;                 /**< the register class to check for */
58         int                         registers_available;  /**< number of available registers */
59         int                         problem_found;        /**< flag indicating if a problem was found */
60 } be_verify_register_pressure_env_t;
61
62 /**
63  * Print all nodes of a pset into a file.
64  */
65 static void print_living_values(FILE *F, pset *live_nodes) {
66         ir_node *node;
67
68         ir_fprintf(F, "\t");
69         foreach_pset(live_nodes, node) {
70                 ir_fprintf(F, "%+F ", node);
71         }
72         ir_fprintf(F, "\n");
73 }
74
75 /**
76  * Check if number of live nodes never exceeds the number of available registers.
77  */
78 static void verify_liveness_walker(ir_node *block, void *data) {
79         be_verify_register_pressure_env_t *env = (be_verify_register_pressure_env_t *)data;
80         pset    *live_nodes = pset_new_ptr_default();
81         ir_node *irn;
82         int pressure;
83
84         /* collect register pressure info, start with end of a block */
85         be_liveness_end_of_block(env->lv, env->arch_env, env->cls, block, live_nodes);
86
87         pressure = pset_count(live_nodes);
88         if(pressure > env->registers_available) {
89                 ir_fprintf(stderr, "Verify Warning: Register pressure too high at end of block %+F(%s) (%d/%d):\n",
90                         block, get_irg_dump_name(env->irg), pressure, env->registers_available);
91                 print_living_values(stderr, live_nodes);
92                 env->problem_found = 1;
93         }
94
95         sched_foreach_reverse(block, irn) {
96                 if (is_Phi(irn))
97                         break;
98
99                 be_liveness_transfer(env->arch_env, env->cls, irn, live_nodes);
100
101                 pressure = pset_count(live_nodes);
102
103                 if(pressure > env->registers_available) {
104                         ir_fprintf(stderr, "Verify Warning: Register pressure too high before node %+F in %+F(%s) (%d/%d):\n",
105                                 irn, block, get_irg_dump_name(env->irg), pressure, env->registers_available);
106                         print_living_values(stderr, live_nodes);
107                         env->problem_found = 1;
108                 }
109         }
110         del_pset(live_nodes);
111 }
112
113 /**
114  * Start a walk over the irg and check the register pressure.
115  */
116 int be_verify_register_pressure(const be_irg_t *birg,
117                                 const arch_register_class_t *cls,
118                                 ir_graph *irg) {
119         be_verify_register_pressure_env_t env;
120
121         env.lv                  = be_liveness(irg);
122         env.irg                 = irg;
123         env.arch_env            = birg->main_env->arch_env;
124         env.cls                 = cls;
125         env.registers_available = env.cls->n_regs - be_put_ignore_regs(birg, env.cls, NULL);
126         env.problem_found       = 0;
127
128         irg_block_walk_graph(irg, verify_liveness_walker, NULL, &env);
129         be_liveness_free(env.lv);
130
131         return ! env.problem_found;
132 }
133
134
135
136 //---------------------------------------------------------------------------
137
138
139
140 typedef struct be_verify_schedule_env_t_ {
141         int      problem_found;     /**< flags indicating if there was a problem */
142         bitset_t *scheduled;        /**< bitset of scheduled nodes */
143         ir_graph *irg;              /**< the irg to check */
144         const arch_env_t *arch_env; /**< the arch_env */
145 } be_verify_schedule_env_t;
146
147 /**
148  * Simple schedule checker.
149  */
150 static void verify_schedule_walker(ir_node *block, void *data) {
151         be_verify_schedule_env_t *env = (be_verify_schedule_env_t*) data;
152         ir_node *node;
153         int non_phi_found  = 0;
154         int cfchange_found = 0;
155         // TODO ask arch about delay branches
156         int delay_branches = 0;
157         int last_timestep = INT_MIN;
158
159         /*
160          * Tests for the following things:
161          *   1. Make sure that all phi nodes are scheduled at the beginning of the block
162          *   2. There is 1 or no control flow changing node scheduled and exactly delay_branches operations after it.
163          *   3. No value is defined after it has been used
164          */
165         sched_foreach(block, node) {
166                 int i, arity;
167                 int timestep;
168
169                 // this node is scheduled
170                 if(bitset_is_set(env->scheduled, get_irn_idx(node))) {
171                         ir_fprintf(stderr, "Verify warning: %+F appears to be schedule twice\n");
172                         env->problem_found = 1;
173                 }
174                 bitset_set(env->scheduled, get_irn_idx(node));
175
176                 // Check that scheduled nodes are in the correct block
177                 if(get_nodes_block(node) != block) {
178                         ir_fprintf(stderr, "Verify warning: %+F is in block %+F but scheduled in %+F\n", node, get_nodes_block(node), block);
179                         env->problem_found = 1;
180                 }
181
182                 // Check that timesteps are increasing
183                 timestep = sched_get_time_step(node);
184                 if(timestep <= last_timestep) {
185                         ir_fprintf(stderr, "Verify warning: Schedule timestep did not increase at node %+F\n",
186                                    node);
187                         env->problem_found = 1;
188                 }
189                 last_timestep = timestep;
190
191                 // Check that phis come before any other node
192                 if (is_Phi(node)) {
193                         if (non_phi_found) {
194                                 ir_fprintf(stderr, "Verify Warning: Phi node %+F scheduled after non-Phi nodes in block %+F (%s)\n",
195                                         node, block, get_irg_dump_name(env->irg));
196                                 env->problem_found = 1;
197                         }
198                 } else {
199                         non_phi_found = 1;
200                 }
201
202                 // Check for control flow changing nodes
203                 if (is_cfop(node) && get_irn_opcode(node) != iro_Start) {
204                         /* check, that only one CF operation is scheduled */
205                         if (cfchange_found == 1) {
206                                 ir_fprintf(stderr, "Verify Warning: More than 1 control flow changing node (%+F) scheduled in block %+F (%s)\n",
207                                         node, block, get_irg_dump_name(env->irg));
208                                 env->problem_found = 1;
209                         }
210                         cfchange_found = 1;
211                 } else if (cfchange_found) {
212                         // proj and keepany aren't real instructions...
213                         if(!is_Proj(node) && !be_is_Keep(node)) {
214                                 /* check for delay branches */
215                                 if (delay_branches == 0) {
216                                         ir_fprintf(stderr, "Verify Warning: Node %+F scheduled after control flow changing node (+delay branches) in block %+F (%s)\n",
217                                                 node, block, get_irg_dump_name(env->irg));
218                                         env->problem_found = 1;
219                                 } else {
220                                         delay_branches--;
221                                 }
222                         }
223                 }
224
225                 // Check that all uses come before their definitions
226                 if(!is_Phi(node)) {
227                         int nodetime = sched_get_time_step(node);
228                         for(i = 0, arity = get_irn_arity(node); i < arity; ++i) {
229                                 ir_node *arg = get_irn_n(node, i);
230                                 if(get_nodes_block(arg) != block
231                                    || !sched_is_scheduled(arg))
232                                         continue;
233
234                                 if(sched_get_time_step(arg) >= nodetime) {
235                                         ir_fprintf(stderr, "Verify Warning: Value %+F used by %+F before it was defined in block %+F (%s)\n",
236                                                    arg, node, block, get_irg_dump_name(env->irg));
237                                         env->problem_found = 1;
238                                 }
239                         }
240                 }
241
242                 // Check that no dead nodes are scheduled
243                 if(get_irn_n_edges(node) == 0) {
244                         ir_fprintf(stderr, "Verify warning: Node %+F is dead but scheduled in block %+F (%s)\n",
245                                    node, block, get_irg_dump_name(env->irg));
246                         env->problem_found = 1;
247                 }
248         }
249
250         /* check that all delay branches are filled (at least with NOPs) */
251         if (cfchange_found && delay_branches != 0) {
252                 ir_fprintf(stderr, "Verify warning: Not all delay slots filled after jump (%d/%d) in block %+F (%s)\n",
253                         block, get_irg_dump_name(env->irg));
254                 env->problem_found = 1;
255         }
256 }
257
258 static int should_be_scheduled(be_verify_schedule_env_t *env, ir_node *node) {
259         if(is_Block(node))
260                 return -1;
261
262         if(get_irn_mode(node) == mode_M) {
263                 if(is_Proj(node))
264                         return -1;
265                 if(is_Phi(node) || is_Sync(node) || is_Pin(node))
266                         return 0;
267         }
268         if(is_Proj(node) && get_irn_mode(node) == mode_X)
269                 return 0;
270         if(be_is_Keep(node) && get_irn_opcode(get_nodes_block(node)) == iro_Bad)
271                 return 0;
272
273         switch(get_irn_opcode(node)) {
274         case iro_End:
275         case iro_NoMem:
276         case iro_Bad:
277         case iro_Unknown:
278                 return 0;
279         default:
280                 break;
281         }
282
283         if(arch_irn_get_flags(env->arch_env, node) & arch_irn_flags_ignore)
284                 return -1;
285
286         return 1;
287 }
288
289 static void check_schedule(ir_node *node, void *data) {
290         be_verify_schedule_env_t *env = data;
291         int should_be;
292         int scheduled;
293
294         should_be = should_be_scheduled(env, node);
295         if(should_be == -1)
296                 return;
297
298         scheduled = bitset_is_set(env->scheduled, get_irn_idx(node)) ? 1 : 0;
299         should_be = should_be ? 1 : 0;
300         if(should_be != scheduled) {
301                 ir_fprintf(stderr, "Verify warning: Node %+F in block %+F(%s) should%s be scheduled\n",
302                         node, get_nodes_block(node), get_irg_dump_name(env->irg), should_be ? "" : " not");
303                 env->problem_found = 1;
304         }
305 }
306
307 /**
308  * Start a walk over the irg and check schedule.
309  */
310 int be_verify_schedule(const be_irg_t *birg)
311 {
312         be_verify_schedule_env_t env;
313
314         env.problem_found = 0;
315         env.irg           = be_get_birg_irg(birg);
316         env.scheduled     = bitset_alloca(get_irg_last_idx(env.irg));
317         env.arch_env      = birg->main_env->arch_env;
318
319         irg_block_walk_graph(env.irg, verify_schedule_walker, NULL, &env);
320         // check if all nodes are scheduled
321         irg_walk_graph(env.irg, check_schedule, NULL, &env);
322
323         return ! env.problem_found;
324 }
325
326
327
328 //---------------------------------------------------------------------------
329
330
331
332 typedef struct _spill_t {
333         ir_node *spill;
334         ir_entity *ent;
335 } spill_t;
336
337 typedef struct {
338         const arch_env_t *arch_env;
339         ir_graph *irg;
340         set *spills;
341         ir_node **reloads;
342         int problem_found;
343 } be_verify_spillslots_env_t;
344
345 static int cmp_spill(const void* d1, const void* d2, size_t size) {
346         const spill_t* s1 = d1;
347         const spill_t* s2 = d2;
348         return s1->spill != s2->spill;
349 }
350
351 static spill_t *find_spill(be_verify_spillslots_env_t *env, ir_node *node) {
352         spill_t spill;
353
354         spill.spill = node;
355         return set_find(env->spills, &spill, sizeof(spill), HASH_PTR(node));
356 }
357
358 static spill_t *get_spill(be_verify_spillslots_env_t *env, ir_node *node, ir_entity *ent) {
359         spill_t spill, *res;
360         int hash = HASH_PTR(node);
361
362         spill.spill = node;
363         res = set_find(env->spills, &spill, sizeof(spill), hash);
364
365         if(res == NULL) {
366                 spill.ent = ent;
367                 res = set_insert(env->spills, &spill, sizeof(spill), hash);
368         }
369
370         return res;
371 }
372
373 static ir_node *get_memory_edge(const ir_node *node) {
374         int i, arity;
375         ir_node *result = NULL;
376
377         arity = get_irn_arity(node);
378         for(i = arity - 1; i >= 0; --i) {
379                 ir_node *arg = get_irn_n(node, i);
380                 if(get_irn_mode(arg) == mode_M) {
381                         assert(result == NULL);
382                         result = arg;
383                 }
384         }
385
386         return result;
387 }
388
389 static void collect(be_verify_spillslots_env_t *env, ir_node *node, ir_node *reload, ir_entity* ent);
390
391 static void check_entity(be_verify_spillslots_env_t *env, ir_node *node, ir_entity *ent) {
392         if(ent == NULL) {
393                 ir_fprintf(stderr, "Verify warning: Node %+F in block %+F(%s) should have an entity assigned\n",
394                            node, get_nodes_block(node), get_irg_dump_name(env->irg));
395         }
396 }
397
398 static void collect_spill(be_verify_spillslots_env_t *env, ir_node *node, ir_node *reload, ir_entity* ent) {
399         ir_entity *spillent = arch_get_frame_entity(env->arch_env, node);
400         check_entity(env, node, spillent);
401         get_spill(env, node, ent);
402
403         if(spillent != ent) {
404                 ir_fprintf(stderr, "Verify warning: Spill %+F has different entity than reload %+F in block %+F(%s)\n",
405                         node, reload, get_nodes_block(node), get_irg_dump_name(env->irg));
406                 env->problem_found = 1;
407         }
408 }
409
410 static void collect_memperm(be_verify_spillslots_env_t *env, ir_node *node, ir_node *reload, ir_entity* ent) {
411         int i, arity;
412         spill_t spill, *res;
413         int hash = HASH_PTR(node);
414         int out;
415         ir_node* memperm;
416         ir_entity *spillent;
417
418         assert(is_Proj(node));
419
420         memperm = get_Proj_pred(node);
421         out = get_Proj_proj(node);
422
423         spillent = be_get_MemPerm_out_entity(memperm, out);
424         check_entity(env, memperm, spillent);
425         if(spillent != ent) {
426                 ir_fprintf(stderr, "Verify warning: MemPerm %+F has different entity than reload %+F in block %+F(%s)\n",
427                         node, reload, get_nodes_block(node), get_irg_dump_name(env->irg));
428                 env->problem_found = 1;
429         }
430
431         spill.spill = node;
432         res = set_find(env->spills, &spill, sizeof(spill), hash);
433         if(res != NULL) {
434                 return;
435         }
436
437         spill.ent = spillent;
438         res = set_insert(env->spills, &spill, sizeof(spill), hash);
439
440         for(i = 0, arity = be_get_MemPerm_entity_arity(memperm); i < arity; ++i) {
441                 ir_node* arg = get_irn_n(memperm, i + 1);
442                 ir_entity* argent = be_get_MemPerm_in_entity(memperm, i);
443
444                 collect(env, arg, memperm, argent);
445         }
446 }
447
448 static void collect_memphi(be_verify_spillslots_env_t *env, ir_node *node, ir_node *reload, ir_entity *ent) {
449         int i, arity;
450         spill_t spill, *res;
451         int hash = HASH_PTR(node);
452
453         assert(is_Phi(node));
454
455         spill.spill = node;
456         res = set_find(env->spills, &spill, sizeof(spill), hash);
457         if(res != NULL) {
458                 return;
459         }
460
461         spill.ent = ent;
462         res = set_insert(env->spills, &spill, sizeof(spill), hash);
463
464         // is 1 of the arguments a spill?
465         for(i = 0, arity = get_irn_arity(node); i < arity; ++i) {
466                 ir_node* arg = get_irn_n(node, i);
467                 collect(env, arg, reload, ent);
468         }
469 }
470
471 static void collect(be_verify_spillslots_env_t *env, ir_node *node, ir_node *reload, ir_entity* ent) {
472         if(be_is_Spill(node)) {
473                 collect_spill(env, node, reload, ent);
474         } else if(is_Proj(node)) {
475                 collect_memperm(env, node, reload, ent);
476         } else if(is_Phi(node) && get_irn_mode(node) == mode_M) {
477                 collect_memphi(env, node, reload, ent);
478         } else {
479                 // Disabled for now, spills might get transformed by the backend
480 #if 0
481                 ir_fprintf(stderr, "Verify warning: No spill, memperm or memphi attached to node %+F found from node %+F in block %+F(%s)\n",
482                         node, reload, get_nodes_block(node), get_irg_dump_name(env->irg));
483                 env->problem_found = 1;
484 #endif
485         }
486 }
487
488 /**
489  * This walker function searches for reloads and collects all the spills
490  * and memphis attached to them.
491  */
492 static void collect_spills_walker(ir_node *node, void *data) {
493         be_verify_spillslots_env_t *env = data;
494         const arch_env_t *arch_env = env->arch_env;
495
496         // @@@ ia32_classify returns classification of Proj_pred :-/
497         if(is_Proj(node))
498                 return;
499
500         if(arch_irn_class_is(arch_env, node, reload)) {
501                 ir_node *spill = get_memory_edge(node);
502                 ir_entity *ent;
503
504                 if(spill == NULL) {
505                         ir_fprintf(stderr, "Verify warning: No spill attached to reload %+F in block %+F(%s)\n",
506                                    node, get_nodes_block(node), get_irg_dump_name(env->irg));
507                         env->problem_found = 1;
508                         return;
509                 }
510                 ent = arch_get_frame_entity(env->arch_env, node);
511                 check_entity(env, node, ent);
512
513                 collect(env, spill, node, ent);
514                 ARR_APP1(ir_node*, env->reloads, node);
515         }
516 }
517
518 static void check_spillslot_interference(be_verify_spillslots_env_t *env) {
519         int spillcount = set_count(env->spills);
520         spill_t **spills = alloca(spillcount * sizeof(spills[0]));
521         spill_t *spill;
522         int i;
523
524         for(spill = set_first(env->spills), i = 0; spill != NULL; spill = set_next(env->spills), ++i) {
525                 spills[i] = spill;
526         }
527
528         for(i = 0; i < spillcount; ++i) {
529                 spill_t *sp1 = spills[i];
530                 int i2;
531
532                 for(i2 = i+1; i2 < spillcount; ++i2) {
533                         spill_t *sp2 = spills[i2];
534
535                         if(sp1->ent != sp2->ent)
536                                 continue;
537
538                         if(my_values_interfere(sp1->spill, sp2->spill)) {
539                                 ir_fprintf(stderr, "Verify warning: Spillslots for %+F in block %+F(%s) and %+F in block %+F(%s) interfere\n",
540                                         sp1->spill, get_nodes_block(sp1->spill), get_irg_dump_name(env->irg),
541                                         sp2->spill, get_nodes_block(sp2->spill), get_irg_dump_name(env->irg));
542                                 env->problem_found = 1;
543                                 my_values_interfere(sp1->spill, sp2->spill);
544                         }
545                 }
546         }
547 }
548
549 static void check_lonely_spills(ir_node *node, void *data) {
550         be_verify_spillslots_env_t *env = data;
551
552         if(be_is_Spill(node) || (is_Proj(node) && be_is_MemPerm(get_Proj_pred(node)))) {
553                 spill_t *spill = find_spill(env, node);
554                 if(be_is_Spill(node)) {
555                         ir_entity *ent = arch_get_frame_entity(env->arch_env, node);
556                         check_entity(env, node, ent);
557                 }
558
559                 if(spill == NULL) {
560                         ir_fprintf(stderr, "Verify warning: Node %+F in block %+F(%s) not connected to a reaload\n",
561                                    node, get_nodes_block(node), get_irg_dump_name(env->irg));
562                 }
563         }
564 }
565
566 int be_verify_spillslots(const arch_env_t *arch_env, ir_graph *irg)
567 {
568         be_verify_spillslots_env_t env;
569
570         env.arch_env = arch_env;
571         env.irg = irg;
572         env.spills = new_set(cmp_spill, 10);
573         env.reloads = NEW_ARR_F(ir_node*, 0);
574         env.problem_found = 0;
575
576         irg_walk_graph(irg, collect_spills_walker, NULL, &env);
577         irg_walk_graph(irg, check_lonely_spills, NULL, &env);
578
579         check_spillslot_interference(&env);
580
581         DEL_ARR_F(env.reloads);
582         del_set(env.spills);
583
584         return ! env.problem_found;
585 }
586
587
588
589 //---------------------------------------------------------------------------
590
591
592
593 /**
594  * Check, if two values interfere.
595  * @param a The first value.
596  * @param b The second value.
597  * @return 1, if a and b interfere, 0 if not.
598  */
599 static int my_values_interfere(const ir_node *a, const ir_node *b) {
600         const ir_edge_t *edge;
601         ir_node *bb;
602         int a2b = value_dominates(a, b);
603         int b2a = value_dominates(b, a);
604
605         /* If there is no dominance relation, they do not interfere. */
606         if(!a2b && !b2a)
607                 return 0;
608
609         /*
610          * Adjust a and b so, that a dominates b if
611          * a dominates b or vice versa.
612          */
613         if(b2a) {
614                 const ir_node *t = a;
615                 a = b;
616                 b = t;
617         }
618
619         bb = get_nodes_block(b);
620
621         /*
622          * Look at all usages of a.
623          * If there's one usage of a in the block of b, then
624          * we check, if this use is dominated by b, if that's true
625          * a and b interfere. Note that b must strictly dominate the user,
626          * since if b is the last user of in the block, b and a do not
627          * interfere.
628          * Uses of a not in b's block can be disobeyed, because the
629          * check for a being live at the end of b's block is already
630          * performed.
631          */
632         foreach_out_edge(a, edge) {
633                 const ir_node *user = get_edge_src_irn(edge);
634                 if(b == user)
635                         continue;
636
637                 if(get_irn_opcode(user) == iro_End)
638                         continue;
639
640                 // in case of phi arguments we compare with the block the value comes from
641                 if(is_Phi(user)) {
642                         ir_node *phiblock = get_nodes_block(user);
643                         if(phiblock == bb)
644                                 continue;
645                         user = get_irn_n(phiblock, get_edge_src_pos(edge));
646                 }
647
648                 if(value_dominates(b, user))
649                         return 1;
650         }
651
652         return 0;
653 }
654
655
656
657 //---------------------------------------------------------------------------
658
659
660
661 typedef struct _be_verify_register_allocation_env_t {
662         const arch_env_t *arch_env;
663         ir_graph *irg;
664         be_lv_t *lv;
665         int problem_found;
666 } be_verify_register_allocation_env_t;
667
668 static void check_register_constraints(ir_node *node, be_verify_register_allocation_env_t *env) {
669         const arch_env_t      *arch_env = env->arch_env;
670         const arch_register_t *reg;
671         int                   i, arity;
672
673         /* verify output register */
674         if (arch_get_irn_reg_class(arch_env, node, -1) != NULL) {
675                 reg = arch_get_irn_register(arch_env, node);
676                 if (reg == NULL) {
677                         ir_fprintf(stderr, "Verify warning: Node %+F in block %+F(%s) should have a register assigned\n",
678                                         node, get_nodes_block(node), get_irg_dump_name(env->irg));
679                         env->problem_found = 1;
680                 }
681                 else if (! arch_register_type_is(reg, joker) && !arch_reg_is_allocatable(arch_env, node, -1, reg)) {
682                         ir_fprintf(stderr, "Verify warning: Register %s assigned as output of %+F not allowed (register constraint) in block %+F(%s)\n",
683                                         reg->name, node, get_nodes_block(node), get_irg_dump_name(env->irg));
684                         env->problem_found = 1;
685                 }
686         }
687
688         /* verify input register */
689         arity = get_irn_arity(node);
690         for (i = 0; i < arity; ++i) {
691                 ir_node *pred = get_irn_n(node, i);
692
693                 if (is_Unknown(pred))
694                         continue;
695
696                 if (is_Bad(pred)) {
697                         ir_fprintf(stderr, "Verify warning: %+F in block %+F(%s) has Bad as input %d\n",
698                                 node, get_nodes_block(node), get_irg_dump_name(env->irg), i);
699                         env->problem_found = 1;
700                         continue;
701                 }
702
703                 if (arch_get_irn_reg_class(arch_env, node, i) == NULL)
704                         continue;
705
706                 reg = arch_get_irn_register(arch_env, pred);
707                 if (reg == NULL) {
708                         ir_fprintf(stderr, "Verify warning: Node %+F in block %+F(%s) should have a register assigned\n",
709                                    pred, get_nodes_block(pred), get_irg_dump_name(env->irg));
710                         env->problem_found = 1;
711                         continue;
712                 }
713                 else if (! arch_register_type_is(reg, joker) && ! arch_reg_is_allocatable(arch_env, node, i, reg)) {
714                         ir_fprintf(stderr, "Verify warning: Register %s as input %d of %+F not allowed (register constraint) in block %+F(%s)\n",
715                                    reg->name, i, node, get_nodes_block(node), get_irg_dump_name(env->irg));
716                         env->problem_found = 1;
717                 }
718         }
719 }
720
721 static void check_register_allocation(be_verify_register_allocation_env_t *env,
722                                       const arch_register_class_t *regclass, pset *nodes) {
723         const arch_env_t      *arch_env  = env->arch_env;
724         const arch_register_t *reg       = NULL;
725         int                   fail       = 0;
726         bitset_t              *registers = bitset_alloca(arch_register_class_n_regs(regclass));
727         ir_node               *node;
728
729         foreach_pset(nodes, node) {
730                 if (arch_get_irn_reg_class(arch_env, node, -1) != regclass)
731                         continue;
732
733                 reg = arch_get_irn_register(arch_env, node);
734
735                 /* this problem is already reported in 'check_register_constraints' */
736                 if (! reg)
737                         continue;
738
739                 if (bitset_is_set(registers, reg->index)) {
740                         pset_break(nodes);
741                         fail = 1;
742                         break;
743                 }
744                 bitset_set(registers, reg->index);
745         }
746
747         if (fail) {
748                 ir_fprintf(stderr, "Verify warning: Register %s assigned more than once in block %+F(%s)\n",
749                                reg->name, get_nodes_block(node), get_irg_dump_name(env->irg));
750                 env->problem_found = 1;
751
752                 foreach_pset(nodes, node) {
753                         if (arch_get_irn_register(arch_env, node) == reg) {
754                                 ir_fprintf(stderr, "  at node %+F\n", node);
755                         }
756                 }
757         }
758 }
759
760 static void verify_block_register_allocation(ir_node *block, void *data) {
761         be_verify_register_allocation_env_t *env = data;
762         const arch_env_t *arch_env = env->arch_env;
763         const arch_isa_t *isa = arch_env->isa;
764         int i, nregclasses;
765
766         nregclasses = arch_isa_get_n_reg_class(isa);
767         for (i = 0; i < nregclasses; ++i) {
768                 const arch_register_class_t *regclass = arch_isa_get_reg_class(isa, i);
769                 ir_node *node;
770                 pset *live_nodes = pset_new_ptr_default();
771
772                 be_liveness_end_of_block(env->lv, env->arch_env, regclass, block, live_nodes);
773                 check_register_allocation(env, regclass, live_nodes);
774
775                 sched_foreach_reverse(block, node) {
776                         if (is_Phi(node))
777                                 break;
778
779                         be_liveness_transfer(env->arch_env, regclass, node, live_nodes);
780                         check_register_allocation(env, regclass, live_nodes);
781                         check_register_constraints(node, env);
782                 }
783
784                 del_pset(live_nodes);
785         }
786 }
787
788 int be_verify_register_allocation(const arch_env_t *arch_env, ir_graph *irg) {
789         be_verify_register_allocation_env_t env;
790
791         env.arch_env = arch_env;
792         env.irg = irg;
793         env.lv = be_liveness(irg);
794         env.problem_found = 0;
795
796         irg_block_walk_graph(irg, verify_block_register_allocation, NULL, &env);
797
798         be_liveness_free(env.lv);
799
800         return !env.problem_found;
801 }
802
803
804
805 //---------------------------------------------------------------------------
806
807
808
809 typedef struct _verify_out_dead_nodes_env {
810         ir_graph *irg;
811         bitset_t *reachable;
812         int problem_found;
813 } verify_out_dead_nodes_env;
814
815 static void check_out_edges(ir_node *node, verify_out_dead_nodes_env *env) {
816         ir_graph *irg = env->irg;
817         const ir_edge_t* edge;
818
819         if(irn_visited(node))
820                 return;
821         mark_irn_visited(node);
822
823         foreach_out_edge(node, edge) {
824                 ir_node* src = get_edge_src_irn(edge);
825
826                 if(!bitset_is_set(env->reachable, get_irn_idx(src)) && !is_Block(node)) {
827                         ir_fprintf(stderr, "Verify warning: Node %+F in block %+F(%s) only reachable through out edges from %+F\n",
828                                    src, get_nodes_block(src), get_irg_dump_name(irg), node);
829                         env->problem_found = 1;
830                         continue;
831                 }
832
833                 check_out_edges(src, env);
834         }
835 }
836
837 static void set_reachable(ir_node *node, void* data)
838 {
839         bitset_t* reachable = data;
840         bitset_set(reachable, get_irn_idx(node));
841 }
842
843 int be_verify_out_edges(ir_graph *irg) {
844         verify_out_dead_nodes_env env;
845
846         env.irg           = irg;
847         env.reachable     = bitset_alloca(get_irg_last_idx(irg));
848         env.problem_found = edges_verify(irg);
849
850         irg_walk_in_or_dep_graph(irg, set_reachable, NULL, env.reachable);
851         irg_walk_anchors(irg, set_reachable, NULL, env.reachable);
852         inc_irg_visited(irg);
853         check_out_edges(get_irg_start(irg), &env);
854
855         return ! env.problem_found;
856 }