summaryrefslogtreecommitdiff
path: root/gcc/caller-save.c
diff options
context:
space:
mode:
authorjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>2010-02-17 08:54:59 +0000
committerjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>2010-02-17 08:54:59 +0000
commit4812f6d00d4844d82b07a4f46e5d018a6f78085e (patch)
treea196fe9766e86407931b220895d3d88ed96745e4 /gcc/caller-save.c
parent6261db624fd97cd38265271dbea9e350c732b31d (diff)
downloadgcc-4812f6d00d4844d82b07a4f46e5d018a6f78085e.tar.gz
PR debug/42918
* caller-save.c (save_call_clobbered_regs): If BB ends with a DEBUG_INSN, move any notes in between last real insn and the last DEBUG_INSN after the last DEBUG_INSN. * gcc.dg/pr42918.c: New test. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@156823 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/caller-save.c')
-rw-r--r--gcc/caller-save.c35
1 files changed, 33 insertions, 2 deletions
diff --git a/gcc/caller-save.c b/gcc/caller-save.c
index a6faeea1969..dbfd42aa793 100644
--- a/gcc/caller-save.c
+++ b/gcc/caller-save.c
@@ -1,6 +1,6 @@
/* Save and restore call-clobbered registers which are live across a call.
Copyright (C) 1989, 1992, 1994, 1995, 1997, 1998, 1999, 2000,
- 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
+ 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
Free Software Foundation, Inc.
This file is part of GCC.
@@ -754,7 +754,7 @@ setup_save_areas (void)
void
save_call_clobbered_regs (void)
{
- struct insn_chain *chain, *next;
+ struct insn_chain *chain, *next, *last = NULL;
enum machine_mode save_mode [FIRST_PSEUDO_REGISTER];
/* Computed in mark_set_regs, holds all registers set by the current
@@ -861,6 +861,7 @@ save_call_clobbered_regs (void)
if (TEST_HARD_REG_BIT (hard_regs_saved, regno))
n_regs_saved++;
}
+ last = chain;
}
else if (DEBUG_INSN_P (insn) && n_regs_saved)
mark_referenced_regs (&PATTERN (insn),
@@ -874,6 +875,36 @@ save_call_clobbered_regs (void)
remain saved. If the last insn in the block is a JUMP_INSN, put
the restore before the insn, otherwise, put it after the insn. */
+ if (DEBUG_INSN_P (insn) && last && last->block == chain->block)
+ {
+ rtx ins, prev;
+ basic_block bb = BLOCK_FOR_INSN (insn);
+
+ /* When adding hard reg restores after a DEBUG_INSN, move
+ all notes between last real insn and this DEBUG_INSN after
+ the DEBUG_INSN, otherwise we could get code
+ -g/-g0 differences. */
+ for (ins = PREV_INSN (insn); ins != last->insn; ins = prev)
+ {
+ prev = PREV_INSN (ins);
+ if (NOTE_P (ins))
+ {
+ NEXT_INSN (prev) = NEXT_INSN (ins);
+ PREV_INSN (NEXT_INSN (ins)) = prev;
+ PREV_INSN (ins) = insn;
+ NEXT_INSN (ins) = NEXT_INSN (insn);
+ NEXT_INSN (insn) = ins;
+ if (NEXT_INSN (ins))
+ PREV_INSN (NEXT_INSN (ins)) = ins;
+ if (BB_END (bb) == insn)
+ BB_END (bb) = ins;
+ }
+ else
+ gcc_assert (DEBUG_INSN_P (ins));
+ }
+ }
+ last = NULL;
+
if (n_regs_saved)
for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
if (TEST_HARD_REG_BIT (hard_regs_saved, regno))