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 
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 
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 
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 
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 
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 
974