public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: Richard Sandiford <richard.sandiford@arm.com>
To: jlaw@ventanamicro.com, vmakarov@redhat.com, gcc-patches@gcc.gnu.org
Cc: Richard Sandiford <richard.sandiford@arm.com>
Subject: [PATCH 2/5] recog: Handle register filters
Date: Sun, 12 Nov 2023 14:52:26 +0000	[thread overview]
Message-ID: <20231112145229.2924713-3-richard.sandiford@arm.com> (raw)
In-Reply-To: <20231112145229.2924713-1-richard.sandiford@arm.com>

The main (but simplest) part of this patch makes constrain_operands
take register filters into account.

The rest of the patch adds register filter information to
operand_alternative.  Generally, if two register constraints
have different register filters, it's better if they're in separate
alternatives.  However, the syntax doesn't enforce that, and we can't
assert it due to inline asms.  So it's a choice between (a) adding
code to enforce consistent filters or (b) dealing with mixes of filters
in a conservatively correct way (in the sense of not allowing invalid
operands).  The latter seems much easier.

The patch therefore adds a mask of the filters that apply
to at least one constraint in a given operand alternative.
A register is OK if it passes all of the filters in the mask.

gcc/
	* recog.h (operand_alternative): Add a register_filters field.
	(alternative_register_filters): New function.
	* recog.cc (preprocess_constraints): Calculate the filters field.
	(constrain_operands): Check register filters.
---
 gcc/recog.cc | 14 ++++++++++++--
 gcc/recog.h  | 24 ++++++++++++++++++++++--
 2 files changed, 34 insertions(+), 4 deletions(-)

diff --git a/gcc/recog.cc b/gcc/recog.cc
index 3bd2d73c259..eaab79c25d7 100644
--- a/gcc/recog.cc
+++ b/gcc/recog.cc
@@ -2857,6 +2857,7 @@ preprocess_constraints (int n_operands, int n_alternatives,
       for (j = 0; j < n_alternatives; j++, op_alt += n_operands)
 	{
 	  op_alt[i].cl = NO_REGS;
+	  op_alt[i].register_filters = 0;
 	  op_alt[i].constraint = p;
 	  op_alt[i].matches = -1;
 	  op_alt[i].matched = -1;
@@ -2919,7 +2920,12 @@ preprocess_constraints (int n_operands, int n_alternatives,
 		    case CT_REGISTER:
 		      cl = reg_class_for_constraint (cn);
 		      if (cl != NO_REGS)
-			op_alt[i].cl = reg_class_subunion[op_alt[i].cl][cl];
+			{
+			  op_alt[i].cl = reg_class_subunion[op_alt[i].cl][cl];
+			  auto filter_id = get_register_filter_id (cn);
+			  if (filter_id >= 0)
+			    op_alt[i].register_filters |= 1U << filter_id;
+			}
 		      break;
 
 		    case CT_CONST_INT:
@@ -3219,13 +3225,17 @@ constrain_operands (int strict, alternative_mask alternatives)
 		  enum reg_class cl = reg_class_for_constraint (cn);
 		  if (cl != NO_REGS)
 		    {
+		      auto *filter = get_register_filter (cn);
 		      if (strict < 0
 			  || (strict == 0
 			      && REG_P (op)
 			      && REGNO (op) >= FIRST_PSEUDO_REGISTER)
 			  || (strict == 0 && GET_CODE (op) == SCRATCH)
 			  || (REG_P (op)
-			      && reg_fits_class_p (op, cl, offset, mode)))
+			      && reg_fits_class_p (op, cl, offset, mode)
+			      && (!filter
+				  || TEST_HARD_REG_BIT (*filter,
+							REGNO (op) + offset))))
 			win = true;
 		    }
 
diff --git a/gcc/recog.h b/gcc/recog.h
index c6ef619c5dd..5c801e7bb81 100644
--- a/gcc/recog.h
+++ b/gcc/recog.h
@@ -42,6 +42,7 @@ enum op_type {
   OP_INOUT
 };
 
+#ifndef GENERATOR_FILE
 struct operand_alternative
 {
   /* Pointer to the beginning of the constraint string for this alternative,
@@ -62,6 +63,11 @@ struct operand_alternative
      matches this one.  */
   int matched : 8;
 
+  /* Bit ID is set if the constraint string includes a register constraint with
+     register filter ID.  Use test_register_filters (REGISTER_FILTERS, REGNO)
+     to test whether REGNO is a valid start register for the operand.  */
+  unsigned int register_filters : MAX (NUM_REGISTER_FILTERS, 1);
+
   /* Nonzero if '&' was found in the constraint string.  */
   unsigned int earlyclobber : 1;
   /* Nonzero if TARGET_MEM_CONSTRAINT was found in the constraint
@@ -72,8 +78,6 @@ struct operand_alternative
   /* Nonzero if 'X' was found in the constraint string, or if the constraint
      string for this alternative was empty.  */
   unsigned int anything_ok : 1;
-
-  unsigned int unused : 12;
 };
 
 /* Return the class for operand I of alternative ALT, taking matching
@@ -85,6 +89,18 @@ alternative_class (const operand_alternative *alt, int i)
   return alt[i].matches >= 0 ? alt[alt[i].matches].cl : alt[i].cl;
 }
 
+/* Return the mask of register filters that should be applied to operand I
+   of alternative ALT, taking matching constraints into account.  */
+
+inline unsigned int
+alternative_register_filters (const operand_alternative *alt, int i)
+{
+  return (alt[i].matches >= 0
+	  ? alt[alt[i].matches].register_filters
+	  : alt[i].register_filters);
+}
+#endif
+
 /* A class for substituting one rtx for another within an instruction,
    or for recursively simplifying the instruction as-is.  Derived classes
    can record or filter certain decisions.  */
@@ -242,9 +258,11 @@ extern void extract_insn (rtx_insn *);
 extern void extract_constrain_insn (rtx_insn *insn);
 extern void extract_constrain_insn_cached (rtx_insn *);
 extern void extract_insn_cached (rtx_insn *);
+#ifndef GENERATOR_FILE
 extern void preprocess_constraints (int, int, const char **,
 				    operand_alternative *, rtx **);
 extern const operand_alternative *preprocess_insn_constraints (unsigned int);
+#endif
 extern void preprocess_constraints (rtx_insn *);
 extern rtx_insn *peep2_next_insn (int);
 extern bool peep2_regno_dead_p (int, int);
@@ -380,6 +398,7 @@ struct recog_data_d
 
 extern struct recog_data_d recog_data;
 
+#ifndef GENERATOR_FILE
 extern const operand_alternative *recog_op_alt;
 
 /* Return a pointer to an array in which index OP describes the constraints
@@ -393,6 +412,7 @@ which_op_alt ()
 				 recog_data.n_alternatives - 1));
   return &recog_op_alt[which_alternative * recog_data.n_operands];
 }
+#endif
 
 /* A table defined in insn-output.cc that give information about
    each insn-code value.  */
-- 
2.25.1


  parent reply	other threads:[~2023-11-12 14:52 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-11-12 14:52 [PATCH 0/5] Add support for operand-specific alignment requirements Richard Sandiford
2023-11-12 14:52 ` [PATCH 1/5] Add register filter operand to define_register_constraint Richard Sandiford
2023-11-19 21:49   ` Jeff Law
2023-11-12 14:52 ` Richard Sandiford [this message]
2023-11-19 21:51   ` [PATCH 2/5] recog: Handle register filters Jeff Law
2023-11-12 14:52 ` [PATCH 3/5] lra: " Richard Sandiford
2023-11-12 14:52 ` [PATCH 4/5] ira: " Richard Sandiford
2023-11-12 14:52 ` [PATCH 5/5] Add an aligned_register_operand predicate Richard Sandiford
2023-11-19 21:52   ` Jeff Law
2023-11-14  0:01 ` [PATCH 0/5] Add support for operand-specific alignment requirements Vladimir Makarov

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=20231112145229.2924713-3-richard.sandiford@arm.com \
    --to=richard.sandiford@arm.com \
    --cc=gcc-patches@gcc.gnu.org \
    --cc=jlaw@ventanamicro.com \
    --cc=vmakarov@redhat.com \
    /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).