LRA assign same hard register with live range overlapped pseduos
Shiva Chen
shiva0217@gmail.com
Thu Apr 18 03:18:00 GMT 2013
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 <shiva0217@gmail.com>:
> Hi, Vladimir
>
> attachment is the ira dump of the case
>
> Shiva
>
> 2013/4/17 Vladimir Makarov <vmakarov@redhat.com>:
>> 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).
More information about the Gcc
mailing list