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. */
24 #include "insn-config.h"
27 #include "hard-reg-set.h"
28 #include "basic-block.h"
33 /* This file contains various dumping and debug functions for
34 the graph coloring register allocator. */
36 static void ra_print_rtx_1op
PARAMS ((FILE *, rtx
));
37 static void ra_print_rtx_2op
PARAMS ((FILE *, rtx
));
38 static void ra_print_rtx_3op
PARAMS ((FILE *, rtx
));
39 static void ra_print_rtx_object
PARAMS ((FILE *, rtx
));
41 /* The hardregs as names, for debugging. */
42 static const char *const reg_class_names
[] = REG_CLASS_NAMES
;
44 /* Print a message to the dump file, if debug_new_regalloc and LEVEL
45 have any bits in common. */
48 ra_debug_msg
VPARAMS ((unsigned int level
, const char *format
, ...))
50 #ifndef ANSI_PROTOTYPES
55 if ((debug_new_regalloc
& level
) != 0 && rtl_dump_file
!= NULL
)
57 VA_START (ap
, format
);
59 #ifndef ANSI_PROTOTYPES
60 format
= va_arg (ap
, const char *);
63 vfprintf (rtl_dump_file
, format
, ap
);
69 /* The following ra_print_xxx() functions print RTL expressions
70 in concise infix form. If the mode can be seen from context it's
71 left out. Most operators are represented by their graphical
72 characters, e.g. LE as "<=". Unknown constructs are currently
73 printed with print_inline_rtx(), which disrupts the nice layout.
74 Currently only the inline asm things are written this way. */
76 /* Print rtx X, which is a one operand rtx (op:mode (Y)), as
80 ra_print_rtx_1op (file
, x
)
84 enum rtx_code code
= GET_CODE (x
);
85 rtx op0
= XEXP (x
, 0);
90 fputs ((code
== NEG
) ? "-(" : "~(", file
);
91 ra_print_rtx (file
, op0
, 0);
96 ra_print_rtx (file
, op0
, 0);
100 fprintf (file
, "%s", GET_RTX_NAME (code
));
101 if (GET_MODE (x
) != VOIDmode
)
102 fprintf (file
, ":%s(", GET_MODE_NAME (GET_MODE (x
)));
105 ra_print_rtx (file
, op0
, 0);
111 /* Print rtx X, which is a two operand rtx (op:mode (Y) (Z))
112 as "(Y op Z)", if the operand is know, or as "op(Y, Z)", if not,
116 ra_print_rtx_2op (file
, x
)
121 const char *opname
= "shitop";
122 enum rtx_code code
= GET_CODE (x
);
123 rtx op0
= XEXP (x
, 0);
124 rtx op1
= XEXP (x
, 1);
128 case COMPARE
: opname
= "?"; break;
129 case MINUS
: opname
= "-"; break;
130 case DIV
: opname
= "/"; break;
131 case UDIV
: opname
= "u/"; break;
132 case MOD
: opname
= "%"; break;
133 case UMOD
: opname
= "u%"; break;
134 case ASHIFT
: opname
= "<<"; break;
135 case ASHIFTRT
: opname
= "a>>"; break;
136 case LSHIFTRT
: opname
= "l>>"; break;
138 case PLUS
: opname
= "+"; break;
139 case MULT
: opname
= "*"; break;
140 case AND
: opname
= "&"; break;
141 case IOR
: opname
= "|"; break;
142 case XOR
: opname
= "^"; break;
144 case NE
: opname
= "!="; break;
145 case EQ
: opname
= "=="; break;
146 case GE
: opname
= "s>="; break;
147 case GT
: opname
= "s>"; break;
148 case LE
: opname
= "s<="; break;
149 case LT
: opname
= "s<"; break;
150 case GEU
: opname
= "u>="; break;
151 case GTU
: opname
= "u>"; break;
152 case LEU
: opname
= "u<="; break;
153 case LTU
: opname
= "u<"; break;
156 opname
= GET_RTX_NAME (code
);
162 ra_print_rtx (file
, op0
, 0);
163 fprintf (file
, " %s ", opname
);
164 ra_print_rtx (file
, op1
, 0);
169 fprintf (file
, "%s(", opname
);
170 ra_print_rtx (file
, op0
, 0);
172 ra_print_rtx (file
, op1
, 0);
177 /* Print rtx X, which a three operand rtx to FILE.
178 I.e. X is either an IF_THEN_ELSE, or a bitmap operation. */
181 ra_print_rtx_3op (file
, x
)
185 enum rtx_code code
= GET_CODE (x
);
186 rtx op0
= XEXP (x
, 0);
187 rtx op1
= XEXP (x
, 1);
188 rtx op2
= XEXP (x
, 2);
189 if (code
== IF_THEN_ELSE
)
191 ra_print_rtx (file
, op0
, 0);
193 ra_print_rtx (file
, op1
, 0);
195 ra_print_rtx (file
, op2
, 0);
199 /* Bitmap-operation */
200 fprintf (file
, "%s:%s(", GET_RTX_NAME (code
),
201 GET_MODE_NAME (GET_MODE (x
)));
202 ra_print_rtx (file
, op0
, 0);
204 ra_print_rtx (file
, op1
, 0);
206 ra_print_rtx (file
, op2
, 0);
211 /* Print rtx X, which represents an object (class 'o' or some constructs
212 of class 'x' (e.g. subreg)), to FILE.
213 (reg XX) rtl is represented as "pXX", of XX was a pseudo,
214 as "name" it name is the nonnull hardreg name, or as "hXX", if XX
215 is a hardreg, whose name is NULL, or empty. */
218 ra_print_rtx_object (file
, x
)
222 enum rtx_code code
= GET_CODE (x
);
223 enum machine_mode mode
= GET_MODE (x
);
227 fprintf (file
, HOST_WIDE_INT_PRINT_DEC
, XWINT (x
, 0));
232 const char *fmt
= GET_RTX_FORMAT (code
);
233 fputs ("dbl(", file
);
234 for (i
= 0; i
< GET_RTX_LENGTH (code
); i
++)
238 if (fmt
[i
] == 'e' && XEXP (x
, i
))
239 /* The MEM or other stuff */
241 ra_print_rtx (file
, XEXP (x
, i
), 0);
244 else if (fmt
[i
] == 'w')
246 fprintf (file
, HOST_WIDE_INT_PRINT_HEX
, XWINT (x
, i
));
252 case CONST_STRING
: fprintf (file
, "\"%s\"", XSTR (x
, 0)); break;
253 case CONST
: fputs ("const(", file
);
254 ra_print_rtx (file
, XEXP (x
, 0), 0);
257 case PC
: fputs ("pc", file
); break;
260 int regno
= REGNO (x
);
261 if (regno
< FIRST_PSEUDO_REGISTER
)
263 int i
, nregs
= HARD_REGNO_NREGS (regno
, mode
);
266 for (i
= 0; i
< nregs
; i
++)
270 if (reg_names
[regno
+i
] && *reg_names
[regno
+ i
])
271 fprintf (file
, "%s", reg_names
[regno
+ i
]);
273 fprintf (file
, "h%d", regno
+ i
);
279 fprintf (file
, "p%d", regno
);
284 rtx sub
= SUBREG_REG (x
);
285 int ofs
= SUBREG_BYTE (x
);
286 if (GET_CODE (sub
) == REG
287 && REGNO (sub
) < FIRST_PSEUDO_REGISTER
)
289 int regno
= REGNO (sub
);
290 int i
, nregs
= HARD_REGNO_NREGS (regno
, mode
);
291 regno
+= subreg_regno_offset (regno
, GET_MODE (sub
),
295 for (i
= 0; i
< nregs
; i
++)
299 if (reg_names
[regno
+i
])
300 fprintf (file
, "%s", reg_names
[regno
+ i
]);
302 fprintf (file
, "h%d", regno
+ i
);
309 ra_print_rtx (file
, sub
, 0);
310 fprintf (file
, ":[%s+%d]", GET_MODE_NAME (mode
), ofs
);
314 case SCRATCH
: fputs ("scratch", file
); break;
315 case CONCAT
: ra_print_rtx_2op (file
, x
); break;
316 case HIGH
: ra_print_rtx_1op (file
, x
); break;
319 ra_print_rtx (file
, XEXP (x
, 0), 0);
320 fputs (" + lo(", file
);
321 ra_print_rtx (file
, XEXP (x
, 1), 0);
324 case MEM
: fputs ("[", file
);
325 ra_print_rtx (file
, XEXP (x
, 0), 0);
326 fprintf (file
, "]:%s", GET_MODE_NAME (GET_MODE (x
)));
327 /* XXX print alias set too ?? */
331 rtx sub
= XEXP (x
, 0);
332 if (GET_CODE (sub
) == NOTE
333 && NOTE_LINE_NUMBER (sub
) == NOTE_INSN_DELETED_LABEL
)
334 fprintf (file
, "(deleted uid=%d)", INSN_UID (sub
));
335 else if (GET_CODE (sub
) == CODE_LABEL
)
336 fprintf (file
, "L%d", CODE_LABEL_NUMBER (sub
));
338 fprintf (file
, "(nonlabel uid=%d)", INSN_UID (sub
));
342 fprintf (file
, "sym(\"%s\")", XSTR (x
, 0)); break;
343 case CC0
: fputs ("cc0", file
); break;
344 default: print_inline_rtx (file
, x
, 0); break;
348 /* Print a general rtx X to FILE in nice infix form.
349 If WITH_PN is set, and X is one of the toplevel constructs
350 (insns, notes, labels or barriers), then print also the UIDs of
351 the preceding and following insn. */
354 ra_print_rtx (file
, x
, with_pn
)
365 class = GET_RTX_CLASS (code
);
367 /* First handle the insn like constructs. */
368 if (INSN_P (x
) || code
== NOTE
|| code
== CODE_LABEL
|| code
== BARRIER
)
372 /* Non-insns are prefixed by a ';'. */
375 else if (code
== NOTE
)
376 /* But notes are indented very far right. */
377 fprintf (file
, "\t\t\t\t\t; ");
378 else if (code
== CODE_LABEL
)
379 /* And labels have their Lxx name first, before the actual UID. */
381 fprintf (file
, "L%d:\t; ", CODE_LABEL_NUMBER (x
));
383 fprintf (file
, "(%s) ", LABEL_NAME (x
));
384 switch (LABEL_KIND (x
))
386 case LABEL_NORMAL
: break;
387 case LABEL_STATIC_ENTRY
: fputs (" (entry)", file
); break;
388 case LABEL_GLOBAL_ENTRY
: fputs (" (global entry)", file
); break;
389 case LABEL_WEAK_ENTRY
: fputs (" (weak entry)", file
); break;
392 fprintf (file
, " [%d uses] uid=(", LABEL_NUSES (x
));
394 fprintf (file
, "%d", INSN_UID (x
));
396 fprintf (file
, " %d %d", PREV_INSN (x
) ? INSN_UID (PREV_INSN (x
)) : 0,
397 NEXT_INSN (x
) ? INSN_UID (NEXT_INSN (x
)) : 0);
399 fputs (" -------- barrier ---------", file
);
400 else if (code
== CODE_LABEL
)
402 else if (code
== NOTE
)
404 int ln
= NOTE_LINE_NUMBER (x
);
405 if (ln
>= (int) NOTE_INSN_BIAS
&& ln
< (int) NOTE_INSN_MAX
)
406 fprintf (file
, " %s", GET_NOTE_INSN_NAME (ln
));
409 fprintf (file
, " line %d", ln
);
410 if (NOTE_SOURCE_FILE (x
))
411 fprintf (file
, ":%s", NOTE_SOURCE_FILE (x
));
416 fprintf (file
, "\t");
417 ra_print_rtx (file
, PATTERN (x
), 0);
423 /* Top-level stuff. */
427 for (j
= 0; j
< XVECLEN (x
, 0); j
++)
430 fputs ("\t;; ", file
);
431 ra_print_rtx (file
, XVECEXP (x
, 0, j
), 0);
435 case UNSPEC
: case UNSPEC_VOLATILE
:
438 fprintf (file
, "unspec%s(%d",
439 (code
== UNSPEC
) ? "" : "_vol", XINT (x
, 1));
440 for (j
= 0; j
< XVECLEN (x
, 0); j
++)
443 ra_print_rtx (file
, XVECEXP (x
, 0, j
), 0);
449 if (GET_CODE (SET_DEST (x
)) == PC
)
451 if (GET_CODE (SET_SRC (x
)) == IF_THEN_ELSE
452 && GET_CODE (XEXP (SET_SRC(x
), 2)) == PC
)
455 ra_print_rtx (file
, XEXP (SET_SRC (x
), 0), 0);
456 fputs (" jump ", file
);
457 ra_print_rtx (file
, XEXP (SET_SRC (x
), 1), 0);
461 fputs ("jump ", file
);
462 ra_print_rtx (file
, SET_SRC (x
), 0);
467 ra_print_rtx (file
, SET_DEST (x
), 0);
468 fputs (" <= ", file
);
469 ra_print_rtx (file
, SET_SRC (x
), 0);
473 fputs ("use <= ", file
);
474 ra_print_rtx (file
, XEXP (x
, 0), 0);
477 ra_print_rtx (file
, XEXP (x
, 0), 0);
478 fputs (" <= clobber", file
);
481 fputs ("call ", file
);
482 ra_print_rtx (file
, XEXP (x
, 0), 0); /* Address */
483 fputs (" numargs=", file
);
484 ra_print_rtx (file
, XEXP (x
, 1), 0); /* Num arguments */
487 fputs ("return", file
);
490 fputs ("if (", file
);
491 ra_print_rtx (file
, XEXP (x
, 0), 0);
492 fputs (") trap ", file
);
493 ra_print_rtx (file
, XEXP (x
, 1), 0);
496 fprintf (file
, "resx from region %d", XINT (x
, 0));
499 /* Different things of class 'x' */
500 case SUBREG
: ra_print_rtx_object (file
, x
); break;
501 case STRICT_LOW_PART
:
502 fputs ("low(", file
);
503 ra_print_rtx (file
, XEXP (x
, 0), 0);
513 ra_print_rtx_1op (file
, x
);
514 else if (class == '2' || class == 'c' || class == '<')
515 ra_print_rtx_2op (file
, x
);
516 else if (class == '3' || class == 'b')
517 ra_print_rtx_3op (file
, x
);
518 else if (class == 'o')
519 ra_print_rtx_object (file
, x
);
521 print_inline_rtx (file
, x
, 0);
524 /* This only calls ra_print_rtx(), but emits a final newline. */
527 ra_print_rtx_top (file
, x
, with_pn
)
532 ra_print_rtx (file
, x
, with_pn
);
533 fprintf (file
, "\n");
536 /* Callable from gdb. This prints rtx X onto stderr. */
542 ra_print_rtx_top (stderr
, x
, 1);
545 /* This prints the content of basic block with index BBI.
546 The first and last insn are emitted with UIDs of prev and next insns. */
552 basic_block bb
= BASIC_BLOCK (bbi
);
554 for (insn
= bb
->head
; insn
; insn
= NEXT_INSN (insn
))
556 ra_print_rtx_top (stderr
, insn
, (insn
== bb
->head
|| insn
== bb
->end
));
557 fprintf (stderr
, "\n");
563 /* Beginning from INSN, emit NUM insns (if NUM is non-negative)
564 or emit a window of NUM insns around INSN, to stderr. */
567 ra_debug_insns (insn
, num
)
571 int i
, count
= (num
== 0 ? 1 : num
< 0 ? -num
: num
);
573 for (i
= count
/ 2; i
> 0 && PREV_INSN (insn
); i
--)
574 insn
= PREV_INSN (insn
);
575 for (i
= count
; i
> 0 && insn
; insn
= NEXT_INSN (insn
), i
--)
577 if (GET_CODE (insn
) == CODE_LABEL
)
578 fprintf (stderr
, "\n");
579 ra_print_rtx_top (stderr
, insn
, (i
== count
|| i
== 1));
583 /* Beginning with INSN, emit the whole insn chain into FILE.
584 This also outputs comments when basic blocks start or end and omits
585 some notes, if flag_ra_dump_notes is zero. */
588 ra_print_rtl_with_bb (file
, insn
)
592 basic_block last_bb
, bb
;
593 unsigned int num
= 0;
597 for (; insn
; insn
= NEXT_INSN (insn
))
599 if (GET_CODE (insn
) == BARRIER
)
602 bb
= BLOCK_FOR_INSN (insn
);
606 fprintf (file
, ";; End of basic block %d\n", last_bb
->index
);
608 fprintf (file
, ";; Begin of basic block %d\n", bb
->index
);
611 if (GET_CODE (insn
) == CODE_LABEL
)
613 if (GET_CODE (insn
) == NOTE
)
615 /* Ignore basic block and maybe other notes not referencing
617 if (NOTE_LINE_NUMBER (insn
) != NOTE_INSN_BASIC_BLOCK
618 && (flag_ra_dump_notes
619 || NOTE_LINE_NUMBER (insn
) == NOTE_INSN_DELETED
620 || NOTE_LINE_NUMBER (insn
) == NOTE_INSN_DELETED_LABEL
))
622 ra_print_rtx_top (file
, insn
, (num
== 0 || !NEXT_INSN (insn
)));
628 ra_print_rtx_top (file
, insn
, (num
== 0 || !NEXT_INSN (insn
)));
634 /* Count how many insns were seen how often, while building the interference
635 graph, and prints the findings. */
644 for (i
= 0; i
< N
; i
++)
646 for (i
= 0; i
< get_max_uid (); i
++)
647 if (number_seen
[i
] < N
- 1)
648 num
[number_seen
[i
]]++;
651 for (i
= 0; i
< N
- 1; i
++)
653 ra_debug_msg (DUMP_PROCESS
, "%d insns seen %d times\n", num
[i
], i
);
655 ra_debug_msg (DUMP_PROCESS
, "%d insns seen %d and more times\n", num
[i
],
657 ra_debug_msg (DUMP_PROCESS
, "from overall %d insns\n", get_max_uid ());
661 /* Dump the interference graph, the move list and the webs. */
665 struct df
*df ATTRIBUTE_UNUSED
;
667 struct move_list
*ml
;
668 unsigned int def1
, def2
;
672 if (!rtl_dump_file
|| (debug_new_regalloc
& (DUMP_IGRAPH
| DUMP_WEBS
)) == 0)
674 ra_debug_msg (DUMP_IGRAPH
, "conflicts:\n ");
675 for (def1
= 0; def1
< num_webs
; def1
++)
678 for (num2
=0, def2
= 0; def2
< num_webs
; def2
++)
679 if (def1
!= def2
&& TEST_BIT (igraph
, igraph_index (def1
, def2
)))
683 if (SUBWEB_P (ID2WEB (def1
)))
684 ra_debug_msg (DUMP_IGRAPH
, "%d (SUBREG %d, %d) with ", def1
,
685 ID2WEB (def1
)->regno
,
686 SUBREG_BYTE (ID2WEB (def1
)->orig_x
));
688 ra_debug_msg (DUMP_IGRAPH
, "%d (REG %d) with ", def1
,
689 ID2WEB (def1
)->regno
);
692 ra_debug_msg (DUMP_IGRAPH
, "\n ");
695 if (SUBWEB_P (ID2WEB (def2
)))
696 ra_debug_msg (DUMP_IGRAPH
, "%d(%d,%d) ", def2
, ID2WEB (def2
)->regno
,
697 SUBREG_BYTE (ID2WEB (def2
)->orig_x
));
699 ra_debug_msg (DUMP_IGRAPH
, "%d(%d) ", def2
, ID2WEB (def2
)->regno
);
702 ra_debug_msg (DUMP_IGRAPH
, "\n ");
704 ra_debug_msg (DUMP_IGRAPH
, "\n");
705 for (ml
= wl_moves
; ml
; ml
= ml
->next
)
708 ra_debug_msg (DUMP_IGRAPH
, "move: insn %d: Web %d <-- Web %d\n",
709 INSN_UID (ml
->move
->insn
), ml
->move
->target_web
->id
,
710 ml
->move
->source_web
->id
);
712 ra_debug_msg (DUMP_WEBS
, "\nWebs:\n");
713 for (i
= 0; i
< num_webs
; i
++)
715 struct web
*web
= ID2WEB (i
);
717 ra_debug_msg (DUMP_WEBS
, " %4d : regno %3d", i
, web
->regno
);
720 ra_debug_msg (DUMP_WEBS
, " sub %d", SUBREG_BYTE (web
->orig_x
));
721 ra_debug_msg (DUMP_WEBS
, " par %d", find_web_for_subweb (web
)->id
);
723 ra_debug_msg (DUMP_WEBS
, " +%d (span %d, cost "
724 HOST_WIDE_INT_PRINT_DEC
") (%s)",
725 web
->add_hardregs
, web
->span_deaths
, web
->spill_cost
,
726 reg_class_names
[web
->regclass
]);
727 if (web
->spill_temp
== 1)
728 ra_debug_msg (DUMP_WEBS
, " (spilltemp)");
729 else if (web
->spill_temp
== 2)
730 ra_debug_msg (DUMP_WEBS
, " (spilltem2)");
731 else if (web
->spill_temp
== 3)
732 ra_debug_msg (DUMP_WEBS
, " (short)");
733 if (web
->type
== PRECOLORED
)
734 ra_debug_msg (DUMP_WEBS
, " (precolored, color=%d)", web
->color
);
735 else if (find_web_for_subweb (web
)->num_uses
== 0)
736 ra_debug_msg (DUMP_WEBS
, " dead");
737 if (web
->crosses_call
)
738 ra_debug_msg (DUMP_WEBS
, " xcall");
739 if (web
->regno
>= max_normal_pseudo
)
740 ra_debug_msg (DUMP_WEBS
, " stack");
741 ra_debug_msg (DUMP_WEBS
, "\n");
745 /* Dump the interference graph and webs in a format easily
746 parsable by programs. Used to emit real world interference graph
747 to my custom graph colorizer. */
750 dump_igraph_machine ()
754 if (!rtl_dump_file
|| (debug_new_regalloc
& DUMP_IGRAPH_M
) == 0)
756 ra_debug_msg (DUMP_IGRAPH_M
, "g %d %d\n", num_webs
- num_subwebs
,
757 FIRST_PSEUDO_REGISTER
);
758 for (i
= 0; i
< num_webs
- num_subwebs
; i
++)
760 struct web
*web
= ID2WEB (i
);
761 struct conflict_link
*cl
;
765 flags
= web
->spill_temp
& 0xF;
766 flags
|= ((web
->type
== PRECOLORED
) ? 1 : 0) << 4;
767 flags
|= (web
->add_hardregs
& 0xF) << 5;
768 for (cl
= web
->conflict_list
; cl
; cl
= cl
->next
)
769 if (cl
->t
->id
< web
->id
)
771 ra_debug_msg (DUMP_IGRAPH_M
, "n %d %d %d %d %d %d %d\n",
772 web
->id
, web
->color
, flags
,
773 (unsigned int)web
->spill_cost
, web
->num_defs
, web
->num_uses
,
775 if (web
->type
!= PRECOLORED
)
777 ra_debug_msg (DUMP_IGRAPH_M
, "s %d", web
->id
);
782 for (n
= 0; n
< 32 && col
< FIRST_PSEUDO_REGISTER
; n
++, col
++)
783 if (TEST_HARD_REG_BIT (web
->usable_regs
, col
))
785 ra_debug_msg (DUMP_IGRAPH_M
, " %u", u
);
786 if (col
>= FIRST_PSEUDO_REGISTER
)
789 ra_debug_msg (DUMP_IGRAPH_M
, "\n");
793 ra_debug_msg (DUMP_IGRAPH_M
, "c %d", web
->id
);
794 for (cl
= web
->conflict_list
; cl
; cl
= cl
->next
)
796 if (cl
->t
->id
< web
->id
)
797 ra_debug_msg (DUMP_IGRAPH_M
, " %d", cl
->t
->id
);
799 ra_debug_msg (DUMP_IGRAPH_M
, "\n");
802 ra_debug_msg (DUMP_IGRAPH_M
, "e\n");
805 /* This runs after colorization and changing the insn stream.
806 It temporarily replaces all pseudo registers with their colors,
807 and emits information, if the resulting insns are strictly valid. */
814 if (!rtl_dump_file
|| (debug_new_regalloc
& DUMP_CONSTRAINTS
) == 0)
816 for (i
= FIRST_PSEUDO_REGISTER
; i
< ra_max_regno
; i
++)
817 if (regno_reg_rtx
[i
] && GET_CODE (regno_reg_rtx
[i
]) == REG
)
818 REGNO (regno_reg_rtx
[i
])
819 = ra_reg_renumber
[i
] >= 0 ? ra_reg_renumber
[i
] : i
;
820 for (insn
= get_insns (); insn
; insn
= NEXT_INSN (insn
))
824 int uid
= INSN_UID (insn
);
826 /* Don't simply force rerecognition, as combine might left us
827 with some unrecongnizable ones, which later leads to aborts
828 in regclass, if we now destroy the remembered INSN_CODE(). */
829 /*INSN_CODE (insn) = -1;*/
830 code
= recog_memoized (insn
);
833 ra_debug_msg (DUMP_CONSTRAINTS
,
834 "%d: asm insn or not recognizable.\n", uid
);
837 ra_debug_msg (DUMP_CONSTRAINTS
,
838 "%d: code %d {%s}, %d operands, constraints: ",
839 uid
, code
, insn_data
[code
].name
, recog_data
.n_operands
);
841 /*preprocess_constraints ();*/
842 for (o
= 0; o
< recog_data
.n_operands
; o
++)
844 ra_debug_msg (DUMP_CONSTRAINTS
,
845 "%d:%s ", o
, recog_data
.constraints
[o
]);
847 if (constrain_operands (1))
848 ra_debug_msg (DUMP_CONSTRAINTS
, "matches strictly alternative %d",
851 ra_debug_msg (DUMP_CONSTRAINTS
, "doesn't match strictly");
852 ra_debug_msg (DUMP_CONSTRAINTS
, "\n");
854 for (i
= FIRST_PSEUDO_REGISTER
; i
< ra_max_regno
; i
++)
855 if (regno_reg_rtx
[i
] && GET_CODE (regno_reg_rtx
[i
]) == REG
)
856 REGNO (regno_reg_rtx
[i
]) = i
;
859 /* This counts and emits the cumulated cost of all spilled webs,
860 preceded by a custom message MSG, with debug level LEVEL. */
863 dump_graph_cost (level
, msg
)
868 unsigned HOST_WIDE_INT cost
;
869 #define LU HOST_WIDE_INT_PRINT_UNSIGNED
870 if (!rtl_dump_file
|| (debug_new_regalloc
& level
) == 0)
874 for (i
= 0; i
< num_webs
; i
++)
876 struct web
*web
= id2web
[i
];
877 if (alias (web
)->type
== SPILLED
)
878 cost
+= web
->orig_spill_cost
;
880 ra_debug_msg (level
, " spill cost of graph (%s) = " LU
"\n",
881 msg
? msg
: "", cost
);
885 /* Dump the color assignment per web, the coalesced and spilled webs. */
889 struct df
*df ATTRIBUTE_UNUSED
;
893 if (!rtl_dump_file
|| (debug_new_regalloc
& DUMP_RESULTS
) == 0)
896 ra_debug_msg (DUMP_RESULTS
, "\nColored:\n");
897 for (d
= WEBS(COLORED
); d
; d
= d
->next
)
900 ra_debug_msg (DUMP_RESULTS
, " %4d : color %d\n", web
->id
, web
->color
);
902 ra_debug_msg (DUMP_RESULTS
, "\nCoalesced:\n");
903 for (d
= WEBS(COALESCED
); d
; d
= d
->next
)
906 ra_debug_msg (DUMP_RESULTS
, " %4d : to web %d, color %d\n", web
->id
,
907 alias (web
)->id
, web
->color
);
909 ra_debug_msg (DUMP_RESULTS
, "\nSpilled:\n");
910 for (d
= WEBS(SPILLED
); d
; d
= d
->next
)
913 ra_debug_msg (DUMP_RESULTS
, " %4d\n", web
->id
);
915 ra_debug_msg (DUMP_RESULTS
, "\n");
916 dump_cost (DUMP_RESULTS
);
919 /* Calculate and dump the cumulated costs of certain types of insns
920 (loads, stores and copies). */
923 dump_static_insn_cost (file
, message
, prefix
)
930 unsigned HOST_WIDE_INT cost
;
933 struct cost load
= {0, 0};
934 struct cost store
= {0, 0};
935 struct cost regcopy
= {0, 0};
936 struct cost selfcopy
= {0, 0};
937 struct cost overall
= {0, 0};
945 unsigned HOST_WIDE_INT block_cost
= bb
->frequency
;
947 for (insn
= bb
->head
; insn
; insn
= NEXT_INSN (insn
))
949 /* Yes, yes. We don't calculate the costs precisely.
950 Only for "simple enough" insns. Those containing single
952 if (INSN_P (insn
) && ((set
= single_set (insn
)) != NULL
))
954 rtx src
= SET_SRC (set
);
955 rtx dest
= SET_DEST (set
);
956 struct cost
*pcost
= NULL
;
957 overall
.cost
+= block_cost
;
959 if (rtx_equal_p (src
, dest
))
961 else if (GET_CODE (src
) == GET_CODE (dest
)
962 && ((GET_CODE (src
) == REG
)
963 || (GET_CODE (src
) == SUBREG
964 && GET_CODE (SUBREG_REG (src
)) == REG
965 && GET_CODE (SUBREG_REG (dest
)) == REG
)))
969 if (GET_CODE (src
) == SUBREG
)
970 src
= SUBREG_REG (src
);
971 if (GET_CODE (dest
) == SUBREG
)
972 dest
= SUBREG_REG (dest
);
973 if (GET_CODE (src
) == MEM
&& GET_CODE (dest
) != MEM
974 && memref_is_stack_slot (src
))
976 else if (GET_CODE (src
) != MEM
&& GET_CODE (dest
) == MEM
977 && memref_is_stack_slot (dest
))
982 pcost
->cost
+= block_cost
;
993 fprintf (file
, "static insn cost %s\n", message
? message
: "");
994 fprintf (file
, " %soverall:\tnum=%6d\tcost=%8d\n", prefix
, overall
.count
,
996 fprintf (file
, " %sloads:\tnum=%6d\tcost=%8d\n", prefix
, load
.count
,
998 fprintf (file
, " %sstores:\tnum=%6d\tcost=%8d\n", prefix
,
999 store
.count
, store
.cost
);
1000 fprintf (file
, " %sregcopy:\tnum=%6d\tcost=%8d\n", prefix
, regcopy
.count
,
1002 fprintf (file
, " %sselfcpy:\tnum=%6d\tcost=%8d\n", prefix
, selfcopy
.count
,
1006 /* Returns nonzero, if WEB1 and WEB2 have some possible
1007 hardregs in common. */
1010 web_conflicts_p (web1
, web2
)
1014 if (web1
->type
== PRECOLORED
&& web2
->type
== PRECOLORED
)
1017 if (web1
->type
== PRECOLORED
)
1018 return TEST_HARD_REG_BIT (web2
->usable_regs
, web1
->regno
);
1020 if (web2
->type
== PRECOLORED
)
1021 return TEST_HARD_REG_BIT (web1
->usable_regs
, web2
->regno
);
1023 return hard_regs_intersect_p (&web1
->usable_regs
, &web2
->usable_regs
);
1026 /* Dump all uids of insns in which WEB is mentioned. */
1029 dump_web_insns (web
)
1034 ra_debug_msg (DUMP_EVER
, "Web: %i(%i)+%i class: %s freedom: %i degree %i\n",
1035 web
->id
, web
->regno
, web
->add_hardregs
,
1036 reg_class_names
[web
->regclass
],
1037 web
->num_freedom
, web
->num_conflicts
);
1038 ra_debug_msg (DUMP_EVER
, " def insns:");
1040 for (i
= 0; i
< web
->num_defs
; ++i
)
1042 ra_debug_msg (DUMP_EVER
, " %d ", INSN_UID (web
->defs
[i
]->insn
));
1045 ra_debug_msg (DUMP_EVER
, "\n use insns:");
1046 for (i
= 0; i
< web
->num_uses
; ++i
)
1048 ra_debug_msg (DUMP_EVER
, " %d ", INSN_UID (web
->uses
[i
]->insn
));
1050 ra_debug_msg (DUMP_EVER
, "\n");
1053 /* Dump conflicts for web WEB. */
1056 dump_web_conflicts (web
)
1062 ra_debug_msg (DUMP_EVER
, "Web: %i(%i)+%i class: %s freedom: %i degree %i\n",
1063 web
->id
, web
->regno
, web
->add_hardregs
,
1064 reg_class_names
[web
->regclass
],
1065 web
->num_freedom
, web
->num_conflicts
);
1067 for (def2
= 0; def2
< num_webs
; def2
++)
1068 if (TEST_BIT (igraph
, igraph_index (web
->id
, def2
)) && web
->id
!= def2
)
1071 ra_debug_msg (DUMP_EVER
, "\n ");
1074 ra_debug_msg (DUMP_EVER
, " %d(%d)", def2
, id2web
[def2
]->regno
);
1075 if (id2web
[def2
]->add_hardregs
)
1076 ra_debug_msg (DUMP_EVER
, "+%d", id2web
[def2
]->add_hardregs
);
1078 if (web_conflicts_p (web
, id2web
[def2
]))
1079 ra_debug_msg (DUMP_EVER
, "/x");
1081 if (id2web
[def2
]->type
== SELECT
)
1082 ra_debug_msg (DUMP_EVER
, "/s");
1084 if (id2web
[def2
]->type
== COALESCED
)
1085 ra_debug_msg (DUMP_EVER
,"/c/%d", alias (id2web
[def2
])->id
);
1087 ra_debug_msg (DUMP_EVER
, "\n");
1089 struct conflict_link
*wl
;
1091 ra_debug_msg (DUMP_EVER
, "By conflicts: ");
1092 for (wl
= web
->conflict_list
; wl
; wl
= wl
->next
)
1094 struct web
* w
= wl
->t
;
1096 ra_debug_msg (DUMP_EVER
, "\n ");
1098 ra_debug_msg (DUMP_EVER
, "%d(%d)%s ", w
->id
, w
->regno
,
1099 web_conflicts_p (web
, w
) ? "+" : "");
1101 ra_debug_msg (DUMP_EVER
, "\n");
1105 /* Output HARD_REG_SET to stderr. */
1108 debug_hard_reg_set (set
)
1112 for (i
=0; i
< FIRST_PSEUDO_REGISTER
; ++i
)
1114 if (TEST_HARD_REG_BIT (set
, i
))
1116 fprintf (stderr
, "%s ", reg_names
[i
]);
1119 fprintf (stderr
, "\n");
1123 vim:cinoptions={.5s,g0,p5,t0,(0,^-0.5s,n-0.5s:tw=78:cindent:sw=4: