/* Control flow optimization code for GNU compiler.
Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2010
+ 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2010, 2011
Free Software Foundation, Inc.
This file is part of GCC.
#include "flags.h"
#include "recog.h"
#include "diagnostic-core.h"
-#include "toplev.h"
#include "cselib.h"
#include "params.h"
#include "tm_p.h"
{
dest = XEXP (exp, 0);
regno = REGNO (dest);
- CLEAR_REGNO_REG_SET (nonequal, regno);
- if (regno < FIRST_PSEUDO_REGISTER)
- {
- int n = hard_regno_nregs[regno][GET_MODE (dest)];
- while (--n > 0)
- CLEAR_REGNO_REG_SET (nonequal, regno + n);
- }
+ if (HARD_REGISTER_NUM_P (regno))
+ bitmap_clear_range (nonequal, regno,
+ hard_regno_nregs[regno][GET_MODE (dest)]);
+ else
+ bitmap_clear_bit (nonequal, regno);
}
return false;
if (!REG_P (dest))
return true;
regno = REGNO (dest);
- SET_REGNO_REG_SET (nonequal, regno);
- if (regno < FIRST_PSEUDO_REGISTER)
- {
- int n = hard_regno_nregs[regno][GET_MODE (dest)];
- while (--n > 0)
- SET_REGNO_REG_SET (nonequal, regno + n);
- }
+ if (HARD_REGISTER_NUM_P (regno))
+ bitmap_set_range (nonequal, regno,
+ hard_regno_nregs[regno][GET_MODE (dest)]);
+ else
+ bitmap_set_bit (nonequal, regno);
return false;
default:
new_target = NULL;
else
{
+ rtx last;
+
if (new_locus)
locus = new_locus;
- new_locus = INSN_P (BB_END (target))
- ? INSN_LOCATOR (BB_END (target)) : 0;
+ last = BB_END (target);
+ if (DEBUG_INSN_P (last))
+ last = prev_nondebug_insn (last);
+
+ new_locus = last && INSN_P (last)
+ ? INSN_LOCATOR (last) : 0;
if (new_locus && locus && !locator_eq (new_locus, locus))
new_target = NULL;
{
rtx i1, i2, last1, last2, afterlast1, afterlast2;
int ninsns = 0;
+ rtx p1;
/* Skip simple jumps at the end of the blocks. Complex jumps still
need to be compared for equivalence, which we'll do below. */
afterlast1 = last1, afterlast2 = last2;
last1 = i1, last2 = i2;
- ninsns++;
+ p1 = PATTERN (i1);
+ if (!(GET_CODE (p1) == USE || GET_CODE (p1) == CLOBBER))
+ ninsns++;
}
i1 = PREV_INSN (i1);
while (true)
{
- /* Ignore notes. */
+ /* Ignore notes, except NOTE_INSN_EPILOGUE_BEG. */
while (!NONDEBUG_INSN_P (i1) && i1 != BB_END (bb1))
- i1 = NEXT_INSN (i1);
+ {
+ if (NOTE_P (i1) && NOTE_KIND (i1) == NOTE_INSN_EPILOGUE_BEG)
+ break;
+ i1 = NEXT_INSN (i1);
+ }
while (!NONDEBUG_INSN_P (i2) && i2 != BB_END (bb2))
- i2 = NEXT_INSN (i2);
+ {
+ if (NOTE_P (i2) && NOTE_KIND (i2) == NOTE_INSN_EPILOGUE_BEG)
+ break;
+ i2 = NEXT_INSN (i2);
+ }
if ((i1 == BB_END (bb1) && !NONDEBUG_INSN_P (i1))
|| (i2 == BB_END (bb2) && !NONDEBUG_INSN_P (i2)))
edge e, e2, fallthru;
bool changed;
unsigned max, ix, ix2;
- basic_block ev, ev2;
/* Nothing to do if there is not at least two incoming edges. */
if (EDGE_COUNT (bb->preds) < 2)
fallthru = find_fallthru_edge (bb->preds);
changed = false;
- for (ix = 0, ev = bb; ix < EDGE_COUNT (ev->preds); )
+ for (ix = 0; ix < EDGE_COUNT (bb->preds);)
{
- e = EDGE_PRED (ev, ix);
+ e = EDGE_PRED (bb, ix);
ix++;
/* As noted above, first try with the fallthru predecessor (or, a
{
changed = true;
ix = 0;
- ev = bb;
continue;
}
}
if (EDGE_SUCC (e->src, 0) != e)
continue;
- for (ix2 = 0, ev2 = bb; ix2 < EDGE_COUNT (ev2->preds); )
+ for (ix2 = 0; ix2 < EDGE_COUNT (bb->preds); ix2++)
{
- e2 = EDGE_PRED (ev2, ix2);
- ix2++;
+ e2 = EDGE_PRED (bb, ix2);
if (e2 == e)
continue;
if (try_crossjump_to_edge (mode, e, e2))
{
changed = true;
- ev2 = bb;
ix = 0;
break;
}
jump, e0->dest, live_union,
NULL, &move_upto);
if (!moveall)
- e0_last_head = move_upto;
+ {
+ if (move_upto == NULL_RTX)
+ goto out;
+
+ while (e0_last_head != move_upto)
+ {
+ df_simulate_one_insn_backwards (e0->dest, e0_last_head,
+ live_union);
+ e0_last_head = PREV_INSN (e0_last_head);
+ }
+ }
if (e0_last_head == NULL_RTX)
goto out;
}
}
delete_basic_block (b);
- if (!(mode & CLEANUP_CFGLAYOUT))
- changed = true;
+ changed = true;
/* Avoid trying to remove ENTRY_BLOCK_PTR. */
b = (c == ENTRY_BLOCK_PTR ? c->next_bb : c);
continue;