]> gcc.gnu.org Git - gcc.git/blobdiff - gcc/ifcvt.c
re PR sanitizer/77823 (ICE: in ubsan_encode_value, at ubsan.c:137 with -fsanitize...
[gcc.git] / gcc / ifcvt.c
index c830b3cb8c4280586b09e63c7f6340c0b6b22709..dbe2485987019e06022f59b365924ae62ed94d57 100644 (file)
@@ -1,5 +1,5 @@
 /* If-conversion support.
-   Copyright (C) 2000-2015 Free Software Foundation, Inc.
+   Copyright (C) 2000-2016 Free Software Foundation, Inc.
 
    This file is part of GCC.
 
@@ -26,6 +26,7 @@
 #include "tree.h"
 #include "cfghooks.h"
 #include "df.h"
+#include "memmodel.h"
 #include "tm_p.h"
 #include "expmed.h"
 #include "optabs.h"
@@ -44,6 +45,7 @@
 #include "shrink-wrap.h"
 #include "rtl-iter.h"
 #include "ifcvt.h"
+#include "params.h"
 
 #ifndef MAX_CONDITIONAL_EXECUTE
 #define MAX_CONDITIONAL_EXECUTE \
@@ -434,7 +436,7 @@ cond_exec_get_condition (rtx_insn *jump)
   /* If this branches to JUMP_LABEL when the condition is false,
      reverse the condition.  */
   if (GET_CODE (XEXP (test_if, 2)) == LABEL_REF
-      && LABEL_REF_LABEL (XEXP (test_if, 2)) == JUMP_LABEL (jump))
+      && label_ref_label (XEXP (test_if, 2)) == JUMP_LABEL (jump))
     {
       enum rtx_code rev = reversed_comparison_code (cond, jump);
       if (rev == UNKNOWN)
@@ -739,7 +741,7 @@ cond_exec_process_if_block (ce_if_block * ce_info,
       rtx_insn *from = then_first_tail;
       if (!INSN_P (from))
        from = find_active_insn_after (then_bb, from);
-      delete_insn_chain (from, BB_END (then_bb), false);
+      delete_insn_chain (from, get_last_bb_insn (then_bb), false);
     }
   if (else_last_head)
     delete_insn_chain (first_active_insn (else_bb), else_last_head, false);
@@ -792,6 +794,9 @@ struct noce_if_info
   /* The SET_DEST of INSN_A.  */
   rtx x;
 
+  /* The original set destination that the THEN and ELSE basic blocks finally
+     write their result to.  */
+  rtx orig_x;
   /* True if this if block is not canonical.  In the canonical form of
      if blocks, the THEN_BB is the block reached via the fallthru edge
      from TEST_BB.  For the noce transformations, we allow the symmetric
@@ -803,16 +808,26 @@ struct noce_if_info
   bool then_simple;
   bool else_simple;
 
-  /* The total rtx cost of the instructions in then_bb and else_bb.  */
-  unsigned int then_cost;
-  unsigned int else_cost;
+  /* True if we're optimisizing the control block for speed, false if
+     we're optimizing for size.  */
+  bool speed_p;
 
-  /* Estimated cost of the particular branch instruction.  */
-  unsigned int branch_cost;
+  /* The combined cost of COND, JUMP and the costs for THEN_BB and
+     ELSE_BB.  */
+  unsigned int original_cost;
+
+  /* Maximum permissible cost for the unconditional sequence we should
+     generate to replace this branch.  */
+  unsigned int max_seq_cost;
+
+  /* The name of the noce transform that succeeded in if-converting
+     this structure.  Used for debugging.  */
+  const char *transform_name;
 };
 
 static rtx noce_emit_store_flag (struct noce_if_info *, rtx, int, int);
 static int noce_try_move (struct noce_if_info *);
+static int noce_try_ifelse_collapse (struct noce_if_info *);
 static int noce_try_store_flag (struct noce_if_info *);
 static int noce_try_addcc (struct noce_if_info *);
 static int noce_try_store_flag_constants (struct noce_if_info *);
@@ -826,6 +841,25 @@ static int noce_try_minmax (struct noce_if_info *);
 static int noce_try_abs (struct noce_if_info *);
 static int noce_try_sign_mask (struct noce_if_info *);
 
+/* Return TRUE if SEQ is a good candidate as a replacement for the
+   if-convertible sequence described in IF_INFO.  */
+
+inline static bool
+noce_conversion_profitable_p (rtx_insn *seq, struct noce_if_info *if_info)
+{
+  bool speed_p = if_info->speed_p;
+
+  /* Cost up the new sequence.  */
+  unsigned int cost = seq_cost (seq, speed_p);
+
+  /* When compiling for size, we can make a reasonably accurately guess
+     at the size growth.  */
+  if (!speed_p)
+    return cost <= if_info->original_cost;
+  else
+    return cost <= if_info->max_seq_cost;
+}
+
 /* Helper function for noce_try_store_flag*.  */
 
 static rtx
@@ -847,7 +881,7 @@ noce_emit_store_flag (struct noce_if_info *if_info, rtx x, int reversep,
       rtx set = pc_set (if_info->jump);
       cond = XEXP (SET_SRC (set), 0);
       if (GET_CODE (XEXP (SET_SRC (set), 2)) == LABEL_REF
-         && LABEL_REF_LABEL (XEXP (SET_SRC (set), 2)) == JUMP_LABEL (if_info->jump))
+         && label_ref_label (XEXP (SET_SRC (set), 2)) == JUMP_LABEL (if_info->jump))
        reversep = !reversep;
       if (if_info->then_else_reversed)
        reversep = !reversep;
@@ -1111,11 +1145,45 @@ noce_try_move (struct noce_if_info *if_info)
          emit_insn_before_setloc (seq, if_info->jump,
                                   INSN_LOCATION (if_info->insn_a));
        }
+      if_info->transform_name = "noce_try_move";
       return TRUE;
     }
   return FALSE;
 }
 
