re PR target/70465 (Poor code for x87 asm)

PR target/70465
	* reg-stack.c (emit_swap_insn): Instead of fld a; fld b; fxchg %st(1);
	emit fld b; fld a; if possible.

	* gcc.target/i386/pr70465.c: New test.

From-SVN: r244921
This commit is contained in:
Jakub Jelinek 2017-01-26 09:46:36 +01:00 committed by Jakub Jelinek
parent e6d55103c3
commit 1a27fab1ad
4 changed files with 90 additions and 0 deletions

View File

@ -1,5 +1,9 @@
2017-01-26 Jakub Jelinek <jakub@redhat.com>
PR target/70465
* reg-stack.c (emit_swap_insn): Instead of fld a; fld b; fxchg %st(1);
emit fld b; fld a; if possible.
* brig-builtins.def: Update copyright years.
* config/arm/arm_acle_builtins.def: Update copyright years.

View File

@ -887,6 +887,77 @@ emit_swap_insn (rtx_insn *insn, stack_ptr regstack, rtx reg)
&& REG_P (i1src) && REGNO (i1src) == FIRST_STACK_REG
&& find_regno_note (i1, REG_DEAD, FIRST_STACK_REG) == NULL_RTX)
return;
/* Instead of
fld a
fld b
fxch %st(1)
just use
fld b
fld a
if possible. */
if (REG_P (i1dest)
&& REGNO (i1dest) == FIRST_STACK_REG
&& MEM_P (SET_SRC (i1set))
&& !side_effects_p (SET_SRC (i1set))
&& hard_regno == FIRST_STACK_REG + 1
&& i1 != BB_HEAD (current_block))
{
/* i1 is the last insn that involves stack regs before insn, and
is known to be a load without other side-effects, i.e. fld b
in the above comment. */
rtx_insn *i2 = NULL;
rtx i2set;
rtx_insn *tmp = PREV_INSN (i1);
rtx_insn *limit = PREV_INSN (BB_HEAD (current_block));
/* Find the previous insn involving stack regs, but don't pass a
block boundary. */
while (tmp != limit)
{
if (LABEL_P (tmp)
|| CALL_P (tmp)
|| NOTE_INSN_BASIC_BLOCK_P (tmp)
|| (NONJUMP_INSN_P (tmp)
&& stack_regs_mentioned (tmp)))
{
i2 = tmp;
break;
}
tmp = PREV_INSN (tmp);
}
if (i2 != NULL_RTX
&& (i2set = single_set (i2)) != NULL_RTX)
{
rtx i2dest = *get_true_reg (&SET_DEST (i2set));
/* If the last two insns before insn that involve
stack regs are loads, where the latter (i1)
pushes onto the register stack and thus
moves the value from the first load (i2) from
%st to %st(1), consider swapping them. */
if (REG_P (i2dest)
&& REGNO (i2dest) == FIRST_STACK_REG
&& MEM_P (SET_SRC (i2set))
/* Ensure i2 doesn't have other side-effects. */
&& !side_effects_p (SET_SRC (i2set))
/* And that the two instructions can actually be
swapped, i.e. there shouldn't be any stores
in between i2 and i1 that might alias with
the i1 memory, and the memory address can't
use registers set in between i2 and i1. */
&& !modified_between_p (SET_SRC (i1set), i2, i1))
{
/* Move i1 (fld b above) right before i2 (fld a
above. */
remove_insn (i1);
SET_PREV_INSN (i1) = NULL_RTX;
SET_NEXT_INSN (i1) = NULL_RTX;
set_block_for_insn (i1, NULL);
emit_insn_before (i1, i2);
return;
}
}
}
}
/* Avoid emitting the swap if this is the first register stack insn

View File

@ -1,5 +1,8 @@
2017-01-26 Jakub Jelinek <jakub@redhat.com>
PR target/70465
* gcc.target/i386/pr70465.c: New test.
* brig.dg/dg.exp: Update copyright years.
* lib/brig-dg.exp: Update copyright years.
* lib/brig.exp: Update copyright years.

View File

@ -0,0 +1,12 @@
/* PR target/70465 */
/* { dg-do compile { target ia32 } } */
/* { dg-options "-O2 -mfpmath=387 -fomit-frame-pointer" } */
/* { dg-final { scan-assembler-not "fxch\t%st.1" } } */
double
atan2 (double y, double x)
{
double res = 0.0;
asm ("fpatan" : "=t" (res) : "u" (y), "0" (x) : "st(1)");
return res;
}