Generate XXSPLTIDP for scalars on power10.

This patch implements XXSPLTIDP support for SF, and DF scalar constants.
The previous patch added support for vector constants.  This patch adds
the support for SFmode and DFmode scalar constants.

I added 2 new tests to test loading up SF and DF scalar constants.

2021-12-15  Michael Meissner  <meissner@the-meissners.org>

gcc/

	* config/rs6000/rs6000.md (UNSPEC_XXSPLTIDP_CONST): New unspec.
	(UNSPEC_XXSPLTIW_CONST): New unspec.
	(movsf_hardfloat): Add support for generating XXSPLTIDP.
	(mov<mode>_hardfloat32): Likewise.
	(mov<mode>_hardfloat64): Likewise.
	(xxspltidp_<mode>_internal): New insns.
	(xxspltiw_<mode>_internal): New insns.
	(splitters for SF/DFmode): Add new splitters for XXSPLTIDP.

gcc/testsuite/

	* gcc.target/powerpc/vec-splat-constant-df.c: New test.
	* gcc.target/powerpc/vec-splat-constant-sf.c: New test.
This commit is contained in:
Michael Meissner 2021-12-15 02:30:20 -05:00
parent 8d443ac032
commit 575ad7700f
3 changed files with 199 additions and 18 deletions

View file

