diff options
author | jakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4> | 2010-02-17 08:54:59 +0000 |
---|---|---|
committer | jakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4> | 2010-02-17 08:54:59 +0000 |
commit | 4812f6d00d4844d82b07a4f46e5d018a6f78085e (patch) | |
tree | a196fe9766e86407931b220895d3d88ed96745e4 /gcc/caller-save.c | |
parent | 6261db624fd97cd38265271dbea9e350c732b31d (diff) | |
download | gcc-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.c | 35 |
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)) |