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