OSDN Git Service

* ifcvt.c (dead_or_predicable): Don't move code if eh regions
[pf3gnuchains/gcc-fork.git] / gcc / ifcvt.c
index ba310da..a5494b8 100644 (file)
 #include "flags.h"
 #include "insn-config.h"
 #include "recog.h"
+#include "hard-reg-set.h"
 #include "basic-block.h"
 #include "expr.h"
 #include "output.h"
-#include "hard-reg-set.h"
 #include "tm_p.h"
 
 
@@ -51,8 +51,6 @@
 #define MAX_CONDITIONAL_EXECUTE   (BRANCH_COST + 1)
 #endif
 
-#define EDGE_COMPLEX   (EDGE_ABNORMAL | EDGE_ABNORMAL_CALL | EDGE_EH)
-
 #define NULL_EDGE      ((struct edge_def *)NULL)
 #define NULL_BLOCK     ((struct basic_block_def *)NULL)
 
@@ -73,8 +71,9 @@ static sbitmap *post_dominators;
 static int count_bb_insns              PARAMS ((basic_block));
 static rtx first_active_insn           PARAMS ((basic_block));
 static int last_active_insn_p          PARAMS ((basic_block, rtx));
+static int seq_contains_jump           PARAMS ((rtx));
 
-static int cond_exec_process_insns     PARAMS ((rtx, rtx, rtx, int));
+static int cond_exec_process_insns     PARAMS ((rtx, rtx, rtx, rtx, int));
 static rtx cond_exec_get_condition     PARAMS ((rtx));
 static int cond_exec_process_if_block  PARAMS ((basic_block, basic_block,
                                                 basic_block, basic_block));
@@ -173,20 +172,40 @@ last_active_insn_p (bb, insn)
 
   return GET_CODE (insn) == JUMP_INSN;
 }
+
+/* It is possible, especially when having dealt with multi-word 
+   arithmetic, for the expanders to have emitted jumps.  Search
+   through the sequence and return TRUE if a jump exists so that
+   we can abort the conversion.  */
+
+static int
+seq_contains_jump (insn)
+     rtx insn;
+{
+  while (insn)
+    {
+      if (GET_CODE (insn) == JUMP_INSN)
+       return 1;
+      insn = NEXT_INSN (insn);
+    }
+  return 0;
+}
 \f
 /* Go through a bunch of insns, converting them to conditional
    execution format if possible.  Return TRUE if all of the non-note
    insns were processed.  */
 
 static int
-cond_exec_process_insns (start, end, test, mod_ok)
+cond_exec_process_insns (start, end, test, prob_val, mod_ok)
      rtx start;                        /* first insn to look at */
      rtx end;                  /* last insn to look at */
      rtx test;                 /* conditional execution test */
+     rtx prob_val;             /* probability of branch taken.  */
      int mod_ok;               /* true if modifications ok last insn.  */
 {
   int must_be_last = FALSE;
   rtx insn;
+  rtx pattern;
 
   for (insn = start; ; insn = NEXT_INSN (insn))
     {
@@ -196,6 +215,17 @@ cond_exec_process_insns (start, end, test, mod_ok)
       if (GET_CODE (insn) != INSN && GET_CODE (insn) != CALL_INSN)
        abort ();
 
+      /* Remove USE insns that get in the way.  */
+      if (reload_completed && GET_CODE (PATTERN (insn)) == USE)
+       {
+         /* ??? Ug.  Actually unlinking the thing is problematic, 
+            given what we'd have to coordinate with our callers.  */
+         PUT_CODE (insn, NOTE);
+         NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
+         NOTE_SOURCE_FILE (insn) = 0;
+         goto insn_done;
+       }
+
       /* Last insn wasn't last?  */
       if (must_be_last)
        return FALSE;
@@ -208,9 +238,25 @@ cond_exec_process_insns (start, end, test, mod_ok)
        }
 
       /* Now build the conditional form of the instruction.  */
+      pattern = PATTERN (insn);
+
+      /* If the machine needs to modify the insn being conditionally executed,
+         say for example to force a constant integer operand into a temp
+         register, do so here.  */
+#ifdef IFCVT_MODIFY_INSN
+      IFCVT_MODIFY_INSN (pattern, insn);
+      if (! pattern)
+       return FALSE;
+#endif
+
       validate_change (insn, &PATTERN (insn),
                       gen_rtx_COND_EXEC (VOIDmode, copy_rtx (test),
-                                         PATTERN (insn)), 1);
+                                         pattern), 1);
+
+      if (GET_CODE (insn) == CALL_INSN && prob_val)
+       validate_change (insn, &REG_NOTES (insn),
+                        alloc_EXPR_LIST (REG_BR_PROB, prob_val,
+                                         REG_NOTES (insn)), 1);
 
     insn_done:
       if (insn == end)
@@ -228,10 +274,8 @@ cond_exec_get_condition (jump)
 {
   rtx test_if, cond;
 
-  if (condjump_p (jump))
-    test_if = SET_SRC (PATTERN (jump));
-  else if (condjump_in_parallel_p (jump))
-    test_if = SET_SRC (XVECEXP (PATTERN (jump), 0, 0));
+  if (any_condjump_p (jump))
+    test_if = SET_SRC (pc_set (jump));
   else
     return NULL_RTX;
   cond = XEXP (test_if, 0);
@@ -261,12 +305,14 @@ cond_exec_process_if_block (test_bb, then_bb, else_bb, join_bb)
   rtx test_expr;               /* expression in IF_THEN_ELSE that is tested */
   rtx then_start;              /* first insn in THEN block */
   rtx then_end;                        /* last insn + 1 in THEN block */
-  rtx else_start;              /* first insn in ELSE block or NULL */
-  rtx else_end;                        /* last insn + 1 in ELSE block */
+  rtx else_start = NULL_RTX;   /* first insn in ELSE block or NULL */
+  rtx else_end = NULL_RTX;     /* last insn + 1 in ELSE block */
   int max;                     /* max # of insns to convert. */
   int then_mod_ok;             /* whether conditional mods are ok in THEN */
   rtx true_expr;               /* test for else block insns */
   rtx false_expr;              /* test for then block insns */
+  rtx true_prob_val;           /* probability of else block */
+  rtx false_prob_val;          /* probability of then block */
   int n_insns;
 
   /* Find the conditional jump to the ELSE or JOIN part, and isolate
@@ -275,11 +321,20 @@ cond_exec_process_if_block (test_bb, then_bb, else_bb, join_bb)
   if (! test_expr)
     return FALSE;
 
+  /* If the conditional jump is more than just a conditional jump,
+     then we can not do conditional execution conversion on this block.  */
+  if (!onlyjump_p (test_bb->end))
+    return FALSE;
+
   /* Collect the bounds of where we're to search.  */
 
   then_start = then_bb->head;
   then_end = then_bb->end;
 
+  /* Skip a label heading THEN block.  */
+  if (GET_CODE (then_start) == CODE_LABEL)
+    then_start = NEXT_INSN (then_start);
+
   /* Skip a (use (const_int 0)) or branch as the final insn.  */
   if (GET_CODE (then_end) == INSN
       && GET_CODE (PATTERN (then_end)) == USE
@@ -324,6 +379,26 @@ cond_exec_process_if_block (test_bb, then_bb, else_bb, join_bb)
                               GET_MODE (true_expr), XEXP (true_expr, 0),
                               XEXP (true_expr, 1));
 
+#ifdef IFCVT_MODIFY_TESTS
+  /* If the machine description needs to modify the tests, such as setting a
+     conditional execution register from a comparison, it can do so here.  */
+  IFCVT_MODIFY_TESTS (true_expr, false_expr, test_bb, then_bb, else_bb,
+                     join_bb);
+
+  /* See if the conversion failed */
+  if (!true_expr || !false_expr)
+    goto fail;
+#endif
+
+  true_prob_val = find_reg_note (test_bb->end, REG_BR_PROB, NULL_RTX);
+  if (true_prob_val)
+    {
+      true_prob_val = XEXP (true_prob_val, 0);
+      false_prob_val = GEN_INT (REG_BR_PROB_BASE - INTVAL (true_prob_val));
+    }
+  else
+    false_prob_val = NULL_RTX;
+
   /* For IF-THEN-ELSE blocks, we don't allow modifications of the test
      on then THEN block.  */
   then_mod_ok = (else_bb == NULL_BLOCK);
@@ -333,17 +408,22 @@ cond_exec_process_if_block (test_bb, then_bb, else_bb, join_bb)
 
   if (then_end
       && ! cond_exec_process_insns (then_start, then_end,
-                                   false_expr, then_mod_ok))
+                                   false_expr, false_prob_val, then_mod_ok))
     goto fail;
 
   if (else_bb
       && ! cond_exec_process_insns (else_start, else_end,
-                                   true_expr, TRUE))
+                                   true_expr, true_prob_val, TRUE))
     goto fail;
 
   if (! apply_change_group ())
     return FALSE;
 
