Commit d804ed43 by Richard Henderson Committed by Richard Henderson

expr.c (do_jump_for_compare): Handle conditional branch expanders emitting…

expr.c (do_jump_for_compare): Handle conditional branch expanders emitting multiple jump instructions.

        * expr.c (do_jump_for_compare): Handle conditional branch expanders
        emitting multiple jump instructions.
        * jump.c (condjump_label): New function.
        * rtl.h (condjump_label): Declare it.

From-SVN: r24773
parent c14c6529
Tue Jan 19 21:20:52 1999 Richard Henderson <rth@cygnus.com>
* expr.c (do_jump_for_compare): Handle conditional branch expanders
emitting multiple jump instructions.
* jump.c (condjump_label): New function.
* rtl.h (condjump_label): Declare it.
Tue Jan 19 21:08:20 1999 Richard Henderson <rth@cygnus.com> Tue Jan 19 21:08:20 1999 Richard Henderson <rth@cygnus.com>
* expr.c (emit_move_insn_1): Revert 17 Dec change. Don't emit * expr.c (emit_move_insn_1): Revert 17 Dec change. Don't emit
......
...@@ -11008,7 +11008,8 @@ do_jump_for_compare (comparison, if_false_label, if_true_label) ...@@ -11008,7 +11008,8 @@ do_jump_for_compare (comparison, if_false_label, if_true_label)
if (if_true_label) if (if_true_label)
{ {
if (bcc_gen_fctn[(int) GET_CODE (comparison)] != 0) if (bcc_gen_fctn[(int) GET_CODE (comparison)] != 0)
emit_jump_insn ((*bcc_gen_fctn[(int) GET_CODE (comparison)]) (if_true_label)); emit_jump_insn ((*bcc_gen_fctn[(int) GET_CODE (comparison)])
(if_true_label));
else else
abort (); abort ();
...@@ -11017,52 +11018,80 @@ do_jump_for_compare (comparison, if_false_label, if_true_label) ...@@ -11017,52 +11018,80 @@ do_jump_for_compare (comparison, if_false_label, if_true_label)
} }
else if (if_false_label) else if (if_false_label)
{ {
rtx insn; rtx first = get_last_insn (), insn, branch;
rtx prev = get_last_insn (); int br_count;
rtx branch = 0;
/* Output the branch with the opposite condition. Then try to invert /* Output the branch with the opposite condition. Then try to invert
what is generated. If more than one insn is a branch, or if the what is generated. If more than one insn is a branch, or if the
branch is not the last insn written, abort. If we can't invert branch is not the last insn written, abort. If we can't invert
the branch, emit make a true label, redirect this jump to that, the branch, emit make a true label, redirect this jump to that,
emit a jump to the false label and define the true label. */ emit a jump to the false label and define the true label. */
/* ??? Note that we wouldn't have to do any of this nonsense if
we passed both labels into a combined compare-and-branch.
Ah well, jump threading does a good job of repairing the damage. */
if (bcc_gen_fctn[(int) GET_CODE (comparison)] != 0) if (bcc_gen_fctn[(int) GET_CODE (comparison)] != 0)
emit_jump_insn ((*bcc_gen_fctn[(int) GET_CODE (comparison)])(if_false_label)); emit_jump_insn ((*bcc_gen_fctn[(int) GET_CODE (comparison)])
(if_false_label));
else else
abort (); abort ();
/* Here we get the first insn that was just emitted. It used to be the /* Here we get the first insn that was just emitted. It used to be the
case that, on some machines, emitting the branch would discard case that, on some machines, emitting the branch would discard
the previous compare insn and emit a replacement. This isn't the previous compare insn and emit a replacement. This isn't
done anymore, but abort if we see that PREV is deleted. */ done anymore, but abort if we see that PREV is deleted. */
if (prev == 0) if (first == 0)
insn = get_insns (); first = get_insns ();
else if (INSN_DELETED_P (prev)) else if (INSN_DELETED_P (first))
abort (); abort ();
else else
insn = NEXT_INSN (prev); first = NEXT_INSN (first);
for (; insn; insn = NEXT_INSN (insn)) /* Look for multiple branches in this sequence, as might be generated
for a multi-word integer comparison. */
br_count = 0;
branch = NULL_RTX;
for (insn = first; insn ; insn = NEXT_INSN (insn))
if (GET_CODE (insn) == JUMP_INSN) if (GET_CODE (insn) == JUMP_INSN)
{ {
if (branch)
abort ();
branch = insn; branch = insn;
br_count += 1;
} }
if (branch != get_last_insn ()) /* If we've got one branch at the end of the sequence,
abort (); we can try to reverse it. */
JUMP_LABEL (branch) = if_false_label; if (br_count == 1 && NEXT_INSN (branch) == NULL_RTX)
if (! invert_jump (branch, if_false_label))
{ {
if_true_label = gen_label_rtx (); rtx insn_label;
redirect_jump (branch, if_true_label); insn_label = XEXP (condjump_label (branch), 0);
emit_jump (if_false_label); JUMP_LABEL (branch) = insn_label;
emit_label (if_true_label);
if (insn_label != if_false_label)
abort ();
if (invert_jump (branch, if_false_label))
return;
} }
/* Multiple branches, or reversion failed. Convert to branches
around an unconditional jump. */
if_true_label = gen_label_rtx ();
for (insn = first; insn; insn = NEXT_INSN (insn))
if (GET_CODE (insn) == JUMP_INSN)
{
rtx insn_label;
insn_label = XEXP (condjump_label (insn), 0);
JUMP_LABEL (insn) = insn_label;
if (insn_label == if_false_label)
redirect_jump (insn, if_true_label);
}
emit_jump (if_false_label);
emit_label (if_true_label);
} }
} }
......
...@@ -3402,6 +3402,32 @@ condjump_in_parallel_p (insn) ...@@ -3402,6 +3402,32 @@ condjump_in_parallel_p (insn)
return 0; return 0;
} }
/* Return the label of a conditional jump. */
rtx
condjump_label (insn)
rtx insn;
{
register rtx x = PATTERN (insn);
if (GET_CODE (x) == PARALLEL)
x = XVECEXP (x, 0, 0);
if (GET_CODE (x) != SET)
return NULL_RTX;
if (GET_CODE (SET_DEST (x)) != PC)
return NULL_RTX;
x = SET_SRC (x);
if (GET_CODE (x) == LABEL_REF)
return x;
if (GET_CODE (x) != IF_THEN_ELSE)
return NULL_RTX;
if (XEXP (x, 2) == pc_rtx && GET_CODE (XEXP (x, 1)) == LABEL_REF)
return XEXP (x, 1);
if (XEXP (x, 1) == pc_rtx && GET_CODE (XEXP (x, 2)) == LABEL_REF)
return XEXP (x, 2);
return NULL_RTX;
}
#ifdef HAVE_cc0 #ifdef HAVE_cc0
/* Return 1 if X is an RTX that does nothing but set the condition codes /* Return 1 if X is an RTX that does nothing but set the condition codes
......
...@@ -1289,6 +1289,7 @@ extern void cse_end_of_basic_block PROTO ((rtx, ...@@ -1289,6 +1289,7 @@ extern void cse_end_of_basic_block PROTO ((rtx,
/* In jump.c */ /* In jump.c */
extern int comparison_dominates_p PROTO ((enum rtx_code, enum rtx_code)); extern int comparison_dominates_p PROTO ((enum rtx_code, enum rtx_code));
extern int condjump_p PROTO ((rtx)); extern int condjump_p PROTO ((rtx));
extern rtx condjump_label PROTO ((rtx));
extern int simplejump_p PROTO ((rtx)); extern int simplejump_p PROTO ((rtx));
extern int sets_cc0_p PROTO ((rtx)); extern int sets_cc0_p PROTO ((rtx));
extern int invert_jump PROTO ((rtx, rtx)); extern int invert_jump PROTO ((rtx, rtx));
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment