diff --git a/gcc/tree-if-conv.c b/gcc/tree-if-conv.c
index 400ee01a5122c0c74b21a9b100f36b2951e45a46..6bd642e54848ed2faf72aa99987ab9f838634ca6 100644
--- a/gcc/tree-if-conv.c
+++ b/gcc/tree-if-conv.c
@@ -455,8 +455,8 @@ add_to_predicate_list (struct loop *loop, basic_block bb, tree nc)
     return;
 
   /* If dominance tells us this basic block is always executed,
-     don't record any predicates for it.  */
-  if (dominated_by_p (CDI_DOMINATORS, loop->latch, bb))
+     i.e. it postdominates the header, don't record any predicates for it.  */
+  if (dominated_by_p (CDI_POST_DOMINATORS, loop->header, bb))
     return;
 
   dom_bb = get_immediate_dominator (CDI_DOMINATORS, bb);
@@ -1025,11 +1025,10 @@ has_pred_critical_p (basic_block bb)
 
    Last restriction is valid if aggressive_if_conv is false.
 
-   EXIT_BB is the basic block containing the exit of the LOOP.  BB is
-   inside LOOP.  */
+   BB is inside LOOP.  */
 
 static bool
-if_convertible_bb_p (struct loop *loop, basic_block bb, basic_block exit_bb)
+if_convertible_bb_p (struct loop *loop, basic_block bb)
 {
   edge e;
   edge_iterator ei;
@@ -1044,30 +1043,6 @@ if_convertible_bb_p (struct loop *loop, basic_block bb, basic_block exit_bb)
       && !aggressive_if_conv)
     return false;
 
-  if (exit_bb)
-    {
-      if (bb != loop->latch)
-	{
-	  if (dump_file && (dump_flags & TDF_DETAILS))
-	    fprintf (dump_file, "basic block after exit bb but before latch\n");
-	  return false;
-	}
-      else if (!empty_block_p (bb))
-	{
-	  if (dump_file && (dump_flags & TDF_DETAILS))
-	    fprintf (dump_file, "non empty basic block after exit bb\n");
-	  return false;
-	}
-      else if (bb == loop->latch
-	       && bb != exit_bb
-	       && !dominated_by_p (CDI_DOMINATORS, bb, exit_bb))
-	  {
-	    if (dump_file && (dump_flags & TDF_DETAILS))
-	      fprintf (dump_file, "latch is not dominated by exit_block\n");
-	    return false;
-	  }
-    }
-
   /* Be less adventurous and handle only normal edges.  */
   FOR_EACH_EDGE (e, ei, bb->succs)
     if (e->flags & (EDGE_EH | EDGE_ABNORMAL | EDGE_IRREDUCIBLE_LOOP))
@@ -1199,15 +1174,6 @@ predicate_bbs (loop_p loop)
       tree cond;
       gimple stmt;
 
-      /* The loop latch and loop exit block are always executed and
-	 have no extra conditions to be processed: skip them.  */
-      if (bb == loop->latch
-	  || bb_with_exit_edge_p (loop, bb))
-	{
-	  reset_bb_predicate (bb);
-	  continue;
-	}
-
       cond = bb_predicate (bb);
       stmt = last_stmt (bb);
       if (stmt && gimple_code (stmt) == GIMPLE_COND)