+#ifdef IFCVT_MODIFY_FINAL
+  /* Do any machine dependent final modifications */
+  IFCVT_MODIFY_FINAL (test_bb, then_bb, else_bb, join_bb);
+#endif
+
   /* Conversion succeeded.  */
   if (rtl_dump_file)
     fprintf (rtl_dump_file, "%d insn%s converted to conditional execution.\n",
@@ -354,6 +434,11 @@ cond_exec_process_if_block (test_bb, then_bb, else_bb, join_bb)
   return TRUE;
 
  fail:
+#ifdef IFCVT_MODIFY_CANCEL
+  /* Cancel any machine dependent changes.  */
+  IFCVT_MODIFY_CANCEL (test_bb, then_bb, else_bb, join_bb);
+#endif
+
   cancel_changes (0);
   return FALSE;
 }
@@ -402,7 +487,7 @@ noce_emit_store_flag (if_info, x, reversep, normalize)
      build the store_flag insn directly.  */
 
   if (cond_complex)
-    cond = XEXP (SET_SRC (PATTERN (if_info->jump)), 0);
+    cond = XEXP (SET_SRC (pc_set (if_info->jump)), 0);
 
   if ((if_info->cond_earliest == if_info->jump || cond_complex)
       && (normalize == 0 || STORE_FLAG_VALUE == normalize))
@@ -605,6 +690,10 @@ noce_try_store_flag_constants (if_info)
 
       seq = get_insns ();
       end_sequence ();
+
+      if (seq_contains_jump (seq))
+       return FALSE;
+
       emit_insns_before (seq, if_info->cond_earliest);
 
       return TRUE;
@@ -659,6 +748,10 @@ noce_try_store_flag_inc (if_info)
 
          seq = get_insns ();
          end_sequence ();
+
+         if (seq_contains_jump (seq))
+           return FALSE;
+
          emit_insns_before (seq, if_info->cond_earliest);
 
          return TRUE;
@@ -706,6 +799,10 @@ noce_try_store_flag_mask (if_info)
 
          seq = get_insns ();
          end_sequence ();
+
+         if (seq_contains_jump (seq))
+           return FALSE;
+
          emit_insns_before (seq, if_info->cond_earliest);
 
          return TRUE;
@@ -758,10 +855,18 @@ noce_emit_cmove (if_info, x, code, cmp_a, cmp_b, vfalse, vtrue)
       || ! general_operand (cmp_b, GET_MODE (cmp_b)))
     return NULL_RTX;
 
+#if HAVE_conditional_move
   return emit_conditional_move (x, code, cmp_a, cmp_b, VOIDmode,
                                vtrue, vfalse, GET_MODE (x),
                                (code == LTU || code == GEU
                                 || code == LEU || code == GTU));
+#else
+  /* We'll never get here, as noce_process_if_block doesn't call the
+     functions involved.  Ifdef code, however, should be discouraged
+     because it leads to typos in the code not selected.  However, 
+     emit_conditional_move won't exist either.  */
+  return NULL_RTX;
+#endif
 }
 
 /* Try only simple constants and registers here.  More complex cases
@@ -835,9 +940,9 @@ noce_try_cmove_arith (if_info)
     }
 
   /* ??? We could handle this if we knew that a load from A or B could
-     not fault.  This is true of stack memories or if we've already loaded
+     not fault.  This is also true if we've already loaded
      from the address along the path from ENTRY.  */
