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