+/* Try forming an IF_THEN_ELSE (cond, b, a) and collapsing that
+   through simplify_rtx.  Sometimes that can eliminate the IF_THEN_ELSE.
+   If that is the case, emit the result into x.  */
+
+static int
+noce_try_ifelse_collapse (struct noce_if_info * if_info)
+{
+  if (!noce_simple_bbs (if_info))
+    return FALSE;
+
+  machine_mode mode = GET_MODE (if_info->x);
+  rtx if_then_else = simplify_gen_ternary (IF_THEN_ELSE, mode, mode,
+                                           if_info->cond, if_info->b,
+                                           if_info->a);
+
+  if (GET_CODE (if_then_else) == IF_THEN_ELSE)
+    return FALSE;
+
+  rtx_insn *seq;
+  start_sequence ();
+  noce_emit_move_insn (if_info->x, if_then_else);
+  seq = end_ifcvt_sequence (if_info);
+  if (!seq)
+    return FALSE;
+
+  emit_insn_before_setloc (seq, if_info->jump,
+                         INSN_LOCATION (if_info->insn_a));
+
+  if_info->transform_name = "noce_try_ifelse_collapse";
+  return TRUE;
+}
+
+
 /* Convert "if (test) x = 1; else x = 0".
 
    Only try 0 and STORE_FLAG_VALUE here.  Other combinations will be
@@ -1159,6 +1227,7 @@ noce_try_store_flag (struct noce_if_info *if_info)
 
       emit_insn_before_setloc (seq, if_info->jump,
                               INSN_LOCATION (if_info->insn_a));
+      if_info->transform_name = "noce_try_store_flag";
       return TRUE;
     }
   else
@@ -1168,6 +1237,84 @@ noce_try_store_flag (struct noce_if_info *if_info)
     }
 }
 
+
+/* Convert "if (test) x = -A; else x = A" into
+   x = A; if (test) x = -x if the machine can do the
+   conditional negate form of this cheaply.
+   Try this before noce_try_cmove that will just load the
+   immediates into two registers and do a conditional select
+   between them.  If the target has a conditional negate or
+   conditional invert operation we can save a potentially
+   expensive constant synthesis.  */
+
+static bool
+noce_try_inverse_constants (struct noce_if_info *if_info)
+{
+  if (!noce_simple_bbs (if_info))
+    return false;
+
+  if (!CONST_INT_P (if_info->a)
+      || !CONST_INT_P (if_info->b)
+      || !REG_P (if_info->x))
+    return false;
+
+  machine_mode mode = GET_MODE (if_info->x);
+
+  HOST_WIDE_INT val_a = INTVAL (if_info->a);
+  HOST_WIDE_INT val_b = INTVAL (if_info->b);
+
+  rtx cond = if_info->cond;
+
+  rtx x = if_info->x;
+  rtx target;
+
+  start_sequence ();
+
+  rtx_code code;
+  if (val_b != HOST_WIDE_INT_MIN && val_a == -val_b)
+    code = NEG;
+  else if (val_a == ~val_b)
+    code = NOT;
+  else
+    {
+      end_sequence ();
+      return false;
+    }
+
+  rtx tmp = gen_reg_rtx (mode);
+  noce_emit_move_insn (tmp, if_info->a);
+
+  target = emit_conditional_neg_or_complement (x, code, mode, cond, tmp, tmp);
+
+  if (target)
+    {
+      rtx_insn *seq = get_insns ();
+
+      if (!seq)
+       {
+         end_sequence ();
+         return false;
+       }
+
+      if (target != if_info->x)
+       noce_emit_move_insn (if_info->x, target);
+
+      seq = end_ifcvt_sequence (if_info);
+
+      if (!seq)
+       return false;
+
+      emit_insn_before_setloc (seq, if_info->jump,
+                              INSN_LOCATION (if_info->insn_a));
+      if_info->transform_name = "noce_try_inverse_constants";
+      return true;
+    }
+
+  end_sequence ();
+  return false;
+}
+
+
 /* Convert "if (test) x = a; else x = b", for A and B constant.
    Also allow A = y + c1, B = y + c2, with a common y between A
    and B.  */
@@ -1193,8 +1340,11 @@ noce_try_store_flag_constants (struct noce_if_info *if_info)
       && CONST_INT_P (XEXP (a, 1))
       && CONST_INT_P (XEXP (b, 1))
       && rtx_equal_p (XEXP (a, 0), XEXP (b, 0))
-      && noce_operand_ok (XEXP (a, 0))
-      && if_info->branch_cost >= 2)
+      /* Allow expressions that are not using the result or plain
+         registers where we handle overlap below.  */
+      && (REG_P (XEXP (a, 0))
+         || (noce_operand_ok (XEXP (a, 0))
+             && ! reg_overlap_mentioned_p (if_info->x, XEXP (a, 0)))))
     {
       common = XEXP (a, 0);
       a = XEXP (a, 1);
@@ -1267,22 +1417,24 @@ noce_try_store_flag_constants (struct noce_if_info *if_info)
          else
            gcc_unreachable ();
        }
-      else if (ifalse == 0 && exact_log2 (itrue) >= 0
-              && (STORE_FLAG_VALUE == 1
-                  || if_info->branch_cost >= 2))
+      /* Is this (cond) ? 2^n : 0?  */
+      else if (ifalse == 0 && pow2p_hwi (itrue)
+              && STORE_FLAG_VALUE == 1)
        normalize = 1;
-      else if (itrue == 0 && exact_log2 (ifalse) >= 0 && can_reverse
-              && (STORE_FLAG_VALUE == 1 || if_info->branch_cost >= 2))
+      /* Is this (cond) ? 0 : 2^n?  */
+      else if (itrue == 0 && pow2p_hwi (ifalse) && can_reverse
+              && STORE_FLAG_VALUE == 1)
        {
          normalize = 1;
          reversep = true;
        }
+      /* Is this (cond) ? -1 : x?  */
       else if (itrue == -1
-              && (STORE_FLAG_VALUE == -1
-                  || if_info->branch_cost >= 2))
+              && STORE_FLAG_VALUE == -1)
        normalize = -1;
+      /* Is this (cond) ? x : -1?  */
       else if (ifalse == -1 && can_reverse
-              && (STORE_FLAG_VALUE == -1 || if_info->branch_cost >= 2))
+              && STORE_FLAG_VALUE == -1)
        {
          normalize = -1;
          reversep = true;
@@ -1371,11 +1523,13 @@ noce_try_store_flag_constants (struct noce_if_info *if_info)
        noce_emit_move_insn (if_info->x, target);
 
       seq = end_ifcvt_sequence (if_info);
-      if (!seq)
+      if (!seq || !noce_conversion_profitable_p (seq, if_info))
        return FALSE;
 
       emit_insn_before_setloc (seq, if_info->jump,
                               INSN_LOCATION (if_info->insn_a));
+      if_info->transform_name = "noce_try_store_flag_constants";
+
       return TRUE;
     }
 
