OSDN Git Service

* sourcebuild.texi (Config Fragments): Use @comma{} in
[pf3gnuchains/gcc-fork.git] / gcc / ifcvt.c
index f92b7e8..0be6472 100644 (file)
@@ -1,5 +1,5 @@
 /* If-conversion support.
-   Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc.
+   Copyright (C) 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
 
    This file is part of GCC.
 
@@ -20,6 +20,8 @@
 
 #include "config.h"
 #include "system.h"
+#include "coretypes.h"
+#include "tm.h"
 
 #include "rtl.h"
 #include "regs.h"
 #include "expr.h"
 #include "real.h"
 #include "output.h"
+#include "optabs.h"
 #include "toplev.h"
 #include "tm_p.h"
+#include "cfgloop.h"
+#include "target.h"
 
 
 #ifndef HAVE_conditional_execution
@@ -70,8 +75,8 @@ static int num_possible_if_blocks;
    execution.  */
 static int num_updated_if_blocks;
 
-/* # of basic blocks that were removed.  */
-static int num_removed_blocks;
+/* # of changes made which require life information to be updated.  */
+static int num_true_changes;
 
 /* Whether conditional execution changes were made.  */
 static int cond_exec_changed_p;
@@ -79,51 +84,75 @@ static int cond_exec_changed_p;
 /* True if life data ok at present.  */
 static bool life_data_ok;
 
-/* The post-dominator relation on the original block numbers.  */
-static dominance_info post_dominators;
-
 /* Forward references.  */
-static int count_bb_insns              PARAMS ((basic_block));
-static rtx first_active_insn           PARAMS ((basic_block));
-static rtx last_active_insn            PARAMS ((basic_block, int));
-static int seq_contains_jump           PARAMS ((rtx));
-static basic_block block_fallthru      PARAMS ((basic_block));
-static int cond_exec_process_insns     PARAMS ((ce_if_block_t *,
-                                                rtx, rtx, rtx, rtx, int));
-static rtx cond_exec_get_condition     PARAMS ((rtx));
-static int cond_exec_process_if_block  PARAMS ((ce_if_block_t *, int));
-static rtx noce_get_condition          PARAMS ((rtx, rtx *));
-static int noce_operand_ok             PARAMS ((rtx));
-static int noce_process_if_block       PARAMS ((ce_if_block_t *));
-static int process_if_block            PARAMS ((ce_if_block_t *));
-static void merge_if_block             PARAMS ((ce_if_block_t *));
-static int find_cond_trap              PARAMS ((basic_block, edge, edge));
-static basic_block find_if_header      PARAMS ((basic_block, int));
-static int block_jumps_and_fallthru_p  PARAMS ((basic_block, basic_block));
-static int find_if_block               PARAMS ((ce_if_block_t *));
-static int find_if_case_1              PARAMS ((basic_block, edge, edge));
-static int find_if_case_2              PARAMS ((basic_block, edge, edge));
-static int find_memory                 PARAMS ((rtx *, void *));
-static int dead_or_predicable          PARAMS ((basic_block, basic_block,
-                                                basic_block, basic_block, int));
-static void noce_emit_move_insn                PARAMS ((rtx, rtx));
-static rtx block_has_only_trap         PARAMS ((basic_block));
+static int count_bb_insns (basic_block);
+static rtx first_active_insn (basic_block);
+static rtx last_active_insn (basic_block, int);
+static basic_block block_fallthru (basic_block);
+static int cond_exec_process_insns (ce_if_block_t *, rtx, rtx, rtx, rtx, int);
+static rtx cond_exec_get_condition (rtx);
+static int cond_exec_process_if_block (ce_if_block_t *, int);
+static rtx noce_get_condition (rtx, rtx *);
+static int noce_operand_ok (rtx);
+static int noce_process_if_block (ce_if_block_t *);
+static int process_if_block (ce_if_block_t *);
+static void merge_if_block (ce_if_block_t *);
+static int find_cond_trap (basic_block, edge, edge);
+static basic_block find_if_header (basic_block, int);
+static int block_jumps_and_fallthru_p (basic_block, basic_block);
+static int find_if_block (ce_if_block_t *);
+static int find_if_case_1 (basic_block, edge, edge);
+static int find_if_case_2 (basic_block, edge, edge);
+static int find_memory (rtx *, void *);
+static int dead_or_predicable (basic_block, basic_block, basic_block,
+                              basic_block, int);
+static void noce_emit_move_insn (rtx, rtx);
+static rtx block_has_only_trap (basic_block);
+static void mark_loop_exit_edges (void);
 \f
+/* Sets EDGE_LOOP_EXIT flag for all loop exits.  */
+static void
+mark_loop_exit_edges (void)
+{
+  struct loops loops;
+  basic_block bb;
+  edge e;
+  
+  flow_loops_find (&loops, LOOP_TREE);
+  free_dominance_info (CDI_DOMINATORS);
+  
+  if (loops.num > 1)
+    {
+      FOR_EACH_BB (bb)
+       {
+         for (e = bb->succ; e; e = e->succ_next)
+           {
+             if (find_common_loop (bb->loop_father, e->dest->loop_father)
+                 != bb->loop_father)
+               e->flags |= EDGE_LOOP_EXIT;
+             else
+               e->flags &= ~EDGE_LOOP_EXIT;
+           }
+       }
+    }
+
+  flow_loops_free (&loops);
+}
+
 /* Count the number of non-jump active insns in BB.  */
 
 static int