-  else if (GET_CODE (a) == MEM || GET_CODE (b) == MEM)
+  else if (may_trap_p (a) || may_trap_p (b))
     return FALSE;
 
   /* if (test) x = a + b; else x = c - d;
@@ -972,14 +1077,17 @@ noce_get_condition (jump, earliest)
      rtx *earliest;
 {
   rtx cond;
+  rtx set;
 
   /* If the condition variable is a register and is MODE_INT, accept it.
      Otherwise, fall back on get_condition.  */
 
-  if (! condjump_p (jump))
+  if (! any_condjump_p (jump))
     return NULL_RTX;
 
-  cond = XEXP (SET_SRC (PATTERN (jump)), 0);
+  set = pc_set (jump);
+
+  cond = XEXP (SET_SRC (set), 0);
   if (GET_CODE (XEXP (cond, 0)) == REG
       && GET_MODE_CLASS (GET_MODE (XEXP (cond, 0))) == MODE_INT)
     {
@@ -987,8 +1095,8 @@ noce_get_condition (jump, earliest)
 
       /* If this branches to JUMP_LABEL when the condition is false,
         reverse the condition.  */
-      if (GET_CODE (XEXP (SET_SRC (PATTERN (jump)), 2)) == LABEL_REF
-         && XEXP (XEXP (SET_SRC (PATTERN (jump)), 2), 0) == JUMP_LABEL (jump))
+      if (GET_CODE (XEXP (SET_SRC (set), 2)) == LABEL_REF
+         && XEXP (XEXP (SET_SRC (set), 2), 0) == JUMP_LABEL (jump))
        cond = gen_rtx_fmt_ee (reverse_condition (GET_CODE (cond)),
                               GET_MODE (cond), XEXP (cond, 0),
                               XEXP (cond, 1));
@@ -1032,6 +1140,11 @@ noce_process_if_block (test_bb, then_bb, else_bb, join_bb)
   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;
@@ -1046,11 +1159,6 @@ noce_process_if_block (test_bb, then_bb, else_bb, join_bb)
   x = SET_DEST (set_a);
   a = SET_SRC (set_a);
 
-  /* X may not be mentioned between cond_earliest and the jump.  */
-  for (insn = jump; insn != if_info.cond_earliest; insn = PREV_INSN (insn))
-    if (INSN_P (insn) && reg_mentioned_p (x, insn))
-      return FALSE;
-
   /* Look for the other potential set.  Make sure we've got equivalent
      destinations.  */
   /* ??? This is overconservative.  Storing to two different mems is
@@ -1075,11 +1183,24 @@ noce_process_if_block (test_bb, then_bb, else_bb, join_bb)
          || GET_CODE (insn_b) != INSN
          || (set_b = single_set (insn_b)) == NULL_RTX
          || ! rtx_equal_p (x, SET_DEST (set_b))
-         || reg_mentioned_p (x, cond))
+         || reg_mentioned_p (x, cond)
+         || reg_mentioned_p (x, a)
+         || reg_mentioned_p (x, SET_SRC (set_b)))
        insn_b = set_b = NULL_RTX;
     }
   b = (set_b ? SET_SRC (set_b) : x);
 
+  /* X may not be mentioned in the range (cond_earliest, jump].  */
+  for (insn = jump; insn != if_info.cond_earliest; insn = PREV_INSN (insn))
+    if (INSN_P (insn) && reg_mentioned_p (x, insn))
+      return FALSE;
+
+  /* A and B may not be modified in the range [cond_earliest, jump).  */
+  for (insn = if_info.cond_earliest; insn != jump; insn = NEXT_INSN (insn))
+    if (INSN_P (insn)
+       && (modified_in_p (a, insn) || modified_in_p (b, insn)))
+      return FALSE;
+
   /* Only operate on register destinations, and even then avoid extending
      the lifetime of hard registers on small register class machines.  */
   orig_x = x;
@@ -1125,8 +1246,13 @@ noce_process_if_block (test_bb, then_bb, else_bb, join_bb)
            else_bb->end = PREV_INSN (insn_b);
          reorder_insns (insn_b, insn_b, PREV_INSN (if_info.cond_earliest));
          insn_b = NULL_RTX;
-         x = orig_x;
        }
+      /* If we have "x = b; if (...) x = a;", and x has side-effects, then
+        x must be executed twice.  */
+      else if (insn_b && side_effects_p (orig_x))
+       return FALSE;
+       
+      x = orig_x;
       goto success;
     }
 
