PR optimization/9325, PR java/6391
[official-gcc.git] / gcc / ra-debug.c
blobacddbe128cd71b87319cf24b4b9472007ea9644e
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; insn; insn = NEXT_INSN (insn))
533 ra_print_rtx_top (stderr, insn, (insn == bb->head || insn == bb->end));
534 fprintf (stderr, "\n");
535 if (insn == bb->end)
536 break;
540 /* Beginning from INSN, emit NUM insns (if NUM is non-negative)
541 or emit a window of NUM insns around INSN, to stderr. */
543 void
544 ra_debug_insns (rtx insn, int num)
546 int i, count = (num == 0 ? 1 : num < 0 ? -num : num);
547 if (num < 0)
548 for (i = count / 2; i > 0 && PREV_INSN (insn); i--)
549 insn = PREV_INSN (insn);
550 for (i = count; i > 0 && insn; insn = NEXT_INSN (insn), i--)
552 if (GET_CODE (insn) == CODE_LABEL)
553 fprintf (stderr, "\n");
554 ra_print_rtx_top (stderr, insn, (i == count || i == 1));
558 /* Beginning with INSN, emit the whole insn chain into FILE.
559 This also outputs comments when basic blocks start or end and omits
560 some notes, if flag_ra_dump_notes is zero. */
562 void
563 ra_print_rtl_with_bb (FILE *file, rtx insn)
565 basic_block last_bb, bb;
566 unsigned int num = 0;
567 if (!insn)
568 fputs ("nil", file);
569 last_bb = NULL;
570 for (; insn; insn = NEXT_INSN (insn))
572 if (GET_CODE (insn) == BARRIER)
573 bb = NULL;
574 else
575 bb = BLOCK_FOR_INSN (insn);
576 if (bb != last_bb)
578 if (last_bb)
579 fprintf (file, ";; End of basic block %d\n", last_bb->index);
580 if (bb)
581 fprintf (file, ";; Begin of basic block %d\n", bb->index);
582 last_bb = bb;
584 if (GET_CODE (insn) == CODE_LABEL)
585 fputc ('\n', file);
586 if (GET_CODE (insn) == NOTE)
588 /* Ignore basic block and maybe other notes not referencing
589 deleted things. */
590 if (NOTE_LINE_NUMBER (insn) != NOTE_INSN_BASIC_BLOCK
591 && (flag_ra_dump_notes
592 || NOTE_LINE_NUMBER (insn) == NOTE_INSN_DELETED
593 || NOTE_LINE_NUMBER (insn) == NOTE_INSN_DELETED_LABEL))
595 ra_print_rtx_top (file, insn, (num == 0 || !NEXT_INSN (insn)));
596 num++;
599 else
601 ra_print_rtx_top (file, insn, (num == 0 || !NEXT_INSN (insn)));
602 num++;
607 /* Count how many insns were seen how often, while building the interference
608 graph, and prints the findings. */
610 void
611 dump_number_seen (void)
613 #define N 17
614 int num[N];
615 int i;
617 for (i = 0; i < N; i++)
618 num[i] = 0;
619 for (i = 0; i < get_max_uid (); i++)
620 if (number_seen[i] < N - 1)
621 num[number_seen[i]]++;
622 else
623 num[N - 1]++;
624 for (i = 0; i < N - 1; i++)
625 if (num[i])
626 ra_debug_msg (DUMP_PROCESS, "%d insns seen %d times\n", num[i], i);
627 if (num[N - 1])
628 ra_debug_msg (DUMP_PROCESS, "%d insns seen %d and more times\n", num[i],
629 N - 1);
630 ra_debug_msg (DUMP_PROCESS, "from overall %d insns\n", get_max_uid ());
631 #undef N
634 /* Dump the interference graph, the move list and the webs. */
636 void
637 dump_igraph (struct df *df ATTRIBUTE_UNUSED)
639 struct move_list *ml;
640 unsigned int def1, def2;
641 int num = 0;
642 int num2;
643 unsigned int i;
644 if (!rtl_dump_file || (debug_new_regalloc & (DUMP_IGRAPH | DUMP_WEBS)) == 0)
645 return;
646 ra_debug_msg (DUMP_IGRAPH, "conflicts:\n ");
647 for (def1 = 0; def1 < num_webs; def1++)
649 int num1 = num;
650 num2 = 0;
651 for (def2 = 0; def2 < num_webs; def2++)
652 if (def1 != def2 && TEST_BIT (igraph, igraph_index (def1, def2)))
654 if (num1 == num)
656 if (SUBWEB_P (ID2WEB (def1)))
657 ra_debug_msg (DUMP_IGRAPH, "%d (SUBREG %d, %d) with ", def1,
658 ID2WEB (def1)->regno,
659 SUBREG_BYTE (ID2WEB (def1)->orig_x));
660 else
661 ra_debug_msg (DUMP_IGRAPH, "%d (REG %d) with ", def1,
662 ID2WEB (def1)->regno);
664 if ((num2 % 9) == 8)
665 ra_debug_msg (DUMP_IGRAPH, "\n ");
666 num++;
667 num2++;
668 if (SUBWEB_P (ID2WEB (def2)))
669 ra_debug_msg (DUMP_IGRAPH, "%d(%d,%d) ", def2, ID2WEB (def2)->regno,
670 SUBREG_BYTE (ID2WEB (def2)->orig_x));
671 else
672 ra_debug_msg (DUMP_IGRAPH, "%d(%d) ", def2, ID2WEB (def2)->regno);
674 if (num1 != num)
675 ra_debug_msg (DUMP_IGRAPH, "\n ");
677 ra_debug_msg (DUMP_IGRAPH, "\n");
678 for (ml = wl_moves; ml; ml = ml->next)
679 if (ml->move)
681 ra_debug_msg (DUMP_IGRAPH, "move: insn %d: Web %d <-- Web %d\n",
682 INSN_UID (ml->move->insn), ml->move->target_web->id,
683 ml->move->source_web->id);
685 ra_debug_msg (DUMP_WEBS, "\nWebs:\n");
686 for (i = 0; i < num_webs; i++)
688 struct web *web = ID2WEB (i);
690 ra_debug_msg (DUMP_WEBS, " %4d : regno %3d", i, web->regno);
691 if (SUBWEB_P (web))
693 ra_debug_msg (DUMP_WEBS, " sub %d", SUBREG_BYTE (web->orig_x));
694 ra_debug_msg (DUMP_WEBS, " par %d", find_web_for_subweb (web)->id);
696 ra_debug_msg (DUMP_WEBS, " +%d (span %d, cost "
697 HOST_WIDE_INT_PRINT_DEC ") (%s)",
698 web->add_hardregs, web->span_deaths, web->spill_cost,
699 reg_class_names[web->regclass]);
700 if (web->spill_temp == 1)
701 ra_debug_msg (DUMP_WEBS, " (spilltemp)");
702 else if (web->spill_temp == 2)
703 ra_debug_msg (DUMP_WEBS, " (spilltem2)");
704 else if (web->spill_temp == 3)
705 ra_debug_msg (DUMP_WEBS, " (short)");
706 if (web->type == PRECOLORED)
707 ra_debug_msg (DUMP_WEBS, " (precolored, color=%d)", web->color);
708 else if (find_web_for_subweb (web)->num_uses == 0)
709 ra_debug_msg (DUMP_WEBS, " dead");
710 if (web->crosses_call)
711 ra_debug_msg (DUMP_WEBS, " xcall");
712 if (web->regno >= max_normal_pseudo)
713 ra_debug_msg (DUMP_WEBS, " stack");
714 ra_debug_msg (DUMP_WEBS, "\n");
718 /* Dump the interference graph and webs in a format easily
719 parsable by programs. Used to emit real world interference graph
720 to my custom graph colorizer. */
722 void
723 dump_igraph_machine (void)
725 unsigned int i;
727 if (!rtl_dump_file || (debug_new_regalloc & DUMP_IGRAPH_M) == 0)
728 return;
729 ra_debug_msg (DUMP_IGRAPH_M, "g %d %d\n", num_webs - num_subwebs,
730 FIRST_PSEUDO_REGISTER);
731 for (i = 0; i < num_webs - num_subwebs; i++)
733 struct web *web = ID2WEB (i);
734 struct conflict_link *cl;
735 int flags = 0;
736 int numc = 0;
737 int col = 0;
738 flags = web->spill_temp & 0xF;
739 flags |= ((web->type == PRECOLORED) ? 1 : 0) << 4;
740 flags |= (web->add_hardregs & 0xF) << 5;
741 for (cl = web->conflict_list; cl; cl = cl->next)
742 if (cl->t->id < web->id)
743 numc++;
744 ra_debug_msg (DUMP_IGRAPH_M, "n %d %d %d %d %d %d %d\n",
745 web->id, web->color, flags,
746 (unsigned int)web->spill_cost, web->num_defs, web->num_uses,
747 numc);
748 if (web->type != PRECOLORED)
750 ra_debug_msg (DUMP_IGRAPH_M, "s %d", web->id);
751 while (1)
753 unsigned int u = 0;
754 int n;
755 for (n = 0; n < 32 && col < FIRST_PSEUDO_REGISTER; n++, col++)
756 if (TEST_HARD_REG_BIT (web->usable_regs, col))
757 u |= 1 << n;
758 ra_debug_msg (DUMP_IGRAPH_M, " %u", u);
759 if (col >= FIRST_PSEUDO_REGISTER)
760 break;
762 ra_debug_msg (DUMP_IGRAPH_M, "\n");
764 if (numc)
766 ra_debug_msg (DUMP_IGRAPH_M, "c %d", web->id);
767 for (cl = web->conflict_list; cl; cl = cl->next)
769 if (cl->t->id < web->id)
770 ra_debug_msg (DUMP_IGRAPH_M, " %d", cl->t->id);
772 ra_debug_msg (DUMP_IGRAPH_M, "\n");
775 ra_debug_msg (DUMP_IGRAPH_M, "e\n");
778 /* This runs after colorization and changing the insn stream.
779 It temporarily replaces all pseudo registers with their colors,
780 and emits information, if the resulting insns are strictly valid. */
782 void
783 dump_constraints (void)
785 rtx insn;
786 int i;
787 if (!rtl_dump_file || (debug_new_regalloc & DUMP_CONSTRAINTS) == 0)
788 return;
789 for (i = FIRST_PSEUDO_REGISTER; i < ra_max_regno; i++)
790 if (regno_reg_rtx[i] && GET_CODE (regno_reg_rtx[i]) == REG)
791 REGNO (regno_reg_rtx[i])
792 = ra_reg_renumber[i] >= 0 ? ra_reg_renumber[i] : i;
793 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
794 if (INSN_P (insn))
796 int code;
797 int uid = INSN_UID (insn);
798 int o;
799 /* Don't simply force rerecognition, as combine might left us
800 with some unrecognizable ones, which later leads to aborts
801 in regclass, if we now destroy the remembered INSN_CODE(). */
802 /*INSN_CODE (insn) = -1;*/
803 code = recog_memoized (insn);
804 if (code < 0)
806 ra_debug_msg (DUMP_CONSTRAINTS,
807 "%d: asm insn or not recognizable.\n", uid);
808 continue;
810 ra_debug_msg (DUMP_CONSTRAINTS,
811 "%d: code %d {%s}, %d operands, constraints: ",
812 uid, code, insn_data[code].name, recog_data.n_operands);
813 extract_insn (insn);
814 /*preprocess_constraints ();*/
815 for (o = 0; o < recog_data.n_operands; o++)
817 ra_debug_msg (DUMP_CONSTRAINTS,
818 "%d:%s ", o, recog_data.constraints[o]);
820 if (constrain_operands (1))
821 ra_debug_msg (DUMP_CONSTRAINTS, "matches strictly alternative %d",
822 which_alternative);
823 else
824 ra_debug_msg (DUMP_CONSTRAINTS, "doesn't match strictly");
825 ra_debug_msg (DUMP_CONSTRAINTS, "\n");
827 for (i = FIRST_PSEUDO_REGISTER; i < ra_max_regno; i++)
828 if (regno_reg_rtx[i] && GET_CODE (regno_reg_rtx[i]) == REG)
829 REGNO (regno_reg_rtx[i]) = i;
832 /* This counts and emits the cumulated cost of all spilled webs,
833 preceded by a custom message MSG, with debug level LEVEL. */
835 void
836 dump_graph_cost (unsigned int level, const char *msg)
838 unsigned int i;
839 unsigned HOST_WIDE_INT cost;
840 if (!rtl_dump_file || (debug_new_regalloc & level) == 0)
841 return;
843 cost = 0;
844 for (i = 0; i < num_webs; i++)
846 struct web *web = id2web[i];
847 if (alias (web)->type == SPILLED)
848 cost += web->orig_spill_cost;
850 ra_debug_msg (level, " spill cost of graph (%s) = "
851 HOST_WIDE_INT_PRINT_UNSIGNED "\n",
852 msg ? msg : "", cost);
855 /* Dump the color assignment per web, the coalesced and spilled webs. */
857 void
858 dump_ra (struct df *df ATTRIBUTE_UNUSED)
860 struct web *web;
861 struct dlist *d;
862 if (!rtl_dump_file || (debug_new_regalloc & DUMP_RESULTS) == 0)
863 return;
865 ra_debug_msg (DUMP_RESULTS, "\nColored:\n");
866 for (d = WEBS(COLORED); d; d = d->next)
868 web = DLIST_WEB (d);
869 ra_debug_msg (DUMP_RESULTS, " %4d : color %d\n", web->id, web->color);
871 ra_debug_msg (DUMP_RESULTS, "\nCoalesced:\n");
872 for (d = WEBS(COALESCED); d; d = d->next)
874 web = DLIST_WEB (d);
875 ra_debug_msg (DUMP_RESULTS, " %4d : to web %d, color %d\n", web->id,
876 alias (web)->id, web->color);
878 ra_debug_msg (DUMP_RESULTS, "\nSpilled:\n");
879 for (d = WEBS(SPILLED); d; d = d->next)
881 web = DLIST_WEB (d);
882 ra_debug_msg (DUMP_RESULTS, " %4d\n", web->id);
884 ra_debug_msg (DUMP_RESULTS, "\n");
885 dump_cost (DUMP_RESULTS);
888 /* Calculate and dump the cumulated costs of certain types of insns
889 (loads, stores and copies). */
891 void
892 dump_static_insn_cost (FILE *file, const char *message, const char *prefix)
894 struct cost
896 unsigned HOST_WIDE_INT cost;
897 unsigned int count;
899 basic_block bb;
900 struct cost load, store, regcopy, selfcopy, overall;
901 memset (&load, 0, sizeof(load));
902 memset (&store, 0, sizeof(store));
903 memset (&regcopy, 0, sizeof(regcopy));
904 memset (&selfcopy, 0, sizeof(selfcopy));
905 memset (&overall, 0, sizeof(overall));
907 if (!file)
908 return;
910 FOR_EACH_BB (bb)
912 unsigned HOST_WIDE_INT block_cost = bb->frequency;
913 rtx insn, set;
914 for (insn = bb->head; insn; insn = NEXT_INSN (insn))
916 /* Yes, yes. We don't calculate the costs precisely.
917 Only for "simple enough" insns. Those containing single
918 sets only. */
919 if (INSN_P (insn) && ((set = single_set (insn)) != NULL))
921 rtx src = SET_SRC (set);
922 rtx dest = SET_DEST (set);
923 struct cost *pcost = NULL;
924 overall.cost += block_cost;
925 overall.count++;
926 if (rtx_equal_p (src, dest))
927 pcost = &selfcopy;
928 else if (GET_CODE (src) == GET_CODE (dest)
929 && ((GET_CODE (src) == REG)
930 || (GET_CODE (src) == SUBREG
931 && GET_CODE (SUBREG_REG (src)) == REG
932 && GET_CODE (SUBREG_REG (dest)) == REG)))
933 pcost = &regcopy;
934 else
936 if (GET_CODE (src) == SUBREG)
937 src = SUBREG_REG (src);
938 if (GET_CODE (dest) == SUBREG)
939 dest = SUBREG_REG (dest);
940 if (GET_CODE (src) == MEM && GET_CODE (dest) != MEM
941 && memref_is_stack_slot (src))
942 pcost = &load;
943 else if (GET_CODE (src) != MEM && GET_CODE (dest) == MEM
944 && memref_is_stack_slot (dest))
945 pcost = &store;
947 if (pcost)
949 pcost->cost += block_cost;
950 pcost->count++;
953 if (insn == bb->end)
954 break;
958 if (!prefix)
959 prefix = "";
960 fprintf (file, "static insn cost %s\n", message ? message : "");
961 fprintf (file, " %soverall:\tnum=%6d\tcost=% 8" HOST_WIDE_INT_PRINT "d\n",
962 prefix, overall.count, overall.cost);
963 fprintf (file, " %sloads:\tnum=%6d\tcost=% 8" HOST_WIDE_INT_PRINT "d\n",
964 prefix, load.count, load.cost);
965 fprintf (file, " %sstores:\tnum=%6d\tcost=% 8" HOST_WIDE_INT_PRINT "d\n",
966 prefix, store.count, store.cost);
967 fprintf (file, " %sregcopy:\tnum=%6d\tcost=% 8" HOST_WIDE_INT_PRINT "d\n",
968 prefix, regcopy.count, regcopy.cost);
969 fprintf (file, " %sselfcpy:\tnum=%6d\tcost=% 8" HOST_WIDE_INT_PRINT "d\n",
970 prefix, selfcopy.count, selfcopy.cost);
973 /* Returns nonzero, if WEB1 and WEB2 have some possible
974 hardregs in common. */
977 web_conflicts_p (struct web *web1, struct web *web2)
979 if (web1->type == PRECOLORED && web2->type == PRECOLORED)
980 return 0;
982 if (web1->type == PRECOLORED)
983 return TEST_HARD_REG_BIT (web2->usable_regs, web1->regno);
985 if (web2->type == PRECOLORED)
986 return TEST_HARD_REG_BIT (web1->usable_regs, web2->regno);
988 return hard_regs_intersect_p (&web1->usable_regs, &web2->usable_regs);
991 /* Dump all uids of insns in which WEB is mentioned. */
993 void
994 dump_web_insns (struct web *web)
996 unsigned int i;
998 ra_debug_msg (DUMP_EVER, "Web: %i(%i)+%i class: %s freedom: %i degree %i\n",
999 web->id, web->regno, web->add_hardregs,
1000 reg_class_names[web->regclass],
1001 web->num_freedom, web->num_conflicts);
1002 ra_debug_msg (DUMP_EVER, " def insns:");
1004 for (i = 0; i < web->num_defs; ++i)
1006 ra_debug_msg (DUMP_EVER, " %d ", INSN_UID (web->defs[i]->insn));
1009 ra_debug_msg (DUMP_EVER, "\n use insns:");
1010 for (i = 0; i < web->num_uses; ++i)
1012 ra_debug_msg (DUMP_EVER, " %d ", INSN_UID (web->uses[i]->insn));
1014 ra_debug_msg (DUMP_EVER, "\n");
1017 /* Dump conflicts for web WEB. */
1019 void
1020 dump_web_conflicts (struct web *web)
1022 int num = 0;
1023 unsigned int def2;
1025 ra_debug_msg (DUMP_EVER, "Web: %i(%i)+%i class: %s freedom: %i degree %i\n",
1026 web->id, web->regno, web->add_hardregs,
1027 reg_class_names[web->regclass],
1028 web->num_freedom, web->num_conflicts);
1030 for (def2 = 0; def2 < num_webs; def2++)
1031 if (TEST_BIT (igraph, igraph_index (web->id, def2)) && web->id != def2)
1033 if ((num % 9) == 5)
1034 ra_debug_msg (DUMP_EVER, "\n ");
1035 num++;
1037 ra_debug_msg (DUMP_EVER, " %d(%d)", def2, id2web[def2]->regno);
1038 if (id2web[def2]->add_hardregs)
1039 ra_debug_msg (DUMP_EVER, "+%d", id2web[def2]->add_hardregs);
1041 if (web_conflicts_p (web, id2web[def2]))
1042 ra_debug_msg (DUMP_EVER, "/x");
1044 if (id2web[def2]->type == SELECT)
1045 ra_debug_msg (DUMP_EVER, "/s");
1047 if (id2web[def2]->type == COALESCED)
1048 ra_debug_msg (DUMP_EVER,"/c/%d", alias (id2web[def2])->id);
1050 ra_debug_msg (DUMP_EVER, "\n");
1052 struct conflict_link *wl;
1053 num = 0;
1054 ra_debug_msg (DUMP_EVER, "By conflicts: ");
1055 for (wl = web->conflict_list; wl; wl = wl->next)
1057 struct web* w = wl->t;
1058 if ((num % 9) == 8)
1059 ra_debug_msg (DUMP_EVER, "\n ");
1060 num++;
1061 ra_debug_msg (DUMP_EVER, "%d(%d)%s ", w->id, w->regno,
1062 web_conflicts_p (web, w) ? "+" : "");
1064 ra_debug_msg (DUMP_EVER, "\n");
1068 /* Output HARD_REG_SET to stderr. */
1070 void
1071 debug_hard_reg_set (HARD_REG_SET set)
1073 int i;
1074 for (i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
1076 if (TEST_HARD_REG_BIT (set, i))
1078 fprintf (stderr, "%s ", reg_names[i]);
1081 fprintf (stderr, "\n");
1085 vim:cinoptions={.5s,g0,p5,t0,(0,^-0.5s,n-0.5s:tw=78:cindent:sw=4: