gfortran.h (gfc_expr): Remove from_H, add "representation" struct.
[official-gcc.git] / gcc / sched-vis.c
blob6c975705ac5958d64e39c66a921afeebd552f01b
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,
434 "<" HOST_WIDE_INT_PRINT_HEX "," HOST_WIDE_INT_PRINT_HEX ">",
435 (unsigned HOST_WIDE_INT) CONST_DOUBLE_LOW (x),
436 (unsigned HOST_WIDE_INT) CONST_DOUBLE_HIGH (x));
437 cur = safe_concat (buf, cur, t);
438 break;
439 case CONST_STRING:
440 cur = safe_concat (buf, cur, "\"");
441 cur = safe_concat (buf, cur, XSTR (x, 0));
442 cur = safe_concat (buf, cur, "\"");
443 break;
444 case SYMBOL_REF:
445 cur = safe_concat (buf, cur, "`");
446 cur = safe_concat (buf, cur, XSTR (x, 0));
447 cur = safe_concat (buf, cur, "'");
448 break;
449 case LABEL_REF:
450 sprintf (t, "L%d", INSN_UID (XEXP (x, 0)));
451 cur = safe_concat (buf, cur, t);
452 break;
453 case CONST:
454 print_value (t, XEXP (x, 0), verbose);
455 cur = safe_concat (buf, cur, "const(");
456 cur = safe_concat (buf, cur, t);
457 cur = safe_concat (buf, cur, ")");
458 break;
459 case HIGH:
460 print_value (t, XEXP (x, 0), verbose);
461 cur = safe_concat (buf, cur, "high(");
462 cur = safe_concat (buf, cur, t);
463 cur = safe_concat (buf, cur, ")");
464 break;
465 case REG:
466 if (REGNO (x) < FIRST_PSEUDO_REGISTER)
468 int c = reg_names[REGNO (x)][0];
469 if (ISDIGIT (c))
470 cur = safe_concat (buf, cur, "%");
472 cur = safe_concat (buf, cur, reg_names[REGNO (x)]);
474 else
476 sprintf (t, "r%d", REGNO (x));
477 cur = safe_concat (buf, cur, t);
479 if (verbose
480 #ifdef INSN_SCHEDULING
481 && !current_sched_info
482 #endif
485 sprintf (t, ":%s", GET_MODE_NAME (GET_MODE (x)));
486 cur = safe_concat (buf, cur, t);
488 break;
489 case SUBREG:
490 print_value (t, SUBREG_REG (x), verbose);
491 cur = safe_concat (buf, cur, t);
492 sprintf (t, "#%d", SUBREG_BYTE (x));
493 cur = safe_concat (buf, cur, t);
494 break;
495 case SCRATCH:
496 cur = safe_concat (buf, cur, "scratch");
497 break;
498 case CC0:
499 cur = safe_concat (buf, cur, "cc0");
500 break;
501 case PC:
502 cur = safe_concat (buf, cur, "pc");
503 break;
504 case MEM:
505 print_value (t, XEXP (x, 0), verbose);
506 cur = safe_concat (buf, cur, "[");
507 cur = safe_concat (buf, cur, t);
508 cur = safe_concat (buf, cur, "]");
509 break;
510 default:
511 print_exp (t, x, verbose);
512 cur = safe_concat (buf, cur, t);
513 break;
515 } /* print_value */
517 /* The next step in insn detalization, its pattern recognition. */
519 static void
520 print_pattern (char *buf, rtx x, int verbose)
522 char t1[BUF_LEN], t2[BUF_LEN], t3[BUF_LEN];
524 switch (GET_CODE (x))
526 case SET:
527 print_value (t1, SET_DEST (x), verbose);
528 print_value (t2, SET_SRC (x), verbose);
529 sprintf (buf, "%s=%s", t1, t2);
530 break;
531 case RETURN:
532 sprintf (buf, "return");
533 break;
534 case CALL:
535 print_exp (buf, x, verbose);
536 break;
537 case CLOBBER:
538 print_value (t1, XEXP (x, 0), verbose);
539 sprintf (buf, "clobber %s", t1);
540 break;
541 case USE:
542 print_value (t1, XEXP (x, 0), verbose);
543 sprintf (buf, "use %s", t1);
544 break;
545 case COND_EXEC:
546 if (GET_CODE (COND_EXEC_TEST (x)) == NE
547 && XEXP (COND_EXEC_TEST (x), 1) == const0_rtx)
548 print_value (t1, XEXP (COND_EXEC_TEST (x), 0), verbose);
549 else if (GET_CODE (COND_EXEC_TEST (x)) == EQ
550 && XEXP (COND_EXEC_TEST (x), 1) == const0_rtx)
552 t1[0] = '!';
553 print_value (t1 + 1, XEXP (COND_EXEC_TEST (x), 0), verbose);
555 else
556 print_value (t1, COND_EXEC_TEST (x), verbose);
557 print_pattern (t2, COND_EXEC_CODE (x), verbose);
558 sprintf (buf, "(%s) %s", t1, t2);
559 break;
560 case PARALLEL:
562 int i;
564 sprintf (t1, "{");
565 for (i = 0; i < XVECLEN (x, 0); i++)
567 print_pattern (t2, XVECEXP (x, 0, i), verbose);
568 sprintf (t3, "%s%s;", t1, t2);
569 strcpy (t1, t3);
571 sprintf (buf, "%s}", t1);
573 break;
574 case SEQUENCE:
575 /* Should never see SEQUENCE codes until after reorg. */
576 gcc_unreachable ();
577 case ASM_INPUT:
578 sprintf (buf, "asm {%s}", XSTR (x, 0));
579 break;
580 case ADDR_VEC:
581 break;
582 case ADDR_DIFF_VEC:
583 print_value (buf, XEXP (x, 0), verbose);
584 break;
585 case TRAP_IF:
586 print_value (t1, TRAP_CONDITION (x), verbose);
587 sprintf (buf, "trap_if %s", t1);
588 break;
589 case UNSPEC:
591 int i;
593 sprintf (t1, "unspec{");
594 for (i = 0; i < XVECLEN (x, 0); i++)
596 print_pattern (t2, XVECEXP (x, 0, i), verbose);
597 sprintf (t3, "%s%s;", t1, t2);
598 strcpy (t1, t3);
600 sprintf (buf, "%s}", t1);
602 break;
603 case UNSPEC_VOLATILE:
605 int i;
607 sprintf (t1, "unspec/v{");
608 for (i = 0; i < XVECLEN (x, 0); i++)
610 print_pattern (t2, XVECEXP (x, 0, i), verbose);
611 sprintf (t3, "%s%s;", t1, t2);
612 strcpy (t1, t3);
614 sprintf (buf, "%s}", t1);
616 break;
617 default:
618 print_value (buf, x, verbose);
620 } /* print_pattern */
622 /* This is the main function in rtl visualization mechanism. It
623 accepts an rtx and tries to recognize it as an insn, then prints it
624 properly in human readable form, resembling assembler mnemonics.
625 For every insn it prints its UID and BB the insn belongs too.
626 (Probably the last "option" should be extended somehow, since it
627 depends now on sched.c inner variables ...) */
629 void
630 print_insn (char *buf, rtx x, int verbose)
632 char t[BUF_LEN];
633 rtx insn = x;
635 switch (GET_CODE (x))
637 case INSN:
638 print_pattern (t, PATTERN (x), verbose);
639 #ifdef INSN_SCHEDULING
640 if (verbose && current_sched_info)
641 sprintf (buf, "%s: %s", (*current_sched_info->print_insn) (x, 1),
643 else
644 #endif
645 sprintf (buf, " %4d %s", INSN_UID (x), t);
646 break;
647 case JUMP_INSN:
648 print_pattern (t, PATTERN (x), verbose);
649 #ifdef INSN_SCHEDULING
650 if (verbose && current_sched_info)
651 sprintf (buf, "%s: jump %s", (*current_sched_info->print_insn) (x, 1),
653 else
654 #endif
655 sprintf (buf, " %4d %s", INSN_UID (x), t);
656 break;
657 case CALL_INSN:
658 x = PATTERN (insn);
659 if (GET_CODE (x) == PARALLEL)
661 x = XVECEXP (x, 0, 0);
662 print_pattern (t, x, verbose);
664 else
665 strcpy (t, "call <...>");
666 #ifdef INSN_SCHEDULING
667 if (verbose && current_sched_info)
668 sprintf (buf, "%s: %s", (*current_sched_info->print_insn) (x, 1), t);
669 else
670 #endif
671 sprintf (buf, " %4d %s", INSN_UID (insn), t);
672 break;
673 case CODE_LABEL:
674 sprintf (buf, "L%d:", INSN_UID (x));
675 break;
676 case BARRIER:
677 sprintf (buf, "i%4d: barrier", INSN_UID (x));
678 break;
679 case NOTE:
680 sprintf (buf, " %4d %s", INSN_UID (x),
681 GET_NOTE_INSN_NAME (NOTE_KIND (x)));
682 break;
683 default:
684 sprintf (buf, "i%4d <What %s?>", INSN_UID (x),
685 GET_RTX_NAME (GET_CODE (x)));
687 } /* print_insn */
690 /* Emit a slim dump of X (an insn) to the file F, including any register
691 note attached to the instruction. */
692 void
693 dump_insn_slim (FILE *f, rtx x)
695 char t[BUF_LEN + 32];
696 rtx note;
698 print_insn (t, x, 1);
699 fputs (t, f);
700 putc ('\n', f);
701 if (INSN_P (x) && REG_NOTES (x))
702 for (note = REG_NOTES (x); note; note = XEXP (note, 1))
704 print_value (t, XEXP (note, 0), 1);
705 fprintf (f, " %s: %s\n",
706 GET_REG_NOTE_NAME (REG_NOTE_KIND (note)), t);
710 /* Emit a slim dump of X (an insn) to stderr. */
711 void
712 debug_insn_slim (rtx x)
714 dump_insn_slim (stderr, x);
717 /* Provide a slim dump the instruction chain starting at FIRST to F, honoring
718 the dump flags given in FLAGS. Currently, TDF_BLOCKS and TDF_DETAILS
719 include more information on the basic blocks. */
720 void
721 print_rtl_slim_with_bb (FILE *f, rtx first, int flags)
723 basic_block current_bb = NULL;
724 rtx insn;
726 for (insn = first; NULL != insn; insn = NEXT_INSN (insn))
728 if ((flags & TDF_BLOCKS)
729 && (INSN_P (insn) || GET_CODE (insn) == NOTE)
730 && BLOCK_FOR_INSN (insn)
731 && !current_bb)
733 current_bb = BLOCK_FOR_INSN (insn);
734 dump_bb_info (current_bb, true, false, flags, ";; ", f);
737 dump_insn_slim (f, insn);
739 if ((flags & TDF_BLOCKS)
740 && current_bb
741 && insn == BB_END (current_bb))
743 dump_bb_info (current_bb, false, true, flags, ";; ", f);
744 current_bb = NULL;