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");