1 /* Graph coloring register allocator
2 Copyright (C) 2001, 2002 Free Software Foundation, Inc.
3 Contributed by Michael Matz <matz@suse.de>
4 and Daniel Berlin <dan@cgsoftware.com>.
6 This file is part of GCC.
8 GCC is free software; you can redistribute it and/or modify it under the
9 terms of the GNU General Public License as published by the Free Software
10 Foundation; either version 2, or (at your option) any later version.
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
17 You should have received a copy of the GNU General Public License along
18 with GCC; see the file COPYING. If not, write to the Free Software
19 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
23 #include "coretypes.h"
26 #include "insn-config.h"
29 #include "hard-reg-set.h"
30 #include "basic-block.h"
36 /* This file contains various dumping and debug functions for
37 the graph coloring register allocator. */
39 static void ra_print_rtx_1op
PARAMS ((FILE *, rtx
));
40 static void ra_print_rtx_2op
PARAMS ((FILE *, rtx
));
41 static void ra_print_rtx_3op
PARAMS ((FILE *, rtx
));
42 static void ra_print_rtx_object
PARAMS ((FILE *, rtx
));
44 /* The hardregs as names, for debugging. */
45 static const char *const reg_class_names
[] = REG_CLASS_NAMES
;
47 /* Print a message to the dump file, if debug_new_regalloc and LEVEL
48 have any bits in common. */
51 ra_debug_msg (unsigned int level
, const char *format
, ...)
55 va_start (ap
, format
);
56 if ((debug_new_regalloc
& level
) != 0 && rtl_dump_file
!= NULL
)
57 vfprintf (rtl_dump_file
, format
, ap
);
62 /* The following ra_print_xxx() functions print RTL expressions
63 in concise infix form. If the mode can be seen from context it's
64 left out. Most operators are represented by their graphical
65 characters, e.g. LE as "<=". Unknown constructs are currently
66 printed with print_inline_rtx(), which disrupts the nice layout.
67 Currently only the inline asm things are written this way. */
69 /* Print rtx X, which is a one operand rtx (op:mode (Y)), as
73 ra_print_rtx_1op (file
, x
)
77 enum rtx_code code
= GET_CODE (x
);
78 rtx op0
= XEXP (x
, 0);
83 fputs ((code
== NEG
) ? "-(" : "~(", file
);
84 ra_print_rtx (file
, op0
, 0);
89 ra_print_rtx (file
, op0
, 0);
93 fprintf (file
, "%s", GET_RTX_NAME (code
));
94 if (GET_MODE (x
) != VOIDmode
)
95 fprintf (file
, ":%s(", GET_MODE_NAME (GET_MODE (x
)));
98 ra_print_rtx (file
, op0
, 0);
104 /* Print rtx X, which is a two operand rtx (op:mode (Y) (Z))
105 as "(Y op Z)", if the operand is know, or as "op(Y, Z)", if not,
109 ra_print_rtx_2op (file
, x
)
114 const char *opname
= "shitop";
115 enum rtx_code code
= GET_CODE (x
);
116 rtx op0
= XEXP (x
, 0);
117 rtx op1
= XEXP (x
, 1);
121 case COMPARE
: opname
= "?"; break;
122 case MINUS
: opname
= "-"; break;
123 case DIV
: opname
= "/"; break;
124 case UDIV
: opname
= "u/"; break;
125 case MOD
: opname
= "%"; break;
126 case UMOD
: opname
= "u%"; break;
127 case ASHIFT
: opname
= "<<"; break;
128 case ASHIFTRT
: opname
= "a>>"; break;
129 case LSHIFTRT
: opname
= "l>>"; break;
131 case PLUS
: opname
= "+"; break;
132 case MULT
: opname
= "*"; break;
133 case AND
: opname
= "&"; break;
134 case IOR
: opname
= "|"; break;
135 case XOR
: opname
= "^"; break;
137 case NE
: opname
= "!="; break;
138 case EQ
: opname
= "=="; break;
139 case GE
: opname
= "s>="; break;
140 case GT
: opname
= "s>"; break;
141 case LE
: opname
= "s<="; break;
142 case LT
: opname
= "s<"; break;
143 case GEU
: opname
= "u>="; break;
144 case GTU
: opname
= "u>"; break;
145 case LEU
: opname
= "u<="; break;
146 case LTU
: opname
= "u<"; break;
149 opname
= GET_RTX_NAME (code
);
155 ra_print_rtx (file
, op0
, 0);
156 fprintf (file
, " %s ", opname
);
157 ra_print_rtx (file
, op1
, 0);
162 fprintf (file
, "%s(", opname
);
163 ra_print_rtx (file
, op0
, 0);
165 ra_print_rtx (file
, op1
, 0);
170 /* Print rtx X, which a three operand rtx to FILE.
171 I.e. X is either an IF_THEN_ELSE, or a bitmap operation. */
174 ra_print_rtx_3op (file
, x
)
178 enum rtx_code code
= GET_CODE (x
);
179 rtx op0
= XEXP (x
, 0);
180 rtx op1
= XEXP (x
, 1);
181 rtx op2
= XEXP (x
, 2);
182 if (code
== IF_THEN_ELSE
)
184 ra_print_rtx (file
, op0
, 0);
186 ra_print_rtx (file
, op1
, 0);
188 ra_print_rtx (file
, op2
, 0);
192 /* Bitmap-operation */
193 fprintf (file
, "%s:%s(", GET_RTX_NAME (code
),
194 GET_MODE_NAME (GET_MODE (x
)));
195 ra_print_rtx (file
, op0
, 0);
197 ra_print_rtx (file
, op1
, 0);
199 ra_print_rtx (file
, op2
, 0);
204 /* Print rtx X, which represents an object (class 'o' or some constructs
205 of class 'x' (e.g. subreg)), to FILE.
206 (reg XX) rtl is represented as "pXX", of XX was a pseudo,
207 as "name" it name is the nonnull hardreg name, or as "hXX", if XX
208 is a hardreg, whose name is NULL, or empty. */
211 ra_print_rtx_object (file
, x
)
215 enum rtx_code code
= GET_CODE (x
);
216 enum machine_mode mode
= GET_MODE (x
);
220 fprintf (file
, HOST_WIDE_INT_PRINT_DEC
, XWINT (x
, 0));
225 const char *fmt
= GET_RTX_FORMAT (code
);
226 fputs ("dbl(", file
);
227 for (i
= 0; i
< GET_RTX_LENGTH (code
); i
++)
231 if (fmt
[i
] == 'e' && XEXP (x
, i
))
232 /* The MEM or other stuff */
234 ra_print_rtx (file
, XEXP (x
, i
), 0);
237 else if (fmt
[i
] == 'w')
239 fprintf (file
, HOST_WIDE_INT_PRINT_HEX
, XWINT (x
, i
));
245 case CONST_STRING
: fprintf (file
, "\"%s\"", XSTR (x
, 0)); break;
246 case CONST
: fputs ("const(", file
);
247 ra_print_rtx (file
, XEXP (x
, 0), 0);
250 case PC
: fputs ("pc", file
); break;
253 int regno
= REGNO (x
);
254 if (regno
< FIRST_PSEUDO_REGISTER
)
256 int i
, nregs
= HARD_REGNO_NREGS (regno
, mode
);
259 for (i
= 0; i
< nregs
; i
++)
263 if (reg_names
[regno
+i
] && *reg_names
[regno
+ i
])
264 fprintf (file
, "%s", reg_names
[regno
+ i
]);
266 fprintf (file
, "h%d", regno
+ i
);
272 fprintf (file
, "p%d", regno
);
277 rtx sub
= SUBREG_REG (x
);
278 int ofs
= SUBREG_BYTE (x
);
279 if (GET_CODE (sub
) == REG
280 && REGNO (sub
) < FIRST_PSEUDO_REGISTER
)
282 int regno
= REGNO (sub
);
283 int i
, nregs
= HARD_REGNO_NREGS (regno
, mode
);
284 regno
+= subreg_regno_offset (regno
, GET_MODE (sub
),
288 for (i
= 0; i
< nregs
; i
++)
292 if (reg_names
[regno
+i
])
293 fprintf (file
, "%s", reg_names
[regno
+ i
]);
295 fprintf (file
, "h%d", regno
+ i
);
302 ra_print_rtx (file
, sub
, 0);
303 fprintf (file
, ":[%s+%d]", GET_MODE_NAME (mode
), ofs
);
307 case SCRATCH
: fputs ("scratch", file
); break;
308 case CONCAT
: ra_print_rtx_2op (file
, x
); break;
309 case HIGH
: ra_print_rtx_1op (file
, x
); break;
312 ra_print_rtx (file
, XEXP (x
, 0), 0);
313 fputs (" + lo(", file
);
314 ra_print_rtx (file
, XEXP (x
, 1), 0);
317 case MEM
: fputs ("[", file
);
318 ra_print_rtx (file
, XEXP (x
, 0), 0);
319 fprintf (file
, "]:%s", GET_MODE_NAME (GET_MODE (x
)));
320 /* XXX print alias set too ?? */
324 rtx sub
= XEXP (x
, 0);
325 if (GET_CODE (sub
) == NOTE
326 && NOTE_LINE_NUMBER (sub
) == NOTE_INSN_DELETED_LABEL
)
327 fprintf (file
, "(deleted uid=%d)", INSN_UID (sub
));
328 else if (GET_CODE (sub
) == CODE_LABEL
)
329 fprintf (file
, "L%d", CODE_LABEL_NUMBER (sub
));
331 fprintf (file
, "(nonlabel uid=%d)", INSN_UID (sub
));
335 fprintf (file
, "sym(\"%s\")", XSTR (x
, 0)); break;
336 case CC0
: fputs ("cc0", file
); break;
337 default: print_inline_rtx (file
, x
, 0); break;
341 /* Print a general rtx X to FILE in nice infix form.
342 If WITH_PN is set, and X is one of the toplevel constructs
343 (insns, notes, labels or barriers), then print also the UIDs of
344 the preceding and following insn. */
347 ra_print_rtx (file
, x
, with_pn
)
358 class = GET_RTX_CLASS (code
);
360 /* First handle the insn like constructs. */
361 if (INSN_P (x
) || code
== NOTE
|| code
== CODE_LABEL
|| code
== BARRIER
)
365 /* Non-insns are prefixed by a ';'. */
368 else if (code
== NOTE
)
369 /* But notes are indented very far right. */
370 fprintf (file
, "\t\t\t\t\t; ");
371 else if (code
== CODE_LABEL
)
372 /* And labels have their Lxx name first, before the actual UID. */
374 fprintf (file
, "L%d:\t; ", CODE_LABEL_NUMBER (x
));
376 fprintf (file
, "(%s) ", LABEL_NAME (x
));
377 switch (LABEL_KIND (x
))
379 case LABEL_NORMAL
: break;
380 case LABEL_STATIC_ENTRY
: fputs (" (entry)", file
); break;
381 case LABEL_GLOBAL_ENTRY
: fputs (" (global entry)", file
); break;
382 case LABEL_WEAK_ENTRY
: fputs (" (weak entry)", file
); break;
385 fprintf (file
, " [%d uses] uid=(", LABEL_NUSES (x
));
387 fprintf (file
, "%d", INSN_UID (x
));
389 fprintf (file
, " %d %d", PREV_INSN (x
) ? INSN_UID (PREV_INSN (x
)) : 0,
390 NEXT_INSN (x
) ? INSN_UID (NEXT_INSN (x
)) : 0);
392 fputs (" -------- barrier ---------", file
);
393 else if (code
== CODE_LABEL
)
395 else if (code
== NOTE
)
397 int ln
= NOTE_LINE_NUMBER (x
);
398 if (ln
>= (int) NOTE_INSN_BIAS
&& ln
< (int) NOTE_INSN_MAX
)
399 fprintf (file
, " %s", GET_NOTE_INSN_NAME (ln
));
402 fprintf (file
, " line %d", ln
);
403 if (NOTE_SOURCE_FILE (x
))
404 fprintf (file
, ":%s", NOTE_SOURCE_FILE (x
));
409 fprintf (file
, "\t");
410 ra_print_rtx (file
, PATTERN (x
), 0);
416 /* Top-level stuff. */
420 for (j
= 0; j
< XVECLEN (x
, 0); j
++)
423 fputs ("\t;; ", file
);
424 ra_print_rtx (file
, XVECEXP (x
, 0, j
), 0);
428 case UNSPEC
: case UNSPEC_VOLATILE
:
431 fprintf (file
, "unspec%s(%d",
432 (code
== UNSPEC
) ? "" : "_vol", XINT (x
, 1));
433 for (j
= 0; j
< XVECLEN (x
, 0); j
++)
436 ra_print_rtx (file
, XVECEXP (x
, 0, j
), 0);
442 if (GET_CODE (SET_DEST (x
)) == PC
)
444 if (GET_CODE (SET_SRC (x
)) == IF_THEN_ELSE
445 && GET_CODE (XEXP (SET_SRC(x
), 2)) == PC
)
448 ra_print_rtx (file
, XEXP (SET_SRC (x
), 0), 0);
449 fputs (" jump ", file
);
450 ra_print_rtx (file
, XEXP (SET_SRC (x
), 1), 0);
454 fputs ("jump ", file
);
455 ra_print_rtx (file
, SET_SRC (x
), 0);
460 ra_print_rtx (file
, SET_DEST (x
), 0);
461 fputs (" <= ", file
);
462 ra_print_rtx (file
, SET_SRC (x
), 0);
466 fputs ("use <= ", file
);
467 ra_print_rtx (file
, XEXP (x
, 0), 0);
470 ra_print_rtx (file
, XEXP (x
, 0), 0);
471 fputs (" <= clobber", file
);
474 fputs ("call ", file
);
475 ra_print_rtx (file
, XEXP (x
, 0), 0); /* Address */
476 fputs (" numargs=", file
);
477 ra_print_rtx (file
, XEXP (x
, 1), 0); /* Num arguments */
480 fputs ("return", file
);
483 fputs ("if (", file
);
484 ra_print_rtx (file
, XEXP (x
, 0), 0);
485 fputs (") trap ", file
);
486 ra_print_rtx (file
, XEXP (x
, 1), 0);
489 fprintf (file
, "resx from region %d", XINT (x
, 0));
492 /* Different things of class 'x' */
493 case SUBREG
: ra_print_rtx_object (file
, x
); break;
494 case STRICT_LOW_PART
:
495 fputs ("low(", file
);
496 ra_print_rtx (file
, XEXP (x
, 0), 0);
506 ra_print_rtx_1op (file
, x
);
507 else if (class == '2' || class == 'c' || class == '<')
508 ra_print_rtx_2op (file
, x
);
509 else if (class == '3' || class == 'b')
510 ra_print_rtx_3op (file
, x
);
511 else if (class == 'o')
512 ra_print_rtx_object (file
, x
);
514 print_inline_rtx (file
, x
, 0);
517 /* This only calls ra_print_rtx(), but emits a final newline. */
520 ra_print_rtx_top (file
, x
, with_pn
)
525 ra_print_rtx (file
, x
, with_pn
);
526 fprintf (file
, "\n");
529 /* Callable from gdb. This prints rtx X onto stderr. */
535 ra_print_rtx_top (stderr
, x
, 1);
538 /* This prints the content of basic block with index BBI.
539 The first and last insn are emitted with UIDs of prev and next insns. */
545 basic_block bb
= BASIC_BLOCK (bbi
);
547 for (insn
= bb
->head
; insn
; insn
= NEXT_INSN (insn
))
549 ra_print_rtx_top (stderr
, insn
, (insn
== bb
->head
|| insn
== bb
->end
));
550 fprintf (stderr
, "\n");
556 /* Beginning from INSN, emit NUM insns (if NUM is non-negative)
557 or emit a window of NUM insns around INSN, to stderr. */
560 ra_debug_insns (insn
, num
)
564 int i
, count
= (num
== 0 ? 1 : num
< 0 ? -num
: num
);
566 for (i
= count
/ 2; i
> 0 && PREV_INSN (insn
); i
--)
567 insn
= PREV_INSN (insn
);
568 for (i
= count
; i
> 0 && insn
; insn
= NEXT_INSN (insn
), i
--)
570 if (GET_CODE (insn
) == CODE_LABEL
)
571 fprintf (stderr
, "\n");
572 ra_print_rtx_top (stderr
, insn
, (i
== count
|| i
== 1));
576 /* Beginning with INSN, emit the whole insn chain into FILE.
577 This also outputs comments when basic blocks start or end and omits
578 some notes, if flag_ra_dump_notes is zero. */
581 ra_print_rtl_with_bb (file
, insn
)
585 basic_block last_bb
, bb
;
586 unsigned int num
= 0;
590 for (; insn
; insn
= NEXT_INSN (insn
))
592 if (GET_CODE (insn
) == BARRIER
)
595 bb
= BLOCK_FOR_INSN (insn
);
599 fprintf (file
, ";; End of basic block %d\n", last_bb
->index
);
601 fprintf (file
, ";; Begin of basic block %d\n", bb
->index
);
604 if (GET_CODE (insn
) == CODE_LABEL
)
606 if (GET_CODE (insn
) == NOTE
)
608 /* Ignore basic block and maybe other notes not referencing
610 if (NOTE_LINE_NUMBER (insn
) != NOTE_INSN_BASIC_BLOCK
611 && (flag_ra_dump_notes
612 || NOTE_LINE_NUMBER (insn
) == NOTE_INSN_DELETED
613 || NOTE_LINE_NUMBER (insn
) == NOTE_INSN_DELETED_LABEL
))
615 ra_print_rtx_top (file
, insn
, (num
== 0 || !NEXT_INSN (insn
)));
621 ra_print_rtx_top (file
, insn
, (num
== 0 || !NEXT_INSN (insn
)));
627 /* Count how many insns were seen how often, while building the interference
628 graph, and prints the findings. */
637 for (i
= 0; i
< N
; i
++)
639 for (i
= 0; i
< get_max_uid (); i
++)
640 if (number_seen
[i
] < N
- 1)
641 num
[number_seen
[i
]]++;
644 for (i
= 0; i
< N
- 1; i
++)
646 ra_debug_msg (DUMP_PROCESS
, "%d insns seen %d times\n", num
[i
], i
);
648 ra_debug_msg (DUMP_PROCESS
, "%d insns seen %d and more times\n", num
[i
],
650 ra_debug_msg (DUMP_PROCESS
, "from overall %d insns\n", get_max_uid ());
654 /* Dump the interference graph, the move list and the webs. */
658 struct df
*df ATTRIBUTE_UNUSED
;
660 struct move_list
*ml
;
661 unsigned int def1
, def2
;
665 if (!rtl_dump_file
|| (debug_new_regalloc
& (DUMP_IGRAPH
| DUMP_WEBS
)) == 0)
667 ra_debug_msg (DUMP_IGRAPH
, "conflicts:\n ");
668 for (def1
= 0; def1
< num_webs
; def1
++)
672 for (def2
= 0; def2
< num_webs
; def2
++)
673 if (def1
!= def2
&& TEST_BIT (igraph
, igraph_index (def1
, def2
)))
677 if (SUBWEB_P (ID2WEB (def1
)))
678 ra_debug_msg (DUMP_IGRAPH
, "%d (SUBREG %d, %d) with ", def1
,
679 ID2WEB (def1
)->regno
,
680 SUBREG_BYTE (ID2WEB (def1
)->orig_x
));
682 ra_debug_msg (DUMP_IGRAPH
, "%d (REG %d) with ", def1
,
683 ID2WEB (def1
)->regno
);
686 ra_debug_msg (DUMP_IGRAPH
, "\n ");
689 if (SUBWEB_P (ID2WEB (def2
)))
690 ra_debug_msg (DUMP_IGRAPH
, "%d(%d,%d) ", def2
, ID2WEB (def2
)->regno
,
691 SUBREG_BYTE (ID2WEB (def2
)->orig_x
));
693 ra_debug_msg (DUMP_IGRAPH
, "%d(%d) ", def2
, ID2WEB (def2
)->regno
);
696 ra_debug_msg (DUMP_IGRAPH
, "\n ");
698 ra_debug_msg (DUMP_IGRAPH
, "\n");
699 for (ml
= wl_moves
; ml
; ml
= ml
->next
)
702 ra_debug_msg (DUMP_IGRAPH
, "move: insn %d: Web %d <-- Web %d\n",
703 INSN_UID (ml
->move
->insn
), ml
->move
->target_web
->id
,
704 ml
->move
->source_web
->id
);
706 ra_debug_msg (DUMP_WEBS
, "\nWebs:\n");
707 for (i
= 0; i
< num_webs
; i
++)
709 struct web
*web
= ID2WEB (i
);
711 ra_debug_msg (DUMP_WEBS
, " %4d : regno %3d", i
, web
->regno
);
714 ra_debug_msg (DUMP_WEBS
, " sub %d", SUBREG_BYTE (web
->orig_x
));
715 ra_debug_msg (DUMP_WEBS
, " par %d", find_web_for_subweb (web
)->id
);
717 ra_debug_msg (DUMP_WEBS
, " +%d (span %d, cost "
718 HOST_WIDE_INT_PRINT_DEC
") (%s)",
719 web
->add_hardregs
, web
->span_deaths
, web
->spill_cost
,
720 reg_class_names
[web
->regclass
]);
721 if (web
->spill_temp
== 1)
722 ra_debug_msg (DUMP_WEBS
, " (spilltemp)");
723 else if (web
->spill_temp
== 2)
724 ra_debug_msg (DUMP_WEBS
, " (spilltem2)");
725 else if (web
->spill_temp
== 3)
726 ra_debug_msg (DUMP_WEBS
, " (short)");
727 if (web
->type
== PRECOLORED
)
728 ra_debug_msg (DUMP_WEBS
, " (precolored, color=%d)", web
->color
);
729 else if (find_web_for_subweb (web
)->num_uses
== 0)
730 ra_debug_msg (DUMP_WEBS
, " dead");
731 if (web
->crosses_call
)
732 ra_debug_msg (DUMP_WEBS
, " xcall");
733 if (web
->regno
>= max_normal_pseudo
)
734 ra_debug_msg (DUMP_WEBS
, " stack");
735 ra_debug_msg (DUMP_WEBS
, "\n");
739 /* Dump the interference graph and webs in a format easily
740 parsable by programs. Used to emit real world interference graph
741 to my custom graph colorizer. */
744 dump_igraph_machine ()
748 if (!rtl_dump_file
|| (debug_new_regalloc
& DUMP_IGRAPH_M
) == 0)
750 ra_debug_msg (DUMP_IGRAPH_M
, "g %d %d\n", num_webs
- num_subwebs
,
751 FIRST_PSEUDO_REGISTER
);
752 for (i
= 0; i
< num_webs
- num_subwebs
; i
++)
754 struct web
*web
= ID2WEB (i
);
755 struct conflict_link
*cl
;
759 flags
= web
->spill_temp
& 0xF;
760 flags
|= ((web
->type
== PRECOLORED
) ? 1 : 0) << 4;
761 flags
|= (web
->add_hardregs
& 0xF) << 5;
762 for (cl
= web
->conflict_list
; cl
; cl
= cl
->next
)
763 if (cl
->t
->id
< web
->id
)
765 ra_debug_msg (DUMP_IGRAPH_M
, "n %d %d %d %d %d %d %d\n",
766 web
->id
, web
->color
, flags
,
767 (unsigned int)web
->spill_cost
, web
->num_defs
, web
->num_uses
,
769 if (web
->type
!= PRECOLORED
)
771 ra_debug_msg (DUMP_IGRAPH_M
, "s %d", web
->id
);
776 for (n
= 0; n
< 32 && col
< FIRST_PSEUDO_REGISTER
; n
++, col
++)
777 if (TEST_HARD_REG_BIT (web
->usable_regs
, col
))
779 ra_debug_msg (DUMP_IGRAPH_M
, " %u", u
);
780 if (col
>= FIRST_PSEUDO_REGISTER
)
783 ra_debug_msg (DUMP_IGRAPH_M
, "\n");
787 ra_debug_msg (DUMP_IGRAPH_M
, "c %d", web
->id
);
788 for (cl
= web
->conflict_list
; cl
; cl
= cl
->next
)
790 if (cl
->t
->id
< web
->id
)
791 ra_debug_msg (DUMP_IGRAPH_M
, " %d", cl
->t
->id
);
793 ra_debug_msg (DUMP_IGRAPH_M
, "\n");
796 ra_debug_msg (DUMP_IGRAPH_M
, "e\n");
799 /* This runs after colorization and changing the insn stream.
800 It temporarily replaces all pseudo registers with their colors,
801 and emits information, if the resulting insns are strictly valid. */
808 if (!rtl_dump_file
|| (debug_new_regalloc
& DUMP_CONSTRAINTS
) == 0)
810 for (i
= FIRST_PSEUDO_REGISTER
; i
< ra_max_regno
; i
++)
811 if (regno_reg_rtx
[i
] && GET_CODE (regno_reg_rtx
[i
]) == REG
)
812 REGNO (regno_reg_rtx
[i
])
813 = ra_reg_renumber
[i
] >= 0 ? ra_reg_renumber
[i
] : i
;
814 for (insn
= get_insns (); insn
; insn
= NEXT_INSN (insn
))
818 int uid
= INSN_UID (insn
);
820 /* Don't simply force rerecognition, as combine might left us
821 with some unrecognizable ones, which later leads to aborts
822 in regclass, if we now destroy the remembered INSN_CODE(). */
823 /*INSN_CODE (insn) = -1;*/
824 code
= recog_memoized (insn
);
827 ra_debug_msg (DUMP_CONSTRAINTS
,
828 "%d: asm insn or not recognizable.\n", uid
);
831 ra_debug_msg (DUMP_CONSTRAINTS
,
832 "%d: code %d {%s}, %d operands, constraints: ",
833 uid
, code
, insn_data
[code
].name
, recog_data
.n_operands
);
835 /*preprocess_constraints ();*/
836 for (o
= 0; o
< recog_data
.n_operands
; o
++)
838 ra_debug_msg (DUMP_CONSTRAINTS
,
839 "%d:%s ", o
, recog_data
.constraints
[o
]);
841 if (constrain_operands (1))
842 ra_debug_msg (DUMP_CONSTRAINTS
, "matches strictly alternative %d",
845 ra_debug_msg (DUMP_CONSTRAINTS
, "doesn't match strictly");
846 ra_debug_msg (DUMP_CONSTRAINTS
, "\n");
848 for (i
= FIRST_PSEUDO_REGISTER
; i
< ra_max_regno
; i
++)
849 if (regno_reg_rtx
[i
] && GET_CODE (regno_reg_rtx
[i
]) == REG
)
850 REGNO (regno_reg_rtx
[i
]) = i
;
853 /* This counts and emits the cumulated cost of all spilled webs,
854 preceded by a custom message MSG, with debug level LEVEL. */
857 dump_graph_cost (level
, msg
)
862 unsigned HOST_WIDE_INT cost
;
863 if (!rtl_dump_file
|| (debug_new_regalloc
& level
) == 0)
867 for (i
= 0; i
< num_webs
; i
++)
869 struct web
*web
= id2web
[i
];
870 if (alias (web
)->type
== SPILLED
)
871 cost
+= web
->orig_spill_cost
;
873 ra_debug_msg (level
, " spill cost of graph (%s) = "
874 HOST_WIDE_INT_PRINT_UNSIGNED
"\n",
875 msg
? msg
: "", cost
);
878 /* Dump the color assignment per web, the coalesced and spilled webs. */
882 struct df
*df ATTRIBUTE_UNUSED
;
886 if (!rtl_dump_file
|| (debug_new_regalloc
& DUMP_RESULTS
) == 0)
889 ra_debug_msg (DUMP_RESULTS
, "\nColored:\n");
890 for (d
= WEBS(COLORED
); d
; d
= d
->next
)
893 ra_debug_msg (DUMP_RESULTS
, " %4d : color %d\n", web
->id
, web
->color
);
895 ra_debug_msg (DUMP_RESULTS
, "\nCoalesced:\n");
896 for (d
= WEBS(COALESCED
); d
; d
= d
->next
)
899 ra_debug_msg (DUMP_RESULTS
, " %4d : to web %d, color %d\n", web
->id
,
900 alias (web
)->id
, web
->color
);
902 ra_debug_msg (DUMP_RESULTS
, "\nSpilled:\n");
903 for (d
= WEBS(SPILLED
); d
; d
= d
->next
)
906 ra_debug_msg (DUMP_RESULTS
, " %4d\n", web
->id
);
908 ra_debug_msg (DUMP_RESULTS
, "\n");
909 dump_cost (DUMP_RESULTS
);
912 /* Calculate and dump the cumulated costs of certain types of insns
913 (loads, stores and copies). */
916 dump_static_insn_cost (file
, message
, prefix
)
923 unsigned HOST_WIDE_INT cost
;
927 struct cost load
, store
, regcopy
, selfcopy
, overall
;
928 memset (&load
, 0, sizeof(load
));
929 memset (&store
, 0, sizeof(store
));
930 memset (®copy
, 0, sizeof(regcopy
));
931 memset (&selfcopy
, 0, sizeof(selfcopy
));
932 memset (&overall
, 0, sizeof(overall
));
939 unsigned HOST_WIDE_INT block_cost
= bb
->frequency
;
941 for (insn
= bb
->head
; insn
; insn
= NEXT_INSN (insn
))
943 /* Yes, yes. We don't calculate the costs precisely.
944 Only for "simple enough" insns. Those containing single
946 if (INSN_P (insn
) && ((set
= single_set (insn
)) != NULL
))
948 rtx src
= SET_SRC (set
);
949 rtx dest
= SET_DEST (set
);
950 struct cost
*pcost
= NULL
;
951 overall
.cost
+= block_cost
;
953 if (rtx_equal_p (src
, dest
))
955 else if (GET_CODE (src
) == GET_CODE (dest
)
956 && ((GET_CODE (src
) == REG
)
957 || (GET_CODE (src
) == SUBREG
958 && GET_CODE (SUBREG_REG (src
)) == REG
959 && GET_CODE (SUBREG_REG (dest
)) == REG
)))
963 if (GET_CODE (src
) == SUBREG
)
964 src
= SUBREG_REG (src
);
965 if (GET_CODE (dest
) == SUBREG
)
966 dest
= SUBREG_REG (dest
);
967 if (GET_CODE (src
) == MEM
&& GET_CODE (dest
) != MEM
968 && memref_is_stack_slot (src
))
970 else if (GET_CODE (src
) != MEM
&& GET_CODE (dest
) == MEM
971 && memref_is_stack_slot (dest
))
976 pcost
->cost
+= block_cost
;
987 fprintf (file
, "static insn cost %s\n", message
? message
: "");
988 fprintf (file
, " %soverall:\tnum=%6d\tcost="
989 HOST_WIDE_INT_PRINT_DEC_SPACE
"\n",
990 prefix
, overall
.count
, 8, overall
.cost
);
991 fprintf (file
, " %sloads:\tnum=%6d\tcost="
992 HOST_WIDE_INT_PRINT_DEC_SPACE
"\n",
993 prefix
, load
.count
, 8, load
.cost
);
994 fprintf (file
, " %sstores:\tnum=%6d\tcost="
995 HOST_WIDE_INT_PRINT_DEC_SPACE
"\n",
996 prefix
, store
.count
, 8, store
.cost
);
997 fprintf (file
, " %sregcopy:\tnum=%6d\tcost="
998 HOST_WIDE_INT_PRINT_DEC_SPACE
"\n",
999 prefix
, regcopy
.count
, 8, regcopy
.cost
);
1000 fprintf (file
, " %sselfcpy:\tnum=%6d\tcost="
1001 HOST_WIDE_INT_PRINT_DEC_SPACE
"\n",
1002 prefix
, selfcopy
.count
, 8, selfcopy
.cost
);
1005 /* Returns nonzero, if WEB1 and WEB2 have some possible
1006 hardregs in common. */
1009 web_conflicts_p (web1
, web2
)
1013 if (web1
->type
== PRECOLORED
&& web2
->type
== PRECOLORED
)
1016 if (web1
->type
== PRECOLORED
)
1017 return TEST_HARD_REG_BIT (web2
->usable_regs
, web1
->regno
);
1019 if (web2
->type
== PRECOLORED
)
1020 return TEST_HARD_REG_BIT (web1
->usable_regs
, web2
->regno
);
1022 return hard_regs_intersect_p (&web1
->usable_regs
, &web2
->usable_regs
);
1025 /* Dump all uids of insns in which WEB is mentioned. */
1028 dump_web_insns (web
)
1033 ra_debug_msg (DUMP_EVER
, "Web: %i(%i)+%i class: %s freedom: %i degree %i\n",
1034 web
->id
, web
->regno
, web
->add_hardregs
,
1035 reg_class_names
[web
->regclass
],
1036 web
->num_freedom
, web
->num_conflicts
);
1037 ra_debug_msg (DUMP_EVER
, " def insns:");
1039 for (i
= 0; i
< web
->num_defs
; ++i
)
1041 ra_debug_msg (DUMP_EVER
, " %d ", INSN_UID (web
->defs
[i
]->insn
));
1044 ra_debug_msg (DUMP_EVER
, "\n use insns:");
1045 for (i
= 0; i
< web
->num_uses
; ++i
)
1047 ra_debug_msg (DUMP_EVER
, " %d ", INSN_UID (web
->uses
[i
]->insn
));
1049 ra_debug_msg (DUMP_EVER
, "\n");
1052 /* Dump conflicts for web WEB. */
1055 dump_web_conflicts (web
)
1061 ra_debug_msg (DUMP_EVER
, "Web: %i(%i)+%i class: %s freedom: %i degree %i\n",
1062 web
->id
, web
->regno
, web
->add_hardregs
,
1063 reg_class_names
[web
->regclass
],
1064 web
->num_freedom
, web
->num_conflicts
);
1066 for (def2
= 0; def2
< num_webs
; def2
++)
1067 if (TEST_BIT (igraph
, igraph_index (web
->id
, def2
)) && web
->id
!= def2
)
1070 ra_debug_msg (DUMP_EVER
, "\n ");
1073 ra_debug_msg (DUMP_EVER
, " %d(%d)", def2
, id2web
[def2
]->regno
);
1074 if (id2web
[def2
]->add_hardregs
)
1075 ra_debug_msg (DUMP_EVER
, "+%d", id2web
[def2
]->add_hardregs
);
1077 if (web_conflicts_p (web
, id2web
[def2
]))
1078 ra_debug_msg (DUMP_EVER
, "/x");
1080 if (id2web
[def2
]->type
== SELECT
)
1081 ra_debug_msg (DUMP_EVER
, "/s");
1083 if (id2web
[def2
]->type
== COALESCED
)
1084 ra_debug_msg (DUMP_EVER
,"/c/%d", alias (id2web
[def2
])->id
);
1086 ra_debug_msg (DUMP_EVER
, "\n");
1088 struct conflict_link
*wl
;
1090 ra_debug_msg (DUMP_EVER
, "By conflicts: ");
1091 for (wl
= web
->conflict_list
; wl
; wl
= wl
->next
)
1093 struct web
* w
= wl
->t
;
1095 ra_debug_msg (DUMP_EVER
, "\n ");
1097 ra_debug_msg (DUMP_EVER
, "%d(%d)%s ", w
->id
, w
->regno
,
1098 web_conflicts_p (web
, w
) ? "+" : "");
1100 ra_debug_msg (DUMP_EVER
, "\n");
1104 /* Output HARD_REG_SET to stderr. */
1107 debug_hard_reg_set (set
)
1111 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; ++i
)
1113 if (TEST_HARD_REG_BIT (set
, i
))
1115 fprintf (stderr
, "%s ", reg_names
[i
]);
1118 fprintf (stderr
, "\n");
1122 vim:cinoptions={.5s,g0,p5,t0,(0,^-0.5s,n-0.5s:tw=78:cindent:sw=4: