sel-sched.h, [...]: New files.
[gcc.git] / gcc / sel-sched-dump.c
1 /* Instruction scheduling pass. Log dumping infrastructure.
2 Copyright (C) 2006, 2007, 2008 Free Software Foundation, Inc.
3
4 This file is part of GCC.
5
6 GCC is free software; you can redistribute it and/or modify it under
7 the terms of the GNU General Public License as published by the Free
8 Software Foundation; either version 3, or (at your option) any later
9 version.
10
11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GCC; see the file COPYING3. If not see
18 <http://www.gnu.org/licenses/>. */
19
20 #include "config.h"
21 #include "system.h"
22 #include "coretypes.h"
23 #include "tm.h"
24 #include "toplev.h"
25 #include "rtl.h"
26 #include "tm_p.h"
27 #include "hard-reg-set.h"
28 #include "regs.h"
29 #include "function.h"
30 #include "flags.h"
31 #include "insn-config.h"
32 #include "insn-attr.h"
33 #include "params.h"
34 #include "output.h"
35 #include "basic-block.h"
36 #include "cselib.h"
37 #include "sel-sched-ir.h"
38 #include "sel-sched-dump.h"
39 \f
40
41 /* These variables control high-level pretty printing. */
42 static int sel_dump_cfg_flags = SEL_DUMP_CFG_FLAGS;
43 static int sel_debug_cfg_flags = SEL_DUMP_CFG_FLAGS;
44
45 /* True when a cfg should be dumped. */
46 static bool sel_dump_cfg_p;
47
48 /* Variables that are used to build the cfg dump file name. */
49 static const char * const sel_debug_cfg_root = "./";
50 static const char * const sel_debug_cfg_root_postfix_default = "";
51 static const char *sel_debug_cfg_root_postfix = "";
52 static int sel_dump_cfg_fileno = -1;
53 static int sel_debug_cfg_fileno = -1;
54
55 /* When this flag is on, we are dumping to the .dot file.
56 When it is off, we are dumping to log.
57 This is useful to differentiate formatting between log and .dot
58 files. */
59 bool sched_dump_to_dot_p = false;
60
61 /* Controls how insns from a fence list should be dumped. */
62 static int dump_flist_insn_flags = (DUMP_INSN_UID | DUMP_INSN_BBN
63 | DUMP_INSN_SEQNO);
64 \f
65
66 /* The variable used to hold the value of sched_dump when temporarily
67 switching dump output to the other source, e.g. the .dot file. */
68 static FILE *saved_sched_dump = NULL;
69
70 /* Switch sched_dump to TO. It must not be called twice. */
71 static void
72 switch_dump (FILE *to)
73 {
74 gcc_assert (saved_sched_dump == NULL);
75
76 saved_sched_dump = sched_dump;
77 sched_dump = to;
78 }
79
80 /* Restore previously switched dump. */
81 static void
82 restore_dump (void)
83 {
84 sched_dump = saved_sched_dump;
85 saved_sched_dump = NULL;
86 }
87 \f
88
89 /* Functions for dumping instructions, av sets, and exprs. */
90
91 /* Default flags for dumping insns. */
92 static int dump_insn_rtx_flags = DUMP_INSN_RTX_PATTERN;
93
94 /* Default flags for dumping vinsns. */
95 static int dump_vinsn_flags = (DUMP_VINSN_INSN_RTX | DUMP_VINSN_TYPE
96 | DUMP_VINSN_COUNT);
97
98 /* Default flags for dumping expressions. */
99 static int dump_expr_flags = DUMP_EXPR_ALL;
100
101 /* Default flags for dumping insns when debugging. */
102 static int debug_insn_rtx_flags = DUMP_INSN_RTX_ALL;
103
104 /* Default flags for dumping vinsns when debugging. */
105 static int debug_vinsn_flags = DUMP_VINSN_ALL;
106
107 /* Default flags for dumping expressions when debugging. */
108 static int debug_expr_flags = DUMP_EXPR_ALL;
109
110 /* Controls how an insn from stream should be dumped when debugging. */
111 static int debug_insn_flags = DUMP_INSN_ALL;
112
113 /* Print an rtx X. */
114 void
115 sel_print_rtl (rtx x)
116 {
117 print_rtl_single (sched_dump, x);
118 }
119
120 /* Dump insn INSN honoring FLAGS. */
121 void
122 dump_insn_rtx_1 (rtx insn, int flags)
123 {
124 int all;
125
126 /* flags == -1 also means dumping all. */
127 all = (flags & 1);;
128 if (all)
129 flags |= DUMP_INSN_RTX_ALL;
130
131 sel_print ("(");
132
133 if (flags & DUMP_INSN_RTX_UID)
134 sel_print ("%d;", INSN_UID (insn));
135
136 if (flags & DUMP_INSN_RTX_PATTERN)
137 {
138 char buf[2048];
139
140 print_insn (buf, insn, 0);
141 sel_print ("%s;", buf);
142 }
143
144 if (flags & DUMP_INSN_RTX_BBN)
145 {
146 basic_block bb = BLOCK_FOR_INSN (insn);
147
148 sel_print ("bb:%d;", bb != NULL ? bb->index : -1);
149 }
150
151 sel_print (")");
152 }
153
154
155 /* Dump INSN with default flags. */
156 void
157 dump_insn_rtx (rtx insn)
158 {
159 dump_insn_rtx_1 (insn, dump_insn_rtx_flags);
160 }
161
162
163 /* Dump INSN to stderr. */
164 void
165 debug_insn_rtx (rtx insn)
166 {
167 switch_dump (stderr);
168 dump_insn_rtx_1 (insn, debug_insn_rtx_flags);
169 sel_print ("\n");
170 restore_dump ();
171 }
172
173 /* Dump vinsn VI honoring flags. */
174 void
175 dump_vinsn_1 (vinsn_t vi, int flags)
176 {
177 int all;
178
179 /* flags == -1 also means dumping all. */
180 all = flags & 1;
181 if (all)
182 flags |= DUMP_VINSN_ALL;
183
184 sel_print ("(");
185
186 if (flags & DUMP_VINSN_INSN_RTX)
187 dump_insn_rtx_1 (VINSN_INSN_RTX (vi), dump_insn_rtx_flags | all);
188
189 if (flags & DUMP_VINSN_TYPE)
190 sel_print ("type:%s;", GET_RTX_NAME (VINSN_TYPE (vi)));
191
192 if (flags & DUMP_VINSN_COUNT)
193 sel_print ("count:%d;", VINSN_COUNT (vi));
194
195 if (flags & DUMP_VINSN_COST)
196 {
197 int cost = vi->cost;
198
199 if (cost != -1)
200 sel_print ("cost:%d;", cost);
201 }
202
203 sel_print (")");
204 }
205
206 /* Dump vinsn VI with default flags. */
207 void
208 dump_vinsn (vinsn_t vi)
209 {
210 dump_vinsn_1 (vi, dump_vinsn_flags);
211 }
212
213 /* Dump vinsn VI to stderr. */
214 void
215 debug_vinsn (vinsn_t vi)
216 {
217 switch_dump (stderr);
218 dump_vinsn_1 (vi, debug_vinsn_flags);
219 sel_print ("\n");
220 restore_dump ();
221 }
222
223 /* Dump EXPR honoring flags. */
224 void
225 dump_expr_1 (expr_t expr, int flags)
226 {
227 int all;
228
229 /* flags == -1 also means dumping all. */
230 all = flags & 1;
231 if (all)
232 flags |= DUMP_EXPR_ALL;
233
234 sel_print ("[");
235
236 if (flags & DUMP_EXPR_VINSN)
237 dump_vinsn_1 (EXPR_VINSN (expr), dump_vinsn_flags | all);
238
239 if (flags & DUMP_EXPR_SPEC)
240 {
241 int spec = EXPR_SPEC (expr);
242
243 if (spec != 0)
244 sel_print ("spec:%d;", spec);
245 }
246
247 if (flags & DUMP_EXPR_USEFULNESS)
248 {
249 int use = EXPR_USEFULNESS (expr);
250
251 if (use != REG_BR_PROB_BASE)
252 sel_print ("use:%d;", use);
253 }
254
255 if (flags & DUMP_EXPR_PRIORITY)
256 sel_print ("prio:%d;", EXPR_PRIORITY (expr));
257
258 if (flags & DUMP_EXPR_SCHED_TIMES)
259 {
260 int times = EXPR_SCHED_TIMES (expr);
261
262 if (times != 0)
263 sel_print ("times:%d;", times);
264 }
265
266 if (flags & DUMP_EXPR_SPEC_DONE_DS)
267 {
268 ds_t spec_done_ds = EXPR_SPEC_DONE_DS (expr);
269
270 if (spec_done_ds != 0)
271 sel_print ("ds:%d;", spec_done_ds);
272 }
273
274 if (flags & DUMP_EXPR_ORIG_BB)
275 {
276 int orig_bb = EXPR_ORIG_BB_INDEX (expr);
277
278 if (orig_bb != 0)
279 sel_print ("orig_bb:%d;", orig_bb);
280 }
281
282 if (EXPR_TARGET_AVAILABLE (expr) < 1)
283 sel_print ("target:%d;", EXPR_TARGET_AVAILABLE (expr));
284 sel_print ("]");
285 }
286
287 /* Dump expression EXPR with default flags. */
288 void
289 dump_expr (expr_t expr)
290 {
291 dump_expr_1 (expr, dump_expr_flags);
292 }
293
294 /* Dump expression EXPR to stderr. */
295 void
296 debug_expr (expr_t expr)
297 {
298 switch_dump (stderr);
299 dump_expr_1 (expr, debug_expr_flags);
300 sel_print ("\n");
301 restore_dump ();
302 }
303
304 /* Dump insn I honoring FLAGS. */
305 void
306 dump_insn_1 (insn_t i, int flags)
307 {
308 int all;
309
310 all = flags & 1;
311 if (all)
312 flags |= DUMP_INSN_ALL;
313
314 if (!sched_dump_to_dot_p)
315 sel_print ("(");
316
317 if (flags & DUMP_INSN_EXPR)
318 {
319 dump_expr_1 (INSN_EXPR (i), dump_expr_flags | all);
320 sel_print (";");
321 }
322 else if (flags & DUMP_INSN_PATTERN)
323 {
324 dump_insn_rtx_1 (i, DUMP_INSN_RTX_PATTERN | all);
325 sel_print (";");
326 }
327 else if (flags & DUMP_INSN_UID)
328 sel_print ("uid:%d;", INSN_UID (i));
329
330 if (flags & DUMP_INSN_SEQNO)
331 sel_print ("seqno:%d;", INSN_SEQNO (i));
332
333 if (flags & DUMP_INSN_SCHED_CYCLE)
334 {
335 int cycle = INSN_SCHED_CYCLE (i);
336
337 if (cycle != 0)
338 sel_print ("cycle:%d;", cycle);
339 }
340
341 if (!sched_dump_to_dot_p)
342 sel_print (")");
343 }
344
345 /* Dump insn I with default flags. */
346 void
347 dump_insn (insn_t i)
348 {
349 dump_insn_1 (i, DUMP_INSN_EXPR | DUMP_INSN_SCHED_CYCLE);
350 }
351
352 /* Dump INSN to stderr. */
353 void
354 debug_insn (insn_t insn)
355 {
356 switch_dump (stderr);
357 dump_insn_1 (insn, debug_insn_flags);
358 sel_print ("\n");
359 restore_dump ();
360 }
361
362 /* Dumps av_set AV. */
363 void
364 dump_av_set (av_set_t av)
365 {
366 av_set_iterator i;
367 expr_t expr;
368
369 if (!sched_dump_to_dot_p)
370 sel_print ("{");
371
372 FOR_EACH_EXPR (expr, i, av)
373 {
374 dump_expr (expr);
375 if (!sched_dump_to_dot_p)
376 sel_print (" ");
377 else
378 sel_print ("\n");
379 }
380
381 if (!sched_dump_to_dot_p)
382 sel_print ("}");
383 }
384
385 /* Dumps lvset LV. */
386 void
387 dump_lv_set (regset lv)
388 {
389 sel_print ("{");
390
391 /* This code was adapted from flow.c: dump_regset (). */
392 if (lv == NULL)
393 sel_print ("nil");
394 else
395 {
396 unsigned i;
397 reg_set_iterator rsi;
398 int count = 0;
399
400 EXECUTE_IF_SET_IN_REG_SET (lv, 0, i, rsi)
401 {
402 sel_print (" %d", i);
403 if (i < FIRST_PSEUDO_REGISTER)
404 {
405 sel_print (" [%s]", reg_names[i]);
406 ++count;
407 }
408
409 ++count;
410
411 if (sched_dump_to_dot_p && count == 12)
412 {
413 count = 0;
414 sel_print ("\n");
415 }
416 }
417 }
418
419 sel_print ("}\n");
420 }
421
422 /* Dumps a list of instructions pointed to by P. */
423 static void
424 dump_ilist (ilist_t p)
425 {
426 while (p)
427 {
428 dump_insn (ILIST_INSN (p));
429 p = ILIST_NEXT (p);
430 }
431 }
432
433 /* Dumps a list of boundaries pointed to by BNDS. */
434 void
435 dump_blist (blist_t bnds)
436 {
437 for (; bnds; bnds = BLIST_NEXT (bnds))
438 {
439 bnd_t bnd = BLIST_BND (bnds);
440
441 sel_print ("[to: %d; ptr: ", INSN_UID (BND_TO (bnd)));
442 dump_ilist (BND_PTR (bnd));
443 sel_print ("] ");
444 }
445 }
446
447 /* Dumps a list of fences pointed to by L. */
448 void
449 dump_flist (flist_t l)
450 {
451 while (l)
452 {
453 dump_insn_1 (FENCE_INSN (FLIST_FENCE (l)), dump_flist_insn_flags);
454 sel_print (" ");
455 l = FLIST_NEXT (l);
456 }
457 }
458
459 /* Dumps an insn vector SUCCS. */
460 void
461 dump_insn_vector (rtx_vec_t succs)
462 {
463 int i;
464 rtx succ;
465
466 for (i = 0; VEC_iterate (rtx, succs, i, succ); i++)
467 if (succ)
468 dump_insn (succ);
469 else
470 sel_print ("NULL ");
471 }
472
473 /* Dumps a hard reg set SET to FILE using PREFIX. */
474 static void
475 print_hard_reg_set (FILE *file, const char *prefix, HARD_REG_SET set)
476 {
477 int i;
478
479 fprintf (file, "%s{ ", prefix);
480 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
481 {
482 if (TEST_HARD_REG_BIT (set, i))
483 fprintf (file, "%d ", i);
484 }
485 fprintf (file, "}\n");
486 }
487
488 /* Dumps a hard reg set SET using PREFIX. */
489 void
490 dump_hard_reg_set (const char *prefix, HARD_REG_SET set)
491 {
492 print_hard_reg_set (sched_dump, prefix, set);
493 }
494
495 /* Pretty print INSN. This is used as a hook. */
496 const char *
497 sel_print_insn (const_rtx insn, int aligned ATTRIBUTE_UNUSED)
498 {
499 static char buf[80];
500
501 /* '+' before insn means it is a new cycle start and it's not been
502 scheduled yet. '>' - has been scheduled. */
503 if (s_i_d && INSN_LUID (insn) > 0)
504 if (GET_MODE (insn) == TImode)
505 sprintf (buf, "%s %4d",
506 INSN_SCHED_TIMES (insn) > 0 ? "> " : "< ",
507 INSN_UID (insn));
508 else
509 sprintf (buf, "%s %4d",
510 INSN_SCHED_TIMES (insn) > 0 ? "! " : " ",
511 INSN_UID (insn));
512 else
513 if (GET_MODE (insn) == TImode)
514 sprintf (buf, "+ %4d", INSN_UID (insn));
515 else
516 sprintf (buf, " %4d", INSN_UID (insn));
517
518 return buf;
519 }
520 \f
521
522 /* Functions for pretty printing of CFG. */
523
524 /* Replace all occurencies of STR1 to STR2 in BUF.
525 The BUF must be large enough to hold the result. */
526 static void
527 replace_str_in_buf (char *buf, const char *str1, const char *str2)
528 {
529 int buf_len = strlen (buf);
530 int str1_len = strlen (str1);
531 int str2_len = strlen (str2);
532 int diff = str2_len - str1_len;
533
534 char *p = buf;
535 do
536 {
537 p = strstr (p, str1);
538 if (p)
539 {
540 char *p1 = p + str1_len;
541 /* Copy the rest of buf and '\0'. */
542 int n = buf + buf_len - p1;
543 int i;
544
545 /* Shift str by DIFF chars. */
546 if (diff > 0)
547 for (i = n; i >= 0; i--)
548 p1[i + diff] = p1[i];
549 else
550 for (i = 0; i <= n; i++)
551 p1[i + diff] = p1[i];
552
553 /* Copy str2. */
554 for (i = 0; i < str2_len; i++)
555 p[i] = str2[i];
556
557 p += str2_len;
558 buf_len += diff;
559 }
560
561 }
562 while (p);
563 }
564
565 /* Replace characters in BUF that have special meaning in .dot file. */
566 void
567 sel_prepare_string_for_dot_label (char *buf)
568 {
569 static char specials_from[7][2] = { "<", ">", "{", "|", "}", "\"",
570 "\n" };
571 static char specials_to[7][3] = { "\\<", "\\>", "\\{", "\\|", "\\}",
572 "\\\"", "\\l" };
573 unsigned i;
574
575 for (i = 0; i < 7; i++)
576 replace_str_in_buf (buf, specials_from[i], specials_to[i]);
577 }
578
579 /* Dump INSN with FLAGS. */
580 static void
581 sel_dump_cfg_insn (insn_t insn, int flags)
582 {
583 int insn_flags = DUMP_INSN_UID | DUMP_INSN_PATTERN;
584
585 if (sched_luids != NULL && INSN_LUID (insn) > 0)
586 {
587 if (flags & SEL_DUMP_CFG_INSN_SEQNO)
588 insn_flags |= DUMP_INSN_SEQNO | DUMP_INSN_SCHED_CYCLE | DUMP_INSN_EXPR;
589 }
590
591 dump_insn_1 (insn, insn_flags);
592 }
593
594 /* Dump E to the dot file F. */
595 static void
596 sel_dump_cfg_edge (FILE *f, edge e)
597 {
598 int w;
599 const char *color;
600
601 if (e->flags & EDGE_FALLTHRU)
602 {
603 w = 10;
604 color = ", color = red";
605 }
606 else if (e->src->next_bb == e->dest)
607 {
608 w = 3;
609 color = ", color = blue";
610 }
611 else
612 {
613 w = 1;
614 color = "";
615 }
616
617 fprintf (f, "\tbb%d -> bb%d [weight = %d%s];\n",
618 e->src->index, e->dest->index, w, color);
619 }
620
621
622 /* Return true if BB has a predesessor from current region.
623 TODO: Either make this function to trace back through empty block
624 or just remove those empty blocks. */
625 static bool
626 has_preds_in_current_region_p (basic_block bb)
627 {
628 edge e;
629 edge_iterator ei;
630
631 gcc_assert (!in_current_region_p (bb));
632
633 FOR_EACH_EDGE (e, ei, bb->preds)
634 if (in_current_region_p (e->src))
635 return true;
636
637 return false;
638 }
639
640 /* Dump a cfg region to the dot file F honoring FLAGS. */
641 static void
642 sel_dump_cfg_2 (FILE *f, int flags)
643 {
644 basic_block bb;
645
646 sched_dump_to_dot_p = true;
647 switch_dump (f);
648
649 fprintf (f, "digraph G {\n"
650 "\tratio = 2.25;\n"
651 "\tnode [shape = record, fontsize = 9];\n");
652
653 if (flags & SEL_DUMP_CFG_FUNCTION_NAME)
654 fprintf (f, "function [label = \"%s\"];\n", current_function_name ());
655
656 FOR_EACH_BB (bb)
657 {
658 insn_t insn = BB_HEAD (bb);
659 insn_t next_tail = NEXT_INSN (BB_END (bb));
660 edge e;
661 edge_iterator ei;
662 bool in_region_p = ((flags & SEL_DUMP_CFG_CURRENT_REGION)
663 && in_current_region_p (bb));
664 bool full_p = (!(flags & SEL_DUMP_CFG_CURRENT_REGION)
665 || in_region_p);
666 bool some_p = full_p || has_preds_in_current_region_p (bb);
667 const char *color;
668 const char *style;
669
670 if (!some_p)
671 continue;
672
673 if ((flags & SEL_DUMP_CFG_CURRENT_REGION)
674 && in_current_region_p (bb)
675 && BLOCK_TO_BB (bb->index) == 0)
676 color = "color = green, ";
677 else
678 color = "";
679
680 if ((flags & SEL_DUMP_CFG_FENCES)
681 && in_region_p)
682 {
683 style = "";
684
685 if (!sel_bb_empty_p (bb))
686 {
687 bool first_p = true;
688 insn_t tail = BB_END (bb);
689 insn_t cur_insn;
690
691 cur_insn = bb_note (bb);
692
693 do
694 {
695 fence_t fence;
696
697 cur_insn = NEXT_INSN (cur_insn);
698 fence = flist_lookup (fences, cur_insn);
699
700 if (fence != NULL)
701 {
702 if (!FENCE_SCHEDULED_P (fence))
703 {
704 if (first_p)
705 color = "color = red, ";
706 else
707 color = "color = yellow, ";
708 }
709 else
710 color = "color = blue, ";
711 }
712
713 first_p = false;
714 }
715 while (cur_insn != tail);
716 }
717 }
718 else if (!full_p)
719 style = "style = dashed, ";
720 else
721 style = "";
722
723 fprintf (f, "\tbb%d [%s%slabel = \"{Basic block %d", bb->index,
724 style, color, bb->index);
725
726 if ((flags & SEL_DUMP_CFG_BB_LOOP)
727 && bb->loop_father != NULL)
728 fprintf (f, ", loop %d", bb->loop_father->num);
729
730 if (full_p
731 && (flags & SEL_DUMP_CFG_BB_NOTES_LIST))
732 {
733 insn_t notes = BB_NOTE_LIST (bb);
734
735 if (notes != NULL_RTX)
736 {
737 fprintf (f, "|");
738
739 /* For simplicity, we dump notes from note_list in reversed order
740 to that what they will appear in the code. */
741 while (notes != NULL_RTX)
742 {
743 sel_dump_cfg_insn (notes, flags);
744 fprintf (f, "\\l");
745
746 notes = PREV_INSN (notes);
747 }
748 }
749 }
750
751 if (full_p
752 && (flags & SEL_DUMP_CFG_AV_SET)
753 && in_current_region_p (bb)
754 && !sel_bb_empty_p (bb))
755 {
756 fprintf (f, "|");
757
758 if (BB_AV_SET_VALID_P (bb))
759 dump_av_set (BB_AV_SET (bb));
760 else if (BB_AV_LEVEL (bb) == -1)
761 fprintf (f, "AV_SET needs update");
762 }
763
764 if ((flags & SEL_DUMP_CFG_LV_SET)
765 && !sel_bb_empty_p (bb))
766 {
767 fprintf (f, "|");
768
769 if (BB_LV_SET_VALID_P (bb))
770 dump_lv_set (BB_LV_SET (bb));
771 else
772 fprintf (f, "LV_SET needs update");
773 }
774
775 if (full_p
776 && (flags & SEL_DUMP_CFG_BB_INSNS))
777 {
778 fprintf (f, "|");
779 while (insn != next_tail)
780 {
781 sel_dump_cfg_insn (insn, flags);
782 fprintf (f, "\\l");
783
784 insn = NEXT_INSN (insn);
785 }
786 }
787
788 fprintf (f, "}\"];\n");
789
790 FOR_EACH_EDGE (e, ei, bb->succs)
791 if (full_p || in_current_region_p (e->dest))
792 sel_dump_cfg_edge (f, e);
793 }
794
795 fprintf (f, "}");
796
797 restore_dump ();
798 sched_dump_to_dot_p = false;
799 }
800
801 /* Dump a cfg region to the file specified by TAG honoring flags.
802 The file is created by the function. */
803 static void
804 sel_dump_cfg_1 (const char *tag, int flags)
805 {
806 char *buf;
807 int i;
808 FILE *f;
809
810 ++sel_dump_cfg_fileno;
811
812 if (!sel_dump_cfg_p)
813 return;
814
815 i = 1 + snprintf (NULL, 0, "%s/%s%05d-%s.dot", sel_debug_cfg_root,
816 sel_debug_cfg_root_postfix, sel_dump_cfg_fileno, tag);
817 buf = XNEWVEC (char, i);
818 snprintf (buf, i, "%s/%s%05d-%s.dot", sel_debug_cfg_root,
819 sel_debug_cfg_root_postfix, sel_dump_cfg_fileno, tag);
820
821 f = fopen (buf, "w");
822
823 if (f == NULL)
824 fprintf (stderr, "Can't create file: %s.\n", buf);
825 else
826 {
827 sel_dump_cfg_2 (f, flags);
828
829 fclose (f);
830 }
831
832 free (buf);
833 }
834
835 /* Setup cfg dumping flags. Used for debugging. */
836 void
837 setup_dump_cfg_params (void)
838 {
839 sel_dump_cfg_flags = SEL_DUMP_CFG_FLAGS;
840 sel_dump_cfg_p = 0;
841 sel_debug_cfg_root_postfix = sel_debug_cfg_root_postfix_default;
842 }
843
844 /* Debug a cfg region with FLAGS. */
845 void
846 sel_debug_cfg_1 (int flags)
847 {
848 bool t1 = sel_dump_cfg_p;
849 int t2 = sel_dump_cfg_fileno;
850
851 sel_dump_cfg_p = true;
852 sel_dump_cfg_fileno = ++sel_debug_cfg_fileno;
853
854 sel_dump_cfg_1 ("sel-debug-cfg", flags);
855
856 sel_dump_cfg_fileno = t2;
857 sel_dump_cfg_p = t1;
858 }
859 \f
860 /* Dumps av_set AV to stderr. */
861 void
862 debug_av_set (av_set_t av)
863 {
864 switch_dump (stderr);
865 dump_av_set (av);
866 sel_print ("\n");
867 restore_dump ();
868 }
869
870 /* Dump LV to stderr. */
871 void
872 debug_lv_set (regset lv)
873 {
874 switch_dump (stderr);
875 dump_lv_set (lv);
876 sel_print ("\n");
877 restore_dump ();
878 }
879
880 /* Dump an instruction list P to stderr. */
881 void
882 debug_ilist (ilist_t p)
883 {
884 switch_dump (stderr);
885 dump_ilist (p);
886 sel_print ("\n");
887 restore_dump ();
888 }
889
890 /* Dump a boundary list BNDS to stderr. */
891 void
892 debug_blist (blist_t bnds)
893 {
894 switch_dump (stderr);
895 dump_blist (bnds);
896 sel_print ("\n");
897 restore_dump ();
898 }
899
900 /* Dump an insn vector SUCCS. */
901 void
902 debug_insn_vector (rtx_vec_t succs)
903 {
904 switch_dump (stderr);
905 dump_insn_vector (succs);
906 sel_print ("\n");
907 restore_dump ();
908 }
909
910 /* Dump a hard reg set SET to stderr. */
911 void
912 debug_hard_reg_set (HARD_REG_SET set)
913 {
914 switch_dump (stderr);
915 dump_hard_reg_set ("", set);
916 sel_print ("\n");
917 restore_dump ();
918 }
919
920 /* Debug a cfg region with default flags. */
921 void
922 sel_debug_cfg (void)
923 {
924 sel_debug_cfg_1 (sel_debug_cfg_flags);
925 }
926
927 /* Print a current cselib value for X's address to stderr. */
928 rtx
929 debug_mem_addr_value (rtx x)
930 {
931 rtx t, addr;
932
933 gcc_assert (MEM_P (x));
934 t = shallow_copy_rtx (x);
935 if (cselib_lookup (XEXP (t, 0), Pmode, 0))
936 XEXP (t, 0) = cselib_subst_to_values (XEXP (t, 0));
937
938 t = canon_rtx (t);
939 addr = get_addr (XEXP (t, 0));
940 debug_rtx (t);
941 debug_rtx (addr);
942 return t;
943 }
944
945