@@ -1242,37 +1368,8 @@ merge_if_block (test_bb, then_bb, else_bb, join_bb)
      get their addresses taken.  */
   if (else_bb)
     {
-      if (LABEL_NUSES (else_bb->head) == 0
-         && ! LABEL_PRESERVE_P (else_bb->head)
-         && ! LABEL_NAME (else_bb->head))
-       {
-         /* We can merge the ELSE.  */
-         merge_blocks_nomove (combo_bb, else_bb);
-         num_removed_blocks++;
-       }
-      else
-       {
-         /* We cannot merge the ELSE.  */
-
-         /* Properly rewire the edge out of the now combined
-            TEST-THEN block to point here.  */
-         remove_edge (combo_bb->succ);
-         if (combo_bb->succ || else_bb->pred)
-           abort ();
-         make_edge (NULL, combo_bb, else_bb, EDGE_FALLTHRU);
-
-         /* Remove the jump and cruft from the end of the TEST-THEN block.  */
-         tidy_fallthru_edge (combo_bb->succ, combo_bb, else_bb);
-
-         /* Make sure we update life info properly.  */
-         SET_UPDATE_LIFE(combo_bb);
-         if (else_bb->global_live_at_end)
-           COPY_REG_SET (else_bb->global_live_at_start,
-                         else_bb->global_live_at_end);
-
-         /* The ELSE is the new combo block.  */
-         combo_bb = else_bb;
-       }
+      merge_blocks_nomove (combo_bb, else_bb);
+      num_removed_blocks++;
     }
 
   /* If there was no join block reported, that means it was not adjacent
@@ -1292,12 +1389,13 @@ merge_if_block (test_bb, then_bb, else_bb, join_bb)
        abort ();
     }
 
-  /* The JOIN block had a label.  It may have had quite a number
-     of other predecessors too, but probably not.  See if we can
-     merge this with the others.  */
-  else if (LABEL_NUSES (join_bb->head) == 0
-      && ! LABEL_PRESERVE_P (join_bb->head)
-      && ! LABEL_NAME (join_bb->head))
+  /* The JOIN block may have had quite a number of other predecessors too.
+     Since we've already merged the TEST, THEN and ELSE blocks, we should
+     have only one remaining edge from our if-then-else diamond.  If there
+     is more than one remaining edge, it must come from elsewhere.  There
+     may be zero incoming edges if the THEN block didn't actually join 
+     back up (as with a call to 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)
@@ -1399,20 +1497,44 @@ find_if_block (test_bb, then_edge, else_edge)
   if (then_bb->pred->pred_next != NULL_EDGE)
     return FALSE;
 
-  /* The THEN block of an IF-THEN combo must have exactly one successor.  */
-  if (then_succ == NULL_EDGE
-      || then_succ->succ_next != NULL_EDGE
-      || (then_succ->flags & EDGE_COMPLEX))
+  /* The THEN block of an IF-THEN combo must have zero or one successors.  */
+  if (then_succ != NULL_EDGE
+      && (then_succ->succ_next != NULL_EDGE
+          || (then_succ->flags & EDGE_COMPLEX)))
     return FALSE;
 
-  /* The THEN block may not start with a label, as might happen with an
-     unused user label that has had its address taken.  */
-  if (GET_CODE (then_bb->head) == CODE_LABEL)
-    return FALSE;
+  /* If the THEN block has no successors, conditional execution can still
+     make a conditional call.  Don't do this unless the ELSE block has
+     only one incoming edge -- the CFG manipulation is too ugly otherwise.
+     Check for the last insn of the THEN block being an indirect jump, which
+     is listed as not having any successors, but confuses the rest of the CE
+     code processing.  XXX we should fix this in the future.  */
+  if (then_succ == NULL)
+    {
+      if (else_bb->pred->pred_next == NULL_EDGE)
+       {
+         rtx last_insn = then_bb->end;
+
+         while (last_insn
+                && GET_CODE (last_insn) == NOTE
+                && last_insn != then_bb->head)
+           last_insn = PREV_INSN (last_insn);
+
+         if (last_insn
+             && GET_CODE (last_insn) == JUMP_INSN
+             && ! simplejump_p (last_insn))
+           return FALSE;
+
+         join_bb = else_bb;
+         else_bb = NULL_BLOCK;
+       }
+      else
+       return FALSE;
+    }
 
   /* If the THEN block's successor is the other edge out of the TEST block,
      then we have an IF-THEN combo without an ELSE.  */
