expr.c (do_jump_for_compare): Handle conditional branch expanders emitting multiple...
authorRichard Henderson <rth@cygnus.com>
Tue, 19 Jan 1999 21:30:48 +0000 (13:30 -0800)
committerRichard Henderson <rth@gcc.gnu.org>
Tue, 19 Jan 1999 21:30:48 +0000 (13:30 -0800)
        * 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
gcc/expr.c
gcc/jump.c
gcc/rtl.h

index bfd8a0b0151fcbfd4b77efb941c9876c155e84c3..572ce6cd7d5f3587eb9ff1dc289113de05602894 100644 (file)
@@ -1,3 +1,10 @@
+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>
 
        * expr.c (emit_move_insn_1): Revert 17 Dec change.  Don't emit
index 88ce1560c5cadd2d7e3b5b0bc4852b88ceea3f1b..591c82613a10ebf78794596c59ee222d76d46a9f 100644 (file)
@@ -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);
     }
 }
 \f
index d5af17c8ad96321bda1feb395b0107b1d85d8db0..47f5fd4cb7f4a011a772b616750791e8c0eaba48 100644 (file)
@@ -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
index 0fef1a75ed5fd64bc0890ee50d8cfff5a9958d4d..76fc6e11263b9021cb549267db6299ea3f1bf7e3 100644 (file)
--- 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));