The following fixes a fixup for loops when merging two basic-blocks. We didn't handle merging two loop headers well which the following patch addresses.
LTO bootstrapped (which was broken before this patch) and tested on x86_64-unknown-linux-gnu, applied. Richard. 2012-12-20 Richard Biener <rguent...@suse.de> PR middle-end/55740 * cfghooks.c (merge_blocks): Properly handle merging of two loop headers. * g++.dg/torture/pr55740.C: New testcase. Index: gcc/cfghooks.c =================================================================== *** gcc/cfghooks.c (revision 194610) --- gcc/cfghooks.c (working copy) *************** merge_blocks (basic_block a, basic_block *** 724,734 **** cfg_hooks->merge_blocks (a, b); - /* If we merge a loop header into its predecessor, update the loop - structure. */ if (current_loops != NULL) { ! if (b->loop_father->header == b) { remove_bb_from_loops (a); add_bb_to_loop (a, b->loop_father); --- 724,746 ---- cfg_hooks->merge_blocks (a, b); if (current_loops != NULL) { ! /* If the block we merge into is a loop header do nothing unless ... */ ! if (a->loop_father->header == a) ! { ! /* ... we merge two loop headers, in which case we kill ! the inner loop. */ ! if (b->loop_father->header == b) ! { ! b->loop_father->header = NULL; ! b->loop_father->latch = NULL; ! loops_state_set (LOOPS_NEED_FIXUP); ! } ! } ! /* If we merge a loop header into its predecessor, update the loop ! structure. */ ! else if (b->loop_father->header == b) { remove_bb_from_loops (a); add_bb_to_loop (a, b->loop_father); Index: gcc/testsuite/g++.dg/torture/pr55740.C =================================================================== *** gcc/testsuite/g++.dg/torture/pr55740.C (revision 0) --- gcc/testsuite/g++.dg/torture/pr55740.C (working copy) *************** *** 0 **** --- 1,19 ---- + // { dg-do compile } + + static bool st_IsPathDelimiter( char c ) { return c == '/'; } + bool IsValidPath( char const * filename ) + { + if ( !filename || filename[0] == 0 ) + return false; + char const * run = filename; + while ( run && *run ) + { + if ( run[0] == '.' ) + if ( run[1] != '.' || ( !st_IsPathDelimiter( run[2] ) && run[2] != 0 ) ) + return false; + while ( *run && !st_IsPathDelimiter( *run ) ) + ++run; + if ( *run ) + ++run; + } + }