diff options
Diffstat (limited to 'contrib/gcc/gcse.c')
-rw-r--r-- | contrib/gcc/gcse.c | 36 |
1 files changed, 31 insertions, 5 deletions
diff --git a/contrib/gcc/gcse.c b/contrib/gcc/gcse.c index c876738..d06a224 100644 --- a/contrib/gcc/gcse.c +++ b/contrib/gcc/gcse.c @@ -4303,7 +4303,8 @@ do_local_cprop (rtx x, rtx insn, int alter_jumps, rtx *libcall_sp) rtx this_rtx = l->loc; rtx note; - if (l->in_libcall) + /* Don't CSE non-constant values out of libcall blocks. */ + if (l->in_libcall && ! CONSTANT_P (this_rtx)) continue; if (gcse_constant_p (this_rtx)) @@ -4388,7 +4389,7 @@ adjust_libcall_notes (rtx oldreg, rtx newval, rtx insn, rtx *libcall_sp) return true; } } - XEXP (note, 0) = replace_rtx (XEXP (note, 0), oldreg, newval); + XEXP (note, 0) = simplify_replace_rtx (XEXP (note, 0), oldreg, newval); insn = end; } return true; @@ -7777,9 +7778,14 @@ remove_reachable_equiv_notes (basic_block bb, struct ls_expr *smexpr) } bb = act->dest; + /* We used to continue the loop without scanning this block if the + store expression was killed in this block. That is wrong as + we could have had a REG_EQUAL note with the store expression + appear in the block before the insn which killed the store + expression and that REG_EQUAL note needs to be removed as it + is invalid. */ if (bb == EXIT_BLOCK_PTR - || TEST_BIT (visited, bb->index) - || TEST_BIT (ae_kill[bb->index], smexpr->index)) + || TEST_BIT (visited, bb->index)) { act = act->succ_next; continue; @@ -7824,7 +7830,7 @@ remove_reachable_equiv_notes (basic_block bb, struct ls_expr *smexpr) static void replace_store_insn (rtx reg, rtx del, basic_block bb, struct ls_expr *smexpr) { - rtx insn, mem, note, set, ptr; + rtx insn, mem, note, set, ptr, pair; mem = smexpr->pattern; insn = gen_move_insn (reg, SET_SRC (single_set (del))); @@ -7846,6 +7852,26 @@ replace_store_insn (rtx reg, rtx del, basic_block bb, struct ls_expr *smexpr) XEXP (ptr, 0) = insn; break; } + + /* Move the notes from the deleted insn to its replacement, and patch + up the LIBCALL notes. */ + REG_NOTES (insn) = REG_NOTES (del); + + note = find_reg_note (insn, REG_RETVAL, NULL_RTX); + if (note) + { + pair = XEXP (note, 0); + note = find_reg_note (pair, REG_LIBCALL, NULL_RTX); + XEXP (note, 0) = insn; + } + note = find_reg_note (insn, REG_LIBCALL, NULL_RTX); + if (note) + { + pair = XEXP (note, 0); + note = find_reg_note (pair, REG_RETVAL, NULL_RTX); + XEXP (note, 0) = insn; + } + delete_insn (del); /* Now we must handle REG_EQUAL notes whose contents is equal to the mem; |