Commit 40a8f07a by Jakub Jelinek Committed by Jakub Jelinek

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
parent a99c6711
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.
......
......@@ -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
}
}
......
......@@ -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
......
/* 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);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment