diff options
-rw-r--r-- | gcc/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/combine-stack-adj.c | 16 |
2 files changed, 19 insertions, 4 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 16ef45abb0c..2af56eb47f2 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2011-10-06 Richard Henderson <rth@redhat.com> + + * combine-stack-adjust.c (maybe_move_args_size_note): Add after + parameter; use it to decide whether to merge two notes. + (combine_stack_adjustments_for_block): Use maybe_move_args_size_note + for the deallocation case as well. + 2011-10-06 Anatoly Sokolov <aesok@post.ru> * system.h (OUTPUT_ADDR_CONST_EXTRA): Poison. diff --git a/gcc/combine-stack-adj.c b/gcc/combine-stack-adj.c index bca078442f7..3cffd662f92 100644 --- a/gcc/combine-stack-adj.c +++ b/gcc/combine-stack-adj.c @@ -296,10 +296,11 @@ record_stack_refs (rtx *xp, void *data) return 0; } -/* If INSN has a REG_ARGS_SIZE note, move it to LAST. */ +/* If INSN has a REG_ARGS_SIZE note, move it to LAST. + AFTER is true iff LAST follows INSN in the instruction stream. */ static void -maybe_move_args_size_note (rtx last, rtx insn) +maybe_move_args_size_note (rtx last, rtx insn, bool after) { rtx note, last_note; @@ -309,7 +310,12 @@ maybe_move_args_size_note (rtx last, rtx insn) last_note = find_reg_note (last, REG_ARGS_SIZE, NULL_RTX); if (last_note) - XEXP (last_note, 0) = XEXP (note, 0); + { + /* The ARGS_SIZE notes are *not* cumulative. They represent an + absolute value, and the "most recent" note wins. */ + if (!after) + XEXP (last_note, 0) = XEXP (note, 0); + } else add_reg_note (last, REG_ARGS_SIZE, XEXP (note, 0)); } @@ -385,7 +391,7 @@ combine_stack_adjustments_for_block (basic_block bb) last_sp_adjust + this_adjust, this_adjust)) { - maybe_move_args_size_note (last_sp_set, insn); + maybe_move_args_size_note (last_sp_set, insn, false); /* It worked! */ delete_insn (insn); @@ -403,6 +409,8 @@ combine_stack_adjustments_for_block (basic_block bb) last_sp_adjust + this_adjust, -last_sp_adjust)) { + maybe_move_args_size_note (insn, last_sp_set, true); + /* It worked! */ delete_insn (last_sp_set); last_sp_set = insn; |