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
; insn
; insn
= NEXT_INSN (insn
))
533 ra_print_rtx_top (stderr
, insn
, (insn
== bb
->head
|| insn
== bb
->end
));
534 fprintf (stderr
, "\n");
540 /* Beginning from INSN, emit NUM insns (if NUM is non-negative)
541 or emit a window of NUM insns around INSN, to stderr. */
544 ra_debug_insns (rtx insn
, int num
)
546 int i
, count
= (num
== 0 ? 1 : num
< 0 ? -num
: num
);
548 for (i
= count
/ 2; i
> 0 && PREV_INSN (insn
); i
--)
549 insn
= PREV_INSN (insn
);
550 for (i
= count
; i
> 0 && insn
; insn
= NEXT_INSN (insn
), i
--)
552 if (GET_CODE (insn
) == CODE_LABEL
)
553 fprintf (stderr
, "\n");
554 ra_print_rtx_top (stderr
, insn
, (i
== count
|| i
== 1));
558 /* Beginning with INSN, emit the whole insn chain into FILE.
559 This also outputs comments when basic blocks start or end and omits
560 some notes, if flag_ra_dump_notes is zero. */
563 ra_print_rtl_with_bb (FILE *file
, rtx insn
)
565 basic_block last_bb
, bb
;
566 unsigned int num
= 0;
570 for (; insn
; insn
= NEXT_INSN (insn
))
572 if (GET_CODE (insn
) == BARRIER
)
575 bb
= BLOCK_FOR_INSN (insn
);
579 fprintf (file
, ";; End of basic block %d\n", last_bb
->index
);
581 fprintf (file
, ";; Begin of basic block %d\n", bb
->index
);
584 if (GET_CODE (insn
) == CODE_LABEL
)
586 if (GET_CODE (insn
) == NOTE
)
588 /* Ignore basic block and maybe other notes not referencing
590 if (NOTE_LINE_NUMBER (insn
) != NOTE_INSN_BASIC_BLOCK
591 && (flag_ra_dump_notes
592 || NOTE_LINE_NUMBER (insn
) == NOTE_INSN_DELETED
593 || NOTE_LINE_NUMBER (insn
) == NOTE_INSN_DELETED_LABEL
))
595 ra_print_rtx_top (file
, insn
, (num
== 0 || !NEXT_INSN (insn
)));
601 ra_print_rtx_top (file
, insn
, (num
== 0 || !NEXT_INSN (insn
)));
607 /* Count how many insns were seen how often, while building the interference
608 graph, and prints the findings. */
611 dump_number_seen (void)
617 for (i
= 0; i
< N
; i
++)
619 for (i
= 0; i
< get_max_uid (); i
++)
620 if (number_seen
[i
] < N
- 1)
621 num
[number_seen
[i
]]++;
624 for (i
= 0; i
< N
- 1; i
++)
626 ra_debug_msg (DUMP_PROCESS
, "%d insns seen %d times\n", num
[i
], i
);
628 ra_debug_msg (DUMP_PROCESS
, "%d insns seen %d and more times\n", num
[i
],
630 ra_debug_msg (DUMP_PROCESS
, "from overall %d insns\n", get_max_uid ());
634 /* Dump the interference graph, the move list and the webs. */
637 dump_igraph (struct df
*df ATTRIBUTE_UNUSED
)
639 struct move_list
*ml
;
640 unsigned int def1
, def2
;
644 if (!rtl_dump_file
|| (debug_new_regalloc
& (DUMP_IGRAPH
| DUMP_WEBS
)) == 0)
646 ra_debug_msg (DUMP_IGRAPH
, "conflicts:\n ");
647 for (def1
= 0; def1
< num_webs
; def1
++)
651 for (def2
= 0; def2
< num_webs
; def2
++)
652 if (def1
!= def2
&& TEST_BIT (igraph
, igraph_index (def1
, def2
)))
656 if (SUBWEB_P (ID2WEB (def1
)))
657 ra_debug_msg (DUMP_IGRAPH
, "%d (SUBREG %d, %d) with ", def1
,
658 ID2WEB (def1
)->regno
,
659 SUBREG_BYTE (ID2WEB (def1
)->orig_x
));
661 ra_debug_msg (DUMP_IGRAPH
, "%d (REG %d) with ", def1
,
662 ID2WEB (def1
)->regno
);
665 ra_debug_msg (DUMP_IGRAPH
, "\n ");
668 if (SUBWEB_P (ID2WEB (def2
)))
669 ra_debug_msg (DUMP_IGRAPH
, "%d(%d,%d) ", def2
, ID2WEB (def2
)->regno
,
670 SUBREG_BYTE (ID2WEB (def2
)->orig_x
));
672 ra_debug_msg (DUMP_IGRAPH
, "%d(%d) ", def2
, ID2WEB (def2
)->regno
);
675 ra_debug_msg (DUMP_IGRAPH
, "\n ");
677 ra_debug_msg (DUMP_IGRAPH
, "\n");
678 for (ml
= wl_moves
; ml
; ml
= ml
->next
)
681 ra_debug_msg (DUMP_IGRAPH
, "move: insn %d: Web %d <-- Web %d\n",
682 INSN_UID (ml
->move
->insn
), ml
->move
->target_web
->id
,
683 ml
->move
->source_web
->id
);
685 ra_debug_msg (DUMP_WEBS
, "\nWebs:\n");
686 for (i
= 0; i
< num_webs
; i
++)
688 struct web
*web
= ID2WEB (i
);
690 ra_debug_msg (DUMP_WEBS
, " %4d : regno %3d", i
, web
->regno
);
693 ra_debug_msg (DUMP_WEBS
, " sub %d", SUBREG_BYTE (web
->orig_x
));
694 ra_debug_msg (DUMP_WEBS
, " par %d", find_web_for_subweb (web
)->id
);
696 ra_debug_msg (DUMP_WEBS
, " +%d (span %d, cost "
697 HOST_WIDE_INT_PRINT_DEC
") (%s)",
698 web
->add_hardregs
, web
->span_deaths
, web
->spill_cost
,
699 reg_class_names
[web
->regclass
]);
700 if (web
->spill_temp
== 1)
701 ra_debug_msg (DUMP_WEBS
, " (spilltemp)");
702 else if (web
->spill_temp
== 2)
703 ra_debug_msg (DUMP_WEBS
, " (spilltem2)");
704 else if (web
->spill_temp
== 3)
705 ra_debug_msg (DUMP_WEBS
, " (short)");
706 if (web
->type
== PRECOLORED
)
707 ra_debug_msg (DUMP_WEBS
, " (precolored, color=%d)", web
->color
);
708 else if (find_web_for_subweb (web
)->num_uses
== 0)
709 ra_debug_msg (DUMP_WEBS
, " dead");
710 if (web
->crosses_call
)
711 ra_debug_msg (DUMP_WEBS
, " xcall");
712 if (web
->regno
>= max_normal_pseudo
)
713 ra_debug_msg (DUMP_WEBS
, " stack");
714 ra_debug_msg (DUMP_WEBS
, "\n");
718 /* Dump the interference graph and webs in a format easily
719 parsable by programs. Used to emit real world interference graph
720 to my custom graph colorizer. */
723 dump_igraph_machine (void)
727 if (!rtl_dump_file
|| (debug_new_regalloc
& DUMP_IGRAPH_M
) == 0)
729 ra_debug_msg (DUMP_IGRAPH_M
, "g %d %d\n", num_webs
- num_subwebs
,
730 FIRST_PSEUDO_REGISTER
);
731 for (i
= 0; i
< num_webs
- num_subwebs
; i
++)
733 struct web
*web
= ID2WEB (i
);
734 struct conflict_link
*cl
;
738 flags
= web
->spill_temp
& 0xF;
739 flags
|= ((web
->type
== PRECOLORED
) ? 1 : 0) << 4;
740 flags
|= (web
->add_hardregs
& 0xF) << 5;
741 for (cl
= web
->conflict_list
; cl
; cl
= cl
->next
)
742 if (cl
->t
->id
< web
->id
)
744 ra_debug_msg (DUMP_IGRAPH_M
, "n %d %d %d %d %d %d %d\n",
745 web
->id
, web
->color
, flags
,
746 (unsigned int)web
->spill_cost
, web
->num_defs
, web
->num_uses
,
748 if (web
->type
!= PRECOLORED
)
750 ra_debug_msg (DUMP_IGRAPH_M
, "s %d", web
->id
);
755 for (n
= 0; n
< 32 && col
< FIRST_PSEUDO_REGISTER
; n
++, col
++)
756 if (TEST_HARD_REG_BIT (web
->usable_regs
, col
))
758 ra_debug_msg (DUMP_IGRAPH_M
, " %u", u
);
759 if (col
>= FIRST_PSEUDO_REGISTER
)
762 ra_debug_msg (DUMP_IGRAPH_M
, "\n");
766 ra_debug_msg (DUMP_IGRAPH_M
, "c %d", web
->id
);
767 for (cl
= web
->conflict_list
; cl
; cl
= cl
->next
)
769 if (cl
->t
->id
< web
->id
)
770 ra_debug_msg (DUMP_IGRAPH_M
, " %d", cl
->t
->id
);
772 ra_debug_msg (DUMP_IGRAPH_M
, "\n");
775 ra_debug_msg (DUMP_IGRAPH_M
, "e\n");
778 /* This runs after colorization and changing the insn stream.
779 It temporarily replaces all pseudo registers with their colors,
780 and emits information, if the resulting insns are strictly valid. */
783 dump_constraints (void)
787 if (!rtl_dump_file
|| (debug_new_regalloc
& DUMP_CONSTRAINTS
) == 0)
789 for (i
= FIRST_PSEUDO_REGISTER
; i
< ra_max_regno
; i
++)
790 if (regno_reg_rtx
[i
] && GET_CODE (regno_reg_rtx
[i
]) == REG
)
791 REGNO (regno_reg_rtx
[i
])
792 = ra_reg_renumber
[i
] >= 0 ? ra_reg_renumber
[i
] : i
;
793 for (insn
= get_insns (); insn
; insn
= NEXT_INSN (insn
))
797 int uid
= INSN_UID (insn
);
799 /* Don't simply force rerecognition, as combine might left us
800 with some unrecognizable ones, which later leads to aborts
801 in regclass, if we now destroy the remembered INSN_CODE(). */
802 /*INSN_CODE (insn) = -1;*/
803 code
= recog_memoized (insn
);
806 ra_debug_msg (DUMP_CONSTRAINTS
,
807 "%d: asm insn or not recognizable.\n", uid
);
810 ra_debug_msg (DUMP_CONSTRAINTS
,
811 "%d: code %d {%s}, %d operands, constraints: ",
812 uid
, code
, insn_data
[code
].name
, recog_data
.n_operands
);
814 /*preprocess_constraints ();*/
815 for (o
= 0; o
< recog_data
.n_operands
; o
++)
817 ra_debug_msg (DUMP_CONSTRAINTS
,
818 "%d:%s ", o
, recog_data
.constraints
[o
]);
820 if (constrain_operands (1))
821 ra_debug_msg (DUMP_CONSTRAINTS
, "matches strictly alternative %d",
824 ra_debug_msg (DUMP_CONSTRAINTS
, "doesn't match strictly");
825 ra_debug_msg (DUMP_CONSTRAINTS
, "\n");
827 for (i
= FIRST_PSEUDO_REGISTER
; i
< ra_max_regno
; i
++)
828 if (regno_reg_rtx
[i
] && GET_CODE (regno_reg_rtx
[i
]) == REG
)
829 REGNO (regno_reg_rtx
[i
]) = i
;
832 /* This counts and emits the cumulated cost of all spilled webs,
833 preceded by a custom message MSG, with debug level LEVEL. */
836 dump_graph_cost (unsigned int level
, const char *msg
)
839 unsigned HOST_WIDE_INT cost
;
840 if (!rtl_dump_file
|| (debug_new_regalloc
& level
) == 0)
844 for (i
= 0; i
< num_webs
; i
++)
846 struct web
*web
= id2web
[i
];
847 if (alias (web
)->type
== SPILLED
)
848 cost
+= web
->orig_spill_cost
;
850 ra_debug_msg (level
, " spill cost of graph (%s) = "
851 HOST_WIDE_INT_PRINT_UNSIGNED
"\n",
852 msg
? msg
: "", cost
);
855 /* Dump the color assignment per web, the coalesced and spilled webs. */
858 dump_ra (struct df
*df ATTRIBUTE_UNUSED
)
862 if (!rtl_dump_file
|| (debug_new_regalloc
& DUMP_RESULTS
) == 0)
865 ra_debug_msg (DUMP_RESULTS
, "\nColored:\n");
866 for (d
= WEBS(COLORED
); d
; d
= d
->next
)
869 ra_debug_msg (DUMP_RESULTS
, " %4d : color %d\n", web
->id
, web
->color
);
871 ra_debug_msg (DUMP_RESULTS
, "\nCoalesced:\n");
872 for (d
= WEBS(COALESCED
); d
; d
= d
->next
)
875 ra_debug_msg (DUMP_RESULTS
, " %4d : to web %d, color %d\n", web
->id
,
876 alias (web
)->id
, web
->color
);
878 ra_debug_msg (DUMP_RESULTS
, "\nSpilled:\n");
879 for (d
= WEBS(SPILLED
); d
; d
= d
->next
)
882 ra_debug_msg (DUMP_RESULTS
, " %4d\n", web
->id
);
884 ra_debug_msg (DUMP_RESULTS
, "\n");
885 dump_cost (DUMP_RESULTS
);
888 /* Calculate and dump the cumulated costs of certain types of insns
889 (loads, stores and copies). */
892 dump_static_insn_cost (FILE *file
, const char *message
, const char *prefix
)
896 unsigned HOST_WIDE_INT cost
;
900 struct cost load
, store
, regcopy
, selfcopy
, overall
;
901 memset (&load
, 0, sizeof(load
));
902 memset (&store
, 0, sizeof(store
));
903 memset (®copy
, 0, sizeof(regcopy
));
904 memset (&selfcopy
, 0, sizeof(selfcopy
));
905 memset (&overall
, 0, sizeof(overall
));
912 unsigned HOST_WIDE_INT block_cost
= bb
->frequency
;
914 for (insn
= bb
->head
; insn
; insn
= NEXT_INSN (insn
))
916 /* Yes, yes. We don't calculate the costs precisely.
917 Only for "simple enough" insns. Those containing single
919 if (INSN_P (insn
) && ((set
= single_set (insn
)) != NULL
))
921 rtx src
= SET_SRC (set
);
922 rtx dest
= SET_DEST (set
);
923 struct cost
*pcost
= NULL
;
924 overall
.cost
+= block_cost
;
926 if (rtx_equal_p (src
, dest
))
928 else if (GET_CODE (src
) == GET_CODE (dest
)
929 && ((GET_CODE (src
) == REG
)
930 || (GET_CODE (src
) == SUBREG
931 && GET_CODE (SUBREG_REG (src
)) == REG
932 && GET_CODE (SUBREG_REG (dest
)) == REG
)))
936 if (GET_CODE (src
) == SUBREG
)
937 src
= SUBREG_REG (src
);
938 if (GET_CODE (dest
) == SUBREG
)
939 dest
= SUBREG_REG (dest
);
940 if (GET_CODE (src
) == MEM
&& GET_CODE (dest
) != MEM
941 && memref_is_stack_slot (src
))
943 else if (GET_CODE (src
) != MEM
&& GET_CODE (dest
) == MEM
944 && memref_is_stack_slot (dest
))
949 pcost
->cost
+= block_cost
;
960 fprintf (file
, "static insn cost %s\n", message
? message
: "");
961 fprintf (file
, " %soverall:\tnum=%6d\tcost=% 8" HOST_WIDE_INT_PRINT
"d\n",
962 prefix
, overall
.count
, overall
.cost
);
963 fprintf (file
, " %sloads:\tnum=%6d\tcost=% 8" HOST_WIDE_INT_PRINT
"d\n",
964 prefix
, load
.count
, load
.cost
);
965 fprintf (file
, " %sstores:\tnum=%6d\tcost=% 8" HOST_WIDE_INT_PRINT
"d\n",
966 prefix
, store
.count
, store
.cost
);
967 fprintf (file
, " %sregcopy:\tnum=%6d\tcost=% 8" HOST_WIDE_INT_PRINT
"d\n",
968 prefix
, regcopy
.count
, regcopy
.cost
);
969 fprintf (file
, " %sselfcpy:\tnum=%6d\tcost=% 8" HOST_WIDE_INT_PRINT
"d\n",
970 prefix
, selfcopy
.count
, selfcopy
.cost
);
973 /* Returns nonzero, if WEB1 and WEB2 have some possible
974 hardregs in common. */
977 web_conflicts_p (struct web
*web1
, struct web
*web2
)
979 if (web1
->type
== PRECOLORED
&& web2
->type
== PRECOLORED
)
982 if (web1
->type
== PRECOLORED
)
983 return TEST_HARD_REG_BIT (web2
->usable_regs
, web1
->regno
);
985 if (web2
->type
== PRECOLORED
)
986 return TEST_HARD_REG_BIT (web1
->usable_regs
, web2
->regno
);
988 return hard_regs_intersect_p (&web1
->usable_regs
, &web2
->usable_regs
);
991 /* Dump all uids of insns in which WEB is mentioned. */
994 dump_web_insns (struct web
*web
)
998 ra_debug_msg (DUMP_EVER
, "Web: %i(%i)+%i class: %s freedom: %i degree %i\n",
999 web
->id
, web
->regno
, web
->add_hardregs
,
1000 reg_class_names
[web
->regclass
],
1001 web
->num_freedom
, web
->num_conflicts
);
1002 ra_debug_msg (DUMP_EVER
, " def insns:");
1004 for (i
= 0; i
< web
->num_defs
; ++i
)
1006 ra_debug_msg (DUMP_EVER
, " %d ", INSN_UID (web
->defs
[i
]->insn
));
1009 ra_debug_msg (DUMP_EVER
, "\n use insns:");
1010 for (i
= 0; i
< web
->num_uses
; ++i
)
1012 ra_debug_msg (DUMP_EVER
, " %d ", INSN_UID (web
->uses
[i
]->insn
));
1014 ra_debug_msg (DUMP_EVER
, "\n");
1017 /* Dump conflicts for web WEB. */
1020 dump_web_conflicts (struct web
*web
)
1025 ra_debug_msg (DUMP_EVER
, "Web: %i(%i)+%i class: %s freedom: %i degree %i\n",
1026 web
->id
, web
->regno
, web
->add_hardregs
,
1027 reg_class_names
[web
->regclass
],
1028 web
->num_freedom
, web
->num_conflicts
);
1030 for (def2
= 0; def2
< num_webs
; def2
++)
1031 if (TEST_BIT (igraph
, igraph_index (web
->id
, def2
)) && web
->id
!= def2
)
1034 ra_debug_msg (DUMP_EVER
, "\n ");
1037 ra_debug_msg (DUMP_EVER
, " %d(%d)", def2
, id2web
[def2
]->regno
);
1038 if (id2web
[def2
]->add_hardregs
)
1039 ra_debug_msg (DUMP_EVER
, "+%d", id2web
[def2
]->add_hardregs
);
1041 if (web_conflicts_p (web
, id2web
[def2
]))
1042 ra_debug_msg (DUMP_EVER
, "/x");
1044 if (id2web
[def2
]->type
== SELECT
)
1045 ra_debug_msg (DUMP_EVER
, "/s");
1047 if (id2web
[def2
]->type
== COALESCED
)
1048 ra_debug_msg (DUMP_EVER
,"/c/%d", alias (id2web
[def2
])->id
);
1050 ra_debug_msg (DUMP_EVER
, "\n");
1052 struct conflict_link
*wl
;
1054 ra_debug_msg (DUMP_EVER
, "By conflicts: ");
1055 for (wl
= web
->conflict_list
; wl
; wl
= wl
->next
)
1057 struct web
* w
= wl
->t
;
1059 ra_debug_msg (DUMP_EVER
, "\n ");
1061 ra_debug_msg (DUMP_EVER
, "%d(%d)%s ", w
->id
, w
->regno
,
1062 web_conflicts_p (web
, w
) ? "+" : "");
1064 ra_debug_msg (DUMP_EVER
, "\n");
1068 /* Output HARD_REG_SET to stderr. */
1071 debug_hard_reg_set (HARD_REG_SET set
)
1074 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; ++i
)
1076 if (TEST_HARD_REG_BIT (set
, i
))
1078 fprintf (stderr
, "%s ", reg_names
[i
]);
1081 fprintf (stderr
, "\n");
1085 vim:cinoptions={.5s,g0,p5,t0,(0,^-0.5s,n-0.5s:tw=78:cindent:sw=4: