diff --git a/gcc/tree-ssa-dom.c b/gcc/tree-ssa-dom.c
index aeb726c..c48951e 100644
--- a/gcc/tree-ssa-dom.c
+++ b/gcc/tree-ssa-dom.c
@@ -609,8 +609,39 @@ pass_dominator::execute (function *fun)
   dom_opt_dom_walker walker (CDI_DOMINATORS,
 			     const_and_copies,
 			     avail_exprs_stack);
+  walker.init_edge_executable (cfun);
   walker.walk (fun->cfg->x_entry_block_ptr);
 
+  /* Look for blocks where we cleared EDGE_EXECUTABLE on an outgoing
+     edge.  When found, remove jump threads which contain any outgoing
+     edge from the affected block.  */
+  if (cfg_altered)
+    {
+      FOR_EACH_BB_FN (bb, fun)
+	{
+	  edge_iterator ei;
+	  edge e;
+
+	  /* First see if there are any edges without EDGE_EXECUTABLE
+	     set.  */
+	  bool found = false;
+	  FOR_EACH_EDGE (e, ei, bb->succs)
+	    {
+	      if ((e->flags & EDGE_EXECUTABLE) == 0)
+		{
+		  found = true;
+		  break;
+		}
+	    }
+
+	  /* If there were any such edges found, then remove jump threads
+	     containing any edge leaving BB.  */
+	  if (found)
+	    FOR_EACH_EDGE (e, ei, bb->succs)
+	      remove_jump_threads_including (e);
+	}
+    }
+
   {
     gimple_stmt_iterator gsi;
     basic_block bb;
@@ -893,6 +924,11 @@ record_temporary_equivalences (edge e,
 void
 dom_opt_dom_walker::thread_across_edge (edge e)
 {
+  /* If E is not executable, then there's no reason to bother
+     threading across it.  */
+  if ((e->flags & EDGE_EXECUTABLE) == 0)
+    return;
+
   if (! m_dummy_cond)
     m_dummy_cond =
         gimple_build_cond (NE_EXPR,
@@ -951,6 +987,11 @@ record_equivalences_from_phis (basic_block bb)
 	  if (lhs == t)
 	    continue;
 
+	  /* If the associated edge is not marked as executable, then it
+	     can be ignored.  */
+	  if ((gimple_phi_arg_edge (phi, i)->flags & EDGE_EXECUTABLE) == 0)
+	    continue;
+
 	  t = dom_valueize (t);
 
 	  /* If we have not processed an alternative yet, then set
@@ -997,6 +1038,10 @@ single_incoming_edge_ignoring_loop_edges (basic_block bb)
       if (dominated_by_p (CDI_DOMINATORS, e->src, e->dest))
 	continue;
 
+      /* We can safely ignore edges that are not executable.  */
+      if ((e->flags & EDGE_EXECUTABLE) == 0)
+	continue;
+
       /* If we have already seen a non-loop edge, then we must have
 	 multiple incoming non-loop edges and thus we return NULL.  */
       if (retval)
@@ -1307,6 +1352,14 @@ dom_opt_dom_walker::before_dom_children (basic_block bb)
   m_avail_exprs_stack->push_marker ();
   m_const_and_copies->push_marker ();
 
+  /* If BB is not reachable, then propagate that property to edges, but
+     do not process this block any further.  */
+  if (!this->bb_reachable (cfun, bb))
+    {
+      this->propagate_unreachable_to_edges (bb, dump_file, dump_flags);
+      return;
+    }
+
   record_equivalences_from_incoming_edge (bb, m_const_and_copies,
 					  m_avail_exprs_stack);
 
@@ -1339,6 +1392,16 @@ dom_opt_dom_walker::after_dom_children (basic_block bb)
 {
   gimple *last;
 
+  /* If this block is not reachable, then there's nothing to do here.
+     However, make sure to restore the tables to their proper state.  */
+  if (!this->bb_reachable (cfun, bb))
+    {
+      this->maybe_clear_unreachable_dom (bb);
+      m_avail_exprs_stack->pop_to_marker ();
+      m_const_and_copies->pop_to_marker ();
+      return;
+    }
+
   /* If we have an outgoing edge to a block with multiple incoming and
      outgoing edges, then we may be able to thread the edge, i.e., we
      may be able to statically determine which of the outgoing edges
@@ -1852,22 +1915,25 @@ optimize_stmt (basic_block bb, gimple_stmt_iterator si,
 	  edge taken_edge = find_taken_edge (bb, val);
 	  if (taken_edge)
 	    {
-
-	      /* We need to remove any queued jump threads that
-		 reference outgoing edges from this block.  */
+	      /* Clear the EXECUTABLE flag on the other edges.  */
 	      edge_iterator ei;
 	      edge e;
 	      FOR_EACH_EDGE (e, ei, bb->succs)
-		remove_jump_threads_including (e);
-
-	      /* Now clean up the control statement at the end of
-		 BB and remove unexecutable edges.  */
-	      remove_ctrl_stmt_and_useless_edges (bb, taken_edge->dest);
+		{
+		  if (e != taken_edge)
+		    e->flags &= ~EDGE_EXECUTABLE;
+		}
 
-	      /* Fixup the flags on the single remaining edge.  */
-	      taken_edge->flags
-		&= ~(EDGE_TRUE_VALUE | EDGE_FALSE_VALUE | EDGE_ABNORMAL);
-	      taken_edge->flags |= EDGE_FALLTHRU;
+	      /* And fix the condition to be either true or false.  */
+	      if (gimple_code (stmt) == GIMPLE_COND)
+		{
+		  if (integer_zerop (val))
+		    gimple_cond_make_false (as_a <gcond *> (stmt));
+		  else if (integer_onep (val))
+		    gimple_cond_make_true (as_a <gcond *> (stmt));
+		  else
+		    gcc_unreachable ();
+		}
 
 	      /* Further simplifications may be possible.  */
 	      cfg_altered = true;