-  if (then_succ->dest == else_bb)
+  else if (then_succ->dest == else_bb)
     {
       join_bb = else_bb;
       else_bb = NULL_BLOCK;
@@ -1567,10 +1689,6 @@ find_if_case_1 (test_bb, then_edge, else_edge)
   if (then_bb->pred->pred_next != NULL)
     return FALSE;
 
-  /* THEN has no label.  */
-  if (GET_CODE (then_bb->head) == CODE_LABEL)
-    return FALSE;
-
   /* ELSE follows THEN.  (??? could be moved)  */
   if (else_bb->index != then_bb->index + 1)
     return FALSE;
@@ -1641,10 +1759,8 @@ find_if_case_2 (test_bb, then_edge, else_edge)
   if (else_bb->pred->pred_next != NULL)
     return FALSE;
 
-  /* ELSE has a label we can delete.  */
-  if (LABEL_NUSES (else_bb->head) > 1
-      || LABEL_PRESERVE_P (else_bb->head)
-      || LABEL_NAME (else_bb->head))
+  /* THEN is not EXIT.  */
+  if (then_bb->index < 0)
     return FALSE;
 
   /* ELSE is predicted or SUCC(ELSE) postdominates THEN.  */
@@ -1652,9 +1768,8 @@ find_if_case_2 (test_bb, then_edge, else_edge)
   if (note && INTVAL (XEXP (note, 0)) >= REG_BR_PROB_BASE / 2)
     ;
   else if (else_succ->dest->index < 0
-          || (then_bb->index >= 0
-              && TEST_BIT (post_dominators[ORIG_INDEX (then_bb)], 
-                           ORIG_INDEX (else_succ->dest))))
+          || TEST_BIT (post_dominators[ORIG_INDEX (then_bb)], 
+                       ORIG_INDEX (else_succ->dest)))
     ;
   else
     return FALSE;
@@ -1740,6 +1855,15 @@ dead_or_predicable (test_bb, merge_bb, other_bb, new_dest, reversep)
 {
   rtx head, end, jump, earliest, old_dest;
 
+  /* No code movement can occur if we'd be scrogging EH regions.
+     Within MERGE_BB, ensure that we've not got stray EH_BEG or EH_END
+     notes within the block.  Between the blocks, checking that the end
+     region numbers match ensures that we won't disrupt the nesting
+     between regions.  */
+  if (merge_bb->eh_beg != merge_bb->eh_end
+      || merge_bb->eh_end != test_bb->eh_end)
+    return FALSE;
+
   jump = test_bb->end;
 
   /* Find the extent of the real code in the merge block.  */
@@ -1768,6 +1892,9 @@ dead_or_predicable (test_bb, merge_bb, other_bb, new_dest, reversep)
       end = PREV_INSN (end);
     }
 
+  /* Disable handling dead code by conditional execution if the machine needs
+     to do anything funny with the tests, etc.  */
+#ifndef IFCVT_MODIFY_TESTS
   if (HAVE_conditional_execution)
     {
       /* In the conditional execution case, we have things easy.  We know
@@ -1776,20 +1903,30 @@ dead_or_predicable (test_bb, merge_bb, other_bb, new_dest, reversep)
         All that's left is making sure the insns involved can actually
         be predicated.  */
 
-      rtx cond;
+      rtx cond, prob_val;
 
       cond = cond_exec_get_condition (jump);
+
+      prob_val = find_reg_note (jump, REG_BR_PROB, NULL_RTX);
+      if (prob_val)
+       prob_val = XEXP (prob_val, 0);
+
       if (reversep)
-       cond = gen_rtx_fmt_ee (reverse_condition (GET_CODE (cond)),
-                              GET_MODE (cond), XEXP (cond, 0),
-                              XEXP (cond, 1));
+       {
+         cond = gen_rtx_fmt_ee (reverse_condition (GET_CODE (cond)),
+                                GET_MODE (cond), XEXP (cond, 0),
+                                XEXP (cond, 1));
+         if (prob_val)
+           prob_val = GEN_INT (REG_BR_PROB_BASE - INTVAL (prob_val));
+       }
 
-      if (! cond_exec_process_insns (head, end, cond, 0))
+      if (! cond_exec_process_insns (head, end, cond, prob_val, 0))
        goto cancel;
 
       earliest = jump;
     }
   else
