PR target/11183
[official-gcc.git] / gcc / ra-debug.c
blob17d89b469eeb2e94fde9423f06a0719e64d649cd
1 /* Graph coloring register allocator
2 Copyright (C) 2001, 2002 Free Software Foundation, Inc.
3 Contributed by Michael Matz <matz@suse.de>
4 and Daniel Berlin <dan@cgsoftware.com>.
6 This file is part of GCC.
8 GCC is free software; you can redistribute it and/or modify it under the
9 terms of the GNU General Public License as published by the Free Software
10 Foundation; either version 2, or (at your option) any later version.
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
15 details.
17 You should have received a copy of the GNU General Public License along
18 with GCC; see the file COPYING. If not, write to the Free Software
19 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
21 #include "config.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include "tm.h"
25 #include "rtl.h"
26 #include "insn-config.h"
27 #include "recog.h"
28 #include "function.h"
29 #include "hard-reg-set.h"
30 #include "basic-block.h"
31 #include "df.h"
32 #include "output.h"
33 #include "ra.h"
34 #include "tm_p.h"
36 /* This file contains various dumping and debug functions for
37 the graph coloring register allocator. */
39 static void ra_print_rtx_1op PARAMS ((FILE *, rtx));
40 static void ra_print_rtx_2op PARAMS ((FILE *, rtx));
41 static void ra_print_rtx_3op PARAMS ((FILE *, rtx));
42 static void ra_print_rtx_object PARAMS ((FILE *, rtx));
44 /* The hardregs as names, for debugging. */
45 static const char *const reg_class_names[] = REG_CLASS_NAMES;
47 /* Print a message to the dump file, if debug_new_regalloc and LEVEL
48 have any bits in common. */
50 void
51 ra_debug_msg (unsigned int level, const char *format, ...)
53 va_list ap;
55 va_start (ap, format);
56 if ((debug_new_regalloc & level) != 0 && rtl_dump_file != NULL)
57 vfprintf (rtl_dump_file, format, ap);
58 va_end (ap);
62 /* The following ra_print_xxx() functions print RTL expressions
63 in concise infix form. If the mode can be seen from context it's
64 left out. Most operators are represented by their graphical
65 characters, e.g. LE as "<=". Unknown constructs are currently
66 printed with print_inline_rtx(), which disrupts the nice layout.
67 Currently only the inline asm things are written this way. */
69 /* Print rtx X, which is a one operand rtx (op:mode (Y)), as
70 "op(Y)" to FILE. */
72 static void
73 ra_print_rtx_1op (file, x)
74 FILE *file;
75 rtx x;
77 enum rtx_code code = GET_CODE (x);
78 rtx op0 = XEXP (x, 0);
79 switch (code)
81 case NEG:
82 case NOT:
83 fputs ((code == NEG) ? "-(" : "~(", file);
84 ra_print_rtx (file, op0, 0);
85 fputs (")", file);
86 break;
87 case HIGH:
88 fputs ("hi(", file);
89 ra_print_rtx (file, op0, 0);
90 fputs (")", file);
91 break;
92 default:
93 fprintf (file, "%s", GET_RTX_NAME (code));
94 if (GET_MODE (x) != VOIDmode)
95 fprintf (file, ":%s(", GET_MODE_NAME (GET_MODE (x)));
96 else
97 fputs ("(", file);
98 ra_print_rtx (file, op0, 0);
99 fputs (")", file);
100 break;
104 /* Print rtx X, which is a two operand rtx (op:mode (Y) (Z))
105 as "(Y op Z)", if the operand is know, or as "op(Y, Z)", if not,
106 to FILE. */
108 static void
109 ra_print_rtx_2op (file, x)
110 FILE *file;
111 rtx x;
113 int infix = 1;
114 const char *opname = "shitop";
115 enum rtx_code code = GET_CODE (x);
116 rtx op0 = XEXP (x, 0);
117 rtx op1 = XEXP (x, 1);
118 switch (code)
120 /* class '2' */
121 case COMPARE: opname = "?"; break;
122 case MINUS: opname = "-"; break;
123 case DIV: opname = "/"; break;
124 case UDIV: opname = "u/"; break;
125 case MOD: opname = "%"; break;
126 case UMOD: opname = "u%"; break;
127 case ASHIFT: opname = "<<"; break;
128 case ASHIFTRT: opname = "a>>"; break;
129 case LSHIFTRT: opname = "l>>"; break;
130 /* class 'c' */
131 case PLUS: opname = "+"; break;
132 case MULT: opname = "*"; break;
133 case AND: opname = "&"; break;
134 case IOR: opname = "|"; break;
135 case XOR: opname = "^"; break;
136 /* class '<' */
137 case NE: opname = "!="; break;
138 case EQ: opname = "=="; break;
139 case GE: opname = "s>="; break;
140 case GT: opname = "s>"; break;
141 case LE: opname = "s<="; break;
142 case LT: opname = "s<"; break;
143 case GEU: opname = "u>="; break;
144 case GTU: opname = "u>"; break;
145 case LEU: opname = "u<="; break;
146 case LTU: opname = "u<"; break;
147 default:
148 infix = 0;
149 opname = GET_RTX_NAME (code);
150 break;
152 if (infix)
154 fputs ("(", file);
155 ra_print_rtx (file, op0, 0);
156 fprintf (file, " %s ", opname);
157 ra_print_rtx (file, op1, 0);
158 fputs (")", file);
160 else
162 fprintf (file, "%s(", opname);
163 ra_print_rtx (file, op0, 0);
164 fputs (", ", file);
165 ra_print_rtx (file, op1, 0);
166 fputs (")", file);
170 /* Print rtx X, which a three operand rtx to FILE.
171 I.e. X is either an IF_THEN_ELSE, or a bitmap operation. */
173 static void
174 ra_print_rtx_3op (file, x)
175 FILE *file;
176 rtx x;
178 enum rtx_code code = GET_CODE (x);
179 rtx op0 = XEXP (x, 0);
180 rtx op1 = XEXP (x, 1);
181 rtx op2 = XEXP (x, 2);
182 if (code == IF_THEN_ELSE)
184 ra_print_rtx (file, op0, 0);
185 fputs (" ? ", file);
186 ra_print_rtx (file, op1, 0);
187 fputs (" : ", file);
188 ra_print_rtx (file, op2, 0);
190 else
192 /* Bitmap-operation */
193 fprintf (file, "%s:%s(", GET_RTX_NAME (code),
194 GET_MODE_NAME (GET_MODE (x)));
195 ra_print_rtx (file, op0, 0);
196 fputs (", ", file);
197 ra_print_rtx (file, op1, 0);
198 fputs (", ", file);
199 ra_print_rtx (file, op2, 0);
200 fputs (")", file);
204 /* Print rtx X, which represents an object (class 'o' or some constructs
205 of class 'x' (e.g. subreg)), to FILE.
206 (reg XX) rtl is represented as "pXX", of XX was a pseudo,
207 as "name" it name is the nonnull hardreg name, or as "hXX", if XX
208 is a hardreg, whose name is NULL, or empty. */
210 static void
211 ra_print_rtx_object (file, x)
212 FILE *file;
213 rtx x;
215 enum rtx_code code = GET_CODE (x);
216 enum machine_mode mode = GET_MODE (x);
217 switch (code)
219 case CONST_INT:
220 fprintf (file, HOST_WIDE_INT_PRINT_DEC, XWINT (x, 0));
221 break;
222 case CONST_DOUBLE:
224 int i, num = 0;
225 const char *fmt = GET_RTX_FORMAT (code);
226 fputs ("dbl(", file);
227 for (i = 0; i < GET_RTX_LENGTH (code); i++)
229 if (num)
230 fputs (", ", file);
231 if (fmt[i] == 'e' && XEXP (x, i))
232 /* The MEM or other stuff */
234 ra_print_rtx (file, XEXP (x, i), 0);
235 num++;
237 else if (fmt[i] == 'w')
239 fprintf (file, HOST_WIDE_INT_PRINT_HEX, XWINT (x, i));
240 num++;
243 break;
245 case CONST_STRING: fprintf (file, "\"%s\"", XSTR (x, 0)); break;
246 case CONST: fputs ("const(", file);
247 ra_print_rtx (file, XEXP (x, 0), 0);
248 fputs (")", file);
249 break;
250 case PC: fputs ("pc", file); break;
251 case REG:
253 int regno = REGNO (x);
254 if (regno < FIRST_PSEUDO_REGISTER)
256 int i, nregs = HARD_REGNO_NREGS (regno, mode);
257 if (nregs > 1)
258 fputs ("[", file);
259 for (i = 0; i < nregs; i++)
261 if (i)
262 fputs (", ", file);
263 if (reg_names[regno+i] && *reg_names[regno + i])
264 fprintf (file, "%s", reg_names[regno + i]);
265 else
266 fprintf (file, "h%d", regno + i);
268 if (nregs > 1)
269 fputs ("]", file);
271 else
272 fprintf (file, "p%d", regno);
273 break;
275 case SUBREG:
277 rtx sub = SUBREG_REG (x);
278 int ofs = SUBREG_BYTE (x);
279 if (GET_CODE (sub) == REG
280 && REGNO (sub) < FIRST_PSEUDO_REGISTER)
282 int regno = REGNO (sub);
283 int i, nregs = HARD_REGNO_NREGS (regno, mode);
284 regno += subreg_regno_offset (regno, GET_MODE (sub),
285 ofs, mode);
286 if (nregs > 1)
287 fputs ("[", file);
288 for (i = 0; i < nregs; i++)
290 if (i)
291 fputs (", ", file);
292 if (reg_names[regno+i])
293 fprintf (file, "%s", reg_names[regno + i]);
294 else
295 fprintf (file, "h%d", regno + i);
297 if (nregs > 1)
298 fputs ("]", file);
300 else
302 ra_print_rtx (file, sub, 0);
303 fprintf (file, ":[%s+%d]", GET_MODE_NAME (mode), ofs);
305 break;
307 case SCRATCH: fputs ("scratch", file); break;
308 case CONCAT: ra_print_rtx_2op (file, x); break;
309 case HIGH: ra_print_rtx_1op (file, x); break;
310 case LO_SUM:
311 fputs ("(", file);
312 ra_print_rtx (file, XEXP (x, 0), 0);
313 fputs (" + lo(", file);
314 ra_print_rtx (file, XEXP (x, 1), 0);
315 fputs ("))", file);
316 break;
317 case MEM: fputs ("[", file);
318 ra_print_rtx (file, XEXP (x, 0), 0);
319 fprintf (file, "]:%s", GET_MODE_NAME (GET_MODE (x)));
320 /* XXX print alias set too ?? */
321 break;
322 case LABEL_REF:
324 rtx sub = XEXP (x, 0);
325 if (GET_CODE (sub) == NOTE
326 && NOTE_LINE_NUMBER (sub) == NOTE_INSN_DELETED_LABEL)
327 fprintf (file, "(deleted uid=%d)", INSN_UID (sub));
328 else if (GET_CODE (sub) == CODE_LABEL)
329 fprintf (file, "L%d", CODE_LABEL_NUMBER (sub));
330 else
331 fprintf (file, "(nonlabel uid=%d)", INSN_UID (sub));
333 break;
334 case SYMBOL_REF:
335 fprintf (file, "sym(\"%s\")", XSTR (x, 0)); break;
336 case CC0: fputs ("cc0", file); break;
337 default: print_inline_rtx (file, x, 0); break;
341 /* Print a general rtx X to FILE in nice infix form.
342 If WITH_PN is set, and X is one of the toplevel constructs
343 (insns, notes, labels or barriers), then print also the UIDs of
344 the preceding and following insn. */
346 void
347 ra_print_rtx (file, x, with_pn)
348 FILE *file;
349 rtx x;
350 int with_pn;
352 enum rtx_code code;
353 char class;
354 int unhandled = 0;
355 if (!x)
356 return;
357 code = GET_CODE (x);
358 class = GET_RTX_CLASS (code);
360 /* First handle the insn like constructs. */
361 if (INSN_P (x) || code == NOTE || code == CODE_LABEL || code == BARRIER)
363 if (INSN_P (x))
364 fputs (" ", file);
365 /* Non-insns are prefixed by a ';'. */
366 if (code == BARRIER)
367 fputs ("; ", file);
368 else if (code == NOTE)
369 /* But notes are indented very far right. */
370 fprintf (file, "\t\t\t\t\t; ");
371 else if (code == CODE_LABEL)
372 /* And labels have their Lxx name first, before the actual UID. */
374 fprintf (file, "L%d:\t; ", CODE_LABEL_NUMBER (x));
375 if (LABEL_NAME (x))
376 fprintf (file, "(%s) ", LABEL_NAME (x));
377 switch (LABEL_KIND (x))
379 case LABEL_NORMAL: break;
380 case LABEL_STATIC_ENTRY: fputs (" (entry)", file); break;
381 case LABEL_GLOBAL_ENTRY: fputs (" (global entry)", file); break;
382 case LABEL_WEAK_ENTRY: fputs (" (weak entry)", file); break;
383 default: abort();
385 fprintf (file, " [%d uses] uid=(", LABEL_NUSES (x));
387 fprintf (file, "%d", INSN_UID (x));
388 if (with_pn)
389 fprintf (file, " %d %d", PREV_INSN (x) ? INSN_UID (PREV_INSN (x)) : 0,
390 NEXT_INSN (x) ? INSN_UID (NEXT_INSN (x)) : 0);
391 if (code == BARRIER)
392 fputs (" -------- barrier ---------", file);
393 else if (code == CODE_LABEL)
394 fputs (")", file);
395 else if (code == NOTE)
397 int ln = NOTE_LINE_NUMBER (x);
398 if (ln >= (int) NOTE_INSN_BIAS && ln < (int) NOTE_INSN_MAX)
399 fprintf (file, " %s", GET_NOTE_INSN_NAME (ln));
400 else
402 fprintf (file, " line %d", ln);
403 if (NOTE_SOURCE_FILE (x))
404 fprintf (file, ":%s", NOTE_SOURCE_FILE (x));
407 else
409 fprintf (file, "\t");
410 ra_print_rtx (file, PATTERN (x), 0);
412 return;
414 switch (code)
416 /* Top-level stuff. */
417 case PARALLEL:
419 int j;
420 for (j = 0; j < XVECLEN (x, 0); j++)
422 if (j)
423 fputs ("\t;; ", file);
424 ra_print_rtx (file, XVECEXP (x, 0, j), 0);
426 break;
428 case UNSPEC: case UNSPEC_VOLATILE:
430 int j;
431 fprintf (file, "unspec%s(%d",
432 (code == UNSPEC) ? "" : "_vol", XINT (x, 1));
433 for (j = 0; j < XVECLEN (x, 0); j++)
435 fputs (", ", file);
436 ra_print_rtx (file, XVECEXP (x, 0, j), 0);
438 fputs (")", file);
439 break;
441 case SET:
442 if (GET_CODE (SET_DEST (x)) == PC)
444 if (GET_CODE (SET_SRC (x)) == IF_THEN_ELSE
445 && GET_CODE (XEXP (SET_SRC(x), 2)) == PC)
447 fputs ("if ", file);
448 ra_print_rtx (file, XEXP (SET_SRC (x), 0), 0);
449 fputs (" jump ", file);
450 ra_print_rtx (file, XEXP (SET_SRC (x), 1), 0);
452 else
454 fputs ("jump ", file);
455 ra_print_rtx (file, SET_SRC (x), 0);
458 else
460 ra_print_rtx (file, SET_DEST (x), 0);
461 fputs (" <= ", file);
462 ra_print_rtx (file, SET_SRC (x), 0);
464 break;
465 case USE:
466 fputs ("use <= ", file);
467 ra_print_rtx (file, XEXP (x, 0), 0);
468 break;
469 case CLOBBER:
470 ra_print_rtx (file, XEXP (x, 0), 0);
471 fputs (" <= clobber", file);
472 break;
473 case CALL:
474 fputs ("call ", file);
475 ra_print_rtx (file, XEXP (x, 0), 0); /* Address */
476 fputs (" numargs=", file);
477 ra_print_rtx (file, XEXP (x, 1), 0); /* Num arguments */
478 break;
479 case RETURN:
480 fputs ("return", file);
481 break;
482 case TRAP_IF:
483 fputs ("if (", file);
484 ra_print_rtx (file, XEXP (x, 0), 0);
485 fputs (") trap ", file);
486 ra_print_rtx (file, XEXP (x, 1), 0);
487 break;
488 case RESX:
489 fprintf (file, "resx from region %d", XINT (x, 0));
490 break;
492 /* Different things of class 'x' */
493 case SUBREG: ra_print_rtx_object (file, x); break;
494 case STRICT_LOW_PART:
495 fputs ("low(", file);
496 ra_print_rtx (file, XEXP (x, 0), 0);
497 fputs (")", file);
498 break;
499 default:
500 unhandled = 1;
501 break;
503 if (!unhandled)
504 return;
505 if (class == '1')
506 ra_print_rtx_1op (file, x);
507 else if (class == '2' || class == 'c' || class == '<')
508 ra_print_rtx_2op (file, x);
509 else if (class == '3' || class == 'b')
510 ra_print_rtx_3op (file, x);
511 else if (class == 'o')
512 ra_print_rtx_object (file, x);
513 else
514 print_inline_rtx (file, x, 0);
517 /* This only calls ra_print_rtx(), but emits a final newline. */
519 void
520 ra_print_rtx_top (file, x, with_pn)
521 FILE *file;
522 rtx x;
523 int with_pn;
525 ra_print_rtx (file, x, with_pn);
526 fprintf (file, "\n");
529 /* Callable from gdb. This prints rtx X onto stderr. */
531 void
532 ra_debug_rtx (x)
533 rtx x;
535 ra_print_rtx_top (stderr, x, 1);
538 /* This prints the content of basic block with index BBI.
539 The first and last insn are emitted with UIDs of prev and next insns. */
541 void
542 ra_debug_bbi (bbi)
543 int bbi;
545 basic_block bb = BASIC_BLOCK (bbi);
546 rtx insn;
547 for (insn = bb->head; insn; insn = NEXT_INSN (insn))
549 ra_print_rtx_top (stderr, insn, (insn == bb->head || insn == bb->end));
550 fprintf (stderr, "\n");
551 if (insn == bb->end)
552 break;
556 /* Beginning from INSN, emit NUM insns (if NUM is non-negative)
557 or emit a window of NUM insns around INSN, to stderr. */
559 void
560 ra_debug_insns (insn, num)
561 rtx insn;
562 int num;
564 int i, count = (num == 0 ? 1 : num < 0 ? -num : num);
565 if (num < 0)
566 for (i = count / 2; i > 0 && PREV_INSN (insn); i--)
567 insn = PREV_INSN (insn);
568 for (i = count; i > 0 && insn; insn = NEXT_INSN (insn), i--)
570 if (GET_CODE (insn) == CODE_LABEL)
571 fprintf (stderr, "\n");
572 ra_print_rtx_top (stderr, insn, (i == count || i == 1));
576 /* Beginning with INSN, emit the whole insn chain into FILE.
577 This also outputs comments when basic blocks start or end and omits
578 some notes, if flag_ra_dump_notes is zero. */
580 void
581 ra_print_rtl_with_bb (file, insn)
582 FILE *file;
583 rtx insn;
585 basic_block last_bb, bb;
586 unsigned int num = 0;
587 if (!insn)
588 fputs ("nil", file);
589 last_bb = NULL;
590 for (; insn; insn = NEXT_INSN (insn))
592 if (GET_CODE (insn) == BARRIER)
593 bb = NULL;
594 else
595 bb = BLOCK_FOR_INSN (insn);
596 if (bb != last_bb)
598 if (last_bb)
599 fprintf (file, ";; End of basic block %d\n", last_bb->index);
600 if (bb)
601 fprintf (file, ";; Begin of basic block %d\n", bb->index);
602 last_bb = bb;
604 if (GET_CODE (insn) == CODE_LABEL)
605 fputc ('\n', file);
606 if (GET_CODE (insn) == NOTE)
608 /* Ignore basic block and maybe other notes not referencing
609 deleted things. */
610 if (NOTE_LINE_NUMBER (insn) != NOTE_INSN_BASIC_BLOCK
611 && (flag_ra_dump_notes
612 || NOTE_LINE_NUMBER (insn) == NOTE_INSN_DELETED
613 || NOTE_LINE_NUMBER (insn) == NOTE_INSN_DELETED_LABEL))
615 ra_print_rtx_top (file, insn, (num == 0 || !NEXT_INSN (insn)));
616 num++;
619 else
621 ra_print_rtx_top (file, insn, (num == 0 || !NEXT_INSN (insn)));
622 num++;
627 /* Count how many insns were seen how often, while building the interference
628 graph, and prints the findings. */
630 void
631 dump_number_seen ()
633 #define N 17
634 int num[N];
635 int i;
637 for (i = 0; i < N; i++)
638 num[i] = 0;
639 for (i = 0; i < get_max_uid (); i++)
640 if (number_seen[i] < N - 1)
641 num[number_seen[i]]++;
642 else
643 num[N - 1]++;
644 for (i = 0; i < N - 1; i++)
645 if (num[i])
646 ra_debug_msg (DUMP_PROCESS, "%d insns seen %d times\n", num[i], i);
647 if (num[N - 1])
648 ra_debug_msg (DUMP_PROCESS, "%d insns seen %d and more times\n", num[i],
649 N - 1);
650 ra_debug_msg (DUMP_PROCESS, "from overall %d insns\n", get_max_uid ());
651 #undef N
654 /* Dump the interference graph, the move list and the webs. */
656 void
657 dump_igraph (df)
658 struct df *df ATTRIBUTE_UNUSED;
660 struct move_list *ml;
661 unsigned int def1, def2;
662 int num = 0;
663 int num2;
664 unsigned int i;
665 if (!rtl_dump_file || (debug_new_regalloc & (DUMP_IGRAPH | DUMP_WEBS)) == 0)
666 return;
667 ra_debug_msg (DUMP_IGRAPH, "conflicts:\n ");
668 for (def1 = 0; def1 < num_webs; def1++)
670 int num1 = num;
671 num2 = 0;
672 for (def2 = 0; def2 < num_webs; def2++)
673 if (def1 != def2 && TEST_BIT (igraph, igraph_index (def1, def2)))
675 if (num1 == num)
677 if (SUBWEB_P (ID2WEB (def1)))
678 ra_debug_msg (DUMP_IGRAPH, "%d (SUBREG %d, %d) with ", def1,
679 ID2WEB (def1)->regno,
680 SUBREG_BYTE (ID2WEB (def1)->orig_x));
681 else
682 ra_debug_msg (DUMP_IGRAPH, "%d (REG %d) with ", def1,
683 ID2WEB (def1)->regno);
685 if ((num2 % 9) == 8)
686 ra_debug_msg (DUMP_IGRAPH, "\n ");
687 num++;
688 num2++;
689 if (SUBWEB_P (ID2WEB (def2)))
690 ra_debug_msg (DUMP_IGRAPH, "%d(%d,%d) ", def2, ID2WEB (def2)->regno,
691 SUBREG_BYTE (ID2WEB (def2)->orig_x));
692 else
693 ra_debug_msg (DUMP_IGRAPH, "%d(%d) ", def2, ID2WEB (def2)->regno);
695 if (num1 != num)
696 ra_debug_msg (DUMP_IGRAPH, "\n ");
698 ra_debug_msg (DUMP_IGRAPH, "\n");
699 for (ml = wl_moves; ml; ml = ml->next)
700 if (ml->move)
702 ra_debug_msg (DUMP_IGRAPH, "move: insn %d: Web %d <-- Web %d\n",
703 INSN_UID (ml->move->insn), ml->move->target_web->id,
704 ml->move->source_web->id);
706 ra_debug_msg (DUMP_WEBS, "\nWebs:\n");
707 for (i = 0; i < num_webs; i++)
709 struct web *web = ID2WEB (i);
711 ra_debug_msg (DUMP_WEBS, " %4d : regno %3d", i, web->regno);
712 if (SUBWEB_P (web))
714 ra_debug_msg (DUMP_WEBS, " sub %d", SUBREG_BYTE (web->orig_x));
715 ra_debug_msg (DUMP_WEBS, " par %d", find_web_for_subweb (web)->id);
717 ra_debug_msg (DUMP_WEBS, " +%d (span %d, cost "
718 HOST_WIDE_INT_PRINT_DEC ") (%s)",
719 web->add_hardregs, web->span_deaths, web->spill_cost,
720 reg_class_names[web->regclass]);
721 if (web->spill_temp == 1)
722 ra_debug_msg (DUMP_WEBS, " (spilltemp)");
723 else if (web->spill_temp == 2)
724 ra_debug_msg (DUMP_WEBS, " (spilltem2)");
725 else if (web->spill_temp == 3)
726 ra_debug_msg (DUMP_WEBS, " (short)");
727 if (web->type == PRECOLORED)
728 ra_debug_msg (DUMP_WEBS, " (precolored, color=%d)", web->color);
729 else if (find_web_for_subweb (web)->num_uses == 0)
730 ra_debug_msg (DUMP_WEBS, " dead");
731 if (web->crosses_call)
732 ra_debug_msg (DUMP_WEBS, " xcall");
733 if (web->regno >= max_normal_pseudo)
734 ra_debug_msg (DUMP_WEBS, " stack");
735 ra_debug_msg (DUMP_WEBS, "\n");
739 /* Dump the interference graph and webs in a format easily
740 parsable by programs. Used to emit real world interference graph
741 to my custom graph colorizer. */
743 void
744 dump_igraph_machine ()
746 unsigned int i;
748 if (!rtl_dump_file || (debug_new_regalloc & DUMP_IGRAPH_M) == 0)
749 return;
750 ra_debug_msg (DUMP_IGRAPH_M, "g %d %d\n", num_webs - num_subwebs,
751 FIRST_PSEUDO_REGISTER);
752 for (i = 0; i < num_webs - num_subwebs; i++)
754 struct web *web = ID2WEB (i);
755 struct conflict_link *cl;
756 int flags = 0;
757 int numc = 0;
758 int col = 0;
759 flags = web->spill_temp & 0xF;
760 flags |= ((web->type == PRECOLORED) ? 1 : 0) << 4;
761 flags |= (web->add_hardregs & 0xF) << 5;
762 for (cl = web->conflict_list; cl; cl = cl->next)
763 if (cl->t->id < web->id)
764 numc++;
765 ra_debug_msg (DUMP_IGRAPH_M, "n %d %d %d %d %d %d %d\n",
766 web->id, web->color, flags,
767 (unsigned int)web->spill_cost, web->num_defs, web->num_uses,
768 numc);
769 if (web->type != PRECOLORED)
771 ra_debug_msg (DUMP_IGRAPH_M, "s %d", web->id);
772 while (1)
774 unsigned int u = 0;
775 int n;
776 for (n = 0; n < 32 && col < FIRST_PSEUDO_REGISTER; n++, col++)
777 if (TEST_HARD_REG_BIT (web->usable_regs, col))
778 u |= 1 << n;
779 ra_debug_msg (DUMP_IGRAPH_M, " %u", u);
780 if (col >= FIRST_PSEUDO_REGISTER)
781 break;
783 ra_debug_msg (DUMP_IGRAPH_M, "\n");
785 if (numc)
787 ra_debug_msg (DUMP_IGRAPH_M, "c %d", web->id);
788 for (cl = web->conflict_list; cl; cl = cl->next)
790 if (cl->t->id < web->id)
791 ra_debug_msg (DUMP_IGRAPH_M, " %d", cl->t->id);
793 ra_debug_msg (DUMP_IGRAPH_M, "\n");
796 ra_debug_msg (DUMP_IGRAPH_M, "e\n");
799 /* This runs after colorization and changing the insn stream.
800 It temporarily replaces all pseudo registers with their colors,
801 and emits information, if the resulting insns are strictly valid. */
803 void
804 dump_constraints ()
806 rtx insn;
807 int i;
808 if (!rtl_dump_file || (debug_new_regalloc & DUMP_CONSTRAINTS) == 0)
809 return;
810 for (i = FIRST_PSEUDO_REGISTER; i < ra_max_regno; i++)
811 if (regno_reg_rtx[i] && GET_CODE (regno_reg_rtx[i]) == REG)
812 REGNO (regno_reg_rtx[i])
813 = ra_reg_renumber[i] >= 0 ? ra_reg_renumber[i] : i;
814 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
815 if (INSN_P (insn))
817 int code;
818 int uid = INSN_UID (insn);
819 int o;
820 /* Don't simply force rerecognition, as combine might left us
821 with some unrecognizable ones, which later leads to aborts
822 in regclass, if we now destroy the remembered INSN_CODE(). */
823 /*INSN_CODE (insn) = -1;*/
824 code = recog_memoized (insn);
825 if (code < 0)
827 ra_debug_msg (DUMP_CONSTRAINTS,
828 "%d: asm insn or not recognizable.\n", uid);
829 continue;
831 ra_debug_msg (DUMP_CONSTRAINTS,
832 "%d: code %d {%s}, %d operands, constraints: ",
833 uid, code, insn_data[code].name, recog_data.n_operands);
834 extract_insn (insn);
835 /*preprocess_constraints ();*/
836 for (o = 0; o < recog_data.n_operands; o++)
838 ra_debug_msg (DUMP_CONSTRAINTS,
839 "%d:%s ", o, recog_data.constraints[o]);
841 if (constrain_operands (1))
842 ra_debug_msg (DUMP_CONSTRAINTS, "matches strictly alternative %d",
843 which_alternative);
844 else
845 ra_debug_msg (DUMP_CONSTRAINTS, "doesn't match strictly");
846 ra_debug_msg (DUMP_CONSTRAINTS, "\n");
848 for (i = FIRST_PSEUDO_REGISTER; i < ra_max_regno; i++)
849 if (regno_reg_rtx[i] && GET_CODE (regno_reg_rtx[i]) == REG)
850 REGNO (regno_reg_rtx[i]) = i;
853 /* This counts and emits the cumulated cost of all spilled webs,
854 preceded by a custom message MSG, with debug level LEVEL. */
856 void
857 dump_graph_cost (level, msg)
858 unsigned int level;
859 const char *msg;
861 unsigned int i;
862 unsigned HOST_WIDE_INT cost;
863 if (!rtl_dump_file || (debug_new_regalloc & level) == 0)
864 return;
866 cost = 0;
867 for (i = 0; i < num_webs; i++)
869 struct web *web = id2web[i];
870 if (alias (web)->type == SPILLED)
871 cost += web->orig_spill_cost;
873 ra_debug_msg (level, " spill cost of graph (%s) = "
874 HOST_WIDE_INT_PRINT_UNSIGNED "\n",
875 msg ? msg : "", cost);
878 /* Dump the color assignment per web, the coalesced and spilled webs. */
880 void
881 dump_ra (df)
882 struct df *df ATTRIBUTE_UNUSED;
884 struct web *web;
885 struct dlist *d;
886 if (!rtl_dump_file || (debug_new_regalloc & DUMP_RESULTS) == 0)
887 return;
889 ra_debug_msg (DUMP_RESULTS, "\nColored:\n");
890 for (d = WEBS(COLORED); d; d = d->next)
892 web = DLIST_WEB (d);
893 ra_debug_msg (DUMP_RESULTS, " %4d : color %d\n", web->id, web->color);
895 ra_debug_msg (DUMP_RESULTS, "\nCoalesced:\n");
896 for (d = WEBS(COALESCED); d; d = d->next)
898 web = DLIST_WEB (d);
899 ra_debug_msg (DUMP_RESULTS, " %4d : to web %d, color %d\n", web->id,
900 alias (web)->id, web->color);
902 ra_debug_msg (DUMP_RESULTS, "\nSpilled:\n");
903 for (d = WEBS(SPILLED); d; d = d->next)
905 web = DLIST_WEB (d);
906 ra_debug_msg (DUMP_RESULTS, " %4d\n", web->id);
908 ra_debug_msg (DUMP_RESULTS, "\n");
909 dump_cost (DUMP_RESULTS);
912 /* Calculate and dump the cumulated costs of certain types of insns
913 (loads, stores and copies). */
915 void
916 dump_static_insn_cost (file, message, prefix)
917 FILE *file;
918 const char *message;
919 const char *prefix;
921 struct cost
923 unsigned HOST_WIDE_INT cost;
924 unsigned int count;
926 basic_block bb;
927 struct cost load, store, regcopy, selfcopy, overall;
928 memset (&load, 0, sizeof(load));
929 memset (&store, 0, sizeof(store));
930 memset (&regcopy, 0, sizeof(regcopy));
931 memset (&selfcopy, 0, sizeof(selfcopy));
932 memset (&overall, 0, sizeof(overall));
934 if (!file)
935 return;
937 FOR_EACH_BB (bb)
939 unsigned HOST_WIDE_INT block_cost = bb->frequency;
940 rtx insn, set;
941 for (insn = bb->head; insn; insn = NEXT_INSN (insn))
943 /* Yes, yes. We don't calculate the costs precisely.
944 Only for "simple enough" insns. Those containing single
945 sets only. */
946 if (INSN_P (insn) && ((set = single_set (insn)) != NULL))
948 rtx src = SET_SRC (set);
949 rtx dest = SET_DEST (set);
950 struct cost *pcost = NULL;
951 overall.cost += block_cost;
952 overall.count++;
953 if (rtx_equal_p (src, dest))
954 pcost = &selfcopy;
955 else if (GET_CODE (src) == GET_CODE (dest)
956 && ((GET_CODE (src) == REG)
957 || (GET_CODE (src) == SUBREG
958 && GET_CODE (SUBREG_REG (src)) == REG
959 && GET_CODE (SUBREG_REG (dest)) == REG)))
960 pcost = &regcopy;
961 else
963 if (GET_CODE (src) == SUBREG)
964 src = SUBREG_REG (src);
965 if (GET_CODE (dest) == SUBREG)
966 dest = SUBREG_REG (dest);
967 if (GET_CODE (src) == MEM && GET_CODE (dest) != MEM
968 && memref_is_stack_slot (src))
969 pcost = &load;
970 else if (GET_CODE (src) != MEM && GET_CODE (dest) == MEM
971 && memref_is_stack_slot (dest))
972 pcost = &store;
974 if (pcost)
976 pcost->cost += block_cost;
977 pcost->count++;
980 if (insn == bb->end)
981 break;
985 if (!prefix)
986 prefix = "";
987 fprintf (file, "static insn cost %s\n", message ? message : "");
988 fprintf (file, " %soverall:\tnum=%6d\tcost="
989 HOST_WIDE_INT_PRINT_DEC_SPACE "\n",
990 prefix, overall.count, 8, overall.cost);
991 fprintf (file, " %sloads:\tnum=%6d\tcost="
992 HOST_WIDE_INT_PRINT_DEC_SPACE "\n",
993 prefix, load.count, 8, load.cost);
994 fprintf (file, " %sstores:\tnum=%6d\tcost="
995 HOST_WIDE_INT_PRINT_DEC_SPACE "\n",
996 prefix, store.count, 8, store.cost);
997 fprintf (file, " %sregcopy:\tnum=%6d\tcost="
998 HOST_WIDE_INT_PRINT_DEC_SPACE "\n",
999 prefix, regcopy.count, 8, regcopy.cost);
1000 fprintf (file, " %sselfcpy:\tnum=%6d\tcost="
1001 HOST_WIDE_INT_PRINT_DEC_SPACE "\n",
1002 prefix, selfcopy.count, 8, selfcopy.cost);
1005 /* Returns nonzero, if WEB1 and WEB2 have some possible
1006 hardregs in common. */
1009 web_conflicts_p (web1, web2)
1010 struct web *web1;
1011 struct web *web2;
1013 if (web1->type == PRECOLORED && web2->type == PRECOLORED)
1014 return 0;
1016 if (web1->type == PRECOLORED)
1017 return TEST_HARD_REG_BIT (web2->usable_regs, web1->regno);
1019 if (web2->type == PRECOLORED)
1020 return TEST_HARD_REG_BIT (web1->usable_regs, web2->regno);
1022 return hard_regs_intersect_p (&web1->usable_regs, &web2->usable_regs);
1025 /* Dump all uids of insns in which WEB is mentioned. */
1027 void
1028 dump_web_insns (web)
1029 struct web *web;
1031 unsigned int i;
1033 ra_debug_msg (DUMP_EVER, "Web: %i(%i)+%i class: %s freedom: %i degree %i\n",
1034 web->id, web->regno, web->add_hardregs,
1035 reg_class_names[web->regclass],
1036 web->num_freedom, web->num_conflicts);
1037 ra_debug_msg (DUMP_EVER, " def insns:");
1039 for (i = 0; i < web->num_defs; ++i)
1041 ra_debug_msg (DUMP_EVER, " %d ", INSN_UID (web->defs[i]->insn));
1044 ra_debug_msg (DUMP_EVER, "\n use insns:");
1045 for (i = 0; i < web->num_uses; ++i)
1047 ra_debug_msg (DUMP_EVER, " %d ", INSN_UID (web->uses[i]->insn));
1049 ra_debug_msg (DUMP_EVER, "\n");
1052 /* Dump conflicts for web WEB. */
1054 void
1055 dump_web_conflicts (web)
1056 struct web *web;
1058 int num = 0;
1059 unsigned int def2;
1061 ra_debug_msg (DUMP_EVER, "Web: %i(%i)+%i class: %s freedom: %i degree %i\n",
1062 web->id, web->regno, web->add_hardregs,
1063 reg_class_names[web->regclass],
1064 web->num_freedom, web->num_conflicts);
1066 for (def2 = 0; def2 < num_webs; def2++)
1067 if (TEST_BIT (igraph, igraph_index (web->id, def2)) && web->id != def2)
1069 if ((num % 9) == 5)
1070 ra_debug_msg (DUMP_EVER, "\n ");
1071 num++;
1073 ra_debug_msg (DUMP_EVER, " %d(%d)", def2, id2web[def2]->regno);
1074 if (id2web[def2]->add_hardregs)
1075 ra_debug_msg (DUMP_EVER, "+%d", id2web[def2]->add_hardregs);
1077 if (web_conflicts_p (web, id2web[def2]))
1078 ra_debug_msg (DUMP_EVER, "/x");
1080 if (id2web[def2]->type == SELECT)
1081 ra_debug_msg (DUMP_EVER, "/s");
1083 if (id2web[def2]->type == COALESCED)
1084 ra_debug_msg (DUMP_EVER,"/c/%d", alias (id2web[def2])->id);
1086 ra_debug_msg (DUMP_EVER, "\n");
1088 struct conflict_link *wl;
1089 num = 0;
1090 ra_debug_msg (DUMP_EVER, "By conflicts: ");
1091 for (wl = web->conflict_list; wl; wl = wl->next)
1093 struct web* w = wl->t;
1094 if ((num % 9) == 8)
1095 ra_debug_msg (DUMP_EVER, "\n ");
1096 num++;
1097 ra_debug_msg (DUMP_EVER, "%d(%d)%s ", w->id, w->regno,
1098 web_conflicts_p (web, w) ? "+" : "");
1100 ra_debug_msg (DUMP_EVER, "\n");
1104 /* Output HARD_REG_SET to stderr. */
1106 void
1107 debug_hard_reg_set (set)
1108 HARD_REG_SET set;
1110 int i;
1111 for (i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
1113 if (TEST_HARD_REG_BIT (set, i))
1115 fprintf (stderr, "%s ", reg_names[i]);
1118 fprintf (stderr, "\n");
1122 vim:cinoptions={.5s,g0,p5,t0,(0,^-0.5s,n-0.5s:tw=78:cindent:sw=4: