1 /* Instruction scheduling pass.
2 Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
3 2002, 2003, 2004, 2005, 2006, 2007 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 "sched-int.h"
33 #include "tree-pass.h"
35 static char *safe_concat (char *, char *, const char *);
36 static void print_exp (char *, const_rtx
, int);
37 static void print_value (char *, const_rtx
, int);
38 static void print_pattern (char *, const_rtx
, int);
43 safe_concat (char *buf
, char *cur
, const char *str
)
45 char *end
= buf
+ BUF_LEN
- 2; /* Leave room for null. */
54 while (cur
< end
&& (c
= *str
++) != '\0')
61 /* This recognizes rtx, I classified as expressions. These are always
62 represent some action on values or results of other expression, that
63 may be stored in objects representing values. */
66 print_exp (char *buf
, const_rtx x
, int verbose
)
71 const char *fun
= (char *) 0;
76 for (i
= 0; i
< 4; i
++)
86 if (GET_CODE (XEXP (x
, 1)) == CONST_INT
87 && INTVAL (XEXP (x
, 1)) < 0)
90 op
[1] = GEN_INT (-INTVAL (XEXP (x
, 1)));
270 fun
= (verbose
) ? "sign_extract" : "sxt";
276 fun
= (verbose
) ? "zero_extract" : "zxt";
282 fun
= (verbose
) ? "sign_extend" : "sxn";
286 fun
= (verbose
) ? "zero_extend" : "zxn";
290 fun
= (verbose
) ? "float_extend" : "fxn";
294 fun
= (verbose
) ? "trunc" : "trn";
298 fun
= (verbose
) ? "float_trunc" : "ftr";
302 fun
= (verbose
) ? "float" : "flt";
306 fun
= (verbose
) ? "uns_float" : "ufl";
314 fun
= (verbose
) ? "uns_fix" : "ufx";
335 op
[0] = XEXP (XEXP (x
, 1), 0);
337 op
[1] = XEXP (XEXP (x
, 1), 1);
341 op
[0] = XEXP (XEXP (x
, 1), 0);
343 op
[1] = XEXP (XEXP (x
, 1), 1);
365 op
[0] = TRAP_CONDITION (x
);
374 case UNSPEC_VOLATILE
:
376 cur
= safe_concat (buf
, cur
, "unspec");
377 if (GET_CODE (x
) == UNSPEC_VOLATILE
)
378 cur
= safe_concat (buf
, cur
, "/v");
379 cur
= safe_concat (buf
, cur
, "[");
381 for (i
= 0; i
< XVECLEN (x
, 0); i
++)
383 print_pattern (tmp
, XVECEXP (x
, 0, i
), verbose
);
384 cur
= safe_concat (buf
, cur
, sep
);
385 cur
= safe_concat (buf
, cur
, tmp
);
388 cur
= safe_concat (buf
, cur
, "] ");
389 sprintf (tmp
, "%d", XINT (x
, 1));
390 cur
= safe_concat (buf
, cur
, tmp
);
394 /* If (verbose) debug_rtx (x); */
395 st
[0] = GET_RTX_NAME (GET_CODE (x
));
399 /* Print this as a function? */
402 cur
= safe_concat (buf
, cur
, fun
);
403 cur
= safe_concat (buf
, cur
, "(");
406 for (i
= 0; i
< 4; i
++)
409 cur
= safe_concat (buf
, cur
, st
[i
]);
414 cur
= safe_concat (buf
, cur
, ",");
416 print_value (tmp
, op
[i
], verbose
);
417 cur
= safe_concat (buf
, cur
, tmp
);
422 cur
= safe_concat (buf
, cur
, ")");
425 /* Prints rtxes, I customarily classified as values. They're constants,
426 registers, labels, symbols and memory accesses. */
429 print_value (char *buf
, const_rtx x
, int verbose
)
434 switch (GET_CODE (x
))
437 sprintf (t
, HOST_WIDE_INT_PRINT_HEX
, INTVAL (x
));
438 cur
= safe_concat (buf
, cur
, t
);
441 if (FLOAT_MODE_P (GET_MODE (x
)))
442 real_to_decimal (t
, CONST_DOUBLE_REAL_VALUE (x
), sizeof (t
), 0, 1);
445 "<" HOST_WIDE_INT_PRINT_HEX
"," HOST_WIDE_INT_PRINT_HEX
">",
446 (unsigned HOST_WIDE_INT
) CONST_DOUBLE_LOW (x
),
447 (unsigned HOST_WIDE_INT
) CONST_DOUBLE_HIGH (x
));
448 cur
= safe_concat (buf
, cur
, t
);
451 fixed_to_decimal (t
, CONST_FIXED_VALUE (x
), sizeof (t
));
452 cur
= safe_concat (buf
, cur
, t
);
455 cur
= safe_concat (buf
, cur
, "\"");
456 cur
= safe_concat (buf
, cur
, XSTR (x
, 0));
457 cur
= safe_concat (buf
, cur
, "\"");
460 cur
= safe_concat (buf
, cur
, "`");
461 cur
= safe_concat (buf
, cur
, XSTR (x
, 0));
462 cur
= safe_concat (buf
, cur
, "'");
465 sprintf (t
, "L%d", INSN_UID (XEXP (x
, 0)));
466 cur
= safe_concat (buf
, cur
, t
);
469 print_value (t
, XEXP (x
, 0), verbose
);
470 cur
= safe_concat (buf
, cur
, "const(");
471 cur
= safe_concat (buf
, cur
, t
);
472 cur
= safe_concat (buf
, cur
, ")");
475 print_value (t
, XEXP (x
, 0), verbose
);
476 cur
= safe_concat (buf
, cur
, "high(");
477 cur
= safe_concat (buf
, cur
, t
);
478 cur
= safe_concat (buf
, cur
, ")");
481 if (REGNO (x
) < FIRST_PSEUDO_REGISTER
)
483 int c
= reg_names
[REGNO (x
)][0];
485 cur
= safe_concat (buf
, cur
, "%");
487 cur
= safe_concat (buf
, cur
, reg_names
[REGNO (x
)]);
491 sprintf (t
, "r%d", REGNO (x
));
492 cur
= safe_concat (buf
, cur
, t
);
495 #ifdef INSN_SCHEDULING
496 && !current_sched_info
500 sprintf (t
, ":%s", GET_MODE_NAME (GET_MODE (x
)));
501 cur
= safe_concat (buf
, cur
, t
);
505 print_value (t
, SUBREG_REG (x
), verbose
);
506 cur
= safe_concat (buf
, cur
, t
);
507 sprintf (t
, "#%d", SUBREG_BYTE (x
));
508 cur
= safe_concat (buf
, cur
, t
);
511 cur
= safe_concat (buf
, cur
, "scratch");
514 cur
= safe_concat (buf
, cur
, "cc0");
517 cur
= safe_concat (buf
, cur
, "pc");
520 print_value (t
, XEXP (x
, 0), verbose
);
521 cur
= safe_concat (buf
, cur
, "[");
522 cur
= safe_concat (buf
, cur
, t
);
523 cur
= safe_concat (buf
, cur
, "]");
526 print_exp (t
, x
, verbose
);
527 cur
= safe_concat (buf
, cur
, t
);
532 /* The next step in insn detalization, its pattern recognition. */
535 print_pattern (char *buf
, const_rtx x
, int verbose
)
537 char t1
[BUF_LEN
], t2
[BUF_LEN
], t3
[BUF_LEN
];
539 switch (GET_CODE (x
))
542 print_value (t1
, SET_DEST (x
), verbose
);
543 print_value (t2
, SET_SRC (x
), verbose
);
544 sprintf (buf
, "%s=%s", t1
, t2
);
547 sprintf (buf
, "return");
550 print_exp (buf
, x
, verbose
);
553 print_value (t1
, XEXP (x
, 0), verbose
);
554 sprintf (buf
, "clobber %s", t1
);
557 print_value (t1
, XEXP (x
, 0), verbose
);
558 sprintf (buf
, "use %s", t1
);
561 if (GET_CODE (COND_EXEC_TEST (x
)) == NE
562 && XEXP (COND_EXEC_TEST (x
), 1) == const0_rtx
)
563 print_value (t1
, XEXP (COND_EXEC_TEST (x
), 0), verbose
);
564 else if (GET_CODE (COND_EXEC_TEST (x
)) == EQ
565 && XEXP (COND_EXEC_TEST (x
), 1) == const0_rtx
)
568 print_value (t1
+ 1, XEXP (COND_EXEC_TEST (x
), 0), verbose
);
571 print_value (t1
, COND_EXEC_TEST (x
), verbose
);
572 print_pattern (t2
, COND_EXEC_CODE (x
), verbose
);
573 sprintf (buf
, "(%s) %s", t1
, t2
);
580 for (i
= 0; i
< XVECLEN (x
, 0); i
++)
582 print_pattern (t2
, XVECEXP (x
, 0, i
), verbose
);
583 sprintf (t3
, "%s%s;", t1
, t2
);
586 sprintf (buf
, "%s}", t1
);
590 /* Should never see SEQUENCE codes until after reorg. */
593 sprintf (buf
, "asm {%s}", XSTR (x
, 0));
598 print_value (buf
, XEXP (x
, 0), verbose
);
601 print_value (t1
, TRAP_CONDITION (x
), verbose
);
602 sprintf (buf
, "trap_if %s", t1
);
608 sprintf (t1
, "unspec{");
609 for (i
= 0; i
< XVECLEN (x
, 0); i
++)
611 print_pattern (t2
, XVECEXP (x
, 0, i
), verbose
);
612 sprintf (t3
, "%s%s;", t1
, t2
);
615 sprintf (buf
, "%s}", t1
);
618 case UNSPEC_VOLATILE
:
622 sprintf (t1
, "unspec/v{");
623 for (i
= 0; i
< XVECLEN (x
, 0); i
++)
625 print_pattern (t2
, XVECEXP (x
, 0, i
), verbose
);
626 sprintf (t3
, "%s%s;", t1
, t2
);
629 sprintf (buf
, "%s}", t1
);
633 print_value (buf
, x
, verbose
);
635 } /* print_pattern */
637 /* This is the main function in rtl visualization mechanism. It
638 accepts an rtx and tries to recognize it as an insn, then prints it
639 properly in human readable form, resembling assembler mnemonics.
640 For every insn it prints its UID and BB the insn belongs too.
641 (Probably the last "option" should be extended somehow, since it
642 depends now on sched.c inner variables ...) */
645 print_insn (char *buf
, rtx x
, int verbose
)
650 switch (GET_CODE (x
))
653 print_pattern (t
, PATTERN (x
), verbose
);
654 #ifdef INSN_SCHEDULING
655 if (verbose
&& current_sched_info
)
656 sprintf (buf
, "%s: %s", (*current_sched_info
->print_insn
) (x
, 1),
660 sprintf (buf
, " %4d %s", INSN_UID (x
), t
);
663 print_pattern (t
, PATTERN (x
), verbose
);
664 #ifdef INSN_SCHEDULING
665 if (verbose
&& current_sched_info
)
666 sprintf (buf
, "%s: jump %s", (*current_sched_info
->print_insn
) (x
, 1),
670 sprintf (buf
, " %4d %s", INSN_UID (x
), t
);
674 if (GET_CODE (x
) == PARALLEL
)
676 x
= XVECEXP (x
, 0, 0);
677 print_pattern (t
, x
, verbose
);
680 strcpy (t
, "call <...>");
681 #ifdef INSN_SCHEDULING
682 if (verbose
&& current_sched_info
)
683 sprintf (buf
, "%s: %s", (*current_sched_info
->print_insn
) (x
, 1), t
);
686 sprintf (buf
, " %4d %s", INSN_UID (insn
), t
);
689 sprintf (buf
, "L%d:", INSN_UID (x
));
692 sprintf (buf
, "i%4d: barrier", INSN_UID (x
));
695 sprintf (buf
, " %4d %s", INSN_UID (x
),
696 GET_NOTE_INSN_NAME (NOTE_KIND (x
)));
699 sprintf (buf
, "i%4d <What %s?>", INSN_UID (x
),
700 GET_RTX_NAME (GET_CODE (x
)));
705 /* Emit a slim dump of X (an insn) to the file F, including any register
706 note attached to the instruction. */
708 dump_insn_slim (FILE *f
, rtx x
)
710 char t
[BUF_LEN
+ 32];
713 print_insn (t
, x
, 1);
716 if (INSN_P (x
) && REG_NOTES (x
))
717 for (note
= REG_NOTES (x
); note
; note
= XEXP (note
, 1))
719 print_value (t
, XEXP (note
, 0), 1);
720 fprintf (f
, " %s: %s\n",
721 GET_REG_NOTE_NAME (REG_NOTE_KIND (note
)), t
);
725 /* Emit a slim dump of X (an insn) to stderr. */
727 debug_insn_slim (rtx x
)
729 dump_insn_slim (stderr
, x
);
732 /* Provide a slim dump the instruction chain starting at FIRST to F, honoring
733 the dump flags given in FLAGS. Currently, TDF_BLOCKS and TDF_DETAILS
734 include more information on the basic blocks. */
736 print_rtl_slim_with_bb (FILE *f
, rtx first
, int flags
)
738 basic_block current_bb
= NULL
;
741 for (insn
= first
; NULL
!= insn
; insn
= NEXT_INSN (insn
))
743 if ((flags
& TDF_BLOCKS
)
744 && (INSN_P (insn
) || GET_CODE (insn
) == NOTE
)
745 && BLOCK_FOR_INSN (insn
)
748 current_bb
= BLOCK_FOR_INSN (insn
);
749 dump_bb_info (current_bb
, true, false, flags
, ";; ", f
);
752 dump_insn_slim (f
, insn
);
754 if ((flags
& TDF_BLOCKS
)
756 && insn
== BB_END (current_bb
))
758 dump_bb_info (current_bb
, false, true, flags
, ";; ", f
);