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