#ifndef HAVE_decscc
#define HAVE_decscc 0
#endif
+#ifndef HAVE_trap
+#define HAVE_trap 0
+#endif
+#ifndef HAVE_conditional_trap
+#define HAVE_conditional_trap 0
+#endif
#ifndef MAX_CONDITIONAL_EXECUTE
#define MAX_CONDITIONAL_EXECUTE (BRANCH_COST + 1)
/* # of basic blocks that were removed. */
static int num_removed_blocks;
+/* True if life data ok at present. */
+static bool life_data_ok;
+
/* The post-dominator relation on the original block numbers. */
static sbitmap *post_dominators;
static int find_if_block PARAMS ((basic_block, edge, edge));
static int find_if_case_1 PARAMS ((basic_block, edge, edge));
static int find_if_case_2 PARAMS ((basic_block, edge, edge));
+static int find_cond_trap PARAMS ((basic_block, edge, edge));
static int find_memory PARAMS ((rtx *, void *));
static int dead_or_predicable PARAMS ((basic_block, basic_block,
basic_block, rtx, int));
reverse the condition. */
if (GET_CODE (XEXP (test_if, 2)) == LABEL_REF
&& XEXP (XEXP (test_if, 2), 0) == JUMP_LABEL (jump))
- cond = gen_rtx_fmt_ee (reverse_condition (GET_CODE (cond)),
- GET_MODE (cond), XEXP (cond, 0),
- XEXP (cond, 1));
+ {
+ enum rtx_code rev = reversed_comparison_code (cond, jump);
+ if (rev == UNKNOWN)
+ return NULL_RTX;
+
+ cond = gen_rtx_fmt_ee (rev, GET_MODE (cond), XEXP (cond, 0),
+ XEXP (cond, 1));
+ }
return cond;
}
rtx true_prob_val; /* probability of else block */
rtx false_prob_val; /* probability of then block */
int n_insns;
+ enum rtx_code false_code;
/* Find the conditional jump to the ELSE or JOIN part, and isolate
the test. */
the conditionally executed code. */
true_expr = test_expr;
- false_expr = gen_rtx_fmt_ee (reverse_condition (GET_CODE (true_expr)),
- GET_MODE (true_expr), XEXP (true_expr, 0),
- XEXP (true_expr, 1));
+
+ false_code = reversed_comparison_code (true_expr, test_bb->end);
+ if (false_code != UNKNOWN)
+ false_expr = gen_rtx_fmt_ee (false_code, GET_MODE (true_expr),
+ XEXP (true_expr, 0), XEXP (true_expr, 1));
+ else
+ false_expr = NULL_RTX;
#ifdef IFCVT_MODIFY_TESTS
/* If the machine description needs to modify the tests, such as setting a
to conditional execution. */
if (then_end
- && ! cond_exec_process_insns (then_start, then_end,
- false_expr, false_prob_val, then_mod_ok))
+ && (! false_expr
+ || ! cond_exec_process_insns (then_start, then_end, false_expr,
+ false_prob_val, then_mod_ok)))
goto fail;
if (else_bb
if (MEM_SCALAR_P (if_info->a) && MEM_SCALAR_P (if_info->b))
MEM_SCALAR_P (tmp) = 1;
if (MEM_ALIAS_SET (if_info->a) == MEM_ALIAS_SET (if_info->b))
- MEM_ALIAS_SET (tmp) = MEM_ALIAS_SET (if_info->a);
+ set_mem_alias_set (tmp, MEM_ALIAS_SET (if_info->a));
noce_emit_move_insn (if_info->x, tmp);
}
/* First merge TEST block into THEN block. This is a no-brainer since
the THEN block did not have a code label to begin with. */
- if (combo_bb->global_live_at_end)
+ if (life_data_ok)
COPY_REG_SET (combo_bb->global_live_at_end, then_bb->global_live_at_end);
merge_blocks_nomove (combo_bb, then_bb);
num_removed_blocks++;
if (combo_bb->succ == NULL_EDGE)
abort ();
- /* There should sill be a branch at the end of the THEN or ELSE
+ /* There should still be a branch at the end of the THEN or ELSE
blocks taking us to our final destination. */
- if (! any_uncondjump_p (combo_bb->end)
- && ! returnjump_p (combo_bb->end))
+ if (GET_CODE (combo_bb->end) != JUMP_INSN)
abort ();
}
else if (join_bb->pred == NULL || join_bb->pred->pred_next == NULL)
{
/* We can merge the JOIN. */
- if (combo_bb->global_live_at_end)
+ if (life_data_ok)
COPY_REG_SET (combo_bb->global_live_at_end,
join_bb->global_live_at_end);
merge_blocks_nomove (combo_bb, join_bb);
if (find_if_block (test_bb, then_edge, else_edge))
goto success;
+ if (HAVE_trap && HAVE_conditional_trap
+ && find_cond_trap (test_bb, then_edge, else_edge))
+ goto success;
if (post_dominators
&& (! HAVE_conditional_execution || reload_completed))
{
return process_if_block (test_bb, then_bb, else_bb, join_bb);
}
+/* Convert a branch over a trap, or a branch to a trap,
+ into a conditional trap. */
+
+static int
+find_cond_trap (test_bb, then_edge, else_edge)
+ basic_block test_bb;
+ edge then_edge, else_edge;
+{
+ basic_block then_bb, else_bb, join_bb, trap_bb;
+ rtx trap, jump, cond, cond_earliest, seq;
+ enum rtx_code code;
+
+ then_bb = then_edge->dest;
+ else_bb = else_edge->dest;
+ join_bb = NULL;
+
+ /* Locate the block with the trap instruction. */
+ /* ??? While we look for no successors, we really ought to allow
+ EH successors. Need to fix merge_if_block for that to work. */
+ /* ??? We can't currently handle merging the blocks if they are not
+ already adjacent. Prevent losage in merge_if_block by detecting
+ this now. */
+ if (then_bb->succ == NULL)
+ {
+ trap_bb = then_bb;
+ if (else_bb->index != then_bb->index + 1)
+ return FALSE;
+ join_bb = else_bb;
+ else_bb = NULL;
+ }
+ else if (else_bb->succ == NULL)
+ {
+ trap_bb = else_bb;
+ if (else_bb->index != then_bb->index + 1)
+ else_bb = NULL;
+ else if (then_bb->succ
+ && ! then_bb->succ->succ_next
+ && ! (then_bb->succ->flags & EDGE_COMPLEX)
+ && then_bb->succ->dest->index == else_bb->index + 1)
+ join_bb = then_bb->succ->dest;
+ }
+ else
+ return FALSE;
+
+ /* Don't confuse a conditional return with something we want to
+ optimize here. */
+ if (trap_bb == EXIT_BLOCK_PTR)
+ return FALSE;
+
+ /* The only instruction in the THEN block must be the trap. */
+ trap = first_active_insn (trap_bb);
+ if (! (trap == trap_bb->end
+ && GET_CODE (PATTERN (trap)) == TRAP_IF
+ && TRAP_CONDITION (PATTERN (trap)) == const_true_rtx))
+ return FALSE;
+
+ if (rtl_dump_file)
+ {
+ if (trap_bb == then_bb)
+ fprintf (rtl_dump_file,
+ "\nTRAP-IF block found, start %d, trap %d",
+ test_bb->index, then_bb->index);
+ else
+ fprintf (rtl_dump_file,
+ "\nTRAP-IF block found, start %d, then %d, trap %d",
+ test_bb->index, then_bb->index, trap_bb->index);
+ if (join_bb)
+ fprintf (rtl_dump_file, ", join %d\n", join_bb->index);
+ else
+ fputc ('\n', rtl_dump_file);
+ }
+
+ /* If this is not a standard conditional jump, we can't parse it. */
+ jump = test_bb->end;
+ cond = noce_get_condition (jump, &cond_earliest);
+ if (! cond)
+ return FALSE;
+
+ /* If the conditional jump is more than just a conditional jump,
+ then we can not do if-conversion on this block. */
+ if (! onlyjump_p (jump))
+ return FALSE;
+
+ /* We must be comparing objects whose modes imply the size. */
+ if (GET_MODE (XEXP (cond, 0)) == BLKmode)
+ return FALSE;
+
+ /* Reverse the comparison code, if necessary. */
+ code = GET_CODE (cond);
+ if (then_bb == trap_bb)
+ {
+ code = reversed_comparison_code (cond, jump);
+ if (code == UNKNOWN)
+ return FALSE;
+ }
+
+ /* Attempt to generate the conditional trap. */
+ seq = gen_cond_trap (code, XEXP (cond, 0), XEXP (cond, 1),
+ TRAP_CODE (PATTERN (trap)));
+ if (seq == NULL)
+ return FALSE;
+
+ /* Emit the new insns before cond_earliest; delete the old jump
+ and trap insns. */
+
+ emit_insn_before (seq, cond_earliest);
+
+ test_bb->end = PREV_INSN (jump);
+ flow_delete_insn (jump);
+
+ trap_bb->end = PREV_INSN (trap);
+ flow_delete_insn (trap);
+
+ /* Merge the blocks! */
+ if (trap_bb != then_bb && ! else_bb)
+ {
+ flow_delete_block (trap_bb);
+ num_removed_blocks++;
+ }
+ merge_if_block (test_bb, then_bb, else_bb, join_bb);
+
+ return TRUE;
+}
+
/* Look for IF-THEN-ELSE cases in which one of THEN or ELSE is
transformable, but not necessarily the other. There need be no
JOIN block.
rtx cond, prob_val;
cond = cond_exec_get_condition (jump);
+ if (! cond)
+ return FALSE;
prob_val = find_reg_note (jump, REG_BR_PROB, NULL_RTX);
if (prob_val)
if (reversep)
{
- cond = gen_rtx_fmt_ee (reverse_condition (GET_CODE (cond)),
- GET_MODE (cond), XEXP (cond, 0),
+ enum rtx_code rev = reversed_comparison_code (cond, jump);
+ if (rev == UNKNOWN)
+ return FALSE;
+ cond = gen_rtx_fmt_ee (rev, GET_MODE (cond), XEXP (cond, 0),
XEXP (cond, 1));
if (prob_val)
prob_val = GEN_INT (REG_BR_PROB_BASE - INTVAL (prob_val));
JUMP_LABEL (jump) = new_dest;
if (reversep)
- {
- rtx note = find_reg_note (jump, REG_BR_PROB, NULL_RTX);
- if (note)
- XEXP (note, 0) = GEN_INT (REG_BR_PROB_BASE - INTVAL (XEXP (note, 0)));
- }
+ invert_br_probabilities (jump);
/* Move the insns out of MERGE_BB to before the branch. */
if (head != NULL)
/* Main entry point for all if-conversion. */
void
-if_convert (life_data_ok)
- int life_data_ok;
+if_convert (x_life_data_ok)
+ int x_life_data_ok;
{
int block_num;
num_possible_if_blocks = 0;
num_updated_if_blocks = 0;
num_removed_blocks = 0;
+ life_data_ok = (x_life_data_ok != 0);
/* Free up basic_block_for_insn so that we don't have to keep it
up to date, either here or in merge_blocks_nomove. */