public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: Sylvain Noiry <snoiry@kalrayinc.com>
To: gcc-patches@gcc.gnu.org
Cc: Sylvain Noiry <snoiry@kalrayinc.com>
Subject: [PATCH 4/9] Native complex operations: Allow native complex regs and ops in rtl
Date: Mon, 17 Jul 2023 11:02:45 +0200	[thread overview]
Message-ID: <20230717090250.4645-5-snoiry@kalrayinc.com> (raw)
In-Reply-To: <20230717090250.4645-1-snoiry@kalrayinc.com>

Support registers of complex types in rtl. Also adapt the functions
called during the expand pass to support native complex operations.

gcc/ChangeLog:

	* explow.cc (trunc_int_for_mode): Allow complex int modes
	* expr.cc (emit_move_complex_parts): Move both parts at the
	same time if it is supported by the backend
	(emit_move_complex): Do not move via integer if not int mode
	corresponds. For complex floats, relax the constraint on the
	number of registers for targets with pairs of registers, and
	use native moves if it is supported by the backend.
	(expand_expr_real_2): Move both parts at the same time if it
	is supported by the backend
	(expand_expr_real_1): Update the expand of complex constants
	(const_vector_from_tree): Add the expand of both parts of a
	complex	constant
	* real.h: update FLOAT_MODE_FORMAT
	* machmode.h: Add COMPLEX_INT_MODE_P and COMPLEX_FLOAT_MODE_P
	predicates
	* optabs-libfuncs.cc (gen_int_libfunc): Add support for
	complex modes
	(gen_intv_fp_libfunc): Likewise
	* recog.cc (general_operand): Likewise
---
 gcc/explow.cc          |  2 +-
 gcc/expr.cc            | 84 ++++++++++++++++++++++++++++++++++++------
 gcc/machmode.h         |  6 +++
 gcc/optabs-libfuncs.cc | 29 ++++++++++++---
 gcc/real.h             |  3 +-
 gcc/recog.cc           |  1 +
 6 files changed, 105 insertions(+), 20 deletions(-)

diff --git a/gcc/explow.cc b/gcc/explow.cc
index 6424c0802f0..48572a40eab 100644
--- a/gcc/explow.cc
+++ b/gcc/explow.cc
@@ -56,7 +56,7 @@ trunc_int_for_mode (HOST_WIDE_INT c, machine_mode mode)
   int width = GET_MODE_PRECISION (smode);
 
   /* You want to truncate to a _what_?  */
-  gcc_assert (SCALAR_INT_MODE_P (mode));
+  gcc_assert (SCALAR_INT_MODE_P (mode) || COMPLEX_INT_MODE_P (mode));
 
   /* Canonicalize BImode to 0 and STORE_FLAG_VALUE.  */
   if (smode == BImode)
diff --git a/gcc/expr.cc b/gcc/expr.cc
index e1a0892b4d9..e94de8a05b5 100644
--- a/gcc/expr.cc
+++ b/gcc/expr.cc
@@ -3847,8 +3847,14 @@ emit_move_complex_parts (rtx x, rtx y)
       && REG_P (x) && !reg_overlap_mentioned_p (x, y))
     emit_clobber (x);
 
-  write_complex_part (x, read_complex_part (y, REAL_P), REAL_P, true);
-  write_complex_part (x, read_complex_part (y, IMAG_P), IMAG_P, false);
+  machine_mode mode = GET_MODE (x);
+  if (optab_handler (mov_optab, mode) != CODE_FOR_nothing)
+    write_complex_part (x, read_complex_part (y, BOTH_P), BOTH_P, false);
+  else
+    {
+      write_complex_part (x, read_complex_part (y, REAL_P), REAL_P, true);
+      write_complex_part (x, read_complex_part (y, IMAG_P), IMAG_P, false);
+    }
 
   return get_last_insn ();
 }
@@ -3868,14 +3874,14 @@ emit_move_complex (machine_mode mode, rtx x, rtx y)
 
   /* See if we can coerce the target into moving both values at once, except
      for floating point where we favor moving as parts if this is easy.  */
