/* Basic block reordering routines for the GNU compiler.
Copyright (C) 2000 Free Software Foundation, Inc.
- This file is part of GNU CC.
+ This file is part of GCC.
- GNU CC is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
- GNU CC is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+ License for more details.
You should have received a copy of the GNU General Public License
- along with GNU CC; see the file COPYING. If not, write to
- the Free Software Foundation, 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
+ along with GCC; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
/* References:
#include "flags.h"
#include "output.h"
#include "function.h"
-#include "except.h"
#include "toplev.h"
#include "recog.h"
#include "expr.h"
#define RBI(BB) ((reorder_block_def) (BB)->aux)
+/* Holds the interesting trailing notes for the function. */
+static rtx function_tail_eff_head;
+
/* Local function prototypes. */
static rtx skip_insns_after_block PARAMS ((basic_block));
skip_insns_after_block (bb)
basic_block bb;
{
- rtx insn, last_insn, next_head;
+ rtx insn, last_insn, next_head, prev;
next_head = NULL_RTX;
if (bb->index + 1 != n_basic_blocks)
next_head = BASIC_BLOCK (bb->index + 1)->head;
- for (last_insn = bb->end; (insn = NEXT_INSN (last_insn)); last_insn = insn)
+ for (last_insn = insn = bb->end; (insn = NEXT_INSN (insn)); )
{
if (insn == next_head)
break;
switch (GET_CODE (insn))
{
case BARRIER:
+ last_insn = insn;
continue;
case NOTE:
{
case NOTE_INSN_LOOP_END:
case NOTE_INSN_BLOCK_END:
+ last_insn = insn;
+ continue;
case NOTE_INSN_DELETED:
case NOTE_INSN_DELETED_LABEL:
continue;
default:
+ continue;
break;
}
break;
|| GET_CODE (PATTERN (NEXT_INSN (insn))) == ADDR_DIFF_VEC))
{
insn = NEXT_INSN (insn);
+ last_insn = insn;
continue;
}
break;
break;
}
+ /* It is possible to hit contradicting sequence. For instance:
+
+ jump_insn
+ NOTE_INSN_LOOP_BEG
+ barrier
+
+ Where barrier belongs to jump_insn, but the note does not.
+ This can be created by removing the basic block originally
+ following NOTE_INSN_LOOP_BEG.
+
+ In such case reorder the notes. */
+ for (insn = last_insn; insn != bb->end; insn = prev)
+ {
+ prev = PREV_INSN (insn);
+ if (GET_CODE (insn) == NOTE)
+ switch (NOTE_LINE_NUMBER (insn))
+ {
+ case NOTE_INSN_LOOP_END:
+ case NOTE_INSN_BLOCK_END:
+ case NOTE_INSN_DELETED:
+ case NOTE_INSN_DELETED_LABEL:
+ continue;
+ default:
+ reorder_insns (insn, insn, last_insn);
+ }
+ }
return last_insn;
}
RBI (bb)->eff_end = end;
next_insn = NEXT_INSN (end);
}
+ function_tail_eff_head = next_insn;
}
taken = probability > REG_BR_PROB_BASE / 2;
/* Find the normal taken edge and the normal fallthru edge.
- Note that there may in fact be other edges due to
- flag_non_call_exceptions.
Note, conditional jumps with other side effects may not
be fully optimized. In this case it is possible for
{
if (e->flags & EDGE_FALLTHRU)
e_fall = e;
- if (! (e->flags & EDGE_EH))
+ else if (! (e->flags & EDGE_EH))
e_taken = e;
}
jump = emit_jump_insn_after (gen_jump (label), after);
JUMP_LABEL (jump) = label;
LABEL_NUSES (label) += 1;
+ if (basic_block_for_insn)
+ set_block_for_new_insns (jump, bb);
if (rtl_dump_file)
fprintf (rtl_dump_file, "Emitting jump to block %d (%d)\n",
last_bb = bb;
bb = RBI (bb)->next;
}
- NEXT_INSN (RBI (last_bb)->eff_end) = NULL_RTX;
- set_last_insn (RBI (last_bb)->eff_end);
+
+ {
+ rtx insn = RBI (last_bb)->eff_end;
+
+ NEXT_INSN (insn) = function_tail_eff_head;
+ if (function_tail_eff_head)
+ PREV_INSN (function_tail_eff_head) = insn;
+
+ while (NEXT_INSN (insn))
+ insn = NEXT_INSN (insn);
+ set_last_insn (insn);
+ }
/* Now add jumps and labels as needed to match the blocks new
outgoing edges. */
nb->global_live_at_start = OBSTACK_ALLOC_REG_SET (&flow_obstack);
nb->global_live_at_end = OBSTACK_ALLOC_REG_SET (&flow_obstack);
nb->local_set = 0;
+ nb->count = e_fall->count;
+ nb->frequency = EDGE_FREQUENCY (e_fall);
COPY_REG_SET (nb->global_live_at_start, bb->global_live_at_start);
COPY_REG_SET (nb->global_live_at_end, bb->global_live_at_start);
/* Link to new block. */
make_edge (NULL, nb, e_fall->dest, 0);
redirect_edge_succ (e_fall, nb);
+ nb->succ->count = e_fall->count;
+ nb->succ->probability = REG_BR_PROB_BASE;
/* Don't process this new block. */
bb = nb;
if (n_basic_blocks <= 1)
return;
- /* We do not currently handle correct re-placement of EH notes.
- But that does not matter unless we intend to use them. */
- if (flag_exceptions)
- for (i = 0; i < n_basic_blocks; i++)
- {
- edge e;
- for (e = BASIC_BLOCK (i)->succ; e ; e = e->succ_next)
- if (e->flags & EDGE_EH)
- return;
- }
-
for (i = 0; i < n_basic_blocks; i++)
BASIC_BLOCK (i)->aux = xcalloc (1, sizeof (struct reorder_block_def));