+static edge
+find_subloop_latch_edge (struct loop *loop)
+{
+ VEC (edge, heap) *latches = get_loop_latch_edges (loop);
+ edge latch = NULL;
+
+ if (VEC_length (edge, latches) > 1)
+ {
+ latch = find_subloop_latch_edge_by_profile (latches);
+
+ if (!latch
+ /* We consider ivs to guess the latch edge only in SSA. Perhaps we
+ should use cfghook for this, but it is hard to imagine it would
+ be useful elsewhere. */
+ && current_ir_type () == IR_GIMPLE)
+ latch = find_subloop_latch_edge_by_ivs (loop, latches);
+ }
+
+ VEC_free (edge, heap, latches);
+ return latch;
+}
+
+/* Callback for make_forwarder_block. Returns true if the edge E is marked
+ in the set MFB_REIS_SET. */
+
+static struct pointer_set_t *mfb_reis_set;
+static bool
+mfb_redirect_edges_in_set (edge e)
+{
+ return pointer_set_contains (mfb_reis_set, e);
+}
+
+/* Creates a subloop of LOOP with latch edge LATCH. */
+
+static void
+form_subloop (struct loop *loop, edge latch)
+{
+ edge_iterator ei;
+ edge e, new_entry;
+ struct loop *new_loop;
+
+ mfb_reis_set = pointer_set_create ();
+ FOR_EACH_EDGE (e, ei, loop->header->preds)
+ {
+ if (e != latch)
+ pointer_set_insert (mfb_reis_set, e);
+ }
+ new_entry = make_forwarder_block (loop->header, mfb_redirect_edges_in_set,
+ NULL);
+ pointer_set_destroy (mfb_reis_set);
+
+ loop->header = new_entry->src;
+
+ /* Find the blocks and subloops that belong to the new loop, and add it to
+ the appropriate place in the loop tree. */
+ new_loop = alloc_loop ();
+ new_loop->header = new_entry->dest;
+ new_loop->latch = latch->src;
+ add_loop (new_loop, loop);
+}
+
+/* Make all the latch edges of LOOP to go to a single forwarder block --
+ a new latch of LOOP. */
+
+static void
+merge_latch_edges (struct loop *loop)
+{
+ VEC (edge, heap) *latches = get_loop_latch_edges (loop);
+ edge latch, e;
+ unsigned i;
+
+ gcc_assert (VEC_length (edge, latches) > 0);
+
+ if (VEC_length (edge, latches) == 1)
+ loop->latch = VEC_index (edge, latches, 0)->src;
+ else
+ {
+ if (dump_file)
+ fprintf (dump_file, "Merged latch edges of loop %d\n", loop->num);
+
+ mfb_reis_set = pointer_set_create ();
+ for (i = 0; VEC_iterate (edge, latches, i, e); i++)
+ pointer_set_insert (mfb_reis_set, e);
+ latch = make_forwarder_block (loop->header, mfb_redirect_edges_in_set,
+ NULL);
+ pointer_set_destroy (mfb_reis_set);
+
+ loop->header = latch->dest;
+ loop->latch = latch->src;
+ }
+
+ VEC_free (edge, heap, latches);
+}
+
+/* LOOP may have several latch edges. Transform it into (possibly several)
+ loops with single latch edge. */
+
+static void
+disambiguate_multiple_latches (struct loop *loop)