Commit 1a27fab1 by Jakub Jelinek Committed by Jakub Jelinek

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
parent e6d55103
2017-01-26 Jakub Jelinek <jakub@redhat.com> 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. * brig-builtins.def: Update copyright years.
* config/arm/arm_acle_builtins.def: Update copyright years. * config/arm/arm_acle_builtins.def: Update copyright years.
......
...@@ -887,6 +887,77 @@ emit_swap_insn (rtx_insn *insn, stack_ptr regstack, rtx reg) ...@@ -887,6 +887,77 @@ emit_swap_insn (rtx_insn *insn, stack_ptr regstack, rtx reg)
&& REG_P (i1src) && REGNO (i1src) == FIRST_STACK_REG && REG_P (i1src) && REGNO (i1src) == FIRST_STACK_REG
&& find_regno_note (i1, REG_DEAD, FIRST_STACK_REG) == NULL_RTX) && find_regno_note (i1, REG_DEAD, FIRST_STACK_REG) == NULL_RTX)
return; 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 /* Avoid emitting the swap if this is the first register stack insn
......
2017-01-26 Jakub Jelinek <jakub@redhat.com> 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. * brig.dg/dg.exp: Update copyright years.
* lib/brig-dg.exp: Update copyright years. * lib/brig-dg.exp: Update copyright years.
* lib/brig.exp: Update copyright years. * lib/brig.exp: Update copyright years.
......
/* 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;
}
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