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
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. */
23 #include "coretypes.h"
26 #include "insn-config.h"
29 #include "hard-reg-set.h"
30 #include "basic-block.h"
36 /* This file contains various dumping and debug functions for
37 the graph coloring register allocator. */
39 static void ra_print_rtx_1op (FILE *, rtx
);
40 static void ra_print_rtx_2op (FILE *, rtx
);
41 static void ra_print_rtx_3op (FILE *, rtx
);
42 static void ra_print_rtx_object (FILE *, rtx
);
44 /* The hardregs as names, for debugging. */
45 static const char *const reg_class_names
[] = REG_CLASS_NAMES
;
47 /* Print a message to the dump file, if debug_new_regalloc and LEVEL
48 have any bits in common. */
51 ra_debug_msg (unsigned int level
, const char *format
, ...)
55 va_start (ap
, format
);
56 if ((debug_new_regalloc
& level
) != 0 && rtl_dump_file
!= NULL
)
57 vfprintf (rtl_dump_file
, format
, ap
);
62 /* The following ra_print_xxx() functions print RTL expressions
63 in concise infix form. If the mode can be seen from context it's
64 left out. Most operators are represented by their graphical
65 characters, e.g. LE as "<=". Unknown constructs are currently
66 printed with print_inline_rtx(), which disrupts the nice layout.
67 Currently only the inline asm things are written this way. */
69 /* Print rtx X, which is a one operand rtx (op:mode (Y)), as
73 ra_print_rtx_1op (FILE *file
, rtx x
)
75 enum rtx_code code
= GET_CODE (x
);
76 rtx op0
= XEXP (x
, 0);
81 fputs ((code
== NEG
) ? "-(" : "~(", file
);
82 ra_print_rtx (file
, op0
, 0);
87 ra_print_rtx (file
, op0
, 0);
91 fprintf (file
, "%s", GET_RTX_NAME (code
));
92 if (GET_MODE (x
) != VOIDmode
)
93 fprintf (file
, ":%s(", GET_MODE_NAME (GET_MODE (x
)));
96 ra_print_rtx (file
, op0
, 0);
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,
107 ra_print_rtx_2op (FILE *file
, rtx x
)
110 const char *opname
= "shitop";
111 enum rtx_code code
= GET_CODE (x
);
112 rtx op0
= XEXP (x
, 0);
113 rtx op1
= XEXP (x
, 1);
117 case COMPARE
: opname
= "?"; break;
118 case MINUS
: opname
= "-"; break;
119 case DIV
: opname
= "/"; break;
120 case UDIV
: opname
= "u/"; break;
121 case MOD
: opname
= "%"; break;
122 case UMOD
: opname
= "u%"; break;
123 case ASHIFT
: opname
= "<<"; break;
124 case ASHIFTRT
: opname
= "a>>"; break;
125 case LSHIFTRT
: opname
= "l>>"; break;
127 case PLUS
: opname
= "+"; break;
128 case MULT
: opname
= "*"; break;
129 case AND
: opname
= "&"; break;
130 case IOR
: opname
= "|"; break;
131 case XOR
: opname
= "^"; break;
133 case NE
: opname
= "!="; break;
134 case EQ
: opname
= "=="; break;
135 case GE
: opname
= "s>="; break;
136 case GT
: opname
= "s>"; break;
137 case LE
: opname
= "s<="; break;
138 case LT
: opname
= "s<"; break;
139 case GEU
: opname
= "u>="; break;
140 case GTU
: opname
= "u>"; break;
141 case LEU
: opname
= "u<="; break;
142 case LTU
: opname
= "u<"; break;
145 opname
= GET_RTX_NAME (code
);
151 ra_print_rtx (file
, op0
, 0);
152 fprintf (file
, " %s ", opname
);
153 ra_print_rtx (file
, op1
, 0);
158 fprintf (file
, "%s(", opname
);
159 ra_print_rtx (file
, op0
, 0);
161 ra_print_rtx (file
, op1
, 0);
166 /* Print rtx X, which a three operand rtx to FILE.
167 I.e. X is either an IF_THEN_ELSE, or a bitmap operation. */
170 ra_print_rtx_3op (FILE *file
, rtx x
)
172 enum rtx_code code
= GET_CODE (x
);
173 rtx op0
= XEXP (x
, 0);
174 rtx op1
= XEXP (x
, 1);
175 rtx op2
= XEXP (x
, 2);
176 if (code
== IF_THEN_ELSE
)
178 ra_print_rtx (file
, op0
, 0);
180 ra_print_rtx (file
, op1
, 0);
182 ra_print_rtx (file
, op2
, 0);
186 /* Bitmap-operation */
187 fprintf (file
, "%s:%s(", GET_RTX_NAME (code
),
188 GET_MODE_NAME (GET_MODE (x
)));
189 ra_print_rtx (file
, op0
, 0);
191 ra_print_rtx (file
, op1
, 0);
193 ra_print_rtx (file
, op2
, 0);
198 /* Print rtx X, which represents an object (class 'o' or some constructs
199 of class 'x' (e.g. subreg)), to FILE.
200 (reg XX) rtl is represented as "pXX", of XX was a pseudo,
201 as "name" it name is the nonnull hardreg name, or as "hXX", if XX
202 is a hardreg, whose name is NULL, or empty. */
205 ra_print_rtx_object (FILE *file
, rtx x
)
207 enum rtx_code code
= GET_CODE (x
);
208 enum machine_mode mode
= GET_MODE (x
);
212 fprintf (file
, HOST_WIDE_INT_PRINT_DEC
, XWINT (x
, 0));
217 const char *fmt
= GET_RTX_FORMAT (code
);
218 fputs ("dbl(", file
);
219 for (i
= 0; i
< GET_RTX_LENGTH (code
); i
++)
223 if (fmt
[i
] == 'e' && XEXP (x
, i
))
224 /* The MEM or other stuff */
226 ra_print_rtx (file
, XEXP (x
, i
), 0);
229 else if (fmt
[i
] == 'w')
231 fprintf (file
, HOST_WIDE_INT_PRINT_HEX
, XWINT (x
, i
));
237 case CONST_STRING
: fprintf (file
, "\"%s\"", XSTR (x
, 0)); break;
238 case CONST
: fputs ("const(", file
);
239 ra_print_rtx (file
, XEXP (x
, 0), 0);
242 case PC
: fputs ("pc", file
); break;
245 int regno
= REGNO (x
);
246 if (regno
< FIRST_PSEUDO_REGISTER
)
248 int i
, nregs
= HARD_REGNO_NREGS (regno
, mode
);
251 for (i
= 0; i
< nregs
; i
++)
255 if (reg_names
[regno
+i
] && *reg_names
[regno
+ i
])
256 fprintf (file
, "%s", reg_names
[regno
+ i
]);
258 fprintf (file
, "h%d", regno
+ i
);
264 fprintf (file
, "p%d", regno
);
269 rtx sub
= SUBREG_REG (x
);
270 int ofs
= SUBREG_BYTE (x
);
271 if (GET_CODE (sub
) == REG
272 && REGNO (sub
) < FIRST_PSEUDO_REGISTER
)
274 int regno
= REGNO (sub
);
275 int i
, nregs
= HARD_REGNO_NREGS (regno
, mode
);
276 regno
+= subreg_regno_offset (regno
, GET_MODE (sub
),
280 for (i
= 0; i
< nregs
; i
++)
284 if (reg_names
[regno
+i
])
285 fprintf (file
, "%s", reg_names
[regno
+ i
]);
287 fprintf (file
, "h%d", regno
+ i
);
294 ra_print_rtx (file
, sub
, 0);
295 fprintf (file
, ":[%s+%d]", GET_MODE_NAME (mode
), ofs
);
299 case SCRATCH
: fputs ("scratch", file
); break;
300 case CONCAT
: ra_print_rtx_2op (file
, x
); break;
301 case HIGH
: ra_print_rtx_1op (file
, x
); break;
304 ra_print_rtx (file
, XEXP (x
, 0), 0);
305 fputs (" + lo(", file
);
306 ra_print_rtx (file
, XEXP (x
, 1), 0);
309 case MEM
: fputs ("[", file
);
310 ra_print_rtx (file
, XEXP (x
, 0), 0);
311 fprintf (file
, "]:%s", GET_MODE_NAME (GET_MODE (x
)));
312 /* XXX print alias set too ?? */
316 rtx sub
= XEXP (x
, 0);
317 if (GET_CODE (sub
) == NOTE
318 && NOTE_LINE_NUMBER (sub
) == NOTE_INSN_DELETED_LABEL
)
319 fprintf (file
, "(deleted uid=%d)", INSN_UID (sub
));
320 else if (GET_CODE (sub
) == CODE_LABEL
)
321 fprintf (file
, "L%d", CODE_LABEL_NUMBER (sub
));
323 fprintf (file
, "(nonlabel uid=%d)", INSN_UID (sub
));
327 fprintf (file
, "sym(\"%s\")", XSTR (x
, 0)); break;
328 case CC0
: fputs ("cc0", file
); break;
329 default: print_inline_rtx (file
, x
, 0); break;
333 /* Print a general rtx X to FILE in nice infix form.
334 If WITH_PN is set, and X is one of the toplevel constructs
335 (insns, notes, labels or barriers), then print also the UIDs of
336 the preceding and following insn. */
339 ra_print_rtx (FILE *file
, rtx x
, int with_pn
)
347 class = GET_RTX_CLASS (code
);
349 /* First handle the insn like constructs. */
350 if (INSN_P (x
) || code
== NOTE
|| code
== CODE_LABEL
|| code
== BARRIER
)
354 /* Non-insns are prefixed by a ';'. */
357 else if (code
== NOTE
)
358 /* But notes are indented very far right. */
359 fprintf (file
, "\t\t\t\t\t; ");
360 else if (code
== CODE_LABEL
)
361 /* And labels have their Lxx name first, before the actual UID. */
363 fprintf (file
, "L%d:\t; ", CODE_LABEL_NUMBER (x
));
365 fprintf (file
, "(%s) ", LABEL_NAME (x
));
366 switch (LABEL_KIND (x
))
368 case LABEL_NORMAL
: break;
369 case LABEL_STATIC_ENTRY
: fputs (" (entry)", file
); break;
370 case LABEL_GLOBAL_ENTRY
: fputs (" (global entry)", file
); break;
371 case LABEL_WEAK_ENTRY
: fputs (" (weak entry)", file
); break;
374 fprintf (file
, " [%d uses] uid=(", LABEL_NUSES (x
));
376 fprintf (file
, "%d", INSN_UID (x
));
378 fprintf (file
, " %d %d", PREV_INSN (x
) ? INSN_UID (PREV_INSN (x
)) : 0,
379 NEXT_INSN (x
) ? INSN_UID (NEXT_INSN (x
)) : 0);
381 fputs (" -------- barrier ---------", file
);
382 else if (code
== CODE_LABEL
)
384 else if (code
== NOTE
)
386 int ln
= NOTE_LINE_NUMBER (x
);
387 if (ln
>= (int) NOTE_INSN_BIAS
&& ln
< (int) NOTE_INSN_MAX
)
388 fprintf (file
, " %s", GET_NOTE_INSN_NAME (ln
));
391 fprintf (file
, " line %d", ln
);
392 if (NOTE_SOURCE_FILE (x
))
393 fprintf (file
, ":%s", NOTE_SOURCE_FILE (x
));
398 fprintf (file
, "\t");
399 ra_print_rtx (file
, PATTERN (x
), 0);
405 /* Top-level stuff. */
409 for (j
= 0; j
< XVECLEN (x
, 0); j
++)
412 fputs ("\t;; ", file
);
413 ra_print_rtx (file
, XVECEXP (x
, 0, j
), 0);
417 case UNSPEC
: case UNSPEC_VOLATILE
:
420 fprintf (file
, "unspec%s(%d",
421 (code
== UNSPEC
) ? "" : "_vol", XINT (x
, 1));
422 for (j
= 0; j
< XVECLEN (x
, 0); j
++)
425 ra_print_rtx (file
, XVECEXP (x
, 0, j
), 0);
431 if (GET_CODE (SET_DEST (x
)) == PC
)
433 if (GET_CODE (SET_SRC (x
)) == IF_THEN_ELSE
434 && GET_CODE (XEXP (SET_SRC(x
), 2)) == PC
)
437 ra_print_rtx (file
, XEXP (SET_SRC (x
), 0), 0);
438 fputs (" jump ", file
);
439 ra_print_rtx (file
, XEXP (SET_SRC (x
), 1), 0);
443 fputs ("jump ", file
);
444 ra_print_rtx (file
, SET_SRC (x
), 0);
449 ra_print_rtx (file
, SET_DEST (x
), 0);
450 fputs (" <= ", file
);
451 ra_print_rtx (file
, SET_SRC (x
), 0);
455 fputs ("use <= ", file
);
456 ra_print_rtx (file
, XEXP (x
, 0), 0);
459 ra_print_rtx (file
, XEXP (x
, 0), 0);
460 fputs (" <= clobber", file
);
463 fputs ("call ", file
);
464 ra_print_rtx (file
, XEXP (x
, 0), 0); /* Address */
465 fputs (" numargs=", file
);
466 ra_print_rtx (file
, XEXP (x
, 1), 0); /* Num arguments */
469 fputs ("return", file
);
472 fputs ("if (", file
);
473 ra_print_rtx (file
, XEXP (x
, 0), 0);
474 fputs (") trap ", file
);
475 ra_print_rtx (file
, XEXP (x
, 1), 0);
478 fprintf (file
, "resx from region %d", XINT (x
, 0));
481 /* Different things of class 'x' */
482 case SUBREG
: ra_print_rtx_object (file
, x
); break;
483 case STRICT_LOW_PART
:
484 fputs ("low(", file
);
485 ra_print_rtx (file
, XEXP (x
, 0), 0);
495 ra_print_rtx_1op (file
, x
);
496 else if (class == '2' || class == 'c' || class == '<')
497 ra_print_rtx_2op (file
, x
);
498 else if (class == '3' || class == 'b')
499 ra_print_rtx_3op (file
, x
);
500 else if (class == 'o')
501 ra_print_rtx_object (file
, x
);
503 print_inline_rtx (file
, x
, 0);
506 /* This only calls ra_print_rtx(), but emits a final newline. */
509 ra_print_rtx_top (FILE *file
, rtx x
, int with_pn
)
511 ra_print_rtx (file
, x
, with_pn
);
512 fprintf (file
, "\n");
515 /* Callable from gdb. This prints rtx X onto stderr. */
520 ra_print_rtx_top (stderr
, x
, 1);
523 /* This prints the content of basic block with index BBI.
524 The first and last insn are emitted with UIDs of prev and next insns. */
527 ra_debug_bbi (int bbi
)
529 basic_block bb
= BASIC_BLOCK (bbi
);
531 for (insn
= BB_HEAD (bb
); insn
; insn
= NEXT_INSN (insn
))
533 ra_print_rtx_top (stderr
, insn
,
534 (insn
== BB_HEAD (bb
) || insn
== BB_END (bb
)));
535 fprintf (stderr
, "\n");
536 if (insn
== BB_END (bb
))
541 /* Beginning from INSN, emit NUM insns (if NUM is non-negative)
542 or emit a window of NUM insns around INSN, to stderr. */
545 ra_debug_insns (rtx insn
, int num
)
547 int i
, count
= (num
== 0 ? 1 : num
< 0 ? -num
: num
);
549 for (i
= count
/ 2; i
> 0 && PREV_INSN (insn
); i
--)
550 insn
= PREV_INSN (insn
);
551 for (i
= count
; i
> 0 && insn
; insn
= NEXT_INSN (insn
), i
--)
553 if (GET_CODE (insn
) == CODE_LABEL
)
554 fprintf (stderr
, "\n");
555 ra_print_rtx_top (stderr
, insn
, (i
== count
|| i
== 1));
559 /* Beginning with INSN, emit the whole insn chain into FILE.
560 This also outputs comments when basic blocks start or end and omits
561 some notes, if flag_ra_dump_notes is zero. */
564 ra_print_rtl_with_bb (FILE *file
, rtx insn
)
566 basic_block last_bb
, bb
;
567 unsigned int num
= 0;
571 for (; insn
; insn
= NEXT_INSN (insn
))
573 if (GET_CODE (insn
) == BARRIER
)
576 bb
= BLOCK_FOR_INSN (insn
);
580 fprintf (file
, ";; End of basic block %d\n", last_bb
->index
);
582 fprintf (file
, ";; Begin of basic block %d\n", bb
->index
);
585 if (GET_CODE (insn
) == CODE_LABEL
)
587 if (GET_CODE (insn
) == NOTE
)
589 /* Ignore basic block and maybe other notes not referencing
591 if (NOTE_LINE_NUMBER (insn
) != NOTE_INSN_BASIC_BLOCK
592 && (flag_ra_dump_notes
593 || NOTE_LINE_NUMBER (insn
) == NOTE_INSN_DELETED
594 || NOTE_LINE_NUMBER (insn
) == NOTE_INSN_DELETED_LABEL
))
596 ra_print_rtx_top (file
, insn
, (num
== 0 || !NEXT_INSN (insn
)));
602 ra_print_rtx_top (file
, insn
, (num
== 0 || !NEXT_INSN (insn
)));
608 /* Count how many insns were seen how often, while building the interference
609 graph, and prints the findings. */
612 dump_number_seen (void)
618 for (i
= 0; i
< N
; i
++)
620 for (i
= 0; i
< get_max_uid (); i
++)
621 if (number_seen
[i
] < N
- 1)
622 num
[number_seen
[i
]]++;
625 for (i
= 0; i
< N
- 1; i
++)
627 ra_debug_msg (DUMP_PROCESS
, "%d insns seen %d times\n", num
[i
], i
);
629 ra_debug_msg (DUMP_PROCESS
, "%d insns seen %d and more times\n", num
[i
],
631 ra_debug_msg (DUMP_PROCESS
, "from overall %d insns\n", get_max_uid ());
635 /* Dump the interference graph, the move list and the webs. */
638 dump_igraph (struct df
*df ATTRIBUTE_UNUSED
)
640 struct move_list
*ml
;
641 unsigned int def1
, def2
;
645 if (!rtl_dump_file
|| (debug_new_regalloc
& (DUMP_IGRAPH
| DUMP_WEBS
)) == 0)
647 ra_debug_msg (DUMP_IGRAPH
, "conflicts:\n ");
648 for (def1
= 0; def1
< num_webs
; def1
++)
652 for (def2
= 0; def2
< num_webs
; def2
++)
653 if (def1
!= def2
&& TEST_BIT (igraph
, igraph_index (def1
, def2
)))
657 if (SUBWEB_P (ID2WEB (def1
)))
658 ra_debug_msg (DUMP_IGRAPH
, "%d (SUBREG %d, %d) with ", def1
,
659 ID2WEB (def1
)->regno
,
660 SUBREG_BYTE (ID2WEB (def1
)->orig_x
));
662 ra_debug_msg (DUMP_IGRAPH
, "%d (REG %d) with ", def1
,
663 ID2WEB (def1
)->regno
);
666 ra_debug_msg (DUMP_IGRAPH
, "\n ");
669 if (SUBWEB_P (ID2WEB (def2
)))
670 ra_debug_msg (DUMP_IGRAPH
, "%d(%d,%d) ", def2
, ID2WEB (def2
)->regno
,
671 SUBREG_BYTE (ID2WEB (def2
)->orig_x
));
673 ra_debug_msg (DUMP_IGRAPH
, "%d(%d) ", def2
, ID2WEB (def2
)->regno
);
676 ra_debug_msg (DUMP_IGRAPH
, "\n ");
678 ra_debug_msg (DUMP_IGRAPH
, "\n");
679 for (ml
= wl_moves
; ml
; ml
= ml
->next
)
682 ra_debug_msg (DUMP_IGRAPH
, "move: insn %d: Web %d <-- Web %d\n",
683 INSN_UID (ml
->move
->insn
), ml
->move
->target_web
->id
,
684 ml
->move
->source_web
->id
);
686 ra_debug_msg (DUMP_WEBS
, "\nWebs:\n");
687 for (i
= 0; i
< num_webs
; i
++)
689 struct web
*web
= ID2WEB (i
);
691 ra_debug_msg (DUMP_WEBS
, " %4d : regno %3d", i
, web
->regno
);
694 ra_debug_msg (DUMP_WEBS
, " sub %d", SUBREG_BYTE (web
->orig_x
));
695 ra_debug_msg (DUMP_WEBS
, " par %d", find_web_for_subweb (web
)->id
);
697 ra_debug_msg (DUMP_WEBS
, " +%d (span %d, cost "
698 HOST_WIDE_INT_PRINT_DEC
") (%s)",
699 web
->add_hardregs
, web
->span_deaths
, web
->spill_cost
,
700 reg_class_names
[web
->regclass
]);
701 if (web
->spill_temp
== 1)
702 ra_debug_msg (DUMP_WEBS
, " (spilltemp)");
703 else if (web
->spill_temp
== 2)
704 ra_debug_msg (DUMP_WEBS
, " (spilltem2)");
705 else if (web
->spill_temp
== 3)
706 ra_debug_msg (DUMP_WEBS
, " (short)");
707 if (web
->type
== PRECOLORED
)
708 ra_debug_msg (DUMP_WEBS
, " (precolored, color=%d)", web
->color
);
709 else if (find_web_for_subweb (web
)->num_uses
== 0)
710 ra_debug_msg (DUMP_WEBS
, " dead");
711 if (web
->crosses_call
)
712 ra_debug_msg (DUMP_WEBS
, " xcall");
713 if (web
->regno
>= max_normal_pseudo
)
714 ra_debug_msg (DUMP_WEBS
, " stack");
715 ra_debug_msg (DUMP_WEBS
, "\n");
719 /* Dump the interference graph and webs in a format easily
720 parsable by programs. Used to emit real world interference graph
721 to my custom graph colorizer. */
724 dump_igraph_machine (void)
728 if (!rtl_dump_file
|| (debug_new_regalloc
& DUMP_IGRAPH_M
) == 0)
730 ra_debug_msg (DUMP_IGRAPH_M
, "g %d %d\n", num_webs
- num_subwebs
,
731 FIRST_PSEUDO_REGISTER
);
732 for (i
= 0; i
< num_webs
- num_subwebs
; i
++)
734 struct web
*web
= ID2WEB (i
);
735 struct conflict_link
*cl
;
739 flags
= web
->spill_temp
& 0xF;
740 flags
|= ((web
->type
== PRECOLORED
) ? 1 : 0) << 4;
741 flags
|= (web
->add_hardregs
& 0xF) << 5;
742 for (cl
= web
->conflict_list
; cl
; cl
= cl
->next
)
743 if (cl
->t
->id
< web
->id
)
745 ra_debug_msg (DUMP_IGRAPH_M
, "n %d %d %d %d %d %d %d\n",
746 web
->id
, web
->color
, flags
,
747 (unsigned int)web
->spill_cost
, web
->num_defs
, web
->num_uses
,
749 if (web
->type
!= PRECOLORED
)
751 ra_debug_msg (DUMP_IGRAPH_M
, "s %d", web
->id
);
756 for (n
= 0; n
< 32 && col
< FIRST_PSEUDO_REGISTER
; n
++, col
++)
757 if (TEST_HARD_REG_BIT (web
->usable_regs
, col
))
759 ra_debug_msg (DUMP_IGRAPH_M
, " %u", u
);
760 if (col
>= FIRST_PSEUDO_REGISTER
)
763 ra_debug_msg (DUMP_IGRAPH_M
, "\n");
767 ra_debug_msg (DUMP_IGRAPH_M
, "c %d", web
->id
);
768 for (cl
= web
->conflict_list
; cl
; cl
= cl
->next
)
770 if (cl
->t
->id
< web
->id
)
771 ra_debug_msg (DUMP_IGRAPH_M
, " %d", cl
->t
->id
);
773 ra_debug_msg (DUMP_IGRAPH_M
, "\n");
776 ra_debug_msg (DUMP_IGRAPH_M
, "e\n");
779 /* This runs after colorization and changing the insn stream.
780 It temporarily replaces all pseudo registers with their colors,
781 and emits information, if the resulting insns are strictly valid. */
784 dump_constraints (void)
788 if (!rtl_dump_file
|| (debug_new_regalloc
& DUMP_CONSTRAINTS
) == 0)
790 for (i
= FIRST_PSEUDO_REGISTER
; i
< ra_max_regno
; i
++)
791 if (regno_reg_rtx
[i
] && GET_CODE (regno_reg_rtx
[i
]) == REG
)
792 REGNO (regno_reg_rtx
[i
])
793 = ra_reg_renumber
[i
] >= 0 ? ra_reg_renumber
[i
] : i
;
794 for (insn
= get_insns (); insn
; insn
= NEXT_INSN (insn
))
798 int uid
= INSN_UID (insn
);
800 /* Don't simply force rerecognition, as combine might left us
801 with some unrecognizable ones, which later leads to aborts
802 in regclass, if we now destroy the remembered INSN_CODE(). */
803 /*INSN_CODE (insn) = -1;*/
804 code
= recog_memoized (insn
);
807 ra_debug_msg (DUMP_CONSTRAINTS
,
808 "%d: asm insn or not recognizable.\n", uid
);
811 ra_debug_msg (DUMP_CONSTRAINTS
,
812 "%d: code %d {%s}, %d operands, constraints: ",
813 uid
, code
, insn_data
[code
].name
, recog_data
.n_operands
);
815 /*preprocess_constraints ();*/
816 for (o
= 0; o
< recog_data
.n_operands
; o
++)
818 ra_debug_msg (DUMP_CONSTRAINTS
,
819 "%d:%s ", o
, recog_data
.constraints
[o
]);
821 if (constrain_operands (1))
822 ra_debug_msg (DUMP_CONSTRAINTS
, "matches strictly alternative %d",
825 ra_debug_msg (DUMP_CONSTRAINTS
, "doesn't match strictly");
826 ra_debug_msg (DUMP_CONSTRAINTS
, "\n");
828 for (i
= FIRST_PSEUDO_REGISTER
; i
< ra_max_regno
; i
++)
829 if (regno_reg_rtx
[i
] && GET_CODE (regno_reg_rtx
[i
]) == REG
)
830 REGNO (regno_reg_rtx
[i
]) = i
;
833 /* This counts and emits the cumulated cost of all spilled webs,
834 preceded by a custom message MSG, with debug level LEVEL. */
837 dump_graph_cost (unsigned int level
, const char *msg
)
840 unsigned HOST_WIDE_INT cost
;
841 if (!rtl_dump_file
|| (debug_new_regalloc
& level
) == 0)
845 for (i
= 0; i
< num_webs
; i
++)
847 struct web
*web
= id2web
[i
];
848 if (alias (web
)->type
== SPILLED
)
849 cost
+= web
->orig_spill_cost
;
851 ra_debug_msg (level
, " spill cost of graph (%s) = "
852 HOST_WIDE_INT_PRINT_UNSIGNED
"\n",
853 msg
? msg
: "", cost
);
856 /* Dump the color assignment per web, the coalesced and spilled webs. */
859 dump_ra (struct df
*df ATTRIBUTE_UNUSED
)
863 if (!rtl_dump_file
|| (debug_new_regalloc
& DUMP_RESULTS
) == 0)
866 ra_debug_msg (DUMP_RESULTS
, "\nColored:\n");
867 for (d
= WEBS(COLORED
); d
; d
= d
->next
)
870 ra_debug_msg (DUMP_RESULTS
, " %4d : color %d\n", web
->id
, web
->color
);
872 ra_debug_msg (DUMP_RESULTS
, "\nCoalesced:\n");
873 for (d
= WEBS(COALESCED
); d
; d
= d
->next
)
876 ra_debug_msg (DUMP_RESULTS
, " %4d : to web %d, color %d\n", web
->id
,
877 alias (web
)->id
, web
->color
);
879 ra_debug_msg (DUMP_RESULTS
, "\nSpilled:\n");
880 for (d
= WEBS(SPILLED
); d
; d
= d
->next
)
883 ra_debug_msg (DUMP_RESULTS
, " %4d\n", web
->id
);
885 ra_debug_msg (DUMP_RESULTS
, "\n");
886 dump_cost (DUMP_RESULTS
);
889 /* Calculate and dump the cumulated costs of certain types of insns
890 (loads, stores and copies). */
893 dump_static_insn_cost (FILE *file
, const char *message
, const char *prefix
)
897 unsigned HOST_WIDE_INT cost
;
901 struct cost load
, store
, regcopy
, selfcopy
, overall
;
902 memset (&load
, 0, sizeof(load
));
903 memset (&store
, 0, sizeof(store
));
904 memset (®copy
, 0, sizeof(regcopy
));
905 memset (&selfcopy
, 0, sizeof(selfcopy
));
906 memset (&overall
, 0, sizeof(overall
));
913 unsigned HOST_WIDE_INT block_cost
= bb
->frequency
;
915 for (insn
= BB_HEAD (bb
); insn
; insn
= NEXT_INSN (insn
))
917 /* Yes, yes. We don't calculate the costs precisely.
918 Only for "simple enough" insns. Those containing single
920 if (INSN_P (insn
) && ((set
= single_set (insn
)) != NULL
))
922 rtx src
= SET_SRC (set
);
923 rtx dest
= SET_DEST (set
);
924 struct cost
*pcost
= NULL
;
925 overall
.cost
+= block_cost
;
927 if (rtx_equal_p (src
, dest
))
929 else if (GET_CODE (src
) == GET_CODE (dest
)
930 && ((GET_CODE (src
) == REG
)
931 || (GET_CODE (src
) == SUBREG
932 && GET_CODE (SUBREG_REG (src
)) == REG
933 && GET_CODE (SUBREG_REG (dest
)) == REG
)))
937 if (GET_CODE (src
) == SUBREG
)
938 src
= SUBREG_REG (src
);
939 if (GET_CODE (dest
) == SUBREG
)
940 dest
= SUBREG_REG (dest
);
941 if (GET_CODE (src
) == MEM
&& GET_CODE (dest
) != MEM
942 && memref_is_stack_slot (src
))
944 else if (GET_CODE (src
) != MEM
&& GET_CODE (dest
) == MEM
945 && memref_is_stack_slot (dest
))
950 pcost
->cost
+= block_cost
;
954 if (insn
== BB_END (bb
))
961 fprintf (file
, "static insn cost %s\n", message
? message
: "");
962 fprintf (file
, " %soverall:\tnum=%6d\tcost=% 8" HOST_WIDE_INT_PRINT
"d\n",
963 prefix
, overall
.count
, overall
.cost
);
964 fprintf (file
, " %sloads:\tnum=%6d\tcost=% 8" HOST_WIDE_INT_PRINT
"d\n",
965 prefix
, load
.count
, load
.cost
);
966 fprintf (file
, " %sstores:\tnum=%6d\tcost=% 8" HOST_WIDE_INT_PRINT
"d\n",
967 prefix
, store
.count
, store
.cost
);
968 fprintf (file
, " %sregcopy:\tnum=%6d\tcost=% 8" HOST_WIDE_INT_PRINT
"d\n",
969 prefix
, regcopy
.count
, regcopy
.cost
);
970 fprintf (file
, " %sselfcpy:\tnum=%6d\tcost=% 8" HOST_WIDE_INT_PRINT
"d\n",
971 prefix
, selfcopy
.count
, selfcopy
.cost
);
974 /* Returns nonzero, if WEB1 and WEB2 have some possible
975 hardregs in common. */
978 web_conflicts_p (struct web
*web1
, struct web
*web2
)
980 if (web1
->type
== PRECOLORED
&& web2
->type
== PRECOLORED
)
983 if (web1
->type
== PRECOLORED
)
984 return TEST_HARD_REG_BIT (web2
->usable_regs
, web1
->regno
);
986 if (web2
->type
== PRECOLORED
)
987 return TEST_HARD_REG_BIT (web1
->usable_regs
, web2
->regno
);
989 return hard_regs_intersect_p (&web1
->usable_regs
, &web2
->usable_regs
);
992 /* Dump all uids of insns in which WEB is mentioned. */
995 dump_web_insns (struct web
*web
)
999 ra_debug_msg (DUMP_EVER
, "Web: %i(%i)+%i class: %s freedom: %i degree %i\n",
1000 web
->id
, web
->regno
, web
->add_hardregs
,
1001 reg_class_names
[web
->regclass
],
1002 web
->num_freedom
, web
->num_conflicts
);
1003 ra_debug_msg (DUMP_EVER
, " def insns:");
1005 for (i
= 0; i
< web
->num_defs
; ++i
)
1007 ra_debug_msg (DUMP_EVER
, " %d ", INSN_UID (web
->defs
[i
]->insn
));
1010 ra_debug_msg (DUMP_EVER
, "\n use insns:");
1011 for (i
= 0; i
< web
->num_uses
; ++i
)
1013 ra_debug_msg (DUMP_EVER
, " %d ", INSN_UID (web
->uses
[i
]->insn
));
1015 ra_debug_msg (DUMP_EVER
, "\n");
1018 /* Dump conflicts for web WEB. */
1021 dump_web_conflicts (struct web
*web
)
1026 ra_debug_msg (DUMP_EVER
, "Web: %i(%i)+%i class: %s freedom: %i degree %i\n",
1027 web
->id
, web
->regno
, web
->add_hardregs
,
1028 reg_class_names
[web
->regclass
],
1029 web
->num_freedom
, web
->num_conflicts
);
1031 for (def2
= 0; def2
< num_webs
; def2
++)
1032 if (TEST_BIT (igraph
, igraph_index (web
->id
, def2
)) && web
->id
!= def2
)
1035 ra_debug_msg (DUMP_EVER
, "\n ");
1038 ra_debug_msg (DUMP_EVER
, " %d(%d)", def2
, id2web
[def2
]->regno
);
1039 if (id2web
[def2
]->add_hardregs
)
1040 ra_debug_msg (DUMP_EVER
, "+%d", id2web
[def2
]->add_hardregs
);
1042 if (web_conflicts_p (web
, id2web
[def2
]))
1043 ra_debug_msg (DUMP_EVER
, "/x");
1045 if (id2web
[def2
]->type
== SELECT
)
1046 ra_debug_msg (DUMP_EVER
, "/s");
1048 if (id2web
[def2
]->type
== COALESCED
)
1049 ra_debug_msg (DUMP_EVER
,"/c/%d", alias (id2web
[def2
])->id
);
1051 ra_debug_msg (DUMP_EVER
, "\n");
1053 struct conflict_link
*wl
;
1055 ra_debug_msg (DUMP_EVER
, "By conflicts: ");
1056 for (wl
= web
->conflict_list
; wl
; wl
= wl
->next
)
1058 struct web
* w
= wl
->t
;
1060 ra_debug_msg (DUMP_EVER
, "\n ");
1062 ra_debug_msg (DUMP_EVER
, "%d(%d)%s ", w
->id
, w
->regno
,
1063 web_conflicts_p (web
, w
) ? "+" : "");
1065 ra_debug_msg (DUMP_EVER
, "\n");
1069 /* Output HARD_REG_SET to stderr. */
1072 debug_hard_reg_set (HARD_REG_SET set
)
1075 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; ++i
)
1077 if (TEST_HARD_REG_BIT (set
, i
))
1079 fprintf (stderr
, "%s ", reg_names
[i
]);
1082 fprintf (stderr
, "\n");
1086 vim:cinoptions={.5s,g0,p5,t0,(0,^-0.5s,n-0.5s:tw=78:cindent:sw=4: