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).