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