diff options
author | Vladimir Makarov <vmakarov@redhat.com> | 2015-04-19 23:48:24 +0000 |
---|---|---|
committer | Vladimir Makarov <vmakarov@gcc.gnu.org> | 2015-04-19 23:48:24 +0000 |
commit | a6af1bf9fe2f76be09384affb063bf49a6706922 (patch) | |
tree | 285ac114828db5fce5b0c688b0f448f3732d0467 | |
parent | 037524d6be91875626a15f71b694537ac5a3bea7 (diff) | |
download | gcc-a6af1bf9fe2f76be09384affb063bf49a6706922.zip gcc-a6af1bf9fe2f76be09384affb063bf49a6706922.tar.gz gcc-a6af1bf9fe2f76be09384affb063bf49a6706922.tar.bz2 |
re PR rtl-optimization/65805 (Chromium gets miscompiled)
2015-04-19 Vladimir Makarov <vmakarov@redhat.com>
PR rtl-optimization/65805
* lra-eliminations.c (lra_eliminate_regs_1): Add new assert.
Don't use difference of offset and previous offset if
update_sp_offset is non-zero.
(eliminate_regs_in_insn): Ditto.
* lra-spills.c (remove_pseudos): Exchange 4th and 6th args in
lra_eliminate_regs_1 call.
* lra-constraints.c (get_equiv_with_elimination): Ditto.
From-SVN: r222223
-rw-r--r-- | gcc/ChangeLog | 11 | ||||
-rw-r--r-- | gcc/lra-constraints.c | 2 | ||||
-rw-r--r-- | gcc/lra-eliminations.c | 67 | ||||
-rw-r--r-- | gcc/lra-spills.c | 2 |
4 files changed, 55 insertions, 27 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index dacdc11..77fc4f9 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,14 @@ +2015-04-19 Vladimir Makarov <vmakarov@redhat.com> + + PR rtl-optimization/65805 + * lra-eliminations.c (lra_eliminate_regs_1): Add new assert. + Don't use difference of offset and previous offset if + update_sp_offset is non-zero. + (eliminate_regs_in_insn): Ditto. + * lra-spills.c (remove_pseudos): Exchange 4th and 6th args in + lra_eliminate_regs_1 call. + * lra-constraints.c (get_equiv_with_elimination): Ditto. + 2015-04-18 Trevor Saunders <tsaunders@mozilla.com> * hash-table.h: Remove version of hash_table that stored value_type *. diff --git a/gcc/lra-constraints.c b/gcc/lra-constraints.c index 90f351b..497d8db 100644 --- a/gcc/lra-constraints.c +++ b/gcc/lra-constraints.c @@ -533,7 +533,7 @@ get_equiv_with_elimination (rtx x, rtx_insn *insn) if (x == res || CONSTANT_P (res)) return res; return lra_eliminate_regs_1 (insn, res, GET_MODE (res), - 0, false, false, true); + false, false, 0, true); } /* Set up curr_operand_mode. */ diff --git a/gcc/lra-eliminations.c b/gcc/lra-eliminations.c index 64eec4a..f7c8e40 100644 --- a/gcc/lra-eliminations.c +++ b/gcc/lra-eliminations.c @@ -318,7 +318,9 @@ get_elimination (rtx reg) substitution if UPDATE_P, or the full offset if FULL_P, or otherwise zero. If FULL_P, we also use the SP offsets for elimination to SP. If UPDATE_P, use UPDATE_SP_OFFSET for updating - offsets of register elimnable to SP. + offsets of register elimnable to SP. If UPDATE_SP_OFFSET is + non-zero, don't use difference of the offset and the previous + offset. MEM_MODE is the mode of an enclosing MEM. We need this to know how much to adjust a register for, e.g., PRE_DEC. Also, if we are @@ -341,7 +343,8 @@ lra_eliminate_regs_1 (rtx_insn *insn, rtx x, machine_mode mem_mode, const char *fmt; int copied = 0; - gcc_assert (!update_p || !full_p); + lra_assert (!update_p || !full_p); + lra_assert (update_sp_offset == 0 || (!subst_p && update_p && !full_p)); if (! current_function_decl) return x; @@ -366,11 +369,14 @@ lra_eliminate_regs_1 (rtx_insn *insn, rtx x, machine_mode mem_mode, { rtx to = subst_p ? ep->to_rtx : ep->from_rtx; - if (update_p) - return plus_constant (Pmode, to, - ep->offset - ep->previous_offset - + (ep->to_rtx == stack_pointer_rtx - ? update_sp_offset : 0)); + if (update_sp_offset != 0) + { + if (ep->to_rtx == stack_pointer_rtx) + return plus_constant (Pmode, to, update_sp_offset); + return to; + } + else if (update_p) + return plus_constant (Pmode, to, ep->offset - ep->previous_offset); else if (full_p) return plus_constant (Pmode, to, ep->offset @@ -395,16 +401,15 @@ lra_eliminate_regs_1 (rtx_insn *insn, rtx x, machine_mode mem_mode, if (! update_p && ! full_p) return gen_rtx_PLUS (Pmode, to, XEXP (x, 1)); - - offset = (update_p - ? ep->offset - ep->previous_offset - + (ep->to_rtx == stack_pointer_rtx - ? update_sp_offset : 0) - : ep->offset); + + if (update_sp_offset != 0) + offset = ep->to_rtx == stack_pointer_rtx ? update_sp_offset : 0; + else + offset = (update_p + ? ep->offset - ep->previous_offset : ep->offset); if (full_p && insn != NULL_RTX && ep->to_rtx == stack_pointer_rtx) offset -= lra_get_insn_recog_data (insn)->sp_offset; - if (CONST_INT_P (XEXP (x, 1)) - && INTVAL (XEXP (x, 1)) == -offset) + if (CONST_INT_P (XEXP (x, 1)) && INTVAL (XEXP (x, 1)) == -offset) return to; else return gen_rtx_PLUS (Pmode, to, @@ -451,12 +456,18 @@ lra_eliminate_regs_1 (rtx_insn *insn, rtx x, machine_mode mem_mode, { rtx to = subst_p ? ep->to_rtx : ep->from_rtx; - if (update_p) + if (update_sp_offset != 0) + { + if (ep->to_rtx == stack_pointer_rtx) + return plus_constant (Pmode, + gen_rtx_MULT (Pmode, to, XEXP (x, 1)), + update_sp_offset * INTVAL (XEXP (x, 1))); + return gen_rtx_MULT (Pmode, to, XEXP (x, 1)); + } + else if (update_p) return plus_constant (Pmode, gen_rtx_MULT (Pmode, to, XEXP (x, 1)), - (ep->offset - ep->previous_offset - + (ep->to_rtx == stack_pointer_rtx - ? update_sp_offset : 0)) + (ep->offset - ep->previous_offset) * INTVAL (XEXP (x, 1))); else if (full_p) { @@ -889,11 +900,12 @@ remove_reg_equal_offset_note (rtx insn, rtx what) If REPLACE_P is false, just update the offsets while keeping the base register the same. If FIRST_P, use the sp offset for - elimination to sp. Otherwise, use UPDATE_SP_OFFSET for this. - Attach the note about used elimination for insns setting frame - pointer to update elimination easy (without parsing already - generated elimination insns to find offset previously used) in - future. */ + elimination to sp. Otherwise, use UPDATE_SP_OFFSET for this. If + UPDATE_SP_OFFSET is non-zero, don't use difference of the offset + and the previous offset. Attach the note about used elimination + for insns setting frame pointer to update elimination easy (without + parsing already generated elimination insns to find offset + previously used) in future. */ void eliminate_regs_in_insn (rtx_insn *insn, bool replace_p, bool first_p, @@ -940,6 +952,10 @@ eliminate_regs_in_insn (rtx_insn *insn, bool replace_p, bool first_p, rtx src = SET_SRC (old_set); rtx off = remove_reg_equal_offset_note (insn, ep->to_rtx); + /* We should never process such insn with non-zero + UPDATE_SP_OFFSET. */ + lra_assert (update_sp_offset == 0); + if (off != NULL_RTX || src == ep->to_rtx || (GET_CODE (src) == PLUS @@ -1026,7 +1042,8 @@ eliminate_regs_in_insn (rtx_insn *insn, bool replace_p, bool first_p, if (! replace_p) { - offset += (ep->offset - ep->previous_offset); + if (update_sp_offset == 0) + offset += (ep->offset - ep->previous_offset); if (ep->to_rtx == stack_pointer_rtx) { if (first_p) diff --git a/gcc/lra-spills.c b/gcc/lra-spills.c index 1847351..ed678d5 100644 --- a/gcc/lra-spills.c +++ b/gcc/lra-spills.c @@ -461,7 +461,7 @@ remove_pseudos (rtx *loc, rtx_insn *insn) { rtx x = lra_eliminate_regs_1 (insn, pseudo_slots[i].mem, GET_MODE (pseudo_slots[i].mem), - 0, false, false, true); + false, false, 0, true); *loc = x != pseudo_slots[i].mem ? x : copy_rtx (x); } return; |