OSDN Git Service

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