public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [RFC][PATCH] Preferred rename register in regrename pass
@ 2015-09-17 14:40 Robert Suchanek
  2015-09-17 17:11 ` Jeff Law
  2015-09-18 15:29 ` Bernd Schmidt
  0 siblings, 2 replies; 21+ messages in thread
From: Robert Suchanek @ 2015-09-17 14:40 UTC (permalink / raw)
  To: gcc-patches

Hi,

We came across a situation for MIPS64 where moves for sign-extension were
not converted into a nop because of IRA spilled some of the allocnos and
assigned different hard register for the output operand in the move.
LRA is not fixing this up as most likely the move was not introduced by
the LRA itself.  I found it hard to fix this in LRA and looked at
an alternative solution where regrename pass appeared to be the best candidate.

The patch below introduces a notion of a preferred rename register and attempts
to use the output register for an input register iff the input register dies
in an instruction.  The preferred register is validated and in the case it fails
to be validated, it falls back to the old technique of finding the best rename register.
Of course, it has slightly limited scope of use as it's not enabled be default,
however, when targeting performance one is likely to enable it via
-funroll-loops or -fpeel-loops.

I did some experiments with -funroll-loops on x86_64-unknown-linux-gnu and
the code size improved almost 0.4% on average case.  I haven't done an extensive
performance testing but it appeared SPEC2006 had some minor improvement on average,
which could be real improvement or just noise.
On MIPS64 with -funroll-loops, there were a number of cases where the unnecessary
moves turned into a nop in CSiBE.  MIPS32 also marginally improved but to
a lower degree.

The patch successfully passed x86_64-unknown-linux-gnu, mips-mti-linux-gnu and
mips-img-linux-gnu.

I'm not sure if this is something that should be enabled by default for everyone
or a target hook should be added.  Any other comments/suggestions?

Regards,
Robert

gcc/
	* regrename.c (find_preferred_rename_reg): New function.
	(record_operand_use): Remove assertion.  Allocate or resize heads and
	chains vectors, if necessary.
	(find_best_rename_reg): Use the new function and validate chosen
	register.
	(build_def_use): Don't allocate and initialize space of size 0.
	(regrename_finish): Free heads and chains vectors.
	(regrename_optimize): Pass true to initializing function.
	* regrename.h (struct operand_rr_info): Replace arrays of heads and
	chains with vectors.
---
 gcc/regrename.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++++++++----
 gcc/regrename.h |  4 +--
 2 files changed, 82 insertions(+), 8 deletions(-)

diff --git a/gcc/regrename.c b/gcc/regrename.c
index c328c1b..90fee98 100644
--- a/gcc/regrename.c
+++ b/gcc/regrename.c
@@ -174,6 +174,51 @@ dump_def_use_chain (int from)
     }
 }
 
