Ayee, missed a file.
[official-gcc.git] / gcc / ra-debug.c
blobd060e0487d3a73c911a1a40e4eba385f84e8f46b
1 /* Graph coloring register allocator
2 Copyright (C) 2001, 2002, 2004 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 && dump_file != NULL)
58 vfprintf (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 LTGT: opname = "<>"; break;
137 /* class '<' */
138 case GE: opname = "s>="; break;
139 case GT: opname = "s>"; break;
140 case LE: opname = "s<="; break;
141 case LT: opname = "s<"; break;
142 case GEU: opname = "u>="; break;
143 case GTU: opname = "u>"; break;
144 case LEU: opname = "u<="; break;
145 case LTU: opname = "u<"; break;
146 default:
147 infix = 0;
148 opname = GET_RTX_NAME (code);
149 break;
151 if (infix)
153 fputs ("(", file);
154 ra_print_rtx (file, op0, 0);
155 fprintf (file, " %s ", opname);
156 ra_print_rtx (file, op1, 0);
157 fputs (")", file);
159 else
161 fprintf (file, "%s(", opname);
162 ra_print_rtx (file, op0, 0);
163 fputs (", ", file);
164 ra_print_rtx (file, op1, 0);
165 fputs (")", file);
169 /* Print rtx X, which a three operand rtx to FILE.
170 I.e. X is either an IF_THEN_ELSE, or a bitmap operation. */
172 static void
173 ra_print_rtx_3op (FILE *file, rtx x)
175 enum rtx_code code = GET_CODE (x);
176 rtx op0 = XEXP (x, 0);
177 rtx op1 = XEXP (x, 1);
178 rtx op2 = XEXP (x, 2);
179 if (code == IF_THEN_ELSE)
181 ra_print_rtx (file, op0, 0);
182 fputs (" ? ", file);
183 ra_print_rtx (file, op1, 0);
184 fputs (" : ", file);
185 ra_print_rtx (file, op2, 0);
187 else
189 /* Bitmap-operation */
190 fprintf (file, "%s:%s(", GET_RTX_NAME (code),
191 GET_MODE_NAME (GET_MODE (x)));
192 ra_print_rtx (file, op0, 0);
193 fputs (", ", file);
194 ra_print_rtx (file, op1, 0);
195 fputs (", ", file);
196 ra_print_rtx (file, op2, 0);
197 fputs (")", file);
201 /* Print rtx X, which represents an object (class 'o', 'C', or some constructs
202 of class 'x' (e.g. subreg)), to FILE.
203 (reg XX) rtl is represented as "pXX", of XX was a pseudo,
204 as "name" it name is the nonnull hardreg name, or as "hXX", if XX
205 is a hardreg, whose name is NULL, or empty. */
207 static void
208 ra_print_rtx_object (FILE *file, rtx x)
210 enum rtx_code code = GET_CODE (x);
211 enum machine_mode mode = GET_MODE (x);
212 switch (code)
214 case CONST_INT:
215 fprintf (file, HOST_WIDE_INT_PRINT_DEC, XWINT (x, 0));
216 break;
217 case CONST_DOUBLE:
219 int i, num = 0;
220 const char *fmt = GET_RTX_FORMAT (code);
221 fputs ("dbl(", file);
222 for (i = 0; i < GET_RTX_LENGTH (code); i++)
224 if (num)
225 fputs (", ", file);
226 if (fmt[i] == 'e' && XEXP (x, i))
227 /* The MEM or other stuff */
229 ra_print_rtx (file, XEXP (x, i), 0);
230 num++;
232 else if (fmt[i] == 'w')
234 fprintf (file, HOST_WIDE_INT_PRINT_HEX, XWINT (x, i));
235 num++;
238 break;
240 case CONST_STRING: fprintf (file, "\"%s\"", XSTR (x, 0)); break;
241 case CONST: fputs ("const(", file);
242 ra_print_rtx (file, XEXP (x, 0), 0);
243 fputs (")", file);
244 break;
245 case PC: fputs ("pc", file); break;
246 case REG:
248 int regno = REGNO (x);
249 if (regno < FIRST_PSEUDO_REGISTER)
251 int i, nregs = hard_regno_nregs[regno][mode];
252 if (nregs > 1)
253 fputs ("[", file);
254 for (i = 0; i < nregs; i++)
256 if (i)
257 fputs (", ", file);
258 if (reg_names[regno+i] && *reg_names[regno + i])
259 fprintf (file, "%s", reg_names[regno + i]);
260 else
261 fprintf (file, "h%d", regno + i);
263 if (nregs > 1)
264 fputs ("]", file);
266 else
267 fprintf (file, "p%d", regno);
268 break;
270 case SUBREG:
272 rtx sub = SUBREG_REG (x);
273 int ofs = SUBREG_BYTE (x);
274 if (REG_P (sub)
275 && REGNO (sub) < FIRST_PSEUDO_REGISTER)
277 int regno = REGNO (sub);
278 int i, nregs = hard_regno_nregs[regno][mode];
279 regno += subreg_regno_offset (regno, GET_MODE (sub),
280 ofs, mode);
281 if (nregs > 1)
282 fputs ("[", file);
283 for (i = 0; i < nregs; i++)
285 if (i)
286 fputs (", ", file);
287 if (reg_names[regno+i])
288 fprintf (file, "%s", reg_names[regno + i]);
289 else
290 fprintf (file, "h%d", regno + i);
292 if (nregs > 1)
293 fputs ("]", file);
295 else
297 ra_print_rtx (file, sub, 0);
298 fprintf (file, ":[%s+%d]", GET_MODE_NAME (mode), ofs);
300 break;
302 case SCRATCH: fputs ("scratch", file); break;
303 case CONCAT: ra_print_rtx_2op (file, x); break;
304 case HIGH: ra_print_rtx_1op (file, x); break;
305 case LO_SUM:
306 fputs ("(", file);
307 ra_print_rtx (file, XEXP (x, 0), 0);
308 fputs (" + lo(", file);
309 ra_print_rtx (file, XEXP (x, 1), 0);
310 fputs ("))", file);
311 break;
312 case MEM: fputs ("[", file);
313 ra_print_rtx (file, XEXP (x, 0), 0);
314 fprintf (file, "]:%s", GET_MODE_NAME (GET_MODE (x)));
315 /* XXX print alias set too ?? */
316 break;
317 case LABEL_REF:
319 rtx sub = XEXP (x, 0);
320 if (NOTE_P (sub)
321 && NOTE_LINE_NUMBER (sub) == NOTE_INSN_DELETED_LABEL)
322 fprintf (file, "(deleted uid=%d)", INSN_UID (sub));
323 else if (LABEL_P (sub))
324 fprintf (file, "L%d", CODE_LABEL_NUMBER (sub));
325 else
326 fprintf (file, "(nonlabel uid=%d)", INSN_UID (sub));
328 break;
329 case SYMBOL_REF:
330 fprintf (file, "sym(\"%s\")", XSTR (x, 0)); break;
331 case CC0: fputs ("cc0", file); break;
332 default: print_inline_rtx (file, x, 0); break;
336 /* Print a general rtx X to FILE in nice infix form.
337 If WITH_PN is set, and X is one of the toplevel constructs
338 (insns, notes, labels or barriers), then print also the UIDs of
339 the preceding and following insn. */
341 void
342 ra_print_rtx (FILE *file, rtx x, int with_pn)
344 enum rtx_code code;
345 int unhandled = 0;
346 if (!x)
347 return;
348 code = GET_CODE (x);
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 expanded_location s;
393 NOTE_EXPANDED_LOCATION (s, x);
394 fprintf (file, " line %d", s.line);
395 if (s.file != NULL)
396 fprintf (file, ":%s", s.file);
399 else
401 fprintf (file, "\t");
402 ra_print_rtx (file, PATTERN (x), 0);
404 return;
406 switch (code)
408 /* Top-level stuff. */
409 case PARALLEL:
411 int j;
412 for (j = 0; j < XVECLEN (x, 0); j++)
414 if (j)
415 fputs ("\t;; ", file);
416 ra_print_rtx (file, XVECEXP (x, 0, j), 0);
418 break;
420 case UNSPEC: case UNSPEC_VOLATILE:
422 int j;
423 fprintf (file, "unspec%s(%d",
424 (code == UNSPEC) ? "" : "_vol", XINT (x, 1));
425 for (j = 0; j < XVECLEN (x, 0); j++)
427 fputs (", ", file);
428 ra_print_rtx (file, XVECEXP (x, 0, j), 0);
430 fputs (")", file);
431 break;
433 case SET:
434 if (GET_CODE (SET_DEST (x)) == PC)
436 if (GET_CODE (SET_SRC (x)) == IF_THEN_ELSE
437 && GET_CODE (XEXP (SET_SRC(x), 2)) == PC)
439 fputs ("if ", file);
440 ra_print_rtx (file, XEXP (SET_SRC (x), 0), 0);
441 fputs (" jump ", file);
442 ra_print_rtx (file, XEXP (SET_SRC (x), 1), 0);
444 else
446 fputs ("jump ", file);
447 ra_print_rtx (file, SET_SRC (x), 0);
450 else
452 ra_print_rtx (file, SET_DEST (x), 0);
453 fputs (" <= ", file);
454 ra_print_rtx (file, SET_SRC (x), 0);
456 break;
457 case USE:
458 fputs ("use <= ", file);
459 ra_print_rtx (file, XEXP (x, 0), 0);
460 break;
461 case CLOBBER:
462 ra_print_rtx (file, XEXP (x, 0), 0);
463 fputs (" <= clobber", file);
464 break;
465 case CALL:
466 fputs ("call ", file);
467 ra_print_rtx (file, XEXP (x, 0), 0); /* Address */
468 fputs (" numargs=", file);
469 ra_print_rtx (file, XEXP (x, 1), 0); /* Num arguments */
470 break;
471 case RETURN:
472 fputs ("return", file);
473 break;
474 case TRAP_IF:
475 fputs ("if (", file);
476 ra_print_rtx (file, XEXP (x, 0), 0);
477 fputs (") trap ", file);
478 ra_print_rtx (file, XEXP (x, 1), 0);
479 break;
480 case RESX:
481 fprintf (file, "resx from region %d", XINT (x, 0));
482 break;
484 /* Different things of class 'x' */
485 case SUBREG: ra_print_rtx_object (file, x); break;
486 case STRICT_LOW_PART:
487 fputs ("low(", file);
488 ra_print_rtx (file, XEXP (x, 0), 0);
489 fputs (")", file);
490 break;
491 default:
492 unhandled = 1;
493 break;
495 if (!unhandled)
496 return;
497 switch (GET_RTX_CLASS (code))
499 case RTX_UNARY:
500 ra_print_rtx_1op (file, x);
501 break;
502 case RTX_BIN_ARITH:
503 case RTX_COMM_ARITH:
504 case RTX_COMPARE:
505 case RTX_COMM_COMPARE:
506 ra_print_rtx_2op (file, x);
507 break;
508 case RTX_TERNARY:
509 case RTX_BITFIELD_OPS:
510 ra_print_rtx_3op (file, x);
511 break;
512 case RTX_OBJ:
513 case RTX_CONST_OBJ:
514 ra_print_rtx_object (file, x);
515 break;
516 default:
517 print_inline_rtx (file, x, 0);
518 break;
522 /* This only calls ra_print_rtx(), but emits a final newline. */
524 void
525 ra_print_rtx_top (FILE *file, rtx x, int with_pn)
527 ra_print_rtx (file, x, with_pn);
528 fprintf (file, "\n");
531 /* Callable from gdb. This prints rtx X onto stderr. */
533 void
534 ra_debug_rtx (rtx x)
536 ra_print_rtx_top (stderr, x, 1);
539 /* This prints the content of basic block with index BBI.
540 The first and last insn are emitted with UIDs of prev and next insns. */
542 void
543 ra_debug_bbi (int bbi)
545 basic_block bb = BASIC_BLOCK (bbi);
546 rtx insn;
547 for (insn = BB_HEAD (bb); insn; insn = NEXT_INSN (insn))
549 ra_print_rtx_top (stderr, insn,
550 (insn == BB_HEAD (bb) || insn == BB_END (bb)));
551 fprintf (stderr, "\n");
552 if (insn == BB_END (bb))
553 break;
557 /* Beginning from INSN, emit NUM insns (if NUM is non-negative)
558 or emit a window of NUM insns around INSN, to stderr. */
560 void
561 ra_debug_insns (rtx insn, int num)
563 int i, count = (num == 0 ? 1 : num < 0 ? -num : num);
564 if (num < 0)
565 for (i = count / 2; i > 0 && PREV_INSN (insn); i--)
566 insn = PREV_INSN (insn);
567 for (i = count; i > 0 && insn; insn = NEXT_INSN (insn), i--)
569 if (LABEL_P (insn))
570 fprintf (stderr, "\n");
571 ra_print_rtx_top (stderr, insn, (i == count || i == 1));
575 /* Beginning with INSN, emit the whole insn chain into FILE.
576 This also outputs comments when basic blocks start or end and omits
577 some notes, if flag_ra_dump_notes is zero. */
579 void
580 ra_print_rtl_with_bb (FILE *file, rtx insn)
582 basic_block last_bb, bb;
583 unsigned int num = 0;
584 if (!insn)
585 fputs ("nil", file);
586 last_bb = NULL;
587 for (; insn; insn = NEXT_INSN (insn))
589 if (BARRIER_P (insn))
590 bb = NULL;
591 else
592 bb = BLOCK_FOR_INSN (insn);
593 if (bb != last_bb)
595 if (last_bb)
596 fprintf (file, ";; End of basic block %d\n", last_bb->index);
597 if (bb)
598 fprintf (file, ";; Begin of basic block %d\n", bb->index);
599 last_bb = bb;
601 if (LABEL_P (insn))
602 fputc ('\n', file);
603 if (NOTE_P (insn))
605 /* Ignore basic block and maybe other notes not referencing
606 deleted things. */
607 if (NOTE_LINE_NUMBER (insn) != NOTE_INSN_BASIC_BLOCK
608 && (flag_ra_dump_notes
609 || NOTE_LINE_NUMBER (insn) == NOTE_INSN_DELETED
610 || NOTE_LINE_NUMBER (insn) == NOTE_INSN_DELETED_LABEL))
612 ra_print_rtx_top (file, insn, (num == 0 || !NEXT_INSN (insn)));
613 num++;
616 else
618 ra_print_rtx_top (file, insn, (num == 0 || !NEXT_INSN (insn)));
619 num++;
624 /* Count how many insns were seen how often, while building the interference
625 graph, and prints the findings. */
627 void
628 dump_number_seen (void)
630 #define N 17
631 int num[N];
632 int i;
634 for (i = 0; i < N; i++)
635 num[i] = 0;
636 for (i = 0; i < get_max_uid (); i++)
637 if (number_seen[i] < N - 1)
638 num[number_seen[i]]++;
639 else
640 num[N - 1]++;
641 for (i = 0; i < N - 1; i++)
642 if (num[i])
643 ra_debug_msg (DUMP_PROCESS, "%d insns seen %d times\n", num[i], i);
644 if (num[N - 1])
645 ra_debug_msg (DUMP_PROCESS, "%d insns seen %d and more times\n", num[i],
646 N - 1);
647 ra_debug_msg (DUMP_PROCESS, "from overall %d insns\n", get_max_uid ());
648 #undef N
651 /* Dump the interference graph, the move list and the webs. */
653 void
654 dump_igraph (struct df *df ATTRIBUTE_UNUSED)
656 struct move_list *ml;
657 unsigned int def1, def2;
658 int num = 0;
659 int num2;
660 unsigned int i;
661 if (!dump_file || (debug_new_regalloc & (DUMP_IGRAPH | DUMP_WEBS)) == 0)
662 return;
663 ra_debug_msg (DUMP_IGRAPH, "conflicts:\n ");
664 for (def1 = 0; def1 < num_webs; def1++)
666 int num1 = num;
667 num2 = 0;
668 for (def2 = 0; def2 < num_webs; def2++)
669 if (def1 != def2 && TEST_BIT (igraph, igraph_index (def1, def2)))
671 if (num1 == num)
673 if (SUBWEB_P (ID2WEB (def1)))
674 ra_debug_msg (DUMP_IGRAPH, "%d (SUBREG %d, %d) with ", def1,
675 ID2WEB (def1)->regno,
676 SUBREG_BYTE (ID2WEB (def1)->orig_x));
677 else
678 ra_debug_msg (DUMP_IGRAPH, "%d (REG %d) with ", def1,
679 ID2WEB (def1)->regno);
681 if ((num2 % 9) == 8)
682 ra_debug_msg (DUMP_IGRAPH, "\n ");
683 num++;
684 num2++;
685 if (SUBWEB_P (ID2WEB (def2)))
686 ra_debug_msg (DUMP_IGRAPH, "%d(%d,%d) ", def2, ID2WEB (def2)->regno,
687 SUBREG_BYTE (ID2WEB (def2)->orig_x));
688 else
689 ra_debug_msg (DUMP_IGRAPH, "%d(%d) ", def2, ID2WEB (def2)->regno);
691 if (num1 != num)
692 ra_debug_msg (DUMP_IGRAPH, "\n ");
694 ra_debug_msg (DUMP_IGRAPH, "\n");
695 for (ml = wl_moves; ml; ml = ml->next)
696 if (ml->move)
698 ra_debug_msg (DUMP_IGRAPH, "move: insn %d: Web %d <-- Web %d\n",
699 INSN_UID (ml->move->insn), ml->move->target_web->id,
700 ml->move->source_web->id);
702 ra_debug_msg (DUMP_WEBS, "\nWebs:\n");
703 for (i = 0; i < num_webs; i++)
705 struct web *web = ID2WEB (i);
707 ra_debug_msg (DUMP_WEBS, " %4d : regno %3d", i, web->regno);
708 if (SUBWEB_P (web))
710 ra_debug_msg (DUMP_WEBS, " sub %d", SUBREG_BYTE (web->orig_x));
711 ra_debug_msg (DUMP_WEBS, " par %d", find_web_for_subweb (web)->id);
713 ra_debug_msg (DUMP_WEBS, " +%d (span %d, cost "
714 HOST_WIDE_INT_PRINT_DEC ") (%s)",
715 web->add_hardregs, web->span_deaths, web->spill_cost,
716 reg_class_names[web->regclass]);
717 if (web->spill_temp == 1)
718 ra_debug_msg (DUMP_WEBS, " (spilltemp)");
719 else if (web->spill_temp == 2)
720 ra_debug_msg (DUMP_WEBS, " (spilltem2)");
721 else if (web->spill_temp == 3)
722 ra_debug_msg (DUMP_WEBS, " (short)");
723 if (web->type == PRECOLORED)
724 ra_debug_msg (DUMP_WEBS, " (precolored, color=%d)", web->color);
725 else if (find_web_for_subweb (web)->num_uses == 0)
726 ra_debug_msg (DUMP_WEBS, " dead");
727 if (web->crosses_call)
728 ra_debug_msg (DUMP_WEBS, " xcall");
729 if (web->regno >= max_normal_pseudo)
730 ra_debug_msg (DUMP_WEBS, " stack");
731 ra_debug_msg (DUMP_WEBS, "\n");
735 /* Dump the interference graph and webs in a format easily
736 parsable by programs. Used to emit real world interference graph
737 to my custom graph colorizer. */
739 void
740 dump_igraph_machine (void)
742 unsigned int i;
744 if (!dump_file || (debug_new_regalloc & DUMP_IGRAPH_M) == 0)
745 return;
746 ra_debug_msg (DUMP_IGRAPH_M, "g %d %d\n", num_webs - num_subwebs,
747 FIRST_PSEUDO_REGISTER);
748 for (i = 0; i < num_webs - num_subwebs; i++)
750 struct web *web = ID2WEB (i);
751 struct conflict_link *cl;
752 int flags = 0;
753 int numc = 0;
754 int col = 0;
755 flags = web->spill_temp & 0xF;
756 flags |= ((web->type == PRECOLORED) ? 1 : 0) << 4;
757 flags |= (web->add_hardregs & 0xF) << 5;
758 for (cl = web->conflict_list; cl; cl = cl->next)
759 if (cl->t->id < web->id)
760 numc++;
761 ra_debug_msg (DUMP_IGRAPH_M, "n %d %d %d %d %d %d %d\n",
762 web->id, web->color, flags,
763 (unsigned int)web->spill_cost, web->num_defs, web->num_uses,
764 numc);
765 if (web->type != PRECOLORED)
767 ra_debug_msg (DUMP_IGRAPH_M, "s %d", web->id);
768 while (1)
770 unsigned int u = 0;
771 int n;
772 for (n = 0; n < 32 && col < FIRST_PSEUDO_REGISTER; n++, col++)
773 if (TEST_HARD_REG_BIT (web->usable_regs, col))
774 u |= 1 << n;
775 ra_debug_msg (DUMP_IGRAPH_M, " %u", u);
776 if (col >= FIRST_PSEUDO_REGISTER)
777 break;
779 ra_debug_msg (DUMP_IGRAPH_M, "\n");
781 if (numc)
783 ra_debug_msg (DUMP_IGRAPH_M, "c %d", web->id);
784 for (cl = web->conflict_list; cl; cl = cl->next)
786 if (cl->t->id < web->id)
787 ra_debug_msg (DUMP_IGRAPH_M, " %d", cl->t->id);
789 ra_debug_msg (DUMP_IGRAPH_M, "\n");
792 ra_debug_msg (DUMP_IGRAPH_M, "e\n");
795 /* This runs after colorization and changing the insn stream.
796 It temporarily replaces all pseudo registers with their colors,
797 and emits information, if the resulting insns are strictly valid. */
799 void
800 dump_constraints (void)
802 rtx insn;
803 int i;
804 if (!dump_file || (debug_new_regalloc & DUMP_CONSTRAINTS) == 0)
805 return;
806 for (i = FIRST_PSEUDO_REGISTER; i < ra_max_regno; i++)
807 if (regno_reg_rtx[i] && REG_P (regno_reg_rtx[i]))
808 REGNO (regno_reg_rtx[i])
809 = ra_reg_renumber[i] >= 0 ? ra_reg_renumber[i] : i;
810 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
811 if (INSN_P (insn))
813 int code;
814 int uid = INSN_UID (insn);
815 int o;
816 /* Don't simply force rerecognition, as combine might left us
817 with some unrecognizable ones, which later leads to aborts
818 in regclass, if we now destroy the remembered INSN_CODE(). */
819 /*INSN_CODE (insn) = -1;*/
820 code = recog_memoized (insn);
821 if (code < 0)
823 ra_debug_msg (DUMP_CONSTRAINTS,
824 "%d: asm insn or not recognizable.\n", uid);
825 continue;
827 ra_debug_msg (DUMP_CONSTRAINTS,
828 "%d: code %d {%s}, %d operands, constraints: ",
829 uid, code, insn_data[code].name, recog_data.n_operands);
830 extract_insn (insn);
831 /*preprocess_constraints ();*/
832 for (o = 0; o < recog_data.n_operands; o++)
834 ra_debug_msg (DUMP_CONSTRAINTS,
835 "%d:%s ", o, recog_data.constraints[o]);
837 if (constrain_operands (1))
838 ra_debug_msg (DUMP_CONSTRAINTS, "matches strictly alternative %d",
839 which_alternative);
840 else
841 ra_debug_msg (DUMP_CONSTRAINTS, "doesn't match strictly");
842 ra_debug_msg (DUMP_CONSTRAINTS, "\n");
844 for (i = FIRST_PSEUDO_REGISTER; i < ra_max_regno; i++)
845 if (regno_reg_rtx[i] && REG_P (regno_reg_rtx[i]))
846 REGNO (regno_reg_rtx[i]) = i;
849 /* This counts and emits the cumulated cost of all spilled webs,
850 preceded by a custom message MSG, with debug level LEVEL. */
852 void
853 dump_graph_cost (unsigned int level, const char *msg)
855 unsigned int i;
856 unsigned HOST_WIDE_INT cost;
857 if (!dump_file || (debug_new_regalloc & level) == 0)
858 return;
860 cost = 0;
861 for (i = 0; i < num_webs; i++)
863 struct web *web = id2web[i];
864 if (alias (web)->type == SPILLED)
865 cost += web->orig_spill_cost;
867 ra_debug_msg (level, " spill cost of graph (%s) = "
868 HOST_WIDE_INT_PRINT_UNSIGNED "\n",
869 msg ? msg : "", cost);
872 /* Dump the color assignment per web, the coalesced and spilled webs. */
874 void
875 dump_ra (struct df *df ATTRIBUTE_UNUSED)
877 struct web *web;
878 struct dlist *d;
879 if (!dump_file || (debug_new_regalloc & DUMP_RESULTS) == 0)
880 return;
882 ra_debug_msg (DUMP_RESULTS, "\nColored:\n");
883 for (d = WEBS(COLORED); d; d = d->next)
885 web = DLIST_WEB (d);
886 ra_debug_msg (DUMP_RESULTS, " %4d : color %d\n", web->id, web->color);
888 ra_debug_msg (DUMP_RESULTS, "\nCoalesced:\n");
889 for (d = WEBS(COALESCED); d; d = d->next)
891 web = DLIST_WEB (d);
892 ra_debug_msg (DUMP_RESULTS, " %4d : to web %d, color %d\n", web->id,
893 alias (web)->id, web->color);
895 ra_debug_msg (DUMP_RESULTS, "\nSpilled:\n");
896 for (d = WEBS(SPILLED); d; d = d->next)
898 web = DLIST_WEB (d);
899 ra_debug_msg (DUMP_RESULTS, " %4d\n", web->id);
901 ra_debug_msg (DUMP_RESULTS, "\n");
902 dump_cost (DUMP_RESULTS);
905 /* Calculate and dump the cumulated costs of certain types of insns
906 (loads, stores and copies). */
908 void
909 dump_static_insn_cost (FILE *file, const char *message, const char *prefix)
911 struct cost
913 unsigned HOST_WIDE_INT cost;
914 unsigned int count;
916 basic_block bb;
917 struct cost load, store, regcopy, selfcopy, overall;
918 memset (&load, 0, sizeof(load));
919 memset (&store, 0, sizeof(store));
920 memset (&regcopy, 0, sizeof(regcopy));
921 memset (&selfcopy, 0, sizeof(selfcopy));
922 memset (&overall, 0, sizeof(overall));
924 if (!file)
925 return;
927 FOR_EACH_BB (bb)
929 unsigned HOST_WIDE_INT block_cost = bb->frequency;
930 rtx insn, set;
931 for (insn = BB_HEAD (bb); insn; insn = NEXT_INSN (insn))
933 /* Yes, yes. We don't calculate the costs precisely.
934 Only for "simple enough" insns. Those containing single
935 sets only. */
936 if (INSN_P (insn) && ((set = single_set (insn)) != NULL))
938 rtx src = SET_SRC (set);
939 rtx dest = SET_DEST (set);
940 struct cost *pcost = NULL;
941 overall.cost += block_cost;
942 overall.count++;
943 if (rtx_equal_p (src, dest))
944 pcost = &selfcopy;
945 else if (GET_CODE (src) == GET_CODE (dest)
946 && ((REG_P (src))
947 || (GET_CODE (src) == SUBREG
948 && REG_P (SUBREG_REG (src))
949 && REG_P (SUBREG_REG (dest)))))
950 /* XXX is dest guaranteed to be a subreg? */
951 pcost = &regcopy;
952 else
954 if (GET_CODE (src) == SUBREG)
955 src = SUBREG_REG (src);
956 if (GET_CODE (dest) == SUBREG)
957 dest = SUBREG_REG (dest);
958 if (MEM_P (src) && !MEM_P (dest)
959 && memref_is_stack_slot (src))
960 pcost = &load;
961 else if (!MEM_P (src) && MEM_P (dest)
962 && memref_is_stack_slot (dest))
963 pcost = &store;
965 if (pcost)
967 pcost->cost += block_cost;
968 pcost->count++;
971 if (insn == BB_END (bb))
972 break;
976 if (!prefix)
977 prefix = "";
978 fprintf (file, "static insn cost %s\n", message ? message : "");
979 fprintf (file, " %soverall:\tnum=%6d\tcost=% 8" HOST_WIDE_INT_PRINT "d\n",
980 prefix, overall.count, overall.cost);
981 fprintf (file, " %sloads:\tnum=%6d\tcost=% 8" HOST_WIDE_INT_PRINT "d\n",
982 prefix, load.count, load.cost);
983 fprintf (file, " %sstores:\tnum=%6d\tcost=% 8" HOST_WIDE_INT_PRINT "d\n",
984 prefix, store.count, store.cost);
985 fprintf (file, " %sregcopy:\tnum=%6d\tcost=% 8" HOST_WIDE_INT_PRINT "d\n",
986 prefix, regcopy.count, regcopy.cost);
987 fprintf (file, " %sselfcpy:\tnum=%6d\tcost=% 8" HOST_WIDE_INT_PRINT "d\n",
988 prefix, selfcopy.count, selfcopy.cost);
991 /* Returns nonzero, if WEB1 and WEB2 have some possible
992 hardregs in common. */
995 web_conflicts_p (struct web *web1, struct web *web2)
997 if (web1->type == PRECOLORED && web2->type == PRECOLORED)
998 return 0;
1000 if (web1->type == PRECOLORED)
1001 return TEST_HARD_REG_BIT (web2->usable_regs, web1->regno);
1003 if (web2->type == PRECOLORED)
1004 return TEST_HARD_REG_BIT (web1->usable_regs, web2->regno);
1006 return hard_regs_intersect_p (&web1->usable_regs, &web2->usable_regs);
1009 /* Dump all uids of insns in which WEB is mentioned. */
1011 void
1012 dump_web_insns (struct web *web)
1014 unsigned int i;
1016 ra_debug_msg (DUMP_EVER, "Web: %i(%i)+%i class: %s freedom: %i degree %i\n",
1017 web->id, web->regno, web->add_hardregs,
1018 reg_class_names[web->regclass],
1019 web->num_freedom, web->num_conflicts);
1020 ra_debug_msg (DUMP_EVER, " def insns:");
1022 for (i = 0; i < web->num_defs; ++i)
1024 ra_debug_msg (DUMP_EVER, " %d ", INSN_UID (web->defs[i]->insn));
1027 ra_debug_msg (DUMP_EVER, "\n use insns:");
1028 for (i = 0; i < web->num_uses; ++i)
1030 ra_debug_msg (DUMP_EVER, " %d ", INSN_UID (web->uses[i]->insn));
1032 ra_debug_msg (DUMP_EVER, "\n");
1035 /* Dump conflicts for web WEB. */
1037 void
1038 dump_web_conflicts (struct web *web)
1040 int num = 0;
1041 unsigned int def2;
1043 ra_debug_msg (DUMP_EVER, "Web: %i(%i)+%i class: %s freedom: %i degree %i\n",
1044 web->id, web->regno, web->add_hardregs,
1045 reg_class_names[web->regclass],
1046 web->num_freedom, web->num_conflicts);
1048 for (def2 = 0; def2 < num_webs; def2++)
1049 if (TEST_BIT (igraph, igraph_index (web->id, def2)) && web->id != def2)
1051 if ((num % 9) == 5)
1052 ra_debug_msg (DUMP_EVER, "\n ");
1053 num++;
1055 ra_debug_msg (DUMP_EVER, " %d(%d)", def2, id2web[def2]->regno);
1056 if (id2web[def2]->add_hardregs)
1057 ra_debug_msg (DUMP_EVER, "+%d", id2web[def2]->add_hardregs);
1059 if (web_conflicts_p (web, id2web[def2]))
1060 ra_debug_msg (DUMP_EVER, "/x");
1062 if (id2web[def2]->type == SELECT)
1063 ra_debug_msg (DUMP_EVER, "/s");
1065 if (id2web[def2]->type == COALESCED)
1066 ra_debug_msg (DUMP_EVER,"/c/%d", alias (id2web[def2])->id);
1068 ra_debug_msg (DUMP_EVER, "\n");
1070 struct conflict_link *wl;
1071 num = 0;
1072 ra_debug_msg (DUMP_EVER, "By conflicts: ");
1073 for (wl = web->conflict_list; wl; wl = wl->next)
1075 struct web* w = wl->t;
1076 if ((num % 9) == 8)
1077 ra_debug_msg (DUMP_EVER, "\n ");
1078 num++;
1079 ra_debug_msg (DUMP_EVER, "%d(%d)%s ", w->id, w->regno,
1080 web_conflicts_p (web, w) ? "+" : "");
1082 ra_debug_msg (DUMP_EVER, "\n");
1086 /* Output HARD_REG_SET to stderr. */
1088 void
1089 debug_hard_reg_set (HARD_REG_SET set)
1091 int i;
1092 for (i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
1094 if (TEST_HARD_REG_BIT (set, i))
1096 fprintf (stderr, "%s ", reg_names[i]);
1099 fprintf (stderr, "\n");
1103 vim:cinoptions={.5s,g0,p5,t0,(0,^-0.5s,n-0.5s:tw=78:cindent:sw=4: