OSDN Git Service

gcc:
[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       num2 = 0;
672       for (def2 = 0; def2 < num_webs; def2++)
673         if (def1 != def2 && TEST_BIT (igraph, igraph_index (def1, def2)))
674           {
675             if (num1 == num)
676               {
677                 if (SUBWEB_P (ID2WEB (def1)))
678                   ra_debug_msg (DUMP_IGRAPH, "%d (SUBREG %d, %d) with ", def1,
679                              ID2WEB (def1)->regno,
680                              SUBREG_BYTE (ID2WEB (def1)->orig_x));
681                 else
682                   ra_debug_msg (DUMP_IGRAPH, "%d (REG %d) with ", def1,
683                              ID2WEB (def1)->regno);
684               }
685             if ((num2 % 9) == 8)
686               ra_debug_msg (DUMP_IGRAPH, "\n              ");
687             num++;
688             num2++;
689             if (SUBWEB_P (ID2WEB (def2)))
690               ra_debug_msg (DUMP_IGRAPH, "%d(%d,%d) ", def2, ID2WEB (def2)->regno,
691                          SUBREG_BYTE (ID2WEB (def2)->orig_x));
692             else
693               ra_debug_msg (DUMP_IGRAPH, "%d(%d) ", def2, ID2WEB (def2)->regno);
694           }
695       if (num1 != num)
696         ra_debug_msg (DUMP_IGRAPH, "\n  ");
697     }
698   ra_debug_msg (DUMP_IGRAPH, "\n");
699   for (ml = wl_moves; ml; ml = ml->next)
700     if (ml->move)
701       {
702         ra_debug_msg (DUMP_IGRAPH, "move: insn %d: Web %d <-- Web %d\n",
703                  INSN_UID (ml->move->insn), ml->move->target_web->id,
704                  ml->move->source_web->id);
705       }
706   ra_debug_msg (DUMP_WEBS, "\nWebs:\n");
707   for (i = 0; i < num_webs; i++)
708     {
709       struct web *web = ID2WEB (i);
710
711       ra_debug_msg (DUMP_WEBS, "  %4d : regno %3d", i, web->regno);
712       if (SUBWEB_P (web))
713         {
714           ra_debug_msg (DUMP_WEBS, " sub %d", SUBREG_BYTE (web->orig_x));
715           ra_debug_msg (DUMP_WEBS, " par %d", find_web_for_subweb (web)->id);
716         }
717       ra_debug_msg (DUMP_WEBS, " +%d (span %d, cost "
718                     HOST_WIDE_INT_PRINT_DEC ") (%s)",
719                     web->add_hardregs, web->span_deaths, web->spill_cost,
720                     reg_class_names[web->regclass]);
721       if (web->spill_temp == 1)
722         ra_debug_msg (DUMP_WEBS, " (spilltemp)");
723       else if (web->spill_temp == 2)
724         ra_debug_msg (DUMP_WEBS, " (spilltem2)");
725       else if (web->spill_temp == 3)
726         ra_debug_msg (DUMP_WEBS, " (short)");
727       if (web->type == PRECOLORED)
728         ra_debug_msg (DUMP_WEBS, " (precolored, color=%d)", web->color);
729       else if (find_web_for_subweb (web)->num_uses == 0)
730         ra_debug_msg (DUMP_WEBS, " dead");
731       if (web->crosses_call)
732         ra_debug_msg (DUMP_WEBS, " xcall");
733       if (web->regno >= max_normal_pseudo)
734         ra_debug_msg (DUMP_WEBS, " stack");
735       ra_debug_msg (DUMP_WEBS, "\n");
736     }
737 }
738
739 /* Dump the interference graph and webs in a format easily
740    parsable by programs.  Used to emit real world interference graph
741    to my custom graph colorizer.  */
742
743 void
744 dump_igraph_machine ()
745 {
746   unsigned int i;
747
748   if (!rtl_dump_file || (debug_new_regalloc & DUMP_IGRAPH_M) == 0)
749     return;
750   ra_debug_msg (DUMP_IGRAPH_M, "g %d %d\n", num_webs - num_subwebs,
751              FIRST_PSEUDO_REGISTER);
752   for (i = 0; i < num_webs - num_subwebs; i++)
753     {
754       struct web *web = ID2WEB (i);
755       struct conflict_link *cl;
756       int flags = 0;
757       int numc = 0;
758       int col = 0;
759       flags = web->spill_temp & 0xF;
760       flags |= ((web->type == PRECOLORED) ? 1 : 0) << 4;
761       flags |= (web->add_hardregs & 0xF) << 5;
762       for (cl = web->conflict_list; cl; cl = cl->next)
763         if (cl->t->id < web->id)
764           numc++;
765       ra_debug_msg (DUMP_IGRAPH_M, "n %d %d %d %d %d %d %d\n",
766                  web->id, web->color, flags,
767                  (unsigned int)web->spill_cost, web->num_defs, web->num_uses,
768                  numc);
769       if (web->type != PRECOLORED)
770         {
771           ra_debug_msg (DUMP_IGRAPH_M, "s %d", web->id);
772           while (1)
773             {
774               unsigned int u = 0;
775               int n;
776               for (n = 0; n < 32 && col < FIRST_PSEUDO_REGISTER; n++, col++)
777                 if (TEST_HARD_REG_BIT (web->usable_regs, col))
778                   u |= 1 << n;
779               ra_debug_msg (DUMP_IGRAPH_M, " %u", u);
780               if (col >= FIRST_PSEUDO_REGISTER)
781                 break;
782             }
783           ra_debug_msg (DUMP_IGRAPH_M, "\n");
784         }
785       if (numc)
786         {
787           ra_debug_msg (DUMP_IGRAPH_M, "c %d", web->id);
788           for (cl = web->conflict_list; cl; cl = cl->next)
789             {
790               if (cl->t->id < web->id)
791                 ra_debug_msg (DUMP_IGRAPH_M, " %d", cl->t->id);
792             }
793           ra_debug_msg (DUMP_IGRAPH_M, "\n");
794         }
795     }
796   ra_debug_msg (DUMP_IGRAPH_M, "e\n");
797 }
798
799 /* This runs after colorization and changing the insn stream.
800    It temporarily replaces all pseudo registers with their colors,
801    and emits information, if the resulting insns are strictly valid.  */
802
803 void
804 dump_constraints ()
805 {
806   rtx insn;
807   int i;
808   if (!rtl_dump_file || (debug_new_regalloc & DUMP_CONSTRAINTS) == 0)
809     return;
810   for (i = FIRST_PSEUDO_REGISTER; i < ra_max_regno; i++)
811     if (regno_reg_rtx[i] && GET_CODE (regno_reg_rtx[i]) == REG)
812       REGNO (regno_reg_rtx[i])
813           = ra_reg_renumber[i] >= 0 ? ra_reg_renumber[i] : i;
814   for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
815     if (INSN_P (insn))
816       {
817         int code;
818         int uid = INSN_UID (insn);
819         int o;
820         /* Don't simply force rerecognition, as combine might left us
821            with some unrecognizable ones, which later leads to aborts
822            in regclass, if we now destroy the remembered INSN_CODE().  */
823         /*INSN_CODE (insn) = -1;*/
824         code = recog_memoized (insn);
825         if (code < 0)
826           {
827             ra_debug_msg (DUMP_CONSTRAINTS,
828                        "%d: asm insn or not recognizable.\n", uid);
829             continue;
830           }
831         ra_debug_msg (DUMP_CONSTRAINTS,
832                    "%d: code %d {%s}, %d operands, constraints: ",
833                    uid, code, insn_data[code].name, recog_data.n_operands);
834         extract_insn (insn);
835         /*preprocess_constraints ();*/
836         for (o = 0; o < recog_data.n_operands; o++)
837           {
838             ra_debug_msg (DUMP_CONSTRAINTS,
839                        "%d:%s ", o, recog_data.constraints[o]);
840           }
841         if (constrain_operands (1))
842           ra_debug_msg (DUMP_CONSTRAINTS, "matches strictly alternative %d",
843                      which_alternative);
844         else
845           ra_debug_msg (DUMP_CONSTRAINTS, "doesn't match strictly");
846         ra_debug_msg (DUMP_CONSTRAINTS, "\n");
847       }
848   for (i = FIRST_PSEUDO_REGISTER; i < ra_max_regno; i++)
849     if (regno_reg_rtx[i] && GET_CODE (regno_reg_rtx[i]) == REG)
850       REGNO (regno_reg_rtx[i]) = i;
851 }
852
853 /* This counts and emits the cumulated cost of all spilled webs,
854    preceded by a custom message MSG, with debug level LEVEL.  */
855
856 void
857 dump_graph_cost (level, msg)
858      unsigned int level;
859      const char *msg;
860 {
861   unsigned int i;
862   unsigned HOST_WIDE_INT cost;
863   if (!rtl_dump_file || (debug_new_regalloc & level) == 0)
864     return;
865
866   cost = 0;
867   for (i = 0; i < num_webs; i++)
868     {
869       struct web *web = id2web[i];
870       if (alias (web)->type == SPILLED)
871         cost += web->orig_spill_cost;
872     }
873   ra_debug_msg (level, " spill cost of graph (%s) = "
874                 HOST_WIDE_INT_PRINT_UNSIGNED "\n",
875                 msg ? msg : "", cost);
876 }
877
878 /* Dump the color assignment per web, the coalesced and spilled webs.  */
879
880 void
881 dump_ra (df)
882      struct df *df ATTRIBUTE_UNUSED;
883 {
884   struct web *web;
885   struct dlist *d;
886   if (!rtl_dump_file || (debug_new_regalloc & DUMP_RESULTS) == 0)
887     return;
888
889   ra_debug_msg (DUMP_RESULTS, "\nColored:\n");
890   for (d = WEBS(COLORED); d; d = d->next)
891     {
892       web = DLIST_WEB (d);
893       ra_debug_msg (DUMP_RESULTS, "  %4d : color %d\n", web->id, web->color);
894     }
895   ra_debug_msg (DUMP_RESULTS, "\nCoalesced:\n");
896   for (d = WEBS(COALESCED); d; d = d->next)
897     {
898       web = DLIST_WEB (d);
899       ra_debug_msg (DUMP_RESULTS, "  %4d : to web %d, color %d\n", web->id,
900                  alias (web)->id, web->color);
901     }
902   ra_debug_msg (DUMP_RESULTS, "\nSpilled:\n");
903   for (d = WEBS(SPILLED); d; d = d->next)
904     {
905       web = DLIST_WEB (d);
906       ra_debug_msg (DUMP_RESULTS, "  %4d\n", web->id);
907     }
908   ra_debug_msg (DUMP_RESULTS, "\n");
909   dump_cost (DUMP_RESULTS);
910 }
911
912 /* Calculate and dump the cumulated costs of certain types of insns
913    (loads, stores and copies).  */
914
915 void
916 dump_static_insn_cost (file, message, prefix)
917      FILE *file;
918      const char *message;
919      const char *prefix;
920 {
921   struct cost
922     {
923       unsigned HOST_WIDE_INT cost;
924       unsigned int count;
925     };
926   basic_block bb;
927   struct cost load, store, regcopy, selfcopy, overall;
928   memset (&load, 0, sizeof(load));
929   memset (&store, 0, sizeof(store));
930   memset (&regcopy, 0, sizeof(regcopy));
931   memset (&selfcopy, 0, sizeof(selfcopy));
932   memset (&overall, 0, sizeof(overall));
933
934   if (!file)
935     return;
936
937   FOR_EACH_BB (bb)
938     {
939       unsigned HOST_WIDE_INT block_cost = bb->frequency;
940       rtx insn, set;
941       for (insn = bb->head; insn; insn = NEXT_INSN (insn))
942         {
943           /* Yes, yes.  We don't calculate the costs precisely.
944              Only for "simple enough" insns.  Those containing single
945              sets only.  */
946           if (INSN_P (insn) && ((set = single_set (insn)) != NULL))
947             {
948               rtx src = SET_SRC (set);
949               rtx dest = SET_DEST (set);
950               struct cost *pcost = NULL;
951               overall.cost += block_cost;
952               overall.count++;
953               if (rtx_equal_p (src, dest))
954                 pcost = &selfcopy;
955               else if (GET_CODE (src) == GET_CODE (dest)
956                        && ((GET_CODE (src) == REG)
957                            || (GET_CODE (src) == SUBREG
958                                && GET_CODE (SUBREG_REG (src)) == REG
959                                && GET_CODE (SUBREG_REG (dest)) == REG)))
960                 pcost = &regcopy;
961               else
962                 {
963                   if (GET_CODE (src) == SUBREG)
964                     src = SUBREG_REG (src);
965                   if (GET_CODE (dest) == SUBREG)
966                     dest = SUBREG_REG (dest);
967                   if (GET_CODE (src) == MEM && GET_CODE (dest) != MEM
968                       && memref_is_stack_slot (src))
969                     pcost = &load;
970                   else if (GET_CODE (src) != MEM && GET_CODE (dest) == MEM
971                            && memref_is_stack_slot (dest))
972                     pcost = &store;
973                 }
974               if (pcost)
975                 {
976                   pcost->cost += block_cost;
977                   pcost->count++;
978                 }
979             }
980           if (insn == bb->end)
981             break;
982         }
983     }
984
985   if (!prefix)
986     prefix = "";
987   fprintf (file, "static insn cost %s\n", message ? message : "");
988   fprintf (file, "  %soverall:\tnum=%6d\tcost="
989            HOST_WIDE_INT_PRINT_DEC_SPACE "\n",
990            prefix, overall.count, 8, overall.cost);
991   fprintf (file, "  %sloads:\tnum=%6d\tcost="
992            HOST_WIDE_INT_PRINT_DEC_SPACE "\n",
993            prefix, load.count, 8, load.cost);
994   fprintf (file, "  %sstores:\tnum=%6d\tcost="
995            HOST_WIDE_INT_PRINT_DEC_SPACE "\n",
996            prefix, store.count, 8, store.cost);
997   fprintf (file, "  %sregcopy:\tnum=%6d\tcost="
998            HOST_WIDE_INT_PRINT_DEC_SPACE "\n",
999            prefix, regcopy.count, 8, regcopy.cost);
1000   fprintf (file, "  %sselfcpy:\tnum=%6d\tcost="
1001            HOST_WIDE_INT_PRINT_DEC_SPACE "\n",
1002            prefix, selfcopy.count, 8, selfcopy.cost);
1003 }
1004
1005 /* Returns nonzero, if WEB1 and WEB2 have some possible
1006    hardregs in common.  */
1007
1008 int
1009 web_conflicts_p (web1, web2)
1010      struct web *web1;
1011      struct web *web2;
1012 {
1013   if (web1->type == PRECOLORED && web2->type == PRECOLORED)
1014     return 0;
1015
1016   if (web1->type == PRECOLORED)
1017     return TEST_HARD_REG_BIT (web2->usable_regs, web1->regno);
1018
1019   if (web2->type == PRECOLORED)
1020     return TEST_HARD_REG_BIT (web1->usable_regs, web2->regno);
1021
1022   return hard_regs_intersect_p (&web1->usable_regs, &web2->usable_regs);
1023 }
1024
1025 /* Dump all uids of insns in which WEB is mentioned.  */
1026
1027 void
1028 dump_web_insns (web)
1029      struct web *web;
1030 {
1031   unsigned int i;
1032
1033   ra_debug_msg (DUMP_EVER, "Web: %i(%i)+%i class: %s freedom: %i degree %i\n",
1034              web->id, web->regno, web->add_hardregs,
1035              reg_class_names[web->regclass],
1036              web->num_freedom, web->num_conflicts);
1037   ra_debug_msg (DUMP_EVER, "   def insns:");
1038
1039   for (i = 0; i < web->num_defs; ++i)
1040     {
1041       ra_debug_msg (DUMP_EVER, " %d ", INSN_UID (web->defs[i]->insn));
1042     }
1043
1044   ra_debug_msg (DUMP_EVER, "\n   use insns:");
1045   for (i = 0; i < web->num_uses; ++i)
1046     {
1047       ra_debug_msg (DUMP_EVER, " %d ", INSN_UID (web->uses[i]->insn));
1048     }
1049   ra_debug_msg (DUMP_EVER, "\n");
1050 }
1051
1052 /* Dump conflicts for web WEB.  */
1053
1054 void
1055 dump_web_conflicts (web)
1056      struct web *web;
1057 {
1058   int num = 0;
1059   unsigned int def2;
1060
1061   ra_debug_msg (DUMP_EVER, "Web: %i(%i)+%i class: %s freedom: %i degree %i\n",
1062              web->id, web->regno, web->add_hardregs,
1063              reg_class_names[web->regclass],
1064              web->num_freedom, web->num_conflicts);
1065
1066   for (def2 = 0; def2 < num_webs; def2++)
1067     if (TEST_BIT (igraph, igraph_index (web->id, def2)) && web->id != def2)
1068       {
1069         if ((num % 9) == 5)
1070           ra_debug_msg (DUMP_EVER, "\n             ");
1071         num++;
1072
1073         ra_debug_msg (DUMP_EVER, " %d(%d)", def2, id2web[def2]->regno);
1074         if (id2web[def2]->add_hardregs)
1075           ra_debug_msg (DUMP_EVER, "+%d", id2web[def2]->add_hardregs);
1076
1077         if (web_conflicts_p (web, id2web[def2]))
1078           ra_debug_msg (DUMP_EVER, "/x");
1079
1080         if (id2web[def2]->type == SELECT)
1081           ra_debug_msg (DUMP_EVER, "/s");
1082
1083         if (id2web[def2]->type == COALESCED)
1084           ra_debug_msg (DUMP_EVER,"/c/%d", alias (id2web[def2])->id);
1085       }
1086   ra_debug_msg (DUMP_EVER, "\n");
1087   {
1088     struct conflict_link *wl;
1089     num = 0;
1090     ra_debug_msg (DUMP_EVER, "By conflicts:     ");
1091     for (wl = web->conflict_list; wl; wl = wl->next)
1092       {
1093         struct web* w = wl->t;
1094         if ((num % 9) == 8)
1095           ra_debug_msg (DUMP_EVER, "\n              ");
1096         num++;
1097         ra_debug_msg (DUMP_EVER, "%d(%d)%s ", w->id, w->regno,
1098                    web_conflicts_p (web, w) ? "+" : "");
1099       }
1100     ra_debug_msg (DUMP_EVER, "\n");
1101   }
1102 }
1103
1104 /* Output HARD_REG_SET to stderr.  */
1105
1106 void
1107 debug_hard_reg_set (set)
1108      HARD_REG_SET set;
1109 {
1110   int i;
1111   for (i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
1112     {
1113       if (TEST_HARD_REG_BIT (set, i))
1114         {
1115           fprintf (stderr, "%s ", reg_names[i]);
1116         }
1117     }
1118   fprintf (stderr, "\n");
1119 }
1120
1121 /*
1122 vim:cinoptions={.5s,g0,p5,t0,(0,^-0.5s,n-0.5s:tw=78:cindent:sw=4:
1123 */