1 /* Graph coloring register allocator
2 Copyright (C) 2001, 2002, 2004, 2005 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"
36 /* This file contains various dumping and debug functions for
37 the graph coloring register allocator. */
39 static void ra_print_rtx_1op (FILE *, rtx
);
40 static void ra_print_rtx_2op (FILE *, rtx
);
41 static void ra_print_rtx_3op (FILE *, rtx
);
42 static void ra_print_rtx_object (FILE *, rtx
);
44 /* Print a message to the dump file, if debug_new_regalloc and LEVEL
45 have any bits in common. */
48 ra_debug_msg (unsigned int level
, const char *format
, ...)
52 va_start (ap
, format
);
53 if ((debug_new_regalloc
& level
) != 0 && dump_file
!= NULL
)
54 vfprintf (dump_file
, format
, ap
);
59 /* The following ra_print_xxx() functions print RTL expressions
60 in concise infix form. If the mode can be seen from context it's
61 left out. Most operators are represented by their graphical
62 characters, e.g. LE as "<=". Unknown constructs are currently
63 printed with print_inline_rtx(), which disrupts the nice layout.
64 Currently only the inline asm things are written this way. */
66 /* Print rtx X, which is a one operand rtx (op:mode (Y)), as
70 ra_print_rtx_1op (FILE *file
, rtx x
)
72 enum rtx_code code
= GET_CODE (x
);
73 rtx op0
= XEXP (x
, 0);
78 fputs ((code
== NEG
) ? "-(" : "~(", file
);
79 ra_print_rtx (file
, op0
, 0);
84 ra_print_rtx (file
, op0
, 0);
88 fprintf (file
, "%s", GET_RTX_NAME (code
));
89 if (GET_MODE (x
) != VOIDmode
)
90 fprintf (file
, ":%s(", GET_MODE_NAME (GET_MODE (x
)));
93 ra_print_rtx (file
, op0
, 0);
99 /* Print rtx X, which is a two operand rtx (op:mode (Y) (Z))
100 as "(Y op Z)", if the operand is know, or as "op(Y, Z)", if not,
104 ra_print_rtx_2op (FILE *file
, rtx x
)
107 const char *opname
= "shitop";
108 enum rtx_code code
= GET_CODE (x
);
109 rtx op0
= XEXP (x
, 0);
110 rtx op1
= XEXP (x
, 1);
114 case COMPARE
: opname
= "?"; break;
115 case MINUS
: opname
= "-"; break;
116 case DIV
: opname
= "/"; break;
117 case UDIV
: opname
= "u/"; break;
118 case MOD
: opname
= "%"; break;
119 case UMOD
: opname
= "u%"; break;
120 case ASHIFT
: opname
= "<<"; break;
121 case ASHIFTRT
: opname
= "a>>"; break;
122 case LSHIFTRT
: opname
= "l>>"; break;
124 case PLUS
: opname
= "+"; break;
125 case MULT
: opname
= "*"; break;
126 case AND
: opname
= "&"; break;
127 case IOR
: opname
= "|"; break;
128 case XOR
: opname
= "^"; break;
130 case NE
: opname
= "!="; break;
131 case EQ
: opname
= "=="; break;
132 case LTGT
: opname
= "<>"; break;
134 case GE
: opname
= "s>="; break;
135 case GT
: opname
= "s>"; break;
136 case LE
: opname
= "s<="; break;
137 case LT
: opname
= "s<"; break;
138 case GEU
: opname
= "u>="; break;
139 case GTU
: opname
= "u>"; break;
140 case LEU
: opname
= "u<="; break;
141 case LTU
: opname
= "u<"; break;
144 opname
= GET_RTX_NAME (code
);
150 ra_print_rtx (file
, op0
, 0);
151 fprintf (file
, " %s ", opname
);
152 ra_print_rtx (file
, op1
, 0);
157 fprintf (file
, "%s(", opname
);
158 ra_print_rtx (file
, op0
, 0);
160 ra_print_rtx (file
, op1
, 0);
165 /* Print rtx X, which a three operand rtx to FILE.
166 I.e. X is either an IF_THEN_ELSE, or a bitmap operation. */
169 ra_print_rtx_3op (FILE *file
, rtx x
)
171 enum rtx_code code
= GET_CODE (x
);
172 rtx op0
= XEXP (x
, 0);
173 rtx op1
= XEXP (x
, 1);
174 rtx op2
= XEXP (x
, 2);
175 if (code
== IF_THEN_ELSE
)
177 ra_print_rtx (file
, op0
, 0);
179 ra_print_rtx (file
, op1
, 0);
181 ra_print_rtx (file
, op2
, 0);
185 /* Bitmap-operation */
186 fprintf (file
, "%s:%s(", GET_RTX_NAME (code
),
187 GET_MODE_NAME (GET_MODE (x
)));
188 ra_print_rtx (file
, op0
, 0);
190 ra_print_rtx (file
, op1
, 0);
192 ra_print_rtx (file
, op2
, 0);
197 /* Print rtx X, which represents an object (class 'o', 'C', or some constructs
198 of class 'x' (e.g. subreg)), to FILE.
199 (reg XX) rtl is represented as "pXX", of XX was a pseudo,
200 as "name" it name is the nonnull hardreg name, or as "hXX", if XX
201 is a hardreg, whose name is NULL, or empty. */
204 ra_print_rtx_object (FILE *file
, rtx x
)
206 enum rtx_code code
= GET_CODE (x
);
207 enum machine_mode mode
= GET_MODE (x
);
211 fprintf (file
, HOST_WIDE_INT_PRINT_DEC
, XWINT (x
, 0));
216 const char *fmt
= GET_RTX_FORMAT (code
);
217 fputs ("dbl(", file
);
218 for (i
= 0; i
< GET_RTX_LENGTH (code
); i
++)
222 if (fmt
[i
] == 'e' && XEXP (x
, i
))
223 /* The MEM or other stuff */
225 ra_print_rtx (file
, XEXP (x
, i
), 0);
228 else if (fmt
[i
] == 'w')
230 fprintf (file
, HOST_WIDE_INT_PRINT_HEX
, XWINT (x
, i
));
236 case CONST_STRING
: fprintf (file
, "\"%s\"", XSTR (x
, 0)); break;
237 case CONST
: fputs ("const(", file
);
238 ra_print_rtx (file
, XEXP (x
, 0), 0);
241 case PC
: fputs ("pc", file
); break;
244 int regno
= REGNO (x
);
245 if (regno
< FIRST_PSEUDO_REGISTER
)
247 int i
, nregs
= hard_regno_nregs
[regno
][mode
];
250 for (i
= 0; i
< nregs
; i
++)
254 if (reg_names
[regno
+i
] && *reg_names
[regno
+ i
])
255 fprintf (file
, "%s", reg_names
[regno
+ i
]);
257 fprintf (file
, "h%d", regno
+ i
);
263 fprintf (file
, "p%d", regno
);
268 rtx sub
= SUBREG_REG (x
);
269 int ofs
= SUBREG_BYTE (x
);
271 && REGNO (sub
) < FIRST_PSEUDO_REGISTER
)
273 int regno
= REGNO (sub
);
274 int i
, nregs
= hard_regno_nregs
[regno
][mode
];
275 regno
+= subreg_regno_offset (regno
, GET_MODE (sub
),
279 for (i
= 0; i
< nregs
; i
++)
283 if (reg_names
[regno
+i
])
284 fprintf (file
, "%s", reg_names
[regno
+ i
]);
286 fprintf (file
, "h%d", regno
+ i
);
293 ra_print_rtx (file
, sub
, 0);
294 fprintf (file
, ":[%s+%d]", GET_MODE_NAME (mode
), ofs
);
298 case SCRATCH
: fputs ("scratch", file
); break;
299 case CONCAT
: ra_print_rtx_2op (file
, x
); break;
300 case HIGH
: ra_print_rtx_1op (file
, x
); break;
303 ra_print_rtx (file
, XEXP (x
, 0), 0);
304 fputs (" + lo(", file
);
305 ra_print_rtx (file
, XEXP (x
, 1), 0);
308 case MEM
: fputs ("[", file
);
309 ra_print_rtx (file
, XEXP (x
, 0), 0);
310 fprintf (file
, "]:%s", GET_MODE_NAME (GET_MODE (x
)));
311 /* XXX print alias set too ?? */
315 rtx sub
= XEXP (x
, 0);
317 && NOTE_LINE_NUMBER (sub
) == NOTE_INSN_DELETED_LABEL
)
318 fprintf (file
, "(deleted uid=%d)", INSN_UID (sub
));
319 else if (LABEL_P (sub
))
320 fprintf (file
, "L%d", CODE_LABEL_NUMBER (sub
));
322 fprintf (file
, "(nonlabel uid=%d)", INSN_UID (sub
));
326 fprintf (file
, "sym(\"%s\")", XSTR (x
, 0)); break;
327 case CC0
: fputs ("cc0", file
); break;
328 default: print_inline_rtx (file
, x
, 0); break;
332 /* Print a general rtx X to FILE in nice infix form.
333 If WITH_PN is set, and X is one of the toplevel constructs
334 (insns, notes, labels or barriers), then print also the UIDs of
335 the preceding and following insn. */
338 ra_print_rtx (FILE *file
, rtx x
, int with_pn
)
346 /* First handle the insn like constructs. */
347 if (INSN_P (x
) || code
== NOTE
|| code
== CODE_LABEL
|| code
== BARRIER
)
351 /* Non-insns are prefixed by a ';'. */
354 else if (code
== NOTE
)
355 /* But notes are indented very far right. */
356 fprintf (file
, "\t\t\t\t\t; ");
357 else if (code
== CODE_LABEL
)
358 /* And labels have their Lxx name first, before the actual UID. */
360 fprintf (file
, "L%d:\t; ", CODE_LABEL_NUMBER (x
));
362 fprintf (file
, "(%s) ", LABEL_NAME (x
));
363 switch (LABEL_KIND (x
))
365 case LABEL_NORMAL
: break;
366 case LABEL_STATIC_ENTRY
: fputs (" (entry)", file
); break;
367 case LABEL_GLOBAL_ENTRY
: fputs (" (global entry)", file
); break;
368 case LABEL_WEAK_ENTRY
: fputs (" (weak entry)", file
); break;
371 fprintf (file
, " [%d uses] uid=(", LABEL_NUSES (x
));
373 fprintf (file
, "%d", INSN_UID (x
));
375 fprintf (file
, " %d %d", PREV_INSN (x
) ? INSN_UID (PREV_INSN (x
)) : 0,
376 NEXT_INSN (x
) ? INSN_UID (NEXT_INSN (x
)) : 0);
378 fputs (" -------- barrier ---------", file
);
379 else if (code
== CODE_LABEL
)
381 else if (code
== NOTE
)
383 int ln
= NOTE_LINE_NUMBER (x
);
384 if (ln
>= (int) NOTE_INSN_BIAS
&& ln
< (int) NOTE_INSN_MAX
)
385 fprintf (file
, " %s", GET_NOTE_INSN_NAME (ln
));
389 NOTE_EXPANDED_LOCATION (s
, x
);
390 fprintf (file
, " line %d", s
.line
);
392 fprintf (file
, ":%s", s
.file
);
397 fprintf (file
, "\t");
398 ra_print_rtx (file
, PATTERN (x
), 0);
404 /* Top-level stuff. */
408 for (j
= 0; j
< XVECLEN (x
, 0); j
++)
411 fputs ("\t;; ", file
);
412 ra_print_rtx (file
, XVECEXP (x
, 0, j
), 0);
416 case UNSPEC
: case UNSPEC_VOLATILE
:
419 fprintf (file
, "unspec%s(%d",
420 (code
== UNSPEC
) ? "" : "_vol", XINT (x
, 1));
421 for (j
= 0; j
< XVECLEN (x
, 0); j
++)
424 ra_print_rtx (file
, XVECEXP (x
, 0, j
), 0);
430 if (GET_CODE (SET_DEST (x
)) == PC
)
432 if (GET_CODE (SET_SRC (x
)) == IF_THEN_ELSE
433 && GET_CODE (XEXP (SET_SRC(x
), 2)) == PC
)
436 ra_print_rtx (file
, XEXP (SET_SRC (x
), 0), 0);
437 fputs (" jump ", file
);
438 ra_print_rtx (file
, XEXP (SET_SRC (x
), 1), 0);
442 fputs ("jump ", file
);
443 ra_print_rtx (file
, SET_SRC (x
), 0);
448 ra_print_rtx (file
, SET_DEST (x
), 0);
449 fputs (" <= ", file
);
450 ra_print_rtx (file
, SET_SRC (x
), 0);
454 fputs ("use <= ", file
);
455 ra_print_rtx (file
, XEXP (x
, 0), 0);
458 ra_print_rtx (file
, XEXP (x
, 0), 0);
459 fputs (" <= clobber", file
);
462 fputs ("call ", file
);
463 ra_print_rtx (file
, XEXP (x
, 0), 0); /* Address */
464 fputs (" numargs=", file
);
465 ra_print_rtx (file
, XEXP (x
, 1), 0); /* Num arguments */
468 fputs ("return", file
);
471 fputs ("if (", file
);
472 ra_print_rtx (file
, XEXP (x
, 0), 0);
473 fputs (") trap ", file
);
474 ra_print_rtx (file
, XEXP (x
, 1), 0);
477 fprintf (file
, "resx from region %d", XINT (x
, 0));
480 /* Different things of class 'x' */
481 case SUBREG
: ra_print_rtx_object (file
, x
); break;
482 case STRICT_LOW_PART
:
483 fputs ("low(", file
);
484 ra_print_rtx (file
, XEXP (x
, 0), 0);
493 switch (GET_RTX_CLASS (code
))
496 ra_print_rtx_1op (file
, x
);
501 case RTX_COMM_COMPARE
:
502 ra_print_rtx_2op (file
, x
);
505 case RTX_BITFIELD_OPS
:
506 ra_print_rtx_3op (file
, x
);
510 ra_print_rtx_object (file
, x
);
513 print_inline_rtx (file
, x
, 0);
518 /* This only calls ra_print_rtx(), but emits a final newline. */
521 ra_print_rtx_top (FILE *file
, rtx x
, int with_pn
)
523 ra_print_rtx (file
, x
, with_pn
);
524 fprintf (file
, "\n");
527 /* Callable from gdb. This prints rtx X onto stderr. */
532 ra_print_rtx_top (stderr
, x
, 1);
535 /* This prints the content of basic block with index BBI.
536 The first and last insn are emitted with UIDs of prev and next insns. */
539 ra_debug_bbi (int bbi
)
541 basic_block bb
= BASIC_BLOCK (bbi
);
543 for (insn
= BB_HEAD (bb
); insn
; insn
= NEXT_INSN (insn
))
545 ra_print_rtx_top (stderr
, insn
,
546 (insn
== BB_HEAD (bb
) || insn
== BB_END (bb
)));
547 fprintf (stderr
, "\n");
548 if (insn
== BB_END (bb
))
553 /* Beginning from INSN, emit NUM insns (if NUM is non-negative)
554 or emit a window of NUM insns around INSN, to stderr. */
557 ra_debug_insns (rtx insn
, int num
)
559 int i
, count
= (num
== 0 ? 1 : num
< 0 ? -num
: num
);
561 for (i
= count
/ 2; i
> 0 && PREV_INSN (insn
); i
--)
562 insn
= PREV_INSN (insn
);
563 for (i
= count
; i
> 0 && insn
; insn
= NEXT_INSN (insn
), i
--)
566 fprintf (stderr
, "\n");
567 ra_print_rtx_top (stderr
, insn
, (i
== count
|| i
== 1));
571 /* Beginning with INSN, emit the whole insn chain into FILE.
572 This also outputs comments when basic blocks start or end and omits
573 some notes, if flag_ra_dump_notes is zero. */
576 ra_print_rtl_with_bb (FILE *file
, rtx insn
)
578 basic_block last_bb
, bb
;
579 unsigned int num
= 0;
583 for (; insn
; insn
= NEXT_INSN (insn
))
585 if (BARRIER_P (insn
))
588 bb
= BLOCK_FOR_INSN (insn
);
592 fprintf (file
, ";; End of basic block %d\n", last_bb
->index
);
594 fprintf (file
, ";; Begin of basic block %d\n", bb
->index
);
601 /* Ignore basic block and maybe other notes not referencing
603 if (NOTE_LINE_NUMBER (insn
) != NOTE_INSN_BASIC_BLOCK
604 && (flag_ra_dump_notes
605 || NOTE_LINE_NUMBER (insn
) == NOTE_INSN_DELETED
606 || NOTE_LINE_NUMBER (insn
) == NOTE_INSN_DELETED_LABEL
))
608 ra_print_rtx_top (file
, insn
, (num
== 0 || !NEXT_INSN (insn
)));
614 ra_print_rtx_top (file
, insn
, (num
== 0 || !NEXT_INSN (insn
)));
620 /* Count how many insns were seen how often, while building the interference
621 graph, and prints the findings. */
624 dump_number_seen (void)
630 for (i
= 0; i
< N
; i
++)
632 for (i
= 0; i
< get_max_uid (); i
++)
633 if (number_seen
[i
] < N
- 1)
634 num
[number_seen
[i
]]++;
637 for (i
= 0; i
< N
- 1; i
++)
639 ra_debug_msg (DUMP_PROCESS
, "%d insns seen %d times\n", num
[i
], i
);
641 ra_debug_msg (DUMP_PROCESS
, "%d insns seen %d and more times\n", num
[i
],
643 ra_debug_msg (DUMP_PROCESS
, "from overall %d insns\n", get_max_uid ());
647 /* Dump the interference graph, the move list and the webs. */
650 dump_igraph (struct df
*df ATTRIBUTE_UNUSED
)
652 struct move_list
*ml
;
653 unsigned int def1
, def2
;
657 if (!dump_file
|| (debug_new_regalloc
& (DUMP_IGRAPH
| DUMP_WEBS
)) == 0)
659 ra_debug_msg (DUMP_IGRAPH
, "conflicts:\n ");
660 for (def1
= 0; def1
< num_webs
; def1
++)
664 for (def2
= 0; def2
< num_webs
; def2
++)
665 if (def1
!= def2
&& TEST_BIT (igraph
, igraph_index (def1
, def2
)))
669 if (SUBWEB_P (ID2WEB (def1
)))
670 ra_debug_msg (DUMP_IGRAPH
, "%d (SUBREG %d, %d) with ", def1
,
671 ID2WEB (def1
)->regno
,
672 SUBREG_BYTE (ID2WEB (def1
)->orig_x
));
674 ra_debug_msg (DUMP_IGRAPH
, "%d (REG %d) with ", def1
,
675 ID2WEB (def1
)->regno
);
678 ra_debug_msg (DUMP_IGRAPH
, "\n ");
681 if (SUBWEB_P (ID2WEB (def2
)))
682 ra_debug_msg (DUMP_IGRAPH
, "%d(%d,%d) ", def2
, ID2WEB (def2
)->regno
,
683 SUBREG_BYTE (ID2WEB (def2
)->orig_x
));
685 ra_debug_msg (DUMP_IGRAPH
, "%d(%d) ", def2
, ID2WEB (def2
)->regno
);
688 ra_debug_msg (DUMP_IGRAPH
, "\n ");
690 ra_debug_msg (DUMP_IGRAPH
, "\n");
691 for (ml
= wl_moves
; ml
; ml
= ml
->next
)
694 ra_debug_msg (DUMP_IGRAPH
, "move: insn %d: Web %d <-- Web %d\n",
695 INSN_UID (ml
->move
->insn
), ml
->move
->target_web
->id
,
696 ml
->move
->source_web
->id
);
698 ra_debug_msg (DUMP_WEBS
, "\nWebs:\n");
699 for (i
= 0; i
< num_webs
; i
++)
701 struct web
*web
= ID2WEB (i
);
703 ra_debug_msg (DUMP_WEBS
, " %4d : regno %3d", i
, web
->regno
);
706 ra_debug_msg (DUMP_WEBS
, " sub %d", SUBREG_BYTE (web
->orig_x
));
707 ra_debug_msg (DUMP_WEBS
, " par %d", find_web_for_subweb (web
)->id
);
709 ra_debug_msg (DUMP_WEBS
, " +%d (span %d, cost "
710 HOST_WIDE_INT_PRINT_DEC
") (%s)",
711 web
->add_hardregs
, web
->span_deaths
, web
->spill_cost
,
712 reg_class_names
[web
->regclass
]);
713 if (web
->spill_temp
== 1)
714 ra_debug_msg (DUMP_WEBS
, " (spilltemp)");
715 else if (web
->spill_temp
== 2)
716 ra_debug_msg (DUMP_WEBS
, " (spilltem2)");
717 else if (web
->spill_temp
== 3)
718 ra_debug_msg (DUMP_WEBS
, " (short)");
719 if (web
->type
== PRECOLORED
)
720 ra_debug_msg (DUMP_WEBS
, " (precolored, color=%d)", web
->color
);
721 else if (find_web_for_subweb (web
)->num_uses
== 0)
722 ra_debug_msg (DUMP_WEBS
, " dead");
723 if (web
->crosses_call
)
724 ra_debug_msg (DUMP_WEBS
, " xcall");
725 if (web
->regno
>= max_normal_pseudo
)
726 ra_debug_msg (DUMP_WEBS
, " stack");
727 ra_debug_msg (DUMP_WEBS
, "\n");
731 /* Dump the interference graph and webs in a format easily
732 parsable by programs. Used to emit real world interference graph
733 to my custom graph colorizer. */
736 dump_igraph_machine (void)
740 if (!dump_file
|| (debug_new_regalloc
& DUMP_IGRAPH_M
) == 0)
742 ra_debug_msg (DUMP_IGRAPH_M
, "g %d %d\n", num_webs
- num_subwebs
,
743 FIRST_PSEUDO_REGISTER
);
744 for (i
= 0; i
< num_webs
- num_subwebs
; i
++)
746 struct web
*web
= ID2WEB (i
);
747 struct conflict_link
*cl
;
751 flags
= web
->spill_temp
& 0xF;
752 flags
|= ((web
->type
== PRECOLORED
) ? 1 : 0) << 4;
753 flags
|= (web
->add_hardregs
& 0xF) << 5;
754 for (cl
= web
->conflict_list
; cl
; cl
= cl
->next
)
755 if (cl
->t
->id
< web
->id
)
757 ra_debug_msg (DUMP_IGRAPH_M
, "n %d %d %d %d %d %d %d\n",
758 web
->id
, web
->color
, flags
,
759 (unsigned int)web
->spill_cost
, web
->num_defs
, web
->num_uses
,
761 if (web
->type
!= PRECOLORED
)
763 ra_debug_msg (DUMP_IGRAPH_M
, "s %d", web
->id
);
768 for (n
= 0; n
< 32 && col
< FIRST_PSEUDO_REGISTER
; n
++, col
++)
769 if (TEST_HARD_REG_BIT (web
->usable_regs
, col
))
771 ra_debug_msg (DUMP_IGRAPH_M
, " %u", u
);
772 if (col
>= FIRST_PSEUDO_REGISTER
)
775 ra_debug_msg (DUMP_IGRAPH_M
, "\n");
779 ra_debug_msg (DUMP_IGRAPH_M
, "c %d", web
->id
);
780 for (cl
= web
->conflict_list
; cl
; cl
= cl
->next
)
782 if (cl
->t
->id
< web
->id
)
783 ra_debug_msg (DUMP_IGRAPH_M
, " %d", cl
->t
->id
);
785 ra_debug_msg (DUMP_IGRAPH_M
, "\n");
788 ra_debug_msg (DUMP_IGRAPH_M
, "e\n");
791 /* This runs after colorization and changing the insn stream.
792 It temporarily replaces all pseudo registers with their colors,
793 and emits information, if the resulting insns are strictly valid. */
796 dump_constraints (void)
800 if (!dump_file
|| (debug_new_regalloc
& DUMP_CONSTRAINTS
) == 0)
802 for (i
= FIRST_PSEUDO_REGISTER
; i
< ra_max_regno
; i
++)
803 if (regno_reg_rtx
[i
] && REG_P (regno_reg_rtx
[i
]))
804 REGNO (regno_reg_rtx
[i
])
805 = ra_reg_renumber
[i
] >= 0 ? ra_reg_renumber
[i
] : i
;
806 for (insn
= get_insns (); insn
; insn
= NEXT_INSN (insn
))
810 int uid
= INSN_UID (insn
);
812 /* Don't simply force rerecognition, as combine might left us
813 with some unrecognizable ones, which later leads to aborts
814 in regclass, if we now destroy the remembered INSN_CODE(). */
815 /*INSN_CODE (insn) = -1;*/
816 code
= recog_memoized (insn
);
819 ra_debug_msg (DUMP_CONSTRAINTS
,
820 "%d: asm insn or not recognizable.\n", uid
);
823 ra_debug_msg (DUMP_CONSTRAINTS
,
824 "%d: code %d {%s}, %d operands, constraints: ",
825 uid
, code
, insn_data
[code
].name
, recog_data
.n_operands
);
827 /*preprocess_constraints ();*/
828 for (o
= 0; o
< recog_data
.n_operands
; o
++)
830 ra_debug_msg (DUMP_CONSTRAINTS
,
831 "%d:%s ", o
, recog_data
.constraints
[o
]);
833 if (constrain_operands (1))
834 ra_debug_msg (DUMP_CONSTRAINTS
, "matches strictly alternative %d",
837 ra_debug_msg (DUMP_CONSTRAINTS
, "doesn't match strictly");
838 ra_debug_msg (DUMP_CONSTRAINTS
, "\n");
840 for (i
= FIRST_PSEUDO_REGISTER
; i
< ra_max_regno
; i
++)
841 if (regno_reg_rtx
[i
] && REG_P (regno_reg_rtx
[i
]))
842 REGNO (regno_reg_rtx
[i
]) = i
;
845 /* This counts and emits the cumulated cost of all spilled webs,
846 preceded by a custom message MSG, with debug level LEVEL. */
849 dump_graph_cost (unsigned int level
, const char *msg
)
852 unsigned HOST_WIDE_INT cost
;
853 if (!dump_file
|| (debug_new_regalloc
& level
) == 0)
857 for (i
= 0; i
< num_webs
; i
++)
859 struct web
*web
= id2web
[i
];
860 if (alias (web
)->type
== SPILLED
)
861 cost
+= web
->orig_spill_cost
;
863 ra_debug_msg (level
, " spill cost of graph (%s) = "
864 HOST_WIDE_INT_PRINT_UNSIGNED
"\n",
865 msg
? msg
: "", cost
);
868 /* Dump the color assignment per web, the coalesced and spilled webs. */
871 dump_ra (struct df
*df ATTRIBUTE_UNUSED
)
875 if (!dump_file
|| (debug_new_regalloc
& DUMP_RESULTS
) == 0)
878 ra_debug_msg (DUMP_RESULTS
, "\nColored:\n");
879 for (d
= WEBS(COLORED
); d
; d
= d
->next
)
882 ra_debug_msg (DUMP_RESULTS
, " %4d : color %d\n", web
->id
, web
->color
);
884 ra_debug_msg (DUMP_RESULTS
, "\nCoalesced:\n");
885 for (d
= WEBS(COALESCED
); d
; d
= d
->next
)
888 ra_debug_msg (DUMP_RESULTS
, " %4d : to web %d, color %d\n", web
->id
,
889 alias (web
)->id
, web
->color
);
891 ra_debug_msg (DUMP_RESULTS
, "\nSpilled:\n");
892 for (d
= WEBS(SPILLED
); d
; d
= d
->next
)
895 ra_debug_msg (DUMP_RESULTS
, " %4d\n", web
->id
);
897 ra_debug_msg (DUMP_RESULTS
, "\n");
898 dump_cost (DUMP_RESULTS
);
901 /* Calculate and dump the cumulated costs of certain types of insns
902 (loads, stores and copies). */
905 dump_static_insn_cost (FILE *file
, const char *message
, const char *prefix
)
909 unsigned HOST_WIDE_INT cost
;
913 struct cost load
, store
, regcopy
, selfcopy
, overall
;
914 memset (&load
, 0, sizeof(load
));
915 memset (&store
, 0, sizeof(store
));
916 memset (®copy
, 0, sizeof(regcopy
));
917 memset (&selfcopy
, 0, sizeof(selfcopy
));
918 memset (&overall
, 0, sizeof(overall
));
925 unsigned HOST_WIDE_INT block_cost
= bb
->frequency
;
927 for (insn
= BB_HEAD (bb
); insn
; insn
= NEXT_INSN (insn
))
929 /* Yes, yes. We don't calculate the costs precisely.
930 Only for "simple enough" insns. Those containing single
932 if (INSN_P (insn
) && ((set
= single_set (insn
)) != NULL
))
934 rtx src
= SET_SRC (set
);
935 rtx dest
= SET_DEST (set
);
936 struct cost
*pcost
= NULL
;
937 overall
.cost
+= block_cost
;
939 if (rtx_equal_p (src
, dest
))
941 else if (GET_CODE (src
) == GET_CODE (dest
)
943 || (GET_CODE (src
) == SUBREG
944 && REG_P (SUBREG_REG (src
))
945 && REG_P (SUBREG_REG (dest
)))))
946 /* XXX is dest guaranteed to be a subreg? */
950 if (GET_CODE (src
) == SUBREG
)
951 src
= SUBREG_REG (src
);
952 if (GET_CODE (dest
) == SUBREG
)
953 dest
= SUBREG_REG (dest
);
954 if (MEM_P (src
) && !MEM_P (dest
)
955 && memref_is_stack_slot (src
))
957 else if (!MEM_P (src
) && MEM_P (dest
)
958 && memref_is_stack_slot (dest
))
963 pcost
->cost
+= block_cost
;
967 if (insn
== BB_END (bb
))
974 fprintf (file
, "static insn cost %s\n", message
? message
: "");
975 fprintf (file
, " %soverall:\tnum=%6d\tcost=% 8" HOST_WIDE_INT_PRINT
"d\n",
976 prefix
, overall
.count
, overall
.cost
);
977 fprintf (file
, " %sloads:\tnum=%6d\tcost=% 8" HOST_WIDE_INT_PRINT
"d\n",
978 prefix
, load
.count
, load
.cost
);
979 fprintf (file
, " %sstores:\tnum=%6d\tcost=% 8" HOST_WIDE_INT_PRINT
"d\n",
980 prefix
, store
.count
, store
.cost
);
981 fprintf (file
, " %sregcopy:\tnum=%6d\tcost=% 8" HOST_WIDE_INT_PRINT
"d\n",
982 prefix
, regcopy
.count
, regcopy
.cost
);
983 fprintf (file
, " %sselfcpy:\tnum=%6d\tcost=% 8" HOST_WIDE_INT_PRINT
"d\n",
984 prefix
, selfcopy
.count
, selfcopy
.cost
);
987 /* Returns nonzero, if WEB1 and WEB2 have some possible
988 hardregs in common. */
991 web_conflicts_p (struct web
*web1
, struct web
*web2
)
993 if (web1
->type
== PRECOLORED
&& web2
->type
== PRECOLORED
)
996 if (web1
->type
== PRECOLORED
)
997 return TEST_HARD_REG_BIT (web2
->usable_regs
, web1
->regno
);
999 if (web2
->type
== PRECOLORED
)
1000 return TEST_HARD_REG_BIT (web1
->usable_regs
, web2
->regno
);
1002 return hard_regs_intersect_p (&web1
->usable_regs
, &web2
->usable_regs
);
1005 /* Dump all uids of insns in which WEB is mentioned. */
1008 dump_web_insns (struct web
*web
)
1012 ra_debug_msg (DUMP_EVER
, "Web: %i(%i)+%i class: %s freedom: %i degree %i\n",
1013 web
->id
, web
->regno
, web
->add_hardregs
,
1014 reg_class_names
[web
->regclass
],
1015 web
->num_freedom
, web
->num_conflicts
);
1016 ra_debug_msg (DUMP_EVER
, " def insns:");
1018 for (i
= 0; i
< web
->num_defs
; ++i
)
1020 ra_debug_msg (DUMP_EVER
, " %d ", INSN_UID (web
->defs
[i
]->insn
));
1023 ra_debug_msg (DUMP_EVER
, "\n use insns:");
1024 for (i
= 0; i
< web
->num_uses
; ++i
)
1026 ra_debug_msg (DUMP_EVER
, " %d ", INSN_UID (web
->uses
[i
]->insn
));
1028 ra_debug_msg (DUMP_EVER
, "\n");
1031 /* Dump conflicts for web WEB. */
1034 dump_web_conflicts (struct web
*web
)
1039 ra_debug_msg (DUMP_EVER
, "Web: %i(%i)+%i class: %s freedom: %i degree %i\n",
1040 web
->id
, web
->regno
, web
->add_hardregs
,
1041 reg_class_names
[web
->regclass
],
1042 web
->num_freedom
, web
->num_conflicts
);
1044 for (def2
= 0; def2
< num_webs
; def2
++)
1045 if (TEST_BIT (igraph
, igraph_index (web
->id
, def2
)) && web
->id
!= def2
)
1048 ra_debug_msg (DUMP_EVER
, "\n ");
1051 ra_debug_msg (DUMP_EVER
, " %d(%d)", def2
, id2web
[def2
]->regno
);
1052 if (id2web
[def2
]->add_hardregs
)
1053 ra_debug_msg (DUMP_EVER
, "+%d", id2web
[def2
]->add_hardregs
);
1055 if (web_conflicts_p (web
, id2web
[def2
]))
1056 ra_debug_msg (DUMP_EVER
, "/x");
1058 if (id2web
[def2
]->type
== SELECT
)
1059 ra_debug_msg (DUMP_EVER
, "/s");
1061 if (id2web
[def2
]->type
== COALESCED
)
1062 ra_debug_msg (DUMP_EVER
,"/c/%d", alias (id2web
[def2
])->id
);
1064 ra_debug_msg (DUMP_EVER
, "\n");
1066 struct conflict_link
*wl
;
1068 ra_debug_msg (DUMP_EVER
, "By conflicts: ");
1069 for (wl
= web
->conflict_list
; wl
; wl
= wl
->next
)
1071 struct web
* w
= wl
->t
;
1073 ra_debug_msg (DUMP_EVER
, "\n ");
1075 ra_debug_msg (DUMP_EVER
, "%d(%d)%s ", w
->id
, w
->regno
,
1076 web_conflicts_p (web
, w
) ? "+" : "");
1078 ra_debug_msg (DUMP_EVER
, "\n");
1082 /* Output HARD_REG_SET to stderr. */
1085 debug_hard_reg_set (HARD_REG_SET set
)
1088 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; ++i
)
1090 if (TEST_HARD_REG_BIT (set
, i
))
1092 fprintf (stderr
, "%s ", reg_names
[i
]);
1095 fprintf (stderr
, "\n");
1099 vim:cinoptions={.5s,g0,p5,t0,(0,^-0.5s,n-0.5s:tw=78:cindent:sw=4: