OSDN Git Service

gcc:
[pf3gnuchains/gcc-fork.git] / gcc / sel-sched-dump.c
1 /* Instruction scheduling pass.   Log dumping infrastructure.
2    Copyright (C) 2006, 2007, 2008 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 "toplev.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 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 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 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 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 (i = 0; VEC_iterate (rtx, succs, i, succ); i++)
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 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 /* Dump INSN with FLAGS.  */
583 static void
584 sel_dump_cfg_insn (insn_t insn, int flags)
585 {
586   int insn_flags = DUMP_INSN_UID | DUMP_INSN_PATTERN;
587
588   if (sched_luids != NULL && INSN_LUID (insn) > 0)
589     {
590       if (flags & SEL_DUMP_CFG_INSN_SEQNO)
591         insn_flags |= DUMP_INSN_SEQNO | DUMP_INSN_SCHED_CYCLE | DUMP_INSN_EXPR;
592     }
593
594   dump_insn_1 (insn, insn_flags);
595 }
596
597 /* Dump E to the dot file F.  */
598 static void
599 sel_dump_cfg_edge (FILE *f, edge e)
600 {
601   int w;
602   const char *color;
603
604   if (e->flags & EDGE_FALLTHRU)
605     {
606       w = 10;
607       color = ", color = red";
608     }
609   else if (e->src->next_bb == e->dest)
610     {
611       w = 3;
612       color = ", color = blue";
613     }
614   else
615     {
616       w = 1;
617       color = "";
618     }
619
620   fprintf (f, "\tbb%d -> bb%d [weight = %d%s];\n",
621            e->src->index, e->dest->index, w, color);
622 }
623
624
625 /* Return true if BB has a predesessor from current region.
626    TODO: Either make this function to trace back through empty block
627    or just remove those empty blocks.  */
628 static bool
629 has_preds_in_current_region_p (basic_block bb)
630 {
631   edge e;
632   edge_iterator ei;
633
634   gcc_assert (!in_current_region_p (bb));
635
636   FOR_EACH_EDGE (e, ei, bb->preds)
637     if (in_current_region_p (e->src))
638       return true;
639
640   return false;
641 }
642
643 /* Dump a cfg region to the dot file F honoring FLAGS.  */
644 static void
645 sel_dump_cfg_2 (FILE *f, int flags)
646 {
647   basic_block bb;
648
649   sched_dump_to_dot_p = true;
650   switch_dump (f);
651
652   fprintf (f, "digraph G {\n"
653            "\tratio = 2.25;\n"
654            "\tnode [shape = record, fontsize = 9];\n");
655
656   if (flags & SEL_DUMP_CFG_FUNCTION_NAME)
657     fprintf (f, "function [label = \"%s\"];\n", current_function_name ());
658
659   FOR_EACH_BB (bb)
660     {
661       insn_t insn = BB_HEAD (bb);
662       insn_t next_tail = NEXT_INSN (BB_END (bb));
663       edge e;
664       edge_iterator ei;
665       bool in_region_p = ((flags & SEL_DUMP_CFG_CURRENT_REGION)
666                           && in_current_region_p (bb));
667       bool full_p = (!(flags & SEL_DUMP_CFG_CURRENT_REGION)
668                      || in_region_p);
669       bool some_p = full_p || has_preds_in_current_region_p (bb);
670       const char *color;
671       const char *style;
672
673       if (!some_p)
674         continue;
675
676       if ((flags & SEL_DUMP_CFG_CURRENT_REGION)
677           && in_current_region_p (bb)
678           && BLOCK_TO_BB (bb->index) == 0)
679         color = "color = green, ";
680       else
681         color = "";
682
683       if ((flags & SEL_DUMP_CFG_FENCES)
684           && in_region_p)
685         {
686           style = "";
687
688           if (!sel_bb_empty_p (bb))
689             {
690               bool first_p = true;
691               insn_t tail = BB_END (bb);
692               insn_t cur_insn;
693
694               cur_insn = bb_note (bb);
695
696               do
697                 {
698                   fence_t fence;
699
700                   cur_insn = NEXT_INSN (cur_insn);
701                   fence = flist_lookup (fences, cur_insn);
702
703                   if (fence != NULL)
704                     {
705                       if (!FENCE_SCHEDULED_P (fence))
706                         {
707                           if (first_p)
708                             color = "color = red, ";
709                           else
710                             color = "color = yellow, ";
711                         }
712                       else
713                         color = "color = blue, ";
714                     }
715
716                   first_p = false;
717                 }
718               while (cur_insn != tail);
719             }
720         }
721       else if (!full_p)
722         style = "style = dashed, ";
723       else
724         style = "";
725
726       fprintf (f, "\tbb%d [%s%slabel = \"{Basic block %d", bb->index,
727                style, color, bb->index);
728
729       if ((flags & SEL_DUMP_CFG_BB_LOOP)
730           && bb->loop_father != NULL)
731         fprintf (f, ", loop %d", bb->loop_father->num);
732
733       if (full_p
734           && (flags & SEL_DUMP_CFG_BB_NOTES_LIST))
735         {
736           insn_t notes = BB_NOTE_LIST (bb);
737
738           if (notes != NULL_RTX)
739             {
740               fprintf (f, "|");
741
742               /* For simplicity, we dump notes from note_list in reversed order
743                  to that what they will appear in the code.  */
744               while (notes != NULL_RTX)
745                 {
746                   sel_dump_cfg_insn (notes, flags);
747                   fprintf (f, "\\l");
748
749                   notes = PREV_INSN (notes);
750                 }
751             }
752         }
753
754       if (full_p
755           && (flags & SEL_DUMP_CFG_AV_SET)
756           && in_current_region_p (bb)
757           && !sel_bb_empty_p (bb))
758         {
759           fprintf (f, "|");
760
761           if (BB_AV_SET_VALID_P (bb))
762             dump_av_set (BB_AV_SET (bb));
763           else if (BB_AV_LEVEL (bb) == -1)
764             fprintf (f, "AV_SET needs update");
765         }
766
767       if ((flags & SEL_DUMP_CFG_LV_SET)
768           && !sel_bb_empty_p (bb))
769         {
770           fprintf (f, "|");
771
772           if (BB_LV_SET_VALID_P (bb))
773             dump_lv_set (BB_LV_SET (bb));
774           else
775             fprintf (f, "LV_SET needs update");
776         }
777
778       if (full_p
779           && (flags & SEL_DUMP_CFG_BB_INSNS))
780         {
781           fprintf (f, "|");
782           while (insn != next_tail)
783             {
784               sel_dump_cfg_insn (insn, flags);
785               fprintf (f, "\\l");
786
787               insn = NEXT_INSN (insn);
788             }
789         }
790
791       fprintf (f, "}\"];\n");
792
793       FOR_EACH_EDGE (e, ei, bb->succs)
794         if (full_p || in_current_region_p (e->dest))
795           sel_dump_cfg_edge (f, e);
796     }
797
798   fprintf (f, "}");
799
800   restore_dump ();
801   sched_dump_to_dot_p = false;
802 }
803
804 /* Dump a cfg region to the file specified by TAG honoring flags.
805    The file is created by the function.  */
806 static void
807 sel_dump_cfg_1 (const char *tag, int flags)
808 {
809   char *buf;
810   int i;
811   FILE *f;
812
813   ++sel_dump_cfg_fileno;
814
815   if (!sel_dump_cfg_p)
816     return;
817
818   i = 1 + snprintf (NULL, 0, "%s/%s%05d-%s.dot", sel_debug_cfg_root,
819                     sel_debug_cfg_root_postfix, sel_dump_cfg_fileno, tag);
820   buf = XNEWVEC (char, i);
821   snprintf (buf, i, "%s/%s%05d-%s.dot", sel_debug_cfg_root,
822             sel_debug_cfg_root_postfix, sel_dump_cfg_fileno, tag);
823
824   f = fopen (buf, "w");
825
826   if (f == NULL)
827     fprintf (stderr, "Can't create file: %s.\n", buf);
828   else
829     {
830       sel_dump_cfg_2 (f, flags);
831
832       fclose (f);
833     }
834
835   free (buf);
836 }
837
838 /* Setup cfg dumping flags.  Used for debugging.  */
839 void
840 setup_dump_cfg_params (void)
841 {
842   sel_dump_cfg_flags = SEL_DUMP_CFG_FLAGS;
843   sel_dump_cfg_p = 0;
844   sel_debug_cfg_root_postfix = sel_debug_cfg_root_postfix_default;
845 }
846
847 /* Debug a cfg region with FLAGS.  */
848 void
849 sel_debug_cfg_1 (int flags)
850 {
851   bool t1 = sel_dump_cfg_p;
852   int t2 = sel_dump_cfg_fileno;
853
854   sel_dump_cfg_p = true;
855   sel_dump_cfg_fileno = ++sel_debug_cfg_fileno;
856
857   sel_dump_cfg_1 ("sel-debug-cfg", flags);
858
859   sel_dump_cfg_fileno = t2;
860   sel_dump_cfg_p = t1;
861 }
862 \f
863 /* Dumps av_set AV to stderr.  */
864 void
865 debug_av_set (av_set_t av)
866 {
867   switch_dump (stderr);
868   dump_av_set (av);
869   sel_print ("\n");
870   restore_dump ();
871 }
872
873 /* Dump LV to stderr.  */
874 void
875 debug_lv_set (regset lv)
876 {
877   switch_dump (stderr);
878   dump_lv_set (lv);
879   sel_print ("\n");
880   restore_dump ();
881 }
882
883 /* Dump an instruction list P to stderr.  */
884 void
885 debug_ilist (ilist_t p)
886 {
887   switch_dump (stderr);
888   dump_ilist (p);
889   sel_print ("\n");
890   restore_dump ();
891 }
892
893 /* Dump a boundary list BNDS to stderr.  */
894 void
895 debug_blist (blist_t bnds)
896 {
897   switch_dump (stderr);
898   dump_blist (bnds);
899   sel_print ("\n");
900   restore_dump ();
901 }
902
903 /* Dump an insn vector SUCCS.  */
904 void
905 debug_insn_vector (rtx_vec_t succs)
906 {
907   switch_dump (stderr);
908   dump_insn_vector (succs);
909   sel_print ("\n");
910   restore_dump ();
911 }
912
913 /* Dump a hard reg set SET to stderr.  */
914 void
915 debug_hard_reg_set (HARD_REG_SET set)
916 {
917   switch_dump (stderr);
918   dump_hard_reg_set ("", set);
919   sel_print ("\n");
920   restore_dump ();
921 }
922
923 /* Debug a cfg region with default flags.  */
924 void
925 sel_debug_cfg (void)
926 {
927   sel_debug_cfg_1 (sel_debug_cfg_flags);
928 }
929
930 /* Print a current cselib value for X's address to stderr.  */
931 rtx
932 debug_mem_addr_value (rtx x)
933 {
934   rtx t, addr;
935   enum machine_mode address_mode;
936
937   gcc_assert (MEM_P (x));
938   address_mode = targetm.addr_space.address_mode (MEM_ADDR_SPACE (x));
939
940   t = shallow_copy_rtx (x);
941   if (cselib_lookup (XEXP (t, 0), address_mode, 0))
942     XEXP (t, 0) = cselib_subst_to_values (XEXP (t, 0));
943
944   t = canon_rtx (t);
945   addr = get_addr (XEXP (t, 0));
946   debug_rtx (t);
947   debug_rtx (addr);
948   return t;
949 }
950 #endif
951