OSDN Git Service

* ra-build.c (check_conflict_numbers): Hide unused function.
[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   VA_OPEN (ap, format);
51   VA_FIXEDARG (ap, unsigned int, level);
52   VA_FIXEDARG (ap, const char *, format);
53   if ((debug_new_regalloc & level) != 0 && rtl_dump_file != NULL)
54     vfprintf (rtl_dump_file, format, ap);
55   VA_CLOSE (ap);
56 }
57
58
59 /* The following ra_print_xxx() functions print RTL expressions
60    in concise infix form.  If the mode can be seen from context it's
61    left out.  Most operators are represented by their graphical
62    characters, e.g. LE as "<=".  Unknown constructs are currently
63    printed with print_inline_rtx(), which disrupts the nice layout.
64    Currently only the inline asm things are written this way.  */
65
66 /* Print rtx X, which is a one operand rtx (op:mode (Y)), as
67    "op(Y)" to FILE.  */
68
69 static void
70 ra_print_rtx_1op (file, x)
71      FILE *file;
72      rtx x;
73 {
74   enum rtx_code code = GET_CODE (x);
75   rtx op0 = XEXP (x, 0);
76   switch (code)
77     {
78       case NEG:
79       case NOT:
80           fputs ((code == NEG) ? "-(" : "~(", file);
81           ra_print_rtx (file, op0, 0);
82           fputs (")", file);
83           break;
84       case HIGH:
85           fputs ("hi(", file);
86           ra_print_rtx (file, op0, 0);
87           fputs (")", file);
88           break;
89       default:
90           fprintf (file, "%s", GET_RTX_NAME (code));
91           if (GET_MODE (x) != VOIDmode)
92             fprintf (file, ":%s(", GET_MODE_NAME (GET_MODE (x)));
93           else
94             fputs ("(", file);
95           ra_print_rtx (file, op0, 0);
96           fputs (")", file);
97           break;
98     }
99 }
100
101 /* Print rtx X, which is a two operand rtx (op:mode (Y) (Z))
102    as "(Y op Z)", if the operand is know, or as "op(Y, Z)", if not,
103    to FILE.  */
104
105 static void
106 ra_print_rtx_2op (file, x)
107      FILE *file;
108      rtx x;
109 {
110   int infix = 1;
111   const char *opname = "shitop";
112   enum rtx_code code = GET_CODE (x);
113   rtx op0 = XEXP (x, 0);
114   rtx op1 = XEXP (x, 1);
115   switch (code)
116     {
117       /* class '2' */
118       case COMPARE: opname = "?"; break;
119       case MINUS: opname = "-"; break;
120       case DIV: opname = "/"; break;
121       case UDIV: opname = "u/"; break;
122       case MOD: opname = "%"; break;
123       case UMOD: opname = "u%"; break;
124       case ASHIFT: opname = "<<"; break;
125       case ASHIFTRT: opname = "a>>"; break;
126       case LSHIFTRT: opname = "l>>"; break;
127       /* class 'c' */
128       case PLUS: opname = "+"; break;
129       case MULT: opname = "*"; break;
130       case AND: opname = "&"; break;
131       case IOR: opname = "|"; break;
132       case XOR: opname = "^"; break;
133       /* class '<' */
134       case NE: opname = "!="; break;
135       case EQ: opname = "=="; break;
136       case GE: opname = "s>="; break;
137       case GT: opname = "s>"; break;
138       case LE: opname = "s<="; break;
139       case LT: opname = "s<"; break;
140       case GEU: opname = "u>="; break;
141       case GTU: opname = "u>"; break;
142       case LEU: opname = "u<="; break;
143       case LTU: opname = "u<"; break;
144       default:
145                 infix = 0;
146                 opname = GET_RTX_NAME (code);
147                 break;
148     }
149   if (infix)
150     {
151       fputs ("(", file);
152       ra_print_rtx (file, op0, 0);
153       fprintf (file, " %s ", opname);
154       ra_print_rtx (file, op1, 0);
155       fputs (")", file);
156     }
157   else
158     {
159       fprintf (file, "%s(", opname);
160       ra_print_rtx (file, op0, 0);
161       fputs (", ", file);
162       ra_print_rtx (file, op1, 0);
163       fputs (")", file);
164     }
165 }
166
167 /* Print rtx X, which a three operand rtx to FILE.
168    I.e. X is either an IF_THEN_ELSE, or a bitmap operation.  */
169
170 static void
171 ra_print_rtx_3op (file, x)
172      FILE *file;
173      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' 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, x)
209      FILE *file;
210      rtx x;
211 {
212   enum rtx_code code = GET_CODE (x);
213   enum machine_mode mode = GET_MODE (x);
214   switch (code)
215     {
216       case CONST_INT:
217           fprintf (file, HOST_WIDE_INT_PRINT_DEC, XWINT (x, 0));
218           break;
219       case CONST_DOUBLE:
220             {
221               int i, num = 0;
222               const char *fmt = GET_RTX_FORMAT (code);
223               fputs ("dbl(", file);
224               for (i = 0; i < GET_RTX_LENGTH (code); i++)
225                 {
226                   if (num)
227                     fputs (", ", file);
228                   if (fmt[i] == 'e' && XEXP (x, i))
229                     /* The MEM or other stuff */
230                     {
231                       ra_print_rtx (file, XEXP (x, i), 0);
232                       num++;
233                     }
234                   else if (fmt[i] == 'w')
235                     {
236                       fprintf (file, HOST_WIDE_INT_PRINT_HEX, XWINT (x, i));
237                       num++;
238                     }
239                 }
240               break;
241             }
242       case CONST_STRING: fprintf (file, "\"%s\"", XSTR (x, 0)); break;
243       case CONST: fputs ("const(", file);
244                   ra_print_rtx (file, XEXP (x, 0), 0);
245                   fputs (")", file);
246                   break;
247       case PC: fputs ("pc", file); break;
248       case REG:
249                {
250                  int regno = REGNO (x);
251                  if (regno < FIRST_PSEUDO_REGISTER)
252                    {
253                      int i, nregs = HARD_REGNO_NREGS (regno, mode);
254                      if (nregs > 1)
255                        fputs ("[", file);
256                      for (i = 0; i < nregs; i++)
257                        {
258                          if (i)
259                            fputs (", ", file);
260                          if (reg_names[regno+i] && *reg_names[regno + i])
261                            fprintf (file, "%s", reg_names[regno + i]);
262                          else
263                            fprintf (file, "h%d", regno + i);
264                        }
265                      if (nregs > 1)
266                        fputs ("]", file);
267                    }
268                  else
269                    fprintf (file, "p%d", regno);
270                  break;
271                }
272       case SUBREG:
273                {
274                  rtx sub = SUBREG_REG (x);
275                  int ofs = SUBREG_BYTE (x);
276                  if (GET_CODE (sub) == REG
277                      && REGNO (sub) < FIRST_PSEUDO_REGISTER)
278                    {
279                      int regno = REGNO (sub);
280                      int i, nregs = HARD_REGNO_NREGS (regno, mode);
281                      regno += subreg_regno_offset (regno, GET_MODE (sub),
282                                                    ofs, mode);
283                      if (nregs > 1)
284                        fputs ("[", file);
285                      for (i = 0; i < nregs; i++)
286                        {
287                          if (i)
288                            fputs (", ", file);
289                          if (reg_names[regno+i])
290                            fprintf (file, "%s", reg_names[regno + i]);
291                          else
292                            fprintf (file, "h%d", regno + i);
293                        }
294                      if (nregs > 1)
295                        fputs ("]", file);
296                    }
297                  else
298                    {
299                      ra_print_rtx (file, sub, 0);
300                      fprintf (file, ":[%s+%d]", GET_MODE_NAME (mode), ofs);
301                    }
302                  break;
303                }
304       case SCRATCH: fputs ("scratch", file); break;
305       case CONCAT: ra_print_rtx_2op (file, x); break;
306       case HIGH: ra_print_rtx_1op (file, x); break;
307       case LO_SUM:
308                  fputs ("(", file);
309                  ra_print_rtx (file, XEXP (x, 0), 0);
310                  fputs (" + lo(", file);
311                  ra_print_rtx (file, XEXP (x, 1), 0);
312                  fputs ("))", file);
313                  break;
314       case MEM: fputs ("[", file);
315                 ra_print_rtx (file, XEXP (x, 0), 0);
316                 fprintf (file, "]:%s", GET_MODE_NAME (GET_MODE (x)));
317                 /* XXX print alias set too ?? */
318                 break;
319       case LABEL_REF:
320                   {
321                     rtx sub = XEXP (x, 0);
322                     if (GET_CODE (sub) == NOTE
323                         && NOTE_LINE_NUMBER (sub) == NOTE_INSN_DELETED_LABEL)
324                       fprintf (file, "(deleted uid=%d)", INSN_UID (sub));
325                     else if (GET_CODE (sub) == CODE_LABEL)
326                       fprintf (file, "L%d", CODE_LABEL_NUMBER (sub));
327                     else
328                       fprintf (file, "(nonlabel uid=%d)", INSN_UID (sub));
329                   }
330                 break;
331       case SYMBOL_REF:
332                 fprintf (file, "sym(\"%s\")", XSTR (x, 0)); break;
333       case CC0: fputs ("cc0", file); break;
334       default: print_inline_rtx (file, x, 0); break;
335     }
336 }
337
338 /* Print a general rtx X to FILE in nice infix form.
339    If WITH_PN is set, and X is one of the toplevel constructs
340    (insns, notes, labels or barriers), then print also the UIDs of
341    the preceding and following insn.  */
342
343 void
344 ra_print_rtx (file, x, with_pn)
345      FILE *file;
346      rtx x;
347      int with_pn;
348 {
349   enum rtx_code code;
350   char class;
351   int unhandled = 0;
352   if (!x)
353     return;
354   code = GET_CODE (x);
355   class = GET_RTX_CLASS (code);
356
357   /* First handle the insn like constructs.  */
358   if (INSN_P (x) || code == NOTE || code == CODE_LABEL || code == BARRIER)
359     {
360       if (INSN_P (x))
361         fputs ("  ", file);
362       /* Non-insns are prefixed by a ';'.  */
363       if (code == BARRIER)
364         fputs ("; ", file);
365       else if (code == NOTE)
366         /* But notes are indented very far right.  */
367         fprintf (file, "\t\t\t\t\t; ");
368       else if (code == CODE_LABEL)
369         /* And labels have their Lxx name first, before the actual UID.  */
370         {
371           fprintf (file, "L%d:\t; ", CODE_LABEL_NUMBER (x));
372           if (LABEL_NAME (x))
373             fprintf (file, "(%s) ", LABEL_NAME (x));
374           switch (LABEL_KIND (x))
375             {
376             case LABEL_NORMAL: break;
377             case LABEL_STATIC_ENTRY: fputs (" (entry)", file); break;
378             case LABEL_GLOBAL_ENTRY: fputs (" (global entry)", file); break;
379             case LABEL_WEAK_ENTRY: fputs (" (weak entry)", file); break;
380             default: abort();
381             }
382           fprintf (file, " [%d uses] uid=(", LABEL_NUSES (x));
383         }
384       fprintf (file, "%d", INSN_UID (x));
385       if (with_pn)
386         fprintf (file, " %d %d", PREV_INSN (x) ? INSN_UID (PREV_INSN (x)) : 0,
387                  NEXT_INSN (x) ? INSN_UID (NEXT_INSN (x)) : 0);
388       if (code == BARRIER)
389         fputs (" -------- barrier ---------", file);
390       else if (code == CODE_LABEL)
391         fputs (")", file);
392       else if (code == NOTE)
393         {
394           int ln = NOTE_LINE_NUMBER (x);
395           if (ln >= (int) NOTE_INSN_BIAS && ln < (int) NOTE_INSN_MAX)
396             fprintf (file, " %s", GET_NOTE_INSN_NAME (ln));
397           else
398             {
399               fprintf (file, " line %d", ln);
400               if (NOTE_SOURCE_FILE (x))
401                 fprintf (file, ":%s", NOTE_SOURCE_FILE (x));
402             }
403         }
404       else
405         {
406           fprintf (file, "\t");
407           ra_print_rtx (file, PATTERN (x), 0);
408         }
409       return;
410     }
411   switch (code)
412     {
413       /* Top-level stuff.  */
414       case PARALLEL:
415             {
416               int j;
417               for (j = 0; j < XVECLEN (x, 0); j++)
418                 {
419                   if (j)
420                     fputs ("\t;; ", file);
421                   ra_print_rtx (file, XVECEXP (x, 0, j), 0);
422                 }
423               break;
424             }
425       case UNSPEC: case UNSPEC_VOLATILE:
426             {
427               int j;
428               fprintf (file, "unspec%s(%d",
429                        (code == UNSPEC) ? "" : "_vol", XINT (x, 1));
430               for (j = 0; j < XVECLEN (x, 0); j++)
431                 {
432                   fputs (", ", file);
433                   ra_print_rtx (file, XVECEXP (x, 0, j), 0);
434                 }
435               fputs (")", file);
436               break;
437             }
438       case SET:
439           if (GET_CODE (SET_DEST (x)) == PC)
440             {
441               if (GET_CODE (SET_SRC (x)) == IF_THEN_ELSE
442                   && GET_CODE (XEXP (SET_SRC(x), 2)) == PC)
443                 {
444                   fputs ("if ", file);
445                   ra_print_rtx (file, XEXP (SET_SRC (x), 0), 0);
446                   fputs (" jump ", file);
447                   ra_print_rtx (file, XEXP (SET_SRC (x), 1), 0);
448                 }
449               else
450                 {
451                   fputs ("jump ", file);
452                   ra_print_rtx (file, SET_SRC (x), 0);
453                 }
454             }
455           else
456             {
457               ra_print_rtx (file, SET_DEST (x), 0);
458               fputs (" <= ", file);
459               ra_print_rtx (file, SET_SRC (x), 0);
460             }
461           break;
462       case USE:
463               fputs ("use <= ", file);
464               ra_print_rtx (file, XEXP (x, 0), 0);
465               break;
466       case CLOBBER:
467               ra_print_rtx (file, XEXP (x, 0), 0);
468               fputs (" <= clobber", file);
469               break;
470       case CALL:
471               fputs ("call ", file);
472               ra_print_rtx (file, XEXP (x, 0), 0); /* Address */
473               fputs (" numargs=", file);
474               ra_print_rtx (file, XEXP (x, 1), 0); /* Num arguments */
475               break;
476       case RETURN:
477               fputs ("return", file);
478               break;
479       case TRAP_IF:
480               fputs ("if (", file);
481               ra_print_rtx (file, XEXP (x, 0), 0);
482               fputs (") trap ", file);
483               ra_print_rtx (file, XEXP (x, 1), 0);
484               break;
485       case RESX:
486               fprintf (file, "resx from region %d", XINT (x, 0));
487               break;
488
489       /* Different things of class 'x' */
490       case SUBREG: ra_print_rtx_object (file, x); break;
491       case STRICT_LOW_PART:
492                    fputs ("low(", file);
493                    ra_print_rtx (file, XEXP (x, 0), 0);
494                    fputs (")", file);
495                    break;
496       default:
497         unhandled = 1;
498         break;
499     }
500   if (!unhandled)
501     return;
502   if (class == '1')
503     ra_print_rtx_1op (file, x);
504   else if (class == '2' || class == 'c' || class == '<')
505     ra_print_rtx_2op (file, x);
506   else if (class == '3' || class == 'b')
507     ra_print_rtx_3op (file, x);
508   else if (class == 'o')
509     ra_print_rtx_object (file, x);
510   else
511     print_inline_rtx (file, x, 0);
512 }
513
514 /* This only calls ra_print_rtx(), but emits a final newline.  */
515
516 void
517 ra_print_rtx_top (file, x, with_pn)
518      FILE *file;
519      rtx x;
520      int with_pn;
521 {
522   ra_print_rtx (file, x, with_pn);
523   fprintf (file, "\n");
524 }
525
526 /* Callable from gdb.  This prints rtx X onto stderr.  */
527
528 void
529 ra_debug_rtx (x)
530      rtx x;
531 {
532   ra_print_rtx_top (stderr, x, 1);
533 }
534
535 /* This prints the content of basic block with index BBI.
536    The first and last insn are emitted with UIDs of prev and next insns.  */
537
538 void
539 ra_debug_bbi (bbi)
540      int bbi;
541 {
542   basic_block bb = BASIC_BLOCK (bbi);
543   rtx insn;
544   for (insn = bb->head; insn; insn = NEXT_INSN (insn))
545     {
546       ra_print_rtx_top (stderr, insn, (insn == bb->head || insn == bb->end));
547       fprintf (stderr, "\n");
548       if (insn == bb->end)
549         break;
550     }
551 }
552
553 /* Beginning from INSN, emit NUM insns (if NUM is non-negative)
554    or emit a window of NUM insns around INSN, to stderr.  */
555
556 void
557 ra_debug_insns (insn, num)
558      rtx insn;
559      int num;
560 {
561   int i, count = (num == 0 ? 1 : num < 0 ? -num : num);
562   if (num < 0)
563     for (i = count / 2; i > 0 && PREV_INSN (insn); i--)
564       insn = PREV_INSN (insn);
565   for (i = count; i > 0 && insn; insn = NEXT_INSN (insn), i--)
566     {
567       if (GET_CODE (insn) == CODE_LABEL)
568         fprintf (stderr, "\n");
569       ra_print_rtx_top (stderr, insn, (i == count || i == 1));
570     }
571 }
572
573 /* Beginning with INSN, emit the whole insn chain into FILE.
574    This also outputs comments when basic blocks start or end and omits
575    some notes, if flag_ra_dump_notes is zero.  */
576
577 void
578 ra_print_rtl_with_bb (file, insn)
579      FILE *file;
580      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 (GET_CODE (insn) == BARRIER)
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 (GET_CODE (insn) == CODE_LABEL)
602         fputc ('\n', file);
603       if (GET_CODE (insn) == NOTE)
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 ()
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 (df)
655      struct df *df ATTRIBUTE_UNUSED;
656 {
657   struct move_list *ml;
658   unsigned int def1, def2;
659   int num = 0;
660   int num2;
661   unsigned int i;
662   if (!rtl_dump_file || (debug_new_regalloc & (DUMP_IGRAPH | DUMP_WEBS)) == 0)
663     return;
664   ra_debug_msg (DUMP_IGRAPH, "conflicts:\n  ");
665   for (def1 = 0; def1 < num_webs; def1++)
666     {
667       int num1 = num;
668       for (num2=0, 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                     web->add_hardregs, web->span_deaths);
715       ra_debug_msg (DUMP_WEBS, HOST_WIDE_INT_PRINT_DEC, web->spill_cost);
716       ra_debug_msg (DUMP_WEBS, ") (%s)", 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 ()
741 {
742   unsigned int i;
743
744   if (!rtl_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 ()
801 {
802   rtx insn;
803   int i;
804   if (!rtl_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] && GET_CODE (regno_reg_rtx[i]) == REG)
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 unrecongnizable 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] && GET_CODE (regno_reg_rtx[i]) == REG)
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 (level, msg)
854      unsigned int level;
855      const char *msg;
856 {
857   unsigned int i;
858   unsigned HOST_WIDE_INT cost;
859   if (!rtl_dump_file || (debug_new_regalloc & level) == 0)
860     return;
861
862   cost = 0;
863   for (i = 0; i < num_webs; i++)
864     {
865       struct web *web = id2web[i];
866       if (alias (web)->type == SPILLED)
867         cost += web->orig_spill_cost;
868     }
869   ra_debug_msg (level, " spill cost of graph (%s) = ", msg ? msg : "");
870   ra_debug_msg (level, HOST_WIDE_INT_PRINT_UNSIGNED, cost);
871   ra_debug_msg (level, "\n");
872 }
873
874 /* Dump the color assignment per web, the coalesced and spilled webs.  */
875
876 void
877 dump_ra (df)
878      struct df *df ATTRIBUTE_UNUSED;
879 {
880   struct web *web;
881   struct dlist *d;
882   if (!rtl_dump_file || (debug_new_regalloc & DUMP_RESULTS) == 0)
883     return;
884
885   ra_debug_msg (DUMP_RESULTS, "\nColored:\n");
886   for (d = WEBS(COLORED); d; d = d->next)
887     {
888       web = DLIST_WEB (d);
889       ra_debug_msg (DUMP_RESULTS, "  %4d : color %d\n", web->id, web->color);
890     }
891   ra_debug_msg (DUMP_RESULTS, "\nCoalesced:\n");
892   for (d = WEBS(COALESCED); d; d = d->next)
893     {
894       web = DLIST_WEB (d);
895       ra_debug_msg (DUMP_RESULTS, "  %4d : to web %d, color %d\n", web->id,
896                  alias (web)->id, web->color);
897     }
898   ra_debug_msg (DUMP_RESULTS, "\nSpilled:\n");
899   for (d = WEBS(SPILLED); d; d = d->next)
900     {
901       web = DLIST_WEB (d);
902       ra_debug_msg (DUMP_RESULTS, "  %4d\n", web->id);
903     }
904   ra_debug_msg (DUMP_RESULTS, "\n");
905   dump_cost (DUMP_RESULTS);
906 }
907
908 /* Calculate and dump the cumulated costs of certain types of insns
909    (loads, stores and copies).  */
910
911 void
912 dump_static_insn_cost (file, message, prefix)
913      FILE *file;
914      const char *message;
915      const char *prefix;
916 {
917   struct cost
918     {
919       unsigned HOST_WIDE_INT cost;
920       unsigned int count;
921     };
922   basic_block bb;
923   struct cost load, store, regcopy, selfcopy, overall;
924   memset (&load, 0, sizeof(load));
925   memset (&store, 0, sizeof(store));
926   memset (&regcopy, 0, sizeof(regcopy));
927   memset (&selfcopy, 0, sizeof(selfcopy));
928   memset (&overall, 0, sizeof(overall));
929
930   if (!file)
931     return;
932
933   FOR_EACH_BB (bb)
934     {
935       unsigned HOST_WIDE_INT block_cost = bb->frequency;
936       rtx insn, set;
937       for (insn = bb->head; insn; insn = NEXT_INSN (insn))
938         {
939           /* Yes, yes.  We don't calculate the costs precisely.
940              Only for "simple enough" insns.  Those containing single
941              sets only.  */
942           if (INSN_P (insn) && ((set = single_set (insn)) != NULL))
943             {
944               rtx src = SET_SRC (set);
945               rtx dest = SET_DEST (set);
946               struct cost *pcost = NULL;
947               overall.cost += block_cost;
948               overall.count++;
949               if (rtx_equal_p (src, dest))
950                 pcost = &selfcopy;
951               else if (GET_CODE (src) == GET_CODE (dest)
952                        && ((GET_CODE (src) == REG)
953                            || (GET_CODE (src) == SUBREG
954                                && GET_CODE (SUBREG_REG (src)) == REG
955                                && GET_CODE (SUBREG_REG (dest)) == REG)))
956                 pcost = &regcopy;
957               else
958                 {
959                   if (GET_CODE (src) == SUBREG)
960                     src = SUBREG_REG (src);
961                   if (GET_CODE (dest) == SUBREG)
962                     dest = SUBREG_REG (dest);
963                   if (GET_CODE (src) == MEM && GET_CODE (dest) != MEM
964                       && memref_is_stack_slot (src))
965                     pcost = &load;
966                   else if (GET_CODE (src) != MEM && GET_CODE (dest) == MEM
967                            && memref_is_stack_slot (dest))
968                     pcost = &store;
969                 }
970               if (pcost)
971                 {
972                   pcost->cost += block_cost;
973                   pcost->count++;
974                 }
975             }
976           if (insn == bb->end)
977             break;
978         }
979     }
980
981   if (!prefix)
982     prefix = "";
983   fprintf (file, "static insn cost %s\n", message ? message : "");
984   fprintf (file, "  %soverall:\tnum=%6d\tcost=%8d\n", prefix, overall.count,
985            overall.cost);
986   fprintf (file, "  %sloads:\tnum=%6d\tcost=%8d\n", prefix, load.count,
987            load.cost);
988   fprintf (file, "  %sstores:\tnum=%6d\tcost=%8d\n", prefix,
989            store.count, store.cost);
990   fprintf (file, "  %sregcopy:\tnum=%6d\tcost=%8d\n", prefix, regcopy.count,
991            regcopy.cost);
992   fprintf (file, "  %sselfcpy:\tnum=%6d\tcost=%8d\n", prefix, selfcopy.count,
993            selfcopy.cost);
994 }
995
996 /* Returns nonzero, if WEB1 and WEB2 have some possible
997    hardregs in common.  */
998
999 int
1000 web_conflicts_p (web1, web2)
1001      struct web *web1;
1002      struct web *web2;
1003 {
1004   if (web1->type == PRECOLORED && web2->type == PRECOLORED)
1005     return 0;
1006
1007   if (web1->type == PRECOLORED)
1008     return TEST_HARD_REG_BIT (web2->usable_regs, web1->regno);
1009
1010   if (web2->type == PRECOLORED)
1011     return TEST_HARD_REG_BIT (web1->usable_regs, web2->regno);
1012
1013   return hard_regs_intersect_p (&web1->usable_regs, &web2->usable_regs);
1014 }
1015
1016 /* Dump all uids of insns in which WEB is mentioned.  */
1017
1018 void
1019 dump_web_insns (web)
1020      struct web *web;
1021 {
1022   unsigned int i;
1023
1024   ra_debug_msg (DUMP_EVER, "Web: %i(%i)+%i class: %s freedom: %i degree %i\n",
1025              web->id, web->regno, web->add_hardregs,
1026              reg_class_names[web->regclass],
1027              web->num_freedom, web->num_conflicts);
1028   ra_debug_msg (DUMP_EVER, "   def insns:");
1029
1030   for (i = 0; i < web->num_defs; ++i)
1031     {
1032       ra_debug_msg (DUMP_EVER, " %d ", INSN_UID (web->defs[i]->insn));
1033     }
1034
1035   ra_debug_msg (DUMP_EVER, "\n   use insns:");
1036   for (i = 0; i < web->num_uses; ++i)
1037     {
1038       ra_debug_msg (DUMP_EVER, " %d ", INSN_UID (web->uses[i]->insn));
1039     }
1040   ra_debug_msg (DUMP_EVER, "\n");
1041 }
1042
1043 /* Dump conflicts for web WEB.  */
1044
1045 void
1046 dump_web_conflicts (web)
1047      struct web *web;
1048 {
1049   int num = 0;
1050   unsigned int def2;
1051
1052   ra_debug_msg (DUMP_EVER, "Web: %i(%i)+%i class: %s freedom: %i degree %i\n",
1053              web->id, web->regno, web->add_hardregs,
1054              reg_class_names[web->regclass],
1055              web->num_freedom, web->num_conflicts);
1056
1057   for (def2 = 0; def2 < num_webs; def2++)
1058     if (TEST_BIT (igraph, igraph_index (web->id, def2)) && web->id != def2)
1059       {
1060         if ((num % 9) == 5)
1061           ra_debug_msg (DUMP_EVER, "\n             ");
1062         num++;
1063
1064         ra_debug_msg (DUMP_EVER, " %d(%d)", def2, id2web[def2]->regno);
1065         if (id2web[def2]->add_hardregs)
1066           ra_debug_msg (DUMP_EVER, "+%d", id2web[def2]->add_hardregs);
1067
1068         if (web_conflicts_p (web, id2web[def2]))
1069           ra_debug_msg (DUMP_EVER, "/x");
1070
1071         if (id2web[def2]->type == SELECT)
1072           ra_debug_msg (DUMP_EVER, "/s");
1073
1074         if (id2web[def2]->type == COALESCED)
1075           ra_debug_msg (DUMP_EVER,"/c/%d", alias (id2web[def2])->id);
1076       }
1077   ra_debug_msg (DUMP_EVER, "\n");
1078   {
1079     struct conflict_link *wl;
1080     num = 0;
1081     ra_debug_msg (DUMP_EVER, "By conflicts:     ");
1082     for (wl = web->conflict_list; wl; wl = wl->next)
1083       {
1084         struct web* w = wl->t;
1085         if ((num % 9) == 8)
1086           ra_debug_msg (DUMP_EVER, "\n              ");
1087         num++;
1088         ra_debug_msg (DUMP_EVER, "%d(%d)%s ", w->id, w->regno,
1089                    web_conflicts_p (web, w) ? "+" : "");
1090       }
1091     ra_debug_msg (DUMP_EVER, "\n");
1092   }
1093 }
1094
1095 /* Output HARD_REG_SET to stderr.  */
1096
1097 void
1098 debug_hard_reg_set (set)
1099      HARD_REG_SET set;
1100 {
1101   int i;
1102   for (i=0; i < FIRST_PSEUDO_REGISTER; ++i)
1103     {
1104       if (TEST_HARD_REG_BIT (set, i))
1105         {
1106           fprintf (stderr, "%s ", reg_names[i]);
1107         }
1108     }
1109   fprintf (stderr, "\n");
1110 }
1111
1112 /*
1113 vim:cinoptions={.5s,g0,p5,t0,(0,^-0.5s,n-0.5s:tw=78:cindent:sw=4:
1114 */