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"
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 /* 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 && dump_file
!= NULL
)
57 vfprintf (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 *file
, rtx x
)
75 enum rtx_code code
= GET_CODE (x
);
76 rtx op0
= XEXP (x
, 0);
81 fputs ((code
== NEG
) ? "-(" : "~(", file
);
82 ra_print_rtx (file
, op0
, 0);
87 ra_print_rtx (file
, op0
, 0);
91 fprintf (file
, "%s", GET_RTX_NAME (code
));
92 if (GET_MODE (x
) != VOIDmode
)
93 fprintf (file
, ":%s(", GET_MODE_NAME (GET_MODE (x
)));
96 ra_print_rtx (file
, op0
, 0);
102 /* Print rtx X, which is a two operand rtx (op:mode (Y) (Z))
103 as "(Y op Z)", if the operand is know, or as "op(Y, Z)", if not,
107 ra_print_rtx_2op (FILE *file
, rtx x
)
110 const char *opname
= "shitop";
111 enum rtx_code code
= GET_CODE (x
);
112 rtx op0
= XEXP (x
, 0);
113 rtx op1
= XEXP (x
, 1);
117 case COMPARE
: opname
= "?"; break;
118 case MINUS
: opname
= "-"; break;
119 case DIV
: opname
= "/"; break;
120 case UDIV
: opname
= "u/"; break;
121 case MOD
: opname
= "%"; break;
122 case UMOD
: opname
= "u%"; break;
123 case ASHIFT
: opname
= "<<"; break;
124 case ASHIFTRT
: opname
= "a>>"; break;
125 case LSHIFTRT
: opname
= "l>>"; break;
127 case PLUS
: opname
= "+"; break;
128 case MULT
: opname
= "*"; break;
129 case AND
: opname
= "&"; break;
130 case IOR
: opname
= "|"; break;
131 case XOR
: opname
= "^"; break;
133 case NE
: opname
= "!="; break;
134 case EQ
: opname
= "=="; break;
135 case LTGT
: opname
= "<>"; break;
137 case GE
: opname
= "s>="; break;
138 case GT
: opname
= "s>"; break;
139 case LE
: opname
= "s<="; break;
140 case LT
: opname
= "s<"; break;
141 case GEU
: opname
= "u>="; break;
142 case GTU
: opname
= "u>"; break;
143 case LEU
: opname
= "u<="; break;
144 case LTU
: opname
= "u<"; break;
147 opname
= GET_RTX_NAME (code
);
153 ra_print_rtx (file
, op0
, 0);
154 fprintf (file
, " %s ", opname
);
155 ra_print_rtx (file
, op1
, 0);
160 fprintf (file
, "%s(", opname
);
161 ra_print_rtx (file
, op0
, 0);
163 ra_print_rtx (file
, op1
, 0);
168 /* Print rtx X, which a three operand rtx to FILE.
169 I.e. X is either an IF_THEN_ELSE, or a bitmap operation. */
172 ra_print_rtx_3op (FILE *file
, rtx x
)
174 enum rtx_code code
= GET_CODE (x
);
175 rtx op0
= XEXP (x
, 0);
176 rtx op1
= XEXP (x
, 1);
177 rtx op2
= XEXP (x
, 2);
178 if (code
== IF_THEN_ELSE
)
180 ra_print_rtx (file
, op0
, 0);
182 ra_print_rtx (file
, op1
, 0);
184 ra_print_rtx (file
, op2
, 0);
188 /* Bitmap-operation */
189 fprintf (file
, "%s:%s(", GET_RTX_NAME (code
),
190 GET_MODE_NAME (GET_MODE (x
)));
191 ra_print_rtx (file
, op0
, 0);
193 ra_print_rtx (file
, op1
, 0);
195 ra_print_rtx (file
, op2
, 0);
200 /* Print rtx X, which represents an object (class 'o', 'C', or some constructs
201 of class 'x' (e.g. subreg)), to FILE.
202 (reg XX) rtl is represented as "pXX", of XX was a pseudo,
203 as "name" it name is the nonnull hardreg name, or as "hXX", if XX
204 is a hardreg, whose name is NULL, or empty. */
207 ra_print_rtx_object (FILE *file
, rtx x
)
209 enum rtx_code code
= GET_CODE (x
);
210 enum machine_mode mode
= GET_MODE (x
);
214 fprintf (file
, HOST_WIDE_INT_PRINT_DEC
, XWINT (x
, 0));
219 const char *fmt
= GET_RTX_FORMAT (code
);
220 fputs ("dbl(", file
);
221 for (i
= 0; i
< GET_RTX_LENGTH (code
); i
++)
225 if (fmt
[i
] == 'e' && XEXP (x
, i
))
226 /* The MEM or other stuff */
228 ra_print_rtx (file
, XEXP (x
, i
), 0);
231 else if (fmt
[i
] == 'w')
233 fprintf (file
, HOST_WIDE_INT_PRINT_HEX
, XWINT (x
, i
));
239 case CONST_STRING
: fprintf (file
, "\"%s\"", XSTR (x
, 0)); break;
240 case CONST
: fputs ("const(", file
);
241 ra_print_rtx (file
, XEXP (x
, 0), 0);
244 case PC
: fputs ("pc", file
); break;
247 int regno
= REGNO (x
);
248 if (regno
< FIRST_PSEUDO_REGISTER
)
250 int i
, nregs
= hard_regno_nregs
[regno
][mode
];
253 for (i
= 0; i
< nregs
; i
++)
257 if (reg_names
[regno
+i
] && *reg_names
[regno
+ i
])
258 fprintf (file
, "%s", reg_names
[regno
+ i
]);
260 fprintf (file
, "h%d", regno
+ i
);
266 fprintf (file
, "p%d", regno
);
271 rtx sub
= SUBREG_REG (x
);
272 int ofs
= SUBREG_BYTE (x
);
274 && REGNO (sub
) < FIRST_PSEUDO_REGISTER
)
276 int regno
= REGNO (sub
);
277 int i
, nregs
= hard_regno_nregs
[regno
][mode
];
278 regno
+= subreg_regno_offset (regno
, GET_MODE (sub
),
282 for (i
= 0; i
< nregs
; i
++)
286 if (reg_names
[regno
+i
])
287 fprintf (file
, "%s", reg_names
[regno
+ i
]);
289 fprintf (file
, "h%d", regno
+ i
);
296 ra_print_rtx (file
, sub
, 0);
297 fprintf (file
, ":[%s+%d]", GET_MODE_NAME (mode
), ofs
);
301 case SCRATCH
: fputs ("scratch", file
); break;
302 case CONCAT
: ra_print_rtx_2op (file
, x
); break;
303 case HIGH
: ra_print_rtx_1op (file
, x
); break;
306 ra_print_rtx (file
, XEXP (x
, 0), 0);
307 fputs (" + lo(", file
);
308 ra_print_rtx (file
, XEXP (x
, 1), 0);
311 case MEM
: fputs ("[", file
);
312 ra_print_rtx (file
, XEXP (x
, 0), 0);
313 fprintf (file
, "]:%s", GET_MODE_NAME (GET_MODE (x
)));
314 /* XXX print alias set too ?? */
318 rtx sub
= XEXP (x
, 0);
320 && NOTE_LINE_NUMBER (sub
) == NOTE_INSN_DELETED_LABEL
)
321 fprintf (file
, "(deleted uid=%d)", INSN_UID (sub
));
322 else if (LABEL_P (sub
))
323 fprintf (file
, "L%d", CODE_LABEL_NUMBER (sub
));
325 fprintf (file
, "(nonlabel uid=%d)", INSN_UID (sub
));
329 fprintf (file
, "sym(\"%s\")", XSTR (x
, 0)); break;
330 case CC0
: fputs ("cc0", file
); break;
331 default: print_inline_rtx (file
, x
, 0); break;
335 /* Print a general rtx X to FILE in nice infix form.
336 If WITH_PN is set, and X is one of the toplevel constructs
337 (insns, notes, labels or barriers), then print also the UIDs of
338 the preceding and following insn. */
341 ra_print_rtx (FILE *file
, rtx x
, int with_pn
)
349 /* First handle the insn like constructs. */
350 if (INSN_P (x
) || code
== NOTE
|| code
== CODE_LABEL
|| code
== BARRIER
)
354 /* Non-insns are prefixed by a ';'. */
357 else if (code
== NOTE
)
358 /* But notes are indented very far right. */
359 fprintf (file
, "\t\t\t\t\t; ");
360 else if (code
== CODE_LABEL
)
361 /* And labels have their Lxx name first, before the actual UID. */
363 fprintf (file
, "L%d:\t; ", CODE_LABEL_NUMBER (x
));
365 fprintf (file
, "(%s) ", LABEL_NAME (x
));
366 switch (LABEL_KIND (x
))
368 case LABEL_NORMAL
: break;
369 case LABEL_STATIC_ENTRY
: fputs (" (entry)", file
); break;
370 case LABEL_GLOBAL_ENTRY
: fputs (" (global entry)", file
); break;
371 case LABEL_WEAK_ENTRY
: fputs (" (weak entry)", file
); break;
374 fprintf (file
, " [%d uses] uid=(", LABEL_NUSES (x
));
376 fprintf (file
, "%d", INSN_UID (x
));
378 fprintf (file
, " %d %d", PREV_INSN (x
) ? INSN_UID (PREV_INSN (x
)) : 0,
379 NEXT_INSN (x
) ? INSN_UID (NEXT_INSN (x
)) : 0);
381 fputs (" -------- barrier ---------", file
);
382 else if (code
== CODE_LABEL
)
384 else if (code
== NOTE
)
386 int ln
= NOTE_LINE_NUMBER (x
);
387 if (ln
>= (int) NOTE_INSN_BIAS
&& ln
< (int) NOTE_INSN_MAX
)
388 fprintf (file
, " %s", GET_NOTE_INSN_NAME (ln
));
392 NOTE_EXPANDED_LOCATION (s
, x
);
393 fprintf (file
, " line %d", s
.line
);
395 fprintf (file
, ":%s", s
.file
);
400 fprintf (file
, "\t");
401 ra_print_rtx (file
, PATTERN (x
), 0);
407 /* Top-level stuff. */
411 for (j
= 0; j
< XVECLEN (x
, 0); j
++)
414 fputs ("\t;; ", file
);
415 ra_print_rtx (file
, XVECEXP (x
, 0, j
), 0);
419 case UNSPEC
: case UNSPEC_VOLATILE
:
422 fprintf (file
, "unspec%s(%d",
423 (code
== UNSPEC
) ? "" : "_vol", XINT (x
, 1));
424 for (j
= 0; j
< XVECLEN (x
, 0); j
++)
427 ra_print_rtx (file
, XVECEXP (x
, 0, j
), 0);
433 if (GET_CODE (SET_DEST (x
)) == PC
)
435 if (GET_CODE (SET_SRC (x
)) == IF_THEN_ELSE
436 && GET_CODE (XEXP (SET_SRC(x
), 2)) == PC
)
439 ra_print_rtx (file
, XEXP (SET_SRC (x
), 0), 0);
440 fputs (" jump ", file
);
441 ra_print_rtx (file
, XEXP (SET_SRC (x
), 1), 0);
445 fputs ("jump ", file
);
446 ra_print_rtx (file
, SET_SRC (x
), 0);
451 ra_print_rtx (file
, SET_DEST (x
), 0);
452 fputs (" <= ", file
);
453 ra_print_rtx (file
, SET_SRC (x
), 0);
457 fputs ("use <= ", file
);
458 ra_print_rtx (file
, XEXP (x
, 0), 0);
461 ra_print_rtx (file
, XEXP (x
, 0), 0);
462 fputs (" <= clobber", file
);
465 fputs ("call ", file
);
466 ra_print_rtx (file
, XEXP (x
, 0), 0); /* Address */
467 fputs (" numargs=", file
);
468 ra_print_rtx (file
, XEXP (x
, 1), 0); /* Num arguments */
471 fputs ("return", file
);
474 fputs ("if (", file
);
475 ra_print_rtx (file
, XEXP (x
, 0), 0);
476 fputs (") trap ", file
);
477 ra_print_rtx (file
, XEXP (x
, 1), 0);
480 fprintf (file
, "resx from region %d", XINT (x
, 0));
483 /* Different things of class 'x' */
484 case SUBREG
: ra_print_rtx_object (file
, x
); break;
485 case STRICT_LOW_PART
:
486 fputs ("low(", file
);
487 ra_print_rtx (file
, XEXP (x
, 0), 0);
496 switch (GET_RTX_CLASS (code
))
499 ra_print_rtx_1op (file
, x
);
504 case RTX_COMM_COMPARE
:
505 ra_print_rtx_2op (file
, x
);
508 case RTX_BITFIELD_OPS
:
509 ra_print_rtx_3op (file
, x
);
513 ra_print_rtx_object (file
, x
);
516 print_inline_rtx (file
, x
, 0);
521 /* This only calls ra_print_rtx(), but emits a final newline. */
524 ra_print_rtx_top (FILE *file
, rtx x
, int with_pn
)
526 ra_print_rtx (file
, x
, with_pn
);
527 fprintf (file
, "\n");
530 /* 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. */
542 ra_debug_bbi (int bbi
)
544 basic_block bb
= BASIC_BLOCK (bbi
);
546 for (insn
= BB_HEAD (bb
); insn
; insn
= NEXT_INSN (insn
))
548 ra_print_rtx_top (stderr
, insn
,
549 (insn
== BB_HEAD (bb
) || insn
== BB_END (bb
)));
550 fprintf (stderr
, "\n");
551 if (insn
== BB_END (bb
))
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 (rtx insn
, int num
)
562 int i
, count
= (num
== 0 ? 1 : num
< 0 ? -num
: num
);
564 for (i
= count
/ 2; i
> 0 && PREV_INSN (insn
); i
--)
565 insn
= PREV_INSN (insn
);
566 for (i
= count
; i
> 0 && insn
; insn
= NEXT_INSN (insn
), i
--)
569 fprintf (stderr
, "\n");
570 ra_print_rtx_top (stderr
, insn
, (i
== count
|| i
== 1));
574 /* Beginning with INSN, emit the whole insn chain into FILE.
575 This also outputs comments when basic blocks start or end and omits
576 some notes, if flag_ra_dump_notes is zero. */
579 ra_print_rtl_with_bb (FILE *file
, rtx insn
)
581 basic_block last_bb
, bb
;
582 unsigned int num
= 0;
586 for (; insn
; insn
= NEXT_INSN (insn
))
588 if (BARRIER_P (insn
))
591 bb
= BLOCK_FOR_INSN (insn
);
595 fprintf (file
, ";; End of basic block %d\n", last_bb
->index
);
597 fprintf (file
, ";; Begin of basic block %d\n", bb
->index
);
604 /* Ignore basic block and maybe other notes not referencing
606 if (NOTE_LINE_NUMBER (insn
) != NOTE_INSN_BASIC_BLOCK
607 && (flag_ra_dump_notes
608 || NOTE_LINE_NUMBER (insn
) == NOTE_INSN_DELETED
609 || NOTE_LINE_NUMBER (insn
) == NOTE_INSN_DELETED_LABEL
))
611 ra_print_rtx_top (file
, insn
, (num
== 0 || !NEXT_INSN (insn
)));
617 ra_print_rtx_top (file
, insn
, (num
== 0 || !NEXT_INSN (insn
)));
623 /* Count how many insns were seen how often, while building the interference
624 graph, and prints the findings. */
627 dump_number_seen (void)
633 for (i
= 0; i
< N
; i
++)
635 for (i
= 0; i
< get_max_uid (); i
++)
636 if (number_seen
[i
] < N
- 1)
637 num
[number_seen
[i
]]++;
640 for (i
= 0; i
< N
- 1; i
++)
642 ra_debug_msg (DUMP_PROCESS
, "%d insns seen %d times\n", num
[i
], i
);
644 ra_debug_msg (DUMP_PROCESS
, "%d insns seen %d and more times\n", num
[i
],
646 ra_debug_msg (DUMP_PROCESS
, "from overall %d insns\n", get_max_uid ());
650 /* Dump the interference graph, the move list and the webs. */
653 dump_igraph (struct df
*df ATTRIBUTE_UNUSED
)
655 struct move_list
*ml
;
656 unsigned int def1
, def2
;
660 if (!dump_file
|| (debug_new_regalloc
& (DUMP_IGRAPH
| DUMP_WEBS
)) == 0)
662 ra_debug_msg (DUMP_IGRAPH
, "conflicts:\n ");
663 for (def1
= 0; def1
< num_webs
; def1
++)
667 for (def2
= 0; def2
< num_webs
; def2
++)
668 if (def1
!= def2
&& TEST_BIT (igraph
, igraph_index (def1
, def2
)))
672 if (SUBWEB_P (ID2WEB (def1
)))
673 ra_debug_msg (DUMP_IGRAPH
, "%d (SUBREG %d, %d) with ", def1
,
674 ID2WEB (def1
)->regno
,
675 SUBREG_BYTE (ID2WEB (def1
)->orig_x
));
677 ra_debug_msg (DUMP_IGRAPH
, "%d (REG %d) with ", def1
,
678 ID2WEB (def1
)->regno
);
681 ra_debug_msg (DUMP_IGRAPH
, "\n ");
684 if (SUBWEB_P (ID2WEB (def2
)))
685 ra_debug_msg (DUMP_IGRAPH
, "%d(%d,%d) ", def2
, ID2WEB (def2
)->regno
,
686 SUBREG_BYTE (ID2WEB (def2
)->orig_x
));
688 ra_debug_msg (DUMP_IGRAPH
, "%d(%d) ", def2
, ID2WEB (def2
)->regno
);
691 ra_debug_msg (DUMP_IGRAPH
, "\n ");
693 ra_debug_msg (DUMP_IGRAPH
, "\n");
694 for (ml
= wl_moves
; ml
; ml
= ml
->next
)
697 ra_debug_msg (DUMP_IGRAPH
, "move: insn %d: Web %d <-- Web %d\n",
698 INSN_UID (ml
->move
->insn
), ml
->move
->target_web
->id
,
699 ml
->move
->source_web
->id
);
701 ra_debug_msg (DUMP_WEBS
, "\nWebs:\n");
702 for (i
= 0; i
< num_webs
; i
++)
704 struct web
*web
= ID2WEB (i
);
706 ra_debug_msg (DUMP_WEBS
, " %4d : regno %3d", i
, web
->regno
);
709 ra_debug_msg (DUMP_WEBS
, " sub %d", SUBREG_BYTE (web
->orig_x
));
710 ra_debug_msg (DUMP_WEBS
, " par %d", find_web_for_subweb (web
)->id
);
712 ra_debug_msg (DUMP_WEBS
, " +%d (span %d, cost "
713 HOST_WIDE_INT_PRINT_DEC
") (%s)",
714 web
->add_hardregs
, web
->span_deaths
, web
->spill_cost
,
715 reg_class_names
[web
->regclass
]);
716 if (web
->spill_temp
== 1)
717 ra_debug_msg (DUMP_WEBS
, " (spilltemp)");
718 else if (web
->spill_temp
== 2)
719 ra_debug_msg (DUMP_WEBS
, " (spilltem2)");
720 else if (web
->spill_temp
== 3)
721 ra_debug_msg (DUMP_WEBS
, " (short)");
722 if (web
->type
== PRECOLORED
)
723 ra_debug_msg (DUMP_WEBS
, " (precolored, color=%d)", web
->color
);
724 else if (find_web_for_subweb (web
)->num_uses
== 0)
725 ra_debug_msg (DUMP_WEBS
, " dead");
726 if (web
->crosses_call
)
727 ra_debug_msg (DUMP_WEBS
, " xcall");
728 if (web
->regno
>= max_normal_pseudo
)
729 ra_debug_msg (DUMP_WEBS
, " stack");
730 ra_debug_msg (DUMP_WEBS
, "\n");
734 /* Dump the interference graph and webs in a format easily
735 parsable by programs. Used to emit real world interference graph
736 to my custom graph colorizer. */
739 dump_igraph_machine (void)
743 if (!dump_file
|| (debug_new_regalloc
& DUMP_IGRAPH_M
) == 0)
745 ra_debug_msg (DUMP_IGRAPH_M
, "g %d %d\n", num_webs
- num_subwebs
,
746 FIRST_PSEUDO_REGISTER
);
747 for (i
= 0; i
< num_webs
- num_subwebs
; i
++)
749 struct web
*web
= ID2WEB (i
);
750 struct conflict_link
*cl
;
754 flags
= web
->spill_temp
& 0xF;
755 flags
|= ((web
->type
== PRECOLORED
) ? 1 : 0) << 4;
756 flags
|= (web
->add_hardregs
& 0xF) << 5;
757 for (cl
= web
->conflict_list
; cl
; cl
= cl
->next
)
758 if (cl
->t
->id
< web
->id
)
760 ra_debug_msg (DUMP_IGRAPH_M
, "n %d %d %d %d %d %d %d\n",
761 web
->id
, web
->color
, flags
,
762 (unsigned int)web
->spill_cost
, web
->num_defs
, web
->num_uses
,
764 if (web
->type
!= PRECOLORED
)
766 ra_debug_msg (DUMP_IGRAPH_M
, "s %d", web
->id
);
771 for (n
= 0; n
< 32 && col
< FIRST_PSEUDO_REGISTER
; n
++, col
++)
772 if (TEST_HARD_REG_BIT (web
->usable_regs
, col
))
774 ra_debug_msg (DUMP_IGRAPH_M
, " %u", u
);
775 if (col
>= FIRST_PSEUDO_REGISTER
)
778 ra_debug_msg (DUMP_IGRAPH_M
, "\n");
782 ra_debug_msg (DUMP_IGRAPH_M
, "c %d", web
->id
);
783 for (cl
= web
->conflict_list
; cl
; cl
= cl
->next
)
785 if (cl
->t
->id
< web
->id
)
786 ra_debug_msg (DUMP_IGRAPH_M
, " %d", cl
->t
->id
);
788 ra_debug_msg (DUMP_IGRAPH_M
, "\n");
791 ra_debug_msg (DUMP_IGRAPH_M
, "e\n");
794 /* This runs after colorization and changing the insn stream.
795 It temporarily replaces all pseudo registers with their colors,
796 and emits information, if the resulting insns are strictly valid. */
799 dump_constraints (void)
803 if (!dump_file
|| (debug_new_regalloc
& DUMP_CONSTRAINTS
) == 0)
805 for (i
= FIRST_PSEUDO_REGISTER
; i
< ra_max_regno
; i
++)
806 if (regno_reg_rtx
[i
] && REG_P (regno_reg_rtx
[i
]))
807 REGNO (regno_reg_rtx
[i
])
808 = ra_reg_renumber
[i
] >= 0 ? ra_reg_renumber
[i
] : i
;
809 for (insn
= get_insns (); insn
; insn
= NEXT_INSN (insn
))
813 int uid
= INSN_UID (insn
);
815 /* Don't simply force rerecognition, as combine might left us
816 with some unrecognizable ones, which later leads to aborts
817 in regclass, if we now destroy the remembered INSN_CODE(). */
818 /*INSN_CODE (insn) = -1;*/
819 code
= recog_memoized (insn
);
822 ra_debug_msg (DUMP_CONSTRAINTS
,
823 "%d: asm insn or not recognizable.\n", uid
);
826 ra_debug_msg (DUMP_CONSTRAINTS
,
827 "%d: code %d {%s}, %d operands, constraints: ",
828 uid
, code
, insn_data
[code
].name
, recog_data
.n_operands
);
830 /*preprocess_constraints ();*/
831 for (o
= 0; o
< recog_data
.n_operands
; o
++)
833 ra_debug_msg (DUMP_CONSTRAINTS
,
834 "%d:%s ", o
, recog_data
.constraints
[o
]);
836 if (constrain_operands (1))
837 ra_debug_msg (DUMP_CONSTRAINTS
, "matches strictly alternative %d",
840 ra_debug_msg (DUMP_CONSTRAINTS
, "doesn't match strictly");
841 ra_debug_msg (DUMP_CONSTRAINTS
, "\n");
843 for (i
= FIRST_PSEUDO_REGISTER
; i
< ra_max_regno
; i
++)
844 if (regno_reg_rtx
[i
] && REG_P (regno_reg_rtx
[i
]))
845 REGNO (regno_reg_rtx
[i
]) = i
;
848 /* This counts and emits the cumulated cost of all spilled webs,
849 preceded by a custom message MSG, with debug level LEVEL. */
852 dump_graph_cost (unsigned int level
, const char *msg
)
855 unsigned HOST_WIDE_INT cost
;
856 if (!dump_file
|| (debug_new_regalloc
& level
) == 0)
860 for (i
= 0; i
< num_webs
; i
++)
862 struct web
*web
= id2web
[i
];
863 if (alias (web
)->type
== SPILLED
)
864 cost
+= web
->orig_spill_cost
;
866 ra_debug_msg (level
, " spill cost of graph (%s) = "
867 HOST_WIDE_INT_PRINT_UNSIGNED
"\n",
868 msg
? msg
: "", cost
);
871 /* Dump the color assignment per web, the coalesced and spilled webs. */
874 dump_ra (struct df
*df ATTRIBUTE_UNUSED
)
878 if (!dump_file
|| (debug_new_regalloc
& DUMP_RESULTS
) == 0)
881 ra_debug_msg (DUMP_RESULTS
, "\nColored:\n");
882 for (d
= WEBS(COLORED
); d
; d
= d
->next
)
885 ra_debug_msg (DUMP_RESULTS
, " %4d : color %d\n", web
->id
, web
->color
);
887 ra_debug_msg (DUMP_RESULTS
, "\nCoalesced:\n");
888 for (d
= WEBS(COALESCED
); d
; d
= d
->next
)
891 ra_debug_msg (DUMP_RESULTS
, " %4d : to web %d, color %d\n", web
->id
,
892 alias (web
)->id
, web
->color
);
894 ra_debug_msg (DUMP_RESULTS
, "\nSpilled:\n");
895 for (d
= WEBS(SPILLED
); d
; d
= d
->next
)
898 ra_debug_msg (DUMP_RESULTS
, " %4d\n", web
->id
);
900 ra_debug_msg (DUMP_RESULTS
, "\n");
901 dump_cost (DUMP_RESULTS
);
904 /* Calculate and dump the cumulated costs of certain types of insns
905 (loads, stores and copies). */
908 dump_static_insn_cost (FILE *file
, const char *message
, const char *prefix
)
912 unsigned HOST_WIDE_INT cost
;
916 struct cost load
, store
, regcopy
, selfcopy
, overall
;
917 memset (&load
, 0, sizeof(load
));
918 memset (&store
, 0, sizeof(store
));
919 memset (®copy
, 0, sizeof(regcopy
));
920 memset (&selfcopy
, 0, sizeof(selfcopy
));
921 memset (&overall
, 0, sizeof(overall
));
928 unsigned HOST_WIDE_INT block_cost
= bb
->frequency
;
930 for (insn
= BB_HEAD (bb
); insn
; insn
= NEXT_INSN (insn
))
932 /* Yes, yes. We don't calculate the costs precisely.
933 Only for "simple enough" insns. Those containing single
935 if (INSN_P (insn
) && ((set
= single_set (insn
)) != NULL
))
937 rtx src
= SET_SRC (set
);
938 rtx dest
= SET_DEST (set
);
939 struct cost
*pcost
= NULL
;
940 overall
.cost
+= block_cost
;
942 if (rtx_equal_p (src
, dest
))
944 else if (GET_CODE (src
) == GET_CODE (dest
)
946 || (GET_CODE (src
) == SUBREG
947 && REG_P (SUBREG_REG (src
))
948 && REG_P (SUBREG_REG (dest
)))))
949 /* XXX is dest guaranteed to be a subreg? */
953 if (GET_CODE (src
) == SUBREG
)
954 src
= SUBREG_REG (src
);
955 if (GET_CODE (dest
) == SUBREG
)
956 dest
= SUBREG_REG (dest
);
957 if (MEM_P (src
) && !MEM_P (dest
)
958 && memref_is_stack_slot (src
))
960 else if (!MEM_P (src
) && MEM_P (dest
)
961 && memref_is_stack_slot (dest
))
966 pcost
->cost
+= block_cost
;
970 if (insn
== BB_END (bb
))
977 fprintf (file
, "static insn cost %s\n", message
? message
: "");
978 fprintf (file
, " %soverall:\tnum=%6d\tcost=% 8" HOST_WIDE_INT_PRINT
"d\n",
979 prefix
, overall
.count
, overall
.cost
);
980 fprintf (file
, " %sloads:\tnum=%6d\tcost=% 8" HOST_WIDE_INT_PRINT
"d\n",
981 prefix
, load
.count
, load
.cost
);
982 fprintf (file
, " %sstores:\tnum=%6d\tcost=% 8" HOST_WIDE_INT_PRINT
"d\n",
983 prefix
, store
.count
, store
.cost
);
984 fprintf (file
, " %sregcopy:\tnum=%6d\tcost=% 8" HOST_WIDE_INT_PRINT
"d\n",
985 prefix
, regcopy
.count
, regcopy
.cost
);
986 fprintf (file
, " %sselfcpy:\tnum=%6d\tcost=% 8" HOST_WIDE_INT_PRINT
"d\n",
987 prefix
, selfcopy
.count
, selfcopy
.cost
);
990 /* Returns nonzero, if WEB1 and WEB2 have some possible
991 hardregs in common. */
994 web_conflicts_p (struct web
*web1
, struct web
*web2
)
996 if (web1
->type
== PRECOLORED
&& web2
->type
== PRECOLORED
)
999 if (web1
->type
== PRECOLORED
)
1000 return TEST_HARD_REG_BIT (web2
->usable_regs
, web1
->regno
);
1002 if (web2
->type
== PRECOLORED
)
1003 return TEST_HARD_REG_BIT (web1
->usable_regs
, web2
->regno
);
1005 return hard_regs_intersect_p (&web1
->usable_regs
, &web2
->usable_regs
);
1008 /* Dump all uids of insns in which WEB is mentioned. */
1011 dump_web_insns (struct web
*web
)
1015 ra_debug_msg (DUMP_EVER
, "Web: %i(%i)+%i class: %s freedom: %i degree %i\n",
1016 web
->id
, web
->regno
, web
->add_hardregs
,
1017 reg_class_names
[web
->regclass
],
1018 web
->num_freedom
, web
->num_conflicts
);
1019 ra_debug_msg (DUMP_EVER
, " def insns:");
1021 for (i
= 0; i
< web
->num_defs
; ++i
)
1023 ra_debug_msg (DUMP_EVER
, " %d ", INSN_UID (web
->defs
[i
]->insn
));
1026 ra_debug_msg (DUMP_EVER
, "\n use insns:");
1027 for (i
= 0; i
< web
->num_uses
; ++i
)
1029 ra_debug_msg (DUMP_EVER
, " %d ", INSN_UID (web
->uses
[i
]->insn
));
1031 ra_debug_msg (DUMP_EVER
, "\n");
1034 /* Dump conflicts for web WEB. */
1037 dump_web_conflicts (struct web
*web
)
1042 ra_debug_msg (DUMP_EVER
, "Web: %i(%i)+%i class: %s freedom: %i degree %i\n",
1043 web
->id
, web
->regno
, web
->add_hardregs
,
1044 reg_class_names
[web
->regclass
],
1045 web
->num_freedom
, web
->num_conflicts
);
1047 for (def2
= 0; def2
< num_webs
; def2
++)
1048 if (TEST_BIT (igraph
, igraph_index (web
->id
, def2
)) && web
->id
!= def2
)
1051 ra_debug_msg (DUMP_EVER
, "\n ");
1054 ra_debug_msg (DUMP_EVER
, " %d(%d)", def2
, id2web
[def2
]->regno
);
1055 if (id2web
[def2
]->add_hardregs
)
1056 ra_debug_msg (DUMP_EVER
, "+%d", id2web
[def2
]->add_hardregs
);
1058 if (web_conflicts_p (web
, id2web
[def2
]))
1059 ra_debug_msg (DUMP_EVER
, "/x");
1061 if (id2web
[def2
]->type
== SELECT
)
1062 ra_debug_msg (DUMP_EVER
, "/s");
1064 if (id2web
[def2
]->type
== COALESCED
)
1065 ra_debug_msg (DUMP_EVER
,"/c/%d", alias (id2web
[def2
])->id
);
1067 ra_debug_msg (DUMP_EVER
, "\n");
1069 struct conflict_link
*wl
;
1071 ra_debug_msg (DUMP_EVER
, "By conflicts: ");
1072 for (wl
= web
->conflict_list
; wl
; wl
= wl
->next
)
1074 struct web
* w
= wl
->t
;
1076 ra_debug_msg (DUMP_EVER
, "\n ");
1078 ra_debug_msg (DUMP_EVER
, "%d(%d)%s ", w
->id
, w
->regno
,
1079 web_conflicts_p (web
, w
) ? "+" : "");
1081 ra_debug_msg (DUMP_EVER
, "\n");
1085 /* Output HARD_REG_SET to stderr. */
1088 debug_hard_reg_set (HARD_REG_SET set
)
1091 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; ++i
)
1093 if (TEST_HARD_REG_BIT (set
, i
))
1095 fprintf (stderr
, "%s ", reg_names
[i
]);
1098 fprintf (stderr
, "\n");
1102 vim:cinoptions={.5s,g0,p5,t0,(0,^-0.5s,n-0.5s:tw=78:cindent:sw=4: