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