information; we should run df_analyze to enable more opportunities. */
static bool block_was_dirty;
-static bool try_crossjump_to_edge (int, edge, edge);
+static bool try_crossjump_to_edge (int, edge, edge, enum replace_direction);
static bool try_crossjump_bb (int, basic_block);
static bool outgoing_edges_match (int, basic_block, basic_block);
static enum replace_direction old_insns_match_p (int, rtx, rtx);
+ REG_BR_PROB_BASE / 2)
/ REG_BR_PROB_BASE);
- if (!FORWARDER_BLOCK_P (b) && forwarder_block_p (b))
- b->flags |= BB_FORWARDER_BLOCK;
-
do
{
edge t;
ei_next (&ei);
}
- if (threaded_edges)
- free (threaded_edges);
+ free (threaded_edges);
return changed;
}
\f
MEM_ATTRS (x) = 0;
else
{
- rtx mem_size;
+ HOST_WIDE_INT mem_size;
if (MEM_ALIAS_SET (x) != MEM_ALIAS_SET (y))
{
{
set_mem_expr (x, 0);
set_mem_expr (y, 0);
- set_mem_offset (x, 0);
- set_mem_offset (y, 0);
+ clear_mem_offset (x);
+ clear_mem_offset (y);
}
- else if (MEM_OFFSET (x) != MEM_OFFSET (y))
+ else if (MEM_OFFSET_KNOWN_P (x) != MEM_OFFSET_KNOWN_P (y)
+ || (MEM_OFFSET_KNOWN_P (x)
+ && MEM_OFFSET (x) != MEM_OFFSET (y)))
{
- set_mem_offset (x, 0);
- set_mem_offset (y, 0);
+ clear_mem_offset (x);
+ clear_mem_offset (y);
}
- if (!MEM_SIZE (x))
- mem_size = NULL_RTX;
- else if (!MEM_SIZE (y))
- mem_size = NULL_RTX;
+ if (MEM_SIZE_KNOWN_P (x) && MEM_SIZE_KNOWN_P (y))
+ {
+ mem_size = MAX (MEM_SIZE (x), MEM_SIZE (y));
+ set_mem_size (x, mem_size);
+ set_mem_size (y, mem_size);
+ }
else
- mem_size = GEN_INT (MAX (INTVAL (MEM_SIZE (x)),
- INTVAL (MEM_SIZE (y))));
- set_mem_size (x, mem_size);
- set_mem_size (y, mem_size);
+ {
+ clear_mem_size (x);
+ clear_mem_size (y);
+ }
set_mem_align (x, MIN (MEM_ALIGN (x), MEM_ALIGN (y)));
set_mem_align (y, MEM_ALIGN (x));
if (NOTE_INSN_BASIC_BLOCK_P (i1) && NOTE_INSN_BASIC_BLOCK_P (i2))
return dir_both;
+ /* ??? Do not allow cross-jumping between different stack levels. */
+ p1 = find_reg_note (i1, REG_ARGS_SIZE, NULL);
+ p2 = find_reg_note (i2, REG_ARGS_SIZE, NULL);
+ if (p1 && p2)
+ {
+ p1 = XEXP (p1, 0);
+ p2 = XEXP (p2, 0);
+ if (!rtx_equal_p (p1, p2))
+ return dir_none;
+
+ /* ??? Worse, this adjustment had better be constant lest we
+ have differing incoming stack levels. */
+ if (!frame_pointer_needed
+ && find_args_size_adjust (i1) == HOST_WIDE_INT_MIN)
+ return dir_none;
+ }
+ else if (p1 || p2)
+ return dir_none;
+
p1 = PATTERN (i1);
p2 = PATTERN (i2);
/* E1 and E2 are edges with the same destination block. Search their
predecessors for common code. If found, redirect control flow from
- (maybe the middle of) E1->SRC to (maybe the middle of) E2->SRC. */
+ (maybe the middle of) E1->SRC to (maybe the middle of) E2->SRC (dir_forward),
+ or the other way around (dir_backward). DIR specifies the allowed
+ replacement direction. */
static bool
-try_crossjump_to_edge (int mode, edge e1, edge e2)
+try_crossjump_to_edge (int mode, edge e1, edge e2,
+ enum replace_direction dir)
{
int nmatch;
basic_block src1 = e1->src, src2 = e2->src;
basic_block redirect_to, redirect_from, to_remove;
basic_block osrc1, osrc2, redirect_edges_to, tmp;
- enum replace_direction dir;
rtx newpos1, newpos2;
edge s;
edge_iterator ei;
return false;
/* ... and part the second. */
- dir = dir_forward;
nmatch = flow_find_cross_jump (src1, src2, &newpos1, &newpos2, &dir);
osrc1 = src1;
if (newpos2 != NULL_RTX)
src2 = BLOCK_FOR_INSN (newpos2);
+ if (dir == dir_backward)
+ {
+#define SWAP(T, X, Y) do { T tmp = (X); (X) = (Y); (Y) = tmp; } while (0)
+ SWAP (basic_block, osrc1, osrc2);
+ SWAP (basic_block, src1, src2);
+ SWAP (edge, e1, e2);
+ SWAP (rtx, newpos1, newpos2);
+#undef SWAP
+ }
+
/* Don't proceed with the crossjump unless we found a sufficient number
of matching instructions or the 'from' block was totally matched
(such that its predecessors will hopefully be redirected and the
|| (fallthru->src->flags & BB_MODIFIED)))
continue;
- if (try_crossjump_to_edge (mode, e, fallthru))
+ if (try_crossjump_to_edge (mode, e, fallthru, dir_forward))
{
changed = true;
ix = 0;
|| (e2->src->flags & BB_MODIFIED)))
continue;
- if (try_crossjump_to_edge (mode, e, e2))
+ /* Both e and e2 are not fallthru edges, so we can crossjump in either
+ direction. */
+ if (try_crossjump_to_edge (mode, e, e2, dir_both))
{
changed = true;
ix = 0;
/* Simplify branch to branch. */
if (try_forward_edges (mode, b))
- changed_here = true;
+ {
+ update_forwarder_flag (b);
+ changed_here = true;
+ }
/* Look for shared code between blocks. */
if ((mode & CLEANUP_CROSSJUMP)
0, /* properties_provided */
0, /* properties_destroyed */
TODO_ggc_collect, /* todo_flags_start */
- TODO_dump_func | TODO_verify_rtl_sharing,/* todo_flags_finish */
+ TODO_verify_rtl_sharing, /* todo_flags_finish */
}
};
-
-