If we have a joiner block and one of its outgoing edges is the latch, then we can end up with multiple latches for a loop when we duplicate the joiner. This (conservative) patch disables threading in that case.
I don't have a test which fails without other changes, but the code is clearly wrong as-is. Revisiting the loop situation is #1 on the priority list after all the basic work for threading through paths with multiple duplicated blocks is in-place.
Bootstrapped and regression tested on x86_64-unknown-linux-gnu. Installed on the trunk.
Jeff
* tree-ssa-threadupdate.c (thread_through_loop_header): Do not thread through a joiner which has the latch edge. diff --git a/gcc/tree-ssa-threadupdate.c b/gcc/tree-ssa-threadupdate.c index 97dc6cb..3fba848 100644 --- a/gcc/tree-ssa-threadupdate.c +++ b/gcc/tree-ssa-threadupdate.c @@ -1060,11 +1142,22 @@ thread_through_loop_header (struct loop *loop, bool may_peel_loop_headers) if (single_succ_p (header)) goto fail; + /* If we threaded the latch using a joiner block, we cancel the + threading opportunity out of an abundance of caution. However, + still allow threading from outside to inside the loop. */ if (latch->aux) { vec<jump_thread_edge *> *path = THREAD_PATH (latch); if ((*path)[1]->type == EDGE_COPY_SRC_JOINER_BLOCK) - goto fail; + { + delete_jump_thread_path (path); + latch->aux = NULL; + } + } + + if (latch->aux) + { + vec<jump_thread_edge *> *path = THREAD_PATH (latch); tgt_edge = (*path)[1]->e; tgt_bb = tgt_edge->dest; }