LIM fails to properly mark new blocks/edges it creates as belonging to irreducible regions.
Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to trunk and 4.9 branch. Richard. 2014-04-23 Richard Biener <rguent...@suse.de> PR tree-optimization/60903 * tree-ssa-loop-im.c (analyze_memory_references): Remove commented code block. (execute_sm_if_changed): Properly apply IRREDUCIBLE_LOOP loop flags to newly created BBs and edges. * gcc.dg/torture/pr60903.c: New testcase. Index: gcc/tree-ssa-loop-im.c =================================================================== *** gcc/tree-ssa-loop-im.c (revision 209677) --- gcc/tree-ssa-loop-im.c (working copy) *************** analyze_memory_references (void) *** 1544,1558 **** struct loop *loop, *outer; unsigned i, n; - #if 0 - /* Initialize bb_loop_postorder with a mapping from loop->num to - its postorder index. */ - i = 0; - bb_loop_postorder = XNEWVEC (unsigned, number_of_loops (cfun)); - FOR_EACH_LOOP (loop, LI_FROM_INNERMOST) - bb_loop_postorder[loop->num] = i++; - #endif - /* Collect all basic-blocks in loops and sort them after their loops postorder. */ i = 0; --- 1547,1552 ---- *************** execute_sm_if_changed (edge ex, tree mem *** 1807,1812 **** --- 1803,1809 ---- gimple_stmt_iterator gsi; gimple stmt; struct prev_flag_edges *prev_edges = (struct prev_flag_edges *) ex->aux; + bool irr = ex->flags & EDGE_IRREDUCIBLE_LOOP; /* ?? Insert store after previous store if applicable. See note below. */ *************** execute_sm_if_changed (edge ex, tree mem *** 1821,1828 **** old_dest = ex->dest; new_bb = split_edge (ex); then_bb = create_empty_bb (new_bb); ! if (current_loops && new_bb->loop_father) ! add_bb_to_loop (then_bb, new_bb->loop_father); gsi = gsi_start_bb (new_bb); stmt = gimple_build_cond (NE_EXPR, flag, boolean_false_node, --- 1818,1826 ---- old_dest = ex->dest; new_bb = split_edge (ex); then_bb = create_empty_bb (new_bb); ! if (irr) ! then_bb->flags = BB_IRREDUCIBLE_LOOP; ! add_bb_to_loop (then_bb, new_bb->loop_father); gsi = gsi_start_bb (new_bb); stmt = gimple_build_cond (NE_EXPR, flag, boolean_false_node, *************** execute_sm_if_changed (edge ex, tree mem *** 1834,1842 **** stmt = gimple_build_assign (unshare_expr (mem), tmp_var); gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING); ! make_edge (new_bb, then_bb, EDGE_TRUE_VALUE); ! make_edge (new_bb, old_dest, EDGE_FALSE_VALUE); ! then_old_edge = make_edge (then_bb, old_dest, EDGE_FALLTHRU); set_immediate_dominator (CDI_DOMINATORS, then_bb, new_bb); --- 1832,1843 ---- stmt = gimple_build_assign (unshare_expr (mem), tmp_var); gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING); ! make_edge (new_bb, then_bb, ! EDGE_TRUE_VALUE | (irr ? EDGE_IRREDUCIBLE_LOOP : 0)); ! make_edge (new_bb, old_dest, ! EDGE_FALSE_VALUE | (irr ? EDGE_IRREDUCIBLE_LOOP : 0)); ! then_old_edge = make_edge (then_bb, old_dest, ! EDGE_FALLTHRU | (irr ? EDGE_IRREDUCIBLE_LOOP : 0)); set_immediate_dominator (CDI_DOMINATORS, then_bb, new_bb); Index: gcc/testsuite/gcc.dg/torture/pr60903.c =================================================================== *** gcc/testsuite/gcc.dg/torture/pr60903.c (revision 0) --- gcc/testsuite/gcc.dg/torture/pr60903.c (working copy) *************** *** 0 **** --- 1,22 ---- + /* { dg-do compile } */ + + extern int a, b, k, q; + + void + foo () + { + if (a) + { + while (q) + { + lbl: + if (a) + { + a = 0; + goto lbl; + } + } + b = k; + } + goto lbl; + }