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 cur
= safe_concat (buf
, cur
, "\"");
452 cur
= safe_concat (buf
, cur
, XSTR (x
, 0));
453 cur
= safe_concat (buf
, cur
, "\"");
456 cur
= safe_concat (buf
, cur
, "`");
457 cur
= safe_concat (buf
, cur
, XSTR (x
, 0));
458 cur
= safe_concat (buf
, cur
, "'");
461 sprintf (t
, "L%d", INSN_UID (XEXP (x
, 0)));
462 cur
= safe_concat (buf
, cur
, t
);
465 print_value (t
, XEXP (x
, 0), verbose
);
466 cur
= safe_concat (buf
, cur
, "const(");
467 cur
= safe_concat (buf
, cur
, t
);
468 cur
= safe_concat (buf
, cur
, ")");
471 print_value (t
, XEXP (x
, 0), verbose
);
472 cur
= safe_concat (buf
, cur
, "high(");
473 cur
= safe_concat (buf
, cur
, t
);
474 cur
= safe_concat (buf
, cur
, ")");
477 if (REGNO (x
) < FIRST_PSEUDO_REGISTER
)
479 int c
= reg_names
[REGNO (x
)][0];
481 cur
= safe_concat (buf
, cur
, "%");
483 cur
= safe_concat (buf
, cur
, reg_names
[REGNO (x
)]);
487 sprintf (t
, "r%d", REGNO (x
));
488 cur
= safe_concat (buf
, cur
, t
);
491 #ifdef INSN_SCHEDULING
492 && !current_sched_info
496 sprintf (t
, ":%s", GET_MODE_NAME (GET_MODE (x
)));
497 cur
= safe_concat (buf
, cur
, t
);
501 print_value (t
, SUBREG_REG (x
), verbose
);
502 cur
= safe_concat (buf
, cur
, t
);
503 sprintf (t
, "#%d", SUBREG_BYTE (x
));
504 cur
= safe_concat (buf
, cur
, t
);
507 cur
= safe_concat (buf
, cur
, "scratch");
510 cur
= safe_concat (buf
, cur
, "cc0");
513 cur
= safe_concat (buf
, cur
, "pc");
516 print_value (t
, XEXP (x
, 0), verbose
);
517 cur
= safe_concat (buf
, cur
, "[");
518 cur
= safe_concat (buf
, cur
, t
);
519 cur
= safe_concat (buf
, cur
, "]");
522 print_exp (t
, x
, verbose
);
523 cur
= safe_concat (buf
, cur
, t
);
528 /* The next step in insn detalization, its pattern recognition. */
531 print_pattern (char *buf
, const_rtx x
, int verbose
)
533 char t1
[BUF_LEN
], t2
[BUF_LEN
], t3
[BUF_LEN
];
535 switch (GET_CODE (x
))
538 print_value (t1
, SET_DEST (x
), verbose
);
539 print_value (t2
, SET_SRC (x
), verbose
);
540 sprintf (buf
, "%s=%s", t1
, t2
);
543 sprintf (buf
, "return");
546 print_exp (buf
, x
, verbose
);
549 print_value (t1
, XEXP (x
, 0), verbose
);
550 sprintf (buf
, "clobber %s", t1
);
553 print_value (t1
, XEXP (x
, 0), verbose
);
554 sprintf (buf
, "use %s", t1
);
557 if (GET_CODE (COND_EXEC_TEST (x
)) == NE
558 && XEXP (COND_EXEC_TEST (x
), 1) == const0_rtx
)
559 print_value (t1
, XEXP (COND_EXEC_TEST (x
), 0), verbose
);
560 else if (GET_CODE (COND_EXEC_TEST (x
)) == EQ
561 && XEXP (COND_EXEC_TEST (x
), 1) == const0_rtx
)
564 print_value (t1
+ 1, XEXP (COND_EXEC_TEST (x
), 0), verbose
);
567 print_value (t1
, COND_EXEC_TEST (x
), verbose
);
568 print_pattern (t2
, COND_EXEC_CODE (x
), verbose
);
569 sprintf (buf
, "(%s) %s", t1
, t2
);
576 for (i
= 0; i
< XVECLEN (x
, 0); i
++)
578 print_pattern (t2
, XVECEXP (x
, 0, i
), verbose
);
579 sprintf (t3
, "%s%s;", t1
, t2
);
582 sprintf (buf
, "%s}", t1
);
586 /* Should never see SEQUENCE codes until after reorg. */
589 sprintf (buf
, "asm {%s}", XSTR (x
, 0));
594 print_value (buf
, XEXP (x
, 0), verbose
);
597 print_value (t1
, TRAP_CONDITION (x
), verbose
);
598 sprintf (buf
, "trap_if %s", t1
);
604 sprintf (t1
, "unspec{");
605 for (i
= 0; i
< XVECLEN (x
, 0); i
++)
607 print_pattern (t2
, XVECEXP (x
, 0, i
), verbose
);
608 sprintf (t3
, "%s%s;", t1
, t2
);
611 sprintf (buf
, "%s}", t1
);
614 case UNSPEC_VOLATILE
:
618 sprintf (t1
, "unspec/v{");
619 for (i
= 0; i
< XVECLEN (x
, 0); i
++)
621 print_pattern (t2
, XVECEXP (x
, 0, i
), verbose
);
622 sprintf (t3
, "%s%s;", t1
, t2
);
625 sprintf (buf
, "%s}", t1
);
629 print_value (buf
, x
, verbose
);
631 } /* print_pattern */
633 /* This is the main function in rtl visualization mechanism. It
634 accepts an rtx and tries to recognize it as an insn, then prints it
635 properly in human readable form, resembling assembler mnemonics.
636 For every insn it prints its UID and BB the insn belongs too.
637 (Probably the last "option" should be extended somehow, since it
638 depends now on sched.c inner variables ...) */
641 print_insn (char *buf
, rtx x
, int verbose
)
646 switch (GET_CODE (x
))
649 print_pattern (t
, PATTERN (x
), verbose
);
650 #ifdef INSN_SCHEDULING
651 if (verbose
&& current_sched_info
)
652 sprintf (buf
, "%s: %s", (*current_sched_info
->print_insn
) (x
, 1),
656 sprintf (buf
, " %4d %s", INSN_UID (x
), t
);
659 print_pattern (t
, PATTERN (x
), verbose
);
660 #ifdef INSN_SCHEDULING
661 if (verbose
&& current_sched_info
)
662 sprintf (buf
, "%s: jump %s", (*current_sched_info
->print_insn
) (x
, 1),
666 sprintf (buf
, " %4d %s", INSN_UID (x
), t
);
670 if (GET_CODE (x
) == PARALLEL
)
672 x
= XVECEXP (x
, 0, 0);
673 print_pattern (t
, x
, verbose
);
676 strcpy (t
, "call <...>");
677 #ifdef INSN_SCHEDULING
678 if (verbose
&& current_sched_info
)
679 sprintf (buf
, "%s: %s", (*current_sched_info
->print_insn
) (x
, 1), t
);
682 sprintf (buf
, " %4d %s", INSN_UID (insn
), t
);
685 sprintf (buf
, "L%d:", INSN_UID (x
));
688 sprintf (buf
, "i%4d: barrier", INSN_UID (x
));
691 sprintf (buf
, " %4d %s", INSN_UID (x
),
692 GET_NOTE_INSN_NAME (NOTE_KIND (x
)));
695 sprintf (buf
, "i%4d <What %s?>", INSN_UID (x
),
696 GET_RTX_NAME (GET_CODE (x
)));
701 /* Emit a slim dump of X (an insn) to the file F, including any register
702 note attached to the instruction. */
704 dump_insn_slim (FILE *f
, rtx x
)
706 char t
[BUF_LEN
+ 32];
709 print_insn (t
, x
, 1);
712 if (INSN_P (x
) && REG_NOTES (x
))
713 for (note
= REG_NOTES (x
); note
; note
= XEXP (note
, 1))
715 print_value (t
, XEXP (note
, 0), 1);
716 fprintf (f
, " %s: %s\n",
717 GET_REG_NOTE_NAME (REG_NOTE_KIND (note
)), t
);
721 /* Emit a slim dump of X (an insn) to stderr. */
723 debug_insn_slim (rtx x
)
725 dump_insn_slim (stderr
, x
);
728 /* Provide a slim dump the instruction chain starting at FIRST to F, honoring
729 the dump flags given in FLAGS. Currently, TDF_BLOCKS and TDF_DETAILS
730 include more information on the basic blocks. */
732 print_rtl_slim_with_bb (FILE *f
, rtx first
, int flags
)
734 basic_block current_bb
= NULL
;
737 for (insn
= first
; NULL
!= insn
; insn
= NEXT_INSN (insn
))
739 if ((flags
& TDF_BLOCKS
)
740 && (INSN_P (insn
) || GET_CODE (insn
) == NOTE
)
741 && BLOCK_FOR_INSN (insn
)
744 current_bb
= BLOCK_FOR_INSN (insn
);
745 dump_bb_info (current_bb
, true, false, flags
, ";; ", f
);
748 dump_insn_slim (f
, insn
);
750 if ((flags
& TDF_BLOCKS
)
752 && insn
== BB_END (current_bb
))
754 dump_bb_info (current_bb
, false, true, flags
, ";; ", f
);