@@ -1423,21 +1577,23 @@ noce_try_addcc (struct noce_if_info *if_info)
                noce_emit_move_insn (if_info->x, target);
 
              seq = end_ifcvt_sequence (if_info);
-             if (!seq)
+             if (!seq || !noce_conversion_profitable_p (seq, if_info))
                return FALSE;
 
              emit_insn_before_setloc (seq, if_info->jump,
                                       INSN_LOCATION (if_info->insn_a));
+             if_info->transform_name = "noce_try_addcc";
+
              return TRUE;
            }
          end_sequence ();
        }
 
       /* If that fails, construct conditional increment or decrement using
-        setcc.  */
-      if (if_info->branch_cost >= 2
-         && (XEXP (if_info->a, 1) == const1_rtx
-             || XEXP (if_info->a, 1) == constm1_rtx))
+        setcc.  We're changing a branch and an increment to a comparison and
+        an ADD/SUB.  */
+      if (XEXP (if_info->a, 1) == const1_rtx
+         || XEXP (if_info->a, 1) == constm1_rtx)
         {
          start_sequence ();
          if (STORE_FLAG_VALUE == INTVAL (XEXP (if_info->a, 1)))
@@ -1463,11 +1619,12 @@ noce_try_addcc (struct noce_if_info *if_info)
                noce_emit_move_insn (if_info->x, target);
 
              seq = end_ifcvt_sequence (if_info);
-             if (!seq)
+             if (!seq || !noce_conversion_profitable_p (seq, if_info))
                return FALSE;
 
              emit_insn_before_setloc (seq, if_info->jump,
                                       INSN_LOCATION (if_info->insn_a));
+             if_info->transform_name = "noce_try_addcc";
              return TRUE;
            }
          end_sequence ();
@@ -1490,15 +1647,14 @@ noce_try_store_flag_mask (struct noce_if_info *if_info)
     return FALSE;
 
   reversep = 0;
-  if ((if_info->branch_cost >= 2
-       || STORE_FLAG_VALUE == -1)
-      && ((if_info->a == const0_rtx
-          && rtx_equal_p (if_info->b, if_info->x))
-         || ((reversep = (reversed_comparison_code (if_info->cond,
-                                                    if_info->jump)
-                          != UNKNOWN))
-             && if_info->b == const0_rtx
-             && rtx_equal_p (if_info->a, if_info->x))))
+
+  if ((if_info->a == const0_rtx
+       && rtx_equal_p (if_info->b, if_info->x))
+      || ((reversep = (reversed_comparison_code (if_info->cond,
+                                                if_info->jump)
+                      != UNKNOWN))
+         && if_info->b == const0_rtx
+         && rtx_equal_p (if_info->a, if_info->x)))
     {
       start_sequence ();
       target = noce_emit_store_flag (if_info,
@@ -1512,26 +1668,17 @@ noce_try_store_flag_mask (struct noce_if_info *if_info)
 
       if (target)
        {
-         int old_cost, new_cost, insn_cost;
-         int speed_p;
-
          if (target != if_info->x)
            noce_emit_move_insn (if_info->x, target);
 
          seq = end_ifcvt_sequence (if_info);
-         if (!seq)
-           return FALSE;
-
-         speed_p = optimize_bb_for_speed_p (BLOCK_FOR_INSN (if_info->insn_a));
-         insn_cost = insn_rtx_cost (PATTERN (if_info->insn_a), speed_p);
-         old_cost = COSTS_N_INSNS (if_info->branch_cost) + insn_cost;
-         new_cost = seq_cost (seq, speed_p);
-
-         if (new_cost > old_cost)
+         if (!seq || !noce_conversion_profitable_p (seq, if_info))
            return FALSE;
 
          emit_insn_before_setloc (seq, if_info->jump,
                                   INSN_LOCATION (if_info->insn_a));
+         if_info->transform_name = "noce_try_store_flag_mask";
+
          return TRUE;
        }
 
@@ -1682,6 +1829,8 @@ noce_try_cmove (struct noce_if_info *if_info)
 
          emit_insn_before_setloc (seq, if_info->jump,
                                   INSN_LOCATION (if_info->insn_a));
+         if_info->transform_name = "noce_try_cmove";
+
          return TRUE;
        }
       /* If both a and b are constants try a last-ditch transformation:
@@ -1692,9 +1841,7 @@ noce_try_cmove (struct noce_if_info *if_info)
         we don't know about, so give them a chance before trying this
         approach.  */
       else if (!targetm.have_conditional_execution ()
-               && CONST_INT_P (if_info->a) && CONST_INT_P (if_info->b)
-               && ((if_info->branch_cost >= 2 && STORE_FLAG_VALUE == -1)
-                   || if_info->branch_cost >= 3))
+               && CONST_INT_P (if_info->a) && CONST_INT_P (if_info->b))
        {
          machine_mode mode = GET_MODE (if_info->x);
          HOST_WIDE_INT ifalse = INTVAL (if_info->a);
@@ -1730,11 +1877,12 @@ noce_try_cmove (struct noce_if_info *if_info)
                noce_emit_move_insn (if_info->x, target);
 
              seq = end_ifcvt_sequence (if_info);
-             if (!seq)
+             if (!seq || !noce_conversion_profitable_p (seq, if_info))
                return FALSE;
 
              emit_insn_before_setloc (seq, if_info->jump,
                                   INSN_LOCATION (if_info->insn_a));
+             if_info->transform_name = "noce_try_cmove";
              return TRUE;
            }
          else
@@ -1789,11 +1937,13 @@ insn_valid_noce_process_p (rtx_insn *insn, rtx cc)
 }
 
 
-/* Return true iff the registers that the insns in BB_A set do not
-   get used in BB_B.  */
+/* Return true iff the registers that the insns in BB_A set do not get
+   used in BB_B.  If TO_RENAME is non-NULL then it is a location that will be
+   renamed later by the caller and so conflicts on it should be ignored
+   in this function.  */
 
 static bool
