2006-10-22 H.J. Lu <hongjiu.lu@intel.com>
[official-gcc.git] / gcc / sched-vis.c
blob20129559470e03004a6c1e3ce3f8170af0034077
1 /* Instruction scheduling pass.
2 Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998,
3 1999, 2000, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
4 Contributed by Michael Tiemann (tiemann@cygnus.com) Enhanced by,
5 and currently maintained by, Jim Wilson (wilson@cygnus.com)
7 This file is part of GCC.
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.
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.
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, 51 Franklin Street, Fifth Floor, Boston, MA
22 02110-1301, USA. */
24 #include "config.h"
25 #include "system.h"
26 #include "coretypes.h"
27 #include "tm.h"
28 #include "rtl.h"
29 #include "obstack.h"
30 #include "hard-reg-set.h"
31 #include "basic-block.h"
32 #include "real.h"
33 #include "sched-int.h"
34 #include "tree-pass.h"
36 static char *safe_concat (char *, char *, const char *);
37 static void print_exp (char *, rtx, int);
38 static void print_value (char *, rtx, int);
39 static void print_pattern (char *, rtx, int);
41 #define BUF_LEN 2048
43 static char *
44 safe_concat (char *buf, char *cur, const char *str)
46 char *end = buf + BUF_LEN - 2; /* Leave room for null. */
47 int c;
49 if (cur > end)
51 *end = '\0';
52 return end;
55 while (cur < end && (c = *str++) != '\0')
56 *cur++ = c;
58 *cur = '\0';
59 return cur;
62 /* This recognizes rtx, I classified as expressions. These are always
63 represent some action on values or results of other expression, that
64 may be stored in objects representing values. */
66 static void
67 print_exp (char *buf, rtx x, int verbose)
69 char tmp[BUF_LEN];
70 const char *st[4];
71 char *cur = buf;
72 const char *fun = (char *) 0;
73 const char *sep;
74 rtx op[4];
75 int i;
77 for (i = 0; i < 4; i++)
79 st[i] = (char *) 0;
80 op[i] = NULL_RTX;
83 switch (GET_CODE (x))
85 case PLUS:
86 op[0] = XEXP (x, 0);
87 if (GET_CODE (XEXP (x, 1)) == CONST_INT
88 && INTVAL (XEXP (x, 1)) < 0)
90 st[1] = "-";
91 op[1] = GEN_INT (-INTVAL (XEXP (x, 1)));
93 else
95 st[1] = "+";
96 op[1] = XEXP (x, 1);
98 break;
99 case LO_SUM:
100 op[0] = XEXP (x, 0);
101 st[1] = "+low(";
102 op[1] = XEXP (x, 1);
103 st[2] = ")";
104 break;
105 case MINUS:
106 op[0] = XEXP (x, 0);
107 st[1] = "-";
108 op[1] = XEXP (x, 1);
109 break;
110 case COMPARE:
111 fun = "cmp";
112 op[0] = XEXP (x, 0);
113 op[1] = XEXP (x, 1);
114 break;
115 case NEG:
116 st[0] = "-";
117 op[0] = XEXP (x, 0);
118 break;
119 case MULT:
120 op[0] = XEXP (x, 0);
121 st[1] = "*";
122 op[1] = XEXP (x, 1);
123 break;
124 case DIV:
125 op[0] = XEXP (x, 0);
126 st[1] = "/";
127 op[1] = XEXP (x, 1);
128 break;
129 case UDIV:
130 fun = "udiv";
131 op[0] = XEXP (x, 0);
132 op[1] = XEXP (x, 1);
133 break;
134 case MOD:
135 op[0] = XEXP (x, 0);
136 st[1] = "%";
137 op[1] = XEXP (x, 1);
138 break;
139 case UMOD:
140 fun = "umod";
141 op[0] = XEXP (x, 0);
142 op[1] = XEXP (x, 1);
143 break;
144 case SMIN:
145 fun = "smin";
146 op[0] = XEXP (x, 0);
147 op[1] = XEXP (x, 1);
148 break;
149 case SMAX:
150 fun = "smax";
151 op[0] = XEXP (x, 0);
152 op[1] = XEXP (x, 1);
153 break;
154 case UMIN:
155 fun = "umin";
156 op[0] = XEXP (x, 0);
157 op[1] = XEXP (x, 1);
158 break;
159 case UMAX:
160 fun = "umax";
161 op[0] = XEXP (x, 0);
162 op[1] = XEXP (x, 1);
163 break;
164 case NOT:
165 st[0] = "!";
166 op[0] = XEXP (x, 0);
167 break;
168 case AND:
169 op[0] = XEXP (x, 0);
170 st[1] = "&";
171 op[1] = XEXP (x, 1);
172 break;
173 case IOR:
174 op[0] = XEXP (x, 0);
175 st[1] = "|";
176 op[1] = XEXP (x, 1);
177 break;
178 case XOR:
179 op[0] = XEXP (x, 0);
180 st[1] = "^";
181 op[1] = XEXP (x, 1);
182 break;
183 case ASHIFT:
184 op[0] = XEXP (x, 0);
185 st[1] = "<<";
186 op[1] = XEXP (x, 1);
187 break;
188 case LSHIFTRT:
189 op[0] = XEXP (x, 0);
190 st[1] = " 0>>";
191 op[1] = XEXP (x, 1);
192 break;
193 case ASHIFTRT:
194 op[0] = XEXP (x, 0);
195 st[1] = ">>";
196 op[1] = XEXP (x, 1);
197 break;
198 case ROTATE:
199 op[0] = XEXP (x, 0);
200 st[1] = "<-<";
201 op[1] = XEXP (x, 1);
202 break;
203 case ROTATERT:
204 op[0] = XEXP (x, 0);
205 st[1] = ">->";
206 op[1] = XEXP (x, 1);
207 break;
208 case ABS:
209 fun = "abs";
210 op[0] = XEXP (x, 0);
211 break;
212 case SQRT:
213 fun = "sqrt";
214 op[0] = XEXP (x, 0);
215 break;
216 case FFS:
217 fun = "ffs";
218 op[0] = XEXP (x, 0);
219 break;
220 case EQ:
221 op[0] = XEXP (x, 0);
222 st[1] = "==";
223 op[1] = XEXP (x, 1);
224 break;
225 case NE:
226 op[0] = XEXP (x, 0);
227 st[1] = "!=";
228 op[1] = XEXP (x, 1);
229 break;
230 case GT:
231 op[0] = XEXP (x, 0);
232 st[1] = ">";
233 op[1] = XEXP (x, 1);
234 break;
235 case GTU:
236 fun = "gtu";
237 op[0] = XEXP (x, 0);
238 op[1] = XEXP (x, 1);
239 break;
240 case LT:
241 op[0] = XEXP (x, 0);
242 st[1] = "<";
243 op[1] = XEXP (x, 1);
244 break;
245 case LTU:
246 fun = "ltu";
247 op[0] = XEXP (x, 0);
248 op[1] = XEXP (x, 1);
249 break;
250 case GE:
251 op[0] = XEXP (x, 0);
252 st[1] = ">=";
253 op[1] = XEXP (x, 1);
254 break;
255 case GEU:
256 fun = "geu";
257 op[0] = XEXP (x, 0);
258 op[1] = XEXP (x, 1);
259 break;
260 case LE:
261 op[0] = XEXP (x, 0);
262 st[1] = "<=";
263 op[1] = XEXP (x, 1);
264 break;
265 case LEU:
266 fun = "leu";
267 op[0] = XEXP (x, 0);
268 op[1] = XEXP (x, 1);
269 break;
270 case SIGN_EXTRACT:
271 fun = (verbose) ? "sign_extract" : "sxt";
272 op[0] = XEXP (x, 0);
273 op[1] = XEXP (x, 1);
274 op[2] = XEXP (x, 2);
275 break;
276 case ZERO_EXTRACT:
277 fun = (verbose) ? "zero_extract" : "zxt";
278 op[0] = XEXP (x, 0);
279 op[1] = XEXP (x, 1);
280 op[2] = XEXP (x, 2);
281 break;
282 case SIGN_EXTEND:
283 fun = (verbose) ? "sign_extend" : "sxn";
284 op[0] = XEXP (x, 0);
285 break;
286 case ZERO_EXTEND:
287 fun = (verbose) ? "zero_extend" : "zxn";
288 op[0] = XEXP (x, 0);
289 break;
290 case FLOAT_EXTEND:
291 fun = (verbose) ? "float_extend" : "fxn";
292 op[0] = XEXP (x, 0);
293 break;
294 case TRUNCATE:
295 fun = (verbose) ? "trunc" : "trn";
296 op[0] = XEXP (x, 0);
297 break;
298 case FLOAT_TRUNCATE:
299 fun = (verbose) ? "float_trunc" : "ftr";
300 op[0] = XEXP (x, 0);
301 break;
302 case FLOAT:
303 fun = (verbose) ? "float" : "flt";
304 op[0] = XEXP (x, 0);
305 break;
306 case UNSIGNED_FLOAT:
307 fun = (verbose) ? "uns_float" : "ufl";
308 op[0] = XEXP (x, 0);
309 break;
310 case FIX:
311 fun = "fix";
312 op[0] = XEXP (x, 0);
313 break;
314 case UNSIGNED_FIX:
315 fun = (verbose) ? "uns_fix" : "ufx";
316 op[0] = XEXP (x, 0);
317 break;
318 case PRE_DEC:
319 st[0] = "--";
320 op[0] = XEXP (x, 0);
321 break;
322 case PRE_INC:
323 st[0] = "++";
324 op[0] = XEXP (x, 0);
325 break;
326 case POST_DEC:
327 op[0] = XEXP (x, 0);
328 st[1] = "--";
329 break;
330 case POST_INC:
331 op[0] = XEXP (x, 0);
332 st[1] = "++";
333 break;
334 case CALL:
335 st[0] = "call ";
336 op[0] = XEXP (x, 0);
337 if (verbose)
339 st[1] = " argc:";
340 op[1] = XEXP (x, 1);
342 break;
343 case IF_THEN_ELSE:
344 st[0] = "{(";
345 op[0] = XEXP (x, 0);
346 st[1] = ")?";
347 op[1] = XEXP (x, 1);
348 st[2] = ":";
349 op[2] = XEXP (x, 2);
350 st[3] = "}";
351 break;
352 case TRAP_IF:
353 fun = "trap_if";
354 op[0] = TRAP_CONDITION (x);
355 break;
356 case PREFETCH:
357 fun = "prefetch";
358 op[0] = XEXP (x, 0);
359 op[1] = XEXP (x, 1);
360 op[2] = XEXP (x, 2);
361 break;
362 case UNSPEC:
363 case UNSPEC_VOLATILE:
365 cur = safe_concat (buf, cur, "unspec");
366 if (GET_CODE (x) == UNSPEC_VOLATILE)
367 cur = safe_concat (buf, cur, "/v");
368 cur = safe_concat (buf, cur, "[");
369 sep = "";
370 for (i = 0; i < XVECLEN (x, 0); i++)
372 print_pattern (tmp, XVECEXP (x, 0, i), verbose);
373 cur = safe_concat (buf, cur, sep);
374 cur = safe_concat (buf, cur, tmp);
375 sep = ",";
377 cur = safe_concat (buf, cur, "] ");
378 sprintf (tmp, "%d", XINT (x, 1));
379 cur = safe_concat (buf, cur, tmp);
381 break;
382 default:
383 /* If (verbose) debug_rtx (x); */
384 st[0] = GET_RTX_NAME (GET_CODE (x));
385 break;
388 /* Print this as a function? */
389 if (fun)
391 cur = safe_concat (buf, cur, fun);
392 cur = safe_concat (buf, cur, "(");
395 for (i = 0; i < 4; i++)
397 if (st[i])
398 cur = safe_concat (buf, cur, st[i]);
400 if (op[i])
402 if (fun && i != 0)
403 cur = safe_concat (buf, cur, ",");
405 print_value (tmp, op[i], verbose);
406 cur = safe_concat (buf, cur, tmp);
410 if (fun)
411 cur = safe_concat (buf, cur, ")");
412 } /* print_exp */
414 /* Prints rtxes, I customarily classified as values. They're constants,
415 registers, labels, symbols and memory accesses. */
417 static void
418 print_value (char *buf, rtx x, int verbose)
420 char t[BUF_LEN];
421 char *cur = buf;
423 switch (GET_CODE (x))
425 case CONST_INT:
426 sprintf (t, HOST_WIDE_INT_PRINT_HEX, INTVAL (x));
427 cur = safe_concat (buf, cur, t);
428 break;
429 case CONST_DOUBLE:
430 if (FLOAT_MODE_P (GET_MODE (x)))
431 real_to_decimal (t, CONST_DOUBLE_REAL_VALUE (x), sizeof (t), 0, 1);
432 else
433 sprintf (t, "<0x%lx,0x%lx>", (long) CONST_DOUBLE_LOW (x), (long) CONST_DOUBLE_HIGH (x));
434 cur = safe_concat (buf, cur, t);
435 break;
436 case CONST_STRING:
437 cur = safe_concat (buf, cur, "\"");
438 cur = safe_concat (buf, cur, XSTR (x, 0));
439 cur = safe_concat (buf, cur, "\"");
440 break;
441 case SYMBOL_REF:
442 cur = safe_concat (buf, cur, "`");
443 cur = safe_concat (buf, cur, XSTR (x, 0));
444 cur = safe_concat (buf, cur, "'");
445 break;
446 case LABEL_REF:
447 sprintf (t, "L%d", INSN_UID (XEXP (x, 0)));
448 cur = safe_concat (buf, cur, t);
449 break;
450 case CONST:
451 print_value (t, XEXP (x, 0), verbose);
452 cur = safe_concat (buf, cur, "const(");
453 cur = safe_concat (buf, cur, t);
454 cur = safe_concat (buf, cur, ")");
455 break;
456 case HIGH:
457 print_value (t, XEXP (x, 0), verbose);
458 cur = safe_concat (buf, cur, "high(");
459 cur = safe_concat (buf, cur, t);
460 cur = safe_concat (buf, cur, ")");
461 break;
462 case REG:
463 if (REGNO (x) < FIRST_PSEUDO_REGISTER)
465 int c = reg_names[REGNO (x)][0];
466 if (ISDIGIT (c))
467 cur = safe_concat (buf, cur, "%");
469 cur = safe_concat (buf, cur, reg_names[REGNO (x)]);
471 else
473 sprintf (t, "r%d", REGNO (x));
474 cur = safe_concat (buf, cur, t);
476 if (verbose
477 #ifdef INSN_SCHEDULING
478 && !current_sched_info
479 #endif
482 sprintf (t, ":%s", GET_MODE_NAME (GET_MODE (x)));
483 cur = safe_concat (buf, cur, t);
485 break;
486 case SUBREG:
487 print_value (t, SUBREG_REG (x), verbose);
488 cur = safe_concat (buf, cur, t);
489 sprintf (t, "#%d", SUBREG_BYTE (x));
490 cur = safe_concat (buf, cur, t);
491 break;
492 case SCRATCH:
493 cur = safe_concat (buf, cur, "scratch");
494 break;
495 case CC0:
496 cur = safe_concat (buf, cur, "cc0");
497 break;
498 case PC:
499 cur = safe_concat (buf, cur, "pc");
500 break;
501 case MEM:
502 print_value (t, XEXP (x, 0), verbose);
503 cur = safe_concat (buf, cur, "[");
504 cur = safe_concat (buf, cur, t);
505 cur = safe_concat (buf, cur, "]");
506 break;
507 default:
508 print_exp (t, x, verbose);
509 cur = safe_concat (buf, cur, t);
510 break;
512 } /* print_value */
514 /* The next step in insn detalization, its pattern recognition. */
516 static void
517 print_pattern (char *buf, rtx x, int verbose)
519 char t1[BUF_LEN], t2[BUF_LEN], t3[BUF_LEN];
521 switch (GET_CODE (x))
523 case SET:
524 print_value (t1, SET_DEST (x), verbose);
525 print_value (t2, SET_SRC (x), verbose);
526 sprintf (buf, "%s=%s", t1, t2);
527 break;
528 case RETURN:
529 sprintf (buf, "return");
530 break;
531 case CALL:
532 print_exp (buf, x, verbose);
533 break;
534 case CLOBBER:
535 print_value (t1, XEXP (x, 0), verbose);
536 sprintf (buf, "clobber %s", t1);
537 break;
538 case USE:
539 print_value (t1, XEXP (x, 0), verbose);
540 sprintf (buf, "use %s", t1);
541 break;
542 case COND_EXEC:
543 if (GET_CODE (COND_EXEC_TEST (x)) == NE
544 && XEXP (COND_EXEC_TEST (x), 1) == const0_rtx)
545 print_value (t1, XEXP (COND_EXEC_TEST (x), 0), verbose);
546 else if (GET_CODE (COND_EXEC_TEST (x)) == EQ
547 && XEXP (COND_EXEC_TEST (x), 1) == const0_rtx)
549 t1[0] = '!';
550 print_value (t1 + 1, XEXP (COND_EXEC_TEST (x), 0), verbose);
552 else
553 print_value (t1, COND_EXEC_TEST (x), verbose);
554 print_pattern (t2, COND_EXEC_CODE (x), verbose);
555 sprintf (buf, "(%s) %s", t1, t2);
556 break;
557 case PARALLEL:
559 int i;
561 sprintf (t1, "{");
562 for (i = 0; i < XVECLEN (x, 0); i++)
564 print_pattern (t2, XVECEXP (x, 0, i), verbose);
565 sprintf (t3, "%s%s;", t1, t2);
566 strcpy (t1, t3);
568 sprintf (buf, "%s}", t1);
570 break;
571 case SEQUENCE:
572 /* Should never see SEQUENCE codes until after reorg. */
573 gcc_unreachable ();
574 case ASM_INPUT:
575 sprintf (buf, "asm {%s}", XSTR (x, 0));
576 break;
577 case ADDR_VEC:
578 break;
579 case ADDR_DIFF_VEC:
580 print_value (buf, XEXP (x, 0), verbose);
581 break;
582 case TRAP_IF:
583 print_value (t1, TRAP_CONDITION (x), verbose);
584 sprintf (buf, "trap_if %s", t1);
585 break;
586 case UNSPEC:
588 int i;
590 sprintf (t1, "unspec{");
591 for (i = 0; i < XVECLEN (x, 0); i++)
593 print_pattern (t2, XVECEXP (x, 0, i), verbose);
594 sprintf (t3, "%s%s;", t1, t2);
595 strcpy (t1, t3);
597 sprintf (buf, "%s}", t1);
599 break;
600 case UNSPEC_VOLATILE:
602 int i;
604 sprintf (t1, "unspec/v{");
605 for (i = 0; i < XVECLEN (x, 0); i++)
607 print_pattern (t2, XVECEXP (x, 0, i), verbose);
608 sprintf (t3, "%s%s;", t1, t2);
609 strcpy (t1, t3);
611 sprintf (buf, "%s}", t1);
613 break;
614 default:
615 print_value (buf, x, verbose);
617 } /* print_pattern */
619 /* This is the main function in rtl visualization mechanism. It
620 accepts an rtx and tries to recognize it as an insn, then prints it
621 properly in human readable form, resembling assembler mnemonics.
622 For every insn it prints its UID and BB the insn belongs too.
623 (Probably the last "option" should be extended somehow, since it
624 depends now on sched.c inner variables ...) */
626 void
627 print_insn (char *buf, rtx x, int verbose)
629 char t[BUF_LEN];
630 rtx insn = x;
632 switch (GET_CODE (x))
634 case INSN:
635 print_pattern (t, PATTERN (x), verbose);
636 #ifdef INSN_SCHEDULING
637 if (verbose && current_sched_info)
638 sprintf (buf, "%s: %s", (*current_sched_info->print_insn) (x, 1),
640 else
641 #endif
642 sprintf (buf, " %4d %s", INSN_UID (x), t);
643 break;
644 case JUMP_INSN:
645 print_pattern (t, PATTERN (x), verbose);
646 #ifdef INSN_SCHEDULING
647 if (verbose && current_sched_info)
648 sprintf (buf, "%s: jump %s", (*current_sched_info->print_insn) (x, 1),
650 else
651 #endif
652 sprintf (buf, " %4d %s", INSN_UID (x), t);
653 break;
654 case CALL_INSN:
655 x = PATTERN (insn);
656 if (GET_CODE (x) == PARALLEL)
658 x = XVECEXP (x, 0, 0);
659 print_pattern (t, x, verbose);
661 else
662 strcpy (t, "call <...>");
663 #ifdef INSN_SCHEDULING
664 if (verbose && current_sched_info)
665 sprintf (buf, "%s: %s", (*current_sched_info->print_insn) (x, 1), t);
666 else
667 #endif
668 sprintf (buf, " %4d %s", INSN_UID (insn), t);
669 break;
670 case CODE_LABEL:
671 sprintf (buf, "L%d:", INSN_UID (x));
672 break;
673 case BARRIER:
674 sprintf (buf, "i%4d: barrier", INSN_UID (x));
675 break;
676 case NOTE:
677 if (NOTE_LINE_NUMBER (x) > 0)
679 expanded_location xloc;
680 NOTE_EXPANDED_LOCATION (xloc, x);
681 sprintf (buf, " %4d note \"%s\" %d", INSN_UID (x),
682 xloc.file, xloc.line);
684 else
685 sprintf (buf, " %4d %s", INSN_UID (x),
686 GET_NOTE_INSN_NAME (NOTE_LINE_NUMBER (x)));
687 break;
688 default:
689 sprintf (buf, "i%4d <What %s?>", INSN_UID (x),
690 GET_RTX_NAME (GET_CODE (x)));
692 } /* print_insn */
695 /* Emit a slim dump of X (an insn) to the file F, including any register
696 note attached to the instruction. */
697 void
698 dump_insn_slim (FILE *f, rtx x)
700 char t[BUF_LEN + 32];
701 rtx note;
703 print_insn (t, x, 1);
704 fputs (t, f);
705 putc ('\n', f);
706 if (INSN_P (x) && REG_NOTES (x))
707 for (note = REG_NOTES (x); note; note = XEXP (note, 1))
709 print_value (t, XEXP (note, 0), 1);
710 fprintf (f, " %s: %s\n",
711 GET_REG_NOTE_NAME (REG_NOTE_KIND (note)), t);
715 /* Emit a slim dump of X (an insn) to stderr. */
716 void
717 debug_insn_slim (rtx x)
719 dump_insn_slim (stderr, x);
722 /* Provide a slim dump the instruction chain starting at FIRST to F, honoring
723 the dump flags given in FLAGS. Currently, TDF_BLOCKS and TDF_DETAILS
724 include more information on the basic blocks. */
725 void
726 print_rtl_slim_with_bb (FILE *f, rtx first, int flags)
728 basic_block current_bb = NULL;
729 rtx insn;
731 for (insn = first; NULL != insn; insn = NEXT_INSN (insn))
733 if ((flags & TDF_BLOCKS)
734 && (INSN_P (insn) || GET_CODE (insn) == NOTE)
735 && BLOCK_FOR_INSN (insn)
736 && !current_bb)
738 current_bb = BLOCK_FOR_INSN (insn);
739 dump_bb_info (current_bb, true, false, flags, ";; ", f);
742 dump_insn_slim (f, insn);
744 if ((flags & TDF_BLOCKS)
745 && current_bb
746 && insn == BB_END (current_bb))
748 dump_bb_info (current_bb, false, true, flags, ";; ", f);
749 current_bb = NULL;