+/* Like flow_find_cross_jump, except start looking for a matching sequence from
+ the head of the two blocks. Do not include jumps at the end.
+ If STOP_AFTER is nonzero, stop after finding that many matching
+ instructions. */
+
+int
+flow_find_head_matching_sequence (basic_block bb1, basic_block bb2, rtx *f1,
+ rtx *f2, int stop_after)
+{
+ rtx i1, i2, last1, last2, beforelast1, beforelast2;
+ int ninsns = 0;
+ edge e;
+ edge_iterator ei;
+ int nehedges1 = 0, nehedges2 = 0;
+
+ FOR_EACH_EDGE (e, ei, bb1->succs)
+ if (e->flags & EDGE_EH)
+ nehedges1++;
+ FOR_EACH_EDGE (e, ei, bb2->succs)
+ if (e->flags & EDGE_EH)
+ nehedges2++;
+
+ i1 = BB_HEAD (bb1);
+ i2 = BB_HEAD (bb2);
+ last1 = beforelast1 = last2 = beforelast2 = NULL_RTX;
+
+ while (true)
+ {
+
+ /* Ignore notes. */
+ while (!NONDEBUG_INSN_P (i1) && i1 != BB_END (bb1))
+ i1 = NEXT_INSN (i1);
+
+ while (!NONDEBUG_INSN_P (i2) && i2 != BB_END (bb2))
+ i2 = NEXT_INSN (i2);
+
+ if (NOTE_P (i1) || NOTE_P (i2)
+ || JUMP_P (i1) || JUMP_P (i2))
+ break;
+
+ /* A sanity check to make sure we're not merging insns with different
+ effects on EH. If only one of them ends a basic block, it shouldn't
+ have an EH edge; if both end a basic block, there should be the same
+ number of EH edges. */
+ if ((i1 == BB_END (bb1) && i2 != BB_END (bb2)
+ && nehedges1 > 0)
+ || (i2 == BB_END (bb2) && i1 != BB_END (bb1)
+ && nehedges2 > 0)
+ || (i1 == BB_END (bb1) && i2 == BB_END (bb2)
+ && nehedges1 != nehedges2))
+ break;
+
+ if (!old_insns_match_p (0, i1, i2))
+ break;
+
+ merge_memattrs (i1, i2);
+
+ /* Don't begin a cross-jump with a NOTE insn. */
+ if (INSN_P (i1))
+ {
+ merge_notes (i1, i2);
+
+ beforelast1 = last1, beforelast2 = last2;
+ last1 = i1, last2 = i2;
+ ninsns++;
+ }
+
+ if (i1 == BB_END (bb1) || i2 == BB_END (bb2)
+ || (stop_after > 0 && ninsns == stop_after))
+ break;
+
+ i1 = NEXT_INSN (i1);
+ i2 = NEXT_INSN (i2);
+ }
+
+#ifdef HAVE_cc0
+ /* Don't allow a compare to be shared by cross-jumping unless the insn
+ after the compare is also shared. */
+ if (ninsns && reg_mentioned_p (cc0_rtx, last1) && sets_cc0_p (last1))
+ last1 = beforelast1, last2 = beforelast2, ninsns--;
+#endif
+
+ if (ninsns)
+ {
+ *f1 = last1;
+ *f2 = last2;
+ }
+
+ return ninsns;
+}
+