diff options
author | Jakub Jelinek <jakub@redhat.com> | 2009-05-16 09:12:02 +0200 |
---|---|---|
committer | Jakub Jelinek <jakub@gcc.gnu.org> | 2009-05-16 09:12:02 +0200 |
commit | 40a8f07a47f1192d06e895ce1a4d0fc91a723743 (patch) | |
tree | 6e8f264af352b2d4f86c2430ec273c272f874f45 /gcc | |
parent | a99c6711f83e23596c5fdbf575484e3fa34d6e45 (diff) | |
download | gcc-40a8f07a47f1192d06e895ce1a4d0fc91a723743.zip gcc-40a8f07a47f1192d06e895ce1a4d0fc91a723743.tar.gz gcc-40a8f07a47f1192d06e895ce1a4d0fc91a723743.tar.bz2 |
re PR target/39942 (Nonoptimal code - leaveq; xchg %ax,%ax; retq)
PR target/39942
* final.c (label_to_max_skip): New function.
(label_to_alignment): Only use LABEL_TO_ALIGNMENT if
CODE_LABEL_NUMBER <= max_labelno.
* output.h (label_to_max_skip): New prototype.
* config/i386/i386.c (ix86_avoid_jump_misspredicts): Renamed to...
(ix86_avoid_jump_mispredicts): ... this. Don't define if
ASM_OUTPUT_MAX_SKIP_ALIGN isn't defined. Update comment.
Handle CODE_LABELs with >= 16 byte alignment or with
max_skip == (1 << align) - 1.
(ix86_reorg): Don't call ix86_avoid_jump_mispredicts if
ASM_OUTPUT_MAX_SKIP_ALIGN isn't defined.
From-SVN: r147607
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 13 | ||||
-rw-r--r-- | gcc/config/i386/i386.c | 57 | ||||
-rw-r--r-- | gcc/final.c | 12 | ||||
-rw-r--r-- | gcc/output.h | 6 |
4 files changed, 78 insertions, 10 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 950c8f5..61c62b6 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,6 +1,19 @@ 2009-05-16 Jakub Jelinek <jakub@redhat.com> PR target/39942 + * final.c (label_to_max_skip): New function. + (label_to_alignment): Only use LABEL_TO_ALIGNMENT if + CODE_LABEL_NUMBER <= max_labelno. + * output.h (label_to_max_skip): New prototype. + * config/i386/i386.c (ix86_avoid_jump_misspredicts): Renamed to... + (ix86_avoid_jump_mispredicts): ... this. Don't define if + ASM_OUTPUT_MAX_SKIP_ALIGN isn't defined. Update comment. + Handle CODE_LABELs with >= 16 byte alignment or with + max_skip == (1 << align) - 1. + (ix86_reorg): Don't call ix86_avoid_jump_mispredicts if + ASM_OUTPUT_MAX_SKIP_ALIGN isn't defined. + + PR target/39942 * config/i386/x86-64.h (ASM_OUTPUT_MAX_SKIP_ALIGN): Don't emit second .p2align 3 if MAX_SKIP is smaller than 7. * config/i386/linux.h (ASM_OUTPUT_MAX_SKIP_ALIGN): Likewise. diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index cc0bb02..acd3069 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -27191,6 +27191,7 @@ x86_function_profiler (FILE *file, int labelno ATTRIBUTE_UNUSED) } } +#ifdef ASM_OUTPUT_MAX_SKIP_ALIGN /* We don't have exact information about the insn sizes, but we may assume quite safely that we are informed about all 1 byte insns and memory address sizes. This is enough to eliminate unnecessary padding in @@ -27241,7 +27242,7 @@ min_insn_size (rtx insn) window. */ static void -ix86_avoid_jump_misspredicts (void) +ix86_avoid_jump_mispredicts (void) { rtx insn, start = get_insns (); int nbytes = 0, njumps = 0; @@ -27255,15 +27256,52 @@ ix86_avoid_jump_misspredicts (void) The smallest offset in the page INSN can start is the case where START ends on the offset 0. Offset of INSN is then NBYTES - sizeof (INSN). - We add p2align to 16byte window with maxskip 17 - NBYTES + sizeof (INSN). + We add p2align to 16byte window with maxskip 15 - NBYTES + sizeof (INSN). */ - for (insn = get_insns (); insn; insn = NEXT_INSN (insn)) + for (insn = start; insn; insn = NEXT_INSN (insn)) { + int min_size; - nbytes += min_insn_size (insn); + if (GET_CODE (insn) == CODE_LABEL) + { + int align = label_to_alignment (insn); + int max_skip = label_to_max_skip (insn); + + if (max_skip > 15) + max_skip = 15; + /* If align > 3, only up to 16 - max_skip - 1 bytes can be + already in the current 16 byte page, because otherwise + ASM_OUTPUT_MAX_SKIP_ALIGN could skip max_skip or fewer + bytes to reach 16 byte boundary. */ + if (align <= 0 + || (align <= 3 && max_skip != (1 << align) - 1)) + max_skip = 0; + if (dump_file) + fprintf (dump_file, "Label %i with max_skip %i\n", + INSN_UID (insn), max_skip); + if (max_skip) + { + while (nbytes + max_skip >= 16) + { + start = NEXT_INSN (start); + if ((JUMP_P (start) + && GET_CODE (PATTERN (start)) != ADDR_VEC + && GET_CODE (PATTERN (start)) != ADDR_DIFF_VEC) + || CALL_P (start)) + njumps--, isjump = 1; + else + isjump = 0; + nbytes -= min_insn_size (start); + } + } + continue; + } + + min_size = min_insn_size (insn); + nbytes += min_size; if (dump_file) - fprintf(dump_file, "Insn %i estimated to %i bytes\n", - INSN_UID (insn), min_insn_size (insn)); + fprintf (dump_file, "Insn %i estimated to %i bytes\n", + INSN_UID (insn), min_size); if ((JUMP_P (insn) && GET_CODE (PATTERN (insn)) != ADDR_VEC && GET_CODE (PATTERN (insn)) != ADDR_DIFF_VEC) @@ -27287,7 +27325,7 @@ ix86_avoid_jump_misspredicts (void) gcc_assert (njumps >= 0); if (dump_file) fprintf (dump_file, "Interval %i to %i has %i bytes\n", - INSN_UID (start), INSN_UID (insn), nbytes); + INSN_UID (start), INSN_UID (insn), nbytes); if (njumps == 3 && isjump && nbytes < 16) { @@ -27300,6 +27338,7 @@ ix86_avoid_jump_misspredicts (void) } } } +#endif /* AMD Athlon works faster when RET is not destination of conditional jump or directly preceded @@ -27363,8 +27402,10 @@ ix86_reorg (void) { if (TARGET_PAD_RETURNS) ix86_pad_returns (); +#ifdef ASM_OUTPUT_MAX_SKIP_ALIGN if (TARGET_FOUR_JUMP_LIMIT) - ix86_avoid_jump_misspredicts (); + ix86_avoid_jump_mispredicts (); +#endif } } diff --git a/gcc/final.c b/gcc/final.c index 30ccc85..3c2e364 100644 --- a/gcc/final.c +++ b/gcc/final.c @@ -553,7 +553,17 @@ static int min_labelno, max_labelno; int label_to_alignment (rtx label) { - return LABEL_TO_ALIGNMENT (label); + if (CODE_LABEL_NUMBER (label) <= max_labelno) + return LABEL_TO_ALIGNMENT (label); + return 0; +} + +int +label_to_max_skip (rtx label) +{ + if (CODE_LABEL_NUMBER (label) <= max_labelno) + return LABEL_TO_MAX_SKIP (label); + return 0; } #ifdef HAVE_ATTR_length diff --git a/gcc/output.h b/gcc/output.h index e7871f9..543164a 100644 --- a/gcc/output.h +++ b/gcc/output.h @@ -1,7 +1,7 @@ /* Declarations for insn-output.c. These functions are defined in recog.c, final.c, and varasm.c. Copyright (C) 1987, 1991, 1994, 1997, 1998, 1999, 2000, 2001, 2002, - 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. + 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc. This file is part of GCC. @@ -94,6 +94,10 @@ extern int insn_current_reference_address (rtx); Defined in final.c. */ extern int label_to_alignment (rtx); +/* Find the alignment maximum skip associated with a CODE_LABEL. + Defined in final.c. */ +extern int label_to_max_skip (rtx); + /* Output a LABEL_REF, or a bare CODE_LABEL, as an assembler symbol. */ extern void output_asm_label (rtx); |