OSDN Git Service

* config.gcc (m68020-*-elf*, m68k-*-elf*, m68010-*-netbsdelf*,
[pf3gnuchains/gcc-fork.git] / gcc / ra-debug.c
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>.
5
6    This file is part of GCC.
7
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.
11
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
15    details.
16
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.  */
20
21 #include "config.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include "tm.h"
25 #include "rtl.h"
26 #include "insn-config.h"
27 #include "recog.h"
28 #include "function.h"
29 #include "hard-reg-set.h"
30 #include "basic-block.h"
31 #include "df.h"
32 #include "output.h"
33 #include "ra.h"
34 #include "tm_p.h"
35
36 /* This file contains various dumping and debug functions for
37    the graph coloring register allocator.  */
38
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);
43
44 /* The hardregs as names, for debugging.  */
45 static const char *const reg_class_names[] = REG_CLASS_NAMES;
46
47 /* Print a message to the dump file, if debug_new_regalloc and LEVEL
48    have any bits in common.  */
49
50 void
51 ra_debug_msg (unsigned int level, const char *format, ...)
52 {
53   va_list ap;
54   
55   va_start (ap, format);
56   if ((debug_new_regalloc & level) != 0 && rtl_dump_file != NULL)
57     vfprintf (rtl_dump_file, format, ap);
58   va_end (ap);
59 }
60
61
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.  */
68
69 /* Print rtx X, which is a one operand rtx (op:mode (Y)), as
70    "op(Y)" to FILE.  */
71
72 static void
73 ra_print_rtx_1op (FILE *file, rtx x)
74 {
75   enum rtx_code code = GET_CODE (x);
76   rtx op0 = XEXP (x, 0);
77   switch (code)
78     {
79       case NEG:
80       case NOT:
81           fputs ((code == NEG) ? "-(" : "~(", file);
82           ra_print_rtx (file, op0, 0);
83           fputs (")", file);
84           break;
85       case HIGH:
86           fputs ("hi(", file);
87           ra_print_rtx (file, op0, 0);
88           fputs (")", file);
89           break;
90       default:
91           fprintf (file, "%s", GET_RTX_NAME (code));
92           if (GET_MODE (x) != VOIDmode)
93             fprintf (file, ":%s(", GET_MODE_NAME (GET_MODE (x)));
94           else
95             fputs ("(", file);
96           ra_print_rtx (file, op0, 0);
97           fputs (")", file);
98           break;
99     }
100 }
101
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,
104    to FILE.  */
105
106 static void
107 ra_print_rtx_2op (FILE *file, rtx x)
108 {
109   int infix = 1;
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);
114   switch (code)
115     {
116       /* class '2' */
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;
126       /* class 'c' */
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;
132       /* class '<' */
133       case NE: opname = "!="; break;
134       case EQ: opname = "=="; break;
135       case GE: opname = "s>="; break;
136       case GT: opname = "s>"; break;
137       case LE: opname = "s<="; break;
138       case LT: opname = "s<"; break;
139       case GEU: opname = "u>="; break;
140       case GTU: opname = "u>"; break;
141       case LEU: opname = "u<="; break;
142       case LTU: opname = "u<"; break;
143       default:
144                 infix = 0;
145                 opname = GET_RTX_NAME (code);
146                 break;
147     }
148   if (infix)
149     {
150       fputs ("(", file);
151       ra_print_rtx (file, op0, 0);
152       fprintf (file, " %s ", opname);
153       ra_print_rtx (file, op1, 0);
154       fputs (")", file);
155     }
156   else
157     {
158       fprintf (file, "%s(", opname);
159       ra_print_rtx (file, op0, 0);
160       fputs (", ", file);
161       ra_print_rtx (file, op1, 0);
162       fputs (")", file);
163     }
164 }
165
166 /* Print rtx X, which a three operand rtx to FILE.
167    I.e. X is either an IF_THEN_ELSE, or a bitmap operation.  */
168
169 static void
170 ra_print_rtx_3op (FILE *file, rtx x)
171 {
172   enum rtx_code code = GET_CODE (x);
173   rtx op0 = XEXP (x, 0);
174   rtx op1 = XEXP (x, 1);
175   rtx op2 = XEXP (x, 2);
176   if (code == IF_THEN_ELSE)
177     {
178       ra_print_rtx (file, op0, 0);
179       fputs (" ? ", file);
180       ra_print_rtx (file, op1, 0);
181       fputs (" : ", file);
182       ra_print_rtx (file, op2, 0);
183     }
184   else
185     {
186       /* Bitmap-operation */
187       fprintf (file, "%s:%s(", GET_RTX_NAME (code),
188                GET_MODE_NAME (GET_MODE (x)));
189       ra_print_rtx (file, op0, 0);
190       fputs (", ", file);
191       ra_print_rtx (file, op1, 0);
192       fputs (", ", file);
193       ra_print_rtx (file, op2, 0);
194       fputs (")", file);
195     }
196 }
197
198 /* Print rtx X, which represents an object (class 'o' or some constructs
199    of class 'x' (e.g. subreg)), to FILE.
200    (reg XX) rtl is represented as "pXX", of XX was a pseudo,
201    as "name" it name is the nonnull hardreg name, or as "hXX", if XX
202    is a hardreg, whose name is NULL, or empty.  */
203
204 static void
205 ra_print_rtx_object (FILE *file, rtx x)
206 {
207   enum rtx_code code = GET_CODE (x);
208   enum machine_mode mode = GET_MODE (x);
209   switch (code)
210     {
211       case CONST_INT:
212           fprintf (file, HOST_WIDE_INT_PRINT_DEC, XWINT (x, 0));
213           break;
214       case CONST_DOUBLE:
215             {
216               int i, num = 0;
217               const char *fmt = GET_RTX_FORMAT (code);
218               fputs ("dbl(", file);
219               for (i = 0; i < GET_RTX_LENGTH (code); i++)
220                 {
221                   if (num)
222                     fputs (", ", file);
223                   if (fmt[i] == 'e' && XEXP (x, i))
224                     /* The MEM or other stuff */
225                     {
226                       ra_print_rtx (file, XEXP (x, i), 0);
227                       num++;
228                     }
229                   else if (fmt[i] == 'w')
230                     {
231                       fprintf (file, HOST_WIDE_INT_PRINT_HEX, XWINT (x, i));
232                       num++;
233                     }
234                 }
235               break;
236             }
237       case CONST_STRING: fprintf (file, "\"%s\"", XSTR (x, 0)); break;
238       case CONST: fputs ("const(", file);
239                   ra_print_rtx (file, XEXP (x, 0), 0);
240                   fputs (")", file);
241                   break;
242       case PC: fputs ("pc", file); break;
243       case REG:
244                {
245                  int regno = REGNO (x);
246                  if (regno < FIRST_PSEUDO_REGISTER)
247                    {
248                      int i, nregs = HARD_REGNO_NREGS (regno, mode);
249                      if (nregs > 1)
250                        fputs ("[", file);
251                      for (i = 0; i < nregs; i++)
252                        {
253                          if (i)
254                            fputs (", ", file);
255                          if (reg_names[regno+i] && *reg_names[regno + i])
256                            fprintf (file, "%s", reg_names[regno + i]);
257                          else
258                            fprintf (file, "h%d", regno + i);
259                        }
260                      if (nregs > 1)
261                        fputs ("]", file);
262                    }
263                  else
264                    fprintf (file, "p%d", regno);
265                  break;
266                }
267       case SUBREG:
268                {
269                  rtx sub = SUBREG_REG (x);
270                  int ofs = SUBREG_BYTE (x);
271                  if (GET_CODE (sub) == REG
272                      && REGNO (sub) < FIRST_PSEUDO_REGISTER)
273                    {
274                      int regno = REGNO (sub);
275                      int i, nregs = HARD_REGNO_NREGS (regno, mode);
276                      regno += subreg_regno_offset (regno, GET_MODE (sub),
277                                                    ofs, mode);
278                      if (nregs > 1)
279                        fputs ("[", file);
280                      for (i = 0; i < nregs; i++)
281                        {
282                          if (i)
283                            fputs (", ", file);
284                          if (reg_names[regno+i])
285                            fprintf (file, "%s", reg_names[regno + i]);
286                          else
287                            fprintf (file, "h%d", regno + i);
288                        }
289                      if (nregs > 1)
290                        fputs ("]", file);
291                    }
292                  else
293                    {
294                      ra_print_rtx (file, sub, 0);
295                      fprintf (file, ":[%s+%d]", GET_MODE_NAME (mode), ofs);
296                    }
297                  break;
298                }
299       case SCRATCH: fputs ("scratch", file); break;
300       case CONCAT: ra_print_rtx_2op (file, x); break;
301       case HIGH: ra_print_rtx_1op (file, x); break;
302       case LO_SUM:
303                  fputs ("(", file);
304                  ra_print_rtx (file, XEXP (x, 0), 0);
305                  fputs (" + lo(", file);
306                  ra_print_rtx (file, XEXP (x, 1), 0);
307                  fputs ("))", file);
308                  break;
309       case MEM: fputs ("[", file);
310                 ra_print_rtx (file, XEXP (x, 0), 0);
311                 fprintf (file, "]:%s", GET_MODE_NAME (GET_MODE (x)));
312                 /* XXX print alias set too ?? */
313                 break;
314       case LABEL_REF:
315                   {
316                     rtx sub = XEXP (x, 0);
317                     if (GET_CODE (sub) == NOTE
318                         && NOTE_LINE_NUMBER (sub) == NOTE_INSN_DELETED_LABEL)
319                       fprintf (file, "(deleted uid=%d)", INSN_UID (sub));
320                     else if (GET_CODE (sub) == CODE_LABEL)
321                       fprintf (file, "L%d", CODE_LABEL_NUMBER (sub));
322                     else
323                       fprintf (file, "(nonlabel uid=%d)", INSN_UID (sub));
324                   }
325                 break;
326       case SYMBOL_REF:
327                 fprintf (file, "sym(\"%s\")", XSTR (x, 0)); break;
328       case CC0: fputs ("cc0", file); break;
329       default: print_inline_rtx (file, x, 0); break;
330     }
331 }
332
333 /* Print a general rtx X to FILE in nice infix form.
334    If WITH_PN is set, and X is one of the toplevel constructs
335    (insns, notes, labels or barriers), then print also the UIDs of
336    the preceding and following insn.  */
337
338 void
339 ra_print_rtx (FILE *file, rtx x, int with_pn)
340 {
341   enum rtx_code code;
342   char class;
343   int unhandled = 0;
344   if (!x)
345     return;
346   code = GET_CODE (x);
347   class = GET_RTX_CLASS (code);
348
349   /* First handle the insn like constructs.  */
350   if (INSN_P (x) || code == NOTE || code == CODE_LABEL || code == BARRIER)
351     {
352       if (INSN_P (x))
353         fputs ("  ", file);
354       /* Non-insns are prefixed by a ';'.  */
355       if (code == BARRIER)
356         fputs ("; ", file);
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.  */
362         {
363           fprintf (file, "L%d:\t; ", CODE_LABEL_NUMBER (x));
364           if (LABEL_NAME (x))
365             fprintf (file, "(%s) ", LABEL_NAME (x));
366           switch (LABEL_KIND (x))
367             {
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;
372             default: abort();
373             }
374           fprintf (file, " [%d uses] uid=(", LABEL_NUSES (x));
375         }
376       fprintf (file, "%d", INSN_UID (x));
377       if (with_pn)
378         fprintf (file, " %d %d", PREV_INSN (x) ? INSN_UID (PREV_INSN (x)) : 0,
379                  NEXT_INSN (x) ? INSN_UID (NEXT_INSN (x)) : 0);
380       if (code == BARRIER)
381         fputs (" -------- barrier ---------", file);
382       else if (code == CODE_LABEL)
383         fputs (")", file);
384       else if (code == NOTE)
385         {
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));
389           else
390             {
391               fprintf (file, " line %d", ln);
392               if (NOTE_SOURCE_FILE (x))
393                 fprintf (file, ":%s", NOTE_SOURCE_FILE (x));
394             }
395         }
396       else
397         {
398           fprintf (file, "\t");
399           ra_print_rtx (file, PATTERN (x), 0);
400         }
401       return;
402     }
403   switch (code)
404     {
405       /* Top-level stuff.  */
406       case PARALLEL:
407             {
408               int j;
409               for (j = 0; j < XVECLEN (x, 0); j++)
410                 {
411                   if (j)
412                     fputs ("\t;; ", file);
413                   ra_print_rtx (file, XVECEXP (x, 0, j), 0);
414                 }
415               break;
416             }
417       case UNSPEC: case UNSPEC_VOLATILE:
418             {
419               int j;
420               fprintf (file, "unspec%s(%d",
421                        (code == UNSPEC) ? "" : "_vol", XINT (x, 1));
422               for (j = 0; j < XVECLEN (x, 0); j++)
423                 {
424                   fputs (", ", file);
425                   ra_print_rtx (file, XVECEXP (x, 0, j), 0);
426                 }
427               fputs (")", file);
428               break;
429             }
430       case SET:
431           if (GET_CODE (SET_DEST (x)) == PC)
432             {
433               if (GET_CODE (SET_SRC (x)) == IF_THEN_ELSE
434                   && GET_CODE (XEXP (SET_SRC(x), 2)) == PC)
435                 {
436                   fputs ("if ", file);
437                   ra_print_rtx (file, XEXP (SET_SRC (x), 0), 0);
438                   fputs (" jump ", file);
439                   ra_print_rtx (file, XEXP (SET_SRC (x), 1), 0);
440                 }
441               else
442                 {
443                   fputs ("jump ", file);
444                   ra_print_rtx (file, SET_SRC (x), 0);
445                 }
446             }
447           else
448             {
449               ra_print_rtx (file, SET_DEST (x), 0);
450               fputs (" <= ", file);
451               ra_print_rtx (file, SET_SRC (x), 0);
452             }
453           break;
454       case USE:
455               fputs ("use <= ", file);
456               ra_print_rtx (file, XEXP (x, 0), 0);
457               break;
458       case CLOBBER:
459               ra_print_rtx (file, XEXP (x, 0), 0);
460               fputs (" <= clobber", file);
461               break;
462       case CALL:
463               fputs ("call ", file);
464               ra_print_rtx (file, XEXP (x, 0), 0); /* Address */
465               fputs (" numargs=", file);
466               ra_print_rtx (file, XEXP (x, 1), 0); /* Num arguments */
467               break;
468       case RETURN:
469               fputs ("return", file);
470               break;
471       case TRAP_IF:
472               fputs ("if (", file);
473               ra_print_rtx (file, XEXP (x, 0), 0);
474               fputs (") trap ", file);
475               ra_print_rtx (file, XEXP (x, 1), 0);
476               break;
477       case RESX:
478               fprintf (file, "resx from region %d", XINT (x, 0));
479               break;
480
481       /* Different things of class 'x' */
482       case SUBREG: ra_print_rtx_object (file, x); break;
483       case STRICT_LOW_PART:
484                    fputs ("low(", file);
485                    ra_print_rtx (file, XEXP (x, 0), 0);
486                    fputs (")", file);
487                    break;
488       default:
489         unhandled = 1;
490         break;
491     }
492   if (!unhandled)
493     return;
494   if (class == '1')
495     ra_print_rtx_1op (file, x);
496   else if (class == '2' || class == 'c' || class == '<')
497     ra_print_rtx_2op (file, x);
498   else if (class == '3' || class == 'b')
499     ra_print_rtx_3op (file, x);
500   else if (class == 'o')
501     ra_print_rtx_object (file, x);
502   else
503     print_inline_rtx (file, x, 0);
504 }
505
506 /* This only calls ra_print_rtx(), but emits a final newline.  */
507
508 void
509 ra_print_rtx_top (FILE *file, rtx x, int with_pn)
510 {
511   ra_print_rtx (file, x, with_pn);
512   fprintf (file, "\n");
513 }
514
515 /* Callable from gdb.  This prints rtx X onto stderr.  */
516
517 void
518 ra_debug_rtx (rtx x)
519 {
520   ra_print_rtx_top (stderr, x, 1);
521 }
522
523 /* This prints the content of basic block with index BBI.
524    The first and last insn are emitted with UIDs of prev and next insns.  */
525
526 void
527 ra_debug_bbi (int bbi)
528 {
529   basic_block bb = BASIC_BLOCK (bbi);
530   rtx insn;
531   for (insn = bb->head; insn; insn = NEXT_INSN (insn))
532     {
533       ra_print_rtx_top (stderr, insn, (insn == bb->head || insn == bb->end));
534       fprintf (stderr, "\n");
535       if (insn == bb->end)
536         break;
537     }
538 }
539
540 /* Beginning from INSN, emit NUM insns (if NUM is non-negative)
541    or emit a window of NUM insns around INSN, to stderr.  */
542
543 void
544 ra_debug_insns (rtx insn, int num)
545 {
546   int i, count = (num == 0 ? 1 : num < 0 ? -num : num);
547   if (num < 0)
548     for (i = count / 2; i > 0 && PREV_INSN (insn); i--)
549       insn = PREV_INSN (insn);
550   for (i = count; i > 0 && insn; insn = NEXT_INSN (insn), i--)
551     {
552       if (GET_CODE (insn) == CODE_LABEL)
553         fprintf (stderr, "\n");
554       ra_print_rtx_top (stderr, insn, (i == count || i == 1));
555     }
556 }
557
558 /* Beginning with INSN, emit the whole insn chain into FILE.
559    This also outputs comments when basic blocks start or end and omits
560    some notes, if flag_ra_dump_notes is zero.  */
561
562 void
563 ra_print_rtl_with_bb (FILE *file, rtx insn)
564 {
565   basic_block last_bb, bb;
566   unsigned int num = 0;
567   if (!insn)
568     fputs ("nil", file);
569   last_bb = NULL;
570   for (; insn; insn = NEXT_INSN (insn))
571     {
572       if (GET_CODE (insn) == BARRIER)
573         bb = NULL;
574       else
575         bb = BLOCK_FOR_INSN (insn);
576       if (bb != last_bb)
577         {
578           if (last_bb)
579             fprintf (file, ";; End of basic block %d\n", last_bb->index);
580           if (bb)
581             fprintf (file, ";; Begin of basic block %d\n", bb->index);
582           last_bb = bb;
583         }
584       if (GET_CODE (insn) == CODE_LABEL)
585         fputc ('\n', file);
586       if (GET_CODE (insn) == NOTE)
587         {
588           /* Ignore basic block and maybe other notes not referencing
589              deleted things.  */
590           if (NOTE_LINE_NUMBER (insn) != NOTE_INSN_BASIC_BLOCK
591               && (flag_ra_dump_notes
592                   || NOTE_LINE_NUMBER (insn) == NOTE_INSN_DELETED
593                   || NOTE_LINE_NUMBER (insn) == NOTE_INSN_DELETED_LABEL))
594             {
595               ra_print_rtx_top (file, insn, (num == 0 || !NEXT_INSN (insn)));
596               num++;
597             }
598         }
599       else
600         {
601           ra_print_rtx_top (file, insn, (num == 0 || !NEXT_INSN (insn)));
602           num++;
603         }
604     }
605 }
606
607 /* Count how many insns were seen how often, while building the interference
608    graph, and prints the findings.  */
609
610 void
611 dump_number_seen (void)
612 {
613 #define N 17
614   int num[N];
615   int i;
616
617   for (i = 0; i < N; i++)
618     num[i] = 0;
619   for (i = 0; i < get_max_uid (); i++)
620     if (number_seen[i] < N - 1)
621       num[number_seen[i]]++;
622     else
623       num[N - 1]++;
624   for (i = 0; i < N - 1; i++)
625     if (num[i])
626       ra_debug_msg (DUMP_PROCESS, "%d insns seen %d times\n", num[i], i);
627   if (num[N - 1])
628     ra_debug_msg (DUMP_PROCESS, "%d insns seen %d and more times\n", num[i],
629                N - 1);
630   ra_debug_msg (DUMP_PROCESS, "from overall %d insns\n", get_max_uid ());
631 #undef N
632 }
633
634 /* Dump the interference graph, the move list and the webs.  */
635
636 void
637 dump_igraph (struct df *df ATTRIBUTE_UNUSED)
638 {
639   struct move_list *ml;
640   unsigned int def1, def2;
641   int num = 0;
642   int num2;
643   unsigned int i;
644   if (!rtl_dump_file || (debug_new_regalloc & (DUMP_IGRAPH | DUMP_WEBS)) == 0)
645     return;
646   ra_debug_msg (DUMP_IGRAPH, "conflicts:\n  ");
647   for (def1 = 0; def1 < num_webs; def1++)
648     {
649       int num1 = num;
650       num2 = 0;
651       for (def2 = 0; def2 < num_webs; def2++)
652         if (def1 != def2 && TEST_BIT (igraph, igraph_index (def1, def2)))
653           {
654             if (num1 == num)
655               {
656                 if (SUBWEB_P (ID2WEB (def1)))
657                   ra_debug_msg (DUMP_IGRAPH, "%d (SUBREG %d, %d) with ", def1,
658                              ID2WEB (def1)->regno,
659                              SUBREG_BYTE (ID2WEB (def1)->orig_x));
660                 else
661                   ra_debug_msg (DUMP_IGRAPH, "%d (REG %d) with ", def1,
662                              ID2WEB (def1)->regno);
663               }
664             if ((num2 % 9) == 8)
665               ra_debug_msg (DUMP_IGRAPH, "\n              ");
666             num++;
667             num2++;
668             if (SUBWEB_P (ID2WEB (def2)))
669               ra_debug_msg (DUMP_IGRAPH, "%d(%d,%d) ", def2, ID2WEB (def2)->regno,
670                          SUBREG_BYTE (ID2WEB (def2)->orig_x));
671             else
672               ra_debug_msg (DUMP_IGRAPH, "%d(%d) ", def2, ID2WEB (def2)->regno);
673           }
674       if (num1 != num)
675         ra_debug_msg (DUMP_IGRAPH, "\n  ");
676     }
677   ra_debug_msg (DUMP_IGRAPH, "\n");
678   for (ml = wl_moves; ml; ml = ml->next)
679     if (ml->move)
680       {
681         ra_debug_msg (DUMP_IGRAPH, "move: insn %d: Web %d <-- Web %d\n",
682                  INSN_UID (ml->move->insn), ml->move->target_web->id,
683                  ml->move->source_web->id);
684       }
685   ra_debug_msg (DUMP_WEBS, "\nWebs:\n");
686   for (i = 0; i < num_webs; i++)
687     {
688       struct web *web = ID2WEB (i);
689
690       ra_debug_msg (DUMP_WEBS, "  %4d : regno %3d", i, web->regno);
691       if (SUBWEB_P (web))
692         {
693           ra_debug_msg (DUMP_WEBS, " sub %d", SUBREG_BYTE (web->orig_x));
694           ra_debug_msg (DUMP_WEBS, " par %d", find_web_for_subweb (web)->id);
695         }
696       ra_debug_msg (DUMP_WEBS, " +%d (span %d, cost "
697                     HOST_WIDE_INT_PRINT_DEC ") (%s)",
698                     web->add_hardregs, web->span_deaths, web->spill_cost,
699                     reg_class_names[web->regclass]);
700       if (web->spill_temp == 1)
701         ra_debug_msg (DUMP_WEBS, " (spilltemp)");
702       else if (web->spill_temp == 2)
703         ra_debug_msg (DUMP_WEBS, " (spilltem2)");
704       else if (web->spill_temp == 3)
705         ra_debug_msg (DUMP_WEBS, " (short)");
706       if (web->type == PRECOLORED)
707         ra_debug_msg (DUMP_WEBS, " (precolored, color=%d)", web->color);
708       else if (find_web_for_subweb (web)->num_uses == 0)
709         ra_debug_msg (DUMP_WEBS, " dead");
710       if (web->crosses_call)
711         ra_debug_msg (DUMP_WEBS, " xcall");
712       if (web->regno >= max_normal_pseudo)
713         ra_debug_msg (DUMP_WEBS, " stack");
714       ra_debug_msg (DUMP_WEBS, "\n");
715     }
716 }
717
718 /* Dump the interference graph and webs in a format easily
719    parsable by programs.  Used to emit real world interference graph
720    to my custom graph colorizer.  */
721
722 void
723 dump_igraph_machine (void)
724 {
725   unsigned int i;
726
727   if (!rtl_dump_file || (debug_new_regalloc & DUMP_IGRAPH_M) == 0)
728     return;
729   ra_debug_msg (DUMP_IGRAPH_M, "g %d %d\n", num_webs - num_subwebs,
730              FIRST_PSEUDO_REGISTER);
731   for (i = 0; i < num_webs - num_subwebs; i++)
732     {
733       struct web *web = ID2WEB (i);
734       struct conflict_link *cl;
735       int flags = 0;
736       int numc = 0;
737       int col = 0;
738       flags = web->spill_temp & 0xF;
739       flags |= ((web->type == PRECOLORED) ? 1 : 0) << 4;
740       flags |= (web->add_hardregs & 0xF) << 5;
741       for (cl = web->conflict_list; cl; cl = cl->next)
742         if (cl->t->id < web->id)
743           numc++;
744       ra_debug_msg (DUMP_IGRAPH_M, "n %d %d %d %d %d %d %d\n",
745                  web->id, web->color, flags,
746                  (unsigned int)web->spill_cost, web->num_defs, web->num_uses,
747                  numc);
748       if (web->type != PRECOLORED)
749         {
750           ra_debug_msg (DUMP_IGRAPH_M, "s %d", web->id);
751           while (1)
752             {
753               unsigned int u = 0;
754               int n;
755               for (n = 0; n < 32 && col < FIRST_PSEUDO_REGISTER; n++, col++)
756                 if (TEST_HARD_REG_BIT (web->usable_regs, col))
757                   u |= 1 << n;
758               ra_debug_msg (DUMP_IGRAPH_M, " %u", u);
759               if (col >= FIRST_PSEUDO_REGISTER)
760                 break;
761             }
762           ra_debug_msg (DUMP_IGRAPH_M, "\n");
763         }
764       if (numc)
765         {
766           ra_debug_msg (DUMP_IGRAPH_M, "c %d", web->id);
767           for (cl = web->conflict_list; cl; cl = cl->next)
768             {
769               if (cl->t->id < web->id)
770                 ra_debug_msg (DUMP_IGRAPH_M, " %d", cl->t->id);
771             }
772           ra_debug_msg (DUMP_IGRAPH_M, "\n");
773         }
774     }
775   ra_debug_msg (DUMP_IGRAPH_M, "e\n");
776 }
777
778 /* This runs after colorization and changing the insn stream.
779    It temporarily replaces all pseudo registers with their colors,
780    and emits information, if the resulting insns are strictly valid.  */
781
782 void
783 dump_constraints (void)
784 {
785   rtx insn;
786   int i;
787   if (!rtl_dump_file || (debug_new_regalloc & DUMP_CONSTRAINTS) == 0)
788     return;
789   for (i = FIRST_PSEUDO_REGISTER; i < ra_max_regno; i++)
790     if (regno_reg_rtx[i] && GET_CODE (regno_reg_rtx[i]) == REG)
791       REGNO (regno_reg_rtx[i])
792           = ra_reg_renumber[i] >= 0 ? ra_reg_renumber[i] : i;
793   for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
794     if (INSN_P (insn))
795       {
796         int code;
797         int uid = INSN_UID (insn);
798         int o;
799         /* Don't simply force rerecognition, as combine might left us
800            with some unrecognizable ones, which later leads to aborts
801            in regclass, if we now destroy the remembered INSN_CODE().  */
802         /*INSN_CODE (insn) = -1;*/
803         code = recog_memoized (insn);
804         if (code < 0)
805           {
806             ra_debug_msg (DUMP_CONSTRAINTS,
807                        "%d: asm insn or not recognizable.\n", uid);
808             continue;
809           }
810         ra_debug_msg (DUMP_CONSTRAINTS,
811                    "%d: code %d {%s}, %d operands, constraints: ",
812                    uid, code, insn_data[code].name, recog_data.n_operands);
813         extract_insn (insn);
814         /*preprocess_constraints ();*/
815         for (o = 0; o < recog_data.n_operands; o++)
816           {
817             ra_debug_msg (DUMP_CONSTRAINTS,
818                        "%d:%s ", o, recog_data.constraints[o]);
819           }
820         if (constrain_operands (1))
821           ra_debug_msg (DUMP_CONSTRAINTS, "matches strictly alternative %d",
822                      which_alternative);
823         else
824           ra_debug_msg (DUMP_CONSTRAINTS, "doesn't match strictly");
825         ra_debug_msg (DUMP_CONSTRAINTS, "\n");
826       }
827   for (i = FIRST_PSEUDO_REGISTER; i < ra_max_regno; i++)
828     if (regno_reg_rtx[i] && GET_CODE (regno_reg_rtx[i]) == REG)
829       REGNO (regno_reg_rtx[i]) = i;
830 }
831
832 /* This counts and emits the cumulated cost of all spilled webs,
833    preceded by a custom message MSG, with debug level LEVEL.  */
834
835 void
836 dump_graph_cost (unsigned int level, const char *msg)
837 {
838   unsigned int i;
839   unsigned HOST_WIDE_INT cost;
840   if (!rtl_dump_file || (debug_new_regalloc & level) == 0)
841     return;
842
843   cost = 0;
844   for (i = 0; i < num_webs; i++)
845     {
846       struct web *web = id2web[i];
847       if (alias (web)->type == SPILLED)
848         cost += web->orig_spill_cost;
849     }
850   ra_debug_msg (level, " spill cost of graph (%s) = "
851                 HOST_WIDE_INT_PRINT_UNSIGNED "\n",
852                 msg ? msg : "", cost);
853 }
854
855 /* Dump the color assignment per web, the coalesced and spilled webs.  */
856
857 void
858 dump_ra (struct df *df ATTRIBUTE_UNUSED)
859 {
860   struct web *web;
861   struct dlist *d;
862   if (!rtl_dump_file || (debug_new_regalloc & DUMP_RESULTS) == 0)
863     return;
864
865   ra_debug_msg (DUMP_RESULTS, "\nColored:\n");
866   for (d = WEBS(COLORED); d; d = d->next)
867     {
868       web = DLIST_WEB (d);
869       ra_debug_msg (DUMP_RESULTS, "  %4d : color %d\n", web->id, web->color);
870     }
871   ra_debug_msg (DUMP_RESULTS, "\nCoalesced:\n");
872   for (d = WEBS(COALESCED); d; d = d->next)
873     {
874       web = DLIST_WEB (d);
875       ra_debug_msg (DUMP_RESULTS, "  %4d : to web %d, color %d\n", web->id,
876                  alias (web)->id, web->color);
877     }
878   ra_debug_msg (DUMP_RESULTS, "\nSpilled:\n");
879   for (d = WEBS(SPILLED); d; d = d->next)
880     {
881       web = DLIST_WEB (d);
882       ra_debug_msg (DUMP_RESULTS, "  %4d\n", web->id);
883     }
884   ra_debug_msg (DUMP_RESULTS, "\n");
885   dump_cost (DUMP_RESULTS);
886 }
887
888 /* Calculate and dump the cumulated costs of certain types of insns
889    (loads, stores and copies).  */
890
891 void
892 dump_static_insn_cost (FILE *file, const char *message, const char *prefix)
893 {
894   struct cost
895     {
896       unsigned HOST_WIDE_INT cost;
897       unsigned int count;
898     };
899   basic_block bb;
900   struct cost load, store, regcopy, selfcopy, overall;
901   memset (&load, 0, sizeof(load));
902   memset (&store, 0, sizeof(store));
903   memset (&regcopy, 0, sizeof(regcopy));
904   memset (&selfcopy, 0, sizeof(selfcopy));
905   memset (&overall, 0, sizeof(overall));
906
907   if (!file)
908     return;
909
910   FOR_EACH_BB (bb)
911     {
912       unsigned HOST_WIDE_INT block_cost = bb->frequency;
913       rtx insn, set;
914       for (insn = bb->head; insn; insn = NEXT_INSN (insn))
915         {
916           /* Yes, yes.  We don't calculate the costs precisely.
917              Only for "simple enough" insns.  Those containing single
918              sets only.  */
919           if (INSN_P (insn) && ((set = single_set (insn)) != NULL))
920             {
921               rtx src = SET_SRC (set);
922               rtx dest = SET_DEST (set);
923               struct cost *pcost = NULL;
924               overall.cost += block_cost;
925               overall.count++;
926               if (rtx_equal_p (src, dest))
927                 pcost = &selfcopy;
928               else if (GET_CODE (src) == GET_CODE (dest)
929                        && ((GET_CODE (src) == REG)
930                            || (GET_CODE (src) == SUBREG
931                                && GET_CODE (SUBREG_REG (src)) == REG
932                                && GET_CODE (SUBREG_REG (dest)) == REG)))
933                 pcost = &regcopy;
934               else
935                 {
936                   if (GET_CODE (src) == SUBREG)
937                     src = SUBREG_REG (src);
938                   if (GET_CODE (dest) == SUBREG)
939                     dest = SUBREG_REG (dest);
940                   if (GET_CODE (src) == MEM && GET_CODE (dest) != MEM
941                       && memref_is_stack_slot (src))
942                     pcost = &load;
943                   else if (GET_CODE (src) != MEM && GET_CODE (dest) == MEM
944                            && memref_is_stack_slot (dest))
945                     pcost = &store;
946                 }
947               if (pcost)
948                 {
949                   pcost->cost += block_cost;
950                   pcost->count++;
951                 }
952             }
953           if (insn == bb->end)
954             break;
955         }
956     }
957
958   if (!prefix)
959     prefix = "";
960   fprintf (file, "static insn cost %s\n", message ? message : "");
961   fprintf (file, "  %soverall:\tnum=%6d\tcost=% 8" HOST_WIDE_INT_PRINT "d\n",
962            prefix, overall.count, overall.cost);
963   fprintf (file, "  %sloads:\tnum=%6d\tcost=% 8" HOST_WIDE_INT_PRINT "d\n",
964            prefix, load.count, load.cost);
965   fprintf (file, "  %sstores:\tnum=%6d\tcost=% 8" HOST_WIDE_INT_PRINT "d\n",
966            prefix, store.count, store.cost);
967   fprintf (file, "  %sregcopy:\tnum=%6d\tcost=% 8" HOST_WIDE_INT_PRINT "d\n",
968            prefix, regcopy.count, regcopy.cost);
969   fprintf (file, "  %sselfcpy:\tnum=%6d\tcost=% 8" HOST_WIDE_INT_PRINT "d\n",
970            prefix, selfcopy.count, selfcopy.cost);
971 }
972
973 /* Returns nonzero, if WEB1 and WEB2 have some possible
974    hardregs in common.  */
975
976 int
977 web_conflicts_p (struct web *web1, struct web *web2)
978 {
979   if (web1->type == PRECOLORED && web2->type == PRECOLORED)
980     return 0;
981
982   if (web1->type == PRECOLORED)
983     return TEST_HARD_REG_BIT (web2->usable_regs, web1->regno);
984
985   if (web2->type == PRECOLORED)
986     return TEST_HARD_REG_BIT (web1->usable_regs, web2->regno);
987
988   return hard_regs_intersect_p (&web1->usable_regs, &web2->usable_regs);
989 }
990
991 /* Dump all uids of insns in which WEB is mentioned.  */
992
993 void
994 dump_web_insns (struct web *web)
995 {
996   unsigned int i;
997
998   ra_debug_msg (DUMP_EVER, "Web: %i(%i)+%i class: %s freedom: %i degree %i\n",
999              web->id, web->regno, web->add_hardregs,
1000              reg_class_names[web->regclass],
1001              web->num_freedom, web->num_conflicts);
1002   ra_debug_msg (DUMP_EVER, "   def insns:");
1003
1004   for (i = 0; i < web->num_defs; ++i)
1005     {
1006       ra_debug_msg (DUMP_EVER, " %d ", INSN_UID (web->defs[i]->insn));
1007     }
1008
1009   ra_debug_msg (DUMP_EVER, "\n   use insns:");
1010   for (i = 0; i < web->num_uses; ++i)
1011     {
1012       ra_debug_msg (DUMP_EVER, " %d ", INSN_UID (web->uses[i]->insn));
1013     }
1014   ra_debug_msg (DUMP_EVER, "\n");
1015 }
1016
1017 /* Dump conflicts for web WEB.  */
1018
1019 void
1020 dump_web_conflicts (struct web *web)
1021 {
1022   int num = 0;
1023   unsigned int def2;
1024
1025   ra_debug_msg (DUMP_EVER, "Web: %i(%i)+%i class: %s freedom: %i degree %i\n",
1026              web->id, web->regno, web->add_hardregs,
1027              reg_class_names[web->regclass],
1028              web->num_freedom, web->num_conflicts);
1029
1030   for (def2 = 0; def2 < num_webs; def2++)
1031     if (TEST_BIT (igraph, igraph_index (web->id, def2)) && web->id != def2)
1032       {
1033         if ((num % 9) == 5)
1034           ra_debug_msg (DUMP_EVER, "\n             ");
1035         num++;
1036
1037         ra_debug_msg (DUMP_EVER, " %d(%d)", def2, id2web[def2]->regno);
1038         if (id2web[def2]->add_hardregs)
1039           ra_debug_msg (DUMP_EVER, "+%d", id2web[def2]->add_hardregs);
1040
1041         if (web_conflicts_p (web, id2web[def2]))
1042           ra_debug_msg (DUMP_EVER, "/x");
1043
1044         if (id2web[def2]->type == SELECT)
1045           ra_debug_msg (DUMP_EVER, "/s");
1046
1047         if (id2web[def2]->type == COALESCED)
1048           ra_debug_msg (DUMP_EVER,"/c/%d", alias (id2web[def2])->id);
1049       }
1050   ra_debug_msg (DUMP_EVER, "\n");
1051   {
1052     struct conflict_link *wl;
1053     num = 0;
1054     ra_debug_msg (DUMP_EVER, "By conflicts:     ");
1055     for (wl = web->conflict_list; wl; wl = wl->next)
1056       {
1057         struct web* w = wl->t;
1058         if ((num % 9) == 8)
1059           ra_debug_msg (DUMP_EVER, "\n              ");
1060         num++;
1061         ra_debug_msg (DUMP_EVER, "%d(%d)%s ", w->id, w->regno,
1062                    web_conflicts_p (web, w) ? "+" : "");
1063       }
1064     ra_debug_msg (DUMP_EVER, "\n");
1065   }
1066 }
1067
1068 /* Output HARD_REG_SET to stderr.  */
1069
1070 void
1071 debug_hard_reg_set (HARD_REG_SET set)
1072 {
1073   int i;
1074   for (i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
1075     {
1076       if (TEST_HARD_REG_BIT (set, i))
1077         {
1078           fprintf (stderr, "%s ", reg_names[i]);
1079         }
1080     }
1081   fprintf (stderr, "\n");
1082 }
1083
1084 /*
1085 vim:cinoptions={.5s,g0,p5,t0,(0,^-0.5s,n-0.5s:tw=78:cindent:sw=4:
1086 */