2003-12-26 Guilhem Lavaux <guilhem@kaffe.org>
[official-gcc.git] / gcc / ra-debug.c
blob26aac12df0ed6756479aaa3cf7cb3b11af1551c5
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 (FILE *, rtx);
40 static void ra_print_rtx_2op (FILE *, rtx);
41 static void ra_print_rtx_3op (FILE *, rtx);
42 static void ra_print_rtx_object (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 *file, rtx x)
75 enum rtx_code code = GET_CODE (x);
76 rtx op0 = XEXP (x, 0);
77 switch (code)
79 case NEG:
80 case NOT:
81 fputs ((code == NEG) ? "-(" : "~(", file);
82 ra_print_rtx (file, op0, 0);
83 fputs (")", file);
84 break;
85 case HIGH:
86 fputs ("hi(", file);
87 ra_print_rtx (file, op0, 0);
88 fputs (")", file);
89 break;
90 default:
91 fprintf (file, "%s", GET_RTX_NAME (code));
92 if (GET_MODE (x) != VOIDmode)
93 fprintf (file, ":%s(", GET_MODE_NAME (GET_MODE (x)));
94 else
95 fputs ("(", file);
96 ra_print_rtx (file, op0, 0);
97 fputs (")", file);
98 break;
102 /* Print rtx X, which is a two operand rtx (op:mode (Y) (Z))
103 as "(Y op Z)", if the operand is know, or as "op(Y, Z)", if not,
104 to FILE. */
106 static void
107 ra_print_rtx_2op (FILE *file, rtx x)
109 int infix = 1;
110 const char *opname = "shitop";
111 enum rtx_code code = GET_CODE (x);
112 rtx op0 = XEXP (x, 0);
113 rtx op1 = XEXP (x, 1);
114 switch (code)
116 /* class '2' */
117 case COMPARE: opname = "?"; break;
118 case MINUS: opname = "-"; break;
119 case DIV: opname = "/"; break;
120 case UDIV: opname = "u/"; break;
121 case MOD: opname = "%"; break;
122 case UMOD: opname = "u%"; break;
123 case ASHIFT: opname = "<<"; break;
124 case ASHIFTRT: opname = "a>>"; break;
125 case LSHIFTRT: opname = "l>>"; break;
126 /* class 'c' */
127 case PLUS: opname = "+"; break;
128 case MULT: opname = "*"; break;
129 case AND: opname = "&"; break;
130 case IOR: opname = "|"; break;
131 case XOR: opname = "^"; break;
132 /* class '<' */
133 case NE: opname = "!="; break;
134 case EQ: opname = "=="; break;
135 case GE: opname = "s>="; break;
136 case GT: opname = "s>"; break;
137 case LE: opname = "s<="; break;
138 case LT: opname = "s<"; break;
139 case GEU: opname = "u>="; break;
140 case GTU: opname = "u>"; break;
141 case LEU: opname = "u<="; break;
142 case LTU: opname = "u<"; break;
143 default:
144 infix = 0;
145 opname = GET_RTX_NAME (code);
146 break;
148 if (infix)
150 fputs ("(", file);
151 ra_print_rtx (file, op0, 0);
152 fprintf (file, " %s ", opname);
153 ra_print_rtx (file, op1, 0);
154 fputs (")", file);
156 else
158 fprintf (file, "%s(", opname);
159 ra_print_rtx (file, op0, 0);
160 fputs (", ", file);
161 ra_print_rtx (file, op1, 0);
162 fputs (")", file);
166 /* Print rtx X, which a three operand rtx to FILE.
167 I.e. X is either an IF_THEN_ELSE, or a bitmap operation. */
169 static void
170 ra_print_rtx_3op (FILE *file, rtx x)
172 enum rtx_code code = GET_CODE (x);
173 rtx op0 = XEXP (x, 0);
174 rtx op1 = XEXP (x, 1);
175 rtx op2 = XEXP (x, 2);
176 if (code == IF_THEN_ELSE)
178 ra_print_rtx (file, op0, 0);
179 fputs (" ? ", file);
180 ra_print_rtx (file, op1, 0);
181 fputs (" : ", file);
182 ra_print_rtx (file, op2, 0);
184 else
186 /* Bitmap-operation */
187 fprintf (file, "%s:%s(", GET_RTX_NAME (code),
188 GET_MODE_NAME (GET_MODE (x)));
189 ra_print_rtx (file, op0, 0);
190 fputs (", ", file);
191 ra_print_rtx (file, op1, 0);
192 fputs (", ", file);
193 ra_print_rtx (file, op2, 0);
194 fputs (")", file);
198 /* Print rtx X, which represents an object (class 'o' or some constructs
199 of class 'x' (e.g. subreg)), to FILE.
200 (reg XX) rtl is represented as "pXX", of XX was a pseudo,
201 as "name" it name is the nonnull hardreg name, or as "hXX", if XX
202 is a hardreg, whose name is NULL, or empty. */
204 static void
205 ra_print_rtx_object (FILE *file, rtx x)
207 enum rtx_code code = GET_CODE (x);
208 enum machine_mode mode = GET_MODE (x);
209 switch (code)
211 case CONST_INT:
212 fprintf (file, HOST_WIDE_INT_PRINT_DEC, XWINT (x, 0));
213 break;
214 case CONST_DOUBLE:
216 int i, num = 0;
217 const char *fmt = GET_RTX_FORMAT (code);
218 fputs ("dbl(", file);
219 for (i = 0; i < GET_RTX_LENGTH (code); i++)
221 if (num)
222 fputs (", ", file);
223 if (fmt[i] == 'e' && XEXP (x, i))
224 /* The MEM or other stuff */
226 ra_print_rtx (file, XEXP (x, i), 0);
227 num++;
229 else if (fmt[i] == 'w')
231 fprintf (file, HOST_WIDE_INT_PRINT_HEX, XWINT (x, i));
232 num++;
235 break;
237 case CONST_STRING: fprintf (file, "\"%s\"", XSTR (x, 0)); break;
238 case CONST: fputs ("const(", file);
239 ra_print_rtx (file, XEXP (x, 0), 0);
240 fputs (")", file);
241 break;
242 case PC: fputs ("pc", file); break;
243 case REG:
245 int regno = REGNO (x);
246 if (regno < FIRST_PSEUDO_REGISTER)
248 int i, nregs = HARD_REGNO_NREGS (regno, mode);
249 if (nregs > 1)
250 fputs ("[", file);
251 for (i = 0; i < nregs; i++)
253 if (i)
254 fputs (", ", file);
255 if (reg_names[regno+i] && *reg_names[regno + i])
256 fprintf (file, "%s", reg_names[regno + i]);
257 else
258 fprintf (file, "h%d", regno + i);
260 if (nregs > 1)
261 fputs ("]", file);
263 else
264 fprintf (file, "p%d", regno);
265 break;
267 case SUBREG:
269 rtx sub = SUBREG_REG (x);
270 int ofs = SUBREG_BYTE (x);
271 if (GET_CODE (sub) == REG
272 && REGNO (sub) < FIRST_PSEUDO_REGISTER)
274 int regno = REGNO (sub);
275 int i, nregs = HARD_REGNO_NREGS (regno, mode);
276 regno += subreg_regno_offset (regno, GET_MODE (sub),
277 ofs, mode);
278 if (nregs > 1)
279 fputs ("[", file);
280 for (i = 0; i < nregs; i++)
282 if (i)
283 fputs (", ", file);
284 if (reg_names[regno+i])
285 fprintf (file, "%s", reg_names[regno + i]);
286 else
287 fprintf (file, "h%d", regno + i);
289 if (nregs > 1)
290 fputs ("]", file);
292 else
294 ra_print_rtx (file, sub, 0);
295 fprintf (file, ":[%s+%d]", GET_MODE_NAME (mode), ofs);
297 break;
299 case SCRATCH: fputs ("scratch", file); break;
300 case CONCAT: ra_print_rtx_2op (file, x); break;
301 case HIGH: ra_print_rtx_1op (file, x); break;
302 case LO_SUM:
303 fputs ("(", file);
304 ra_print_rtx (file, XEXP (x, 0), 0);
305 fputs (" + lo(", file);
306 ra_print_rtx (file, XEXP (x, 1), 0);
307 fputs ("))", file);
308 break;
309 case MEM: fputs ("[", file);
310 ra_print_rtx (file, XEXP (x, 0), 0);
311 fprintf (file, "]:%s", GET_MODE_NAME (GET_MODE (x)));
312 /* XXX print alias set too ?? */
313 break;
314 case LABEL_REF:
316 rtx sub = XEXP (x, 0);
317 if (GET_CODE (sub) == NOTE
318 && NOTE_LINE_NUMBER (sub) == NOTE_INSN_DELETED_LABEL)
319 fprintf (file, "(deleted uid=%d)", INSN_UID (sub));
320 else if (GET_CODE (sub) == CODE_LABEL)
321 fprintf (file, "L%d", CODE_LABEL_NUMBER (sub));
322 else
323 fprintf (file, "(nonlabel uid=%d)", INSN_UID (sub));
325 break;
326 case SYMBOL_REF:
327 fprintf (file, "sym(\"%s\")", XSTR (x, 0)); break;
328 case CC0: fputs ("cc0", file); break;
329 default: print_inline_rtx (file, x, 0); break;
333 /* Print a general rtx X to FILE in nice infix form.
334 If WITH_PN is set, and X is one of the toplevel constructs
335 (insns, notes, labels or barriers), then print also the UIDs of
336 the preceding and following insn. */
338 void
339 ra_print_rtx (FILE *file, rtx x, int with_pn)
341 enum rtx_code code;
342 char class;
343 int unhandled = 0;
344 if (!x)
345 return;
346 code = GET_CODE (x);
347 class = GET_RTX_CLASS (code);
349 /* First handle the insn like constructs. */
350 if (INSN_P (x) || code == NOTE || code == CODE_LABEL || code == BARRIER)
352 if (INSN_P (x))
353 fputs (" ", file);
354 /* Non-insns are prefixed by a ';'. */
355 if (code == BARRIER)
356 fputs ("; ", file);
357 else if (code == NOTE)
358 /* But notes are indented very far right. */
359 fprintf (file, "\t\t\t\t\t; ");
360 else if (code == CODE_LABEL)
361 /* And labels have their Lxx name first, before the actual UID. */
363 fprintf (file, "L%d:\t; ", CODE_LABEL_NUMBER (x));
364 if (LABEL_NAME (x))
365 fprintf (file, "(%s) ", LABEL_NAME (x));
366 switch (LABEL_KIND (x))
368 case LABEL_NORMAL: break;
369 case LABEL_STATIC_ENTRY: fputs (" (entry)", file); break;
370 case LABEL_GLOBAL_ENTRY: fputs (" (global entry)", file); break;
371 case LABEL_WEAK_ENTRY: fputs (" (weak entry)", file); break;
372 default: abort();
374 fprintf (file, " [%d uses] uid=(", LABEL_NUSES (x));
376 fprintf (file, "%d", INSN_UID (x));
377 if (with_pn)
378 fprintf (file, " %d %d", PREV_INSN (x) ? INSN_UID (PREV_INSN (x)) : 0,
379 NEXT_INSN (x) ? INSN_UID (NEXT_INSN (x)) : 0);
380 if (code == BARRIER)
381 fputs (" -------- barrier ---------", file);
382 else if (code == CODE_LABEL)
383 fputs (")", file);
384 else if (code == NOTE)
386 int ln = NOTE_LINE_NUMBER (x);
387 if (ln >= (int) NOTE_INSN_BIAS && ln < (int) NOTE_INSN_MAX)
388 fprintf (file, " %s", GET_NOTE_INSN_NAME (ln));
389 else
391 fprintf (file, " line %d", ln);
392 if (NOTE_SOURCE_FILE (x))
393 fprintf (file, ":%s", NOTE_SOURCE_FILE (x));
396 else
398 fprintf (file, "\t");
399 ra_print_rtx (file, PATTERN (x), 0);
401 return;
403 switch (code)
405 /* Top-level stuff. */
406 case PARALLEL:
408 int j;
409 for (j = 0; j < XVECLEN (x, 0); j++)
411 if (j)
412 fputs ("\t;; ", file);
413 ra_print_rtx (file, XVECEXP (x, 0, j), 0);
415 break;
417 case UNSPEC: case UNSPEC_VOLATILE:
419 int j;
420 fprintf (file, "unspec%s(%d",
421 (code == UNSPEC) ? "" : "_vol", XINT (x, 1));
422 for (j = 0; j < XVECLEN (x, 0); j++)
424 fputs (", ", file);
425 ra_print_rtx (file, XVECEXP (x, 0, j), 0);
427 fputs (")", file);
428 break;
430 case SET:
431 if (GET_CODE (SET_DEST (x)) == PC)
433 if (GET_CODE (SET_SRC (x)) == IF_THEN_ELSE
434 && GET_CODE (XEXP (SET_SRC(x), 2)) == PC)
436 fputs ("if ", file);
437 ra_print_rtx (file, XEXP (SET_SRC (x), 0), 0);
438 fputs (" jump ", file);
439 ra_print_rtx (file, XEXP (SET_SRC (x), 1), 0);
441 else
443 fputs ("jump ", file);
444 ra_print_rtx (file, SET_SRC (x), 0);
447 else
449 ra_print_rtx (file, SET_DEST (x), 0);
450 fputs (" <= ", file);
451 ra_print_rtx (file, SET_SRC (x), 0);
453 break;
454 case USE:
455 fputs ("use <= ", file);
456 ra_print_rtx (file, XEXP (x, 0), 0);
457 break;
458 case CLOBBER:
459 ra_print_rtx (file, XEXP (x, 0), 0);
460 fputs (" <= clobber", file);
461 break;
462 case CALL:
463 fputs ("call ", file);
464 ra_print_rtx (file, XEXP (x, 0), 0); /* Address */
465 fputs (" numargs=", file);
466 ra_print_rtx (file, XEXP (x, 1), 0); /* Num arguments */
467 break;
468 case RETURN:
469 fputs ("return", file);
470 break;
471 case TRAP_IF:
472 fputs ("if (", file);
473 ra_print_rtx (file, XEXP (x, 0), 0);
474 fputs (") trap ", file);
475 ra_print_rtx (file, XEXP (x, 1), 0);
476 break;
477 case RESX:
478 fprintf (file, "resx from region %d", XINT (x, 0));
479 break;
481 /* Different things of class 'x' */
482 case SUBREG: ra_print_rtx_object (file, x); break;
483 case STRICT_LOW_PART:
484 fputs ("low(", file);
485 ra_print_rtx (file, XEXP (x, 0), 0);
486 fputs (")", file);
487 break;
488 default:
489 unhandled = 1;
490 break;
492 if (!unhandled)
493 return;
494 if (class == '1')
495 ra_print_rtx_1op (file, x);
496 else if (class == '2' || class == 'c' || class == '<')
497 ra_print_rtx_2op (file, x);
498 else if (class == '3' || class == 'b')
499 ra_print_rtx_3op (file, x);
500 else if (class == 'o')
501 ra_print_rtx_object (file, x);
502 else
503 print_inline_rtx (file, x, 0);
506 /* This only calls ra_print_rtx(), but emits a final newline. */
508 void
509 ra_print_rtx_top (FILE *file, rtx x, int with_pn)
511 ra_print_rtx (file, x, with_pn);
512 fprintf (file, "\n");
515 /* Callable from gdb. This prints rtx X onto stderr. */
517 void
518 ra_debug_rtx (rtx x)
520 ra_print_rtx_top (stderr, x, 1);
523 /* This prints the content of basic block with index BBI.
524 The first and last insn are emitted with UIDs of prev and next insns. */
526 void
527 ra_debug_bbi (int bbi)
529 basic_block bb = BASIC_BLOCK (bbi);
530 rtx insn;
531 for (insn = BB_HEAD (bb); insn; insn = NEXT_INSN (insn))
533 ra_print_rtx_top (stderr, insn,
534 (insn == BB_HEAD (bb) || insn == BB_END (bb)));
535 fprintf (stderr, "\n");
536 if (insn == BB_END (bb))
537 break;
541 /* Beginning from INSN, emit NUM insns (if NUM is non-negative)
542 or emit a window of NUM insns around INSN, to stderr. */
544 void
545 ra_debug_insns (rtx insn, int num)
547 int i, count = (num == 0 ? 1 : num < 0 ? -num : num);
548 if (num < 0)
549 for (i = count / 2; i > 0 && PREV_INSN (insn); i--)
550 insn = PREV_INSN (insn);
551 for (i = count; i > 0 && insn; insn = NEXT_INSN (insn), i--)
553 if (GET_CODE (insn) == CODE_LABEL)
554 fprintf (stderr, "\n");
555 ra_print_rtx_top (stderr, insn, (i == count || i == 1));
559 /* Beginning with INSN, emit the whole insn chain into FILE.
560 This also outputs comments when basic blocks start or end and omits
561 some notes, if flag_ra_dump_notes is zero. */
563 void
564 ra_print_rtl_with_bb (FILE *file, rtx insn)
566 basic_block last_bb, bb;
567 unsigned int num = 0;
568 if (!insn)
569 fputs ("nil", file);
570 last_bb = NULL;
571 for (; insn; insn = NEXT_INSN (insn))
573 if (GET_CODE (insn) == BARRIER)
574 bb = NULL;
575 else
576 bb = BLOCK_FOR_INSN (insn);
577 if (bb != last_bb)
579 if (last_bb)
580 fprintf (file, ";; End of basic block %d\n", last_bb->index);
581 if (bb)
582 fprintf (file, ";; Begin of basic block %d\n", bb->index);
583 last_bb = bb;
585 if (GET_CODE (insn) == CODE_LABEL)
586 fputc ('\n', file);
587 if (GET_CODE (insn) == NOTE)
589 /* Ignore basic block and maybe other notes not referencing
590 deleted things. */
591 if (NOTE_LINE_NUMBER (insn) != NOTE_INSN_BASIC_BLOCK
592 && (flag_ra_dump_notes
593 || NOTE_LINE_NUMBER (insn) == NOTE_INSN_DELETED
594 || NOTE_LINE_NUMBER (insn) == NOTE_INSN_DELETED_LABEL))
596 ra_print_rtx_top (file, insn, (num == 0 || !NEXT_INSN (insn)));
597 num++;
600 else
602 ra_print_rtx_top (file, insn, (num == 0 || !NEXT_INSN (insn)));
603 num++;
608 /* Count how many insns were seen how often, while building the interference
609 graph, and prints the findings. */
611 void
612 dump_number_seen (void)
614 #define N 17
615 int num[N];
616 int i;
618 for (i = 0; i < N; i++)
619 num[i] = 0;
620 for (i = 0; i < get_max_uid (); i++)
621 if (number_seen[i] < N - 1)
622 num[number_seen[i]]++;
623 else
624 num[N - 1]++;
625 for (i = 0; i < N - 1; i++)
626 if (num[i])
627 ra_debug_msg (DUMP_PROCESS, "%d insns seen %d times\n", num[i], i);
628 if (num[N - 1])
629 ra_debug_msg (DUMP_PROCESS, "%d insns seen %d and more times\n", num[i],
630 N - 1);
631 ra_debug_msg (DUMP_PROCESS, "from overall %d insns\n", get_max_uid ());
632 #undef N
635 /* Dump the interference graph, the move list and the webs. */
637 void
638 dump_igraph (struct df *df ATTRIBUTE_UNUSED)
640 struct move_list *ml;
641 unsigned int def1, def2;
642 int num = 0;
643 int num2;
644 unsigned int i;
645 if (!rtl_dump_file || (debug_new_regalloc & (DUMP_IGRAPH | DUMP_WEBS)) == 0)
646 return;
647 ra_debug_msg (DUMP_IGRAPH, "conflicts:\n ");
648 for (def1 = 0; def1 < num_webs; def1++)
650 int num1 = num;
651 num2 = 0;
652 for (def2 = 0; def2 < num_webs; def2++)
653 if (def1 != def2 && TEST_BIT (igraph, igraph_index (def1, def2)))
655 if (num1 == num)
657 if (SUBWEB_P (ID2WEB (def1)))
658 ra_debug_msg (DUMP_IGRAPH, "%d (SUBREG %d, %d) with ", def1,
659 ID2WEB (def1)->regno,
660 SUBREG_BYTE (ID2WEB (def1)->orig_x));
661 else
662 ra_debug_msg (DUMP_IGRAPH, "%d (REG %d) with ", def1,
663 ID2WEB (def1)->regno);
665 if ((num2 % 9) == 8)
666 ra_debug_msg (DUMP_IGRAPH, "\n ");
667 num++;
668 num2++;
669 if (SUBWEB_P (ID2WEB (def2)))
670 ra_debug_msg (DUMP_IGRAPH, "%d(%d,%d) ", def2, ID2WEB (def2)->regno,
671 SUBREG_BYTE (ID2WEB (def2)->orig_x));
672 else
673 ra_debug_msg (DUMP_IGRAPH, "%d(%d) ", def2, ID2WEB (def2)->regno);
675 if (num1 != num)
676 ra_debug_msg (DUMP_IGRAPH, "\n ");
678 ra_debug_msg (DUMP_IGRAPH, "\n");
679 for (ml = wl_moves; ml; ml = ml->next)
680 if (ml->move)
682 ra_debug_msg (DUMP_IGRAPH, "move: insn %d: Web %d <-- Web %d\n",
683 INSN_UID (ml->move->insn), ml->move->target_web->id,
684 ml->move->source_web->id);
686 ra_debug_msg (DUMP_WEBS, "\nWebs:\n");
687 for (i = 0; i < num_webs; i++)
689 struct web *web = ID2WEB (i);
691 ra_debug_msg (DUMP_WEBS, " %4d : regno %3d", i, web->regno);
692 if (SUBWEB_P (web))
694 ra_debug_msg (DUMP_WEBS, " sub %d", SUBREG_BYTE (web->orig_x));
695 ra_debug_msg (DUMP_WEBS, " par %d", find_web_for_subweb (web)->id);
697 ra_debug_msg (DUMP_WEBS, " +%d (span %d, cost "
698 HOST_WIDE_INT_PRINT_DEC ") (%s)",
699 web->add_hardregs, web->span_deaths, web->spill_cost,
700 reg_class_names[web->regclass]);
701 if (web->spill_temp == 1)
702 ra_debug_msg (DUMP_WEBS, " (spilltemp)");
703 else if (web->spill_temp == 2)
704 ra_debug_msg (DUMP_WEBS, " (spilltem2)");
705 else if (web->spill_temp == 3)
706 ra_debug_msg (DUMP_WEBS, " (short)");
707 if (web->type == PRECOLORED)
708 ra_debug_msg (DUMP_WEBS, " (precolored, color=%d)", web->color);
709 else if (find_web_for_subweb (web)->num_uses == 0)
710 ra_debug_msg (DUMP_WEBS, " dead");
711 if (web->crosses_call)
712 ra_debug_msg (DUMP_WEBS, " xcall");
713 if (web->regno >= max_normal_pseudo)
714 ra_debug_msg (DUMP_WEBS, " stack");
715 ra_debug_msg (DUMP_WEBS, "\n");
719 /* Dump the interference graph and webs in a format easily
720 parsable by programs. Used to emit real world interference graph
721 to my custom graph colorizer. */
723 void
724 dump_igraph_machine (void)
726 unsigned int i;
728 if (!rtl_dump_file || (debug_new_regalloc & DUMP_IGRAPH_M) == 0)
729 return;
730 ra_debug_msg (DUMP_IGRAPH_M, "g %d %d\n", num_webs - num_subwebs,
731 FIRST_PSEUDO_REGISTER);
732 for (i = 0; i < num_webs - num_subwebs; i++)
734 struct web *web = ID2WEB (i);
735 struct conflict_link *cl;
736 int flags = 0;
737 int numc = 0;
738 int col = 0;
739 flags = web->spill_temp & 0xF;
740 flags |= ((web->type == PRECOLORED) ? 1 : 0) << 4;
741 flags |= (web->add_hardregs & 0xF) << 5;
742 for (cl = web->conflict_list; cl; cl = cl->next)
743 if (cl->t->id < web->id)
744 numc++;
745 ra_debug_msg (DUMP_IGRAPH_M, "n %d %d %d %d %d %d %d\n",
746 web->id, web->color, flags,
747 (unsigned int)web->spill_cost, web->num_defs, web->num_uses,
748 numc);
749 if (web->type != PRECOLORED)
751 ra_debug_msg (DUMP_IGRAPH_M, "s %d", web->id);
752 while (1)
754 unsigned int u = 0;
755 int n;
756 for (n = 0; n < 32 && col < FIRST_PSEUDO_REGISTER; n++, col++)
757 if (TEST_HARD_REG_BIT (web->usable_regs, col))
758 u |= 1 << n;
759 ra_debug_msg (DUMP_IGRAPH_M, " %u", u);
760 if (col >= FIRST_PSEUDO_REGISTER)
761 break;
763 ra_debug_msg (DUMP_IGRAPH_M, "\n");
765 if (numc)
767 ra_debug_msg (DUMP_IGRAPH_M, "c %d", web->id);
768 for (cl = web->conflict_list; cl; cl = cl->next)
770 if (cl->t->id < web->id)
771 ra_debug_msg (DUMP_IGRAPH_M, " %d", cl->t->id);
773 ra_debug_msg (DUMP_IGRAPH_M, "\n");
776 ra_debug_msg (DUMP_IGRAPH_M, "e\n");
779 /* This runs after colorization and changing the insn stream.
780 It temporarily replaces all pseudo registers with their colors,
781 and emits information, if the resulting insns are strictly valid. */
783 void
784 dump_constraints (void)
786 rtx insn;
787 int i;
788 if (!rtl_dump_file || (debug_new_regalloc & DUMP_CONSTRAINTS) == 0)
789 return;
790 for (i = FIRST_PSEUDO_REGISTER; i < ra_max_regno; i++)
791 if (regno_reg_rtx[i] && GET_CODE (regno_reg_rtx[i]) == REG)
792 REGNO (regno_reg_rtx[i])
793 = ra_reg_renumber[i] >= 0 ? ra_reg_renumber[i] : i;
794 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
795 if (INSN_P (insn))
797 int code;
798 int uid = INSN_UID (insn);
799 int o;
800 /* Don't simply force rerecognition, as combine might left us
801 with some unrecognizable ones, which later leads to aborts
802 in regclass, if we now destroy the remembered INSN_CODE(). */
803 /*INSN_CODE (insn) = -1;*/
804 code = recog_memoized (insn);
805 if (code < 0)
807 ra_debug_msg (DUMP_CONSTRAINTS,
808 "%d: asm insn or not recognizable.\n", uid);
809 continue;
811 ra_debug_msg (DUMP_CONSTRAINTS,
812 "%d: code %d {%s}, %d operands, constraints: ",
813 uid, code, insn_data[code].name, recog_data.n_operands);
814 extract_insn (insn);
815 /*preprocess_constraints ();*/
816 for (o = 0; o < recog_data.n_operands; o++)
818 ra_debug_msg (DUMP_CONSTRAINTS,
819 "%d:%s ", o, recog_data.constraints[o]);
821 if (constrain_operands (1))
822 ra_debug_msg (DUMP_CONSTRAINTS, "matches strictly alternative %d",
823 which_alternative);
824 else
825 ra_debug_msg (DUMP_CONSTRAINTS, "doesn't match strictly");
826 ra_debug_msg (DUMP_CONSTRAINTS, "\n");
828 for (i = FIRST_PSEUDO_REGISTER; i < ra_max_regno; i++)
829 if (regno_reg_rtx[i] && GET_CODE (regno_reg_rtx[i]) == REG)
830 REGNO (regno_reg_rtx[i]) = i;
833 /* This counts and emits the cumulated cost of all spilled webs,
834 preceded by a custom message MSG, with debug level LEVEL. */
836 void
837 dump_graph_cost (unsigned int level, const char *msg)
839 unsigned int i;
840 unsigned HOST_WIDE_INT cost;
841 if (!rtl_dump_file || (debug_new_regalloc & level) == 0)
842 return;
844 cost = 0;
845 for (i = 0; i < num_webs; i++)
847 struct web *web = id2web[i];
848 if (alias (web)->type == SPILLED)
849 cost += web->orig_spill_cost;
851 ra_debug_msg (level, " spill cost of graph (%s) = "
852 HOST_WIDE_INT_PRINT_UNSIGNED "\n",
853 msg ? msg : "", cost);
856 /* Dump the color assignment per web, the coalesced and spilled webs. */
858 void
859 dump_ra (struct df *df ATTRIBUTE_UNUSED)
861 struct web *web;
862 struct dlist *d;
863 if (!rtl_dump_file || (debug_new_regalloc & DUMP_RESULTS) == 0)
864 return;
866 ra_debug_msg (DUMP_RESULTS, "\nColored:\n");
867 for (d = WEBS(COLORED); d; d = d->next)
869 web = DLIST_WEB (d);
870 ra_debug_msg (DUMP_RESULTS, " %4d : color %d\n", web->id, web->color);
872 ra_debug_msg (DUMP_RESULTS, "\nCoalesced:\n");
873 for (d = WEBS(COALESCED); d; d = d->next)
875 web = DLIST_WEB (d);
876 ra_debug_msg (DUMP_RESULTS, " %4d : to web %d, color %d\n", web->id,
877 alias (web)->id, web->color);
879 ra_debug_msg (DUMP_RESULTS, "\nSpilled:\n");
880 for (d = WEBS(SPILLED); d; d = d->next)
882 web = DLIST_WEB (d);
883 ra_debug_msg (DUMP_RESULTS, " %4d\n", web->id);
885 ra_debug_msg (DUMP_RESULTS, "\n");
886 dump_cost (DUMP_RESULTS);
889 /* Calculate and dump the cumulated costs of certain types of insns
890 (loads, stores and copies). */
892 void
893 dump_static_insn_cost (FILE *file, const char *message, const char *prefix)
895 struct cost
897 unsigned HOST_WIDE_INT cost;
898 unsigned int count;
900 basic_block bb;
901 struct cost load, store, regcopy, selfcopy, overall;
902 memset (&load, 0, sizeof(load));
903 memset (&store, 0, sizeof(store));
904 memset (&regcopy, 0, sizeof(regcopy));
905 memset (&selfcopy, 0, sizeof(selfcopy));
906 memset (&overall, 0, sizeof(overall));
908 if (!file)
909 return;
911 FOR_EACH_BB (bb)
913 unsigned HOST_WIDE_INT block_cost = bb->frequency;
914 rtx insn, set;
915 for (insn = BB_HEAD (bb); insn; insn = NEXT_INSN (insn))
917 /* Yes, yes. We don't calculate the costs precisely.
918 Only for "simple enough" insns. Those containing single
919 sets only. */
920 if (INSN_P (insn) && ((set = single_set (insn)) != NULL))
922 rtx src = SET_SRC (set);
923 rtx dest = SET_DEST (set);
924 struct cost *pcost = NULL;
925 overall.cost += block_cost;
926 overall.count++;
927 if (rtx_equal_p (src, dest))
928 pcost = &selfcopy;
929 else if (GET_CODE (src) == GET_CODE (dest)
930 && ((GET_CODE (src) == REG)
931 || (GET_CODE (src) == SUBREG
932 && GET_CODE (SUBREG_REG (src)) == REG
933 && GET_CODE (SUBREG_REG (dest)) == REG)))
934 pcost = &regcopy;
935 else
937 if (GET_CODE (src) == SUBREG)
938 src = SUBREG_REG (src);
939 if (GET_CODE (dest) == SUBREG)
940 dest = SUBREG_REG (dest);
941 if (GET_CODE (src) == MEM && GET_CODE (dest) != MEM
942 && memref_is_stack_slot (src))
943 pcost = &load;
944 else if (GET_CODE (src) != MEM && GET_CODE (dest) == MEM
945 && memref_is_stack_slot (dest))
946 pcost = &store;
948 if (pcost)
950 pcost->cost += block_cost;
951 pcost->count++;
954 if (insn == BB_END (bb))
955 break;
959 if (!prefix)
960 prefix = "";
961 fprintf (file, "static insn cost %s\n", message ? message : "");
962 fprintf (file, " %soverall:\tnum=%6d\tcost=% 8" HOST_WIDE_INT_PRINT "d\n",
963 prefix, overall.count, overall.cost);
964 fprintf (file, " %sloads:\tnum=%6d\tcost=% 8" HOST_WIDE_INT_PRINT "d\n",
965 prefix, load.count, load.cost);
966 fprintf (file, " %sstores:\tnum=%6d\tcost=% 8" HOST_WIDE_INT_PRINT "d\n",
967 prefix, store.count, store.cost);
968 fprintf (file, " %sregcopy:\tnum=%6d\tcost=% 8" HOST_WIDE_INT_PRINT "d\n",
969 prefix, regcopy.count, regcopy.cost);
970 fprintf (file, " %sselfcpy:\tnum=%6d\tcost=% 8" HOST_WIDE_INT_PRINT "d\n",
971 prefix, selfcopy.count, selfcopy.cost);
974 /* Returns nonzero, if WEB1 and WEB2 have some possible
975 hardregs in common. */
978 web_conflicts_p (struct web *web1, struct web *web2)
980 if (web1->type == PRECOLORED && web2->type == PRECOLORED)
981 return 0;
983 if (web1->type == PRECOLORED)
984 return TEST_HARD_REG_BIT (web2->usable_regs, web1->regno);
986 if (web2->type == PRECOLORED)
987 return TEST_HARD_REG_BIT (web1->usable_regs, web2->regno);
989 return hard_regs_intersect_p (&web1->usable_regs, &web2->usable_regs);
992 /* Dump all uids of insns in which WEB is mentioned. */
994 void
995 dump_web_insns (struct web *web)
997 unsigned int i;
999 ra_debug_msg (DUMP_EVER, "Web: %i(%i)+%i class: %s freedom: %i degree %i\n",
1000 web->id, web->regno, web->add_hardregs,
1001 reg_class_names[web->regclass],
1002 web->num_freedom, web->num_conflicts);
1003 ra_debug_msg (DUMP_EVER, " def insns:");
1005 for (i = 0; i < web->num_defs; ++i)
1007 ra_debug_msg (DUMP_EVER, " %d ", INSN_UID (web->defs[i]->insn));
1010 ra_debug_msg (DUMP_EVER, "\n use insns:");
1011 for (i = 0; i < web->num_uses; ++i)
1013 ra_debug_msg (DUMP_EVER, " %d ", INSN_UID (web->uses[i]->insn));
1015 ra_debug_msg (DUMP_EVER, "\n");
1018 /* Dump conflicts for web WEB. */
1020 void
1021 dump_web_conflicts (struct web *web)
1023 int num = 0;
1024 unsigned int def2;
1026 ra_debug_msg (DUMP_EVER, "Web: %i(%i)+%i class: %s freedom: %i degree %i\n",
1027 web->id, web->regno, web->add_hardregs,
1028 reg_class_names[web->regclass],
1029 web->num_freedom, web->num_conflicts);
1031 for (def2 = 0; def2 < num_webs; def2++)
1032 if (TEST_BIT (igraph, igraph_index (web->id, def2)) && web->id != def2)
1034 if ((num % 9) == 5)
1035 ra_debug_msg (DUMP_EVER, "\n ");
1036 num++;
1038 ra_debug_msg (DUMP_EVER, " %d(%d)", def2, id2web[def2]->regno);
1039 if (id2web[def2]->add_hardregs)
1040 ra_debug_msg (DUMP_EVER, "+%d", id2web[def2]->add_hardregs);
1042 if (web_conflicts_p (web, id2web[def2]))
1043 ra_debug_msg (DUMP_EVER, "/x");
1045 if (id2web[def2]->type == SELECT)
1046 ra_debug_msg (DUMP_EVER, "/s");
1048 if (id2web[def2]->type == COALESCED)
1049 ra_debug_msg (DUMP_EVER,"/c/%d", alias (id2web[def2])->id);
1051 ra_debug_msg (DUMP_EVER, "\n");
1053 struct conflict_link *wl;
1054 num = 0;
1055 ra_debug_msg (DUMP_EVER, "By conflicts: ");
1056 for (wl = web->conflict_list; wl; wl = wl->next)
1058 struct web* w = wl->t;
1059 if ((num % 9) == 8)
1060 ra_debug_msg (DUMP_EVER, "\n ");
1061 num++;
1062 ra_debug_msg (DUMP_EVER, "%d(%d)%s ", w->id, w->regno,
1063 web_conflicts_p (web, w) ? "+" : "");
1065 ra_debug_msg (DUMP_EVER, "\n");
1069 /* Output HARD_REG_SET to stderr. */
1071 void
1072 debug_hard_reg_set (HARD_REG_SET set)
1074 int i;
1075 for (i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
1077 if (TEST_HARD_REG_BIT (set, i))
1079 fprintf (stderr, "%s ", reg_names[i]);
1082 fprintf (stderr, "\n");
1086 vim:cinoptions={.5s,g0,p5,t0,(0,^-0.5s,n-0.5s:tw=78:cindent:sw=4: