OSDN Git Service

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