rtl.def (DEFINE_CPU_UNIT, [...]): New RTL constructions.
[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 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 the
21 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 "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 fuction. 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 {
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 UNSPEC:
487 case UNSPEC_VOLATILE:
488 {
489 cur = safe_concat (buf, cur, "unspec");
490 if (GET_CODE (x) == UNSPEC_VOLATILE)
491 cur = safe_concat (buf, cur, "/v");
492 cur = safe_concat (buf, cur, "[");
493 sep = "";
494 for (i = 0; i < XVECLEN (x, 0); i++)
495 {
496 print_pattern (tmp, XVECEXP (x, 0, i), verbose);
497 cur = safe_concat (buf, cur, sep);
498 cur = safe_concat (buf, cur, tmp);
499 sep = ",";
500 }
501 cur = safe_concat (buf, cur, "] ");
502 sprintf (tmp, "%d", XINT (x, 1));
503 cur = safe_concat (buf, cur, tmp);
504 }
505 break;
506 default:
507 /* If (verbose) debug_rtx (x); */
508 st[0] = GET_RTX_NAME (GET_CODE (x));
509 break;
510 }
511
512 /* Print this as a function? */
513 if (fun)
514 {
515 cur = safe_concat (buf, cur, fun);
516 cur = safe_concat (buf, cur, "(");
517 }
518
519 for (i = 0; i < 4; i++)
520 {
521 if (st[i])
522 cur = safe_concat (buf, cur, st[i]);
523
524 if (op[i])
525 {
526 if (fun && i != 0)
527 cur = safe_concat (buf, cur, ",");
528
529 print_value (tmp, op[i], verbose);
530 cur = safe_concat (buf, cur, tmp);
531 }
532 }
533
534 if (fun)
535 cur = safe_concat (buf, cur, ")");
536 } /* print_exp */
537
538 /* Prints rtxes, I customly classified as values. They're constants,
539 registers, labels, symbols and memory accesses. */
540
541 static void
542 print_value (buf, x, verbose)
543 char *buf;
544 rtx x;
545 int verbose;
546 {
547 char t[BUF_LEN];
548 char *cur = buf;
549
550 switch (GET_CODE (x))
551 {
552 case CONST_INT:
553 sprintf (t, HOST_WIDE_INT_PRINT_HEX, INTVAL (x));
554 cur = safe_concat (buf, cur, t);
555 break;
556 case CONST_DOUBLE:
557 sprintf (t, "<0x%lx,0x%lx>", (long) XWINT (x, 2), (long) XWINT (x, 3));
558 cur = safe_concat (buf, cur, t);
559 break;
560 case CONST_STRING:
561 cur = safe_concat (buf, cur, "\"");
562 cur = safe_concat (buf, cur, XSTR (x, 0));
563 cur = safe_concat (buf, cur, "\"");
564 break;
565 case SYMBOL_REF:
566 cur = safe_concat (buf, cur, "`");
567 cur = safe_concat (buf, cur, XSTR (x, 0));
568 cur = safe_concat (buf, cur, "'");
569 break;
570 case LABEL_REF:
571 sprintf (t, "L%d", INSN_UID (XEXP (x, 0)));
572 cur = safe_concat (buf, cur, t);
573 break;
574 case CONST:
575 print_value (t, XEXP (x, 0), verbose);
576 cur = safe_concat (buf, cur, "const(");
577 cur = safe_concat (buf, cur, t);
578 cur = safe_concat (buf, cur, ")");
579 break;
580 case HIGH:
581 print_value (t, XEXP (x, 0), verbose);
582 cur = safe_concat (buf, cur, "high(");
583 cur = safe_concat (buf, cur, t);
584 cur = safe_concat (buf, cur, ")");
585 break;
586 case REG:
587 if (REGNO (x) < FIRST_PSEUDO_REGISTER)
588 {
589 int c = reg_names[REGNO (x)][0];
590 if (c >= '0' && c <= '9')
591 cur = safe_concat (buf, cur, "%");
592
593 cur = safe_concat (buf, cur, reg_names[REGNO (x)]);
594 }
595 else
596 {
597 sprintf (t, "r%d", REGNO (x));
598 cur = safe_concat (buf, cur, t);
599 }
600 break;
601 case SUBREG:
602 print_value (t, SUBREG_REG (x), verbose);
603 cur = safe_concat (buf, cur, t);
604 sprintf (t, "#%d", SUBREG_BYTE (x));
605 cur = safe_concat (buf, cur, t);
606 break;
607 case SCRATCH:
608 cur = safe_concat (buf, cur, "scratch");
609 break;
610 case CC0:
611 cur = safe_concat (buf, cur, "cc0");
612 break;
613 case PC:
614 cur = safe_concat (buf, cur, "pc");
615 break;
616 case MEM:
617 print_value (t, XEXP (x, 0), verbose);
618 cur = safe_concat (buf, cur, "[");
619 cur = safe_concat (buf, cur, t);
620 cur = safe_concat (buf, cur, "]");
621 break;
622 default:
623 print_exp (t, x, verbose);
624 cur = safe_concat (buf, cur, t);
625 break;
626 }
627 } /* print_value */
628
629 /* The next step in insn detalization, its pattern recognition. */
630
631 static void
632 print_pattern (buf, x, verbose)
633 char *buf;
634 rtx x;
635 int verbose;
636 {
637 char t1[BUF_LEN], t2[BUF_LEN], t3[BUF_LEN];
638
639 switch (GET_CODE (x))
640 {
641 case SET:
642 print_value (t1, SET_DEST (x), verbose);
643 print_value (t2, SET_SRC (x), verbose);
644 sprintf (buf, "%s=%s", t1, t2);
645 break;
646 case RETURN:
647 sprintf (buf, "return");
648 break;
649 case CALL:
650 print_exp (buf, x, verbose);
651 break;
652 case CLOBBER:
653 print_value (t1, XEXP (x, 0), verbose);
654 sprintf (buf, "clobber %s", t1);
655 break;
656 case USE:
657 print_value (t1, XEXP (x, 0), verbose);
658 sprintf (buf, "use %s", t1);
659 break;
660 case COND_EXEC:
661 if (GET_CODE (COND_EXEC_TEST (x)) == NE
662 && XEXP (COND_EXEC_TEST (x), 1) == const0_rtx)
663 print_value (t1, XEXP (COND_EXEC_TEST (x), 0), verbose);
664 else if (GET_CODE (COND_EXEC_TEST (x)) == EQ
665 && XEXP (COND_EXEC_TEST (x), 1) == const0_rtx)
666 {
667 t1[0] = '!';
668 print_value (t1 + 1, XEXP (COND_EXEC_TEST (x), 0), verbose);
669 }
670 else
671 print_value (t1, COND_EXEC_TEST (x), verbose);
672 print_pattern (t2, COND_EXEC_CODE (x), verbose);
673 sprintf (buf, "(%s) %s", t1, t2);
674 break;
675 case PARALLEL:
676 {
677 int i;
678
679 sprintf (t1, "{");
680 for (i = 0; i < XVECLEN (x, 0); i++)
681 {
682 print_pattern (t2, XVECEXP (x, 0, i), verbose);
683 sprintf (t3, "%s%s;", t1, t2);
684 strcpy (t1, t3);
685 }
686 sprintf (buf, "%s}", t1);
687 }
688 break;
689 case SEQUENCE:
690 {
691 int i;
692
693 sprintf (t1, "%%{");
694 for (i = 0; i < XVECLEN (x, 0); i++)
695 {
696 print_insn (t2, XVECEXP (x, 0, i), verbose);
697 sprintf (t3, "%s%s;", t1, t2);
698 strcpy (t1, t3);
699 }
700 sprintf (buf, "%s%%}", t1);
701 }
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 static void
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
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
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
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
915 visualize_stall_cycles (stalls)
916 int stalls;
917 {
918 const char *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
951 visualize_alloc ()
952 {
953 visual_tbl = xmalloc (get_visual_tbl_length ());
954 }
955
956 /* Free data used for visualization. */
957
958 void
959 visualize_free ()
960 {
961 free (visual_tbl);
962 }
963 #endif