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