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 4/5] ira: Handle register filters
Date: Sun, 12 Nov 2023 14:52:28 +0000	[thread overview]
Message-ID: <20231112145229.2924713-5-richard.sandiford@arm.com> (raw)
In-Reply-To: <20231112145229.2924713-1-richard.sandiford@arm.com>

This patch makes IRA apply register filters when picking hard registers.
All the new code should be optimised away on targets that don't use
register filters.  On targets that do use them, the new register_filters
bitfield is expected to be only a handful of bits.

Information about register filters is recorded in process_bb_node_lives.
The information isn't really related to liveness, but it's a convenient
point because (a) we've already built the allocno structures and
(b) we've already extracted the insn and preprocessed the constraints.

gcc/
	* ira-int.h (ira_allocno): Add a register_filters field.
	(ALLOCNO_REGISTER_FILTERS): New macro.
	(ALLOCNO_SET_REGISTER_FILTERS): Likewise.
	* ira-build.cc (ira_create_allocno): Initialize register_filters.
	(create_cap_allocno): Propagate register_filters.
	(propagate_allocno_info): Likewise.
	(propagate_some_info_from_allocno): Likewise.
	* ira-lives.cc (process_register_constraint_filters): New function.
	(process_bb_node_lives): Use it to record register filter
	information.
	* ira-color.cc (assign_hard_reg): Check register filters.
	(improve_allocation, fast_allocation): Likewise.
---
 gcc/ira-build.cc |  8 +++++++
 gcc/ira-color.cc | 10 ++++++++
 gcc/ira-int.h    | 14 +++++++++++
 gcc/ira-lives.cc | 61 ++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 93 insertions(+)