-bbs_ok_for_cmove_arith (basic_block bb_a, basic_block bb_b)
+bbs_ok_for_cmove_arith (basic_block bb_a, basic_block bb_b, rtx to_rename)
 {
   rtx_insn *a_insn;
   bitmap bba_sets = BITMAP_ALLOC (&reg_obstack);
@@ -1813,10 +1963,10 @@ bbs_ok_for_cmove_arith (basic_block bb_a, basic_block bb_b)
          BITMAP_FREE (bba_sets);
          return false;
        }
-
       /* Record all registers that BB_A sets.  */
       FOR_EACH_INSN_DEF (def, a_insn)
-       bitmap_set_bit (bba_sets, DF_REF_REGNO (def));
+       if (!(to_rename && DF_REF_REG (def) == to_rename))
+         bitmap_set_bit (bba_sets, DF_REF_REGNO (def));
     }
 
   rtx_insn *b_insn;
@@ -1835,8 +1985,15 @@ bbs_ok_for_cmove_arith (basic_block bb_a, basic_block bb_b)
        }
 
       /* Make sure this is a REG and not some instance
-        of ZERO_EXTRACT or SUBREG or other dangerous stuff.  */
-      if (!REG_P (SET_DEST (sset_b)))
+        of ZERO_EXTRACT or SUBREG or other dangerous stuff.
+        If we have a memory destination then we have a pair of simple
+        basic blocks performing an operation of the form [addr] = c ? a : b.
+        bb_valid_for_noce_process_p will have ensured that these are
+        the only stores present.  In that case [addr] should be the location
+        to be renamed.  Assert that the callers set this up properly.  */
+      if (MEM_P (SET_DEST (sset_b)))
+       gcc_assert (rtx_equal_p (SET_DEST (sset_b), to_rename));
+      else if (!REG_P (SET_DEST (sset_b)))
        {
          BITMAP_FREE (bba_sets);
          return false;
@@ -1933,11 +2090,9 @@ noce_try_cmove_arith (struct noce_if_info *if_info)
      conditional on their addresses followed by a load.  Don't do this
      early because it'll screw alias analysis.  Note that we've
      already checked for no side effects.  */
-  /* ??? FIXME: Magic number 5.  */
   if (cse_not_expected
       && MEM_P (a) && MEM_P (b)
-      && MEM_ADDR_SPACE (a) == MEM_ADDR_SPACE (b)
-      && if_info->branch_cost >= 5)
+      && MEM_ADDR_SPACE (a) == MEM_ADDR_SPACE (b))
     {
       machine_mode address_mode = get_address_mode (a);
 
@@ -1969,23 +2124,6 @@ noce_try_cmove_arith (struct noce_if_info *if_info)
   if (!can_conditionally_move_p (x_mode))
     return FALSE;
 
-  unsigned int then_cost;
-  unsigned int else_cost;
-  if (insn_a)
-    then_cost = if_info->then_cost;
-  else
-    then_cost = 0;
-
-  if (insn_b)
-    else_cost = if_info->else_cost;
-  else
-    else_cost = 0;
-
-  /* We're going to execute one of the basic blocks anyway, so
-     bail out if the most expensive of the two blocks is unacceptable.  */
-  if (MAX (then_cost, else_cost) > COSTS_N_INSNS (if_info->branch_cost))
-    return FALSE;
-
   /* Possibly rearrange operands to make things come out more natural.  */
   if (reversed_comparison_code (if_info->cond, if_info->jump) != UNKNOWN)
     {
@@ -2005,9 +2143,9 @@ noce_try_cmove_arith (struct noce_if_info *if_info)
        }
     }
 
-  if (then_bb && else_bb && !a_simple && !b_simple
-      && (!bbs_ok_for_cmove_arith (then_bb, else_bb)
-         || !bbs_ok_for_cmove_arith (else_bb, then_bb)))
+  if (then_bb && else_bb
+      && (!bbs_ok_for_cmove_arith (then_bb, else_bb,  if_info->orig_x)
+         || !bbs_ok_for_cmove_arith (else_bb, then_bb,  if_info->orig_x)))
     return FALSE;
 
   start_sequence ();
@@ -2095,52 +2233,56 @@ noce_try_cmove_arith (struct noce_if_info *if_info)
        }
     }
 
-    /* If insn to set up A clobbers any registers B depends on, try to
-       swap insn that sets up A with the one that sets up B.  If even
-       that doesn't help, punt.  */
-
   modified_in_a = emit_a != NULL_RTX && modified_in_p (orig_b, emit_a);
   if (tmp_b && then_bb)
     {
       FOR_BB_INSNS (then_bb, tmp_insn)
-       if (modified_in_p (orig_b, tmp_insn))
+       /* Don't check inside insn_a.  We will have changed it to emit_a
+          with a destination that doesn't conflict.  */
+       if (!(insn_a && tmp_insn == insn_a)
+           && modified_in_p (orig_b, tmp_insn))
          {
            modified_in_a = true;
            break;
          }
 
     }
-    if (emit_a && modified_in_a)
-      {
-       modified_in_b = emit_b != NULL_RTX && modified_in_p (orig_a, emit_b);
-       if (tmp_b && else_bb)
-         {
-           FOR_BB_INSNS (else_bb, tmp_insn)
-             if (modified_in_p (orig_a, tmp_insn))
-               {
-                 modified_in_b = true;
-                 break;
-               }
-
-         }
-       if (modified_in_b)
-         goto end_seq_and_fail;
 
-       if (!noce_emit_bb (emit_b, else_bb, b_simple))
-         goto end_seq_and_fail;
+  modified_in_b = emit_b != NULL_RTX && modified_in_p (orig_a, emit_b);
+  if (tmp_a && else_bb)
+    {
+      FOR_BB_INSNS (else_bb, tmp_insn)
+      /* Don't check inside insn_b.  We will have changed it to emit_b
+        with a destination that doesn't conflict.  */
+      if (!(insn_b && tmp_insn == insn_b)
+         && modified_in_p (orig_a, tmp_insn))
+       {
+         modified_in_b = true;
+         break;
+       }
+    }
 
-       if (!noce_emit_bb (emit_a, then_bb, a_simple))
-         goto end_seq_and_fail;
-      }
-    else
-      {
-       if (!noce_emit_bb (emit_a, then_bb, a_simple))
-         goto end_seq_and_fail;
+  /* If insn to set up A clobbers any registers B depends on, try to
+     swap insn that sets up A with the one that sets up B.  If even
+     that doesn't help, punt.  */
+  if (modified_in_a && !modified_in_b)
+    {
+      if (!noce_emit_bb (emit_b, else_bb, b_simple))
+       goto end_seq_and_fail;
 
-       if (!noce_emit_bb (emit_b, else_bb, b_simple))
-         goto end_seq_and_fail;
+      if (!noce_emit_bb (emit_a, then_bb, a_simple))
+       goto end_seq_and_fail;
+    }
+  else if (!modified_in_a)
+    {
+      if (!noce_emit_bb (emit_a, then_bb, a_simple))
+       goto end_seq_and_fail;
 
-      }
+      if (!noce_emit_bb (emit_b, else_bb, b_simple))
+       goto end_seq_and_fail;
+    }
+  else
+    goto end_seq_and_fail;
 
   target = noce_emit_cmove (if_info, x, code, XEXP (if_info->cond, 0),
                            XEXP (if_info->cond, 1), a, b);
@@ -2170,11 +2312,12 @@ noce_try_cmove_arith (struct noce_if_info *if_info)
     noce_emit_move_insn (x, target);
 
   ifcvt_seq = end_ifcvt_sequence (if_info);
-  if (!ifcvt_seq)
+  if (!ifcvt_seq || !noce_conversion_profitable_p (ifcvt_seq, if_info))
     return FALSE;
 
   emit_insn_before_setloc (ifcvt_seq, if_info->jump,
                           INSN_LOCATION (if_info->insn_a));
+  if_info->transform_name = "noce_try_cmove_arith";
   return TRUE;
 
  end_seq_and_fail:
@@ -2205,7 +2348,7 @@ noce_get_alt_condition (struct noce_if_info *if_info, rtx target,
   cond = XEXP (SET_SRC (set), 0);
   reverse
     = GET_CODE (XEXP (SET_SRC (set), 2)) == LABEL_REF
-      && LABEL_REF_LABEL (XEXP (SET_SRC (set), 2)) == JUMP_LABEL (if_info->jump);
+      && label_ref_label (XEXP (SET_SRC (set), 2)) == JUMP_LABEL (if_info->jump);
   if (if_info->then_else_reversed)
     reverse = !reverse;
 
@@ -2266,28 +2409,32 @@ noce_get_alt_condition (struct noce_if_info *if_info, rtx target,
          switch (code)
            {
            case LT:
-             if (actual_val == desired_val + 1)
+             if (desired_val != HOST_WIDE_INT_MAX
+                 && actual_val == desired_val + 1)
                {
                  code = LE;
                  op_b = GEN_INT (desired_val);
                }
              break;
            case LE:
-             if (actual_val == desired_val - 1)
+             if (desired_val != HOST_WIDE_INT_MIN
+                 && actual_val == desired_val - 1)
                {
                  code = LT;
                  op_b = GEN_INT (desired_val);
                }
              break;
            case GT:
-             if (actual_val == desired_val - 1)
+             if (desired_val != HOST_WIDE_INT_MIN
+                 && actual_val == desired_val - 1)
                {
                  code = GE;
                  op_b = GEN_INT (desired_val);
                }
              break;
            case GE:
-             if (actual_val == desired_val + 1)
+             if (desired_val != HOST_WIDE_INT_MAX
+                 && actual_val == desired_val + 1)
                {
                  code = GT;
                  op_b = GEN_INT (desired_val);
@@ -2427,6 +2574,7 @@ noce_try_minmax (struct noce_if_info *if_info)
   emit_insn_before_setloc (seq, if_info->jump, INSN_LOCATION (if_info->insn_a));
   if_info->cond = cond;
   if_info->cond_earliest = earliest;
+  if_info->transform_name = "noce_try_minmax";
 
   return TRUE;
 }
@@ -2518,12 +2666,26 @@ noce_try_abs (struct noce_if_info *if_info)
 
   /* Work around funny ideas get_condition has wrt canonicalization.
      Note that these rtx constants are known to be CONST_INT, and
-     therefore imply integer comparisons.  */
+     therefore imply integer comparisons.
+     The one_cmpl case is more complicated, as we want to handle
+     only x < 0 ? ~x : x or x >= 0 ? x : ~x to one_cmpl_abs (x)
+     and x < 0 ? x : ~x or x >= 0 ? ~x : x to ~one_cmpl_abs (x),
+     but not other cases (x > -1 is equivalent of x >= 0).  */
   if (c == constm1_rtx && GET_CODE (cond) == GT)
     ;
   else if (c == const1_rtx && GET_CODE (cond) == LT)
-    ;
-  else if (c != CONST0_RTX (GET_MODE (b)))
+    {
+      if (one_cmpl)
+       return FALSE;
+    }
+  else if (c == CONST0_RTX (GET_MODE (b)))
+    {
+      if (one_cmpl
+         && GET_CODE (cond) != GE
+         && GET_CODE (cond) != LT)
+       return FALSE;
+    }
+  else
     return FALSE;
 
   /* Determine what sort of operation this is.  */
@@ -2579,6 +2741,7 @@ noce_try_abs (struct noce_if_info *if_info)
   emit_insn_before_setloc (seq, if_info->jump, INSN_LOCATION (if_info->insn_a));
   if_info->cond = cond;
   if_info->cond_earliest = earliest;
+  if_info->transform_name = "noce_try_abs";
 
   return TRUE;
 }
@@ -2635,7 +2798,7 @@ noce_try_sign_mask (struct noce_if_info *if_info)
      && (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, optimize_bb_for_speed_p (if_info->test_bb))
+       || (set_src_cost (t, mode, if_info->speed_p)
            < COSTS_N_INSNS (2))))
     return FALSE;
 
@@ -2660,6 +2823,8 @@ noce_try_sign_mask (struct noce_if_info *if_info)
     return FALSE;
 
   emit_insn_before_setloc (seq, if_info->jump, INSN_LOCATION (if_info->insn_a));
+  if_info->transform_name = "noce_try_sign_mask";
+
   return TRUE;
 }
 
