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.

Reply via email to