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