* config/alpha/alpha.c: Follow spelling conventions.
[official-gcc.git] / gcc / ra-debug.c
blob8daa63d04563dd2471afedc6c2db722a18671888
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"
32 #include "tm_p.h"
34 /* This file contains various dumping and debug functions for
35 the graph coloring register allocator. */
37 static void ra_print_rtx_1op PARAMS ((FILE *, rtx));
38 static void ra_print_rtx_2op PARAMS ((FILE *, rtx));
39 static void ra_print_rtx_3op PARAMS ((FILE *, rtx));
40 static void ra_print_rtx_object PARAMS ((FILE *, rtx));
42 /* The hardregs as names, for debugging. */
43 static const char *const reg_class_names[] = REG_CLASS_NAMES;
45 /* Print a message to the dump file, if debug_new_regalloc and LEVEL
46 have any bits in common. */
48 void
49 ra_debug_msg VPARAMS ((unsigned int level, const char *format, ...))
51 VA_OPEN (ap, format);
52 VA_FIXEDARG (ap, unsigned int, level);
53 VA_FIXEDARG (ap, const char *, format);
54 if ((debug_new_regalloc & level) != 0 && rtl_dump_file != NULL)
55 vfprintf (rtl_dump_file, format, ap);
56 VA_CLOSE (ap);
60 /* The following ra_print_xxx() functions print RTL expressions
61 in concise infix form. If the mode can be seen from context it's
62 left out. Most operators are represented by their graphical
63 characters, e.g. LE as "<=". Unknown constructs are currently
64 printed with print_inline_rtx(), which disrupts the nice layout.
65 Currently only the inline asm things are written this way. */
67 /* Print rtx X, which is a one operand rtx (op:mode (Y)), as
68 "op(Y)" to FILE. */
70 static void
71 ra_print_rtx_1op (file, x)
72 FILE *file;
73 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, x)
108 FILE *file;
109 rtx x;
111 int infix = 1;
112 const char *opname = "shitop";
113 enum rtx_code code = GET_CODE (x);
114 rtx op0 = XEXP (x, 0);
115 rtx op1 = XEXP (x, 1);
116 switch (code)
118 /* class '2' */
119 case COMPARE: opname = "?"; break;
120 case MINUS: opname = "-"; break;
121 case DIV: opname = "/"; break;
122 case UDIV: opname = "u/"; break;
123 case MOD: opname = "%"; break;
124 case UMOD: opname = "u%"; break;
125 case ASHIFT: opname = "<<"; break;
126 case ASHIFTRT: opname = "a>>"; break;
127 case LSHIFTRT: opname = "l>>"; break;
128 /* class 'c' */
129 case PLUS: opname = "+"; break;
130 case MULT: opname = "*"; break;
131 case AND: opname = "&"; break;
132 case IOR: opname = "|"; break;
133 case XOR: opname = "^"; break;
134 /* class '<' */
135 case NE: opname = "!="; break;
136 case EQ: opname = "=="; break;
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, x)
173 FILE *file;
174 rtx x;
176 enum rtx_code code = GET_CODE (x);
177 rtx op0 = XEXP (x, 0);
178 rtx op1 = XEXP (x, 1);
179 rtx op2 = XEXP (x, 2);
180 if (code == IF_THEN_ELSE)
182 ra_print_rtx (file, op0, 0);
183 fputs (" ? ", file);
184 ra_print_rtx (file, op1, 0);
185 fputs (" : ", file);
186 ra_print_rtx (file, op2, 0);
188 else
190 /* Bitmap-operation */
191 fprintf (file, "%s:%s(", GET_RTX_NAME (code),
192 GET_MODE_NAME (GET_MODE (x)));
193 ra_print_rtx (file, op0, 0);
194 fputs (", ", file);
195 ra_print_rtx (file, op1, 0);
196 fputs (", ", file);
197 ra_print_rtx (file, op2, 0);
198 fputs (")", file);
202 /* Print rtx X, which represents an object (class 'o' or some constructs
203 of class 'x' (e.g. subreg)), to FILE.
204 (reg XX) rtl is represented as "pXX", of XX was a pseudo,
205 as "name" it name is the nonnull hardreg name, or as "hXX", if XX
206 is a hardreg, whose name is NULL, or empty. */
208 static void
209 ra_print_rtx_object (file, x)
210 FILE *file;
211 rtx x;
213 enum rtx_code code = GET_CODE (x);
214 enum machine_mode mode = GET_MODE (x);
215 switch (code)
217 case CONST_INT:
218 fprintf (file, HOST_WIDE_INT_PRINT_DEC, XWINT (x, 0));
219 break;
220 case CONST_DOUBLE:
222 int i, num = 0;
223 const char *fmt = GET_RTX_FORMAT (code);
224 fputs ("dbl(", file);
225 for (i = 0; i < GET_RTX_LENGTH (code); i++)
227 if (num)
228 fputs (", ", file);
229 if (fmt[i] == 'e' && XEXP (x, i))
230 /* The MEM or other stuff */
232 ra_print_rtx (file, XEXP (x, i), 0);
233 num++;
235 else if (fmt[i] == 'w')
237 fprintf (file, HOST_WIDE_INT_PRINT_HEX, XWINT (x, i));
238 num++;
241 break;
243 case CONST_STRING: fprintf (file, "\"%s\"", XSTR (x, 0)); break;
244 case CONST: fputs ("const(", file);
245 ra_print_rtx (file, XEXP (x, 0), 0);
246 fputs (")", file);
247 break;
248 case PC: fputs ("pc", file); break;
249 case REG:
251 int regno = REGNO (x);
252 if (regno < FIRST_PSEUDO_REGISTER)
254 int i, nregs = HARD_REGNO_NREGS (regno, mode);
255 if (nregs > 1)
256 fputs ("[", file);
257 for (i = 0; i < nregs; i++)
259 if (i)
260 fputs (", ", file);
261 if (reg_names[regno+i] && *reg_names[regno + i])
262 fprintf (file, "%s", reg_names[regno + i]);
263 else
264 fprintf (file, "h%d", regno + i);
266 if (nregs > 1)
267 fputs ("]", file);
269 else
270 fprintf (file, "p%d", regno);
271 break;
273 case SUBREG:
275 rtx sub = SUBREG_REG (x);
276 int ofs = SUBREG_BYTE (x);
277 if (GET_CODE (sub) == REG
278 && REGNO (sub) < FIRST_PSEUDO_REGISTER)
280 int regno = REGNO (sub);
281 int i, nregs = HARD_REGNO_NREGS (regno, mode);
282 regno += subreg_regno_offset (regno, GET_MODE (sub),
283 ofs, mode);
284 if (nregs > 1)
285 fputs ("[", file);
286 for (i = 0; i < nregs; i++)
288 if (i)
289 fputs (", ", file);
290 if (reg_names[regno+i])
291 fprintf (file, "%s", reg_names[regno + i]);
292 else
293 fprintf (file, "h%d", regno + i);
295 if (nregs > 1)
296 fputs ("]", file);
298 else
300 ra_print_rtx (file, sub, 0);
301 fprintf (file, ":[%s+%d]", GET_MODE_NAME (mode), ofs);
303 break;
305 case SCRATCH: fputs ("scratch", file); break;
306 case CONCAT: ra_print_rtx_2op (file, x); break;
307 case HIGH: ra_print_rtx_1op (file, x); break;
308 case LO_SUM:
309 fputs ("(", file);
310 ra_print_rtx (file, XEXP (x, 0), 0);
311 fputs (" + lo(", file);
312 ra_print_rtx (file, XEXP (x, 1), 0);
313 fputs ("))", file);
314 break;
315 case MEM: fputs ("[", file);
316 ra_print_rtx (file, XEXP (x, 0), 0);
317 fprintf (file, "]:%s", GET_MODE_NAME (GET_MODE (x)));
318 /* XXX print alias set too ?? */
319 break;
320 case LABEL_REF:
322 rtx sub = XEXP (x, 0);
323 if (GET_CODE (sub) == NOTE
324 && NOTE_LINE_NUMBER (sub) == NOTE_INSN_DELETED_LABEL)
325 fprintf (file, "(deleted uid=%d)", INSN_UID (sub));
326 else if (GET_CODE (sub) == CODE_LABEL)
327 fprintf (file, "L%d", CODE_LABEL_NUMBER (sub));
328 else
329 fprintf (file, "(nonlabel uid=%d)", INSN_UID (sub));
331 break;
332 case SYMBOL_REF:
333 fprintf (file, "sym(\"%s\")", XSTR (x, 0)); break;
334 case CC0: fputs ("cc0", file); break;
335 default: print_inline_rtx (file, x, 0); break;
339 /* Print a general rtx X to FILE in nice infix form.
340 If WITH_PN is set, and X is one of the toplevel constructs
341 (insns, notes, labels or barriers), then print also the UIDs of
342 the preceding and following insn. */
344 void
345 ra_print_rtx (file, x, with_pn)
346 FILE *file;
347 rtx x;
348 int with_pn;
350 enum rtx_code code;
351 char class;
352 int unhandled = 0;
353 if (!x)
354 return;
355 code = GET_CODE (x);
356 class = GET_RTX_CLASS (code);
358 /* First handle the insn like constructs. */
359 if (INSN_P (x) || code == NOTE || code == CODE_LABEL || code == BARRIER)
361 if (INSN_P (x))
362 fputs (" ", file);
363 /* Non-insns are prefixed by a ';'. */
364 if (code == BARRIER)
365 fputs ("; ", file);
366 else if (code == NOTE)
367 /* But notes are indented very far right. */
368 fprintf (file, "\t\t\t\t\t; ");
369 else if (code == CODE_LABEL)
370 /* And labels have their Lxx name first, before the actual UID. */
372 fprintf (file, "L%d:\t; ", CODE_LABEL_NUMBER (x));
373 if (LABEL_NAME (x))
374 fprintf (file, "(%s) ", LABEL_NAME (x));
375 switch (LABEL_KIND (x))
377 case LABEL_NORMAL: break;
378 case LABEL_STATIC_ENTRY: fputs (" (entry)", file); break;
379 case LABEL_GLOBAL_ENTRY: fputs (" (global entry)", file); break;
380 case LABEL_WEAK_ENTRY: fputs (" (weak entry)", file); break;
381 default: abort();
383 fprintf (file, " [%d uses] uid=(", LABEL_NUSES (x));
385 fprintf (file, "%d", INSN_UID (x));
386 if (with_pn)
387 fprintf (file, " %d %d", PREV_INSN (x) ? INSN_UID (PREV_INSN (x)) : 0,
388 NEXT_INSN (x) ? INSN_UID (NEXT_INSN (x)) : 0);
389 if (code == BARRIER)
390 fputs (" -------- barrier ---------", file);
391 else if (code == CODE_LABEL)
392 fputs (")", file);
393 else if (code == NOTE)
395 int ln = NOTE_LINE_NUMBER (x);
396 if (ln >= (int) NOTE_INSN_BIAS && ln < (int) NOTE_INSN_MAX)
397 fprintf (file, " %s", GET_NOTE_INSN_NAME (ln));
398 else
400 fprintf (file, " line %d", ln);
401 if (NOTE_SOURCE_FILE (x))
402 fprintf (file, ":%s", NOTE_SOURCE_FILE (x));
405 else
407 fprintf (file, "\t");
408 ra_print_rtx (file, PATTERN (x), 0);
410 return;
412 switch (code)
414 /* Top-level stuff. */
415 case PARALLEL:
417 int j;
418 for (j = 0; j < XVECLEN (x, 0); j++)
420 if (j)
421 fputs ("\t;; ", file);
422 ra_print_rtx (file, XVECEXP (x, 0, j), 0);
424 break;
426 case UNSPEC: case UNSPEC_VOLATILE:
428 int j;
429 fprintf (file, "unspec%s(%d",
430 (code == UNSPEC) ? "" : "_vol", XINT (x, 1));
431 for (j = 0; j < XVECLEN (x, 0); j++)
433 fputs (", ", file);
434 ra_print_rtx (file, XVECEXP (x, 0, j), 0);
436 fputs (")", file);
437 break;
439 case SET:
440 if (GET_CODE (SET_DEST (x)) == PC)
442 if (GET_CODE (SET_SRC (x)) == IF_THEN_ELSE
443 && GET_CODE (XEXP (SET_SRC(x), 2)) == PC)
445 fputs ("if ", file);
446 ra_print_rtx (file, XEXP (SET_SRC (x), 0), 0);
447 fputs (" jump ", file);
448 ra_print_rtx (file, XEXP (SET_SRC (x), 1), 0);
450 else
452 fputs ("jump ", file);
453 ra_print_rtx (file, SET_SRC (x), 0);
456 else
458 ra_print_rtx (file, SET_DEST (x), 0);
459 fputs (" <= ", file);
460 ra_print_rtx (file, SET_SRC (x), 0);
462 break;
463 case USE:
464 fputs ("use <= ", file);
465 ra_print_rtx (file, XEXP (x, 0), 0);
466 break;
467 case CLOBBER:
468 ra_print_rtx (file, XEXP (x, 0), 0);
469 fputs (" <= clobber", file);
470 break;
471 case CALL:
472 fputs ("call ", file);
473 ra_print_rtx (file, XEXP (x, 0), 0); /* Address */
474 fputs (" numargs=", file);
475 ra_print_rtx (file, XEXP (x, 1), 0); /* Num arguments */
476 break;
477 case RETURN:
478 fputs ("return", file);
479 break;
480 case TRAP_IF:
481 fputs ("if (", file);
482 ra_print_rtx (file, XEXP (x, 0), 0);
483 fputs (") trap ", file);
484 ra_print_rtx (file, XEXP (x, 1), 0);
485 break;
486 case RESX:
487 fprintf (file, "resx from region %d", XINT (x, 0));
488 break;
490 /* Different things of class 'x' */
491 case SUBREG: ra_print_rtx_object (file, x); break;
492 case STRICT_LOW_PART:
493 fputs ("low(", file);
494 ra_print_rtx (file, XEXP (x, 0), 0);
495 fputs (")", file);
496 break;
497 default:
498 unhandled = 1;
499 break;
501 if (!unhandled)
502 return;
503 if (class == '1')
504 ra_print_rtx_1op (file, x);
505 else if (class == '2' || class == 'c' || class == '<')
506 ra_print_rtx_2op (file, x);
507 else if (class == '3' || class == 'b')
508 ra_print_rtx_3op (file, x);
509 else if (class == 'o')
510 ra_print_rtx_object (file, x);
511 else
512 print_inline_rtx (file, x, 0);
515 /* This only calls ra_print_rtx(), but emits a final newline. */
517 void
518 ra_print_rtx_top (file, x, with_pn)
519 FILE *file;
520 rtx x;
521 int with_pn;
523 ra_print_rtx (file, x, with_pn);
524 fprintf (file, "\n");
527 /* Callable from gdb. This prints rtx X onto stderr. */
529 void
530 ra_debug_rtx (x)
531 rtx x;
533 ra_print_rtx_top (stderr, x, 1);
536 /* This prints the content of basic block with index BBI.
537 The first and last insn are emitted with UIDs of prev and next insns. */
539 void
540 ra_debug_bbi (bbi)
541 int bbi;
543 basic_block bb = BASIC_BLOCK (bbi);
544 rtx insn;
545 for (insn = bb->head; insn; insn = NEXT_INSN (insn))
547 ra_print_rtx_top (stderr, insn, (insn == bb->head || insn == bb->end));
548 fprintf (stderr, "\n");
549 if (insn == bb->end)
550 break;
554 /* Beginning from INSN, emit NUM insns (if NUM is non-negative)
555 or emit a window of NUM insns around INSN, to stderr. */
557 void
558 ra_debug_insns (insn, num)
559 rtx insn;
560 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 (GET_CODE (insn) == CODE_LABEL)
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, insn)
580 FILE *file;
581 rtx insn;
583 basic_block last_bb, bb;
584 unsigned int num = 0;
585 if (!insn)
586 fputs ("nil", file);
587 last_bb = NULL;
588 for (; insn; insn = NEXT_INSN (insn))
590 if (GET_CODE (insn) == BARRIER)
591 bb = NULL;
592 else
593 bb = BLOCK_FOR_INSN (insn);
594 if (bb != last_bb)
596 if (last_bb)
597 fprintf (file, ";; End of basic block %d\n", last_bb->index);
598 if (bb)
599 fprintf (file, ";; Begin of basic block %d\n", bb->index);
600 last_bb = bb;
602 if (GET_CODE (insn) == CODE_LABEL)
603 fputc ('\n', file);
604 if (GET_CODE (insn) == NOTE)
606 /* Ignore basic block and maybe other notes not referencing
607 deleted things. */
608 if (NOTE_LINE_NUMBER (insn) != NOTE_INSN_BASIC_BLOCK
609 && (flag_ra_dump_notes
610 || NOTE_LINE_NUMBER (insn) == NOTE_INSN_DELETED
611 || NOTE_LINE_NUMBER (insn) == NOTE_INSN_DELETED_LABEL))
613 ra_print_rtx_top (file, insn, (num == 0 || !NEXT_INSN (insn)));
614 num++;
617 else
619 ra_print_rtx_top (file, insn, (num == 0 || !NEXT_INSN (insn)));
620 num++;
625 /* Count how many insns were seen how often, while building the interference
626 graph, and prints the findings. */
628 void
629 dump_number_seen ()
631 #define N 17
632 int num[N];
633 int i;
635 for (i = 0; i < N; i++)
636 num[i] = 0;
637 for (i = 0; i < get_max_uid (); i++)
638 if (number_seen[i] < N - 1)
639 num[number_seen[i]]++;
640 else
641 num[N - 1]++;
642 for (i = 0; i < N - 1; i++)
643 if (num[i])
644 ra_debug_msg (DUMP_PROCESS, "%d insns seen %d times\n", num[i], i);
645 if (num[N - 1])
646 ra_debug_msg (DUMP_PROCESS, "%d insns seen %d and more times\n", num[i],
647 N - 1);
648 ra_debug_msg (DUMP_PROCESS, "from overall %d insns\n", get_max_uid ());
649 #undef N
652 /* Dump the interference graph, the move list and the webs. */
654 void
655 dump_igraph (df)
656 struct df *df ATTRIBUTE_UNUSED;
658 struct move_list *ml;
659 unsigned int def1, def2;
660 int num = 0;
661 int num2;
662 unsigned int i;
663 if (!rtl_dump_file || (debug_new_regalloc & (DUMP_IGRAPH | DUMP_WEBS)) == 0)
664 return;
665 ra_debug_msg (DUMP_IGRAPH, "conflicts:\n ");
666 for (def1 = 0; def1 < num_webs; def1++)
668 int num1 = num;
669 for (num2=0, def2 = 0; def2 < num_webs; def2++)
670 if (def1 != def2 && TEST_BIT (igraph, igraph_index (def1, def2)))
672 if (num1 == num)
674 if (SUBWEB_P (ID2WEB (def1)))
675 ra_debug_msg (DUMP_IGRAPH, "%d (SUBREG %d, %d) with ", def1,
676 ID2WEB (def1)->regno,
677 SUBREG_BYTE (ID2WEB (def1)->orig_x));
678 else
679 ra_debug_msg (DUMP_IGRAPH, "%d (REG %d) with ", def1,
680 ID2WEB (def1)->regno);
682 if ((num2 % 9) == 8)
683 ra_debug_msg (DUMP_IGRAPH, "\n ");
684 num++;
685 num2++;
686 if (SUBWEB_P (ID2WEB (def2)))
687 ra_debug_msg (DUMP_IGRAPH, "%d(%d,%d) ", def2, ID2WEB (def2)->regno,
688 SUBREG_BYTE (ID2WEB (def2)->orig_x));
689 else
690 ra_debug_msg (DUMP_IGRAPH, "%d(%d) ", def2, ID2WEB (def2)->regno);
692 if (num1 != num)
693 ra_debug_msg (DUMP_IGRAPH, "\n ");
695 ra_debug_msg (DUMP_IGRAPH, "\n");
696 for (ml = wl_moves; ml; ml = ml->next)
697 if (ml->move)
699 ra_debug_msg (DUMP_IGRAPH, "move: insn %d: Web %d <-- Web %d\n",
700 INSN_UID (ml->move->insn), ml->move->target_web->id,
701 ml->move->source_web->id);
703 ra_debug_msg (DUMP_WEBS, "\nWebs:\n");
704 for (i = 0; i < num_webs; i++)
706 struct web *web = ID2WEB (i);
708 ra_debug_msg (DUMP_WEBS, " %4d : regno %3d", i, web->regno);
709 if (SUBWEB_P (web))
711 ra_debug_msg (DUMP_WEBS, " sub %d", SUBREG_BYTE (web->orig_x));
712 ra_debug_msg (DUMP_WEBS, " par %d", find_web_for_subweb (web)->id);
714 ra_debug_msg (DUMP_WEBS, " +%d (span %d, cost ",
715 web->add_hardregs, web->span_deaths);
716 ra_debug_msg (DUMP_WEBS, HOST_WIDE_INT_PRINT_DEC, web->spill_cost);
717 ra_debug_msg (DUMP_WEBS, ") (%s)", reg_class_names[web->regclass]);
718 if (web->spill_temp == 1)
719 ra_debug_msg (DUMP_WEBS, " (spilltemp)");
720 else if (web->spill_temp == 2)
721 ra_debug_msg (DUMP_WEBS, " (spilltem2)");
722 else if (web->spill_temp == 3)
723 ra_debug_msg (DUMP_WEBS, " (short)");
724 if (web->type == PRECOLORED)
725 ra_debug_msg (DUMP_WEBS, " (precolored, color=%d)", web->color);
726 else if (find_web_for_subweb (web)->num_uses == 0)
727 ra_debug_msg (DUMP_WEBS, " dead");
728 if (web->crosses_call)
729 ra_debug_msg (DUMP_WEBS, " xcall");
730 if (web->regno >= max_normal_pseudo)
731 ra_debug_msg (DUMP_WEBS, " stack");
732 ra_debug_msg (DUMP_WEBS, "\n");
736 /* Dump the interference graph and webs in a format easily
737 parsable by programs. Used to emit real world interference graph
738 to my custom graph colorizer. */
740 void
741 dump_igraph_machine ()
743 unsigned int i;
745 if (!rtl_dump_file || (debug_new_regalloc & DUMP_IGRAPH_M) == 0)
746 return;
747 ra_debug_msg (DUMP_IGRAPH_M, "g %d %d\n", num_webs - num_subwebs,
748 FIRST_PSEUDO_REGISTER);
749 for (i = 0; i < num_webs - num_subwebs; i++)
751 struct web *web = ID2WEB (i);
752 struct conflict_link *cl;
753 int flags = 0;
754 int numc = 0;
755 int col = 0;
756 flags = web->spill_temp & 0xF;
757 flags |= ((web->type == PRECOLORED) ? 1 : 0) << 4;
758 flags |= (web->add_hardregs & 0xF) << 5;
759 for (cl = web->conflict_list; cl; cl = cl->next)
760 if (cl->t->id < web->id)
761 numc++;
762 ra_debug_msg (DUMP_IGRAPH_M, "n %d %d %d %d %d %d %d\n",
763 web->id, web->color, flags,
764 (unsigned int)web->spill_cost, web->num_defs, web->num_uses,
765 numc);
766 if (web->type != PRECOLORED)
768 ra_debug_msg (DUMP_IGRAPH_M, "s %d", web->id);
769 while (1)
771 unsigned int u = 0;
772 int n;
773 for (n = 0; n < 32 && col < FIRST_PSEUDO_REGISTER; n++, col++)
774 if (TEST_HARD_REG_BIT (web->usable_regs, col))
775 u |= 1 << n;
776 ra_debug_msg (DUMP_IGRAPH_M, " %u", u);
777 if (col >= FIRST_PSEUDO_REGISTER)
778 break;
780 ra_debug_msg (DUMP_IGRAPH_M, "\n");
782 if (numc)
784 ra_debug_msg (DUMP_IGRAPH_M, "c %d", web->id);
785 for (cl = web->conflict_list; cl; cl = cl->next)
787 if (cl->t->id < web->id)
788 ra_debug_msg (DUMP_IGRAPH_M, " %d", cl->t->id);
790 ra_debug_msg (DUMP_IGRAPH_M, "\n");
793 ra_debug_msg (DUMP_IGRAPH_M, "e\n");
796 /* This runs after colorization and changing the insn stream.
797 It temporarily replaces all pseudo registers with their colors,
798 and emits information, if the resulting insns are strictly valid. */
800 void
801 dump_constraints ()
803 rtx insn;
804 int i;
805 if (!rtl_dump_file || (debug_new_regalloc & DUMP_CONSTRAINTS) == 0)
806 return;
807 for (i = FIRST_PSEUDO_REGISTER; i < ra_max_regno; i++)
808 if (regno_reg_rtx[i] && GET_CODE (regno_reg_rtx[i]) == REG)
809 REGNO (regno_reg_rtx[i])
810 = ra_reg_renumber[i] >= 0 ? ra_reg_renumber[i] : i;
811 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
812 if (INSN_P (insn))
814 int code;
815 int uid = INSN_UID (insn);
816 int o;
817 /* Don't simply force rerecognition, as combine might left us
818 with some unrecongnizable ones, which later leads to aborts
819 in regclass, if we now destroy the remembered INSN_CODE(). */
820 /*INSN_CODE (insn) = -1;*/
821 code = recog_memoized (insn);
822 if (code < 0)
824 ra_debug_msg (DUMP_CONSTRAINTS,
825 "%d: asm insn or not recognizable.\n", uid);
826 continue;
828 ra_debug_msg (DUMP_CONSTRAINTS,
829 "%d: code %d {%s}, %d operands, constraints: ",
830 uid, code, insn_data[code].name, recog_data.n_operands);
831 extract_insn (insn);
832 /*preprocess_constraints ();*/
833 for (o = 0; o < recog_data.n_operands; o++)
835 ra_debug_msg (DUMP_CONSTRAINTS,
836 "%d:%s ", o, recog_data.constraints[o]);
838 if (constrain_operands (1))
839 ra_debug_msg (DUMP_CONSTRAINTS, "matches strictly alternative %d",
840 which_alternative);
841 else
842 ra_debug_msg (DUMP_CONSTRAINTS, "doesn't match strictly");
843 ra_debug_msg (DUMP_CONSTRAINTS, "\n");
845 for (i = FIRST_PSEUDO_REGISTER; i < ra_max_regno; i++)
846 if (regno_reg_rtx[i] && GET_CODE (regno_reg_rtx[i]) == REG)
847 REGNO (regno_reg_rtx[i]) = i;
850 /* This counts and emits the cumulated cost of all spilled webs,
851 preceded by a custom message MSG, with debug level LEVEL. */
853 void
854 dump_graph_cost (level, msg)
855 unsigned int level;
856 const char *msg;
858 unsigned int i;
859 unsigned HOST_WIDE_INT cost;
860 if (!rtl_dump_file || (debug_new_regalloc & level) == 0)
861 return;
863 cost = 0;
864 for (i = 0; i < num_webs; i++)
866 struct web *web = id2web[i];
867 if (alias (web)->type == SPILLED)
868 cost += web->orig_spill_cost;
870 ra_debug_msg (level, " spill cost of graph (%s) = ", msg ? msg : "");
871 ra_debug_msg (level, HOST_WIDE_INT_PRINT_UNSIGNED, cost);
872 ra_debug_msg (level, "\n");
875 /* Dump the color assignment per web, the coalesced and spilled webs. */
877 void
878 dump_ra (df)
879 struct df *df ATTRIBUTE_UNUSED;
881 struct web *web;
882 struct dlist *d;
883 if (!rtl_dump_file || (debug_new_regalloc & DUMP_RESULTS) == 0)
884 return;
886 ra_debug_msg (DUMP_RESULTS, "\nColored:\n");
887 for (d = WEBS(COLORED); d; d = d->next)
889 web = DLIST_WEB (d);
890 ra_debug_msg (DUMP_RESULTS, " %4d : color %d\n", web->id, web->color);
892 ra_debug_msg (DUMP_RESULTS, "\nCoalesced:\n");
893 for (d = WEBS(COALESCED); d; d = d->next)
895 web = DLIST_WEB (d);
896 ra_debug_msg (DUMP_RESULTS, " %4d : to web %d, color %d\n", web->id,
897 alias (web)->id, web->color);
899 ra_debug_msg (DUMP_RESULTS, "\nSpilled:\n");
900 for (d = WEBS(SPILLED); d; d = d->next)
902 web = DLIST_WEB (d);
903 ra_debug_msg (DUMP_RESULTS, " %4d\n", web->id);
905 ra_debug_msg (DUMP_RESULTS, "\n");
906 dump_cost (DUMP_RESULTS);
909 /* Calculate and dump the cumulated costs of certain types of insns
910 (loads, stores and copies). */
912 void
913 dump_static_insn_cost (file, message, prefix)
914 FILE *file;
915 const char *message;
916 const char *prefix;
918 struct cost
920 unsigned HOST_WIDE_INT cost;
921 unsigned int count;
923 basic_block bb;
924 struct cost load, store, regcopy, selfcopy, overall;
925 memset (&load, 0, sizeof(load));
926 memset (&store, 0, sizeof(store));
927 memset (&regcopy, 0, sizeof(regcopy));
928 memset (&selfcopy, 0, sizeof(selfcopy));
929 memset (&overall, 0, sizeof(overall));
931 if (!file)
932 return;
934 FOR_EACH_BB (bb)
936 unsigned HOST_WIDE_INT block_cost = bb->frequency;
937 rtx insn, set;
938 for (insn = bb->head; insn; insn = NEXT_INSN (insn))
940 /* Yes, yes. We don't calculate the costs precisely.
941 Only for "simple enough" insns. Those containing single
942 sets only. */
943 if (INSN_P (insn) && ((set = single_set (insn)) != NULL))
945 rtx src = SET_SRC (set);
946 rtx dest = SET_DEST (set);
947 struct cost *pcost = NULL;
948 overall.cost += block_cost;
949 overall.count++;
950 if (rtx_equal_p (src, dest))
951 pcost = &selfcopy;
952 else if (GET_CODE (src) == GET_CODE (dest)
953 && ((GET_CODE (src) == REG)
954 || (GET_CODE (src) == SUBREG
955 && GET_CODE (SUBREG_REG (src)) == REG
956 && GET_CODE (SUBREG_REG (dest)) == REG)))
957 pcost = &regcopy;
958 else
960 if (GET_CODE (src) == SUBREG)
961 src = SUBREG_REG (src);
962 if (GET_CODE (dest) == SUBREG)
963 dest = SUBREG_REG (dest);
964 if (GET_CODE (src) == MEM && GET_CODE (dest) != MEM
965 && memref_is_stack_slot (src))
966 pcost = &load;
967 else if (GET_CODE (src) != MEM && GET_CODE (dest) == MEM
968 && memref_is_stack_slot (dest))
969 pcost = &store;
971 if (pcost)
973 pcost->cost += block_cost;
974 pcost->count++;
977 if (insn == bb->end)
978 break;
982 if (!prefix)
983 prefix = "";
984 fprintf (file, "static insn cost %s\n", message ? message : "");
985 fprintf (file, " %soverall:\tnum=%6d\tcost=", prefix, overall.count);
986 fprintf (file, HOST_WIDE_INT_PRINT_DEC_SPACE, 8, overall.cost);
987 fprintf (file, "\n");
988 fprintf (file, " %sloads:\tnum=%6d\tcost=", prefix, load.count);
989 fprintf (file, HOST_WIDE_INT_PRINT_DEC_SPACE, 8, load.cost);
990 fprintf (file, "\n");
991 fprintf (file, " %sstores:\tnum=%6d\tcost=", prefix, store.count);
992 fprintf (file, HOST_WIDE_INT_PRINT_DEC_SPACE, 8, store.cost);
993 fprintf (file, "\n");
994 fprintf (file, " %sregcopy:\tnum=%6d\tcost=", prefix, regcopy.count);
995 fprintf (file, HOST_WIDE_INT_PRINT_DEC_SPACE, 8, regcopy.cost);
996 fprintf (file, "\n");
997 fprintf (file, " %sselfcpy:\tnum=%6d\tcost=", prefix, selfcopy.count);
998 fprintf (file, HOST_WIDE_INT_PRINT_DEC_SPACE, 8, selfcopy.cost);
999 fprintf (file, "\n");
1002 /* Returns nonzero, if WEB1 and WEB2 have some possible
1003 hardregs in common. */
1006 web_conflicts_p (web1, web2)
1007 struct web *web1;
1008 struct web *web2;
1010 if (web1->type == PRECOLORED && web2->type == PRECOLORED)
1011 return 0;
1013 if (web1->type == PRECOLORED)
1014 return TEST_HARD_REG_BIT (web2->usable_regs, web1->regno);
1016 if (web2->type == PRECOLORED)
1017 return TEST_HARD_REG_BIT (web1->usable_regs, web2->regno);
1019 return hard_regs_intersect_p (&web1->usable_regs, &web2->usable_regs);
1022 /* Dump all uids of insns in which WEB is mentioned. */
1024 void
1025 dump_web_insns (web)
1026 struct web *web;
1028 unsigned int i;
1030 ra_debug_msg (DUMP_EVER, "Web: %i(%i)+%i class: %s freedom: %i degree %i\n",
1031 web->id, web->regno, web->add_hardregs,
1032 reg_class_names[web->regclass],
1033 web->num_freedom, web->num_conflicts);
1034 ra_debug_msg (DUMP_EVER, " def insns:");
1036 for (i = 0; i < web->num_defs; ++i)
1038 ra_debug_msg (DUMP_EVER, " %d ", INSN_UID (web->defs[i]->insn));
1041 ra_debug_msg (DUMP_EVER, "\n use insns:");
1042 for (i = 0; i < web->num_uses; ++i)
1044 ra_debug_msg (DUMP_EVER, " %d ", INSN_UID (web->uses[i]->insn));
1046 ra_debug_msg (DUMP_EVER, "\n");
1049 /* Dump conflicts for web WEB. */
1051 void
1052 dump_web_conflicts (web)
1053 struct web *web;
1055 int num = 0;
1056 unsigned int def2;
1058 ra_debug_msg (DUMP_EVER, "Web: %i(%i)+%i class: %s freedom: %i degree %i\n",
1059 web->id, web->regno, web->add_hardregs,
1060 reg_class_names[web->regclass],
1061 web->num_freedom, web->num_conflicts);
1063 for (def2 = 0; def2 < num_webs; def2++)
1064 if (TEST_BIT (igraph, igraph_index (web->id, def2)) && web->id != def2)
1066 if ((num % 9) == 5)
1067 ra_debug_msg (DUMP_EVER, "\n ");
1068 num++;
1070 ra_debug_msg (DUMP_EVER, " %d(%d)", def2, id2web[def2]->regno);
1071 if (id2web[def2]->add_hardregs)
1072 ra_debug_msg (DUMP_EVER, "+%d", id2web[def2]->add_hardregs);
1074 if (web_conflicts_p (web, id2web[def2]))
1075 ra_debug_msg (DUMP_EVER, "/x");
1077 if (id2web[def2]->type == SELECT)
1078 ra_debug_msg (DUMP_EVER, "/s");
1080 if (id2web[def2]->type == COALESCED)
1081 ra_debug_msg (DUMP_EVER,"/c/%d", alias (id2web[def2])->id);
1083 ra_debug_msg (DUMP_EVER, "\n");
1085 struct conflict_link *wl;
1086 num = 0;
1087 ra_debug_msg (DUMP_EVER, "By conflicts: ");
1088 for (wl = web->conflict_list; wl; wl = wl->next)
1090 struct web* w = wl->t;
1091 if ((num % 9) == 8)
1092 ra_debug_msg (DUMP_EVER, "\n ");
1093 num++;
1094 ra_debug_msg (DUMP_EVER, "%d(%d)%s ", w->id, w->regno,
1095 web_conflicts_p (web, w) ? "+" : "");
1097 ra_debug_msg (DUMP_EVER, "\n");
1101 /* Output HARD_REG_SET to stderr. */
1103 void
1104 debug_hard_reg_set (set)
1105 HARD_REG_SET set;
1107 int i;
1108 for (i=0; i < FIRST_PSEUDO_REGISTER; ++i)
1110 if (TEST_HARD_REG_BIT (set, i))
1112 fprintf (stderr, "%s ", reg_names[i]);
1115 fprintf (stderr, "\n");
1119 vim:cinoptions={.5s,g0,p5,t0,(0,^-0.5s,n-0.5s:tw=78:cindent:sw=4: