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 (CONST_INT_P (XEXP (x
, 1))
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 sprintf (t
, "D#%i", DEBUG_TEMP_UID (XTREE (x
, 0)));
526 cur
= safe_concat (buf
, cur
, t
);
529 print_exp (t
, x
, verbose
);
530 cur
= safe_concat (buf
, cur
, t
);
535 /* The next step in insn detalization, its pattern recognition. */
538 print_pattern (char *buf
, const_rtx x
, int verbose
)
540 char t1
[BUF_LEN
], t2
[BUF_LEN
], t3
[BUF_LEN
];
542 switch (GET_CODE (x
))
545 print_value (t1
, SET_DEST (x
), verbose
);
546 print_value (t2
, SET_SRC (x
), verbose
);
547 sprintf (buf
, "%s=%s", t1
, t2
);
550 sprintf (buf
, "return");
553 print_exp (buf
, x
, verbose
);
556 print_value (t1
, XEXP (x
, 0), verbose
);
557 sprintf (buf
, "clobber %s", t1
);
560 print_value (t1
, XEXP (x
, 0), verbose
);
561 sprintf (buf
, "use %s", t1
);
564 print_value (t1
, PAT_VAR_LOCATION_LOC (x
), verbose
);
565 sprintf (buf
, "loc %s", t1
);
568 if (GET_CODE (COND_EXEC_TEST (x
)) == NE
569 && XEXP (COND_EXEC_TEST (x
), 1) == const0_rtx
)
570 print_value (t1
, XEXP (COND_EXEC_TEST (x
), 0), verbose
);
571 else if (GET_CODE (COND_EXEC_TEST (x
)) == EQ
572 && XEXP (COND_EXEC_TEST (x
), 1) == const0_rtx
)
575 print_value (t1
+ 1, XEXP (COND_EXEC_TEST (x
), 0), verbose
);
578 print_value (t1
, COND_EXEC_TEST (x
), verbose
);
579 print_pattern (t2
, COND_EXEC_CODE (x
), verbose
);
580 sprintf (buf
, "(%s) %s", t1
, t2
);
587 for (i
= 0; i
< XVECLEN (x
, 0); i
++)
589 print_pattern (t2
, XVECEXP (x
, 0, i
), verbose
);
590 sprintf (t3
, "%s%s;", t1
, t2
);
593 sprintf (buf
, "%s}", t1
);
597 /* Should never see SEQUENCE codes until after reorg. */
600 sprintf (buf
, "asm {%s}", XSTR (x
, 0));
605 print_value (buf
, XEXP (x
, 0), verbose
);
608 print_value (t1
, TRAP_CONDITION (x
), verbose
);
609 sprintf (buf
, "trap_if %s", t1
);
615 sprintf (t1
, "unspec{");
616 for (i
= 0; i
< XVECLEN (x
, 0); i
++)
618 print_pattern (t2
, XVECEXP (x
, 0, i
), verbose
);
619 sprintf (t3
, "%s%s;", t1
, t2
);
622 sprintf (buf
, "%s}", t1
);
625 case UNSPEC_VOLATILE
:
629 sprintf (t1
, "unspec/v{");
630 for (i
= 0; i
< XVECLEN (x
, 0); i
++)
632 print_pattern (t2
, XVECEXP (x
, 0, i
), verbose
);
633 sprintf (t3
, "%s%s;", t1
, t2
);
636 sprintf (buf
, "%s}", t1
);
640 print_value (buf
, x
, verbose
);
642 } /* print_pattern */
644 /* This is the main function in rtl visualization mechanism. It
645 accepts an rtx and tries to recognize it as an insn, then prints it
646 properly in human readable form, resembling assembler mnemonics.
647 For every insn it prints its UID and BB the insn belongs too.
648 (Probably the last "option" should be extended somehow, since it
649 depends now on sched.c inner variables ...) */
652 print_insn (char *buf
, const_rtx x
, int verbose
)
657 switch (GET_CODE (x
))
660 print_pattern (t
, PATTERN (x
), verbose
);
661 #ifdef INSN_SCHEDULING
662 if (verbose
&& current_sched_info
)
663 sprintf (buf
, "%s: %s", (*current_sched_info
->print_insn
) (x
, 1),
667 sprintf (buf
, " %4d %s", INSN_UID (x
), t
);
672 const char *name
= "?";
674 if (DECL_P (INSN_VAR_LOCATION_DECL (insn
)))
676 tree id
= DECL_NAME (INSN_VAR_LOCATION_DECL (insn
));
679 name
= IDENTIFIER_POINTER (id
);
680 else if (TREE_CODE (INSN_VAR_LOCATION_DECL (insn
))
683 sprintf (idbuf
, "D#%i",
684 DEBUG_TEMP_UID (INSN_VAR_LOCATION_DECL (insn
)));
689 sprintf (idbuf
, "D.%i",
690 DECL_UID (INSN_VAR_LOCATION_DECL (insn
)));
694 if (VAR_LOC_UNKNOWN_P (INSN_VAR_LOCATION_LOC (insn
)))
695 sprintf (buf
, " %4d: debug %s optimized away", INSN_UID (insn
), name
);
698 print_pattern (t
, INSN_VAR_LOCATION_LOC (insn
), verbose
);
699 sprintf (buf
, " %4d: debug %s => %s", INSN_UID (insn
), name
, t
);
705 print_pattern (t
, PATTERN (x
), verbose
);
706 #ifdef INSN_SCHEDULING
707 if (verbose
&& current_sched_info
)
708 sprintf (buf
, "%s: jump %s", (*current_sched_info
->print_insn
) (x
, 1),
712 sprintf (buf
, " %4d %s", INSN_UID (x
), t
);
716 if (GET_CODE (x
) == PARALLEL
)
718 x
= XVECEXP (x
, 0, 0);
719 print_pattern (t
, x
, verbose
);
722 strcpy (t
, "call <...>");
723 #ifdef INSN_SCHEDULING
724 if (verbose
&& current_sched_info
)
725 sprintf (buf
, "%s: %s", (*current_sched_info
->print_insn
) (insn
, 1), t
);
728 sprintf (buf
, " %4d %s", INSN_UID (insn
), t
);
731 sprintf (buf
, "L%d:", INSN_UID (x
));
734 sprintf (buf
, "i%4d: barrier", INSN_UID (x
));
737 sprintf (buf
, " %4d %s", INSN_UID (x
),
738 GET_NOTE_INSN_NAME (NOTE_KIND (x
)));
741 sprintf (buf
, "i%4d <What %s?>", INSN_UID (x
),
742 GET_RTX_NAME (GET_CODE (x
)));
746 /* Emit a slim dump of X (an insn) to the file F, including any register
747 note attached to the instruction. */
749 dump_insn_slim (FILE *f
, rtx x
)
751 char t
[BUF_LEN
+ 32];
754 print_insn (t
, x
, 1);
757 if (INSN_P (x
) && REG_NOTES (x
))
758 for (note
= REG_NOTES (x
); note
; note
= XEXP (note
, 1))
760 print_value (t
, XEXP (note
, 0), 1);
761 fprintf (f
, " %s: %s\n",
762 GET_REG_NOTE_NAME (REG_NOTE_KIND (note
)), t
);
766 /* Emit a slim dump of X (an insn) to stderr. */
768 debug_insn_slim (rtx x
)
770 dump_insn_slim (stderr
, x
);
773 /* Provide a slim dump the instruction chain starting at FIRST to F, honoring
774 the dump flags given in FLAGS. Currently, TDF_BLOCKS and TDF_DETAILS
775 include more information on the basic blocks. */
777 print_rtl_slim_with_bb (FILE *f
, rtx first
, int flags
)
779 print_rtl_slim (f
, first
, NULL
, -1, flags
);
782 /* Same as above, but stop at LAST or when COUNT == 0.
783 If COUNT < 0 it will stop only at LAST or NULL rtx. */
785 print_rtl_slim (FILE *f
, rtx first
, rtx last
, int count
, int flags
)
787 basic_block current_bb
= NULL
;
790 tail
= last
? NEXT_INSN (last
) : NULL_RTX
;
792 (insn
!= NULL
) && (insn
!= tail
) && (count
!= 0);
793 insn
= NEXT_INSN (insn
))
795 if ((flags
& TDF_BLOCKS
)
796 && (INSN_P (insn
) || NOTE_P (insn
))
797 && BLOCK_FOR_INSN (insn
)
800 current_bb
= BLOCK_FOR_INSN (insn
);
801 dump_bb_info (current_bb
, true, false, flags
, ";; ", f
);
804 dump_insn_slim (f
, insn
);
806 if ((flags
& TDF_BLOCKS
)
808 && insn
== BB_END (current_bb
))
810 dump_bb_info (current_bb
, false, true, flags
, ";; ", f
);
819 debug_bb_slim (struct basic_block_def
*bb
)
821 print_rtl_slim (stderr
, BB_HEAD (bb
), BB_END (bb
), -1, 32);
825 debug_bb_n_slim (int n
)
827 struct basic_block_def
*bb
= BASIC_BLOCK (n
);