-count_bb_insns (bb)
-     basic_block bb;
+count_bb_insns (basic_block bb)
 {
   int count = 0;
-  rtx insn = bb->head;
+  rtx insn = BB_HEAD (bb);
 
   while (1)
     {
       if (GET_CODE (insn) == CALL_INSN || GET_CODE (insn) == INSN)
        count++;
 
-      if (insn == bb->end)
+      if (insn == BB_END (bb))
        break;
       insn = NEXT_INSN (insn);
     }
@@ -134,21 +163,20 @@ count_bb_insns (bb)
 /* Return the first non-jump active insn in the basic block.  */
 
 static rtx
-first_active_insn (bb)
-     basic_block bb;
+first_active_insn (basic_block bb)
 {
-  rtx insn = bb->head;
+  rtx insn = BB_HEAD (bb);
 
   if (GET_CODE (insn) == CODE_LABEL)
     {
-      if (insn == bb->end)
+      if (insn == BB_END (bb))
        return NULL_RTX;
       insn = NEXT_INSN (insn);
     }
 
   while (GET_CODE (insn) == NOTE)
     {
-      if (insn == bb->end)
+      if (insn == BB_END (bb))
        return NULL_RTX;
       insn = NEXT_INSN (insn);
     }
@@ -162,12 +190,10 @@ first_active_insn (bb)
 /* Return the last non-jump active (non-jump) insn in the basic block.  */
 
 static rtx
-last_active_insn (bb, skip_use_p)
-     basic_block bb;
-     int skip_use_p;
+last_active_insn (basic_block bb, int skip_use_p)
 {
-  rtx insn = bb->end;
-  rtx head = bb->head;
+  rtx insn = BB_END (bb);
+  rtx head = BB_HEAD (bb);
 
   while (GET_CODE (insn) == NOTE
         || GET_CODE (insn) == JUMP_INSN
@@ -186,27 +212,10 @@ last_active_insn (bb, skip_use_p)
   return 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;
-}
+/* Return the basic block reached by falling though the basic block BB.  */
 
 static basic_block
-block_fallthru (bb)
-     basic_block bb;
+block_fallthru (basic_block bb)
 {
   edge e;
 
@@ -223,13 +232,12 @@ block_fallthru (bb)
    insns were processed.  */
 
 static int
-cond_exec_process_insns (ce_info, start, end, test, prob_val, mod_ok)
-     ce_if_block_t *ce_info ATTRIBUTE_UNUSED;  /* if block information */
-     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.  */
+cond_exec_process_insns (ce_if_block_t *ce_info ATTRIBUTE_UNUSED,
+                        /* if block information */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)
 {
   int must_be_last = FALSE;
   rtx insn;
@@ -250,11 +258,9 @@ cond_exec_process_insns (ce_info, start, end, test, prob_val, mod_ok)
       /* Remove USE insns that get in the way.  */
       if (reload_completed && GET_CODE (PATTERN (insn)) == USE)
        {
-         /* ??? Ug.  Actually unlinking the thing is problematic, 
+         /* ??? 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;
+         SET_INSN_DELETED (insn);
          goto insn_done;
        }
 
@@ -314,8 +320,7 @@ cond_exec_process_insns (ce_info, start, end, test, prob_val, mod_ok)
 /* Return the condition for a jump.  Do not do any special processing.  */
 
 static rtx
-cond_exec_get_condition (jump)
-     rtx jump;
+cond_exec_get_condition (rtx jump)
 {
   rtx test_if, cond;
 
@@ -346,9 +351,8 @@ cond_exec_get_condition (jump)
    converting the block.  */
 
 static int
-cond_exec_process_if_block (ce_info, do_multiple_p)
-     ce_if_block_t * ce_info;  /* if block information */
-     int do_multiple_p;                /* != 0 if we should handle && and || blocks */
+cond_exec_process_if_block (ce_if_block_t * ce_info,
+                           /* if block information */int do_multiple_p)
 {
   basic_block test_bb = ce_info->test_bb;      /* last test block */
   basic_block then_bb = ce_info->then_bb;      /* THEN */
@@ -358,7 +362,7 @@ cond_exec_process_if_block (ce_info, do_multiple_p)
   rtx then_end;                        /* last insn + 1 in THEN 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 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 */
@@ -383,13 +387,13 @@ cond_exec_process_if_block (ce_info, do_multiple_p)
 
   /* Find the conditional jump to the ELSE or JOIN part, and isolate
      the test.  */
-  test_expr = cond_exec_get_condition (test_bb->end);
+  test_expr = cond_exec_get_condition (BB_END (test_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))
+  if (! onlyjump_p (BB_END (test_bb)))
     return FALSE;
 
   /* Collect the bounds of where we're to search, skipping any labels, jumps
@@ -413,10 +417,10 @@ cond_exec_process_if_block (ce_info, do_multiple_p)
 
   /* Map test_expr/test_jump into the appropriate MD tests to use on
      the conditionally executed code.  */
-  
+
   true_expr = test_expr;
 
-  false_code = reversed_comparison_code (true_expr, test_bb->end);
+  false_code = reversed_comparison_code (true_expr, BB_END (test_bb));
   if (false_code != UNKNOWN)
     false_expr = gen_rtx_fmt_ee (false_code, GET_MODE (true_expr),
                                 XEXP (true_expr, 0), XEXP (true_expr, 1));
@@ -428,12 +432,12 @@ cond_exec_process_if_block (ce_info, do_multiple_p)
      conditional execution register from a comparison, it can do so here.  */
   IFCVT_MODIFY_TESTS (ce_info, true_expr, false_expr);
 
-  /* See if the conversion failed */
+  /* 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);
+  true_prob_val = find_reg_note (BB_END (test_bb), REG_BR_PROB, NULL_RTX);
   if (true_prob_val)
     {
       true_prob_val = XEXP (true_prob_val, 0);
@@ -467,11 +471,11 @@ cond_exec_process_if_block (ce_info, do_multiple_p)
 
          /* 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 (bb->end))
+         if (! onlyjump_p (BB_END (bb)))
            goto fail;
 
          /* Find the conditional jump and isolate the test.  */
-         t = cond_exec_get_condition (bb->end);
+         t = cond_exec_get_condition (BB_END (bb));
          if (! t)
            goto fail;
 
@@ -497,7 +501,7 @@ cond_exec_process_if_block (ce_info, do_multiple_p)
 #ifdef IFCVT_MODIFY_MULTIPLE_TESTS
          IFCVT_MODIFY_MULTIPLE_TESTS (ce_info, bb, t, f);
 
-         /* See if the conversion failed */
+         /* See if the conversion failed */
          if (!t || !f)
            goto fail;
 #endif
@@ -539,13 +543,13 @@ cond_exec_process_if_block (ce_info, do_multiple_p)
     }
 
 #ifdef IFCVT_MODIFY_FINAL
-  /* Do any machine dependent final modifications */
+  /* Do any machine dependent final modifications */
   IFCVT_MODIFY_FINAL (ce_info);
 #endif
 
   /* Conversion succeeded.  */
-  if (rtl_dump_file)
-    fprintf (rtl_dump_file, "%d insn%s converted to conditional execution.\n",
+  if (dump_file)
+    fprintf (dump_file, "%d insn%s converted to conditional execution.\n",
             n_insns, (n_insns == 1) ? " was" : "s were");
 
   /* Merge the blocks!  */
@@ -563,10 +567,10 @@ cond_exec_process_if_block (ce_info, do_multiple_p)
   return FALSE;
 }
 \f
-/* Used by noce_process_if_block to communicate with its subroutines. 
+/* Used by noce_process_if_block to communicate with its subroutines.
 
    The subroutines know that A and B may be evaluated freely.  They
-   know that X is a register.  They should insert new instructions 
+   know that X is a register.  They should insert new instructions
    before cond_earliest.  */
 
 struct noce_if_info
@@ -577,29 +581,26 @@ struct noce_if_info
   rtx jump, cond, cond_earliest;
 };
 
-static rtx noce_emit_store_flag                PARAMS ((struct noce_if_info *,
-                                                rtx, int, int));
-static int noce_try_store_flag         PARAMS ((struct noce_if_info *));
-static int noce_try_store_flag_inc     PARAMS ((struct noce_if_info *));
-static int noce_try_store_flag_constants PARAMS ((struct noce_if_info *));
-static int noce_try_store_flag_mask    PARAMS ((struct noce_if_info *));
-static rtx noce_emit_cmove             PARAMS ((struct noce_if_info *,
-                                                rtx, enum rtx_code, rtx,
-                                                rtx, rtx, rtx));
-static int noce_try_cmove              PARAMS ((struct noce_if_info *));
-static int noce_try_cmove_arith                PARAMS ((struct noce_if_info *));
-static rtx noce_get_alt_condition      PARAMS ((struct noce_if_info *,
-                                                rtx, rtx *));
-static int noce_try_minmax             PARAMS ((struct noce_if_info *));
-static int noce_try_abs                        PARAMS ((struct noce_if_info *));
+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_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 *);
+static int noce_try_store_flag_mask (struct noce_if_info *);
+static rtx noce_emit_cmove (struct noce_if_info *, rtx, enum rtx_code, rtx,
+                           rtx, rtx, rtx);
+static int noce_try_cmove (struct noce_if_info *);
+static int noce_try_cmove_arith (struct noce_if_info *);
+static rtx noce_get_alt_condition (struct noce_if_info *, rtx, rtx *);
+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 *);
 
 /* Helper function for noce_try_store_flag*.  */
 
 static rtx
-noce_emit_store_flag (if_info, x, reversep, normalize)
-     struct noce_if_info *if_info;
-     rtx x;
-     int reversep, normalize;
+noce_emit_store_flag (struct noce_if_info *if_info, rtx x, int reversep,
+                     int normalize)
 {
   rtx cond = if_info->cond;
   int cond_complex;
@@ -645,8 +646,8 @@ noce_emit_store_flag (if_info, x, reversep, normalize)
       end_sequence ();
     }
 
-  /* Don't even try if the comparison operands are weird.  */
-  if (cond_complex)
+  /* Don't even try if the comparison operands or the mode of X are weird.  */
+  if (cond_complex || !SCALAR_INT_MODE_P (GET_MODE (x)))
     return NULL_RTX;
 
   return emit_store_flag (x, code, XEXP (cond, 0),
@@ -655,10 +656,11 @@ noce_emit_store_flag (if_info, x, reversep, normalize)
                           || code == GEU || code == GTU), normalize);
 }
 
-/* Emit instruction to move an rtx into STRICT_LOW_PART.  */
+/* Emit instruction to move an rtx, possibly into STRICT_LOW_PART.
+   X is the destination/target and Y is the value to copy.  */
+
 static void
-noce_emit_move_insn (x, y)
-     rtx x, y;
+noce_emit_move_insn (rtx x, rtx y)
 {
   enum machine_mode outmode, inmode;
   rtx outer, inner;
@@ -679,6 +681,79 @@ noce_emit_move_insn (x, y)
                   GET_MODE_BITSIZE (inmode));
 }
 
+/* Return sequence of instructions generated by if conversion.  This
+   function calls end_sequence() to end the current stream, ensures
+   that are instructions are unshared, recognizable non-jump insns.
+   On failure, this function returns a NULL_RTX.  */
+
+static rtx
+end_ifcvt_sequence (struct noce_if_info *if_info)
+{
+  rtx insn;
+  rtx seq = get_insns ();
+
+  set_used_flags (if_info->x);
+  set_used_flags (if_info->cond);
+  unshare_all_rtl_in_chain (seq);
+  end_sequence ();
+
+  /* Make sure that all of the instructions emitted are recognizable,
+     and that we haven't introduced a new jump instruction.
+     As an exercise for the reader, build a general mechanism that
+     allows proper placement of required clobbers.  */
+  for (insn = seq; insn; insn = NEXT_INSN (insn))
+    if (GET_CODE (insn) == JUMP_INSN
+       || recog_memoized (insn) == -1)
+      return NULL_RTX;
+
+  return seq;
+}
+
+/* Convert "if (a != b) x = a; else x = b" into "x = a" and
+   "if (a == b) x = a; else x = b" into "x = b".  */
+
+static int
+noce_try_move (struct noce_if_info *if_info)
+{
+  rtx cond = if_info->cond;
+  enum rtx_code code = GET_CODE (cond);
+  rtx y, seq;
+
+  if (code != NE && code != EQ)
+    return FALSE;
+
+  /* This optimization isn't valid if either A or B could be a NaN
+     or a signed zero.  */
+  if (HONOR_NANS (GET_MODE (if_info->x))
+      || HONOR_SIGNED_ZEROS (GET_MODE (if_info->x)))
+    return FALSE;
+
+  /* Check whether the operands of the comparison are A and in
+     either order.  */
+  if ((rtx_equal_p (if_info->a, XEXP (cond, 0))
+       && rtx_equal_p (if_info->b, XEXP (cond, 1)))
+      || (rtx_equal_p (if_info->a, XEXP (cond, 1))
+         && rtx_equal_p (if_info->b, XEXP (cond, 0))))
+    {
+      y = (code == EQ) ? if_info->a : if_info->b;
+
+      /* Avoid generating the move if the source is the destination.  */
+      if (! rtx_equal_p (if_info->x, y))
+       {
+         start_sequence ();
+         noce_emit_move_insn (if_info->x, y);
+         seq = end_ifcvt_sequence (if_info);
+         if (!seq)
+           return FALSE;
+
+         emit_insn_before_setloc (seq, if_info->jump,
+                                  INSN_LOCATOR (if_info->insn_a));
+       }
+      return TRUE;
+    }
+  return FALSE;
+}
+
 /* Convert "if (test) x = 1; else x = 0".
 
    Only try 0 and STORE_FLAG_VALUE here.  Other combinations will be
@@ -686,8 +761,7 @@ noce_emit_move_insn (x, y)
    a go at the conversion.  */
 
 static int
-noce_try_store_flag (if_info)
-     struct noce_if_info *if_info;
+noce_try_store_flag (struct noce_if_info *if_info)
 {
   int reversep;
   rtx target, seq;
@@ -713,10 +787,12 @@ noce_try_store_flag (if_info)
       if (target != if_info->x)
        noce_emit_move_insn (if_info->x, target);
 
-      seq = get_insns ();
-      end_sequence ();
-      emit_insn_before_scope (seq, if_info->jump, INSN_SCOPE (if_info->insn_a));
+      seq = end_ifcvt_sequence (if_info);
+      if (! seq)
+       return FALSE;
 
+      emit_insn_before_setloc (seq, if_info->jump,
+                              INSN_LOCATOR (if_info->insn_a));
       return TRUE;
     }
   else
@@ -729,8 +805,7 @@ noce_try_store_flag (if_info)
 /* Convert "if (test) x = a; else x = b", for A and B constant.  */
 
 static int
-noce_try_store_flag_constants (if_info)
-     struct noce_if_info *if_info;
+noce_try_store_flag_constants (struct noce_if_info *if_info)
 {
   rtx target, seq;
   int reversep;
@@ -780,7 +855,7 @@ noce_try_store_flag_constants (if_info)
        return FALSE;
 
       if (reversep)
-       {
+       {
          tmp = itrue; itrue = ifalse; ifalse = tmp;
          diff = trunc_int_for_mode (-diff, mode);
        }
@@ -844,79 +919,105 @@ noce_try_store_flag_constants (if_info)
       if (target != if_info->x)
        noce_emit_move_insn (if_info->x, target);
 
-      seq = get_insns ();
-      end_sequence ();
-
-      if (seq_contains_jump (seq))
+      seq = end_ifcvt_sequence (if_info);
+      if (!seq)
        return FALSE;
 
-      emit_insn_before_scope (seq, if_info->jump, INSN_SCOPE (if_info->insn_a));
-
+      emit_insn_before_setloc (seq, if_info->jump,
+                              INSN_LOCATOR (if_info->insn_a));
       return TRUE;
     }
 
   return FALSE;
 }
 
-/* Convert "if (test) foo++" into "foo += (test != 0)", and 
+/* Convert "if (test) foo++" into "foo += (test != 0)", and
    similarly for "foo--".  */
 
 static int
-noce_try_store_flag_inc (if_info)
-     struct noce_if_info *if_info;
+noce_try_addcc (struct noce_if_info *if_info)
 {
   rtx target, seq;
   int subtract, normalize;
 
   if (! no_new_pseudos
-      && (BRANCH_COST >= 2
-         || HAVE_incscc
-         || HAVE_decscc)
-      /* Should be no `else' case to worry about.  */
-      && if_info->b == if_info->x
       && GET_CODE (if_info->a) == PLUS
-      && (XEXP (if_info->a, 1) == const1_rtx
-         || XEXP (if_info->a, 1) == constm1_rtx)
-      && rtx_equal_p (XEXP (if_info->a, 0), if_info->x)
+      && rtx_equal_p (XEXP (if_info->a, 0), if_info->b)
       && (reversed_comparison_code (if_info->cond, if_info->jump)
          != UNKNOWN))
     {
-      if (STORE_FLAG_VALUE == INTVAL (XEXP (if_info->a, 1)))
-       subtract = 0, normalize = 0;
-      else if (-STORE_FLAG_VALUE == INTVAL (XEXP (if_info->a, 1)))
-       subtract = 1, normalize = 0;
-      else
-       subtract = 0, normalize = INTVAL (XEXP (if_info->a, 1));
-      
-      start_sequence ();
-
-      target = noce_emit_store_flag (if_info,
-                                    gen_reg_rtx (GET_MODE (if_info->x)),
-                                    1, normalize);
+      rtx cond = if_info->cond;
+      enum rtx_code code = reversed_comparison_code (cond, if_info->jump);
 
-      if (target)
-       target = expand_simple_binop (GET_MODE (if_info->x),
-                                     subtract ? MINUS : PLUS,
-                                     if_info->x, target, if_info->x,
-                                     0, OPTAB_WIDEN);
-      if (target)
+      /* First try to use addcc pattern.  */
+      if (general_operand (XEXP (cond, 0), VOIDmode)
+         && general_operand (XEXP (cond, 1), VOIDmode))
        {
-         if (target != if_info->x)
-           noce_emit_move_insn (if_info->x, target);
+         start_sequence ();
+         target = emit_conditional_add (if_info->x, code,
+                                        XEXP (cond, 0),
+                                        XEXP (cond, 1),
+                                        VOIDmode,
+                                        if_info->b,
+                                        XEXP (if_info->a, 1),
+                                        GET_MODE (if_info->x),
+                                        (code == LTU || code == GEU
+                                         || code == LEU || code == GTU));
+         if (target)
+           {
+             if (target != if_info->x)
+               noce_emit_move_insn (if_info->x, target);
+
+             seq = end_ifcvt_sequence (if_info);
+             if (!seq)
+               return FALSE;
 
-         seq = get_insns ();
+             emit_insn_before_setloc (seq, if_info->jump,
+                                      INSN_LOCATOR (if_info->insn_a));
+             return TRUE;
+           }
          end_sequence ();
+       }
 
-         if (seq_contains_jump (seq))
-           return FALSE;
+      /* If that fails, construct conditional increment or decrement using
+        setcc.  */
+      if (BRANCH_COST >= 2
+         && (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)))
+           subtract = 0, normalize = 0;
+         else if (-STORE_FLAG_VALUE == INTVAL (XEXP (if_info->a, 1)))
+           subtract = 1, normalize = 0;
+         else
+           subtract = 0, normalize = INTVAL (XEXP (if_info->a, 1));
 
-         emit_insn_before_scope (seq, if_info->jump,
-                                 INSN_SCOPE (if_info->insn_a));
 
-         return TRUE;
-       }
+         target = noce_emit_store_flag (if_info,
+                                        gen_reg_rtx (GET_MODE (if_info->x)),
+                                        1, normalize);
 
-      end_sequence ();
+         if (target)
+           target = expand_simple_binop (GET_MODE (if_info->x),
+                                         subtract ? MINUS : PLUS,
+                                         if_info->b, target, if_info->x,
+                                         0, OPTAB_WIDEN);
+         if (target)
+           {
+             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_LOCATOR (if_info->insn_a));
+             return TRUE;
+           }
+         end_sequence ();
+       }
     }
 
   return FALSE;
