This is the mail archive of the gcc@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]

Re: LRA assign same hard register with live range overlapped pseduos


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

Attachment: test2.c.208r.ira
Description: Binary data


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