This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

regrename: don't overflow insn_rr_info


This one is a fix for something that could currently only affect c6x, but I have code that exposes it on i386.

When optionally gathering operand info in regrename, we can overflow the array in certain situations. This can occur when we have a situation where a value is constructed in multiple small registers and then accessed as a larger one (CDImode in the testcase I have). In that case we enter the "superset" path, which fails the involved chains, but the smaller pieces still all get seen by record_operand_use, and there may be more of them than MAX_REGS_PER_ADDRESS.

The following fixes it. Bootstrapped and tested with -frename-registers enabled at -O1 on x86_64-linux. Ok?


Bernd
	* regrename.c (record_operand_use): Keep track of failed operands
	and stop appending if we see any.
	* regrename.h (struct operand_rr_info): Add a failed field and shrink
	n_chains to short.

Index: gcc/regrename.c
===================================================================
--- gcc/regrename.c	(revision 229049)
+++ gcc/regrename.c	(working copy)
@@ -204,8 +204,13 @@ mark_conflict (struct du_head *chains, u
 static void
 record_operand_use (struct du_head *head, struct du_chain *this_du)
 {
-  if (cur_operand == NULL)
+  if (cur_operand == NULL || cur_operand->failed)
     return;
+  if (head->cannot_rename)
+    {
+      cur_operand->failed = true;
+      return;
+    }
   gcc_assert (cur_operand->n_chains < MAX_REGS_PER_ADDRESS);
   cur_operand->heads[cur_operand->n_chains] = head;
   cur_operand->chains[cur_operand->n_chains++] = this_du;
Index: gcc/regrename.h
===================================================================
--- gcc/regrename.h	(revision 229049)
+++ gcc/regrename.h	(working copy)
@@ -68,7 +71,8 @@ struct du_chain
 struct operand_rr_info
 {
   /* The number of chains recorded for this operand.  */
-  int n_chains;
+  short n_chains;
+  bool failed;
   /* Holds either the chain for the operand itself, or for the registers in
      a memory operand.  */
   struct du_chain *chains[MAX_REGS_PER_ADDRESS];

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]