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