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