OSDN Git Service

2001-11-11 H.J. Lu <hjl@gnu.org>
[pf3gnuchains/gcc-fork.git] / gcc / sched-vis.c
1 /* Instruction scheduling pass.
2    Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998,
3    1999, 2000 Free Software Foundation, Inc.
4    Contributed by Michael Tiemann (tiemann@cygnus.com) Enhanced by,
5    and currently maintained by, Jim Wilson (wilson@cygnus.com)
6
7 This file is part of GCC.
8
9 GCC is free software; you can redistribute it and/or modify it under
10 the terms of the GNU General Public License as published by the Free
11 Software Foundation; either version 2, or (at your option) any later
12 version.
13
14 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
15 WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
17 for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with GCC; see the file COPYING.  If not, write to the Free
21 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
22 02111-1307, USA.  */
23 \f
24 #include "config.h"
25 #include "system.h"
26 #include "toplev.h"
27 #include "rtl.h"
28 #include "tm_p.h"
29 #include "regs.h"
30 #include "hard-reg-set.h"
31 #include "basic-block.h"
32 #include "insn-attr.h"
33 #include "sched-int.h"
34
35 #ifdef INSN_SCHEDULING
36 /* target_units bitmask has 1 for each unit in the cpu.  It should be
37    possible to compute this variable from the machine description.
38    But currently it is computed by examining the insn list.  Since
39    this is only needed for visualization, it seems an acceptable
40    solution.  (For understanding the mapping of bits to units, see
41    definition of function_units[] in "insn-attrtab.c".)  */
42
43 static int target_units = 0;
44
45 static char *safe_concat PARAMS ((char *, char *, const char *));
46 static int get_visual_tbl_length PARAMS ((void));
47 static void print_exp PARAMS ((char *, rtx, int));
48 static void print_value PARAMS ((char *, rtx, int));
49 static void print_pattern PARAMS ((char *, rtx, int));
50 static void print_insn PARAMS ((char *, rtx, int));
51
52 /* Print names of units on which insn can/should execute, for debugging.  */
53
54 void
55 insn_print_units (insn)
56      rtx insn;
57 {
58   int i;
59   int unit = insn_unit (insn);
60
61   if (unit == -1)
62     fprintf (sched_dump, "none");
63   else if (unit >= 0)
64     fprintf (sched_dump, "%s", function_units[unit].name);
65   else
66     {
67       fprintf (sched_dump, "[");
68       for (i = 0, unit = ~unit; unit; i++, unit >>= 1)
69         if (unit & 1)
70           {
71             fprintf (sched_dump, "%s", function_units[i].name);
72             if (unit != 1)
73               fprintf (sched_dump, " ");
74           }
75       fprintf (sched_dump, "]");
76     }
77 }
78
79 /* MAX_VISUAL_LINES is the maximum number of lines in visualization table
80    of a basic block.  If more lines are needed, table is splitted to two.
81    n_visual_lines is the number of lines printed so far for a block.
82    visual_tbl contains the block visualization info.
83    vis_no_unit holds insns in a cycle that are not mapped to any unit.  */
84 #define MAX_VISUAL_LINES 100
85 #define INSN_LEN 30
86 int n_visual_lines;
87 static unsigned visual_tbl_line_length;
88 char *visual_tbl;
89 int n_vis_no_unit;
90 #define MAX_VISUAL_NO_UNIT 20
91 rtx vis_no_unit[MAX_VISUAL_NO_UNIT];
92
93 /* Finds units that are in use in this function.  Required only
94    for visualization.  */
95
96 void
97 init_target_units ()
98 {
99   rtx insn;
100   int unit;
101
102   for (insn = get_last_insn (); insn; insn = PREV_INSN (insn))
103     {
104       if (! INSN_P (insn))
105         continue;
106
107       unit = insn_unit (insn);
108
109       if (unit < 0)
110         target_units |= ~unit;
111       else
112         target_units |= (1 << unit);
113     }
114 }
115
116 /* Return the length of the visualization table.  */
117
118 static int
119 get_visual_tbl_length ()
120 {
121   int unit, i;
122   int n, n1;
123   char *s;
124
125   /* Compute length of one field in line.  */
126   s = (char *) alloca (INSN_LEN + 6);
127   sprintf (s, "  %33s", "uname");
128   n1 = strlen (s);
129
130   /* Compute length of one line.  */
131   n = strlen (";; ");
132   n += n1;
133   for (unit = 0; unit < FUNCTION_UNITS_SIZE; unit++)
134     if (function_units[unit].bitmask & target_units)
135       for (i = 0; i < function_units[unit].multiplicity; i++)
136         n += n1;
137   n += n1;
138   n += strlen ("\n") + 2;
139
140   visual_tbl_line_length = n;
141
142   /* Compute length of visualization string.  */
143   return (MAX_VISUAL_LINES * n);
144 }
145
146 /* Init block visualization debugging info.  */
147
148 void
149 init_block_visualization ()
150 {
151   strcpy (visual_tbl, "");
152   n_visual_lines = 0;
153   n_vis_no_unit = 0;
154 }
155
156 #define BUF_LEN 2048
157
158 static char *
159 safe_concat (buf, cur, str)
160      char *buf;
161      char *cur;
162      const char *str;
163 {
164   char *end = buf + BUF_LEN - 2;        /* Leave room for null.  */
165   int c;
166
167   if (cur > end)
168     {
169       *end = '\0';
170       return end;
171     }
172
173   while (cur < end && (c = *str++) != '\0')
174     *cur++ = c;
175
176   *cur = '\0';
177   return cur;
178 }
179
180 /* This recognizes rtx, I classified as expressions.  These are always
181    represent some action on values or results of other expression, that
182    may be stored in objects representing values.  */
183
184 static void
185 print_exp (buf, x, verbose)
186      char *buf;
187      rtx x;
188      int verbose;
189 {
190   char tmp[BUF_LEN];
191   const char *st[4];
192   char *cur = buf;
193   const char *fun = (char *) 0;
194   const char *sep;
195   rtx op[4];
196   int i;
197
198   for (i = 0; i < 4; i++)
199     {
200       st[i] = (char *) 0;
201       op[i] = NULL_RTX;
202     }
203
204   switch (GET_CODE (x))
205     {
206     case PLUS:
207       op[0] = XEXP (x, 0);
208       if (GET_CODE (XEXP (x, 1)) == CONST_INT
209           && INTVAL (XEXP (x, 1)) < 0)
210         {
211           st[1] = "-";
212           op[1] = GEN_INT (-INTVAL (XEXP (x, 1)));
213         }
214       else
215         {
216           st[1] = "+";
217           op[1] = XEXP (x, 1);
218         }
219       break;
220     case LO_SUM:
221       op[0] = XEXP (x, 0);
222       st[1] = "+low(";
223       op[1] = XEXP (x, 1);
224       st[2] = ")";
225       break;
226     case MINUS:
227       op[0] = XEXP (x, 0);
228       st[1] = "-";
229       op[1] = XEXP (x, 1);
230       break;
231     case COMPARE:
232       fun = "cmp";
233       op[0] = XEXP (x, 0);
234       op[1] = XEXP (x, 1);
235       break;
236     case NEG:
237       st[0] = "-";
238       op[0] = XEXP (x, 0);
239       break;
240     case MULT:
241       op[0] = XEXP (x, 0);
242       st[1] = "*";
243       op[1] = XEXP (x, 1);
244       break;
245     case DIV:
246       op[0] = XEXP (x, 0);
247       st[1] = "/";
248       op[1] = XEXP (x, 1);
249       break;
250     case UDIV:
251       fun = "udiv";
252       op[0] = XEXP (x, 0);
253       op[1] = XEXP (x, 1);
254       break;
255     case MOD:
256       op[0] = XEXP (x, 0);
257       st[1] = "%";
258       op[1] = XEXP (x, 1);
259       break;
260     case UMOD:
261       fun = "umod";
262       op[0] = XEXP (x, 0);
263       op[1] = XEXP (x, 1);
264       break;
265     case SMIN:
266       fun = "smin";
267       op[0] = XEXP (x, 0);
268       op[1] = XEXP (x, 1);
269       break;
270     case SMAX:
271       fun = "smax";
272       op[0] = XEXP (x, 0);
273       op[1] = XEXP (x, 1);
274       break;
275     case UMIN:
276       fun = "umin";
277       op[0] = XEXP (x, 0);
278       op[1] = XEXP (x, 1);
279       break;
280     case UMAX:
281       fun = "umax";
282       op[0] = XEXP (x, 0);
283       op[1] = XEXP (x, 1);
284       break;
285     case NOT:
286       st[0] = "!";
287       op[0] = XEXP (x, 0);
288       break;
289     case AND:
290       op[0] = XEXP (x, 0);
291       st[1] = "&";
292       op[1] = XEXP (x, 1);
293       break;
294     case IOR:
295       op[0] = XEXP (x, 0);
296       st[1] = "|";
297       op[1] = XEXP (x, 1);
298       break;
299     case XOR:
300       op[0] = XEXP (x, 0);
301       st[1] = "^";
302       op[1] = XEXP (x, 1);
303       break;
304     case ASHIFT:
305       op[0] = XEXP (x, 0);
306       st[1] = "<<";
307       op[1] = XEXP (x, 1);
308       break;
309     case LSHIFTRT:
310       op[0] = XEXP (x, 0);
311       st[1] = " 0>>";
312       op[1] = XEXP (x, 1);
313       break;
314     case ASHIFTRT:
315       op[0] = XEXP (x, 0);
316       st[1] = ">>";
317       op[1] = XEXP (x, 1);
318       break;
319     case ROTATE:
320       op[0] = XEXP (x, 0);
321       st[1] = "<-<";
322       op[1] = XEXP (x, 1);
323       break;
324     case ROTATERT:
325       op[0] = XEXP (x, 0);
326       st[1] = ">->";
327       op[1] = XEXP (x, 1);
328       break;
329     case ABS:
330       fun = "abs";
331       op[0] = XEXP (x, 0);
332       break;
333     case SQRT:
334       fun = "sqrt";
335       op[0] = XEXP (x, 0);
336       break;
337     case FFS:
338       fun = "ffs";
339       op[0] = XEXP (x, 0);
340       break;
341     case EQ:
342       op[0] = XEXP (x, 0);
343       st[1] = "==";
344       op[1] = XEXP (x, 1);
345       break;
346     case NE:
347       op[0] = XEXP (x, 0);
348       st[1] = "!=";
349       op[1] = XEXP (x, 1);
350       break;
351     case GT:
352       op[0] = XEXP (x, 0);
353       st[1] = ">";
354       op[1] = XEXP (x, 1);
355       break;
356     case GTU:
357       fun = "gtu";
358       op[0] = XEXP (x, 0);
359       op[1] = XEXP (x, 1);
360       break;
361     case LT:
362       op[0] = XEXP (x, 0);
363       st[1] = "<";
364       op[1] = XEXP (x, 1);
365       break;
366     case LTU:
367       fun = "ltu";
368       op[0] = XEXP (x, 0);
369       op[1] = XEXP (x, 1);
370       break;
371     case GE:
372       op[0] = XEXP (x, 0);
373       st[1] = ">=";
374       op[1] = XEXP (x, 1);
375       break;
376     case GEU:
377       fun = "geu";
378       op[0] = XEXP (x, 0);
379       op[1] = XEXP (x, 1);
380       break;
381     case LE:
382       op[0] = XEXP (x, 0);
383       st[1] = "<=";
384       op[1] = XEXP (x, 1);
385       break;
386     case LEU:
387       fun = "leu";
388       op[0] = XEXP (x, 0);
389       op[1] = XEXP (x, 1);
390       break;
391     case SIGN_EXTRACT:
392       fun = (verbose) ? "sign_extract" : "sxt";
393       op[0] = XEXP (x, 0);
394       op[1] = XEXP (x, 1);
395       op[2] = XEXP (x, 2);
396       break;
397     case ZERO_EXTRACT:
398       fun = (verbose) ? "zero_extract" : "zxt";
399       op[0] = XEXP (x, 0);
400       op[1] = XEXP (x, 1);
401       op[2] = XEXP (x, 2);
402       break;
403     case SIGN_EXTEND:
404       fun = (verbose) ? "sign_extend" : "sxn";
405       op[0] = XEXP (x, 0);
406       break;
407     case ZERO_EXTEND:
408       fun = (verbose) ? "zero_extend" : "zxn";
409       op[0] = XEXP (x, 0);
410       break;
411     case FLOAT_EXTEND:
412       fun = (verbose) ? "float_extend" : "fxn";
413       op[0] = XEXP (x, 0);
414       break;
415     case TRUNCATE:
416       fun = (verbose) ? "trunc" : "trn";
417       op[0] = XEXP (x, 0);
418       break;
419     case FLOAT_TRUNCATE:
420       fun = (verbose) ? "float_trunc" : "ftr";
421       op[0] = XEXP (x, 0);
422       break;
423     case FLOAT:
424       fun = (verbose) ? "float" : "flt";
425       op[0] = XEXP (x, 0);
426       break;
427     case UNSIGNED_FLOAT:
428       fun = (verbose) ? "uns_float" : "ufl";
429       op[0] = XEXP (x, 0);
430       break;
431     case FIX:
432       fun = "fix";
433       op[0] = XEXP (x, 0);
434       break;
435     case UNSIGNED_FIX:
436       fun = (verbose) ? "uns_fix" : "ufx";
437       op[0] = XEXP (x, 0);
438       break;
439     case PRE_DEC:
440       st[0] = "--";
441       op[0] = XEXP (x, 0);
442       break;
443     case PRE_INC:
444       st[0] = "++";
445       op[0] = XEXP (x, 0);
446       break;
447     case POST_DEC:
448       op[0] = XEXP (x, 0);
449       st[1] = "--";
450       break;
451     case POST_INC:
452       op[0] = XEXP (x, 0);
453       st[1] = "++";
454       break;
455     case CALL:
456       st[0] = "call ";
457       op[0] = XEXP (x, 0);
458       if (verbose)
459         {
460           st[1] = " argc:";
461           op[1] = XEXP (x, 1);
462         }
463       break;
464     case IF_THEN_ELSE:
465       st[0] = "{(";
466       op[0] = XEXP (x, 0);
467       st[1] = ")?";
468       op[1] = XEXP (x, 1);
469       st[2] = ":";
470       op[2] = XEXP (x, 2);
471       st[3] = "}";
472       break;
473     case TRAP_IF:
474       fun = "trap_if";
475       op[0] = TRAP_CONDITION (x);
476       break;
477     case UNSPEC:
478     case UNSPEC_VOLATILE:
479       {
480         cur = safe_concat (buf, cur, "unspec");
481         if (GET_CODE (x) == UNSPEC_VOLATILE)
482           cur = safe_concat (buf, cur, "/v");
483         cur = safe_concat (buf, cur, "[");
484         sep = "";
485         for (i = 0; i < XVECLEN (x, 0); i++)
486           {
487             print_pattern (tmp, XVECEXP (x, 0, i), verbose);
488             cur = safe_concat (buf, cur, sep);
489             cur = safe_concat (buf, cur, tmp);
490             sep = ",";
491           }
492         cur = safe_concat (buf, cur, "] ");
493         sprintf (tmp, "%d", XINT (x, 1));
494         cur = safe_concat (buf, cur, tmp);
495       }
496       break;
497     default:
498       /* If (verbose) debug_rtx (x);  */
499       st[0] = GET_RTX_NAME (GET_CODE (x));
500       break;
501     }
502
503   /* Print this as a function?  */
504   if (fun)
505     {
506       cur = safe_concat (buf, cur, fun);
507       cur = safe_concat (buf, cur, "(");
508     }
509
510   for (i = 0; i < 4; i++)
511     {
512       if (st[i])
513         cur = safe_concat (buf, cur, st[i]);
514
515       if (op[i])
516         {
517           if (fun && i != 0)
518             cur = safe_concat (buf, cur, ",");
519
520           print_value (tmp, op[i], verbose);
521           cur = safe_concat (buf, cur, tmp);
522         }
523     }
524
525   if (fun)
526     cur = safe_concat (buf, cur, ")");
527 }               /* print_exp */
528
529 /* Prints rtxes, I customly classified as values.  They're constants,
530    registers, labels, symbols and memory accesses.  */
531
532 static void
533 print_value (buf, x, verbose)
534      char *buf;
535      rtx x;
536      int verbose;
537 {
538   char t[BUF_LEN];
539   char *cur = buf;
540
541   switch (GET_CODE (x))
542     {
543     case CONST_INT:
544       sprintf (t, HOST_WIDE_INT_PRINT_HEX, INTVAL (x));
545       cur = safe_concat (buf, cur, t);
546       break;
547     case CONST_DOUBLE:
548       sprintf (t, "<0x%lx,0x%lx>", (long) XWINT (x, 2), (long) XWINT (x, 3));
549       cur = safe_concat (buf, cur, t);
550       break;
551     case CONST_STRING:
552       cur = safe_concat (buf, cur, "\"");
553       cur = safe_concat (buf, cur, XSTR (x, 0));
554       cur = safe_concat (buf, cur, "\"");
555       break;
556     case SYMBOL_REF:
557       cur = safe_concat (buf, cur, "`");
558       cur = safe_concat (buf, cur, XSTR (x, 0));
559       cur = safe_concat (buf, cur, "'");
560       break;
561     case LABEL_REF:
562       sprintf (t, "L%d", INSN_UID (XEXP (x, 0)));
563       cur = safe_concat (buf, cur, t);
564       break;
565     case CONST:
566       print_value (t, XEXP (x, 0), verbose);
567       cur = safe_concat (buf, cur, "const(");
568       cur = safe_concat (buf, cur, t);
569       cur = safe_concat (buf, cur, ")");
570       break;
571     case HIGH:
572       print_value (t, XEXP (x, 0), verbose);
573       cur = safe_concat (buf, cur, "high(");
574       cur = safe_concat (buf, cur, t);
575       cur = safe_concat (buf, cur, ")");
576       break;
577     case REG:
578       if (REGNO (x) < FIRST_PSEUDO_REGISTER)
579         {
580           int c = reg_names[REGNO (x)][0];
581           if (ISDIGIT (c))
582             cur = safe_concat (buf, cur, "%");
583
584           cur = safe_concat (buf, cur, reg_names[REGNO (x)]);
585         }
586       else
587         {
588           sprintf (t, "r%d", REGNO (x));
589           cur = safe_concat (buf, cur, t);
590         }
591       break;
592     case SUBREG:
593       print_value (t, SUBREG_REG (x), verbose);
594       cur = safe_concat (buf, cur, t);
595       sprintf (t, "#%d", SUBREG_BYTE (x));
596       cur = safe_concat (buf, cur, t);
597       break;
598     case SCRATCH:
599       cur = safe_concat (buf, cur, "scratch");
600       break;
601     case CC0:
602       cur = safe_concat (buf, cur, "cc0");
603       break;
604     case PC:
605       cur = safe_concat (buf, cur, "pc");
606       break;
607     case MEM:
608       print_value (t, XEXP (x, 0), verbose);
609       cur = safe_concat (buf, cur, "[");
610       cur = safe_concat (buf, cur, t);
611       cur = safe_concat (buf, cur, "]");
612       break;
613     default:
614       print_exp (t, x, verbose);
615       cur = safe_concat (buf, cur, t);
616       break;
617     }
618 }                               /* print_value */
619
620 /* The next step in insn detalization, its pattern recognition.  */
621
622 static void
623 print_pattern (buf, x, verbose)
624      char *buf;
625      rtx x;
626      int verbose;
627 {
628   char t1[BUF_LEN], t2[BUF_LEN], t3[BUF_LEN];
629
630   switch (GET_CODE (x))
631     {
632     case SET:
633       print_value (t1, SET_DEST (x), verbose);
634       print_value (t2, SET_SRC (x), verbose);
635       sprintf (buf, "%s=%s", t1, t2);
636       break;
637     case RETURN:
638       sprintf (buf, "return");
639       break;
640     case CALL:
641       print_exp (buf, x, verbose);
642       break;
643     case CLOBBER:
644       print_value (t1, XEXP (x, 0), verbose);
645       sprintf (buf, "clobber %s", t1);
646       break;
647     case USE:
648       print_value (t1, XEXP (x, 0), verbose);
649       sprintf (buf, "use %s", t1);
650       break;
651     case COND_EXEC:
652       if (GET_CODE (COND_EXEC_TEST (x)) == NE
653           && XEXP (COND_EXEC_TEST (x), 1) == const0_rtx)
654         print_value (t1, XEXP (COND_EXEC_TEST (x), 0), verbose);
655       else if (GET_CODE (COND_EXEC_TEST (x)) == EQ
656                && XEXP (COND_EXEC_TEST (x), 1) == const0_rtx)
657         {
658           t1[0] = '!';
659           print_value (t1 + 1, XEXP (COND_EXEC_TEST (x), 0), verbose);
660         }
661       else
662         print_value (t1, COND_EXEC_TEST (x), verbose);
663       print_pattern (t2, COND_EXEC_CODE (x), verbose);
664       sprintf (buf, "(%s) %s", t1, t2);
665       break;
666     case PARALLEL:
667       {
668         int i;
669
670         sprintf (t1, "{");
671         for (i = 0; i < XVECLEN (x, 0); i++)
672           {
673             print_pattern (t2, XVECEXP (x, 0, i), verbose);
674             sprintf (t3, "%s%s;", t1, t2);
675             strcpy (t1, t3);
676           }
677         sprintf (buf, "%s}", t1);
678       }
679       break;
680     case SEQUENCE:
681       {
682         int i;
683
684         sprintf (t1, "%%{");
685         for (i = 0; i < XVECLEN (x, 0); i++)
686           {
687             print_insn (t2, XVECEXP (x, 0, i), verbose);
688             sprintf (t3, "%s%s;", t1, t2);
689             strcpy (t1, t3);
690           }
691         sprintf (buf, "%s%%}", t1);
692       }
693       break;
694     case ASM_INPUT:
695       sprintf (buf, "asm {%s}", XSTR (x, 0));
696       break;
697     case ADDR_VEC:
698       break;
699     case ADDR_DIFF_VEC:
700       print_value (buf, XEXP (x, 0), verbose);
701       break;
702     case TRAP_IF:
703       print_value (t1, TRAP_CONDITION (x), verbose);
704       sprintf (buf, "trap_if %s", t1);
705       break;
706     case UNSPEC:
707       {
708         int i;
709
710         sprintf (t1, "unspec{");
711         for (i = 0; i < XVECLEN (x, 0); i++)
712           {
713             print_pattern (t2, XVECEXP (x, 0, i), verbose);
714             sprintf (t3, "%s%s;", t1, t2);
715             strcpy (t1, t3);
716           }
717         sprintf (buf, "%s}", t1);
718       }
719       break;
720     case UNSPEC_VOLATILE:
721       {
722         int i;
723
724         sprintf (t1, "unspec/v{");
725         for (i = 0; i < XVECLEN (x, 0); i++)
726           {
727             print_pattern (t2, XVECEXP (x, 0, i), verbose);
728             sprintf (t3, "%s%s;", t1, t2);
729             strcpy (t1, t3);
730           }
731         sprintf (buf, "%s}", t1);
732       }
733       break;
734     default:
735       print_value (buf, x, verbose);
736     }
737 }                               /* print_pattern */
738
739 /* This is the main function in rtl visualization mechanism. It
740    accepts an rtx and tries to recognize it as an insn, then prints it
741    properly in human readable form, resembling assembler mnemonics.
742    For every insn it prints its UID and BB the insn belongs too.
743    (Probably the last "option" should be extended somehow, since it
744    depends now on sched.c inner variables ...)  */
745
746 static void
747 print_insn (buf, x, verbose)
748      char *buf;
749      rtx x;
750      int verbose;
751 {
752   char t[BUF_LEN];
753   rtx insn = x;
754
755   switch (GET_CODE (x))
756     {
757     case INSN:
758       print_pattern (t, PATTERN (x), verbose);
759       if (verbose)
760         sprintf (buf, "%s: %s", (*current_sched_info->print_insn) (x, 1),
761                  t);
762       else
763         sprintf (buf, "%-4d %s", INSN_UID (x), t);
764       break;
765     case JUMP_INSN:
766       print_pattern (t, PATTERN (x), verbose);
767       if (verbose)
768         sprintf (buf, "%s: jump %s", (*current_sched_info->print_insn) (x, 1),
769                  t);
770       else
771         sprintf (buf, "%-4d %s", INSN_UID (x), t);
772       break;
773     case CALL_INSN:
774       x = PATTERN (insn);
775       if (GET_CODE (x) == PARALLEL)
776         {
777           x = XVECEXP (x, 0, 0);
778           print_pattern (t, x, verbose);
779         }
780       else
781         strcpy (t, "call <...>");
782       if (verbose)
783         sprintf (buf, "%s: %s", (*current_sched_info->print_insn) (x, 1), t);
784       else
785         sprintf (buf, "%-4d %s", INSN_UID (insn), t);
786       break;
787     case CODE_LABEL:
788       sprintf (buf, "L%d:", INSN_UID (x));
789       break;
790     case BARRIER:
791       sprintf (buf, "i% 4d: barrier", INSN_UID (x));
792       break;
793     case NOTE:
794       if (NOTE_LINE_NUMBER (x) > 0)
795         sprintf (buf, "%4d note \"%s\" %d", INSN_UID (x),
796                  NOTE_SOURCE_FILE (x), NOTE_LINE_NUMBER (x));
797       else
798         sprintf (buf, "%4d %s", INSN_UID (x),
799                  GET_NOTE_INSN_NAME (NOTE_LINE_NUMBER (x)));
800       break;
801     default:
802       if (verbose)
803         {
804           sprintf (buf, "Not an INSN at all\n");
805           debug_rtx (x);
806         }
807       else
808         sprintf (buf, "i%-4d  <What?>", INSN_UID (x));
809     }
810 }                               /* print_insn */
811
812 /* Print visualization debugging info.  */
813
814 void
815 print_block_visualization (s)
816      const char *s;
817 {
818   int unit, i;
819
820   /* Print header.  */
821   fprintf (sched_dump, "\n;;   ==================== scheduling visualization %s \n", s);
822
823   /* Print names of units.  */
824   fprintf (sched_dump, ";;   %-8s", "clock");
825   for (unit = 0; unit < FUNCTION_UNITS_SIZE; unit++)
826     if (function_units[unit].bitmask & target_units)
827       for (i = 0; i < function_units[unit].multiplicity; i++)
828         fprintf (sched_dump, "  %-33s", function_units[unit].name);
829   fprintf (sched_dump, "  %-8s\n", "no-unit");
830
831   fprintf (sched_dump, ";;   %-8s", "=====");
832   for (unit = 0; unit < FUNCTION_UNITS_SIZE; unit++)
833     if (function_units[unit].bitmask & target_units)
834       for (i = 0; i < function_units[unit].multiplicity; i++)
835         fprintf (sched_dump, "  %-33s", "==============================");
836   fprintf (sched_dump, "  %-8s\n", "=======");
837
838   /* Print insns in each cycle.  */
839   fprintf (sched_dump, "%s\n", visual_tbl);
840 }
841
842 /* Print insns in the 'no_unit' column of visualization.  */
843
844 void
845 visualize_no_unit (insn)
846      rtx insn;
847 {
848   if (n_vis_no_unit < MAX_VISUAL_NO_UNIT)
849     {
850       vis_no_unit[n_vis_no_unit] = insn;
851       n_vis_no_unit++;
852     }
853 }
854
855 /* Print insns scheduled in clock, for visualization.  */
856
857 void
858 visualize_scheduled_insns (clock)
859      int clock;
860 {
861   int i, unit;
862
863   /* If no more room, split table into two.  */
864   if (n_visual_lines >= MAX_VISUAL_LINES)
865     {
866       print_block_visualization ("(incomplete)");
867       init_block_visualization ();
868     }
869
870   n_visual_lines++;
871
872   sprintf (visual_tbl + strlen (visual_tbl), ";;   %-8d", clock);
873   for (unit = 0; unit < FUNCTION_UNITS_SIZE; unit++)
874     if (function_units[unit].bitmask & target_units)
875       for (i = 0; i < function_units[unit].multiplicity; i++)
876         {
877           int instance = unit + i * FUNCTION_UNITS_SIZE;
878           rtx insn = get_unit_last_insn (instance);
879
880           /* Print insns that still keep the unit busy.  */
881           if (insn
882               && actual_hazard_this_instance (unit, instance, insn, clock, 0))
883             {
884               char str[BUF_LEN];
885               print_insn (str, insn, 0);
886               str[INSN_LEN] = '\0';
887               sprintf (visual_tbl + strlen (visual_tbl), "  %-33s", str);
888             }
889           else
890             sprintf (visual_tbl + strlen (visual_tbl), "  %-33s", "------------------------------");
891         }
892
893   /* Print insns that are not assigned to any unit.  */
894   for (i = 0; i < n_vis_no_unit; i++)
895     sprintf (visual_tbl + strlen (visual_tbl), "  %-8d",
896              INSN_UID (vis_no_unit[i]));
897   n_vis_no_unit = 0;
898
899   sprintf (visual_tbl + strlen (visual_tbl), "\n");
900 }
901
902 /* Print stalled cycles.  */
903
904 void
905 visualize_stall_cycles (stalls)
906      int stalls;
907 {
908   static const char *const prefix = ";;       ";
909   const char *suffix = "\n";
910   char *p;
911
912   /* If no more room, split table into two.  */
913   if (n_visual_lines >= MAX_VISUAL_LINES)
914     {
915       print_block_visualization ("(incomplete)");
916       init_block_visualization ();
917     }
918
919   n_visual_lines++;
920
921   p = visual_tbl + strlen (visual_tbl);
922   strcpy (p, prefix);
923   p += strlen (prefix);
924
925   if ((unsigned)stalls >
926       visual_tbl_line_length - strlen (prefix) - strlen (suffix))
927     {
928       suffix = "[...]\n";
929       stalls = visual_tbl_line_length - strlen (prefix) - strlen (suffix);
930     }
931
932   memset (p, '.', stalls);
933   p += stalls;
934
935   strcpy (p, suffix);
936 }
937
938 /* Allocate data used for visualization during scheduling.  */
939
940 void
941 visualize_alloc ()
942 {
943   visual_tbl = xmalloc (get_visual_tbl_length ());
944 }
945
946 /* Free data used for visualization.  */
947
948 void
949 visualize_free ()
950 {
951   free (visual_tbl);
952 }
953 #endif