* config/rs6000/rs6000.c (spe_init_builtins,
[official-gcc.git] / gcc / ra-debug.c
bloba20e9901ae50ce8ea2ed37ee58c829967237032e
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 VA_OPEN (ap, format);
51 VA_FIXEDARG (ap, unsigned int, level);
52 VA_FIXEDARG (ap, const char *, format);
53 if ((debug_new_regalloc & level) != 0 && rtl_dump_file != NULL)
54 vfprintf (rtl_dump_file, format, ap);
55 VA_CLOSE (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, x)
71 FILE *file;
72 rtx x;
74 enum rtx_code code = GET_CODE (x);
75 rtx op0 = XEXP (x, 0);
76 switch (code)
78 case NEG:
79 case NOT:
80 fputs ((code == NEG) ? "-(" : "~(", file);
81 ra_print_rtx (file, op0, 0);
82 fputs (")", file);
83 break;
84 case HIGH:
85 fputs ("hi(", file);
86 ra_print_rtx (file, op0, 0);
87 fputs (")", file);
88 break;
89 default:
90 fprintf (file, "%s", GET_RTX_NAME (code));
91 if (GET_MODE (x) != VOIDmode)
92 fprintf (file, ":%s(", GET_MODE_NAME (GET_MODE (x)));
93 else
94 fputs ("(", file);
95 ra_print_rtx (file, op0, 0);
96 fputs (")", file);
97 break;
101 /* Print rtx X, which is a two operand rtx (op:mode (Y) (Z))
102 as "(Y op Z)", if the operand is know, or as "op(Y, Z)", if not,
103 to FILE. */
105 static void
106 ra_print_rtx_2op (file, x)
107 FILE *file;
108 rtx x;
110 int infix = 1;
111 const char *opname = "shitop";
112 enum rtx_code code = GET_CODE (x);
113 rtx op0 = XEXP (x, 0);
114 rtx op1 = XEXP (x, 1);
115 switch (code)
117 /* class '2' */
118 case COMPARE: opname = "?"; break;
119 case MINUS: opname = "-"; break;
120 case DIV: opname = "/"; break;
121 case UDIV: opname = "u/"; break;
122 case MOD: opname = "%"; break;
123 case UMOD: opname = "u%"; break;
124 case ASHIFT: opname = "<<"; break;
125 case ASHIFTRT: opname = "a>>"; break;
126 case LSHIFTRT: opname = "l>>"; break;
127 /* class 'c' */
128 case PLUS: opname = "+"; break;
129 case MULT: opname = "*"; break;
130 case AND: opname = "&"; break;
131 case IOR: opname = "|"; break;
132 case XOR: opname = "^"; break;
133 /* class '<' */
134 case NE: opname = "!="; break;
135 case EQ: opname = "=="; break;
136 case GE: opname = "s>="; break;
137 case GT: opname = "s>"; break;
138 case LE: opname = "s<="; break;
139 case LT: opname = "s<"; break;
140 case GEU: opname = "u>="; break;
141 case GTU: opname = "u>"; break;
142 case LEU: opname = "u<="; break;
143 case LTU: opname = "u<"; break;
144 default:
145 infix = 0;
146 opname = GET_RTX_NAME (code);
147 break;
149 if (infix)
151 fputs ("(", file);
152 ra_print_rtx (file, op0, 0);
153 fprintf (file, " %s ", opname);
154 ra_print_rtx (file, op1, 0);
155 fputs (")", file);
157 else
159 fprintf (file, "%s(", opname);
160 ra_print_rtx (file, op0, 0);
161 fputs (", ", file);
162 ra_print_rtx (file, op1, 0);
163 fputs (")", file);
167 /* Print rtx X, which a three operand rtx to FILE.
168 I.e. X is either an IF_THEN_ELSE, or a bitmap operation. */
170 static void
171 ra_print_rtx_3op (file, x)
172 FILE *file;
173 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' 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, x)
209 FILE *file;
210 rtx x;
212 enum rtx_code code = GET_CODE (x);
213 enum machine_mode mode = GET_MODE (x);
214 switch (code)
216 case CONST_INT:
217 fprintf (file, HOST_WIDE_INT_PRINT_DEC, XWINT (x, 0));
218 break;
219 case CONST_DOUBLE:
221 int i, num = 0;
222 const char *fmt = GET_RTX_FORMAT (code);
223 fputs ("dbl(", file);
224 for (i = 0; i < GET_RTX_LENGTH (code); i++)
226 if (num)
227 fputs (", ", file);
228 if (fmt[i] == 'e' && XEXP (x, i))
229 /* The MEM or other stuff */
231 ra_print_rtx (file, XEXP (x, i), 0);
232 num++;
234 else if (fmt[i] == 'w')
236 fprintf (file, HOST_WIDE_INT_PRINT_HEX, XWINT (x, i));
237 num++;
240 break;
242 case CONST_STRING: fprintf (file, "\"%s\"", XSTR (x, 0)); break;
243 case CONST: fputs ("const(", file);
244 ra_print_rtx (file, XEXP (x, 0), 0);
245 fputs (")", file);
246 break;
247 case PC: fputs ("pc", file); break;
248 case REG:
250 int regno = REGNO (x);
251 if (regno < FIRST_PSEUDO_REGISTER)
253 int i, nregs = HARD_REGNO_NREGS (regno, mode);
254 if (nregs > 1)
255 fputs ("[", file);
256 for (i = 0; i < nregs; i++)
258 if (i)
259 fputs (", ", file);
260 if (reg_names[regno+i] && *reg_names[regno + i])
261 fprintf (file, "%s", reg_names[regno + i]);
262 else
263 fprintf (file, "h%d", regno + i);
265 if (nregs > 1)
266 fputs ("]", file);
268 else
269 fprintf (file, "p%d", regno);
270 break;
272 case SUBREG:
274 rtx sub = SUBREG_REG (x);
275 int ofs = SUBREG_BYTE (x);
276 if (GET_CODE (sub) == REG
277 && REGNO (sub) < FIRST_PSEUDO_REGISTER)
279 int regno = REGNO (sub);
280 int i, nregs = HARD_REGNO_NREGS (regno, mode);
281 regno += subreg_regno_offset (regno, GET_MODE (sub),
282 ofs, mode);
283 if (nregs > 1)
284 fputs ("[", file);
285 for (i = 0; i < nregs; i++)
287 if (i)
288 fputs (", ", file);
289 if (reg_names[regno+i])
290 fprintf (file, "%s", reg_names[regno + i]);
291 else
292 fprintf (file, "h%d", regno + i);
294 if (nregs > 1)
295 fputs ("]", file);
297 else
299 ra_print_rtx (file, sub, 0);
300 fprintf (file, ":[%s+%d]", GET_MODE_NAME (mode), ofs);
302 break;
304 case SCRATCH: fputs ("scratch", file); break;
305 case CONCAT: ra_print_rtx_2op (file, x); break;
306 case HIGH: ra_print_rtx_1op (file, x); break;
307 case LO_SUM:
308 fputs ("(", file);
309 ra_print_rtx (file, XEXP (x, 0), 0);
310 fputs (" + lo(", file);
311 ra_print_rtx (file, XEXP (x, 1), 0);
312 fputs ("))", file);
313 break;
314 case MEM: fputs ("[", file);
315 ra_print_rtx (file, XEXP (x, 0), 0);
316 fprintf (file, "]:%s", GET_MODE_NAME (GET_MODE (x)));
317 /* XXX print alias set too ?? */
318 break;
319 case LABEL_REF:
321 rtx sub = XEXP (x, 0);
322 if (GET_CODE (sub) == NOTE
323 && NOTE_LINE_NUMBER (sub) == NOTE_INSN_DELETED_LABEL)
324 fprintf (file, "(deleted uid=%d)", INSN_UID (sub));
325 else if (GET_CODE (sub) == CODE_LABEL)
326 fprintf (file, "L%d", CODE_LABEL_NUMBER (sub));
327 else
328 fprintf (file, "(nonlabel uid=%d)", INSN_UID (sub));
330 break;
331 case SYMBOL_REF:
332 fprintf (file, "sym(\"%s\")", XSTR (x, 0)); break;
333 case CC0: fputs ("cc0", file); break;
334 default: print_inline_rtx (file, x, 0); break;
338 /* Print a general rtx X to FILE in nice infix form.
339 If WITH_PN is set, and X is one of the toplevel constructs
340 (insns, notes, labels or barriers), then print also the UIDs of
341 the preceding and following insn. */
343 void
344 ra_print_rtx (file, x, with_pn)
345 FILE *file;
346 rtx x;
347 int with_pn;
349 enum rtx_code code;
350 char class;
351 int unhandled = 0;
352 if (!x)
353 return;
354 code = GET_CODE (x);
355 class = GET_RTX_CLASS (code);
357 /* First handle the insn like constructs. */
358 if (INSN_P (x) || code == NOTE || code == CODE_LABEL || code == BARRIER)
360 if (INSN_P (x))
361 fputs (" ", file);
362 /* Non-insns are prefixed by a ';'. */
363 if (code == BARRIER)
364 fputs ("; ", file);
365 else if (code == NOTE)
366 /* But notes are indented very far right. */
367 fprintf (file, "\t\t\t\t\t; ");
368 else if (code == CODE_LABEL)
369 /* And labels have their Lxx name first, before the actual UID. */
371 fprintf (file, "L%d:\t; ", CODE_LABEL_NUMBER (x));
372 if (LABEL_NAME (x))
373 fprintf (file, "(%s) ", LABEL_NAME (x));
374 switch (LABEL_KIND (x))
376 case LABEL_NORMAL: break;
377 case LABEL_STATIC_ENTRY: fputs (" (entry)", file); break;
378 case LABEL_GLOBAL_ENTRY: fputs (" (global entry)", file); break;
379 case LABEL_WEAK_ENTRY: fputs (" (weak entry)", file); break;
380 default: abort();
382 fprintf (file, " [%d uses] uid=(", LABEL_NUSES (x));
384 fprintf (file, "%d", INSN_UID (x));
385 if (with_pn)
386 fprintf (file, " %d %d", PREV_INSN (x) ? INSN_UID (PREV_INSN (x)) : 0,
387 NEXT_INSN (x) ? INSN_UID (NEXT_INSN (x)) : 0);
388 if (code == BARRIER)
389 fputs (" -------- barrier ---------", file);
390 else if (code == CODE_LABEL)
391 fputs (")", file);
392 else if (code == NOTE)
394 int ln = NOTE_LINE_NUMBER (x);
395 if (ln >= (int) NOTE_INSN_BIAS && ln < (int) NOTE_INSN_MAX)
396 fprintf (file, " %s", GET_NOTE_INSN_NAME (ln));
397 else
399 fprintf (file, " line %d", ln);
400 if (NOTE_SOURCE_FILE (x))
401 fprintf (file, ":%s", NOTE_SOURCE_FILE (x));
404 else
406 fprintf (file, "\t");
407 ra_print_rtx (file, PATTERN (x), 0);
409 return;
411 switch (code)
413 /* Top-level stuff. */
414 case PARALLEL:
416 int j;
417 for (j = 0; j < XVECLEN (x, 0); j++)
419 if (j)
420 fputs ("\t;; ", file);
421 ra_print_rtx (file, XVECEXP (x, 0, j), 0);
423 break;
425 case UNSPEC: case UNSPEC_VOLATILE:
427 int j;
428 fprintf (file, "unspec%s(%d",
429 (code == UNSPEC) ? "" : "_vol", XINT (x, 1));
430 for (j = 0; j < XVECLEN (x, 0); j++)
432 fputs (", ", file);
433 ra_print_rtx (file, XVECEXP (x, 0, j), 0);
435 fputs (")", file);
436 break;
438 case SET:
439 if (GET_CODE (SET_DEST (x)) == PC)
441 if (GET_CODE (SET_SRC (x)) == IF_THEN_ELSE
442 && GET_CODE (XEXP (SET_SRC(x), 2)) == PC)
444 fputs ("if ", file);
445 ra_print_rtx (file, XEXP (SET_SRC (x), 0), 0);
446 fputs (" jump ", file);
447 ra_print_rtx (file, XEXP (SET_SRC (x), 1), 0);
449 else
451 fputs ("jump ", file);
452 ra_print_rtx (file, SET_SRC (x), 0);
455 else
457 ra_print_rtx (file, SET_DEST (x), 0);
458 fputs (" <= ", file);
459 ra_print_rtx (file, SET_SRC (x), 0);
461 break;
462 case USE:
463 fputs ("use <= ", file);
464 ra_print_rtx (file, XEXP (x, 0), 0);
465 break;
466 case CLOBBER:
467 ra_print_rtx (file, XEXP (x, 0), 0);
468 fputs (" <= clobber", file);
469 break;
470 case CALL:
471 fputs ("call ", file);
472 ra_print_rtx (file, XEXP (x, 0), 0); /* Address */
473 fputs (" numargs=", file);
474 ra_print_rtx (file, XEXP (x, 1), 0); /* Num arguments */
475 break;
476 case RETURN:
477 fputs ("return", file);
478 break;
479 case TRAP_IF:
480 fputs ("if (", file);
481 ra_print_rtx (file, XEXP (x, 0), 0);
482 fputs (") trap ", file);
483 ra_print_rtx (file, XEXP (x, 1), 0);
484 break;
485 case RESX:
486 fprintf (file, "resx from region %d", XINT (x, 0));
487 break;
489 /* Different things of class 'x' */
490 case SUBREG: ra_print_rtx_object (file, x); break;
491 case STRICT_LOW_PART:
492 fputs ("low(", file);
493 ra_print_rtx (file, XEXP (x, 0), 0);
494 fputs (")", file);
495 break;
496 default:
497 unhandled = 1;
498 break;
500 if (!unhandled)
501 return;
502 if (class == '1')
503 ra_print_rtx_1op (file, x);
504 else if (class == '2' || class == 'c' || class == '<')
505 ra_print_rtx_2op (file, x);
506 else if (class == '3' || class == 'b')
507 ra_print_rtx_3op (file, x);
508 else if (class == 'o')
509 ra_print_rtx_object (file, x);
510 else
511 print_inline_rtx (file, x, 0);
514 /* This only calls ra_print_rtx(), but emits a final newline. */
516 void
517 ra_print_rtx_top (file, x, with_pn)
518 FILE *file;
519 rtx x;
520 int with_pn;
522 ra_print_rtx (file, x, with_pn);
523 fprintf (file, "\n");
526 /* Callable from gdb. This prints rtx X onto stderr. */
528 void
529 ra_debug_rtx (x)
530 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 (bbi)
540 int bbi;
542 basic_block bb = BASIC_BLOCK (bbi);
543 rtx insn;
544 for (insn = bb->head; insn; insn = NEXT_INSN (insn))
546 ra_print_rtx_top (stderr, insn, (insn == bb->head || insn == bb->end));
547 fprintf (stderr, "\n");
548 if (insn == bb->end)
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 (insn, num)
558 rtx insn;
559 int num;
561 int i, count = (num == 0 ? 1 : num < 0 ? -num : num);
562 if (num < 0)
563 for (i = count / 2; i > 0 && PREV_INSN (insn); i--)
564 insn = PREV_INSN (insn);
565 for (i = count; i > 0 && insn; insn = NEXT_INSN (insn), i--)
567 if (GET_CODE (insn) == CODE_LABEL)
568 fprintf (stderr, "\n");
569 ra_print_rtx_top (stderr, insn, (i == count || i == 1));
573 /* Beginning with INSN, emit the whole insn chain into FILE.
574 This also outputs comments when basic blocks start or end and omits
575 some notes, if flag_ra_dump_notes is zero. */
577 void
578 ra_print_rtl_with_bb (file, insn)
579 FILE *file;
580 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 (GET_CODE (insn) == BARRIER)
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 (GET_CODE (insn) == CODE_LABEL)
602 fputc ('\n', file);
603 if (GET_CODE (insn) == NOTE)
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 ()
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 (df)
655 struct df *df ATTRIBUTE_UNUSED;
657 struct move_list *ml;
658 unsigned int def1, def2;
659 int num = 0;
660 int num2;
661 unsigned int i;
662 if (!rtl_dump_file || (debug_new_regalloc & (DUMP_IGRAPH | DUMP_WEBS)) == 0)
663 return;
664 ra_debug_msg (DUMP_IGRAPH, "conflicts:\n ");
665 for (def1 = 0; def1 < num_webs; def1++)
667 int num1 = num;
668 for (num2=0, 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 web->add_hardregs, web->span_deaths);
715 ra_debug_msg (DUMP_WEBS, HOST_WIDE_INT_PRINT_DEC, web->spill_cost);
716 ra_debug_msg (DUMP_WEBS, ") (%s)", 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 ()
742 unsigned int i;
744 if (!rtl_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 ()
802 rtx insn;
803 int i;
804 if (!rtl_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] && GET_CODE (regno_reg_rtx[i]) == REG)
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 unrecongnizable 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] && GET_CODE (regno_reg_rtx[i]) == REG)
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 (level, msg)
854 unsigned int level;
855 const char *msg;
857 unsigned int i;
858 unsigned HOST_WIDE_INT cost;
859 if (!rtl_dump_file || (debug_new_regalloc & level) == 0)
860 return;
862 cost = 0;
863 for (i = 0; i < num_webs; i++)
865 struct web *web = id2web[i];
866 if (alias (web)->type == SPILLED)
867 cost += web->orig_spill_cost;
869 ra_debug_msg (level, " spill cost of graph (%s) = ", msg ? msg : "");
870 ra_debug_msg (level, HOST_WIDE_INT_PRINT_UNSIGNED, cost);
871 ra_debug_msg (level, "\n");
874 /* Dump the color assignment per web, the coalesced and spilled webs. */
876 void
877 dump_ra (df)
878 struct df *df ATTRIBUTE_UNUSED;
880 struct web *web;
881 struct dlist *d;
882 if (!rtl_dump_file || (debug_new_regalloc & DUMP_RESULTS) == 0)
883 return;
885 ra_debug_msg (DUMP_RESULTS, "\nColored:\n");
886 for (d = WEBS(COLORED); d; d = d->next)
888 web = DLIST_WEB (d);
889 ra_debug_msg (DUMP_RESULTS, " %4d : color %d\n", web->id, web->color);
891 ra_debug_msg (DUMP_RESULTS, "\nCoalesced:\n");
892 for (d = WEBS(COALESCED); d; d = d->next)
894 web = DLIST_WEB (d);
895 ra_debug_msg (DUMP_RESULTS, " %4d : to web %d, color %d\n", web->id,
896 alias (web)->id, web->color);
898 ra_debug_msg (DUMP_RESULTS, "\nSpilled:\n");
899 for (d = WEBS(SPILLED); d; d = d->next)
901 web = DLIST_WEB (d);
902 ra_debug_msg (DUMP_RESULTS, " %4d\n", web->id);
904 ra_debug_msg (DUMP_RESULTS, "\n");
905 dump_cost (DUMP_RESULTS);
908 /* Calculate and dump the cumulated costs of certain types of insns
909 (loads, stores and copies). */
911 void
912 dump_static_insn_cost (file, message, prefix)
913 FILE *file;
914 const char *message;
915 const char *prefix;
917 struct cost
919 unsigned HOST_WIDE_INT cost;
920 unsigned int count;
922 basic_block bb;
923 struct cost load, store, regcopy, selfcopy, overall;
924 memset (&load, 0, sizeof(load));
925 memset (&store, 0, sizeof(store));
926 memset (&regcopy, 0, sizeof(regcopy));
927 memset (&selfcopy, 0, sizeof(selfcopy));
928 memset (&overall, 0, sizeof(overall));
930 if (!file)
931 return;
933 FOR_EACH_BB (bb)
935 unsigned HOST_WIDE_INT block_cost = bb->frequency;
936 rtx insn, set;
937 for (insn = bb->head; insn; insn = NEXT_INSN (insn))
939 /* Yes, yes. We don't calculate the costs precisely.
940 Only for "simple enough" insns. Those containing single
941 sets only. */
942 if (INSN_P (insn) && ((set = single_set (insn)) != NULL))
944 rtx src = SET_SRC (set);
945 rtx dest = SET_DEST (set);
946 struct cost *pcost = NULL;
947 overall.cost += block_cost;
948 overall.count++;
949 if (rtx_equal_p (src, dest))
950 pcost = &selfcopy;
951 else if (GET_CODE (src) == GET_CODE (dest)
952 && ((GET_CODE (src) == REG)
953 || (GET_CODE (src) == SUBREG
954 && GET_CODE (SUBREG_REG (src)) == REG
955 && GET_CODE (SUBREG_REG (dest)) == REG)))
956 pcost = &regcopy;
957 else
959 if (GET_CODE (src) == SUBREG)
960 src = SUBREG_REG (src);
961 if (GET_CODE (dest) == SUBREG)
962 dest = SUBREG_REG (dest);
963 if (GET_CODE (src) == MEM && GET_CODE (dest) != MEM
964 && memref_is_stack_slot (src))
965 pcost = &load;
966 else if (GET_CODE (src) != MEM && GET_CODE (dest) == MEM
967 && memref_is_stack_slot (dest))
968 pcost = &store;
970 if (pcost)
972 pcost->cost += block_cost;
973 pcost->count++;
976 if (insn == bb->end)
977 break;
981 if (!prefix)
982 prefix = "";
983 fprintf (file, "static insn cost %s\n", message ? message : "");
984 fprintf (file, " %soverall:\tnum=%6d\tcost=", prefix, overall.count);
985 fprintf (file, HOST_WIDE_INT_PRINT_DEC_SPACE, 8, overall.cost);
986 fprintf (file, "\n");
987 fprintf (file, " %sloads:\tnum=%6d\tcost=", prefix, load.count);
988 fprintf (file, HOST_WIDE_INT_PRINT_DEC_SPACE, 8, load.cost);
989 fprintf (file, "\n");
990 fprintf (file, " %sstores:\tnum=%6d\tcost=", prefix, store.count);
991 fprintf (file, HOST_WIDE_INT_PRINT_DEC_SPACE, 8, store.cost);
992 fprintf (file, "\n");
993 fprintf (file, " %sregcopy:\tnum=%6d\tcost=", prefix, regcopy.count);
994 fprintf (file, HOST_WIDE_INT_PRINT_DEC_SPACE, 8, regcopy.cost);
995 fprintf (file, "\n");
996 fprintf (file, " %sselfcpy:\tnum=%6d\tcost=", prefix, selfcopy.count);
997 fprintf (file, HOST_WIDE_INT_PRINT_DEC_SPACE, 8, selfcopy.cost);
998 fprintf (file, "\n");
1001 /* Returns nonzero, if WEB1 and WEB2 have some possible
1002 hardregs in common. */
1005 web_conflicts_p (web1, web2)
1006 struct web *web1;
1007 struct web *web2;
1009 if (web1->type == PRECOLORED && web2->type == PRECOLORED)
1010 return 0;
1012 if (web1->type == PRECOLORED)
1013 return TEST_HARD_REG_BIT (web2->usable_regs, web1->regno);
1015 if (web2->type == PRECOLORED)
1016 return TEST_HARD_REG_BIT (web1->usable_regs, web2->regno);
1018 return hard_regs_intersect_p (&web1->usable_regs, &web2->usable_regs);
1021 /* Dump all uids of insns in which WEB is mentioned. */
1023 void
1024 dump_web_insns (web)
1025 struct web *web;
1027 unsigned int i;
1029 ra_debug_msg (DUMP_EVER, "Web: %i(%i)+%i class: %s freedom: %i degree %i\n",
1030 web->id, web->regno, web->add_hardregs,
1031 reg_class_names[web->regclass],
1032 web->num_freedom, web->num_conflicts);
1033 ra_debug_msg (DUMP_EVER, " def insns:");
1035 for (i = 0; i < web->num_defs; ++i)
1037 ra_debug_msg (DUMP_EVER, " %d ", INSN_UID (web->defs[i]->insn));
1040 ra_debug_msg (DUMP_EVER, "\n use insns:");
1041 for (i = 0; i < web->num_uses; ++i)
1043 ra_debug_msg (DUMP_EVER, " %d ", INSN_UID (web->uses[i]->insn));
1045 ra_debug_msg (DUMP_EVER, "\n");
1048 /* Dump conflicts for web WEB. */
1050 void
1051 dump_web_conflicts (web)
1052 struct web *web;
1054 int num = 0;
1055 unsigned int def2;
1057 ra_debug_msg (DUMP_EVER, "Web: %i(%i)+%i class: %s freedom: %i degree %i\n",
1058 web->id, web->regno, web->add_hardregs,
1059 reg_class_names[web->regclass],
1060 web->num_freedom, web->num_conflicts);
1062 for (def2 = 0; def2 < num_webs; def2++)
1063 if (TEST_BIT (igraph, igraph_index (web->id, def2)) && web->id != def2)
1065 if ((num % 9) == 5)
1066 ra_debug_msg (DUMP_EVER, "\n ");
1067 num++;
1069 ra_debug_msg (DUMP_EVER, " %d(%d)", def2, id2web[def2]->regno);
1070 if (id2web[def2]->add_hardregs)
1071 ra_debug_msg (DUMP_EVER, "+%d", id2web[def2]->add_hardregs);
1073 if (web_conflicts_p (web, id2web[def2]))
1074 ra_debug_msg (DUMP_EVER, "/x");
1076 if (id2web[def2]->type == SELECT)
1077 ra_debug_msg (DUMP_EVER, "/s");
1079 if (id2web[def2]->type == COALESCED)
1080 ra_debug_msg (DUMP_EVER,"/c/%d", alias (id2web[def2])->id);
1082 ra_debug_msg (DUMP_EVER, "\n");
1084 struct conflict_link *wl;
1085 num = 0;
1086 ra_debug_msg (DUMP_EVER, "By conflicts: ");
1087 for (wl = web->conflict_list; wl; wl = wl->next)
1089 struct web* w = wl->t;
1090 if ((num % 9) == 8)
1091 ra_debug_msg (DUMP_EVER, "\n ");
1092 num++;
1093 ra_debug_msg (DUMP_EVER, "%d(%d)%s ", w->id, w->regno,
1094 web_conflicts_p (web, w) ? "+" : "");
1096 ra_debug_msg (DUMP_EVER, "\n");
1100 /* Output HARD_REG_SET to stderr. */
1102 void
1103 debug_hard_reg_set (set)
1104 HARD_REG_SET set;
1106 int i;
1107 for (i=0; i < FIRST_PSEUDO_REGISTER; ++i)
1109 if (TEST_HARD_REG_BIT (set, i))
1111 fprintf (stderr, "%s ", reg_names[i]);
1114 fprintf (stderr, "\n");
1118 vim:cinoptions={.5s,g0,p5,t0,(0,^-0.5s,n-0.5s:tw=78:cindent:sw=4: