aboutsummaryrefslogtreecommitdiff
path: root/gcc/caller-save.c
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2010-02-17 09:54:59 +0100
committerJakub Jelinek <jakub@gcc.gnu.org>2010-02-17 09:54:59 +0100
commit169e464e66d4b35e80d66781c6aa53fcc1726f65 (patch)
treea196fe9766e86407931b220895d3d88ed96745e4 /gcc/caller-save.c
parent32ade5590ec9650b24dbd0965831397c7b009314 (diff)
downloadgcc-169e464e66d4b35e80d66781c6aa53fcc1726f65.zip
gcc-169e464e66d4b35e80d66781c6aa53fcc1726f65.tar.gz
gcc-169e464e66d4b35e80d66781c6aa53fcc1726f65.tar.bz2
re PR debug/42918 ("-fcompare-debug failure" with "-O2 -ftracer" (2))
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. From-SVN: r156823
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 a6faeea..dbfd42a 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))