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