OSDN Git Service

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