From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 1005) id B8F663857821; Fri, 18 Jun 2021 04:55:54 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org B8F663857821 Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: Michael Meissner To: gcc-cvs@gcc.gnu.org Subject: [gcc(refs/users/meissner/heads/work056)] PR 101019: Improve loading 64-bit constants on power10. X-Act-Checkin: gcc X-Git-Author: Michael Meissner X-Git-Refname: refs/users/meissner/heads/work056 X-Git-Oldrev: eb8e1184b11abbe2bb0e7aad61c6e57286a597f9 X-Git-Newrev: 6305b55e8686a1d709876e6210ce4a47d0dd294f Message-Id: <20210618045554.B8F663857821@sourceware.org> Date: Fri, 18 Jun 2021 04:55:54 +0000 (GMT) X-BeenThere: gcc-cvs@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-cvs mailing list List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 18 Jun 2021 04:55:54 -0000 https://gcc.gnu.org/g:6305b55e8686a1d709876e6210ce4a47d0dd294f commit 6305b55e8686a1d709876e6210ce4a47d0dd294f Author: Michael Meissner Date: Fri Jun 18 00:55:16 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-18 Michael Meissner PR target/101019 * config/rs6000/rs6000-cpus.def (ISA_3_1_MASKS_SERVER): Add -mpower10-large-consts support. (POWERPC_MASKS): Add -mpower10-large-consts support. * config/rs6000/rs6000.c (rs6000_option_override_internal): Add -mpower10-large-consts support. (num_insns_constant_gpr): Add -mpower10-large-consts support. (rs6000_emit_set_long_const): Add -mpower10-large-consts support. (rs6000_opt_masks): Add -mpower10-large-consts. * config/rs6000/rs6000.opt (-mpower10-large-consts): New switch. gcc/testsuite/ 2021-06-18 Michael Meissner PR target/101019 * gcc.target/powerpc/prefix-large-const.c: New test. Diff: --- gcc/config/rs6000/rs6000-cpus.def | 2 + gcc/config/rs6000/rs6000.c | 67 ++++++++++++++++++++-- gcc/config/rs6000/rs6000.opt | 4 ++ .../gcc.target/powerpc/prefix-large-const.c | 57 ++++++++++++++++++ 4 files changed, 126 insertions(+), 4 deletions(-) diff --git a/gcc/config/rs6000/rs6000-cpus.def b/gcc/config/rs6000/rs6000-cpus.def index c0d89434fcd..b119f574e4c 100644 --- a/gcc/config/rs6000/rs6000-cpus.def +++ b/gcc/config/rs6000/rs6000-cpus.def @@ -90,6 +90,7 @@ | OPTION_MASK_P10_FUSION_LOGADD \ | OPTION_MASK_P10_FUSION_ADDLOG \ | OPTION_MASK_P10_FUSION_2ADD \ + | OPTION_MASK_P10_LARGE_CONSTS \ | OPTION_MASK_XXSPLTI32DX \ | OPTION_MASK_XXSPLTIDP \ | OPTION_MASK_XXSPLTIW) @@ -145,6 +146,7 @@ | OPTION_MASK_P10_FUSION_LOGADD \ | OPTION_MASK_P10_FUSION_ADDLOG \ | OPTION_MASK_P10_FUSION_2ADD \ + | OPTION_MASK_P10_LARGE_CONSTS \ | OPTION_MASK_HTM \ | OPTION_MASK_ISEL \ | OPTION_MASK_LXVKQ \ diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index d34d8ba0ce9..01a586e1b14 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -4489,6 +4489,12 @@ rs6000_option_override_internal (bool global_init_p) && (rs6000_isa_flags_explicit & OPTION_MASK_P10_FUSION_2ADD) == 0) rs6000_isa_flags |= OPTION_MASK_P10_FUSION_2ADD; + if (TARGET_PREFIXED + && (rs6000_isa_flags_explicit & OPTION_MASK_P10_LARGE_CONSTS) == 0) + rs6000_isa_flags |= OPTION_MASK_P10_LARGE_CONSTS; + else if (!TARGET_PREFIXED) + rs6000_isa_flags &= ~OPTION_MASK_P10_LARGE_CONSTS; + /* Turn off vector pair/mma options on non-power10 systems. */ else if (!TARGET_POWER10 && TARGET_MMA) { @@ -5964,9 +5970,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_P10_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) { @@ -10420,7 +10437,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_P10_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); @@ -24432,6 +24490,7 @@ static struct rs6000_opt_mask const rs6000_opt_masks[] = { "power9-misc", OPTION_MASK_P9_MISC, false, true }, { "power9-vector", OPTION_MASK_P9_VECTOR, false, true }, { "power10-fusion", OPTION_MASK_P10_FUSION, false, true }, + { "power10-large-consts", OPTION_MASK_P10_LARGE_CONSTS, false, true }, { "powerpc-gfxopt", OPTION_MASK_PPC_GFXOPT, false, true }, { "powerpc-gpopt", OPTION_MASK_PPC_GPOPT, false, true }, { "prefixed", OPTION_MASK_PREFIXED, false, true }, diff --git a/gcc/config/rs6000/rs6000.opt b/gcc/config/rs6000/rs6000.opt index e65dd8762a4..add22c8be1a 100644 --- a/gcc/config/rs6000/rs6000.opt +++ b/gcc/config/rs6000/rs6000.opt @@ -655,3 +655,7 @@ Generate (do not generate) XXSPLTI32DX instructions. mlxvkq Target Undocumented Mask(LXVKQ) Var(rs6000_isa_flags) Generate (do not generate) LXVKQ instructions. + +mpower10-large-consts +Target Undocumented Mask(P10_LARGE_CONSTS) Var(rs6000_isa_flags) +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 } } */