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