@@ -925,8 +1026,7 @@ noce_try_store_flag_inc (if_info)
 /* Convert "if (test) x = 0;" to "x &= -(test == 0);"  */
 
 static int
-noce_try_store_flag_mask (if_info)
-     struct noce_if_info *if_info;
+noce_try_store_flag_mask (struct noce_if_info *if_info)
 {
   rtx target, seq;
   int reversep;
@@ -949,7 +1049,8 @@ noce_try_store_flag_mask (if_info)
                                     reversep, -1);
       if (target)
         target = expand_simple_binop (GET_MODE (if_info->x), AND,
-                                     if_info->x, target, if_info->x, 0,
+                                     if_info->x,
+                                     target, if_info->x, 0,
                                      OPTAB_WIDEN);
 
       if (target)
@@ -957,15 +1058,12 @@ noce_try_store_flag_mask (if_info)
          if (target != if_info->x)
            noce_emit_move_insn (if_info->x, target);
 
-         seq = get_insns ();
-         end_sequence ();
-
-         if (seq_contains_jump (seq))
+         seq = end_ifcvt_sequence (if_info);
+         if (!seq)
            return FALSE;
 
-         emit_insn_before_scope (seq, if_info->jump,
-                                 INSN_SCOPE (if_info->insn_a));
-
+         emit_insn_before_setloc (seq, if_info->jump,
+                                  INSN_LOCATOR (if_info->insn_a));
          return TRUE;
        }
 
@@ -978,10 +1076,8 @@ noce_try_store_flag_mask (if_info)
 /* Helper function for noce_try_cmove and noce_try_cmove_arith.  */
 
 static rtx
