https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66846
Bug ID: 66846 Summary: parloops does not always mark loops for fixup if needed Product: gcc Version: 6.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: tree-optimization Assignee: unassigned at gcc dot gnu.org Reporter: vries at gcc dot gnu.org Target Milestone: --- In openmp expansion of loops, we do some effort to try to create matching loops in the loop state of the child function, and if that doesn't work out, to mark the loop state for fixup. This checking code checks that we actually do one or the other: ... diff --git a/gcc/omp-low.c b/gcc/omp-low.c index 0e69bc2..1b64298 100644 --- a/gcc/omp-low.c +++ b/gcc/omp-low.c @@ -5603,6 +5603,12 @@ expand_omp_taskreg (struct omp_region *region) } if (gimple_in_ssa_p (cfun)) update_ssa (TODO_update_ssa); + if (!loops_state_satisfies_p (LOOPS_NEED_FIXUP)) + { +#ifdef ENABLE_CHECKING + verify_loop_structure (); +#endif + } pop_cfun (); } ... With this checking code enabled, we run into errors here: ... src/gcc/testsuite/gcc.dg/autopar/outer-1.c: In function ‘parloop._loopfn.0’: src/gcc/testsuite/gcc.dg/autopar/outer-1.c:11:3: error: loop with header 5 not in loop tree src/gcc/testsuite/gcc.dg/autopar/outer-1.c:11:3: internal compiler error: in verify_loop_structure, at cfgloop.c:1647 0x884d18 verify_loop_structure() src/gcc/cfgloop.c:1647 0xe1d746 expand_omp_taskreg src/gcc/omp-low.c:5609 0xe2d904 expand_omp src/gcc/omp-low.c:9301 0xe2de07 execute_expand_omp src/gcc/omp-low.c:9498 0xe2df54 execute src/gcc/omp-low.c:9583 Please submit a full bug report, with preprocessed source if appropriate. Please include the complete backtrace with any bug report. See <http://gcc.gnu.org/bugs.html> for instructions. ... In outer-1.c, we parallelize an outer loop. In the parloops pass, we cancel both the outer and inner loop in the loop state: ... /* Cancel the loop (it is simpler to do it here rather than to teach the expander to do it). */ cancel_loop_tree (loop); ... During omp-expand, we only create a loop in the loop state for the new outer loop, but not the inner loop. Hence the ICE. Normally, we don't run into trouble because we set the loop state for fixup anyway in execute_fixup_cfg in pass_fixup_cfg: ... 8804 if (current_loops 8805 && (todo & TODO_cleanup_cfg)) 8806 loops_state_set (LOOPS_NEED_FIXUP); ... The todo contains TODO_cleanup_cfg, because of this code, in the 'gimple_in_ssa_p (cfun)' branch: ... if (decl) { int flags = gimple_call_flags (stmt); if (flags & (ECF_CONST | ECF_PURE | ECF_LOOPING_CONST_OR_PURE)) { if (gimple_purge_dead_abnormal_call_edges (bb)) todo |= TODO_cleanup_cfg; if (gimple_in_ssa_p (cfun)) { todo |= TODO_update_ssa | TODO_cleanup_cfg; update_stmt (stmt); } } ... The code is triggered for stmt: ... _7 = __builtin_omp_get_num_threads (); ... which has flags ECF_CONST.