-  if (GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT
+  scalar_int_mode imode;
+  if (!int_mode_for_mode (mode).exists (&imode))
+    try_int = false;
+  else if (GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT
       && optab_handler (mov_optab, GET_MODE_INNER (mode)) != CODE_FOR_nothing
-      && !(REG_P (x)
-	   && HARD_REGISTER_P (x)
-	   && REG_NREGS (x) == 1)
-      && !(REG_P (y)
-	   && HARD_REGISTER_P (y)
-	   && REG_NREGS (y) == 1))
+      && optab_handler (mov_optab, mode) != CODE_FOR_nothing
+      && !(REG_P (x) && HARD_REGISTER_P (x))
+      && !(REG_P (y) && HARD_REGISTER_P (y)))
     try_int = false;
   /* Not possible if the values are inherently not adjacent.  */
   else if (GET_CODE (x) == CONCAT || GET_CODE (y) == CONCAT)
@@ -10246,9 +10252,14 @@ expand_expr_real_2 (sepops ops, rtx target, machine_mode tmode,
 	    break;
 	  }
 
-      /* Move the real (op0) and imaginary (op1) parts to their location.  */
-      write_complex_part (target, op0, REAL_P, true);
-      write_complex_part (target, op1, IMAG_P, false);
+      if ((op0 == op1) && (GET_CODE (op0) == CONST_VECTOR))
+	write_complex_part (target, op0, BOTH_P, false);
+      else
+	{
+	  /* Move the real (op0) and imaginary (op1) parts to their location.  */
+	  write_complex_part (target, op0, REAL_P, true);
+	  write_complex_part (target, op1, IMAG_P, false);
+	}
 
       return target;
 
@@ -11001,6 +11012,51 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode,
 
 	  return original_target;
 	}
+      else if (original_target && (GET_CODE (original_target) == REG)
+	       &&
+	       ((GET_MODE_CLASS (GET_MODE (original_target)) ==
+		 MODE_COMPLEX_INT)
+		|| (GET_MODE_CLASS (GET_MODE (original_target)) ==
+		    MODE_COMPLEX_FLOAT)))
+	{
+	  mode = TYPE_MODE (TREE_TYPE (exp));
+
+	  /* Move both parts at the same time if possible */
+	  if (TREE_COMPLEX_BOTH_PARTS (exp) != NULL)
+	    {
+	      op0 =
+		expand_expr (TREE_COMPLEX_BOTH_PARTS (exp), original_target,
+			     mode, EXPAND_NORMAL);
+	      write_complex_part (original_target, op0, BOTH_P, false);
+	    }
+	  else
+	    {
+	      mode = TYPE_MODE (TREE_TYPE (TREE_TYPE (exp)));
+
+	      rtx rtarg = gen_reg_rtx (mode);
+	      rtx itarg = gen_reg_rtx (mode);
+	      op0 =
+		expand_expr (TREE_REALPART (exp), rtarg, mode, EXPAND_NORMAL);
+	      op1 =
+		expand_expr (TREE_IMAGPART (exp), itarg, mode, EXPAND_NORMAL);
+
+	      write_complex_part (original_target, op0, REAL_P, false);
+	      write_complex_part (original_target, op1, IMAG_P, false);
+
+	      return original_target;
+	    }
+	}
+      /* TODO use a finer grain approach than just size of 2 words */
+      else if ((TREE_COMPLEX_BOTH_PARTS (exp) != NULL)
+	       && (known_le (GET_MODE_BITSIZE (mode), 2 * BITS_PER_WORD)))
+	{
+	  op0 =
+	    expand_expr (TREE_COMPLEX_BOTH_PARTS (exp), original_target, mode,
+			 EXPAND_NORMAL);
+	  rtx tmp = gen_reg_rtx (mode);
+	  write_complex_part (tmp, op0, BOTH_P, false);
+	  return tmp;
+	}
 
       /* fall through */
 
@@ -13347,6 +13403,10 @@ const_vector_from_tree (tree exp)
       else if (TREE_CODE (elt) == FIXED_CST)
 	builder.quick_push (CONST_FIXED_FROM_FIXED_VALUE
 			    (TREE_FIXED_CST (elt), inner));
+      else if (TREE_CODE (elt) == COMPLEX_CST)
+	builder.quick_push (expand_expr
+			    (TREE_COMPLEX_BOTH_PARTS (elt), NULL_RTX, mode,
+			     EXPAND_NORMAL));
       else
 	builder.quick_push (immed_wide_int_const (wi::to_poly_wide (elt),
 						  inner));
