]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - gcc/ifcvt.c
Correct a function pre/postcondition [PR102403].
[thirdparty/gcc.git] / gcc / ifcvt.c
index 75458589468b50262eeb682e3224a94c92c3f8d3..017944f4f79aa687f89788f1ea0a78c0abd05298 100644 (file)
@@ -1,5 +1,5 @@
 /* If-conversion support.
-   Copyright (C) 2000-2017 Free Software Foundation, Inc.
+   Copyright (C) 2000-2021 Free Software Foundation, Inc.
 
    This file is part of GCC.
 
@@ -45,7 +45,6 @@
 #include "shrink-wrap.h"
 #include "rtl-iter.h"
 #include "ifcvt.h"
-#include "params.h"
 
 #ifndef MAX_CONDITIONAL_EXECUTE
 #define MAX_CONDITIONAL_EXECUTE \
@@ -78,14 +77,12 @@ static int cond_exec_changed_p;
 
 /* Forward references.  */
 static int count_bb_insns (const_basic_block);
-static bool cheap_bb_rtx_cost_p (const_basic_block, int, int);
+static bool cheap_bb_rtx_cost_p (const_basic_block, profile_probability, int);
 static rtx_insn *first_active_insn (basic_block);
 static rtx_insn *last_active_insn (basic_block, int);
 static rtx_insn *find_active_insn_before (basic_block, rtx_insn *);
 static rtx_insn *find_active_insn_after (basic_block, rtx_insn *);
 static basic_block block_fallthru (basic_block);
-static int cond_exec_process_insns (ce_if_block *, rtx_insn *, rtx, rtx, int,
-                                   int);
 static rtx cond_exec_get_condition (rtx_insn *);
 static rtx noce_get_condition (rtx_insn *, rtx_insn **, bool);
 static int noce_operand_ok (const_rtx);
@@ -123,7 +120,7 @@ count_bb_insns (const_basic_block bb)
   return count;
 }
 
-/* Determine whether the total insn_rtx_cost on non-jump insns in
+/* Determine whether the total insn_cost on non-jump insns in
    basic block BB is less than MAX_COST.  This function returns
    false if the cost of any instruction could not be estimated. 
 
@@ -132,14 +129,17 @@ count_bb_insns (const_basic_block bb)
    plus a small fudge factor.  */
 
 static bool
-cheap_bb_rtx_cost_p (const_basic_block bb, int scale, int max_cost)
+cheap_bb_rtx_cost_p (const_basic_block bb,
+                    profile_probability prob, int max_cost)
 {
   int count = 0;
   rtx_insn *insn = BB_HEAD (bb);
   bool speed = optimize_bb_for_speed_p (bb);
+  int scale = prob.initialized_p () ? prob.to_reg_br_prob_base ()
+             : REG_BR_PROB_BASE;
 
   /* Set scale to REG_BR_PROB_BASE to void the identical scaling
-     applied to insn_rtx_cost when optimizing for size.  Only do
+     applied to insn_cost when optimizing for size.  Only do
      this after combine because if-conversion might interfere with
      passes before combine.
 
@@ -162,7 +162,7 @@ cheap_bb_rtx_cost_p (const_basic_block bb, int scale, int max_cost)
     {
       if (NONJUMP_INSN_P (insn))
        {
-         int cost = insn_rtx_cost (PATTERN (insn), speed) * REG_BR_PROB_BASE;
+         int cost = insn_cost (insn, speed) * REG_BR_PROB_BASE;
          if (cost == 0)
            return false;
 
@@ -332,7 +332,8 @@ cond_exec_process_insns (ce_if_block *ce_info ATTRIBUTE_UNUSED,
                         /* if block information */rtx_insn *start,
                         /* first insn to look at */rtx end,
                         /* last insn to look at */rtx test,
-                        /* conditional execution test */int prob_val,
+                        /* conditional execution test */profile_probability
+                                                           prob_val,
                         /* probability of branch taken. */int mod_ok)
 {
   int must_be_last = FALSE;
@@ -407,10 +408,11 @@ cond_exec_process_insns (ce_if_block *ce_info ATTRIBUTE_UNUSED,
 
       validate_change (insn, &PATTERN (insn), pattern, 1);
 
-      if (CALL_P (insn) && prob_val >= 0)
+      if (CALL_P (insn) && prob_val.initialized_p ())
        validate_change (insn, &REG_NOTES (insn),
                         gen_rtx_INT_LIST ((machine_mode) REG_BR_PROB,
-                                          prob_val, REG_NOTES (insn)), 1);
+                                          prob_val.to_reg_br_prob_note (),
+                                          REG_NOTES (insn)), 1);
 
     insn_done:
       if (insn == end)
