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]

LRA assign same hard register with live range overlapped pseduos


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

Best regards, Shiva


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