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