aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2018-12-01 00:05:25 +1030
committerAlan Modra <amodra@gcc.gnu.org>2018-12-01 00:05:25 +1030
commitb49f1a7e7c85add83637cf7df46b8fc9b5b299e9 (patch)
treed3cba1d26194ebe465ba3abbdc1bc4b7e64133af /gcc
parentceb8c8c4cae47fd07cd7dda74bb31b98ce4adadc (diff)
downloadgcc-b49f1a7e7c85add83637cf7df46b8fc9b5b299e9.zip
gcc-b49f1a7e7c85add83637cf7df46b8fc9b5b299e9.tar.gz
gcc-b49f1a7e7c85add83637cf7df46b8fc9b5b299e9.tar.bz2
[RS6000] PowerPC64 soft-float
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog9
-rw-r--r--gcc/config/rs6000/predicates.md21
-rw-r--r--gcc/config/rs6000/rs6000.c19
-rw-r--r--gcc/config/rs6000/rs6000.md2
4 files changed, 48 insertions, 3 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 617a3d6..15cbe00 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,14 @@
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
num_insns_constant_wide. Make static. Revise comment.
(num_insns_constant_multi): New function.
diff --git a/gcc/config/rs6000/predicates.md b/gcc/config/rs6000/predicates.md
index cf07d5c..94feae2 100644
--- a/gcc/config/rs6000/predicates.md
+++ b/gcc/config/rs6000/predicates.md
@@ -564,9 +564,26 @@
{
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))
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index fe58bc1..03b983b 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -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 ();
}
diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index d2f6f11..797d5c3 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -7729,7 +7729,7 @@
(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")