-noce_emit_cmove (if_info, x, code, cmp_a, cmp_b, vfalse, vtrue)
-     struct noce_if_info *if_info;
-     rtx x, cmp_a, cmp_b, vfalse, vtrue;
-     enum rtx_code code;
+noce_emit_cmove (struct noce_if_info *if_info, rtx x, enum rtx_code code,
+                rtx cmp_a, rtx cmp_b, rtx vfalse, rtx vtrue)
 {
   /* If earliest == jump, try to build the cmove insn directly.
      This is helpful when combine has created some complex condition
@@ -1024,7 +1120,7 @@ noce_emit_cmove (if_info, x, code, cmp_a, cmp_b, vfalse, vtrue)
 #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, 
+     because it leads to typos in the code not selected.  However,
      emit_conditional_move won't exist either.  */
   return NULL_RTX;
 #endif
@@ -1035,8 +1131,7 @@ noce_emit_cmove (if_info, x, code, cmp_a, cmp_b, vfalse, vtrue)
    has had a go at it.  */
 
 static int
-noce_try_cmove (if_info)
-     struct noce_if_info *if_info;
+noce_try_cmove (struct noce_if_info *if_info)
 {
   enum rtx_code code;
   rtx target, seq;
@@ -1057,10 +1152,12 @@ noce_try_cmove (if_info)
          if (target != if_info->x)
            noce_emit_move_insn (if_info->x, target);
 
-         seq = get_insns ();
-         end_sequence ();
-         emit_insn_before_scope (seq, if_info->jump,
-                                 INSN_SCOPE (if_info->insn_a));
+         seq = end_ifcvt_sequence (if_info);
+         if (!seq)
+           return FALSE;
+
+         emit_insn_before_setloc (seq, if_info->jump,
+                                  INSN_LOCATOR (if_info->insn_a));
          return TRUE;
        }
       else
@@ -1076,8 +1173,7 @@ noce_try_cmove (if_info)
 /* Try more complex cases involving conditional_move.  */
 
 static int
-noce_try_cmove_arith (if_info)
-     struct noce_if_info *if_info;
+noce_try_cmove_arith (struct noce_if_info *if_info)
 {
   rtx a = if_info->a;
   rtx b = if_info->b;
@@ -1092,7 +1188,7 @@ noce_try_cmove_arith (if_info)
      early because it'll screw alias analysis.  Note that we've
      already checked for no side effects.  */
   if (! no_new_pseudos && cse_not_expected
-      && GET_CODE (a) == MEM && GET_CODE (b) == MEM
+      && MEM_P (a) && MEM_P (b)
       && BRANCH_COST >= 5)
     {
       a = XEXP (a, 0);
@@ -1113,7 +1209,7 @@ noce_try_cmove_arith (if_info)
        if (test)
          x = y;
   */
-  
+
   code = GET_CODE (if_info->cond);
   insn_a = if_info->insn_a;
   insn_b = if_info->insn_b;
@@ -1139,7 +1235,7 @@ noce_try_cmove_arith (if_info)
 
   /* If either operand is complex, load it into a register first.
      The best way to do this is to copy the original insn.  In this
-     way we preserve any clobbers etc that the insn may have had.  
+     way we preserve any clobbers etc that the insn may have had.
      This is of course not possible in the IS_MEM case.  */
   if (! general_operand (a, GET_MODE (a)))
     {
@@ -1176,7 +1272,9 @@ noce_try_cmove_arith (if_info)
       if (is_mem)
        {
           tmp = gen_reg_rtx (GET_MODE (b));
-         tmp = emit_insn (gen_rtx_SET (VOIDmode, tmp, b));
+         tmp = emit_insn (gen_rtx_SET (VOIDmode,
+                                       tmp,
+                                       b));
        }
       else if (! insn_b)
        goto end_seq_and_fail;
@@ -1220,9 +1318,11 @@ noce_try_cmove_arith (if_info)
   else if (target != x)
     noce_emit_move_insn (x, target);
 
-  tmp = get_insns ();
-  end_sequence ();
-  emit_insn_before_scope (tmp, if_info->jump, INSN_SCOPE (if_info->insn_a));
+  tmp = end_ifcvt_sequence (if_info);
+  if (!tmp)
+    return FALSE;
+
+  emit_insn_before_setloc (tmp, if_info->jump, INSN_LOCATOR (if_info->insn_a));
   return TRUE;
 
  end_seq_and_fail:
@@ -1235,10 +1335,8 @@ noce_try_cmove_arith (if_info)
    For these we wish to know that it is A or B in the condition.  */
 
 static rtx
-noce_get_alt_condition (if_info, target, earliest)
-     struct noce_if_info *if_info;
-     rtx target;
-     rtx *earliest;
+noce_get_alt_condition (struct noce_if_info *if_info, rtx target,
+                       rtx *earliest)
 {
   rtx cond, set, insn;
   int reverse;
@@ -1359,7 +1457,7 @@ noce_get_alt_condition (if_info, target, earliest)
     }
 
   cond = canonicalize_condition (if_info->jump, cond, reverse,
-                                earliest, target);
+                                earliest, target, false);
   if (! cond || ! reg_mentioned_p (target, cond))
     return NULL;
 
@@ -1384,9 +1482,8 @@ noce_get_alt_condition (if_info, target, earliest)
 /* Convert "if (a < b) x = a; else x = b;" to "x = min(a, b);", etc.  */
 
 static int
-noce_try_minmax (if_info)
-     struct noce_if_info *if_info;
-{ 
+noce_try_minmax (struct noce_if_info *if_info)
+{
   rtx cond, earliest, target, seq;
   enum rtx_code code, op;
   int unsignedp;
@@ -1468,13 +1565,11 @@ noce_try_minmax (if_info)
   if (target != if_info->x)
     noce_emit_move_insn (if_info->x, target);
 
-  seq = get_insns ();
-  end_sequence ();  
-
-  if (seq_contains_jump (seq))
+  seq = end_ifcvt_sequence (if_info);
+  if (!seq)
     return FALSE;
 
-  emit_insn_before_scope (seq, if_info->jump, INSN_SCOPE (if_info->insn_a));
+  emit_insn_before_setloc (seq, if_info->jump, INSN_LOCATOR (if_info->insn_a));
   if_info->cond = cond;
   if_info->cond_earliest = earliest;
 
@@ -1484,9 +1579,8 @@ noce_try_minmax (if_info)
 /* Convert "if (a < 0) x = -a; else x = a;" to "x = abs(a);", etc.  */
 
 static int
-noce_try_abs (if_info)
-     struct noce_if_info *if_info;
-{ 
+noce_try_abs (struct noce_if_info *if_info)
+{
   rtx cond, earliest, target, seq, a, b, c;
   int negate;
 
@@ -1506,7 +1600,7 @@ noce_try_abs (if_info)
     }
   else
     return FALSE;
-   
+
   cond = noce_get_alt_condition (if_info, b, &earliest);
   if (!cond)
     return FALSE;
@@ -1525,9 +1619,9 @@ noce_try_abs (if_info)
     {
       rtx insn, note = NULL;
       for (insn = earliest;
-          insn != if_info->test_bb->head;
+          insn != BB_HEAD (if_info->test_bb);
           insn = PREV_INSN (insn))
-       if (INSN_P (insn) 
+       if (INSN_P (insn)
            && ((note = find_reg_note (insn, REG_EQUAL, c))
                || (note = find_reg_note (insn, REG_EQUIV, c))))
          break;
@@ -1535,13 +1629,13 @@ noce_try_abs (if_info)
        return FALSE;
       c = XEXP (note, 0);
     }
-  if (GET_CODE (c) == MEM
+  if (MEM_P (c)
       && GET_CODE (XEXP (c, 0)) == SYMBOL_REF
       && CONSTANT_POOL_ADDRESS_P (XEXP (c, 0)))
     c = get_pool_constant (XEXP (c, 0));
 
   /* Work around funny ideas get_condition has wrt canonicalization.
-     Note that these rtx constants are known to be CONST_INT, and 
+     Note that these rtx constants are known to be CONST_INT, and
      therefore imply integer comparisons.  */
   if (c == constm1_rtx && GET_CODE (cond) == GT)
     ;
@@ -1570,9 +1664,9 @@ noce_try_abs (if_info)
 
   start_sequence ();
 
-  target = expand_simple_unop (GET_MODE (if_info->x), ABS, b, if_info->x, 0);
+  target = expand_abs_nojump (GET_MODE (if_info->x), b, if_info->x, 1);
 
-  /* ??? It's a quandry whether cmove would be better here, especially
+  /* ??? It's a quandary whether cmove would be better here, especially
      for integers.  Perhaps combine will clean things up.  */
   if (target && negate)
     target = expand_simple_unop (GET_MODE (target), NEG, target, if_info->x, 0);
@@ -1586,26 +1680,90 @@ noce_try_abs (if_info)
   if (target != if_info->x)
     noce_emit_move_insn (if_info->x, target);
 
-  seq = get_insns ();
-  end_sequence ();  
-
-  if (seq_contains_jump (seq))
+  seq = end_ifcvt_sequence (if_info);
+  if (!seq)
     return FALSE;
 
-  emit_insn_before_scope (seq, if_info->jump, INSN_SCOPE (if_info->insn_a));
+  emit_insn_before_setloc (seq, if_info->jump, INSN_LOCATOR (if_info->insn_a));
   if_info->cond = cond;
   if_info->cond_earliest = earliest;
 
   return TRUE;
 }
 
+/* Convert "if (m < 0) x = b; else x = 0;" to "x = (m >> C) & b;".  */
+
+static int
+noce_try_sign_mask (struct noce_if_info *if_info)
+{
+  rtx cond, t, m, c, seq;
+  enum machine_mode mode;
+  enum rtx_code code;
+
+  if (no_new_pseudos)
+    return FALSE;
+
+  cond = if_info->cond;
+  code = GET_CODE (cond);
+  m = XEXP (cond, 0);
+  c = XEXP (cond, 1);
+
+  t = NULL_RTX;
+  if (if_info->a == const0_rtx)
+    {
+      if ((code == LT && c == const0_rtx)
+         || (code == LE && c == constm1_rtx))
+       t = if_info->b;
+    }
+  else if (if_info->b == const0_rtx)
+    {
+      if ((code == GE && c == const0_rtx)
+         || (code == GT && c == constm1_rtx))
+       t = if_info->a;
+    }
+
+  if (! t || side_effects_p (t))
+    return FALSE;
+
+  /* We currently don't handle different modes.  */
+  mode = GET_MODE (t);
+  if (GET_MODE (m) != mode)
+    return FALSE;
+
+  /* This is only profitable if T is cheap.  */
+  if (rtx_cost (t, SET) >= COSTS_N_INSNS (2))
+    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
+     insns to obtain the signmask, but still uses ashr_optab otherwise.  */
+  m = emit_store_flag (gen_reg_rtx (mode), LT, m, const0_rtx, mode, 0, -1);
+  t = m ? expand_binop (mode, and_optab, m, t, NULL_RTX, 0, OPTAB_DIRECT)
+       : NULL_RTX;
+
+  if (!t)
+    {
+      end_sequence ();
+      return FALSE;
+    }
+
+  noce_emit_move_insn (if_info->x, t);
+
+  seq = end_ifcvt_sequence (if_info);
+  if (!seq)
+    return FALSE;
+
+  emit_insn_before_setloc (seq, if_info->jump, INSN_LOCATOR (if_info->insn_a));
+  return TRUE;
+}
+
+
 /* Similar to get_condition, only the resulting condition must be
    valid at JUMP, instead of at EARLIEST.  */
 
 static rtx
-noce_get_condition (jump, earliest)
-     rtx jump;
-     rtx *earliest;
+noce_get_condition (rtx jump, rtx *earliest)
 {
   rtx cond, set, tmp, insn;
   bool reverse;
@@ -1637,7 +1795,8 @@ noce_get_condition (jump, earliest)
   /* Otherwise, fall back on canonicalize_condition to do the dirty
      work of manipulating MODE_CC values and COMPARE rtx codes.  */
 
-  tmp = canonicalize_condition (jump, cond, reverse, earliest, NULL_RTX);
+  tmp = canonicalize_condition (jump, cond, reverse, earliest, NULL_RTX,
+                               false);
   if (!tmp)
     return NULL_RTX;
 
@@ -1656,7 +1815,8 @@ noce_get_condition (jump, earliest)
   tmp = XEXP (tmp, 0);
   if (!REG_P (tmp) || GET_MODE_CLASS (GET_MODE (tmp)) != MODE_INT)
     return NULL_RTX;
-  tmp = canonicalize_condition (jump, cond, reverse, earliest, tmp);
+  tmp = canonicalize_condition (jump, cond, reverse, earliest, tmp,
+                               false);
   if (!tmp)
     return NULL_RTX;
 
@@ -1671,12 +1831,11 @@ noce_get_condition (jump, earliest)
 /* Return true if OP is ok for if-then-else processing.  */
 
 static int
-noce_operand_ok (op)
-     rtx op;
+noce_operand_ok (rtx op)
 {
   /* We special-case memories, so handle any of them with
      no address side effects.  */
-  if (GET_CODE (op) == MEM)
+  if (MEM_P (op))
     return ! side_effects_p (XEXP (op, 0));
 
   if (side_effects_p (op))
@@ -1690,8 +1849,7 @@ noce_operand_ok (op)
    successful at converting the block.  */
 
 static int
-noce_process_if_block (ce_info)
-     struct ce_if_block * ce_info;
+noce_process_if_block (struct ce_if_block * ce_info)
 {
   basic_block test_bb = ce_info->test_bb;      /* test block */
   basic_block then_bb = ce_info->then_bb;      /* THEN */
@@ -1700,7 +1858,7 @@ noce_process_if_block (ce_info)
   rtx insn_a, insn_b;
   rtx set_a, set_b;
   rtx orig_x, x, a, b;
-  rtx jump, cond, insn;
+  rtx jump, cond;
 
   /* We're looking for patterns of the form
 
@@ -1726,7 +1884,7 @@ noce_process_if_block (ce_info)
     }
 
   /* If this is not a standard conditional jump, we can't parse it.  */
-  jump = test_bb->end;
+  jump = BB_END (test_bb);
   cond = noce_get_condition (jump, &if_info.cond_earliest);
   if (! cond)
     return FALSE;
@@ -1770,38 +1928,43 @@ noce_process_if_block (ce_info)
   else
     {
       insn_b = prev_nonnote_insn (if_info.cond_earliest);
+      /* We're going to be moving the evaluation of B down from above
+        COND_EARLIEST to JUMP.  Make sure the relevant data is still
+        intact.  */
       if (! insn_b
          || GET_CODE (insn_b) != INSN
          || (set_b = single_set (insn_b)) == NULL_RTX
          || ! rtx_equal_p (x, SET_DEST (set_b))
+         || reg_overlap_mentioned_p (x, SET_SRC (set_b))
+         || modified_between_p (SET_SRC (set_b),
+                                PREV_INSN (if_info.cond_earliest), jump)
+         /* Likewise with X.  In particular this can happen when
+            noce_get_condition looks farther back in the instruction
+            stream than one might expect.  */
          || reg_overlap_mentioned_p (x, cond)
          || reg_overlap_mentioned_p (x, a)
-         || reg_overlap_mentioned_p (x, SET_SRC (set_b)))
+         || modified_between_p (x, PREV_INSN (if_info.cond_earliest), jump))
        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]. 
-     Note the use of reg_overlap_mentioned_p, which handles memories
-     properly, as opposed to reg_mentioned_p, which doesn't.  */
-  for (insn = jump; insn != if_info.cond_earliest; insn = PREV_INSN (insn))
-    if (INSN_P (insn) && reg_overlap_mentioned_p (x, PATTERN (insn)))
-      return FALSE;
+  /* If x has side effects then only the if-then-else form is safe to
+     convert.  But even in that case we would need to restore any notes
+     (such as REG_INC) at then end.  That can be tricky if
+     noce_emit_move_insn expands to more than one insn, so disable the
+     optimization entirely for now if there are side effects.  */
+  if (side_effects_p (x))
+    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;
+  b = (set_b ? SET_SRC (set_b) : x);
 
   /* Only operate on register destinations, and even then avoid extending
      the lifetime of hard registers on small register class machines.  */
   orig_x = x;
-  if (GET_CODE (x) != REG
+  if (!REG_P (x)
       || (SMALL_REGISTER_CLASSES
          && REGNO (x) < FIRST_PSEUDO_REGISTER))
     {
-      if (no_new_pseudos)
+      if (no_new_pseudos || GET_MODE (x) == BLKmode)
        return FALSE;
       x = gen_reg_rtx (GET_MODE (GET_CODE (x) == STRICT_LOW_PART
                                 ? XEXP (x, 0) : x));
@@ -1837,9 +2000,9 @@ noce_process_if_block (ce_info)
        {
          rtx note;
 
-         if (else_bb && insn_b == else_bb->end)
-           else_bb->end = PREV_INSN (insn_b);
-         reorder_insns (insn_b, insn_b, PREV_INSN (if_info.cond_earliest));
+         if (else_bb && insn_b == BB_END (else_bb))
+           BB_END (else_bb) = PREV_INSN (insn_b);
+         reorder_insns (insn_b, insn_b, PREV_INSN (jump));
 
          /* If there was a REG_EQUAL note, delete it since it may have been
             true due to this insn being after a jump.  */
@@ -1852,11 +2015,32 @@ noce_process_if_block (ce_info)
         x must be executed twice.  */
       else if (insn_b && side_effects_p (orig_x))
        return FALSE;
-       
+
       x = orig_x;
       goto success;
     }
 
+  /* Disallow the "if (...) x = a;" form (with an implicit "else x = x;")
+     for most optimizations if writing to x may trap, i.e. it's a memory
+     other than a static var or a stack slot.  */
+  if (! set_b
+      && MEM_P (orig_x)
+      && ! MEM_NOTRAP_P (orig_x)
+      && rtx_addr_can_trap_p (XEXP (orig_x, 0)))
+    {
+      if (HAVE_conditional_move)
+       {
+         if (noce_try_cmove (&if_info))
+           goto success;
+         if (! HAVE_conditional_execution
+             && noce_try_cmove_arith (&if_info))
+           goto success;
+       }
+      return FALSE;
+    }
+
+  if (noce_try_move (&if_info))
+    goto success;
   if (noce_try_store_flag (&if_info))
     goto success;
   if (noce_try_minmax (&if_info))
@@ -1870,13 +2054,15 @@ noce_process_if_block (ce_info)
     {
       if (noce_try_store_flag_constants (&if_info))
        goto success;
-      if (noce_try_store_flag_inc (&if_info))
+      if (noce_try_addcc (&if_info))
        goto success;
       if (noce_try_store_flag_mask (&if_info))
        goto success;
       if (HAVE_conditional_move
          && noce_try_cmove_arith (&if_info))
        goto success;
+      if (noce_try_sign_mask (&if_info))
+       goto success;
     }
 
   return FALSE;
@@ -1894,20 +2080,22 @@ noce_process_if_block (ce_info)
   if (insn_b && else_bb)
     delete_insn (insn_b);
 
-  /* The new insns will have been inserted before cond_earliest.  We should
-     be able to remove the jump with impunity, but the condition itself may
-     have been modified by gcse to be shared across basic blocks.  */
+  /* The new insns will have been inserted immediately before the jump.  We
+     should be able to remove the jump with impunity, but the condition itself
+     may have been modified by gcse to be shared across basic blocks.  */
   delete_insn (jump);
 
   /* If we used a temporary, fix it up now.  */
   if (orig_x != x)
     {
       start_sequence ();
-      noce_emit_move_insn (copy_rtx (orig_x), x);
+      noce_emit_move_insn (orig_x, x);
       insn_b = get_insns ();
+      set_used_flags (orig_x);
+      unshare_all_rtl_in_chain (insn_b);
       end_sequence ();
 
-      emit_insn_after_scope (insn_b, test_bb->end, INSN_SCOPE (insn_a));
+      emit_insn_after_setloc (insn_b, BB_END (test_bb), INSN_LOCATOR (insn_a));
     }
 
   /* Merge the blocks!  */
@@ -1920,8 +2108,7 @@ noce_process_if_block (ce_info)
    straight line code.  Return true if successful.  */
 
 static int
-process_if_block (ce_info)
-     struct ce_if_block * ce_info;
+process_if_block (struct ce_if_block * ce_info)
 {
   if (! reload_completed
       && noce_process_if_block (ce_info))
@@ -1951,8 +2138,7 @@ process_if_block (ce_info)
 /* Merge the blocks and mark for local life update.  */
 
 static void
-merge_if_block (ce_info)
-     struct ce_if_block * ce_info;
+merge_if_block (struct ce_if_block * ce_info)
 {
   basic_block test_bb = ce_info->test_bb;      /* last test block */
   basic_block then_bb = ce_info->then_bb;      /* THEN */
@@ -1971,15 +2157,13 @@ merge_if_block (ce_info)
       basic_block bb = test_bb;
       basic_block last_test_bb = ce_info->last_test_bb;
       basic_block fallthru = block_fallthru (bb);
-      
+
       do
        {
          bb = fallthru;
          fallthru = block_fallthru (bb);
-         if (post_dominators)
-           delete_from_dominance_info (post_dominators, bb);
-         merge_blocks_nomove (combo_bb, bb);
-         num_removed_blocks++;
+         merge_blocks (combo_bb, bb);
+         num_true_changes++;
        }
       while (bb != last_test_bb);
     }
@@ -1993,10 +2177,8 @@ merge_if_block (ce_info)
       if (combo_bb->global_live_at_end)
        COPY_REG_SET (combo_bb->global_live_at_end,
                      then_bb->global_live_at_end);
-      if (post_dominators)
-       delete_from_dominance_info (post_dominators, then_bb);
-      merge_blocks_nomove (combo_bb, then_bb);
-      num_removed_blocks++;
+      merge_blocks (combo_bb, then_bb);
+      num_true_changes++;
     }
 
   /* The ELSE block, if it existed, had a label.  That label count
@@ -2004,10 +2186,8 @@ merge_if_block (ce_info)
      get their addresses taken.  */
   if (else_bb)
     {
-      if (post_dominators)
-       delete_from_dominance_info (post_dominators, else_bb);
-      merge_blocks_nomove (combo_bb, else_bb);
-      num_removed_blocks++;
+      merge_blocks (combo_bb, else_bb);
+      num_true_changes++;
     }
 
   /* If there was no join block reported, that means it was not adjacent
@@ -2015,7 +2195,7 @@ merge_if_block (ce_info)
 
   if (! join_bb)
     {
-      rtx last = combo_bb->end;
+      rtx last = BB_END (combo_bb);
 
       /* The outgoing edge for the current COMBO block should already
         be correct.  Verify this.  */
@@ -2050,7 +2230,7 @@ merge_if_block (ce_info)
      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 
+     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)
@@ -2061,10 +2241,8 @@ merge_if_block (ce_info)
        COPY_REG_SET (combo_bb->global_live_at_end,
                      join_bb->global_live_at_end);
 
-      if (post_dominators)
-       delete_from_dominance_info (post_dominators, join_bb);
-      merge_blocks_nomove (combo_bb, join_bb);
-      num_removed_blocks++;
+      merge_blocks (combo_bb, join_bb);
+      num_true_changes++;
     }
   else
     {
@@ -2078,7 +2256,7 @@ merge_if_block (ce_info)
 
       /* Remove the jump and cruft from the end of the COMBO block.  */
       if (join_bb != EXIT_BLOCK_PTR)
-       tidy_fallthru_edge (combo_bb->succ, combo_bb, join_bb);
+       tidy_fallthru_edge (combo_bb->succ);
     }
 
   num_updated_if_blocks++;
@@ -2090,9 +2268,7 @@ merge_if_block (ce_info)
    first block if some transformation was done.  Return NULL otherwise.  */
 
 static basic_block
-find_if_header (test_bb, pass)
-     basic_block test_bb;
-     int pass;
+find_if_header (basic_block test_bb, int pass)
 {
   ce_if_block_t ce_info;
   edge then_edge;
@@ -2109,6 +2285,11 @@ find_if_header (test_bb, pass)
       || (else_edge->flags & EDGE_COMPLEX))
     return NULL;
 
+  /* Nor exit the loop.  */
+  if ((then_edge->flags & EDGE_LOOP_EXIT)
+      || (else_edge->flags & EDGE_LOOP_EXIT))
+    return NULL;
+
   /* The THEN edge is canonically the one that falls through.  */
   if (then_edge->flags & EDGE_FALLTHRU)
     ;
@@ -2122,7 +2303,7 @@ find_if_header (test_bb, pass)
     /* Otherwise this must be a multiway branch of some sort.  */
     return NULL;
 
-  memset ((PTR) &ce_info, '\0', sizeof (ce_info));
+  memset (&ce_info, '\0', sizeof (ce_info));
   ce_info.test_bb = test_bb;
   ce_info.then_bb = then_edge->dest;
   ce_info.else_bb = else_edge->dest;
@@ -2139,7 +2320,7 @@ find_if_header (test_bb, pass)
       && find_cond_trap (test_bb, then_edge, else_edge))
     goto success;
 
-  if (post_dominators
+  if (dom_computed[CDI_POST_DOMINATORS] >= DOM_NO_FAST_QUERY
       && (! HAVE_conditional_execution || reload_completed))
     {
       if (find_if_case_1 (test_bb, then_edge, else_edge))
@@ -2151,8 +2332,8 @@ find_if_header (test_bb, pass)
   return NULL;
 
  success:
-  if (rtl_dump_file)
-    fprintf (rtl_dump_file, "Conversion succeeded on pass %d.\n", pass);
+  if (dump_file)
+    fprintf (dump_file, "Conversion succeeded on pass %d.\n", pass);
   return ce_info.test_bb;
 }
 
@@ -2162,9 +2343,7 @@ find_if_header (test_bb, pass)
    of non-note, non-jump, non-USE/CLOBBER insns in the block.  */
 
 static int
-block_jumps_and_fallthru_p (cur_bb, target_bb)
-     basic_block cur_bb;
-     basic_block target_bb;
+block_jumps_and_fallthru_p (basic_block cur_bb, basic_block target_bb)
 {
   edge cur_edge;
   int fallthru_p = FALSE;
@@ -2205,8 +2384,8 @@ block_jumps_and_fallthru_p (cur_bb, target_bb)
      together for conditional execution support.  ??? we should support
      conditional execution support across calls for IA-64 some day, but
      for now it makes the code simpler.  */
-  end = cur_bb->end;
-  insn = cur_bb->head;
+  end = BB_END (cur_bb);
+  insn = BB_HEAD (cur_bb);
 
   while (insn != NULL_RTX)
     {
@@ -2233,8 +2412,7 @@ block_jumps_and_fallthru_p (cur_bb, target_bb)
    Return TRUE if we were successful at converting the block.  */
 
 static int
-find_if_block (ce_info)
-     struct ce_if_block * ce_info;
+find_if_block (struct ce_if_block * ce_info)
 {
   basic_block test_bb = ce_info->test_bb;
   basic_block then_bb = ce_info->then_bb;
@@ -2262,7 +2440,7 @@ find_if_block (ce_info)
       int max_insns = MAX_CONDITIONAL_EXECUTE;
       int n_insns;
 
-      /* Determine if the preceeding block is an && or || block.  */
+      /* Determine if the preceding block is an && or || block.  */
       if ((n_insns = block_jumps_and_fallthru_p (bb, else_bb)) >= 0)
        {
          ce_info->and_and_p = TRUE;
@@ -2270,7 +2448,7 @@ find_if_block (ce_info)
        }
       else if ((n_insns = block_jumps_and_fallthru_p (bb, then_bb)) >= 0)
        {
-         ce_info->and_and_p = FALSE;     
+         ce_info->and_and_p = FALSE;
          target_bb = then_bb;
        }
       else
@@ -2337,7 +2515,8 @@ find_if_block (ce_info)
   /* 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)))
+          || (then_succ->flags & EDGE_COMPLEX)
+         || (flow2_completed && tablejump_p (BB_END (then_bb), NULL, NULL))))
     return FALSE;
 
   /* If the THEN block has no successors, conditional execution can still
@@ -2350,11 +2529,11 @@ find_if_block (ce_info)
     {
       if (else_bb->pred->pred_next == NULL_EDGE)
        {
-         rtx last_insn = then_bb->end;
+         rtx last_insn = BB_END (then_bb);
 
          while (last_insn
                 && GET_CODE (last_insn) == NOTE
-                && last_insn != then_bb->head)
+                && last_insn != BB_HEAD (then_bb))
            last_insn = PREV_INSN (last_insn);
 
          if (last_insn
@@ -2384,41 +2563,48 @@ find_if_block (ce_info)
           && then_succ->dest == else_succ->dest
           && else_bb->pred->pred_next == NULL_EDGE
           && else_succ->succ_next == NULL_EDGE
-          && ! (else_succ->flags & EDGE_COMPLEX))
+          && ! (else_succ->flags & EDGE_COMPLEX)
+          && ! (flow2_completed && tablejump_p (BB_END (else_bb), NULL, NULL)))
     join_bb = else_succ->dest;
 
   /* Otherwise it is not an IF-THEN or IF-THEN-ELSE combination.  */
   else
-    return FALSE;         
+    return FALSE;
 
   num_possible_if_blocks++;
 
-  if (rtl_dump_file)
+  if (dump_file)
     {
-      fprintf (rtl_dump_file, "\nIF-THEN%s block found, pass %d, start block %d [insn %d], then %d [%d]",
+      fprintf (dump_file,
+              "\nIF-THEN%s block found, pass %d, start block %d "
+              "[insn %d], then %d [%d]",
               (else_bb) ? "-ELSE" : "",
               ce_info->pass,
-              test_bb->index, (test_bb->head) ? (int)INSN_UID (test_bb->head) : -1,
-              then_bb->index, (then_bb->head) ? (int)INSN_UID (then_bb->head) : -1);
+              test_bb->index,
+              BB_HEAD (test_bb) ? (int)INSN_UID (BB_HEAD (test_bb)) : -1,
+              then_bb->index,
+              BB_HEAD (then_bb) ? (int)INSN_UID (BB_HEAD (then_bb)) : -1);
 
       if (else_bb)
-       fprintf (rtl_dump_file, ", else %d [%d]",
-                else_bb->index, (else_bb->head) ? (int)INSN_UID (else_bb->head) : -1);
+       fprintf (dump_file, ", else %d [%d]",
+                else_bb->index,
+                BB_HEAD (else_bb) ? (int)INSN_UID (BB_HEAD (else_bb)) : -1);
 
-      fprintf (rtl_dump_file, ", join %d [%d]",
-              join_bb->index, (join_bb->head) ? (int)INSN_UID (join_bb->head) : -1);
+      fprintf (dump_file, ", join %d [%d]",
+              join_bb->index,
+              BB_HEAD (join_bb) ? (int)INSN_UID (BB_HEAD (join_bb)) : -1);
 
       if (ce_info->num_multiple_test_blocks > 0)
-       fprintf (rtl_dump_file, ", %d %s block%s last test %d [%d]",
+       fprintf (dump_file, ", %d %s block%s last test %d [%d]",
                 ce_info->num_multiple_test_blocks,
                 (ce_info->and_and_p) ? "&&" : "||",
                 (ce_info->num_multiple_test_blocks == 1) ? "" : "s",
                 ce_info->last_test_bb->index,
-                ((ce_info->last_test_bb->head)
-                 ? (int)INSN_UID (ce_info->last_test_bb->head)
+                ((BB_HEAD (ce_info->last_test_bb))
+                 ? (int)INSN_UID (BB_HEAD (ce_info->last_test_bb))
                  : -1));
 
-      fputc ('\n', rtl_dump_file);
+      fputc ('\n', dump_file);
     }
 
   /* Make sure IF, THEN, and ELSE, blocks are adjacent.  Actually, we get the
@@ -2451,9 +2637,7 @@ find_if_block (ce_info)
    to a trap, into a conditional trap.  */
 
 static int
-find_cond_trap (test_bb, then_edge, else_edge)
-     basic_block test_bb;
-     edge then_edge, else_edge;
+find_cond_trap (basic_block test_bb, edge then_edge, edge else_edge)
 {
   basic_block then_bb = then_edge->dest;
   basic_block else_bb = else_edge->dest;
@@ -2471,14 +2655,14 @@ find_cond_trap (test_bb, then_edge, else_edge)
   else
     return FALSE;
 
-  if (rtl_dump_file)
+  if (dump_file)
     {
-      fprintf (rtl_dump_file, "\nTRAP-IF block found, start %d, trap %d\n",
+      fprintf (dump_file, "\nTRAP-IF block found, start %d, trap %d\n",
               test_bb->index, trap_bb->index);
     }
 
   /* If this is not a standard conditional jump, we can't parse it.  */
-  jump = test_bb->end;
+  jump = BB_END (test_bb);
   cond = noce_get_condition (jump, &cond_earliest);
   if (! cond)
     return FALSE;
@@ -2502,23 +2686,21 @@ find_cond_trap (test_bb, then_edge, else_edge)
     }
 
   /* Attempt to generate the conditional trap.  */
-  seq = gen_cond_trap (code, XEXP (cond, 0), XEXP (cond, 1),
+  seq = gen_cond_trap (code, XEXP (cond, 0),
+                      XEXP (cond, 1),
                       TRAP_CODE (PATTERN (trap)));
   if (seq == NULL)
     return FALSE;
 
+  num_true_changes++;
+
   /* Emit the new insns before cond_earliest.  */
-  emit_insn_before_scope (seq, cond_earliest, INSN_SCOPE (trap));
+  emit_insn_before_setloc (seq, cond_earliest, INSN_LOCATOR (trap));
 
   /* Delete the trap block if possible.  */
   remove_edge (trap_bb == then_bb ? then_edge : else_edge);
   if (trap_bb->pred == NULL)
-    {
-      if (post_dominators)
-       delete_from_dominance_info (post_dominators, trap_bb);
-      flow_delete_block (trap_bb);
-      num_removed_blocks++;
-    }
+    delete_basic_block (trap_bb);
 
   /* If the non-trap block and the test are now adjacent, merge them.
      Otherwise we must insert a direct branch.  */
@@ -2526,7 +2708,7 @@ find_cond_trap (test_bb, then_edge, else_edge)
     {
       struct ce_if_block new_ce_info;
       delete_insn (jump);
-      memset ((PTR) &new_ce_info, '\0', sizeof (new_ce_info));
+      memset (&new_ce_info, '\0', sizeof (new_ce_info));
       new_ce_info.test_bb = test_bb;
       new_ce_info.then_bb = NULL;
       new_ce_info.else_bb = NULL;
@@ -2549,12 +2731,11 @@ find_cond_trap (test_bb, then_edge, else_edge)
   return TRUE;
 }
 
-/* Subroutine of find_cond_trap: if BB contains only a trap insn, 
+/* Subroutine of find_cond_trap: if BB contains only a trap insn,
    return it.  */
 
 static rtx
-block_has_only_trap (bb)
-     basic_block bb;
+block_has_only_trap (basic_block bb)
 {
   rtx trap;
 
@@ -2568,7 +2749,7 @@ block_has_only_trap (bb)
 
   /* The only instruction in the THEN block must be the trap.  */
   trap = first_active_insn (bb);
-  if (! (trap == bb->end
+  if (! (trap == BB_END (bb)
         && GET_CODE (PATTERN (trap)) == TRAP_IF
          && TRAP_CONDITION (PATTERN (trap)) == const_true_rtx))
     return NULL_RTX;
@@ -2654,15 +2835,25 @@ block_has_only_trap (bb)
 /* Tests for case 1 above.  */
 
 static int
-find_if_case_1 (test_bb, then_edge, else_edge)
-      basic_block test_bb;
-      edge then_edge, else_edge;
+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, new_bb;
   edge then_succ = then_bb->succ;
   int then_bb_index;
 
+  /* If we are partitioning hot/cold basic blocks, we don't want to
+     mess up unconditional or indirect jumps that cross between hot
+     and cold sections.  */
+  
+  if (flag_reorder_blocks_and_partition
+      && ((BB_END (then_bb) 
+          && find_reg_note (BB_END (then_bb), REG_CROSSING_JUMP, NULL_RTX))
+         || (BB_END (else_bb)
+             && find_reg_note (BB_END (else_bb), REG_CROSSING_JUMP, 
+                               NULL_RTX))))
+    return FALSE;
+
   /* THEN has one successor.  */
   if (!then_succ || then_succ->succ_next != NULL)
     return FALSE;
@@ -2680,8 +2871,8 @@ find_if_case_1 (test_bb, then_edge, else_edge)
     return FALSE;
 
   num_possible_if_blocks++;
-  if (rtl_dump_file)
-    fprintf (rtl_dump_file,
+  if (dump_file)
+    fprintf (dump_file,
             "\nIF-CASE-1 found, start %d, then %d\n",
             test_bb->index, then_bb->index);
 
@@ -2690,7 +2881,7 @@ find_if_case_1 (test_bb, then_edge, else_edge)
     return FALSE;
 
   /* Registers set are dead, or are predicable.  */
-  if (! dead_or_predicable (test_bb, then_bb, else_bb, 
+  if (! dead_or_predicable (test_bb, then_bb, else_bb,
                            then_bb->succ->dest, 1))
     return FALSE;
 
@@ -2700,12 +2891,10 @@ find_if_case_1 (test_bb, then_edge, else_edge)
   bitmap_operation (test_bb->global_live_at_end,
                    else_bb->global_live_at_start,
                    then_bb->global_live_at_end, BITMAP_IOR);
-  
+
   new_bb = redirect_edge_and_branch_force (FALLTHRU_EDGE (test_bb), else_bb);
   then_bb_index = then_bb->index;
-  if (post_dominators)
-    delete_from_dominance_info (post_dominators, then_bb);
-  flow_delete_block (then_bb);
+  delete_basic_block (then_bb);
 
   /* Make rest of code believe that the newly created block is the THEN_BB
      block we removed.  */
@@ -2717,7 +2906,7 @@ find_if_case_1 (test_bb, then_edge, else_edge)
   /* We've possibly created jump to next insn, cleanup_cfg will solve that
      later.  */
 
-  num_removed_blocks++;
+  num_true_changes++;
   num_updated_if_blocks++;
 
   return TRUE;
@@ -2726,15 +2915,25 @@ find_if_case_1 (test_bb, then_edge, else_edge)
 /* Test for case 2 above.  */
 
 static int
-find_if_case_2 (test_bb, then_edge, else_edge)
-      basic_block test_bb;
-      edge then_edge, else_edge;
+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 = else_bb->succ;
   rtx note;
 
+  /* If we are partitioning hot/cold basic blocks, we don't want to
+     mess up unconditional or indirect jumps that cross between hot
+     and cold sections.  */
+  
+  if (flag_reorder_blocks_and_partition
+      && ((BB_END (then_bb)
+          && find_reg_note (BB_END (then_bb), REG_CROSSING_JUMP, NULL_RTX))
+         || (BB_END (else_bb) 
+             && find_reg_note (BB_END (else_bb), REG_CROSSING_JUMP, 
+                               NULL_RTX))))
+    return FALSE;
+
   /* ELSE has one successor.  */
   if (!else_succ || else_succ->succ_next != NULL)
     return FALSE;
@@ -2752,19 +2951,19 @@ find_if_case_2 (test_bb, then_edge, else_edge)
     return FALSE;
 
   /* ELSE is predicted or SUCC(ELSE) postdominates THEN.  */
-  note = find_reg_note (test_bb->end, REG_BR_PROB, NULL_RTX);
+  note = find_reg_note (BB_END (test_bb), REG_BR_PROB, NULL_RTX);
   if (note && INTVAL (XEXP (note, 0)) >= REG_BR_PROB_BASE / 2)
     ;
   else if (else_succ->dest->index < 0
-          || dominated_by_p (post_dominators, then_bb, 
+          || dominated_by_p (CDI_POST_DOMINATORS, then_bb,
                              else_succ->dest))
     ;
   else
     return FALSE;
 
   num_possible_if_blocks++;
-  if (rtl_dump_file)
-    fprintf (rtl_dump_file,
+  if (dump_file)
+    fprintf (dump_file,
             "\nIF-CASE-2 found, start %d, else %d\n",
             test_bb->index, else_bb->index);
 
@@ -2782,12 +2981,10 @@ find_if_case_2 (test_bb, then_edge, else_edge)
   bitmap_operation (test_bb->global_live_at_end,
                    then_bb->global_live_at_start,
                    else_bb->global_live_at_end, BITMAP_IOR);
-  
-  if (post_dominators)
-    delete_from_dominance_info (post_dominators, else_bb);
-  flow_delete_block (else_bb);
 
-  num_removed_blocks++;
+  delete_basic_block (else_bb);
+
+  num_true_changes++;
   num_updated_if_blocks++;
 
   /* ??? We may now fallthru from one of THEN's successors into a join
@@ -2800,11 +2997,9 @@ find_if_case_2 (test_bb, then_edge, else_edge)
    Return 1 if a memory is found.  */
 
 static int
-find_memory (px, data)
-     rtx *px;
-     void *data ATTRIBUTE_UNUSED;
+find_memory (rtx *px, void *data ATTRIBUTE_UNUSED)
 {
-  return GET_CODE (*px) == MEM;
+  return MEM_P (*px);
 }
 
 /* Used by the code above to perform the actual rtl transformations.
@@ -2816,18 +3011,16 @@ find_memory (px, data)
    REVERSEP is true if the sense of the branch should be reversed.  */
 
 static int
-dead_or_predicable (test_bb, merge_bb, other_bb, new_dest, reversep)
-     basic_block test_bb, merge_bb, other_bb;
-     basic_block new_dest;
-     int reversep;
+dead_or_predicable (basic_block test_bb, basic_block merge_bb,
+                   basic_block other_bb, basic_block new_dest, int reversep)
 {
-  rtx head, end, jump, earliest, old_dest, new_label = NULL_RTX;
+  rtx head, end, jump, earliest = NULL_RTX, old_dest, new_label = NULL_RTX;
 
-  jump = test_bb->end;
+  jump = BB_END (test_bb);
 
   /* Find the extent of the real code in the merge block.  */
-  head = merge_bb->head;
-  end = merge_bb->end;
+  head = BB_HEAD (merge_bb);
+  end = BB_END (merge_bb);
 
   if (GET_CODE (head) == CODE_LABEL)
     head = NEXT_INSN (head);
@@ -2857,8 +3050,8 @@ dead_or_predicable (test_bb, merge_bb, other_bb, new_dest, reversep)
   if (HAVE_conditional_execution)
     {
       /* In the conditional execution case, we have things easy.  We know
-        the condition is reversable.  We don't have to check life info,
-        becase we're going to conditionally execute the code anyway.
+        the condition is reversible.  We don't have to check life info
+        because we're going to conditionally execute the code anyway.
         All that's left is making sure the insns involved can actually
         be predicated.  */
 
@@ -2944,7 +3137,7 @@ dead_or_predicable (test_bb, merge_bb, other_bb, new_dest, reversep)
       test_set = INITIALIZE_REG_SET (test_set_head);
 
       /* ??? bb->local_set is only valid during calculate_global_regs_live,
-        so we must recompute usage for MERGE_BB.  Not so bad, I suppose, 
+        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, merge_set, 0);
 
@@ -3047,8 +3240,8 @@ dead_or_predicable (test_bb, merge_bb, other_bb, new_dest, reversep)
   /* Move the insns out of MERGE_BB to before the branch.  */
   if (head != NULL)
     {
-      if (end == merge_bb->end)
-       merge_bb->end = PREV_INSN (head);
+      if (end == BB_END (merge_bb))
+       BB_END (merge_bb) = PREV_INSN (head);
 
       if (squeeze_notes (&head, &end))
        return TRUE;
@@ -3075,27 +3268,24 @@ dead_or_predicable (test_bb, merge_bb, other_bb, new_dest, reversep)
 /* Main entry point for all if-conversion.  */
 
 void
-if_convert (x_life_data_ok)
-     int x_life_data_ok;
+if_convert (int x_life_data_ok)
 {
   basic_block bb;
   int pass;
 
   num_possible_if_blocks = 0;
   num_updated_if_blocks = 0;
-  num_removed_blocks = 0;
+  num_true_changes = 0;
   life_data_ok = (x_life_data_ok != 0);
 
-  /* Free up basic_block_for_insn so that we don't have to keep it
-     up to date, either here or in merge_blocks_nomove.  */
-  free_basic_block_vars (1);
+  if ((! targetm.cannot_modify_jumps_p ())
+      && (!flag_reorder_blocks_and_partition || !no_new_pseudos))
+    mark_loop_exit_edges ();
 
   /* Compute postdominators if we think we'll use them.  */
-  post_dominators = NULL;
   if (HAVE_conditional_execution || life_data_ok)
-    {
-      post_dominators = calculate_dominance_info (CDI_POST_DOMINATORS);
-    }
+    calculate_dominance_info (CDI_POST_DOMINATORS);
+
   if (life_data_ok)
     clear_bb_flags ();
 
@@ -3109,39 +3299,38 @@ if_convert (x_life_data_ok)
       pass++;
 
 #ifdef IFCVT_MULTIPLE_DUMPS
-      if (rtl_dump_file && pass > 1)
-       fprintf (rtl_dump_file, "\n\n========== Pass %d ==========\n", pass);
+      if (dump_file && pass > 1)
+       fprintf (dump_file, "\n\n========== Pass %d ==========\n", pass);
 #endif
 
       FOR_EACH_BB (bb)
        {
-         basic_block new_bb = find_if_header (bb, pass);
-         if (new_bb)
+         basic_block new_bb;
+         while ((new_bb = find_if_header (bb, pass)))
            bb = new_bb;
        }
 
 #ifdef IFCVT_MULTIPLE_DUMPS
-      if (rtl_dump_file && cond_exec_changed_p)
-       print_rtl_with_bb (rtl_dump_file, get_insns ());
+      if (dump_file && cond_exec_changed_p)
+       print_rtl_with_bb (dump_file, get_insns ());
 #endif
     }
   while (cond_exec_changed_p);
 
 #ifdef IFCVT_MULTIPLE_DUMPS
-  if (rtl_dump_file)
-    fprintf (rtl_dump_file, "\n\n========== no more changes\n");
+  if (dump_file)
+    fprintf (dump_file, "\n\n========== no more changes\n");
 #endif
 
-  if (post_dominators)
-    free_dominance_info (post_dominators);
+  free_dominance_info (CDI_POST_DOMINATORS);
 
-  if (rtl_dump_file)
-    fflush (rtl_dump_file);
+  if (dump_file)
+    fflush (dump_file);
 
   clear_aux_for_blocks ();
 
   /* Rebuild life info for basic blocks that require it.  */
-  if (num_removed_blocks && life_data_ok)
+  if (num_true_changes && life_data_ok)
     {
       /* If we allocated new pseudos, we must resize the array for sched1.  */
       if (max_regno < max_reg_num ())
@@ -3155,17 +3344,17 @@ if_convert (x_life_data_ok)
     }
 
   /* Write the final stats.  */
-  if (rtl_dump_file && num_possible_if_blocks > 0)
+  if (dump_file && num_possible_if_blocks > 0)
     {
-      fprintf (rtl_dump_file,
+      fprintf (dump_file,
               "\n%d possible IF blocks searched.\n",
               num_possible_if_blocks);
-      fprintf (rtl_dump_file,
+      fprintf (dump_file,
               "%d IF blocks converted.\n",
               num_updated_if_blocks);
-      fprintf (rtl_dump_file,
-              "%d basic blocks deleted.\n\n\n",
-              num_removed_blocks);
+      fprintf (dump_file,
+              "%d true changes made.\n\n\n",
+              num_true_changes);
     }
 
 #ifdef ENABLE_CHECKING