@@ -2718,7 +2883,7 @@ noce_try_bitop (struct noce_if_info *if_info)
       if (! rtx_equal_p (x, XEXP (a, 0))
           || !CONST_INT_P (XEXP (a, 1))
          || (INTVAL (XEXP (a, 1)) & GET_MODE_MASK (mode))
-            != (unsigned HOST_WIDE_INT) 1 << bitnum)
+            != HOST_WIDE_INT_1U << bitnum)
         return FALSE;
 
       /* if ((x & C) == 0) x |= C; is transformed to x |= C.   */
@@ -2728,13 +2893,13 @@ noce_try_bitop (struct noce_if_info *if_info)
       else if (code == NE)
        {
          /* if ((x & C) == 0) x ^= C; is transformed to x |= C.   */
-         result = gen_int_mode ((HOST_WIDE_INT) 1 << bitnum, mode);
+         result = gen_int_mode (HOST_WIDE_INT_1 << bitnum, mode);
          result = simplify_gen_binary (IOR, mode, x, result);
        }
       else
        {
          /* if ((x & C) != 0) x ^= C; is transformed to x &= ~C.  */
-         result = gen_int_mode (~((HOST_WIDE_INT) 1 << bitnum), mode);
+         result = gen_int_mode (~(HOST_WIDE_INT_1 << bitnum), mode);
          result = simplify_gen_binary (AND, mode, x, result);
        }
     }
@@ -2744,7 +2909,7 @@ noce_try_bitop (struct noce_if_info *if_info)
       if (! rtx_equal_p (x, XEXP (a, 0))
          || !CONST_INT_P (XEXP (a, 1))
          || (INTVAL (XEXP (a, 1)) & GET_MODE_MASK (mode))
-            != (~((HOST_WIDE_INT) 1 << bitnum) & GET_MODE_MASK (mode)))
+            != (~(HOST_WIDE_INT_1 << bitnum) & GET_MODE_MASK (mode)))
         return FALSE;
 
       /* if ((x & C) == 0) x &= ~C; is transformed to nothing.  */
@@ -2765,6 +2930,7 @@ noce_try_bitop (struct noce_if_info *if_info)
       emit_insn_before_setloc (seq, if_info->jump,
                               INSN_LOCATION (if_info->insn_a));
     }
+  if_info->transform_name = "noce_try_bitop";
   return TRUE;
 }
 
@@ -2789,7 +2955,7 @@ noce_get_condition (rtx_insn *jump, rtx_insn **earliest, bool then_else_reversed
   /* If this branches to JUMP_LABEL when the condition is false,
      reverse the condition.  */
   reverse = (GET_CODE (XEXP (SET_SRC (set), 2)) == LABEL_REF
-            && LABEL_REF_LABEL (XEXP (SET_SRC (set), 2)) == JUMP_LABEL (jump));
+            && label_ref_label (XEXP (SET_SRC (set), 2)) == JUMP_LABEL (jump));
 
   /* We may have to reverse because the caller's if block is not canonical,
      i.e. the THEN block isn't the fallthrough block for the TEST block
@@ -2842,97 +3008,6 @@ noce_operand_ok (const_rtx op)
   return ! may_trap_p (op);
 }
 
-/* Return true if a write into MEM may trap or fault.  */
-
-static bool
-noce_mem_write_may_trap_or_fault_p (const_rtx mem)
-{
-  rtx addr;
-
-  if (MEM_READONLY_P (mem))
-    return true;
-
-  if (may_trap_or_fault_p (mem))
-    return true;
-
-  addr = XEXP (mem, 0);
-
-  /* Call target hook to avoid the effects of -fpic etc....  */
-  addr = targetm.delegitimize_address (addr);
-
-  while (addr)
-    switch (GET_CODE (addr))
-      {
-      case CONST:
-      case PRE_DEC:
-      case PRE_INC:
-      case POST_DEC:
-      case POST_INC:
-      case POST_MODIFY:
-       addr = XEXP (addr, 0);
-       break;
-      case LO_SUM:
-      case PRE_MODIFY:
-       addr = XEXP (addr, 1);
-       break;
-      case PLUS:
-       if (CONST_INT_P (XEXP (addr, 1)))
-         addr = XEXP (addr, 0);
-       else
-         return false;
-       break;
-      case LABEL_REF:
-       return true;
-      case SYMBOL_REF:
-       if (SYMBOL_REF_DECL (addr)
-           && decl_readonly_section (SYMBOL_REF_DECL (addr), 0))
-         return true;
-       return false;
-      default:
-       return false;
-      }
-
-  return false;
-}
-
-/* Return whether we can use store speculation for MEM.  TOP_BB is the
-   basic block above the conditional block where we are considering
-   doing the speculative store.  We look for whether MEM is set
-   unconditionally later in the function.  */
-
-static bool
-noce_can_store_speculate_p (basic_block top_bb, const_rtx mem)
-{
-  basic_block dominator;
-
-  for (dominator = get_immediate_dominator (CDI_POST_DOMINATORS, top_bb);
-       dominator != NULL;
-       dominator = get_immediate_dominator (CDI_POST_DOMINATORS, dominator))
-    {
-      rtx_insn *insn;
-
-      FOR_BB_INSNS (dominator, insn)
-       {
-         /* If we see something that might be a memory barrier, we
-            have to stop looking.  Even if the MEM is set later in
-            the function, we still don't want to set it
-            unconditionally before the barrier.  */
-         if (INSN_P (insn)
-             && (volatile_insn_p (PATTERN (insn))
-                 || (CALL_P (insn) && (!RTL_CONST_CALL_P (insn)))))
-           return false;
-
-         if (memory_must_be_modified_in_insn_p (mem, insn))
-           return true;
-         if (modified_in_p (XEXP (mem, 0), insn))
-           return false;
-
-       }
-    }
-
-  return false;
-}
-
 /* Return true if X contains a MEM subrtx.  */
 
 static bool
@@ -2952,8 +3027,8 @@ contains_mem_rtx_p (rtx x)
    x := a and all previous computations
    in TEST_BB don't produce any values that are live after TEST_BB.
    In other words, all the insns in TEST_BB are there only
-   to compute a value for x.  Put the rtx cost of the insns
-   in TEST_BB into COST.  Record whether TEST_BB is a single simple
+   to compute a value for x.  Add the rtx cost of the insns
+   in TEST_BB to COST.  Record whether TEST_BB is a single simple
    set instruction in SIMPLE_P.  */
 
 static bool
