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