=================================================================== --- gcc/cfgcleanup.c (revision 108405) +++ gcc/cfgcleanup.c (working copy) @@ -1151,11 +1151,43 @@ return false; }
- /* We don't need to match the rest of edges as above checks should be enough - to ensure that they are equivalent. */ + /* The same checks as in try_crossjump_to_edge. It is required for RTL + version of sequence abstraction. */ + FOR_EACH_EDGE (e1, ei, bb2->succs) + { + edge e2; + edge_iterator ei; + basic_block d1 = e1->dest; + + if (FORWARDER_BLOCK_P (d1)) + d1 = EDGE_SUCC (d1, 0)->dest; + + FOR_EACH_EDGE (e2, ei, bb1->succs) + { + basic_block d2 = e2->dest; + if (FORWARDER_BLOCK_P (d2)) + d2 = EDGE_SUCC (d2, 0)->dest; + if (d1 == d2) + break; + } + + if (!e2) + return false; + } + return true; } These are not 'The same checks as in try_crossjump_to_edge. try_crossjump_to_edge will crash on a mismatch. This way of matching of equivalent edges cost quadratic time in the number of edges, and you just doubled that cost. This is likely to slow down compilation of the output of parser generators If the edges tend to appear in like order, keeping a pointer to the last find makes sense. Otherwise, quadratic time cost could be avoided by sorting the edges first. This might be conditional on the number of edges to avoid slowdown or simple cases. If the edges are sorted by pointer, the sort should be used only for the matching, but not actually affect the edge lists (as otherwise we get memory-allocation dependent compiler behaviour). Using extra memory can be avoided by sorting the edges by something pointer-independent, like destination basic block index, and using mergesort on the edge chains themselves. Sorting edges in place and keeping a pointer to the last match can also be combined to avoid unnecessary sorting without the need for a basic block flag: The node lists are first compared assuming they are sorted; if this doesn't give an instant match for a successor, this one successor is searched linearily. If that fails, the match fails; if it succeeds, the two lists - or only the uncompared parts - are sorted, and the sorted list compared. (Refinements are possible where usually only one lists needs sorting if the other list is already sorted, and the comparison picked up where it was before the re-sort.) It should be possible to encapsulate this matching with an iterator macro, to be used like: edge_match_iterator emi; FOR_EACH_EDGE_MATCH (e1, e2, emi, bb1, bb2, succs); if (emi.mismatch) return false; or in try_crossjump_to_ edge: edge_match_iterator emi; FOR_EACH_EDGE_MATCH (s, s2, emi, redirect_to, src1, succs) { s->count += s2->count; ... } gcc_assert (!emi.mismatch) If the exact edge matching is implemented sufficiently fast, there is also no point in counting various types and matching selected edges first. + /* Avoid deleting preseve label when redirecting ABNORMAL edeges. */ Typo: preseve