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);
433 sprintf (t
, "<0x%lx,0x%lx>", (long) CONST_DOUBLE_LOW (x
), (long) CONST_DOUBLE_HIGH (x
));
434 cur
= safe_concat (buf
, cur
, t
);
437 cur
= safe_concat (buf
, cur
, "\"");
438 cur
= safe_concat (buf
, cur
, XSTR (x
, 0));
439 cur
= safe_concat (buf
, cur
, "\"");
442 cur
= safe_concat (buf
, cur
, "`");
443 cur
= safe_concat (buf
, cur
, XSTR (x
, 0));
444 cur
= safe_concat (buf
, cur
, "'");
447 sprintf (t
, "L%d", INSN_UID (XEXP (x
, 0)));
448 cur
= safe_concat (buf
, cur
, t
);
451 print_value (t
, XEXP (x
, 0), verbose
);
452 cur
= safe_concat (buf
, cur
, "const(");
453 cur
= safe_concat (buf
, cur
, t
);
454 cur
= safe_concat (buf
, cur
, ")");
457 print_value (t
, XEXP (x
, 0), verbose
);
458 cur
= safe_concat (buf
, cur
, "high(");
459 cur
= safe_concat (buf
, cur
, t
);
460 cur
= safe_concat (buf
, cur
, ")");
463 if (REGNO (x
) < FIRST_PSEUDO_REGISTER
)
465 int c
= reg_names
[REGNO (x
)][0];
467 cur
= safe_concat (buf
, cur
, "%");
469 cur
= safe_concat (buf
, cur
, reg_names
[REGNO (x
)]);
473 sprintf (t
, "r%d", REGNO (x
));
474 cur
= safe_concat (buf
, cur
, t
);
477 #ifdef INSN_SCHEDULING
478 && !current_sched_info
482 sprintf (t
, ":%s", GET_MODE_NAME (GET_MODE (x
)));
483 cur
= safe_concat (buf
, cur
, t
);
487 print_value (t
, SUBREG_REG (x
), verbose
);
488 cur
= safe_concat (buf
, cur
, t
);
489 sprintf (t
, "#%d", SUBREG_BYTE (x
));
490 cur
= safe_concat (buf
, cur
, t
);
493 cur
= safe_concat (buf
, cur
, "scratch");
496 cur
= safe_concat (buf
, cur
, "cc0");
499 cur
= safe_concat (buf
, cur
, "pc");
502 print_value (t
, XEXP (x
, 0), verbose
);
503 cur
= safe_concat (buf
, cur
, "[");
504 cur
= safe_concat (buf
, cur
, t
);
505 cur
= safe_concat (buf
, cur
, "]");
508 print_exp (t
, x
, verbose
);
509 cur
= safe_concat (buf
, cur
, t
);
514 /* The next step in insn detalization, its pattern recognition. */
517 print_pattern (char *buf
, rtx x
, int verbose
)
519 char t1
[BUF_LEN
], t2
[BUF_LEN
], t3
[BUF_LEN
];
521 switch (GET_CODE (x
))
524 print_value (t1
, SET_DEST (x
), verbose
);
525 print_value (t2
, SET_SRC (x
), verbose
);
526 sprintf (buf
, "%s=%s", t1
, t2
);
529 sprintf (buf
, "return");
532 print_exp (buf
, x
, verbose
);
535 print_value (t1
, XEXP (x
, 0), verbose
);
536 sprintf (buf
, "clobber %s", t1
);
539 print_value (t1
, XEXP (x
, 0), verbose
);
540 sprintf (buf
, "use %s", t1
);
543 if (GET_CODE (COND_EXEC_TEST (x
)) == NE
544 && XEXP (COND_EXEC_TEST (x
), 1) == const0_rtx
)
545 print_value (t1
, XEXP (COND_EXEC_TEST (x
), 0), verbose
);
546 else if (GET_CODE (COND_EXEC_TEST (x
)) == EQ
547 && XEXP (COND_EXEC_TEST (x
), 1) == const0_rtx
)
550 print_value (t1
+ 1, XEXP (COND_EXEC_TEST (x
), 0), verbose
);
553 print_value (t1
, COND_EXEC_TEST (x
), verbose
);
554 print_pattern (t2
, COND_EXEC_CODE (x
), verbose
);
555 sprintf (buf
, "(%s) %s", t1
, t2
);
562 for (i
= 0; i
< XVECLEN (x
, 0); i
++)
564 print_pattern (t2
, XVECEXP (x
, 0, i
), verbose
);
565 sprintf (t3
, "%s%s;", t1
, t2
);
568 sprintf (buf
, "%s}", t1
);
572 /* Should never see SEQUENCE codes until after reorg. */
575 sprintf (buf
, "asm {%s}", XSTR (x
, 0));
580 print_value (buf
, XEXP (x
, 0), verbose
);
583 print_value (t1
, TRAP_CONDITION (x
), verbose
);
584 sprintf (buf
, "trap_if %s", t1
);
590 sprintf (t1
, "unspec{");
591 for (i
= 0; i
< XVECLEN (x
, 0); i
++)
593 print_pattern (t2
, XVECEXP (x
, 0, i
), verbose
);
594 sprintf (t3
, "%s%s;", t1
, t2
);
597 sprintf (buf
, "%s}", t1
);
600 case UNSPEC_VOLATILE
:
604 sprintf (t1
, "unspec/v{");
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
);
615 print_value (buf
, x
, verbose
);
617 } /* print_pattern */
619 /* This is the main function in rtl visualization mechanism. It
620 accepts an rtx and tries to recognize it as an insn, then prints it
621 properly in human readable form, resembling assembler mnemonics.
622 For every insn it prints its UID and BB the insn belongs too.
623 (Probably the last "option" should be extended somehow, since it
624 depends now on sched.c inner variables ...) */
627 print_insn (char *buf
, rtx x
, int verbose
)
632 switch (GET_CODE (x
))
635 print_pattern (t
, PATTERN (x
), verbose
);
636 #ifdef INSN_SCHEDULING
637 if (verbose
&& current_sched_info
)
638 sprintf (buf
, "%s: %s", (*current_sched_info
->print_insn
) (x
, 1),
642 sprintf (buf
, " %4d %s", INSN_UID (x
), t
);
645 print_pattern (t
, PATTERN (x
), verbose
);
646 #ifdef INSN_SCHEDULING
647 if (verbose
&& current_sched_info
)
648 sprintf (buf
, "%s: jump %s", (*current_sched_info
->print_insn
) (x
, 1),
652 sprintf (buf
, " %4d %s", INSN_UID (x
), t
);
656 if (GET_CODE (x
) == PARALLEL
)
658 x
= XVECEXP (x
, 0, 0);
659 print_pattern (t
, x
, verbose
);
662 strcpy (t
, "call <...>");
663 #ifdef INSN_SCHEDULING
664 if (verbose
&& current_sched_info
)
665 sprintf (buf
, "%s: %s", (*current_sched_info
->print_insn
) (x
, 1), t
);
668 sprintf (buf
, " %4d %s", INSN_UID (insn
), t
);
671 sprintf (buf
, "L%d:", INSN_UID (x
));
674 sprintf (buf
, "i%4d: barrier", INSN_UID (x
));
677 if (NOTE_LINE_NUMBER (x
) > 0)
679 expanded_location xloc
;
680 NOTE_EXPANDED_LOCATION (xloc
, x
);
681 sprintf (buf
, " %4d note \"%s\" %d", INSN_UID (x
),
682 xloc
.file
, xloc
.line
);
685 sprintf (buf
, " %4d %s", INSN_UID (x
),
686 GET_NOTE_INSN_NAME (NOTE_LINE_NUMBER (x
)));
689 sprintf (buf
, "i%4d <What %s?>", INSN_UID (x
),
690 GET_RTX_NAME (GET_CODE (x
)));
695 /* Emit a slim dump of X (an insn) to the file F, including any register
696 note attached to the instruction. */
698 dump_insn_slim (FILE *f
, rtx x
)
700 char t
[BUF_LEN
+ 32];
703 print_insn (t
, x
, 1);
706 if (INSN_P (x
) && REG_NOTES (x
))
707 for (note
= REG_NOTES (x
); note
; note
= XEXP (note
, 1))
709 print_value (t
, XEXP (note
, 0), 1);
710 fprintf (f
, " %s: %s\n",
711 GET_REG_NOTE_NAME (REG_NOTE_KIND (note
)), t
);
715 /* Emit a slim dump of X (an insn) to stderr. */
717 debug_insn_slim (rtx x
)
719 dump_insn_slim (stderr
, x
);
722 /* Provide a slim dump the instruction chain starting at FIRST to F, honoring
723 the dump flags given in FLAGS. Currently, TDF_BLOCKS and TDF_DETAILS
724 include more information on the basic blocks. */
726 print_rtl_slim_with_bb (FILE *f
, rtx first
, int flags
)
728 basic_block current_bb
= NULL
;
731 for (insn
= first
; NULL
!= insn
; insn
= NEXT_INSN (insn
))
733 if ((flags
& TDF_BLOCKS
)
734 && (INSN_P (insn
) || GET_CODE (insn
) == NOTE
)
735 && BLOCK_FOR_INSN (insn
)
738 current_bb
= BLOCK_FOR_INSN (insn
);
739 dump_bb_info (current_bb
, true, false, flags
, ";; ", f
);
742 dump_insn_slim (f
, insn
);
744 if ((flags
& TDF_BLOCKS
)
746 && insn
== BB_END (current_bb
))
748 dump_bb_info (current_bb
, false, true, flags
, ";; ", f
);