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];