Hi, Vladimir
Previous patch probably not completed.
The new patch will record lra_reg_info[i].offset as the offset from
eliminate register to the pseudo i
and keep updating when the stack has been changed.
Therefore, lra-assign could get the latest offset to identify the
pseudo content is equal or not.
gcc/lra-assigns.c | 6 ++++--
gcc/lra-eliminations.c | 12 ++++++++++--
gcc/lra-int.h | 2 ++
gcc/lra.c | 5 ++++-
4 files changed, 20 insertions(+), 5 deletions(-)
diff --git a/gcc/lra-assigns.c b/gcc/lra-assigns.c
index b204513..daf0aa9 100644
--- a/gcc/lra-assigns.c
+++ b/gcc/lra-assigns.c
@@ -448,7 +448,7 @@ find_hard_regno_for (int regno, int *cost, int
try_only_hard_regno)
int hr, conflict_hr, nregs;
enum machine_mode biggest_mode;
unsigned int k, conflict_regno;
- int val, biggest_nregs, nregs_diff;
+ int offset, val, biggest_nregs, nregs_diff;
enum reg_class rclass;
bitmap_iterator bi;
bool *rclass_intersect_p;
@@ -508,9 +508,11 @@ find_hard_regno_for (int regno, int *cost, int
try_only_hard_regno)
#endif
sparseset_clear_bit (conflict_reload_and_inheritance_pseudos, regno);
val = lra_reg_info[regno].val;
+ offset = lra_reg_info[regno].offset;
CLEAR_HARD_REG_SET (impossible_start_hard_regs);
EXECUTE_IF_SET_IN_SPARSESET (live_range_hard_reg_pseudos, conflict_regno)
- if (val == lra_reg_info[conflict_regno].val)
+ if ((val == lra_reg_info[conflict_regno].val)
+ && (offset == lra_reg_info[conflict_regno].offset))
{
conflict_hr = live_pseudos_reg_renumber[conflict_regno];
nregs = (hard_regno_nregs[conflict_hr]
diff --git a/gcc/lra-eliminations.c b/gcc/lra-eliminations.c
index 9df0bae..2d34b51 100644
--- a/gcc/lra-eliminations.c
+++ b/gcc/lra-eliminations.c
@@ -1046,6 +1046,7 @@ spill_pseudos (HARD_REG_SET set)
static void
update_reg_eliminate (bitmap insns_with_changed_offsets)
{
+ int i;
bool prev;
struct elim_table *ep, *ep1;
HARD_REG_SET temp_hard_reg_set;
@@ -1124,8 +1125,15 @@ update_reg_eliminate (bitmap insns_with_changed_offsets)
setup_elimination_map ();
for (ep = reg_eliminate; ep < ®_eliminate[NUM_ELIMINABLE_REGS]; ep++)
if (elimination_map[ep->from] == ep && ep->previous_offset != ep->offset)
- bitmap_ior_into (insns_with_changed_offsets,
- &lra_reg_info[ep->from].insn_bitmap);
+ {
+ bitmap_ior_into (insns_with_changed_offsets,
+ &lra_reg_info[ep->from].insn_bitmap);
+
+ /* Update offset when the eliminate offset have been changed. */
+ for (i = FIRST_PSEUDO_REGISTER; i < max_reg_num (); i++)
+ if (lra_reg_info[i].val - 1 == ep->from)
+ lra_reg_info[i].offset += (ep->offset - ep->previous_offset);
+ }
}
/* Initialize the table of hard registers to eliminate.
diff --git a/gcc/lra-int.h b/gcc/lra-int.h
index 98f2ff7..944cad1 100644
--- a/gcc/lra-int.h
+++ b/gcc/lra-int.h
@@ -116,6 +116,8 @@ struct lra_reg
/* Value holding by register. If the pseudos have the same value
they do not conflict. */
int val;
+ /* Offset from relative eliminate register to pesudo reg. */
+ int offset;
/* These members are set up in lra-lives.c and updated in
lra-coalesce.c. */
/* The biggest size mode in which each pseudo reg is referred in
diff --git a/gcc/lra.c b/gcc/lra.c
index 9df24b5..7a60281 100644
--- a/gcc/lra.c
+++ b/gcc/lra.c
@@ -194,7 +194,10 @@ lra_create_new_reg (enum machine_mode md_mode,
rtx original,
new_reg
= lra_create_new_reg_with_unique_value (md_mode, original, rclass, title);
if (original != NULL_RTX && REG_P (original))
- lra_reg_info[REGNO (new_reg)].val = lra_reg_info[REGNO (original)].val;
+ {
+ lra_reg_info[REGNO (new_reg)].val = lra_reg_info[REGNO (original)].val;
+ lra_reg_info[REGNO (new_reg)].offset = 0;
+ }
return new_reg;
}
Thanks for the comment :)
Shiva
2013/4/18 Shiva Chen <[email protected]>:
> Full test2.c.209r.reload is about 296kb and i can't send successfully.
> Is there another way to send the dump file?
>
> Shiva
>
> 2013/4/18 Shiva Chen <[email protected]>:
>> Hi, Vladimir
>>
>> attachment is the ira dump of the case
>>
>> Shiva
>>
>> 2013/4/17 Vladimir Makarov <[email protected]>:
>>> On 13-04-15 1:20 AM, shiva Chen wrote:
>>>>
>>>> HI,
>>>>
>>>> I'm trying to port a new 32bit target to GCC 4.8.0 with LRA enabled
>>>>
>>>> There is an error case which generates following RTL
>>>>
>>>>
>>>> (insn 536 267 643 3 (set (reg/f:SI 0 $r0 [477]) <== r477 assign to r0
>>>> (plus:SI (reg/f:SI 31 $sp)
>>>> (const_int 112 [0x70]))) test2.c:95 64 {*addsi3}
>>>> (nil))
>>>> (insn 643 536 537 3 (set (reg/f:SI 0 $r0 [565]) <== r565 assign to
>>>> r0, and corrupt the usage of r477
>>>> (reg/f:SI 31 $sp)) test2.c:95 44 {*movsi}
>>>> (nil))
>>>> (insn 537 643 538 3 (set (reg/v:SI 13 $r13 [orig:61 i14 ] [61])
>>>> (mem/c:SI (plus:SI (reg/f:SI 0 $r0 [565]) <== use r565
>>>> (const_int 136 [0x88])) [5 %sfp+24 S4 A32])) test2.c:95
>>>> 39
>>>> {*load_si}
>>>> (expr_list:REG_DEAD (reg/f:SI 0 $r0 [565])
>>>> (nil)))
>>>> ...
>>>> (insn 539 540 270 3 (set (reg:SI 0 $r0 [479])
>>>> (plus:SI (reg/f:SI 0 $r0 [477])
>>>> (reg:SI 5 $r5 [480]))) test2.c:95 62 {*add_16bit}
>>>> (expr_list:REG_DEAD (reg:SI 5 $r5 [480])
>>>> (expr_list:REG_DEAD (reg/f:SI 0 $r0 [477]) <== use r477 which
>>>> should be $sp +112
>>>>
>>>> Note that the live ranges of r477 and r565 are overlapped but assigned
>>>> same register $r0. (r31 is stack pointer)
>>>>
>>>> By tracing LRA process, I noticed that when r477 is created,
>>>> the lra_reg_info[r477].val = lra_reg_info[r31] due to (set r477 r31).
>>>> But after lra_eliminate(), the stack offset changes and
>>>> r477 is equal to r31+112 instead.
>>>>
>>>> In next lra-iteration round, r565 is created, and r565 = r31.
>>>>
>>>> In that case, register content of r477 should treat as not equal to
>>>> r565 due to eliminate offset have been changed.
>>>>
>>>> Otherwise, r565 and r477 may assign to same hard register.
>>>>
>>>>
>>>> To recognize that, I record the eliminate offset when the pseudo
>>>> register have been created.
>>>>
>>>> Register content are the same only when lra_reg_info[].val and
>>>> lra_reg_info[].offset are equal.
>>>>
>>>>
>>>> gcc/lra-assigns.c | 6 ++++--
>>>> gcc/lra-int.h | 2 ++
>>>> gcc/lra.c | 12 +++++++++++-
>>>> 3 files changed, 17 insertions(+), 3 deletions(-)
>>>>
>>>> diff --git a/gcc/lra-assigns.c b/gcc/lra-assigns.c
>>>> index b204513..daf0aa9 100644
>>>> --- a/gcc/lra-assigns.c
>>>> +++ b/gcc/lra-assigns.c
>>>> @@ -448,7 +448,7 @@ find_hard_regno_for (int regno, int *cost, int
>>>> try_only_hard_regno)
>>>> int hr, conflict_hr, nregs;
>>>> enum machine_mode biggest_mode;
>>>> unsigned int k, conflict_regno;
>>>> - int val, biggest_nregs, nregs_diff;
>>>> + int offset, val, biggest_nregs, nregs_diff;
>>>> enum reg_class rclass;
>>>> bitmap_iterator bi;
>>>> bool *rclass_intersect_p;
>>>> @@ -508,9 +508,11 @@ find_hard_regno_for (int regno, int *cost, int
>>>> try_only_hard_regno)
>>>> #endif
>>>> sparseset_clear_bit (conflict_reload_and_inheritance_pseudos, regno);
>>>> val = lra_reg_info[regno].val;
>>>> + offset = lra_reg_info[regno].offset;
>>>> CLEAR_HARD_REG_SET (impossible_start_hard_regs);
>>>> EXECUTE_IF_SET_IN_SPARSESET (live_range_hard_reg_pseudos,
>>>> conflict_regno)
>>>> - if (val == lra_reg_info[conflict_regno].val)
>>>> + if ((val == lra_reg_info[conflict_regno].val)
>>>> + && (offset == lra_reg_info[conflict_regno].offset))
>>>> {
>>>> conflict_hr = live_pseudos_reg_renumber[conflict_regno];
>>>> nregs = (hard_regno_nregs[conflict_hr]
>>>> diff --git a/gcc/lra-int.h b/gcc/lra-int.h
>>>> index 98f2ff7..8ae4eb0 100644
>>>> --- a/gcc/lra-int.h
>>>> +++ b/gcc/lra-int.h
>>>> @@ -116,6 +116,8 @@ struct lra_reg
>>>> /* Value holding by register. If the pseudos have the same
>>>> value
>>>> they do not conflict. */
>>>> int val;
>>>> + /* Eliminate offset of the pseduo have been created. */
>>>> + int offset;
>>>> /* These members are set up in lra-lives.c and updated in
>>>> lra-coalesce.c. */
>>>> /* The biggest size mode in which each pseudo reg is referred in
>>>> diff --git a/gcc/lra.c b/gcc/lra.c
>>>> index 9df24b5..69962be 100644
>>>> --- a/gcc/lra.c
>>>> +++ b/gcc/lra.c
>>>> @@ -194,7 +194,17 @@ lra_create_new_reg (enum machine_mode md_mode,
>>>> rtx original,
>>>> new_reg
>>>> = lra_create_new_reg_with_unique_value (md_mode, original, rclass,
>>>> title);
>>>> if (original != NULL_RTX && REG_P (original))
>>>> - lra_reg_info[REGNO (new_reg)].val = lra_reg_info[REGNO
>>>> (original)].val;
>>>> + {
>>>> + lra_reg_info[REGNO (new_reg)].val = lra_reg_info[REGNO
>>>> (original)].val;
>>>> +
>>>> + rtx x = lra_eliminate_regs (original, VOIDmode, NULL_RTX);
>>>> +
>>>> + if (GET_CODE (x) == PLUS
>>>> + && GET_CODE (XEXP (x, 1)) == CONST_INT)
>>>> + lra_reg_info[REGNO (new_reg)].offset = INTVAL (XEXP (x, 1));
>>>> + else
>>>> + lra_reg_info[REGNO (new_reg)].offset = 0;
>>>> + }
>>>> return new_reg;
>>>> }
>>>>
>>>> --
>>>> 1.7.9.5
>>>>
>>>>
>>>> Comments?
>>>>
>>>>
>>> Thanks for working on it, Shiva. Could you send me full dump for lra (and
>>> ira if possible) for better understanding the problem situation. It is hard
>>> for me to say now that your solution is complete (e.g. offsets can be
>>> changed again).