aboutsummaryrefslogtreecommitdiff
path: root/gcc/sel-sched-ir.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/sel-sched-ir.c')
-rw-r--r--gcc/sel-sched-ir.c50
1 files changed, 36 insertions, 14 deletions
diff --git a/gcc/sel-sched-ir.c b/gcc/sel-sched-ir.c
index ea1c690d49b..957a3fd10d5 100644
--- a/gcc/sel-sched-ir.c
+++ b/gcc/sel-sched-ir.c
@@ -1360,6 +1360,8 @@ sel_move_insn (expr_t expr, int seqno, insn_t after)
basic_block bb = BLOCK_FOR_INSN (after);
insn_t next = NEXT_INSN (after);
+ /* Assert that in move_op we disconnected this insn properly. */
+ gcc_assert (EXPR_VINSN (INSN_EXPR (insn)) != NULL);
PREV_INSN (insn) = after;
NEXT_INSN (insn) = next;
@@ -1779,7 +1781,7 @@ merge_expr_data (expr_t to, expr_t from, insn_t split_point)
phist->spec_ds);
EXPR_WAS_SUBSTITUTED (to) |= EXPR_WAS_SUBSTITUTED (from);
- EXPR_WAS_RENAMED (to) |= EXPR_WAS_RENAMED (to);
+ EXPR_WAS_RENAMED (to) |= EXPR_WAS_RENAMED (from);
EXPR_CANT_MOVE (to) |= EXPR_CANT_MOVE (from);
update_target_availability (to, from, split_point);
@@ -1825,7 +1827,32 @@ set_unavailable_target_for_expr (expr_t expr, regset lv_set)
{
if (REG_P (EXPR_LHS (expr))
&& bitmap_bit_p (lv_set, REGNO (EXPR_LHS (expr))))
- EXPR_TARGET_AVAILABLE (expr) = false;
+ {
+ /* If it's an insn like r1 = use (r1, ...), and it exists in
+ different forms in each of the av_sets being merged, we can't say
+ whether original destination register is available or not.
+ However, this still works if destination register is not used
+ in the original expression: if the branch at which LV_SET we're
+ looking here is not actually 'other branch' in sense that same
+ expression is available through it (but it can't be determined
+ at computation stage because of transformations on one of the
+ branches), it still won't affect the availability.
+ Liveness of a register somewhere on a code motion path means
+ it's either read somewhere on a codemotion path, live on
+ 'other' branch, live at the point immediately following
+ the original operation, or is read by the original operation.
+ The latter case is filtered out in the condition below.
+ It still doesn't cover the case when register is defined and used
+ somewhere within the code motion path, and in this case we could
+ miss a unifying code motion along both branches using a renamed
+ register, but it won't affect a code correctness since upon
+ an actual code motion a bookkeeping code would be generated. */
+ if (bitmap_bit_p (VINSN_REG_USES (EXPR_VINSN (expr)),
+ REGNO (EXPR_LHS (expr))))
+ EXPR_TARGET_AVAILABLE (expr) = -1;
+ else
+ EXPR_TARGET_AVAILABLE (expr) = false;
+ }
}
else
{
@@ -3489,7 +3516,7 @@ verify_backedges (void)
#endif
/* Tidy the possibly empty block BB. */
-static bool
+bool
maybe_tidy_empty_bb (basic_block bb)
{
basic_block succ_bb, pred_bb;
@@ -3504,6 +3531,8 @@ maybe_tidy_empty_bb (basic_block bb)
|| !(single_pred_edge (bb)->flags & EDGE_FALLTHRU))))
return false;
+ free_data_sets (bb);
+
/* Do not delete BB if it has more than one successor.
That can occur when we moving a jump. */
if (!single_succ_p (bb))
@@ -3588,6 +3617,7 @@ tidy_control_flow (basic_block xbb, bool full_tidying)
basic block we will not get a jump to next instruction, which
can be harmful. */
if (sel_bb_head (xbb) == sel_bb_end (xbb)
+ && !sel_bb_empty_p (xbb)
&& INSN_NOP_P (sel_bb_end (xbb))
/* Flow goes fallthru from current block to the next. */
&& EDGE_COUNT (xbb->succs) == 1
@@ -3611,15 +3641,10 @@ tidy_control_flow (basic_block xbb, bool full_tidying)
remove it too. */
if (sel_bb_empty_p (xbb->prev_bb))
{
- free_data_sets (xbb->prev_bb);
changed = maybe_tidy_empty_bb (xbb->prev_bb);
}
}
-#ifdef ENABLE_CHECKING
- verify_backedges ();
-#endif
-
return changed;
}
@@ -3660,9 +3685,6 @@ sel_remove_insn (insn_t insn, bool only_disconnect, bool full_tidying)
PREV_INSN (insn) = NULL_RTX;
NEXT_INSN (insn) = NULL_RTX;
- if (sel_bb_empty_p (bb))
- free_data_sets (bb);
-
return tidy_control_flow (bb, full_tidying);
}
@@ -5235,7 +5257,7 @@ remove_empty_bb (basic_block empty_bb, bool remove_from_cfg_p)
succ = NULL;
if (EDGE_COUNT (empty_bb->preds) > 0 && succ != NULL)
- redirect_edge_succ_nodup (EDGE_PRED (empty_bb, 0), succ);
+ sel_redirect_edge_and_branch (EDGE_PRED (empty_bb, 0), succ);
if (EDGE_COUNT (empty_bb->succs) > 0 && pred != NULL)
{
@@ -5525,7 +5547,7 @@ sel_redirect_edge_and_branch (edge e, basic_block to)
gcc_assert (loop_latch_edge (current_loop_nest));
}
- gcc_assert (ee == e && last_added_blocks == NULL);
+ gcc_assert (last_added_blocks == NULL);
/* Now the CFG has been updated, and we can init data for the newly
created insns. */
@@ -6182,7 +6204,7 @@ jump_leads_only_to_bb_p (insn_t jump, basic_block dest_bb)
/* It is not jump, jump with side-effects or jump can lead to several
basic blocks. */
if (!onlyjump_p (jump)
- || !any_uncondjump_p(jump))
+ || !any_uncondjump_p (jump))
return false;
/* Several outgoing edges, abnormal edge or destination of jump is