Abstract out can_duplicate_block_on_edge_p from tree-ssa-threadedge.cc [PR126896]

Both the jump threader's joiner registration and the upcoming phiopt
replication of PHI-of-compares joins need a way to determine if a
block on an edge can be duplicated.  Abstract out the code in
tree-ssa-threadedge.cc to be reusable by the upcoming work.

	PR tree-optimization/126896

gcc/ChangeLog:

	* cfghooks.cc (can_duplicate_block_on_edge_p): New.
	* cfghooks.h (can_duplicate_block_on_edge_p): Declare.
	* tree-ssa-threadedge.cc: Include cfghooks.h.
	(jump_threader::thread_across_edge): Use
	can_duplicate_block_on_edge_p.
diff --git a/gcc/cfghooks.cc b/gcc/cfghooks.cc
index a219b4a..9e20c82 100644
--- a/gcc/cfghooks.cc
+++ b/gcc/cfghooks.cc
@@ -1141,6 +1141,29 @@
   return cfg_hooks->can_duplicate_block_p (bb);
 }
 
+/* Returns true if we can duplicate E's destination with E redirected to the
+   copy.  */
+
+bool
+can_duplicate_block_on_edge_p (edge e)
+{
+  basic_block bb = e->dest;
+
+  if (!can_duplicate_block_p (bb))
+    return false;
+
+  if (e->flags & EDGE_COMPLEX)
+    return false;
+
+  edge s;
+  edge_iterator ei;
+  FOR_EACH_EDGE (s, ei, bb->succs)
+    if (s->flags & EDGE_COMPLEX)
+      return false;
+
+  return true;
+}
+
 /* Duplicate basic block BB, place it after AFTER (if non-null) and redirect
    edge E to it (if non-null).  Return the new basic block.
 
diff --git a/gcc/cfghooks.h b/gcc/cfghooks.h
index aa7071e..8d7cb2d 100644
--- a/gcc/cfghooks.h
+++ b/gcc/cfghooks.h
@@ -252,6 +252,7 @@
 extern void predict_edge (edge e, enum br_predictor predictor, int probability);
 extern bool predicted_by_p (const_basic_block bb, enum br_predictor predictor);
 extern bool can_duplicate_block_p (const_basic_block);
+extern bool can_duplicate_block_on_edge_p (edge);
 extern basic_block duplicate_block (basic_block, edge, basic_block,
 				    copy_bb_data * = NULL);
 extern bool block_ends_with_call_p (basic_block bb);
diff --git a/gcc/tree-ssa-threadedge.cc b/gcc/tree-ssa-threadedge.cc
index ce757b4..98184d1 100644
--- a/gcc/tree-ssa-threadedge.cc
+++ b/gcc/tree-ssa-threadedge.cc
@@ -22,6 +22,7 @@
 #include "system.h"
 #include "coretypes.h"
 #include "backend.h"
+#include "cfghooks.h"
 #include "tree.h"
 #include "gimple.h"
 #include "predict.h"
@@ -1010,12 +1011,11 @@
 
     /* If E->dest has abnormal outgoing edges, then there's no guarantee
        we can safely redirect any of the edges.  Just punt those cases.  */
-    FOR_EACH_EDGE (taken_edge, ei, e->dest->succs)
-      if (taken_edge->flags & EDGE_COMPLEX)
-	{
-	  m_state->pop ();
-	  return;
-	}
+    if (!can_duplicate_block_on_edge_p (e))
+      {
+	m_state->pop ();
+	return;
+      }
 
     /* Look at each successor of E->dest to see if we can thread through it.  */
     FOR_EACH_EDGE (taken_edge, ei, e->dest->succs)