(extendsfdf2): Add pattern accidentally deleted when cirrus instructions were
[official-gcc.git] / gcc / ra-debug.c
blobe415df4e69ba5da070b434b97fe01981de5e7775
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 "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"
36 /* This file contains various dumping and debug functions for
37 the graph coloring register allocator. */
39 static void ra_print_rtx_1op PARAMS ((FILE *, rtx));
40 static void ra_print_rtx_2op PARAMS ((FILE *, rtx));
41 static void ra_print_rtx_3op PARAMS ((FILE *, rtx));
42 static void ra_print_rtx_object PARAMS ((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 VPARAMS ((unsigned int level, const char *format, ...))
53 VA_OPEN (ap, format);
54 VA_FIXEDARG (ap, unsigned int, level);
55 VA_FIXEDARG (ap, const char *, format);
56 if ((debug_new_regalloc & level) != 0 && rtl_dump_file != NULL)
57 vfprintf (rtl_dump_file, format, ap);
58 VA_CLOSE (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, x)
74 FILE *file;
75 rtx x;
77 enum rtx_code code = GET_CODE (x);
78 rtx op0 = XEXP (x, 0);
79 switch (code)
81 case NEG:
82 case NOT:
83 fputs ((code == NEG) ? "-(" : "~(", file);
84 ra_print_rtx (file, op0, 0);
85 fputs (")", file);
86 break;
87 case HIGH:
88 fputs ("hi(", file);
89 ra_print_rtx (file, op0, 0);
90 fputs (")", file);
91 break;
92 default:
93 fprintf (file, "%s", GET_RTX_NAME (code));
94 if (GET_MODE (x) != VOIDmode)
95 fprintf (file, ":%s(", GET_MODE_NAME (GET_MODE (x)));
96 else
97 fputs ("(", file);
98 ra_print_rtx (file, op0, 0);
99 fputs (")", file);
100 break;
104 /* Print rtx X, which is a two operand rtx (op:mode (Y) (Z))
105 as "(Y op Z)", if the operand is know, or as "op(Y, Z)", if not,
106 to FILE. */
108 static void
109 ra_print_rtx_2op (file, x)
110 FILE *file;
111 rtx x;
113 int infix = 1;
114 const char *opname = "shitop";
115 enum rtx_code code = GET_CODE (x);
116 rtx op0 = XEXP (x, 0);
117 rtx op1 = XEXP (x, 1);
118 switch (code)
120 /* class '2' */
121 case COMPARE: opname = "?"; break;
122 case MINUS: opname = "-"; break;
123 case DIV: opname = "/"; break;
124 case UDIV: opname = "u/"; break;
125 case MOD: opname = "%"; break;
126 case UMOD: opname = "u%"; break;
127 case ASHIFT: opname = "<<"; break;
128 case ASHIFTRT: opname = "a>>"; break;
129 case LSHIFTRT: opname = "l>>"; break;
130 /* class 'c' */
131 case PLUS: opname = "+"; break;
132 case MULT: opname = "*"; break;
133 case AND: opname = "&"; break;
134 case IOR: opname = "|"; break;
135 case XOR: opname = "^"; break;
136 /* class '<' */
137 case NE: opname = "!="; break;
138 case EQ: opname = "=="; break;
139 case GE: opname = "s>="; break;
140 case GT: opname = "s>"; break;
141 case LE: opname = "s<="; break;
142 case LT: opname = "s<"; break;
143 case GEU: opname = "u>="; break;
144 case GTU: opname = "u>"; break;
145 case LEU: opname = "u<="; break;
146 case LTU: opname = "u<"; break;
147 default:
148 infix = 0;
149 opname = GET_RTX_NAME (code);
150 break;
152 if (infix)
154 fputs ("(", file);
155 ra_print_rtx (file, op0, 0);
156 fprintf (file, " %s ", opname);
157 ra_print_rtx (file, op1, 0);
158 fputs (")", file);
160 else
162 fprintf (file, "%s(", opname);
163 ra_print_rtx (file, op0, 0);
164 fputs (", ", file);
165 ra_print_rtx (file, op1, 0);
166 fputs (")", file);
170 /* Print rtx X, which a three operand rtx to FILE.
171 I.e. X is either an IF_THEN_ELSE, or a bitmap operation. */
173 static void
174 ra_print_rtx_3op (file, x)
175 FILE *file;
176 rtx x;
178 enum rtx_code code = GET_CODE (x);
179 rtx op0 = XEXP (x, 0);
180 rtx op1 = XEXP (x, 1);
181 rtx op2 = XEXP (x, 2);
182 if (code == IF_THEN_ELSE)
184 ra_print_rtx (file, op0, 0);
185 fputs (" ? ", file);
186 ra_print_rtx (file, op1, 0);
187 fputs (" : ", file);
188 ra_print_rtx (file, op2, 0);
190 else
192 /* Bitmap-operation */
193 fprintf (file, "%s:%s(", GET_RTX_NAME (code),
194 GET_MODE_NAME (GET_MODE (x)));
195 ra_print_rtx (file, op0, 0);
196 fputs (", ", file);
197 ra_print_rtx (file, op1, 0);
198 fputs (", ", file);
199 ra_print_rtx (file, op2, 0);
200 fputs (")", file);
204 /* Print rtx X, which represents an object (class 'o' or some constructs
205 of class 'x' (e.g. subreg)), to FILE.
206 (reg XX) rtl is represented as "pXX", of XX was a pseudo,
207 as "name" it name is the nonnull hardreg name, or as "hXX", if XX
208 is a hardreg, whose name is NULL, or empty. */
210 static void
211 ra_print_rtx_object (file, x)
212 FILE *file;
213 rtx x;
215 enum rtx_code code = GET_CODE (x);
216 enum machine_mode mode = GET_MODE (x);
217 switch (code)
219 case CONST_INT:
220 fprintf (file, HOST_WIDE_INT_PRINT_DEC, XWINT (x, 0));
221 break;
222 case CONST_DOUBLE:
224 int i, num = 0;
225 const char *fmt = GET_RTX_FORMAT (code);
226 fputs ("dbl(", file);
227 for (i = 0; i < GET_RTX_LENGTH (code); i++)
229 if (num)
230 fputs (", ", file);
231 if (fmt[i] == 'e' && XEXP (x, i))
232 /* The MEM or other stuff */
234 ra_print_rtx (file, XEXP (x, i), 0);
235 num++;
237 else if (fmt[i] == 'w')
239 fprintf (file, HOST_WIDE_INT_PRINT_HEX, XWINT (x, i));
240 num++;
243 break;
245 case CONST_STRING: fprintf (file, "\"%s\"", XSTR (x, 0)); break;
246 case CONST: fputs ("const(", file);
247 ra_print_rtx (file, XEXP (x, 0), 0);
248 fputs (")", file);
249 break;
250 case PC: fputs ("pc", file); break;
251 case REG:
253 int regno = REGNO (x);
254 if (regno < FIRST_PSEUDO_REGISTER)
256 int i, nregs = HARD_REGNO_NREGS (regno, mode);
257 if (nregs > 1)
258 fputs ("[", file);
259 for (i = 0; i < nregs; i++)
261 if (i)
262 fputs (", ", file);
263 if (reg_names[regno+i] && *reg_names[regno + i])
264 fprintf (file, "%s", reg_names[regno + i]);
265 else
266 fprintf (file, "h%d", regno + i);
268 if (nregs > 1)
269 fputs ("]", file);
271 else
272 fprintf (file, "p%d", regno);
273 break;
275 case SUBREG:
277 rtx sub = SUBREG_REG (x);
278 int ofs = SUBREG_BYTE (x);
279 if (GET_CODE (sub) == REG
280 && REGNO (sub) < FIRST_PSEUDO_REGISTER)
282 int regno = REGNO (sub);
283 int i, nregs = HARD_REGNO_NREGS (regno, mode);
284 regno += subreg_regno_offset (regno, GET_MODE (sub),
285 ofs, mode);
286 if (nregs > 1)
287 fputs ("[", file);
288 for (i = 0; i < nregs; i++)
290 if (i)
291 fputs (", ", file);
292 if (reg_names[regno+i])
293 fprintf (file, "%s", reg_names[regno + i]);
294 else
295 fprintf (file, "h%d", regno + i);
297 if (nregs > 1)
298 fputs ("]", file);
300 else
302 ra_print_rtx (file, sub, 0);
303 fprintf (file, ":[%s+%d]", GET_MODE_NAME (mode), ofs);
305 break;
307 case SCRATCH: fputs ("scratch", file); break;
308 case CONCAT: ra_print_rtx_2op (file, x); break;
309 case HIGH: ra_print_rtx_1op (file, x); break;
310 case LO_SUM:
311 fputs ("(", file);
312 ra_print_rtx (file, XEXP (x, 0), 0);
313 fputs (" + lo(", file);
314 ra_print_rtx (file, XEXP (x, 1), 0);
315 fputs ("))", file);
316 break;
317 case MEM: fputs ("[", file);
318 ra_print_rtx (file, XEXP (x, 0), 0);
319 fprintf (file, "]:%s", GET_MODE_NAME (GET_MODE (x)));
320 /* XXX print alias set too ?? */
321 break;
322 case LABEL_REF:
324 rtx sub = XEXP (x, 0);
325 if (GET_CODE (sub) == NOTE
326 && NOTE_LINE_NUMBER (sub) == NOTE_INSN_DELETED_LABEL)
327 fprintf (file, "(deleted uid=%d)", INSN_UID (sub));
328 else if (GET_CODE (sub) == CODE_LABEL)
329 fprintf (file, "L%d", CODE_LABEL_NUMBER (sub));
330 else
331 fprintf (file, "(nonlabel uid=%d)", INSN_UID (sub));
333 break;
334 case SYMBOL_REF:
335 fprintf (file, "sym(\"%s\")", XSTR (x, 0)); break;
336 case CC0: fputs ("cc0", file); break;
337 default: print_inline_rtx (file, x, 0); break;
341 /* Print a general rtx X to FILE in nice infix form.
342 If WITH_PN is set, and X is one of the toplevel constructs
343 (insns, notes, labels or barriers), then print also the UIDs of
344 the preceding and following insn. */
346 void
347 ra_print_rtx (file, x, with_pn)
348 FILE *file;
349 rtx x;
350 int with_pn;
352 enum rtx_code code;
353 char class;
354 int unhandled = 0;
355 if (!x)
356 return;
357 code = GET_CODE (x);
358 class = GET_RTX_CLASS (code);
360 /* First handle the insn like constructs. */
361 if (INSN_P (x) || code == NOTE || code == CODE_LABEL || code == BARRIER)
363 if (INSN_P (x))
364 fputs (" ", file);
365 /* Non-insns are prefixed by a ';'. */
366 if (code == BARRIER)
367 fputs ("; ", file);
368 else if (code == NOTE)
369 /* But notes are indented very far right. */
370 fprintf (file, "\t\t\t\t\t; ");
371 else if (code == CODE_LABEL)
372 /* And labels have their Lxx name first, before the actual UID. */
374 fprintf (file, "L%d:\t; ", CODE_LABEL_NUMBER (x));
375 if (LABEL_NAME (x))
376 fprintf (file, "(%s) ", LABEL_NAME (x));
377 switch (LABEL_KIND (x))
379 case LABEL_NORMAL: break;
380 case LABEL_STATIC_ENTRY: fputs (" (entry)", file); break;
381 case LABEL_GLOBAL_ENTRY: fputs (" (global entry)", file); break;
382 case LABEL_WEAK_ENTRY: fputs (" (weak entry)", file); break;
383 default: abort();
385 fprintf (file, " [%d uses] uid=(", LABEL_NUSES (x));
387 fprintf (file, "%d", INSN_UID (x));
388 if (with_pn)
389 fprintf (file, " %d %d", PREV_INSN (x) ? INSN_UID (PREV_INSN (x)) : 0,
390 NEXT_INSN (x) ? INSN_UID (NEXT_INSN (x)) : 0);
391 if (code == BARRIER)
392 fputs (" -------- barrier ---------", file);
393 else if (code == CODE_LABEL)
394 fputs (")", file);
395 else if (code == NOTE)
397 int ln = NOTE_LINE_NUMBER (x);
398 if (ln >= (int) NOTE_INSN_BIAS && ln < (int) NOTE_INSN_MAX)
399 fprintf (file, " %s", GET_NOTE_INSN_NAME (ln));
400 else
402 fprintf (file, " line %d", ln);
403 if (NOTE_SOURCE_FILE (x))
404 fprintf (file, ":%s", NOTE_SOURCE_FILE (x));
407 else
409 fprintf (file, "\t");
410 ra_print_rtx (file, PATTERN (x), 0);
412 return;
414 switch (code)
416 /* Top-level stuff. */
417 case PARALLEL:
419 int j;
420 for (j = 0; j < XVECLEN (x, 0); j++)
422 if (j)
423 fputs ("\t;; ", file);
424 ra_print_rtx (file, XVECEXP (x, 0, j), 0);
426 break;
428 case UNSPEC: case UNSPEC_VOLATILE:
430 int j;
431 fprintf (file, "unspec%s(%d",
432 (code == UNSPEC) ? "" : "_vol", XINT (x, 1));
433 for (j = 0; j < XVECLEN (x, 0); j++)
435 fputs (", ", file);
436 ra_print_rtx (file, XVECEXP (x, 0, j), 0);
438 fputs (")", file);
439 break;
441 case SET:
442 if (GET_CODE (SET_DEST (x)) == PC)
444 if (GET_CODE (SET_SRC (x)) == IF_THEN_ELSE
445 && GET_CODE (XEXP (SET_SRC(x), 2)) == PC)
447 fputs ("if ", file);
448 ra_print_rtx (file, XEXP (SET_SRC (x), 0), 0);
449 fputs (" jump ", file);
450 ra_print_rtx (file, XEXP (SET_SRC (x), 1), 0);
452 else
454 fputs ("jump ", file);
455 ra_print_rtx (file, SET_SRC (x), 0);
458 else
460 ra_print_rtx (file, SET_DEST (x), 0);
461 fputs (" <= ", file);
462 ra_print_rtx (file, SET_SRC (x), 0);
464 break;
465 case USE:
466 fputs ("use <= ", file);
467 ra_print_rtx (file, XEXP (x, 0), 0);
468 break;
469 case CLOBBER:
470 ra_print_rtx (file, XEXP (x, 0), 0);
471 fputs (" <= clobber", file);
472 break;
473 case CALL:
474 fputs ("call ", file);
475 ra_print_rtx (file, XEXP (x, 0), 0); /* Address */
476 fputs (" numargs=", file);
477 ra_print_rtx (file, XEXP (x, 1), 0); /* Num arguments */
478 break;
479 case RETURN:
480 fputs ("return", file);
481 break;
482 case TRAP_IF:
483 fputs ("if (", file);
484 ra_print_rtx (file, XEXP (x, 0), 0);
485 fputs (") trap ", file);
486 ra_print_rtx (file, XEXP (x, 1), 0);
487 break;
488 case RESX:
489 fprintf (file, "resx from region %d", XINT (x, 0));
490 break;
492 /* Different things of class 'x' */
493 case SUBREG: ra_print_rtx_object (file, x); break;
494 case STRICT_LOW_PART:
495 fputs ("low(", file);
496 ra_print_rtx (file, XEXP (x, 0), 0);
497 fputs (")", file);
498 break;
499 default:
500 unhandled = 1;
501 break;
503 if (!unhandled)
504 return;
505 if (class == '1')
506 ra_print_rtx_1op (file, x);
507 else if (class == '2' || class == 'c' || class == '<')
508 ra_print_rtx_2op (file, x);
509 else if (class == '3' || class == 'b')
510 ra_print_rtx_3op (file, x);
511 else if (class == 'o')
512 ra_print_rtx_object (file, x);
513 else
514 print_inline_rtx (file, x, 0);
517 /* This only calls ra_print_rtx(), but emits a final newline. */
519 void
520 ra_print_rtx_top (file, x, with_pn)
521 FILE *file;
522 rtx x;
523 int with_pn;
525 ra_print_rtx (file, x, with_pn);
526 fprintf (file, "\n");
529 /* Callable from gdb. This prints rtx X onto stderr. */
531 void
532 ra_debug_rtx (x)
533 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 (bbi)
543 int bbi;
545 basic_block bb = BASIC_BLOCK (bbi);
546 rtx insn;
547 for (insn = bb->head; insn; insn = NEXT_INSN (insn))
549 ra_print_rtx_top (stderr, insn, (insn == bb->head || insn == bb->end));
550 fprintf (stderr, "\n");
551 if (insn == bb->end)
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 (insn, num)
561 rtx insn;
562 int num;
564 int i, count = (num == 0 ? 1 : num < 0 ? -num : num);
565 if (num < 0)
566 for (i = count / 2; i > 0 && PREV_INSN (insn); i--)
567 insn = PREV_INSN (insn);
568 for (i = count; i > 0 && insn; insn = NEXT_INSN (insn), i--)
570 if (GET_CODE (insn) == CODE_LABEL)
571 fprintf (stderr, "\n");
572 ra_print_rtx_top (stderr, insn, (i == count || i == 1));
576 /* Beginning with INSN, emit the whole insn chain into FILE.
577 This also outputs comments when basic blocks start or end and omits
578 some notes, if flag_ra_dump_notes is zero. */
580 void
581 ra_print_rtl_with_bb (file, insn)
582 FILE *file;
583 rtx insn;
585 basic_block last_bb, bb;
586 unsigned int num = 0;
587 if (!insn)
588 fputs ("nil", file);
589 last_bb = NULL;
590 for (; insn; insn = NEXT_INSN (insn))
592 if (GET_CODE (insn) == BARRIER)
593 bb = NULL;
594 else
595 bb = BLOCK_FOR_INSN (insn);
596 if (bb != last_bb)
598 if (last_bb)
599 fprintf (file, ";; End of basic block %d\n", last_bb->index);
600 if (bb)
601 fprintf (file, ";; Begin of basic block %d\n", bb->index);
602 last_bb = bb;
604 if (GET_CODE (insn) == CODE_LABEL)
605 fputc ('\n', file);
606 if (GET_CODE (insn) == NOTE)
608 /* Ignore basic block and maybe other notes not referencing
609 deleted things. */
610 if (NOTE_LINE_NUMBER (insn) != NOTE_INSN_BASIC_BLOCK
611 && (flag_ra_dump_notes
612 || NOTE_LINE_NUMBER (insn) == NOTE_INSN_DELETED
613 || NOTE_LINE_NUMBER (insn) == NOTE_INSN_DELETED_LABEL))
615 ra_print_rtx_top (file, insn, (num == 0 || !NEXT_INSN (insn)));
616 num++;
619 else
621 ra_print_rtx_top (file, insn, (num == 0 || !NEXT_INSN (insn)));
622 num++;
627 /* Count how many insns were seen how often, while building the interference
628 graph, and prints the findings. */
630 void
631 dump_number_seen ()
633 #define N 17
634 int num[N];
635 int i;
637 for (i = 0; i < N; i++)
638 num[i] = 0;
639 for (i = 0; i < get_max_uid (); i++)
640 if (number_seen[i] < N - 1)
641 num[number_seen[i]]++;
642 else
643 num[N - 1]++;
644 for (i = 0; i < N - 1; i++)
645 if (num[i])
646 ra_debug_msg (DUMP_PROCESS, "%d insns seen %d times\n", num[i], i);
647 if (num[N - 1])
648 ra_debug_msg (DUMP_PROCESS, "%d insns seen %d and more times\n", num[i],
649 N - 1);
650 ra_debug_msg (DUMP_PROCESS, "from overall %d insns\n", get_max_uid ());
651 #undef N
654 /* Dump the interference graph, the move list and the webs. */
656 void
657 dump_igraph (df)
658 struct df *df ATTRIBUTE_UNUSED;
660 struct move_list *ml;
661 unsigned int def1, def2;
662 int num = 0;
663 int num2;
664 unsigned int i;
665 if (!rtl_dump_file || (debug_new_regalloc & (DUMP_IGRAPH | DUMP_WEBS)) == 0)
666 return;
667 ra_debug_msg (DUMP_IGRAPH, "conflicts:\n ");
668 for (def1 = 0; def1 < num_webs; def1++)
670 int num1 = num;
671 for (num2=0, def2 = 0; def2 < num_webs; def2++)
672 if (def1 != def2 && TEST_BIT (igraph, igraph_index (def1, def2)))
674 if (num1 == num)
676 if (SUBWEB_P (ID2WEB (def1)))
677 ra_debug_msg (DUMP_IGRAPH, "%d (SUBREG %d, %d) with ", def1,
678 ID2WEB (def1)->regno,
679 SUBREG_BYTE (ID2WEB (def1)->orig_x));
680 else
681 ra_debug_msg (DUMP_IGRAPH, "%d (REG %d) with ", def1,
682 ID2WEB (def1)->regno);
684 if ((num2 % 9) == 8)
685 ra_debug_msg (DUMP_IGRAPH, "\n ");
686 num++;
687 num2++;
688 if (SUBWEB_P (ID2WEB (def2)))
689 ra_debug_msg (DUMP_IGRAPH, "%d(%d,%d) ", def2, ID2WEB (def2)->regno,
690 SUBREG_BYTE (ID2WEB (def2)->orig_x));
691 else
692 ra_debug_msg (DUMP_IGRAPH, "%d(%d) ", def2, ID2WEB (def2)->regno);
694 if (num1 != num)
695 ra_debug_msg (DUMP_IGRAPH, "\n ");
697 ra_debug_msg (DUMP_IGRAPH, "\n");
698 for (ml = wl_moves; ml; ml = ml->next)
699 if (ml->move)
701 ra_debug_msg (DUMP_IGRAPH, "move: insn %d: Web %d <-- Web %d\n",
702 INSN_UID (ml->move->insn), ml->move->target_web->id,
703 ml->move->source_web->id);
705 ra_debug_msg (DUMP_WEBS, "\nWebs:\n");
706 for (i = 0; i < num_webs; i++)
708 struct web *web = ID2WEB (i);
710 ra_debug_msg (DUMP_WEBS, " %4d : regno %3d", i, web->regno);
711 if (SUBWEB_P (web))
713 ra_debug_msg (DUMP_WEBS, " sub %d", SUBREG_BYTE (web->orig_x));
714 ra_debug_msg (DUMP_WEBS, " par %d", find_web_for_subweb (web)->id);
716 ra_debug_msg (DUMP_WEBS, " +%d (span %d, cost ",
717 web->add_hardregs, web->span_deaths);
718 ra_debug_msg (DUMP_WEBS, HOST_WIDE_INT_PRINT_DEC, web->spill_cost);
719 ra_debug_msg (DUMP_WEBS, ") (%s)", reg_class_names[web->regclass]);
720 if (web->spill_temp == 1)
721 ra_debug_msg (DUMP_WEBS, " (spilltemp)");
722 else if (web->spill_temp == 2)
723 ra_debug_msg (DUMP_WEBS, " (spilltem2)");
724 else if (web->spill_temp == 3)
725 ra_debug_msg (DUMP_WEBS, " (short)");
726 if (web->type == PRECOLORED)
727 ra_debug_msg (DUMP_WEBS, " (precolored, color=%d)", web->color);
728 else if (find_web_for_subweb (web)->num_uses == 0)
729 ra_debug_msg (DUMP_WEBS, " dead");
730 if (web->crosses_call)
731 ra_debug_msg (DUMP_WEBS, " xcall");
732 if (web->regno >= max_normal_pseudo)
733 ra_debug_msg (DUMP_WEBS, " stack");
734 ra_debug_msg (DUMP_WEBS, "\n");
738 /* Dump the interference graph and webs in a format easily
739 parsable by programs. Used to emit real world interference graph
740 to my custom graph colorizer. */
742 void
743 dump_igraph_machine ()
745 unsigned int i;
747 if (!rtl_dump_file || (debug_new_regalloc & DUMP_IGRAPH_M) == 0)
748 return;
749 ra_debug_msg (DUMP_IGRAPH_M, "g %d %d\n", num_webs - num_subwebs,
750 FIRST_PSEUDO_REGISTER);
751 for (i = 0; i < num_webs - num_subwebs; i++)
753 struct web *web = ID2WEB (i);
754 struct conflict_link *cl;
755 int flags = 0;
756 int numc = 0;
757 int col = 0;
758 flags = web->spill_temp & 0xF;
759 flags |= ((web->type == PRECOLORED) ? 1 : 0) << 4;
760 flags |= (web->add_hardregs & 0xF) << 5;
761 for (cl = web->conflict_list; cl; cl = cl->next)
762 if (cl->t->id < web->id)
763 numc++;
764 ra_debug_msg (DUMP_IGRAPH_M, "n %d %d %d %d %d %d %d\n",
765 web->id, web->color, flags,
766 (unsigned int)web->spill_cost, web->num_defs, web->num_uses,
767 numc);
768 if (web->type != PRECOLORED)
770 ra_debug_msg (DUMP_IGRAPH_M, "s %d", web->id);
771 while (1)
773 unsigned int u = 0;
774 int n;
775 for (n = 0; n < 32 && col < FIRST_PSEUDO_REGISTER; n++, col++)
776 if (TEST_HARD_REG_BIT (web->usable_regs, col))
777 u |= 1 << n;
778 ra_debug_msg (DUMP_IGRAPH_M, " %u", u);
779 if (col >= FIRST_PSEUDO_REGISTER)
780 break;
782 ra_debug_msg (DUMP_IGRAPH_M, "\n");
784 if (numc)
786 ra_debug_msg (DUMP_IGRAPH_M, "c %d", web->id);
787 for (cl = web->conflict_list; cl; cl = cl->next)
789 if (cl->t->id < web->id)
790 ra_debug_msg (DUMP_IGRAPH_M, " %d", cl->t->id);
792 ra_debug_msg (DUMP_IGRAPH_M, "\n");
795 ra_debug_msg (DUMP_IGRAPH_M, "e\n");
798 /* This runs after colorization and changing the insn stream.
799 It temporarily replaces all pseudo registers with their colors,
800 and emits information, if the resulting insns are strictly valid. */
802 void
803 dump_constraints ()
805 rtx insn;
806 int i;
807 if (!rtl_dump_file || (debug_new_regalloc & DUMP_CONSTRAINTS) == 0)
808 return;
809 for (i = FIRST_PSEUDO_REGISTER; i < ra_max_regno; i++)
810 if (regno_reg_rtx[i] && GET_CODE (regno_reg_rtx[i]) == REG)
811 REGNO (regno_reg_rtx[i])
812 = ra_reg_renumber[i] >= 0 ? ra_reg_renumber[i] : i;
813 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
814 if (INSN_P (insn))
816 int code;
817 int uid = INSN_UID (insn);
818 int o;
819 /* Don't simply force rerecognition, as combine might left us
820 with some unrecognizable ones, which later leads to aborts
821 in regclass, if we now destroy the remembered INSN_CODE(). */
822 /*INSN_CODE (insn) = -1;*/
823 code = recog_memoized (insn);
824 if (code < 0)
826 ra_debug_msg (DUMP_CONSTRAINTS,
827 "%d: asm insn or not recognizable.\n", uid);
828 continue;
830 ra_debug_msg (DUMP_CONSTRAINTS,
831 "%d: code %d {%s}, %d operands, constraints: ",
832 uid, code, insn_data[code].name, recog_data.n_operands);
833 extract_insn (insn);
834 /*preprocess_constraints ();*/
835 for (o = 0; o < recog_data.n_operands; o++)
837 ra_debug_msg (DUMP_CONSTRAINTS,
838 "%d:%s ", o, recog_data.constraints[o]);
840 if (constrain_operands (1))
841 ra_debug_msg (DUMP_CONSTRAINTS, "matches strictly alternative %d",
842 which_alternative);
843 else
844 ra_debug_msg (DUMP_CONSTRAINTS, "doesn't match strictly");
845 ra_debug_msg (DUMP_CONSTRAINTS, "\n");
847 for (i = FIRST_PSEUDO_REGISTER; i < ra_max_regno; i++)
848 if (regno_reg_rtx[i] && GET_CODE (regno_reg_rtx[i]) == REG)
849 REGNO (regno_reg_rtx[i]) = i;
852 /* This counts and emits the cumulated cost of all spilled webs,
853 preceded by a custom message MSG, with debug level LEVEL. */
855 void
856 dump_graph_cost (level, msg)
857 unsigned int level;
858 const char *msg;
860 unsigned int i;
861 unsigned HOST_WIDE_INT cost;
862 if (!rtl_dump_file || (debug_new_regalloc & level) == 0)
863 return;
865 cost = 0;
866 for (i = 0; i < num_webs; i++)
868 struct web *web = id2web[i];
869 if (alias (web)->type == SPILLED)
870 cost += web->orig_spill_cost;
872 ra_debug_msg (level, " spill cost of graph (%s) = ", msg ? msg : "");
873 ra_debug_msg (level, HOST_WIDE_INT_PRINT_UNSIGNED, cost);
874 ra_debug_msg (level, "\n");
877 /* Dump the color assignment per web, the coalesced and spilled webs. */
879 void
880 dump_ra (df)
881 struct df *df ATTRIBUTE_UNUSED;
883 struct web *web;
884 struct dlist *d;
885 if (!rtl_dump_file || (debug_new_regalloc & DUMP_RESULTS) == 0)
886 return;
888 ra_debug_msg (DUMP_RESULTS, "\nColored:\n");
889 for (d = WEBS(COLORED); d; d = d->next)
891 web = DLIST_WEB (d);
892 ra_debug_msg (DUMP_RESULTS, " %4d : color %d\n", web->id, web->color);
894 ra_debug_msg (DUMP_RESULTS, "\nCoalesced:\n");
895 for (d = WEBS(COALESCED); d; d = d->next)
897 web = DLIST_WEB (d);
898 ra_debug_msg (DUMP_RESULTS, " %4d : to web %d, color %d\n", web->id,
899 alias (web)->id, web->color);
901 ra_debug_msg (DUMP_RESULTS, "\nSpilled:\n");
902 for (d = WEBS(SPILLED); d; d = d->next)
904 web = DLIST_WEB (d);
905 ra_debug_msg (DUMP_RESULTS, " %4d\n", web->id);
907 ra_debug_msg (DUMP_RESULTS, "\n");
908 dump_cost (DUMP_RESULTS);
911 /* Calculate and dump the cumulated costs of certain types of insns
912 (loads, stores and copies). */
914 void
915 dump_static_insn_cost (file, message, prefix)
916 FILE *file;
917 const char *message;
918 const char *prefix;
920 struct cost
922 unsigned HOST_WIDE_INT cost;
923 unsigned int count;
925 basic_block bb;
926 struct cost load, store, regcopy, selfcopy, overall;
927 memset (&load, 0, sizeof(load));
928 memset (&store, 0, sizeof(store));
929 memset (&regcopy, 0, sizeof(regcopy));
930 memset (&selfcopy, 0, sizeof(selfcopy));
931 memset (&overall, 0, sizeof(overall));
933 if (!file)
934 return;
936 FOR_EACH_BB (bb)
938 unsigned HOST_WIDE_INT block_cost = bb->frequency;
939 rtx insn, set;
940 for (insn = bb->head; insn; insn = NEXT_INSN (insn))
942 /* Yes, yes. We don't calculate the costs precisely.
943 Only for "simple enough" insns. Those containing single
944 sets only. */
945 if (INSN_P (insn) && ((set = single_set (insn)) != NULL))
947 rtx src = SET_SRC (set);
948 rtx dest = SET_DEST (set);
949 struct cost *pcost = NULL;
950 overall.cost += block_cost;
951 overall.count++;
952 if (rtx_equal_p (src, dest))
953 pcost = &selfcopy;
954 else if (GET_CODE (src) == GET_CODE (dest)
955 && ((GET_CODE (src) == REG)
956 || (GET_CODE (src) == SUBREG
957 && GET_CODE (SUBREG_REG (src)) == REG
958 && GET_CODE (SUBREG_REG (dest)) == REG)))
959 pcost = &regcopy;
960 else
962 if (GET_CODE (src) == SUBREG)
963 src = SUBREG_REG (src);
964 if (GET_CODE (dest) == SUBREG)
965 dest = SUBREG_REG (dest);
966 if (GET_CODE (src) == MEM && GET_CODE (dest) != MEM
967 && memref_is_stack_slot (src))
968 pcost = &load;
969 else if (GET_CODE (src) != MEM && GET_CODE (dest) == MEM
970 && memref_is_stack_slot (dest))
971 pcost = &store;
973 if (pcost)
975 pcost->cost += block_cost;
976 pcost->count++;
979 if (insn == bb->end)
980 break;
984 if (!prefix)
985 prefix = "";
986 fprintf (file, "static insn cost %s\n", message ? message : "");
987 fprintf (file, " %soverall:\tnum=%6d\tcost=", prefix, overall.count);
988 fprintf (file, HOST_WIDE_INT_PRINT_DEC_SPACE, 8, overall.cost);
989 fprintf (file, "\n");
990 fprintf (file, " %sloads:\tnum=%6d\tcost=", prefix, load.count);
991 fprintf (file, HOST_WIDE_INT_PRINT_DEC_SPACE, 8, load.cost);
992 fprintf (file, "\n");
993 fprintf (file, " %sstores:\tnum=%6d\tcost=", prefix, store.count);
994 fprintf (file, HOST_WIDE_INT_PRINT_DEC_SPACE, 8, store.cost);
995 fprintf (file, "\n");
996 fprintf (file, " %sregcopy:\tnum=%6d\tcost=", prefix, regcopy.count);
997 fprintf (file, HOST_WIDE_INT_PRINT_DEC_SPACE, 8, regcopy.cost);
998 fprintf (file, "\n");
999 fprintf (file, " %sselfcpy:\tnum=%6d\tcost=", prefix, selfcopy.count);
1000 fprintf (file, HOST_WIDE_INT_PRINT_DEC_SPACE, 8, selfcopy.cost);
1001 fprintf (file, "\n");
1004 /* Returns nonzero, if WEB1 and WEB2 have some possible
1005 hardregs in common. */
1008 web_conflicts_p (web1, web2)
1009 struct web *web1;
1010 struct web *web2;
1012 if (web1->type == PRECOLORED && web2->type == PRECOLORED)
1013 return 0;
1015 if (web1->type == PRECOLORED)
1016 return TEST_HARD_REG_BIT (web2->usable_regs, web1->regno);
1018 if (web2->type == PRECOLORED)
1019 return TEST_HARD_REG_BIT (web1->usable_regs, web2->regno);
1021 return hard_regs_intersect_p (&web1->usable_regs, &web2->usable_regs);
1024 /* Dump all uids of insns in which WEB is mentioned. */
1026 void
1027 dump_web_insns (web)
1028 struct web *web;
1030 unsigned int i;
1032 ra_debug_msg (DUMP_EVER, "Web: %i(%i)+%i class: %s freedom: %i degree %i\n",
1033 web->id, web->regno, web->add_hardregs,
1034 reg_class_names[web->regclass],
1035 web->num_freedom, web->num_conflicts);
1036 ra_debug_msg (DUMP_EVER, " def insns:");
1038 for (i = 0; i < web->num_defs; ++i)
1040 ra_debug_msg (DUMP_EVER, " %d ", INSN_UID (web->defs[i]->insn));
1043 ra_debug_msg (DUMP_EVER, "\n use insns:");
1044 for (i = 0; i < web->num_uses; ++i)
1046 ra_debug_msg (DUMP_EVER, " %d ", INSN_UID (web->uses[i]->insn));
1048 ra_debug_msg (DUMP_EVER, "\n");
1051 /* Dump conflicts for web WEB. */
1053 void
1054 dump_web_conflicts (web)
1055 struct web *web;
1057 int num = 0;
1058 unsigned int def2;
1060 ra_debug_msg (DUMP_EVER, "Web: %i(%i)+%i class: %s freedom: %i degree %i\n",
1061 web->id, web->regno, web->add_hardregs,
1062 reg_class_names[web->regclass],
1063 web->num_freedom, web->num_conflicts);
1065 for (def2 = 0; def2 < num_webs; def2++)
1066 if (TEST_BIT (igraph, igraph_index (web->id, def2)) && web->id != def2)
1068 if ((num % 9) == 5)
1069 ra_debug_msg (DUMP_EVER, "\n ");
1070 num++;
1072 ra_debug_msg (DUMP_EVER, " %d(%d)", def2, id2web[def2]->regno);
1073 if (id2web[def2]->add_hardregs)
1074 ra_debug_msg (DUMP_EVER, "+%d", id2web[def2]->add_hardregs);
1076 if (web_conflicts_p (web, id2web[def2]))
1077 ra_debug_msg (DUMP_EVER, "/x");
1079 if (id2web[def2]->type == SELECT)
1080 ra_debug_msg (DUMP_EVER, "/s");
1082 if (id2web[def2]->type == COALESCED)
1083 ra_debug_msg (DUMP_EVER,"/c/%d", alias (id2web[def2])->id);
1085 ra_debug_msg (DUMP_EVER, "\n");
1087 struct conflict_link *wl;
1088 num = 0;
1089 ra_debug_msg (DUMP_EVER, "By conflicts: ");
1090 for (wl = web->conflict_list; wl; wl = wl->next)
1092 struct web* w = wl->t;
1093 if ((num % 9) == 8)
1094 ra_debug_msg (DUMP_EVER, "\n ");
1095 num++;
1096 ra_debug_msg (DUMP_EVER, "%d(%d)%s ", w->id, w->regno,
1097 web_conflicts_p (web, w) ? "+" : "");
1099 ra_debug_msg (DUMP_EVER, "\n");
1103 /* Output HARD_REG_SET to stderr. */
1105 void
1106 debug_hard_reg_set (set)
1107 HARD_REG_SET set;
1109 int i;
1110 for (i=0; i < FIRST_PSEUDO_REGISTER; ++i)
1112 if (TEST_HARD_REG_BIT (set, i))
1114 fprintf (stderr, "%s ", reg_names[i]);
1117 fprintf (stderr, "\n");
1121 vim:cinoptions={.5s,g0,p5,t0,(0,^-0.5s,n-0.5s:tw=78:cindent:sw=4: