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"
31 #include "insn-attr.h"
32 #include "sched-int.h"
33 #include "tree-pass.h"
35 static char *safe_concat (char *, char *, const char *);
40 safe_concat (char *buf
, char *cur
, const char *str
)
42 char *end
= buf
+ BUF_LEN
- 2; /* Leave room for null. */
51 while (cur
< end
&& (c
= *str
++) != '\0')
58 /* This recognizes rtx, I classified as expressions. These are always
59 represent some action on values or results of other expression, that
60 may be stored in objects representing values. */
63 print_exp (char *buf
, const_rtx x
, int verbose
)
68 const char *fun
= (char *) 0;
73 for (i
= 0; i
< 4; i
++)
83 if (CONST_INT_P (XEXP (x
, 1))
84 && INTVAL (XEXP (x
, 1)) < 0)
87 op
[1] = GEN_INT (-INTVAL (XEXP (x
, 1)));
267 fun
= (verbose
) ? "sign_extract" : "sxt";
273 fun
= (verbose
) ? "zero_extract" : "zxt";
279 fun
= (verbose
) ? "sign_extend" : "sxn";
283 fun
= (verbose
) ? "zero_extend" : "zxn";
287 fun
= (verbose
) ? "float_extend" : "fxn";
291 fun
= (verbose
) ? "trunc" : "trn";
295 fun
= (verbose
) ? "float_trunc" : "ftr";
299 fun
= (verbose
) ? "float" : "flt";
303 fun
= (verbose
) ? "uns_float" : "ufl";
311 fun
= (verbose
) ? "uns_fix" : "ufx";
332 op
[0] = XEXP (XEXP (x
, 1), 0);
334 op
[1] = XEXP (XEXP (x
, 1), 1);
338 op
[0] = XEXP (XEXP (x
, 1), 0);
340 op
[1] = XEXP (XEXP (x
, 1), 1);
362 op
[0] = TRAP_CONDITION (x
);
371 case UNSPEC_VOLATILE
:
373 cur
= safe_concat (buf
, cur
, "unspec");
374 if (GET_CODE (x
) == UNSPEC_VOLATILE
)
375 cur
= safe_concat (buf
, cur
, "/v");
376 cur
= safe_concat (buf
, cur
, "[");
378 for (i
= 0; i
< XVECLEN (x
, 0); i
++)
380 print_pattern (tmp
, XVECEXP (x
, 0, i
), verbose
);
381 cur
= safe_concat (buf
, cur
, sep
);
382 cur
= safe_concat (buf
, cur
, tmp
);
385 cur
= safe_concat (buf
, cur
, "] ");
386 sprintf (tmp
, "%d", XINT (x
, 1));
387 cur
= safe_concat (buf
, cur
, tmp
);
391 /* If (verbose) debug_rtx (x); */
392 st
[0] = GET_RTX_NAME (GET_CODE (x
));
396 /* Print this as a function? */
399 cur
= safe_concat (buf
, cur
, fun
);
400 cur
= safe_concat (buf
, cur
, "(");
403 for (i
= 0; i
< 4; i
++)
406 cur
= safe_concat (buf
, cur
, st
[i
]);
411 cur
= safe_concat (buf
, cur
, ",");
413 print_value (tmp
, op
[i
], verbose
);
414 cur
= safe_concat (buf
, cur
, tmp
);
419 cur
= safe_concat (buf
, cur
, ")");
422 /* Prints rtxes, I customarily classified as values. They're constants,
423 registers, labels, symbols and memory accesses. */
426 print_value (char *buf
, const_rtx x
, int verbose
)
431 switch (GET_CODE (x
))
434 sprintf (t
, HOST_WIDE_INT_PRINT_HEX
,
435 (unsigned HOST_WIDE_INT
) INTVAL (x
));
436 cur
= safe_concat (buf
, cur
, t
);
439 if (FLOAT_MODE_P (GET_MODE (x
)))
440 real_to_decimal (t
, CONST_DOUBLE_REAL_VALUE (x
), sizeof (t
), 0, 1);
443 "<" HOST_WIDE_INT_PRINT_HEX
"," HOST_WIDE_INT_PRINT_HEX
">",
444 (unsigned HOST_WIDE_INT
) CONST_DOUBLE_LOW (x
),
445 (unsigned HOST_WIDE_INT
) CONST_DOUBLE_HIGH (x
));
446 cur
= safe_concat (buf
, cur
, t
);
449 fixed_to_decimal (t
, CONST_FIXED_VALUE (x
), sizeof (t
));
450 cur
= safe_concat (buf
, cur
, t
);
453 cur
= safe_concat (buf
, cur
, "\"");
454 cur
= safe_concat (buf
, cur
, XSTR (x
, 0));
455 cur
= safe_concat (buf
, cur
, "\"");
458 cur
= safe_concat (buf
, cur
, "`");
459 cur
= safe_concat (buf
, cur
, XSTR (x
, 0));
460 cur
= safe_concat (buf
, cur
, "'");
463 sprintf (t
, "L%d", INSN_UID (XEXP (x
, 0)));
464 cur
= safe_concat (buf
, cur
, t
);
467 print_value (t
, XEXP (x
, 0), verbose
);
468 cur
= safe_concat (buf
, cur
, "const(");
469 cur
= safe_concat (buf
, cur
, t
);
470 cur
= safe_concat (buf
, cur
, ")");
473 print_value (t
, XEXP (x
, 0), verbose
);
474 cur
= safe_concat (buf
, cur
, "high(");
475 cur
= safe_concat (buf
, cur
, t
);
476 cur
= safe_concat (buf
, cur
, ")");
479 if (REGNO (x
) < FIRST_PSEUDO_REGISTER
)
481 int c
= reg_names
[REGNO (x
)][0];
483 cur
= safe_concat (buf
, cur
, "%");
485 cur
= safe_concat (buf
, cur
, reg_names
[REGNO (x
)]);
489 sprintf (t
, "r%d", REGNO (x
));
490 cur
= safe_concat (buf
, cur
, t
);
493 #ifdef INSN_SCHEDULING
494 && !current_sched_info
498 sprintf (t
, ":%s", GET_MODE_NAME (GET_MODE (x
)));
499 cur
= safe_concat (buf
, cur
, t
);
503 print_value (t
, SUBREG_REG (x
), verbose
);
504 cur
= safe_concat (buf
, cur
, t
);
505 sprintf (t
, "#%d", SUBREG_BYTE (x
));
506 cur
= safe_concat (buf
, cur
, t
);
509 cur
= safe_concat (buf
, cur
, "scratch");
512 cur
= safe_concat (buf
, cur
, "cc0");
515 cur
= safe_concat (buf
, cur
, "pc");
518 print_value (t
, XEXP (x
, 0), verbose
);
519 cur
= safe_concat (buf
, cur
, "[");
520 cur
= safe_concat (buf
, cur
, t
);
521 cur
= safe_concat (buf
, cur
, "]");
524 sprintf (t
, "D#%i", DEBUG_TEMP_UID (DEBUG_EXPR_TREE_DECL (x
)));
525 cur
= safe_concat (buf
, cur
, t
);
528 print_exp (t
, x
, verbose
);
529 cur
= safe_concat (buf
, cur
, t
);
534 /* The next step in insn detalization, its pattern recognition. */
537 print_pattern (char *buf
, const_rtx x
, int verbose
)
539 char t1
[BUF_LEN
], t2
[BUF_LEN
], t3
[BUF_LEN
];
541 switch (GET_CODE (x
))
544 print_value (t1
, SET_DEST (x
), verbose
);
545 print_value (t2
, SET_SRC (x
), verbose
);
546 sprintf (buf
, "%s=%s", t1
, t2
);
549 sprintf (buf
, "return");
552 print_exp (buf
, x
, verbose
);
555 print_value (t1
, XEXP (x
, 0), verbose
);
556 sprintf (buf
, "clobber %s", t1
);
559 print_value (t1
, XEXP (x
, 0), verbose
);
560 sprintf (buf
, "use %s", t1
);
563 print_value (t1
, PAT_VAR_LOCATION_LOC (x
), verbose
);
564 sprintf (buf
, "loc %s", t1
);
567 if (GET_CODE (COND_EXEC_TEST (x
)) == NE
568 && XEXP (COND_EXEC_TEST (x
), 1) == const0_rtx
)
569 print_value (t1
, XEXP (COND_EXEC_TEST (x
), 0), verbose
);
570 else if (GET_CODE (COND_EXEC_TEST (x
)) == EQ
571 && XEXP (COND_EXEC_TEST (x
), 1) == const0_rtx
)
574 print_value (t1
+ 1, XEXP (COND_EXEC_TEST (x
), 0), verbose
);
577 print_value (t1
, COND_EXEC_TEST (x
), verbose
);
578 print_pattern (t2
, COND_EXEC_CODE (x
), verbose
);
579 sprintf (buf
, "(%s) %s", t1
, t2
);
586 for (i
= 0; i
< XVECLEN (x
, 0); i
++)
588 print_pattern (t2
, XVECEXP (x
, 0, i
), verbose
);
589 sprintf (t3
, "%s%s;", t1
, t2
);
592 sprintf (buf
, "%s}", t1
);
596 /* Should never see SEQUENCE codes until after reorg. */
599 sprintf (buf
, "asm {%s}", XSTR (x
, 0));
604 print_value (buf
, XEXP (x
, 0), verbose
);
607 print_value (t1
, TRAP_CONDITION (x
), verbose
);
608 sprintf (buf
, "trap_if %s", t1
);
614 sprintf (t1
, "unspec{");
615 for (i
= 0; i
< XVECLEN (x
, 0); i
++)
617 print_pattern (t2
, XVECEXP (x
, 0, i
), verbose
);
618 sprintf (t3
, "%s%s;", t1
, t2
);
621 sprintf (buf
, "%s}", t1
);
624 case UNSPEC_VOLATILE
:
628 sprintf (t1
, "unspec/v{");
629 for (i
= 0; i
< XVECLEN (x
, 0); i
++)
631 print_pattern (t2
, XVECEXP (x
, 0, i
), verbose
);
632 sprintf (t3
, "%s%s;", t1
, t2
);
635 sprintf (buf
, "%s}", t1
);
639 print_value (buf
, x
, verbose
);
641 } /* print_pattern */
643 /* This is the main function in rtl visualization mechanism. It
644 accepts an rtx and tries to recognize it as an insn, then prints it
645 properly in human readable form, resembling assembler mnemonics.
646 For every insn it prints its UID and BB the insn belongs too.
647 (Probably the last "option" should be extended somehow, since it
648 depends now on sched.c inner variables ...) */
651 print_insn (char *buf
, const_rtx x
, int verbose
)
656 switch (GET_CODE (x
))
659 print_pattern (t
, PATTERN (x
), verbose
);
660 #ifdef INSN_SCHEDULING
661 if (verbose
&& current_sched_info
)
662 sprintf (buf
, "%s: %s", (*current_sched_info
->print_insn
) (x
, 1),
666 sprintf (buf
, " %4d %s", INSN_UID (x
), t
);
671 const char *name
= "?";
673 if (DECL_P (INSN_VAR_LOCATION_DECL (insn
)))
675 tree id
= DECL_NAME (INSN_VAR_LOCATION_DECL (insn
));
678 name
= IDENTIFIER_POINTER (id
);
679 else if (TREE_CODE (INSN_VAR_LOCATION_DECL (insn
))
682 sprintf (idbuf
, "D#%i",
683 DEBUG_TEMP_UID (INSN_VAR_LOCATION_DECL (insn
)));
688 sprintf (idbuf
, "D.%i",
689 DECL_UID (INSN_VAR_LOCATION_DECL (insn
)));
693 if (VAR_LOC_UNKNOWN_P (INSN_VAR_LOCATION_LOC (insn
)))
694 sprintf (buf
, " %4d: debug %s optimized away", INSN_UID (insn
), name
);
697 print_pattern (t
, INSN_VAR_LOCATION_LOC (insn
), verbose
);
698 sprintf (buf
, " %4d: debug %s => %s", INSN_UID (insn
), name
, t
);
704 print_pattern (t
, PATTERN (x
), verbose
);
705 #ifdef INSN_SCHEDULING
706 if (verbose
&& current_sched_info
)
707 sprintf (buf
, "%s: jump %s", (*current_sched_info
->print_insn
) (x
, 1),
711 sprintf (buf
, " %4d %s", INSN_UID (x
), t
);
715 if (GET_CODE (x
) == PARALLEL
)
717 x
= XVECEXP (x
, 0, 0);
718 print_pattern (t
, x
, verbose
);
721 strcpy (t
, "call <...>");
722 #ifdef INSN_SCHEDULING
723 if (verbose
&& current_sched_info
)
724 sprintf (buf
, "%s: %s", (*current_sched_info
->print_insn
) (insn
, 1), t
);
727 sprintf (buf
, " %4d %s", INSN_UID (insn
), t
);
730 sprintf (buf
, "L%d:", INSN_UID (x
));
733 sprintf (buf
, "i%4d: barrier", INSN_UID (x
));
736 sprintf (buf
, " %4d %s", INSN_UID (x
),
737 GET_NOTE_INSN_NAME (NOTE_KIND (x
)));
740 sprintf (buf
, "i%4d <What %s?>", INSN_UID (x
),
741 GET_RTX_NAME (GET_CODE (x
)));
745 /* Emit a slim dump of X (an insn) to the file F, including any register
746 note attached to the instruction. */
748 dump_insn_slim (FILE *f
, rtx x
)
750 char t
[BUF_LEN
+ 32];
753 print_insn (t
, x
, 1);
756 if (INSN_P (x
) && REG_NOTES (x
))
757 for (note
= REG_NOTES (x
); note
; note
= XEXP (note
, 1))
759 print_value (t
, XEXP (note
, 0), 1);
760 fprintf (f
, " %s: %s\n",
761 GET_REG_NOTE_NAME (REG_NOTE_KIND (note
)), t
);
765 /* Emit a slim dump of X (an insn) to stderr. */
767 debug_insn_slim (rtx x
)
769 dump_insn_slim (stderr
, x
);
772 /* Provide a slim dump the instruction chain starting at FIRST to F, honoring
773 the dump flags given in FLAGS. Currently, TDF_BLOCKS and TDF_DETAILS
774 include more information on the basic blocks. */
776 print_rtl_slim_with_bb (FILE *f
, rtx first
, int flags
)
778 print_rtl_slim (f
, first
, NULL
, -1, flags
);
781 /* Same as above, but stop at LAST or when COUNT == 0.
782 If COUNT < 0 it will stop only at LAST or NULL rtx. */
784 print_rtl_slim (FILE *f
, rtx first
, rtx last
, int count
, int flags
)
786 basic_block current_bb
= NULL
;
789 tail
= last
? NEXT_INSN (last
) : NULL_RTX
;
791 (insn
!= NULL
) && (insn
!= tail
) && (count
!= 0);
792 insn
= NEXT_INSN (insn
))
794 if ((flags
& TDF_BLOCKS
)
795 && (INSN_P (insn
) || NOTE_P (insn
))
796 && BLOCK_FOR_INSN (insn
)
799 current_bb
= BLOCK_FOR_INSN (insn
);
800 dump_bb_info (current_bb
, true, false, flags
, ";; ", f
);
803 dump_insn_slim (f
, insn
);
805 if ((flags
& TDF_BLOCKS
)
807 && insn
== BB_END (current_bb
))
809 dump_bb_info (current_bb
, false, true, flags
, ";; ", f
);
818 debug_bb_slim (struct basic_block_def
*bb
)
820 print_rtl_slim (stderr
, BB_HEAD (bb
), BB_END (bb
), -1, 32);
824 debug_bb_n_slim (int n
)
826 struct basic_block_def
*bb
= BASIC_BLOCK (n
);