public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: Richard Sandiford <richard.sandiford@linaro.org>
To: gcc-patches@gcc.gnu.org
Subject: Use extract_bit_field_as_subreg for vectors
Date: Fri, 03 Nov 2017 16:37:00 -0000	[thread overview]
Message-ID: <87lgjnnwrr.fsf@linaro.org> (raw)

extract_bit_field_1 tries to use vec_extract to extract part of a
vector.  However, if that pattern isn't defined or if the operands
aren't suitable, another good approach is to try a direct subreg
reference.  This is particularly useful for multi-vector modes on
SVE (e.g. when extracting one vector from an LD2 result).

The function would go on to try the same thing anyway, but only
if there is an integer mode with the same size as the vector mode,
which isn't true for SVE modes (and doesn't seem a good thing to
require in general).  Even when there is an integer mode, doing the
operation on the original modes avoids some unnecessary bitcasting.

Tested on aarch64-linux-gnu, x86_64-linux-gnu and powerpc64-linux-gnu.
OK to install?

Richard


2017-11-03  Richard Sandiford  <richard.sandiford@linaro.org>
	    Alan Hayward  <alan.hayward@arm.com>
	    David Sherwood  <david.sherwood@arm.com>

gcc/
	* expmed.c (extract_bit_field_1): For vector extracts,
	fall back to extract_bit_field_as_subreg if vec_extract
	isn't available.

Index: gcc/expmed.c
===================================================================
--- gcc/expmed.c	2017-11-03 12:15:45.018033355 +0000
+++ gcc/expmed.c	2017-11-03 12:23:33.286459352 +0000
@@ -1708,33 +1708,49 @@ extract_bit_field_1 (rtx str_rtx, poly_u
     }
 
   /* Use vec_extract patterns for extracting parts of vectors whenever
-     available.  */
+     available.  If that fails, see whether the current modes and bitregion
+     give a natural subreg.  */
   machine_mode outermode = GET_MODE (op0);
-  scalar_mode innermode = GET_MODE_INNER (outermode);
-  poly_uint64 pos;
-  if (VECTOR_MODE_P (outermode)
-      && !MEM_P (op0)
-      && (convert_optab_handler (vec_extract_optab, outermode, innermode)
-	  != CODE_FOR_nothing)
-      && must_eq (bitsize, GET_MODE_BITSIZE (innermode))
-      && multiple_p (bitnum, GET_MODE_BITSIZE (innermode), &pos))
+  if (VECTOR_MODE_P (outermode) && !MEM_P (op0))
     {
-      struct expand_operand ops[3];
+      scalar_mode innermode = GET_MODE_INNER (outermode);
       enum insn_code icode
 	= convert_optab_handler (vec_extract_optab, outermode, innermode);
+      poly_uint64 pos;
+      if (icode != CODE_FOR_nothing
+	  && must_eq (bitsize, GET_MODE_BITSIZE (innermode))
+	  && multiple_p (bitnum, GET_MODE_BITSIZE (innermode), &pos))
+	{
+	  struct expand_operand ops[3];
+
+	  create_output_operand (&ops[0], target, innermode);
+	  ops[0].target = 1;
+	  create_input_operand (&ops[1], op0, outermode);
+	  create_integer_operand (&ops[2], pos);
+	  if (maybe_expand_insn (icode, 3, ops))
+	    {
+	      if (alt_rtl && ops[0].target)
+		*alt_rtl = target;
+	      target = ops[0].value;
+	      if (GET_MODE (target) != mode)
+		return gen_lowpart (tmode, target);
+	      return target;
+	    }
+	}
+      /* Using subregs is useful if we're extracting the least-significant
+	 vector element, or if we're extracting one register vector from
+	 a multi-register vector.  extract_bit_field_as_subreg checks
+	 for valid bitsize and bitnum, so we don't need to do that here.
 
-      create_output_operand (&ops[0], target, innermode);
-      ops[0].target = 1;
-      create_input_operand (&ops[1], op0, outermode);
-      create_integer_operand (&ops[2], pos);
-      if (maybe_expand_insn (icode, 3, ops))
+	 The mode check makes sure that we're extracting either
+	 a single element or a subvector with the same element type.
+	 If the modes aren't such a natural fit, fall through and
+	 bitcast to integers first.  */
+      if (GET_MODE_INNER (mode) == innermode)
 	{
-	  if (alt_rtl && ops[0].target)
-	    *alt_rtl = target;
-	  target = ops[0].value;
-      	  if (GET_MODE (target) != mode)
-	    return gen_lowpart (tmode, target);
-	  return target;
+	  rtx sub = extract_bit_field_as_subreg (mode, op0, bitsize, bitnum);
+	  if (sub)
+	    return sub;
 	}
     }
 

             reply	other threads:[~2017-11-03 16:37 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-11-03 16:37 Richard Sandiford [this message]
2017-11-19 23:57 ` Jeff Law

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=87lgjnnwrr.fsf@linaro.org \
    --to=richard.sandiford@linaro.org \
    --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).