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:
parent
e6d55103c3
commit
1a27fab1ad
4 changed files with 90 additions and 0 deletions
|
@ -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.
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
12
gcc/testsuite/gcc.target/i386/pr70465.c
Normal file
12
gcc/testsuite/gcc.target/i386/pr70465.c
Normal 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;
|
||||
}
|
Loading…
Add table
Reference in a new issue