#include "config.h"
#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
#include "rtl.h"
#include "hard-reg-set.h"
#include "basic-block.h"
#include "tm_p.h"
#include "target.h"
-#include "obstack.h"
-
/* cleanup_cfg maintains following flags for each basic block. */
enum bb_flags
return 0;
}
/* Attempt to prove that the basic block B will have no side effects and
- allways continues in the same edge if reached via E. Return the edge
+ always continues in the same edge if reached via E. Return the edge
if exist, NULL otherwise. */
static edge
return NULL;
/* Ensure that the comparison operators are equivalent.
- ??? This is far too pesimistic. We should allow swapped operands,
+ ??? This is far too pessimistic. We should allow swapped operands,
different CCmodes, or for example comparisons for interval, that
dominate even when operands are not equivalent. */
if (!rtx_equal_p (XEXP (cond1, 0), XEXP (cond2, 0))
if (GET_CODE (insn) == NOTE)
break;
+
+ /* Do not clean up branches to just past the end of a loop
+ at this time; it can mess up the loop optimizer's
+ recognition of some patterns. */
+
+ insn = PREV_INSN (target->head);
+ if (insn && GET_CODE (insn) == NOTE
+ && NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_END)
+ break;
}
counter++;
equal, they were constructed identically. */
if (GET_CODE (i1) == CALL_INSN
- && !rtx_equal_p (CALL_INSN_FUNCTION_USAGE (i1),
- CALL_INSN_FUNCTION_USAGE (i2)))
+ && (!rtx_equal_p (CALL_INSN_FUNCTION_USAGE (i1),
+ CALL_INSN_FUNCTION_USAGE (i2))
+ || SIBLING_CALL_P (i1) != SIBLING_CALL_P (i2)))
return false;
#ifdef STACK_REGS
/* If BB1 has only one successor, we may be looking at either an
unconditional jump, or a fake edge to exit. */
if (bb1->succ && !bb1->succ->succ_next
- && !(bb1->succ->flags & (EDGE_COMPLEX | EDGE_FAKE)))
+ && (bb1->succ->flags & (EDGE_COMPLEX | EDGE_FAKE)) == 0
+ && (GET_CODE (bb1->end) != JUMP_INSN || simplejump_p (bb1->end)))
return (bb2->succ && !bb2->succ->succ_next
- && (bb2->succ->flags & (EDGE_COMPLEX | EDGE_FAKE)) == 0);
+ && (bb2->succ->flags & (EDGE_COMPLEX | EDGE_FAKE)) == 0
+ && (GET_CODE (bb2->end) != JUMP_INSN || simplejump_p (bb2->end)));
/* Match conditional jumps - this may get tricky when fallthru and branch
edges are crossed. */
|| !onlyjump_p (bb2->end))
return false;
- /* Do not crossjump across loop boundaries. This is a temporary
- workaround for the common scenario in which crossjumping results
- in killing the duplicated loop condition, making bb-reorder rotate
- the loop incorectly, leaving an extra unconditional jump inside
- the loop.
-
- This check should go away once bb-reorder knows how to duplicate
- code in this case or rotate the loops to avoid this scenario. */
- if (bb1->loop_depth != bb2->loop_depth)
- return false;
-
b1 = BRANCH_EDGE (bb1);
b2 = BRANCH_EDGE (bb2);
f1 = FALLTHRU_EDGE (bb1);
return match;
}
- /* Generic case - we are seeing an computed jump, table jump or trapping
+ /* Generic case - we are seeing a computed jump, table jump or trapping
instruction. */
/* First ensure that the instructions match. There may be many outgoing
{
int nmatch;
basic_block src1 = e1->src, src2 = e2->src;
- basic_block redirect_to;
+ basic_block redirect_to, redirect_from, to_remove;
rtx newpos1, newpos2;
edge s;
- rtx last;
- rtx label;
/* Search backward through forwarder blocks. We don't need to worry
about multiple entry or chained forwarders, as they will be optimized
if (GET_CODE (newpos1) == NOTE)
newpos1 = NEXT_INSN (newpos1);
- last = src1->end;
-
- /* Emit the jump insn. */
- label = block_label (redirect_to);
- emit_jump_insn_after (gen_jump (label), src1->end);
- JUMP_LABEL (src1->end) = label;
- LABEL_NUSES (label)++;
-
- /* Delete the now unreachable instructions. */
- delete_insn_chain (newpos1, last);
- /* Make sure there is a barrier after the new jump. */
- last = next_nonnote_insn (src1->end);
- if (!last || GET_CODE (last) != BARRIER)
- emit_barrier_after (src1->end);
+ redirect_from = split_block (src1, PREV_INSN (newpos1))->src;
+ to_remove = redirect_from->succ->dest;
- /* Update CFG. */
- while (src1->succ)
- remove_edge (src1->succ);
- make_single_succ_edge (src1, redirect_to, 0);
+ redirect_edge_and_branch_force (redirect_from->succ, redirect_to);
+ flow_delete_block (to_remove);
- update_forwarder_flag (src1);
+ update_forwarder_flag (redirect_from);
return true;
}
&& !(s->flags & EDGE_COMPLEX)
&& (c = s->dest) != EXIT_BLOCK_PTR
&& c->pred->pred_next == NULL
+ && b != c
/* If the jump insn has side effects,
we can't kill the edge. */
&& (GET_CODE (b->end) != JUMP_INSN
{
changed = true;
/* We've possibly created trivially dead code. Cleanup it right
- now to introduce more oppurtunities for try_optimize_cfg. */
+ now to introduce more opportunities for try_optimize_cfg. */
if (!(mode & (CLEANUP_NO_INSN_DEL
| CLEANUP_UPDATE_LIFE | CLEANUP_PRE_SIBCALL))
&& !reload_completed)
delete_unreachable_blocks (), changed = true;
if (mode & CLEANUP_UPDATE_LIFE)
{
- /* Cleaning up CFG introduces more oppurtunities for dead code
- removal that in turn may introduce more oppurtunities for
+ /* Cleaning up CFG introduces more opportunities for dead code
+ removal that in turn may introduce more opportunities for
cleaning up the CFG. */
if (!update_life_info_in_dirty_blocks (UPDATE_LIFE_GLOBAL_RM_NOTES,
PROP_DEATH_NOTES