* reload1.c (fixup_abnormal_edges): Remove unused variable.
[official-gcc.git] / gcc / ra-debug.c
blobfd8c8d4bb5b61386516e71ba5b3c199819e5153d
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 "rtl.h"
24 #include "insn-config.h"
25 #include "recog.h"
26 #include "function.h"
27 #include "hard-reg-set.h"
28 #include "basic-block.h"
29 #include "df.h"
30 #include "output.h"
31 #include "ra.h"
33 /* This file contains various dumping and debug functions for
34 the graph coloring register allocator. */
36 static void ra_print_rtx_1op PARAMS ((FILE *, rtx));
37 static void ra_print_rtx_2op PARAMS ((FILE *, rtx));
38 static void ra_print_rtx_3op PARAMS ((FILE *, rtx));
39 static void ra_print_rtx_object PARAMS ((FILE *, rtx));
41 /* The hardregs as names, for debugging. */
42 static const char *const reg_class_names[] = REG_CLASS_NAMES;
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 VPARAMS ((unsigned int level, const char *format, ...))
50 #ifndef ANSI_PROTOTYPES
51 int level;
52 const char *format;
53 #endif
54 va_list ap;
55 if ((debug_new_regalloc & level) != 0 && rtl_dump_file != NULL)
57 VA_START (ap, format);
59 #ifndef ANSI_PROTOTYPES
60 format = va_arg (ap, const char *);
61 #endif
63 vfprintf (rtl_dump_file, format, ap);
64 va_end (ap);
69 /* The following ra_print_xxx() functions print RTL expressions
70 in concise infix form. If the mode can be seen from context it's
71 left out. Most operators are represented by their graphical
72 characters, e.g. LE as "<=". Unknown constructs are currently
73 printed with print_inline_rtx(), which disrupts the nice layout.
74 Currently only the inline asm things are written this way. */
76 /* Print rtx X, which is a one operand rtx (op:mode (Y)), as
77 "op(Y)" to FILE. */
79 static void
80 ra_print_rtx_1op (file, x)
81 FILE *file;
82 rtx x;
84 enum rtx_code code = GET_CODE (x);
85 rtx op0 = XEXP (x, 0);
86 switch (code)
88 case NEG:
89 case NOT:
90 fputs ((code == NEG) ? "-(" : "~(", file);
91 ra_print_rtx (file, op0, 0);
92 fputs (")", file);
93 break;
94 case HIGH:
95 fputs ("hi(", file);
96 ra_print_rtx (file, op0, 0);
97 fputs (")", file);
98 break;
99 default:
100 fprintf (file, "%s", GET_RTX_NAME (code));
101 if (GET_MODE (x) != VOIDmode)
102 fprintf (file, ":%s(", GET_MODE_NAME (GET_MODE (x)));
103 else
104 fputs ("(", file);
105 ra_print_rtx (file, op0, 0);
106 fputs (")", file);
107 break;
111 /* Print rtx X, which is a two operand rtx (op:mode (Y) (Z))
112 as "(Y op Z)", if the operand is know, or as "op(Y, Z)", if not,
113 to FILE. */
115 static void
116 ra_print_rtx_2op (file, x)
117 FILE *file;
118 rtx x;
120 int infix = 1;
121 const char *opname = "shitop";
122 enum rtx_code code = GET_CODE (x);
123 rtx op0 = XEXP (x, 0);
124 rtx op1 = XEXP (x, 1);
125 switch (code)
127 /* class '2' */
128 case COMPARE: opname = "?"; break;
129 case MINUS: opname = "-"; break;
130 case DIV: opname = "/"; break;
131 case UDIV: opname = "u/"; break;
132 case MOD: opname = "%"; break;
133 case UMOD: opname = "u%"; break;
134 case ASHIFT: opname = "<<"; break;
135 case ASHIFTRT: opname = "a>>"; break;
136 case LSHIFTRT: opname = "l>>"; break;
137 /* class 'c' */
138 case PLUS: opname = "+"; break;
139 case MULT: opname = "*"; break;
140 case AND: opname = "&"; break;
141 case IOR: opname = "|"; break;
142 case XOR: opname = "^"; break;
143 /* class '<' */
144 case NE: opname = "!="; break;
145 case EQ: opname = "=="; break;
146 case GE: opname = "s>="; break;
147 case GT: opname = "s>"; break;
148 case LE: opname = "s<="; break;
149 case LT: opname = "s<"; break;
150 case GEU: opname = "u>="; break;
151 case GTU: opname = "u>"; break;
152 case LEU: opname = "u<="; break;
153 case LTU: opname = "u<"; break;
154 default:
155 infix = 0;
156 opname = GET_RTX_NAME (code);
157 break;
159 if (infix)
161 fputs ("(", file);
162 ra_print_rtx (file, op0, 0);
163 fprintf (file, " %s ", opname);
164 ra_print_rtx (file, op1, 0);
165 fputs (")", file);
167 else
169 fprintf (file, "%s(", opname);
170 ra_print_rtx (file, op0, 0);
171 fputs (", ", file);
172 ra_print_rtx (file, op1, 0);
173 fputs (")", file);
177 /* Print rtx X, which a three operand rtx to FILE.
178 I.e. X is either an IF_THEN_ELSE, or a bitmap operation. */
180 static void
181 ra_print_rtx_3op (file, x)
182 FILE *file;
183 rtx x;
185 enum rtx_code code = GET_CODE (x);
186 rtx op0 = XEXP (x, 0);
187 rtx op1 = XEXP (x, 1);
188 rtx op2 = XEXP (x, 2);
189 if (code == IF_THEN_ELSE)
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);
197 else
199 /* Bitmap-operation */
200 fprintf (file, "%s:%s(", GET_RTX_NAME (code),
201 GET_MODE_NAME (GET_MODE (x)));
202 ra_print_rtx (file, op0, 0);
203 fputs (", ", file);
204 ra_print_rtx (file, op1, 0);
205 fputs (", ", file);
206 ra_print_rtx (file, op2, 0);
207 fputs (")", file);
211 /* Print rtx X, which represents an object (class 'o' or some constructs
212 of class 'x' (e.g. subreg)), to FILE.
213 (reg XX) rtl is represented as "pXX", of XX was a pseudo,
214 as "name" it name is the nonnull hardreg name, or as "hXX", if XX
215 is a hardreg, whose name is NULL, or empty. */
217 static void
218 ra_print_rtx_object (file, x)
219 FILE *file;
220 rtx x;
222 enum rtx_code code = GET_CODE (x);
223 enum machine_mode mode = GET_MODE (x);
224 switch (code)
226 case CONST_INT:
227 fprintf (file, HOST_WIDE_INT_PRINT_DEC, XWINT (x, 0));
228 break;
229 case CONST_DOUBLE:
231 int i, num = 0;
232 const char *fmt = GET_RTX_FORMAT (code);
233 fputs ("dbl(", file);
234 for (i = 0; i < GET_RTX_LENGTH (code); i++)
236 if (num)
237 fputs (", ", file);
238 if (fmt[i] == 'e' && XEXP (x, i))
239 /* The MEM or other stuff */
241 ra_print_rtx (file, XEXP (x, i), 0);
242 num++;
244 else if (fmt[i] == 'w')
246 fprintf (file, HOST_WIDE_INT_PRINT_HEX, XWINT (x, i));
247 num++;
250 break;
252 case CONST_STRING: fprintf (file, "\"%s\"", XSTR (x, 0)); break;
253 case CONST: fputs ("const(", file);
254 ra_print_rtx (file, XEXP (x, 0), 0);
255 fputs (")", file);
256 break;
257 case PC: fputs ("pc", file); break;
258 case REG:
260 int regno = REGNO (x);
261 if (regno < FIRST_PSEUDO_REGISTER)
263 int i, nregs = HARD_REGNO_NREGS (regno, mode);
264 if (nregs > 1)
265 fputs ("[", file);
266 for (i = 0; i < nregs; i++)
268 if (i)
269 fputs (", ", file);
270 if (reg_names[regno+i] && *reg_names[regno + i])
271 fprintf (file, "%s", reg_names[regno + i]);
272 else
273 fprintf (file, "h%d", regno + i);
275 if (nregs > 1)
276 fputs ("]", file);
278 else
279 fprintf (file, "p%d", regno);
280 break;
282 case SUBREG:
284 rtx sub = SUBREG_REG (x);
285 int ofs = SUBREG_BYTE (x);
286 if (GET_CODE (sub) == REG
287 && REGNO (sub) < FIRST_PSEUDO_REGISTER)
289 int regno = REGNO (sub);
290 int i, nregs = HARD_REGNO_NREGS (regno, mode);
291 regno += subreg_regno_offset (regno, GET_MODE (sub),
292 ofs, mode);
293 if (nregs > 1)
294 fputs ("[", file);
295 for (i = 0; i < nregs; i++)
297 if (i)
298 fputs (", ", file);
299 if (reg_names[regno+i])
300 fprintf (file, "%s", reg_names[regno + i]);
301 else
302 fprintf (file, "h%d", regno + i);
304 if (nregs > 1)
305 fputs ("]", file);
307 else
309 ra_print_rtx (file, sub, 0);
310 fprintf (file, ":[%s+%d]", GET_MODE_NAME (mode), ofs);
312 break;
314 case SCRATCH: fputs ("scratch", file); break;
315 case CONCAT: ra_print_rtx_2op (file, x); break;
316 case HIGH: ra_print_rtx_1op (file, x); break;
317 case LO_SUM:
318 fputs ("(", file);
319 ra_print_rtx (file, XEXP (x, 0), 0);
320 fputs (" + lo(", file);
321 ra_print_rtx (file, XEXP (x, 1), 0);
322 fputs ("))", file);
323 break;
324 case MEM: fputs ("[", file);
325 ra_print_rtx (file, XEXP (x, 0), 0);
326 fprintf (file, "]:%s", GET_MODE_NAME (GET_MODE (x)));
327 /* XXX print alias set too ?? */
328 break;
329 case LABEL_REF:
331 rtx sub = XEXP (x, 0);
332 if (GET_CODE (sub) == NOTE
333 && NOTE_LINE_NUMBER (sub) == NOTE_INSN_DELETED_LABEL)
334 fprintf (file, "(deleted uid=%d)", INSN_UID (sub));
335 else if (GET_CODE (sub) == CODE_LABEL)
336 fprintf (file, "L%d", CODE_LABEL_NUMBER (sub));
337 else
338 fprintf (file, "(nonlabel uid=%d)", INSN_UID (sub));
340 break;
341 case SYMBOL_REF:
342 fprintf (file, "sym(\"%s\")", XSTR (x, 0)); break;
343 case CC0: fputs ("cc0", file); break;
344 default: print_inline_rtx (file, x, 0); break;
348 /* Print a general rtx X to FILE in nice infix form.
349 If WITH_PN is set, and X is one of the toplevel constructs
350 (insns, notes, labels or barriers), then print also the UIDs of
351 the preceding and following insn. */
353 void
354 ra_print_rtx (file, x, with_pn)
355 FILE *file;
356 rtx x;
357 int with_pn;
359 enum rtx_code code;
360 char class;
361 int unhandled = 0;
362 if (!x)
363 return;
364 code = GET_CODE (x);
365 class = GET_RTX_CLASS (code);
367 /* First handle the insn like constructs. */
368 if (INSN_P (x) || code == NOTE || code == CODE_LABEL || code == BARRIER)
370 if (INSN_P (x))
371 fputs (" ", file);
372 /* Non-insns are prefixed by a ';'. */
373 if (code == BARRIER)
374 fputs ("; ", file);
375 else if (code == NOTE)
376 /* But notes are indented very far right. */
377 fprintf (file, "\t\t\t\t\t; ");
378 else if (code == CODE_LABEL)
379 /* And labels have their Lxx name first, before the actual UID. */
381 fprintf (file, "L%d:\t; ", CODE_LABEL_NUMBER (x));
382 if (LABEL_NAME (x))
383 fprintf (file, "(%s) ", LABEL_NAME (x));
384 switch (LABEL_KIND (x))
386 case LABEL_NORMAL: break;
387 case LABEL_STATIC_ENTRY: fputs (" (entry)", file); break;
388 case LABEL_GLOBAL_ENTRY: fputs (" (global entry)", file); break;
389 case LABEL_WEAK_ENTRY: fputs (" (weak entry)", file); break;
390 default: abort();
392 fprintf (file, " [%d uses] uid=(", LABEL_NUSES (x));
394 fprintf (file, "%d", INSN_UID (x));
395 if (with_pn)
396 fprintf (file, " %d %d", PREV_INSN (x) ? INSN_UID (PREV_INSN (x)) : 0,
397 NEXT_INSN (x) ? INSN_UID (NEXT_INSN (x)) : 0);
398 if (code == BARRIER)
399 fputs (" -------- barrier ---------", file);
400 else if (code == CODE_LABEL)
401 fputs (")", file);
402 else if (code == NOTE)
404 int ln = NOTE_LINE_NUMBER (x);
405 if (ln >= (int) NOTE_INSN_BIAS && ln < (int) NOTE_INSN_MAX)
406 fprintf (file, " %s", GET_NOTE_INSN_NAME (ln));
407 else
409 fprintf (file, " line %d", ln);
410 if (NOTE_SOURCE_FILE (x))
411 fprintf (file, ":%s", NOTE_SOURCE_FILE (x));
414 else
416 fprintf (file, "\t");
417 ra_print_rtx (file, PATTERN (x), 0);
419 return;
421 switch (code)
423 /* Top-level stuff. */
424 case PARALLEL:
426 int j;
427 for (j = 0; j < XVECLEN (x, 0); j++)
429 if (j)
430 fputs ("\t;; ", file);
431 ra_print_rtx (file, XVECEXP (x, 0, j), 0);
433 break;
435 case UNSPEC: case UNSPEC_VOLATILE:
437 int j;
438 fprintf (file, "unspec%s(%d",
439 (code == UNSPEC) ? "" : "_vol", XINT (x, 1));
440 for (j = 0; j < XVECLEN (x, 0); j++)
442 fputs (", ", file);
443 ra_print_rtx (file, XVECEXP (x, 0, j), 0);
445 fputs (")", file);
446 break;
448 case SET:
449 if (GET_CODE (SET_DEST (x)) == PC)
451 if (GET_CODE (SET_SRC (x)) == IF_THEN_ELSE
452 && GET_CODE (XEXP (SET_SRC(x), 2)) == PC)
454 fputs ("if ", file);
455 ra_print_rtx (file, XEXP (SET_SRC (x), 0), 0);
456 fputs (" jump ", file);
457 ra_print_rtx (file, XEXP (SET_SRC (x), 1), 0);
459 else
461 fputs ("jump ", file);
462 ra_print_rtx (file, SET_SRC (x), 0);
465 else
467 ra_print_rtx (file, SET_DEST (x), 0);
468 fputs (" <= ", file);
469 ra_print_rtx (file, SET_SRC (x), 0);
471 break;
472 case USE:
473 fputs ("use <= ", file);
474 ra_print_rtx (file, XEXP (x, 0), 0);
475 break;
476 case CLOBBER:
477 ra_print_rtx (file, XEXP (x, 0), 0);
478 fputs (" <= clobber", file);
479 break;
480 case CALL:
481 fputs ("call ", file);
482 ra_print_rtx (file, XEXP (x, 0), 0); /* Address */
483 fputs (" numargs=", file);
484 ra_print_rtx (file, XEXP (x, 1), 0); /* Num arguments */
485 break;
486 case RETURN:
487 fputs ("return", file);
488 break;
489 case TRAP_IF:
490 fputs ("if (", file);
491 ra_print_rtx (file, XEXP (x, 0), 0);
492 fputs (") trap ", file);
493 ra_print_rtx (file, XEXP (x, 1), 0);
494 break;
495 case RESX:
496 fprintf (file, "resx from region %d", XINT (x, 0));
497 break;
499 /* Different things of class 'x' */
500 case SUBREG: ra_print_rtx_object (file, x); break;
501 case STRICT_LOW_PART:
502 fputs ("low(", file);
503 ra_print_rtx (file, XEXP (x, 0), 0);
504 fputs (")", file);
505 break;
506 default:
507 unhandled = 1;
508 break;
510 if (!unhandled)
511 return;
512 if (class == '1')
513 ra_print_rtx_1op (file, x);
514 else if (class == '2' || class == 'c' || class == '<')
515 ra_print_rtx_2op (file, x);
516 else if (class == '3' || class == 'b')
517 ra_print_rtx_3op (file, x);
518 else if (class == 'o')
519 ra_print_rtx_object (file, x);
520 else
521 print_inline_rtx (file, x, 0);
524 /* This only calls ra_print_rtx(), but emits a final newline. */
526 void
527 ra_print_rtx_top (file, x, with_pn)
528 FILE *file;
529 rtx x;
530 int with_pn;
532 ra_print_rtx (file, x, with_pn);
533 fprintf (file, "\n");
536 /* Callable from gdb. This prints rtx X onto stderr. */
538 void
539 ra_debug_rtx (x)
540 rtx x;
542 ra_print_rtx_top (stderr, x, 1);
545 /* This prints the content of basic block with index BBI.
546 The first and last insn are emitted with UIDs of prev and next insns. */
548 void
549 ra_debug_bbi (bbi)
550 int bbi;
552 basic_block bb = BASIC_BLOCK (bbi);
553 rtx insn;
554 for (insn = bb->head; insn; insn = NEXT_INSN (insn))
556 ra_print_rtx_top (stderr, insn, (insn == bb->head || insn == bb->end));
557 fprintf (stderr, "\n");
558 if (insn == bb->end)
559 break;
563 /* Beginning from INSN, emit NUM insns (if NUM is non-negative)
564 or emit a window of NUM insns around INSN, to stderr. */
566 void
567 ra_debug_insns (insn, num)
568 rtx insn;
569 int num;
571 int i, count = (num == 0 ? 1 : num < 0 ? -num : num);
572 if (num < 0)
573 for (i = count / 2; i > 0 && PREV_INSN (insn); i--)
574 insn = PREV_INSN (insn);
575 for (i = count; i > 0 && insn; insn = NEXT_INSN (insn), i--)
577 if (GET_CODE (insn) == CODE_LABEL)
578 fprintf (stderr, "\n");
579 ra_print_rtx_top (stderr, insn, (i == count || i == 1));
583 /* Beginning with INSN, emit the whole insn chain into FILE.
584 This also outputs comments when basic blocks start or end and omits
585 some notes, if flag_ra_dump_notes is zero. */
587 void
588 ra_print_rtl_with_bb (file, insn)
589 FILE *file;
590 rtx insn;
592 basic_block last_bb, bb;
593 unsigned int num = 0;
594 if (!insn)
595 fputs ("nil", file);
596 last_bb = NULL;
597 for (; insn; insn = NEXT_INSN (insn))
599 if (GET_CODE (insn) == BARRIER)
600 bb = NULL;
601 else
602 bb = BLOCK_FOR_INSN (insn);
603 if (bb != last_bb)
605 if (last_bb)
606 fprintf (file, ";; End of basic block %d\n", last_bb->index);
607 if (bb)
608 fprintf (file, ";; Begin of basic block %d\n", bb->index);
609 last_bb = bb;
611 if (GET_CODE (insn) == CODE_LABEL)
612 fputc ('\n', file);
613 if (GET_CODE (insn) == NOTE)
615 /* Ignore basic block and maybe other notes not referencing
616 deleted things. */
617 if (NOTE_LINE_NUMBER (insn) != NOTE_INSN_BASIC_BLOCK
618 && (flag_ra_dump_notes
619 || NOTE_LINE_NUMBER (insn) == NOTE_INSN_DELETED
620 || NOTE_LINE_NUMBER (insn) == NOTE_INSN_DELETED_LABEL))
622 ra_print_rtx_top (file, insn, (num == 0 || !NEXT_INSN (insn)));
623 num++;
626 else
628 ra_print_rtx_top (file, insn, (num == 0 || !NEXT_INSN (insn)));
629 num++;
634 /* Count how many insns were seen how often, while building the interference
635 graph, and prints the findings. */
637 void
638 dump_number_seen ()
640 #define N 17
641 int num[N];
642 int i;
644 for (i = 0; i < N; i++)
645 num[i] = 0;
646 for (i = 0; i < get_max_uid (); i++)
647 if (number_seen[i] < N - 1)
648 num[number_seen[i]]++;
649 else
650 num[N - 1]++;
651 for (i = 0; i < N - 1; i++)
652 if (num[i])
653 ra_debug_msg (DUMP_PROCESS, "%d insns seen %d times\n", num[i], i);
654 if (num[N - 1])
655 ra_debug_msg (DUMP_PROCESS, "%d insns seen %d and more times\n", num[i],
656 N - 1);
657 ra_debug_msg (DUMP_PROCESS, "from overall %d insns\n", get_max_uid ());
658 #undef N
661 /* Dump the interference graph, the move list and the webs. */
663 void
664 dump_igraph (df)
665 struct df *df ATTRIBUTE_UNUSED;
667 struct move_list *ml;
668 unsigned int def1, def2;
669 int num = 0;
670 int num2;
671 unsigned int i;
672 if (!rtl_dump_file || (debug_new_regalloc & (DUMP_IGRAPH | DUMP_WEBS)) == 0)
673 return;
674 ra_debug_msg (DUMP_IGRAPH, "conflicts:\n ");
675 for (def1 = 0; def1 < num_webs; def1++)
677 int num1 = num;
678 for (num2=0, def2 = 0; def2 < num_webs; def2++)
679 if (def1 != def2 && TEST_BIT (igraph, igraph_index (def1, def2)))
681 if (num1 == num)
683 if (SUBWEB_P (ID2WEB (def1)))
684 ra_debug_msg (DUMP_IGRAPH, "%d (SUBREG %d, %d) with ", def1,
685 ID2WEB (def1)->regno,
686 SUBREG_BYTE (ID2WEB (def1)->orig_x));
687 else
688 ra_debug_msg (DUMP_IGRAPH, "%d (REG %d) with ", def1,
689 ID2WEB (def1)->regno);
691 if ((num2 % 9) == 8)
692 ra_debug_msg (DUMP_IGRAPH, "\n ");
693 num++;
694 num2++;
695 if (SUBWEB_P (ID2WEB (def2)))
696 ra_debug_msg (DUMP_IGRAPH, "%d(%d,%d) ", def2, ID2WEB (def2)->regno,
697 SUBREG_BYTE (ID2WEB (def2)->orig_x));
698 else
699 ra_debug_msg (DUMP_IGRAPH, "%d(%d) ", def2, ID2WEB (def2)->regno);
701 if (num1 != num)
702 ra_debug_msg (DUMP_IGRAPH, "\n ");
704 ra_debug_msg (DUMP_IGRAPH, "\n");
705 for (ml = wl_moves; ml; ml = ml->next)
706 if (ml->move)
708 ra_debug_msg (DUMP_IGRAPH, "move: insn %d: Web %d <-- Web %d\n",
709 INSN_UID (ml->move->insn), ml->move->target_web->id,
710 ml->move->source_web->id);
712 ra_debug_msg (DUMP_WEBS, "\nWebs:\n");
713 for (i = 0; i < num_webs; i++)
715 struct web *web = ID2WEB (i);
717 ra_debug_msg (DUMP_WEBS, " %4d : regno %3d", i, web->regno);
718 if (SUBWEB_P (web))
720 ra_debug_msg (DUMP_WEBS, " sub %d", SUBREG_BYTE (web->orig_x));
721 ra_debug_msg (DUMP_WEBS, " par %d", find_web_for_subweb (web)->id);
723 ra_debug_msg (DUMP_WEBS, " +%d (span %d, cost "
724 HOST_WIDE_INT_PRINT_DEC ") (%s)",
725 web->add_hardregs, web->span_deaths, web->spill_cost,
726 reg_class_names[web->regclass]);
727 if (web->spill_temp == 1)
728 ra_debug_msg (DUMP_WEBS, " (spilltemp)");
729 else if (web->spill_temp == 2)
730 ra_debug_msg (DUMP_WEBS, " (spilltem2)");
731 else if (web->spill_temp == 3)
732 ra_debug_msg (DUMP_WEBS, " (short)");
733 if (web->type == PRECOLORED)
734 ra_debug_msg (DUMP_WEBS, " (precolored, color=%d)", web->color);
735 else if (find_web_for_subweb (web)->num_uses == 0)
736 ra_debug_msg (DUMP_WEBS, " dead");
737 if (web->crosses_call)
738 ra_debug_msg (DUMP_WEBS, " xcall");
739 if (web->regno >= max_normal_pseudo)
740 ra_debug_msg (DUMP_WEBS, " stack");
741 ra_debug_msg (DUMP_WEBS, "\n");
745 /* Dump the interference graph and webs in a format easily
746 parsable by programs. Used to emit real world interference graph
747 to my custom graph colorizer. */
749 void
750 dump_igraph_machine ()
752 unsigned int i;
754 if (!rtl_dump_file || (debug_new_regalloc & DUMP_IGRAPH_M) == 0)
755 return;
756 ra_debug_msg (DUMP_IGRAPH_M, "g %d %d\n", num_webs - num_subwebs,
757 FIRST_PSEUDO_REGISTER);
758 for (i = 0; i < num_webs - num_subwebs; i++)
760 struct web *web = ID2WEB (i);
761 struct conflict_link *cl;
762 int flags = 0;
763 int numc = 0;
764 int col = 0;
765 flags = web->spill_temp & 0xF;
766 flags |= ((web->type == PRECOLORED) ? 1 : 0) << 4;
767 flags |= (web->add_hardregs & 0xF) << 5;
768 for (cl = web->conflict_list; cl; cl = cl->next)
769 if (cl->t->id < web->id)
770 numc++;
771 ra_debug_msg (DUMP_IGRAPH_M, "n %d %d %d %d %d %d %d\n",
772 web->id, web->color, flags,
773 (unsigned int)web->spill_cost, web->num_defs, web->num_uses,
774 numc);
775 if (web->type != PRECOLORED)
777 ra_debug_msg (DUMP_IGRAPH_M, "s %d", web->id);
778 while (1)
780 unsigned int u = 0;
781 int n;
782 for (n = 0; n < 32 && col < FIRST_PSEUDO_REGISTER; n++, col++)
783 if (TEST_HARD_REG_BIT (web->usable_regs, col))
784 u |= 1 << n;
785 ra_debug_msg (DUMP_IGRAPH_M, " %u", u);
786 if (col >= FIRST_PSEUDO_REGISTER)
787 break;
789 ra_debug_msg (DUMP_IGRAPH_M, "\n");
791 if (numc)
793 ra_debug_msg (DUMP_IGRAPH_M, "c %d", web->id);
794 for (cl = web->conflict_list; cl; cl = cl->next)
796 if (cl->t->id < web->id)
797 ra_debug_msg (DUMP_IGRAPH_M, " %d", cl->t->id);
799 ra_debug_msg (DUMP_IGRAPH_M, "\n");
802 ra_debug_msg (DUMP_IGRAPH_M, "e\n");
805 /* This runs after colorization and changing the insn stream.
806 It temporarily replaces all pseudo registers with their colors,
807 and emits information, if the resulting insns are strictly valid. */
809 void
810 dump_constraints ()
812 rtx insn;
813 int i;
814 if (!rtl_dump_file || (debug_new_regalloc & DUMP_CONSTRAINTS) == 0)
815 return;
816 for (i = FIRST_PSEUDO_REGISTER; i < ra_max_regno; i++)
817 if (regno_reg_rtx[i] && GET_CODE (regno_reg_rtx[i]) == REG)
818 REGNO (regno_reg_rtx[i])
819 = ra_reg_renumber[i] >= 0 ? ra_reg_renumber[i] : i;
820 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
821 if (INSN_P (insn))
823 int code;
824 int uid = INSN_UID (insn);
825 int o;
826 /* Don't simply force rerecognition, as combine might left us
827 with some unrecongnizable ones, which later leads to aborts
828 in regclass, if we now destroy the remembered INSN_CODE(). */
829 /*INSN_CODE (insn) = -1;*/
830 code = recog_memoized (insn);
831 if (code < 0)
833 ra_debug_msg (DUMP_CONSTRAINTS,
834 "%d: asm insn or not recognizable.\n", uid);
835 continue;
837 ra_debug_msg (DUMP_CONSTRAINTS,
838 "%d: code %d {%s}, %d operands, constraints: ",
839 uid, code, insn_data[code].name, recog_data.n_operands);
840 extract_insn (insn);
841 /*preprocess_constraints ();*/
842 for (o = 0; o < recog_data.n_operands; o++)
844 ra_debug_msg (DUMP_CONSTRAINTS,
845 "%d:%s ", o, recog_data.constraints[o]);
847 if (constrain_operands (1))
848 ra_debug_msg (DUMP_CONSTRAINTS, "matches strictly alternative %d",
849 which_alternative);
850 else
851 ra_debug_msg (DUMP_CONSTRAINTS, "doesn't match strictly");
852 ra_debug_msg (DUMP_CONSTRAINTS, "\n");
854 for (i = FIRST_PSEUDO_REGISTER; i < ra_max_regno; i++)
855 if (regno_reg_rtx[i] && GET_CODE (regno_reg_rtx[i]) == REG)
856 REGNO (regno_reg_rtx[i]) = i;
859 /* This counts and emits the cumulated cost of all spilled webs,
860 preceded by a custom message MSG, with debug level LEVEL. */
862 void
863 dump_graph_cost (level, msg)
864 unsigned int level;
865 const char *msg;
867 unsigned int i;
868 unsigned HOST_WIDE_INT cost;
869 #define LU HOST_WIDE_INT_PRINT_UNSIGNED
870 if (!rtl_dump_file || (debug_new_regalloc & level) == 0)
871 return;
873 cost = 0;
874 for (i = 0; i < num_webs; i++)
876 struct web *web = id2web[i];
877 if (alias (web)->type == SPILLED)
878 cost += web->orig_spill_cost;
880 ra_debug_msg (level, " spill cost of graph (%s) = " LU "\n",
881 msg ? msg : "", cost);
882 #undef LU
885 /* Dump the color assignment per web, the coalesced and spilled webs. */
887 void
888 dump_ra (df)
889 struct df *df ATTRIBUTE_UNUSED;
891 struct web *web;
892 struct dlist *d;
893 if (!rtl_dump_file || (debug_new_regalloc & DUMP_RESULTS) == 0)
894 return;
896 ra_debug_msg (DUMP_RESULTS, "\nColored:\n");
897 for (d = WEBS(COLORED); d; d = d->next)
899 web = DLIST_WEB (d);
900 ra_debug_msg (DUMP_RESULTS, " %4d : color %d\n", web->id, web->color);
902 ra_debug_msg (DUMP_RESULTS, "\nCoalesced:\n");
903 for (d = WEBS(COALESCED); d; d = d->next)
905 web = DLIST_WEB (d);
906 ra_debug_msg (DUMP_RESULTS, " %4d : to web %d, color %d\n", web->id,
907 alias (web)->id, web->color);
909 ra_debug_msg (DUMP_RESULTS, "\nSpilled:\n");
910 for (d = WEBS(SPILLED); d; d = d->next)
912 web = DLIST_WEB (d);
913 ra_debug_msg (DUMP_RESULTS, " %4d\n", web->id);
915 ra_debug_msg (DUMP_RESULTS, "\n");
916 dump_cost (DUMP_RESULTS);
919 /* Calculate and dump the cumulated costs of certain types of insns
920 (loads, stores and copies). */
922 void
923 dump_static_insn_cost (file, message, prefix)
924 FILE *file;
925 const char *message;
926 const char *prefix;
928 struct cost
930 unsigned HOST_WIDE_INT cost;
931 unsigned int count;
933 struct cost load = {0, 0};
934 struct cost store = {0, 0};
935 struct cost regcopy = {0, 0};
936 struct cost selfcopy = {0, 0};
937 struct cost overall = {0, 0};
938 basic_block bb;
940 if (!file)
941 return;
943 FOR_EACH_BB (bb)
945 unsigned HOST_WIDE_INT block_cost = bb->frequency;
946 rtx insn, set;
947 for (insn = bb->head; insn; insn = NEXT_INSN (insn))
949 /* Yes, yes. We don't calculate the costs precisely.
950 Only for "simple enough" insns. Those containing single
951 sets only. */
952 if (INSN_P (insn) && ((set = single_set (insn)) != NULL))
954 rtx src = SET_SRC (set);
955 rtx dest = SET_DEST (set);
956 struct cost *pcost = NULL;
957 overall.cost += block_cost;
958 overall.count++;
959 if (rtx_equal_p (src, dest))
960 pcost = &selfcopy;
961 else if (GET_CODE (src) == GET_CODE (dest)
962 && ((GET_CODE (src) == REG)
963 || (GET_CODE (src) == SUBREG
964 && GET_CODE (SUBREG_REG (src)) == REG
965 && GET_CODE (SUBREG_REG (dest)) == REG)))
966 pcost = &regcopy;
967 else
969 if (GET_CODE (src) == SUBREG)
970 src = SUBREG_REG (src);
971 if (GET_CODE (dest) == SUBREG)
972 dest = SUBREG_REG (dest);
973 if (GET_CODE (src) == MEM && GET_CODE (dest) != MEM
974 && memref_is_stack_slot (src))
975 pcost = &load;
976 else if (GET_CODE (src) != MEM && GET_CODE (dest) == MEM
977 && memref_is_stack_slot (dest))
978 pcost = &store;
980 if (pcost)
982 pcost->cost += block_cost;
983 pcost->count++;
986 if (insn == bb->end)
987 break;
991 if (!prefix)
992 prefix = "";
993 fprintf (file, "static insn cost %s\n", message ? message : "");
994 fprintf (file, " %soverall:\tnum=%6d\tcost=%8d\n", prefix, overall.count,
995 overall.cost);
996 fprintf (file, " %sloads:\tnum=%6d\tcost=%8d\n", prefix, load.count,
997 load.cost);
998 fprintf (file, " %sstores:\tnum=%6d\tcost=%8d\n", prefix,
999 store.count, store.cost);
1000 fprintf (file, " %sregcopy:\tnum=%6d\tcost=%8d\n", prefix, regcopy.count,
1001 regcopy.cost);
1002 fprintf (file, " %sselfcpy:\tnum=%6d\tcost=%8d\n", prefix, selfcopy.count,
1003 selfcopy.cost);
1006 /* Returns nonzero, if WEB1 and WEB2 have some possible
1007 hardregs in common. */
1010 web_conflicts_p (web1, web2)
1011 struct web *web1;
1012 struct web *web2;
1014 if (web1->type == PRECOLORED && web2->type == PRECOLORED)
1015 return 0;
1017 if (web1->type == PRECOLORED)
1018 return TEST_HARD_REG_BIT (web2->usable_regs, web1->regno);
1020 if (web2->type == PRECOLORED)
1021 return TEST_HARD_REG_BIT (web1->usable_regs, web2->regno);
1023 return hard_regs_intersect_p (&web1->usable_regs, &web2->usable_regs);
1026 /* Dump all uids of insns in which WEB is mentioned. */
1028 void
1029 dump_web_insns (web)
1030 struct web *web;
1032 unsigned int i;
1034 ra_debug_msg (DUMP_EVER, "Web: %i(%i)+%i class: %s freedom: %i degree %i\n",
1035 web->id, web->regno, web->add_hardregs,
1036 reg_class_names[web->regclass],
1037 web->num_freedom, web->num_conflicts);
1038 ra_debug_msg (DUMP_EVER, " def insns:");
1040 for (i = 0; i < web->num_defs; ++i)
1042 ra_debug_msg (DUMP_EVER, " %d ", INSN_UID (web->defs[i]->insn));
1045 ra_debug_msg (DUMP_EVER, "\n use insns:");
1046 for (i = 0; i < web->num_uses; ++i)
1048 ra_debug_msg (DUMP_EVER, " %d ", INSN_UID (web->uses[i]->insn));
1050 ra_debug_msg (DUMP_EVER, "\n");
1053 /* Dump conflicts for web WEB. */
1055 void
1056 dump_web_conflicts (web)
1057 struct web *web;
1059 int num = 0;
1060 unsigned int def2;
1062 ra_debug_msg (DUMP_EVER, "Web: %i(%i)+%i class: %s freedom: %i degree %i\n",
1063 web->id, web->regno, web->add_hardregs,
1064 reg_class_names[web->regclass],
1065 web->num_freedom, web->num_conflicts);
1067 for (def2 = 0; def2 < num_webs; def2++)
1068 if (TEST_BIT (igraph, igraph_index (web->id, def2)) && web->id != def2)
1070 if ((num % 9) == 5)
1071 ra_debug_msg (DUMP_EVER, "\n ");
1072 num++;
1074 ra_debug_msg (DUMP_EVER, " %d(%d)", def2, id2web[def2]->regno);
1075 if (id2web[def2]->add_hardregs)
1076 ra_debug_msg (DUMP_EVER, "+%d", id2web[def2]->add_hardregs);
1078 if (web_conflicts_p (web, id2web[def2]))
1079 ra_debug_msg (DUMP_EVER, "/x");
1081 if (id2web[def2]->type == SELECT)
1082 ra_debug_msg (DUMP_EVER, "/s");
1084 if (id2web[def2]->type == COALESCED)
1085 ra_debug_msg (DUMP_EVER,"/c/%d", alias (id2web[def2])->id);
1087 ra_debug_msg (DUMP_EVER, "\n");
1089 struct conflict_link *wl;
1090 num = 0;
1091 ra_debug_msg (DUMP_EVER, "By conflicts: ");
1092 for (wl = web->conflict_list; wl; wl = wl->next)
1094 struct web* w = wl->t;
1095 if ((num % 9) == 8)
1096 ra_debug_msg (DUMP_EVER, "\n ");
1097 num++;
1098 ra_debug_msg (DUMP_EVER, "%d(%d)%s ", w->id, w->regno,
1099 web_conflicts_p (web, w) ? "+" : "");
1101 ra_debug_msg (DUMP_EVER, "\n");
1105 /* Output HARD_REG_SET to stderr. */
1107 void
1108 debug_hard_reg_set (set)
1109 HARD_REG_SET set;
1111 int i;
1112 for (i=0; i < FIRST_PSEUDO_REGISTER; ++i)
1114 if (TEST_HARD_REG_BIT (set, i))
1116 fprintf (stderr, "%s ", reg_names[i]);
1119 fprintf (stderr, "\n");
1123 vim:cinoptions={.5s,g0,p5,t0,(0,^-0.5s,n-0.5s:tw=78:cindent:sw=4: