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