gcc-8.0.0-alpha20170611 snapshot ICEs when compiling the following snippet w/ -O2 (-O3, -Ofast) -floop-nest-optimize: int x3, za; int hg[1]; void yw (int dq) { const int r7 = 2; while (dq < 1) { for (x3 = 0; x3 < r7; ++x3) for (za = 0; za < r7; ++za) hg[1] = 0; ++dq; } x3 = 0; while (x3 < r7) { ++x3; if (x3 == 0) break; } } % gcc-8.0.0-alpha20170611 -O2 -floop-nest-optimize -c yrfe1sre.c during GIMPLE pass: graphite yrfe1sre.c: In function 'yw': yrfe1sre.c:5:1: internal compiler error: Segmentation fault yw (int dq) ^~ (gdb) where #0 0x000000000087c4e8 in loop_preheader_edge(loop const*) () #1 0x0000000000d44621 in analyze_scalar_evolution(loop*, tree_node*) () #2 0x0000000000d47d7b in analyze_scalar_evolution_in_loop(loop*, loop*, tree_node*, bool*) () #3 0x0000000000d47ed2 in simple_iv_with_niters(loop*, loop*, tree_node*, affine_iv*, tree_node**, bool) () #4 0x0000000000bad67f in is_comparison_with_loop_invariant_p(gcond*, loop*, tree_node**, tree_code*, tree_node**, tree_node**) () #5 0x0000000000bb4139 in predict_loops() () #6 0x0000000000bb6023 in tree_estimate_probability(bool) () #7 0x0000000001375172 in graphite_transform_loops() () #8 0x0000000001375701 in (anonymous namespace)::pass_graphite_transforms::execute(function*) () #9 0x0000000000b9b629 in execute_one_pass(opt_pass*) () #10 0x0000000000b9be55 in execute_pass_list_1(opt_pass*) () #11 0x0000000000b9be67 in execute_pass_list_1(opt_pass*) () #12 0x0000000000b9be67 in execute_pass_list_1(opt_pass*) () #13 0x0000000000b9be67 in execute_pass_list_1(opt_pass*) () #14 0x0000000000b9be99 in execute_pass_list(function*, opt_pass*) () #15 0x00000000008a4720 in cgraph_node::expand() () #16 0x00000000008a5bd1 in symbol_table::compile() [clone .part.51] () #17 0x00000000008a7dc7 in symbol_table::finalize_compilation_unit() () #18 0x0000000000c71655 in compile_file() () #19 0x000000000072f69a in toplev::main(int, char**) () #20 0x00000000007315bb in main ()
#6 0x0000000000de6e8e in is_comparison_with_loop_invariant_p ( stmt=0x7ffff69d7460, loop=0x7ffff69d8210, loop_invariant=0x7fffffffd800, compare_code=0x7fffffffd814, loop_step=0x7fffffffd808, loop_iv_base=0x7fffffffd7f8) at /space/rguenther/src/svn/early-lto-debug/gcc/predict.c:1397 1397 if (!simple_iv (loop, loop_containing_stmt (stmt), op0, &iv0, true)) (gdb) p stmt $1 = (gcond *) 0x7ffff69d7460 (gdb) p debug_gimple_stmt (stmt) if (0 != 0) $2 = void (gdb) p gimple_bb (stmt) $3 = <basic_block 0x0> hum. Ok, so it looks like loop->bounds got invalid and we have stale nb_iter->stmt pointers. Caused by moving of IVCANON pass as well. Testcase works with -fdisable-tree-ivcanon. But sth is fishy, I suppose ivcanon fails to invalidate recorded niters. Honza? Like the following which fixes the ICE: Index: gcc/tree-ssa-loop-ivcanon.c =================================================================== --- gcc/tree-ssa-loop-ivcanon.c (revision 249185) +++ gcc/tree-ssa-loop-ivcanon.c (working copy) @@ -1216,11 +1216,13 @@ canonicalize_induction_variables (void) estimate_numbers_of_iterations (); FOR_EACH_LOOP (loop, LI_FROM_INNERMOST) - { - changed |= canonicalize_loop_induction_variables (loop, - true, UL_SINGLE_ITER, - true); - } + if (canonicalize_loop_induction_variables (loop, + true, UL_SINGLE_ITER, + true)) + { + changed = true; + free_numbers_of_iterations_estimates_loop (loop); + } gcc_assert (!need_ssa_update_p (cfun)); unloop_loops (loop_closed_ssa_invalidated, &irred_invalidated); but I can't see where ivcanon builds a new exit condition stmt, it just updates the existing one...
Ah, it is CFG cleanup removing a loop exit edge but not updating loop info it seems. So when remove_edge calls rescan_loop_exit it doesn't adjust bounds. So either we are not supposed to keep those "live" at all or we somehow need to manage them as well during CFG cleanup and other loop opts...
Mine.
So amending scev_reset to do free_numbers_of_iterations_estimates causes issues with complete peeling which uses gimple_duplicate_loop_to_header_edge which calls scev_reset (peeling invalidates cached CHRECs for the loop header PHIs and derived SSA names) but then using ->bounds to mark paths in the loop copies as gcc_unreachable () (remove_exits_and_undefined_stmts). That looks fishy somewhat, also because we defer this operation when processing adjacent loops which will then eventually clear estimates before the 2nd adjacent loop is processed (that might still work in the end if we only reset estimates for a single loop at a time or estimates are computed on-demand again when using the correct API). Even more ugly so we ggc_free bounds ...
Author: rguenth Date: Fri Jun 16 12:19:24 2017 New Revision: 249249 URL: https://gcc.gnu.org/viewcvs?rev=249249&root=gcc&view=rev Log: 2017-06-16 Richard Biener <rguenther@suse.de> PR tree-optimization/81090 * passes.def (pass_record_bounds): Remove. * tree-pass.h (make_pass_record_bounds): Likewise. * tree-ssa-loop.c (pass_data_record_bounds, pass_record_bounds, make_pass_record_bounds): Likewise. * tree-ssa-loop-ivcanon.c (canonicalize_induction_variables): Do not free niter estimates at the beginning but at the end. * tree-scalar-evolution.c (scev_finalize): Free niter estimates. * gcc.dg/graphite/pr81090.c: New testcase. Added: trunk/gcc/testsuite/gcc.dg/graphite/pr81090.c Modified: trunk/gcc/ChangeLog trunk/gcc/passes.def trunk/gcc/testsuite/ChangeLog trunk/gcc/tree-pass.h trunk/gcc/tree-scalar-evolution.c trunk/gcc/tree-ssa-loop-ivcanon.c trunk/gcc/tree-ssa-loop.c
Fixed.