xref: /openbsd-src/gnu/usr.bin/gcc/gcc/sched-vis.c (revision c87b03e512fc05ed6e0222f6fb0ae86264b1d05b)
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 
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
insn_print_units(insn)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
init_target_units()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
get_visual_tbl_length()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
init_block_visualization()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 *
safe_concat(buf,cur,str)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
print_exp(buf,x,verbose)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
print_value(buf,x,verbose)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 	real_to_decimal (t, CONST_DOUBLE_REAL_VALUE (x), sizeof (t), 0, 1);
566       else
567 	sprintf (t, "<0x%lx,0x%lx>", (long) XWINT (x, 2), (long) XWINT (x, 3));
568       cur = safe_concat (buf, cur, t);
569       break;
570     case CONST_STRING:
571       cur = safe_concat (buf, cur, "\"");
572       cur = safe_concat (buf, cur, XSTR (x, 0));
573       cur = safe_concat (buf, cur, "\"");
574       break;
575     case SYMBOL_REF:
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 LABEL_REF:
581       sprintf (t, "L%d", INSN_UID (XEXP (x, 0)));
582       cur = safe_concat (buf, cur, t);
583       break;
584     case CONST:
585       print_value (t, XEXP (x, 0), verbose);
586       cur = safe_concat (buf, cur, "const(");
587       cur = safe_concat (buf, cur, t);
588       cur = safe_concat (buf, cur, ")");
589       break;
590     case HIGH:
591       print_value (t, XEXP (x, 0), verbose);
592       cur = safe_concat (buf, cur, "high(");
593       cur = safe_concat (buf, cur, t);
594       cur = safe_concat (buf, cur, ")");
595       break;
596     case REG:
597       if (REGNO (x) < FIRST_PSEUDO_REGISTER)
598 	{
599 	  int c = reg_names[REGNO (x)][0];
600 	  if (ISDIGIT (c))
601 	    cur = safe_concat (buf, cur, "%");
602 
603 	  cur = safe_concat (buf, cur, reg_names[REGNO (x)]);
604 	}
605       else
606 	{
607 	  sprintf (t, "r%d", REGNO (x));
608 	  cur = safe_concat (buf, cur, t);
609 	}
610       break;
611     case SUBREG:
612       print_value (t, SUBREG_REG (x), verbose);
613       cur = safe_concat (buf, cur, t);
614       sprintf (t, "#%d", SUBREG_BYTE (x));
615       cur = safe_concat (buf, cur, t);
616       break;
617     case SCRATCH:
618       cur = safe_concat (buf, cur, "scratch");
619       break;
620     case CC0:
621       cur = safe_concat (buf, cur, "cc0");
622       break;
623     case PC:
624       cur = safe_concat (buf, cur, "pc");
625       break;
626     case MEM:
627       print_value (t, XEXP (x, 0), verbose);
628       cur = safe_concat (buf, cur, "[");
629       cur = safe_concat (buf, cur, t);
630       cur = safe_concat (buf, cur, "]");
631       break;
632     default:
633       print_exp (t, x, verbose);
634       cur = safe_concat (buf, cur, t);
635       break;
636     }
637 }				/* print_value */
638 
639 /* The next step in insn detalization, its pattern recognition.  */
640 
641 static void
print_pattern(buf,x,verbose)642 print_pattern (buf, x, verbose)
643      char *buf;
644      rtx x;
645      int verbose;
646 {
647   char t1[BUF_LEN], t2[BUF_LEN], t3[BUF_LEN];
648 
649   switch (GET_CODE (x))
650     {
651     case SET:
652       print_value (t1, SET_DEST (x), verbose);
653       print_value (t2, SET_SRC (x), verbose);
654       sprintf (buf, "%s=%s", t1, t2);
655       break;
656     case RETURN:
657       sprintf (buf, "return");
658       break;
659     case CALL:
660       print_exp (buf, x, verbose);
661       break;
662     case CLOBBER:
663       print_value (t1, XEXP (x, 0), verbose);
664       sprintf (buf, "clobber %s", t1);
665       break;
666     case USE:
667       print_value (t1, XEXP (x, 0), verbose);
668       sprintf (buf, "use %s", t1);
669       break;
670     case COND_EXEC:
671       if (GET_CODE (COND_EXEC_TEST (x)) == NE
672 	  && XEXP (COND_EXEC_TEST (x), 1) == const0_rtx)
673 	print_value (t1, XEXP (COND_EXEC_TEST (x), 0), verbose);
674       else if (GET_CODE (COND_EXEC_TEST (x)) == EQ
675 	       && XEXP (COND_EXEC_TEST (x), 1) == const0_rtx)
676 	{
677 	  t1[0] = '!';
678 	  print_value (t1 + 1, XEXP (COND_EXEC_TEST (x), 0), verbose);
679 	}
680       else
681 	print_value (t1, COND_EXEC_TEST (x), verbose);
682       print_pattern (t2, COND_EXEC_CODE (x), verbose);
683       sprintf (buf, "(%s) %s", t1, t2);
684       break;
685     case PARALLEL:
686       {
687 	int i;
688 
689 	sprintf (t1, "{");
690 	for (i = 0; i < XVECLEN (x, 0); i++)
691 	  {
692 	    print_pattern (t2, XVECEXP (x, 0, i), verbose);
693 	    sprintf (t3, "%s%s;", t1, t2);
694 	    strcpy (t1, t3);
695 	  }
696 	sprintf (buf, "%s}", t1);
697       }
698       break;
699     case SEQUENCE:
700       /* Should never see SEQUENCE codes until after reorg.  */
701       abort ();
702       break;
703     case ASM_INPUT:
704       sprintf (buf, "asm {%s}", XSTR (x, 0));
705       break;
706     case ADDR_VEC:
707       break;
708     case ADDR_DIFF_VEC:
709       print_value (buf, XEXP (x, 0), verbose);
710       break;
711     case TRAP_IF:
712       print_value (t1, TRAP_CONDITION (x), verbose);
713       sprintf (buf, "trap_if %s", t1);
714       break;
715     case UNSPEC:
716       {
717 	int i;
718 
719 	sprintf (t1, "unspec{");
720 	for (i = 0; i < XVECLEN (x, 0); i++)
721 	  {
722 	    print_pattern (t2, XVECEXP (x, 0, i), verbose);
723 	    sprintf (t3, "%s%s;", t1, t2);
724 	    strcpy (t1, t3);
725 	  }
726 	sprintf (buf, "%s}", t1);
727       }
728       break;
729     case UNSPEC_VOLATILE:
730       {
731 	int i;
732 
733 	sprintf (t1, "unspec/v{");
734 	for (i = 0; i < XVECLEN (x, 0); i++)
735 	  {
736 	    print_pattern (t2, XVECEXP (x, 0, i), verbose);
737 	    sprintf (t3, "%s%s;", t1, t2);
738 	    strcpy (t1, t3);
739 	  }
740 	sprintf (buf, "%s}", t1);
741       }
742       break;
743     default:
744       print_value (buf, x, verbose);
745     }
746 }				/* print_pattern */
747 
748 /* This is the main function in rtl visualization mechanism. It
749    accepts an rtx and tries to recognize it as an insn, then prints it
750    properly in human readable form, resembling assembler mnemonics.
751    For every insn it prints its UID and BB the insn belongs too.
752    (Probably the last "option" should be extended somehow, since it
753    depends now on sched.c inner variables ...)  */
754 
755 void
print_insn(buf,x,verbose)756 print_insn (buf, x, verbose)
757      char *buf;
758      rtx x;
759      int verbose;
760 {
761   char t[BUF_LEN];
762   rtx insn = x;
763 
764   switch (GET_CODE (x))
765     {
766     case INSN:
767       print_pattern (t, PATTERN (x), verbose);
768       if (verbose)
769 	sprintf (buf, "%s: %s", (*current_sched_info->print_insn) (x, 1),
770 		 t);
771       else
772 	sprintf (buf, "%-4d %s", INSN_UID (x), t);
773       break;
774     case JUMP_INSN:
775       print_pattern (t, PATTERN (x), verbose);
776       if (verbose)
777 	sprintf (buf, "%s: jump %s", (*current_sched_info->print_insn) (x, 1),
778 		 t);
779       else
780 	sprintf (buf, "%-4d %s", INSN_UID (x), t);
781       break;
782     case CALL_INSN:
783       x = PATTERN (insn);
784       if (GET_CODE (x) == PARALLEL)
785 	{
786 	  x = XVECEXP (x, 0, 0);
787 	  print_pattern (t, x, verbose);
788 	}
789       else
790 	strcpy (t, "call <...>");
791       if (verbose)
792 	sprintf (buf, "%s: %s", (*current_sched_info->print_insn) (x, 1), t);
793       else
794 	sprintf (buf, "%-4d %s", INSN_UID (insn), t);
795       break;
796     case CODE_LABEL:
797       sprintf (buf, "L%d:", INSN_UID (x));
798       break;
799     case BARRIER:
800       sprintf (buf, "i% 4d: barrier", INSN_UID (x));
801       break;
802     case NOTE:
803       if (NOTE_LINE_NUMBER (x) > 0)
804 	sprintf (buf, "%4d note \"%s\" %d", INSN_UID (x),
805 		 NOTE_SOURCE_FILE (x), NOTE_LINE_NUMBER (x));
806       else
807 	sprintf (buf, "%4d %s", INSN_UID (x),
808 		 GET_NOTE_INSN_NAME (NOTE_LINE_NUMBER (x)));
809       break;
810     default:
811       if (verbose)
812 	{
813 	  sprintf (buf, "Not an INSN at all\n");
814 	  debug_rtx (x);
815 	}
816       else
817 	sprintf (buf, "i%-4d  <What?>", INSN_UID (x));
818     }
819 }				/* print_insn */
820 
821 /* Print visualization debugging info.  The scheduler using only DFA
822    description should never use the following function.  */
823 
824 void
print_block_visualization(s)825 print_block_visualization (s)
826      const char *s;
827 {
828   int unit, i;
829 
830   /* Print header.  */
831   fprintf (sched_dump, "\n;;   ==================== scheduling visualization %s \n", s);
832 
833   /* Print names of units.  */
834   fprintf (sched_dump, ";;   %-8s", "clock");
835   for (unit = 0; unit < FUNCTION_UNITS_SIZE; unit++)
836     if (function_units[unit].bitmask & target_units)
837       for (i = 0; i < function_units[unit].multiplicity; i++)
838 	fprintf (sched_dump, "  %-33s", function_units[unit].name);
839   fprintf (sched_dump, "  %-8s\n", "no-unit");
840 
841   fprintf (sched_dump, ";;   %-8s", "=====");
842   for (unit = 0; unit < FUNCTION_UNITS_SIZE; unit++)
843     if (function_units[unit].bitmask & target_units)
844       for (i = 0; i < function_units[unit].multiplicity; i++)
845 	fprintf (sched_dump, "  %-33s", "==============================");
846   fprintf (sched_dump, "  %-8s\n", "=======");
847 
848   /* Print insns in each cycle.  */
849   fprintf (sched_dump, "%s\n", visual_tbl);
850 }
851 
852 /* Print insns in the 'no_unit' column of visualization.  */
853 
854 void
visualize_no_unit(insn)855 visualize_no_unit (insn)
856      rtx insn;
857 {
858   if (n_vis_no_unit < MAX_VISUAL_NO_UNIT)
859     {
860       vis_no_unit[n_vis_no_unit] = insn;
861       n_vis_no_unit++;
862     }
863 }
864 
865 /* Print insns scheduled in clock, for visualization.  */
866 
867 void
visualize_scheduled_insns(clock)868 visualize_scheduled_insns (clock)
869      int clock;
870 {
871   int i, unit;
872 
873   /* If no more room, split table into two.  */
874   if (n_visual_lines >= MAX_VISUAL_LINES)
875     {
876       print_block_visualization ("(incomplete)");
877       init_block_visualization ();
878     }
879 
880   n_visual_lines++;
881 
882   sprintf (visual_tbl + strlen (visual_tbl), ";;   %-8d", clock);
883   for (unit = 0; unit < FUNCTION_UNITS_SIZE; unit++)
884     if (function_units[unit].bitmask & target_units)
885       for (i = 0; i < function_units[unit].multiplicity; i++)
886 	{
887 	  int instance = unit + i * FUNCTION_UNITS_SIZE;
888 	  rtx insn = get_unit_last_insn (instance);
889 
890 	  /* Print insns that still keep the unit busy.  */
891 	  if (insn
892 	      && actual_hazard_this_instance (unit, instance, insn, clock, 0))
893 	    {
894 	      char str[BUF_LEN];
895 	      print_insn (str, insn, 0);
896 	      str[INSN_LEN] = '\0';
897 	      sprintf (visual_tbl + strlen (visual_tbl), "  %-33s", str);
898 	    }
899 	  else
900 	    sprintf (visual_tbl + strlen (visual_tbl), "  %-33s", "------------------------------");
901 	}
902 
903   /* Print insns that are not assigned to any unit.  */
904   for (i = 0; i < n_vis_no_unit; i++)
905     sprintf (visual_tbl + strlen (visual_tbl), "  %-8d",
906 	     INSN_UID (vis_no_unit[i]));
907   n_vis_no_unit = 0;
908 
909   sprintf (visual_tbl + strlen (visual_tbl), "\n");
910 }
911 
912 /* Print stalled cycles.  */
913 
914 void
visualize_stall_cycles(stalls)915 visualize_stall_cycles (stalls)
916      int stalls;
917 {
918   static const char *const prefix = ";;       ";
919   const char *suffix = "\n";
920   char *p;
921 
922   /* If no more room, split table into two.  */
923   if (n_visual_lines >= MAX_VISUAL_LINES)
924     {
925       print_block_visualization ("(incomplete)");
926       init_block_visualization ();
927     }
928 
929   n_visual_lines++;
930 
931   p = visual_tbl + strlen (visual_tbl);
932   strcpy (p, prefix);
933   p += strlen (prefix);
934 
935   if ((unsigned) stalls >
936       visual_tbl_line_length - strlen (prefix) - strlen (suffix))
937     {
938       suffix = "[...]\n";
939       stalls = visual_tbl_line_length - strlen (prefix) - strlen (suffix);
940     }
941 
942   memset (p, '.', stalls);
943   p += stalls;
944 
945   strcpy (p, suffix);
946 }
947 
948 /* Allocate data used for visualization during scheduling.  */
949 
950 void
visualize_alloc()951 visualize_alloc ()
952 {
953   visual_tbl = xmalloc (get_visual_tbl_length ());
954 }
955 
956 /* Free data used for visualization.  */
957 
958 void
visualize_free()959 visualize_free ()
960 {
961   free (visual_tbl);
962 }
963 #endif
964