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
,
438 (unsigned HOST_WIDE_INT
) INTVAL (x
));
439 cur
= safe_concat (buf
, cur
, t
);
442 if (FLOAT_MODE_P (GET_MODE (x
)))
443 real_to_decimal (t
, CONST_DOUBLE_REAL_VALUE (x
), sizeof (t
), 0, 1);
446 "<" HOST_WIDE_INT_PRINT_HEX
"," HOST_WIDE_INT_PRINT_HEX
">",
447 (unsigned HOST_WIDE_INT
) CONST_DOUBLE_LOW (x
),
448 (unsigned HOST_WIDE_INT
) CONST_DOUBLE_HIGH (x
));
449 cur
= safe_concat (buf
, cur
, t
);
452 fixed_to_decimal (t
, CONST_FIXED_VALUE (x
), sizeof (t
));
453 cur
= safe_concat (buf
, cur
, t
);
456 cur
= safe_concat (buf
, cur
, "\"");
457 cur
= safe_concat (buf
, cur
, XSTR (x
, 0));
458 cur
= safe_concat (buf
, cur
, "\"");
461 cur
= safe_concat (buf
, cur
, "`");
462 cur
= safe_concat (buf
, cur
, XSTR (x
, 0));
463 cur
= safe_concat (buf
, cur
, "'");
466 sprintf (t
, "L%d", INSN_UID (XEXP (x
, 0)));
467 cur
= safe_concat (buf
, cur
, t
);
470 print_value (t
, XEXP (x
, 0), verbose
);
471 cur
= safe_concat (buf
, cur
, "const(");
472 cur
= safe_concat (buf
, cur
, t
);
473 cur
= safe_concat (buf
, cur
, ")");
476 print_value (t
, XEXP (x
, 0), verbose
);
477 cur
= safe_concat (buf
, cur
, "high(");
478 cur
= safe_concat (buf
, cur
, t
);
479 cur
= safe_concat (buf
, cur
, ")");
482 if (REGNO (x
) < FIRST_PSEUDO_REGISTER
)
484 int c
= reg_names
[REGNO (x
)][0];
486 cur
= safe_concat (buf
, cur
, "%");
488 cur
= safe_concat (buf
, cur
, reg_names
[REGNO (x
)]);
492 sprintf (t
, "r%d", REGNO (x
));
493 cur
= safe_concat (buf
, cur
, t
);
496 #ifdef INSN_SCHEDULING
497 && !current_sched_info
501 sprintf (t
, ":%s", GET_MODE_NAME (GET_MODE (x
)));
502 cur
= safe_concat (buf
, cur
, t
);
506 print_value (t
, SUBREG_REG (x
), verbose
);
507 cur
= safe_concat (buf
, cur
, t
);
508 sprintf (t
, "#%d", SUBREG_BYTE (x
));
509 cur
= safe_concat (buf
, cur
, t
);
512 cur
= safe_concat (buf
, cur
, "scratch");
515 cur
= safe_concat (buf
, cur
, "cc0");
518 cur
= safe_concat (buf
, cur
, "pc");
521 print_value (t
, XEXP (x
, 0), verbose
);
522 cur
= safe_concat (buf
, cur
, "[");
523 cur
= safe_concat (buf
, cur
, t
);
524 cur
= safe_concat (buf
, cur
, "]");
527 print_exp (t
, x
, verbose
);
528 cur
= safe_concat (buf
, cur
, t
);
533 /* The next step in insn detalization, its pattern recognition. */
536 print_pattern (char *buf
, const_rtx x
, int verbose
)
538 char t1
[BUF_LEN
], t2
[BUF_LEN
], t3
[BUF_LEN
];
540 switch (GET_CODE (x
))
543 print_value (t1
, SET_DEST (x
), verbose
);
544 print_value (t2
, SET_SRC (x
), verbose
);
545 sprintf (buf
, "%s=%s", t1
, t2
);
548 sprintf (buf
, "return");
551 print_exp (buf
, x
, verbose
);
554 print_value (t1
, XEXP (x
, 0), verbose
);
555 sprintf (buf
, "clobber %s", t1
);
558 print_value (t1
, XEXP (x
, 0), verbose
);
559 sprintf (buf
, "use %s", t1
);
562 if (GET_CODE (COND_EXEC_TEST (x
)) == NE
563 && XEXP (COND_EXEC_TEST (x
), 1) == const0_rtx
)
564 print_value (t1
, XEXP (COND_EXEC_TEST (x
), 0), verbose
);
565 else if (GET_CODE (COND_EXEC_TEST (x
)) == EQ
566 && XEXP (COND_EXEC_TEST (x
), 1) == const0_rtx
)
569 print_value (t1
+ 1, XEXP (COND_EXEC_TEST (x
), 0), verbose
);
572 print_value (t1
, COND_EXEC_TEST (x
), verbose
);
573 print_pattern (t2
, COND_EXEC_CODE (x
), verbose
);
574 sprintf (buf
, "(%s) %s", t1
, t2
);
581 for (i
= 0; i
< XVECLEN (x
, 0); i
++)
583 print_pattern (t2
, XVECEXP (x
, 0, i
), verbose
);
584 sprintf (t3
, "%s%s;", t1
, t2
);
587 sprintf (buf
, "%s}", t1
);
591 /* Should never see SEQUENCE codes until after reorg. */
594 sprintf (buf
, "asm {%s}", XSTR (x
, 0));
599 print_value (buf
, XEXP (x
, 0), verbose
);
602 print_value (t1
, TRAP_CONDITION (x
), verbose
);
603 sprintf (buf
, "trap_if %s", t1
);
609 sprintf (t1
, "unspec{");
610 for (i
= 0; i
< XVECLEN (x
, 0); i
++)
612 print_pattern (t2
, XVECEXP (x
, 0, i
), verbose
);
613 sprintf (t3
, "%s%s;", t1
, t2
);
616 sprintf (buf
, "%s}", t1
);
619 case UNSPEC_VOLATILE
:
623 sprintf (t1
, "unspec/v{");
624 for (i
= 0; i
< XVECLEN (x
, 0); i
++)
626 print_pattern (t2
, XVECEXP (x
, 0, i
), verbose
);
627 sprintf (t3
, "%s%s;", t1
, t2
);
630 sprintf (buf
, "%s}", t1
);
634 print_value (buf
, x
, verbose
);
636 } /* print_pattern */
638 /* This is the main function in rtl visualization mechanism. It
639 accepts an rtx and tries to recognize it as an insn, then prints it
640 properly in human readable form, resembling assembler mnemonics.
641 For every insn it prints its UID and BB the insn belongs too.
642 (Probably the last "option" should be extended somehow, since it
643 depends now on sched.c inner variables ...) */
646 print_insn (char *buf
, rtx x
, int verbose
)
651 switch (GET_CODE (x
))
654 print_pattern (t
, PATTERN (x
), verbose
);
655 #ifdef INSN_SCHEDULING
656 if (verbose
&& current_sched_info
)
657 sprintf (buf
, "%s: %s", (*current_sched_info
->print_insn
) (x
, 1),
661 sprintf (buf
, " %4d %s", INSN_UID (x
), t
);
664 print_pattern (t
, PATTERN (x
), verbose
);
665 #ifdef INSN_SCHEDULING
666 if (verbose
&& current_sched_info
)
667 sprintf (buf
, "%s: jump %s", (*current_sched_info
->print_insn
) (x
, 1),
671 sprintf (buf
, " %4d %s", INSN_UID (x
), t
);
675 if (GET_CODE (x
) == PARALLEL
)
677 x
= XVECEXP (x
, 0, 0);
678 print_pattern (t
, x
, verbose
);
681 strcpy (t
, "call <...>");
682 #ifdef INSN_SCHEDULING
683 if (verbose
&& current_sched_info
)
684 sprintf (buf
, "%s: %s", (*current_sched_info
->print_insn
) (x
, 1), t
);
687 sprintf (buf
, " %4d %s", INSN_UID (insn
), t
);
690 sprintf (buf
, "L%d:", INSN_UID (x
));
693 sprintf (buf
, "i%4d: barrier", INSN_UID (x
));
696 sprintf (buf
, " %4d %s", INSN_UID (x
),
697 GET_NOTE_INSN_NAME (NOTE_KIND (x
)));
700 sprintf (buf
, "i%4d <What %s?>", INSN_UID (x
),
701 GET_RTX_NAME (GET_CODE (x
)));
706 /* Emit a slim dump of X (an insn) to the file F, including any register
707 note attached to the instruction. */
709 dump_insn_slim (FILE *f
, rtx x
)
711 char t
[BUF_LEN
+ 32];
714 print_insn (t
, x
, 1);
717 if (INSN_P (x
) && REG_NOTES (x
))
718 for (note
= REG_NOTES (x
); note
; note
= XEXP (note
, 1))
720 print_value (t
, XEXP (note
, 0), 1);
721 fprintf (f
, " %s: %s\n",
722 GET_REG_NOTE_NAME (REG_NOTE_KIND (note
)), t
);
726 /* Emit a slim dump of X (an insn) to stderr. */
728 debug_insn_slim (rtx x
)
730 dump_insn_slim (stderr
, x
);
733 /* Provide a slim dump the instruction chain starting at FIRST to F, honoring
734 the dump flags given in FLAGS. Currently, TDF_BLOCKS and TDF_DETAILS
735 include more information on the basic blocks. */
737 print_rtl_slim_with_bb (FILE *f
, rtx first
, int flags
)
739 basic_block current_bb
= NULL
;
742 for (insn
= first
; NULL
!= insn
; insn
= NEXT_INSN (insn
))
744 if ((flags
& TDF_BLOCKS
)
745 && (INSN_P (insn
) || GET_CODE (insn
) == NOTE
)
746 && BLOCK_FOR_INSN (insn
)
749 current_bb
= BLOCK_FOR_INSN (insn
);
750 dump_bb_info (current_bb
, true, false, flags
, ";; ", f
);
753 dump_insn_slim (f
, insn
);
755 if ((flags
& TDF_BLOCKS
)
757 && insn
== BB_END (current_bb
))
759 dump_bb_info (current_bb
, false, true, flags
, ";; ", f
);