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"
37 /* This file contains various dumping and debug functions for
38 the graph coloring register allocator. */
40 static void ra_print_rtx_1op (FILE *, rtx
);
41 static void ra_print_rtx_2op (FILE *, rtx
);
42 static void ra_print_rtx_3op (FILE *, rtx
);
43 static void ra_print_rtx_object (FILE *, rtx
);
45 /* The hardregs as names, for debugging. */
46 static const char *const reg_class_names
[] = REG_CLASS_NAMES
;
48 /* Print a message to the dump file, if debug_new_regalloc and LEVEL
49 have any bits in common. */
52 ra_debug_msg (unsigned int level
, const char *format
, ...)
56 va_start (ap
, format
);
57 if ((debug_new_regalloc
& level
) != 0 && rtl_dump_file
!= NULL
)
58 vfprintf (rtl_dump_file
, format
, ap
);
63 /* The following ra_print_xxx() functions print RTL expressions
64 in concise infix form. If the mode can be seen from context it's
65 left out. Most operators are represented by their graphical
66 characters, e.g. LE as "<=". Unknown constructs are currently
67 printed with print_inline_rtx(), which disrupts the nice layout.
68 Currently only the inline asm things are written this way. */
70 /* Print rtx X, which is a one operand rtx (op:mode (Y)), as
74 ra_print_rtx_1op (FILE *file
, rtx x
)
76 enum rtx_code code
= GET_CODE (x
);
77 rtx op0
= XEXP (x
, 0);
82 fputs ((code
== NEG
) ? "-(" : "~(", file
);
83 ra_print_rtx (file
, op0
, 0);
88 ra_print_rtx (file
, op0
, 0);
92 fprintf (file
, "%s", GET_RTX_NAME (code
));
93 if (GET_MODE (x
) != VOIDmode
)
94 fprintf (file
, ":%s(", GET_MODE_NAME (GET_MODE (x
)));
97 ra_print_rtx (file
, op0
, 0);
103 /* Print rtx X, which is a two operand rtx (op:mode (Y) (Z))
104 as "(Y op Z)", if the operand is know, or as "op(Y, Z)", if not,
108 ra_print_rtx_2op (FILE *file
, rtx x
)
111 const char *opname
= "shitop";
112 enum rtx_code code
= GET_CODE (x
);
113 rtx op0
= XEXP (x
, 0);
114 rtx op1
= XEXP (x
, 1);
118 case COMPARE
: opname
= "?"; break;
119 case MINUS
: opname
= "-"; break;
120 case DIV
: opname
= "/"; break;
121 case UDIV
: opname
= "u/"; break;
122 case MOD
: opname
= "%"; break;
123 case UMOD
: opname
= "u%"; break;
124 case ASHIFT
: opname
= "<<"; break;
125 case ASHIFTRT
: opname
= "a>>"; break;
126 case LSHIFTRT
: opname
= "l>>"; break;
128 case PLUS
: opname
= "+"; break;
129 case MULT
: opname
= "*"; break;
130 case AND
: opname
= "&"; break;
131 case IOR
: opname
= "|"; break;
132 case XOR
: opname
= "^"; break;
134 case NE
: opname
= "!="; break;
135 case EQ
: opname
= "=="; break;
136 case GE
: opname
= "s>="; break;
137 case GT
: opname
= "s>"; break;
138 case LE
: opname
= "s<="; break;
139 case LT
: opname
= "s<"; break;
140 case GEU
: opname
= "u>="; break;
141 case GTU
: opname
= "u>"; break;
142 case LEU
: opname
= "u<="; break;
143 case LTU
: opname
= "u<"; break;
146 opname
= GET_RTX_NAME (code
);
152 ra_print_rtx (file
, op0
, 0);
153 fprintf (file
, " %s ", opname
);
154 ra_print_rtx (file
, op1
, 0);
159 fprintf (file
, "%s(", opname
);
160 ra_print_rtx (file
, op0
, 0);
162 ra_print_rtx (file
, op1
, 0);
167 /* Print rtx X, which a three operand rtx to FILE.
168 I.e. X is either an IF_THEN_ELSE, or a bitmap operation. */
171 ra_print_rtx_3op (FILE *file
, rtx x
)
173 enum rtx_code code
= GET_CODE (x
);
174 rtx op0
= XEXP (x
, 0);
175 rtx op1
= XEXP (x
, 1);
176 rtx op2
= XEXP (x
, 2);
177 if (code
== IF_THEN_ELSE
)
179 ra_print_rtx (file
, op0
, 0);
181 ra_print_rtx (file
, op1
, 0);
183 ra_print_rtx (file
, op2
, 0);
187 /* Bitmap-operation */
188 fprintf (file
, "%s:%s(", GET_RTX_NAME (code
),
189 GET_MODE_NAME (GET_MODE (x
)));
190 ra_print_rtx (file
, op0
, 0);
192 ra_print_rtx (file
, op1
, 0);
194 ra_print_rtx (file
, op2
, 0);
199 /* Print rtx X, which represents an object (class 'o' or some constructs
200 of class 'x' (e.g. subreg)), to FILE.
201 (reg XX) rtl is represented as "pXX", of XX was a pseudo,
202 as "name" it name is the nonnull hardreg name, or as "hXX", if XX
203 is a hardreg, whose name is NULL, or empty. */
206 ra_print_rtx_object (FILE *file
, rtx x
)
208 enum rtx_code code
= GET_CODE (x
);
209 enum machine_mode mode
= GET_MODE (x
);
213 fprintf (file
, HOST_WIDE_INT_PRINT_DEC
, XWINT (x
, 0));
218 const char *fmt
= GET_RTX_FORMAT (code
);
219 fputs ("dbl(", file
);
220 for (i
= 0; i
< GET_RTX_LENGTH (code
); i
++)
224 if (fmt
[i
] == 'e' && XEXP (x
, i
))
225 /* The MEM or other stuff */
227 ra_print_rtx (file
, XEXP (x
, i
), 0);
230 else if (fmt
[i
] == 'w')
232 fprintf (file
, HOST_WIDE_INT_PRINT_HEX
, XWINT (x
, i
));
238 case CONST_STRING
: fprintf (file
, "\"%s\"", XSTR (x
, 0)); break;
239 case CONST
: fputs ("const(", file
);
240 ra_print_rtx (file
, XEXP (x
, 0), 0);
243 case PC
: fputs ("pc", file
); break;
246 int regno
= REGNO (x
);
247 if (regno
< FIRST_PSEUDO_REGISTER
)
249 int i
, nregs
= hard_regno_nregs
[regno
][mode
];
252 for (i
= 0; i
< nregs
; i
++)
256 if (reg_names
[regno
+i
] && *reg_names
[regno
+ i
])
257 fprintf (file
, "%s", reg_names
[regno
+ i
]);
259 fprintf (file
, "h%d", regno
+ i
);
265 fprintf (file
, "p%d", regno
);
270 rtx sub
= SUBREG_REG (x
);
271 int ofs
= SUBREG_BYTE (x
);
272 if (GET_CODE (sub
) == REG
273 && REGNO (sub
) < FIRST_PSEUDO_REGISTER
)
275 int regno
= REGNO (sub
);
276 int i
, nregs
= hard_regno_nregs
[regno
][mode
];
277 regno
+= subreg_regno_offset (regno
, GET_MODE (sub
),
281 for (i
= 0; i
< nregs
; i
++)
285 if (reg_names
[regno
+i
])
286 fprintf (file
, "%s", reg_names
[regno
+ i
]);
288 fprintf (file
, "h%d", regno
+ i
);
295 ra_print_rtx (file
, sub
, 0);
296 fprintf (file
, ":[%s+%d]", GET_MODE_NAME (mode
), ofs
);
300 case SCRATCH
: fputs ("scratch", file
); break;
301 case CONCAT
: ra_print_rtx_2op (file
, x
); break;
302 case HIGH
: ra_print_rtx_1op (file
, x
); break;
305 ra_print_rtx (file
, XEXP (x
, 0), 0);
306 fputs (" + lo(", file
);
307 ra_print_rtx (file
, XEXP (x
, 1), 0);
310 case MEM
: fputs ("[", file
);
311 ra_print_rtx (file
, XEXP (x
, 0), 0);
312 fprintf (file
, "]:%s", GET_MODE_NAME (GET_MODE (x
)));
313 /* XXX print alias set too ?? */
317 rtx sub
= XEXP (x
, 0);
318 if (GET_CODE (sub
) == NOTE
319 && NOTE_LINE_NUMBER (sub
) == NOTE_INSN_DELETED_LABEL
)
320 fprintf (file
, "(deleted uid=%d)", INSN_UID (sub
));
321 else if (GET_CODE (sub
) == CODE_LABEL
)
322 fprintf (file
, "L%d", CODE_LABEL_NUMBER (sub
));
324 fprintf (file
, "(nonlabel uid=%d)", INSN_UID (sub
));
328 fprintf (file
, "sym(\"%s\")", XSTR (x
, 0)); break;
329 case CC0
: fputs ("cc0", file
); break;
330 default: print_inline_rtx (file
, x
, 0); break;
334 /* Print a general rtx X to FILE in nice infix form.
335 If WITH_PN is set, and X is one of the toplevel constructs
336 (insns, notes, labels or barriers), then print also the UIDs of
337 the preceding and following insn. */
340 ra_print_rtx (FILE *file
, rtx x
, int with_pn
)
348 class = GET_RTX_CLASS (code
);
350 /* First handle the insn like constructs. */
351 if (INSN_P (x
) || code
== NOTE
|| code
== CODE_LABEL
|| code
== BARRIER
)
355 /* Non-insns are prefixed by a ';'. */
358 else if (code
== NOTE
)
359 /* But notes are indented very far right. */
360 fprintf (file
, "\t\t\t\t\t; ");
361 else if (code
== CODE_LABEL
)
362 /* And labels have their Lxx name first, before the actual UID. */
364 fprintf (file
, "L%d:\t; ", CODE_LABEL_NUMBER (x
));
366 fprintf (file
, "(%s) ", LABEL_NAME (x
));
367 switch (LABEL_KIND (x
))
369 case LABEL_NORMAL
: break;
370 case LABEL_STATIC_ENTRY
: fputs (" (entry)", file
); break;
371 case LABEL_GLOBAL_ENTRY
: fputs (" (global entry)", file
); break;
372 case LABEL_WEAK_ENTRY
: fputs (" (weak entry)", file
); break;
375 fprintf (file
, " [%d uses] uid=(", LABEL_NUSES (x
));
377 fprintf (file
, "%d", INSN_UID (x
));
379 fprintf (file
, " %d %d", PREV_INSN (x
) ? INSN_UID (PREV_INSN (x
)) : 0,
380 NEXT_INSN (x
) ? INSN_UID (NEXT_INSN (x
)) : 0);
382 fputs (" -------- barrier ---------", file
);
383 else if (code
== CODE_LABEL
)
385 else if (code
== NOTE
)
387 int ln
= NOTE_LINE_NUMBER (x
);
388 if (ln
>= (int) NOTE_INSN_BIAS
&& ln
< (int) NOTE_INSN_MAX
)
389 fprintf (file
, " %s", GET_NOTE_INSN_NAME (ln
));
392 fprintf (file
, " line %d", ln
);
393 if (NOTE_SOURCE_FILE (x
))
394 fprintf (file
, ":%s", NOTE_SOURCE_FILE (x
));
399 fprintf (file
, "\t");
400 ra_print_rtx (file
, PATTERN (x
), 0);
406 /* Top-level stuff. */
410 for (j
= 0; j
< XVECLEN (x
, 0); j
++)
413 fputs ("\t;; ", file
);
414 ra_print_rtx (file
, XVECEXP (x
, 0, j
), 0);
418 case UNSPEC
: case UNSPEC_VOLATILE
:
421 fprintf (file
, "unspec%s(%d",
422 (code
== UNSPEC
) ? "" : "_vol", XINT (x
, 1));
423 for (j
= 0; j
< XVECLEN (x
, 0); j
++)
426 ra_print_rtx (file
, XVECEXP (x
, 0, j
), 0);
432 if (GET_CODE (SET_DEST (x
)) == PC
)
434 if (GET_CODE (SET_SRC (x
)) == IF_THEN_ELSE
435 && GET_CODE (XEXP (SET_SRC(x
), 2)) == PC
)
438 ra_print_rtx (file
, XEXP (SET_SRC (x
), 0), 0);
439 fputs (" jump ", file
);
440 ra_print_rtx (file
, XEXP (SET_SRC (x
), 1), 0);
444 fputs ("jump ", file
);
445 ra_print_rtx (file
, SET_SRC (x
), 0);
450 ra_print_rtx (file
, SET_DEST (x
), 0);
451 fputs (" <= ", file
);
452 ra_print_rtx (file
, SET_SRC (x
), 0);
456 fputs ("use <= ", file
);
457 ra_print_rtx (file
, XEXP (x
, 0), 0);
460 ra_print_rtx (file
, XEXP (x
, 0), 0);
461 fputs (" <= clobber", file
);
464 fputs ("call ", file
);
465 ra_print_rtx (file
, XEXP (x
, 0), 0); /* Address */
466 fputs (" numargs=", file
);
467 ra_print_rtx (file
, XEXP (x
, 1), 0); /* Num arguments */
470 fputs ("return", file
);
473 fputs ("if (", file
);
474 ra_print_rtx (file
, XEXP (x
, 0), 0);
475 fputs (") trap ", file
);
476 ra_print_rtx (file
, XEXP (x
, 1), 0);
479 fprintf (file
, "resx from region %d", XINT (x
, 0));
482 /* Different things of class 'x' */
483 case SUBREG
: ra_print_rtx_object (file
, x
); break;
484 case STRICT_LOW_PART
:
485 fputs ("low(", file
);
486 ra_print_rtx (file
, XEXP (x
, 0), 0);
496 ra_print_rtx_1op (file
, x
);
497 else if (class == '2' || class == 'c' || class == '<')
498 ra_print_rtx_2op (file
, x
);
499 else if (class == '3' || class == 'b')
500 ra_print_rtx_3op (file
, x
);
501 else if (class == 'o')
502 ra_print_rtx_object (file
, x
);
504 print_inline_rtx (file
, x
, 0);
507 /* This only calls ra_print_rtx(), but emits a final newline. */
510 ra_print_rtx_top (FILE *file
, rtx x
, int with_pn
)
512 ra_print_rtx (file
, x
, with_pn
);
513 fprintf (file
, "\n");
516 /* Callable from gdb. This prints rtx X onto stderr. */
521 ra_print_rtx_top (stderr
, x
, 1);
524 /* This prints the content of basic block with index BBI.
525 The first and last insn are emitted with UIDs of prev and next insns. */
528 ra_debug_bbi (int bbi
)
530 basic_block bb
= BASIC_BLOCK (bbi
);
532 for (insn
= BB_HEAD (bb
); insn
; insn
= NEXT_INSN (insn
))
534 ra_print_rtx_top (stderr
, insn
,
535 (insn
== BB_HEAD (bb
) || insn
== BB_END (bb
)));
536 fprintf (stderr
, "\n");
537 if (insn
== BB_END (bb
))
542 /* Beginning from INSN, emit NUM insns (if NUM is non-negative)
543 or emit a window of NUM insns around INSN, to stderr. */
546 ra_debug_insns (rtx insn
, int num
)
548 int i
, count
= (num
== 0 ? 1 : num
< 0 ? -num
: num
);
550 for (i
= count
/ 2; i
> 0 && PREV_INSN (insn
); i
--)
551 insn
= PREV_INSN (insn
);
552 for (i
= count
; i
> 0 && insn
; insn
= NEXT_INSN (insn
), i
--)
554 if (GET_CODE (insn
) == CODE_LABEL
)
555 fprintf (stderr
, "\n");
556 ra_print_rtx_top (stderr
, insn
, (i
== count
|| i
== 1));
560 /* Beginning with INSN, emit the whole insn chain into FILE.
561 This also outputs comments when basic blocks start or end and omits
562 some notes, if flag_ra_dump_notes is zero. */
565 ra_print_rtl_with_bb (FILE *file
, rtx insn
)
567 basic_block last_bb
, bb
;
568 unsigned int num
= 0;
572 for (; insn
; insn
= NEXT_INSN (insn
))
574 if (GET_CODE (insn
) == BARRIER
)
577 bb
= BLOCK_FOR_INSN (insn
);
581 fprintf (file
, ";; End of basic block %d\n", last_bb
->index
);
583 fprintf (file
, ";; Begin of basic block %d\n", bb
->index
);
586 if (GET_CODE (insn
) == CODE_LABEL
)
588 if (GET_CODE (insn
) == NOTE
)
590 /* Ignore basic block and maybe other notes not referencing
592 if (NOTE_LINE_NUMBER (insn
) != NOTE_INSN_BASIC_BLOCK
593 && (flag_ra_dump_notes
594 || NOTE_LINE_NUMBER (insn
) == NOTE_INSN_DELETED
595 || NOTE_LINE_NUMBER (insn
) == NOTE_INSN_DELETED_LABEL
))
597 ra_print_rtx_top (file
, insn
, (num
== 0 || !NEXT_INSN (insn
)));
603 ra_print_rtx_top (file
, insn
, (num
== 0 || !NEXT_INSN (insn
)));
609 /* Count how many insns were seen how often, while building the interference
610 graph, and prints the findings. */
613 dump_number_seen (void)
619 for (i
= 0; i
< N
; i
++)
621 for (i
= 0; i
< get_max_uid (); i
++)
622 if (number_seen
[i
] < N
- 1)
623 num
[number_seen
[i
]]++;
626 for (i
= 0; i
< N
- 1; i
++)
628 ra_debug_msg (DUMP_PROCESS
, "%d insns seen %d times\n", num
[i
], i
);
630 ra_debug_msg (DUMP_PROCESS
, "%d insns seen %d and more times\n", num
[i
],
632 ra_debug_msg (DUMP_PROCESS
, "from overall %d insns\n", get_max_uid ());
636 /* Dump the interference graph, the move list and the webs. */
639 dump_igraph (struct df
*df ATTRIBUTE_UNUSED
)
641 struct move_list
*ml
;
642 unsigned int def1
, def2
;
646 if (!rtl_dump_file
|| (debug_new_regalloc
& (DUMP_IGRAPH
| DUMP_WEBS
)) == 0)
648 ra_debug_msg (DUMP_IGRAPH
, "conflicts:\n ");
649 for (def1
= 0; def1
< num_webs
; def1
++)
653 for (def2
= 0; def2
< num_webs
; def2
++)
654 if (def1
!= def2
&& TEST_BIT (igraph
, igraph_index (def1
, def2
)))
658 if (SUBWEB_P (ID2WEB (def1
)))
659 ra_debug_msg (DUMP_IGRAPH
, "%d (SUBREG %d, %d) with ", def1
,
660 ID2WEB (def1
)->regno
,
661 SUBREG_BYTE (ID2WEB (def1
)->orig_x
));
663 ra_debug_msg (DUMP_IGRAPH
, "%d (REG %d) with ", def1
,
664 ID2WEB (def1
)->regno
);
667 ra_debug_msg (DUMP_IGRAPH
, "\n ");
670 if (SUBWEB_P (ID2WEB (def2
)))
671 ra_debug_msg (DUMP_IGRAPH
, "%d(%d,%d) ", def2
, ID2WEB (def2
)->regno
,
672 SUBREG_BYTE (ID2WEB (def2
)->orig_x
));
674 ra_debug_msg (DUMP_IGRAPH
, "%d(%d) ", def2
, ID2WEB (def2
)->regno
);
677 ra_debug_msg (DUMP_IGRAPH
, "\n ");
679 ra_debug_msg (DUMP_IGRAPH
, "\n");
680 for (ml
= wl_moves
; ml
; ml
= ml
->next
)
683 ra_debug_msg (DUMP_IGRAPH
, "move: insn %d: Web %d <-- Web %d\n",
684 INSN_UID (ml
->move
->insn
), ml
->move
->target_web
->id
,
685 ml
->move
->source_web
->id
);
687 ra_debug_msg (DUMP_WEBS
, "\nWebs:\n");
688 for (i
= 0; i
< num_webs
; i
++)
690 struct web
*web
= ID2WEB (i
);
692 ra_debug_msg (DUMP_WEBS
, " %4d : regno %3d", i
, web
->regno
);
695 ra_debug_msg (DUMP_WEBS
, " sub %d", SUBREG_BYTE (web
->orig_x
));
696 ra_debug_msg (DUMP_WEBS
, " par %d", find_web_for_subweb (web
)->id
);
698 ra_debug_msg (DUMP_WEBS
, " +%d (span %d, cost "
699 HOST_WIDE_INT_PRINT_DEC
") (%s)",
700 web
->add_hardregs
, web
->span_deaths
, web
->spill_cost
,
701 reg_class_names
[web
->regclass
]);
702 if (web
->spill_temp
== 1)
703 ra_debug_msg (DUMP_WEBS
, " (spilltemp)");
704 else if (web
->spill_temp
== 2)
705 ra_debug_msg (DUMP_WEBS
, " (spilltem2)");
706 else if (web
->spill_temp
== 3)
707 ra_debug_msg (DUMP_WEBS
, " (short)");
708 if (web
->type
== PRECOLORED
)
709 ra_debug_msg (DUMP_WEBS
, " (precolored, color=%d)", web
->color
);
710 else if (find_web_for_subweb (web
)->num_uses
== 0)
711 ra_debug_msg (DUMP_WEBS
, " dead");
712 if (web
->crosses_call
)
713 ra_debug_msg (DUMP_WEBS
, " xcall");
714 if (web
->regno
>= max_normal_pseudo
)
715 ra_debug_msg (DUMP_WEBS
, " stack");
716 ra_debug_msg (DUMP_WEBS
, "\n");
720 /* Dump the interference graph and webs in a format easily
721 parsable by programs. Used to emit real world interference graph
722 to my custom graph colorizer. */
725 dump_igraph_machine (void)
729 if (!rtl_dump_file
|| (debug_new_regalloc
& DUMP_IGRAPH_M
) == 0)
731 ra_debug_msg (DUMP_IGRAPH_M
, "g %d %d\n", num_webs
- num_subwebs
,
732 FIRST_PSEUDO_REGISTER
);
733 for (i
= 0; i
< num_webs
- num_subwebs
; i
++)
735 struct web
*web
= ID2WEB (i
);
736 struct conflict_link
*cl
;
740 flags
= web
->spill_temp
& 0xF;
741 flags
|= ((web
->type
== PRECOLORED
) ? 1 : 0) << 4;
742 flags
|= (web
->add_hardregs
& 0xF) << 5;
743 for (cl
= web
->conflict_list
; cl
; cl
= cl
->next
)
744 if (cl
->t
->id
< web
->id
)
746 ra_debug_msg (DUMP_IGRAPH_M
, "n %d %d %d %d %d %d %d\n",
747 web
->id
, web
->color
, flags
,
748 (unsigned int)web
->spill_cost
, web
->num_defs
, web
->num_uses
,
750 if (web
->type
!= PRECOLORED
)
752 ra_debug_msg (DUMP_IGRAPH_M
, "s %d", web
->id
);
757 for (n
= 0; n
< 32 && col
< FIRST_PSEUDO_REGISTER
; n
++, col
++)
758 if (TEST_HARD_REG_BIT (web
->usable_regs
, col
))
760 ra_debug_msg (DUMP_IGRAPH_M
, " %u", u
);
761 if (col
>= FIRST_PSEUDO_REGISTER
)
764 ra_debug_msg (DUMP_IGRAPH_M
, "\n");
768 ra_debug_msg (DUMP_IGRAPH_M
, "c %d", web
->id
);
769 for (cl
= web
->conflict_list
; cl
; cl
= cl
->next
)
771 if (cl
->t
->id
< web
->id
)
772 ra_debug_msg (DUMP_IGRAPH_M
, " %d", cl
->t
->id
);
774 ra_debug_msg (DUMP_IGRAPH_M
, "\n");
777 ra_debug_msg (DUMP_IGRAPH_M
, "e\n");
780 /* This runs after colorization and changing the insn stream.
781 It temporarily replaces all pseudo registers with their colors,
782 and emits information, if the resulting insns are strictly valid. */
785 dump_constraints (void)
789 if (!rtl_dump_file
|| (debug_new_regalloc
& DUMP_CONSTRAINTS
) == 0)
791 for (i
= FIRST_PSEUDO_REGISTER
; i
< ra_max_regno
; i
++)
792 if (regno_reg_rtx
[i
] && GET_CODE (regno_reg_rtx
[i
]) == REG
)
793 REGNO (regno_reg_rtx
[i
])
794 = ra_reg_renumber
[i
] >= 0 ? ra_reg_renumber
[i
] : i
;
795 for (insn
= get_insns (); insn
; insn
= NEXT_INSN (insn
))
799 int uid
= INSN_UID (insn
);
801 /* Don't simply force rerecognition, as combine might left us
802 with some unrecognizable ones, which later leads to aborts
803 in regclass, if we now destroy the remembered INSN_CODE(). */
804 /*INSN_CODE (insn) = -1;*/
805 code
= recog_memoized (insn
);
808 ra_debug_msg (DUMP_CONSTRAINTS
,
809 "%d: asm insn or not recognizable.\n", uid
);
812 ra_debug_msg (DUMP_CONSTRAINTS
,
813 "%d: code %d {%s}, %d operands, constraints: ",
814 uid
, code
, insn_data
[code
].name
, recog_data
.n_operands
);
816 /*preprocess_constraints ();*/
817 for (o
= 0; o
< recog_data
.n_operands
; o
++)
819 ra_debug_msg (DUMP_CONSTRAINTS
,
820 "%d:%s ", o
, recog_data
.constraints
[o
]);
822 if (constrain_operands (1))
823 ra_debug_msg (DUMP_CONSTRAINTS
, "matches strictly alternative %d",
826 ra_debug_msg (DUMP_CONSTRAINTS
, "doesn't match strictly");
827 ra_debug_msg (DUMP_CONSTRAINTS
, "\n");
829 for (i
= FIRST_PSEUDO_REGISTER
; i
< ra_max_regno
; i
++)
830 if (regno_reg_rtx
[i
] && GET_CODE (regno_reg_rtx
[i
]) == REG
)
831 REGNO (regno_reg_rtx
[i
]) = i
;
834 /* This counts and emits the cumulated cost of all spilled webs,
835 preceded by a custom message MSG, with debug level LEVEL. */
838 dump_graph_cost (unsigned int level
, const char *msg
)
841 unsigned HOST_WIDE_INT cost
;
842 if (!rtl_dump_file
|| (debug_new_regalloc
& level
) == 0)
846 for (i
= 0; i
< num_webs
; i
++)
848 struct web
*web
= id2web
[i
];
849 if (alias (web
)->type
== SPILLED
)
850 cost
+= web
->orig_spill_cost
;
852 ra_debug_msg (level
, " spill cost of graph (%s) = "
853 HOST_WIDE_INT_PRINT_UNSIGNED
"\n",
854 msg
? msg
: "", cost
);
857 /* Dump the color assignment per web, the coalesced and spilled webs. */
860 dump_ra (struct df
*df ATTRIBUTE_UNUSED
)
864 if (!rtl_dump_file
|| (debug_new_regalloc
& DUMP_RESULTS
) == 0)
867 ra_debug_msg (DUMP_RESULTS
, "\nColored:\n");
868 for (d
= WEBS(COLORED
); d
; d
= d
->next
)
871 ra_debug_msg (DUMP_RESULTS
, " %4d : color %d\n", web
->id
, web
->color
);
873 ra_debug_msg (DUMP_RESULTS
, "\nCoalesced:\n");
874 for (d
= WEBS(COALESCED
); d
; d
= d
->next
)
877 ra_debug_msg (DUMP_RESULTS
, " %4d : to web %d, color %d\n", web
->id
,
878 alias (web
)->id
, web
->color
);
880 ra_debug_msg (DUMP_RESULTS
, "\nSpilled:\n");
881 for (d
= WEBS(SPILLED
); d
; d
= d
->next
)
884 ra_debug_msg (DUMP_RESULTS
, " %4d\n", web
->id
);
886 ra_debug_msg (DUMP_RESULTS
, "\n");
887 dump_cost (DUMP_RESULTS
);
890 /* Calculate and dump the cumulated costs of certain types of insns
891 (loads, stores and copies). */
894 dump_static_insn_cost (FILE *file
, const char *message
, const char *prefix
)
898 unsigned HOST_WIDE_INT cost
;
902 struct cost load
, store
, regcopy
, selfcopy
, overall
;
903 memset (&load
, 0, sizeof(load
));
904 memset (&store
, 0, sizeof(store
));
905 memset (®copy
, 0, sizeof(regcopy
));
906 memset (&selfcopy
, 0, sizeof(selfcopy
));
907 memset (&overall
, 0, sizeof(overall
));
914 unsigned HOST_WIDE_INT block_cost
= bb
->frequency
;
916 for (insn
= BB_HEAD (bb
); insn
; insn
= NEXT_INSN (insn
))
918 /* Yes, yes. We don't calculate the costs precisely.
919 Only for "simple enough" insns. Those containing single
921 if (INSN_P (insn
) && ((set
= single_set (insn
)) != NULL
))
923 rtx src
= SET_SRC (set
);
924 rtx dest
= SET_DEST (set
);
925 struct cost
*pcost
= NULL
;
926 overall
.cost
+= block_cost
;
928 if (rtx_equal_p (src
, dest
))
930 else if (GET_CODE (src
) == GET_CODE (dest
)
931 && ((GET_CODE (src
) == REG
)
932 || (GET_CODE (src
) == SUBREG
933 && GET_CODE (SUBREG_REG (src
)) == REG
934 && GET_CODE (SUBREG_REG (dest
)) == REG
)))
938 if (GET_CODE (src
) == SUBREG
)
939 src
= SUBREG_REG (src
);
940 if (GET_CODE (dest
) == SUBREG
)
941 dest
= SUBREG_REG (dest
);
942 if (GET_CODE (src
) == MEM
&& GET_CODE (dest
) != MEM
943 && memref_is_stack_slot (src
))
945 else if (GET_CODE (src
) != MEM
&& GET_CODE (dest
) == MEM
946 && memref_is_stack_slot (dest
))
951 pcost
->cost
+= block_cost
;
955 if (insn
== BB_END (bb
))
962 fprintf (file
, "static insn cost %s\n", message
? message
: "");
963 fprintf (file
, " %soverall:\tnum=%6d\tcost=% 8" HOST_WIDE_INT_PRINT
"d\n",
964 prefix
, overall
.count
, overall
.cost
);
965 fprintf (file
, " %sloads:\tnum=%6d\tcost=% 8" HOST_WIDE_INT_PRINT
"d\n",
966 prefix
, load
.count
, load
.cost
);
967 fprintf (file
, " %sstores:\tnum=%6d\tcost=% 8" HOST_WIDE_INT_PRINT
"d\n",
968 prefix
, store
.count
, store
.cost
);
969 fprintf (file
, " %sregcopy:\tnum=%6d\tcost=% 8" HOST_WIDE_INT_PRINT
"d\n",
970 prefix
, regcopy
.count
, regcopy
.cost
);
971 fprintf (file
, " %sselfcpy:\tnum=%6d\tcost=% 8" HOST_WIDE_INT_PRINT
"d\n",
972 prefix
, selfcopy
.count
, selfcopy
.cost
);
975 /* Returns nonzero, if WEB1 and WEB2 have some possible
976 hardregs in common. */
979 web_conflicts_p (struct web
*web1
, struct web
*web2
)
981 if (web1
->type
== PRECOLORED
&& web2
->type
== PRECOLORED
)
984 if (web1
->type
== PRECOLORED
)
985 return TEST_HARD_REG_BIT (web2
->usable_regs
, web1
->regno
);
987 if (web2
->type
== PRECOLORED
)
988 return TEST_HARD_REG_BIT (web1
->usable_regs
, web2
->regno
);
990 return hard_regs_intersect_p (&web1
->usable_regs
, &web2
->usable_regs
);
993 /* Dump all uids of insns in which WEB is mentioned. */
996 dump_web_insns (struct web
*web
)
1000 ra_debug_msg (DUMP_EVER
, "Web: %i(%i)+%i class: %s freedom: %i degree %i\n",
1001 web
->id
, web
->regno
, web
->add_hardregs
,
1002 reg_class_names
[web
->regclass
],
1003 web
->num_freedom
, web
->num_conflicts
);
1004 ra_debug_msg (DUMP_EVER
, " def insns:");
1006 for (i
= 0; i
< web
->num_defs
; ++i
)
1008 ra_debug_msg (DUMP_EVER
, " %d ", INSN_UID (web
->defs
[i
]->insn
));
1011 ra_debug_msg (DUMP_EVER
, "\n use insns:");
1012 for (i
= 0; i
< web
->num_uses
; ++i
)
1014 ra_debug_msg (DUMP_EVER
, " %d ", INSN_UID (web
->uses
[i
]->insn
));
1016 ra_debug_msg (DUMP_EVER
, "\n");
1019 /* Dump conflicts for web WEB. */
1022 dump_web_conflicts (struct web
*web
)
1027 ra_debug_msg (DUMP_EVER
, "Web: %i(%i)+%i class: %s freedom: %i degree %i\n",
1028 web
->id
, web
->regno
, web
->add_hardregs
,
1029 reg_class_names
[web
->regclass
],
1030 web
->num_freedom
, web
->num_conflicts
);
1032 for (def2
= 0; def2
< num_webs
; def2
++)
1033 if (TEST_BIT (igraph
, igraph_index (web
->id
, def2
)) && web
->id
!= def2
)
1036 ra_debug_msg (DUMP_EVER
, "\n ");
1039 ra_debug_msg (DUMP_EVER
, " %d(%d)", def2
, id2web
[def2
]->regno
);
1040 if (id2web
[def2
]->add_hardregs
)
1041 ra_debug_msg (DUMP_EVER
, "+%d", id2web
[def2
]->add_hardregs
);
1043 if (web_conflicts_p (web
, id2web
[def2
]))
1044 ra_debug_msg (DUMP_EVER
, "/x");
1046 if (id2web
[def2
]->type
== SELECT
)
1047 ra_debug_msg (DUMP_EVER
, "/s");
1049 if (id2web
[def2
]->type
== COALESCED
)
1050 ra_debug_msg (DUMP_EVER
,"/c/%d", alias (id2web
[def2
])->id
);
1052 ra_debug_msg (DUMP_EVER
, "\n");
1054 struct conflict_link
*wl
;
1056 ra_debug_msg (DUMP_EVER
, "By conflicts: ");
1057 for (wl
= web
->conflict_list
; wl
; wl
= wl
->next
)
1059 struct web
* w
= wl
->t
;
1061 ra_debug_msg (DUMP_EVER
, "\n ");
1063 ra_debug_msg (DUMP_EVER
, "%d(%d)%s ", w
->id
, w
->regno
,
1064 web_conflicts_p (web
, w
) ? "+" : "");
1066 ra_debug_msg (DUMP_EVER
, "\n");
1070 /* Output HARD_REG_SET to stderr. */
1073 debug_hard_reg_set (HARD_REG_SET set
)
1076 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; ++i
)
1078 if (TEST_HARD_REG_BIT (set
, i
))
1080 fprintf (stderr
, "%s ", reg_names
[i
]);
1083 fprintf (stderr
, "\n");
1087 vim:cinoptions={.5s,g0,p5,t0,(0,^-0.5s,n-0.5s:tw=78:cindent:sw=4: