The following patch fixes PR64284 by removing loops we copied the header for with FSM threading. There may be better solutions, but at least for the testcase it looks difficult to update loops within the constraints of the calling passes.
Bootstrap and regtest ongoing on x86_64-unknown-linux-gnu. Richard. 2014-12-12 Richard Biener <rguent...@suse.de> PR tree-optimization/64284 * tree-ssa-threadupdate.c (duplicate_seme_region): Mark the loop for removal if we copied the loop header. * gcc.dg/torture/pr64284.c: New testcase. Index: gcc/tree-ssa-threadupdate.c =================================================================== --- gcc/tree-ssa-threadupdate.c (revision 218621) +++ gcc/tree-ssa-threadupdate.c (working copy) @@ -2364,7 +2364,7 @@ duplicate_seme_region (edge entry, edge basic_block *region_copy) { unsigned i; - bool free_region_copy = false, copying_header = false; + bool free_region_copy = false; struct loop *loop = entry->dest->loop_father; edge exit_copy; edge redirected; @@ -2388,10 +2388,7 @@ duplicate_seme_region (edge entry, edge initialize_original_copy_tables (); - if (copying_header) - set_loop_copy (loop, loop_outer (loop)); - else - set_loop_copy (loop, loop); + set_loop_copy (loop, loop); if (!region_copy) { @@ -2453,6 +2450,8 @@ duplicate_seme_region (edge entry, edge } /* Redirect the entry and add the phi node arguments. */ + if (entry->dest == loop->header) + mark_loop_for_removal (loop); redirected = redirect_edge_and_branch (entry, get_bb_copy (entry->dest)); gcc_assert (redirected != NULL); flush_pending_stmts (entry); Index: gcc/testsuite/gcc.dg/torture/pr64284.c =================================================================== --- gcc/testsuite/gcc.dg/torture/pr64284.c (revision 0) +++ gcc/testsuite/gcc.dg/torture/pr64284.c (working copy) @@ -0,0 +1,21 @@ +/* { dg-do compile } */ + +int *a; +int b; +int +fn1() { + enum { QSTRING } c = 0; + while (1) { + switch (*a) { + case '\'': + c = 0; + default: + switch (c) + case 0: + if (b) + return 0; + c = 1; + } + a++; + } +}