-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1
The underlying problem here is a botched update of a PHI argument when we thread all incoming edges for a particular block. In that case we used to use the original block as the template block which saved a little bit of memory at the expense of slightly more complex SSA updating. However, after looking a some of the changes over the last few years to tree-ssa-threadupdate.c, I'm not sure that's safe anymore. Furthermore, the SSA graph updating code was going to need another hack to deal with the case where we thread deeper into the CFG. Rather than try to make those two things work, it's easier to just delete all the code which tried to reuse the soon-to-be-unreachable block. I like it when removing code fixes bugs. Installed after a bootstrap and regression test cycle (including Ada bootstrapping which triggered the bug report). -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.11 (GNU/Linux) Comment: Using GnuPG with Fedora - http://enigmail.mozdev.org/ iQEcBAEBAgAGBQJNkmNNAAoJEBRtltQi2kC7d8EH/0XN0oGPYrRFwnuHjD3TjaT8 361rgDyakOGwD3JVRYE2xte/aDXAJQYTk46DazoCZtL1Q5H4R7HIH0nsy380Qvg6 amJmCBGDItGdYOCVwny0cRQJf3QgDfCn69GNAaDuE2myM8cUz0H9Mr5uuB+chCFY 1EUyDVRk9hWY72FxZ1drADXD4ROtxhEwipcCXj6a67jGd0WnWMgLyxMVdYiJ5oRw ezoL1rxwMABTJKM1blG38Osl8xU1SZuIzpctR7RTcdXYc6ZTe39bY9ysHmRHHDGi M35mZMEw6DtAjKnYBSjDzw513fHUip/qkqeH4rIjSAwCSW4XIemJ3eEQPF7Kb84= =vXqW -----END PGP SIGNATURE-----
* tree-ssa-threadupdate.c (struct redirection_data): Remove do_not_duplicate field. (lookup_redirection_data): Corresponding changes. (create_duplicates): Always create a template block. (redirect_edges): Remove code which reused the original block when it was going to become unreachable code. (thread_block): Don't set do_not_duplicate field. Index: tree-ssa-threadupdate.c =================================================================== *** tree-ssa-threadupdate.c (revision 171692) --- tree-ssa-threadupdate.c (working copy) *************** along with GCC; see the file COPYING3. *** 69,77 **** Note that block duplication can be minimized by first collecting the set of unique destination blocks that the incoming edges should ! be threaded to. Block duplication can be further minimized by using ! B instead of creating B' for one destination if all edges into B are ! going to be threaded to a successor of B. We further reduce the number of edges and statements we create by not copying all the outgoing edges and the control statement in --- 69,84 ---- Note that block duplication can be minimized by first collecting the set of unique destination blocks that the incoming edges should ! be threaded to. ! ! Block duplication can be further minimized by using B instead of ! creating B' for one destination if all edges into B are going to be ! threaded to a successor of B. We had code to do this at one time, but ! I'm not convinced it is correct with the changes to avoid mucking up ! the loop structure (which may cancel threading requests, thus a block ! which we thought was going to become unreachable may still be reachable). ! This code was also going to get ugly with the introduction of the ability ! for a single jump thread request to bypass multiple blocks. We further reduce the number of edges and statements we create by not copying all the outgoing edges and the control statement in *************** struct redirection_data *** 117,127 **** /* A list of incoming edges which we want to thread to OUTGOING_EDGE->dest. */ struct el *incoming_edges; - - /* Flag indicating whether or not we should create a duplicate block - for this thread destination. This is only true if we are threading - all incoming edges and thus are using BB itself as a duplicate block. */ - bool do_not_duplicate; }; /* Main data structure to hold information for duplicates of BB. */ --- 124,129 ---- *************** lookup_redirection_data (edge e, edge in *** 249,255 **** elt = XNEW (struct redirection_data); elt->outgoing_edge = e; elt->dup_block = NULL; - elt->do_not_duplicate = false; elt->incoming_edges = NULL; slot = htab_find_slot (redirection_data, elt, insert); --- 251,256 ---- *************** create_duplicates (void **slot, void *da *** 338,348 **** struct redirection_data *rd = (struct redirection_data *) *slot; struct local_info *local_info = (struct local_info *)data; - /* If this entry should not have a duplicate created, then there's - nothing to do. */ - if (rd->do_not_duplicate) - return 1; - /* Create a template block if we have not done so already. Otherwise use the template to create a new block. */ if (local_info->template_block == NULL) --- 339,344 ---- *************** redirect_edges (void **slot, void *data) *** 433,463 **** gcc_assert (e == e2); flush_pending_stmts (e2); } - else - { - if (dump_file && (dump_flags & TDF_DETAILS)) - fprintf (dump_file, " Threaded jump %d --> %d to %d\n", - e->src->index, e->dest->index, local_info->bb->index); - - /* We are using BB as the duplicate. Remove the unnecessary - outgoing edges and statements from BB. */ - remove_ctrl_stmt_and_useless_edges (local_info->bb, - rd->outgoing_edge->dest); - - /* If we are threading beyond the immediate successors of - the duplicate, then BB will have no edges, create one. */ - if (EDGE_COUNT (local_info->bb->succs) == 0) - create_edge_and_update_destination_phis (rd, local_info->bb); - - /* Fixup the flags on the single remaining edge. */ - single_succ_edge (local_info->bb)->flags - &= ~(EDGE_TRUE_VALUE | EDGE_FALSE_VALUE | EDGE_ABNORMAL); - single_succ_edge (local_info->bb)->flags |= EDGE_FALLTHRU; - - /* And adjust count and frequency on BB. */ - local_info->bb->count = e->count; - local_info->bb->frequency = EDGE_FREQUENCY (e); - } } /* Indicate that we actually threaded one or more jumps. */ --- 429,434 ---- *************** thread_block (basic_block bb, bool noloo *** 526,535 **** struct local_info local_info; struct loop *loop = bb->loop_father; - /* ALL indicates whether or not all incoming edges into BB should - be threaded to a duplicate of BB. */ - bool all = true; - /* To avoid scanning a linear array for the element we need we instead use a hash table. For normal code there should be no noticeable difference. However, if we have a block with a large number of --- 497,502 ---- *************** thread_block (basic_block bb, bool noloo *** 566,575 **** || (noloop_only && bb == bb->loop_father->header && !loop_exit_edge_p (bb->loop_father, e2))) ! { ! all = false; ! continue; ! } if (e->dest == e2->src) update_bb_profile_for_threading (e->dest, EDGE_FREQUENCY (e), --- 533,539 ---- || (noloop_only && bb == bb->loop_father->header && !loop_exit_edge_p (bb->loop_father, e2))) ! continue; if (e->dest == e2->src) update_bb_profile_for_threading (e->dest, EDGE_FREQUENCY (e), *************** thread_block (basic_block bb, bool noloo *** 580,595 **** lookup_redirection_data (e2, e, INSERT); } - /* If we are going to thread all incoming edges to an outgoing edge, then - BB will become unreachable. Rather than just throwing it away, use - it for one of the duplicates. Mark the first incoming edge with the - DO_NOT_DUPLICATE attribute. */ - if (all) - { - edge e = (edge) EDGE_PRED (bb, 0)->aux; - lookup_redirection_data (e, NULL, NO_INSERT)->do_not_duplicate = true; - } - /* We do not update dominance info. */ free_dominance_info (CDI_DOMINATORS); --- 544,549 ----