#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)
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));
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 ();
}
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;
+
+ /* 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.
int first = 1;
int max_uid = 0;
rtx last_insn;
-#ifdef HAVE_trap
- enum rtx_code reversed_code;
-#endif
cross_jump_death_matters = (cross_jump == 2);
max_uid = init_label_info (f) + 1;
changed = 1;
next = NEXT_INSN (insn);
}
-
-#ifdef HAVE_trap
- /* Detect a conditional jump jumping over an unconditional trap. */
- if (HAVE_trap
- && this_is_any_condjump && this_is_onlyjump
- && reallabelprev != 0
- && GET_CODE (reallabelprev) == INSN
- && GET_CODE (PATTERN (reallabelprev)) == TRAP_IF
- && TRAP_CONDITION (PATTERN (reallabelprev)) == const_true_rtx
- && prev_active_insn (reallabelprev) == insn
- && no_labels_between_p (insn, reallabelprev)
- && (temp2 = get_condition (insn, &temp4))
- && ((reversed_code = reversed_comparison_code (temp2, insn))
- != UNKNOWN))
- {
- rtx new = gen_cond_trap (reversed_code,
- XEXP (temp2, 0), XEXP (temp2, 1),
- TRAP_CODE (PATTERN (reallabelprev)));
-
- if (new)
- {
- emit_insn_before (new, temp4);
- delete_insn (reallabelprev);
- delete_jump (insn);
- changed = 1;
- continue;
- }
- }
- /* Detect a jump jumping to an unconditional trap. */
- else if (HAVE_trap && this_is_onlyjump
- && (temp = next_active_insn (JUMP_LABEL (insn)))
- && GET_CODE (temp) == INSN
- && GET_CODE (PATTERN (temp)) == TRAP_IF
- && (this_is_any_uncondjump
- || (this_is_any_condjump
- && (temp2 = get_condition (insn, &temp4)))))
- {
- rtx tc = TRAP_CONDITION (PATTERN (temp));
-
- if (tc == const_true_rtx
- || (! this_is_any_uncondjump && rtx_equal_p (temp2, tc)))
- {
- rtx new;
- /* Replace an unconditional jump to a trap with a trap. */
- if (this_is_any_uncondjump)
- {
- emit_barrier_after (emit_insn_before (gen_trap (), insn));
- delete_jump (insn);
- changed = 1;
- continue;
- }
- new = gen_cond_trap (GET_CODE (temp2), XEXP (temp2, 0),
- XEXP (temp2, 1),
- TRAP_CODE (PATTERN (temp)));
- if (new)
- {
- emit_insn_before (new, temp4);
- delete_jump (insn);
- changed = 1;
- continue;
- }
- }
- /* If the trap condition and jump condition are mutually
- exclusive, redirect the jump to the following insn. */
- else if (GET_RTX_CLASS (GET_CODE (tc)) == '<'
- && this_is_any_condjump
- && swap_condition (GET_CODE (temp2)) == GET_CODE (tc)
- && rtx_equal_p (XEXP (tc, 0), XEXP (temp2, 0))
- && rtx_equal_p (XEXP (tc, 1), XEXP (temp2, 1))
- && redirect_jump (insn, get_label_after (temp), 1))
- {
- changed = 1;
- continue;
- }
- }
-#endif
else
{
/* Now that the jump has been tensioned,