]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/ra-debug.c
alias.c (nonlocal_mentioned_p, [...]): Use, LABEL_P, JUMP_P, CALL_P, NONJUMP_INSN_P...
[thirdparty/gcc.git] / gcc / ra-debug.c
CommitLineData
ed8d2920 1/* Graph coloring register allocator
ec8e098d 2 Copyright (C) 2001, 2002, 2004 Free Software Foundation, Inc.
ed8d2920
MM
3 Contributed by Michael Matz <matz@suse.de>
4 and Daniel Berlin <dan@cgsoftware.com>.
5
6 This file is part of GCC.
7
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.
11
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.
16
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. */
20
21#include "config.h"
22#include "system.h"
4977bab6
ZW
23#include "coretypes.h"
24#include "tm.h"
ed8d2920
MM
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"
a6be5aee 34#include "tm_p.h"
66fd46b6 35#include "regs.h"
ed8d2920
MM
36
37/* This file contains various dumping and debug functions for
38 the graph coloring register allocator. */
39
93bad80e
SB
40static void ra_print_rtx_1op (FILE *, rtx);
41static void ra_print_rtx_2op (FILE *, rtx);
42static void ra_print_rtx_3op (FILE *, rtx);
43static void ra_print_rtx_object (FILE *, rtx);
ed8d2920
MM
44
45/* The hardregs as names, for debugging. */
46static const char *const reg_class_names[] = REG_CLASS_NAMES;
47
48/* Print a message to the dump file, if debug_new_regalloc and LEVEL
49 have any bits in common. */
50
51void
e34d07f2 52ra_debug_msg (unsigned int level, const char *format, ...)
ed8d2920 53{
e34d07f2
KG
54 va_list ap;
55
56 va_start (ap, format);
c263766c
RH
57 if ((debug_new_regalloc & level) != 0 && dump_file != NULL)
58 vfprintf (dump_file, format, ap);
e34d07f2 59 va_end (ap);
ed8d2920
MM
60}
61
62
63/* The following ra_print_xxx() functions print RTL expressions
64 in concise infix form. If the mode can be seen from context it's
65 left out. Most operators are represented by their graphical
66 characters, e.g. LE as "<=". Unknown constructs are currently
67 printed with print_inline_rtx(), which disrupts the nice layout.
68 Currently only the inline asm things are written this way. */
69
70/* Print rtx X, which is a one operand rtx (op:mode (Y)), as
71 "op(Y)" to FILE. */
72
73static void
93bad80e 74ra_print_rtx_1op (FILE *file, rtx x)
ed8d2920
MM
75{
76 enum rtx_code code = GET_CODE (x);
77 rtx op0 = XEXP (x, 0);
78 switch (code)
79 {
80 case NEG:
81 case NOT:
82 fputs ((code == NEG) ? "-(" : "~(", file);
83 ra_print_rtx (file, op0, 0);
84 fputs (")", file);
85 break;
86 case HIGH:
87 fputs ("hi(", file);
88 ra_print_rtx (file, op0, 0);
89 fputs (")", file);
90 break;
91 default:
92 fprintf (file, "%s", GET_RTX_NAME (code));
93 if (GET_MODE (x) != VOIDmode)
94 fprintf (file, ":%s(", GET_MODE_NAME (GET_MODE (x)));
95 else
96 fputs ("(", file);
97 ra_print_rtx (file, op0, 0);
98 fputs (")", file);
99 break;
100 }
101}
102
103/* Print rtx X, which is a two operand rtx (op:mode (Y) (Z))
104 as "(Y op Z)", if the operand is know, or as "op(Y, Z)", if not,
105 to FILE. */
106
107static void
93bad80e 108ra_print_rtx_2op (FILE *file, rtx x)
ed8d2920
MM
109{
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)
116 {
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;
ec8e098d 133 /* class '=' */
ed8d2920
MM
134 case NE: opname = "!="; break;
135 case EQ: opname = "=="; break;
ec8e098d
PB
136 case LTGT: opname = "<>"; break;
137 /* class '<' */
ed8d2920
MM
138 case GE: opname = "s>="; break;
139 case GT: opname = "s>"; break;
140 case LE: opname = "s<="; break;
141 case LT: opname = "s<"; break;
142 case GEU: opname = "u>="; break;
143 case GTU: opname = "u>"; break;
144 case LEU: opname = "u<="; break;
145 case LTU: opname = "u<"; break;
146 default:
147 infix = 0;
148 opname = GET_RTX_NAME (code);
149 break;
150 }
151 if (infix)
152 {
153 fputs ("(", file);
154 ra_print_rtx (file, op0, 0);
155 fprintf (file, " %s ", opname);
156 ra_print_rtx (file, op1, 0);
157 fputs (")", file);
158 }
159 else
160 {
161 fprintf (file, "%s(", opname);
162 ra_print_rtx (file, op0, 0);
163 fputs (", ", file);
164 ra_print_rtx (file, op1, 0);
165 fputs (")", file);
166 }
167}
168
169/* Print rtx X, which a three operand rtx to FILE.
170 I.e. X is either an IF_THEN_ELSE, or a bitmap operation. */
171
172static void
93bad80e 173ra_print_rtx_3op (FILE *file, rtx x)
ed8d2920
MM
174{
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)
180 {
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);
186 }
187 else
188 {
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);
198 }
199}
200
ec8e098d 201/* Print rtx X, which represents an object (class 'o', 'C', or some constructs
ed8d2920
MM
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. */
206
207static void
93bad80e 208ra_print_rtx_object (FILE *file, rtx x)
ed8d2920
MM
209{
210 enum rtx_code code = GET_CODE (x);
211 enum machine_mode mode = GET_MODE (x);
212 switch (code)
213 {
214 case CONST_INT:
215 fprintf (file, HOST_WIDE_INT_PRINT_DEC, XWINT (x, 0));
216 break;
217 case CONST_DOUBLE:
218 {
219 int i, num = 0;
220 const char *fmt = GET_RTX_FORMAT (code);
221 fputs ("dbl(", file);
222 for (i = 0; i < GET_RTX_LENGTH (code); i++)
223 {
224 if (num)
225 fputs (", ", file);
226 if (fmt[i] == 'e' && XEXP (x, i))
227 /* The MEM or other stuff */
228 {
229 ra_print_rtx (file, XEXP (x, i), 0);
230 num++;
231 }
232 else if (fmt[i] == 'w')
233 {
234 fprintf (file, HOST_WIDE_INT_PRINT_HEX, XWINT (x, i));
235 num++;
236 }
237 }
238 break;
239 }
240 case CONST_STRING: fprintf (file, "\"%s\"", XSTR (x, 0)); break;
241 case CONST: fputs ("const(", file);
242 ra_print_rtx (file, XEXP (x, 0), 0);
243 fputs (")", file);
244 break;
245 case PC: fputs ("pc", file); break;
246 case REG:
247 {
248 int regno = REGNO (x);
249 if (regno < FIRST_PSEUDO_REGISTER)
250 {
66fd46b6 251 int i, nregs = hard_regno_nregs[regno][mode];
ed8d2920
MM
252 if (nregs > 1)
253 fputs ("[", file);
254 for (i = 0; i < nregs; i++)
255 {
256 if (i)
257 fputs (", ", file);
258 if (reg_names[regno+i] && *reg_names[regno + i])
259 fprintf (file, "%s", reg_names[regno + i]);
260 else
261 fprintf (file, "h%d", regno + i);
262 }
263 if (nregs > 1)
264 fputs ("]", file);
265 }
266 else
267 fprintf (file, "p%d", regno);
268 break;
269 }
270 case SUBREG:
271 {
272 rtx sub = SUBREG_REG (x);
273 int ofs = SUBREG_BYTE (x);
f8cfc6aa 274 if (REG_P (sub)
ed8d2920
MM
275 && REGNO (sub) < FIRST_PSEUDO_REGISTER)
276 {
277 int regno = REGNO (sub);
66fd46b6 278 int i, nregs = hard_regno_nregs[regno][mode];
ed8d2920
MM
279 regno += subreg_regno_offset (regno, GET_MODE (sub),
280 ofs, mode);
281 if (nregs > 1)
282 fputs ("[", file);
283 for (i = 0; i < nregs; i++)
284 {
285 if (i)
286 fputs (", ", file);
287 if (reg_names[regno+i])
288 fprintf (file, "%s", reg_names[regno + i]);
289 else
290 fprintf (file, "h%d", regno + i);
291 }
292 if (nregs > 1)
293 fputs ("]", file);
294 }
295 else
296 {
297 ra_print_rtx (file, sub, 0);
298 fprintf (file, ":[%s+%d]", GET_MODE_NAME (mode), ofs);
299 }
300 break;
301 }
302 case SCRATCH: fputs ("scratch", file); break;
303 case CONCAT: ra_print_rtx_2op (file, x); break;
304 case HIGH: ra_print_rtx_1op (file, x); break;
305 case LO_SUM:
306 fputs ("(", file);
307 ra_print_rtx (file, XEXP (x, 0), 0);
308 fputs (" + lo(", file);
309 ra_print_rtx (file, XEXP (x, 1), 0);
310 fputs ("))", file);
311 break;
312 case MEM: fputs ("[", file);
313 ra_print_rtx (file, XEXP (x, 0), 0);
314 fprintf (file, "]:%s", GET_MODE_NAME (GET_MODE (x)));
315 /* XXX print alias set too ?? */
316 break;
317 case LABEL_REF:
318 {
319 rtx sub = XEXP (x, 0);
4b4bf941 320 if (NOTE_P (sub)
ed8d2920
MM
321 && NOTE_LINE_NUMBER (sub) == NOTE_INSN_DELETED_LABEL)
322 fprintf (file, "(deleted uid=%d)", INSN_UID (sub));
4b4bf941 323 else if (LABEL_P (sub))
ed8d2920
MM
324 fprintf (file, "L%d", CODE_LABEL_NUMBER (sub));
325 else
326 fprintf (file, "(nonlabel uid=%d)", INSN_UID (sub));
327 }
328 break;
329 case SYMBOL_REF:
330 fprintf (file, "sym(\"%s\")", XSTR (x, 0)); break;
331 case CC0: fputs ("cc0", file); break;
332 default: print_inline_rtx (file, x, 0); break;
333 }
334}
335
336/* Print a general rtx X to FILE in nice infix form.
337 If WITH_PN is set, and X is one of the toplevel constructs
338 (insns, notes, labels or barriers), then print also the UIDs of
339 the preceding and following insn. */
340
341void
93bad80e 342ra_print_rtx (FILE *file, rtx x, int with_pn)
ed8d2920
MM
343{
344 enum rtx_code code;
ed8d2920
MM
345 int unhandled = 0;
346 if (!x)
347 return;
348 code = GET_CODE (x);
ed8d2920
MM
349
350 /* First handle the insn like constructs. */
351 if (INSN_P (x) || code == NOTE || code == CODE_LABEL || code == BARRIER)
352 {
353 if (INSN_P (x))
354 fputs (" ", file);
355 /* Non-insns are prefixed by a ';'. */
356 if (code == BARRIER)
357 fputs ("; ", file);
358 else if (code == NOTE)
359 /* But notes are indented very far right. */
360 fprintf (file, "\t\t\t\t\t; ");
361 else if (code == CODE_LABEL)
362 /* And labels have their Lxx name first, before the actual UID. */
363 {
364 fprintf (file, "L%d:\t; ", CODE_LABEL_NUMBER (x));
365 if (LABEL_NAME (x))
366 fprintf (file, "(%s) ", LABEL_NAME (x));
0dc36574
ZW
367 switch (LABEL_KIND (x))
368 {
369 case LABEL_NORMAL: break;
370 case LABEL_STATIC_ENTRY: fputs (" (entry)", file); break;
371 case LABEL_GLOBAL_ENTRY: fputs (" (global entry)", file); break;
372 case LABEL_WEAK_ENTRY: fputs (" (weak entry)", file); break;
373 default: abort();
374 }
ed8d2920
MM
375 fprintf (file, " [%d uses] uid=(", LABEL_NUSES (x));
376 }
377 fprintf (file, "%d", INSN_UID (x));
378 if (with_pn)
379 fprintf (file, " %d %d", PREV_INSN (x) ? INSN_UID (PREV_INSN (x)) : 0,
380 NEXT_INSN (x) ? INSN_UID (NEXT_INSN (x)) : 0);
381 if (code == BARRIER)
382 fputs (" -------- barrier ---------", file);
383 else if (code == CODE_LABEL)
384 fputs (")", file);
385 else if (code == NOTE)
386 {
387 int ln = NOTE_LINE_NUMBER (x);
388 if (ln >= (int) NOTE_INSN_BIAS && ln < (int) NOTE_INSN_MAX)
389 fprintf (file, " %s", GET_NOTE_INSN_NAME (ln));
390 else
391 {
9506ac2b
PB
392 expanded_location s;
393 NOTE_EXPANDED_LOCATION (s, x);
394 fprintf (file, " line %d", s.line);
395 if (s.file != NULL)
396 fprintf (file, ":%s", s.file);
ed8d2920
MM
397 }
398 }
399 else
400 {
401 fprintf (file, "\t");
402 ra_print_rtx (file, PATTERN (x), 0);
403 }
404 return;
405 }
406 switch (code)
407 {
408 /* Top-level stuff. */
409 case PARALLEL:
410 {
411 int j;
412 for (j = 0; j < XVECLEN (x, 0); j++)
413 {
414 if (j)
415 fputs ("\t;; ", file);
416 ra_print_rtx (file, XVECEXP (x, 0, j), 0);
417 }
418 break;
419 }
420 case UNSPEC: case UNSPEC_VOLATILE:
421 {
422 int j;
423 fprintf (file, "unspec%s(%d",
424 (code == UNSPEC) ? "" : "_vol", XINT (x, 1));
425 for (j = 0; j < XVECLEN (x, 0); j++)
426 {
427 fputs (", ", file);
428 ra_print_rtx (file, XVECEXP (x, 0, j), 0);
429 }
430 fputs (")", file);
431 break;
432 }
433 case SET:
434 if (GET_CODE (SET_DEST (x)) == PC)
435 {
436 if (GET_CODE (SET_SRC (x)) == IF_THEN_ELSE
437 && GET_CODE (XEXP (SET_SRC(x), 2)) == PC)
438 {
439 fputs ("if ", file);
440 ra_print_rtx (file, XEXP (SET_SRC (x), 0), 0);
441 fputs (" jump ", file);
442 ra_print_rtx (file, XEXP (SET_SRC (x), 1), 0);
443 }
444 else
445 {
446 fputs ("jump ", file);
447 ra_print_rtx (file, SET_SRC (x), 0);
448 }
449 }
450 else
451 {
452 ra_print_rtx (file, SET_DEST (x), 0);
453 fputs (" <= ", file);
454 ra_print_rtx (file, SET_SRC (x), 0);
455 }
456 break;
457 case USE:
458 fputs ("use <= ", file);
459 ra_print_rtx (file, XEXP (x, 0), 0);
460 break;
461 case CLOBBER:
462 ra_print_rtx (file, XEXP (x, 0), 0);
463 fputs (" <= clobber", file);
464 break;
465 case CALL:
466 fputs ("call ", file);
467 ra_print_rtx (file, XEXP (x, 0), 0); /* Address */
468 fputs (" numargs=", file);
469 ra_print_rtx (file, XEXP (x, 1), 0); /* Num arguments */
470 break;
471 case RETURN:
472 fputs ("return", file);
473 break;
474 case TRAP_IF:
475 fputs ("if (", file);
476 ra_print_rtx (file, XEXP (x, 0), 0);
477 fputs (") trap ", file);
478 ra_print_rtx (file, XEXP (x, 1), 0);
479 break;
480 case RESX:
481 fprintf (file, "resx from region %d", XINT (x, 0));
482 break;
483
484 /* Different things of class 'x' */
485 case SUBREG: ra_print_rtx_object (file, x); break;
486 case STRICT_LOW_PART:
487 fputs ("low(", file);
488 ra_print_rtx (file, XEXP (x, 0), 0);
489 fputs (")", file);
490 break;
491 default:
492 unhandled = 1;
493 break;
494 }
495 if (!unhandled)
496 return;
ec8e098d
PB
497 switch (GET_RTX_CLASS (code))
498 {
499 case RTX_UNARY:
c87fbb0a
PH
500 ra_print_rtx_1op (file, x);
501 break;
ec8e098d
PB
502 case RTX_BIN_ARITH:
503 case RTX_COMM_ARITH:
504 case RTX_COMPARE:
505 case RTX_COMM_COMPARE:
c87fbb0a
PH
506 ra_print_rtx_2op (file, x);
507 break;
ec8e098d
PB
508 case RTX_TERNARY:
509 case RTX_BITFIELD_OPS:
c87fbb0a
PH
510 ra_print_rtx_3op (file, x);
511 break;
ec8e098d
PB
512 case RTX_OBJ:
513 case RTX_CONST_OBJ:
c87fbb0a
PH
514 ra_print_rtx_object (file, x);
515 break;
ec8e098d 516 default:
c87fbb0a
PH
517 print_inline_rtx (file, x, 0);
518 break;
ec8e098d 519 }
ed8d2920
MM
520}
521
522/* This only calls ra_print_rtx(), but emits a final newline. */
523
524void
93bad80e 525ra_print_rtx_top (FILE *file, rtx x, int with_pn)
ed8d2920
MM
526{
527 ra_print_rtx (file, x, with_pn);
528 fprintf (file, "\n");
529}
530
531/* Callable from gdb. This prints rtx X onto stderr. */
532
533void
93bad80e 534ra_debug_rtx (rtx x)
ed8d2920
MM
535{
536 ra_print_rtx_top (stderr, x, 1);
537}
538
539/* This prints the content of basic block with index BBI.
540 The first and last insn are emitted with UIDs of prev and next insns. */
541
542void
93bad80e 543ra_debug_bbi (int bbi)
ed8d2920
MM
544{
545 basic_block bb = BASIC_BLOCK (bbi);
546 rtx insn;
a813c111 547 for (insn = BB_HEAD (bb); insn; insn = NEXT_INSN (insn))
ed8d2920 548 {
a813c111
SB
549 ra_print_rtx_top (stderr, insn,
550 (insn == BB_HEAD (bb) || insn == BB_END (bb)));
ed8d2920 551 fprintf (stderr, "\n");
a813c111 552 if (insn == BB_END (bb))
ed8d2920
MM
553 break;
554 }
555}
556
557/* Beginning from INSN, emit NUM insns (if NUM is non-negative)
558 or emit a window of NUM insns around INSN, to stderr. */
559
560void
93bad80e 561ra_debug_insns (rtx insn, int num)
ed8d2920
MM
562{
563 int i, count = (num == 0 ? 1 : num < 0 ? -num : num);
564 if (num < 0)
565 for (i = count / 2; i > 0 && PREV_INSN (insn); i--)
566 insn = PREV_INSN (insn);
567 for (i = count; i > 0 && insn; insn = NEXT_INSN (insn), i--)
568 {
4b4bf941 569 if (LABEL_P (insn))
ed8d2920
MM
570 fprintf (stderr, "\n");
571 ra_print_rtx_top (stderr, insn, (i == count || i == 1));
572 }
573}
574
575/* Beginning with INSN, emit the whole insn chain into FILE.
576 This also outputs comments when basic blocks start or end and omits
577 some notes, if flag_ra_dump_notes is zero. */
578
579void
93bad80e 580ra_print_rtl_with_bb (FILE *file, rtx insn)
ed8d2920
MM
581{
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))
588 {
4b4bf941 589 if (BARRIER_P (insn))
ed8d2920
MM
590 bb = NULL;
591 else
592 bb = BLOCK_FOR_INSN (insn);
593 if (bb != last_bb)
594 {
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;
600 }
4b4bf941 601 if (LABEL_P (insn))
ed8d2920 602 fputc ('\n', file);
4b4bf941 603 if (NOTE_P (insn))
ed8d2920
MM
604 {
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))
611 {
612 ra_print_rtx_top (file, insn, (num == 0 || !NEXT_INSN (insn)));
613 num++;
614 }
615 }
616 else
617 {
618 ra_print_rtx_top (file, insn, (num == 0 || !NEXT_INSN (insn)));
619 num++;
620 }
621 }
622}
623
624/* Count how many insns were seen how often, while building the interference
625 graph, and prints the findings. */
626
627void
93bad80e 628dump_number_seen (void)
ed8d2920
MM
629{
630#define N 17
631 int num[N];
632 int i;
633
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
649}
650
651/* Dump the interference graph, the move list and the webs. */
652
653void
93bad80e 654dump_igraph (struct df *df ATTRIBUTE_UNUSED)
ed8d2920
MM
655{
656 struct move_list *ml;
657 unsigned int def1, def2;
658 int num = 0;
659 int num2;
660 unsigned int i;
c263766c 661 if (!dump_file || (debug_new_regalloc & (DUMP_IGRAPH | DUMP_WEBS)) == 0)
ed8d2920
MM
662 return;
663 ra_debug_msg (DUMP_IGRAPH, "conflicts:\n ");
664 for (def1 = 0; def1 < num_webs; def1++)
665 {
666 int num1 = num;
6a87d634
RS
667 num2 = 0;
668 for (def2 = 0; def2 < num_webs; def2++)
ed8d2920
MM
669 if (def1 != def2 && TEST_BIT (igraph, igraph_index (def1, def2)))
670 {
671 if (num1 == num)
672 {
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);
680 }
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);
690 }
691 if (num1 != num)
692 ra_debug_msg (DUMP_IGRAPH, "\n ");
693 }
694 ra_debug_msg (DUMP_IGRAPH, "\n");
695 for (ml = wl_moves; ml; ml = ml->next)
696 if (ml->move)
697 {
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);
701 }
702 ra_debug_msg (DUMP_WEBS, "\nWebs:\n");
703 for (i = 0; i < num_webs; i++)
704 {
705 struct web *web = ID2WEB (i);
706
707 ra_debug_msg (DUMP_WEBS, " %4d : regno %3d", i, web->regno);
708 if (SUBWEB_P (web))
709 {
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);
712 }
90ff44cf
KG
713 ra_debug_msg (DUMP_WEBS, " +%d (span %d, cost "
714 HOST_WIDE_INT_PRINT_DEC ") (%s)",
715 web->add_hardregs, web->span_deaths, web->spill_cost,
716 reg_class_names[web->regclass]);
ed8d2920
MM
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");
732 }
733}
734
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. */
738
739void
93bad80e 740dump_igraph_machine (void)
ed8d2920
MM
741{
742 unsigned int i;
743
c263766c 744 if (!dump_file || (debug_new_regalloc & DUMP_IGRAPH_M) == 0)
ed8d2920
MM
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++)
749 {
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)
766 {
767 ra_debug_msg (DUMP_IGRAPH_M, "s %d", web->id);
768 while (1)
769 {
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;
778 }
779 ra_debug_msg (DUMP_IGRAPH_M, "\n");
780 }
781 if (numc)
782 {
783 ra_debug_msg (DUMP_IGRAPH_M, "c %d", web->id);
784 for (cl = web->conflict_list; cl; cl = cl->next)
785 {
786 if (cl->t->id < web->id)
787 ra_debug_msg (DUMP_IGRAPH_M, " %d", cl->t->id);
788 }
789 ra_debug_msg (DUMP_IGRAPH_M, "\n");
790 }
791 }
792 ra_debug_msg (DUMP_IGRAPH_M, "e\n");
793}
794
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. */
798
799void
93bad80e 800dump_constraints (void)
ed8d2920
MM
801{
802 rtx insn;
803 int i;
c263766c 804 if (!dump_file || (debug_new_regalloc & DUMP_CONSTRAINTS) == 0)
ed8d2920
MM
805 return;
806 for (i = FIRST_PSEUDO_REGISTER; i < ra_max_regno; i++)
f8cfc6aa 807 if (regno_reg_rtx[i] && REG_P (regno_reg_rtx[i]))
ed8d2920
MM
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))
812 {
813 int code;
814 int uid = INSN_UID (insn);
815 int o;
816 /* Don't simply force rerecognition, as combine might left us
d55d8fc7 817 with some unrecognizable ones, which later leads to aborts
ed8d2920
MM
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)
822 {
823 ra_debug_msg (DUMP_CONSTRAINTS,
824 "%d: asm insn or not recognizable.\n", uid);
825 continue;
826 }
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++)
833 {
834 ra_debug_msg (DUMP_CONSTRAINTS,
835 "%d:%s ", o, recog_data.constraints[o]);
836 }
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");
843 }
844 for (i = FIRST_PSEUDO_REGISTER; i < ra_max_regno; i++)
f8cfc6aa 845 if (regno_reg_rtx[i] && REG_P (regno_reg_rtx[i]))
ed8d2920
MM
846 REGNO (regno_reg_rtx[i]) = i;
847}
848
849/* This counts and emits the cumulated cost of all spilled webs,
850 preceded by a custom message MSG, with debug level LEVEL. */
851
852void
93bad80e 853dump_graph_cost (unsigned int level, const char *msg)
ed8d2920
MM
854{
855 unsigned int i;
856 unsigned HOST_WIDE_INT cost;
c263766c 857 if (!dump_file || (debug_new_regalloc & level) == 0)
ed8d2920
MM
858 return;
859
860 cost = 0;
861 for (i = 0; i < num_webs; i++)
862 {
863 struct web *web = id2web[i];
864 if (alias (web)->type == SPILLED)
865 cost += web->orig_spill_cost;
866 }
90ff44cf
KG
867 ra_debug_msg (level, " spill cost of graph (%s) = "
868 HOST_WIDE_INT_PRINT_UNSIGNED "\n",
869 msg ? msg : "", cost);
ed8d2920
MM
870}
871
872/* Dump the color assignment per web, the coalesced and spilled webs. */
873
874void
93bad80e 875dump_ra (struct df *df ATTRIBUTE_UNUSED)
ed8d2920
MM
876{
877 struct web *web;
878 struct dlist *d;
c263766c 879 if (!dump_file || (debug_new_regalloc & DUMP_RESULTS) == 0)
ed8d2920
MM
880 return;
881
882 ra_debug_msg (DUMP_RESULTS, "\nColored:\n");
883 for (d = WEBS(COLORED); d; d = d->next)
884 {
885 web = DLIST_WEB (d);
886 ra_debug_msg (DUMP_RESULTS, " %4d : color %d\n", web->id, web->color);
887 }
888 ra_debug_msg (DUMP_RESULTS, "\nCoalesced:\n");
889 for (d = WEBS(COALESCED); d; d = d->next)
890 {
891 web = DLIST_WEB (d);
892 ra_debug_msg (DUMP_RESULTS, " %4d : to web %d, color %d\n", web->id,
893 alias (web)->id, web->color);
894 }
895 ra_debug_msg (DUMP_RESULTS, "\nSpilled:\n");
896 for (d = WEBS(SPILLED); d; d = d->next)
897 {
898 web = DLIST_WEB (d);
899 ra_debug_msg (DUMP_RESULTS, " %4d\n", web->id);
900 }
901 ra_debug_msg (DUMP_RESULTS, "\n");
902 dump_cost (DUMP_RESULTS);
903}
904
905/* Calculate and dump the cumulated costs of certain types of insns
906 (loads, stores and copies). */
907
908void
93bad80e 909dump_static_insn_cost (FILE *file, const char *message, const char *prefix)
ed8d2920
MM
910{
911 struct cost
912 {
913 unsigned HOST_WIDE_INT cost;
914 unsigned int count;
915 };
ed8d2920 916 basic_block bb;
533c4863
KG
917 struct cost load, store, regcopy, selfcopy, overall;
918 memset (&load, 0, sizeof(load));
919 memset (&store, 0, sizeof(store));
920 memset (&regcopy, 0, sizeof(regcopy));
921 memset (&selfcopy, 0, sizeof(selfcopy));
922 memset (&overall, 0, sizeof(overall));
ed8d2920
MM
923
924 if (!file)
925 return;
926
927 FOR_EACH_BB (bb)
928 {
929 unsigned HOST_WIDE_INT block_cost = bb->frequency;
930 rtx insn, set;
a813c111 931 for (insn = BB_HEAD (bb); insn; insn = NEXT_INSN (insn))
ed8d2920
MM
932 {
933 /* Yes, yes. We don't calculate the costs precisely.
934 Only for "simple enough" insns. Those containing single
935 sets only. */
936 if (INSN_P (insn) && ((set = single_set (insn)) != NULL))
937 {
938 rtx src = SET_SRC (set);
939 rtx dest = SET_DEST (set);
940 struct cost *pcost = NULL;
941 overall.cost += block_cost;
942 overall.count++;
943 if (rtx_equal_p (src, dest))
944 pcost = &selfcopy;
945 else if (GET_CODE (src) == GET_CODE (dest)
f8cfc6aa 946 && ((REG_P (src))
ed8d2920 947 || (GET_CODE (src) == SUBREG
f8cfc6aa
JQ
948 && REG_P (SUBREG_REG (src))
949 && REG_P (SUBREG_REG (dest)))))
950 /* XXX is dest guaranteed to be a subreg? */
ed8d2920
MM
951 pcost = &regcopy;
952 else
953 {
954 if (GET_CODE (src) == SUBREG)
955 src = SUBREG_REG (src);
956 if (GET_CODE (dest) == SUBREG)
957 dest = SUBREG_REG (dest);
3c0cb5de 958 if (MEM_P (src) && !MEM_P (dest)
ed8d2920
MM
959 && memref_is_stack_slot (src))
960 pcost = &load;
3c0cb5de 961 else if (!MEM_P (src) && MEM_P (dest)
ed8d2920
MM
962 && memref_is_stack_slot (dest))
963 pcost = &store;
964 }
965 if (pcost)
966 {
967 pcost->cost += block_cost;
968 pcost->count++;
969 }
970 }
a813c111 971 if (insn == BB_END (bb))
ed8d2920
MM
972 break;
973 }
974 }
975
976 if (!prefix)
977 prefix = "";
978 fprintf (file, "static insn cost %s\n", message ? message : "");
85f015e1
KG
979 fprintf (file, " %soverall:\tnum=%6d\tcost=% 8" HOST_WIDE_INT_PRINT "d\n",
980 prefix, overall.count, overall.cost);
981 fprintf (file, " %sloads:\tnum=%6d\tcost=% 8" HOST_WIDE_INT_PRINT "d\n",
982 prefix, load.count, load.cost);
983 fprintf (file, " %sstores:\tnum=%6d\tcost=% 8" HOST_WIDE_INT_PRINT "d\n",
984 prefix, store.count, store.cost);
985 fprintf (file, " %sregcopy:\tnum=%6d\tcost=% 8" HOST_WIDE_INT_PRINT "d\n",
986 prefix, regcopy.count, regcopy.cost);
987 fprintf (file, " %sselfcpy:\tnum=%6d\tcost=% 8" HOST_WIDE_INT_PRINT "d\n",
988 prefix, selfcopy.count, selfcopy.cost);
ed8d2920
MM
989}
990
991/* Returns nonzero, if WEB1 and WEB2 have some possible
992 hardregs in common. */
993
994int
93bad80e 995web_conflicts_p (struct web *web1, struct web *web2)
ed8d2920
MM
996{
997 if (web1->type == PRECOLORED && web2->type == PRECOLORED)
998 return 0;
999
1000 if (web1->type == PRECOLORED)
1001 return TEST_HARD_REG_BIT (web2->usable_regs, web1->regno);
1002
1003 if (web2->type == PRECOLORED)
1004 return TEST_HARD_REG_BIT (web1->usable_regs, web2->regno);
1005
1006 return hard_regs_intersect_p (&web1->usable_regs, &web2->usable_regs);
1007}
1008
1009/* Dump all uids of insns in which WEB is mentioned. */
1010
1011void
93bad80e 1012dump_web_insns (struct web *web)
ed8d2920
MM
1013{
1014 unsigned int i;
1015
1016 ra_debug_msg (DUMP_EVER, "Web: %i(%i)+%i class: %s freedom: %i degree %i\n",
1017 web->id, web->regno, web->add_hardregs,
1018 reg_class_names[web->regclass],
1019 web->num_freedom, web->num_conflicts);
1020 ra_debug_msg (DUMP_EVER, " def insns:");
1021
1022 for (i = 0; i < web->num_defs; ++i)
1023 {
1024 ra_debug_msg (DUMP_EVER, " %d ", INSN_UID (web->defs[i]->insn));
1025 }
1026
1027 ra_debug_msg (DUMP_EVER, "\n use insns:");
1028 for (i = 0; i < web->num_uses; ++i)
1029 {
1030 ra_debug_msg (DUMP_EVER, " %d ", INSN_UID (web->uses[i]->insn));
1031 }
1032 ra_debug_msg (DUMP_EVER, "\n");
1033}
1034
1035/* Dump conflicts for web WEB. */
1036
1037void
93bad80e 1038dump_web_conflicts (struct web *web)
ed8d2920
MM
1039{
1040 int num = 0;
1041 unsigned int def2;
1042
1043 ra_debug_msg (DUMP_EVER, "Web: %i(%i)+%i class: %s freedom: %i degree %i\n",
1044 web->id, web->regno, web->add_hardregs,
1045 reg_class_names[web->regclass],
1046 web->num_freedom, web->num_conflicts);
1047
1048 for (def2 = 0; def2 < num_webs; def2++)
1049 if (TEST_BIT (igraph, igraph_index (web->id, def2)) && web->id != def2)
1050 {
1051 if ((num % 9) == 5)
1052 ra_debug_msg (DUMP_EVER, "\n ");
1053 num++;
1054
1055 ra_debug_msg (DUMP_EVER, " %d(%d)", def2, id2web[def2]->regno);
1056 if (id2web[def2]->add_hardregs)
1057 ra_debug_msg (DUMP_EVER, "+%d", id2web[def2]->add_hardregs);
1058
1059 if (web_conflicts_p (web, id2web[def2]))
1060 ra_debug_msg (DUMP_EVER, "/x");
1061
1062 if (id2web[def2]->type == SELECT)
1063 ra_debug_msg (DUMP_EVER, "/s");
1064
1065 if (id2web[def2]->type == COALESCED)
1066 ra_debug_msg (DUMP_EVER,"/c/%d", alias (id2web[def2])->id);
1067 }
1068 ra_debug_msg (DUMP_EVER, "\n");
1069 {
1070 struct conflict_link *wl;
1071 num = 0;
1072 ra_debug_msg (DUMP_EVER, "By conflicts: ");
1073 for (wl = web->conflict_list; wl; wl = wl->next)
1074 {
1075 struct web* w = wl->t;
1076 if ((num % 9) == 8)
1077 ra_debug_msg (DUMP_EVER, "\n ");
1078 num++;
1079 ra_debug_msg (DUMP_EVER, "%d(%d)%s ", w->id, w->regno,
1080 web_conflicts_p (web, w) ? "+" : "");
1081 }
1082 ra_debug_msg (DUMP_EVER, "\n");
1083 }
1084}
1085
1086/* Output HARD_REG_SET to stderr. */
1087
1088void
93bad80e 1089debug_hard_reg_set (HARD_REG_SET set)
ed8d2920
MM
1090{
1091 int i;
6a87d634 1092 for (i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
ed8d2920
MM
1093 {
1094 if (TEST_HARD_REG_BIT (set, i))
1095 {
1096 fprintf (stderr, "%s ", reg_names[i]);
1097 }
1098 }
1099 fprintf (stderr, "\n");
1100}
1101
1102/*
1103vim:cinoptions={.5s,g0,p5,t0,(0,^-0.5s,n-0.5s:tw=78:cindent:sw=4:
1104*/