OSDN Git Service

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