+#endif
     {
       /* In the non-conditional execution case, we have to verify that there
         are no trapping operations, no calls, no references to memory, and
@@ -1823,7 +1960,7 @@ dead_or_predicable (test_bb, merge_bb, other_bb, new_dest, reversep)
            break;
        }
 
-      if (! condjump_p (jump))
+      if (! any_condjump_p (jump))
        return FALSE;
 
       /* Find the extent of the conditional.  */
@@ -1845,7 +1982,7 @@ dead_or_predicable (test_bb, merge_bb, other_bb, new_dest, reversep)
       /* ??? bb->local_set is only valid during calculate_global_regs_live,
         so we must recompute usage for MERGE_BB.  Not so bad, I suppose, 
          since we've already asserted that MERGE_BB is small.  */
-      propagate_block (merge_bb, tmp, merge_set, 0);
+      propagate_block (merge_bb, tmp, merge_set, merge_set, 0);
 
       /* For small register class machines, don't lengthen lifetimes of
         hard registers before reload.  */
@@ -1865,7 +2002,8 @@ dead_or_predicable (test_bb, merge_bb, other_bb, new_dest, reversep)
         Moreover, we're interested in the insns live from OTHER_BB.  */
 
       COPY_REG_SET (test_live, other_bb->global_live_at_start);
-      pbi = init_propagate_block_info (test_bb, test_live, test_set, 0);
+      pbi = init_propagate_block_info (test_bb, test_live, test_set, test_set,
+                                      0);
 
       for (insn = jump; ; insn = prev)
        {
@@ -1927,10 +2065,11 @@ dead_or_predicable (test_bb, merge_bb, other_bb, new_dest, reversep)
     }
 
   /* Move the insns out of MERGE_BB to before the branch.  */
-  if (end == merge_bb->end)
-    merge_bb->end = merge_bb->head;
   if (head != NULL)
     {
+      if (end == merge_bb->end)
+       merge_bb->end = PREV_INSN (head);
+
       head = squeeze_notes (head, end);
       if (GET_CODE (end) == NOTE
          && (NOTE_LINE_NUMBER (end) == NOTE_INSN_BLOCK_END
@@ -1975,7 +2114,7 @@ if_convert (life_data_ok)
   if (HAVE_conditional_execution || life_data_ok)
     {
       post_dominators = sbitmap_vector_alloc (n_basic_blocks, n_basic_blocks);
-      compute_flow_dominators (NULL, post_dominators);
+      calculate_dominance_info (NULL, post_dominators, CDI_POST_DOMINATORS);
     }
 
   /* Record initial block numbers.  */
@@ -1992,7 +2131,8 @@ if_convert (life_data_ok)
        block_num++;
     }
 
-  sbitmap_vector_free (post_dominators);
+  if (post_dominators)
+    sbitmap_vector_free (post_dominators);
 
   if (rtl_dump_file)
     fflush (rtl_dump_file);
@@ -2018,8 +2158,11 @@ if_convert (life_data_ok)
          SET_BIT (update_life_blocks, block_num);
 
       count_or_remove_death_notes (update_life_blocks, 1);
-      update_life_info (update_life_blocks, UPDATE_LIFE_LOCAL,
-                       PROP_DEATH_NOTES);
+      /* ??? See about adding a mode that verifies that the initial
+       set of blocks don't let registers come live.  */
+      update_life_info (update_life_blocks, UPDATE_LIFE_GLOBAL,
+                       PROP_DEATH_NOTES | PROP_SCAN_DEAD_CODE
+                       | PROP_KILL_DEAD_CODE);
 
       sbitmap_free (update_life_blocks);
     }
@@ -2038,5 +2181,7 @@ if_convert (life_data_ok)
               num_removed_blocks);
     }
 
+#ifdef ENABLE_CHECKING
   verify_flow_info ();
+#endif
 }