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.
---
 gcc/config/i386/i386.c  | 14 +++++++++++++-
 gcc/config/i386/i386.md |  3 ++-
 2 files changed, 15 insertions(+), 2 deletions(-)

diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index e4e505c..aceeb13 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -22747,7 +22747,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 load.  */
+  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.  */
@@ -22825,10 +22827,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
@@ -22935,6 +22941,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;")
-- 
2.4.3

Reply via email to