1 /* Graph coloring register allocator
2 Copyright (C) 2001, 2002, 2004 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 && dump_file
!= NULL
)
58 vfprintf (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 LTGT
: opname
= "<>"; break;
138 case GE
: opname
= "s>="; break;
139 case GT
: opname
= "s>"; break;
140 case LE
: opname
= "s<="; break;
141 case LT
: opname
= "s<"; break;
142 case GEU
: opname
= "u>="; break;
143 case GTU
: opname
= "u>"; break;
144 case LEU
: opname
= "u<="; break;
145 case LTU
: opname
= "u<"; break;
148 opname
= GET_RTX_NAME (code
);
154 ra_print_rtx (file
, op0
, 0);
155 fprintf (file
, " %s ", opname
);
156 ra_print_rtx (file
, op1
, 0);
161 fprintf (file
, "%s(", opname
);
162 ra_print_rtx (file
, op0
, 0);
164 ra_print_rtx (file
, op1
, 0);
169 /* Print rtx X, which a three operand rtx to FILE.
170 I.e. X is either an IF_THEN_ELSE, or a bitmap operation. */
173 ra_print_rtx_3op (FILE *file
, rtx x
)
175 enum rtx_code code
= GET_CODE (x
);
176 rtx op0
= XEXP (x
, 0);
177 rtx op1
= XEXP (x
, 1);
178 rtx op2
= XEXP (x
, 2);
179 if (code
== IF_THEN_ELSE
)
181 ra_print_rtx (file
, op0
, 0);
183 ra_print_rtx (file
, op1
, 0);
185 ra_print_rtx (file
, op2
, 0);
189 /* Bitmap-operation */
190 fprintf (file
, "%s:%s(", GET_RTX_NAME (code
),
191 GET_MODE_NAME (GET_MODE (x
)));
192 ra_print_rtx (file
, op0
, 0);
194 ra_print_rtx (file
, op1
, 0);
196 ra_print_rtx (file
, op2
, 0);
201 /* Print rtx X, which represents an object (class 'o', 'C', or some constructs
202 of class 'x' (e.g. subreg)), to FILE.
203 (reg XX) rtl is represented as "pXX", of XX was a pseudo,
204 as "name" it name is the nonnull hardreg name, or as "hXX", if XX
205 is a hardreg, whose name is NULL, or empty. */
208 ra_print_rtx_object (FILE *file
, rtx x
)
210 enum rtx_code code
= GET_CODE (x
);
211 enum machine_mode mode
= GET_MODE (x
);
215 fprintf (file
, HOST_WIDE_INT_PRINT_DEC
, XWINT (x
, 0));
220 const char *fmt
= GET_RTX_FORMAT (code
);
221 fputs ("dbl(", file
);
222 for (i
= 0; i
< GET_RTX_LENGTH (code
); i
++)
226 if (fmt
[i
] == 'e' && XEXP (x
, i
))
227 /* The MEM or other stuff */
229 ra_print_rtx (file
, XEXP (x
, i
), 0);
232 else if (fmt
[i
] == 'w')
234 fprintf (file
, HOST_WIDE_INT_PRINT_HEX
, XWINT (x
, i
));
240 case CONST_STRING
: fprintf (file
, "\"%s\"", XSTR (x
, 0)); break;
241 case CONST
: fputs ("const(", file
);
242 ra_print_rtx (file
, XEXP (x
, 0), 0);
245 case PC
: fputs ("pc", file
); break;
248 int regno
= REGNO (x
);
249 if (regno
< FIRST_PSEUDO_REGISTER
)
251 int i
, nregs
= hard_regno_nregs
[regno
][mode
];
254 for (i
= 0; i
< nregs
; i
++)
258 if (reg_names
[regno
+i
] && *reg_names
[regno
+ i
])
259 fprintf (file
, "%s", reg_names
[regno
+ i
]);
261 fprintf (file
, "h%d", regno
+ i
);
267 fprintf (file
, "p%d", regno
);
272 rtx sub
= SUBREG_REG (x
);
273 int ofs
= SUBREG_BYTE (x
);
275 && REGNO (sub
) < FIRST_PSEUDO_REGISTER
)
277 int regno
= REGNO (sub
);
278 int i
, nregs
= hard_regno_nregs
[regno
][mode
];
279 regno
+= subreg_regno_offset (regno
, GET_MODE (sub
),
283 for (i
= 0; i
< nregs
; i
++)
287 if (reg_names
[regno
+i
])
288 fprintf (file
, "%s", reg_names
[regno
+ i
]);
290 fprintf (file
, "h%d", regno
+ i
);
297 ra_print_rtx (file
, sub
, 0);
298 fprintf (file
, ":[%s+%d]", GET_MODE_NAME (mode
), ofs
);
302 case SCRATCH
: fputs ("scratch", file
); break;
303 case CONCAT
: ra_print_rtx_2op (file
, x
); break;
304 case HIGH
: ra_print_rtx_1op (file
, x
); break;
307 ra_print_rtx (file
, XEXP (x
, 0), 0);
308 fputs (" + lo(", file
);
309 ra_print_rtx (file
, XEXP (x
, 1), 0);
312 case MEM
: fputs ("[", file
);
313 ra_print_rtx (file
, XEXP (x
, 0), 0);
314 fprintf (file
, "]:%s", GET_MODE_NAME (GET_MODE (x
)));
315 /* XXX print alias set too ?? */
319 rtx sub
= XEXP (x
, 0);
321 && NOTE_LINE_NUMBER (sub
) == NOTE_INSN_DELETED_LABEL
)
322 fprintf (file
, "(deleted uid=%d)", INSN_UID (sub
));
323 else if (LABEL_P (sub
))
324 fprintf (file
, "L%d", CODE_LABEL_NUMBER (sub
));
326 fprintf (file
, "(nonlabel uid=%d)", INSN_UID (sub
));
330 fprintf (file
, "sym(\"%s\")", XSTR (x
, 0)); break;
331 case CC0
: fputs ("cc0", file
); break;
332 default: print_inline_rtx (file
, x
, 0); break;
336 /* Print a general rtx X to FILE in nice infix form.
337 If WITH_PN is set, and X is one of the toplevel constructs
338 (insns, notes, labels or barriers), then print also the UIDs of
339 the preceding and following insn. */
342 ra_print_rtx (FILE *file
, rtx x
, int with_pn
)
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
));
393 NOTE_EXPANDED_LOCATION (s
, x
);
394 fprintf (file
, " line %d", s
.line
);
396 fprintf (file
, ":%s", s
.file
);
401 fprintf (file
, "\t");
402 ra_print_rtx (file
, PATTERN (x
), 0);
408 /* Top-level stuff. */
412 for (j
= 0; j
< XVECLEN (x
, 0); j
++)
415 fputs ("\t;; ", file
);
416 ra_print_rtx (file
, XVECEXP (x
, 0, j
), 0);
420 case UNSPEC
: case UNSPEC_VOLATILE
:
423 fprintf (file
, "unspec%s(%d",
424 (code
== UNSPEC
) ? "" : "_vol", XINT (x
, 1));
425 for (j
= 0; j
< XVECLEN (x
, 0); j
++)
428 ra_print_rtx (file
, XVECEXP (x
, 0, j
), 0);
434 if (GET_CODE (SET_DEST (x
)) == PC
)
436 if (GET_CODE (SET_SRC (x
)) == IF_THEN_ELSE
437 && GET_CODE (XEXP (SET_SRC(x
), 2)) == PC
)
440 ra_print_rtx (file
, XEXP (SET_SRC (x
), 0), 0);
441 fputs (" jump ", file
);
442 ra_print_rtx (file
, XEXP (SET_SRC (x
), 1), 0);
446 fputs ("jump ", file
);
447 ra_print_rtx (file
, SET_SRC (x
), 0);
452 ra_print_rtx (file
, SET_DEST (x
), 0);
453 fputs (" <= ", file
);
454 ra_print_rtx (file
, SET_SRC (x
), 0);
458 fputs ("use <= ", file
);
459 ra_print_rtx (file
, XEXP (x
, 0), 0);
462 ra_print_rtx (file
, XEXP (x
, 0), 0);
463 fputs (" <= clobber", file
);
466 fputs ("call ", file
);
467 ra_print_rtx (file
, XEXP (x
, 0), 0); /* Address */
468 fputs (" numargs=", file
);
469 ra_print_rtx (file
, XEXP (x
, 1), 0); /* Num arguments */
472 fputs ("return", file
);
475 fputs ("if (", file
);
476 ra_print_rtx (file
, XEXP (x
, 0), 0);
477 fputs (") trap ", file
);
478 ra_print_rtx (file
, XEXP (x
, 1), 0);
481 fprintf (file
, "resx from region %d", XINT (x
, 0));
484 /* Different things of class 'x' */
485 case SUBREG
: ra_print_rtx_object (file
, x
); break;
486 case STRICT_LOW_PART
:
487 fputs ("low(", file
);
488 ra_print_rtx (file
, XEXP (x
, 0), 0);
497 switch (GET_RTX_CLASS (code
))
500 ra_print_rtx_1op (file
, x
);
505 case RTX_COMM_COMPARE
:
506 ra_print_rtx_2op (file
, x
);
509 case RTX_BITFIELD_OPS
:
510 ra_print_rtx_3op (file
, x
);
514 ra_print_rtx_object (file
, x
);
517 print_inline_rtx (file
, x
, 0);
522 /* This only calls ra_print_rtx(), but emits a final newline. */
525 ra_print_rtx_top (FILE *file
, rtx x
, int with_pn
)
527 ra_print_rtx (file
, x
, with_pn
);
528 fprintf (file
, "\n");
531 /* Callable from gdb. This prints rtx X onto stderr. */
536 ra_print_rtx_top (stderr
, x
, 1);
539 /* This prints the content of basic block with index BBI.
540 The first and last insn are emitted with UIDs of prev and next insns. */
543 ra_debug_bbi (int bbi
)
545 basic_block bb
= BASIC_BLOCK (bbi
);
547 for (insn
= BB_HEAD (bb
); insn
; insn
= NEXT_INSN (insn
))
549 ra_print_rtx_top (stderr
, insn
,
550 (insn
== BB_HEAD (bb
) || insn
== BB_END (bb
)));
551 fprintf (stderr
, "\n");
552 if (insn
== BB_END (bb
))
557 /* Beginning from INSN, emit NUM insns (if NUM is non-negative)
558 or emit a window of NUM insns around INSN, to stderr. */
561 ra_debug_insns (rtx insn
, int num
)
563 int i
, count
= (num
== 0 ? 1 : num
< 0 ? -num
: num
);
565 for (i
= count
/ 2; i
> 0 && PREV_INSN (insn
); i
--)
566 insn
= PREV_INSN (insn
);
567 for (i
= count
; i
> 0 && insn
; insn
= NEXT_INSN (insn
), i
--)
570 fprintf (stderr
, "\n");
571 ra_print_rtx_top (stderr
, insn
, (i
== count
|| i
== 1));
575 /* Beginning with INSN, emit the whole insn chain into FILE.
576 This also outputs comments when basic blocks start or end and omits
577 some notes, if flag_ra_dump_notes is zero. */
580 ra_print_rtl_with_bb (FILE *file
, rtx insn
)
582 basic_block last_bb
, bb
;
583 unsigned int num
= 0;
587 for (; insn
; insn
= NEXT_INSN (insn
))
589 if (BARRIER_P (insn
))
592 bb
= BLOCK_FOR_INSN (insn
);
596 fprintf (file
, ";; End of basic block %d\n", last_bb
->index
);
598 fprintf (file
, ";; Begin of basic block %d\n", bb
->index
);
605 /* Ignore basic block and maybe other notes not referencing
607 if (NOTE_LINE_NUMBER (insn
) != NOTE_INSN_BASIC_BLOCK
608 && (flag_ra_dump_notes
609 || NOTE_LINE_NUMBER (insn
) == NOTE_INSN_DELETED
610 || NOTE_LINE_NUMBER (insn
) == NOTE_INSN_DELETED_LABEL
))
612 ra_print_rtx_top (file
, insn
, (num
== 0 || !NEXT_INSN (insn
)));
618 ra_print_rtx_top (file
, insn
, (num
== 0 || !NEXT_INSN (insn
)));
624 /* Count how many insns were seen how often, while building the interference
625 graph, and prints the findings. */
628 dump_number_seen (void)
634 for (i
= 0; i
< N
; i
++)
636 for (i
= 0; i
< get_max_uid (); i
++)
637 if (number_seen
[i
] < N
- 1)
638 num
[number_seen
[i
]]++;
641 for (i
= 0; i
< N
- 1; i
++)
643 ra_debug_msg (DUMP_PROCESS
, "%d insns seen %d times\n", num
[i
], i
);
645 ra_debug_msg (DUMP_PROCESS
, "%d insns seen %d and more times\n", num
[i
],
647 ra_debug_msg (DUMP_PROCESS
, "from overall %d insns\n", get_max_uid ());
651 /* Dump the interference graph, the move list and the webs. */
654 dump_igraph (struct df
*df ATTRIBUTE_UNUSED
)
656 struct move_list
*ml
;
657 unsigned int def1
, def2
;
661 if (!dump_file
|| (debug_new_regalloc
& (DUMP_IGRAPH
| DUMP_WEBS
)) == 0)
663 ra_debug_msg (DUMP_IGRAPH
, "conflicts:\n ");
664 for (def1
= 0; def1
< num_webs
; def1
++)
668 for (def2
= 0; def2
< num_webs
; def2
++)
669 if (def1
!= def2
&& TEST_BIT (igraph
, igraph_index (def1
, def2
)))
673 if (SUBWEB_P (ID2WEB (def1
)))
674 ra_debug_msg (DUMP_IGRAPH
, "%d (SUBREG %d, %d) with ", def1
,
675 ID2WEB (def1
)->regno
,
676 SUBREG_BYTE (ID2WEB (def1
)->orig_x
));
678 ra_debug_msg (DUMP_IGRAPH
, "%d (REG %d) with ", def1
,
679 ID2WEB (def1
)->regno
);
682 ra_debug_msg (DUMP_IGRAPH
, "\n ");
685 if (SUBWEB_P (ID2WEB (def2
)))
686 ra_debug_msg (DUMP_IGRAPH
, "%d(%d,%d) ", def2
, ID2WEB (def2
)->regno
,
687 SUBREG_BYTE (ID2WEB (def2
)->orig_x
));
689 ra_debug_msg (DUMP_IGRAPH
, "%d(%d) ", def2
, ID2WEB (def2
)->regno
);
692 ra_debug_msg (DUMP_IGRAPH
, "\n ");
694 ra_debug_msg (DUMP_IGRAPH
, "\n");
695 for (ml
= wl_moves
; ml
; ml
= ml
->next
)
698 ra_debug_msg (DUMP_IGRAPH
, "move: insn %d: Web %d <-- Web %d\n",
699 INSN_UID (ml
->move
->insn
), ml
->move
->target_web
->id
,
700 ml
->move
->source_web
->id
);
702 ra_debug_msg (DUMP_WEBS
, "\nWebs:\n");
703 for (i
= 0; i
< num_webs
; i
++)
705 struct web
*web
= ID2WEB (i
);
707 ra_debug_msg (DUMP_WEBS
, " %4d : regno %3d", i
, web
->regno
);
710 ra_debug_msg (DUMP_WEBS
, " sub %d", SUBREG_BYTE (web
->orig_x
));
711 ra_debug_msg (DUMP_WEBS
, " par %d", find_web_for_subweb (web
)->id
);
713 ra_debug_msg (DUMP_WEBS
, " +%d (span %d, cost "
714 HOST_WIDE_INT_PRINT_DEC
") (%s)",
715 web
->add_hardregs
, web
->span_deaths
, web
->spill_cost
,
716 reg_class_names
[web
->regclass
]);
717 if (web
->spill_temp
== 1)
718 ra_debug_msg (DUMP_WEBS
, " (spilltemp)");
719 else if (web
->spill_temp
== 2)
720 ra_debug_msg (DUMP_WEBS
, " (spilltem2)");
721 else if (web
->spill_temp
== 3)
722 ra_debug_msg (DUMP_WEBS
, " (short)");
723 if (web
->type
== PRECOLORED
)
724 ra_debug_msg (DUMP_WEBS
, " (precolored, color=%d)", web
->color
);
725 else if (find_web_for_subweb (web
)->num_uses
== 0)
726 ra_debug_msg (DUMP_WEBS
, " dead");
727 if (web
->crosses_call
)
728 ra_debug_msg (DUMP_WEBS
, " xcall");
729 if (web
->regno
>= max_normal_pseudo
)
730 ra_debug_msg (DUMP_WEBS
, " stack");
731 ra_debug_msg (DUMP_WEBS
, "\n");
735 /* Dump the interference graph and webs in a format easily
736 parsable by programs. Used to emit real world interference graph
737 to my custom graph colorizer. */
740 dump_igraph_machine (void)
744 if (!dump_file
|| (debug_new_regalloc
& DUMP_IGRAPH_M
) == 0)
746 ra_debug_msg (DUMP_IGRAPH_M
, "g %d %d\n", num_webs
- num_subwebs
,
747 FIRST_PSEUDO_REGISTER
);
748 for (i
= 0; i
< num_webs
- num_subwebs
; i
++)
750 struct web
*web
= ID2WEB (i
);
751 struct conflict_link
*cl
;
755 flags
= web
->spill_temp
& 0xF;
756 flags
|= ((web
->type
== PRECOLORED
) ? 1 : 0) << 4;
757 flags
|= (web
->add_hardregs
& 0xF) << 5;
758 for (cl
= web
->conflict_list
; cl
; cl
= cl
->next
)
759 if (cl
->t
->id
< web
->id
)
761 ra_debug_msg (DUMP_IGRAPH_M
, "n %d %d %d %d %d %d %d\n",
762 web
->id
, web
->color
, flags
,
763 (unsigned int)web
->spill_cost
, web
->num_defs
, web
->num_uses
,
765 if (web
->type
!= PRECOLORED
)
767 ra_debug_msg (DUMP_IGRAPH_M
, "s %d", web
->id
);
772 for (n
= 0; n
< 32 && col
< FIRST_PSEUDO_REGISTER
; n
++, col
++)
773 if (TEST_HARD_REG_BIT (web
->usable_regs
, col
))
775 ra_debug_msg (DUMP_IGRAPH_M
, " %u", u
);
776 if (col
>= FIRST_PSEUDO_REGISTER
)
779 ra_debug_msg (DUMP_IGRAPH_M
, "\n");
783 ra_debug_msg (DUMP_IGRAPH_M
, "c %d", web
->id
);
784 for (cl
= web
->conflict_list
; cl
; cl
= cl
->next
)
786 if (cl
->t
->id
< web
->id
)
787 ra_debug_msg (DUMP_IGRAPH_M
, " %d", cl
->t
->id
);
789 ra_debug_msg (DUMP_IGRAPH_M
, "\n");
792 ra_debug_msg (DUMP_IGRAPH_M
, "e\n");
795 /* This runs after colorization and changing the insn stream.
796 It temporarily replaces all pseudo registers with their colors,
797 and emits information, if the resulting insns are strictly valid. */
800 dump_constraints (void)
804 if (!dump_file
|| (debug_new_regalloc
& DUMP_CONSTRAINTS
) == 0)
806 for (i
= FIRST_PSEUDO_REGISTER
; i
< ra_max_regno
; i
++)
807 if (regno_reg_rtx
[i
] && REG_P (regno_reg_rtx
[i
]))
808 REGNO (regno_reg_rtx
[i
])
809 = ra_reg_renumber
[i
] >= 0 ? ra_reg_renumber
[i
] : i
;
810 for (insn
= get_insns (); insn
; insn
= NEXT_INSN (insn
))
814 int uid
= INSN_UID (insn
);
816 /* Don't simply force rerecognition, as combine might left us
817 with some unrecognizable ones, which later leads to aborts
818 in regclass, if we now destroy the remembered INSN_CODE(). */
819 /*INSN_CODE (insn) = -1;*/
820 code
= recog_memoized (insn
);
823 ra_debug_msg (DUMP_CONSTRAINTS
,
824 "%d: asm insn or not recognizable.\n", uid
);
827 ra_debug_msg (DUMP_CONSTRAINTS
,
828 "%d: code %d {%s}, %d operands, constraints: ",
829 uid
, code
, insn_data
[code
].name
, recog_data
.n_operands
);
831 /*preprocess_constraints ();*/
832 for (o
= 0; o
< recog_data
.n_operands
; o
++)
834 ra_debug_msg (DUMP_CONSTRAINTS
,
835 "%d:%s ", o
, recog_data
.constraints
[o
]);
837 if (constrain_operands (1))
838 ra_debug_msg (DUMP_CONSTRAINTS
, "matches strictly alternative %d",
841 ra_debug_msg (DUMP_CONSTRAINTS
, "doesn't match strictly");
842 ra_debug_msg (DUMP_CONSTRAINTS
, "\n");
844 for (i
= FIRST_PSEUDO_REGISTER
; i
< ra_max_regno
; i
++)
845 if (regno_reg_rtx
[i
] && REG_P (regno_reg_rtx
[i
]))
846 REGNO (regno_reg_rtx
[i
]) = i
;
849 /* This counts and emits the cumulated cost of all spilled webs,
850 preceded by a custom message MSG, with debug level LEVEL. */
853 dump_graph_cost (unsigned int level
, const char *msg
)
856 unsigned HOST_WIDE_INT cost
;
857 if (!dump_file
|| (debug_new_regalloc
& level
) == 0)
861 for (i
= 0; i
< num_webs
; i
++)
863 struct web
*web
= id2web
[i
];
864 if (alias (web
)->type
== SPILLED
)
865 cost
+= web
->orig_spill_cost
;
867 ra_debug_msg (level
, " spill cost of graph (%s) = "
868 HOST_WIDE_INT_PRINT_UNSIGNED
"\n",
869 msg
? msg
: "", cost
);
872 /* Dump the color assignment per web, the coalesced and spilled webs. */
875 dump_ra (struct df
*df ATTRIBUTE_UNUSED
)
879 if (!dump_file
|| (debug_new_regalloc
& DUMP_RESULTS
) == 0)
882 ra_debug_msg (DUMP_RESULTS
, "\nColored:\n");
883 for (d
= WEBS(COLORED
); d
; d
= d
->next
)
886 ra_debug_msg (DUMP_RESULTS
, " %4d : color %d\n", web
->id
, web
->color
);
888 ra_debug_msg (DUMP_RESULTS
, "\nCoalesced:\n");
889 for (d
= WEBS(COALESCED
); d
; d
= d
->next
)
892 ra_debug_msg (DUMP_RESULTS
, " %4d : to web %d, color %d\n", web
->id
,
893 alias (web
)->id
, web
->color
);
895 ra_debug_msg (DUMP_RESULTS
, "\nSpilled:\n");
896 for (d
= WEBS(SPILLED
); d
; d
= d
->next
)
899 ra_debug_msg (DUMP_RESULTS
, " %4d\n", web
->id
);
901 ra_debug_msg (DUMP_RESULTS
, "\n");
902 dump_cost (DUMP_RESULTS
);
905 /* Calculate and dump the cumulated costs of certain types of insns
906 (loads, stores and copies). */
909 dump_static_insn_cost (FILE *file
, const char *message
, const char *prefix
)
913 unsigned HOST_WIDE_INT cost
;
917 struct cost load
, store
, regcopy
, selfcopy
, overall
;
918 memset (&load
, 0, sizeof(load
));
919 memset (&store
, 0, sizeof(store
));
920 memset (®copy
, 0, sizeof(regcopy
));
921 memset (&selfcopy
, 0, sizeof(selfcopy
));
922 memset (&overall
, 0, sizeof(overall
));
929 unsigned HOST_WIDE_INT block_cost
= bb
->frequency
;
931 for (insn
= BB_HEAD (bb
); insn
; insn
= NEXT_INSN (insn
))
933 /* Yes, yes. We don't calculate the costs precisely.
934 Only for "simple enough" insns. Those containing single
936 if (INSN_P (insn
) && ((set
= single_set (insn
)) != NULL
))
938 rtx src
= SET_SRC (set
);
939 rtx dest
= SET_DEST (set
);
940 struct cost
*pcost
= NULL
;
941 overall
.cost
+= block_cost
;
943 if (rtx_equal_p (src
, dest
))
945 else if (GET_CODE (src
) == GET_CODE (dest
)
947 || (GET_CODE (src
) == SUBREG
948 && REG_P (SUBREG_REG (src
))
949 && REG_P (SUBREG_REG (dest
)))))
950 /* XXX is dest guaranteed to be a subreg? */
954 if (GET_CODE (src
) == SUBREG
)
955 src
= SUBREG_REG (src
);
956 if (GET_CODE (dest
) == SUBREG
)
957 dest
= SUBREG_REG (dest
);
958 if (MEM_P (src
) && !MEM_P (dest
)
959 && memref_is_stack_slot (src
))
961 else if (!MEM_P (src
) && MEM_P (dest
)
962 && memref_is_stack_slot (dest
))
967 pcost
->cost
+= block_cost
;
971 if (insn
== BB_END (bb
))
978 fprintf (file
, "static insn cost %s\n", message
? message
: "");
979 fprintf (file
, " %soverall:\tnum=%6d\tcost=% 8" HOST_WIDE_INT_PRINT
"d\n",
980 prefix
, overall
.count
, overall
.cost
);
981 fprintf (file
, " %sloads:\tnum=%6d\tcost=% 8" HOST_WIDE_INT_PRINT
"d\n",
982 prefix
, load
.count
, load
.cost
);
983 fprintf (file
, " %sstores:\tnum=%6d\tcost=% 8" HOST_WIDE_INT_PRINT
"d\n",
984 prefix
, store
.count
, store
.cost
);
985 fprintf (file
, " %sregcopy:\tnum=%6d\tcost=% 8" HOST_WIDE_INT_PRINT
"d\n",
986 prefix
, regcopy
.count
, regcopy
.cost
);
987 fprintf (file
, " %sselfcpy:\tnum=%6d\tcost=% 8" HOST_WIDE_INT_PRINT
"d\n",
988 prefix
, selfcopy
.count
, selfcopy
.cost
);
991 /* Returns nonzero, if WEB1 and WEB2 have some possible
992 hardregs in common. */
995 web_conflicts_p (struct web
*web1
, struct web
*web2
)
997 if (web1
->type
== PRECOLORED
&& web2
->type
== PRECOLORED
)
1000 if (web1
->type
== PRECOLORED
)
1001 return TEST_HARD_REG_BIT (web2
->usable_regs
, web1
->regno
);
1003 if (web2
->type
== PRECOLORED
)
1004 return TEST_HARD_REG_BIT (web1
->usable_regs
, web2
->regno
);
1006 return hard_regs_intersect_p (&web1
->usable_regs
, &web2
->usable_regs
);
1009 /* Dump all uids of insns in which WEB is mentioned. */
1012 dump_web_insns (struct web
*web
)
1016 ra_debug_msg (DUMP_EVER
, "Web: %i(%i)+%i class: %s freedom: %i degree %i\n",
1017 web
->id
, web
->regno
, web
->add_hardregs
,
1018 reg_class_names
[web
->regclass
],
1019 web
->num_freedom
, web
->num_conflicts
);
1020 ra_debug_msg (DUMP_EVER
, " def insns:");
1022 for (i
= 0; i
< web
->num_defs
; ++i
)
1024 ra_debug_msg (DUMP_EVER
, " %d ", INSN_UID (web
->defs
[i
]->insn
));
1027 ra_debug_msg (DUMP_EVER
, "\n use insns:");
1028 for (i
= 0; i
< web
->num_uses
; ++i
)
1030 ra_debug_msg (DUMP_EVER
, " %d ", INSN_UID (web
->uses
[i
]->insn
));
1032 ra_debug_msg (DUMP_EVER
, "\n");
1035 /* Dump conflicts for web WEB. */
1038 dump_web_conflicts (struct web
*web
)
1043 ra_debug_msg (DUMP_EVER
, "Web: %i(%i)+%i class: %s freedom: %i degree %i\n",
1044 web
->id
, web
->regno
, web
->add_hardregs
,
1045 reg_class_names
[web
->regclass
],
1046 web
->num_freedom
, web
->num_conflicts
);
1048 for (def2
= 0; def2
< num_webs
; def2
++)
1049 if (TEST_BIT (igraph
, igraph_index (web
->id
, def2
)) && web
->id
!= def2
)
1052 ra_debug_msg (DUMP_EVER
, "\n ");
1055 ra_debug_msg (DUMP_EVER
, " %d(%d)", def2
, id2web
[def2
]->regno
);
1056 if (id2web
[def2
]->add_hardregs
)
1057 ra_debug_msg (DUMP_EVER
, "+%d", id2web
[def2
]->add_hardregs
);
1059 if (web_conflicts_p (web
, id2web
[def2
]))
1060 ra_debug_msg (DUMP_EVER
, "/x");
1062 if (id2web
[def2
]->type
== SELECT
)
1063 ra_debug_msg (DUMP_EVER
, "/s");
1065 if (id2web
[def2
]->type
== COALESCED
)
1066 ra_debug_msg (DUMP_EVER
,"/c/%d", alias (id2web
[def2
])->id
);
1068 ra_debug_msg (DUMP_EVER
, "\n");
1070 struct conflict_link
*wl
;
1072 ra_debug_msg (DUMP_EVER
, "By conflicts: ");
1073 for (wl
= web
->conflict_list
; wl
; wl
= wl
->next
)
1075 struct web
* w
= wl
->t
;
1077 ra_debug_msg (DUMP_EVER
, "\n ");
1079 ra_debug_msg (DUMP_EVER
, "%d(%d)%s ", w
->id
, w
->regno
,
1080 web_conflicts_p (web
, w
) ? "+" : "");
1082 ra_debug_msg (DUMP_EVER
, "\n");
1086 /* Output HARD_REG_SET to stderr. */
1089 debug_hard_reg_set (HARD_REG_SET set
)
1092 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; ++i
)
1094 if (TEST_HARD_REG_BIT (set
, i
))
1096 fprintf (stderr
, "%s ", reg_names
[i
]);
1099 fprintf (stderr
, "\n");
1103 vim:cinoptions={.5s,g0,p5,t0,(0,^-0.5s,n-0.5s:tw=78:cindent:sw=4: