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