re PR target/70465 (Poor code for x87 asm)
authorJakub Jelinek <jakub@redhat.com>
Wed, 22 Feb 2017 17:17:17 +0000 (18:17 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Wed, 22 Feb 2017 17:17:17 +0000 (18:17 +0100)
PR target/70465
* reg-stack.c (emit_swap_insn): Treat (float_extend:?F (mem:?F))
and (const_double:?F) like (mem:?F) for the purpose of fxch %st(1)
elimination by swapping fld*.

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

From-SVN: r245654

gcc/ChangeLog
gcc/reg-stack.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/i386/pr70465-2.c [new file with mode: 0644]

index e7eb867ea5b58294e98631512720e1aa78b7634b..7585f37940bb1dd88db1b484359703a56d928c7e 100644 (file)
@@ -1,3 +1,10 @@
+2017-02-22  Jakub Jelinek  <jakub@redhat.com>
+
+       PR target/70465
+       * reg-stack.c (emit_swap_insn): Treat (float_extend:?F (mem:?F))
+       and (const_double:?F) like (mem:?F) for the purpose of fxch %st(1)
+       elimination by swapping fld*.
+
 2017-02-22  Richard Biener  <rguenther@suse.de>
 
        PR tree-optimization/79673
index 7bf007cea45ef6b2336dd44d47386281626a1987..41ae7e4fb9cdba8935b2210dc72396104b1b9a5e 100644 (file)
@@ -895,12 +895,16 @@ emit_swap_insn (rtx_insn *insn, stack_ptr regstack, rtx reg)
         just use
           fld b
           fld a
-         if possible.  */
+        if possible.  Similarly for fld1, fldz, fldpi etc. instead of any
+        of the loads or for float extension from memory.  */
 
+      i1src = SET_SRC (i1set);
+      if (GET_CODE (i1src) == FLOAT_EXTEND)
+       i1src = XEXP (i1src, 0);
       if (REG_P (i1dest)
          && REGNO (i1dest) == FIRST_STACK_REG
-         && MEM_P (SET_SRC (i1set))
-         && !side_effects_p (SET_SRC (i1set))
+         && (MEM_P (i1src) || GET_CODE (i1src) == CONST_DOUBLE)
+         && !side_effects_p (i1src)
          && hard_regno == FIRST_STACK_REG + 1
          && i1 != BB_HEAD (current_block))
        {
@@ -930,6 +934,9 @@ emit_swap_insn (rtx_insn *insn, stack_ptr regstack, rtx reg)
              && (i2set = single_set (i2)) != NULL_RTX)
            {
              rtx i2dest = *get_true_reg (&SET_DEST (i2set));
+             rtx i2src = SET_SRC (i2set);
+             if (GET_CODE (i2src) == FLOAT_EXTEND)
+               i2src = XEXP (i2src, 0);
              /* If the last two insns before insn that involve
                 stack regs are loads, where the latter (i1)
                 pushes onto the register stack and thus
@@ -937,9 +944,9 @@ emit_swap_insn (rtx_insn *insn, stack_ptr regstack, rtx reg)
                 %st to %st(1), consider swapping them.  */
              if (REG_P (i2dest)
                  && REGNO (i2dest) == FIRST_STACK_REG
-                 && MEM_P (SET_SRC (i2set))
+                 && (MEM_P (i2src) || GET_CODE (i2src) == CONST_DOUBLE)
                  /* Ensure i2 doesn't have other side-effects.  */
-                 && !side_effects_p (SET_SRC (i2set))
+                 && !side_effects_p (i2src)
                  /* 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
index 1737c0ffc954859289759afe369541ae8dbfccd9..395620c6c540ed7e2ba5aee7f749f5475670a28d 100644 (file)
@@ -1,3 +1,8 @@
+2017-02-22  Jakub Jelinek  <jakub@redhat.com>
+
+       PR target/70465
+       * gcc.target/i386/pr70465-2.c: New test.
+
 2017-02-21  Uros Bizjak  <ubizjak@gmail.com>
 
        * gcc.dg/pr61441.c: Use dg-add-options ieee.
diff --git a/gcc/testsuite/gcc.target/i386/pr70465-2.c b/gcc/testsuite/gcc.target/i386/pr70465-2.c
new file mode 100644 (file)
index 0000000..71b683a
--- /dev/null
@@ -0,0 +1,25 @@
+/* PR target/70465 */
+/* { dg-do compile } */
+/* { dg-options "-Ofast -mfpmath=387 -fomit-frame-pointer" } */
+/* { dg-final { scan-assembler-not "fxch\t%st.1" } } */
+
+extern float d[1024];
+
+static inline long double
+foo (long double a, long double b)
+{
+  return a < b ? a : b;
+}
+
+static inline long double
+bar (long double a, long double b)
+{
+  return a > b ? a : b;
+}
+
+float
+baz (void)
+{
+  long double c = d[0];
+  return foo (bar (c, 0.0l), 1.0l);
+}