diff --git a/gcc/ira-build.cc b/gcc/ira-build.cc
index 93e46033170..c715a834f12 100644
--- a/gcc/ira-build.cc
+++ b/gcc/ira-build.cc
@@ -498,6 +498,7 @@ ira_create_allocno (int regno, bool cap_p,
   ALLOCNO_NREFS (a) = 0;
   ALLOCNO_FREQ (a) = 0;
   ALLOCNO_MIGHT_CONFLICT_WITH_PARENT_P (a) = false;
+  ALLOCNO_SET_REGISTER_FILTERS (a, 0);
   ALLOCNO_HARD_REGNO (a) = -1;
   ALLOCNO_CALL_FREQ (a) = 0;
   ALLOCNO_CALLS_CROSSED_NUM (a) = 0;
@@ -902,6 +903,7 @@ create_cap_allocno (ira_allocno_t a)
   ALLOCNO_NREFS (cap) = ALLOCNO_NREFS (a);
   ALLOCNO_FREQ (cap) = ALLOCNO_FREQ (a);
   ALLOCNO_CALL_FREQ (cap) = ALLOCNO_CALL_FREQ (a);
+  ALLOCNO_SET_REGISTER_FILTERS (cap, ALLOCNO_REGISTER_FILTERS (a));
 
   merge_hard_reg_conflicts (a, cap, false);
 
@@ -2064,6 +2066,9 @@ propagate_allocno_info (void)
 	    ALLOCNO_BAD_SPILL_P (parent_a) = false;
 	  ALLOCNO_NREFS (parent_a) += ALLOCNO_NREFS (a);
 	  ALLOCNO_FREQ (parent_a) += ALLOCNO_FREQ (a);
+	  ALLOCNO_SET_REGISTER_FILTERS (parent_a,
+					ALLOCNO_REGISTER_FILTERS (parent_a)
+					| ALLOCNO_REGISTER_FILTERS (a));
 
 	  /* If A's allocation can differ from PARENT_A's, we can if necessary
 	     spill PARENT_A on entry to A's loop and restore it afterwards.
@@ -2465,6 +2470,9 @@ propagate_some_info_from_allocno (ira_allocno_t a, ira_allocno_t from_a)
   ALLOCNO_CROSSED_CALLS_ABIS (a) |= ALLOCNO_CROSSED_CALLS_ABIS (from_a);
   ALLOCNO_CROSSED_CALLS_CLOBBERED_REGS (a)
     |= ALLOCNO_CROSSED_CALLS_CLOBBERED_REGS (from_a);
+  ALLOCNO_SET_REGISTER_FILTERS (a,
+				ALLOCNO_REGISTER_FILTERS (from_a)
+				| ALLOCNO_REGISTER_FILTERS (a));
 
   ALLOCNO_EXCESS_PRESSURE_POINTS_NUM (a)
     += ALLOCNO_EXCESS_PRESSURE_POINTS_NUM (from_a);
diff --git a/gcc/ira-color.cc b/gcc/ira-color.cc
index f2e8ea34152..214a4f16d3c 100644
--- a/gcc/ira-color.cc
+++ b/gcc/ira-color.cc
@@ -2163,6 +2163,9 @@ assign_hard_reg (ira_allocno_t a, bool retry_p)
       if (! check_hard_reg_p (a, hard_regno,
 			      conflicting_regs, profitable_hard_regs))
 	continue;
+      if (NUM_REGISTER_FILTERS
+	  && !test_register_filters (ALLOCNO_REGISTER_FILTERS (a), hard_regno))
+	continue;
       cost = costs[i];
       full_cost = full_costs[i];
       if (!HONOR_REG_ALLOC_ORDER)
@@ -3205,6 +3208,9 @@ improve_allocation (void)
 	  if (! check_hard_reg_p (a, hregno,
 				  conflicting_regs, profitable_hard_regs))
 	    continue;
+	  if (NUM_REGISTER_FILTERS
+	      && !test_register_filters (ALLOCNO_REGISTER_FILTERS (a), hregno))
+	    continue;
 	  ira_assert (ira_class_hard_reg_index[aclass][hregno] == j);
 	  k = allocno_costs == NULL ? 0 : j;
 	  costs[hregno] = (allocno_costs == NULL
@@ -5275,6 +5281,10 @@ fast_allocation (void)
 	      || (TEST_HARD_REG_BIT
 		  (ira_prohibited_class_mode_regs[aclass][mode], hard_regno)))
 	    continue;
+	  if (NUM_REGISTER_FILTERS
+	      && !test_register_filters (ALLOCNO_REGISTER_FILTERS (a),
+					 hard_regno))
+	    continue;
 	  if (costs == NULL)
 	    {
 	      best_hard_regno = hard_regno;
diff --git a/gcc/ira-int.h b/gcc/ira-int.h
index 0685e1f4e8d..1c3548df4ea 100644
--- a/gcc/ira-int.h
+++ b/gcc/ira-int.h
@@ -328,6 +328,13 @@ struct ira_allocno
 
      This is only ever true for non-cap allocnos.  */
   unsigned int might_conflict_with_parent_p : 1;
+#ifndef NUM_REGISTER_FILTERS
+#error "insn-config.h not included"
+#elif NUM_REGISTER_FILTERS
+  /* The set of register filters applied to the allocno by operand
+     alternatives that accept class ACLASS.  */
+  unsigned int register_filters : NUM_REGISTER_FILTERS;
+#endif
   /* Accumulated usage references of the allocno.  Here and below,
      word 'accumulated' means info for given region and all nested
      subregions.  In this case, 'accumulated' means sum of references
@@ -432,6 +439,13 @@ struct ira_allocno
 #define ALLOCNO_FREQ(A) ((A)->freq)
 #define ALLOCNO_MIGHT_CONFLICT_WITH_PARENT_P(A) \
   ((A)->might_conflict_with_parent_p)
+#if NUM_REGISTER_FILTERS
+#define ALLOCNO_REGISTER_FILTERS(A) (A)->register_filters
+#define ALLOCNO_SET_REGISTER_FILTERS(A, X) ((A)->register_filters = (X))
+#else
+#define ALLOCNO_REGISTER_FILTERS(A) 0
+#define ALLOCNO_SET_REGISTER_FILTERS(A, X) ((void) (A), gcc_assert ((X) == 0))
+#endif
 #define ALLOCNO_HARD_REGNO(A) ((A)->hard_regno)
 #define ALLOCNO_CALL_FREQ(A) ((A)->call_freq)
 #define ALLOCNO_CALLS_CROSSED_NUM(A) ((A)->calls_crossed_num)
diff --git a/gcc/ira-lives.cc b/gcc/ira-lives.cc
index 81af5c06460..63f2314409f 100644
--- a/gcc/ira-lives.cc
+++ b/gcc/ira-lives.cc
@@ -1066,6 +1066,66 @@ process_single_reg_class_operands (bool in_p, int freq)
     }
 }
 
+/* Go through the operands of the extracted insn looking for operand
+   alternatives that apply a register filter.  Record any such filters
+   in the operand's allocno.  */
+static void
+process_register_constraint_filters ()
+{
+  for (int opno = 0; opno < recog_data.n_operands; ++opno)
+    {
+      rtx op = recog_data.operand[opno];
+      if (SUBREG_P (op))
+	op = SUBREG_REG (op);
+      if (REG_P (op) && !HARD_REGISTER_P (op))
+	{
+	  ira_allocno_t a = ira_curr_regno_allocno_map[REGNO (op)];
+	  for (int alt = 0; alt < recog_data.n_alternatives; alt++)
+	    {
+	      if (!TEST_BIT (preferred_alternatives, alt))
+		continue;
+
+	      auto *op_alt = &recog_op_alt[alt * recog_data.n_operands];
+	      auto cl = alternative_class (op_alt, opno);
+	      /* The two extremes are easy:
+
+		 - We should record the filter if CL matches the
+		   allocno class.
+
+		 - We should ignore the filter if CL and the allocno class
+		   are disjoint.  We'll either pick a different alternative
+		   or reload the operand.
+
+		 Things are trickier if the classes overlap.  However:
+
+		 - If the allocno class includes registers that are not
+		   in CL, some choices of hard register will need a reload
+		   anyway.  It isn't obvious that reloads due to filters
+		   are worse than reloads due to regnos being outside CL.
+
+		 - Conversely, if the allocno class is a subset of CL,
+		   any allocation will satisfy the class requirement.
+		   We should try to make sure it satisfies the filter
+		   requirement too.  This is useful if, for example,
+		   an allocno needs to be in "low" registers to satisfy
+		   some uses, and its allocno class is therefore those
+		   low registers, but the allocno is elsewhere allowed
+		   to be in any even-numbered register.  Picking an
+		   even-numbered low register satisfies both types of use.  */
+	      if (!ira_class_subset_p[ALLOCNO_CLASS (a)][cl])
+		continue;
+
+	      auto filters = alternative_register_filters (op_alt, opno);
+	      if (!filters)
+		continue;
+
+	      filters |= ALLOCNO_REGISTER_FILTERS (a);
+	      ALLOCNO_SET_REGISTER_FILTERS (a, filters);
+	    }
+	}
+    }
+}
+
 /* Look through the CALL_INSN_FUNCTION_USAGE of a call insn INSN, and see if
    we find a SET rtx that we can use to deduce that a register can be cheaply
    caller-saved.  Return such a register, or NULL_RTX if none is found.  */
@@ -1378,6 +1438,7 @@ process_bb_node_lives (ira_loop_tree_node_t loop_tree_node)
 	      }
 
 	  preferred_alternatives = ira_setup_alts (insn);
+	  process_register_constraint_filters ();
 	  process_single_reg_class_operands (false, freq);
 
 	  if (call_p)
-- 
2.25.1


  parent reply	other threads:[~2023-11-12 14:53 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 ` [PATCH 2/5] recog: Handle register filters Richard Sandiford
2023-11-19 21:51   ` Jeff Law
2023-11-12 14:52 ` [PATCH 3/5] lra: " Richard Sandiford
2023-11-12 14:52 ` Richard Sandiford [this message]
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-5-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).