PR target/19236
[official-gcc.git] / gcc / ra-debug.c
blob84315343f195890d8bdb6ea500eb41f8033ff1fd
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 "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 /* 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 && dump_file != NULL)
57 vfprintf (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 LTGT: opname = "<>"; break;
136 /* class '<' */
137 case GE: opname = "s>="; break;
138 case GT: opname = "s>"; break;
139 case LE: opname = "s<="; break;
140 case LT: opname = "s<"; break;
141 case GEU: opname = "u>="; break;
142 case GTU: opname = "u>"; break;
143 case LEU: opname = "u<="; break;
144 case LTU: opname = "u<"; break;
145 default:
146 infix = 0;
147 opname = GET_RTX_NAME (code);
148 break;
150 if (infix)
152 fputs ("(", file);
153 ra_print_rtx (file, op0, 0);
154 fprintf (file, " %s ", opname);
155 ra_print_rtx (file, op1, 0);
156 fputs (")", file);
158 else
160 fprintf (file, "%s(", opname);
161 ra_print_rtx (file, op0, 0);
162 fputs (", ", file);
163 ra_print_rtx (file, op1, 0);
164 fputs (")", file);
168 /* Print rtx X, which a three operand rtx to FILE.
169 I.e. X is either an IF_THEN_ELSE, or a bitmap operation. */
171 static void
172 ra_print_rtx_3op (FILE *file, rtx x)
174 enum rtx_code code = GET_CODE (x);
175 rtx op0 = XEXP (x, 0);
176 rtx op1 = XEXP (x, 1);
177 rtx op2 = XEXP (x, 2);
178 if (code == IF_THEN_ELSE)
180 ra_print_rtx (file, op0, 0);
181 fputs (" ? ", file);
182 ra_print_rtx (file, op1, 0);
183 fputs (" : ", file);
184 ra_print_rtx (file, op2, 0);
186 else
188 /* Bitmap-operation */
189 fprintf (file, "%s:%s(", GET_RTX_NAME (code),
190 GET_MODE_NAME (GET_MODE (x)));
191 ra_print_rtx (file, op0, 0);
192 fputs (", ", file);
193 ra_print_rtx (file, op1, 0);
194 fputs (", ", file);
195 ra_print_rtx (file, op2, 0);
196 fputs (")", file);
200 /* Print rtx X, which represents an object (class 'o', 'C', or some constructs
201 of class 'x' (e.g. subreg)), to FILE.
202 (reg XX) rtl is represented as "pXX", of XX was a pseudo,
203 as "name" it name is the nonnull hardreg name, or as "hXX", if XX
204 is a hardreg, whose name is NULL, or empty. */
206 static void
207 ra_print_rtx_object (FILE *file, rtx x)
209 enum rtx_code code = GET_CODE (x);
210 enum machine_mode mode = GET_MODE (x);
211 switch (code)
213 case CONST_INT:
214 fprintf (file, HOST_WIDE_INT_PRINT_DEC, XWINT (x, 0));
215 break;
216 case CONST_DOUBLE:
218 int i, num = 0;
219 const char *fmt = GET_RTX_FORMAT (code);
220 fputs ("dbl(", file);
221 for (i = 0; i < GET_RTX_LENGTH (code); i++)
223 if (num)
224 fputs (", ", file);
225 if (fmt[i] == 'e' && XEXP (x, i))
226 /* The MEM or other stuff */
228 ra_print_rtx (file, XEXP (x, i), 0);
229 num++;
231 else if (fmt[i] == 'w')
233 fprintf (file, HOST_WIDE_INT_PRINT_HEX, XWINT (x, i));
234 num++;
237 break;
239 case CONST_STRING: fprintf (file, "\"%s\"", XSTR (x, 0)); break;
240 case CONST: fputs ("const(", file);
241 ra_print_rtx (file, XEXP (x, 0), 0);
242 fputs (")", file);
243 break;
244 case PC: fputs ("pc", file); break;
245 case REG:
247 int regno = REGNO (x);
248 if (regno < FIRST_PSEUDO_REGISTER)
250 int i, nregs = hard_regno_nregs[regno][mode];
251 if (nregs > 1)
252 fputs ("[", file);
253 for (i = 0; i < nregs; i++)
255 if (i)
256 fputs (", ", file);
257 if (reg_names[regno+i] && *reg_names[regno + i])
258 fprintf (file, "%s", reg_names[regno + i]);
259 else
260 fprintf (file, "h%d", regno + i);
262 if (nregs > 1)
263 fputs ("]", file);
265 else
266 fprintf (file, "p%d", regno);
267 break;
269 case SUBREG:
271 rtx sub = SUBREG_REG (x);
272 int ofs = SUBREG_BYTE (x);
273 if (REG_P (sub)
274 && REGNO (sub) < FIRST_PSEUDO_REGISTER)
276 int regno = REGNO (sub);
277 int i, nregs = hard_regno_nregs[regno][mode];
278 regno += subreg_regno_offset (regno, GET_MODE (sub),
279 ofs, mode);
280 if (nregs > 1)
281 fputs ("[", file);
282 for (i = 0; i < nregs; i++)
284 if (i)
285 fputs (", ", file);
286 if (reg_names[regno+i])
287 fprintf (file, "%s", reg_names[regno + i]);
288 else
289 fprintf (file, "h%d", regno + i);
291 if (nregs > 1)
292 fputs ("]", file);
294 else
296 ra_print_rtx (file, sub, 0);
297 fprintf (file, ":[%s+%d]", GET_MODE_NAME (mode), ofs);
299 break;
301 case SCRATCH: fputs ("scratch", file); break;
302 case CONCAT: ra_print_rtx_2op (file, x); break;
303 case HIGH: ra_print_rtx_1op (file, x); break;
304 case LO_SUM:
305 fputs ("(", file);
306 ra_print_rtx (file, XEXP (x, 0), 0);
307 fputs (" + lo(", file);
308 ra_print_rtx (file, XEXP (x, 1), 0);
309 fputs ("))", file);
310 break;
311 case MEM: fputs ("[", file);
312 ra_print_rtx (file, XEXP (x, 0), 0);
313 fprintf (file, "]:%s", GET_MODE_NAME (GET_MODE (x)));
314 /* XXX print alias set too ?? */
315 break;
316 case LABEL_REF:
318 rtx sub = XEXP (x, 0);
319 if (NOTE_P (sub)
320 && NOTE_LINE_NUMBER (sub) == NOTE_INSN_DELETED_LABEL)
321 fprintf (file, "(deleted uid=%d)", INSN_UID (sub));
322 else if (LABEL_P (sub))
323 fprintf (file, "L%d", CODE_LABEL_NUMBER (sub));
324 else
325 fprintf (file, "(nonlabel uid=%d)", INSN_UID (sub));
327 break;
328 case SYMBOL_REF:
329 fprintf (file, "sym(\"%s\")", XSTR (x, 0)); break;
330 case CC0: fputs ("cc0", file); break;
331 default: print_inline_rtx (file, x, 0); break;
335 /* Print a general rtx X to FILE in nice infix form.
336 If WITH_PN is set, and X is one of the toplevel constructs
337 (insns, notes, labels or barriers), then print also the UIDs of
338 the preceding and following insn. */
340 void
341 ra_print_rtx (FILE *file, rtx x, int with_pn)
343 enum rtx_code code;
344 int unhandled = 0;
345 if (!x)
346 return;
347 code = GET_CODE (x);
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 expanded_location s;
392 NOTE_EXPANDED_LOCATION (s, x);
393 fprintf (file, " line %d", s.line);
394 if (s.file != NULL)
395 fprintf (file, ":%s", s.file);
398 else
400 fprintf (file, "\t");
401 ra_print_rtx (file, PATTERN (x), 0);
403 return;
405 switch (code)
407 /* Top-level stuff. */
408 case PARALLEL:
410 int j;
411 for (j = 0; j < XVECLEN (x, 0); j++)
413 if (j)
414 fputs ("\t;; ", file);
415 ra_print_rtx (file, XVECEXP (x, 0, j), 0);
417 break;
419 case UNSPEC: case UNSPEC_VOLATILE:
421 int j;
422 fprintf (file, "unspec%s(%d",
423 (code == UNSPEC) ? "" : "_vol", XINT (x, 1));
424 for (j = 0; j < XVECLEN (x, 0); j++)
426 fputs (", ", file);
427 ra_print_rtx (file, XVECEXP (x, 0, j), 0);
429 fputs (")", file);
430 break;
432 case SET:
433 if (GET_CODE (SET_DEST (x)) == PC)
435 if (GET_CODE (SET_SRC (x)) == IF_THEN_ELSE
436 && GET_CODE (XEXP (SET_SRC(x), 2)) == PC)
438 fputs ("if ", file);
439 ra_print_rtx (file, XEXP (SET_SRC (x), 0), 0);
440 fputs (" jump ", file);
441 ra_print_rtx (file, XEXP (SET_SRC (x), 1), 0);
443 else
445 fputs ("jump ", file);
446 ra_print_rtx (file, SET_SRC (x), 0);
449 else
451 ra_print_rtx (file, SET_DEST (x), 0);
452 fputs (" <= ", file);
453 ra_print_rtx (file, SET_SRC (x), 0);
455 break;
456 case USE:
457 fputs ("use <= ", file);
458 ra_print_rtx (file, XEXP (x, 0), 0);
459 break;
460 case CLOBBER:
461 ra_print_rtx (file, XEXP (x, 0), 0);
462 fputs (" <= clobber", file);
463 break;
464 case CALL:
465 fputs ("call ", file);
466 ra_print_rtx (file, XEXP (x, 0), 0); /* Address */
467 fputs (" numargs=", file);
468 ra_print_rtx (file, XEXP (x, 1), 0); /* Num arguments */
469 break;
470 case RETURN:
471 fputs ("return", file);
472 break;
473 case TRAP_IF:
474 fputs ("if (", file);
475 ra_print_rtx (file, XEXP (x, 0), 0);
476 fputs (") trap ", file);
477 ra_print_rtx (file, XEXP (x, 1), 0);
478 break;
479 case RESX:
480 fprintf (file, "resx from region %d", XINT (x, 0));
481 break;
483 /* Different things of class 'x' */
484 case SUBREG: ra_print_rtx_object (file, x); break;
485 case STRICT_LOW_PART:
486 fputs ("low(", file);
487 ra_print_rtx (file, XEXP (x, 0), 0);
488 fputs (")", file);
489 break;
490 default:
491 unhandled = 1;
492 break;
494 if (!unhandled)
495 return;
496 switch (GET_RTX_CLASS (code))
498 case RTX_UNARY:
499 ra_print_rtx_1op (file, x);
500 break;
501 case RTX_BIN_ARITH:
502 case RTX_COMM_ARITH:
503 case RTX_COMPARE:
504 case RTX_COMM_COMPARE:
505 ra_print_rtx_2op (file, x);
506 break;
507 case RTX_TERNARY:
508 case RTX_BITFIELD_OPS:
509 ra_print_rtx_3op (file, x);
510 break;
511 case RTX_OBJ:
512 case RTX_CONST_OBJ:
513 ra_print_rtx_object (file, x);
514 break;
515 default:
516 print_inline_rtx (file, x, 0);
517 break;
521 /* This only calls ra_print_rtx(), but emits a final newline. */
523 void
524 ra_print_rtx_top (FILE *file, rtx x, int with_pn)
526 ra_print_rtx (file, x, with_pn);
527 fprintf (file, "\n");
530 /* Callable from gdb. This prints rtx X onto stderr. */
532 void
533 ra_debug_rtx (rtx x)
535 ra_print_rtx_top (stderr, x, 1);
538 /* This prints the content of basic block with index BBI.
539 The first and last insn are emitted with UIDs of prev and next insns. */
541 void
542 ra_debug_bbi (int bbi)
544 basic_block bb = BASIC_BLOCK (bbi);
545 rtx insn;
546 for (insn = BB_HEAD (bb); insn; insn = NEXT_INSN (insn))
548 ra_print_rtx_top (stderr, insn,
549 (insn == BB_HEAD (bb) || insn == BB_END (bb)));
550 fprintf (stderr, "\n");
551 if (insn == BB_END (bb))
552 break;
556 /* Beginning from INSN, emit NUM insns (if NUM is non-negative)
557 or emit a window of NUM insns around INSN, to stderr. */
559 void
560 ra_debug_insns (rtx insn, int num)
562 int i, count = (num == 0 ? 1 : num < 0 ? -num : num);
563 if (num < 0)
564 for (i = count / 2; i > 0 && PREV_INSN (insn); i--)
565 insn = PREV_INSN (insn);
566 for (i = count; i > 0 && insn; insn = NEXT_INSN (insn), i--)
568 if (LABEL_P (insn))
569 fprintf (stderr, "\n");
570 ra_print_rtx_top (stderr, insn, (i == count || i == 1));
574 /* Beginning with INSN, emit the whole insn chain into FILE.
575 This also outputs comments when basic blocks start or end and omits
576 some notes, if flag_ra_dump_notes is zero. */
578 void
579 ra_print_rtl_with_bb (FILE *file, rtx insn)
581 basic_block last_bb, bb;
582 unsigned int num = 0;
583 if (!insn)
584 fputs ("nil", file);
585 last_bb = NULL;
586 for (; insn; insn = NEXT_INSN (insn))
588 if (BARRIER_P (insn))
589 bb = NULL;
590 else
591 bb = BLOCK_FOR_INSN (insn);
592 if (bb != last_bb)
594 if (last_bb)
595 fprintf (file, ";; End of basic block %d\n", last_bb->index);
596 if (bb)
597 fprintf (file, ";; Begin of basic block %d\n", bb->index);
598 last_bb = bb;
600 if (LABEL_P (insn))
601 fputc ('\n', file);
602 if (NOTE_P (insn))
604 /* Ignore basic block and maybe other notes not referencing
605 deleted things. */
606 if (NOTE_LINE_NUMBER (insn) != NOTE_INSN_BASIC_BLOCK
607 && (flag_ra_dump_notes
608 || NOTE_LINE_NUMBER (insn) == NOTE_INSN_DELETED
609 || NOTE_LINE_NUMBER (insn) == NOTE_INSN_DELETED_LABEL))
611 ra_print_rtx_top (file, insn, (num == 0 || !NEXT_INSN (insn)));
612 num++;
615 else
617 ra_print_rtx_top (file, insn, (num == 0 || !NEXT_INSN (insn)));
618 num++;
623 /* Count how many insns were seen how often, while building the interference
624 graph, and prints the findings. */
626 void
627 dump_number_seen (void)
629 #define N 17
630 int num[N];
631 int i;
633 for (i = 0; i < N; i++)
634 num[i] = 0;
635 for (i = 0; i < get_max_uid (); i++)
636 if (number_seen[i] < N - 1)
637 num[number_seen[i]]++;
638 else
639 num[N - 1]++;
640 for (i = 0; i < N - 1; i++)
641 if (num[i])
642 ra_debug_msg (DUMP_PROCESS, "%d insns seen %d times\n", num[i], i);
643 if (num[N - 1])
644 ra_debug_msg (DUMP_PROCESS, "%d insns seen %d and more times\n", num[i],
645 N - 1);
646 ra_debug_msg (DUMP_PROCESS, "from overall %d insns\n", get_max_uid ());
647 #undef N
650 /* Dump the interference graph, the move list and the webs. */
652 void
653 dump_igraph (struct df *df ATTRIBUTE_UNUSED)
655 struct move_list *ml;
656 unsigned int def1, def2;
657 int num = 0;
658 int num2;
659 unsigned int i;
660 if (!dump_file || (debug_new_regalloc & (DUMP_IGRAPH | DUMP_WEBS)) == 0)
661 return;
662 ra_debug_msg (DUMP_IGRAPH, "conflicts:\n ");
663 for (def1 = 0; def1 < num_webs; def1++)
665 int num1 = num;
666 num2 = 0;
667 for (def2 = 0; def2 < num_webs; def2++)
668 if (def1 != def2 && TEST_BIT (igraph, igraph_index (def1, def2)))
670 if (num1 == num)
672 if (SUBWEB_P (ID2WEB (def1)))
673 ra_debug_msg (DUMP_IGRAPH, "%d (SUBREG %d, %d) with ", def1,
674 ID2WEB (def1)->regno,
675 SUBREG_BYTE (ID2WEB (def1)->orig_x));
676 else
677 ra_debug_msg (DUMP_IGRAPH, "%d (REG %d) with ", def1,
678 ID2WEB (def1)->regno);
680 if ((num2 % 9) == 8)
681 ra_debug_msg (DUMP_IGRAPH, "\n ");
682 num++;
683 num2++;
684 if (SUBWEB_P (ID2WEB (def2)))
685 ra_debug_msg (DUMP_IGRAPH, "%d(%d,%d) ", def2, ID2WEB (def2)->regno,
686 SUBREG_BYTE (ID2WEB (def2)->orig_x));
687 else
688 ra_debug_msg (DUMP_IGRAPH, "%d(%d) ", def2, ID2WEB (def2)->regno);
690 if (num1 != num)
691 ra_debug_msg (DUMP_IGRAPH, "\n ");
693 ra_debug_msg (DUMP_IGRAPH, "\n");
694 for (ml = wl_moves; ml; ml = ml->next)
695 if (ml->move)
697 ra_debug_msg (DUMP_IGRAPH, "move: insn %d: Web %d <-- Web %d\n",
698 INSN_UID (ml->move->insn), ml->move->target_web->id,
699 ml->move->source_web->id);
701 ra_debug_msg (DUMP_WEBS, "\nWebs:\n");
702 for (i = 0; i < num_webs; i++)
704 struct web *web = ID2WEB (i);
706 ra_debug_msg (DUMP_WEBS, " %4d : regno %3d", i, web->regno);
707 if (SUBWEB_P (web))
709 ra_debug_msg (DUMP_WEBS, " sub %d", SUBREG_BYTE (web->orig_x));
710 ra_debug_msg (DUMP_WEBS, " par %d", find_web_for_subweb (web)->id);
712 ra_debug_msg (DUMP_WEBS, " +%d (span %d, cost "
713 HOST_WIDE_INT_PRINT_DEC ") (%s)",
714 web->add_hardregs, web->span_deaths, web->spill_cost,
715 reg_class_names[web->regclass]);
716 if (web->spill_temp == 1)
717 ra_debug_msg (DUMP_WEBS, " (spilltemp)");
718 else if (web->spill_temp == 2)
719 ra_debug_msg (DUMP_WEBS, " (spilltem2)");
720 else if (web->spill_temp == 3)
721 ra_debug_msg (DUMP_WEBS, " (short)");
722 if (web->type == PRECOLORED)
723 ra_debug_msg (DUMP_WEBS, " (precolored, color=%d)", web->color);
724 else if (find_web_for_subweb (web)->num_uses == 0)
725 ra_debug_msg (DUMP_WEBS, " dead");
726 if (web->crosses_call)
727 ra_debug_msg (DUMP_WEBS, " xcall");
728 if (web->regno >= max_normal_pseudo)
729 ra_debug_msg (DUMP_WEBS, " stack");
730 ra_debug_msg (DUMP_WEBS, "\n");
734 /* Dump the interference graph and webs in a format easily
735 parsable by programs. Used to emit real world interference graph
736 to my custom graph colorizer. */
738 void
739 dump_igraph_machine (void)
741 unsigned int i;
743 if (!dump_file || (debug_new_regalloc & DUMP_IGRAPH_M) == 0)
744 return;
745 ra_debug_msg (DUMP_IGRAPH_M, "g %d %d\n", num_webs - num_subwebs,
746 FIRST_PSEUDO_REGISTER);
747 for (i = 0; i < num_webs - num_subwebs; i++)
749 struct web *web = ID2WEB (i);
750 struct conflict_link *cl;
751 int flags = 0;
752 int numc = 0;
753 int col = 0;
754 flags = web->spill_temp & 0xF;
755 flags |= ((web->type == PRECOLORED) ? 1 : 0) << 4;
756 flags |= (web->add_hardregs & 0xF) << 5;
757 for (cl = web->conflict_list; cl; cl = cl->next)
758 if (cl->t->id < web->id)
759 numc++;
760 ra_debug_msg (DUMP_IGRAPH_M, "n %d %d %d %d %d %d %d\n",
761 web->id, web->color, flags,
762 (unsigned int)web->spill_cost, web->num_defs, web->num_uses,
763 numc);
764 if (web->type != PRECOLORED)
766 ra_debug_msg (DUMP_IGRAPH_M, "s %d", web->id);
767 while (1)
769 unsigned int u = 0;
770 int n;
771 for (n = 0; n < 32 && col < FIRST_PSEUDO_REGISTER; n++, col++)
772 if (TEST_HARD_REG_BIT (web->usable_regs, col))
773 u |= 1 << n;
774 ra_debug_msg (DUMP_IGRAPH_M, " %u", u);
775 if (col >= FIRST_PSEUDO_REGISTER)
776 break;
778 ra_debug_msg (DUMP_IGRAPH_M, "\n");
780 if (numc)
782 ra_debug_msg (DUMP_IGRAPH_M, "c %d", web->id);
783 for (cl = web->conflict_list; cl; cl = cl->next)
785 if (cl->t->id < web->id)
786 ra_debug_msg (DUMP_IGRAPH_M, " %d", cl->t->id);
788 ra_debug_msg (DUMP_IGRAPH_M, "\n");
791 ra_debug_msg (DUMP_IGRAPH_M, "e\n");
794 /* This runs after colorization and changing the insn stream.
795 It temporarily replaces all pseudo registers with their colors,
796 and emits information, if the resulting insns are strictly valid. */
798 void
799 dump_constraints (void)
801 rtx insn;
802 int i;
803 if (!dump_file || (debug_new_regalloc & DUMP_CONSTRAINTS) == 0)
804 return;
805 for (i = FIRST_PSEUDO_REGISTER; i < ra_max_regno; i++)
806 if (regno_reg_rtx[i] && REG_P (regno_reg_rtx[i]))
807 REGNO (regno_reg_rtx[i])
808 = ra_reg_renumber[i] >= 0 ? ra_reg_renumber[i] : i;
809 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
810 if (INSN_P (insn))
812 int code;
813 int uid = INSN_UID (insn);
814 int o;
815 /* Don't simply force rerecognition, as combine might left us
816 with some unrecognizable ones, which later leads to aborts
817 in regclass, if we now destroy the remembered INSN_CODE(). */
818 /*INSN_CODE (insn) = -1;*/
819 code = recog_memoized (insn);
820 if (code < 0)
822 ra_debug_msg (DUMP_CONSTRAINTS,
823 "%d: asm insn or not recognizable.\n", uid);
824 continue;
826 ra_debug_msg (DUMP_CONSTRAINTS,
827 "%d: code %d {%s}, %d operands, constraints: ",
828 uid, code, insn_data[code].name, recog_data.n_operands);
829 extract_insn (insn);
830 /*preprocess_constraints ();*/
831 for (o = 0; o < recog_data.n_operands; o++)
833 ra_debug_msg (DUMP_CONSTRAINTS,
834 "%d:%s ", o, recog_data.constraints[o]);
836 if (constrain_operands (1))
837 ra_debug_msg (DUMP_CONSTRAINTS, "matches strictly alternative %d",
838 which_alternative);
839 else
840 ra_debug_msg (DUMP_CONSTRAINTS, "doesn't match strictly");
841 ra_debug_msg (DUMP_CONSTRAINTS, "\n");
843 for (i = FIRST_PSEUDO_REGISTER; i < ra_max_regno; i++)
844 if (regno_reg_rtx[i] && REG_P (regno_reg_rtx[i]))
845 REGNO (regno_reg_rtx[i]) = i;
848 /* This counts and emits the cumulated cost of all spilled webs,
849 preceded by a custom message MSG, with debug level LEVEL. */
851 void
852 dump_graph_cost (unsigned int level, const char *msg)
854 unsigned int i;
855 unsigned HOST_WIDE_INT cost;
856 if (!dump_file || (debug_new_regalloc & level) == 0)
857 return;
859 cost = 0;
860 for (i = 0; i < num_webs; i++)
862 struct web *web = id2web[i];
863 if (alias (web)->type == SPILLED)
864 cost += web->orig_spill_cost;
866 ra_debug_msg (level, " spill cost of graph (%s) = "
867 HOST_WIDE_INT_PRINT_UNSIGNED "\n",
868 msg ? msg : "", cost);
871 /* Dump the color assignment per web, the coalesced and spilled webs. */
873 void
874 dump_ra (struct df *df ATTRIBUTE_UNUSED)
876 struct web *web;
877 struct dlist *d;
878 if (!dump_file || (debug_new_regalloc & DUMP_RESULTS) == 0)
879 return;
881 ra_debug_msg (DUMP_RESULTS, "\nColored:\n");
882 for (d = WEBS(COLORED); d; d = d->next)
884 web = DLIST_WEB (d);
885 ra_debug_msg (DUMP_RESULTS, " %4d : color %d\n", web->id, web->color);
887 ra_debug_msg (DUMP_RESULTS, "\nCoalesced:\n");
888 for (d = WEBS(COALESCED); d; d = d->next)
890 web = DLIST_WEB (d);
891 ra_debug_msg (DUMP_RESULTS, " %4d : to web %d, color %d\n", web->id,
892 alias (web)->id, web->color);
894 ra_debug_msg (DUMP_RESULTS, "\nSpilled:\n");
895 for (d = WEBS(SPILLED); d; d = d->next)
897 web = DLIST_WEB (d);
898 ra_debug_msg (DUMP_RESULTS, " %4d\n", web->id);
900 ra_debug_msg (DUMP_RESULTS, "\n");
901 dump_cost (DUMP_RESULTS);
904 /* Calculate and dump the cumulated costs of certain types of insns
905 (loads, stores and copies). */
907 void
908 dump_static_insn_cost (FILE *file, const char *message, const char *prefix)
910 struct cost
912 unsigned HOST_WIDE_INT cost;
913 unsigned int count;
915 basic_block bb;
916 struct cost load, store, regcopy, selfcopy, overall;
917 memset (&load, 0, sizeof(load));
918 memset (&store, 0, sizeof(store));
919 memset (&regcopy, 0, sizeof(regcopy));
920 memset (&selfcopy, 0, sizeof(selfcopy));
921 memset (&overall, 0, sizeof(overall));
923 if (!file)
924 return;
926 FOR_EACH_BB (bb)
928 unsigned HOST_WIDE_INT block_cost = bb->frequency;
929 rtx insn, set;
930 for (insn = BB_HEAD (bb); insn; insn = NEXT_INSN (insn))
932 /* Yes, yes. We don't calculate the costs precisely.
933 Only for "simple enough" insns. Those containing single
934 sets only. */
935 if (INSN_P (insn) && ((set = single_set (insn)) != NULL))
937 rtx src = SET_SRC (set);
938 rtx dest = SET_DEST (set);
939 struct cost *pcost = NULL;
940 overall.cost += block_cost;
941 overall.count++;
942 if (rtx_equal_p (src, dest))
943 pcost = &selfcopy;
944 else if (GET_CODE (src) == GET_CODE (dest)
945 && ((REG_P (src))
946 || (GET_CODE (src) == SUBREG
947 && REG_P (SUBREG_REG (src))
948 && REG_P (SUBREG_REG (dest)))))
949 /* XXX is dest guaranteed to be a subreg? */
950 pcost = &regcopy;
951 else
953 if (GET_CODE (src) == SUBREG)
954 src = SUBREG_REG (src);
955 if (GET_CODE (dest) == SUBREG)
956 dest = SUBREG_REG (dest);
957 if (MEM_P (src) && !MEM_P (dest)
958 && memref_is_stack_slot (src))
959 pcost = &load;
960 else if (!MEM_P (src) && MEM_P (dest)
961 && memref_is_stack_slot (dest))
962 pcost = &store;
964 if (pcost)
966 pcost->cost += block_cost;
967 pcost->count++;
970 if (insn == BB_END (bb))
971 break;
975 if (!prefix)
976 prefix = "";
977 fprintf (file, "static insn cost %s\n", message ? message : "");
978 fprintf (file, " %soverall:\tnum=%6d\tcost=% 8" HOST_WIDE_INT_PRINT "d\n",
979 prefix, overall.count, overall.cost);
980 fprintf (file, " %sloads:\tnum=%6d\tcost=% 8" HOST_WIDE_INT_PRINT "d\n",
981 prefix, load.count, load.cost);
982 fprintf (file, " %sstores:\tnum=%6d\tcost=% 8" HOST_WIDE_INT_PRINT "d\n",
983 prefix, store.count, store.cost);
984 fprintf (file, " %sregcopy:\tnum=%6d\tcost=% 8" HOST_WIDE_INT_PRINT "d\n",
985 prefix, regcopy.count, regcopy.cost);
986 fprintf (file, " %sselfcpy:\tnum=%6d\tcost=% 8" HOST_WIDE_INT_PRINT "d\n",
987 prefix, selfcopy.count, selfcopy.cost);
990 /* Returns nonzero, if WEB1 and WEB2 have some possible
991 hardregs in common. */
994 web_conflicts_p (struct web *web1, struct web *web2)
996 if (web1->type == PRECOLORED && web2->type == PRECOLORED)
997 return 0;
999 if (web1->type == PRECOLORED)
1000 return TEST_HARD_REG_BIT (web2->usable_regs, web1->regno);
1002 if (web2->type == PRECOLORED)
1003 return TEST_HARD_REG_BIT (web1->usable_regs, web2->regno);
1005 return hard_regs_intersect_p (&web1->usable_regs, &web2->usable_regs);
1008 /* Dump all uids of insns in which WEB is mentioned. */
1010 void
1011 dump_web_insns (struct web *web)
1013 unsigned int i;
1015 ra_debug_msg (DUMP_EVER, "Web: %i(%i)+%i class: %s freedom: %i degree %i\n",
1016 web->id, web->regno, web->add_hardregs,
1017 reg_class_names[web->regclass],
1018 web->num_freedom, web->num_conflicts);
1019 ra_debug_msg (DUMP_EVER, " def insns:");
1021 for (i = 0; i < web->num_defs; ++i)
1023 ra_debug_msg (DUMP_EVER, " %d ", INSN_UID (web->defs[i]->insn));
1026 ra_debug_msg (DUMP_EVER, "\n use insns:");
1027 for (i = 0; i < web->num_uses; ++i)
1029 ra_debug_msg (DUMP_EVER, " %d ", INSN_UID (web->uses[i]->insn));
1031 ra_debug_msg (DUMP_EVER, "\n");
1034 /* Dump conflicts for web WEB. */
1036 void
1037 dump_web_conflicts (struct web *web)
1039 int num = 0;
1040 unsigned int def2;
1042 ra_debug_msg (DUMP_EVER, "Web: %i(%i)+%i class: %s freedom: %i degree %i\n",
1043 web->id, web->regno, web->add_hardregs,
1044 reg_class_names[web->regclass],
1045 web->num_freedom, web->num_conflicts);
1047 for (def2 = 0; def2 < num_webs; def2++)
1048 if (TEST_BIT (igraph, igraph_index (web->id, def2)) && web->id != def2)
1050 if ((num % 9) == 5)
1051 ra_debug_msg (DUMP_EVER, "\n ");
1052 num++;
1054 ra_debug_msg (DUMP_EVER, " %d(%d)", def2, id2web[def2]->regno);
1055 if (id2web[def2]->add_hardregs)
1056 ra_debug_msg (DUMP_EVER, "+%d", id2web[def2]->add_hardregs);
1058 if (web_conflicts_p (web, id2web[def2]))
1059 ra_debug_msg (DUMP_EVER, "/x");
1061 if (id2web[def2]->type == SELECT)
1062 ra_debug_msg (DUMP_EVER, "/s");
1064 if (id2web[def2]->type == COALESCED)
1065 ra_debug_msg (DUMP_EVER,"/c/%d", alias (id2web[def2])->id);
1067 ra_debug_msg (DUMP_EVER, "\n");
1069 struct conflict_link *wl;
1070 num = 0;
1071 ra_debug_msg (DUMP_EVER, "By conflicts: ");
1072 for (wl = web->conflict_list; wl; wl = wl->next)
1074 struct web* w = wl->t;
1075 if ((num % 9) == 8)
1076 ra_debug_msg (DUMP_EVER, "\n ");
1077 num++;
1078 ra_debug_msg (DUMP_EVER, "%d(%d)%s ", w->id, w->regno,
1079 web_conflicts_p (web, w) ? "+" : "");
1081 ra_debug_msg (DUMP_EVER, "\n");
1085 /* Output HARD_REG_SET to stderr. */
1087 void
1088 debug_hard_reg_set (HARD_REG_SET set)
1090 int i;
1091 for (i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
1093 if (TEST_HARD_REG_BIT (set, i))
1095 fprintf (stderr, "%s ", reg_names[i]);
1098 fprintf (stderr, "\n");
1102 vim:cinoptions={.5s,g0,p5,t0,(0,^-0.5s,n-0.5s:tw=78:cindent:sw=4: