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
PARAMS ((FILE *, rtx
));
40 static void ra_print_rtx_2op
PARAMS ((FILE *, rtx
));
41 static void ra_print_rtx_3op
PARAMS ((FILE *, rtx
));
42 static void ra_print_rtx_object
PARAMS ((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
VPARAMS ((unsigned int level
, const char *format
, ...))
54 VA_FIXEDARG (ap
, unsigned int, level
);
55 VA_FIXEDARG (ap
, const char *, 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
, x
)
77 enum rtx_code code
= GET_CODE (x
);
78 rtx op0
= XEXP (x
, 0);
83 fputs ((code
== NEG
) ? "-(" : "~(", file
);
84 ra_print_rtx (file
, op0
, 0);
89 ra_print_rtx (file
, op0
, 0);
93 fprintf (file
, "%s", GET_RTX_NAME (code
));
94 if (GET_MODE (x
) != VOIDmode
)
95 fprintf (file
, ":%s(", GET_MODE_NAME (GET_MODE (x
)));
98 ra_print_rtx (file
, op0
, 0);
104 /* Print rtx X, which is a two operand rtx (op:mode (Y) (Z))
105 as "(Y op Z)", if the operand is know, or as "op(Y, Z)", if not,
109 ra_print_rtx_2op (file
, x
)
114 const char *opname
= "shitop";
115 enum rtx_code code
= GET_CODE (x
);
116 rtx op0
= XEXP (x
, 0);
117 rtx op1
= XEXP (x
, 1);
121 case COMPARE
: opname
= "?"; break;
122 case MINUS
: opname
= "-"; break;
123 case DIV
: opname
= "/"; break;
124 case UDIV
: opname
= "u/"; break;
125 case MOD
: opname
= "%"; break;
126 case UMOD
: opname
= "u%"; break;
127 case ASHIFT
: opname
= "<<"; break;
128 case ASHIFTRT
: opname
= "a>>"; break;
129 case LSHIFTRT
: opname
= "l>>"; break;
131 case PLUS
: opname
= "+"; break;
132 case MULT
: opname
= "*"; break;
133 case AND
: opname
= "&"; break;
134 case IOR
: opname
= "|"; break;
135 case XOR
: opname
= "^"; break;
137 case NE
: opname
= "!="; break;
138 case EQ
: opname
= "=="; break;
139 case GE
: opname
= "s>="; break;
140 case GT
: opname
= "s>"; break;
141 case LE
: opname
= "s<="; break;
142 case LT
: opname
= "s<"; break;
143 case GEU
: opname
= "u>="; break;
144 case GTU
: opname
= "u>"; break;
145 case LEU
: opname
= "u<="; break;
146 case LTU
: opname
= "u<"; break;
149 opname
= GET_RTX_NAME (code
);
155 ra_print_rtx (file
, op0
, 0);
156 fprintf (file
, " %s ", opname
);
157 ra_print_rtx (file
, op1
, 0);
162 fprintf (file
, "%s(", opname
);
163 ra_print_rtx (file
, op0
, 0);
165 ra_print_rtx (file
, op1
, 0);
170 /* Print rtx X, which a three operand rtx to FILE.
171 I.e. X is either an IF_THEN_ELSE, or a bitmap operation. */
174 ra_print_rtx_3op (file
, x
)
178 enum rtx_code code
= GET_CODE (x
);
179 rtx op0
= XEXP (x
, 0);
180 rtx op1
= XEXP (x
, 1);
181 rtx op2
= XEXP (x
, 2);
182 if (code
== IF_THEN_ELSE
)
184 ra_print_rtx (file
, op0
, 0);
186 ra_print_rtx (file
, op1
, 0);
188 ra_print_rtx (file
, op2
, 0);
192 /* Bitmap-operation */
193 fprintf (file
, "%s:%s(", GET_RTX_NAME (code
),
194 GET_MODE_NAME (GET_MODE (x
)));
195 ra_print_rtx (file
, op0
, 0);
197 ra_print_rtx (file
, op1
, 0);
199 ra_print_rtx (file
, op2
, 0);
204 /* Print rtx X, which represents an object (class 'o' or some constructs
205 of class 'x' (e.g. subreg)), to FILE.
206 (reg XX) rtl is represented as "pXX", of XX was a pseudo,
207 as "name" it name is the nonnull hardreg name, or as "hXX", if XX
208 is a hardreg, whose name is NULL, or empty. */
211 ra_print_rtx_object (file
, x
)
215 enum rtx_code code
= GET_CODE (x
);
216 enum machine_mode mode
= GET_MODE (x
);
220 fprintf (file
, HOST_WIDE_INT_PRINT_DEC
, XWINT (x
, 0));
225 const char *fmt
= GET_RTX_FORMAT (code
);
226 fputs ("dbl(", file
);
227 for (i
= 0; i
< GET_RTX_LENGTH (code
); i
++)
231 if (fmt
[i
] == 'e' && XEXP (x
, i
))
232 /* The MEM or other stuff */
234 ra_print_rtx (file
, XEXP (x
, i
), 0);
237 else if (fmt
[i
] == 'w')
239 fprintf (file
, HOST_WIDE_INT_PRINT_HEX
, XWINT (x
, i
));
245 case CONST_STRING
: fprintf (file
, "\"%s\"", XSTR (x
, 0)); break;
246 case CONST
: fputs ("const(", file
);
247 ra_print_rtx (file
, XEXP (x
, 0), 0);
250 case PC
: fputs ("pc", file
); break;
253 int regno
= REGNO (x
);
254 if (regno
< FIRST_PSEUDO_REGISTER
)
256 int i
, nregs
= HARD_REGNO_NREGS (regno
, mode
);
259 for (i
= 0; i
< nregs
; i
++)
263 if (reg_names
[regno
+i
] && *reg_names
[regno
+ i
])
264 fprintf (file
, "%s", reg_names
[regno
+ i
]);
266 fprintf (file
, "h%d", regno
+ i
);
272 fprintf (file
, "p%d", regno
);
277 rtx sub
= SUBREG_REG (x
);
278 int ofs
= SUBREG_BYTE (x
);
279 if (GET_CODE (sub
) == REG
280 && REGNO (sub
) < FIRST_PSEUDO_REGISTER
)
282 int regno
= REGNO (sub
);
283 int i
, nregs
= HARD_REGNO_NREGS (regno
, mode
);
284 regno
+= subreg_regno_offset (regno
, GET_MODE (sub
),
288 for (i
= 0; i
< nregs
; i
++)
292 if (reg_names
[regno
+i
])
293 fprintf (file
, "%s", reg_names
[regno
+ i
]);
295 fprintf (file
, "h%d", regno
+ i
);
302 ra_print_rtx (file
, sub
, 0);
303 fprintf (file
, ":[%s+%d]", GET_MODE_NAME (mode
), ofs
);
307 case SCRATCH
: fputs ("scratch", file
); break;
308 case CONCAT
: ra_print_rtx_2op (file
, x
); break;
309 case HIGH
: ra_print_rtx_1op (file
, x
); break;
312 ra_print_rtx (file
, XEXP (x
, 0), 0);
313 fputs (" + lo(", file
);
314 ra_print_rtx (file
, XEXP (x
, 1), 0);
317 case MEM
: fputs ("[", file
);
318 ra_print_rtx (file
, XEXP (x
, 0), 0);
319 fprintf (file
, "]:%s", GET_MODE_NAME (GET_MODE (x
)));
320 /* XXX print alias set too ?? */
324 rtx sub
= XEXP (x
, 0);
325 if (GET_CODE (sub
) == NOTE
326 && NOTE_LINE_NUMBER (sub
) == NOTE_INSN_DELETED_LABEL
)
327 fprintf (file
, "(deleted uid=%d)", INSN_UID (sub
));
328 else if (GET_CODE (sub
) == CODE_LABEL
)
329 fprintf (file
, "L%d", CODE_LABEL_NUMBER (sub
));
331 fprintf (file
, "(nonlabel uid=%d)", INSN_UID (sub
));
335 fprintf (file
, "sym(\"%s\")", XSTR (x
, 0)); break;
336 case CC0
: fputs ("cc0", file
); break;
337 default: print_inline_rtx (file
, x
, 0); break;
341 /* Print a general rtx X to FILE in nice infix form.
342 If WITH_PN is set, and X is one of the toplevel constructs
343 (insns, notes, labels or barriers), then print also the UIDs of
344 the preceding and following insn. */
347 ra_print_rtx (file
, x
, with_pn
)
358 class = GET_RTX_CLASS (code
);
360 /* First handle the insn like constructs. */
361 if (INSN_P (x
) || code
== NOTE
|| code
== CODE_LABEL
|| code
== BARRIER
)
365 /* Non-insns are prefixed by a ';'. */
368 else if (code
== NOTE
)
369 /* But notes are indented very far right. */
370 fprintf (file
, "\t\t\t\t\t; ");
371 else if (code
== CODE_LABEL
)
372 /* And labels have their Lxx name first, before the actual UID. */
374 fprintf (file
, "L%d:\t; ", CODE_LABEL_NUMBER (x
));
376 fprintf (file
, "(%s) ", LABEL_NAME (x
));
377 switch (LABEL_KIND (x
))
379 case LABEL_NORMAL
: break;
380 case LABEL_STATIC_ENTRY
: fputs (" (entry)", file
); break;
381 case LABEL_GLOBAL_ENTRY
: fputs (" (global entry)", file
); break;
382 case LABEL_WEAK_ENTRY
: fputs (" (weak entry)", file
); break;
385 fprintf (file
, " [%d uses] uid=(", LABEL_NUSES (x
));
387 fprintf (file
, "%d", INSN_UID (x
));
389 fprintf (file
, " %d %d", PREV_INSN (x
) ? INSN_UID (PREV_INSN (x
)) : 0,
390 NEXT_INSN (x
) ? INSN_UID (NEXT_INSN (x
)) : 0);
392 fputs (" -------- barrier ---------", file
);
393 else if (code
== CODE_LABEL
)
395 else if (code
== NOTE
)
397 int ln
= NOTE_LINE_NUMBER (x
);
398 if (ln
>= (int) NOTE_INSN_BIAS
&& ln
< (int) NOTE_INSN_MAX
)
399 fprintf (file
, " %s", GET_NOTE_INSN_NAME (ln
));
402 fprintf (file
, " line %d", ln
);
403 if (NOTE_SOURCE_FILE (x
))
404 fprintf (file
, ":%s", NOTE_SOURCE_FILE (x
));
409 fprintf (file
, "\t");
410 ra_print_rtx (file
, PATTERN (x
), 0);
416 /* Top-level stuff. */
420 for (j
= 0; j
< XVECLEN (x
, 0); j
++)
423 fputs ("\t;; ", file
);
424 ra_print_rtx (file
, XVECEXP (x
, 0, j
), 0);
428 case UNSPEC
: case UNSPEC_VOLATILE
:
431 fprintf (file
, "unspec%s(%d",
432 (code
== UNSPEC
) ? "" : "_vol", XINT (x
, 1));
433 for (j
= 0; j
< XVECLEN (x
, 0); j
++)
436 ra_print_rtx (file
, XVECEXP (x
, 0, j
), 0);
442 if (GET_CODE (SET_DEST (x
)) == PC
)
444 if (GET_CODE (SET_SRC (x
)) == IF_THEN_ELSE
445 && GET_CODE (XEXP (SET_SRC(x
), 2)) == PC
)
448 ra_print_rtx (file
, XEXP (SET_SRC (x
), 0), 0);
449 fputs (" jump ", file
);
450 ra_print_rtx (file
, XEXP (SET_SRC (x
), 1), 0);
454 fputs ("jump ", file
);
455 ra_print_rtx (file
, SET_SRC (x
), 0);
460 ra_print_rtx (file
, SET_DEST (x
), 0);
461 fputs (" <= ", file
);
462 ra_print_rtx (file
, SET_SRC (x
), 0);
466 fputs ("use <= ", file
);
467 ra_print_rtx (file
, XEXP (x
, 0), 0);
470 ra_print_rtx (file
, XEXP (x
, 0), 0);
471 fputs (" <= clobber", file
);
474 fputs ("call ", file
);
475 ra_print_rtx (file
, XEXP (x
, 0), 0); /* Address */
476 fputs (" numargs=", file
);
477 ra_print_rtx (file
, XEXP (x
, 1), 0); /* Num arguments */
480 fputs ("return", file
);
483 fputs ("if (", file
);
484 ra_print_rtx (file
, XEXP (x
, 0), 0);
485 fputs (") trap ", file
);
486 ra_print_rtx (file
, XEXP (x
, 1), 0);
489 fprintf (file
, "resx from region %d", XINT (x
, 0));
492 /* Different things of class 'x' */
493 case SUBREG
: ra_print_rtx_object (file
, x
); break;
494 case STRICT_LOW_PART
:
495 fputs ("low(", file
);
496 ra_print_rtx (file
, XEXP (x
, 0), 0);
506 ra_print_rtx_1op (file
, x
);
507 else if (class == '2' || class == 'c' || class == '<')
508 ra_print_rtx_2op (file
, x
);
509 else if (class == '3' || class == 'b')
510 ra_print_rtx_3op (file
, x
);
511 else if (class == 'o')
512 ra_print_rtx_object (file
, x
);
514 print_inline_rtx (file
, x
, 0);
517 /* This only calls ra_print_rtx(), but emits a final newline. */
520 ra_print_rtx_top (file
, x
, with_pn
)
525 ra_print_rtx (file
, x
, with_pn
);
526 fprintf (file
, "\n");
529 /* Callable from gdb. This prints rtx X onto stderr. */
535 ra_print_rtx_top (stderr
, x
, 1);
538 /* This prints the content of basic block with index BBI.
539 The first and last insn are emitted with UIDs of prev and next insns. */
545 basic_block bb
= BASIC_BLOCK (bbi
);
547 for (insn
= bb
->head
; insn
; insn
= NEXT_INSN (insn
))
549 ra_print_rtx_top (stderr
, insn
, (insn
== bb
->head
|| insn
== bb
->end
));
550 fprintf (stderr
, "\n");
556 /* Beginning from INSN, emit NUM insns (if NUM is non-negative)
557 or emit a window of NUM insns around INSN, to stderr. */
560 ra_debug_insns (insn
, num
)
564 int i
, count
= (num
== 0 ? 1 : num
< 0 ? -num
: num
);
566 for (i
= count
/ 2; i
> 0 && PREV_INSN (insn
); i
--)
567 insn
= PREV_INSN (insn
);
568 for (i
= count
; i
> 0 && insn
; insn
= NEXT_INSN (insn
), i
--)
570 if (GET_CODE (insn
) == CODE_LABEL
)
571 fprintf (stderr
, "\n");
572 ra_print_rtx_top (stderr
, insn
, (i
== count
|| i
== 1));
576 /* Beginning with INSN, emit the whole insn chain into FILE.
577 This also outputs comments when basic blocks start or end and omits
578 some notes, if flag_ra_dump_notes is zero. */
581 ra_print_rtl_with_bb (file
, insn
)
585 basic_block last_bb
, bb
;
586 unsigned int num
= 0;
590 for (; insn
; insn
= NEXT_INSN (insn
))
592 if (GET_CODE (insn
) == BARRIER
)
595 bb
= BLOCK_FOR_INSN (insn
);
599 fprintf (file
, ";; End of basic block %d\n", last_bb
->index
);
601 fprintf (file
, ";; Begin of basic block %d\n", bb
->index
);
604 if (GET_CODE (insn
) == CODE_LABEL
)
606 if (GET_CODE (insn
) == NOTE
)
608 /* Ignore basic block and maybe other notes not referencing
610 if (NOTE_LINE_NUMBER (insn
) != NOTE_INSN_BASIC_BLOCK
611 && (flag_ra_dump_notes
612 || NOTE_LINE_NUMBER (insn
) == NOTE_INSN_DELETED
613 || NOTE_LINE_NUMBER (insn
) == NOTE_INSN_DELETED_LABEL
))
615 ra_print_rtx_top (file
, insn
, (num
== 0 || !NEXT_INSN (insn
)));
621 ra_print_rtx_top (file
, insn
, (num
== 0 || !NEXT_INSN (insn
)));
627 /* Count how many insns were seen how often, while building the interference
628 graph, and prints the findings. */
637 for (i
= 0; i
< N
; i
++)
639 for (i
= 0; i
< get_max_uid (); i
++)
640 if (number_seen
[i
] < N
- 1)
641 num
[number_seen
[i
]]++;
644 for (i
= 0; i
< N
- 1; i
++)
646 ra_debug_msg (DUMP_PROCESS
, "%d insns seen %d times\n", num
[i
], i
);
648 ra_debug_msg (DUMP_PROCESS
, "%d insns seen %d and more times\n", num
[i
],
650 ra_debug_msg (DUMP_PROCESS
, "from overall %d insns\n", get_max_uid ());
654 /* Dump the interference graph, the move list and the webs. */
658 struct df
*df ATTRIBUTE_UNUSED
;
660 struct move_list
*ml
;
661 unsigned int def1
, def2
;
665 if (!rtl_dump_file
|| (debug_new_regalloc
& (DUMP_IGRAPH
| DUMP_WEBS
)) == 0)
667 ra_debug_msg (DUMP_IGRAPH
, "conflicts:\n ");
668 for (def1
= 0; def1
< num_webs
; def1
++)
671 for (num2
=0, def2
= 0; def2
< num_webs
; def2
++)
672 if (def1
!= def2
&& TEST_BIT (igraph
, igraph_index (def1
, def2
)))
676 if (SUBWEB_P (ID2WEB (def1
)))
677 ra_debug_msg (DUMP_IGRAPH
, "%d (SUBREG %d, %d) with ", def1
,
678 ID2WEB (def1
)->regno
,
679 SUBREG_BYTE (ID2WEB (def1
)->orig_x
));
681 ra_debug_msg (DUMP_IGRAPH
, "%d (REG %d) with ", def1
,
682 ID2WEB (def1
)->regno
);
685 ra_debug_msg (DUMP_IGRAPH
, "\n ");
688 if (SUBWEB_P (ID2WEB (def2
)))
689 ra_debug_msg (DUMP_IGRAPH
, "%d(%d,%d) ", def2
, ID2WEB (def2
)->regno
,
690 SUBREG_BYTE (ID2WEB (def2
)->orig_x
));
692 ra_debug_msg (DUMP_IGRAPH
, "%d(%d) ", def2
, ID2WEB (def2
)->regno
);
695 ra_debug_msg (DUMP_IGRAPH
, "\n ");
697 ra_debug_msg (DUMP_IGRAPH
, "\n");
698 for (ml
= wl_moves
; ml
; ml
= ml
->next
)
701 ra_debug_msg (DUMP_IGRAPH
, "move: insn %d: Web %d <-- Web %d\n",
702 INSN_UID (ml
->move
->insn
), ml
->move
->target_web
->id
,
703 ml
->move
->source_web
->id
);
705 ra_debug_msg (DUMP_WEBS
, "\nWebs:\n");
706 for (i
= 0; i
< num_webs
; i
++)
708 struct web
*web
= ID2WEB (i
);
710 ra_debug_msg (DUMP_WEBS
, " %4d : regno %3d", i
, web
->regno
);
713 ra_debug_msg (DUMP_WEBS
, " sub %d", SUBREG_BYTE (web
->orig_x
));
714 ra_debug_msg (DUMP_WEBS
, " par %d", find_web_for_subweb (web
)->id
);
716 ra_debug_msg (DUMP_WEBS
, " +%d (span %d, cost ",
717 web
->add_hardregs
, web
->span_deaths
);
718 ra_debug_msg (DUMP_WEBS
, HOST_WIDE_INT_PRINT_DEC
, web
->spill_cost
);
719 ra_debug_msg (DUMP_WEBS
, ") (%s)", reg_class_names
[web
->regclass
]);
720 if (web
->spill_temp
== 1)
721 ra_debug_msg (DUMP_WEBS
, " (spilltemp)");
722 else if (web
->spill_temp
== 2)
723 ra_debug_msg (DUMP_WEBS
, " (spilltem2)");
724 else if (web
->spill_temp
== 3)
725 ra_debug_msg (DUMP_WEBS
, " (short)");
726 if (web
->type
== PRECOLORED
)
727 ra_debug_msg (DUMP_WEBS
, " (precolored, color=%d)", web
->color
);
728 else if (find_web_for_subweb (web
)->num_uses
== 0)
729 ra_debug_msg (DUMP_WEBS
, " dead");
730 if (web
->crosses_call
)
731 ra_debug_msg (DUMP_WEBS
, " xcall");
732 if (web
->regno
>= max_normal_pseudo
)
733 ra_debug_msg (DUMP_WEBS
, " stack");
734 ra_debug_msg (DUMP_WEBS
, "\n");
738 /* Dump the interference graph and webs in a format easily
739 parsable by programs. Used to emit real world interference graph
740 to my custom graph colorizer. */
743 dump_igraph_machine ()
747 if (!rtl_dump_file
|| (debug_new_regalloc
& DUMP_IGRAPH_M
) == 0)
749 ra_debug_msg (DUMP_IGRAPH_M
, "g %d %d\n", num_webs
- num_subwebs
,
750 FIRST_PSEUDO_REGISTER
);
751 for (i
= 0; i
< num_webs
- num_subwebs
; i
++)
753 struct web
*web
= ID2WEB (i
);
754 struct conflict_link
*cl
;
758 flags
= web
->spill_temp
& 0xF;
759 flags
|= ((web
->type
== PRECOLORED
) ? 1 : 0) << 4;
760 flags
|= (web
->add_hardregs
& 0xF) << 5;
761 for (cl
= web
->conflict_list
; cl
; cl
= cl
->next
)
762 if (cl
->t
->id
< web
->id
)
764 ra_debug_msg (DUMP_IGRAPH_M
, "n %d %d %d %d %d %d %d\n",
765 web
->id
, web
->color
, flags
,
766 (unsigned int)web
->spill_cost
, web
->num_defs
, web
->num_uses
,
768 if (web
->type
!= PRECOLORED
)
770 ra_debug_msg (DUMP_IGRAPH_M
, "s %d", web
->id
);
775 for (n
= 0; n
< 32 && col
< FIRST_PSEUDO_REGISTER
; n
++, col
++)
776 if (TEST_HARD_REG_BIT (web
->usable_regs
, col
))
778 ra_debug_msg (DUMP_IGRAPH_M
, " %u", u
);
779 if (col
>= FIRST_PSEUDO_REGISTER
)
782 ra_debug_msg (DUMP_IGRAPH_M
, "\n");
786 ra_debug_msg (DUMP_IGRAPH_M
, "c %d", web
->id
);
787 for (cl
= web
->conflict_list
; cl
; cl
= cl
->next
)
789 if (cl
->t
->id
< web
->id
)
790 ra_debug_msg (DUMP_IGRAPH_M
, " %d", cl
->t
->id
);
792 ra_debug_msg (DUMP_IGRAPH_M
, "\n");
795 ra_debug_msg (DUMP_IGRAPH_M
, "e\n");
798 /* This runs after colorization and changing the insn stream.
799 It temporarily replaces all pseudo registers with their colors,
800 and emits information, if the resulting insns are strictly valid. */
807 if (!rtl_dump_file
|| (debug_new_regalloc
& DUMP_CONSTRAINTS
) == 0)
809 for (i
= FIRST_PSEUDO_REGISTER
; i
< ra_max_regno
; i
++)
810 if (regno_reg_rtx
[i
] && GET_CODE (regno_reg_rtx
[i
]) == REG
)
811 REGNO (regno_reg_rtx
[i
])
812 = ra_reg_renumber
[i
] >= 0 ? ra_reg_renumber
[i
] : i
;
813 for (insn
= get_insns (); insn
; insn
= NEXT_INSN (insn
))
817 int uid
= INSN_UID (insn
);
819 /* Don't simply force rerecognition, as combine might left us
820 with some unrecognizable ones, which later leads to aborts
821 in regclass, if we now destroy the remembered INSN_CODE(). */
822 /*INSN_CODE (insn) = -1;*/
823 code
= recog_memoized (insn
);
826 ra_debug_msg (DUMP_CONSTRAINTS
,
827 "%d: asm insn or not recognizable.\n", uid
);
830 ra_debug_msg (DUMP_CONSTRAINTS
,
831 "%d: code %d {%s}, %d operands, constraints: ",
832 uid
, code
, insn_data
[code
].name
, recog_data
.n_operands
);
834 /*preprocess_constraints ();*/
835 for (o
= 0; o
< recog_data
.n_operands
; o
++)
837 ra_debug_msg (DUMP_CONSTRAINTS
,
838 "%d:%s ", o
, recog_data
.constraints
[o
]);
840 if (constrain_operands (1))
841 ra_debug_msg (DUMP_CONSTRAINTS
, "matches strictly alternative %d",
844 ra_debug_msg (DUMP_CONSTRAINTS
, "doesn't match strictly");
845 ra_debug_msg (DUMP_CONSTRAINTS
, "\n");
847 for (i
= FIRST_PSEUDO_REGISTER
; i
< ra_max_regno
; i
++)
848 if (regno_reg_rtx
[i
] && GET_CODE (regno_reg_rtx
[i
]) == REG
)
849 REGNO (regno_reg_rtx
[i
]) = i
;
852 /* This counts and emits the cumulated cost of all spilled webs,
853 preceded by a custom message MSG, with debug level LEVEL. */
856 dump_graph_cost (level
, msg
)
861 unsigned HOST_WIDE_INT cost
;
862 if (!rtl_dump_file
|| (debug_new_regalloc
& level
) == 0)
866 for (i
= 0; i
< num_webs
; i
++)
868 struct web
*web
= id2web
[i
];
869 if (alias (web
)->type
== SPILLED
)
870 cost
+= web
->orig_spill_cost
;
872 ra_debug_msg (level
, " spill cost of graph (%s) = ", msg
? msg
: "");
873 ra_debug_msg (level
, HOST_WIDE_INT_PRINT_UNSIGNED
, cost
);
874 ra_debug_msg (level
, "\n");
877 /* Dump the color assignment per web, the coalesced and spilled webs. */
881 struct df
*df ATTRIBUTE_UNUSED
;
885 if (!rtl_dump_file
|| (debug_new_regalloc
& DUMP_RESULTS
) == 0)
888 ra_debug_msg (DUMP_RESULTS
, "\nColored:\n");
889 for (d
= WEBS(COLORED
); d
; d
= d
->next
)
892 ra_debug_msg (DUMP_RESULTS
, " %4d : color %d\n", web
->id
, web
->color
);
894 ra_debug_msg (DUMP_RESULTS
, "\nCoalesced:\n");
895 for (d
= WEBS(COALESCED
); d
; d
= d
->next
)
898 ra_debug_msg (DUMP_RESULTS
, " %4d : to web %d, color %d\n", web
->id
,
899 alias (web
)->id
, web
->color
);
901 ra_debug_msg (DUMP_RESULTS
, "\nSpilled:\n");
902 for (d
= WEBS(SPILLED
); d
; d
= d
->next
)
905 ra_debug_msg (DUMP_RESULTS
, " %4d\n", web
->id
);
907 ra_debug_msg (DUMP_RESULTS
, "\n");
908 dump_cost (DUMP_RESULTS
);
911 /* Calculate and dump the cumulated costs of certain types of insns
912 (loads, stores and copies). */
915 dump_static_insn_cost (file
, message
, prefix
)
922 unsigned HOST_WIDE_INT cost
;
926 struct cost load
, store
, regcopy
, selfcopy
, overall
;
927 memset (&load
, 0, sizeof(load
));
928 memset (&store
, 0, sizeof(store
));
929 memset (®copy
, 0, sizeof(regcopy
));
930 memset (&selfcopy
, 0, sizeof(selfcopy
));
931 memset (&overall
, 0, sizeof(overall
));
938 unsigned HOST_WIDE_INT block_cost
= bb
->frequency
;
940 for (insn
= bb
->head
; insn
; insn
= NEXT_INSN (insn
))
942 /* Yes, yes. We don't calculate the costs precisely.
943 Only for "simple enough" insns. Those containing single
945 if (INSN_P (insn
) && ((set
= single_set (insn
)) != NULL
))
947 rtx src
= SET_SRC (set
);
948 rtx dest
= SET_DEST (set
);
949 struct cost
*pcost
= NULL
;
950 overall
.cost
+= block_cost
;
952 if (rtx_equal_p (src
, dest
))
954 else if (GET_CODE (src
) == GET_CODE (dest
)
955 && ((GET_CODE (src
) == REG
)
956 || (GET_CODE (src
) == SUBREG
957 && GET_CODE (SUBREG_REG (src
)) == REG
958 && GET_CODE (SUBREG_REG (dest
)) == REG
)))
962 if (GET_CODE (src
) == SUBREG
)
963 src
= SUBREG_REG (src
);
964 if (GET_CODE (dest
) == SUBREG
)
965 dest
= SUBREG_REG (dest
);
966 if (GET_CODE (src
) == MEM
&& GET_CODE (dest
) != MEM
967 && memref_is_stack_slot (src
))
969 else if (GET_CODE (src
) != MEM
&& GET_CODE (dest
) == MEM
970 && memref_is_stack_slot (dest
))
975 pcost
->cost
+= block_cost
;
986 fprintf (file
, "static insn cost %s\n", message
? message
: "");
987 fprintf (file
, " %soverall:\tnum=%6d\tcost=", prefix
, overall
.count
);
988 fprintf (file
, HOST_WIDE_INT_PRINT_DEC_SPACE
, 8, overall
.cost
);
989 fprintf (file
, "\n");
990 fprintf (file
, " %sloads:\tnum=%6d\tcost=", prefix
, load
.count
);
991 fprintf (file
, HOST_WIDE_INT_PRINT_DEC_SPACE
, 8, load
.cost
);
992 fprintf (file
, "\n");
993 fprintf (file
, " %sstores:\tnum=%6d\tcost=", prefix
, store
.count
);
994 fprintf (file
, HOST_WIDE_INT_PRINT_DEC_SPACE
, 8, store
.cost
);
995 fprintf (file
, "\n");
996 fprintf (file
, " %sregcopy:\tnum=%6d\tcost=", prefix
, regcopy
.count
);
997 fprintf (file
, HOST_WIDE_INT_PRINT_DEC_SPACE
, 8, regcopy
.cost
);
998 fprintf (file
, "\n");
999 fprintf (file
, " %sselfcpy:\tnum=%6d\tcost=", prefix
, selfcopy
.count
);
1000 fprintf (file
, HOST_WIDE_INT_PRINT_DEC_SPACE
, 8, selfcopy
.cost
);
1001 fprintf (file
, "\n");
1004 /* Returns nonzero, if WEB1 and WEB2 have some possible
1005 hardregs in common. */
1008 web_conflicts_p (web1
, web2
)
1012 if (web1
->type
== PRECOLORED
&& web2
->type
== PRECOLORED
)
1015 if (web1
->type
== PRECOLORED
)
1016 return TEST_HARD_REG_BIT (web2
->usable_regs
, web1
->regno
);
1018 if (web2
->type
== PRECOLORED
)
1019 return TEST_HARD_REG_BIT (web1
->usable_regs
, web2
->regno
);
1021 return hard_regs_intersect_p (&web1
->usable_regs
, &web2
->usable_regs
);
1024 /* Dump all uids of insns in which WEB is mentioned. */
1027 dump_web_insns (web
)
1032 ra_debug_msg (DUMP_EVER
, "Web: %i(%i)+%i class: %s freedom: %i degree %i\n",
1033 web
->id
, web
->regno
, web
->add_hardregs
,
1034 reg_class_names
[web
->regclass
],
1035 web
->num_freedom
, web
->num_conflicts
);
1036 ra_debug_msg (DUMP_EVER
, " def insns:");
1038 for (i
= 0; i
< web
->num_defs
; ++i
)
1040 ra_debug_msg (DUMP_EVER
, " %d ", INSN_UID (web
->defs
[i
]->insn
));
1043 ra_debug_msg (DUMP_EVER
, "\n use insns:");
1044 for (i
= 0; i
< web
->num_uses
; ++i
)
1046 ra_debug_msg (DUMP_EVER
, " %d ", INSN_UID (web
->uses
[i
]->insn
));
1048 ra_debug_msg (DUMP_EVER
, "\n");
1051 /* Dump conflicts for web WEB. */
1054 dump_web_conflicts (web
)
1060 ra_debug_msg (DUMP_EVER
, "Web: %i(%i)+%i class: %s freedom: %i degree %i\n",
1061 web
->id
, web
->regno
, web
->add_hardregs
,
1062 reg_class_names
[web
->regclass
],
1063 web
->num_freedom
, web
->num_conflicts
);
1065 for (def2
= 0; def2
< num_webs
; def2
++)
1066 if (TEST_BIT (igraph
, igraph_index (web
->id
, def2
)) && web
->id
!= def2
)
1069 ra_debug_msg (DUMP_EVER
, "\n ");
1072 ra_debug_msg (DUMP_EVER
, " %d(%d)", def2
, id2web
[def2
]->regno
);
1073 if (id2web
[def2
]->add_hardregs
)
1074 ra_debug_msg (DUMP_EVER
, "+%d", id2web
[def2
]->add_hardregs
);
1076 if (web_conflicts_p (web
, id2web
[def2
]))
1077 ra_debug_msg (DUMP_EVER
, "/x");
1079 if (id2web
[def2
]->type
== SELECT
)
1080 ra_debug_msg (DUMP_EVER
, "/s");
1082 if (id2web
[def2
]->type
== COALESCED
)
1083 ra_debug_msg (DUMP_EVER
,"/c/%d", alias (id2web
[def2
])->id
);
1085 ra_debug_msg (DUMP_EVER
, "\n");
1087 struct conflict_link
*wl
;
1089 ra_debug_msg (DUMP_EVER
, "By conflicts: ");
1090 for (wl
= web
->conflict_list
; wl
; wl
= wl
->next
)
1092 struct web
* w
= wl
->t
;
1094 ra_debug_msg (DUMP_EVER
, "\n ");
1096 ra_debug_msg (DUMP_EVER
, "%d(%d)%s ", w
->id
, w
->regno
,
1097 web_conflicts_p (web
, w
) ? "+" : "");
1099 ra_debug_msg (DUMP_EVER
, "\n");
1103 /* Output HARD_REG_SET to stderr. */
1106 debug_hard_reg_set (set
)
1110 for (i
=0; i
< FIRST_PSEUDO_REGISTER
; ++i
)
1112 if (TEST_HARD_REG_BIT (set
, i
))
1114 fprintf (stderr
, "%s ", reg_names
[i
]);
1117 fprintf (stderr
, "\n");
1121 vim:cinoptions={.5s,g0,p5,t0,(0,^-0.5s,n-0.5s:tw=78:cindent:sw=4: