public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc(refs/users/meissner/heads/work058)] PR 101019: Improve loading 64-bit constants on power10.
@ 2021-07-04 13:16 Michael Meissner
0 siblings, 0 replies; 2+ messages in thread
From: Michael Meissner @ 2021-07-04 13:16 UTC (permalink / raw)
To: gcc-cvs
https://gcc.gnu.org/g:ece17549f76f29b5bd9b0751ef9bc1c5e1bf5ea5
commit ece17549f76f29b5bd9b0751ef9bc1c5e1bf5ea5
Author: Michael Meissner <meissner@linux.ibm.com>
Date: Sun Jul 4 09:16:35 2021 -0400
PR 101019: Improve loading 64-bit constants on power10.
When the support for prefixed instructions went into GCC, we did not
modify loading up larger constants to use one or two PLI/PADDI
instructions. This patch adds this support.
2021-07-04 Michael Meissner <meissner@linux.ibm.com>
gcc/
PR target/101019
* config/rs6000/rs6000.c (rs6000_option_override_internal): Add
-mprefixed-large-consts support.
(num_insns_constant_gpr): Add -mprefixed-large-consts support.
(rs6000_emit_set_long_const): Add -mprefixed-large-consts
support.
* config/rs6000/rs6000.opt (-mprefixed-large-consts): New switch.
gcc/testsuite/
PR target/101019
* gcc.target/powerpc/prefix-large-const.c: New test.
Diff:
---
gcc/config/rs6000/rs6000.c | 68 ++++++++++++++++++++--
gcc/config/rs6000/rs6000.opt | 4 ++
.../gcc.target/powerpc/prefix-large-const.c | 57 ++++++++++++++++++
3 files changed, 125 insertions(+), 4 deletions(-)
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index dd24e11ad8d..72dc0aa70a2 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -4502,6 +4502,14 @@ rs6000_option_override_internal (bool global_init_p)
if (!TARGET_PCREL && TARGET_PCREL_OPT)
rs6000_isa_flags &= ~OPTION_MASK_PCREL_OPT;
+ if (TARGET_PREFIXED_LARGE_CONSTS < 0)
+ TARGET_PREFIXED_LARGE_CONSTS = TARGET_PREFIXED;
+ else if (TARGET_PREFIXED_LARGE_CONSTS > 0 && !TARGET_PREFIXED)
+ {
+ error ("%qs requires %qs", "-mprefixed-large-consts", "-mprefixed");
+ TARGET_PREFIXED_LARGE_CONSTS = 0;
+ }
+
/* Possibly set the const_anchor to the maximum value, based on whether we
have prefixed addressing. */
if (TARGET_CONST_ANCHOR)
@@ -5945,9 +5953,20 @@ num_insns_constant_gpr (HOST_WIDE_INT value)
&& (value >> 31 == -1 || value >> 31 == 0))
return 1;
- /* PADDI can support up to 34 bit signed integers. */
- else if (TARGET_PREFIXED && SIGNED_INTEGER_34BIT_P (value))
- return 1;
+ /* PADDI can support up to 34 bit signed integers, or using a combination of
+ PADDI and shift left. */
+ else if (TARGET_PREFIXED_LARGE_CONSTS)
+ {
+ if (SIGNED_INTEGER_34BIT_P (value))
+ return 1;
+
+ /* PLI and SLDI. */
+ if ((value & 0xffffffff) == 0)
+ return 2;
+
+ /* PLI, SLDI, PADDI. */
+ return 3;
+ }
else if (TARGET_POWERPC64)
{
@@ -10113,7 +10132,48 @@ rs6000_emit_set_long_const (rtx dest, HOST_WIDE_INT c)
rtx two = gen_rtx_ASHIFT (DImode, temp, GEN_INT (32));
emit_move_insn (dest, gen_rtx_IOR (DImode, one, two));
}
- else if ((ud4 == 0xffff && (ud3 & 0x8000))
+ else if (TARGET_PREFIXED_LARGE_CONSTS)
+ {
+ HOST_WIDE_INT low_32bit = ud1 | (ud2 << 16);
+ HOST_WIDE_INT high_32bit = ud3 | (ud4 << 16);
+
+ temp = !can_create_pseudo_p () ? copy_rtx (dest) : gen_reg_rtx (DImode);
+ emit_move_insn (temp, GEN_INT (high_32bit));
+
+ if (!low_32bit)
+ emit_insn (gen_ashldi3 (dest, temp, GEN_INT (32)));
+ else
+ {
+ rtx temp2 = (!can_create_pseudo_p ()
+ ? copy_rtx (dest)
+ : gen_reg_rtx (DImode));
+
+ emit_insn (gen_ashldi3 (temp2, temp, GEN_INT (32)));
+
+ /* See if a simple ORI or ORIS will suffice to fill in the
+ constant. */
+ if (ud2 == 0)
+ emit_insn (gen_iordi3 (dest, temp2, GEN_INT (ud1)));
+ else if (ud1 == 0)
+ emit_insn (gen_iordi3 (dest, temp2, GEN_INT (ud2 << 16)));
+ /* If the register is not r0, we can do a PADDI. However, if the
+ register is r0, we need to do an ORI and ORIS instead of a PADDI.
+ This is because R0 as the register is interpreted as 0 and not
+ R0. */
+ else if (REGNO (dest) != FIRST_GPR_REGNO)
+ emit_insn (gen_adddi3 (dest, temp2, GEN_INT (low_32bit)));
+ else
+ {
+ rtx temp3 = (!can_create_pseudo_p ()
+ ? copy_rtx (dest)
+ : gen_reg_rtx (DImode));
+
+ emit_insn (gen_iordi3 (temp3, temp2, GEN_INT (ud2 << 16)));
+ emit_insn (gen_iordi3 (dest, temp3, GEN_INT (ud1)));
+ }
+ }
+ }
+ else if ((ud4 == 0xaffff && (ud3 & 0x8000))
|| (ud4 == 0 && ! (ud3 & 0x8000)))
{
temp = !can_create_pseudo_p () ? dest : gen_reg_rtx (DImode);
diff --git a/gcc/config/rs6000/rs6000.opt b/gcc/config/rs6000/rs6000.opt
index 70f89d42113..bdef71592f0 100644
--- a/gcc/config/rs6000/rs6000.opt
+++ b/gcc/config/rs6000/rs6000.opt
@@ -643,3 +643,7 @@ Generate code that will run in privileged state.
mconst-anchor
Target Undocumented Var(TARGET_CONST_ANCHOR) Save
Set targetm.const_anchor
+
+mprefixed-large-consts
+Target Undocumented Var(TARGET_PREFIXED_LARGE_CONSTS) Init(-1) Save
+Generate (do not generate) PLI/SLDI/PADDI to load large constants.
diff --git a/gcc/testsuite/gcc.target/powerpc/prefix-large-const.c b/gcc/testsuite/gcc.target/powerpc/prefix-large-const.c
new file mode 100644
index 00000000000..df0e333d148
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/prefix-large-const.c
@@ -0,0 +1,57 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target powerpc_prefixed_addr } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-options "-O2 -mdejagnu-cpu=power10" } */
+
+/* Test whether we can use PLI/PADDI to load up large constants. */
+
+long
+foo_1 (void)
+{
+ return 1L << 53; /* LIS, SLDI. */
+}
+
+long
+foo_2 (void)
+{
+ return 1L << 34; /* LI, SLDI. */
+}
+
+long
+foo_3 (void)
+{
+ return (1L << 53) | (1L << 35); /* PLI, SLDI. */
+}
+
+long
+foo_4 (void)
+{
+ return ((1L << 53) /* PLI, SLDI, PADDI. */
+ | (1L << 35)
+ | (1L << 30)
+ | (1L << 2));
+}
+
+long
+foo_5 (void)
+{
+ return ((1L << 53) /* PLI, SLDI, ORI. */
+ | (1L << 35)
+ | (1L << 2));
+}
+
+long
+foo_6 (void)
+{
+ return ((1L << 53) /* PLI, SLDI, ORIS. */
+ | (1L << 35)
+ | (1L << 30));
+}
+
+/* { dg-final { scan-assembler-times {\mli\M} 1 } } */
+/* { dg-final { scan-assembler-times {\mlis\M} 1 } } */
+/* { dg-final { scan-assembler-times {\mori\M} 1 } } */
+/* { dg-final { scan-assembler-times {\moris\M} 1 } } */
+/* { dg-final { scan-assembler-times {\mpaddi\M} 1 } } */
+/* { dg-final { scan-assembler-times {\mpli\M} 4 } } */
+/* { dg-final { scan-assembler-times {\msldi\M} 6 } } */
^ permalink raw reply [flat|nested] 2+ messages in thread
* [gcc(refs/users/meissner/heads/work058)] PR 101019: Improve loading 64-bit constants on power10.
@ 2021-06-30 22:05 Michael Meissner
0 siblings, 0 replies; 2+ messages in thread
From: Michael Meissner @ 2021-06-30 22:05 UTC (permalink / raw)
To: gcc-cvs
https://gcc.gnu.org/g:9e033b50fdf9644b1d0f49729ad2b28706507a39
commit 9e033b50fdf9644b1d0f49729ad2b28706507a39
Author: Michael Meissner <meissner@linux.ibm.com>
Date: Wed Jun 30 18:04:41 2021 -0400
PR 101019: Improve loading 64-bit constants on power10.
When the support for prefixed instructions went into GCC, we did not
modify loading up larger constants to use one or two PLI/PADDI
instructions. This patch adds this support.
gcc/
2021-06-30 Michael Meissner <meissner@linux.ibm.com>
PR target/101019
* config/rs6000/rs6000.c (rs6000_option_override_internal): Add
-mprefixed-large-consts support.
(num_insns_constant_gpr): Add -mprefixed-large-consts support.
(rs6000_emit_set_long_const): Add -mprefixed-large-consts
support.
* config/rs6000/rs6000.opt (-mprefixed-large-consts): New switch.
gcc/testsuite/
2021-06-18 Michael Meissner <meissner@linux.ibm.com>
PR target/101019
* gcc.target/powerpc/prefix-large-const.c: New test.
Diff:
---
gcc/config/rs6000/rs6000.c | 65 ++++++++++++++++++++--
gcc/config/rs6000/rs6000.opt | 4 ++
.../gcc.target/powerpc/prefix-large-const.c | 57 +++++++++++++++++++
3 files changed, 122 insertions(+), 4 deletions(-)
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index 2de3de01cce..47d79b00b8b 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -4502,6 +4502,11 @@ rs6000_option_override_internal (bool global_init_p)
if (!TARGET_PCREL && TARGET_PCREL_OPT)
rs6000_isa_flags &= ~OPTION_MASK_PCREL_OPT;
+ if (TARGET_PREFIXED_LARGE_CONSTS < 0)
+ TARGET_PREFIXED_LARGE_CONSTS = TARGET_PREFIXED;
+ else if (TARGET_PREFIXED_LARGE_CONSTS > 0 && !TARGET_PREFIXED)
+ error ("%qs requires %qs", "-mprefixed-large-consts", "-mprefixed");
+
/* Possibly set the const_anchor to the maximum value, based on whether we
have prefixed addressing. */
if (TARGET_CONST_ANCHOR)
@@ -5945,9 +5950,20 @@ num_insns_constant_gpr (HOST_WIDE_INT value)
&& (value >> 31 == -1 || value >> 31 == 0))
return 1;
- /* PADDI can support up to 34 bit signed integers. */
- else if (TARGET_PREFIXED && SIGNED_INTEGER_34BIT_P (value))
- return 1;
+ /* PADDI can support up to 34 bit signed integers, or using a combination of
+ PADDI and shift left. */
+ else if (TARGET_PREFIXED_LARGE_CONSTS)
+ {
+ if (SIGNED_INTEGER_34BIT_P (value))
+ return 1;
+
+ /* PLI and SLDI. */
+ if ((value & 0xffffffff) == 0)
+ return 2;
+
+ /* PLI, SLDI, PADDI. */
+ return 3;
+ }
else if (TARGET_POWERPC64)
{
@@ -10113,7 +10129,48 @@ rs6000_emit_set_long_const (rtx dest, HOST_WIDE_INT c)
rtx two = gen_rtx_ASHIFT (DImode, temp, GEN_INT (32));
emit_move_insn (dest, gen_rtx_IOR (DImode, one, two));
}
- else if ((ud4 == 0xffff && (ud3 & 0x8000))
+ else if (TARGET_PREFIXED_LARGE_CONSTS)
+ {
+ HOST_WIDE_INT low_32bit = ud1 | (ud2 << 16);
+ HOST_WIDE_INT high_32bit = ud3 | (ud4 << 16);
+
+ temp = !can_create_pseudo_p () ? copy_rtx (dest) : gen_reg_rtx (DImode);
+ emit_move_insn (temp, GEN_INT (high_32bit));
+
+ if (!low_32bit)
+ emit_insn (gen_ashldi3 (dest, temp, GEN_INT (32)));
+ else
+ {
+ rtx temp2 = (!can_create_pseudo_p ()
+ ? copy_rtx (dest)
+ : gen_reg_rtx (DImode));
+
+ emit_insn (gen_ashldi3 (temp2, temp, GEN_INT (32)));
+
+ /* See if a simple ORI or ORIS will suffice to fill in the
+ constant. */
+ if (ud2 == 0)
+ emit_insn (gen_iordi3 (dest, temp2, GEN_INT (ud1)));
+ else if (ud1 == 0)
+ emit_insn (gen_iordi3 (dest, temp2, GEN_INT (ud2 << 16)));
+ /* If the register is not r0, we can do a PADDI. However, if the
+ register is r0, we need to do an ORI and ORIS instead of a PADDI.
+ This is because R0 as the register is interpreted as 0 and not
+ R0. */
+ else if (REGNO (dest) != FIRST_GPR_REGNO)
+ emit_insn (gen_adddi3 (dest, temp2, GEN_INT (low_32bit)));
+ else
+ {
+ rtx temp3 = (!can_create_pseudo_p ()
+ ? copy_rtx (dest)
+ : gen_reg_rtx (DImode));
+
+ emit_insn (gen_iordi3 (temp3, temp2, GEN_INT (ud2 << 16)));
+ emit_insn (gen_iordi3 (dest, temp3, GEN_INT (ud1)));
+ }
+ }
+ }
+ else if ((ud4 == 0xaffff && (ud3 & 0x8000))
|| (ud4 == 0 && ! (ud3 & 0x8000)))
{
temp = !can_create_pseudo_p () ? dest : gen_reg_rtx (DImode);
diff --git a/gcc/config/rs6000/rs6000.opt b/gcc/config/rs6000/rs6000.opt
index 70f89d42113..bdef71592f0 100644
--- a/gcc/config/rs6000/rs6000.opt
+++ b/gcc/config/rs6000/rs6000.opt
@@ -643,3 +643,7 @@ Generate code that will run in privileged state.
mconst-anchor
Target Undocumented Var(TARGET_CONST_ANCHOR) Save
Set targetm.const_anchor
+
+mprefixed-large-consts
+Target Undocumented Var(TARGET_PREFIXED_LARGE_CONSTS) Init(-1) Save
+Generate (do not generate) PLI/SLDI/PADDI to load large constants.
diff --git a/gcc/testsuite/gcc.target/powerpc/prefix-large-const.c b/gcc/testsuite/gcc.target/powerpc/prefix-large-const.c
new file mode 100644
index 00000000000..df0e333d148
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/prefix-large-const.c
@@ -0,0 +1,57 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target powerpc_prefixed_addr } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-options "-O2 -mdejagnu-cpu=power10" } */
+
+/* Test whether we can use PLI/PADDI to load up large constants. */
+
+long
+foo_1 (void)
+{
+ return 1L << 53; /* LIS, SLDI. */
+}
+
+long
+foo_2 (void)
+{
+ return 1L << 34; /* LI, SLDI. */
+}
+
+long
+foo_3 (void)
+{
+ return (1L << 53) | (1L << 35); /* PLI, SLDI. */
+}
+
+long
+foo_4 (void)
+{
+ return ((1L << 53) /* PLI, SLDI, PADDI. */
+ | (1L << 35)
+ | (1L << 30)
+ | (1L << 2));
+}
+
+long
+foo_5 (void)
+{
+ return ((1L << 53) /* PLI, SLDI, ORI. */
+ | (1L << 35)
+ | (1L << 2));
+}
+
+long
+foo_6 (void)
+{
+ return ((1L << 53) /* PLI, SLDI, ORIS. */
+ | (1L << 35)
+ | (1L << 30));
+}
+
+/* { dg-final { scan-assembler-times {\mli\M} 1 } } */
+/* { dg-final { scan-assembler-times {\mlis\M} 1 } } */
+/* { dg-final { scan-assembler-times {\mori\M} 1 } } */
+/* { dg-final { scan-assembler-times {\moris\M} 1 } } */
+/* { dg-final { scan-assembler-times {\mpaddi\M} 1 } } */
+/* { dg-final { scan-assembler-times {\mpli\M} 4 } } */
+/* { dg-final { scan-assembler-times {\msldi\M} 6 } } */
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2021-07-04 13:16 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-07-04 13:16 [gcc(refs/users/meissner/heads/work058)] PR 101019: Improve loading 64-bit constants on power10 Michael Meissner
-- strict thread matches above, loose matches on Subject: below --
2021-06-30 22:05 Michael Meissner
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).