@ -156,6 +156,8 @@
UNSPEC_PEXTD
UNSPEC_HASHST
UNSPEC_HASHCHK
UNSPEC_XXSPLTIDP_CONST
UNSPEC_XXSPLTIW_CONST
])
;;
@ -7764,17 +7766,17 @@
;;
;; LWZ LFS LXSSP LXSSPX STFS STXSSP
;; STXSSPX STW XXLXOR LI FMR XSCPSGNDP
;; MR MT<x> MF<x> NOP
;; MR MT<x> MF<x> NOP XXSPLTIDP
(define_insn "movsf_hardfloat"
[(set (match_operand:SF 0 "nonimmediate_operand"
"=!r, f, v, wa, m, wY,
Z, m, wa, !r, f, wa,
!r, *c*l, !r, *h")
!r, *c*l, !r, *h, wa")
(match_operand:SF 1 "input_operand"
"m, m, wY, Z, f, v,
wa, r, j, j, f, wa,
r, r, *h, 0"))]
r, r, *h, 0, eP"))]
"(register_operand (operands[0], SFmode)
|| register_operand (operands[1], SFmode))
&& TARGET_HARD_FLOAT
@ -7796,15 +7798,16 @@
mr %0,%1
mt%0 %1
mf%1 %0
nop"
nop
#"
[(set_attr "type"
"load, fpload, fpload, fpload, fpstore, fpstore,
fpstore, store, veclogical, integer, fpsimple, fpsimple,
*, mtjmpr, mfjmpr, *")
*, mtjmpr, mfjmpr, *, vecperm")
(set_attr "isa"
"*, *, p9v, p8v, *, p9v,
p8v, *, *, *, *, *,
*, *, *, *")])
*, *, *, *, p10")])
;; LWZ LFIWZX STW STFIWX MTVSRWZ MFVSRWZ
;; FMR MR MT%0 MF%1 NOP
@ -8064,18 +8067,18 @@
;; STFD LFD FMR LXSD STXSD
;; LXSD STXSD XXLOR XXLXOR GPR<-0
;; LWZ STW MR
;; LWZ STW MR XXSPLTIDP
(define_insn "*mov<mode>_hardfloat32"
[(set (match_operand:FMOVE64 0 "nonimmediate_operand"
"=m, d, d, <f64_p9>, wY,
<f64_av>, Z, <f64_vsx>, <f64_vsx>, !r,
Y, r, !r")
Y, r, !r, wa")
(match_operand:FMOVE64 1 "input_operand"
"d, m, d, wY, <f64_p9>,
Z, <f64_av>, <f64_vsx>, <zero_fp>, <zero_fp>,
r, Y, r"))]
r, Y, r, eP"))]
"! TARGET_POWERPC64 && TARGET_HARD_FLOAT
&& (gpc_reg_operand (operands[0], <MODE>mode)
|| gpc_reg_operand (operands[1], <MODE>mode))"
@ -8092,20 +8095,21 @@
#
#
#
#
#"
[(set_attr "type"
"fpstore, fpload, fpsimple, fpload, fpstore,
fpload, fpstore, veclogical, veclogical, two,
store, load, two")
store, load, two, vecperm")
(set_attr "size" "64")
(set_attr "length"
"*, *, *, *, *,
*, *, *, *, 8,
8, 8, 8")
8, 8, 8, *")
(set_attr "isa"
"*, *, *, p9v, p9v,
p7v, p7v, *, *, *,
*, *, *")])
*, *, *, p10")])
;; STW LWZ MR G-const H-const F-const
@ -8132,19 +8136,19 @@
;; STFD LFD FMR LXSD STXSD
;; LXSDX STXSDX XXLOR XXLXOR LI 0
;; STD LD MR MT{CTR,LR} MF{CTR,LR}
;; NOP MFVSRD MTVSRD
;; NOP MFVSRD MTVSRD XXSPLTIDP
(define_insn "*mov<mode>_hardfloat64"
[(set (match_operand:FMOVE64 0 "nonimmediate_operand"
"=m, d, d, <f64_p9>, wY,
<f64_av>, Z, <f64_vsx>, <f64_vsx>, !r,
YZ, r, !r, *c*l, !r,
*h, r, <f64_dm>")
*h, r, <f64_dm>, wa")
(match_operand:FMOVE64 1 "input_operand"
"d, m, d, wY, <f64_p9>,
Z, <f64_av>, <f64_vsx>, <zero_fp>, <zero_fp>,
r, YZ, r, r, *h,
0, <f64_dm>, r"))]
0, <f64_dm>, r, eP"))]
"TARGET_POWERPC64 && TARGET_HARD_FLOAT
&& (gpc_reg_operand (operands[0], <MODE>mode)
|| gpc_reg_operand (operands[1], <MODE>mode))"
@ -8166,18 +8170,19 @@
mf%1 %0
nop
mfvsrd %0,%x1
mtvsrd %x0,%1"
mtvsrd %x0,%1
#"
[(set_attr "type"
"fpstore, fpload, fpsimple, fpload, fpstore,
fpload, fpstore, veclogical, veclogical, integer,
store, load, *, mtjmpr, mfjmpr,
*, mfvsr, mtvsr")
*, mfvsr, mtvsr, vecperm")
(set_attr "size" "64")
(set_attr "isa"
"*, *, *, p9v, p9v,
p7v, p7v, *, *, *,
*, *, *, *, *,
*, p8v, p8v")])
*, p8v, p8v, p10")])
;; STD LD MR MT<SPR> MF<SPR> G-const
;; H-const F-const Special
@ -8211,6 +8216,62 @@
(set_attr "length"
"*, *, *, *, *, 8,
12, 16, *")])
;; Split the VSX prefixed instruction to support SFmode and DFmode scalar
;; constants that look like DFmode floating point values where both elements
;; are the same. The constant has to be expressible as a SFmode constant that
;; is not a SFmode denormal value.
;;
;; We don't need splitters for the 128-bit types, since the function
;; rs6000_output_move_128bit handles the generation of XXSPLTIDP.
(define_insn "xxspltidp_<mode>_internal"
[(set (match_operand:SFDF 0 "register_operand" "=wa")
(unspec:SFDF [(match_operand:SI 1 "c32bit_cint_operand" "n")]
UNSPEC_XXSPLTIDP_CONST))]
"TARGET_POWER10"
"xxspltidp %x0,%1"
[(set_attr "type" "vecperm")
(set_attr "prefixed" "yes")])
(define_insn "xxspltiw_<mode>_internal"
[(set (match_operand:SFDF 0 "register_operand" "=wa")
(unspec:SFDF [(match_operand:SI 1 "c32bit_cint_operand" "n")]
UNSPEC_XXSPLTIW_CONST))]
"TARGET_POWER10"
"xxspltiw %x0,%1"
[(set_attr "type" "vecperm")
(set_attr "prefixed" "yes")])
(define_split
[(set (match_operand:SFDF 0 "vsx_register_operand")
(match_operand:SFDF 1 "vsx_prefixed_constant"))]
"TARGET_POWER10"
[(pc)]
{
rtx dest = operands[0];
rtx src = operands[1];
vec_const_128bit_type vsx_const;
if (!vec_const_128bit_to_bytes (src, <MODE>mode, &vsx_const))
gcc_unreachable ();
unsigned imm = constant_generates_xxspltidp (&vsx_const);
if (imm)
{
emit_insn (gen_xxspltidp_<mode>_internal (dest, GEN_INT (imm)));
DONE;
}
imm = constant_generates_xxspltiw (&vsx_const);
if (imm)
{
emit_insn (gen_xxspltiw_<mode>_internal (dest, GEN_INT (imm)));
DONE;
}
else
gcc_unreachable ();
})
(define_expand "mov<mode>"
[(set (match_operand:FMOVE128 0 "general_operand")

View file

@ -0,0 +1,60 @@
/* { dg-do compile } */
/* { dg-require-effective-target power10_ok } */
/* { dg-options "-mdejagnu-cpu=power10 -O2" } */
#include <math.h>
/* Test generating DFmode constants with the ISA 3.1 (power10) XXSPLTIDP
instruction. */
double
scalar_double_0 (void)
{
return 0.0; /* XXSPLTIB or XXLXOR. */
}
double
scalar_double_1 (void)
{
return 1.0; /* XXSPLTIDP. */
}
#ifndef __FAST_MATH__
double
scalar_double_m0 (void)
{
return -0.0; /* XXSPLTIDP. */
}
double
scalar_double_nan (void)
{
return __builtin_nan (""); /* XXSPLTIDP. */
}
double
scalar_double_inf (void)
{
return __builtin_inf (); /* XXSPLTIDP. */
}
double
scalar_double_m_inf (void) /* XXSPLTIDP. */
{
return - __builtin_inf ();
}
#endif
double
scalar_double_pi (void)
{
return M_PI; /* PLFD. */
}
double
scalar_double_denorm (void)
{
return 0x1p-149f; /* PLFD. */
}
/* { dg-final { scan-assembler-times {\mxxspltidp\M} 5 } } */

View file

@ -0,0 +1,60 @@
/* { dg-do compile } */
/* { dg-require-effective-target power10_ok } */
/* { dg-options "-mdejagnu-cpu=power10 -O2" } */
#include <math.h>
/* Test generating SFmode constants with the ISA 3.1 (power10) XXSPLTIDP
instruction. */
float
scalar_float_0 (void)
{
return 0.0f; /* XXSPLTIB or XXLXOR. */
}
float
scalar_float_1 (void)
{
return 1.0f; /* XXSPLTIDP. */
}
#ifndef __FAST_MATH__
float
scalar_float_m0 (void)
{
return -0.0f; /* XXSPLTIDP. */
}
float
scalar_float_nan (void)
{
return __builtin_nanf (""); /* XXSPLTIDP. */
}
float
scalar_float_inf (void)
{
return __builtin_inff (); /* XXSPLTIDP. */
}
float
scalar_float_m_inf (void) /* XXSPLTIDP. */
{
return - __builtin_inff ();
}
#endif
float
scalar_float_pi (void)
{
return (float)M_PI; /* XXSPLTIDP. */
}
float
scalar_float_denorm (void)
{
return 0x1p-149f; /* PLFS. */
}
/* { dg-final { scan-assembler-times {\mxxspltidp\M} 6 } } */