From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 1005) id E1B873858C52; Fri, 3 Feb 2023 19:28:05 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org E1B873858C52 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1675452485; bh=ECE2NryP9+CJf1RymmdM9pc/IPZUTc+yyrOJK6CnNTM=; h=From:To:Subject:Date:From; b=OVJV17RxV57U1acfrIDCra/fGVIFVyOEudF9s2/msdpdYP3Bv2H7lnB4WcO+CH7Pn PA3H+0uVPhiN/tMwZsk7r4wv+WhBRP3Kn67GfPH2iTCqR/zHRGOHVKBaCSOfKkItru Cpdw2N8dquUjH6HDLdZD4EJ4rtWEjnvdK+wwWcdY= 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/dmf008)] Support load/store vector with right length. X-Act-Checkin: gcc X-Git-Author: Michael Meissner X-Git-Refname: refs/users/meissner/heads/dmf008 X-Git-Oldrev: e625820b066fc5631c38bf0b83e5e905496e2931 X-Git-Newrev: c4b34034148412c5d79580d2c4bee5683ff4e5d0 Message-Id: <20230203192805.E1B873858C52@sourceware.org> Date: Fri, 3 Feb 2023 19:28:05 +0000 (GMT) List-Id: https://gcc.gnu.org/g:c4b34034148412c5d79580d2c4bee5683ff4e5d0 commit c4b34034148412c5d79580d2c4bee5683ff4e5d0 Author: Michael Meissner Date: Fri Feb 3 14:27:16 2023 -0500 Support load/store vector with right length. This patch adds support for new instructions that may be added to the PowerPC architecture in the future to enhance the load and store vector with length instructions. The current instructions (lxvl, lxvll, stxvl, and stxvll) are inconvient to use since the count for the number of bytes must be in the top 8 bits of the GPR register, instead of the bottom 8 bits. This meant that code generating these instructions typically had to do a shift left by 56 bits to get the count into the right position. In a future version of the PowerPC architecture, new variants of these instructions might be added that expect the count to be in the bottom 8 bits of the GPR register. These patches add this support to GCC if the user uses the -mcpu=future option. I discovered that the code in rs6000-string.cc to generate ISA 3.1 lxvl/stxvl future lxvll/stxvll instructions would generate these instructions on 32-bit. However the patterns for these instructions is only done on 64-bit systems. So I added a check for 64-bit support before generating the instructions. I tested this patch on a little endian power10 system with long double using the tradiational IBM double double format. Assuming the other 6 patches for -mcpu=future are checked in (or at least the first patch), can I check this patch into the master branch for GCC 13? 2023-02-03 Michael Meissner gcc/ * config/rs6000/rs6000-string.cc (expand_block_move): Do generate lxvl and stxvl on 32-bit. * config/rs6000/vsx.md (lxvl): If -mcpu=future, generate the lxvl with the shift count automaticaly used in the insn. (lxvrl): New insn for -mcpu=future. (lxvrll): Likewise. (stxvl): If -mcpu=future, generate the stxvl with the shift count automaticaly used in the insn. (stxvrl): New insn for -mcpu=future. (stxvrll): Likewise. gcc/testsuite/ * gcc.target/powerpc/lxvrl.c: New test. * lib/target-supports.exp (check_effective_target_powerpc_future_ok): New effective target. Diff: --- gcc/config/rs6000/rs6000-string.cc | 1 + gcc/config/rs6000/vsx.md | 122 +++++++++++++++++++++++++------ gcc/testsuite/gcc.target/powerpc/lxvrl.c | 32 ++++++++ gcc/testsuite/lib/target-supports.exp | 16 +++- 4 files changed, 148 insertions(+), 23 deletions(-) diff --git a/gcc/config/rs6000/rs6000-string.cc b/gcc/config/rs6000/rs6000-string.cc index 75e6f8803a5..9b2f1b83b22 100644 --- a/gcc/config/rs6000/rs6000-string.cc +++ b/gcc/config/rs6000/rs6000-string.cc @@ -2811,6 +2811,7 @@ expand_block_move (rtx operands[], bool might_overlap) gen_func.mov = gen_vsx_movv2di_64bit; } else if (TARGET_BLOCK_OPS_UNALIGNED_VSX + && TARGET_POWERPC64 && TARGET_POWER10 && bytes < 16 && orig_bytes > 16 && !(bytes == 1 || bytes == 2 diff --git a/gcc/config/rs6000/vsx.md b/gcc/config/rs6000/vsx.md index 0865608f94a..1ab8dc373c0 100644 --- a/gcc/config/rs6000/vsx.md +++ b/gcc/config/rs6000/vsx.md @@ -5582,20 +5582,32 @@ DONE; }) -;; Load VSX Vector with Length +;; Load VSX Vector with Length. If we have lxvrl, we don't have to do an +;; explicit shift left into a pseudo. (define_expand "lxvl" - [(set (match_dup 3) - (ashift:DI (match_operand:DI 2 "register_operand") - (const_int 56))) - (set (match_operand:V16QI 0 "vsx_register_operand") - (unspec:V16QI - [(match_operand:DI 1 "gpc_reg_operand") - (mem:V16QI (match_dup 1)) - (match_dup 3)] - UNSPEC_LXVL))] + [(use (match_operand:V16QI 0 "vsx_register_operand")) + (use (match_operand:DI 1 "gpc_reg_operand")) + (use (match_operand:DI 2 "gpc_reg_operand"))] "TARGET_P9_VECTOR && TARGET_64BIT" { - operands[3] = gen_reg_rtx (DImode); + rtx shift_len = gen_rtx_ASHIFT (DImode, operands[2], GEN_INT (56)); + rtx len; + + if (TARGET_FUTURE) + len = shift_len; + else + { + len = gen_reg_rtx (DImode); + emit_insn (gen_rtx_SET (len, shift_len)); + } + + rtx dest = operands[0]; + rtx addr = operands[1]; + rtx mem = gen_rtx_MEM (V16QImode, addr); + rtvec rv = gen_rtvec (3, addr, mem, len); + rtx lxvl = gen_rtx_UNSPEC (V16QImode, rv, UNSPEC_LXVL); + emit_insn (gen_rtx_SET (dest, lxvl)); + DONE; }) (define_insn "*lxvl" @@ -5619,6 +5631,34 @@ "lxvll %x0,%1,%2" [(set_attr "type" "vecload")]) +;; For lxvrl and lxvrll, use the combiner to eliminate the shift. The +;; define_expand for lxvl will already incorporate the shift in generating the +;; insn. The lxvll buitl-in function required the user to have already done +;; the shift. Defining lxvrll this way, will optimize cases where the user has +;; done the shift immediately before the built-in. +(define_insn "*lxvrl" + [(set (match_operand:V16QI 0 "vsx_register_operand" "=wa") + (unspec:V16QI + [(match_operand:DI 1 "gpc_reg_operand" "b") + (mem:V16QI (match_dup 1)) + (ashift:DI (match_operand:DI 2 "register_operand" "r") + (const_int 56))] + UNSPEC_LXVL))] + "TARGET_FUTURE && TARGET_64BIT" + "lxvrl %x0,%1,%2" + [(set_attr "type" "vecload")]) + +(define_insn "*lxvrll" + [(set (match_operand:V16QI 0 "vsx_register_operand" "=wa") + (unspec:V16QI [(match_operand:DI 1 "gpc_reg_operand" "b") + (mem:V16QI (match_dup 1)) + (ashift:DI (match_operand:DI 2 "register_operand" "r") + (const_int 56))] + UNSPEC_LXVLL))] + "TARGET_FUTURE" + "lxvrll %x0,%1,%2" + [(set_attr "type" "vecload")]) + ;; Expand for builtin xl_len_r (define_expand "xl_len_r" [(match_operand:V16QI 0 "vsx_register_operand") @@ -5650,18 +5690,29 @@ ;; Store VSX Vector with Length (define_expand "stxvl" - [(set (match_dup 3) - (ashift:DI (match_operand:DI 2 "register_operand") - (const_int 56))) - (set (mem:V16QI (match_operand:DI 1 "gpc_reg_operand")) - (unspec:V16QI - [(match_operand:V16QI 0 "vsx_register_operand") - (mem:V16QI (match_dup 1)) - (match_dup 3)] - UNSPEC_STXVL))] + [(use (match_operand:V16QI 0 "vsx_register_operand")) + (use (match_operand:DI 1 "gpc_reg_operand")) + (use (match_operand:DI 2 "gpc_reg_operand"))] "TARGET_P9_VECTOR && TARGET_64BIT" { - operands[3] = gen_reg_rtx (DImode); + rtx shift_len = gen_rtx_ASHIFT (DImode, operands[2], GEN_INT (56)); + rtx len; + + if (TARGET_FUTURE) + len = shift_len; + else + { + len = gen_reg_rtx (DImode); + emit_insn (gen_rtx_SET (len, shift_len)); + } + + rtx src = operands[0]; + rtx addr = operands[1]; + rtx mem = gen_rtx_MEM (V16QImode, addr); + rtvec rv = gen_rtvec (3, src, mem, len); + rtx stxvl = gen_rtx_UNSPEC (V16QImode, rv, UNSPEC_STXVL); + emit_insn (gen_rtx_SET (mem, stxvl)); + DONE; }) ;; Define optab for vector access with length vectorization exploitation. @@ -5705,6 +5756,35 @@ "stxvl %x0,%1,%2" [(set_attr "type" "vecstore")]) +;; For stxvrl and stxvrll, use the combiner to eliminate the shift. The +;; define_expand for stxvl will already incorporate the shift in generating the +;; insn. The stxvll buitl-in function required the user to have already done +;; the shift. Defining stxvrll this way, will optimize cases where the user +;; has done the shift immediately before the built-in. + +(define_insn "*stxvrl" + [(set (mem:V16QI (match_operand:DI 1 "gpc_reg_operand" "b")) + (unspec:V16QI + [(match_operand:V16QI 0 "vsx_register_operand" "wa") + (mem:V16QI (match_dup 1)) + (ashift:DI (match_operand:DI 2 "register_operand" "r") + (const_int 56))] + UNSPEC_STXVL))] + "TARGET_FUTURE && TARGET_64BIT" + "stxvrl %x0,%1,%2" + [(set_attr "type" "vecstore")]) + +(define_insn "*stxvrll" + [(set (mem:V16QI (match_operand:DI 1 "gpc_reg_operand" "b")) + (unspec:V16QI [(match_operand:V16QI 0 "vsx_register_operand" "wa") + (mem:V16QI (match_dup 1)) + (ashift:DI (match_operand:DI 2 "register_operand" "r") + (const_int 56))] + UNSPEC_STXVLL))] + "TARGET_FUTURE" + "stxvrll %x0,%1,%2" + [(set_attr "type" "vecstore")]) + ;; Expand for builtin xst_len_r (define_expand "xst_len_r" [(match_operand:V16QI 0 "vsx_register_operand" "=wa") diff --git a/gcc/testsuite/gcc.target/powerpc/lxvrl.c b/gcc/testsuite/gcc.target/powerpc/lxvrl.c new file mode 100644 index 00000000000..71854c50c91 --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/lxvrl.c @@ -0,0 +1,32 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target powerpc_future_ok } */ +/* { dg-require-effective-target lp64 } */ +/* { dg-options "-mdejagnu-cpu=future -O2" } */ + +/* Test whether the lxvrl and stxvrl instructions are generated for + -mcpu=future on memory copy operations. */ + +#ifndef VSIZE +#define VSIZE 2 +#endif + +#ifndef LSIZE +#define LSIZE 5 +#endif + +struct foo { + vector unsigned char vc[VSIZE]; + unsigned char leftover[LSIZE]; +}; + +void memcpy_ptr (struct foo *p, struct foo *q) +{ + __builtin_memcpy ((void *) p, /* lxvrl and stxvrl. */ + (void *) q, + (sizeof (vector unsigned char) * VSIZE) + LSIZE); +} + +/* { dg-final { scan-assembler {\mlxvrl\M} } } */ +/* { dg-final { scan-assembler {\mstxvrl\M} } } */ +/* { dg-final { scan-assembler-not {\mlxvl\M} } } */ +/* { dg-final { scan-assembler-not {\mstxvl\M} } } */ diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp index 9586ed3ae47..47adf407f83 100644 --- a/gcc/testsuite/lib/target-supports.exp +++ b/gcc/testsuite/lib/target-supports.exp @@ -6581,8 +6581,8 @@ proc check_effective_target_power10_ok { } { } } -# Return 1 if this is a PowerPC target supporting -mcpu=future or -mdense-math -# which enables the dense math operations. +# Return 1 if this is a PowerPC target supporting -mcpu=future which enables +# the dense math operations. proc check_effective_target_powerpc_dense_math_ok { } { return [check_no_compiler_messages_nocache powerpc_dense_math_ok assembly { __vector_quad vq; @@ -6600,6 +6600,18 @@ proc check_effective_target_powerpc_dense_math_ok { } { } "-mcpu=future"] } +# Return 1 if this is a PowerPC target supporting -mcpu=future which enables +# the saturating subtract instruction. +proc check_effective_target_powerpc_future_ok { } { + return [check_no_compiler_messages powerpc_future_ok object { + #ifndef _ARCH_PWR_FUTURE + #error "not -mcpu=future" + #else + int dummy; + #endif + } "-mcpu=future"] +} + # Return 1 if this is a PowerPC target supporting -mfloat128 via either # software emulation on power7/power8 systems or hardware support on power9.