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"
33 /* This file contains various dumping and debug functions for
34 the graph coloring register allocator. */
36 static void ra_print_rtx_1op PARAMS ((FILE *, rtx));
37 static void ra_print_rtx_2op PARAMS ((FILE *, rtx));
38 static void ra_print_rtx_3op PARAMS ((FILE *, rtx));
39 static void ra_print_rtx_object PARAMS ((FILE *, rtx));
41 /* The hardregs as names, for debugging. */
42 static const char *const reg_class_names[] = REG_CLASS_NAMES;
44 /* Print a message to the dump file, if debug_new_regalloc and LEVEL
45 have any bits in common. */
48 ra_debug_msg VPARAMS ((unsigned int level, const char *format, ...))
50 #ifndef ANSI_PROTOTYPES
55 if ((debug_new_regalloc & level) != 0 && rtl_dump_file != NULL)
57 VA_START (ap, format);
59 #ifndef ANSI_PROTOTYPES
60 format = va_arg (ap, const char *);
63 vfprintf (rtl_dump_file, format, ap);
69 /* The following ra_print_xxx() functions print RTL expressions
70 in concise infix form. If the mode can be seen from context it's
71 left out. Most operators are represented by their graphical
72 characters, e.g. LE as "<=". Unknown constructs are currently
73 printed with print_inline_rtx(), which disrupts the nice layout.
74 Currently only the inline asm things are written this way. */
76 /* Print rtx X, which is a one operand rtx (op:mode (Y)), as
80 ra_print_rtx_1op (file, x)
84 enum rtx_code code = GET_CODE (x);
85 rtx op0 = XEXP (x, 0);
90 fputs ((code == NEG) ? "-(" : "~(", file);
91 ra_print_rtx (file, op0, 0);
96 ra_print_rtx (file, op0, 0);
100 fprintf (file, "%s", GET_RTX_NAME (code));
101 if (GET_MODE (x) != VOIDmode)
102 fprintf (file, ":%s(", GET_MODE_NAME (GET_MODE (x)));
105 ra_print_rtx (file, op0, 0);
111 /* Print rtx X, which is a two operand rtx (op:mode (Y) (Z))
112 as "(Y op Z)", if the operand is know, or as "op(Y, Z)", if not,
116 ra_print_rtx_2op (file, x)
121 const char *opname = "shitop";
122 enum rtx_code code = GET_CODE (x);
123 rtx op0 = XEXP (x, 0);
124 rtx op1 = XEXP (x, 1);
128 case COMPARE: opname = "?"; break;
129 case MINUS: opname = "-"; break;
130 case DIV: opname = "/"; break;
131 case UDIV: opname = "u/"; break;
132 case MOD: opname = "%"; break;
133 case UMOD: opname = "u%"; break;
134 case ASHIFT: opname = "<<"; break;
135 case ASHIFTRT: opname = "a>>"; break;
136 case LSHIFTRT: opname = "l>>"; break;
138 case PLUS: opname = "+"; break;
139 case MULT: opname = "*"; break;
140 case AND: opname = "&"; break;
141 case IOR: opname = "|"; break;
142 case XOR: opname = "^"; break;
144 case NE: opname = "!="; break;
145 case EQ: opname = "=="; break;
146 case GE: opname = "s>="; break;
147 case GT: opname = "s>"; break;
148 case LE: opname = "s<="; break;
149 case LT: opname = "s<"; break;
150 case GEU: opname = "u>="; break;
151 case GTU: opname = "u>"; break;
152 case LEU: opname = "u<="; break;
153 case LTU: opname = "u<"; break;
156 opname = GET_RTX_NAME (code);
162 ra_print_rtx (file, op0, 0);
163 fprintf (file, " %s ", opname);
164 ra_print_rtx (file, op1, 0);
169 fprintf (file, "%s(", opname);
170 ra_print_rtx (file, op0, 0);
172 ra_print_rtx (file, op1, 0);
177 /* Print rtx X, which a three operand rtx to FILE.
178 I.e. X is either an IF_THEN_ELSE, or a bitmap operation. */
181 ra_print_rtx_3op (file, x)
185 enum rtx_code code = GET_CODE (x);
186 rtx op0 = XEXP (x, 0);
187 rtx op1 = XEXP (x, 1);
188 rtx op2 = XEXP (x, 2);
189 if (code == IF_THEN_ELSE)
191 ra_print_rtx (file, op0, 0);
193 ra_print_rtx (file, op1, 0);
195 ra_print_rtx (file, op2, 0);
199 /* Bitmap-operation */
200 fprintf (file, "%s:%s(", GET_RTX_NAME (code),
201 GET_MODE_NAME (GET_MODE (x)));
202 ra_print_rtx (file, op0, 0);
204 ra_print_rtx (file, op1, 0);
206 ra_print_rtx (file, op2, 0);
211 /* Print rtx X, which represents an object (class 'o' or some constructs
212 of class 'x' (e.g. subreg)), to FILE.
213 (reg XX) rtl is represented as "pXX", of XX was a pseudo,
214 as "name" it name is the nonnull hardreg name, or as "hXX", if XX
215 is a hardreg, whose name is NULL, or empty. */
218 ra_print_rtx_object (file, x)
222 enum rtx_code code = GET_CODE (x);
223 enum machine_mode mode = GET_MODE (x);
227 fprintf (file, HOST_WIDE_INT_PRINT_DEC, XWINT (x, 0));
232 const char *fmt = GET_RTX_FORMAT (code);
233 fputs ("dbl(", file);
234 for (i = 0; i < GET_RTX_LENGTH (code); i++)
238 if (fmt[i] == 'e' && XEXP (x, i))
239 /* The MEM or other stuff */
241 ra_print_rtx (file, XEXP (x, i), 0);
244 else if (fmt[i] == 'w')
246 fprintf (file, HOST_WIDE_INT_PRINT_HEX, XWINT (x, i));
252 case CONST_STRING: fprintf (file, "\"%s\"", XSTR (x, 0)); break;
253 case CONST: fputs ("const(", file);
254 ra_print_rtx (file, XEXP (x, 0), 0);
257 case PC: fputs ("pc", file); break;
260 int regno = REGNO (x);
261 if (regno < FIRST_PSEUDO_REGISTER)
263 int i, nregs = HARD_REGNO_NREGS (regno, mode);
266 for (i = 0; i < nregs; i++)
270 if (reg_names[regno+i] && *reg_names[regno + i])
271 fprintf (file, "%s", reg_names[regno + i]);
273 fprintf (file, "h%d", regno + i);
279 fprintf (file, "p%d", regno);
284 rtx sub = SUBREG_REG (x);
285 int ofs = SUBREG_BYTE (x);
286 if (GET_CODE (sub) == REG
287 && REGNO (sub) < FIRST_PSEUDO_REGISTER)
289 int regno = REGNO (sub);
290 int i, nregs = HARD_REGNO_NREGS (regno, mode);
291 regno += subreg_regno_offset (regno, GET_MODE (sub),
295 for (i = 0; i < nregs; i++)
299 if (reg_names[regno+i])
300 fprintf (file, "%s", reg_names[regno + i]);
302 fprintf (file, "h%d", regno + i);
309 ra_print_rtx (file, sub, 0);
310 fprintf (file, ":[%s+%d]", GET_MODE_NAME (mode), ofs);
314 case SCRATCH: fputs ("scratch", file); break;
315 case CONCAT: ra_print_rtx_2op (file, x); break;
316 case HIGH: ra_print_rtx_1op (file, x); break;
319 ra_print_rtx (file, XEXP (x, 0), 0);
320 fputs (" + lo(", file);
321 ra_print_rtx (file, XEXP (x, 1), 0);
324 case MEM: fputs ("[", file);
325 ra_print_rtx (file, XEXP (x, 0), 0);
326 fprintf (file, "]:%s", GET_MODE_NAME (GET_MODE (x)));
327 /* XXX print alias set too ?? */
331 rtx sub = XEXP (x, 0);
332 if (GET_CODE (sub) == NOTE
333 && NOTE_LINE_NUMBER (sub) == NOTE_INSN_DELETED_LABEL)
334 fprintf (file, "(deleted uid=%d)", INSN_UID (sub));
335 else if (GET_CODE (sub) == CODE_LABEL)
336 fprintf (file, "L%d", CODE_LABEL_NUMBER (sub));
338 fprintf (file, "(nonlabel uid=%d)", INSN_UID (sub));
342 fprintf (file, "sym(\"%s\")", XSTR (x, 0)); break;
343 case CC0: fputs ("cc0", file); break;
344 default: print_inline_rtx (file, x, 0); break;
348 /* Print a general rtx X to FILE in nice infix form.
349 If WITH_PN is set, and X is one of the toplevel constructs
350 (insns, notes, labels or barriers), then print also the UIDs of
351 the preceding and following insn. */
354 ra_print_rtx (file, x, with_pn)
365 class = GET_RTX_CLASS (code);
367 /* First handle the insn like constructs. */
368 if (INSN_P (x) || code == NOTE || code == CODE_LABEL || code == BARRIER)
372 /* Non-insns are prefixed by a ';'. */
375 else if (code == NOTE)
376 /* But notes are indented very far right. */
377 fprintf (file, "\t\t\t\t\t; ");
378 else if (code == CODE_LABEL)
379 /* And labels have their Lxx name first, before the actual UID. */
381 fprintf (file, "L%d:\t; ", CODE_LABEL_NUMBER (x));
383 fprintf (file, "(%s) ", LABEL_NAME (x));
384 if (LABEL_ALTERNATE_NAME (x))
385 fprintf (file, "(alternate: %s) ", LABEL_ALTERNATE_NAME (x));
386 fprintf (file, " [%d uses] uid=(", LABEL_NUSES (x));
388 fprintf (file, "%d", INSN_UID (x));
390 fprintf (file, " %d %d", PREV_INSN (x) ? INSN_UID (PREV_INSN (x)) : 0,
391 NEXT_INSN (x) ? INSN_UID (NEXT_INSN (x)) : 0);
393 fputs (" -------- barrier ---------", file);
394 else if (code == CODE_LABEL)
396 else if (code == NOTE)
398 int ln = NOTE_LINE_NUMBER (x);
399 if (ln >= (int) NOTE_INSN_BIAS && ln < (int) NOTE_INSN_MAX)
400 fprintf (file, " %s", GET_NOTE_INSN_NAME (ln));
403 fprintf (file, " line %d", ln);
404 if (NOTE_SOURCE_FILE (x))
405 fprintf (file, ":%s", NOTE_SOURCE_FILE (x));
410 fprintf (file, "\t");
411 ra_print_rtx (file, PATTERN (x), 0);
417 /* Top-level stuff. */
421 for (j = 0; j < XVECLEN (x, 0); j++)
424 fputs ("\t;; ", file);
425 ra_print_rtx (file, XVECEXP (x, 0, j), 0);
429 case UNSPEC: case UNSPEC_VOLATILE:
432 fprintf (file, "unspec%s(%d",
433 (code == UNSPEC) ? "" : "_vol", XINT (x, 1));
434 for (j = 0; j < XVECLEN (x, 0); j++)
437 ra_print_rtx (file, XVECEXP (x, 0, j), 0);
443 if (GET_CODE (SET_DEST (x)) == PC)
445 if (GET_CODE (SET_SRC (x)) == IF_THEN_ELSE
446 && GET_CODE (XEXP (SET_SRC(x), 2)) == PC)
449 ra_print_rtx (file, XEXP (SET_SRC (x), 0), 0);
450 fputs (" jump ", file);
451 ra_print_rtx (file, XEXP (SET_SRC (x), 1), 0);
455 fputs ("jump ", file);
456 ra_print_rtx (file, SET_SRC (x), 0);
461 ra_print_rtx (file, SET_DEST (x), 0);
462 fputs (" <= ", file);
463 ra_print_rtx (file, SET_SRC (x), 0);
467 fputs ("use <= ", file);
468 ra_print_rtx (file, XEXP (x, 0), 0);
471 ra_print_rtx (file, XEXP (x, 0), 0);
472 fputs (" <= clobber", file);
475 fputs ("call ", file);
476 ra_print_rtx (file, XEXP (x, 0), 0); /* Address */
477 fputs (" numargs=", file);
478 ra_print_rtx (file, XEXP (x, 1), 0); /* Num arguments */
481 fputs ("return", file);
484 fputs ("if (", file);
485 ra_print_rtx (file, XEXP (x, 0), 0);
486 fputs (") trap ", file);
487 ra_print_rtx (file, XEXP (x, 1), 0);
490 fprintf (file, "resx from region %d", XINT (x, 0));
493 /* Different things of class 'x' */
494 case SUBREG: ra_print_rtx_object (file, x); break;
495 case STRICT_LOW_PART:
496 fputs ("low(", file);
497 ra_print_rtx (file, XEXP (x, 0), 0);
507 ra_print_rtx_1op (file, x);
508 else if (class == '2' || class == 'c' || class == '<')
509 ra_print_rtx_2op (file, x);
510 else if (class == '3' || class == 'b')
511 ra_print_rtx_3op (file, x);
512 else if (class == 'o')
513 ra_print_rtx_object (file, x);
515 print_inline_rtx (file, x, 0);
518 /* This only calls ra_print_rtx(), but emits a final newline. */
521 ra_print_rtx_top (file, x, with_pn)
526 ra_print_rtx (file, x, with_pn);
527 fprintf (file, "\n");
530 /* 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. */
546 basic_block bb = BASIC_BLOCK (bbi);
548 for (insn = bb->head; insn; insn = NEXT_INSN (insn))
550 ra_print_rtx_top (stderr, insn, (insn == bb->head || insn == bb->end));
551 fprintf (stderr, "\n");
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 (insn, num)
565 int i, count = (num == 0 ? 1 : num < 0 ? -num : num);
567 for (i = count / 2; i > 0 && PREV_INSN (insn); i--)
568 insn = PREV_INSN (insn);
569 for (i = count; i > 0 && insn; insn = NEXT_INSN (insn), i--)
571 if (GET_CODE (insn) == CODE_LABEL)
572 fprintf (stderr, "\n");
573 ra_print_rtx_top (stderr, insn, (i == count || i == 1));
577 /* Beginning with INSN, emit the whole insn chain into FILE.
578 This also outputs comments when basic blocks start or end and omits
579 some notes, if flag_ra_dump_notes is zero. */
582 ra_print_rtl_with_bb (file, insn)
586 basic_block last_bb, bb;
587 unsigned int num = 0;
591 for (; insn; insn = NEXT_INSN (insn))
593 if (GET_CODE (insn) == BARRIER)
596 bb = BLOCK_FOR_INSN (insn);
600 fprintf (file, ";; End of basic block %d\n", last_bb->index);
602 fprintf (file, ";; Begin of basic block %d\n", bb->index);
605 if (GET_CODE (insn) == CODE_LABEL)
607 if (GET_CODE (insn) == NOTE)
609 /* Ignore basic block and maybe other notes not referencing
611 if (NOTE_LINE_NUMBER (insn) != NOTE_INSN_BASIC_BLOCK
612 && (flag_ra_dump_notes
613 || NOTE_LINE_NUMBER (insn) == NOTE_INSN_DELETED
614 || NOTE_LINE_NUMBER (insn) == NOTE_INSN_DELETED_LABEL))
616 ra_print_rtx_top (file, insn, (num == 0 || !NEXT_INSN (insn)));
622 ra_print_rtx_top (file, insn, (num == 0 || !NEXT_INSN (insn)));
628 /* Count how many insns were seen how often, while building the interference
629 graph, and prints the findings. */
638 for (i = 0; i < N; i++)
640 for (i = 0; i < get_max_uid (); i++)
641 if (number_seen[i] < N - 1)
642 num[number_seen[i]]++;
645 for (i = 0; i < N - 1; i++)
647 ra_debug_msg (DUMP_PROCESS, "%d insns seen %d times\n", num[i], i);
649 ra_debug_msg (DUMP_PROCESS, "%d insns seen %d and more times\n", num[i],
651 ra_debug_msg (DUMP_PROCESS, "from overall %d insns\n", get_max_uid ());
655 /* Dump the interference graph, the move list and the webs. */
659 struct df *df ATTRIBUTE_UNUSED;
661 struct move_list *ml;
662 unsigned int def1, def2;
666 if (!rtl_dump_file || (debug_new_regalloc & (DUMP_IGRAPH | DUMP_WEBS)) == 0)
668 ra_debug_msg (DUMP_IGRAPH, "conflicts:\n ");
669 for (def1 = 0; def1 < num_webs; def1++)
672 for (num2=0, 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 unrecongnizable 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 #define LU HOST_WIDE_INT_PRINT_UNSIGNED
864 if (!rtl_dump_file || (debug_new_regalloc & level) == 0)
868 for (i = 0; i < num_webs; i++)
870 struct web *web = id2web[i];
871 if (alias (web)->type == SPILLED)
872 cost += web->orig_spill_cost;
874 ra_debug_msg (level, " spill cost of graph (%s) = " LU "\n",
875 msg ? msg : "", cost);
879 /* Dump the color assignment per web, the coalesced and spilled webs. */
883 struct df *df ATTRIBUTE_UNUSED;
887 if (!rtl_dump_file || (debug_new_regalloc & DUMP_RESULTS) == 0)
890 ra_debug_msg (DUMP_RESULTS, "\nColored:\n");
891 for (d = WEBS(COLORED); d; d = d->next)
894 ra_debug_msg (DUMP_RESULTS, " %4d : color %d\n", web->id, web->color);
896 ra_debug_msg (DUMP_RESULTS, "\nCoalesced:\n");
897 for (d = WEBS(COALESCED); d; d = d->next)
900 ra_debug_msg (DUMP_RESULTS, " %4d : to web %d, color %d\n", web->id,
901 alias (web)->id, web->color);
903 ra_debug_msg (DUMP_RESULTS, "\nSpilled:\n");
904 for (d = WEBS(SPILLED); d; d = d->next)
907 ra_debug_msg (DUMP_RESULTS, " %4d\n", web->id);
909 ra_debug_msg (DUMP_RESULTS, "\n");
910 dump_cost (DUMP_RESULTS);
913 /* Calculate and dump the cumulated costs of certain types of insns
914 (loads, stores and copies). */
917 dump_static_insn_cost (file, message, prefix)
924 unsigned HOST_WIDE_INT cost;
927 struct cost load = {0, 0};
928 struct cost store = {0, 0};
929 struct cost regcopy = {0, 0};
930 struct cost selfcopy = {0, 0};
931 struct cost overall = {0, 0};
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=%8d\n", prefix, overall.count,
990 fprintf (file, " %sloads:\tnum=%6d\tcost=%8d\n", prefix, load.count,
992 fprintf (file, " %sstores:\tnum=%6d\tcost=%8d\n", prefix,
993 store.count, store.cost);
994 fprintf (file, " %sregcopy:\tnum=%6d\tcost=%8d\n", prefix, regcopy.count,
996 fprintf (file, " %sselfcpy:\tnum=%6d\tcost=%8d\n", prefix, selfcopy.count,
1000 /* Returns nonzero, if WEB1 and WEB2 have some possible
1001 hardregs in common. */
1004 web_conflicts_p (web1, web2)
1008 if (web1->type == PRECOLORED && web2->type == PRECOLORED)
1011 if (web1->type == PRECOLORED)
1012 return TEST_HARD_REG_BIT (web2->usable_regs, web1->regno);
1014 if (web2->type == PRECOLORED)
1015 return TEST_HARD_REG_BIT (web1->usable_regs, web2->regno);
1017 return hard_regs_intersect_p (&web1->usable_regs, &web2->usable_regs);
1020 /* Dump all uids of insns in which WEB is mentioned. */
1023 dump_web_insns (web)
1028 ra_debug_msg (DUMP_EVER, "Web: %i(%i)+%i class: %s freedom: %i degree %i\n",
1029 web->id, web->regno, web->add_hardregs,
1030 reg_class_names[web->regclass],
1031 web->num_freedom, web->num_conflicts);
1032 ra_debug_msg (DUMP_EVER, " def insns:");
1034 for (i = 0; i < web->num_defs; ++i)
1036 ra_debug_msg (DUMP_EVER, " %d ", INSN_UID (web->defs[i]->insn));
1039 ra_debug_msg (DUMP_EVER, "\n use insns:");
1040 for (i = 0; i < web->num_uses; ++i)
1042 ra_debug_msg (DUMP_EVER, " %d ", INSN_UID (web->uses[i]->insn));
1044 ra_debug_msg (DUMP_EVER, "\n");
1047 /* Dump conflicts for web WEB. */
1050 dump_web_conflicts (web)
1056 ra_debug_msg (DUMP_EVER, "Web: %i(%i)+%i class: %s freedom: %i degree %i\n",
1057 web->id, web->regno, web->add_hardregs,
1058 reg_class_names[web->regclass],
1059 web->num_freedom, web->num_conflicts);
1061 for (def2 = 0; def2 < num_webs; def2++)
1062 if (TEST_BIT (igraph, igraph_index (web->id, def2)) && web->id != def2)
1065 ra_debug_msg (DUMP_EVER, "\n ");
1068 ra_debug_msg (DUMP_EVER, " %d(%d)", def2, id2web[def2]->regno);
1069 if (id2web[def2]->add_hardregs)
1070 ra_debug_msg (DUMP_EVER, "+%d", id2web[def2]->add_hardregs);
1072 if (web_conflicts_p (web, id2web[def2]))
1073 ra_debug_msg (DUMP_EVER, "/x");
1075 if (id2web[def2]->type == SELECT)
1076 ra_debug_msg (DUMP_EVER, "/s");
1078 if (id2web[def2]->type == COALESCED)
1079 ra_debug_msg (DUMP_EVER,"/c/%d", alias (id2web[def2])->id);
1081 ra_debug_msg (DUMP_EVER, "\n");
1083 struct conflict_link *wl;
1085 ra_debug_msg (DUMP_EVER, "By conflicts: ");
1086 for (wl = web->conflict_list; wl; wl = wl->next)
1088 struct web* w = wl->t;
1090 ra_debug_msg (DUMP_EVER, "\n ");
1092 ra_debug_msg (DUMP_EVER, "%d(%d)%s ", w->id, w->regno,
1093 web_conflicts_p (web, w) ? "+" : "");
1095 ra_debug_msg (DUMP_EVER, "\n");
1099 /* Output HARD_REG_SET to stderr. */
1102 debug_hard_reg_set (set)
1106 for (i=0; i < FIRST_PSEUDO_REGISTER; ++i)
1108 if (TEST_HARD_REG_BIT (set, i))
1110 fprintf (stderr, "%s ", reg_names[i]);
1113 fprintf (stderr, "\n");
1117 vim:cinoptions={.5s,g0,p5,t0,(0,^-0.5s,n-0.5s:tw=78:cindent:sw=4: