diff options
author | bstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4> | 2012-05-15 11:35:22 +0000 |
---|---|---|
committer | bstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4> | 2012-05-15 11:35:22 +0000 |
commit | 74fa23922a189845dad4cca1e8854de624b0ca12 (patch) | |
tree | 95f19784c581a1f85cb35235a5b5aea1f6c73e5b /gcc/regcprop.c | |
parent | b6297c58cda06dc31302af6bcf3878d96fdcce33 (diff) | |
download | gcc-74fa23922a189845dad4cca1e8854de624b0ca12.tar.gz |
2012-05-15 Basile Starynkevitch <basile@starynkevitch.net>
MELT branch merged with trunk rev 187525 using svnmerge
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/melt-branch@187527 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/regcprop.c')
-rw-r--r-- | gcc/regcprop.c | 49 |
1 files changed, 42 insertions, 7 deletions
diff --git a/gcc/regcprop.c b/gcc/regcprop.c index ceb46355359..4d6ea29f7f7 100644 --- a/gcc/regcprop.c +++ b/gcc/regcprop.c @@ -254,18 +254,27 @@ kill_clobbered_value (rtx x, const_rtx set, void *data) kill_value (x, vd); } +/* A structure passed as data to kill_set_value through note_stores. */ +struct kill_set_value_data +{ + struct value_data *vd; + rtx ignore_set_reg; +}; + /* Called through note_stores. If X is set, not clobbered, kill its current value and install it as the root of its own value list. */ static void kill_set_value (rtx x, const_rtx set, void *data) { - struct value_data *const vd = (struct value_data *) data; + struct kill_set_value_data *ksvd = (struct kill_set_value_data *) data; + if (rtx_equal_p (x, ksvd->ignore_set_reg)) + return; if (GET_CODE (set) != CLOBBER) { - kill_value (x, vd); + kill_value (x, ksvd->vd); if (REG_P (x)) - set_value_regno (REGNO (x), GET_MODE (x), vd); + set_value_regno (REGNO (x), GET_MODE (x), ksvd->vd); } } @@ -743,6 +752,7 @@ copyprop_hardreg_forward_1 (basic_block bb, struct value_data *vd) rtx set; bool replaced[MAX_RECOG_OPERANDS]; bool changed = false; + struct kill_set_value_data ksvd; if (!NONDEBUG_INSN_P (insn)) { @@ -976,14 +986,39 @@ copyprop_hardreg_forward_1 (basic_block bb, struct value_data *vd) note_uses (&PATTERN (insn), cprop_find_used_regs, vd); } + ksvd.vd = vd; + ksvd.ignore_set_reg = NULL_RTX; + /* Clobber call-clobbered registers. */ if (CALL_P (insn)) - for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) - if (TEST_HARD_REG_BIT (regs_invalidated_by_call, i)) - kill_value_regno (i, 1, vd); + { + int set_regno = INVALID_REGNUM; + int set_nregs = 0; + rtx exp; + for (exp = CALL_INSN_FUNCTION_USAGE (insn); exp; exp = XEXP (exp, 1)) + { + rtx x = XEXP (exp, 0); + if (GET_CODE (x) == SET) + { + rtx dest = SET_DEST (x); + kill_value (dest, vd); + set_value_regno (REGNO (dest), GET_MODE (dest), vd); + copy_value (dest, SET_SRC (x), vd); + ksvd.ignore_set_reg = dest; + set_regno = REGNO (dest); + set_nregs + = hard_regno_nregs[set_regno][GET_MODE (dest)]; + break; + } + } + for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) + if (TEST_HARD_REG_BIT (regs_invalidated_by_call, i) + && (i < set_regno || i >= set_regno + set_nregs)) + kill_value_regno (i, 1, vd); + } /* Notice stores. */ - note_stores (PATTERN (insn), kill_set_value, vd); + note_stores (PATTERN (insn), kill_set_value, &ksvd); /* Notice copies. */ if (set && REG_P (SET_DEST (set)) && REG_P (SET_SRC (set))) |