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