+/* Return a preferred rename register for HEAD.  */
+
+static int
+find_preferred_rename_reg (du_head_p head)
+{
+  struct du_chain *this_du;
+  int preferred_reg = -1;
+
+  for (this_du = head->first; this_du; this_du = this_du->next_use)
+    {
+      rtx note;
+      insn_rr_info *p;
+
+      /* The preferred rename register is an output register iff an input
+	 register dies in an instruction but the candidate must be validated by
+	 check_new_reg_p.  */
+      for (note = REG_NOTES (this_du->insn); note; note = XEXP (note, 1))
+	if (insn_rr.exists()
+	    && REG_NOTE_KIND (note) == REG_DEAD
+	    && REGNO (XEXP (note, 0)) == head->regno
+	    && (p = &insn_rr[INSN_UID (this_du->insn)])
+	    && p->op_info)
+	  {
+	    int i;
+	    for (i = 0; i < p->op_info->n_chains; i++)
+	      {
+		struct du_head *next_head = p->op_info->heads[i];
+		if (head != next_head)
+		  {
+		    preferred_reg = next_head->regno;
+		    if (dump_file)
+		      fprintf (dump_file,
+			       "Chain %s (%d) has preferred rename register"
+			       " %s for insn %d [%s]\n",
+			       reg_names[head->regno], head->id,
+			       reg_names[preferred_reg],
+			       INSN_UID (this_du->insn),
+			       reg_class_names[this_du->cl]);
+		  }
+	      }
+	  }
+    }
+  return preferred_reg;
+}
+
 static void
 free_chain_data (void)
 {
@@ -206,7 +251,16 @@ record_operand_use (struct du_head *head, struct du_chain *this_du)
 {
   if (cur_operand == NULL)
     return;
-  gcc_assert (cur_operand->n_chains < MAX_REGS_PER_ADDRESS);
+
+  if (!cur_operand->heads.exists ())
+    cur_operand->heads.create (0);
+  if (!cur_operand->chains.exists ())
+    cur_operand->chains.create (0);
+  if (cur_operand->heads.length () <= (unsigned) cur_operand->n_chains)
+    cur_operand->heads.safe_grow_cleared (cur_operand->n_chains + 1);
+  if (cur_operand->chains.length () <= (unsigned) cur_operand->n_chains)
+    cur_operand->chains.safe_grow_cleared (cur_operand->n_chains + 1);
+
   cur_operand->heads[cur_operand->n_chains] = head;
   cur_operand->chains[cur_operand->n_chains++] = this_du;
 }
@@ -355,6 +409,7 @@ find_rename_reg (du_head_p this_head, enum reg_class super_class,
   enum reg_class preferred_class;
   int pass;
   int best_new_reg = old_reg;
+  int preferred_reg = -1;
 
   /* Further narrow the set of registers we can use for renaming.
      If the chain needs a call-saved register, mark the call-used
@@ -370,6 +425,11 @@ find_rename_reg (du_head_p this_head, enum reg_class super_class,
   preferred_class
     = (enum reg_class) targetm.preferred_rename_class (super_class);
 
+  /* Try to find a preferred rename register for THIS_HEAD.  */
+  if ((preferred_reg = find_preferred_rename_reg (this_head)) != -1
+      && check_new_reg_p (old_reg, preferred_reg, this_head, *unavailable))
+    return preferred_reg;
+
   /* If PREFERRED_CLASS is not NO_REGS, we iterate in the first pass
      over registers that belong to PREFERRED_CLASS and try to find the
      best register within the class.  If that failed, we iterate in
@@ -1588,10 +1648,14 @@ build_def_use (basic_block bb)
 	  if (insn_rr.exists ())
 	    {
 	      insn_info = &insn_rr[INSN_UID (insn)];
-	      insn_info->op_info = XOBNEWVEC (&rename_obstack, operand_rr_info,
-					      recog_data.n_operands);
-	      memset (insn_info->op_info, 0,
-		      sizeof (operand_rr_info) * recog_data.n_operands);
+	      if (recog_data.n_operands > 0)
+		{
+		  insn_info->op_info = XOBNEWVEC (&rename_obstack,
+						  operand_rr_info,
+						  recog_data.n_operands);
+		  memset (insn_info->op_info, 0,
+			  sizeof (operand_rr_info) * recog_data.n_operands);
+		}
 	    }
 
 	  /* Simplify the code below by promoting OP_OUT to OP_INOUT in
@@ -1811,6 +1875,16 @@ regrename_init (bool insn_info)
 void
 regrename_finish (void)
 {
+  int i;
+  struct insn_rr_info *item;
+
+  FOR_EACH_VEC_ELT (insn_rr, i, item)
+    if (item->op_info)
+      {
+	item->op_info->heads.release ();
+	item->op_info->chains.release ();
+      }
+
   insn_rr.release ();
   free_chain_data ();
   obstack_free (&rename_obstack, NULL);
@@ -1826,7 +1900,7 @@ regrename_optimize (void)
   df_analyze ();
   df_set_flags (DF_DEFER_INSN_RESCAN);
 
-  regrename_init (false);
+  regrename_init (true);
 
   regrename_analyze (NULL);
 
diff --git a/gcc/regrename.h b/gcc/regrename.h
index bbe156d..2e3bc20 100644
--- a/gcc/regrename.h
+++ b/gcc/regrename.h
@@ -71,8 +71,8 @@ struct operand_rr_info
   int n_chains;
   /* Holds either the chain for the operand itself, or for the registers in
      a memory operand.  */
-  struct du_chain *chains[MAX_REGS_PER_ADDRESS];
-  struct du_head *heads[MAX_REGS_PER_ADDRESS];
+  vec<struct du_chain *> chains;
+  vec<struct du_head *> heads;
 };
 
 /* A struct to hold a vector of operand_rr_info structures describing the
-- 
2.4.5

^ permalink raw reply	[flat|nested] 21+ messages in thread

end of thread, other threads:[~2015-11-12 12:57 UTC | newest]

Thread overview: 21+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-09-17 14:40 [RFC][PATCH] Preferred rename register in regrename pass Robert Suchanek
2015-09-17 17:11 ` Jeff Law
2015-09-17 21:28   ` Eric Botcazou
2015-09-18 15:29 ` Bernd Schmidt
2015-10-09  7:10   ` Robert Suchanek
2015-10-09 11:06     ` Bernd Schmidt
2015-10-09 11:20       ` Robert Suchanek
2015-11-09 13:32       ` Robert Suchanek
2015-11-09 16:30         ` Bernd Schmidt
2015-11-09 17:01           ` Robert Suchanek
2015-11-10 11:21             ` Christophe Lyon
2015-11-10 11:41               ` Robert Suchanek
2015-11-10 16:22                 ` Christophe Lyon
2015-11-10 17:43                   ` James Greenhalgh
2015-11-10 22:33                     ` Robert Suchanek
2015-11-10 22:57                       ` Bernd Schmidt
2015-11-11  0:06                         ` Robert Suchanek
2015-11-11  8:50                         ` Robert Suchanek
2015-11-12  7:47                           ` Christophe Lyon
2015-11-12 12:57                             ` Robert Suchanek
2015-11-10 12:10         ` Bernd Schmidt

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