diff --git a/gcc/testsuite/gcc.dg/infinite-loop.c b/gcc/testsuite/gcc.dg/infinite-loop.c
new file mode 100644
index 00000000000..25037a2027e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/infinite-loop.c
@@ -0,0 +1,26 @@
+/* { dg-do link } */
+/* { dg-options "-O2" } */
+void link_error (void);
+
+void __attribute__ ((noinline,noipa))
+foo(int a)
+{
+ int b = 0;
+
+ while (1)
+   {
+     if (!a)
+       break;
+     b = 1;
+   }
+
+ if (b != 0)
+   link_error ();
+}
+
+int
+main()
+{
+  foo (0);
+}
+
diff --git a/gcc/tree-ssa-dom.cc b/gcc/tree-ssa-dom.cc
index fa43dbe6c44..8d8312ca350 100644
--- a/gcc/tree-ssa-dom.cc
+++ b/gcc/tree-ssa-dom.cc
@@ -426,6 +426,74 @@ free_all_edge_infos (void)
     }
 }
 
+/* Return TRUE if BB has precisely two preds, one of which
+   is a backedge from a forwarder block where the forwarder
+   block is a direct successor of BB.  Being a forwarder
+   block, it has no side effects other than transfer of
+   control.  Otherwise return FALSE.  */
+
+static bool
+single_block_loop_p (basic_block bb)
+{
+  /* Two preds.  */
+  if (EDGE_COUNT (bb->preds) != 2)
+    return false;
+
+  /* One and only one of the edges must be marked with
+     EDGE_DFS_BACK.  */
+  basic_block pred = NULL;
+  unsigned int count = 0;
+  if (EDGE_PRED (bb, 0)->flags & EDGE_DFS_BACK)
+    {
+      pred = EDGE_PRED (bb, 0)->src;
+      count++;
+    }
+  if (EDGE_PRED (bb, 1)->flags & EDGE_DFS_BACK)
+    {
+      pred = EDGE_PRED (bb, 1)->src;
+      count++;
+    }
+
+  if (count != 1)
+    return false;
+
+  /* Now examine PRED.  It should have a single predecessor which
+     is BB and a single successor that is also BB.  */
+  if (EDGE_COUNT (pred->preds) != 1
+      || EDGE_COUNT (pred->succs) != 1
+      || EDGE_PRED (pred, 0)->src != bb
+      || EDGE_SUCC (pred, 0)->dest != bb)
+    return false;
+
+  /* This looks good from a CFG standpoint.  Now look at the guts
+     of PRED.  Basically we want to verify there are no PHI nodes
+     and no real statements.  */
+  if (! gimple_seq_empty_p (phi_nodes (pred)))
+    return false;
+
+  gimple_stmt_iterator gsi;
+  for (gsi = gsi_last_bb (pred); !gsi_end_p (gsi); gsi_prev (&gsi))
+    {
+      gimple *stmt = gsi_stmt (gsi);
+
+      switch (gimple_code (stmt))
+	{
+	  case GIMPLE_LABEL:
+	    if (DECL_NONLOCAL (gimple_label_label (as_a <glabel *> (stmt))))
+	      return false;
+	    break;
+
+	  case GIMPLE_DEBUG:
+	    break;
+
+	  default:
+	    return false;
+	}
+    }
+
+  return true;
+}
+
 /* We have finished optimizing BB, record any information implied by
    taking a specific outgoing edge from BB.  */
 
@@ -435,6 +503,13 @@ record_edge_info (basic_block bb)
   gimple_stmt_iterator gsi = gsi_last_bb (bb);
   class edge_info *edge_info;
 
+  /* Free all the outgoing edge info data associated with
+     BB's outgoing edges.  */
+  edge e;
+  edge_iterator ei;
+  FOR_EACH_EDGE (e, ei, bb->succs)
+    free_dom_edge_info (e);
+
   if (! gsi_end_p (gsi))
     {
       gimple *stmt = gsi_stmt (gsi);
@@ -450,8 +525,6 @@ record_edge_info (basic_block bb)
 	      int i;
               int n_labels = gimple_switch_num_labels (switch_stmt);
 	      tree *info = XCNEWVEC (tree, last_basic_block_for_fn (cfun));
-	      edge e;
-	      edge_iterator ei;
 
 	      for (i = 0; i < n_labels; i++)
 		{
@@ -583,6 +656,62 @@ record_edge_info (basic_block bb)
               if (can_infer_simple_equiv && TREE_CODE (inverted) == EQ_EXPR)
 		edge_info->record_simple_equiv (op0, op1);
             }
+
+	  /* If this block is a single block loop, then we may be able to
+	     record some equivalences on the loop's exit edge.  */
+	  if (single_block_loop_p (bb))
+	    {
+	      /* We know it's a single block loop.  Now look at the loop
+		 exit condition.  What we're looking for is whether or not
+		 the exit condition is loop invariant which we can detect
+		 by checking if all the SSA_NAMEs referenced are defined
+		 outside the loop.  */
+	      if ((TREE_CODE (op0) != SSA_NAME
+		   || gimple_bb (SSA_NAME_DEF_STMT (op0)) != bb)
+		  && (TREE_CODE (op1) != SSA_NAME
+		      || gimple_bb (SSA_NAME_DEF_STMT (op1)) != bb))
+		{
+		  /* At this point we know the exit condition is loop
+		     invariant.  The only way to get out of the loop is
+		     if never traverses the backedge to begin with.  This
+		     implies that any PHI nodes create equivalances we can
+		     attach to the loop exit edge.  */
+		  int alternative
+		    = (EDGE_PRED (bb, 0)->flags & EDGE_DFS_BACK) ? 1 : 0;
+
+		  gphi_iterator gsi;
+		  for (gsi = gsi_start_phis (bb);
+		       !gsi_end_p (gsi);
+		       gsi_next (&gsi))
+		    {
+		      /* If the other alternative is the same as the result,
+			 then this is a degenerate and can be ignored.  */
+		      if (dst == PHI_ARG_DEF (phi, !alternative))
+			continue;
+
+		      /* Now get the EDGE_INFO class so we can append
+			 it to our list.  We want the successor edge
+			 where the destination is not the source of
+			 an incoming edge.  */
+		      gphi *phi = gsi.phi ();
+		      tree src = PHI_ARG_DEF (phi, alternative);
+		      tree dst = PHI_RESULT (phi);
+
+		      if (EDGE_SUCC (bb, 0)->dest
+			  != EDGE_PRED (bb, !alternative)->src)
+			edge_info = (class edge_info *)EDGE_SUCC (bb, 0)->aux;
+		      else
+			edge_info = (class edge_info *)EDGE_SUCC (bb, 1)->aux;
+
+		      /* Note that since this processing is done independently
+			 of other edge equivalency processing, we may not
+			 have an EDGE_INFO structure set up yet.  */
+		      if (edge_info == NULL)
+			edge_info = new class edge_info (false_edge);
+		      edge_info->record_simple_equiv (dst, src);
+		    }
+		}
+	    }
         }
     }
 }
