/* 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:
{
/* When not optimizing, ensure that edges or forwarder
blocks with different locus are not optimized out. */
- int locus = single_succ_edge (target)->goto_locus;
-
- if (locus && goto_locus && !locator_eq (locus, goto_locus))
- counter = n_basic_blocks;
- else if (locus)
- goto_locus = locus;
+ int new_locus = single_succ_edge (target)->goto_locus;
+ int locus = goto_locus;
- if (INSN_P (BB_END (target)))
+ if (new_locus && locus && !locator_eq (new_locus, locus))
+ new_target = NULL;
+ else
{
- locus = INSN_LOCATOR (BB_END (target));
+ rtx last;
+
+ if (new_locus)
+ locus = new_locus;
- if (locus && goto_locus
- && !locator_eq (locus, goto_locus))
- counter = n_basic_blocks;
- else if (locus)
- goto_locus = locus;
+ 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;
+ else
+ {
+ if (new_locus)
+ locus = new_locus;
+
+ goto_locus = locus;
+ }
}
}
}
edge tmp_edge, b_fallthru_edge;
bool c_has_outgoing_fallthru;
bool b_has_incoming_fallthru;
- edge_iterator ei;
/* Avoid overactive code motion, as the forwarder blocks should be
eliminated by edge redirection instead. One exception might have
and loop notes. This is done by squeezing out all the notes
and leaving them there to lie. Not ideal, but functional. */
- FOR_EACH_EDGE (tmp_edge, ei, c->succs)
- if (tmp_edge->flags & EDGE_FALLTHRU)
- break;
-
+ tmp_edge = find_fallthru_edge (c->succs);
c_has_outgoing_fallthru = (tmp_edge != NULL);
- FOR_EACH_EDGE (tmp_edge, ei, b->preds)
- if (tmp_edge->flags & EDGE_FALLTHRU)
- break;
-
+ tmp_edge = find_fallthru_edge (b->preds);
b_has_incoming_fallthru = (tmp_edge != NULL);
b_fallthru_edge = tmp_edge;
next = b->prev_bb;
{
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;
- edge_iterator ei;
/* Nothing to do if there is not at least two incoming edges. */
if (EDGE_COUNT (bb->preds) < 2)
if (EDGE_COUNT (bb->preds) > max)
return false;
- FOR_EACH_EDGE (e, ei, bb->preds)
- {
- if (e->flags & EDGE_FALLTHRU)
- {
- fallthru = e;
- break;
- }
- }
+ 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;
continue;
}
+ /* Merge B with its single successor, if any. */
if (single_succ_p (b)
&& (s = single_succ_edge (b))
&& !(s->flags & EDGE_COMPLEX)