OSDN Git Service

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