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"
34 /* This file contains various dumping and debug functions for
35 the graph coloring register allocator. */
37 static void ra_print_rtx_1op
PARAMS ((FILE *, rtx
));
38 static void ra_print_rtx_2op
PARAMS ((FILE *, rtx
));
39 static void ra_print_rtx_3op
PARAMS ((FILE *, rtx
));
40 static void ra_print_rtx_object
PARAMS ((FILE *, rtx
));
42 /* The hardregs as names, for debugging. */
43 static const char *const reg_class_names
[] = REG_CLASS_NAMES
;
45 /* Print a message to the dump file, if debug_new_regalloc and LEVEL
46 have any bits in common. */
49 ra_debug_msg
VPARAMS ((unsigned int level
, const char *format
, ...))
52 VA_FIXEDARG (ap
, unsigned int, level
);
53 VA_FIXEDARG (ap
, const char *, format
);
54 if ((debug_new_regalloc
& level
) != 0 && rtl_dump_file
!= NULL
)
55 vfprintf (rtl_dump_file
, format
, ap
);
60 /* The following ra_print_xxx() functions print RTL expressions
61 in concise infix form. If the mode can be seen from context it's
62 left out. Most operators are represented by their graphical
63 characters, e.g. LE as "<=". Unknown constructs are currently
64 printed with print_inline_rtx(), which disrupts the nice layout.
65 Currently only the inline asm things are written this way. */
67 /* Print rtx X, which is a one operand rtx (op:mode (Y)), as
71 ra_print_rtx_1op (file
, 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
, x
)
112 const char *opname
= "shitop";
113 enum rtx_code code
= GET_CODE (x
);
114 rtx op0
= XEXP (x
, 0);
115 rtx op1
= XEXP (x
, 1);
119 case COMPARE
: opname
= "?"; break;
120 case MINUS
: opname
= "-"; break;
121 case DIV
: opname
= "/"; break;
122 case UDIV
: opname
= "u/"; break;
123 case MOD
: opname
= "%"; break;
124 case UMOD
: opname
= "u%"; break;
125 case ASHIFT
: opname
= "<<"; break;
126 case ASHIFTRT
: opname
= "a>>"; break;
127 case LSHIFTRT
: opname
= "l>>"; break;
129 case PLUS
: opname
= "+"; break;
130 case MULT
: opname
= "*"; break;
131 case AND
: opname
= "&"; break;
132 case IOR
: opname
= "|"; break;
133 case XOR
: opname
= "^"; break;
135 case NE
: opname
= "!="; break;
136 case EQ
: opname
= "=="; break;
137 case GE
: opname
= "s>="; break;
138 case GT
: opname
= "s>"; break;
139 case LE
: opname
= "s<="; break;
140 case LT
: opname
= "s<"; break;
141 case GEU
: opname
= "u>="; break;
142 case GTU
: opname
= "u>"; break;
143 case LEU
: opname
= "u<="; break;
144 case LTU
: opname
= "u<"; break;
147 opname
= GET_RTX_NAME (code
);
153 ra_print_rtx (file
, op0
, 0);
154 fprintf (file
, " %s ", opname
);
155 ra_print_rtx (file
, op1
, 0);
160 fprintf (file
, "%s(", opname
);
161 ra_print_rtx (file
, op0
, 0);
163 ra_print_rtx (file
, op1
, 0);
168 /* Print rtx X, which a three operand rtx to FILE.
169 I.e. X is either an IF_THEN_ELSE, or a bitmap operation. */
172 ra_print_rtx_3op (file
, x
)
176 enum rtx_code code
= GET_CODE (x
);
177 rtx op0
= XEXP (x
, 0);
178 rtx op1
= XEXP (x
, 1);
179 rtx op2
= XEXP (x
, 2);
180 if (code
== IF_THEN_ELSE
)
182 ra_print_rtx (file
, op0
, 0);
184 ra_print_rtx (file
, op1
, 0);
186 ra_print_rtx (file
, op2
, 0);
190 /* Bitmap-operation */
191 fprintf (file
, "%s:%s(", GET_RTX_NAME (code
),
192 GET_MODE_NAME (GET_MODE (x
)));
193 ra_print_rtx (file
, op0
, 0);
195 ra_print_rtx (file
, op1
, 0);
197 ra_print_rtx (file
, op2
, 0);
202 /* Print rtx X, which represents an object (class 'o' or some constructs
203 of class 'x' (e.g. subreg)), to FILE.
204 (reg XX) rtl is represented as "pXX", of XX was a pseudo,
205 as "name" it name is the nonnull hardreg name, or as "hXX", if XX
206 is a hardreg, whose name is NULL, or empty. */
209 ra_print_rtx_object (file
, x
)
213 enum rtx_code code
= GET_CODE (x
);
214 enum machine_mode mode
= GET_MODE (x
);
218 fprintf (file
, HOST_WIDE_INT_PRINT_DEC
, XWINT (x
, 0));
223 const char *fmt
= GET_RTX_FORMAT (code
);
224 fputs ("dbl(", file
);
225 for (i
= 0; i
< GET_RTX_LENGTH (code
); i
++)
229 if (fmt
[i
] == 'e' && XEXP (x
, i
))
230 /* The MEM or other stuff */
232 ra_print_rtx (file
, XEXP (x
, i
), 0);
235 else if (fmt
[i
] == 'w')
237 fprintf (file
, HOST_WIDE_INT_PRINT_HEX
, XWINT (x
, i
));
243 case CONST_STRING
: fprintf (file
, "\"%s\"", XSTR (x
, 0)); break;
244 case CONST
: fputs ("const(", file
);
245 ra_print_rtx (file
, XEXP (x
, 0), 0);
248 case PC
: fputs ("pc", file
); break;
251 int regno
= REGNO (x
);
252 if (regno
< FIRST_PSEUDO_REGISTER
)
254 int i
, nregs
= HARD_REGNO_NREGS (regno
, mode
);
257 for (i
= 0; i
< nregs
; i
++)
261 if (reg_names
[regno
+i
] && *reg_names
[regno
+ i
])
262 fprintf (file
, "%s", reg_names
[regno
+ i
]);
264 fprintf (file
, "h%d", regno
+ i
);
270 fprintf (file
, "p%d", regno
);
275 rtx sub
= SUBREG_REG (x
);
276 int ofs
= SUBREG_BYTE (x
);
277 if (GET_CODE (sub
) == REG
278 && REGNO (sub
) < FIRST_PSEUDO_REGISTER
)
280 int regno
= REGNO (sub
);
281 int i
, nregs
= HARD_REGNO_NREGS (regno
, mode
);
282 regno
+= subreg_regno_offset (regno
, GET_MODE (sub
),
286 for (i
= 0; i
< nregs
; i
++)
290 if (reg_names
[regno
+i
])
291 fprintf (file
, "%s", reg_names
[regno
+ i
]);
293 fprintf (file
, "h%d", regno
+ i
);
300 ra_print_rtx (file
, sub
, 0);
301 fprintf (file
, ":[%s+%d]", GET_MODE_NAME (mode
), ofs
);
305 case SCRATCH
: fputs ("scratch", file
); break;
306 case CONCAT
: ra_print_rtx_2op (file
, x
); break;
307 case HIGH
: ra_print_rtx_1op (file
, x
); break;
310 ra_print_rtx (file
, XEXP (x
, 0), 0);
311 fputs (" + lo(", file
);
312 ra_print_rtx (file
, XEXP (x
, 1), 0);
315 case MEM
: fputs ("[", file
);
316 ra_print_rtx (file
, XEXP (x
, 0), 0);
317 fprintf (file
, "]:%s", GET_MODE_NAME (GET_MODE (x
)));
318 /* XXX print alias set too ?? */
322 rtx sub
= XEXP (x
, 0);
323 if (GET_CODE (sub
) == NOTE
324 && NOTE_LINE_NUMBER (sub
) == NOTE_INSN_DELETED_LABEL
)
325 fprintf (file
, "(deleted uid=%d)", INSN_UID (sub
));
326 else if (GET_CODE (sub
) == CODE_LABEL
)
327 fprintf (file
, "L%d", CODE_LABEL_NUMBER (sub
));
329 fprintf (file
, "(nonlabel uid=%d)", INSN_UID (sub
));
333 fprintf (file
, "sym(\"%s\")", XSTR (x
, 0)); break;
334 case CC0
: fputs ("cc0", file
); break;
335 default: print_inline_rtx (file
, x
, 0); break;
339 /* Print a general rtx X to FILE in nice infix form.
340 If WITH_PN is set, and X is one of the toplevel constructs
341 (insns, notes, labels or barriers), then print also the UIDs of
342 the preceding and following insn. */
345 ra_print_rtx (file
, x
, with_pn
)
356 class = GET_RTX_CLASS (code
);
358 /* First handle the insn like constructs. */
359 if (INSN_P (x
) || code
== NOTE
|| code
== CODE_LABEL
|| code
== BARRIER
)
363 /* Non-insns are prefixed by a ';'. */
366 else if (code
== NOTE
)
367 /* But notes are indented very far right. */
368 fprintf (file
, "\t\t\t\t\t; ");
369 else if (code
== CODE_LABEL
)
370 /* And labels have their Lxx name first, before the actual UID. */
372 fprintf (file
, "L%d:\t; ", CODE_LABEL_NUMBER (x
));
374 fprintf (file
, "(%s) ", LABEL_NAME (x
));
375 switch (LABEL_KIND (x
))
377 case LABEL_NORMAL
: break;
378 case LABEL_STATIC_ENTRY
: fputs (" (entry)", file
); break;
379 case LABEL_GLOBAL_ENTRY
: fputs (" (global entry)", file
); break;
380 case LABEL_WEAK_ENTRY
: fputs (" (weak entry)", file
); break;
383 fprintf (file
, " [%d uses] uid=(", LABEL_NUSES (x
));
385 fprintf (file
, "%d", INSN_UID (x
));
387 fprintf (file
, " %d %d", PREV_INSN (x
) ? INSN_UID (PREV_INSN (x
)) : 0,
388 NEXT_INSN (x
) ? INSN_UID (NEXT_INSN (x
)) : 0);
390 fputs (" -------- barrier ---------", file
);
391 else if (code
== CODE_LABEL
)
393 else if (code
== NOTE
)
395 int ln
= NOTE_LINE_NUMBER (x
);
396 if (ln
>= (int) NOTE_INSN_BIAS
&& ln
< (int) NOTE_INSN_MAX
)
397 fprintf (file
, " %s", GET_NOTE_INSN_NAME (ln
));
400 fprintf (file
, " line %d", ln
);
401 if (NOTE_SOURCE_FILE (x
))
402 fprintf (file
, ":%s", NOTE_SOURCE_FILE (x
));
407 fprintf (file
, "\t");
408 ra_print_rtx (file
, PATTERN (x
), 0);
414 /* Top-level stuff. */
418 for (j
= 0; j
< XVECLEN (x
, 0); j
++)
421 fputs ("\t;; ", file
);
422 ra_print_rtx (file
, XVECEXP (x
, 0, j
), 0);
426 case UNSPEC
: case UNSPEC_VOLATILE
:
429 fprintf (file
, "unspec%s(%d",
430 (code
== UNSPEC
) ? "" : "_vol", XINT (x
, 1));
431 for (j
= 0; j
< XVECLEN (x
, 0); j
++)
434 ra_print_rtx (file
, XVECEXP (x
, 0, j
), 0);
440 if (GET_CODE (SET_DEST (x
)) == PC
)
442 if (GET_CODE (SET_SRC (x
)) == IF_THEN_ELSE
443 && GET_CODE (XEXP (SET_SRC(x
), 2)) == PC
)
446 ra_print_rtx (file
, XEXP (SET_SRC (x
), 0), 0);
447 fputs (" jump ", file
);
448 ra_print_rtx (file
, XEXP (SET_SRC (x
), 1), 0);
452 fputs ("jump ", file
);
453 ra_print_rtx (file
, SET_SRC (x
), 0);
458 ra_print_rtx (file
, SET_DEST (x
), 0);
459 fputs (" <= ", file
);
460 ra_print_rtx (file
, SET_SRC (x
), 0);
464 fputs ("use <= ", file
);
465 ra_print_rtx (file
, XEXP (x
, 0), 0);
468 ra_print_rtx (file
, XEXP (x
, 0), 0);
469 fputs (" <= clobber", file
);
472 fputs ("call ", file
);
473 ra_print_rtx (file
, XEXP (x
, 0), 0); /* Address */
474 fputs (" numargs=", file
);
475 ra_print_rtx (file
, XEXP (x
, 1), 0); /* Num arguments */
478 fputs ("return", file
);
481 fputs ("if (", file
);
482 ra_print_rtx (file
, XEXP (x
, 0), 0);
483 fputs (") trap ", file
);
484 ra_print_rtx (file
, XEXP (x
, 1), 0);
487 fprintf (file
, "resx from region %d", XINT (x
, 0));
490 /* Different things of class 'x' */
491 case SUBREG
: ra_print_rtx_object (file
, x
); break;
492 case STRICT_LOW_PART
:
493 fputs ("low(", file
);
494 ra_print_rtx (file
, XEXP (x
, 0), 0);
504 ra_print_rtx_1op (file
, x
);
505 else if (class == '2' || class == 'c' || class == '<')
506 ra_print_rtx_2op (file
, x
);
507 else if (class == '3' || class == 'b')
508 ra_print_rtx_3op (file
, x
);
509 else if (class == 'o')
510 ra_print_rtx_object (file
, x
);
512 print_inline_rtx (file
, x
, 0);
515 /* This only calls ra_print_rtx(), but emits a final newline. */
518 ra_print_rtx_top (file
, x
, with_pn
)
523 ra_print_rtx (file
, x
, with_pn
);
524 fprintf (file
, "\n");
527 /* Callable from gdb. This prints rtx X onto stderr. */
533 ra_print_rtx_top (stderr
, x
, 1);
536 /* This prints the content of basic block with index BBI.
537 The first and last insn are emitted with UIDs of prev and next insns. */
543 basic_block bb
= BASIC_BLOCK (bbi
);
545 for (insn
= bb
->head
; insn
; insn
= NEXT_INSN (insn
))
547 ra_print_rtx_top (stderr
, insn
, (insn
== bb
->head
|| insn
== bb
->end
));
548 fprintf (stderr
, "\n");
554 /* Beginning from INSN, emit NUM insns (if NUM is non-negative)
555 or emit a window of NUM insns around INSN, to stderr. */
558 ra_debug_insns (insn
, num
)
562 int i
, count
= (num
== 0 ? 1 : num
< 0 ? -num
: num
);
564 for (i
= count
/ 2; i
> 0 && PREV_INSN (insn
); i
--)
565 insn
= PREV_INSN (insn
);
566 for (i
= count
; i
> 0 && insn
; insn
= NEXT_INSN (insn
), i
--)
568 if (GET_CODE (insn
) == CODE_LABEL
)
569 fprintf (stderr
, "\n");
570 ra_print_rtx_top (stderr
, insn
, (i
== count
|| i
== 1));
574 /* Beginning with INSN, emit the whole insn chain into FILE.
575 This also outputs comments when basic blocks start or end and omits
576 some notes, if flag_ra_dump_notes is zero. */
579 ra_print_rtl_with_bb (file
, insn
)
583 basic_block last_bb
, bb
;
584 unsigned int num
= 0;
588 for (; insn
; insn
= NEXT_INSN (insn
))
590 if (GET_CODE (insn
) == BARRIER
)
593 bb
= BLOCK_FOR_INSN (insn
);
597 fprintf (file
, ";; End of basic block %d\n", last_bb
->index
);
599 fprintf (file
, ";; Begin of basic block %d\n", bb
->index
);
602 if (GET_CODE (insn
) == CODE_LABEL
)
604 if (GET_CODE (insn
) == NOTE
)
606 /* Ignore basic block and maybe other notes not referencing
608 if (NOTE_LINE_NUMBER (insn
) != NOTE_INSN_BASIC_BLOCK
609 && (flag_ra_dump_notes
610 || NOTE_LINE_NUMBER (insn
) == NOTE_INSN_DELETED
611 || NOTE_LINE_NUMBER (insn
) == NOTE_INSN_DELETED_LABEL
))
613 ra_print_rtx_top (file
, insn
, (num
== 0 || !NEXT_INSN (insn
)));
619 ra_print_rtx_top (file
, insn
, (num
== 0 || !NEXT_INSN (insn
)));
625 /* Count how many insns were seen how often, while building the interference
626 graph, and prints the findings. */
635 for (i
= 0; i
< N
; i
++)
637 for (i
= 0; i
< get_max_uid (); i
++)
638 if (number_seen
[i
] < N
- 1)
639 num
[number_seen
[i
]]++;
642 for (i
= 0; i
< N
- 1; i
++)
644 ra_debug_msg (DUMP_PROCESS
, "%d insns seen %d times\n", num
[i
], i
);
646 ra_debug_msg (DUMP_PROCESS
, "%d insns seen %d and more times\n", num
[i
],
648 ra_debug_msg (DUMP_PROCESS
, "from overall %d insns\n", get_max_uid ());
652 /* Dump the interference graph, the move list and the webs. */
656 struct df
*df ATTRIBUTE_UNUSED
;
658 struct move_list
*ml
;
659 unsigned int def1
, def2
;
663 if (!rtl_dump_file
|| (debug_new_regalloc
& (DUMP_IGRAPH
| DUMP_WEBS
)) == 0)
665 ra_debug_msg (DUMP_IGRAPH
, "conflicts:\n ");
666 for (def1
= 0; def1
< num_webs
; def1
++)
669 for (num2
=0, def2
= 0; def2
< num_webs
; def2
++)
670 if (def1
!= def2
&& TEST_BIT (igraph
, igraph_index (def1
, def2
)))
674 if (SUBWEB_P (ID2WEB (def1
)))
675 ra_debug_msg (DUMP_IGRAPH
, "%d (SUBREG %d, %d) with ", def1
,
676 ID2WEB (def1
)->regno
,
677 SUBREG_BYTE (ID2WEB (def1
)->orig_x
));
679 ra_debug_msg (DUMP_IGRAPH
, "%d (REG %d) with ", def1
,
680 ID2WEB (def1
)->regno
);
683 ra_debug_msg (DUMP_IGRAPH
, "\n ");
686 if (SUBWEB_P (ID2WEB (def2
)))
687 ra_debug_msg (DUMP_IGRAPH
, "%d(%d,%d) ", def2
, ID2WEB (def2
)->regno
,
688 SUBREG_BYTE (ID2WEB (def2
)->orig_x
));
690 ra_debug_msg (DUMP_IGRAPH
, "%d(%d) ", def2
, ID2WEB (def2
)->regno
);
693 ra_debug_msg (DUMP_IGRAPH
, "\n ");
695 ra_debug_msg (DUMP_IGRAPH
, "\n");
696 for (ml
= wl_moves
; ml
; ml
= ml
->next
)
699 ra_debug_msg (DUMP_IGRAPH
, "move: insn %d: Web %d <-- Web %d\n",
700 INSN_UID (ml
->move
->insn
), ml
->move
->target_web
->id
,
701 ml
->move
->source_web
->id
);
703 ra_debug_msg (DUMP_WEBS
, "\nWebs:\n");
704 for (i
= 0; i
< num_webs
; i
++)
706 struct web
*web
= ID2WEB (i
);
708 ra_debug_msg (DUMP_WEBS
, " %4d : regno %3d", i
, web
->regno
);
711 ra_debug_msg (DUMP_WEBS
, " sub %d", SUBREG_BYTE (web
->orig_x
));
712 ra_debug_msg (DUMP_WEBS
, " par %d", find_web_for_subweb (web
)->id
);
714 ra_debug_msg (DUMP_WEBS
, " +%d (span %d, cost ",
715 web
->add_hardregs
, web
->span_deaths
);
716 ra_debug_msg (DUMP_WEBS
, HOST_WIDE_INT_PRINT_DEC
, web
->spill_cost
);
717 ra_debug_msg (DUMP_WEBS
, ") (%s)", reg_class_names
[web
->regclass
]);
718 if (web
->spill_temp
== 1)
719 ra_debug_msg (DUMP_WEBS
, " (spilltemp)");
720 else if (web
->spill_temp
== 2)
721 ra_debug_msg (DUMP_WEBS
, " (spilltem2)");
722 else if (web
->spill_temp
== 3)
723 ra_debug_msg (DUMP_WEBS
, " (short)");
724 if (web
->type
== PRECOLORED
)
725 ra_debug_msg (DUMP_WEBS
, " (precolored, color=%d)", web
->color
);
726 else if (find_web_for_subweb (web
)->num_uses
== 0)
727 ra_debug_msg (DUMP_WEBS
, " dead");
728 if (web
->crosses_call
)
729 ra_debug_msg (DUMP_WEBS
, " xcall");
730 if (web
->regno
>= max_normal_pseudo
)
731 ra_debug_msg (DUMP_WEBS
, " stack");
732 ra_debug_msg (DUMP_WEBS
, "\n");
736 /* Dump the interference graph and webs in a format easily
737 parsable by programs. Used to emit real world interference graph
738 to my custom graph colorizer. */
741 dump_igraph_machine ()
745 if (!rtl_dump_file
|| (debug_new_regalloc
& DUMP_IGRAPH_M
) == 0)
747 ra_debug_msg (DUMP_IGRAPH_M
, "g %d %d\n", num_webs
- num_subwebs
,
748 FIRST_PSEUDO_REGISTER
);
749 for (i
= 0; i
< num_webs
- num_subwebs
; i
++)
751 struct web
*web
= ID2WEB (i
);
752 struct conflict_link
*cl
;
756 flags
= web
->spill_temp
& 0xF;
757 flags
|= ((web
->type
== PRECOLORED
) ? 1 : 0) << 4;
758 flags
|= (web
->add_hardregs
& 0xF) << 5;
759 for (cl
= web
->conflict_list
; cl
; cl
= cl
->next
)
760 if (cl
->t
->id
< web
->id
)
762 ra_debug_msg (DUMP_IGRAPH_M
, "n %d %d %d %d %d %d %d\n",
763 web
->id
, web
->color
, flags
,
764 (unsigned int)web
->spill_cost
, web
->num_defs
, web
->num_uses
,
766 if (web
->type
!= PRECOLORED
)
768 ra_debug_msg (DUMP_IGRAPH_M
, "s %d", web
->id
);
773 for (n
= 0; n
< 32 && col
< FIRST_PSEUDO_REGISTER
; n
++, col
++)
774 if (TEST_HARD_REG_BIT (web
->usable_regs
, col
))
776 ra_debug_msg (DUMP_IGRAPH_M
, " %u", u
);
777 if (col
>= FIRST_PSEUDO_REGISTER
)
780 ra_debug_msg (DUMP_IGRAPH_M
, "\n");
784 ra_debug_msg (DUMP_IGRAPH_M
, "c %d", web
->id
);
785 for (cl
= web
->conflict_list
; cl
; cl
= cl
->next
)
787 if (cl
->t
->id
< web
->id
)
788 ra_debug_msg (DUMP_IGRAPH_M
, " %d", cl
->t
->id
);
790 ra_debug_msg (DUMP_IGRAPH_M
, "\n");
793 ra_debug_msg (DUMP_IGRAPH_M
, "e\n");
796 /* This runs after colorization and changing the insn stream.
797 It temporarily replaces all pseudo registers with their colors,
798 and emits information, if the resulting insns are strictly valid. */
805 if (!rtl_dump_file
|| (debug_new_regalloc
& DUMP_CONSTRAINTS
) == 0)
807 for (i
= FIRST_PSEUDO_REGISTER
; i
< ra_max_regno
; i
++)
808 if (regno_reg_rtx
[i
] && GET_CODE (regno_reg_rtx
[i
]) == REG
)
809 REGNO (regno_reg_rtx
[i
])
810 = ra_reg_renumber
[i
] >= 0 ? ra_reg_renumber
[i
] : i
;
811 for (insn
= get_insns (); insn
; insn
= NEXT_INSN (insn
))
815 int uid
= INSN_UID (insn
);
817 /* Don't simply force rerecognition, as combine might left us
818 with some unrecongnizable ones, which later leads to aborts
819 in regclass, if we now destroy the remembered INSN_CODE(). */
820 /*INSN_CODE (insn) = -1;*/
821 code
= recog_memoized (insn
);
824 ra_debug_msg (DUMP_CONSTRAINTS
,
825 "%d: asm insn or not recognizable.\n", uid
);
828 ra_debug_msg (DUMP_CONSTRAINTS
,
829 "%d: code %d {%s}, %d operands, constraints: ",
830 uid
, code
, insn_data
[code
].name
, recog_data
.n_operands
);
832 /*preprocess_constraints ();*/
833 for (o
= 0; o
< recog_data
.n_operands
; o
++)
835 ra_debug_msg (DUMP_CONSTRAINTS
,
836 "%d:%s ", o
, recog_data
.constraints
[o
]);
838 if (constrain_operands (1))
839 ra_debug_msg (DUMP_CONSTRAINTS
, "matches strictly alternative %d",
842 ra_debug_msg (DUMP_CONSTRAINTS
, "doesn't match strictly");
843 ra_debug_msg (DUMP_CONSTRAINTS
, "\n");
845 for (i
= FIRST_PSEUDO_REGISTER
; i
< ra_max_regno
; i
++)
846 if (regno_reg_rtx
[i
] && GET_CODE (regno_reg_rtx
[i
]) == REG
)
847 REGNO (regno_reg_rtx
[i
]) = i
;
850 /* This counts and emits the cumulated cost of all spilled webs,
851 preceded by a custom message MSG, with debug level LEVEL. */
854 dump_graph_cost (level
, msg
)
859 unsigned HOST_WIDE_INT cost
;
860 if (!rtl_dump_file
|| (debug_new_regalloc
& level
) == 0)
864 for (i
= 0; i
< num_webs
; i
++)
866 struct web
*web
= id2web
[i
];
867 if (alias (web
)->type
== SPILLED
)
868 cost
+= web
->orig_spill_cost
;
870 ra_debug_msg (level
, " spill cost of graph (%s) = ", msg
? msg
: "");
871 ra_debug_msg (level
, HOST_WIDE_INT_PRINT_UNSIGNED
, cost
);
872 ra_debug_msg (level
, "\n");
875 /* Dump the color assignment per web, the coalesced and spilled webs. */
879 struct df
*df ATTRIBUTE_UNUSED
;
883 if (!rtl_dump_file
|| (debug_new_regalloc
& DUMP_RESULTS
) == 0)
886 ra_debug_msg (DUMP_RESULTS
, "\nColored:\n");
887 for (d
= WEBS(COLORED
); d
; d
= d
->next
)
890 ra_debug_msg (DUMP_RESULTS
, " %4d : color %d\n", web
->id
, web
->color
);
892 ra_debug_msg (DUMP_RESULTS
, "\nCoalesced:\n");
893 for (d
= WEBS(COALESCED
); d
; d
= d
->next
)
896 ra_debug_msg (DUMP_RESULTS
, " %4d : to web %d, color %d\n", web
->id
,
897 alias (web
)->id
, web
->color
);
899 ra_debug_msg (DUMP_RESULTS
, "\nSpilled:\n");
900 for (d
= WEBS(SPILLED
); d
; d
= d
->next
)
903 ra_debug_msg (DUMP_RESULTS
, " %4d\n", web
->id
);
905 ra_debug_msg (DUMP_RESULTS
, "\n");
906 dump_cost (DUMP_RESULTS
);
909 /* Calculate and dump the cumulated costs of certain types of insns
910 (loads, stores and copies). */
913 dump_static_insn_cost (file
, message
, prefix
)
920 unsigned HOST_WIDE_INT cost
;
924 struct cost load
, store
, regcopy
, selfcopy
, overall
;
925 memset (&load
, 0, sizeof(load
));
926 memset (&store
, 0, sizeof(store
));
927 memset (®copy
, 0, sizeof(regcopy
));
928 memset (&selfcopy
, 0, sizeof(selfcopy
));
929 memset (&overall
, 0, sizeof(overall
));
936 unsigned HOST_WIDE_INT block_cost
= bb
->frequency
;
938 for (insn
= bb
->head
; insn
; insn
= NEXT_INSN (insn
))
940 /* Yes, yes. We don't calculate the costs precisely.
941 Only for "simple enough" insns. Those containing single
943 if (INSN_P (insn
) && ((set
= single_set (insn
)) != NULL
))
945 rtx src
= SET_SRC (set
);
946 rtx dest
= SET_DEST (set
);
947 struct cost
*pcost
= NULL
;
948 overall
.cost
+= block_cost
;
950 if (rtx_equal_p (src
, dest
))
952 else if (GET_CODE (src
) == GET_CODE (dest
)
953 && ((GET_CODE (src
) == REG
)
954 || (GET_CODE (src
) == SUBREG
955 && GET_CODE (SUBREG_REG (src
)) == REG
956 && GET_CODE (SUBREG_REG (dest
)) == REG
)))
960 if (GET_CODE (src
) == SUBREG
)
961 src
= SUBREG_REG (src
);
962 if (GET_CODE (dest
) == SUBREG
)
963 dest
= SUBREG_REG (dest
);
964 if (GET_CODE (src
) == MEM
&& GET_CODE (dest
) != MEM
965 && memref_is_stack_slot (src
))
967 else if (GET_CODE (src
) != MEM
&& GET_CODE (dest
) == MEM
968 && memref_is_stack_slot (dest
))
973 pcost
->cost
+= block_cost
;
984 fprintf (file
, "static insn cost %s\n", message
? message
: "");
985 fprintf (file
, " %soverall:\tnum=%6d\tcost=", prefix
, overall
.count
);
986 fprintf (file
, HOST_WIDE_INT_PRINT_DEC_SPACE
, 8, overall
.cost
);
987 fprintf (file
, "\n");
988 fprintf (file
, " %sloads:\tnum=%6d\tcost=", prefix
, load
.count
);
989 fprintf (file
, HOST_WIDE_INT_PRINT_DEC_SPACE
, 8, load
.cost
);
990 fprintf (file
, "\n");
991 fprintf (file
, " %sstores:\tnum=%6d\tcost=", prefix
, store
.count
);
992 fprintf (file
, HOST_WIDE_INT_PRINT_DEC_SPACE
, 8, store
.cost
);
993 fprintf (file
, "\n");
994 fprintf (file
, " %sregcopy:\tnum=%6d\tcost=", prefix
, regcopy
.count
);
995 fprintf (file
, HOST_WIDE_INT_PRINT_DEC_SPACE
, 8, regcopy
.cost
);
996 fprintf (file
, "\n");
997 fprintf (file
, " %sselfcpy:\tnum=%6d\tcost=", prefix
, selfcopy
.count
);
998 fprintf (file
, HOST_WIDE_INT_PRINT_DEC_SPACE
, 8, selfcopy
.cost
);
999 fprintf (file
, "\n");
1002 /* Returns nonzero, if WEB1 and WEB2 have some possible
1003 hardregs in common. */
1006 web_conflicts_p (web1
, web2
)
1010 if (web1
->type
== PRECOLORED
&& web2
->type
== PRECOLORED
)
1013 if (web1
->type
== PRECOLORED
)
1014 return TEST_HARD_REG_BIT (web2
->usable_regs
, web1
->regno
);
1016 if (web2
->type
== PRECOLORED
)
1017 return TEST_HARD_REG_BIT (web1
->usable_regs
, web2
->regno
);
1019 return hard_regs_intersect_p (&web1
->usable_regs
, &web2
->usable_regs
);
1022 /* Dump all uids of insns in which WEB is mentioned. */
1025 dump_web_insns (web
)
1030 ra_debug_msg (DUMP_EVER
, "Web: %i(%i)+%i class: %s freedom: %i degree %i\n",
1031 web
->id
, web
->regno
, web
->add_hardregs
,
1032 reg_class_names
[web
->regclass
],
1033 web
->num_freedom
, web
->num_conflicts
);
1034 ra_debug_msg (DUMP_EVER
, " def insns:");
1036 for (i
= 0; i
< web
->num_defs
; ++i
)
1038 ra_debug_msg (DUMP_EVER
, " %d ", INSN_UID (web
->defs
[i
]->insn
));
1041 ra_debug_msg (DUMP_EVER
, "\n use insns:");
1042 for (i
= 0; i
< web
->num_uses
; ++i
)
1044 ra_debug_msg (DUMP_EVER
, " %d ", INSN_UID (web
->uses
[i
]->insn
));
1046 ra_debug_msg (DUMP_EVER
, "\n");
1049 /* Dump conflicts for web WEB. */
1052 dump_web_conflicts (web
)
1058 ra_debug_msg (DUMP_EVER
, "Web: %i(%i)+%i class: %s freedom: %i degree %i\n",
1059 web
->id
, web
->regno
, web
->add_hardregs
,
1060 reg_class_names
[web
->regclass
],
1061 web
->num_freedom
, web
->num_conflicts
);
1063 for (def2
= 0; def2
< num_webs
; def2
++)
1064 if (TEST_BIT (igraph
, igraph_index (web
->id
, def2
)) && web
->id
!= def2
)
1067 ra_debug_msg (DUMP_EVER
, "\n ");
1070 ra_debug_msg (DUMP_EVER
, " %d(%d)", def2
, id2web
[def2
]->regno
);
1071 if (id2web
[def2
]->add_hardregs
)
1072 ra_debug_msg (DUMP_EVER
, "+%d", id2web
[def2
]->add_hardregs
);
1074 if (web_conflicts_p (web
, id2web
[def2
]))
1075 ra_debug_msg (DUMP_EVER
, "/x");
1077 if (id2web
[def2
]->type
== SELECT
)
1078 ra_debug_msg (DUMP_EVER
, "/s");
1080 if (id2web
[def2
]->type
== COALESCED
)
1081 ra_debug_msg (DUMP_EVER
,"/c/%d", alias (id2web
[def2
])->id
);
1083 ra_debug_msg (DUMP_EVER
, "\n");
1085 struct conflict_link
*wl
;
1087 ra_debug_msg (DUMP_EVER
, "By conflicts: ");
1088 for (wl
= web
->conflict_list
; wl
; wl
= wl
->next
)
1090 struct web
* w
= wl
->t
;
1092 ra_debug_msg (DUMP_EVER
, "\n ");
1094 ra_debug_msg (DUMP_EVER
, "%d(%d)%s ", w
->id
, w
->regno
,
1095 web_conflicts_p (web
, w
) ? "+" : "");
1097 ra_debug_msg (DUMP_EVER
, "\n");
1101 /* Output HARD_REG_SET to stderr. */
1104 debug_hard_reg_set (set
)
1108 for (i
=0; i
< FIRST_PSEUDO_REGISTER
; ++i
)
1110 if (TEST_HARD_REG_BIT (set
, i
))
1112 fprintf (stderr
, "%s ", reg_names
[i
]);
1115 fprintf (stderr
, "\n");
1119 vim:cinoptions={.5s,g0,p5,t0,(0,^-0.5s,n-0.5s:tw=78:cindent:sw=4: