2014-04-03 Richard Biener <rguenther@suse.de>
[official-gcc.git] / gcc / sel-sched-dump.c
blob97dcb9396eb9ab6084395e008a9eca383cc50a09
1 /* Instruction scheduling pass. Log dumping infrastructure.
2 Copyright (C) 2006-2014 Free Software Foundation, Inc.
4 This file is part of GCC.
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.
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.
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/>. */
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 "basic-block.h"
35 #include "cselib.h"
36 #include "target.h"
38 #ifdef INSN_SCHEDULING
39 #include "sel-sched-ir.h"
40 #include "sel-sched-dump.h"
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;
47 /* True when a cfg should be dumped. */
48 static bool sel_dump_cfg_p;
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;
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;
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);
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;
72 /* Switch sched_dump to TO. It must not be called twice. */
73 static void
74 switch_dump (FILE *to)
76 gcc_assert (saved_sched_dump == NULL);
78 saved_sched_dump = sched_dump;
79 sched_dump = to;
82 /* Restore previously switched dump. */
83 static void
84 restore_dump (void)
86 sched_dump = saved_sched_dump;
87 saved_sched_dump = NULL;
91 /* Functions for dumping instructions, av sets, and exprs. */
93 /* Default flags for dumping insns. */
94 static int dump_insn_rtx_flags = DUMP_INSN_RTX_UID | DUMP_INSN_RTX_PATTERN;
96 /* Default flags for dumping vinsns. */
97 static int dump_vinsn_flags = (DUMP_VINSN_INSN_RTX | DUMP_VINSN_TYPE
98 | DUMP_VINSN_COUNT);
100 /* Default flags for dumping expressions. */
101 static int dump_expr_flags = DUMP_EXPR_ALL;
103 /* Default flags for dumping insns when debugging. */
104 static int debug_insn_rtx_flags = DUMP_INSN_RTX_ALL;
106 /* Default flags for dumping vinsns when debugging. */
107 static int debug_vinsn_flags = DUMP_VINSN_ALL;
109 /* Default flags for dumping expressions when debugging. */
110 static int debug_expr_flags = DUMP_EXPR_ALL;
112 /* Controls how an insn from stream should be dumped when debugging. */
113 static int debug_insn_flags = DUMP_INSN_ALL;
115 /* Print an rtx X. */
116 void
117 sel_print_rtl (rtx x)
119 print_rtl_single (sched_dump, x);
122 /* Dump insn INSN honoring FLAGS. */
123 void
124 dump_insn_rtx_1 (rtx insn, int flags)
126 int all;
128 /* flags == -1 also means dumping all. */
129 all = (flags & 1);;
130 if (all)
131 flags |= DUMP_INSN_RTX_ALL;
133 sel_print ("(");
135 if (flags & DUMP_INSN_RTX_UID)
136 sel_print ("%d;", INSN_UID (insn));
138 if (flags & DUMP_INSN_RTX_PATTERN)
139 sel_print ("%s;", str_pattern_slim (PATTERN (insn)));
141 if (flags & DUMP_INSN_RTX_BBN)
143 basic_block bb = BLOCK_FOR_INSN (insn);
145 sel_print ("bb:%d;", bb != NULL ? bb->index : -1);
148 sel_print (")");
152 /* Dump INSN with default flags. */
153 void
154 dump_insn_rtx (rtx insn)
156 dump_insn_rtx_1 (insn, dump_insn_rtx_flags);
160 /* Dump INSN to stderr. */
161 DEBUG_FUNCTION void
162 debug_insn_rtx (rtx insn)
164 switch_dump (stderr);
165 dump_insn_rtx_1 (insn, debug_insn_rtx_flags);
166 sel_print ("\n");
167 restore_dump ();
170 /* Dump vinsn VI honoring flags. */
171 void
172 dump_vinsn_1 (vinsn_t vi, int flags)
174 int all;
176 /* flags == -1 also means dumping all. */
177 all = flags & 1;
178 if (all)
179 flags |= DUMP_VINSN_ALL;
181 sel_print ("(");
183 if (flags & DUMP_VINSN_INSN_RTX)
184 dump_insn_rtx_1 (VINSN_INSN_RTX (vi), dump_insn_rtx_flags | all);
186 if (flags & DUMP_VINSN_TYPE)
187 sel_print ("type:%s;", GET_RTX_NAME (VINSN_TYPE (vi)));
189 if (flags & DUMP_VINSN_COUNT)
190 sel_print ("count:%d;", VINSN_COUNT (vi));
192 if (flags & DUMP_VINSN_COST)
194 int cost = vi->cost;
196 if (cost != -1)
197 sel_print ("cost:%d;", cost);
200 sel_print (")");
203 /* Dump vinsn VI with default flags. */
204 void
205 dump_vinsn (vinsn_t vi)
207 dump_vinsn_1 (vi, dump_vinsn_flags);
210 DEBUG_FUNCTION void
211 debug (vinsn_def &ref)
213 switch_dump (stderr);
214 dump_vinsn_1 (&ref, dump_vinsn_flags);
215 sel_print ("\n");
216 restore_dump ();
219 DEBUG_FUNCTION void
220 debug (vinsn_def *ptr)
222 if (ptr)
223 debug (*ptr);
224 else
225 fprintf (stderr, "<nil>\n");
228 DEBUG_FUNCTION void
229 debug_verbose (vinsn_def &ref)
231 switch_dump (stderr);
232 dump_vinsn_1 (&ref, debug_vinsn_flags);
233 sel_print ("\n");
234 restore_dump ();
237 DEBUG_FUNCTION void
238 debug_verbose (vinsn_def *ptr)
240 if (ptr)
241 debug (*ptr);
242 else
243 fprintf (stderr, "<nil>\n");
246 /* Dump vinsn VI to stderr. */
247 DEBUG_FUNCTION void
248 debug_vinsn (vinsn_t vi)
250 switch_dump (stderr);
251 dump_vinsn_1 (vi, debug_vinsn_flags);
252 sel_print ("\n");
253 restore_dump ();
256 /* Dump EXPR honoring flags. */
257 void
258 dump_expr_1 (expr_t expr, int flags)
260 int all;
262 /* flags == -1 also means dumping all. */
263 all = flags & 1;
264 if (all)
265 flags |= DUMP_EXPR_ALL;
267 sel_print ("[");
269 if (flags & DUMP_EXPR_VINSN)
270 dump_vinsn_1 (EXPR_VINSN (expr), dump_vinsn_flags | all);
272 if (flags & DUMP_EXPR_SPEC)
274 int spec = EXPR_SPEC (expr);
276 if (spec != 0)
277 sel_print ("spec:%d;", spec);
280 if (flags & DUMP_EXPR_USEFULNESS)
282 int use = EXPR_USEFULNESS (expr);
284 if (use != REG_BR_PROB_BASE)
285 sel_print ("use:%d;", use);
288 if (flags & DUMP_EXPR_PRIORITY)
289 sel_print ("prio:%d;", EXPR_PRIORITY (expr));
291 if (flags & DUMP_EXPR_SCHED_TIMES)
293 int times = EXPR_SCHED_TIMES (expr);
295 if (times != 0)
296 sel_print ("times:%d;", times);
299 if (flags & DUMP_EXPR_SPEC_DONE_DS)
301 ds_t spec_done_ds = EXPR_SPEC_DONE_DS (expr);
303 if (spec_done_ds != 0)
304 sel_print ("ds:%d;", spec_done_ds);
307 if (flags & DUMP_EXPR_ORIG_BB)
309 int orig_bb = EXPR_ORIG_BB_INDEX (expr);
311 if (orig_bb != 0)
312 sel_print ("orig_bb:%d;", orig_bb);
315 if (EXPR_TARGET_AVAILABLE (expr) < 1)
316 sel_print ("target:%d;", EXPR_TARGET_AVAILABLE (expr));
317 sel_print ("]");
320 /* Dump expression EXPR with default flags. */
321 void
322 dump_expr (expr_t expr)
324 dump_expr_1 (expr, dump_expr_flags);
327 /* Dump expression EXPR to stderr. */
328 DEBUG_FUNCTION void
329 debug_expr (expr_t expr)
331 switch_dump (stderr);
332 dump_expr_1 (expr, debug_expr_flags);
333 sel_print ("\n");
334 restore_dump ();
337 /* Dump expression REF. */
339 DEBUG_FUNCTION void
340 debug (expr_def &ref)
342 switch_dump (stderr);
343 dump_expr_1 (&ref, 0);
344 sel_print ("\n");
345 restore_dump ();
348 DEBUG_FUNCTION void
349 debug (expr_def *ptr)
351 if (ptr)
352 debug (*ptr);
353 else
354 fprintf (stderr, "<nil>\n");
357 /* Dump expression REF verbosely. */
359 DEBUG_FUNCTION void
360 debug_verbose (expr_def &ref)
362 switch_dump (stderr);
363 dump_expr_1 (&ref, DUMP_EXPR_ALL);
364 sel_print ("\n");
365 restore_dump ();
368 DEBUG_FUNCTION void
369 debug_verbose (expr_def *ptr)
371 if (ptr)
372 debug_verbose (*ptr);
373 else
374 fprintf (stderr, "<nil>\n");
377 /* Dump insn I honoring FLAGS. */
378 void
379 dump_insn_1 (insn_t i, int flags)
381 int all;
383 all = flags & 1;
384 if (all)
385 flags |= DUMP_INSN_ALL;
387 if (!sched_dump_to_dot_p)
388 sel_print ("(");
390 if (flags & DUMP_INSN_EXPR)
392 dump_expr_1 (INSN_EXPR (i), dump_expr_flags | all);
393 sel_print (";");
395 else if (flags & DUMP_INSN_PATTERN)
397 dump_insn_rtx_1 (i, DUMP_INSN_RTX_PATTERN | all);
398 sel_print (";");
400 else if (flags & DUMP_INSN_UID)
401 sel_print ("uid:%d;", INSN_UID (i));
403 if (flags & DUMP_INSN_SEQNO)
404 sel_print ("seqno:%d;", INSN_SEQNO (i));
406 if (flags & DUMP_INSN_SCHED_CYCLE)
408 int cycle = INSN_SCHED_CYCLE (i);
410 if (cycle != 0)
411 sel_print ("cycle:%d;", cycle);
414 if (!sched_dump_to_dot_p)
415 sel_print (")");
418 /* Dump insn I with default flags. */
419 void
420 dump_insn (insn_t i)
422 dump_insn_1 (i, DUMP_INSN_EXPR | DUMP_INSN_SCHED_CYCLE);
425 /* Dump INSN to stderr. */
426 DEBUG_FUNCTION void
427 debug_insn (insn_t insn)
429 switch_dump (stderr);
430 dump_insn_1 (insn, debug_insn_flags);
431 sel_print ("\n");
432 restore_dump ();
435 /* Dumps av_set AV. */
436 void
437 dump_av_set (av_set_t av)
439 av_set_iterator i;
440 expr_t expr;
442 if (!sched_dump_to_dot_p)
443 sel_print ("{");
445 FOR_EACH_EXPR (expr, i, av)
447 dump_expr (expr);
448 if (!sched_dump_to_dot_p)
449 sel_print (" ");
450 else
451 sel_print ("\n");
454 if (!sched_dump_to_dot_p)
455 sel_print ("}");
458 /* Dumps lvset LV. */
459 void
460 dump_lv_set (regset lv)
462 sel_print ("{");
464 /* This code was adapted from cfg.c: dump_regset (). */
465 if (lv == NULL)
466 sel_print ("nil");
467 else
469 unsigned i;
470 reg_set_iterator rsi;
471 int count = 0;
473 EXECUTE_IF_SET_IN_REG_SET (lv, 0, i, rsi)
475 sel_print (" %d", i);
476 if (i < FIRST_PSEUDO_REGISTER)
478 sel_print (" [%s]", reg_names[i]);
479 ++count;
482 ++count;
484 if (sched_dump_to_dot_p && count == 12)
486 count = 0;
487 sel_print ("\n");
492 sel_print ("}\n");
495 /* Dumps a list of instructions pointed to by P. */
496 static void
497 dump_ilist (ilist_t p)
499 while (p)
501 dump_insn (ILIST_INSN (p));
502 p = ILIST_NEXT (p);
506 /* Dumps a list of boundaries pointed to by BNDS. */
507 void
508 dump_blist (blist_t bnds)
510 for (; bnds; bnds = BLIST_NEXT (bnds))
512 bnd_t bnd = BLIST_BND (bnds);
514 sel_print ("[to: %d; ptr: ", INSN_UID (BND_TO (bnd)));
515 dump_ilist (BND_PTR (bnd));
516 sel_print ("] ");
520 /* Dumps a list of fences pointed to by L. */
521 void
522 dump_flist (flist_t l)
524 while (l)
526 dump_insn_1 (FENCE_INSN (FLIST_FENCE (l)), dump_flist_insn_flags);
527 sel_print (" ");
528 l = FLIST_NEXT (l);
532 /* Dumps an insn vector SUCCS. */
533 void
534 dump_insn_vector (rtx_vec_t succs)
536 int i;
537 rtx succ;
539 FOR_EACH_VEC_ELT (succs, i, succ)
540 if (succ)
541 dump_insn (succ);
542 else
543 sel_print ("NULL ");
546 /* Dumps a hard reg set SET to FILE using PREFIX. */
547 static void
548 print_hard_reg_set (FILE *file, const char *prefix, HARD_REG_SET set)
550 int i;
552 fprintf (file, "%s{ ", prefix);
553 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
555 if (TEST_HARD_REG_BIT (set, i))
556 fprintf (file, "%d ", i);
558 fprintf (file, "}\n");
561 /* Dumps a hard reg set SET using PREFIX. */
562 void
563 dump_hard_reg_set (const char *prefix, HARD_REG_SET set)
565 print_hard_reg_set (sched_dump, prefix, set);
568 /* Pretty print INSN. This is used as a hook. */
569 const char *
570 sel_print_insn (const_rtx insn, int aligned ATTRIBUTE_UNUSED)
572 static char buf[80];
574 /* '+' before insn means it is a new cycle start and it's not been
575 scheduled yet. '>' - has been scheduled. */
576 if (s_i_d.exists () && INSN_LUID (insn) > 0)
577 if (GET_MODE (insn) == TImode)
578 sprintf (buf, "%s %4d",
579 INSN_SCHED_TIMES (insn) > 0 ? "> " : "< ",
580 INSN_UID (insn));
581 else
582 sprintf (buf, "%s %4d",
583 INSN_SCHED_TIMES (insn) > 0 ? "! " : " ",
584 INSN_UID (insn));
585 else
586 if (GET_MODE (insn) == TImode)
587 sprintf (buf, "+ %4d", INSN_UID (insn));
588 else
589 sprintf (buf, " %4d", INSN_UID (insn));
591 return buf;
595 /* Functions for pretty printing of CFG. */
596 /* FIXME: Using pretty-print here could simplify this stuff. */
598 /* Replace all occurencies of STR1 to STR2 in BUF.
599 The BUF must be large enough to hold the result. */
600 static void
601 replace_str_in_buf (char *buf, const char *str1, const char *str2)
603 int buf_len = strlen (buf);
604 int str1_len = strlen (str1);
605 int str2_len = strlen (str2);
606 int diff = str2_len - str1_len;
608 char *p = buf;
611 p = strstr (p, str1);
612 if (p)
614 char *p1 = p + str1_len;
615 /* Copy the rest of buf and '\0'. */
616 int n = buf + buf_len - p1;
617 int i;
619 /* Shift str by DIFF chars. */
620 if (diff > 0)
621 for (i = n; i >= 0; i--)
622 p1[i + diff] = p1[i];
623 else
624 for (i = 0; i <= n; i++)
625 p1[i + diff] = p1[i];
627 /* Copy str2. */
628 for (i = 0; i < str2_len; i++)
629 p[i] = str2[i];
631 p += str2_len;
632 buf_len += diff;
636 while (p);
639 /* Replace characters in BUF that have special meaning in .dot file.
640 Similar to pp_write_text_as_dot_label_to_stream. */
641 static void
642 sel_prepare_string_for_dot_label (char *buf)
644 static char specials_from[7][2] = { "<", ">", "{", "|", "}", "\"",
645 "\n" };
646 static char specials_to[7][3] = { "\\<", "\\>", "\\{", "\\|", "\\}",
647 "\\\"", "\\l" };
648 unsigned i;
650 for (i = 0; i < 7; i++)
651 replace_str_in_buf (buf, specials_from[i], specials_to[i]);
654 /* This function acts like printf but dumps to the sched_dump file. */
655 void
656 sel_print (const char *fmt, ...)
658 va_list ap;
659 va_start (ap, fmt);
660 if (sched_dump_to_dot_p)
662 char *message;
663 if (vasprintf (&message, fmt, ap) >= 0 && message != NULL)
665 message = (char *) xrealloc (message, 2 * strlen (message) + 1);
666 sel_prepare_string_for_dot_label (message);
667 fprintf (sched_dump, "%s", message);
668 free (message);
671 else
672 vfprintf (sched_dump, fmt, ap);
673 va_end (ap);
676 /* Dump INSN with FLAGS. */
677 static void
678 sel_dump_cfg_insn (insn_t insn, int flags)
680 int insn_flags = DUMP_INSN_UID | DUMP_INSN_PATTERN;
682 if (sched_luids.exists () && INSN_LUID (insn) > 0)
684 if (flags & SEL_DUMP_CFG_INSN_SEQNO)
685 insn_flags |= DUMP_INSN_SEQNO | DUMP_INSN_SCHED_CYCLE | DUMP_INSN_EXPR;
688 dump_insn_1 (insn, insn_flags);
691 /* Dump E to the dot file F. */
692 static void
693 sel_dump_cfg_edge (FILE *f, edge e)
695 int w;
696 const char *color;
698 if (e->flags & EDGE_FALLTHRU)
700 w = 10;
701 color = ", color = red";
703 else if (e->src->next_bb == e->dest)
705 w = 3;
706 color = ", color = blue";
708 else
710 w = 1;
711 color = "";
714 fprintf (f, "\tbb%d -> bb%d [weight = %d%s];\n",
715 e->src->index, e->dest->index, w, color);
719 /* Return true if BB has a predesessor from current region.
720 TODO: Either make this function to trace back through empty block
721 or just remove those empty blocks. */
722 static bool
723 has_preds_in_current_region_p (basic_block bb)
725 edge e;
726 edge_iterator ei;
728 gcc_assert (!in_current_region_p (bb));
730 FOR_EACH_EDGE (e, ei, bb->preds)
731 if (in_current_region_p (e->src))
732 return true;
734 return false;
737 /* Dump a cfg region to the dot file F honoring FLAGS. */
738 static void
739 sel_dump_cfg_2 (FILE *f, int flags)
741 basic_block bb;
743 sched_dump_to_dot_p = true;
744 switch_dump (f);
746 fprintf (f, "digraph G {\n"
747 "\tratio = 2.25;\n"
748 "\tnode [shape = record, fontsize = 9];\n");
750 if (flags & SEL_DUMP_CFG_FUNCTION_NAME)
751 fprintf (f, "function [label = \"%s\"];\n", current_function_name ());
753 FOR_EACH_BB_FN (bb, cfun)
755 insn_t insn = BB_HEAD (bb);
756 insn_t next_tail = NEXT_INSN (BB_END (bb));
757 edge e;
758 edge_iterator ei;
759 bool in_region_p = ((flags & SEL_DUMP_CFG_CURRENT_REGION)
760 && in_current_region_p (bb));
761 bool full_p = (!(flags & SEL_DUMP_CFG_CURRENT_REGION)
762 || in_region_p);
763 bool some_p = full_p || has_preds_in_current_region_p (bb);
764 const char *color;
765 const char *style;
767 if (!some_p)
768 continue;
770 if ((flags & SEL_DUMP_CFG_CURRENT_REGION)
771 && in_current_region_p (bb)
772 && BLOCK_TO_BB (bb->index) == 0)
773 color = "color = green, ";
774 else
775 color = "";
777 if ((flags & SEL_DUMP_CFG_FENCES)
778 && in_region_p)
780 style = "";
782 if (!sel_bb_empty_p (bb))
784 bool first_p = true;
785 insn_t tail = BB_END (bb);
786 insn_t cur_insn;
788 cur_insn = bb_note (bb);
792 fence_t fence;
794 cur_insn = NEXT_INSN (cur_insn);
795 fence = flist_lookup (fences, cur_insn);
797 if (fence != NULL)
799 if (!FENCE_SCHEDULED_P (fence))
801 if (first_p)
802 color = "color = red, ";
803 else
804 color = "color = yellow, ";
806 else
807 color = "color = blue, ";
810 first_p = false;
812 while (cur_insn != tail);
815 else if (!full_p)
816 style = "style = dashed, ";
817 else
818 style = "";
820 fprintf (f, "\tbb%d [%s%slabel = \"{Basic block %d", bb->index,
821 style, color, bb->index);
823 if ((flags & SEL_DUMP_CFG_BB_LOOP)
824 && bb->loop_father != NULL)
825 fprintf (f, ", loop %d", bb->loop_father->num);
827 if (full_p
828 && (flags & SEL_DUMP_CFG_BB_NOTES_LIST))
830 insn_t notes = BB_NOTE_LIST (bb);
832 if (notes != NULL_RTX)
834 fprintf (f, "|");
836 /* For simplicity, we dump notes from note_list in reversed order
837 to that what they will appear in the code. */
838 while (notes != NULL_RTX)
840 sel_dump_cfg_insn (notes, flags);
841 fprintf (f, "\\l");
843 notes = PREV_INSN (notes);
848 if (full_p
849 && (flags & SEL_DUMP_CFG_AV_SET)
850 && in_current_region_p (bb)
851 && !sel_bb_empty_p (bb))
853 fprintf (f, "|");
855 if (BB_AV_SET_VALID_P (bb))
856 dump_av_set (BB_AV_SET (bb));
857 else if (BB_AV_LEVEL (bb) == -1)
858 fprintf (f, "AV_SET needs update");
861 if ((flags & SEL_DUMP_CFG_LV_SET)
862 && !sel_bb_empty_p (bb))
864 fprintf (f, "|");
866 if (BB_LV_SET_VALID_P (bb))
867 dump_lv_set (BB_LV_SET (bb));
868 else
869 fprintf (f, "LV_SET needs update");
872 if (full_p
873 && (flags & SEL_DUMP_CFG_BB_INSNS))
875 fprintf (f, "|");
876 while (insn != next_tail)
878 sel_dump_cfg_insn (insn, flags);
879 fprintf (f, "\\l");
881 insn = NEXT_INSN (insn);
885 fprintf (f, "}\"];\n");
887 FOR_EACH_EDGE (e, ei, bb->succs)
888 if (full_p || in_current_region_p (e->dest))
889 sel_dump_cfg_edge (f, e);
892 fprintf (f, "}");
894 restore_dump ();
895 sched_dump_to_dot_p = false;
898 /* Dump a cfg region to the file specified by TAG honoring flags.
899 The file is created by the function. */
900 static void
901 sel_dump_cfg_1 (const char *tag, int flags)
903 char *buf;
904 int i;
905 FILE *f;
907 ++sel_dump_cfg_fileno;
909 if (!sel_dump_cfg_p)
910 return;
912 i = 1 + snprintf (NULL, 0, "%s/%s%05d-%s.dot", sel_debug_cfg_root,
913 sel_debug_cfg_root_postfix, sel_dump_cfg_fileno, tag);
914 buf = XNEWVEC (char, i);
915 snprintf (buf, i, "%s/%s%05d-%s.dot", sel_debug_cfg_root,
916 sel_debug_cfg_root_postfix, sel_dump_cfg_fileno, tag);
918 f = fopen (buf, "w");
920 if (f == NULL)
921 fprintf (stderr, "Can't create file: %s.\n", buf);
922 else
924 sel_dump_cfg_2 (f, flags);
926 fclose (f);
929 free (buf);
932 /* Setup cfg dumping flags. Used for debugging. */
933 void
934 setup_dump_cfg_params (void)
936 sel_dump_cfg_flags = SEL_DUMP_CFG_FLAGS;
937 sel_dump_cfg_p = 0;
938 sel_debug_cfg_root_postfix = sel_debug_cfg_root_postfix_default;
941 /* Debug a cfg region with FLAGS. */
942 void
943 sel_debug_cfg_1 (int flags)
945 bool t1 = sel_dump_cfg_p;
946 int t2 = sel_dump_cfg_fileno;
948 sel_dump_cfg_p = true;
949 sel_dump_cfg_fileno = ++sel_debug_cfg_fileno;
951 sel_dump_cfg_1 ("sel-debug-cfg", flags);
953 sel_dump_cfg_fileno = t2;
954 sel_dump_cfg_p = t1;
957 /* Dumps av_set AV to stderr. */
958 DEBUG_FUNCTION void
959 debug_av_set (av_set_t av)
961 switch_dump (stderr);
962 dump_av_set (av);
963 sel_print ("\n");
964 restore_dump ();
967 /* Dump LV to stderr. */
968 DEBUG_FUNCTION void
969 debug_lv_set (regset lv)
971 switch_dump (stderr);
972 dump_lv_set (lv);
973 sel_print ("\n");
974 restore_dump ();
977 /* Dump an instruction list P to stderr. */
978 DEBUG_FUNCTION void
979 debug_ilist (ilist_t p)
981 switch_dump (stderr);
982 dump_ilist (p);
983 sel_print ("\n");
984 restore_dump ();
987 /* Dump a boundary list BNDS to stderr. */
988 DEBUG_FUNCTION void
989 debug_blist (blist_t bnds)
991 switch_dump (stderr);
992 dump_blist (bnds);
993 sel_print ("\n");
994 restore_dump ();
997 /* Dump a rtx vector REF. */
998 DEBUG_FUNCTION void
999 debug (vec<rtx> &ref)
1001 switch_dump (stderr);
1002 dump_insn_vector (ref);
1003 sel_print ("\n");
1004 restore_dump ();
1007 DEBUG_FUNCTION void
1008 debug (vec<rtx> *ptr)
1010 if (ptr)
1011 debug (*ptr);
1012 else
1013 fprintf (stderr, "<nil>\n");
1016 /* Dump an insn vector SUCCS. */
1017 DEBUG_FUNCTION void
1018 debug_insn_vector (rtx_vec_t succs)
1020 switch_dump (stderr);
1021 dump_insn_vector (succs);
1022 sel_print ("\n");
1023 restore_dump ();
1026 /* Dump a hard reg set SET to stderr. */
1027 DEBUG_FUNCTION void
1028 debug_hard_reg_set (HARD_REG_SET set)
1030 switch_dump (stderr);
1031 dump_hard_reg_set ("", set);
1032 sel_print ("\n");
1033 restore_dump ();
1036 /* Debug a cfg region with default flags. */
1037 void
1038 sel_debug_cfg (void)
1040 sel_debug_cfg_1 (sel_debug_cfg_flags);
1043 /* Print a current cselib value for X's address to stderr. */
1044 DEBUG_FUNCTION rtx
1045 debug_mem_addr_value (rtx x)
1047 rtx t, addr;
1048 enum machine_mode address_mode;
1050 gcc_assert (MEM_P (x));
1051 address_mode = get_address_mode (x);
1053 t = shallow_copy_rtx (x);
1054 if (cselib_lookup (XEXP (t, 0), address_mode, 0, GET_MODE (t)))
1055 XEXP (t, 0) = cselib_subst_to_values (XEXP (t, 0), GET_MODE (t));
1057 t = canon_rtx (t);
1058 addr = get_addr (XEXP (t, 0));
1059 debug_rtx (t);
1060 debug_rtx (addr);
1061 return t;
1063 #endif