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>.
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"
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"
33
34 /* This file contains various dumping and debug functions for
35 the graph coloring register allocator. */
36
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));
41
42 /* The hardregs as names, for debugging. */
43 static const char *const reg_class_names[] = REG_CLASS_NAMES;
44
45 /* Print a message to the dump file, if debug_new_regalloc and LEVEL
46 have any bits in common. */
47
48 void
ra_debug_msg(unsigned int level,const char * format,...)49 ra_debug_msg VPARAMS ((unsigned int level, const char *format, ...))
50 {
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);
57 }
58
59
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. */
66
67 /* Print rtx X, which is a one operand rtx (op:mode (Y)), as
68 "op(Y)" to FILE. */
69
70 static void
ra_print_rtx_1op(file,x)71 ra_print_rtx_1op (file, x)
72 FILE *file;
73 rtx x;
74 {
75 enum rtx_code code = GET_CODE (x);
76 rtx op0 = XEXP (x, 0);
77 switch (code)
78 {
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;
99 }
100 }
101
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. */
105
106 static void
ra_print_rtx_2op(file,x)107 ra_print_rtx_2op (file, x)
108 FILE *file;
109 rtx x;
110 {
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)
117 {
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;
149 }
150 if (infix)
151 {
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);
157 }
158 else
159 {
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);
165 }
166 }
167
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. */
170
171 static void
ra_print_rtx_3op(file,x)172 ra_print_rtx_3op (file, x)
173 FILE *file;
174 rtx x;
175 {
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)
181 {
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);
187 }
188 else
189 {
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);
199 }
200 }
201
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. */
207
208 static void
ra_print_rtx_object(file,x)209 ra_print_rtx_object (file, x)
210 FILE *file;
211 rtx x;
212 {
213 enum rtx_code code = GET_CODE (x);
214 enum machine_mode mode = GET_MODE (x);
215 switch (code)
216 {
217 case CONST_INT:
218 fprintf (file, HOST_WIDE_INT_PRINT_DEC, XWINT (x, 0));
219 break;
220 case CONST_DOUBLE:
221 {
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++)
226 {
227 if (num)
228 fputs (", ", file);
229 if (fmt[i] == 'e' && XEXP (x, i))
230 /* The MEM or other stuff */
231 {
232 ra_print_rtx (file, XEXP (x, i), 0);
233 num++;
234 }
235 else if (fmt[i] == 'w')
236 {
237 fprintf (file, HOST_WIDE_INT_PRINT_HEX, XWINT (x, i));
238 num++;
239 }
240 }
241 break;
242 }
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:
250 {
251 int regno = REGNO (x);
252 if (regno < FIRST_PSEUDO_REGISTER)
253 {
254 int i, nregs = HARD_REGNO_NREGS (regno, mode);
255 if (nregs > 1)
256 fputs ("[", file);
257 for (i = 0; i < nregs; i++)
258 {
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);
265 }
266 if (nregs > 1)
267 fputs ("]", file);
268 }
269 else
270 fprintf (file, "p%d", regno);
271 break;
272 }
273 case SUBREG:
274 {
275 rtx sub = SUBREG_REG (x);
276 int ofs = SUBREG_BYTE (x);
277 if (GET_CODE (sub) == REG
278 && REGNO (sub) < FIRST_PSEUDO_REGISTER)
279 {
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++)
287 {
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);
294 }
295 if (nregs > 1)
296 fputs ("]", file);
297 }
298 else
299 {
300 ra_print_rtx (file, sub, 0);
301 fprintf (file, ":[%s+%d]", GET_MODE_NAME (mode), ofs);
302 }
303 break;
304 }
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:
321 {
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));
330 }
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;
336 }
337 }
338
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. */
343
344 void
ra_print_rtx(file,x,with_pn)345 ra_print_rtx (file, x, with_pn)
346 FILE *file;
347 rtx x;
348 int with_pn;
349 {
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);
357
358 /* First handle the insn like constructs. */
359 if (INSN_P (x) || code == NOTE || code == CODE_LABEL || code == BARRIER)
360 {
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. */
371 {
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))
376 {
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();
382 }
383 fprintf (file, " [%d uses] uid=(", LABEL_NUSES (x));
384 }
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)
394 {
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
399 {
400 fprintf (file, " line %d", ln);
401 if (NOTE_SOURCE_FILE (x))
402 fprintf (file, ":%s", NOTE_SOURCE_FILE (x));
403 }
404 }
405 else
406 {
407 fprintf (file, "\t");
408 ra_print_rtx (file, PATTERN (x), 0);
409 }
410 return;
411 }
412 switch (code)
413 {
414 /* Top-level stuff. */
415 case PARALLEL:
416 {
417 int j;
418 for (j = 0; j < XVECLEN (x, 0); j++)
419 {
420 if (j)
421 fputs ("\t;; ", file);
422 ra_print_rtx (file, XVECEXP (x, 0, j), 0);
423 }
424 break;
425 }
426 case UNSPEC: case UNSPEC_VOLATILE:
427 {
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++)
432 {
433 fputs (", ", file);
434 ra_print_rtx (file, XVECEXP (x, 0, j), 0);
435 }
436 fputs (")", file);
437 break;
438 }
439 case SET:
440 if (GET_CODE (SET_DEST (x)) == PC)
441 {
442 if (GET_CODE (SET_SRC (x)) == IF_THEN_ELSE
443 && GET_CODE (XEXP (SET_SRC(x), 2)) == PC)
444 {
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);
449 }
450 else
451 {
452 fputs ("jump ", file);
453 ra_print_rtx (file, SET_SRC (x), 0);
454 }
455 }
456 else
457 {
458 ra_print_rtx (file, SET_DEST (x), 0);
459 fputs (" <= ", file);
460 ra_print_rtx (file, SET_SRC (x), 0);
461 }
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;
489
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;
500 }
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);
513 }
514
515 /* This only calls ra_print_rtx(), but emits a final newline. */
516
517 void
ra_print_rtx_top(file,x,with_pn)518 ra_print_rtx_top (file, x, with_pn)
519 FILE *file;
520 rtx x;
521 int with_pn;
522 {
523 ra_print_rtx (file, x, with_pn);
524 fprintf (file, "\n");
525 }
526
527 /* Callable from gdb. This prints rtx X onto stderr. */
528
529 void
ra_debug_rtx(x)530 ra_debug_rtx (x)
531 rtx x;
532 {
533 ra_print_rtx_top (stderr, x, 1);
534 }
535
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. */
538
539 void
ra_debug_bbi(bbi)540 ra_debug_bbi (bbi)
541 int bbi;
542 {
543 basic_block bb = BASIC_BLOCK (bbi);
544 rtx insn;
545 for (insn = bb->head; insn; insn = NEXT_INSN (insn))
546 {
547 ra_print_rtx_top (stderr, insn, (insn == bb->head || insn == bb->end));
548 fprintf (stderr, "\n");
549 if (insn == bb->end)
550 break;
551 }
552 }
553
554 /* Beginning from INSN, emit NUM insns (if NUM is non-negative)
555 or emit a window of NUM insns around INSN, to stderr. */
556
557 void
ra_debug_insns(insn,num)558 ra_debug_insns (insn, num)
559 rtx insn;
560 int num;
561 {
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--)
567 {
568 if (GET_CODE (insn) == CODE_LABEL)
569 fprintf (stderr, "\n");
570 ra_print_rtx_top (stderr, insn, (i == count || i == 1));
571 }
572 }
573
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. */
577
578 void
ra_print_rtl_with_bb(file,insn)579 ra_print_rtl_with_bb (file, insn)
580 FILE *file;
581 rtx insn;
582 {
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))
589 {
590 if (GET_CODE (insn) == BARRIER)
591 bb = NULL;
592 else
593 bb = BLOCK_FOR_INSN (insn);
594 if (bb != last_bb)
595 {
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;
601 }
602 if (GET_CODE (insn) == CODE_LABEL)
603 fputc ('\n', file);
604 if (GET_CODE (insn) == NOTE)
605 {
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))
612 {
613 ra_print_rtx_top (file, insn, (num == 0 || !NEXT_INSN (insn)));
614 num++;
615 }
616 }
617 else
618 {
619 ra_print_rtx_top (file, insn, (num == 0 || !NEXT_INSN (insn)));
620 num++;
621 }
622 }
623 }
624
625 /* Count how many insns were seen how often, while building the interference
626 graph, and prints the findings. */
627
628 void
dump_number_seen()629 dump_number_seen ()
630 {
631 #define N 17
632 int num[N];
633 int i;
634
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
650 }
651
652 /* Dump the interference graph, the move list and the webs. */
653
654 void
dump_igraph(df)655 dump_igraph (df)
656 struct df *df ATTRIBUTE_UNUSED;
657 {
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++)
667 {
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)))
671 {
672 if (num1 == num)
673 {
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);
681 }
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);
691 }
692 if (num1 != num)
693 ra_debug_msg (DUMP_IGRAPH, "\n ");
694 }
695 ra_debug_msg (DUMP_IGRAPH, "\n");
696 for (ml = wl_moves; ml; ml = ml->next)
697 if (ml->move)
698 {
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);
702 }
703 ra_debug_msg (DUMP_WEBS, "\nWebs:\n");
704 for (i = 0; i < num_webs; i++)
705 {
706 struct web *web = ID2WEB (i);
707
708 ra_debug_msg (DUMP_WEBS, " %4d : regno %3d", i, web->regno);
709 if (SUBWEB_P (web))
710 {
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);
713 }
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");
733 }
734 }
735
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. */
739
740 void
dump_igraph_machine()741 dump_igraph_machine ()
742 {
743 unsigned int i;
744
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++)
750 {
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)
767 {
768 ra_debug_msg (DUMP_IGRAPH_M, "s %d", web->id);
769 while (1)
770 {
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;
779 }
780 ra_debug_msg (DUMP_IGRAPH_M, "\n");
781 }
782 if (numc)
783 {
784 ra_debug_msg (DUMP_IGRAPH_M, "c %d", web->id);
785 for (cl = web->conflict_list; cl; cl = cl->next)
786 {
787 if (cl->t->id < web->id)
788 ra_debug_msg (DUMP_IGRAPH_M, " %d", cl->t->id);
789 }
790 ra_debug_msg (DUMP_IGRAPH_M, "\n");
791 }
792 }
793 ra_debug_msg (DUMP_IGRAPH_M, "e\n");
794 }
795
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. */
799
800 void
dump_constraints()801 dump_constraints ()
802 {
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))
813 {
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)
823 {
824 ra_debug_msg (DUMP_CONSTRAINTS,
825 "%d: asm insn or not recognizable.\n", uid);
826 continue;
827 }
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++)
834 {
835 ra_debug_msg (DUMP_CONSTRAINTS,
836 "%d:%s ", o, recog_data.constraints[o]);
837 }
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");
844 }
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;
848 }
849
850 /* This counts and emits the cumulated cost of all spilled webs,
851 preceded by a custom message MSG, with debug level LEVEL. */
852
853 void
dump_graph_cost(level,msg)854 dump_graph_cost (level, msg)
855 unsigned int level;
856 const char *msg;
857 {
858 unsigned int i;
859 unsigned HOST_WIDE_INT cost;
860 if (!rtl_dump_file || (debug_new_regalloc & level) == 0)
861 return;
862
863 cost = 0;
864 for (i = 0; i < num_webs; i++)
865 {
866 struct web *web = id2web[i];
867 if (alias (web)->type == SPILLED)
868 cost += web->orig_spill_cost;
869 }
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");
873 }
874
875 /* Dump the color assignment per web, the coalesced and spilled webs. */
876
877 void
dump_ra(df)878 dump_ra (df)
879 struct df *df ATTRIBUTE_UNUSED;
880 {
881 struct web *web;
882 struct dlist *d;
883 if (!rtl_dump_file || (debug_new_regalloc & DUMP_RESULTS) == 0)
884 return;
885
886 ra_debug_msg (DUMP_RESULTS, "\nColored:\n");
887 for (d = WEBS(COLORED); d; d = d->next)
888 {
889 web = DLIST_WEB (d);
890 ra_debug_msg (DUMP_RESULTS, " %4d : color %d\n", web->id, web->color);
891 }
892 ra_debug_msg (DUMP_RESULTS, "\nCoalesced:\n");
893 for (d = WEBS(COALESCED); d; d = d->next)
894 {
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);
898 }
899 ra_debug_msg (DUMP_RESULTS, "\nSpilled:\n");
900 for (d = WEBS(SPILLED); d; d = d->next)
901 {
902 web = DLIST_WEB (d);
903 ra_debug_msg (DUMP_RESULTS, " %4d\n", web->id);
904 }
905 ra_debug_msg (DUMP_RESULTS, "\n");
906 dump_cost (DUMP_RESULTS);
907 }
908
909 /* Calculate and dump the cumulated costs of certain types of insns
910 (loads, stores and copies). */
911
912 void
dump_static_insn_cost(file,message,prefix)913 dump_static_insn_cost (file, message, prefix)
914 FILE *file;
915 const char *message;
916 const char *prefix;
917 {
918 struct cost
919 {
920 unsigned HOST_WIDE_INT cost;
921 unsigned int count;
922 };
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 (®copy, 0, sizeof(regcopy));
928 memset (&selfcopy, 0, sizeof(selfcopy));
929 memset (&overall, 0, sizeof(overall));
930
931 if (!file)
932 return;
933
934 FOR_EACH_BB (bb)
935 {
936 unsigned HOST_WIDE_INT block_cost = bb->frequency;
937 rtx insn, set;
938 for (insn = bb->head; insn; insn = NEXT_INSN (insn))
939 {
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))
944 {
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 = ®copy;
958 else
959 {
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;
970 }
971 if (pcost)
972 {
973 pcost->cost += block_cost;
974 pcost->count++;
975 }
976 }
977 if (insn == bb->end)
978 break;
979 }
980 }
981
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");
1000 }
1001
1002 /* Returns nonzero, if WEB1 and WEB2 have some possible
1003 hardregs in common. */
1004
1005 int
web_conflicts_p(web1,web2)1006 web_conflicts_p (web1, web2)
1007 struct web *web1;
1008 struct web *web2;
1009 {
1010 if (web1->type == PRECOLORED && web2->type == PRECOLORED)
1011 return 0;
1012
1013 if (web1->type == PRECOLORED)
1014 return TEST_HARD_REG_BIT (web2->usable_regs, web1->regno);
1015
1016 if (web2->type == PRECOLORED)
1017 return TEST_HARD_REG_BIT (web1->usable_regs, web2->regno);
1018
1019 return hard_regs_intersect_p (&web1->usable_regs, &web2->usable_regs);
1020 }
1021
1022 /* Dump all uids of insns in which WEB is mentioned. */
1023
1024 void
dump_web_insns(web)1025 dump_web_insns (web)
1026 struct web *web;
1027 {
1028 unsigned int i;
1029
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:");
1035
1036 for (i = 0; i < web->num_defs; ++i)
1037 {
1038 ra_debug_msg (DUMP_EVER, " %d ", INSN_UID (web->defs[i]->insn));
1039 }
1040
1041 ra_debug_msg (DUMP_EVER, "\n use insns:");
1042 for (i = 0; i < web->num_uses; ++i)
1043 {
1044 ra_debug_msg (DUMP_EVER, " %d ", INSN_UID (web->uses[i]->insn));
1045 }
1046 ra_debug_msg (DUMP_EVER, "\n");
1047 }
1048
1049 /* Dump conflicts for web WEB. */
1050
1051 void
dump_web_conflicts(web)1052 dump_web_conflicts (web)
1053 struct web *web;
1054 {
1055 int num = 0;
1056 unsigned int def2;
1057
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);
1062
1063 for (def2 = 0; def2 < num_webs; def2++)
1064 if (TEST_BIT (igraph, igraph_index (web->id, def2)) && web->id != def2)
1065 {
1066 if ((num % 9) == 5)
1067 ra_debug_msg (DUMP_EVER, "\n ");
1068 num++;
1069
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);
1073
1074 if (web_conflicts_p (web, id2web[def2]))
1075 ra_debug_msg (DUMP_EVER, "/x");
1076
1077 if (id2web[def2]->type == SELECT)
1078 ra_debug_msg (DUMP_EVER, "/s");
1079
1080 if (id2web[def2]->type == COALESCED)
1081 ra_debug_msg (DUMP_EVER,"/c/%d", alias (id2web[def2])->id);
1082 }
1083 ra_debug_msg (DUMP_EVER, "\n");
1084 {
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)
1089 {
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) ? "+" : "");
1096 }
1097 ra_debug_msg (DUMP_EVER, "\n");
1098 }
1099 }
1100
1101 /* Output HARD_REG_SET to stderr. */
1102
1103 void
debug_hard_reg_set(set)1104 debug_hard_reg_set (set)
1105 HARD_REG_SET set;
1106 {
1107 int i;
1108 for (i=0; i < FIRST_PSEUDO_REGISTER; ++i)
1109 {
1110 if (TEST_HARD_REG_BIT (set, i))
1111 {
1112 fprintf (stderr, "%s ", reg_names[i]);
1113 }
1114 }
1115 fprintf (stderr, "\n");
1116 }
1117
1118 /*
1119 vim:cinoptions={.5s,g0,p5,t0,(0,^-0.5s,n-0.5s:tw=78:cindent:sw=4:
1120 */
1121