OSDN Git Service

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