1 /* Instruction scheduling pass.
2 Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
3 2002, 2003, 2004, 2005, 2006, 2007, 2008 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 3, or (at your option) any later
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
19 You should have received a copy of the GNU General Public License
20 along with GCC; see the file COPYING3. If not see
21 <http://www.gnu.org/licenses/>. */
25 #include "coretypes.h"
29 #include "hard-reg-set.h"
30 #include "basic-block.h"
32 #include "insn-attr.h"
33 #include "sched-int.h"
34 #include "tree-pass.h"
36 static char *safe_concat (char *, char *, const char *);
41 safe_concat (char *buf
, char *cur
, const char *str
)
43 char *end
= buf
+ BUF_LEN
- 2; /* Leave room for null. */
52 while (cur
< end
&& (c
= *str
++) != '\0')
59 /* This recognizes rtx, I classified as expressions. These are always
60 represent some action on values or results of other expression, that
61 may be stored in objects representing values. */
64 print_exp (char *buf
, const_rtx x
, int verbose
)
69 const char *fun
= (char *) 0;
74 for (i
= 0; i
< 4; i
++)
84 if (GET_CODE (XEXP (x
, 1)) == CONST_INT
85 && INTVAL (XEXP (x
, 1)) < 0)
88 op
[1] = GEN_INT (-INTVAL (XEXP (x
, 1)));
268 fun
= (verbose
) ? "sign_extract" : "sxt";
274 fun
= (verbose
) ? "zero_extract" : "zxt";
280 fun
= (verbose
) ? "sign_extend" : "sxn";
284 fun
= (verbose
) ? "zero_extend" : "zxn";
288 fun
= (verbose
) ? "float_extend" : "fxn";
292 fun
= (verbose
) ? "trunc" : "trn";
296 fun
= (verbose
) ? "float_trunc" : "ftr";
300 fun
= (verbose
) ? "float" : "flt";
304 fun
= (verbose
) ? "uns_float" : "ufl";
312 fun
= (verbose
) ? "uns_fix" : "ufx";
333 op
[0] = XEXP (XEXP (x
, 1), 0);
335 op
[1] = XEXP (XEXP (x
, 1), 1);
339 op
[0] = XEXP (XEXP (x
, 1), 0);
341 op
[1] = XEXP (XEXP (x
, 1), 1);
363 op
[0] = TRAP_CONDITION (x
);
372 case UNSPEC_VOLATILE
:
374 cur
= safe_concat (buf
, cur
, "unspec");
375 if (GET_CODE (x
) == UNSPEC_VOLATILE
)
376 cur
= safe_concat (buf
, cur
, "/v");
377 cur
= safe_concat (buf
, cur
, "[");
379 for (i
= 0; i
< XVECLEN (x
, 0); i
++)
381 print_pattern (tmp
, XVECEXP (x
, 0, i
), verbose
);
382 cur
= safe_concat (buf
, cur
, sep
);
383 cur
= safe_concat (buf
, cur
, tmp
);
386 cur
= safe_concat (buf
, cur
, "] ");
387 sprintf (tmp
, "%d", XINT (x
, 1));
388 cur
= safe_concat (buf
, cur
, tmp
);
392 /* If (verbose) debug_rtx (x); */
393 st
[0] = GET_RTX_NAME (GET_CODE (x
));
397 /* Print this as a function? */
400 cur
= safe_concat (buf
, cur
, fun
);
401 cur
= safe_concat (buf
, cur
, "(");
404 for (i
= 0; i
< 4; i
++)
407 cur
= safe_concat (buf
, cur
, st
[i
]);
412 cur
= safe_concat (buf
, cur
, ",");
414 print_value (tmp
, op
[i
], verbose
);
415 cur
= safe_concat (buf
, cur
, tmp
);
420 cur
= safe_concat (buf
, cur
, ")");
423 /* Prints rtxes, I customarily classified as values. They're constants,
424 registers, labels, symbols and memory accesses. */
427 print_value (char *buf
, const_rtx x
, int verbose
)
432 switch (GET_CODE (x
))
435 sprintf (t
, HOST_WIDE_INT_PRINT_HEX
,
436 (unsigned HOST_WIDE_INT
) INTVAL (x
));
437 cur
= safe_concat (buf
, cur
, t
);
440 if (FLOAT_MODE_P (GET_MODE (x
)))
441 real_to_decimal (t
, CONST_DOUBLE_REAL_VALUE (x
), sizeof (t
), 0, 1);
444 "<" HOST_WIDE_INT_PRINT_HEX
"," HOST_WIDE_INT_PRINT_HEX
">",
445 (unsigned HOST_WIDE_INT
) CONST_DOUBLE_LOW (x
),
446 (unsigned HOST_WIDE_INT
) CONST_DOUBLE_HIGH (x
));
447 cur
= safe_concat (buf
, cur
, t
);
450 fixed_to_decimal (t
, CONST_FIXED_VALUE (x
), sizeof (t
));
451 cur
= safe_concat (buf
, cur
, t
);
454 cur
= safe_concat (buf
, cur
, "\"");
455 cur
= safe_concat (buf
, cur
, XSTR (x
, 0));
456 cur
= safe_concat (buf
, cur
, "\"");
459 cur
= safe_concat (buf
, cur
, "`");
460 cur
= safe_concat (buf
, cur
, XSTR (x
, 0));
461 cur
= safe_concat (buf
, cur
, "'");
464 sprintf (t
, "L%d", INSN_UID (XEXP (x
, 0)));
465 cur
= safe_concat (buf
, cur
, t
);
468 print_value (t
, XEXP (x
, 0), verbose
);
469 cur
= safe_concat (buf
, cur
, "const(");
470 cur
= safe_concat (buf
, cur
, t
);
471 cur
= safe_concat (buf
, cur
, ")");
474 print_value (t
, XEXP (x
, 0), verbose
);
475 cur
= safe_concat (buf
, cur
, "high(");
476 cur
= safe_concat (buf
, cur
, t
);
477 cur
= safe_concat (buf
, cur
, ")");
480 if (REGNO (x
) < FIRST_PSEUDO_REGISTER
)
482 int c
= reg_names
[REGNO (x
)][0];
484 cur
= safe_concat (buf
, cur
, "%");
486 cur
= safe_concat (buf
, cur
, reg_names
[REGNO (x
)]);
490 sprintf (t
, "r%d", REGNO (x
));
491 cur
= safe_concat (buf
, cur
, t
);
494 #ifdef INSN_SCHEDULING
495 && !current_sched_info
499 sprintf (t
, ":%s", GET_MODE_NAME (GET_MODE (x
)));
500 cur
= safe_concat (buf
, cur
, t
);
504 print_value (t
, SUBREG_REG (x
), verbose
);
505 cur
= safe_concat (buf
, cur
, t
);
506 sprintf (t
, "#%d", SUBREG_BYTE (x
));
507 cur
= safe_concat (buf
, cur
, t
);
510 cur
= safe_concat (buf
, cur
, "scratch");
513 cur
= safe_concat (buf
, cur
, "cc0");
516 cur
= safe_concat (buf
, cur
, "pc");
519 print_value (t
, XEXP (x
, 0), verbose
);
520 cur
= safe_concat (buf
, cur
, "[");
521 cur
= safe_concat (buf
, cur
, t
);
522 cur
= safe_concat (buf
, cur
, "]");
525 print_exp (t
, x
, verbose
);
526 cur
= safe_concat (buf
, cur
, t
);
531 /* The next step in insn detalization, its pattern recognition. */
534 print_pattern (char *buf
, const_rtx x
, int verbose
)
536 char t1
[BUF_LEN
], t2
[BUF_LEN
], t3
[BUF_LEN
];
538 switch (GET_CODE (x
))
541 print_value (t1
, SET_DEST (x
), verbose
);
542 print_value (t2
, SET_SRC (x
), verbose
);
543 sprintf (buf
, "%s=%s", t1
, t2
);
546 sprintf (buf
, "return");
549 print_exp (buf
, x
, verbose
);
552 print_value (t1
, XEXP (x
, 0), verbose
);
553 sprintf (buf
, "clobber %s", t1
);
556 print_value (t1
, XEXP (x
, 0), verbose
);
557 sprintf (buf
, "use %s", t1
);
560 if (GET_CODE (COND_EXEC_TEST (x
)) == NE
561 && XEXP (COND_EXEC_TEST (x
), 1) == const0_rtx
)
562 print_value (t1
, XEXP (COND_EXEC_TEST (x
), 0), verbose
);
563 else if (GET_CODE (COND_EXEC_TEST (x
)) == EQ
564 && XEXP (COND_EXEC_TEST (x
), 1) == const0_rtx
)
567 print_value (t1
+ 1, XEXP (COND_EXEC_TEST (x
), 0), verbose
);
570 print_value (t1
, COND_EXEC_TEST (x
), verbose
);
571 print_pattern (t2
, COND_EXEC_CODE (x
), verbose
);
572 sprintf (buf
, "(%s) %s", t1
, t2
);
579 for (i
= 0; i
< XVECLEN (x
, 0); i
++)
581 print_pattern (t2
, XVECEXP (x
, 0, i
), verbose
);
582 sprintf (t3
, "%s%s;", t1
, t2
);
585 sprintf (buf
, "%s}", t1
);
589 /* Should never see SEQUENCE codes until after reorg. */
592 sprintf (buf
, "asm {%s}", XSTR (x
, 0));
597 print_value (buf
, XEXP (x
, 0), verbose
);
600 print_value (t1
, TRAP_CONDITION (x
), verbose
);
601 sprintf (buf
, "trap_if %s", t1
);
607 sprintf (t1
, "unspec{");
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
);
614 sprintf (buf
, "%s}", t1
);
617 case UNSPEC_VOLATILE
:
621 sprintf (t1
, "unspec/v{");
622 for (i
= 0; i
< XVECLEN (x
, 0); i
++)
624 print_pattern (t2
, XVECEXP (x
, 0, i
), verbose
);
625 sprintf (t3
, "%s%s;", t1
, t2
);
628 sprintf (buf
, "%s}", t1
);
632 print_value (buf
, x
, verbose
);
634 } /* print_pattern */
636 /* This is the main function in rtl visualization mechanism. It
637 accepts an rtx and tries to recognize it as an insn, then prints it
638 properly in human readable form, resembling assembler mnemonics.
639 For every insn it prints its UID and BB the insn belongs too.
640 (Probably the last "option" should be extended somehow, since it
641 depends now on sched.c inner variables ...) */
644 print_insn (char *buf
, const_rtx x
, int verbose
)
649 switch (GET_CODE (x
))
652 print_pattern (t
, PATTERN (x
), verbose
);
653 #ifdef INSN_SCHEDULING
654 if (verbose
&& current_sched_info
)
655 sprintf (buf
, "%s: %s", (*current_sched_info
->print_insn
) (x
, 1),
659 sprintf (buf
, " %4d %s", INSN_UID (x
), t
);
662 print_pattern (t
, PATTERN (x
), verbose
);
663 #ifdef INSN_SCHEDULING
664 if (verbose
&& current_sched_info
)
665 sprintf (buf
, "%s: jump %s", (*current_sched_info
->print_insn
) (x
, 1),
669 sprintf (buf
, " %4d %s", INSN_UID (x
), t
);
673 if (GET_CODE (x
) == PARALLEL
)
675 x
= XVECEXP (x
, 0, 0);
676 print_pattern (t
, x
, verbose
);
679 strcpy (t
, "call <...>");
680 #ifdef INSN_SCHEDULING
681 if (verbose
&& current_sched_info
)
682 sprintf (buf
, "%s: %s", (*current_sched_info
->print_insn
) (insn
, 1), t
);
685 sprintf (buf
, " %4d %s", INSN_UID (insn
), t
);
688 sprintf (buf
, "L%d:", INSN_UID (x
));
691 sprintf (buf
, "i%4d: barrier", INSN_UID (x
));
694 sprintf (buf
, " %4d %s", INSN_UID (x
),
695 GET_NOTE_INSN_NAME (NOTE_KIND (x
)));
698 sprintf (buf
, "i%4d <What %s?>", INSN_UID (x
),
699 GET_RTX_NAME (GET_CODE (x
)));
703 /* Emit a slim dump of X (an insn) to the file F, including any register
704 note attached to the instruction. */
706 dump_insn_slim (FILE *f
, rtx x
)
708 char t
[BUF_LEN
+ 32];
711 print_insn (t
, x
, 1);
714 if (INSN_P (x
) && REG_NOTES (x
))
715 for (note
= REG_NOTES (x
); note
; note
= XEXP (note
, 1))
717 print_value (t
, XEXP (note
, 0), 1);
718 fprintf (f
, " %s: %s\n",
719 GET_REG_NOTE_NAME (REG_NOTE_KIND (note
)), t
);
723 /* Emit a slim dump of X (an insn) to stderr. */
725 debug_insn_slim (rtx x
)
727 dump_insn_slim (stderr
, x
);
730 /* Provide a slim dump the instruction chain starting at FIRST to F, honoring
731 the dump flags given in FLAGS. Currently, TDF_BLOCKS and TDF_DETAILS
732 include more information on the basic blocks. */
734 print_rtl_slim_with_bb (FILE *f
, rtx first
, int flags
)
736 print_rtl_slim (f
, first
, NULL
, -1, flags
);
739 /* Same as above, but stop at LAST or when COUNT == 0.
740 If COUNT < 0 it will stop only at LAST or NULL rtx. */
742 print_rtl_slim (FILE *f
, rtx first
, rtx last
, int count
, int flags
)
744 basic_block current_bb
= NULL
;
747 tail
= last
? NEXT_INSN (last
) : NULL_RTX
;
749 (insn
!= NULL
) && (insn
!= tail
) && (count
!= 0);
750 insn
= NEXT_INSN (insn
))
752 if ((flags
& TDF_BLOCKS
)
753 && (INSN_P (insn
) || GET_CODE (insn
) == NOTE
)
754 && BLOCK_FOR_INSN (insn
)
757 current_bb
= BLOCK_FOR_INSN (insn
);
758 dump_bb_info (current_bb
, true, false, flags
, ";; ", f
);
761 dump_insn_slim (f
, insn
);
763 if ((flags
& TDF_BLOCKS
)
765 && insn
== BB_END (current_bb
))
767 dump_bb_info (current_bb
, false, true, flags
, ";; ", f
);
776 debug_bb_slim (struct basic_block_def
*bb
)
778 print_rtl_slim (stderr
, BB_HEAD (bb
), BB_END (bb
), -1, 32);
782 debug_bb_n_slim (int n
)
784 struct basic_block_def
*bb
= BASIC_BLOCK (n
);