diff --git a/gcc/machmode.h b/gcc/machmode.h
index a22df60dc20..b1937eafdc3 100644
--- a/gcc/machmode.h
+++ b/gcc/machmode.h
@@ -119,6 +119,12 @@ extern const unsigned char mode_class[NUM_MACHINE_MODES];
    || GET_MODE_CLASS (MODE) == MODE_COMPLEX_FLOAT \
    || GET_MODE_CLASS (MODE) == MODE_VECTOR_FLOAT)
 
+#define COMPLEX_INT_MODE_P(MODE) \
+   (GET_MODE_CLASS (MODE) == MODE_COMPLEX_INT)
+
+#define COMPLEX_FLOAT_MODE_P(MODE) \
+  (GET_MODE_CLASS (MODE) == MODE_COMPLEX_FLOAT)
+
 /* Nonzero if MODE is a complex mode.  */
 #define COMPLEX_MODE_P(MODE)			\
   (GET_MODE_CLASS (MODE) == MODE_COMPLEX_INT	\
diff --git a/gcc/optabs-libfuncs.cc b/gcc/optabs-libfuncs.cc
index f1abe6916d3..fe390a592eb 100644
--- a/gcc/optabs-libfuncs.cc
+++ b/gcc/optabs-libfuncs.cc
@@ -190,19 +190,34 @@ gen_int_libfunc (optab optable, const char *opname, char suffix,
   int maxsize = 2 * BITS_PER_WORD;
   int minsize = BITS_PER_WORD;
   scalar_int_mode int_mode;
+  complex_mode cplx_int_mode;
+  int bitsize;
+  bool cplx = false;
 
-  if (!is_int_mode (mode, &int_mode))
+  if (is_int_mode (mode, &int_mode))
+    bitsize = GET_MODE_BITSIZE (int_mode);
+  else if (is_complex_int_mode (mode, &cplx_int_mode))
+  {
+    cplx = true;
+    bitsize = GET_MODE_BITSIZE (cplx_int_mode);
+  }
+  else
     return;
+
   if (maxsize < LONG_LONG_TYPE_SIZE)
     maxsize = LONG_LONG_TYPE_SIZE;
   if (minsize > INT_TYPE_SIZE
       && (trapv_binoptab_p (optable)
 	  || trapv_unoptab_p (optable)))
     minsize = INT_TYPE_SIZE;
-  if (GET_MODE_BITSIZE (int_mode) < minsize
-      || GET_MODE_BITSIZE (int_mode) > maxsize)
+
+  if (bitsize < minsize || bitsize > maxsize)
     return;
-  gen_libfunc (optable, opname, suffix, int_mode);
+
+  if (GET_MODE_CLASS (mode) == MODE_INT)
+    gen_libfunc (optable, opname, suffix, int_mode);
+  else if (cplx)
+    gen_libfunc (optable, opname, suffix, cplx_int_mode);
 }
 
 /* Like gen_libfunc, but verify that FP and set decimal prefix if needed.  */
@@ -280,9 +295,11 @@ void
 gen_intv_fp_libfunc (optab optable, const char *name, char suffix,
 		     machine_mode mode)
 {
-  if (DECIMAL_FLOAT_MODE_P (mode) || GET_MODE_CLASS (mode) == MODE_FLOAT)
+  if (DECIMAL_FLOAT_MODE_P (mode) || GET_MODE_CLASS (mode) == MODE_FLOAT
+      || GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT)
     gen_fp_libfunc (optable, name, suffix, mode);
-  if (GET_MODE_CLASS (mode) == MODE_INT)
+  if (GET_MODE_CLASS (mode) == MODE_INT
+      || GET_MODE_CLASS (mode) == MODE_COMPLEX_INT)
     {
       int len = strlen (name);
       char *v_name = XALLOCAVEC (char, len + 2);
diff --git a/gcc/real.h b/gcc/real.h
index 9ed6c372b14..53585418e68 100644
--- a/gcc/real.h
+++ b/gcc/real.h
@@ -189,7 +189,8 @@ extern const struct real_format *
 			: (gcc_unreachable (), 0)])
 
 #define FLOAT_MODE_FORMAT(MODE) \
-  (REAL_MODE_FORMAT (as_a <scalar_float_mode> (GET_MODE_INNER (MODE))))
+  (REAL_MODE_FORMAT (as_a <scalar_float_mode> \
+    (GET_MODE_INNER ((COMPLEX_FLOAT_MODE_P (MODE)) ? (GET_MODE_INNER (MODE)) : (MODE)))))
 
 /* The following macro determines whether the floating point format is
    composite, i.e. may contain non-consecutive mantissa bits, in which
diff --git a/gcc/recog.cc b/gcc/recog.cc
index 37432087812..687fe2b1b8a 100644
--- a/gcc/recog.cc
+++ b/gcc/recog.cc
@@ -1441,6 +1441,7 @@ general_operand (rtx op, machine_mode mode)
      if the caller wants something floating.  */
   if (GET_MODE (op) == VOIDmode && mode != VOIDmode
       && GET_MODE_CLASS (mode) != MODE_INT
+      && GET_MODE_CLASS (mode) != MODE_COMPLEX_INT
       && GET_MODE_CLASS (mode) != MODE_PARTIAL_INT)
     return false;
 
-- 
2.17.1






  parent reply	other threads:[~2023-07-17  9:03 UTC|newest]

Thread overview: 24+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-07-17  9:02 [PATCH 0/9] Native complex operations Sylvain Noiry
2023-07-17  9:02 ` [PATCH 1/9] Native complex operations: Conditional lowering Sylvain Noiry
2023-07-17  9:02 ` [PATCH 2/9] Native complex operations: Move functions to hooks Sylvain Noiry
2023-07-17  9:02 ` [PATCH 3/9] Native complex operations: Add gen_rtx_complex hook Sylvain Noiry
2023-07-17  9:02 ` Sylvain Noiry [this message]
2023-07-17  9:02 ` [PATCH 5/9] Native complex operations: Add the conjugate op in optabs Sylvain Noiry
2023-07-17  9:02 ` [PATCH 6/9] Native complex operations: Update how complex rotations are handled Sylvain Noiry
2023-07-17  9:02 ` [PATCH 7/9] Native complex operations: Vectorization of native complex operations Sylvain Noiry
2023-07-17  9:02 ` [PATCH 8/9] Native complex operations: Add explicit vector of complex Sylvain Noiry
2023-07-17  9:02 ` [PATCH 9/9] Native complex operation: Experimental support in x86 backend Sylvain Noiry
2023-09-12 10:07   ` [PATCH v2 0/11] Native complex operations Sylvain Noiry
2023-09-12 10:07     ` [PATCH v2 01/11] Native complex ops : Conditional lowering Sylvain Noiry
2023-09-12 10:07     ` [PATCH v2 02/11] Native complex ops: Move functions to hooks Sylvain Noiry
2023-09-12 10:07     ` [PATCH v2 03/11] Native complex ops: Add gen_rtx_complex hook Sylvain Noiry
2023-09-12 10:07     ` [PATCH v2 04/11] Native complex ops: Allow native complex regs and ops in rtl Sylvain Noiry
2023-09-12 10:07     ` [PATCH v2 05/11] Native complex ops: Add the conjugate op in optabs Sylvain Noiry
2023-09-12 10:07     ` [PATCH v2 06/11] Native complex ops: Update how complex rotations are handled Sylvain Noiry
2023-09-12 10:07     ` [PATCH v2 07/11] Native complex ops: Vectorization of native complex operations Sylvain Noiry
2023-09-12 10:07     ` [PATCH v2 08/11] Native complex ops: Add explicit vector of complex Sylvain Noiry
2023-09-12 17:25       ` Joseph Myers
2023-09-13  6:48         ` Richard Biener
2023-09-12 10:07     ` [PATCH v2 09/11] Native complex ops: remove useless special cases Sylvain Noiry
2023-09-12 10:07     ` [PATCH v2 10/11] Native complex ops: Add a fast complex multiplication pattern Sylvain Noiry
2023-09-12 10:07     ` [PATCH v2 11/11] Native complex ops: Experimental support in x86 backend Sylvain Noiry

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20230717090250.4645-5-snoiry@kalrayinc.com \
    --to=snoiry@kalrayinc.com \
    --cc=gcc-patches@gcc.gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).