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