1 /* Instruction scheduling pass.
2 Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998,
3 1999, 2000, 2002, 2003, 2004, 2005 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 2, 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 COPYING. If not, write to the Free
21 Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
26 #include "coretypes.h"
30 #include "hard-reg-set.h"
31 #include "basic-block.h"
33 #include "sched-int.h"
34 #include "tree-pass.h"
36 static char *safe_concat (char *, char *, const char *);
37 static void print_exp (char *, rtx
, int);
38 static void print_value (char *, rtx
, int);
39 static void print_pattern (char *, rtx
, int);
44 safe_concat (char *buf
, char *cur
, const char *str
)
46 char *end
= buf
+ BUF_LEN
- 2; /* Leave room for null. */
55 while (cur
< end
&& (c
= *str
++) != '\0')
62 /* This recognizes rtx, I classified as expressions. These are always
63 represent some action on values or results of other expression, that
64 may be stored in objects representing values. */
67 print_exp (char *buf
, rtx x
, int verbose
)
72 const char *fun
= (char *) 0;
77 for (i
= 0; i
< 4; i
++)
87 if (GET_CODE (XEXP (x
, 1)) == CONST_INT
88 && INTVAL (XEXP (x
, 1)) < 0)
91 op
[1] = GEN_INT (-INTVAL (XEXP (x
, 1)));
271 fun
= (verbose
) ? "sign_extract" : "sxt";
277 fun
= (verbose
) ? "zero_extract" : "zxt";
283 fun
= (verbose
) ? "sign_extend" : "sxn";
287 fun
= (verbose
) ? "zero_extend" : "zxn";
291 fun
= (verbose
) ? "float_extend" : "fxn";
295 fun
= (verbose
) ? "trunc" : "trn";
299 fun
= (verbose
) ? "float_trunc" : "ftr";
303 fun
= (verbose
) ? "float" : "flt";
307 fun
= (verbose
) ? "uns_float" : "ufl";
315 fun
= (verbose
) ? "uns_fix" : "ufx";
354 op
[0] = TRAP_CONDITION (x
);
363 case UNSPEC_VOLATILE
:
365 cur
= safe_concat (buf
, cur
, "unspec");
366 if (GET_CODE (x
) == UNSPEC_VOLATILE
)
367 cur
= safe_concat (buf
, cur
, "/v");
368 cur
= safe_concat (buf
, cur
, "[");
370 for (i
= 0; i
< XVECLEN (x
, 0); i
++)
372 print_pattern (tmp
, XVECEXP (x
, 0, i
), verbose
);
373 cur
= safe_concat (buf
, cur
, sep
);
374 cur
= safe_concat (buf
, cur
, tmp
);
377 cur
= safe_concat (buf
, cur
, "] ");
378 sprintf (tmp
, "%d", XINT (x
, 1));
379 cur
= safe_concat (buf
, cur
, tmp
);
383 /* If (verbose) debug_rtx (x); */
384 st
[0] = GET_RTX_NAME (GET_CODE (x
));
388 /* Print this as a function? */
391 cur
= safe_concat (buf
, cur
, fun
);
392 cur
= safe_concat (buf
, cur
, "(");
395 for (i
= 0; i
< 4; i
++)
398 cur
= safe_concat (buf
, cur
, st
[i
]);
403 cur
= safe_concat (buf
, cur
, ",");
405 print_value (tmp
, op
[i
], verbose
);
406 cur
= safe_concat (buf
, cur
, tmp
);
411 cur
= safe_concat (buf
, cur
, ")");
414 /* Prints rtxes, I customarily classified as values. They're constants,
415 registers, labels, symbols and memory accesses. */
418 print_value (char *buf
, rtx x
, int verbose
)
423 switch (GET_CODE (x
))
426 sprintf (t
, HOST_WIDE_INT_PRINT_HEX
, INTVAL (x
));
427 cur
= safe_concat (buf
, cur
, t
);
430 if (FLOAT_MODE_P (GET_MODE (x
)))
431 real_to_decimal (t
, CONST_DOUBLE_REAL_VALUE (x
), sizeof (t
), 0, 1);
434 "<" HOST_WIDE_INT_PRINT_HEX
"," HOST_WIDE_INT_PRINT_HEX
">",
435 (unsigned HOST_WIDE_INT
) CONST_DOUBLE_LOW (x
),
436 (unsigned HOST_WIDE_INT
) CONST_DOUBLE_HIGH (x
));
437 cur
= safe_concat (buf
, cur
, t
);
440 cur
= safe_concat (buf
, cur
, "\"");
441 cur
= safe_concat (buf
, cur
, XSTR (x
, 0));
442 cur
= safe_concat (buf
, cur
, "\"");
445 cur
= safe_concat (buf
, cur
, "`");
446 cur
= safe_concat (buf
, cur
, XSTR (x
, 0));
447 cur
= safe_concat (buf
, cur
, "'");
450 sprintf (t
, "L%d", INSN_UID (XEXP (x
, 0)));
451 cur
= safe_concat (buf
, cur
, t
);
454 print_value (t
, XEXP (x
, 0), verbose
);
455 cur
= safe_concat (buf
, cur
, "const(");
456 cur
= safe_concat (buf
, cur
, t
);
457 cur
= safe_concat (buf
, cur
, ")");
460 print_value (t
, XEXP (x
, 0), verbose
);
461 cur
= safe_concat (buf
, cur
, "high(");
462 cur
= safe_concat (buf
, cur
, t
);
463 cur
= safe_concat (buf
, cur
, ")");
466 if (REGNO (x
) < FIRST_PSEUDO_REGISTER
)
468 int c
= reg_names
[REGNO (x
)][0];
470 cur
= safe_concat (buf
, cur
, "%");
472 cur
= safe_concat (buf
, cur
, reg_names
[REGNO (x
)]);
476 sprintf (t
, "r%d", REGNO (x
));
477 cur
= safe_concat (buf
, cur
, t
);
480 #ifdef INSN_SCHEDULING
481 && !current_sched_info
485 sprintf (t
, ":%s", GET_MODE_NAME (GET_MODE (x
)));
486 cur
= safe_concat (buf
, cur
, t
);
490 print_value (t
, SUBREG_REG (x
), verbose
);
491 cur
= safe_concat (buf
, cur
, t
);
492 sprintf (t
, "#%d", SUBREG_BYTE (x
));
493 cur
= safe_concat (buf
, cur
, t
);
496 cur
= safe_concat (buf
, cur
, "scratch");
499 cur
= safe_concat (buf
, cur
, "cc0");
502 cur
= safe_concat (buf
, cur
, "pc");
505 print_value (t
, XEXP (x
, 0), verbose
);
506 cur
= safe_concat (buf
, cur
, "[");
507 cur
= safe_concat (buf
, cur
, t
);
508 cur
= safe_concat (buf
, cur
, "]");
511 print_exp (t
, x
, verbose
);
512 cur
= safe_concat (buf
, cur
, t
);
517 /* The next step in insn detalization, its pattern recognition. */
520 print_pattern (char *buf
, rtx x
, int verbose
)
522 char t1
[BUF_LEN
], t2
[BUF_LEN
], t3
[BUF_LEN
];
524 switch (GET_CODE (x
))
527 print_value (t1
, SET_DEST (x
), verbose
);
528 print_value (t2
, SET_SRC (x
), verbose
);
529 sprintf (buf
, "%s=%s", t1
, t2
);
532 sprintf (buf
, "return");
535 print_exp (buf
, x
, verbose
);
538 print_value (t1
, XEXP (x
, 0), verbose
);
539 sprintf (buf
, "clobber %s", t1
);
542 print_value (t1
, XEXP (x
, 0), verbose
);
543 sprintf (buf
, "use %s", t1
);
546 if (GET_CODE (COND_EXEC_TEST (x
)) == NE
547 && XEXP (COND_EXEC_TEST (x
), 1) == const0_rtx
)
548 print_value (t1
, XEXP (COND_EXEC_TEST (x
), 0), verbose
);
549 else if (GET_CODE (COND_EXEC_TEST (x
)) == EQ
550 && XEXP (COND_EXEC_TEST (x
), 1) == const0_rtx
)
553 print_value (t1
+ 1, XEXP (COND_EXEC_TEST (x
), 0), verbose
);
556 print_value (t1
, COND_EXEC_TEST (x
), verbose
);
557 print_pattern (t2
, COND_EXEC_CODE (x
), verbose
);
558 sprintf (buf
, "(%s) %s", t1
, t2
);
565 for (i
= 0; i
< XVECLEN (x
, 0); i
++)
567 print_pattern (t2
, XVECEXP (x
, 0, i
), verbose
);
568 sprintf (t3
, "%s%s;", t1
, t2
);
571 sprintf (buf
, "%s}", t1
);
575 /* Should never see SEQUENCE codes until after reorg. */
578 sprintf (buf
, "asm {%s}", XSTR (x
, 0));
583 print_value (buf
, XEXP (x
, 0), verbose
);
586 print_value (t1
, TRAP_CONDITION (x
), verbose
);
587 sprintf (buf
, "trap_if %s", t1
);
593 sprintf (t1
, "unspec{");
594 for (i
= 0; i
< XVECLEN (x
, 0); i
++)
596 print_pattern (t2
, XVECEXP (x
, 0, i
), verbose
);
597 sprintf (t3
, "%s%s;", t1
, t2
);
600 sprintf (buf
, "%s}", t1
);
603 case UNSPEC_VOLATILE
:
607 sprintf (t1
, "unspec/v{");
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
);
618 print_value (buf
, x
, verbose
);
620 } /* print_pattern */
622 /* This is the main function in rtl visualization mechanism. It
623 accepts an rtx and tries to recognize it as an insn, then prints it
624 properly in human readable form, resembling assembler mnemonics.
625 For every insn it prints its UID and BB the insn belongs too.
626 (Probably the last "option" should be extended somehow, since it
627 depends now on sched.c inner variables ...) */
630 print_insn (char *buf
, rtx x
, int verbose
)
635 switch (GET_CODE (x
))
638 print_pattern (t
, PATTERN (x
), verbose
);
639 #ifdef INSN_SCHEDULING
640 if (verbose
&& current_sched_info
)
641 sprintf (buf
, "%s: %s", (*current_sched_info
->print_insn
) (x
, 1),
645 sprintf (buf
, " %4d %s", INSN_UID (x
), t
);
648 print_pattern (t
, PATTERN (x
), verbose
);
649 #ifdef INSN_SCHEDULING
650 if (verbose
&& current_sched_info
)
651 sprintf (buf
, "%s: jump %s", (*current_sched_info
->print_insn
) (x
, 1),
655 sprintf (buf
, " %4d %s", INSN_UID (x
), t
);
659 if (GET_CODE (x
) == PARALLEL
)
661 x
= XVECEXP (x
, 0, 0);
662 print_pattern (t
, x
, verbose
);
665 strcpy (t
, "call <...>");
666 #ifdef INSN_SCHEDULING
667 if (verbose
&& current_sched_info
)
668 sprintf (buf
, "%s: %s", (*current_sched_info
->print_insn
) (x
, 1), t
);
671 sprintf (buf
, " %4d %s", INSN_UID (insn
), t
);
674 sprintf (buf
, "L%d:", INSN_UID (x
));
677 sprintf (buf
, "i%4d: barrier", INSN_UID (x
));
680 if (NOTE_LINE_NUMBER (x
) > 0)
682 expanded_location xloc
;
683 NOTE_EXPANDED_LOCATION (xloc
, x
);
684 sprintf (buf
, " %4d note \"%s\" %d", INSN_UID (x
),
685 xloc
.file
, xloc
.line
);
688 sprintf (buf
, " %4d %s", INSN_UID (x
),
689 GET_NOTE_INSN_NAME (NOTE_LINE_NUMBER (x
)));
692 sprintf (buf
, "i%4d <What %s?>", INSN_UID (x
),
693 GET_RTX_NAME (GET_CODE (x
)));
698 /* Emit a slim dump of X (an insn) to the file F, including any register
699 note attached to the instruction. */
701 dump_insn_slim (FILE *f
, rtx x
)
703 char t
[BUF_LEN
+ 32];
706 print_insn (t
, x
, 1);
709 if (INSN_P (x
) && REG_NOTES (x
))
710 for (note
= REG_NOTES (x
); note
; note
= XEXP (note
, 1))
712 print_value (t
, XEXP (note
, 0), 1);
713 fprintf (f
, " %s: %s\n",
714 GET_REG_NOTE_NAME (REG_NOTE_KIND (note
)), t
);
718 /* Emit a slim dump of X (an insn) to stderr. */
720 debug_insn_slim (rtx x
)
722 dump_insn_slim (stderr
, x
);
725 /* Provide a slim dump the instruction chain starting at FIRST to F, honoring
726 the dump flags given in FLAGS. Currently, TDF_BLOCKS and TDF_DETAILS
727 include more information on the basic blocks. */
729 print_rtl_slim_with_bb (FILE *f
, rtx first
, int flags
)
731 basic_block current_bb
= NULL
;
734 for (insn
= first
; NULL
!= insn
; insn
= NEXT_INSN (insn
))
736 if ((flags
& TDF_BLOCKS
)
737 && (INSN_P (insn
) || GET_CODE (insn
) == NOTE
)
738 && BLOCK_FOR_INSN (insn
)
741 current_bb
= BLOCK_FOR_INSN (insn
);
742 dump_bb_info (current_bb
, true, false, flags
, ";; ", f
);
745 dump_insn_slim (f
, insn
);
747 if ((flags
& TDF_BLOCKS
)
749 && insn
== BB_END (current_bb
))
751 dump_bb_info (current_bb
, false, true, flags
, ";; ", f
);