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

I write the new patch as your suggestion.
Could you help me to check is there something missing ?

Thanks, Shiva

 gcc/lra-assigns.c      |   12 +++++++-----
 gcc/lra-constraints.c  |    5 ++---
 gcc/lra-eliminations.c |   10 ++++++++--
 gcc/lra-int.h          |   33 +++++++++++++++++++++++++++++++++
 gcc/lra.c              |    1 +
 5 files changed, 51 insertions(+), 10 deletions(-)

diff --git a/gcc/lra-assigns.c b/gcc/lra-assigns.c
index b204513..3f8a899 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,10 @@ 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 (lra_reg_val_equal_p (conflict_regno, val, offset))
       {
        conflict_hr = live_pseudos_reg_renumber[conflict_regno];
        nregs = (hard_regno_nregs[conflict_hr]
@@ -538,7 +539,7 @@ find_hard_regno_for (int regno, int *cost, int
try_only_hard_regno)
       }
   EXECUTE_IF_SET_IN_SPARSESET (conflict_reload_and_inheritance_pseudos,
                               conflict_regno)
-    if (val != lra_reg_info[conflict_regno].val)
+    if (!lra_reg_val_equal_p (conflict_regno, val, offset))
       {
        lra_assert (live_pseudos_reg_renumber[conflict_regno] < 0);
        if ((hard_regno
@@ -1007,7 +1008,7 @@
setup_live_pseudos_and_spill_after_risky_transforms (bitmap
 {
   int p, i, j, n, regno, hard_regno;
   unsigned int k, conflict_regno;
-  int val;
+  int val, offset;
   HARD_REG_SET conflict_set;
   enum machine_mode mode;
   lra_live_range_t r;
@@ -1050,8 +1051,9 @@
setup_live_pseudos_and_spill_after_risky_transforms (bitmap
       COPY_HARD_REG_SET (conflict_set, lra_no_alloc_regs);
       IOR_HARD_REG_SET (conflict_set, lra_reg_info[regno].conflict_hard_regs);
       val = lra_reg_info[regno].val;
+      offset = lra_reg_info[regno].offset;
       EXECUTE_IF_SET_IN_SPARSESET (live_range_hard_reg_pseudos, conflict_regno)
-       if (val != lra_reg_info[conflict_regno].val
+       if (!lra_reg_val_equal_p (conflict_regno, val, offset)
            /* If it is multi-register pseudos they should start on
               the same hard register.  */
            || hard_regno != reg_renumber[conflict_regno])
diff --git a/gcc/lra-constraints.c b/gcc/lra-constraints.c
index e3b4add..2a72aef 100644
--- a/gcc/lra-constraints.c
+++ b/gcc/lra-constraints.c
@@ -704,7 +704,7 @@ match_reload (signed char out, signed char *ins,
enum reg_class goal_class,
             pseudos still live where reload pseudos dies.  */
          if (REG_P (in_rtx) && (int) REGNO (in_rtx) < lra_new_regno_start
              && find_regno_note (curr_insn, REG_DEAD, REGNO (in_rtx)))
-           lra_reg_info[REGNO (reg)].val = lra_reg_info[REGNO (in_rtx)].val;
+           lra_assign_reg_val (REGNO (in_rtx), REGNO (reg));
        }
       else
        {
@@ -733,8 +733,7 @@ match_reload (signed char out, signed char *ins,
enum reg_class goal_class,
                  && GET_MODE (subreg_reg) == outmode
                  && SUBREG_BYTE (in_rtx) == SUBREG_BYTE (new_in_reg)
                  && find_regno_note (curr_insn, REG_DEAD, REGNO (subreg_reg)))
-               lra_reg_info[REGNO (reg)].val
-                 = lra_reg_info[REGNO (subreg_reg)].val;
+               lra_assign_reg_val (REGNO (subreg_reg), REGNO (reg));
            }
        }
     }
diff --git a/gcc/lra-eliminations.c b/gcc/lra-eliminations.c
index 9df0bae..0e75cc2 100644
--- a/gcc/lra-eliminations.c
+++ b/gcc/lra-eliminations.c
@@ -1124,8 +1124,14 @@ 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.  */
+       lra_set_up_reg_val (lra_reg_info[ep->from].val,
+                           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..69f8f8a 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
@@ -439,6 +441,37 @@ lra_get_insn_recog_data (rtx insn)
   return lra_set_insn_recog_data (insn);
 }
+/* Update offset from eliminate register to pseduo i.  */
+static inline void
+lra_set_up_reg_val (int val, int offset)
+{
+  int i;
+
+  for (i = FIRST_PSEUDO_REGISTER; i < max_reg_num (); i++)
+    {
+      if (lra_reg_info[i].val == val)
+        lra_reg_info[i].offset += offset;
+    }
+}
+
+/* Return true if register content are equal.  */
+static inline bool
+lra_reg_val_equal_p (int regno, int val, int offset)
+{
+  if (lra_reg_info[regno].val == val
+      && lra_reg_info[regno].offset == offset)
+    return true;
+
+  return false;
+}
+
+/* Assign register content record.  */
+static inline void
+lra_assign_reg_val (int from, int to)
+{
+  lra_reg_info[to].val = lra_reg_info[from].val;
+  lra_reg_info[to].offset = lra_reg_info[from].offset;
+}
 struct target_lra_int
diff --git a/gcc/lra.c b/gcc/lra.c
index 9df24b5..4c06a0c 100644
--- a/gcc/lra.c
+++ b/gcc/lra.c
@@ -1392,6 +1392,7 @@ initialize_lra_reg_info_element (int i)
   lra_reg_info[i].last_reload = 0;
   lra_reg_info[i].restore_regno = -1;
   lra_reg_info[i].val = get_new_reg_value ();
+  lra_reg_info[i].offset = 0;
   lra_reg_info[i].copies = NULL;
 }

2013/4/20 Vladimir Makarov <vmakarov@redhat.com>:
> On 13-04-17 11:11 PM, Shiva Chen wrote:
>>
>> Hi, Vladimir
>>
>> Overlapped live range RTL is from line 7577 to 7597 in test2.c.209r.reload
>>
>> 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)
>
> I guess, -1 here is typo.
>
>> +           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 dump files.  They help me to understand better the situation.
> The patch is better but it is still incomplete.  There are more places where
> the values are used (more places in lra-assigns.c, a few places in
> lra-constraints.c).
>
> As there are many places it would be nice to have helper functions (I'd make
> them static inline and put them in lra-int.h):
>
> static inline void
> lra_set_up_reg_val (int regno, int val, int offset)
>
> and
>
> static inline bool
> lra_reg_val_equal_p (int regno, int val, int offset)
>
> and use them wherever it is possible.
>
> So could you check all the places where .val is used, define the helper
> functions, and use them wherever it is possible and send me the new version
> of the patch.  I'll approve it after some checking.
>
> Thanks for working on this problem.  I really appreciate it.
>


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