OSDN Git Service

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