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 < &reg_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 <shiva0...@gmail.com>:
> 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 <shiva0...@gmail.com>:
>> Hi, Vladimir
>>
>> attachment is the ira dump of the case
>>
>> Shiva
>>
>> 2013/4/17 Vladimir Makarov <vmaka...@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).

Reply via email to