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