@@ -1271,7 +1237,6 @@ if_convertible_loop_p_1 (struct loop *loop,
 {
   bool res;
   unsigned int i;
-  basic_block exit_bb = NULL;
 
   /* Don't if-convert the loop when the data dependences cannot be
      computed: the loop won't be vectorized in that case.  */
@@ -1295,11 +1260,8 @@ if_convertible_loop_p_1 (struct loop *loop,
     {
       basic_block bb = ifc_bbs[i];
 
-      if (!if_convertible_bb_p (loop, bb, exit_bb))
+      if (!if_convertible_bb_p (loop, bb))
 	return false;
-
-      if (bb_with_exit_edge_p (loop, bb))
-	exit_bb = bb;
     }
 
   for (i = 0; i < loop->num_nodes; i++)
@@ -1375,14 +1337,11 @@ if_convertible_loop_p_1 (struct loop *loop,
    - it is innermost,
    - it has two or more basic blocks,
    - it has only one exit,
-   - loop header is not the exit edge,
    - if its basic blocks and phi nodes are if convertible.  */
 
 static bool
 if_convertible_loop_p (struct loop *loop, bool *any_mask_load_store)
 {
-  edge e;
-  edge_iterator ei;
   bool res = false;
   vec<data_reference_p> refs;
   vec<ddr_p> ddrs;
@@ -1411,12 +1370,6 @@ if_convertible_loop_p (struct loop *loop, bool *any_mask_load_store)
       return false;
     }
 
-  /* If one of the loop header's edge is an exit edge then do not
-     apply if-conversion.  */
-  FOR_EACH_EDGE (e, ei, loop->header->succs)
-    if (loop_exit_edge_p (loop, e))
-      return false;
-
   refs.create (5);
   ddrs.create (25);
   auto_vec<loop_p, 3> loop_nest;
@@ -2249,7 +2202,6 @@ remove_conditions_and_labels (loop_p loop)
 static void
 combine_blocks (struct loop *loop, bool any_mask_load_store)
 {
-  basic_block bb, exit_bb, merge_target_bb;
   unsigned int orig_loop_num_nodes = loop->num_nodes;
   unsigned int i;
   edge e;
@@ -2265,10 +2217,10 @@ combine_blocks (struct loop *loop, bool any_mask_load_store)
 
   /* Merge basic blocks: first remove all the edges in the loop,
      except for those from the exit block.  */
-  exit_bb = NULL;
+  basic_block exit_bb = NULL;
   for (i = 0; i < orig_loop_num_nodes; i++)
     {
-      bb = ifc_bbs[i];
+      basic_block bb = ifc_bbs[i];
       free_bb_predicate (bb);
       if (bb_with_exit_edge_p (loop, bb))
 	{
@@ -2280,7 +2232,7 @@ combine_blocks (struct loop *loop, bool any_mask_load_store)
 
   for (i = 1; i < orig_loop_num_nodes; i++)
     {
-      bb = ifc_bbs[i];
+      basic_block bb = ifc_bbs[i];
 
       for (ei = ei_start (bb->preds); (e = ei_safe_edge (ei));)
 	{
@@ -2315,37 +2267,53 @@ combine_blocks (struct loop *loop, bool any_mask_load_store)
       set_immediate_dominator (CDI_DOMINATORS, loop->latch, loop->header);
     }
 
-  merge_target_bb = loop->header;
+  basic_block merge_target_bb = loop->header;
+  /* Indicates that any further statements must be inserted
+     _before_ the final jump.  */
+  bool seen_exit = (loop->header == exit_bb);
   for (i = 1; i < orig_loop_num_nodes; i++)
     {
-      gimple_stmt_iterator gsi;
-      gimple_stmt_iterator last;
-
-      bb = ifc_bbs[i];
+      basic_block bb = ifc_bbs[i];
 
-      if (bb == exit_bb || bb == loop->latch)
-	continue;
+      if (bb == exit_bb)
+	{
+	  /* If possible, merge loop header to the block with the exit edge.
+	     This reduces the number of basic blocks to two, to please the
+	     vectorizer that handles only loops with two nodes.  */
+	  if (can_merge_blocks_p (loop->header, bb))
+	    merge_blocks (loop->header, bb);
+	  else
+	    {
+	      /* Must leave stmts in this BB; move following stmts here too.  */
+	      merge_target_bb = bb;
+	    }
+	  seen_exit = true;
+	  continue;
+	}
 
       /* Make stmts member of loop->header.  */
-      for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+      for (gimple_stmt_iterator gsi = gsi_start_bb (bb);
+	   !gsi_end_p (gsi);
+	   gsi_next (&gsi))
 	gimple_set_bb (gsi_stmt (gsi), merge_target_bb);
 
       /* Update stmt list.  */
-      last = gsi_last_bb (merge_target_bb);
-      gsi_insert_seq_after (&last, bb_seq (bb), GSI_NEW_STMT);
+      gimple_stmt_iterator last = gsi_last_bb (merge_target_bb);
+
+      if (seen_exit)
+	{
+	  gcc_assert (is_ctrl_stmt (gsi_stmt (last)));
+	  gsi_insert_seq_before (&last, bb_seq(bb), GSI_SAME_STMT);
+	}
+      else
+	  gsi_insert_seq_after (&last, bb_seq (bb), GSI_NEW_STMT);
+
       set_bb_seq (bb, NULL);
 
-      delete_basic_block (bb);
+      if (bb != loop->latch)
+	delete_basic_block (bb);
     }
 
-  /* If possible, merge loop header to the block with the exit edge.
-     This reduces the number of basic blocks to two, to please the
-     vectorizer that handles only loops with two nodes.  */
-  if (exit_bb
-      && exit_bb != loop->header
-      && can_merge_blocks_p (loop->header, exit_bb))
-    merge_blocks (loop->header, exit_bb);
-
   free (ifc_bbs);
   ifc_bbs = NULL;
 }