@@ -469,8 +471,8 @@ cond_exec_process_if_block (ce_if_block * ce_info,
   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 */
-  int true_prob_val;           /* probability of else block */
-  int false_prob_val;          /* probability of then block */
+  profile_probability true_prob_val;/* probability of else block */
+  profile_probability false_prob_val;/* probability of then block */
   rtx_insn *then_last_head = NULL;     /* Last match at the head of THEN */
   rtx_insn *else_last_head = NULL;     /* Last match at the head of ELSE */
   rtx_insn *then_first_tail = NULL;    /* First match at the tail of THEN */
@@ -500,7 +502,7 @@ cond_exec_process_if_block (ce_if_block * ce_info,
     return FALSE;
 
   /* If the conditional jump is more than just a conditional jump,
-     then we can not do conditional execution conversion on this block.  */
+     then we cannot do conditional execution conversion on this block.  */
   if (! onlyjump_p (BB_END (test_bb)))
     return FALSE;
 
@@ -615,13 +617,13 @@ cond_exec_process_if_block (ce_if_block * ce_info,
   note = find_reg_note (BB_END (test_bb), REG_BR_PROB, NULL_RTX);
   if (note)
     {
-      true_prob_val = XINT (note, 0);
-      false_prob_val = REG_BR_PROB_BASE - true_prob_val;
+      true_prob_val = profile_probability::from_reg_br_prob_note (XINT (note, 0));
+      false_prob_val = true_prob_val.invert ();
     }
   else
     {
-      true_prob_val = -1;
-      false_prob_val = -1;
+      true_prob_val = profile_probability::uninitialized ();
+      false_prob_val = profile_probability::uninitialized ();
     }
 
   /* If we have && or || tests, do them here.  These tests are in the adjacent
@@ -649,7 +651,7 @@ cond_exec_process_if_block (ce_if_block * ce_info,
            goto fail;
 
          /* If the conditional jump is more than just a conditional jump, then
-            we can not do conditional execution conversion on this block.  */
+            we cannot do conditional execution conversion on this block.  */
          if (! onlyjump_p (BB_END (bb)))
            goto fail;
 
@@ -883,6 +885,60 @@ noce_emit_store_flag (struct noce_if_info *if_info, rtx x, int reversep,
                           || code == GEU || code == GTU), normalize);
 }
 
+/* Return true if X can be safely forced into a register by copy_to_mode_reg
+   / force_operand.  */
+
+static bool
+noce_can_force_operand (rtx x)
+{
+  if (general_operand (x, VOIDmode))
+    return true;
+  if (SUBREG_P (x))
+    {
+      if (!noce_can_force_operand (SUBREG_REG (x)))
+       return false;
+      return true;
+    }
+  if (ARITHMETIC_P (x))
+    {
+      if (!noce_can_force_operand (XEXP (x, 0))
+         || !noce_can_force_operand (XEXP (x, 1)))
+       return false;
+      switch (GET_CODE (x))
+       {
+       case MULT:
+       case DIV:
+       case MOD:
+       case UDIV:
+       case UMOD:
+         return true;
+       default:
+         return code_to_optab (GET_CODE (x));
+       }
+    }
+  if (UNARY_P (x))
+    {
+      if (!noce_can_force_operand (XEXP (x, 0)))
+       return false;
+      switch (GET_CODE (x))
+       {
+       case ZERO_EXTEND:
+       case SIGN_EXTEND:
+       case TRUNCATE:
+       case FLOAT_EXTEND:
+       case FLOAT_TRUNCATE:
+       case FIX:
+       case UNSIGNED_FIX:
+       case FLOAT:
+       case UNSIGNED_FLOAT:
+         return true;
+       default:
+         return code_to_optab (GET_CODE (x));
+       }
+    }
+  return false;
+}
+
 /* Emit instruction to move an rtx, possibly into STRICT_LOW_PART.
    X is the destination/target and Y is the value to copy.  */
 
@@ -891,7 +947,7 @@ noce_emit_move_insn (rtx x, rtx y)
 {
   machine_mode outmode;
   rtx outer, inner;
-  int bitpos;
+  poly_int64 bitpos;
 
   if (GET_CODE (x) != STRICT_LOW_PART)
     {
@@ -941,7 +997,7 @@ noce_emit_move_insn (rtx x, rtx y)
            {
            case RTX_UNARY:
              ot = code_to_optab (GET_CODE (y));
-             if (ot)
+             if (ot && noce_can_force_operand (XEXP (y, 0)))
                {
                  start_sequence ();
                  target = expand_unop (GET_MODE (y), ot, XEXP (y, 0), x, 0);
@@ -958,7 +1014,9 @@ noce_emit_move_insn (rtx x, rtx y)
            case RTX_BIN_ARITH:
            case RTX_COMM_ARITH:
              ot = code_to_optab (GET_CODE (y));
-             if (ot)
+             if (ot
+                 && noce_can_force_operand (XEXP (y, 0))
+                 && noce_can_force_operand (XEXP (y, 1)))
                {
                  start_sequence ();
                  target = expand_binop (GET_MODE (y), ot,
@@ -1284,7 +1342,7 @@ noce_try_store_flag_constants (struct noce_if_info *if_info)
   HOST_WIDE_INT itrue, ifalse, diff, tmp;
   int normalize;
   bool can_reverse;
-  machine_mode mode = GET_MODE (if_info->x);;
+  machine_mode mode = GET_MODE (if_info->x);
   rtx common = NULL_RTX;
 
   rtx a = if_info->a;
@@ -1721,12 +1779,12 @@ noce_emit_cmove (struct noce_if_info *if_info, rtx x, enum rtx_code code,
     {
       rtx reg_vtrue = SUBREG_REG (vtrue);
       rtx reg_vfalse = SUBREG_REG (vfalse);
-      unsigned int byte_vtrue = SUBREG_BYTE (vtrue);
-      unsigned int byte_vfalse = SUBREG_BYTE (vfalse);
+      poly_uint64 byte_vtrue = SUBREG_BYTE (vtrue);
+      poly_uint64 byte_vfalse = SUBREG_BYTE (vfalse);
       rtx promoted_target;
 
       if (GET_MODE (reg_vtrue) != GET_MODE (reg_vfalse)
-         || byte_vtrue != byte_vfalse
+         || maybe_ne (byte_vtrue, byte_vfalse)
          || (SUBREG_PROMOTED_VAR_P (vtrue)
              != SUBREG_PROMOTED_VAR_P (vfalse))
          || (SUBREG_PROMOTED_GET (vtrue)
@@ -2340,7 +2398,7 @@ noce_get_alt_condition (struct noce_if_info *if_info, rtx target,
       rtx_insn *prev_insn;
 
       /* First, look to see if we put a constant in a register.  */
-      prev_insn = prev_nonnote_insn (if_info->cond_earliest);
+      prev_insn = prev_nonnote_nondebug_insn (if_info->cond_earliest);
       if (prev_insn
          && BLOCK_FOR_INSN (prev_insn)
             == BLOCK_FOR_INSN (if_info->cond_earliest)
@@ -2611,7 +2669,7 @@ noce_try_abs (struct noce_if_info *if_info)
   if (REG_P (c))
     {
       rtx set;
-      rtx_insn *insn = prev_nonnote_insn (earliest);
+      rtx_insn *insn = prev_nonnote_nondebug_insn (earliest);
       if (insn
          && BLOCK_FOR_INSN (insn) == BLOCK_FOR_INSN (earliest)
          && (set = single_set (insn))
@@ -2761,15 +2819,18 @@ noce_try_sign_mask (struct noce_if_info *if_info)
      INSN_B which can happen for e.g. conditional stores to memory.  For the
      cost computation use the block TEST_BB where the evaluation will end up
      after the transformation.  */
-  t_unconditional =
-    (t == if_info->b
-     && (if_info->insn_b == NULL_RTX
-        || BLOCK_FOR_INSN (if_info->insn_b) == if_info->test_bb));
+  t_unconditional
+    (t == if_info->b
+       && (if_info->insn_b == NULL_RTX
+          || BLOCK_FOR_INSN (if_info->insn_b) == if_info->test_bb));
   if (!(t_unconditional
        || (set_src_cost (t, mode, if_info->speed_p)
            < COSTS_N_INSNS (2))))
     return FALSE;
 
+  if (!noce_can_force_operand (t))
+    return FALSE;
+
   start_sequence ();
   /* Use emit_store_flag to generate "m < 0 ? -1 : 0" instead of expanding
      "(signed) m >> 31" directly.  This benefits targets with specialized
@@ -2805,7 +2866,7 @@ noce_try_bitop (struct noce_if_info *if_info)
 {
   rtx cond, x, a, result;
   rtx_insn *seq;
-  machine_mode mode;
+  scalar_int_mode mode;
   enum rtx_code code;
   int bitnum;
 
@@ -2813,6 +2874,10 @@ noce_try_bitop (struct noce_if_info *if_info)
   cond = if_info->cond;
   code = GET_CODE (cond);
 
+  /* Check for an integer operation.  */
+  if (!is_a <scalar_int_mode> (GET_MODE (x), &mode))
+    return FALSE;
+
   if (!noce_simple_bbs (if_info))
     return FALSE;
 
@@ -2835,7 +2900,6 @@ noce_try_bitop (struct noce_if_info *if_info)
          || ! rtx_equal_p (x, XEXP (cond, 0)))
        return FALSE;
       bitnum = INTVAL (XEXP (cond, 2));
-      mode = GET_MODE (x);
       if (BITS_BIG_ENDIAN)
        bitnum = GET_MODE_BITSIZE (mode) - 1 - bitnum;
       if (bitnum < 0 || bitnum >= HOST_BITS_PER_WIDE_INT)
@@ -3015,7 +3079,7 @@ bb_valid_for_noce_process_p (basic_block test_bb, rtx cond,
   if (first_insn == last_insn)
     {
       *simple_p = noce_operand_ok (SET_DEST (first_set));
-      *cost += insn_rtx_cost (first_set, speed_p);
+      *cost += pattern_cost (first_set, speed_p);
       return *simple_p;
     }
 
@@ -3031,7 +3095,7 @@ bb_valid_for_noce_process_p (basic_block test_bb, rtx cond,
   /* The regs that are live out of test_bb.  */
   bitmap test_bb_live_out = df_get_live_out (test_bb);
 
-  int potential_cost = insn_rtx_cost (last_set, speed_p);
+  int potential_cost = pattern_cost (last_set, speed_p);
   rtx_insn *insn;
   FOR_BB_INSNS (test_bb, insn)
     {
@@ -3051,7 +3115,7 @@ bb_valid_for_noce_process_p (basic_block test_bb, rtx cond,
              || reg_overlap_mentioned_p (SET_DEST (sset), cond))
            goto free_bitmap_and_fail;
 
-         potential_cost += insn_rtx_cost (sset, speed_p);
+         potential_cost += pattern_cost (sset, speed_p);
          bitmap_set_bit (test_bb_temps, REGNO (SET_DEST (sset)));
        }
     }
@@ -3192,7 +3256,7 @@ noce_convert_multiple_sets (struct noce_if_info *if_info)
        {
          machine_mode src_mode = GET_MODE (new_val);
          machine_mode dst_mode = GET_MODE (temp);
-         if (GET_MODE_SIZE (src_mode) <= GET_MODE_SIZE (dst_mode))
+         if (!partial_subreg_p (dst_mode, src_mode))
            {
              end_sequence ();
              return FALSE;
@@ -3203,7 +3267,7 @@ noce_convert_multiple_sets (struct noce_if_info *if_info)
        {
          machine_mode src_mode = GET_MODE (old_val);
          machine_mode dst_mode = GET_MODE (temp);
-         if (GET_MODE_SIZE (src_mode) <= GET_MODE_SIZE (dst_mode))
+         if (!partial_subreg_p (dst_mode, src_mode))
            {
              end_sequence ();
              return FALSE;
@@ -3305,7 +3369,7 @@ bb_ok_for_noce_convert_multiple_sets (basic_block test_bb)
 {
   rtx_insn *insn;
   unsigned count = 0;
-  unsigned param = PARAM_VALUE (PARAM_MAX_RTL_IF_CONVERSION_INSNS);
+  unsigned param = param_max_rtl_if_conversion_insns;
 
   FOR_BB_INSNS (test_bb, insn)
     {
@@ -3352,6 +3416,16 @@ bb_ok_for_noce_convert_multiple_sets (basic_block test_bb)
   return count > 1 && count <= param;
 }
 
+/* Compute average of two given costs weighted by relative probabilities
+   of respective basic blocks in an IF-THEN-ELSE.  E is the IF-THEN edge.
+   With P as the probability to take the IF-THEN branch, return
+   P * THEN_COST + (1 - P) * ELSE_COST.  */
+static unsigned
+average_cost (unsigned then_cost, unsigned else_cost, edge e)
+{
+  return else_cost + e->probability.apply ((signed) (then_cost - else_cost));
+}
+
 /* Given a simple IF-THEN-JOIN or IF-THEN-ELSE-JOIN block, attempt to convert
    it without using conditional execution.  Return TRUE if we were successful
    at converting the block.  */
@@ -3384,7 +3458,6 @@ noce_process_if_block (struct noce_if_info *if_info)
   /* First look for multiple SETS.  */
   if (!else_bb
       && HAVE_conditional_move
-      && !HAVE_cc0
       && bb_ok_for_noce_convert_multiple_sets (then_bb))
     {
       if (noce_convert_multiple_sets (if_info))
@@ -3407,10 +3480,9 @@ noce_process_if_block (struct noce_if_info *if_info)
                                       &if_info->else_simple))
     return false;
 
-  if (else_bb == NULL)
-    if_info->original_cost += then_cost;
-  else if (speed_p)
-    if_info->original_cost += MIN (then_cost, else_cost);
+  if (speed_p)
+    if_info->original_cost += average_cost (then_cost, else_cost,
+                                           find_edge (test_bb, then_bb));
   else
     if_info->original_cost += then_cost + else_cost;
 
@@ -3817,13 +3889,11 @@ cond_move_process_if_block (struct noce_if_info *if_info)
   rtx_insn *jump = if_info->jump;
   rtx cond = if_info->cond;
   rtx_insn *seq, *loc_insn;
-  rtx reg;
   int c;
   vec<rtx> then_regs = vNULL;
   vec<rtx> else_regs = vNULL;
-  unsigned int i;
   int success_p = FALSE;
-  int limit = PARAM_VALUE (PARAM_MAX_RTL_IF_CONVERSION_INSNS);
+  int limit = param_max_rtl_if_conversion_insns;
 
   /* Build a mapping for each block to the value used for each
      register.  */
@@ -3843,7 +3913,7 @@ cond_move_process_if_block (struct noce_if_info *if_info)
      source register does not change after the assignment.  Also count
      the number of registers set in only one of the blocks.  */
   c = 0;
-  FOR_EACH_VEC_ELT (then_regs, i, reg)
+  for (rtx reg : then_regs)
     {
       rtx *then_slot = then_vals.get (reg);
       rtx *else_slot = else_vals.get (reg);
@@ -3862,7 +3932,7 @@ cond_move_process_if_block (struct noce_if_info *if_info)
     }
 
   /* Finish off c for MAX_CONDITIONAL_EXECUTE.  */
-  FOR_EACH_VEC_ELT (else_regs, i, reg)
+  for (rtx reg : else_regs)
     {
       gcc_checking_assert (else_vals.get (reg));
       if (!then_vals.get (reg))
@@ -4016,7 +4086,7 @@ noce_find_if_block (basic_block test_bb, edge then_edge, edge else_edge,
     }
 
   /* If the conditional jump is more than just a conditional
-     jump, then we can not do if-conversion on this block.  */
+     jump, then we cannot do if-conversion on this block.  */
   jump = BB_END (test_bb);
   if (! onlyjump_p (jump))
     return FALSE;
@@ -4636,7 +4706,7 @@ find_cond_trap (basic_block test_bb, edge then_edge, edge else_edge)
     return FALSE;
 
   /* If the conditional jump is more than just a conditional jump, then
-     we can not do if-conversion on this block.  Give up for returnjump_p,
+     we cannot do if-conversion on this block.  Give up for returnjump_p,
      changing a conditional return followed by unconditional trap for
      conditional trap followed by unconditional return is likely not
      beneficial and harder to handle.  */
@@ -4807,7 +4877,8 @@ find_if_case_1 (basic_block test_bb, edge then_edge, edge else_edge)
   basic_block then_bb = then_edge->dest;
   basic_block else_bb = else_edge->dest;
   basic_block new_bb;
-  int then_bb_index, then_prob;
+  int then_bb_index;
+  profile_probability then_prob;
   rtx else_target = NULL_RTX;
 
   /* If we are partitioning hot/cold basic blocks, we don't want to
@@ -4853,10 +4924,7 @@ find_if_case_1 (basic_block test_bb, edge then_edge, edge else_edge)
             "\nIF-CASE-1 found, start %d, then %d\n",
             test_bb->index, then_bb->index);
 
-  if (then_edge->probability)
-    then_prob = REG_BR_PROB_BASE - then_edge->probability;
-  else
-    then_prob = REG_BR_PROB_BASE / 2;
+  then_prob = then_edge->probability.invert ();
 
   /* We're speculating from the THEN path, we want to make sure the cost
      of speculation is within reason.  */
@@ -4927,7 +4995,7 @@ find_if_case_2 (basic_block test_bb, edge then_edge, edge else_edge)
   basic_block then_bb = then_edge->dest;
   basic_block else_bb = else_edge->dest;
   edge else_succ;
-  int then_prob, else_prob;
+  profile_probability then_prob, else_prob;
 
   /* We do not want to speculate (empty) loop latches.  */
   if (current_loops
@@ -4973,16 +5041,8 @@ find_if_case_2 (basic_block test_bb, edge then_edge, edge else_edge)
   if (then_bb->index < NUM_FIXED_BLOCKS)
     return FALSE;
 
-  if (else_edge->probability)
-    {
-      else_prob = else_edge->probability;
-      then_prob = REG_BR_PROB_BASE - else_prob;
-    }
-  else
-    {
-      else_prob = REG_BR_PROB_BASE / 2;
-      then_prob = REG_BR_PROB_BASE / 2;
-    }
+  else_prob = else_edge->probability;
+  then_prob = else_prob.invert ();
 
   /* ELSE is predicted or SUCC(ELSE) postdominates THEN.  */
   if (else_prob > then_prob)
@@ -5123,12 +5183,19 @@ dead_or_predicable (basic_block test_bb, basic_block merge_bb,
 
       rtx cond;
 
+      /* If the conditional jump is more than just a conditional jump,
+        then we cannot do conditional execution conversion on this block.  */
+      if (!onlyjump_p (jump))
+       goto nce;
+
       cond = cond_exec_get_condition (jump);
       if (! cond)
-       return FALSE;
+       goto nce;
 
       rtx note = find_reg_note (jump, REG_BR_PROB, NULL_RTX);
-      int prob_val = (note ? XINT (note, 0) : -1);
+      profile_probability prob_val
+         = (note ? profile_probability::from_reg_br_prob_note (XINT (note, 0))
+            : profile_probability::uninitialized ());
 
       if (reversep)
        {
@@ -5137,8 +5204,7 @@ dead_or_predicable (basic_block test_bb, basic_block merge_bb,
            return FALSE;
          cond = gen_rtx_fmt_ee (rev, GET_MODE (cond), XEXP (cond, 0),
                                 XEXP (cond, 1));
-         if (prob_val >= 0)
-           prob_val = REG_BR_PROB_BASE - prob_val;
+         prob_val = prob_val.invert ();
        }
 
       if (cond_exec_process_insns (NULL, head, end, cond, prob_val, 0)
@@ -5149,6 +5215,7 @@ dead_or_predicable (basic_block test_bb, basic_block merge_bb,
 
       earliest = jump;
     }
+ nce:
 #endif
 
   /* If we allocated new pseudos (e.g. in the conditional move
@@ -5286,8 +5353,6 @@ dead_or_predicable (basic_block test_bb, basic_block merge_bb,
       redirect_edge_succ (BRANCH_EDGE (test_bb), new_dest);
       if (reversep)
        {
-         std::swap (BRANCH_EDGE (test_bb)->count,
-                    FALLTHRU_EDGE (test_bb)->count);
          std::swap (BRANCH_EDGE (test_bb)->probability,
                     FALLTHRU_EDGE (test_bb)->probability);
          update_br_prob_note (test_bb);
@@ -5451,6 +5516,10 @@ if_convert (bool after_combine)
   if (optimize == 1)
     df_remove_problem (df_live);
 
+  /* Some non-cold blocks may now be only reachable from cold blocks.
+     Fix that up.  */
+  fixup_partitions ();
+
   checking_verify_flow_info ();
 }
 \f
@@ -5458,6 +5527,8 @@ if_convert (bool after_combine)
 static unsigned int
 rest_of_handle_if_conversion (void)
 {
+  int flags = 0;
+
   if (flag_if_conversion)
     {
       if (dump_file)
@@ -5467,9 +5538,12 @@ rest_of_handle_if_conversion (void)
        }
       cleanup_cfg (CLEANUP_EXPENSIVE);
       if_convert (false);
+      if (num_updated_if_blocks)
+       /* Get rid of any dead CC-related instructions.  */
+       flags |= CLEANUP_FORCE_FAST_DCE;
     }
 
-  cleanup_cfg (0);
+  cleanup_cfg (flags);
   return 0;
 }