From d804ed43d00126b959d19621d7c546463d990e1a Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 19 Jan 1999 13:30:48 -0800 Subject: [PATCH] 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 --- gcc/ChangeLog | 7 +++++ gcc/expr.c | 71 ++++++++++++++++++++++++++++++++++++--------------- gcc/jump.c | 26 +++++++++++++++++++ gcc/rtl.h | 1 + 4 files changed, 84 insertions(+), 21 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index bfd8a0b0151..572ce6cd7d5 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +Tue Jan 19 21:20:52 1999 Richard Henderson + + * 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 * expr.c (emit_move_insn_1): Revert 17 Dec change. Don't emit diff --git a/gcc/expr.c b/gcc/expr.c index 88ce1560c5c..591c82613a1 100644 --- a/gcc/expr.c +++ b/gcc/expr.c @@ -11008,7 +11008,8 @@ do_jump_for_compare (comparison, if_false_label, if_true_label) if (if_true_label) { 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 abort (); @@ -11017,52 +11018,80 @@ do_jump_for_compare (comparison, if_false_label, if_true_label) } else if (if_false_label) { - rtx insn; - rtx prev = get_last_insn (); - rtx branch = 0; + rtx first = get_last_insn (), insn, branch; + int br_count; /* 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 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, 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) - 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 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 the previous compare insn and emit a replacement. This isn't done anymore, but abort if we see that PREV is deleted. */ - if (prev == 0) - insn = get_insns (); - else if (INSN_DELETED_P (prev)) + if (first == 0) + first = get_insns (); + else if (INSN_DELETED_P (first)) abort (); 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 (branch) - abort (); branch = insn; + br_count += 1; } - if (branch != get_last_insn ()) - abort (); + /* If we've got one branch at the end of the sequence, + we can try to reverse it. */ - JUMP_LABEL (branch) = if_false_label; - if (! invert_jump (branch, if_false_label)) + if (br_count == 1 && NEXT_INSN (branch) == NULL_RTX) { - if_true_label = gen_label_rtx (); - redirect_jump (branch, if_true_label); - emit_jump (if_false_label); - emit_label (if_true_label); + rtx insn_label; + insn_label = XEXP (condjump_label (branch), 0); + JUMP_LABEL (branch) = insn_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); } } diff --git a/gcc/jump.c b/gcc/jump.c index d5af17c8ad9..47f5fd4cb7f 100644 --- a/gcc/jump.c +++ b/gcc/jump.c @@ -3402,6 +3402,32 @@ condjump_in_parallel_p (insn) 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 /* Return 1 if X is an RTX that does nothing but set the condition codes diff --git a/gcc/rtl.h b/gcc/rtl.h index 0fef1a75ed5..76fc6e11263 100644 --- a/gcc/rtl.h +++ b/gcc/rtl.h @@ -1289,6 +1289,7 @@ extern void cse_end_of_basic_block PROTO ((rtx, /* In jump.c */ extern int comparison_dominates_p PROTO ((enum rtx_code, enum rtx_code)); extern int condjump_p PROTO ((rtx)); +extern rtx condjump_label PROTO ((rtx)); extern int simplejump_p PROTO ((rtx)); extern int sets_cc0_p PROTO ((rtx)); extern int invert_jump PROTO ((rtx, rtx)); -- 2.30.2