On Thu, Jul 09, 2015 at 12:13:38PM -0700, H.J. Lu wrote:
> ix86_split_long_move can optimize floating point constant move, which
> can be used to optimize SFmode move for IA MCU.
> 
> OK for trunk if there is no regression?
> 
> 
> H.J.
> ---
> gcc/
> 
>       PR target/66824
>       * config/i386/i386.c (ix86_split_to_parts): Allow SFmode move
>       for IA MCU.
>       (ix86_split_long_move): Support single move.
>       * config/i386/i386.md (FP splitter): Allow SFmode for IA MCU.
> 
> gcc/testsuite/
> 
>       PR target/66824
>       * gcc.target/i386/pr66824.c: New test.
> ---


I missed the testcase.  Here is the updated patch.

H.J.
---
---
 gcc/config/i386/i386.c                  | 14 +++++++++++++-
 gcc/config/i386/i386.md                 |  3 ++-
 gcc/testsuite/gcc.target/i386/pr66824.c | 23 +++++++++++++++++++++++
 3 files changed, 38 insertions(+), 2 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/i386/pr66824.c

diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index a18c733..d2925bc 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -22744,7 +22744,9 @@ ix86_split_to_parts (rtx operand, rtx *parts, 
machine_mode mode)
     size = (GET_MODE_SIZE (mode) + 4) / 8;
 
   gcc_assert (!REG_P (operand) || !MMX_REGNO_P (REGNO (operand)));
-  gcc_assert (size >= 2 && size <= 4);
+  /* For IA MCU, we can optimize SFmode move.  */
+  gcc_assert ((size >= 2 || (TARGET_IAMCU && mode == SFmode))
+             && size <= 4);
 
   /* Optimize constant pool reference to immediates.  This is used by fp
      moves, that force all constants to memory to allow combining.  */
@@ -22822,10 +22824,14 @@ ix86_split_to_parts (rtx operand, rtx *parts, 
machine_mode mode)
                case DFmode:
                  REAL_VALUE_TO_TARGET_DOUBLE (r, l);
                  break;
+               case SFmode:
+                 REAL_VALUE_TO_TARGET_SINGLE (r, l[0]);
+                 goto part0;
                default:
                  gcc_unreachable ();
                }
              parts[1] = gen_int_mode (l[1], SImode);
+part0:
              parts[0] = gen_int_mode (l[0], SImode);
            }
          else
@@ -22932,6 +22938,12 @@ ix86_split_long_move (rtx operands[])
   nparts = ix86_split_to_parts (operands[1], part[1], GET_MODE (operands[0]));
   ix86_split_to_parts (operands[0], part[0], GET_MODE (operands[0]));
 
+  if (nparts == 1)
+    {
+      emit_move_insn (part[0][0], part[1][0]);
+      return;
+    }
+
   /* When emitting push, take care for source operands on the stack.  */
   if (push && MEM_P (operands[1])
       && reg_overlap_mentioned_p (stack_pointer_rtx, operands[1]))
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index 1d43aaf..e723eab 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -3507,7 +3507,8 @@
   "reload_completed
    && (GET_MODE (operands[0]) == TFmode
        || GET_MODE (operands[0]) == XFmode
-       || GET_MODE (operands[0]) == DFmode)
+       || GET_MODE (operands[0]) == DFmode
+       || (TARGET_IAMCU && GET_MODE (operands[0]) == SFmode))
    && !(ANY_FP_REG_P (operands[0]) || ANY_FP_REG_P (operands[1]))"
   [(const_int 0)]
   "ix86_split_long_move (operands); DONE;")
diff --git a/gcc/testsuite/gcc.target/i386/pr66824.c 
b/gcc/testsuite/gcc.target/i386/pr66824.c
new file mode 100644
index 0000000..0966736
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr66824.c
@@ -0,0 +1,23 @@
+/* { dg-do compile { target ia32 } } */
+/* { dg-options "-O2 -miamcu" } */
+/* { dg-final { scan-assembler-not "\.LC\[0-9\]" } } */
+
+double foo (float);
+
+double
+f1 (void)
+{
+  return foo (1.0);
+}
+
+double
+f2 (void)
+{
+  return foo (0.0);
+}
+
+void
+f3 (float *x, float t)
+{
+  *x = 0.0 + t;
+}
-- 
2.4.3

Reply via email to