@@ -2985,7 +3060,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 += insn_rtx_cost (first_set, speed_p);
       return *simple_p;
     }
 
@@ -3032,7 +3107,7 @@ bb_valid_for_noce_process_p (basic_block test_bb, rtx cond,
     goto free_bitmap_and_fail;
 
   BITMAP_FREE (test_bb_temps);
-  *cost = potential_cost;
+  *cost += potential_cost;
   *simple_p = false;
   return true;
 
@@ -3146,6 +3221,41 @@ noce_convert_multiple_sets (struct noce_if_info *if_info)
       if (if_info->then_else_reversed)
        std::swap (old_val, new_val);
 
+
+      /* We allow simple lowpart register subreg SET sources in
+        bb_ok_for_noce_convert_multiple_sets.  Be careful when processing
+        sequences like:
+        (set (reg:SI r1) (reg:SI r2))
+        (set (reg:HI r3) (subreg:HI (r1)))
+        For the second insn new_val or old_val (r1 in this example) will be
+        taken from the temporaries and have the wider mode which will not
+        match with the mode of the other source of the conditional move, so
+        we'll end up trying to emit r4:HI = cond ? (r1:SI) : (r3:HI).
+        Wrap the two cmove operands into subregs if appropriate to prevent
+        that.  */
+      if (GET_MODE (new_val) != GET_MODE (temp))
+       {
+         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))
+           {
+             end_sequence ();
+             return FALSE;
+           }
+         new_val = lowpart_subreg (dst_mode, new_val, src_mode);
+       }
+      if (GET_MODE (old_val) != GET_MODE (temp))
+       {
+         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))
+           {
+             end_sequence ();
+             return FALSE;
+           }
+         old_val = lowpart_subreg (dst_mode, old_val, src_mode);
+       }
+
       /* Actually emit the conditional move.  */
       rtx temp_dest = noce_emit_cmove (if_info, temp, cond_code,
                                       x, y, new_val, old_val);
@@ -3173,9 +3283,15 @@ noce_convert_multiple_sets (struct noce_if_info *if_info)
   for (int i = 0; i < count; i++)
     noce_emit_move_insn (targets[i], temporaries[i]);
 
-  /* Actually emit the sequence.  */
+  /* Actually emit the sequence if it isn't too expensive.  */
   rtx_insn *seq = get_insns ();
 
+  if (!noce_conversion_profitable_p (seq, if_info))
+    {
+      end_sequence ();
+      return FALSE;
+    }
+
   for (insn = seq; insn; insn = NEXT_INSN (insn))
     set_used_flags (insn);
 
@@ -3219,25 +3335,22 @@ noce_convert_multiple_sets (struct noce_if_info *if_info)
     }
 
   num_updated_if_blocks++;
+  if_info->transform_name = "noce_convert_multiple_sets";
   return TRUE;
 }
 
 /* Return true iff basic block TEST_BB is comprised of only
    (SET (REG) (REG)) insns suitable for conversion to a series
-   of conditional moves.  FORNOW: Use II to find the expected cost of
-   the branch into/over TEST_BB.
-
-   TODO: This creates an implicit "magic number" for branch_cost.
-   II->branch_cost now guides the maximum number of set instructions in
-   a basic block which is considered profitable to completely
-   if-convert.  */
+   of conditional moves.  Also check that we have more than one set
+   (other routines can handle a single set better than we would), and
+   fewer than PARAM_MAX_RTL_IF_CONVERSION_INSNS sets.  */
 
 static bool
-bb_ok_for_noce_convert_multiple_sets (basic_block test_bb,
-                                     struct noce_if_info *ii)
+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);
 
   FOR_BB_INSNS (test_bb, insn)
     {
@@ -3254,9 +3367,15 @@ bb_ok_for_noce_convert_multiple_sets (basic_block test_bb,
       rtx src = SET_SRC (set);
 
       /* We can possibly relax this, but for now only handle REG to REG
-        moves.  This avoids any issues that might come from introducing
-        loads/stores that might violate data-race-freedom guarantees.  */
-      if (!(REG_P (src) && REG_P (dest)))
+        (including subreg) moves.  This avoids any issues that might come
+        from introducing loads/stores that might violate data-race-freedom
+        guarantees.  */
+      if (!REG_P (dest))
+       return false;
+
+      if (!(REG_P (src)
+          || (GET_CODE (src) == SUBREG && REG_P (SUBREG_REG (src))
+              && subreg_lowpart_p (src))))
        return false;
 
       /* Destination must be appropriate for a conditional write.  */
@@ -3267,16 +3386,15 @@ bb_ok_for_noce_convert_multiple_sets (basic_block test_bb,
       if (!can_conditionally_move_p (GET_MODE (dest)))
        return false;
 
-      ++count;
+      count++;
     }
 
-  /* FORNOW: Our cost model is a count of the number of instructions we
-     would if-convert.  This is suboptimal, and should be improved as part
-     of a wider rework of branch_cost.  */
-  if (count > ii->branch_cost)
-    return FALSE;
-
-  return count > 0;
+  /* If we would only put out one conditional move, the other strategies
+     this pass tries are better optimized and will be more appropriate.
+     Some targets want to strictly limit the number of conditional moves
+     that are emitted, they set this through PARAM, we need to respect
+     that.  */
+  return count > 1 && count <= param;
 }
 
 /* Given a simple IF-THEN-JOIN or IF-THEN-ELSE-JOIN block, attempt to convert
@@ -3312,18 +3430,23 @@ noce_process_if_block (struct noce_if_info *if_info)
   if (!else_bb
       && HAVE_conditional_move
       && !HAVE_cc0
-      && bb_ok_for_noce_convert_multiple_sets (then_bb, if_info))
+      && bb_ok_for_noce_convert_multiple_sets (then_bb))
     {
       if (noce_convert_multiple_sets (if_info))
-       return TRUE;
+       {
+         if (dump_file && if_info->transform_name)
+           fprintf (dump_file, "if-conversion succeeded through %s\n",
+                    if_info->transform_name);
+         return TRUE;
+       }
     }
 
-  if (! bb_valid_for_noce_process_p (then_bb, cond, &if_info->then_cost,
+  if (! bb_valid_for_noce_process_p (then_bb, cond, &if_info->original_cost,
                                    &if_info->then_simple))
     return false;
 
   if (else_bb
-      && ! bb_valid_for_noce_process_p (else_bb, cond, &if_info->else_cost,
+      && ! bb_valid_for_noce_process_p (else_bb, cond, &if_info->original_cost,
                                      &if_info->else_simple))
     return false;
 
@@ -3396,6 +3519,7 @@ noce_process_if_block (struct noce_if_info *if_info)
   /* Only operate on register destinations, and even then avoid extending
      the lifetime of hard registers on small register class machines.  */
   orig_x = x;
+  if_info->orig_x = orig_x;
   if (!REG_P (x)
       || (HARD_REGISTER_P (x)
          && targetm.small_register_classes_for_mode_p (GET_MODE (x))))
@@ -3462,33 +3586,17 @@ noce_process_if_block (struct noce_if_info *if_info)
     }
 
   if (!set_b && MEM_P (orig_x))
