public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc(refs/users/meissner/heads/work127-vpair)] Add V8SF and V4DF constants.
@ 2023-07-18 22:11 Michael Meissner
0 siblings, 0 replies; only message in thread
From: Michael Meissner @ 2023-07-18 22:11 UTC (permalink / raw)
To: gcc-cvs
https://gcc.gnu.org/g:bae9104f9e7d7fb6b5807370ac7a405555003d80
commit bae9104f9e7d7fb6b5807370ac7a405555003d80
Author: Michael Meissner <meissner@linux.ibm.com>
Date: Tue Jul 18 18:10:57 2023 -0400
Add V8SF and V4DF constants.
2023-07-18 Michael Meissner <meissner@linux.ibm.com>
gcc/
* config/rs6000/constraints.md (eP constraint): Update comment.
* config/rs6000/mma.md (mov<mode>, VPAIR iterator): Add spport for
loading constants.
* config/rs6000/predicates.md (vsx_prefixed_constant): Handle V8SFmode
and V4DFmode constants.
(easy_vector_constant): Update V8SFmode and V4DFmode support.
* config/rs6000/rs6000-protos.h (rs6000_split_vpair_constant): New
declaration.
* config/rs6000/rs6000.cc (rs6000_split_vpair_constant): New helper
function.
(rs6000_split_multireg_move): Handle splitting a vector pair constant
into 2 separate vector instructions.
Diff:
---
gcc/config/rs6000/constraints.md | 3 +-
gcc/config/rs6000/mma.md | 9 ++---
gcc/config/rs6000/predicates.md | 30 +++++++++++++---
gcc/config/rs6000/rs6000-protos.h | 1 +
gcc/config/rs6000/rs6000.cc | 73 +++++++++++++++++++++++++++++++++++++++
5 files changed, 106 insertions(+), 10 deletions(-)
diff --git a/gcc/config/rs6000/constraints.md b/gcc/config/rs6000/constraints.md
index c4a6ccf4efb..955abe03ec9 100644
--- a/gcc/config/rs6000/constraints.md
+++ b/gcc/config/rs6000/constraints.md
@@ -208,7 +208,8 @@
(match_operand 0 "cint34_operand"))
;; A SF/DF scalar constant or a vector constant that can be loaded into vector
-;; registers with one prefixed instruction such as XXSPLTIDP or XXSPLTIW.
+;; registers with one prefixed instruction such as XXSPLTIDP or XXSPLTIW (or
+;; two prefixed instructions if the constant is a vector pair constant).
(define_constraint "eP"
"A constant that can be loaded into a VSX register with one prefixed insn."
(match_operand 0 "vsx_prefixed_constant"))
diff --git a/gcc/config/rs6000/mma.md b/gcc/config/rs6000/mma.md
index 2ffc68feb53..b3ba0643302 100644
--- a/gcc/config/rs6000/mma.md
+++ b/gcc/config/rs6000/mma.md
@@ -326,8 +326,8 @@
})
(define_insn_and_split "*mov<mode>"
- [(set (match_operand:VPAIR 0 "nonimmediate_operand" "=wa,m,wa,wa")
- (match_operand:VPAIR 1 "input_operand" "m,wa,wa,j"))]
+ [(set (match_operand:VPAIR 0 "nonimmediate_operand" "=wa,m,wa,wa,wa")
+ (match_operand:VPAIR 1 "input_operand" "m,wa,wa,j,eP"))]
"TARGET_MMA
&& (gpc_reg_operand (operands[0], <MODE>mode)
|| gpc_reg_operand (operands[1], <MODE>mode))"
@@ -335,6 +335,7 @@
lxvp%X1 %x0,%1
stxvp%X0 %x1,%0
#
+ #
#"
"&& reload_completed
&& (!MEM_P (operands[0]) && !MEM_P (operands[1]))"
@@ -343,9 +344,9 @@
rs6000_split_multireg_move (operands[0], operands[1]);
DONE;
}
- [(set_attr "type" "vecload,vecstore,veclogical,veclogical")
+ [(set_attr "type" "vecload,vecstore,veclogical,vecperm,vecperm")
(set_attr "size" "256")
- (set_attr "length" "*,*,8")])
+ (set_attr "length" "*,*,8,8,40")])
\f
;; Vector quad support. XOmode can only live in FPRs.
diff --git a/gcc/config/rs6000/predicates.md b/gcc/config/rs6000/predicates.md
index fe53e3083df..7451dd90b3e 100644
--- a/gcc/config/rs6000/predicates.md
+++ b/gcc/config/rs6000/predicates.md
@@ -635,10 +635,22 @@
;; constants that need to be loaded into vector registers, the instructions
;; don't work well with TImode variables assigned a constant. This is because
;; the 64-bit scalar constants are splatted into both halves of the register.
+;;
+;; Also handle vector pair constants by splitting the constant into 2 separate
+;; constants that will be loaded into each separate vector.
(define_predicate "vsx_prefixed_constant"
(match_code "const_double,const_vector,vec_duplicate")
{
+ rtx vpair_hi, vpair_lo;
+
+ /* If this is a vpair constant, break the constant into 2 separate vectors.
+ In this case, we allow either constant to be an easy altivec constant. */
+ if (CONST_VECTOR_P (op) && VECTOR_PAIR_MODE_P (mode) && TARGET_MMA
+ && rs6000_split_vpair_constant (op, &vpair_hi, &vpair_lo))
+ return (easy_vector_constant (vpair_hi, GET_MODE (vpair_hi))
+ && easy_vector_constant (vpair_lo, GET_MODE (vpair_lo)));
+
/* If we can generate the constant with a few Altivec instructions, don't
generate a prefixed instruction. */
if (CONST_VECTOR_P (op) && easy_altivec_constant (op, mode))
@@ -716,11 +728,22 @@
return num_insns == 1;
})
-;; Return 1 if the operand is a CONST_VECTOR and can be loaded into a
-;; vector register without using memory.
+;; Return 1 if the operand is a CONST_VECTOR and can be loaded into a vector
+;; register without using memory. If this is a vector pair constant, see if
+;; the constants for each vector register can be loaded.
(define_predicate "easy_vector_constant"
(match_code "const_vector")
{
+ rtx vpair_hi, vpair_lo;
+
+ if (VECTOR_PAIR_MODE_P (mode) && TARGET_MMA
+ && rs6000_split_vpair_constant (op, &vpair_hi, &vpair_lo))
+ return (easy_vector_constant (vpair_hi, GET_MODE (vpair_hi))
+ && easy_vector_constant (vpair_lo, GET_MODE (vpair_lo)));
+
+ if (GET_MODE_SIZE (mode) != 16)
+ return false;
+
if (VECTOR_MEM_ALTIVEC_OR_VSX_P (mode))
{
int value = 256;
@@ -729,9 +752,6 @@
if (zero_constant (op, mode) || all_ones_constant (op, mode))
return true;
- if (GET_MODE_SIZE (mode) != 16)
- return false;
-
/* Constants that can be generated with ISA 3.1 instructions are
easy. */
vec_const_128bit_type vsx_const;
diff --git a/gcc/config/rs6000/rs6000-protos.h b/gcc/config/rs6000/rs6000-protos.h
index f70118ea40f..2d0f8b2e916 100644
--- a/gcc/config/rs6000/rs6000-protos.h
+++ b/gcc/config/rs6000/rs6000-protos.h
@@ -138,6 +138,7 @@ extern void rs6000_emit_swsqrt (rtx, rtx, bool);
extern void output_toc (FILE *, rtx, int, machine_mode);
extern void rs6000_fatal_bad_address (rtx);
extern rtx create_TOC_reference (rtx, rtx);
+extern bool rs6000_split_vpair_constant (rtx, rtx *, rtx *);
extern void rs6000_split_multireg_move (rtx, rtx);
extern void rs6000_emit_le_vsx_permute (rtx, rtx, machine_mode);
extern void rs6000_emit_le_vsx_move (rtx, rtx, machine_mode);
diff --git a/gcc/config/rs6000/rs6000.cc b/gcc/config/rs6000/rs6000.cc
index a1d72f28138..f8f80d41483 100644
--- a/gcc/config/rs6000/rs6000.cc
+++ b/gcc/config/rs6000/rs6000.cc
@@ -27167,6 +27167,54 @@ rs6000_split_logical (rtx operands[3],
return;
}
+/* Split a vector constant for a type that can be held into a vector register
+ pair into 2 separate constants that can be held in a single vector register.
+ Return true if we can split the constant. */
+
+bool
+rs6000_split_vpair_constant (rtx op, rtx *high, rtx *low)
+{
+ *high = *low = NULL_RTX;
+ if (!CONST_VECTOR_P (op))
+ return false;
+
+ if (GET_MODE (op) == V8SFmode)
+ {
+ rtvec hi_vec = gen_rtvec (4,
+ CONST_VECTOR_ELT (op, 0),
+ CONST_VECTOR_ELT (op, 1),
+ CONST_VECTOR_ELT (op, 2),
+ CONST_VECTOR_ELT (op, 3));
+
+ rtvec lo_vec = gen_rtvec (4,
+ CONST_VECTOR_ELT (op, 4),
+ CONST_VECTOR_ELT (op, 5),
+ CONST_VECTOR_ELT (op, 6),
+ CONST_VECTOR_ELT (op, 7));
+
+ *high = gen_rtx_CONST_VECTOR (V4SFmode, hi_vec);
+ *low = gen_rtx_CONST_VECTOR (V4SFmode, lo_vec);
+ return true;
+ }
+
+ else if (GET_MODE (op) == V4DFmode)
+ {
+ rtvec hi_vec = gen_rtvec (2,
+ CONST_VECTOR_ELT (op, 0),
+ CONST_VECTOR_ELT (op, 1));
+
+ rtvec lo_vec = gen_rtvec (2,
+ CONST_VECTOR_ELT (op, 3),
+ CONST_VECTOR_ELT (op, 4));
+
+ *high = gen_rtx_CONST_VECTOR (V2DFmode, hi_vec);
+ *low = gen_rtx_CONST_VECTOR (V2DFmode, lo_vec);
+ return true;
+ }
+
+ return false;
+}
+
/* Emit instructions to move SRC to DST. Called by splitters for
multi-register moves. It will emit at most one instruction for
each register that is accessed; that is, it won't emit li/lis pairs
@@ -27185,6 +27233,8 @@ rs6000_split_multireg_move (rtx dst, rtx src)
int reg_mode_size;
/* The number of registers that will be moved. */
int nregs;
+ /* Hi/lo values for splitting vector pair constants. */
+ rtx vpair_hi, vpair_lo;
reg = REG_P (dst) ? REGNO (dst) : REGNO (src);
mode = GET_MODE (dst);
@@ -27213,6 +27263,29 @@ rs6000_split_multireg_move (rtx dst, rtx src)
gcc_assert (reg_mode_size * nregs == GET_MODE_SIZE (mode));
+ /* Handle vector pair constants. */
+ if (CONST_VECTOR_P (src) && VECTOR_PAIR_MODE_P (mode) && TARGET_MMA
+ && rs6000_split_vpair_constant (src, &vpair_hi, &vpair_lo)
+ && VSX_REGNO_P (reg))
+ {
+ reg_mode = GET_MODE (vpair_hi);
+ rtx reg_hi = gen_rtx_REG (reg_mode, reg);
+ rtx reg_lo = gen_rtx_REG (reg_mode, reg + 1);
+
+ emit_move_insn (reg_hi, vpair_hi);
+
+ /* 0.0 is easy. For other constants, copy the high register into the low
+ register if the two sets of constants are equal. This means we won't
+ be doing back to back prefixed load immediate instructions. */
+ if (rtx_equal_p (vpair_hi, vpair_lo)
+ && !rtx_equal_p (vpair_hi, CONST0_RTX (reg_mode)))
+ emit_move_insn (reg_lo, reg_hi);
+ else
+ emit_move_insn (reg_lo, vpair_lo);
+
+ return;
+ }
+
/* TDmode residing in FP registers is special, since the ISA requires that
the lower-numbered word of a register pair is always the most significant
word, even in little-endian mode. This does not match the usual subreg
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2023-07-18 22:11 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-07-18 22:11 [gcc(refs/users/meissner/heads/work127-vpair)] Add V8SF and V4DF constants 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).