OSDN Git Service

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