-    {
-      /* Disallow the "if (...) x = a;" form (implicit "else x = x;")
-        for optimizations if writing to x may trap or fault,
-        i.e. it's a memory other than a static var or a stack slot,
-        is misaligned on strict aligned machines or is read-only.  If
-        x is a read-only memory, then the program is valid only if we
-        avoid the store into it.  If there are stores on both the
-        THEN and ELSE arms, then we can go ahead with the conversion;
-        either the program is broken, or the condition is always
-        false such that the other memory is selected.  */
-      if (noce_mem_write_may_trap_or_fault_p (orig_x))
-       return FALSE;
-
-      /* Avoid store speculation: given "if (...) x = a" where x is a
-        MEM, we only want to do the store if x is always set
-        somewhere in the function.  This avoids cases like
-          if (pthread_mutex_trylock(mutex))
-            ++global_variable;
-        where we only want global_variable to be changed if the mutex
-        is held.  FIXME: This should ideally be expressed directly in
-        RTL somehow.  */
-      if (!noce_can_store_speculate_p (test_bb, orig_x))
-       return FALSE;
-    }
+    /* We want to avoid store speculation to avoid cases like
+        if (pthread_mutex_trylock(mutex))
+          ++global_variable;
+       Rather than go to much effort here, we rely on the SSA optimizers,
+       which do a good enough job these days.  */
+    return FALSE;
 
   if (noce_try_move (if_info))
     goto success;
+  if (noce_try_ifelse_collapse (if_info))
+    goto success;
   if (noce_try_store_flag (if_info))
     goto success;
   if (noce_try_bitop (if_info))
@@ -3497,6 +3605,8 @@ noce_process_if_block (struct noce_if_info *if_info)
     goto success;
   if (noce_try_abs (if_info))
     goto success;
+  if (noce_try_inverse_constants (if_info))
+    goto success;
   if (!targetm.have_conditional_execution ()
       && noce_try_store_flag_constants (if_info))
     goto success;
@@ -3527,6 +3637,9 @@ noce_process_if_block (struct noce_if_info *if_info)
   return FALSE;
 
  success:
+  if (dump_file && if_info->transform_name)
+    fprintf (dump_file, "if-conversion succeeded through %s\n",
+            if_info->transform_name);
 
   /* If we used a temporary, fix it up now.  */
   if (orig_x != x)
@@ -3739,6 +3852,7 @@ cond_move_process_if_block (struct noce_if_info *if_info)
   vec<rtx> else_regs = vNULL;
   unsigned int i;
   int success_p = FALSE;
+  int limit = PARAM_VALUE (PARAM_MAX_RTL_IF_CONVERSION_INSNS);
 
   /* Build a mapping for each block to the value used for each
      register.  */
@@ -3788,7 +3902,8 @@ cond_move_process_if_block (struct noce_if_info *if_info)
      is the number of assignments currently made in only one of the
      branches, since if we convert we are going to always execute
      them.  */
-  if (c > MAX_CONDITIONAL_EXECUTE)
+  if (c > MAX_CONDITIONAL_EXECUTE
+      || c > limit)
     goto done;
 
   /* Try to emit the conditional moves.  First do the then block,
@@ -3835,7 +3950,6 @@ cond_move_process_if_block (struct noce_if_info *if_info)
     }
 
   num_updated_if_blocks++;
-
   success_p = TRUE;
 
 done:
@@ -3863,6 +3977,7 @@ noce_find_if_block (basic_block test_bb, edge then_edge, edge else_edge,
   rtx cond;
   rtx_insn *cond_earliest;
   struct noce_if_info if_info;
+  bool speed_p = optimize_bb_for_speed_p (test_bb);
 
   /* We only ever should get here before reload.  */
   gcc_assert (!reload_completed);
@@ -3954,8 +4069,16 @@ noce_find_if_block (basic_block test_bb, edge then_edge, edge else_edge,
   if_info.cond_earliest = cond_earliest;
   if_info.jump = jump;
   if_info.then_else_reversed = then_else_reversed;
-  if_info.branch_cost = BRANCH_COST (optimize_bb_for_speed_p (test_bb),
-                                    predictable_edge_p (then_edge));
+  if_info.speed_p = speed_p;
+  if_info.max_seq_cost
+    = targetm.max_noce_ifcvt_seq_cost (then_edge);
+  /* We'll add in the cost of THEN_BB and ELSE_BB later, when we check
+     that they are valid to transform.  We can't easily get back to the insn
+     for COND (and it may not exist if we had to canonicalize to get COND),
+     and jump_insns are always given a cost of 1 by seq_cost, so treat
+     both instructions as having cost COSTS_N_INSNS (1).  */
+  if_info.original_cost = COSTS_N_INSNS (2);
+
 
   /* Do the real work.  */
 
@@ -4538,8 +4661,11 @@ 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.  */
-  if (! onlyjump_p (jump))
+     we can not 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.  */
+  if (! onlyjump_p (jump) || returnjump_p (jump))
     return FALSE;
 
   /* We must be comparing objects whose modes imply the size.  */
@@ -4819,7 +4945,6 @@ find_if_case_1 (basic_block test_bb, edge then_edge, edge else_edge)
 
   num_true_changes++;
   num_updated_if_blocks++;
-
   return TRUE;
 }
 
This page took 0.064278 seconds and 5 git commands to generate.