2005-01-16 Steven G. Kargl <kargls@comcast.net>
[official-gcc.git] / gcc / ra-debug.c
blob1d4bfc722c48a1d9435ad4f20bcead2886c11ead
1 /* Graph coloring register allocator
2 Copyright (C) 2001, 2002, 2004, 2005 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 "regs.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 /* Print a message to the dump file, if debug_new_regalloc and LEVEL
45 have any bits in common. */
47 void
48 ra_debug_msg (unsigned int level, const char *format, ...)
50 va_list ap;
52 va_start (ap, format);
53 if ((debug_new_regalloc & level) != 0 && dump_file != NULL)
54 vfprintf (dump_file, format, ap);
55 va_end (ap);
59 /* The following ra_print_xxx() functions print RTL expressions
60 in concise infix form. If the mode can be seen from context it's
61 left out. Most operators are represented by their graphical
62 characters, e.g. LE as "<=". Unknown constructs are currently
63 printed with print_inline_rtx(), which disrupts the nice layout.
64 Currently only the inline asm things are written this way. */
66 /* Print rtx X, which is a one operand rtx (op:mode (Y)), as
67 "op(Y)" to FILE. */
69 static void
70 ra_print_rtx_1op (FILE *file, rtx x)
72 enum rtx_code code = GET_CODE (x);
73 rtx op0 = XEXP (x, 0);
74 switch (code)
76 case NEG:
77 case NOT:
78 fputs ((code == NEG) ? "-(" : "~(", file);
79 ra_print_rtx (file, op0, 0);
80 fputs (")", file);
81 break;
82 case HIGH:
83 fputs ("hi(", file);
84 ra_print_rtx (file, op0, 0);
85 fputs (")", file);
86 break;
87 default:
88 fprintf (file, "%s", GET_RTX_NAME (code));
89 if (GET_MODE (x) != VOIDmode)
90 fprintf (file, ":%s(", GET_MODE_NAME (GET_MODE (x)));
91 else
92 fputs ("(", file);
93 ra_print_rtx (file, op0, 0);
94 fputs (")", file);
95 break;
99 /* Print rtx X, which is a two operand rtx (op:mode (Y) (Z))
100 as "(Y op Z)", if the operand is know, or as "op(Y, Z)", if not,
101 to FILE. */
103 static void
104 ra_print_rtx_2op (FILE *file, rtx x)
106 int infix = 1;
107 const char *opname = "shitop";
108 enum rtx_code code = GET_CODE (x);
109 rtx op0 = XEXP (x, 0);
110 rtx op1 = XEXP (x, 1);
111 switch (code)
113 /* class '2' */
114 case COMPARE: opname = "?"; break;
115 case MINUS: opname = "-"; break;
116 case DIV: opname = "/"; break;
117 case UDIV: opname = "u/"; break;
118 case MOD: opname = "%"; break;
119 case UMOD: opname = "u%"; break;
120 case ASHIFT: opname = "<<"; break;
121 case ASHIFTRT: opname = "a>>"; break;
122 case LSHIFTRT: opname = "l>>"; break;
123 /* class 'c' */
124 case PLUS: opname = "+"; break;
125 case MULT: opname = "*"; break;
126 case AND: opname = "&"; break;
127 case IOR: opname = "|"; break;
128 case XOR: opname = "^"; break;
129 /* class '=' */
130 case NE: opname = "!="; break;
131 case EQ: opname = "=="; break;
132 case LTGT: opname = "<>"; break;
133 /* class '<' */
134 case GE: opname = "s>="; break;
135 case GT: opname = "s>"; break;
136 case LE: opname = "s<="; break;
137 case LT: opname = "s<"; break;
138 case GEU: opname = "u>="; break;
139 case GTU: opname = "u>"; break;
140 case LEU: opname = "u<="; break;
141 case LTU: opname = "u<"; break;
142 default:
143 infix = 0;
144 opname = GET_RTX_NAME (code);
145 break;
147 if (infix)
149 fputs ("(", file);
150 ra_print_rtx (file, op0, 0);
151 fprintf (file, " %s ", opname);
152 ra_print_rtx (file, op1, 0);
153 fputs (")", file);
155 else
157 fprintf (file, "%s(", opname);
158 ra_print_rtx (file, op0, 0);
159 fputs (", ", file);
160 ra_print_rtx (file, op1, 0);
161 fputs (")", file);
165 /* Print rtx X, which a three operand rtx to FILE.
166 I.e. X is either an IF_THEN_ELSE, or a bitmap operation. */
168 static void
169 ra_print_rtx_3op (FILE *file, rtx x)
171 enum rtx_code code = GET_CODE (x);
172 rtx op0 = XEXP (x, 0);
173 rtx op1 = XEXP (x, 1);
174 rtx op2 = XEXP (x, 2);
175 if (code == IF_THEN_ELSE)
177 ra_print_rtx (file, op0, 0);
178 fputs (" ? ", file);
179 ra_print_rtx (file, op1, 0);
180 fputs (" : ", file);
181 ra_print_rtx (file, op2, 0);
183 else
185 /* Bitmap-operation */
186 fprintf (file, "%s:%s(", GET_RTX_NAME (code),
187 GET_MODE_NAME (GET_MODE (x)));
188 ra_print_rtx (file, op0, 0);
189 fputs (", ", file);
190 ra_print_rtx (file, op1, 0);
191 fputs (", ", file);
192 ra_print_rtx (file, op2, 0);
193 fputs (")", file);
197 /* Print rtx X, which represents an object (class 'o', 'C', or some constructs
198 of class 'x' (e.g. subreg)), to FILE.
199 (reg XX) rtl is represented as "pXX", of XX was a pseudo,
200 as "name" it name is the nonnull hardreg name, or as "hXX", if XX
201 is a hardreg, whose name is NULL, or empty. */
203 static void
204 ra_print_rtx_object (FILE *file, rtx x)
206 enum rtx_code code = GET_CODE (x);
207 enum machine_mode mode = GET_MODE (x);
208 switch (code)
210 case CONST_INT:
211 fprintf (file, HOST_WIDE_INT_PRINT_DEC, XWINT (x, 0));
212 break;
213 case CONST_DOUBLE:
215 int i, num = 0;
216 const char *fmt = GET_RTX_FORMAT (code);
217 fputs ("dbl(", file);
218 for (i = 0; i < GET_RTX_LENGTH (code); i++)
220 if (num)
221 fputs (", ", file);
222 if (fmt[i] == 'e' && XEXP (x, i))
223 /* The MEM or other stuff */
225 ra_print_rtx (file, XEXP (x, i), 0);
226 num++;
228 else if (fmt[i] == 'w')
230 fprintf (file, HOST_WIDE_INT_PRINT_HEX, XWINT (x, i));
231 num++;
234 break;
236 case CONST_STRING: fprintf (file, "\"%s\"", XSTR (x, 0)); break;
237 case CONST: fputs ("const(", file);
238 ra_print_rtx (file, XEXP (x, 0), 0);
239 fputs (")", file);
240 break;
241 case PC: fputs ("pc", file); break;
242 case REG:
244 int regno = REGNO (x);
245 if (regno < FIRST_PSEUDO_REGISTER)
247 int i, nregs = hard_regno_nregs[regno][mode];
248 if (nregs > 1)
249 fputs ("[", file);
250 for (i = 0; i < nregs; i++)
252 if (i)
253 fputs (", ", file);
254 if (reg_names[regno+i] && *reg_names[regno + i])
255 fprintf (file, "%s", reg_names[regno + i]);
256 else
257 fprintf (file, "h%d", regno + i);
259 if (nregs > 1)
260 fputs ("]", file);
262 else
263 fprintf (file, "p%d", regno);
264 break;
266 case SUBREG:
268 rtx sub = SUBREG_REG (x);
269 int ofs = SUBREG_BYTE (x);
270 if (REG_P (sub)
271 && REGNO (sub) < FIRST_PSEUDO_REGISTER)
273 int regno = REGNO (sub);
274 int i, nregs = hard_regno_nregs[regno][mode];
275 regno += subreg_regno_offset (regno, GET_MODE (sub),
276 ofs, mode);
277 if (nregs > 1)
278 fputs ("[", file);
279 for (i = 0; i < nregs; i++)
281 if (i)
282 fputs (", ", file);
283 if (reg_names[regno+i])
284 fprintf (file, "%s", reg_names[regno + i]);
285 else
286 fprintf (file, "h%d", regno + i);
288 if (nregs > 1)
289 fputs ("]", file);
291 else
293 ra_print_rtx (file, sub, 0);
294 fprintf (file, ":[%s+%d]", GET_MODE_NAME (mode), ofs);
296 break;
298 case SCRATCH: fputs ("scratch", file); break;
299 case CONCAT: ra_print_rtx_2op (file, x); break;
300 case HIGH: ra_print_rtx_1op (file, x); break;
301 case LO_SUM:
302 fputs ("(", file);
303 ra_print_rtx (file, XEXP (x, 0), 0);
304 fputs (" + lo(", file);
305 ra_print_rtx (file, XEXP (x, 1), 0);
306 fputs ("))", file);
307 break;
308 case MEM: fputs ("[", file);
309 ra_print_rtx (file, XEXP (x, 0), 0);
310 fprintf (file, "]:%s", GET_MODE_NAME (GET_MODE (x)));
311 /* XXX print alias set too ?? */
312 break;
313 case LABEL_REF:
315 rtx sub = XEXP (x, 0);
316 if (NOTE_P (sub)
317 && NOTE_LINE_NUMBER (sub) == NOTE_INSN_DELETED_LABEL)
318 fprintf (file, "(deleted uid=%d)", INSN_UID (sub));
319 else if (LABEL_P (sub))
320 fprintf (file, "L%d", CODE_LABEL_NUMBER (sub));
321 else
322 fprintf (file, "(nonlabel uid=%d)", INSN_UID (sub));
324 break;
325 case SYMBOL_REF:
326 fprintf (file, "sym(\"%s\")", XSTR (x, 0)); break;
327 case CC0: fputs ("cc0", file); break;
328 default: print_inline_rtx (file, x, 0); break;
332 /* Print a general rtx X to FILE in nice infix form.
333 If WITH_PN is set, and X is one of the toplevel constructs
334 (insns, notes, labels or barriers), then print also the UIDs of
335 the preceding and following insn. */
337 void
338 ra_print_rtx (FILE *file, rtx x, int with_pn)
340 enum rtx_code code;
341 int unhandled = 0;
342 if (!x)
343 return;
344 code = GET_CODE (x);
346 /* First handle the insn like constructs. */
347 if (INSN_P (x) || code == NOTE || code == CODE_LABEL || code == BARRIER)
349 if (INSN_P (x))
350 fputs (" ", file);
351 /* Non-insns are prefixed by a ';'. */
352 if (code == BARRIER)
353 fputs ("; ", file);
354 else if (code == NOTE)
355 /* But notes are indented very far right. */
356 fprintf (file, "\t\t\t\t\t; ");
357 else if (code == CODE_LABEL)
358 /* And labels have their Lxx name first, before the actual UID. */
360 fprintf (file, "L%d:\t; ", CODE_LABEL_NUMBER (x));
361 if (LABEL_NAME (x))
362 fprintf (file, "(%s) ", LABEL_NAME (x));
363 switch (LABEL_KIND (x))
365 case LABEL_NORMAL: break;
366 case LABEL_STATIC_ENTRY: fputs (" (entry)", file); break;
367 case LABEL_GLOBAL_ENTRY: fputs (" (global entry)", file); break;
368 case LABEL_WEAK_ENTRY: fputs (" (weak entry)", file); break;
369 default: abort();
371 fprintf (file, " [%d uses] uid=(", LABEL_NUSES (x));
373 fprintf (file, "%d", INSN_UID (x));
374 if (with_pn)
375 fprintf (file, " %d %d", PREV_INSN (x) ? INSN_UID (PREV_INSN (x)) : 0,
376 NEXT_INSN (x) ? INSN_UID (NEXT_INSN (x)) : 0);
377 if (code == BARRIER)
378 fputs (" -------- barrier ---------", file);
379 else if (code == CODE_LABEL)
380 fputs (")", file);
381 else if (code == NOTE)
383 int ln = NOTE_LINE_NUMBER (x);
384 if (ln >= (int) NOTE_INSN_BIAS && ln < (int) NOTE_INSN_MAX)
385 fprintf (file, " %s", GET_NOTE_INSN_NAME (ln));
386 else
388 expanded_location s;
389 NOTE_EXPANDED_LOCATION (s, x);
390 fprintf (file, " line %d", s.line);
391 if (s.file != NULL)
392 fprintf (file, ":%s", s.file);
395 else
397 fprintf (file, "\t");
398 ra_print_rtx (file, PATTERN (x), 0);
400 return;
402 switch (code)
404 /* Top-level stuff. */
405 case PARALLEL:
407 int j;
408 for (j = 0; j < XVECLEN (x, 0); j++)
410 if (j)
411 fputs ("\t;; ", file);
412 ra_print_rtx (file, XVECEXP (x, 0, j), 0);
414 break;
416 case UNSPEC: case UNSPEC_VOLATILE:
418 int j;
419 fprintf (file, "unspec%s(%d",
420 (code == UNSPEC) ? "" : "_vol", XINT (x, 1));
421 for (j = 0; j < XVECLEN (x, 0); j++)
423 fputs (", ", file);
424 ra_print_rtx (file, XVECEXP (x, 0, j), 0);
426 fputs (")", file);
427 break;
429 case SET:
430 if (GET_CODE (SET_DEST (x)) == PC)
432 if (GET_CODE (SET_SRC (x)) == IF_THEN_ELSE
433 && GET_CODE (XEXP (SET_SRC(x), 2)) == PC)
435 fputs ("if ", file);
436 ra_print_rtx (file, XEXP (SET_SRC (x), 0), 0);
437 fputs (" jump ", file);
438 ra_print_rtx (file, XEXP (SET_SRC (x), 1), 0);
440 else
442 fputs ("jump ", file);
443 ra_print_rtx (file, SET_SRC (x), 0);
446 else
448 ra_print_rtx (file, SET_DEST (x), 0);
449 fputs (" <= ", file);
450 ra_print_rtx (file, SET_SRC (x), 0);
452 break;
453 case USE:
454 fputs ("use <= ", file);
455 ra_print_rtx (file, XEXP (x, 0), 0);
456 break;
457 case CLOBBER:
458 ra_print_rtx (file, XEXP (x, 0), 0);
459 fputs (" <= clobber", file);
460 break;
461 case CALL:
462 fputs ("call ", file);
463 ra_print_rtx (file, XEXP (x, 0), 0); /* Address */
464 fputs (" numargs=", file);
465 ra_print_rtx (file, XEXP (x, 1), 0); /* Num arguments */
466 break;
467 case RETURN:
468 fputs ("return", file);
469 break;
470 case TRAP_IF:
471 fputs ("if (", file);
472 ra_print_rtx (file, XEXP (x, 0), 0);
473 fputs (") trap ", file);
474 ra_print_rtx (file, XEXP (x, 1), 0);
475 break;
476 case RESX:
477 fprintf (file, "resx from region %d", XINT (x, 0));
478 break;
480 /* Different things of class 'x' */
481 case SUBREG: ra_print_rtx_object (file, x); break;
482 case STRICT_LOW_PART:
483 fputs ("low(", file);
484 ra_print_rtx (file, XEXP (x, 0), 0);
485 fputs (")", file);
486 break;
487 default:
488 unhandled = 1;
489 break;
491 if (!unhandled)
492 return;
493 switch (GET_RTX_CLASS (code))
495 case RTX_UNARY:
496 ra_print_rtx_1op (file, x);
497 break;
498 case RTX_BIN_ARITH:
499 case RTX_COMM_ARITH:
500 case RTX_COMPARE:
501 case RTX_COMM_COMPARE:
502 ra_print_rtx_2op (file, x);
503 break;
504 case RTX_TERNARY:
505 case RTX_BITFIELD_OPS:
506 ra_print_rtx_3op (file, x);
507 break;
508 case RTX_OBJ:
509 case RTX_CONST_OBJ:
510 ra_print_rtx_object (file, x);
511 break;
512 default:
513 print_inline_rtx (file, x, 0);
514 break;
518 /* This only calls ra_print_rtx(), but emits a final newline. */
520 void
521 ra_print_rtx_top (FILE *file, rtx x, int with_pn)
523 ra_print_rtx (file, x, with_pn);
524 fprintf (file, "\n");
527 /* Callable from gdb. This prints rtx X onto stderr. */
529 void
530 ra_debug_rtx (rtx x)
532 ra_print_rtx_top (stderr, x, 1);
535 /* This prints the content of basic block with index BBI.
536 The first and last insn are emitted with UIDs of prev and next insns. */
538 void
539 ra_debug_bbi (int bbi)
541 basic_block bb = BASIC_BLOCK (bbi);
542 rtx insn;
543 for (insn = BB_HEAD (bb); insn; insn = NEXT_INSN (insn))
545 ra_print_rtx_top (stderr, insn,
546 (insn == BB_HEAD (bb) || insn == BB_END (bb)));
547 fprintf (stderr, "\n");
548 if (insn == BB_END (bb))
549 break;
553 /* Beginning from INSN, emit NUM insns (if NUM is non-negative)
554 or emit a window of NUM insns around INSN, to stderr. */
556 void
557 ra_debug_insns (rtx insn, int num)
559 int i, count = (num == 0 ? 1 : num < 0 ? -num : num);
560 if (num < 0)
561 for (i = count / 2; i > 0 && PREV_INSN (insn); i--)
562 insn = PREV_INSN (insn);
563 for (i = count; i > 0 && insn; insn = NEXT_INSN (insn), i--)
565 if (LABEL_P (insn))
566 fprintf (stderr, "\n");
567 ra_print_rtx_top (stderr, insn, (i == count || i == 1));
571 /* Beginning with INSN, emit the whole insn chain into FILE.
572 This also outputs comments when basic blocks start or end and omits
573 some notes, if flag_ra_dump_notes is zero. */
575 void
576 ra_print_rtl_with_bb (FILE *file, rtx insn)
578 basic_block last_bb, bb;
579 unsigned int num = 0;
580 if (!insn)
581 fputs ("nil", file);
582 last_bb = NULL;
583 for (; insn; insn = NEXT_INSN (insn))
585 if (BARRIER_P (insn))
586 bb = NULL;
587 else
588 bb = BLOCK_FOR_INSN (insn);
589 if (bb != last_bb)
591 if (last_bb)
592 fprintf (file, ";; End of basic block %d\n", last_bb->index);
593 if (bb)
594 fprintf (file, ";; Begin of basic block %d\n", bb->index);
595 last_bb = bb;
597 if (LABEL_P (insn))
598 fputc ('\n', file);
599 if (NOTE_P (insn))
601 /* Ignore basic block and maybe other notes not referencing
602 deleted things. */
603 if (NOTE_LINE_NUMBER (insn) != NOTE_INSN_BASIC_BLOCK
604 && (flag_ra_dump_notes
605 || NOTE_LINE_NUMBER (insn) == NOTE_INSN_DELETED
606 || NOTE_LINE_NUMBER (insn) == NOTE_INSN_DELETED_LABEL))
608 ra_print_rtx_top (file, insn, (num == 0 || !NEXT_INSN (insn)));
609 num++;
612 else
614 ra_print_rtx_top (file, insn, (num == 0 || !NEXT_INSN (insn)));
615 num++;
620 /* Count how many insns were seen how often, while building the interference
621 graph, and prints the findings. */
623 void
624 dump_number_seen (void)
626 #define N 17
627 int num[N];
628 int i;
630 for (i = 0; i < N; i++)
631 num[i] = 0;
632 for (i = 0; i < get_max_uid (); i++)
633 if (number_seen[i] < N - 1)
634 num[number_seen[i]]++;
635 else
636 num[N - 1]++;
637 for (i = 0; i < N - 1; i++)
638 if (num[i])
639 ra_debug_msg (DUMP_PROCESS, "%d insns seen %d times\n", num[i], i);
640 if (num[N - 1])
641 ra_debug_msg (DUMP_PROCESS, "%d insns seen %d and more times\n", num[i],
642 N - 1);
643 ra_debug_msg (DUMP_PROCESS, "from overall %d insns\n", get_max_uid ());
644 #undef N
647 /* Dump the interference graph, the move list and the webs. */
649 void
650 dump_igraph (struct df *df ATTRIBUTE_UNUSED)
652 struct move_list *ml;
653 unsigned int def1, def2;
654 int num = 0;
655 int num2;
656 unsigned int i;
657 if (!dump_file || (debug_new_regalloc & (DUMP_IGRAPH | DUMP_WEBS)) == 0)
658 return;
659 ra_debug_msg (DUMP_IGRAPH, "conflicts:\n ");
660 for (def1 = 0; def1 < num_webs; def1++)
662 int num1 = num;
663 num2 = 0;
664 for (def2 = 0; def2 < num_webs; def2++)
665 if (def1 != def2 && TEST_BIT (igraph, igraph_index (def1, def2)))
667 if (num1 == num)
669 if (SUBWEB_P (ID2WEB (def1)))
670 ra_debug_msg (DUMP_IGRAPH, "%d (SUBREG %d, %d) with ", def1,
671 ID2WEB (def1)->regno,
672 SUBREG_BYTE (ID2WEB (def1)->orig_x));
673 else
674 ra_debug_msg (DUMP_IGRAPH, "%d (REG %d) with ", def1,
675 ID2WEB (def1)->regno);
677 if ((num2 % 9) == 8)
678 ra_debug_msg (DUMP_IGRAPH, "\n ");
679 num++;
680 num2++;
681 if (SUBWEB_P (ID2WEB (def2)))
682 ra_debug_msg (DUMP_IGRAPH, "%d(%d,%d) ", def2, ID2WEB (def2)->regno,
683 SUBREG_BYTE (ID2WEB (def2)->orig_x));
684 else
685 ra_debug_msg (DUMP_IGRAPH, "%d(%d) ", def2, ID2WEB (def2)->regno);
687 if (num1 != num)
688 ra_debug_msg (DUMP_IGRAPH, "\n ");
690 ra_debug_msg (DUMP_IGRAPH, "\n");
691 for (ml = wl_moves; ml; ml = ml->next)
692 if (ml->move)
694 ra_debug_msg (DUMP_IGRAPH, "move: insn %d: Web %d <-- Web %d\n",
695 INSN_UID (ml->move->insn), ml->move->target_web->id,
696 ml->move->source_web->id);
698 ra_debug_msg (DUMP_WEBS, "\nWebs:\n");
699 for (i = 0; i < num_webs; i++)
701 struct web *web = ID2WEB (i);
703 ra_debug_msg (DUMP_WEBS, " %4d : regno %3d", i, web->regno);
704 if (SUBWEB_P (web))
706 ra_debug_msg (DUMP_WEBS, " sub %d", SUBREG_BYTE (web->orig_x));
707 ra_debug_msg (DUMP_WEBS, " par %d", find_web_for_subweb (web)->id);
709 ra_debug_msg (DUMP_WEBS, " +%d (span %d, cost "
710 HOST_WIDE_INT_PRINT_DEC ") (%s)",
711 web->add_hardregs, web->span_deaths, web->spill_cost,
712 reg_class_names[web->regclass]);
713 if (web->spill_temp == 1)
714 ra_debug_msg (DUMP_WEBS, " (spilltemp)");
715 else if (web->spill_temp == 2)
716 ra_debug_msg (DUMP_WEBS, " (spilltem2)");
717 else if (web->spill_temp == 3)
718 ra_debug_msg (DUMP_WEBS, " (short)");
719 if (web->type == PRECOLORED)
720 ra_debug_msg (DUMP_WEBS, " (precolored, color=%d)", web->color);
721 else if (find_web_for_subweb (web)->num_uses == 0)
722 ra_debug_msg (DUMP_WEBS, " dead");
723 if (web->crosses_call)
724 ra_debug_msg (DUMP_WEBS, " xcall");
725 if (web->regno >= max_normal_pseudo)
726 ra_debug_msg (DUMP_WEBS, " stack");
727 ra_debug_msg (DUMP_WEBS, "\n");
731 /* Dump the interference graph and webs in a format easily
732 parsable by programs. Used to emit real world interference graph
733 to my custom graph colorizer. */
735 void
736 dump_igraph_machine (void)
738 unsigned int i;
740 if (!dump_file || (debug_new_regalloc & DUMP_IGRAPH_M) == 0)
741 return;
742 ra_debug_msg (DUMP_IGRAPH_M, "g %d %d\n", num_webs - num_subwebs,
743 FIRST_PSEUDO_REGISTER);
744 for (i = 0; i < num_webs - num_subwebs; i++)
746 struct web *web = ID2WEB (i);
747 struct conflict_link *cl;
748 int flags = 0;
749 int numc = 0;
750 int col = 0;
751 flags = web->spill_temp & 0xF;
752 flags |= ((web->type == PRECOLORED) ? 1 : 0) << 4;
753 flags |= (web->add_hardregs & 0xF) << 5;
754 for (cl = web->conflict_list; cl; cl = cl->next)
755 if (cl->t->id < web->id)
756 numc++;
757 ra_debug_msg (DUMP_IGRAPH_M, "n %d %d %d %d %d %d %d\n",
758 web->id, web->color, flags,
759 (unsigned int)web->spill_cost, web->num_defs, web->num_uses,
760 numc);
761 if (web->type != PRECOLORED)
763 ra_debug_msg (DUMP_IGRAPH_M, "s %d", web->id);
764 while (1)
766 unsigned int u = 0;
767 int n;
768 for (n = 0; n < 32 && col < FIRST_PSEUDO_REGISTER; n++, col++)
769 if (TEST_HARD_REG_BIT (web->usable_regs, col))
770 u |= 1 << n;
771 ra_debug_msg (DUMP_IGRAPH_M, " %u", u);
772 if (col >= FIRST_PSEUDO_REGISTER)
773 break;
775 ra_debug_msg (DUMP_IGRAPH_M, "\n");
777 if (numc)
779 ra_debug_msg (DUMP_IGRAPH_M, "c %d", web->id);
780 for (cl = web->conflict_list; cl; cl = cl->next)
782 if (cl->t->id < web->id)
783 ra_debug_msg (DUMP_IGRAPH_M, " %d", cl->t->id);
785 ra_debug_msg (DUMP_IGRAPH_M, "\n");
788 ra_debug_msg (DUMP_IGRAPH_M, "e\n");
791 /* This runs after colorization and changing the insn stream.
792 It temporarily replaces all pseudo registers with their colors,
793 and emits information, if the resulting insns are strictly valid. */
795 void
796 dump_constraints (void)
798 rtx insn;
799 int i;
800 if (!dump_file || (debug_new_regalloc & DUMP_CONSTRAINTS) == 0)
801 return;
802 for (i = FIRST_PSEUDO_REGISTER; i < ra_max_regno; i++)
803 if (regno_reg_rtx[i] && REG_P (regno_reg_rtx[i]))
804 REGNO (regno_reg_rtx[i])
805 = ra_reg_renumber[i] >= 0 ? ra_reg_renumber[i] : i;
806 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
807 if (INSN_P (insn))
809 int code;
810 int uid = INSN_UID (insn);
811 int o;
812 /* Don't simply force rerecognition, as combine might left us
813 with some unrecognizable ones, which later leads to aborts
814 in regclass, if we now destroy the remembered INSN_CODE(). */
815 /*INSN_CODE (insn) = -1;*/
816 code = recog_memoized (insn);
817 if (code < 0)
819 ra_debug_msg (DUMP_CONSTRAINTS,
820 "%d: asm insn or not recognizable.\n", uid);
821 continue;
823 ra_debug_msg (DUMP_CONSTRAINTS,
824 "%d: code %d {%s}, %d operands, constraints: ",
825 uid, code, insn_data[code].name, recog_data.n_operands);
826 extract_insn (insn);
827 /*preprocess_constraints ();*/
828 for (o = 0; o < recog_data.n_operands; o++)
830 ra_debug_msg (DUMP_CONSTRAINTS,
831 "%d:%s ", o, recog_data.constraints[o]);
833 if (constrain_operands (1))
834 ra_debug_msg (DUMP_CONSTRAINTS, "matches strictly alternative %d",
835 which_alternative);
836 else
837 ra_debug_msg (DUMP_CONSTRAINTS, "doesn't match strictly");
838 ra_debug_msg (DUMP_CONSTRAINTS, "\n");
840 for (i = FIRST_PSEUDO_REGISTER; i < ra_max_regno; i++)
841 if (regno_reg_rtx[i] && REG_P (regno_reg_rtx[i]))
842 REGNO (regno_reg_rtx[i]) = i;
845 /* This counts and emits the cumulated cost of all spilled webs,
846 preceded by a custom message MSG, with debug level LEVEL. */
848 void
849 dump_graph_cost (unsigned int level, const char *msg)
851 unsigned int i;
852 unsigned HOST_WIDE_INT cost;
853 if (!dump_file || (debug_new_regalloc & level) == 0)
854 return;
856 cost = 0;
857 for (i = 0; i < num_webs; i++)
859 struct web *web = id2web[i];
860 if (alias (web)->type == SPILLED)
861 cost += web->orig_spill_cost;
863 ra_debug_msg (level, " spill cost of graph (%s) = "
864 HOST_WIDE_INT_PRINT_UNSIGNED "\n",
865 msg ? msg : "", cost);
868 /* Dump the color assignment per web, the coalesced and spilled webs. */
870 void
871 dump_ra (struct df *df ATTRIBUTE_UNUSED)
873 struct web *web;
874 struct dlist *d;
875 if (!dump_file || (debug_new_regalloc & DUMP_RESULTS) == 0)
876 return;
878 ra_debug_msg (DUMP_RESULTS, "\nColored:\n");
879 for (d = WEBS(COLORED); d; d = d->next)
881 web = DLIST_WEB (d);
882 ra_debug_msg (DUMP_RESULTS, " %4d : color %d\n", web->id, web->color);
884 ra_debug_msg (DUMP_RESULTS, "\nCoalesced:\n");
885 for (d = WEBS(COALESCED); d; d = d->next)
887 web = DLIST_WEB (d);
888 ra_debug_msg (DUMP_RESULTS, " %4d : to web %d, color %d\n", web->id,
889 alias (web)->id, web->color);
891 ra_debug_msg (DUMP_RESULTS, "\nSpilled:\n");
892 for (d = WEBS(SPILLED); d; d = d->next)
894 web = DLIST_WEB (d);
895 ra_debug_msg (DUMP_RESULTS, " %4d\n", web->id);
897 ra_debug_msg (DUMP_RESULTS, "\n");
898 dump_cost (DUMP_RESULTS);
901 /* Calculate and dump the cumulated costs of certain types of insns
902 (loads, stores and copies). */
904 void
905 dump_static_insn_cost (FILE *file, const char *message, const char *prefix)
907 struct cost
909 unsigned HOST_WIDE_INT cost;
910 unsigned int count;
912 basic_block bb;
913 struct cost load, store, regcopy, selfcopy, overall;
914 memset (&load, 0, sizeof(load));
915 memset (&store, 0, sizeof(store));
916 memset (&regcopy, 0, sizeof(regcopy));
917 memset (&selfcopy, 0, sizeof(selfcopy));
918 memset (&overall, 0, sizeof(overall));
920 if (!file)
921 return;
923 FOR_EACH_BB (bb)
925 unsigned HOST_WIDE_INT block_cost = bb->frequency;
926 rtx insn, set;
927 for (insn = BB_HEAD (bb); insn; insn = NEXT_INSN (insn))
929 /* Yes, yes. We don't calculate the costs precisely.
930 Only for "simple enough" insns. Those containing single
931 sets only. */
932 if (INSN_P (insn) && ((set = single_set (insn)) != NULL))
934 rtx src = SET_SRC (set);
935 rtx dest = SET_DEST (set);
936 struct cost *pcost = NULL;
937 overall.cost += block_cost;
938 overall.count++;
939 if (rtx_equal_p (src, dest))
940 pcost = &selfcopy;
941 else if (GET_CODE (src) == GET_CODE (dest)
942 && ((REG_P (src))
943 || (GET_CODE (src) == SUBREG
944 && REG_P (SUBREG_REG (src))
945 && REG_P (SUBREG_REG (dest)))))
946 /* XXX is dest guaranteed to be a subreg? */
947 pcost = &regcopy;
948 else
950 if (GET_CODE (src) == SUBREG)
951 src = SUBREG_REG (src);
952 if (GET_CODE (dest) == SUBREG)
953 dest = SUBREG_REG (dest);
954 if (MEM_P (src) && !MEM_P (dest)
955 && memref_is_stack_slot (src))
956 pcost = &load;
957 else if (!MEM_P (src) && MEM_P (dest)
958 && memref_is_stack_slot (dest))
959 pcost = &store;
961 if (pcost)
963 pcost->cost += block_cost;
964 pcost->count++;
967 if (insn == BB_END (bb))
968 break;
972 if (!prefix)
973 prefix = "";
974 fprintf (file, "static insn cost %s\n", message ? message : "");
975 fprintf (file, " %soverall:\tnum=%6d\tcost=% 8" HOST_WIDE_INT_PRINT "d\n",
976 prefix, overall.count, overall.cost);
977 fprintf (file, " %sloads:\tnum=%6d\tcost=% 8" HOST_WIDE_INT_PRINT "d\n",
978 prefix, load.count, load.cost);
979 fprintf (file, " %sstores:\tnum=%6d\tcost=% 8" HOST_WIDE_INT_PRINT "d\n",
980 prefix, store.count, store.cost);
981 fprintf (file, " %sregcopy:\tnum=%6d\tcost=% 8" HOST_WIDE_INT_PRINT "d\n",
982 prefix, regcopy.count, regcopy.cost);
983 fprintf (file, " %sselfcpy:\tnum=%6d\tcost=% 8" HOST_WIDE_INT_PRINT "d\n",
984 prefix, selfcopy.count, selfcopy.cost);
987 /* Returns nonzero, if WEB1 and WEB2 have some possible
988 hardregs in common. */
991 web_conflicts_p (struct web *web1, struct web *web2)
993 if (web1->type == PRECOLORED && web2->type == PRECOLORED)
994 return 0;
996 if (web1->type == PRECOLORED)
997 return TEST_HARD_REG_BIT (web2->usable_regs, web1->regno);
999 if (web2->type == PRECOLORED)
1000 return TEST_HARD_REG_BIT (web1->usable_regs, web2->regno);
1002 return hard_regs_intersect_p (&web1->usable_regs, &web2->usable_regs);
1005 /* Dump all uids of insns in which WEB is mentioned. */
1007 void
1008 dump_web_insns (struct web *web)
1010 unsigned int i;
1012 ra_debug_msg (DUMP_EVER, "Web: %i(%i)+%i class: %s freedom: %i degree %i\n",
1013 web->id, web->regno, web->add_hardregs,
1014 reg_class_names[web->regclass],
1015 web->num_freedom, web->num_conflicts);
1016 ra_debug_msg (DUMP_EVER, " def insns:");
1018 for (i = 0; i < web->num_defs; ++i)
1020 ra_debug_msg (DUMP_EVER, " %d ", INSN_UID (web->defs[i]->insn));
1023 ra_debug_msg (DUMP_EVER, "\n use insns:");
1024 for (i = 0; i < web->num_uses; ++i)
1026 ra_debug_msg (DUMP_EVER, " %d ", INSN_UID (web->uses[i]->insn));
1028 ra_debug_msg (DUMP_EVER, "\n");
1031 /* Dump conflicts for web WEB. */
1033 void
1034 dump_web_conflicts (struct web *web)
1036 int num = 0;
1037 unsigned int def2;
1039 ra_debug_msg (DUMP_EVER, "Web: %i(%i)+%i class: %s freedom: %i degree %i\n",
1040 web->id, web->regno, web->add_hardregs,
1041 reg_class_names[web->regclass],
1042 web->num_freedom, web->num_conflicts);
1044 for (def2 = 0; def2 < num_webs; def2++)
1045 if (TEST_BIT (igraph, igraph_index (web->id, def2)) && web->id != def2)
1047 if ((num % 9) == 5)
1048 ra_debug_msg (DUMP_EVER, "\n ");
1049 num++;
1051 ra_debug_msg (DUMP_EVER, " %d(%d)", def2, id2web[def2]->regno);
1052 if (id2web[def2]->add_hardregs)
1053 ra_debug_msg (DUMP_EVER, "+%d", id2web[def2]->add_hardregs);
1055 if (web_conflicts_p (web, id2web[def2]))
1056 ra_debug_msg (DUMP_EVER, "/x");
1058 if (id2web[def2]->type == SELECT)
1059 ra_debug_msg (DUMP_EVER, "/s");
1061 if (id2web[def2]->type == COALESCED)
1062 ra_debug_msg (DUMP_EVER,"/c/%d", alias (id2web[def2])->id);
1064 ra_debug_msg (DUMP_EVER, "\n");
1066 struct conflict_link *wl;
1067 num = 0;
1068 ra_debug_msg (DUMP_EVER, "By conflicts: ");
1069 for (wl = web->conflict_list; wl; wl = wl->next)
1071 struct web* w = wl->t;
1072 if ((num % 9) == 8)
1073 ra_debug_msg (DUMP_EVER, "\n ");
1074 num++;
1075 ra_debug_msg (DUMP_EVER, "%d(%d)%s ", w->id, w->regno,
1076 web_conflicts_p (web, w) ? "+" : "");
1078 ra_debug_msg (DUMP_EVER, "\n");
1082 /* Output HARD_REG_SET to stderr. */
1084 void
1085 debug_hard_reg_set (HARD_REG_SET set)
1087 int i;
1088 for (i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
1090 if (TEST_HARD_REG_BIT (set, i))
1092 fprintf (stderr, "%s ", reg_names[i]);
1095 fprintf (stderr, "\n");
1099 vim:cinoptions={.5s,g0,p5,t0,(0,^-0.5s,n-0.5s:tw=78:cindent:sw=4: