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