https://gcc.gnu.org/bugzilla/show_bug.cgi?id=121452

            Bug ID: 121452
           Summary: [14/15/16 Regression] Bogus 'OpenMP constructs ... may
                    not be nested inside ‘simd’ region' due to
                    compiler-inserted "#pragma omp __structured_block"
           Product: gcc
           Version: 16.0
            Status: UNCONFIRMED
          Keywords: openmp, rejects-valid
          Severity: normal
          Priority: P3
         Component: fortran
          Assignee: unassigned at gcc dot gnu.org
          Reporter: burnus at gcc dot gnu.org
                CC: sandra at gcc dot gnu.org
  Target Milestone: ---

This shows up with SPEC Accel for 463.swim - and is a regression due to
handling intervening code with 'collapse(2)' → see list of commits below.

It's a true regression for the code shown first, it is also a rejects-valid but
no regression for the code variants (C, C++, Fortran).


The example fails with:

Error: OpenMP constructs other than ‘ordered simd’, ‘simd’, ‘loop’ or ‘atomic’
may not be nested inside ‘simd’ region


Simplified testcase:

implicit none
integer :: i, j
integer :: A(5,5), B(5,5) = 1

!$omp simd collapse(2)
   do 10 i = 1, 5
     do 20 j = 1, 5
       A(i,j) = B(i,j)
20   continue
10 continue

if (any(A /= 1)) stop 1
end


The code looks as follows - note the "#pragma omp __structured_block".
Note that CONTINUE is an old way to end a loop and nothing is actually using
the label on tree level. (On Fortran level, the '10' / '20' are used in 'DO'.)

  #pragma omp simd collapse(2)
  for (i = 1; i <= 5; i = i + 1)
    for (j = 1; j <= 5; j = j + 1)
      {
        {
          a[((integer(kind=8)) j * 5 + (integer(kind=8)) i) + -6] =
b[((integer(kind=8)) j * 5 + (integer(kind=8)) i) + -6];
          __label_000020:;
          #pragma omp __structured_block
            {
              __label_000010:
            }
          L.2:;
        }
        L.1:;
      }

* * *

VARIANT - has the same issue and points at the 'x = 1' line:

integer :: x
…
!$omp simd collapse(2)
   do i = 1, 5
     do j = 1, 5
       A(i,j) = B(i,j)
     end do
     x = 1  ! Actual intervening code
   end do

* * *

C/C++ VARIANT - like last example, again with intervening code.
[Error points a '}' after the 'C[i] = 4;' line.]

void f(int *A, int *B, int *C)
{
  #pragma omp simd collapse(2)
  for (int i=0; i < 1; i++) {
    for (int j=0; j < 1; j++)
      A[i] += B[j];
    C[i] = 4;
  }
}

* * *

Side remark 1: Using 'omp do' it works.

Side remark 2: Old Fortran also liked to share the continue lines; but that has
no issue with regard to 'omp simd':

     do 10 i = 1, 5
       do 10 j = 1, 5
         A(i,j) = B(i,j)
  10 continue 
  ! "Warning: Fortran 2018 deleted feature: Shared DO termination label 10"

* * *

Regression causing is the combination of following two patches:

"#pragma omp __structured_block" was added in:

commit r14-3488-ga62c8324e7e31ae6614f549bdf9d8a653233f8fc
Author: Sandra Loosemore <san...@codesourcery.com>
Date:   Thu Aug 24 17:34:59 2023 +0000

    OpenMP: Add OMP_STRUCTURED_BLOCK and GIMPLE_OMP_STRUCTURED_BLOCK.

    In order to detect invalid jumps in and out of intervening code in
    imperfectly-nested loops, the front ends need to insert some sort of
    marker to identify the structured block sequences that they push into
    the inner body of the loop.  The error checking happens in the
    diagnose_omp_blocks pass, between gimplification and OMP lowering, so
    we need both GENERIC and GIMPLE representations of these markers.
    They are removed in OMP lowering so no subsequent passes need to know
    about them.

but only activated for Fortran in commit:

commit r14-3492-gb7c4a12a9df3170090a431fa4364b97b30b87752
Author: Sandra Loosemore <san...@codesourcery.com>
Date:   Thu Aug 24 17:35:01 2023 +0000

    OpenMP: Fortran support for imperfectly-nested loops

* * *

Showing the error is omp-low.cc's

/* Check nesting restrictions.  */
static bool   
check_omp_nesting_restrictions (gimple *stmt, omp_context *ctx)
{
...
      if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
          && gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_SIMD
          && !ctx->loop_p)
        {
          c = NULL_TREE;
          if (ctx->order_concurrent
              && (gimple_code (stmt) == GIMPLE_OMP_ORDERED
                  || gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD
                  || gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE))
            {
              error_at (gimple_location (stmt),
                        "OpenMP constructs other than %<parallel%>, %<loop%>"
                        " or %<simd%> may not be nested inside a region with"
                        " the %<order(concurrent)%> clause");

Reply via email to