2004-02-19 David Daney <ddaney@avtrex.com>
[official-gcc.git] / gcc / ra-debug.c
blob780c765d4d1a92e47729dca681f8acee42ff7636
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"
35 #include "regs.h"
37 /* This file contains various dumping and debug functions for
38 the graph coloring register allocator. */
40 static void ra_print_rtx_1op (FILE *, rtx);
41 static void ra_print_rtx_2op (FILE *, rtx);
42 static void ra_print_rtx_3op (FILE *, rtx);
43 static void ra_print_rtx_object (FILE *, rtx);
45 /* The hardregs as names, for debugging. */
46 static const char *const reg_class_names[] = REG_CLASS_NAMES;
48 /* Print a message to the dump file, if debug_new_regalloc and LEVEL
49 have any bits in common. */
51 void
52 ra_debug_msg (unsigned int level, const char *format, ...)
54 va_list ap;
56 va_start (ap, format);
57 if ((debug_new_regalloc & level) != 0 && rtl_dump_file != NULL)
58 vfprintf (rtl_dump_file, format, ap);
59 va_end (ap);
63 /* The following ra_print_xxx() functions print RTL expressions
64 in concise infix form. If the mode can be seen from context it's
65 left out. Most operators are represented by their graphical
66 characters, e.g. LE as "<=". Unknown constructs are currently
67 printed with print_inline_rtx(), which disrupts the nice layout.
68 Currently only the inline asm things are written this way. */
70 /* Print rtx X, which is a one operand rtx (op:mode (Y)), as
71 "op(Y)" to FILE. */
73 static void
74 ra_print_rtx_1op (FILE *file, rtx x)
76 enum rtx_code code = GET_CODE (x);
77 rtx op0 = XEXP (x, 0);
78 switch (code)
80 case NEG:
81 case NOT:
82 fputs ((code == NEG) ? "-(" : "~(", file);
83 ra_print_rtx (file, op0, 0);
84 fputs (")", file);
85 break;
86 case HIGH:
87 fputs ("hi(", file);
88 ra_print_rtx (file, op0, 0);
89 fputs (")", file);
90 break;
91 default:
92 fprintf (file, "%s", GET_RTX_NAME (code));
93 if (GET_MODE (x) != VOIDmode)
94 fprintf (file, ":%s(", GET_MODE_NAME (GET_MODE (x)));
95 else
96 fputs ("(", file);
97 ra_print_rtx (file, op0, 0);
98 fputs (")", file);
99 break;
103 /* Print rtx X, which is a two operand rtx (op:mode (Y) (Z))
104 as "(Y op Z)", if the operand is know, or as "op(Y, Z)", if not,
105 to FILE. */
107 static void
108 ra_print_rtx_2op (FILE *file, rtx x)
110 int infix = 1;
111 const char *opname = "shitop";
112 enum rtx_code code = GET_CODE (x);
113 rtx op0 = XEXP (x, 0);
114 rtx op1 = XEXP (x, 1);
115 switch (code)
117 /* class '2' */
118 case COMPARE: opname = "?"; break;
119 case MINUS: opname = "-"; break;
120 case DIV: opname = "/"; break;
121 case UDIV: opname = "u/"; break;
122 case MOD: opname = "%"; break;
123 case UMOD: opname = "u%"; break;
124 case ASHIFT: opname = "<<"; break;
125 case ASHIFTRT: opname = "a>>"; break;
126 case LSHIFTRT: opname = "l>>"; break;
127 /* class 'c' */
128 case PLUS: opname = "+"; break;
129 case MULT: opname = "*"; break;
130 case AND: opname = "&"; break;
131 case IOR: opname = "|"; break;
132 case XOR: opname = "^"; break;
133 /* class '<' */
134 case NE: opname = "!="; break;
135 case EQ: opname = "=="; break;
136 case GE: opname = "s>="; break;
137 case GT: opname = "s>"; break;
138 case LE: opname = "s<="; break;
139 case LT: opname = "s<"; break;
140 case GEU: opname = "u>="; break;
141 case GTU: opname = "u>"; break;
142 case LEU: opname = "u<="; break;
143 case LTU: opname = "u<"; break;
144 default:
145 infix = 0;
146 opname = GET_RTX_NAME (code);
147 break;
149 if (infix)
151 fputs ("(", file);
152 ra_print_rtx (file, op0, 0);
153 fprintf (file, " %s ", opname);
154 ra_print_rtx (file, op1, 0);
155 fputs (")", file);
157 else
159 fprintf (file, "%s(", opname);
160 ra_print_rtx (file, op0, 0);
161 fputs (", ", file);
162 ra_print_rtx (file, op1, 0);
163 fputs (")", file);
167 /* Print rtx X, which a three operand rtx to FILE.
168 I.e. X is either an IF_THEN_ELSE, or a bitmap operation. */
170 static void
171 ra_print_rtx_3op (FILE *file, rtx x)
173 enum rtx_code code = GET_CODE (x);
174 rtx op0 = XEXP (x, 0);
175 rtx op1 = XEXP (x, 1);
176 rtx op2 = XEXP (x, 2);
177 if (code == IF_THEN_ELSE)
179 ra_print_rtx (file, op0, 0);
180 fputs (" ? ", file);
181 ra_print_rtx (file, op1, 0);
182 fputs (" : ", file);
183 ra_print_rtx (file, op2, 0);
185 else
187 /* Bitmap-operation */
188 fprintf (file, "%s:%s(", GET_RTX_NAME (code),
189 GET_MODE_NAME (GET_MODE (x)));
190 ra_print_rtx (file, op0, 0);
191 fputs (", ", file);
192 ra_print_rtx (file, op1, 0);
193 fputs (", ", file);
194 ra_print_rtx (file, op2, 0);
195 fputs (")", file);
199 /* Print rtx X, which represents an object (class 'o' or some constructs
200 of class 'x' (e.g. subreg)), to FILE.
201 (reg XX) rtl is represented as "pXX", of XX was a pseudo,
202 as "name" it name is the nonnull hardreg name, or as "hXX", if XX
203 is a hardreg, whose name is NULL, or empty. */
205 static void
206 ra_print_rtx_object (FILE *file, rtx x)
208 enum rtx_code code = GET_CODE (x);
209 enum machine_mode mode = GET_MODE (x);
210 switch (code)
212 case CONST_INT:
213 fprintf (file, HOST_WIDE_INT_PRINT_DEC, XWINT (x, 0));
214 break;
215 case CONST_DOUBLE:
217 int i, num = 0;
218 const char *fmt = GET_RTX_FORMAT (code);
219 fputs ("dbl(", file);
220 for (i = 0; i < GET_RTX_LENGTH (code); i++)
222 if (num)
223 fputs (", ", file);
224 if (fmt[i] == 'e' && XEXP (x, i))
225 /* The MEM or other stuff */
227 ra_print_rtx (file, XEXP (x, i), 0);
228 num++;
230 else if (fmt[i] == 'w')
232 fprintf (file, HOST_WIDE_INT_PRINT_HEX, XWINT (x, i));
233 num++;
236 break;
238 case CONST_STRING: fprintf (file, "\"%s\"", XSTR (x, 0)); break;
239 case CONST: fputs ("const(", file);
240 ra_print_rtx (file, XEXP (x, 0), 0);
241 fputs (")", file);
242 break;
243 case PC: fputs ("pc", file); break;
244 case REG:
246 int regno = REGNO (x);
247 if (regno < FIRST_PSEUDO_REGISTER)
249 int i, nregs = hard_regno_nregs[regno][mode];
250 if (nregs > 1)
251 fputs ("[", file);
252 for (i = 0; i < nregs; i++)
254 if (i)
255 fputs (", ", file);
256 if (reg_names[regno+i] && *reg_names[regno + i])
257 fprintf (file, "%s", reg_names[regno + i]);
258 else
259 fprintf (file, "h%d", regno + i);
261 if (nregs > 1)
262 fputs ("]", file);
264 else
265 fprintf (file, "p%d", regno);
266 break;
268 case SUBREG:
270 rtx sub = SUBREG_REG (x);
271 int ofs = SUBREG_BYTE (x);
272 if (GET_CODE (sub) == REG
273 && REGNO (sub) < FIRST_PSEUDO_REGISTER)
275 int regno = REGNO (sub);
276 int i, nregs = hard_regno_nregs[regno][mode];
277 regno += subreg_regno_offset (regno, GET_MODE (sub),
278 ofs, mode);
279 if (nregs > 1)
280 fputs ("[", file);
281 for (i = 0; i < nregs; i++)
283 if (i)
284 fputs (", ", file);
285 if (reg_names[regno+i])
286 fprintf (file, "%s", reg_names[regno + i]);
287 else
288 fprintf (file, "h%d", regno + i);
290 if (nregs > 1)
291 fputs ("]", file);
293 else
295 ra_print_rtx (file, sub, 0);
296 fprintf (file, ":[%s+%d]", GET_MODE_NAME (mode), ofs);
298 break;
300 case SCRATCH: fputs ("scratch", file); break;
301 case CONCAT: ra_print_rtx_2op (file, x); break;
302 case HIGH: ra_print_rtx_1op (file, x); break;
303 case LO_SUM:
304 fputs ("(", file);
305 ra_print_rtx (file, XEXP (x, 0), 0);
306 fputs (" + lo(", file);
307 ra_print_rtx (file, XEXP (x, 1), 0);
308 fputs ("))", file);
309 break;
310 case MEM: fputs ("[", file);
311 ra_print_rtx (file, XEXP (x, 0), 0);
312 fprintf (file, "]:%s", GET_MODE_NAME (GET_MODE (x)));
313 /* XXX print alias set too ?? */
314 break;
315 case LABEL_REF:
317 rtx sub = XEXP (x, 0);
318 if (GET_CODE (sub) == NOTE
319 && NOTE_LINE_NUMBER (sub) == NOTE_INSN_DELETED_LABEL)
320 fprintf (file, "(deleted uid=%d)", INSN_UID (sub));
321 else if (GET_CODE (sub) == CODE_LABEL)
322 fprintf (file, "L%d", CODE_LABEL_NUMBER (sub));
323 else
324 fprintf (file, "(nonlabel uid=%d)", INSN_UID (sub));
326 break;
327 case SYMBOL_REF:
328 fprintf (file, "sym(\"%s\")", XSTR (x, 0)); break;
329 case CC0: fputs ("cc0", file); break;
330 default: print_inline_rtx (file, x, 0); break;
334 /* Print a general rtx X to FILE in nice infix form.
335 If WITH_PN is set, and X is one of the toplevel constructs
336 (insns, notes, labels or barriers), then print also the UIDs of
337 the preceding and following insn. */
339 void
340 ra_print_rtx (FILE *file, rtx x, int with_pn)
342 enum rtx_code code;
343 char class;
344 int unhandled = 0;
345 if (!x)
346 return;
347 code = GET_CODE (x);
348 class = GET_RTX_CLASS (code);
350 /* First handle the insn like constructs. */
351 if (INSN_P (x) || code == NOTE || code == CODE_LABEL || code == BARRIER)
353 if (INSN_P (x))
354 fputs (" ", file);
355 /* Non-insns are prefixed by a ';'. */
356 if (code == BARRIER)
357 fputs ("; ", file);
358 else if (code == NOTE)
359 /* But notes are indented very far right. */
360 fprintf (file, "\t\t\t\t\t; ");
361 else if (code == CODE_LABEL)
362 /* And labels have their Lxx name first, before the actual UID. */
364 fprintf (file, "L%d:\t; ", CODE_LABEL_NUMBER (x));
365 if (LABEL_NAME (x))
366 fprintf (file, "(%s) ", LABEL_NAME (x));
367 switch (LABEL_KIND (x))
369 case LABEL_NORMAL: break;
370 case LABEL_STATIC_ENTRY: fputs (" (entry)", file); break;
371 case LABEL_GLOBAL_ENTRY: fputs (" (global entry)", file); break;
372 case LABEL_WEAK_ENTRY: fputs (" (weak entry)", file); break;
373 default: abort();
375 fprintf (file, " [%d uses] uid=(", LABEL_NUSES (x));
377 fprintf (file, "%d", INSN_UID (x));
378 if (with_pn)
379 fprintf (file, " %d %d", PREV_INSN (x) ? INSN_UID (PREV_INSN (x)) : 0,
380 NEXT_INSN (x) ? INSN_UID (NEXT_INSN (x)) : 0);
381 if (code == BARRIER)
382 fputs (" -------- barrier ---------", file);
383 else if (code == CODE_LABEL)
384 fputs (")", file);
385 else if (code == NOTE)
387 int ln = NOTE_LINE_NUMBER (x);
388 if (ln >= (int) NOTE_INSN_BIAS && ln < (int) NOTE_INSN_MAX)
389 fprintf (file, " %s", GET_NOTE_INSN_NAME (ln));
390 else
392 fprintf (file, " line %d", ln);
393 if (NOTE_SOURCE_FILE (x))
394 fprintf (file, ":%s", NOTE_SOURCE_FILE (x));
397 else
399 fprintf (file, "\t");
400 ra_print_rtx (file, PATTERN (x), 0);
402 return;
404 switch (code)
406 /* Top-level stuff. */
407 case PARALLEL:
409 int j;
410 for (j = 0; j < XVECLEN (x, 0); j++)
412 if (j)
413 fputs ("\t;; ", file);
414 ra_print_rtx (file, XVECEXP (x, 0, j), 0);
416 break;
418 case UNSPEC: case UNSPEC_VOLATILE:
420 int j;
421 fprintf (file, "unspec%s(%d",
422 (code == UNSPEC) ? "" : "_vol", XINT (x, 1));
423 for (j = 0; j < XVECLEN (x, 0); j++)
425 fputs (", ", file);
426 ra_print_rtx (file, XVECEXP (x, 0, j), 0);
428 fputs (")", file);
429 break;
431 case SET:
432 if (GET_CODE (SET_DEST (x)) == PC)
434 if (GET_CODE (SET_SRC (x)) == IF_THEN_ELSE
435 && GET_CODE (XEXP (SET_SRC(x), 2)) == PC)
437 fputs ("if ", file);
438 ra_print_rtx (file, XEXP (SET_SRC (x), 0), 0);
439 fputs (" jump ", file);
440 ra_print_rtx (file, XEXP (SET_SRC (x), 1), 0);
442 else
444 fputs ("jump ", file);
445 ra_print_rtx (file, SET_SRC (x), 0);
448 else
450 ra_print_rtx (file, SET_DEST (x), 0);
451 fputs (" <= ", file);
452 ra_print_rtx (file, SET_SRC (x), 0);
454 break;
455 case USE:
456 fputs ("use <= ", file);
457 ra_print_rtx (file, XEXP (x, 0), 0);
458 break;
459 case CLOBBER:
460 ra_print_rtx (file, XEXP (x, 0), 0);
461 fputs (" <= clobber", file);
462 break;
463 case CALL:
464 fputs ("call ", file);
465 ra_print_rtx (file, XEXP (x, 0), 0); /* Address */
466 fputs (" numargs=", file);
467 ra_print_rtx (file, XEXP (x, 1), 0); /* Num arguments */
468 break;
469 case RETURN:
470 fputs ("return", file);
471 break;
472 case TRAP_IF:
473 fputs ("if (", file);
474 ra_print_rtx (file, XEXP (x, 0), 0);
475 fputs (") trap ", file);
476 ra_print_rtx (file, XEXP (x, 1), 0);
477 break;
478 case RESX:
479 fprintf (file, "resx from region %d", XINT (x, 0));
480 break;
482 /* Different things of class 'x' */
483 case SUBREG: ra_print_rtx_object (file, x); break;
484 case STRICT_LOW_PART:
485 fputs ("low(", file);
486 ra_print_rtx (file, XEXP (x, 0), 0);
487 fputs (")", file);
488 break;
489 default:
490 unhandled = 1;
491 break;
493 if (!unhandled)
494 return;
495 if (class == '1')
496 ra_print_rtx_1op (file, x);
497 else if (class == '2' || class == 'c' || class == '<')
498 ra_print_rtx_2op (file, x);
499 else if (class == '3' || class == 'b')
500 ra_print_rtx_3op (file, x);
501 else if (class == 'o')
502 ra_print_rtx_object (file, x);
503 else
504 print_inline_rtx (file, x, 0);
507 /* This only calls ra_print_rtx(), but emits a final newline. */
509 void
510 ra_print_rtx_top (FILE *file, rtx x, int with_pn)
512 ra_print_rtx (file, x, with_pn);
513 fprintf (file, "\n");
516 /* Callable from gdb. This prints rtx X onto stderr. */
518 void
519 ra_debug_rtx (rtx x)
521 ra_print_rtx_top (stderr, x, 1);
524 /* This prints the content of basic block with index BBI.
525 The first and last insn are emitted with UIDs of prev and next insns. */
527 void
528 ra_debug_bbi (int bbi)
530 basic_block bb = BASIC_BLOCK (bbi);
531 rtx insn;
532 for (insn = BB_HEAD (bb); insn; insn = NEXT_INSN (insn))
534 ra_print_rtx_top (stderr, insn,
535 (insn == BB_HEAD (bb) || insn == BB_END (bb)));
536 fprintf (stderr, "\n");
537 if (insn == BB_END (bb))
538 break;
542 /* Beginning from INSN, emit NUM insns (if NUM is non-negative)
543 or emit a window of NUM insns around INSN, to stderr. */
545 void
546 ra_debug_insns (rtx insn, int num)
548 int i, count = (num == 0 ? 1 : num < 0 ? -num : num);
549 if (num < 0)
550 for (i = count / 2; i > 0 && PREV_INSN (insn); i--)
551 insn = PREV_INSN (insn);
552 for (i = count; i > 0 && insn; insn = NEXT_INSN (insn), i--)
554 if (GET_CODE (insn) == CODE_LABEL)
555 fprintf (stderr, "\n");
556 ra_print_rtx_top (stderr, insn, (i == count || i == 1));
560 /* Beginning with INSN, emit the whole insn chain into FILE.
561 This also outputs comments when basic blocks start or end and omits
562 some notes, if flag_ra_dump_notes is zero. */
564 void
565 ra_print_rtl_with_bb (FILE *file, rtx insn)
567 basic_block last_bb, bb;
568 unsigned int num = 0;
569 if (!insn)
570 fputs ("nil", file);
571 last_bb = NULL;
572 for (; insn; insn = NEXT_INSN (insn))
574 if (GET_CODE (insn) == BARRIER)
575 bb = NULL;
576 else
577 bb = BLOCK_FOR_INSN (insn);
578 if (bb != last_bb)
580 if (last_bb)
581 fprintf (file, ";; End of basic block %d\n", last_bb->index);
582 if (bb)
583 fprintf (file, ";; Begin of basic block %d\n", bb->index);
584 last_bb = bb;
586 if (GET_CODE (insn) == CODE_LABEL)
587 fputc ('\n', file);
588 if (GET_CODE (insn) == NOTE)
590 /* Ignore basic block and maybe other notes not referencing
591 deleted things. */
592 if (NOTE_LINE_NUMBER (insn) != NOTE_INSN_BASIC_BLOCK
593 && (flag_ra_dump_notes
594 || NOTE_LINE_NUMBER (insn) == NOTE_INSN_DELETED
595 || NOTE_LINE_NUMBER (insn) == NOTE_INSN_DELETED_LABEL))
597 ra_print_rtx_top (file, insn, (num == 0 || !NEXT_INSN (insn)));
598 num++;
601 else
603 ra_print_rtx_top (file, insn, (num == 0 || !NEXT_INSN (insn)));
604 num++;
609 /* Count how many insns were seen how often, while building the interference
610 graph, and prints the findings. */
612 void
613 dump_number_seen (void)
615 #define N 17
616 int num[N];
617 int i;
619 for (i = 0; i < N; i++)
620 num[i] = 0;
621 for (i = 0; i < get_max_uid (); i++)
622 if (number_seen[i] < N - 1)
623 num[number_seen[i]]++;
624 else
625 num[N - 1]++;
626 for (i = 0; i < N - 1; i++)
627 if (num[i])
628 ra_debug_msg (DUMP_PROCESS, "%d insns seen %d times\n", num[i], i);
629 if (num[N - 1])
630 ra_debug_msg (DUMP_PROCESS, "%d insns seen %d and more times\n", num[i],
631 N - 1);
632 ra_debug_msg (DUMP_PROCESS, "from overall %d insns\n", get_max_uid ());
633 #undef N
636 /* Dump the interference graph, the move list and the webs. */
638 void
639 dump_igraph (struct df *df ATTRIBUTE_UNUSED)
641 struct move_list *ml;
642 unsigned int def1, def2;
643 int num = 0;
644 int num2;
645 unsigned int i;
646 if (!rtl_dump_file || (debug_new_regalloc & (DUMP_IGRAPH | DUMP_WEBS)) == 0)
647 return;
648 ra_debug_msg (DUMP_IGRAPH, "conflicts:\n ");
649 for (def1 = 0; def1 < num_webs; def1++)
651 int num1 = num;
652 num2 = 0;
653 for (def2 = 0; def2 < num_webs; def2++)
654 if (def1 != def2 && TEST_BIT (igraph, igraph_index (def1, def2)))
656 if (num1 == num)
658 if (SUBWEB_P (ID2WEB (def1)))
659 ra_debug_msg (DUMP_IGRAPH, "%d (SUBREG %d, %d) with ", def1,
660 ID2WEB (def1)->regno,
661 SUBREG_BYTE (ID2WEB (def1)->orig_x));
662 else
663 ra_debug_msg (DUMP_IGRAPH, "%d (REG %d) with ", def1,
664 ID2WEB (def1)->regno);
666 if ((num2 % 9) == 8)
667 ra_debug_msg (DUMP_IGRAPH, "\n ");
668 num++;
669 num2++;
670 if (SUBWEB_P (ID2WEB (def2)))
671 ra_debug_msg (DUMP_IGRAPH, "%d(%d,%d) ", def2, ID2WEB (def2)->regno,
672 SUBREG_BYTE (ID2WEB (def2)->orig_x));
673 else
674 ra_debug_msg (DUMP_IGRAPH, "%d(%d) ", def2, ID2WEB (def2)->regno);
676 if (num1 != num)
677 ra_debug_msg (DUMP_IGRAPH, "\n ");
679 ra_debug_msg (DUMP_IGRAPH, "\n");
680 for (ml = wl_moves; ml; ml = ml->next)
681 if (ml->move)
683 ra_debug_msg (DUMP_IGRAPH, "move: insn %d: Web %d <-- Web %d\n",
684 INSN_UID (ml->move->insn), ml->move->target_web->id,
685 ml->move->source_web->id);
687 ra_debug_msg (DUMP_WEBS, "\nWebs:\n");
688 for (i = 0; i < num_webs; i++)
690 struct web *web = ID2WEB (i);
692 ra_debug_msg (DUMP_WEBS, " %4d : regno %3d", i, web->regno);
693 if (SUBWEB_P (web))
695 ra_debug_msg (DUMP_WEBS, " sub %d", SUBREG_BYTE (web->orig_x));
696 ra_debug_msg (DUMP_WEBS, " par %d", find_web_for_subweb (web)->id);
698 ra_debug_msg (DUMP_WEBS, " +%d (span %d, cost "
699 HOST_WIDE_INT_PRINT_DEC ") (%s)",
700 web->add_hardregs, web->span_deaths, web->spill_cost,
701 reg_class_names[web->regclass]);
702 if (web->spill_temp == 1)
703 ra_debug_msg (DUMP_WEBS, " (spilltemp)");
704 else if (web->spill_temp == 2)
705 ra_debug_msg (DUMP_WEBS, " (spilltem2)");
706 else if (web->spill_temp == 3)
707 ra_debug_msg (DUMP_WEBS, " (short)");
708 if (web->type == PRECOLORED)
709 ra_debug_msg (DUMP_WEBS, " (precolored, color=%d)", web->color);
710 else if (find_web_for_subweb (web)->num_uses == 0)
711 ra_debug_msg (DUMP_WEBS, " dead");
712 if (web->crosses_call)
713 ra_debug_msg (DUMP_WEBS, " xcall");
714 if (web->regno >= max_normal_pseudo)
715 ra_debug_msg (DUMP_WEBS, " stack");
716 ra_debug_msg (DUMP_WEBS, "\n");
720 /* Dump the interference graph and webs in a format easily
721 parsable by programs. Used to emit real world interference graph
722 to my custom graph colorizer. */
724 void
725 dump_igraph_machine (void)
727 unsigned int i;
729 if (!rtl_dump_file || (debug_new_regalloc & DUMP_IGRAPH_M) == 0)
730 return;
731 ra_debug_msg (DUMP_IGRAPH_M, "g %d %d\n", num_webs - num_subwebs,
732 FIRST_PSEUDO_REGISTER);
733 for (i = 0; i < num_webs - num_subwebs; i++)
735 struct web *web = ID2WEB (i);
736 struct conflict_link *cl;
737 int flags = 0;
738 int numc = 0;
739 int col = 0;
740 flags = web->spill_temp & 0xF;
741 flags |= ((web->type == PRECOLORED) ? 1 : 0) << 4;
742 flags |= (web->add_hardregs & 0xF) << 5;
743 for (cl = web->conflict_list; cl; cl = cl->next)
744 if (cl->t->id < web->id)
745 numc++;
746 ra_debug_msg (DUMP_IGRAPH_M, "n %d %d %d %d %d %d %d\n",
747 web->id, web->color, flags,
748 (unsigned int)web->spill_cost, web->num_defs, web->num_uses,
749 numc);
750 if (web->type != PRECOLORED)
752 ra_debug_msg (DUMP_IGRAPH_M, "s %d", web->id);
753 while (1)
755 unsigned int u = 0;
756 int n;
757 for (n = 0; n < 32 && col < FIRST_PSEUDO_REGISTER; n++, col++)
758 if (TEST_HARD_REG_BIT (web->usable_regs, col))
759 u |= 1 << n;
760 ra_debug_msg (DUMP_IGRAPH_M, " %u", u);
761 if (col >= FIRST_PSEUDO_REGISTER)
762 break;
764 ra_debug_msg (DUMP_IGRAPH_M, "\n");
766 if (numc)
768 ra_debug_msg (DUMP_IGRAPH_M, "c %d", web->id);
769 for (cl = web->conflict_list; cl; cl = cl->next)
771 if (cl->t->id < web->id)
772 ra_debug_msg (DUMP_IGRAPH_M, " %d", cl->t->id);
774 ra_debug_msg (DUMP_IGRAPH_M, "\n");
777 ra_debug_msg (DUMP_IGRAPH_M, "e\n");
780 /* This runs after colorization and changing the insn stream.
781 It temporarily replaces all pseudo registers with their colors,
782 and emits information, if the resulting insns are strictly valid. */
784 void
785 dump_constraints (void)
787 rtx insn;
788 int i;
789 if (!rtl_dump_file || (debug_new_regalloc & DUMP_CONSTRAINTS) == 0)
790 return;
791 for (i = FIRST_PSEUDO_REGISTER; i < ra_max_regno; i++)
792 if (regno_reg_rtx[i] && GET_CODE (regno_reg_rtx[i]) == REG)
793 REGNO (regno_reg_rtx[i])
794 = ra_reg_renumber[i] >= 0 ? ra_reg_renumber[i] : i;
795 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
796 if (INSN_P (insn))
798 int code;
799 int uid = INSN_UID (insn);
800 int o;
801 /* Don't simply force rerecognition, as combine might left us
802 with some unrecognizable ones, which later leads to aborts
803 in regclass, if we now destroy the remembered INSN_CODE(). */
804 /*INSN_CODE (insn) = -1;*/
805 code = recog_memoized (insn);
806 if (code < 0)
808 ra_debug_msg (DUMP_CONSTRAINTS,
809 "%d: asm insn or not recognizable.\n", uid);
810 continue;
812 ra_debug_msg (DUMP_CONSTRAINTS,
813 "%d: code %d {%s}, %d operands, constraints: ",
814 uid, code, insn_data[code].name, recog_data.n_operands);
815 extract_insn (insn);
816 /*preprocess_constraints ();*/
817 for (o = 0; o < recog_data.n_operands; o++)
819 ra_debug_msg (DUMP_CONSTRAINTS,
820 "%d:%s ", o, recog_data.constraints[o]);
822 if (constrain_operands (1))
823 ra_debug_msg (DUMP_CONSTRAINTS, "matches strictly alternative %d",
824 which_alternative);
825 else
826 ra_debug_msg (DUMP_CONSTRAINTS, "doesn't match strictly");
827 ra_debug_msg (DUMP_CONSTRAINTS, "\n");
829 for (i = FIRST_PSEUDO_REGISTER; i < ra_max_regno; i++)
830 if (regno_reg_rtx[i] && GET_CODE (regno_reg_rtx[i]) == REG)
831 REGNO (regno_reg_rtx[i]) = i;
834 /* This counts and emits the cumulated cost of all spilled webs,
835 preceded by a custom message MSG, with debug level LEVEL. */
837 void
838 dump_graph_cost (unsigned int level, const char *msg)
840 unsigned int i;
841 unsigned HOST_WIDE_INT cost;
842 if (!rtl_dump_file || (debug_new_regalloc & level) == 0)
843 return;
845 cost = 0;
846 for (i = 0; i < num_webs; i++)
848 struct web *web = id2web[i];
849 if (alias (web)->type == SPILLED)
850 cost += web->orig_spill_cost;
852 ra_debug_msg (level, " spill cost of graph (%s) = "
853 HOST_WIDE_INT_PRINT_UNSIGNED "\n",
854 msg ? msg : "", cost);
857 /* Dump the color assignment per web, the coalesced and spilled webs. */
859 void
860 dump_ra (struct df *df ATTRIBUTE_UNUSED)
862 struct web *web;
863 struct dlist *d;
864 if (!rtl_dump_file || (debug_new_regalloc & DUMP_RESULTS) == 0)
865 return;
867 ra_debug_msg (DUMP_RESULTS, "\nColored:\n");
868 for (d = WEBS(COLORED); d; d = d->next)
870 web = DLIST_WEB (d);
871 ra_debug_msg (DUMP_RESULTS, " %4d : color %d\n", web->id, web->color);
873 ra_debug_msg (DUMP_RESULTS, "\nCoalesced:\n");
874 for (d = WEBS(COALESCED); d; d = d->next)
876 web = DLIST_WEB (d);
877 ra_debug_msg (DUMP_RESULTS, " %4d : to web %d, color %d\n", web->id,
878 alias (web)->id, web->color);
880 ra_debug_msg (DUMP_RESULTS, "\nSpilled:\n");
881 for (d = WEBS(SPILLED); d; d = d->next)
883 web = DLIST_WEB (d);
884 ra_debug_msg (DUMP_RESULTS, " %4d\n", web->id);
886 ra_debug_msg (DUMP_RESULTS, "\n");
887 dump_cost (DUMP_RESULTS);
890 /* Calculate and dump the cumulated costs of certain types of insns
891 (loads, stores and copies). */
893 void
894 dump_static_insn_cost (FILE *file, const char *message, const char *prefix)
896 struct cost
898 unsigned HOST_WIDE_INT cost;
899 unsigned int count;
901 basic_block bb;
902 struct cost load, store, regcopy, selfcopy, overall;
903 memset (&load, 0, sizeof(load));
904 memset (&store, 0, sizeof(store));
905 memset (&regcopy, 0, sizeof(regcopy));
906 memset (&selfcopy, 0, sizeof(selfcopy));
907 memset (&overall, 0, sizeof(overall));
909 if (!file)
910 return;
912 FOR_EACH_BB (bb)
914 unsigned HOST_WIDE_INT block_cost = bb->frequency;
915 rtx insn, set;
916 for (insn = BB_HEAD (bb); insn; insn = NEXT_INSN (insn))
918 /* Yes, yes. We don't calculate the costs precisely.
919 Only for "simple enough" insns. Those containing single
920 sets only. */
921 if (INSN_P (insn) && ((set = single_set (insn)) != NULL))
923 rtx src = SET_SRC (set);
924 rtx dest = SET_DEST (set);
925 struct cost *pcost = NULL;
926 overall.cost += block_cost;
927 overall.count++;
928 if (rtx_equal_p (src, dest))
929 pcost = &selfcopy;
930 else if (GET_CODE (src) == GET_CODE (dest)
931 && ((GET_CODE (src) == REG)
932 || (GET_CODE (src) == SUBREG
933 && GET_CODE (SUBREG_REG (src)) == REG
934 && GET_CODE (SUBREG_REG (dest)) == REG)))
935 pcost = &regcopy;
936 else
938 if (GET_CODE (src) == SUBREG)
939 src = SUBREG_REG (src);
940 if (GET_CODE (dest) == SUBREG)
941 dest = SUBREG_REG (dest);
942 if (GET_CODE (src) == MEM && GET_CODE (dest) != MEM
943 && memref_is_stack_slot (src))
944 pcost = &load;
945 else if (GET_CODE (src) != MEM && GET_CODE (dest) == MEM
946 && memref_is_stack_slot (dest))
947 pcost = &store;
949 if (pcost)
951 pcost->cost += block_cost;
952 pcost->count++;
955 if (insn == BB_END (bb))
956 break;
960 if (!prefix)
961 prefix = "";
962 fprintf (file, "static insn cost %s\n", message ? message : "");
963 fprintf (file, " %soverall:\tnum=%6d\tcost=% 8" HOST_WIDE_INT_PRINT "d\n",
964 prefix, overall.count, overall.cost);
965 fprintf (file, " %sloads:\tnum=%6d\tcost=% 8" HOST_WIDE_INT_PRINT "d\n",
966 prefix, load.count, load.cost);
967 fprintf (file, " %sstores:\tnum=%6d\tcost=% 8" HOST_WIDE_INT_PRINT "d\n",
968 prefix, store.count, store.cost);
969 fprintf (file, " %sregcopy:\tnum=%6d\tcost=% 8" HOST_WIDE_INT_PRINT "d\n",
970 prefix, regcopy.count, regcopy.cost);
971 fprintf (file, " %sselfcpy:\tnum=%6d\tcost=% 8" HOST_WIDE_INT_PRINT "d\n",
972 prefix, selfcopy.count, selfcopy.cost);
975 /* Returns nonzero, if WEB1 and WEB2 have some possible
976 hardregs in common. */
979 web_conflicts_p (struct web *web1, struct web *web2)
981 if (web1->type == PRECOLORED && web2->type == PRECOLORED)
982 return 0;
984 if (web1->type == PRECOLORED)
985 return TEST_HARD_REG_BIT (web2->usable_regs, web1->regno);
987 if (web2->type == PRECOLORED)
988 return TEST_HARD_REG_BIT (web1->usable_regs, web2->regno);
990 return hard_regs_intersect_p (&web1->usable_regs, &web2->usable_regs);
993 /* Dump all uids of insns in which WEB is mentioned. */
995 void
996 dump_web_insns (struct web *web)
998 unsigned int i;
1000 ra_debug_msg (DUMP_EVER, "Web: %i(%i)+%i class: %s freedom: %i degree %i\n",
1001 web->id, web->regno, web->add_hardregs,
1002 reg_class_names[web->regclass],
1003 web->num_freedom, web->num_conflicts);
1004 ra_debug_msg (DUMP_EVER, " def insns:");
1006 for (i = 0; i < web->num_defs; ++i)
1008 ra_debug_msg (DUMP_EVER, " %d ", INSN_UID (web->defs[i]->insn));
1011 ra_debug_msg (DUMP_EVER, "\n use insns:");
1012 for (i = 0; i < web->num_uses; ++i)
1014 ra_debug_msg (DUMP_EVER, " %d ", INSN_UID (web->uses[i]->insn));
1016 ra_debug_msg (DUMP_EVER, "\n");
1019 /* Dump conflicts for web WEB. */
1021 void
1022 dump_web_conflicts (struct web *web)
1024 int num = 0;
1025 unsigned int def2;
1027 ra_debug_msg (DUMP_EVER, "Web: %i(%i)+%i class: %s freedom: %i degree %i\n",
1028 web->id, web->regno, web->add_hardregs,
1029 reg_class_names[web->regclass],
1030 web->num_freedom, web->num_conflicts);
1032 for (def2 = 0; def2 < num_webs; def2++)
1033 if (TEST_BIT (igraph, igraph_index (web->id, def2)) && web->id != def2)
1035 if ((num % 9) == 5)
1036 ra_debug_msg (DUMP_EVER, "\n ");
1037 num++;
1039 ra_debug_msg (DUMP_EVER, " %d(%d)", def2, id2web[def2]->regno);
1040 if (id2web[def2]->add_hardregs)
1041 ra_debug_msg (DUMP_EVER, "+%d", id2web[def2]->add_hardregs);
1043 if (web_conflicts_p (web, id2web[def2]))
1044 ra_debug_msg (DUMP_EVER, "/x");
1046 if (id2web[def2]->type == SELECT)
1047 ra_debug_msg (DUMP_EVER, "/s");
1049 if (id2web[def2]->type == COALESCED)
1050 ra_debug_msg (DUMP_EVER,"/c/%d", alias (id2web[def2])->id);
1052 ra_debug_msg (DUMP_EVER, "\n");
1054 struct conflict_link *wl;
1055 num = 0;
1056 ra_debug_msg (DUMP_EVER, "By conflicts: ");
1057 for (wl = web->conflict_list; wl; wl = wl->next)
1059 struct web* w = wl->t;
1060 if ((num % 9) == 8)
1061 ra_debug_msg (DUMP_EVER, "\n ");
1062 num++;
1063 ra_debug_msg (DUMP_EVER, "%d(%d)%s ", w->id, w->regno,
1064 web_conflicts_p (web, w) ? "+" : "");
1066 ra_debug_msg (DUMP_EVER, "\n");
1070 /* Output HARD_REG_SET to stderr. */
1072 void
1073 debug_hard_reg_set (HARD_REG_SET set)
1075 int i;
1076 for (i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
1078 if (TEST_HARD_REG_BIT (set, i))
1080 fprintf (stderr, "%s ", reg_names[i]);
1083 fprintf (stderr, "\n");
1087 vim:cinoptions={.5s,g0,p5,t0,(0,^-0.5s,n-0.5s:tw=78:cindent:sw=4: