[RS6000] PowerPC64 soft-float
authorAlan Modra <amodra@gmail.com>
Fri, 30 Nov 2018 13:35:25 +0000 (00:05 +1030)
committerAlan Modra <amodra@gcc.gnu.org>
Fri, 30 Nov 2018 13:35:25 +0000 (00:05 +1030)
This patch aims to prevent long sequences loading soft-float
constants.  For 32-bit, it makes sense to load values inline to a gpr
with lis, addi, but not so much for 64-bit where a 5 insn sequence
might be needed for each gpr.  For TFmode in particular, a 10 insn
sequence is reduced to 2 loads from memory plus 1 or 2 address setup
insns.

* config/rs6000/predicates.md (easy_fp_constant): Avoid long
dependent insn sequences.
* config/rs6000/rs6000.c (num_insns_constant): Support long
double constants.
* config/rs6000/rs6000.md (mov<mode>_softfloat <FMOVE128>): Adjust
length attribute.

From-SVN: r266663

gcc/ChangeLog
gcc/config/rs6000/predicates.md
gcc/config/rs6000/rs6000.c
gcc/config/rs6000/rs6000.md

index 617a3d64d2ae0292f8fe21ee8b84ea2ab91d4e21..15cbe00abd6e1c0b48e726944e14ae425cda4ce5 100644 (file)
@@ -1,3 +1,12 @@
+2018-11-30  Alan Modra  <amodra@gmail.com>
+
+       * config/rs6000/predicates.md (easy_fp_constant): Avoid long
+       dependent insn sequences.
+       * config/rs6000/rs6000.c (num_insns_constant): Support long
+       double constants.
+       * config/rs6000/rs6000.md (mov<mode>_softfloat <FMOVE128>): Adjust
+       length attribute.
+
 2018-11-30  Alan Modra  <amodra@gmail.com>
 
        * config/rs6000/rs6000.c (num_insns_constant_gpr): Renamed from
index cf07d5c6372cc6157a94ed06d2b733959e9d7210..94feae28c0224871ac3de3c596cbd2ca695db718 100644 (file)
 {
   gcc_assert (GET_MODE (op) == mode && SCALAR_FLOAT_MODE_P (mode));
 
-  /* Consider all constants with -msoft-float to be easy.  */
+  /* Consider all constants with -msoft-float to be easy when regs are
+     32-bit and thus can be loaded with a maximum of 2 insns.  For
+     64-bit avoid long dependent insn sequences.  */
   if (TARGET_SOFT_FLOAT)
-    return 1;
+    {
+      if (!TARGET_POWERPC64)
+        return 1;
+
+      int size = GET_MODE_SIZE (mode);
+      if (size < 8)
+        return 1;
+
+      int load_from_mem_insns = 2;
+      if (size > 8)
+        load_from_mem_insns++;
+      if (TARGET_CMODEL != CMODEL_SMALL)
+        load_from_mem_insns++;
+      if (num_insns_constant (op, mode) <= load_from_mem_insns)
+        return 1;
+    }
 
   /* 0.0D is not all zero bits.  */
   if (DECIMAL_FLOAT_MODE_P (mode))
index fe58bc1a3dddc96465281d8e689d07ee27623668..03b983b6d60f7e5af7fea2c03a6e040945993663 100644 (file)
@@ -5940,6 +5940,25 @@ num_insns_constant (rtx op, machine_mode mode)
            val |= l[WORDS_BIG_ENDIAN ? 1 : 0] & 0xffffffffUL;
            mode = DImode;
          }
+       else if (mode == TFmode || mode == TDmode
+                || mode == KFmode || mode == IFmode)
+         {
+           long l[4];
+           int insns;
+
+           if (mode == TDmode)
+             REAL_VALUE_TO_TARGET_DECIMAL128 (*rv, l);
+           else
+             REAL_VALUE_TO_TARGET_LONG_DOUBLE (*rv, l);
+
+           val = (unsigned HOST_WIDE_INT) l[WORDS_BIG_ENDIAN ? 0 : 3] << 32;
+           val |= l[WORDS_BIG_ENDIAN ? 1 : 2] & 0xffffffffUL;
+           insns = num_insns_constant_multi (val, DImode);
+           val = (unsigned HOST_WIDE_INT) l[WORDS_BIG_ENDIAN ? 2 : 1] << 32;
+           val |= l[WORDS_BIG_ENDIAN ? 3 : 0] & 0xffffffffUL;
+           insns += num_insns_constant_multi (val, DImode);
+           return insns;
+         }
        else
          gcc_unreachable ();
       }
index d2f6f11b3e5b19cacfe5a70b4686fcf953dbc806..797d5c32e64dabcabe069835690f57f3ac51d5e3 100644 (file)
            (const_string "8")
            (const_string "16"))
        (if_then_else (match_test "TARGET_POWERPC64")
-           (const_string "40")
+           (const_string "16")
            (const_string "32"))
        (if_then_else (match_test "TARGET_POWERPC64")
            (const_string "8")