* [PATCH, OpenMP 5.1, Fortran] Strictly-structured block support for OpenMP directives @ 2021-10-07 13:59 Chung-Lin Tang 2021-10-07 16:33 ` Tobias Burnus 2021-10-07 17:09 ` Jakub Jelinek 0 siblings, 2 replies; 12+ messages in thread From: Chung-Lin Tang @ 2021-10-07 13:59 UTC (permalink / raw) To: gcc-patches, Fortran List, Tobias Burnus, Catherine Moore, Jakub Jelinek [-- Attachment #1: Type: text/plain, Size: 1587 bytes --] Hi all, this patch add support for "strictly-structured blocks" introduced in OpenMP 5.1, basically allowing BLOCK constructs to serve as the body for directives: !$omp target block ... end block [!$omp end target] !! end directive is optional !$omp parallel block ... end block ... !$omp end parallel !! error, considered as not match to above parallel directive The parsing loop in parse_omp_structured_block() has been modified to allow a BLOCK construct after the first statement has been detected to be ST_BLOCK. This is done by a hard modification of the state into (the new) COMP_OMP_STRICTLY_STRUCTURED_BLOCK after the statement is known (I'm not sure if there's a way to 'peek' the next statement/token in the Fortran FE, open to suggestions on how to better write this) Tested with no regressions on trunk, is this okay to commit? Thanks, Chung-Lin 2021-10-07 Chung-Lin Tang <cltang@codesourcery.com> gcc/fortran/ChangeLog: * decl.c (gfc_match_end): Add COMP_OMP_STRICTLY_STRUCTURED_BLOCK case together with COMP_BLOCK. * parse.c (parse_omp_structured_block): Adjust declaration, add 'bool strictly_structured_block' default true parameter, add handling for strictly-structured block case, adjust recursive calls to parse_omp_structured_block. (parse_executable): Adjust calls to parse_omp_structured_block. * parse.h (enum gfc_compile_state): Add COMP_OMP_STRICTLY_STRUCTURED_BLOCK. * trans-openmp.c (gfc_trans_omp_workshare): Add EXEC_BLOCK case handling. gcc/testsuite/ChangeLog: * gfortran.dg/gomp/strictly-structured-block-1.f90: New test. [-- Attachment #2: fortran-omp51-strictly-structured-block.patch --] [-- Type: text/plain, Size: 11179 bytes --] diff --git a/gcc/fortran/decl.c b/gcc/fortran/decl.c index b3c65b7175b..ff66d1f9475 100644 --- a/gcc/fortran/decl.c +++ b/gcc/fortran/decl.c @@ -8445,6 +8445,7 @@ gfc_match_end (gfc_statement *st) break; case COMP_BLOCK: + case COMP_OMP_STRICTLY_STRUCTURED_BLOCK: *st = ST_END_BLOCK; target = " block"; eos_ok = 0; diff --git a/gcc/fortran/parse.c b/gcc/fortran/parse.c index 7d765a0866d..d78bf9b8fa5 100644 --- a/gcc/fortran/parse.c +++ b/gcc/fortran/parse.c @@ -5451,8 +5451,9 @@ parse_oacc_loop (gfc_statement acc_st) /* Parse the statements of an OpenMP structured block. */ -static void -parse_omp_structured_block (gfc_statement omp_st, bool workshare_stmts_only) +static gfc_statement +parse_omp_structured_block (gfc_statement omp_st, bool workshare_stmts_only, + bool strictly_structured_block = true) { gfc_statement st, omp_end_st; gfc_code *cp, *np; @@ -5538,6 +5539,32 @@ parse_omp_structured_block (gfc_statement omp_st, bool workshare_stmts_only) gcc_unreachable (); } + bool block_construct = false; + gfc_namespace* my_ns = NULL; + gfc_namespace* my_parent = NULL; + + st = next_statement (); + + if (strictly_structured_block && st == ST_BLOCK) + { + /* Adjust state to a strictly-structured block, now that we found that + the body starts with a BLOCK construct. */ + s.state = COMP_OMP_STRICTLY_STRUCTURED_BLOCK; + + block_construct = true; + gfc_notify_std (GFC_STD_F2008, "BLOCK construct at %C"); + + my_ns = gfc_build_block_ns (gfc_current_ns); + gfc_current_ns = my_ns; + my_parent = my_ns->parent; + + new_st.op = EXEC_BLOCK; + new_st.ext.block.ns = my_ns; + new_st.ext.block.assoc = NULL; + accept_statement (ST_BLOCK); + st = parse_spec (ST_NONE); + } + do { if (workshare_stmts_only) @@ -5554,7 +5581,6 @@ parse_omp_structured_block (gfc_statement omp_st, bool workshare_stmts_only) restrictions apply recursively. */ bool cycle = true; - st = next_statement (); for (;;) { switch (st) @@ -5576,17 +5602,20 @@ parse_omp_structured_block (gfc_statement omp_st, bool workshare_stmts_only) parse_forall_block (); break; + case ST_OMP_PARALLEL_SECTIONS: + st = parse_omp_structured_block (st, false, false); + continue; + case ST_OMP_PARALLEL: case ST_OMP_PARALLEL_MASKED: case ST_OMP_PARALLEL_MASTER: - case ST_OMP_PARALLEL_SECTIONS: - parse_omp_structured_block (st, false); - break; + st = parse_omp_structured_block (st, false); + continue; case ST_OMP_PARALLEL_WORKSHARE: case ST_OMP_CRITICAL: - parse_omp_structured_block (st, true); - break; + st = parse_omp_structured_block (st, true); + continue; case ST_OMP_PARALLEL_DO: case ST_OMP_PARALLEL_DO_SIMD: @@ -5609,7 +5638,7 @@ parse_omp_structured_block (gfc_statement omp_st, bool workshare_stmts_only) } } else - st = parse_executable (ST_NONE); + st = parse_executable (st); if (st == ST_NONE) unexpected_eof (); else if (st == ST_OMP_SECTION @@ -5619,9 +5648,27 @@ parse_omp_structured_block (gfc_statement omp_st, bool workshare_stmts_only) np = new_level (np); np->op = cp->op; np->block = NULL; + st = next_statement (); + } + else if (block_construct && st == ST_END_BLOCK) + { + accept_statement (st); + gfc_current_ns = my_parent; + pop_state (); + + st = next_statement (); + if (st == omp_end_st) + { + accept_statement (st); + st = next_statement (); + } + return st; } else if (st != omp_end_st) - unexpected_statement (st); + { + unexpected_statement (st); + st = next_statement (); + } } while (st != omp_end_st); @@ -5657,6 +5704,8 @@ parse_omp_structured_block (gfc_statement omp_st, bool workshare_stmts_only) gfc_commit_symbols (); gfc_warning_check (); pop_state (); + st = next_statement (); + return st; } @@ -5779,16 +5828,19 @@ parse_executable (gfc_statement st) parse_oacc_structured_block (st); break; + case ST_OMP_PARALLEL_SECTIONS: + case ST_OMP_SECTIONS: + st = parse_omp_structured_block (st, false, false); + continue; + case ST_OMP_PARALLEL: case ST_OMP_PARALLEL_MASKED: case ST_OMP_PARALLEL_MASTER: - case ST_OMP_PARALLEL_SECTIONS: case ST_OMP_ORDERED: case ST_OMP_CRITICAL: case ST_OMP_MASKED: case ST_OMP_MASTER: case ST_OMP_SCOPE: - case ST_OMP_SECTIONS: case ST_OMP_SINGLE: case ST_OMP_TARGET: case ST_OMP_TARGET_DATA: @@ -5797,13 +5849,13 @@ parse_executable (gfc_statement st) case ST_OMP_TEAMS: case ST_OMP_TASK: case ST_OMP_TASKGROUP: - parse_omp_structured_block (st, false); - break; + st = parse_omp_structured_block (st, false); + continue; case ST_OMP_WORKSHARE: case ST_OMP_PARALLEL_WORKSHARE: - parse_omp_structured_block (st, true); - break; + st = parse_omp_structured_block (st, true); + continue; case ST_OMP_DISTRIBUTE: case ST_OMP_DISTRIBUTE_PARALLEL_DO: diff --git a/gcc/fortran/parse.h b/gcc/fortran/parse.h index 55f02299304..66b275de89b 100644 --- a/gcc/fortran/parse.h +++ b/gcc/fortran/parse.h @@ -31,7 +31,7 @@ enum gfc_compile_state COMP_STRUCTURE, COMP_UNION, COMP_MAP, COMP_DO, COMP_SELECT, COMP_FORALL, COMP_WHERE, COMP_CONTAINS, COMP_ENUM, COMP_SELECT_TYPE, COMP_SELECT_RANK, COMP_OMP_STRUCTURED_BLOCK, COMP_CRITICAL, - COMP_DO_CONCURRENT + COMP_DO_CONCURRENT, COMP_OMP_STRICTLY_STRUCTURED_BLOCK }; /* Stack element for the current compilation state. These structures diff --git a/gcc/fortran/trans-openmp.c b/gcc/fortran/trans-openmp.c index d234d1b070f..9fdea8c67fd 100644 --- a/gcc/fortran/trans-openmp.c +++ b/gcc/fortran/trans-openmp.c @@ -6993,7 +6993,11 @@ gfc_trans_omp_workshare (gfc_code *code, gfc_omp_clauses *clauses) res = gfc_trans_omp_directive (code); ompws_flags = saved_ompws_flags; break; - + + case EXEC_BLOCK: + res = gfc_trans_block_construct (code); + break; + default: gfc_internal_error ("gfc_trans_omp_workshare(): Bad statement code"); } diff --git a/gcc/testsuite/gfortran.dg/gomp/strictly-structured-block-1.f90 b/gcc/testsuite/gfortran.dg/gomp/strictly-structured-block-1.f90 new file mode 100644 index 00000000000..bc798c1c218 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/gomp/strictly-structured-block-1.f90 @@ -0,0 +1,295 @@ +! { dg-do compile } +! { dg-options "-fopenmp" } + +program main + integer :: x + + !$omp parallel + block + x = x + 1 + end block + + !$omp parallel + block + x = x + 1 + end block + !$omp end parallel + + !$omp parallel + block + x = x + 1 + end block + x = x + 1 + !$omp end parallel ! { dg-error "Unexpected !.OMP END PARALLEL statement" } + + !$omp teams + block + x = x + 1 + end block + + !$omp teams + block + x = x + 1 + end block + !$omp end teams + + !$omp teams + block + x = x + 1 + end block + x = x + 1 + !$omp end teams ! { dg-error "Unexpected !.OMP END TEAMS statement" } + + !$omp masked + block + x = x + 1 + end block + + !$omp masked + block + x = x + 1 + end block + !$omp end masked + + !$omp masked + block + x = x + 1 + end block + x = x + 1 + !$omp end masked ! { dg-error "Unexpected !.OMP END MASKED statement" } + + !$omp scope + block + x = x + 1 + end block + + !$omp scope + block + x = x + 1 + end block + !$omp end scope + + !$omp scope + block + x = x + 1 + end block + x = x + 1 + !$omp end scope ! { dg-error "Unexpected !.OMP END SCOPE statement" } + + !$omp single + block + x = x + 1 + end block + + !$omp single + block + x = x + 1 + end block + !$omp end single + + !$omp single + block + x = x + 1 + end block + x = x + 1 + !$omp end single ! { dg-error "Unexpected !.OMP END SINGLE statement" } + + !$omp workshare + block + x = x + 1 + end block + + !$omp workshare + block + x = x + 1 + end block + !$omp end workshare + + !$omp workshare + block + x = x + 1 + end block + x = x + 1 + !$omp end workshare ! { dg-error "Unexpected !.OMP END WORKSHARE statement" } + + !$omp task + block + x = x + 1 + end block + + !$omp task + block + x = x + 1 + end block + !$omp end task + + !$omp task + block + x = x + 1 + end block + x = x + 1 + !$omp end task ! { dg-error "Unexpected !.OMP END TASK statement" } + + !$omp target data map(x) + block + x = x + 1 + end block + + !$omp target data map(x) + block + x = x + 1 + end block + !$omp end target data + + !$omp target data map(x) + block + x = x + 1 + end block + x = x + 1 + !$omp end target data ! { dg-error "Unexpected !.OMP END TARGET DATA statement" } + + !$omp target + block + x = x + 1 + end block + + !$omp target + block + x = x + 1 + end block + !$omp end target + + !$omp target + block + x = x + 1 + end block + x = x + 1 + !$omp end target ! { dg-error "Unexpected !.OMP END TARGET statement" } + + !$omp parallel workshare + block + x = x + 1 + end block + + !$omp parallel workshare + block + x = x + 1 + end block + !$omp end parallel workshare + + !$omp parallel workshare + block + x = x + 1 + end block + x = x + 1 + !$omp end parallel workshare ! { dg-error "Unexpected !.OMP END PARALLEL WORKSHARE statement" } + + !$omp parallel masked + block + x = x + 1 + end block + + !$omp parallel masked + block + x = x + 1 + end block + !$omp end parallel masked + + !$omp parallel masked + block + x = x + 1 + end block + x = x + 1 + !$omp end parallel masked ! { dg-error "Unexpected !.OMP END PARALLEL MASKED statement" } + + !$omp target parallel + block + x = x + 1 + end block + + !$omp target parallel + block + x = x + 1 + end block + !$omp end target parallel + + !$omp target parallel + block + x = x + 1 + end block + x = x + 1 + !$omp end target parallel ! { dg-error "Unexpected !.OMP END TARGET PARALLEL statement" } + + !$omp target teams + block + x = x + 1 + end block + + !$omp target teams + block + x = x + 1 + end block + !$omp end target teams + + !$omp target teams + block + x = x + 1 + end block + x = x + 1 + !$omp end target teams ! { dg-error "Unexpected !.OMP END TARGET TEAMS statement" } + + !$omp critical + block + x = x + 1 + end block + + !$omp critical + block + x = x + 1 + end block + !$omp end critical + + !$omp critical + block + x = x + 1 + end block + x = x + 1 + !$omp end critical ! { dg-error "Unexpected !.OMP END CRITICAL statement" } + + !$omp taskgroup + block + x = x + 1 + end block + + !$omp taskgroup + block + x = x + 1 + end block + !$omp end taskgroup + + !$omp taskgroup + block + x = x + 1 + end block + x = x + 1 + !$omp end taskgroup ! { dg-error "Unexpected !.OMP END TASKGROUP statement" } + + !$omp ordered + block + x = x + 1 + end block + + !$omp ordered + block + x = x + 1 + end block + !$omp end ordered + + !$omp ordered + block + x = x + 1 + end block + x = x + 1 + !$omp end ordered ! { dg-error "Unexpected !.OMP END ORDERED statement" } + +end program ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH, OpenMP 5.1, Fortran] Strictly-structured block support for OpenMP directives 2021-10-07 13:59 [PATCH, OpenMP 5.1, Fortran] Strictly-structured block support for OpenMP directives Chung-Lin Tang @ 2021-10-07 16:33 ` Tobias Burnus 2021-10-07 17:09 ` Jakub Jelinek 1 sibling, 0 replies; 12+ messages in thread From: Tobias Burnus @ 2021-10-07 16:33 UTC (permalink / raw) To: Chung-Lin Tang, gcc-patches, Fortran List, Catherine Moore, Jakub Jelinek Hi Chung-Lin, On 07.10.21 15:59, Chung-Lin Tang wrote: > this patch add support for "strictly-structured blocks" introduced in > OpenMP 5.1, > basically allowing BLOCK constructs to serve as the body for directives: > > !$omp target > block > ... > end block > [!$omp end target] !! end directive is optional Pre-remark: That OpenMP feature causes ambiguities. I have filled an OpenMP spec issue to discuss this, Issue 3154. Namely the following is unclear: !$omp parallel !$omp parallel block x= x+ 1 end block !$omp end parallel Does the 'end parallel' end the inner strictly structured block or the outer loosely structured block? In principle, a compiler could defer this until later during parsing, but this requires a tremendous state tracking and it is surely not simple to do in gfortran (and probably all other compilers). — Thus, I think the spec will change and probably in the way which this patch has implemented. NOTE: It takes the kind of directive into account, i.e. 'omp end target' vs. 'omp end parallel' aren't ambiguous. > The parsing loop in parse_omp_structured_block() has been modified to > allow > a BLOCK construct after the first statement has been detected to be > ST_BLOCK. > This is done by a hard modification of the state into (the new) > COMP_OMP_STRICTLY_STRUCTURED_BLOCK > after the statement is known (I'm not sure if there's a way to 'peek' > the next > statement/token in the Fortran FE, open to suggestions on how to > better write this) > > Tested with no regressions on trunk, is this okay to commit? LGTM – unless Jakub has further comments. However, I have two requests: First, can you include an update of the implementation status in libgomp/libgomp.texi (+ fix the ...ppp... typo): "@item Suppport of strictly structured blocks in Fortran @tab N @tab" Secondly, can you extend the testcase a bit to include nesting a BLOCK inside the other BLOCK – and nesting the directive with a strictly structured block inside another (different) directive to ensure that the 'omp end ...' is correctly matched. I mean something like: integer :: x !$omp target map(i) !$omp parallel block block x = x + 1 end block end block !$omp end target !$omp target map(i) !$omp parallel block block x = x + 1 end block end block !$omp end parallel !$omp end target end Thanks, Tobias > 2021-10-07 Chung-Lin Tang <cltang@codesourcery.com> > > gcc/fortran/ChangeLog: > > * decl.c (gfc_match_end): Add COMP_OMP_STRICTLY_STRUCTURED_BLOCK case > together with COMP_BLOCK. > * parse.c (parse_omp_structured_block): Adjust declaration, add > 'bool strictly_structured_block' default true parameter, add handling > for strictly-structured block case, adjust recursive calls to > parse_omp_structured_block. > (parse_executable): Adjust calls to parse_omp_structured_block. > * parse.h (enum gfc_compile_state): Add > COMP_OMP_STRICTLY_STRUCTURED_BLOCK. > * trans-openmp.c (gfc_trans_omp_workshare): Add EXEC_BLOCK case > handling. > > gcc/testsuite/ChangeLog: > > * gfortran.dg/gomp/strictly-structured-block-1.f90: New test. ----------------- Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201, 80634 München; Gesellschaft mit beschränkter Haftung; Geschäftsführer: Thomas Heurung, Frank Thürauf; Sitz der Gesellschaft: München; Registergericht München, HRB 106955 ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH, OpenMP 5.1, Fortran] Strictly-structured block support for OpenMP directives 2021-10-07 13:59 [PATCH, OpenMP 5.1, Fortran] Strictly-structured block support for OpenMP directives Chung-Lin Tang 2021-10-07 16:33 ` Tobias Burnus @ 2021-10-07 17:09 ` Jakub Jelinek 2021-10-08 16:14 ` [PATCH] openmp: Add support for OpenMP 5.1 structured-block-sequences Jakub Jelinek 2021-10-14 10:20 ` [PATCH, OpenMP 5.1, Fortran] Strictly-structured block support for OpenMP directives Jakub Jelinek 1 sibling, 2 replies; 12+ messages in thread From: Jakub Jelinek @ 2021-10-07 17:09 UTC (permalink / raw) To: Chung-Lin Tang; +Cc: gcc-patches, Fortran List, Tobias Burnus, Catherine Moore On Thu, Oct 07, 2021 at 09:59:00PM +0800, Chung-Lin Tang wrote: > this patch add support for "strictly-structured blocks" introduced in OpenMP 5.1, > basically allowing BLOCK constructs to serve as the body for directives: > > !$omp target > block > ... > end block > [!$omp end target] !! end directive is optional > > !$omp parallel > block > ... > end block > ... > !$omp end parallel !! error, considered as not match to above parallel directive > > The parsing loop in parse_omp_structured_block() has been modified to allow > a BLOCK construct after the first statement has been detected to be ST_BLOCK. > This is done by a hard modification of the state into (the new) COMP_OMP_STRICTLY_STRUCTURED_BLOCK > after the statement is known (I'm not sure if there's a way to 'peek' the next > statement/token in the Fortran FE, open to suggestions on how to better write this) Thanks for working on this. The workshare/parallel workshare case is unclear, I've filed https://github.com/OpenMP/spec/issues/3153 for it. Either don't allow block if workshare_stmts_only for now until that is clarified, or if we do, we need to make sure that it does the expected thing, does that gfc_trans_block_construct call ensure it? Then we have the https://github.com/OpenMP/spec/issues/3154 issue Tobias discovered, if that issue is resolved to end always applying to the directive before the block statement, I think your patch handles it that way but we want testsuite coverage for some of those cases. For the testcases, I think best would be to split it into two, one that contains only what we want to accept and another one with dg-errors in it. I don't think the patch does the right thing for sections/parallel sections. That is (at least in 5.1) defined as: !$omp sections clauses... [!$omp section] structured-block-sequence [!$omp section structured-block-sequence] ... !$omp end sections (and similarly for parallel sections). I believe your patch properly disallows: !$omp sections block ... !$omp section ... end block !$omp end sections - block itself is allowed, e.g. !$omp sections block a=1 b=2 end block !$omp end sections with the meaning that the block is after the first implied !$omp section and there is nothing else. But does the patch actually check that !$omp sections block ... end block c=1 !$omp end sections or !$omp sections !$omp section block ... end block c=1 !$omp section d=1 !$omp end sections is invalid? Though, not sure if that was the intended effect, in OpenMP 5.0 that used to be fine. But then the other changes are backwards incompatible too, !$omp parallel block ... end block c=1 !$omp end parallel used to be valid but no longer is. structured-block-sequence is fortran defined as structured-block and structured-block is defined as either loosely-structured-block or strictly-structured-block, so for sections in between each !$omp section should be either anything not starting with block, or, if it starts with block, after end block there should be immediately !$omp section or !$omp end {,parallel }sections. Another thing is scan, the wording is similar and newly !$omp do reduction(+,inscan:a) do i=1,10 block ... end block x=1 !$omp scan block ... end block x=2 end do is invalid. > @@ -5538,6 +5539,32 @@ parse_omp_structured_block (gfc_statement omp_st, bool workshare_stmts_only) > gcc_unreachable (); > } > > + bool block_construct = false; > + gfc_namespace* my_ns = NULL; > + gfc_namespace* my_parent = NULL; The usual coding conventions put * before variable name instead of after it (except for libstdc++). > --- /dev/null > +++ b/gcc/testsuite/gfortran.dg/gomp/strictly-structured-block-1.f90 > @@ -0,0 +1,295 @@ > +! { dg-do compile } > +! { dg-options "-fopenmp" } > + > +program main > + integer :: x > + > + !$omp parallel > + block > + x = x + 1 > + end block > + > + !$omp parallel > + block > + x = x + 1 > + end block > + !$omp end parallel > + > + !$omp parallel > + block > + x = x + 1 > + end block > + x = x + 1 > + !$omp end parallel ! { dg-error "Unexpected !.OMP END PARALLEL statement" } Other than the splitting into non-dg-error stuff in one testcase and dg-error in another one, I think we want (probably in yet another pair of testcases) test what we are not required to do but with your patch we actually implement, in particular that !$omp master behaves the same way. > + !$omp ordered > + block > + x = x + 1 > + end block > + > + !$omp ordered > + block > + x = x + 1 > + end block > + !$omp end ordered > + > + !$omp ordered > + block > + x = x + 1 > + end block > + x = x + 1 > + !$omp end ordered ! { dg-error "Unexpected !.OMP END ORDERED statement" } I believe these 3 can't be done in the program, would either need to be wrapped in some !$omp do with ordered clause or should go each ordered into its own orphaned subroutine, because ordered region must bind to a worksharing-loop with ordered clause. I think wrapping it inside of !$omp do ordered is easier. Jakub ^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH] openmp: Add support for OpenMP 5.1 structured-block-sequences 2021-10-07 17:09 ` Jakub Jelinek @ 2021-10-08 16:14 ` Jakub Jelinek 2021-10-14 10:20 ` [PATCH, OpenMP 5.1, Fortran] Strictly-structured block support for OpenMP directives Jakub Jelinek 1 sibling, 0 replies; 12+ messages in thread From: Jakub Jelinek @ 2021-10-08 16:14 UTC (permalink / raw) To: Chung-Lin Tang, Tobias Burnus, gcc-patches Hi! Related to this is the addition of structured-block-sequence in OpenMP 5.1, which doesn't change anything for Fortran, but for C/C++ allows multiple statements instead of just one possibly compound around the separating directives (section and scan). The following patch implements that, will commit to trunk if it passes bootstrap/regtest. I've also made some updates to the OpenMP 5.1 support list in libgomp.texi. 2021-10-08 Jakub Jelinek <jakub@redhat.com> gcc/c/ * c-parser.c (c_parser_omp_structured_block_sequence): New function. (c_parser_omp_scan_loop_body): Use it. (c_parser_omp_sections_scope): Likewise. gcc/cp/ * parser.c (cp_parser_omp_structured_block): Remove disallow_omp_attrs argument. (cp_parser_omp_structured_block_sequence): New function. (cp_parser_omp_scan_loop_body): Use it. (cp_parser_omp_sections_scope): Likewise. gcc/testsuite/ * c-c++-common/gomp/sections1.c (foo): Don't expect errors on multiple statements in between section directive(s). Add testcases for invalid no statements in between section directive(s). * gcc.dg/gomp/sections-2.c (foo): Don't expect errors on multiple statements in between section directive(s). * g++.dg/gomp/sections-2.C (foo): Likewise. * g++.dg/gomp/attrs-6.C (foo): Add testcases for multiple statements in between section directive(s). (bar): Add testcases for multiple statements in between scan directive. * g++.dg/gomp/attrs-7.C (bar): Adjust expected error recovery. libgomp/ * libgomp.texi (OpenMP 5.1): Mention implemented support for structured block sequences in C/C++. Mention support for unconstrained/reproducible modifiers on order clause. Mention partial (C/C++ only) support of extentensions to atomics construct. Mention partial (C/C++ on clause only) support of align/allocator modifiers on allocate clause. --- gcc/c/c-parser.c.jj 2021-10-07 12:52:34.923913144 +0200 +++ gcc/c/c-parser.c 2021-10-08 13:56:43.989987499 +0200 @@ -18976,6 +18976,31 @@ c_parser_omp_flush (c_parser *parser) c_finish_omp_flush (loc, mo); } +/* Parse an OpenMP structured block sequence. KIND is the corresponding + separating directive. */ + +static tree +c_parser_omp_structured_block_sequence (c_parser *parser, + enum pragma_kind kind) +{ + tree stmt = push_stmt_list (); + c_parser_statement (parser, NULL); + do + { + if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE)) + break; + if (c_parser_next_token_is (parser, CPP_EOF)) + break; + + if (kind != PRAGMA_NONE + && c_parser_peek_token (parser)->pragma_kind == kind) + break; + c_parser_statement (parser, NULL); + } + while (1); + return pop_stmt_list (stmt); +} + /* OpenMP 5.0: scan-loop-body: @@ -18997,7 +19022,7 @@ c_parser_omp_scan_loop_body (c_parser *p return; } - substmt = c_parser_omp_structured_block (parser, NULL); + substmt = c_parser_omp_structured_block_sequence (parser, PRAGMA_OMP_SCAN); substmt = build2 (OMP_SCAN, void_type_node, substmt, NULL_TREE); SET_EXPR_LOCATION (substmt, loc); add_stmt (substmt); @@ -19032,7 +19057,7 @@ c_parser_omp_scan_loop_body (c_parser *p error ("expected %<#pragma omp scan%>"); clauses = c_finish_omp_clauses (clauses, C_ORT_OMP); - substmt = c_parser_omp_structured_block (parser, NULL); + substmt = c_parser_omp_structured_block_sequence (parser, PRAGMA_NONE); substmt = build2 (OMP_SCAN, void_type_node, substmt, clauses); SET_EXPR_LOCATION (substmt, loc); add_stmt (substmt); @@ -19860,6 +19885,8 @@ c_parser_omp_ordered (c_parser *parser, section-directive[opt] structured-block section-sequence section-directive structured-block + OpenMP 5.1 allows structured-block-sequence instead of structured-block. + SECTIONS_LOC is the location of the #pragma omp sections. */ static tree @@ -19881,7 +19908,8 @@ c_parser_omp_sections_scope (location_t if (c_parser_peek_token (parser)->pragma_kind != PRAGMA_OMP_SECTION) { - substmt = c_parser_omp_structured_block (parser, NULL); + substmt = c_parser_omp_structured_block_sequence (parser, + PRAGMA_OMP_SECTION); substmt = build1 (OMP_SECTION, void_type_node, substmt); SET_EXPR_LOCATION (substmt, loc); add_stmt (substmt); @@ -19907,7 +19935,8 @@ c_parser_omp_sections_scope (location_t error_suppress = true; } - substmt = c_parser_omp_structured_block (parser, NULL); + substmt = c_parser_omp_structured_block_sequence (parser, + PRAGMA_OMP_SECTION); substmt = build1 (OMP_SECTION, void_type_node, substmt); SET_EXPR_LOCATION (substmt, loc); add_stmt (substmt); --- gcc/cp/parser.c.jj 2021-10-08 10:58:48.974436064 +0200 +++ gcc/cp/parser.c 2021-10-08 14:07:21.179102547 +0200 @@ -40136,14 +40136,12 @@ cp_parser_end_omp_structured_block (cp_p } static tree -cp_parser_omp_structured_block (cp_parser *parser, bool *if_p, - bool disallow_omp_attrs = true) +cp_parser_omp_structured_block (cp_parser *parser, bool *if_p) { tree stmt = begin_omp_structured_block (); unsigned int save = cp_parser_begin_omp_structured_block (parser); - if (disallow_omp_attrs) - parser->omp_attrs_forbidden_p = true; + parser->omp_attrs_forbidden_p = true; cp_parser_statement (parser, NULL_TREE, false, if_p); cp_parser_end_omp_structured_block (parser, save); @@ -42001,6 +41999,43 @@ cp_parser_omp_section_scan (cp_parser *p return true; } +/* Parse an OpenMP structured block sequence. KIND is the corresponding + separating directive. */ + +static tree +cp_parser_omp_structured_block_sequence (cp_parser *parser, + enum pragma_kind kind) +{ + tree stmt = begin_omp_structured_block (); + unsigned int save = cp_parser_begin_omp_structured_block (parser); + + cp_parser_statement (parser, NULL_TREE, false, NULL); + while (true) + { + cp_token *token = cp_lexer_peek_token (parser->lexer); + + if (token->type == CPP_CLOSE_BRACE + || token->type == CPP_EOF + || token->type == CPP_PRAGMA_EOL + || (token->type == CPP_KEYWORD && token->keyword == RID_AT_END) + || (kind != PRAGMA_NONE + && cp_parser_pragma_kind (token) == kind)) + break; + + if (kind != PRAGMA_NONE + && cp_parser_omp_section_scan (parser, + kind == PRAGMA_OMP_SCAN + ? "scan" : "section", false)) + break; + + cp_parser_statement (parser, NULL_TREE, false, NULL); + } + + cp_parser_end_omp_structured_block (parser, save); + return finish_omp_structured_block (stmt); +} + + /* OpenMP 5.0: scan-loop-body: @@ -42015,11 +42050,10 @@ cp_parser_omp_scan_loop_body (cp_parser if (!braces.require_open (parser)) return; - substmt = cp_parser_omp_structured_block (parser, NULL, false); + substmt = cp_parser_omp_structured_block_sequence (parser, PRAGMA_OMP_SCAN); substmt = build2 (OMP_SCAN, void_type_node, substmt, NULL_TREE); add_stmt (substmt); - cp_parser_omp_section_scan (parser, "scan", false); cp_token *tok = cp_lexer_peek_token (parser->lexer); if (cp_parser_pragma_kind (tok) == PRAGMA_OMP_SCAN) { @@ -42055,7 +42089,7 @@ cp_parser_omp_scan_loop_body (cp_parser error ("expected %<#pragma omp scan%>"); clauses = finish_omp_clauses (clauses, C_ORT_OMP); - substmt = cp_parser_omp_structured_block (parser, NULL, false); + substmt = cp_parser_omp_structured_block_sequence (parser, PRAGMA_NONE); substmt = build2_loc (tok->location, OMP_SCAN, void_type_node, substmt, clauses); add_stmt (substmt); @@ -42924,7 +42958,8 @@ cp_parser_omp_sections_scope (cp_parser != PRAGMA_OMP_SECTION && !cp_parser_omp_section_scan (parser, "section", true)) { - substmt = cp_parser_omp_structured_block (parser, NULL, false); + substmt = cp_parser_omp_structured_block_sequence (parser, + PRAGMA_OMP_SECTION); substmt = build1 (OMP_SECTION, void_type_node, substmt); add_stmt (substmt); } @@ -42951,7 +42986,8 @@ cp_parser_omp_sections_scope (cp_parser error_suppress = true; } - substmt = cp_parser_omp_structured_block (parser, NULL, false); + substmt = cp_parser_omp_structured_block_sequence (parser, + PRAGMA_OMP_SECTION); substmt = build1 (OMP_SECTION, void_type_node, substmt); add_stmt (substmt); } --- gcc/testsuite/c-c++-common/gomp/sections1.c.jj 2020-01-12 11:54:37.016404311 +0100 +++ gcc/testsuite/c-c++-common/gomp/sections1.c 2021-10-08 16:10:27.711160436 +0200 @@ -50,7 +50,7 @@ foo () #pragma omp sections { bar (12); - bar (13); /* { dg-error "pragma omp section" } */ + bar (13); #pragma omp section bar (14); } @@ -63,11 +63,29 @@ foo () bar (15); #pragma omp section bar (16); - bar (17); /* { dg-error "pragma omp section" } */ + bar (17); } #pragma omp sections { bar (18); #pragma omp section } /* { dg-error "expression before" } */ + #pragma omp sections + { + #pragma omp section + #pragma omp section /* { dg-error "may only be used in" } */ + bar (19); + } + #pragma omp sections + { + bar (20); + #pragma omp section + #pragma omp section /* { dg-error "may only be used in" } */ + bar (21); + } + #pragma omp sections + { + bar (22); + #pragma omp section + } /* { dg-error "expression before" } */ } --- gcc/testsuite/gcc.dg/gomp/sections-2.c.jj 2020-01-11 16:31:55.148291802 +0100 +++ gcc/testsuite/gcc.dg/gomp/sections-2.c 2021-10-08 14:21:41.218108482 +0200 @@ -19,11 +19,11 @@ void foo(void) { #pragma omp section bar(2); - bar(3); // { dg-error "expected" } + bar(3); bar(4); #pragma omp section bar(5); - bar(6); // { dg-error "expected" } + bar(6); bar(7); } } --- gcc/testsuite/g++.dg/gomp/sections-2.C.jj 2020-01-11 16:31:54.712298338 +0100 +++ gcc/testsuite/g++.dg/gomp/sections-2.C 2021-10-08 14:45:36.474085819 +0200 @@ -19,11 +19,11 @@ void foo(void) { #pragma omp section bar(2); - bar(3); // { dg-error "expected" } + bar(3); bar(4); #pragma omp section bar(5); - bar(6); // { dg-error "expected" } + bar(6); bar(7); } } --- gcc/testsuite/g++.dg/gomp/attrs-6.C.jj 2021-07-27 09:47:44.222778645 +0200 +++ gcc/testsuite/g++.dg/gomp/attrs-6.C 2021-10-08 16:07:32.030598778 +0200 @@ -26,6 +26,41 @@ foo () #pragma omp section { a[3]++; } } + #pragma omp parallel sections + { + #pragma omp section + a[0]++; + a[4]++; + l1: a[5]++; + if (a[5] == 42) goto l1; + [[omp::directive (section)]] { + a[1]++; + a[6]++; + } [[omp::directive (section)]] + a[2]++; + a[7]++; + #pragma omp section + { a[3]++; } + a[8]++; + } + [[omp::directive (parallel sections)]] + { + #pragma omp section + a[0]++; + a[4]++; + [[omp::directive (section)]] { + a[1]++; + a[5]++; + } [[omp::directive (section)]] + a[2]++; + l2: a[6]++; + if (a[6] == 42) + goto l2; + a[7]++; + #pragma omp section + a[8]++; + { a[3]++; } + } } int @@ -46,5 +81,23 @@ bar (int a, int *c, int *d, int *e, int #pragma omp scan inclusive (a) d[i] = a; } + #pragma omp simd reduction (inscan, +: a) + for (i = 0; i < 64; i++) + { + int t = a; + d[i] = t; + [[omp::directive (scan, exclusive (a))]] + int u = c[i]; + a += u; + } + [[omp::directive (simd reduction (inscan, +: a))]] + for (i = 0; i < 64; i++) + { + int t = c[i]; + a += t; + #pragma omp scan inclusive (a) + int u = a; + d[i] = u; + } return a; } --- gcc/testsuite/g++.dg/gomp/attrs-7.C.jj 2021-08-19 11:42:27.432421468 +0200 +++ gcc/testsuite/g++.dg/gomp/attrs-7.C 2021-10-08 17:31:48.432307745 +0200 @@ -29,29 +29,33 @@ bar (int a, int *c, int *d, int *e, int { d[i] = a; [[omp::sequence (omp::directive (parallel), omp::directive (scan, exclusive (a)))]] // { dg-error "must be the only specified attribute on a statement" } - a += c[i]; // { dg-error "#pragma omp scan" "" { target *-*-* } .-1 } - } + // { dg-error "#pragma omp scan" "" { target *-*-* } .-1 } + a += c[i]; // { dg-error "expected" } + } // { dg-error "expected" } [[omp::directive (parallel for reduction (inscan, +: a))]] // { dg-error "'a' specified in 'inscan' 'reduction' clause but not in 'scan' directive clause" } for (i = 0; i < 64; i++) { a += c[i]; [[omp::sequence (directive (scan inclusive (a)), directive (critical))]] // { dg-error "must be the only specified attribute on a statement" } - d[i] = a; // { dg-error "#pragma omp scan" "" { target *-*-* } .-1 } - } + // { dg-error "#pragma omp scan" "" { target *-*-* } .-1 } + d[i] = a; // { dg-error "expected" } + } // { dg-error "expected" } [[omp::directive (parallel for reduction (inscan, +: a))]] // { dg-error "'a' specified in 'inscan' 'reduction' clause but not in 'scan' directive clause" } for (i = 0; i < 64; i++) { d[i] = a; [[gnu::cold]] [[omp::directive (scan, exclusive (a))]] // { dg-error "must be the only specified attribute on a statement" } - a += c[i]; // { dg-error "#pragma omp scan" "" { target *-*-* } .-1 } - } + // { dg-error "#pragma omp scan" "" { target *-*-* } .-1 } + a += c[i]; // { dg-error "expected" } + } // { dg-error "expected" } [[omp::directive (parallel for reduction (inscan, +: a))]] // { dg-error "'a' specified in 'inscan' 'reduction' clause but not in 'scan' directive clause" } for (i = 0; i < 64; i++) { d[i] = a; [[omp::directive (scan, exclusive (a)), gnu::cold]] // { dg-error "must be the only specified attribute on a statement" } - a += c[i]; // { dg-error "#pragma omp scan" "" { target *-*-* } .-1 } - } + // { dg-error "#pragma omp scan" "" { target *-*-* } .-1 } + a += c[i]; // { dg-error "expected" } + } // { dg-error "expected" } [[omp::directive (parallel for reduction (inscan, +: a))]] // { dg-error "'a' specified in 'inscan' 'reduction' clause but not in 'scan' directive clause" } for (i = 0; i < 64; i++) { --- libgomp/libgomp.texi.jj 2021-09-30 17:12:15.238586878 +0200 +++ libgomp/libgomp.texi 2021-10-08 17:46:36.021964258 +0200 @@ -291,7 +291,7 @@ The OpenMP 4.5 specification is fully su @item @code{strict} modifier in the @code{grainsize} and @code{num_tasks} clauses of the taskloop construct @tab Y @tab @item @code{align} clause/modifier in @code{allocate} directive/clause - and @code{allocator} directive @tab N @tab + and @code{allocator} directive @tab P @tab C/C++ on clause only @item @code{thread_limit} clause to @code{target} construct @tab N @tab @item @code{has_device_addr} clause to @code{target} construct @tab N @tab @item iterators in @code{target update} motion clauses and @code{map} @@ -301,7 +301,7 @@ The OpenMP 4.5 specification is fully su @item @code{interop} directive @tab N @tab @item @code{omp_interop_t} object support in runtime routines @tab N @tab @item @code{nowait} clause in @code{taskwait} directive @tab N @tab -@item Extensions to the @code{atomic} directive @tab N @tab +@item Extensions to the @code{atomic} directive @tab P @tab C/C++ only @item @code{seq_cst} clause on a @code{flush} construct @tab Y @tab @item @code{inoutset} argument to the @code{depend} clause @tab N @tab @item @code{private} and @code{firstprivate} argument to @code{default} @@ -337,7 +337,10 @@ The OpenMP 4.5 specification is fully su @multitable @columnfractions .60 .10 .25 @headitem Description @tab Status @tab Comments -@item Suppport of strictly structured blocks in Fortran @tab N @tab +@item Support of strictly structured blocks in Fortran @tab N @tab +@item Support of structured block sequences in C/C++ @tab Y @tab +@item @code{unconstrained} and @code{reproducible} modifiers on @code{order} + clause @tab Y @tab @end multitable Jakub ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH, OpenMP 5.1, Fortran] Strictly-structured block support for OpenMP directives 2021-10-07 17:09 ` Jakub Jelinek 2021-10-08 16:14 ` [PATCH] openmp: Add support for OpenMP 5.1 structured-block-sequences Jakub Jelinek @ 2021-10-14 10:20 ` Jakub Jelinek 2021-10-14 11:19 ` Jakub Jelinek 1 sibling, 1 reply; 12+ messages in thread From: Jakub Jelinek @ 2021-10-14 10:20 UTC (permalink / raw) To: Chung-Lin Tang; +Cc: gcc-patches, Fortran List, Tobias Burnus, Catherine Moore On Thu, Oct 07, 2021 at 07:09:07PM +0200, Jakub Jelinek wrote: > The workshare/parallel workshare case is unclear, I've filed > https://github.com/OpenMP/spec/issues/3153 > for it. Either don't allow block if workshare_stmts_only for now > until that is clarified, or if we do, we need to make sure that it does the > expected thing, does that gfc_trans_block_construct call ensure it? > > Then we have the > https://github.com/OpenMP/spec/issues/3154 > issue Tobias discovered, if that issue is resolved to end always applying to > the directive before the block statement, I think your patch handles it that > way but we want testsuite coverage for some of those cases. Just want to follow-up on this, we now have resolutions of the https://github.com/OpenMP/spec/issues/3153 https://github.com/OpenMP/spec/issues/3154 https://github.com/OpenMP/spec/issues/3155 issues and we can use that to guide this patch. BLOCK is now explicitly allowed for workshare around the body of workshare/parallel workshare or around the body of critical in it but not arbitrarily nested. My understanding of the patch is that it most likely implements that, just we need a testsuite coverage that !$omp workshare block a = 1 b = 2 !$omp critical block c = 3 end block end block is fine (also with !$omp end {criticial,workshare} after the block), but that !$omp workshare a = 1 block b = 2 c = 3 end block !$omp end workshare etc. is diagnosed. For Tobias' issue that !$omp end whatever after end block for strictly structured block binds to the directive above the strictly structured block I think the patch also implements it but we want again testsuite coverage, that subroutine foo !$omp parallel !$omp parallel block end block !$omp end parallel !$omp end parallel end subroutine foo subroutine bar !$omp teams !$omp parallel block end block !$omp end teams end subroutine bar is fine while e.g. subroutine baz !$omp parallel !$omp parallel block end block !$omp end parallel end subroutine baz is not (!$omp end parallel pairs with the inner parallel rather than outer, and the outer parallel's body doesn't start with BLOCK, so needs to be paired with its !$omp end parallel). And lastly, the 3rd ticket clarifies that for the separating directives for Fortran basically the 5.0 state remains except that the body can be now also optionally wrapped in a single BLOCK. (And for C/C++ allows no statements at all in between the separating directives or after/before them but still requires the {}s around it like 5.1 and earlier. Here we implement the 5.1 wording and let's stay with that.) Thinking more about the Fortran case for !$omp sections, there is an ambiguity. !$omp sections block !$omp section end block is clear and !$omp end sections is optional, but !$omp sections block end block is ambiguous during parsing, it could be either followed by !$omp section and then the BLOCK would be first section, or by !$omp end sections and then it would be clearly the whole sections, with first section being empty inside of the block, or if it is followed by something else, it is ambiguous whether the block ... end block is part of the first section, followed by something and then we should be looking later for either !$omp section or !$omp end section to prove that, or if !$omp sections block end block was the whole sections construct and we shouldn't await anything further. I'm afraid back to the drawing board. Jakub ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH, OpenMP 5.1, Fortran] Strictly-structured block support for OpenMP directives 2021-10-14 10:20 ` [PATCH, OpenMP 5.1, Fortran] Strictly-structured block support for OpenMP directives Jakub Jelinek @ 2021-10-14 11:19 ` Jakub Jelinek 2021-10-15 18:44 ` Chung-Lin Tang 0 siblings, 1 reply; 12+ messages in thread From: Jakub Jelinek @ 2021-10-14 11:19 UTC (permalink / raw) To: Chung-Lin Tang, Tobias Burnus, gcc-patches, Fortran List On Thu, Oct 14, 2021 at 12:20:51PM +0200, Jakub Jelinek via Gcc-patches wrote: > Thinking more about the Fortran case for !$omp sections, there is an > ambiguity. > !$omp sections > block > !$omp section > end block > is clear and !$omp end sections is optional, but > !$omp sections > block > end block > is ambiguous during parsing, it could be either followed by !$omp section > and then the BLOCK would be first section, or by !$omp end sections and then > it would be clearly the whole sections, with first section being empty > inside of the block, or if it is followed by something else, it is > ambiguous whether the block ... end block is part of the first section, > followed by something and then we should be looking later for either > !$omp section or !$omp end section to prove that, or if > !$omp sections > block > end block > was the whole sections construct and we shouldn't await anything further. > I'm afraid back to the drawing board. And I have to correct myself, there is no ambiguity in 5.2 here, the important fact is hidden in sections/parallel sections being block-associated constructs. That means the body of the whole construct has to be a structured-block, and by the 5.1+ definition of Fortran structured block, it is either block ... end block or something that doesn't start with block. So, !$omp sections block end block a = 1 is only ambiguous in whether it is actually !$omp sections block !$omp section end block a = 1 or !$omp sections !$omp section block end block !$omp end sections a = 1 but both actually do the same thing, work roughly as !$omp single. If one wants block statement as first in structured-block-sequence of the first section, followed by either some further statements or by other sections, then one needs to write !$omp sections !$omp section block end block a = 1 ... !$omp end sections or !$omp sections block block end block a = 1 ... end block Your patch probably already handles it that way, but we again need testsuite coverage to prove it is handled the way it should in all these cases (and that we diagnose what is invalid). Jakub ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH, OpenMP 5.1, Fortran] Strictly-structured block support for OpenMP directives 2021-10-14 11:19 ` Jakub Jelinek @ 2021-10-15 18:44 ` Chung-Lin Tang 2021-10-15 19:02 ` Jakub Jelinek 0 siblings, 1 reply; 12+ messages in thread From: Chung-Lin Tang @ 2021-10-15 18:44 UTC (permalink / raw) To: Jakub Jelinek, Tobias Burnus, gcc-patches, Fortran List On 2021/10/14 7:19 PM, Jakub Jelinek wrote: > On Thu, Oct 14, 2021 at 12:20:51PM +0200, Jakub Jelinek via Gcc-patches wrote: >> Thinking more about the Fortran case for !$omp sections, there is an >> ambiguity. >> !$omp sections >> block >> !$omp section >> end block >> is clear and !$omp end sections is optional, but >> !$omp sections >> block >> end block >> is ambiguous during parsing, it could be either followed by !$omp section >> and then the BLOCK would be first section, or by !$omp end sections and then >> it would be clearly the whole sections, with first section being empty >> inside of the block, or if it is followed by something else, it is >> ambiguous whether the block ... end block is part of the first section, >> followed by something and then we should be looking later for either >> !$omp section or !$omp end section to prove that, or if >> !$omp sections >> block >> end block >> was the whole sections construct and we shouldn't await anything further. >> I'm afraid back to the drawing board. > > And I have to correct myself, there is no ambiguity in 5.2 here, > the important fact is hidden in sections/parallel sections being > block-associated constructs. That means the body of the whole construct > has to be a structured-block, and by the 5.1+ definition of Fortran > structured block, it is either block ... end block or something that > doesn't start with block. > So, > !$omp sections > block > end block > a = 1 > is only ambiguous in whether it is actually > !$omp sections > block > !$omp section > end block > a = 1 > or > !$omp sections > !$omp section > block > end block > !$omp end sections > a = 1 > but both actually do the same thing, work roughly as !$omp single. > If one wants block statement as first in structured-block-sequence > of the first section, followed by either some further statements > or by other sections, then one needs to write > !$omp sections > !$omp section > block > end block > a = 1 > ... > !$omp end sections > or > !$omp sections > block > block > end block > a = 1 > ... > end block > > Your patch probably already handles it that way, but we again need > testsuite coverage to prove it is handled the way it should in all these > cases (and that we diagnose what is invalid). The patch currently does not allow strictly-structured BLOCK for sections/parallel sections, since I was referencing the 5.1 spec while writing it, although that is trivially fixable. (was sensing a bit odd why those two constructs had to be specially treated in 5.1 anyways) The bigger issue is that under the current way the patch is written, the statements inside a [parallel] sections construct are parsed automatically by parse_executable(), so to enforce the specified meaning of "structured-block-sequence" (i.e. BLOCK or non-BLOCK starting sequence of stmts) will probably be more a bit harder to implement: !$omp sections block !$omp section block x=0 end block x=1 !! This is allowed now, though should be wrong spec-wise !$omp section x=2 end block Currently "$!omp section" acts essentially as a top-level separator within a sections-construct, rather than a structured directive. Though I would kind of argue this is actually better to use for the user (why prohibit what looks like very apparent meaning of the program?) So Jakub, my question for this is, is this current state okay? Or must we implement the spec pedantically? As for the other issues: (1) BLOCK/END BLOCK is not generally handled in parse_omp_structured_block, so for workshare, it is only handled for the top-level construct, not within workshare. I think this is what you meant in the last mail. (2) As for the dangling-!$omp_end issue Tobias raised, because we are basically using 1-statement lookahead, any "!$omp end <*>" is naturally bound with the adjacent BLOCK/END BLOCK, so we should be okay there. Thanks, Chung-Lin ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH, OpenMP 5.1, Fortran] Strictly-structured block support for OpenMP directives 2021-10-15 18:44 ` Chung-Lin Tang @ 2021-10-15 19:02 ` Jakub Jelinek 2021-10-20 12:30 ` [PATCH, v2, OpenMP 5.2, " Chung-Lin Tang 0 siblings, 1 reply; 12+ messages in thread From: Jakub Jelinek @ 2021-10-15 19:02 UTC (permalink / raw) To: Chung-Lin Tang; +Cc: Tobias Burnus, gcc-patches, Fortran List On Sat, Oct 16, 2021 at 02:44:12AM +0800, Chung-Lin Tang wrote: > The patch currently does not allow strictly-structured BLOCK for sections/parallel sections, > since I was referencing the 5.1 spec while writing it, although that is trivially fixable. > (was sensing a bit odd why those two constructs had to be specially treated in 5.1 anyways) > > The bigger issue is that under the current way the patch is written, the statements inside > a [parallel] sections construct are parsed automatically by parse_executable(), so to enforce > the specified meaning of "structured-block-sequence" (i.e. BLOCK or non-BLOCK starting sequence of stmts) > will probably be more a bit harder to implement: > > !$omp sections > block > !$omp section > block > x=0 > end block > x=1 !! This is allowed now, though should be wrong spec-wise > !$omp section > x=2 > end block > > Currently "$!omp section" acts essentially as a top-level separator within a sections-construct, > rather than a structured directive. Though I would kind of argue this is actually better to use for the > user (why prohibit what looks like very apparent meaning of the program?) > > So Jakub, my question for this is, is this current state okay? Or must we implement the spec pedantically? I'd certainly not implement 5.1 pedantically when we know we'd change one way for 5.0 -> 5.1 and change it back again for 5.1 -> 5.2. An example of that is !$omp sections !$omp section block end block x = 1 !$end omp sections This is valid in 5.0 and will be valid again in 5.2 with the same meaning, so let's just use the 5.0/5.2 wording here. Ditto the !$omp end ambiguity Tobias raised etc. Whether to add support for the 5.2 behavior when one sees !$omp {,parallel }sections block or not is more tough question, I bet the answer should be what is easier to implement right now (i.e. don't spend too much effort on hard 5.1 implementation if 5.2 would be easier, as eventually we'd need to do the 5.2 implementation afterwards anyway). So, for block right after sections either we implement the 5.2 wording right away and therefore look for !$omp section only within that block and not outside of it, or we for the 1st section with omitted !$omp section before it only implement the 5.1 pedantic behavior, i.e. if it starts with a block, don't look for !$omp section in the block, but require either !$omp section or !$omp end sections right after the corresponding end block. Does this answer all questions? Jakub ^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH, v2, OpenMP 5.2, Fortran] Strictly-structured block support for OpenMP directives 2021-10-15 19:02 ` Jakub Jelinek @ 2021-10-20 12:30 ` Chung-Lin Tang 2021-10-20 16:15 ` Jakub Jelinek 0 siblings, 1 reply; 12+ messages in thread From: Chung-Lin Tang @ 2021-10-20 12:30 UTC (permalink / raw) To: Jakub Jelinek; +Cc: Tobias Burnus, gcc-patches, Fortran List, Catherine Moore [-- Attachment #1: Type: text/plain, Size: 1802 bytes --] Hi Jakub, this version adjusts the patch to let sections/parallel sections also use strictly-structured blocks, making it more towards 5.2. Because of this change, some of the testcases using the sections-construct need a bit of adjustment too, since "block; end block" at the start of the construct now means something different than before. There are now three new testcases, with the non-dg-error/dg-error cases separated, and a third testcase containing a few cases listed in prior emails. I hope this is enough. The implementation status entry in libgomp/libgomp.texi for strictly-structured blocks has also been changed to "Y" in this patch. Tested without regressions, is this now okay for trunk? Thanks, Chung-Lin 2021-10-20 Chung-Lin Tang <cltang@codesourcery.com> gcc/fortran/ChangeLog: * decl.c (gfc_match_end): Add COMP_OMP_STRICTLY_STRUCTURED_BLOCK case together with COMP_BLOCK. * parse.c (parse_omp_structured_block): Change return type to 'gfc_statement', add handling for strictly-structured block case, adjust recursive calls to parse_omp_structured_block. (parse_executable): Adjust calls to parse_omp_structured_block. * parse.h (enum gfc_compile_state): Add COMP_OMP_STRICTLY_STRUCTURED_BLOCK. * trans-openmp.c (gfc_trans_omp_workshare): Add EXEC_BLOCK case handling. gcc/testsuite/ChangeLog: * gfortran.dg/gomp/cancel-1.f90: Adjust testcase. * gfortran.dg/gomp/nesting-3.f90: Adjust testcase. * gfortran.dg/gomp/strictly-structured-block-1.f90: New test. * gfortran.dg/gomp/strictly-structured-block-2.f90: New test. * gfortran.dg/gomp/strictly-structured-block-3.f90: New test. libgomp/ChangeLog: * libgomp.texi (Support of strictly structured blocks in Fortran): Adjust to 'Y'. * testsuite/libgomp.fortran/task-reduction-16.f90: Adjust testcase. [-- Attachment #2: omp52-fortran-strictblocks-v2.patch --] [-- Type: text/plain, Size: 17406 bytes --] diff --git a/gcc/fortran/decl.c b/gcc/fortran/decl.c index d6a22d13451..66489da12be 100644 --- a/gcc/fortran/decl.c +++ b/gcc/fortran/decl.c @@ -8449,6 +8449,7 @@ gfc_match_end (gfc_statement *st) break; case COMP_BLOCK: + case COMP_OMP_STRICTLY_STRUCTURED_BLOCK: *st = ST_END_BLOCK; target = " block"; eos_ok = 0; diff --git a/gcc/fortran/parse.c b/gcc/fortran/parse.c index 7d765a0866d..2fb98844356 100644 --- a/gcc/fortran/parse.c +++ b/gcc/fortran/parse.c @@ -5451,7 +5451,7 @@ parse_oacc_loop (gfc_statement acc_st) /* Parse the statements of an OpenMP structured block. */ -static void +static gfc_statement parse_omp_structured_block (gfc_statement omp_st, bool workshare_stmts_only) { gfc_statement st, omp_end_st; @@ -5538,6 +5538,32 @@ parse_omp_structured_block (gfc_statement omp_st, bool workshare_stmts_only) gcc_unreachable (); } + bool block_construct = false; + gfc_namespace *my_ns = NULL; + gfc_namespace *my_parent = NULL; + + st = next_statement (); + + if (st == ST_BLOCK) + { + /* Adjust state to a strictly-structured block, now that we found that + the body starts with a BLOCK construct. */ + s.state = COMP_OMP_STRICTLY_STRUCTURED_BLOCK; + + block_construct = true; + gfc_notify_std (GFC_STD_F2008, "BLOCK construct at %C"); + + my_ns = gfc_build_block_ns (gfc_current_ns); + gfc_current_ns = my_ns; + my_parent = my_ns->parent; + + new_st.op = EXEC_BLOCK; + new_st.ext.block.ns = my_ns; + new_st.ext.block.assoc = NULL; + accept_statement (ST_BLOCK); + st = parse_spec (ST_NONE); + } + do { if (workshare_stmts_only) @@ -5554,7 +5580,6 @@ parse_omp_structured_block (gfc_statement omp_st, bool workshare_stmts_only) restrictions apply recursively. */ bool cycle = true; - st = next_statement (); for (;;) { switch (st) @@ -5580,13 +5605,13 @@ parse_omp_structured_block (gfc_statement omp_st, bool workshare_stmts_only) case ST_OMP_PARALLEL_MASKED: case ST_OMP_PARALLEL_MASTER: case ST_OMP_PARALLEL_SECTIONS: - parse_omp_structured_block (st, false); - break; + st = parse_omp_structured_block (st, false); + continue; case ST_OMP_PARALLEL_WORKSHARE: case ST_OMP_CRITICAL: - parse_omp_structured_block (st, true); - break; + st = parse_omp_structured_block (st, true); + continue; case ST_OMP_PARALLEL_DO: case ST_OMP_PARALLEL_DO_SIMD: @@ -5609,7 +5634,7 @@ parse_omp_structured_block (gfc_statement omp_st, bool workshare_stmts_only) } } else - st = parse_executable (ST_NONE); + st = parse_executable (st); if (st == ST_NONE) unexpected_eof (); else if (st == ST_OMP_SECTION @@ -5619,9 +5644,27 @@ parse_omp_structured_block (gfc_statement omp_st, bool workshare_stmts_only) np = new_level (np); np->op = cp->op; np->block = NULL; + st = next_statement (); + } + else if (block_construct && st == ST_END_BLOCK) + { + accept_statement (st); + gfc_current_ns = my_parent; + pop_state (); + + st = next_statement (); + if (st == omp_end_st) + { + accept_statement (st); + st = next_statement (); + } + return st; } else if (st != omp_end_st) - unexpected_statement (st); + { + unexpected_statement (st); + st = next_statement (); + } } while (st != omp_end_st); @@ -5657,6 +5700,8 @@ parse_omp_structured_block (gfc_statement omp_st, bool workshare_stmts_only) gfc_commit_symbols (); gfc_warning_check (); pop_state (); + st = next_statement (); + return st; } @@ -5797,13 +5842,13 @@ parse_executable (gfc_statement st) case ST_OMP_TEAMS: case ST_OMP_TASK: case ST_OMP_TASKGROUP: - parse_omp_structured_block (st, false); - break; + st = parse_omp_structured_block (st, false); + continue; case ST_OMP_WORKSHARE: case ST_OMP_PARALLEL_WORKSHARE: - parse_omp_structured_block (st, true); - break; + st = parse_omp_structured_block (st, true); + continue; case ST_OMP_DISTRIBUTE: case ST_OMP_DISTRIBUTE_PARALLEL_DO: diff --git a/gcc/fortran/parse.h b/gcc/fortran/parse.h index 55f02299304..66b275de89b 100644 --- a/gcc/fortran/parse.h +++ b/gcc/fortran/parse.h @@ -31,7 +31,7 @@ enum gfc_compile_state COMP_STRUCTURE, COMP_UNION, COMP_MAP, COMP_DO, COMP_SELECT, COMP_FORALL, COMP_WHERE, COMP_CONTAINS, COMP_ENUM, COMP_SELECT_TYPE, COMP_SELECT_RANK, COMP_OMP_STRUCTURED_BLOCK, COMP_CRITICAL, - COMP_DO_CONCURRENT + COMP_DO_CONCURRENT, COMP_OMP_STRICTLY_STRUCTURED_BLOCK }; /* Stack element for the current compilation state. These structures diff --git a/gcc/fortran/trans-openmp.c b/gcc/fortran/trans-openmp.c index d234d1b070f..9fdea8c67fd 100644 --- a/gcc/fortran/trans-openmp.c +++ b/gcc/fortran/trans-openmp.c @@ -6993,7 +6993,11 @@ gfc_trans_omp_workshare (gfc_code *code, gfc_omp_clauses *clauses) res = gfc_trans_omp_directive (code); ompws_flags = saved_ompws_flags; break; - + + case EXEC_BLOCK: + res = gfc_trans_block_construct (code); + break; + default: gfc_internal_error ("gfc_trans_omp_workshare(): Bad statement code"); } diff --git a/gcc/testsuite/gfortran.dg/gomp/cancel-1.f90 b/gcc/testsuite/gfortran.dg/gomp/cancel-1.f90 index d60dd72bd4c..1bfddc7b9db 100644 --- a/gcc/testsuite/gfortran.dg/gomp/cancel-1.f90 +++ b/gcc/testsuite/gfortran.dg/gomp/cancel-1.f90 @@ -265,6 +265,7 @@ subroutine f2 end do !$omp end do !$omp sections + !$omp section block !$omp cancel parallel ! { dg-error "not closely nested inside" } !$omp cancel do ! { dg-error "not closely nested inside" } @@ -417,6 +418,7 @@ subroutine f2 !$omp end ordered end do !$omp sections + !$omp section block !$omp cancel parallel ! { dg-error "not closely nested inside" } !$omp cancel do ! { dg-error "not closely nested inside" } @@ -515,6 +517,7 @@ subroutine f3 end do !$omp end do nowait !$omp sections + !$omp section block !$omp cancel sections ! { dg-warning "nowait" } end block diff --git a/gcc/testsuite/gfortran.dg/gomp/nesting-3.f90 b/gcc/testsuite/gfortran.dg/gomp/nesting-3.f90 index cd2e39ae082..6422185a0f7 100644 --- a/gcc/testsuite/gfortran.dg/gomp/nesting-3.f90 +++ b/gcc/testsuite/gfortran.dg/gomp/nesting-3.f90 @@ -1,5 +1,5 @@ subroutine f1 - integer i, j + integer i, j, x !$omp do do i = 0, 2 !$omp do ! { dg-error "may not be closely nested" } @@ -7,7 +7,7 @@ subroutine f1 block; end block end do !$omp sections ! { dg-error "may not be closely nested" } - block; end block + x = j !$omp section block; end block !$omp end sections @@ -33,7 +33,7 @@ subroutine f1 !$omp end sections !$omp sections !$omp sections ! { dg-error "may not be closely nested" } - block; end block + x = i !$omp section block; end block !$omp end sections @@ -72,7 +72,7 @@ subroutine f1 !$omp sections !$omp section !$omp sections ! { dg-error "may not be closely nested" } - block; end block + x = i !$omp section block; end block !$omp end sections @@ -105,7 +105,7 @@ subroutine f1 block; end block end do !$omp sections ! { dg-error "may not be closely nested" } - block; end block + x = i !$omp section block; end block !$omp end sections @@ -129,7 +129,7 @@ subroutine f1 block; end block end do !$omp sections ! { dg-error "may not be closely nested" } - block; end block + x = i !$omp section block; end block !$omp end sections @@ -150,7 +150,7 @@ subroutine f1 block; end block end do !$omp sections ! { dg-error "may not be closely nested" } - block; end block + x = i !$omp section block; end block !$omp end sections @@ -171,7 +171,7 @@ subroutine f1 block; end block end do !$omp sections ! { dg-error "may not be closely nested" } - block; end block + x = i !$omp section block; end block !$omp end sections @@ -195,7 +195,7 @@ subroutine f1 block; end block end do !$omp sections - block; end block + x = i !$omp section block; end block !$omp end sections @@ -224,7 +224,7 @@ subroutine f1 block; end block end do !$omp sections - block; end block + x = i !$omp section block; end block !$omp end sections @@ -250,14 +250,14 @@ subroutine f1 end subroutine f2 - integer i, j + integer i, j, x !$omp ordered !$omp do ! { dg-error "may not be closely nested" } do j = 0, 2 block; end block end do !$omp sections ! { dg-error "may not be closely nested" } - block; end block + x = i !$omp section block; end block !$omp end sections diff --git a/gcc/testsuite/gfortran.dg/gomp/strictly-structured-block-1.f90 b/gcc/testsuite/gfortran.dg/gomp/strictly-structured-block-1.f90 new file mode 100644 index 00000000000..931661af433 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/gomp/strictly-structured-block-1.f90 @@ -0,0 +1,211 @@ +! { dg-do compile } +! { dg-options "-fopenmp" } + +program main + integer :: x, i, n + + !$omp parallel + block + x = x + 1 + end block + + !$omp parallel + block + x = x + 1 + end block + !$omp end parallel + + !$omp teams + block + x = x + 1 + end block + + !$omp teams + block + x = x + 1 + end block + !$omp end teams + + !$omp masked + block + x = x + 1 + end block + + !$omp masked + block + x = x + 1 + end block + !$omp end masked + + !$omp scope + block + x = x + 1 + end block + + !$omp scope + block + x = x + 1 + end block + !$omp end scope + + !$omp single + block + x = x + 1 + end block + + !$omp single + block + x = x + 1 + end block + !$omp end single + + !$omp workshare + block + x = x + 1 + end block + + !$omp workshare + block + x = x + 1 + end block + !$omp end workshare + + !$omp task + block + x = x + 1 + end block + + !$omp task + block + x = x + 1 + end block + !$omp end task + + !$omp target data map(x) + block + x = x + 1 + end block + + !$omp target data map(x) + block + x = x + 1 + end block + !$omp end target data + + !$omp target + block + x = x + 1 + end block + + !$omp target + block + x = x + 1 + end block + !$omp end target + + !$omp parallel workshare + block + x = x + 1 + end block + + !$omp parallel workshare + block + x = x + 1 + end block + !$omp end parallel workshare + + !$omp parallel masked + block + x = x + 1 + end block + + !$omp parallel masked + block + x = x + 1 + end block + !$omp end parallel masked + + !$omp target parallel + block + x = x + 1 + end block + + !$omp target parallel + block + x = x + 1 + end block + !$omp end target parallel + + !$omp target teams + block + x = x + 1 + end block + + !$omp target teams + block + x = x + 1 + end block + !$omp end target teams + + !$omp critical + block + x = x + 1 + end block + + !$omp critical + block + x = x + 1 + end block + !$omp end critical + + !$omp taskgroup + block + x = x + 1 + end block + + !$omp taskgroup + block + x = x + 1 + end block + !$omp end taskgroup + + !$omp do ordered + do i = 1, n + !$omp ordered + block + x = x + 1 + end block + end do + + !$omp do ordered + do i = 1, n + !$omp ordered + block + x = x + 1 + end block + !$omp end ordered + end do + + !$omp master + block + x = x + 1 + end block + + !$omp master + block + x = x + 1 + end block + !$omp end master + + !$omp parallel master + block + x = x + 1 + end block + + !$omp parallel master + block + x = x + 1 + end block + !$omp end parallel master + +end program diff --git a/gcc/testsuite/gfortran.dg/gomp/strictly-structured-block-2.f90 b/gcc/testsuite/gfortran.dg/gomp/strictly-structured-block-2.f90 new file mode 100644 index 00000000000..815934e6ad6 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/gomp/strictly-structured-block-2.f90 @@ -0,0 +1,136 @@ +! { dg-do compile } +! { dg-options "-fopenmp" } + +program main + integer :: x, i, n + + !$omp parallel + block + x = x + 1 + end block + x = x + 1 + !$omp end parallel ! { dg-error "Unexpected !.OMP END PARALLEL statement" } + + !$omp teams + block + x = x + 1 + end block + x = x + 1 + !$omp end teams ! { dg-error "Unexpected !.OMP END TEAMS statement" } + + !$omp masked + block + x = x + 1 + end block + x = x + 1 + !$omp end masked ! { dg-error "Unexpected !.OMP END MASKED statement" } + + !$omp scope + block + x = x + 1 + end block + x = x + 1 + !$omp end scope ! { dg-error "Unexpected !.OMP END SCOPE statement" } + + !$omp single + block + x = x + 1 + end block + x = x + 1 + !$omp end single ! { dg-error "Unexpected !.OMP END SINGLE statement" } + + !$omp workshare + block + x = x + 1 + end block + x = x + 1 + !$omp end workshare ! { dg-error "Unexpected !.OMP END WORKSHARE statement" } + + !$omp task + block + x = x + 1 + end block + x = x + 1 + !$omp end task ! { dg-error "Unexpected !.OMP END TASK statement" } + + !$omp target data map(x) + block + x = x + 1 + end block + x = x + 1 + !$omp end target data ! { dg-error "Unexpected !.OMP END TARGET DATA statement" } + + !$omp target + block + x = x + 1 + end block + x = x + 1 + !$omp end target ! { dg-error "Unexpected !.OMP END TARGET statement" } + + !$omp parallel workshare + block + x = x + 1 + end block + x = x + 1 + !$omp end parallel workshare ! { dg-error "Unexpected !.OMP END PARALLEL WORKSHARE statement" } + + !$omp parallel masked + block + x = x + 1 + end block + x = x + 1 + !$omp end parallel masked ! { dg-error "Unexpected !.OMP END PARALLEL MASKED statement" } + + !$omp target parallel + block + x = x + 1 + end block + x = x + 1 + !$omp end target parallel ! { dg-error "Unexpected !.OMP END TARGET PARALLEL statement" } + + !$omp target teams + block + x = x + 1 + end block + x = x + 1 + !$omp end target teams ! { dg-error "Unexpected !.OMP END TARGET TEAMS statement" } + + !$omp critical + block + x = x + 1 + end block + x = x + 1 + !$omp end critical ! { dg-error "Unexpected !.OMP END CRITICAL statement" } + + !$omp taskgroup + block + x = x + 1 + end block + x = x + 1 + !$omp end taskgroup ! { dg-error "Unexpected !.OMP END TASKGROUP statement" } + + !$omp do ordered + do i = 1, n + !$omp ordered + block + x = x + 1 + end block + x = x + 1 + !$omp end ordered ! { dg-error "Unexpected !.OMP END ORDERED statement" } + end do + + !$omp master + block + x = x + 1 + end block + x = x + 1 + !$omp end master ! { dg-error "Unexpected !.OMP END MASTER statement" } + + !$omp parallel master + block + x = x + 1 + end block + x = x + 1 + !$omp end parallel master ! { dg-error "Unexpected !.OMP END PARALLEL MASTER statement" } + +end program diff --git a/gcc/testsuite/gfortran.dg/gomp/strictly-structured-block-3.f90 b/gcc/testsuite/gfortran.dg/gomp/strictly-structured-block-3.f90 new file mode 100644 index 00000000000..f786d1c6c10 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/gomp/strictly-structured-block-3.f90 @@ -0,0 +1,49 @@ +! { dg-do compile } +! { dg-options "-fopenmp" } + +program main + integer :: x + + !$omp parallel + !$omp parallel + block + x = x + 1 + end block + !$omp end parallel + !$omp end parallel + + !$omp workshare + block + x = 1 + !$omp critical + block + x = 3 + end block + end block + + !$omp sections + block + !$omp section + block + x = 1 + end block + x = x + 2 + !$omp section + x = x + 4 + end block + + !$omp sections + !$omp section + block + end block + x = 1 + !$omp end sections + + !$omp sections + block + block + end block + x = 1 + end block + +end program main diff --git a/libgomp/libgomp.texi b/libgomp/libgomp.texi index bdd7e3ac442..d996e32c93b 100644 --- a/libgomp/libgomp.texi +++ b/libgomp/libgomp.texi @@ -337,7 +337,7 @@ The OpenMP 4.5 specification is fully supported. @multitable @columnfractions .60 .10 .25 @headitem Description @tab Status @tab Comments -@item Support of strictly structured blocks in Fortran @tab N @tab +@item Support of strictly structured blocks in Fortran @tab Y @tab @item Support of structured block sequences in C/C++ @tab Y @tab @item @code{unconstrained} and @code{reproducible} modifiers on @code{order} clause @tab Y @tab diff --git a/libgomp/testsuite/libgomp.fortran/task-reduction-16.f90 b/libgomp/testsuite/libgomp.fortran/task-reduction-16.f90 index c6b39e0b391..5b8617a6f5d 100644 --- a/libgomp/testsuite/libgomp.fortran/task-reduction-16.f90 +++ b/libgomp/testsuite/libgomp.fortran/task-reduction-16.f90 @@ -20,6 +20,7 @@ contains !$omp scope reduction (task, iand: c) !$omp barrier !$omp sections + !$omp section block a = a + 1; b(0) = b(0) * 2; call bar (2); b(2) = b(2) * 3 c(1) = iand(c(1), not(ishft(1_8, 2))) ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH, v2, OpenMP 5.2, Fortran] Strictly-structured block support for OpenMP directives 2021-10-20 12:30 ` [PATCH, v2, OpenMP 5.2, " Chung-Lin Tang @ 2021-10-20 16:15 ` Jakub Jelinek 2021-10-21 7:00 ` Chung-Lin Tang 0 siblings, 1 reply; 12+ messages in thread From: Jakub Jelinek @ 2021-10-20 16:15 UTC (permalink / raw) To: Chung-Lin Tang; +Cc: Tobias Burnus, gcc-patches, Fortran List, Catherine Moore On Wed, Oct 20, 2021 at 08:30:34PM +0800, Chung-Lin Tang wrote: > 2021-10-20 Chung-Lin Tang <cltang@codesourcery.com> > > gcc/fortran/ChangeLog: > > * decl.c (gfc_match_end): Add COMP_OMP_STRICTLY_STRUCTURED_BLOCK case > together with COMP_BLOCK. > * parse.c (parse_omp_structured_block): Change return type to > 'gfc_statement', add handling for strictly-structured block case, adjust > recursive calls to parse_omp_structured_block. > (parse_executable): Adjust calls to parse_omp_structured_block. > * parse.h (enum gfc_compile_state): Add > COMP_OMP_STRICTLY_STRUCTURED_BLOCK. > * trans-openmp.c (gfc_trans_omp_workshare): Add EXEC_BLOCK case > handling. > > gcc/testsuite/ChangeLog: > > * gfortran.dg/gomp/cancel-1.f90: Adjust testcase. > * gfortran.dg/gomp/nesting-3.f90: Adjust testcase. > * gfortran.dg/gomp/strictly-structured-block-1.f90: New test. > * gfortran.dg/gomp/strictly-structured-block-2.f90: New test. > * gfortran.dg/gomp/strictly-structured-block-3.f90: New test. > > libgomp/ChangeLog: > > * libgomp.texi (Support of strictly structured blocks in Fortran): > Adjust to 'Y'. > * testsuite/libgomp.fortran/task-reduction-16.f90: Adjust testcase. Thanks, looks mostly good now, but I still have nits for the testsuite. > --- /dev/null > +++ b/gcc/testsuite/gfortran.dg/gomp/strictly-structured-block-1.f90 > @@ -0,0 +1,211 @@ > +! { dg-do compile } > +! { dg-options "-fopenmp" } > + > +program main > + integer :: x, i, n > + > + !$omp parallel > + block > + x = x + 1 > + end block I'd prefer not to use those x = j or x = x + 1 etc. as statements that do random work here whenever possible. While those are dg-do compile testcases, especially if it is without dg-errors I think it is preferrable not to show bad coding examples. E.g. the x = x + 1 above is wrong for 2 reasons, x is uninitialized before the parallel, and there is a data race, the threads, teams etc. can write to x concurrently. I think better would be to use something like call do_work which doesn't have to be defined anywhere and will just stand there as a black box for unspecified work. > + !$omp workshare > + block > + x = x + 1 > + end block There are exceptions though, e.g. workshare is such a case, because e.g. call do_work is not valid in workshare. So, it is ok to keep using x = x + 1 here if you initialize it first at the start of the program. > + !$omp workshare > + block > + x = 1 > + !$omp critical > + block > + x = 3 > + end block > + end block And then there are cases like the above, please just use different variables there (all initialized) or say an array and access different elements in the different spots. Jakub ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH, v2, OpenMP 5.2, Fortran] Strictly-structured block support for OpenMP directives 2021-10-20 16:15 ` Jakub Jelinek @ 2021-10-21 7:00 ` Chung-Lin Tang 2021-10-21 9:19 ` [committed] testsuite: Fix up gfortran.dg/gomp/strictly*.f90 testcases Jakub Jelinek 0 siblings, 1 reply; 12+ messages in thread From: Chung-Lin Tang @ 2021-10-21 7:00 UTC (permalink / raw) To: Jakub Jelinek; +Cc: Tobias Burnus, gcc-patches, Fortran List, Catherine Moore [-- Attachment #1: Type: text/plain, Size: 1451 bytes --] On 2021/10/21 12:15 AM, Jakub Jelinek wrote: >> +program main >> + integer :: x, i, n >> + >> + !$omp parallel >> + block >> + x = x + 1 >> + end block > I'd prefer not to use those x = j or x = x + 1 etc. > as statements that do random work here whenever possible. > While those are dg-do compile testcases, especially if > it is without dg-errors I think it is preferrable not to show > bad coding examples. > E.g. the x = x + 1 above is wrong for 2 reasons, x is uninitialized > before the parallel, and there is a data race, the threads, teams etc. > can write to x concurrently. > I think better would be to use something like > call do_work > which doesn't have to be defined anywhere and will just stand there > as a black box for unspecified work. > >> + !$omp workshare >> + block >> + x = x + 1 >> + end block > There are exceptions though, e.g. workshare is such a case, because > e.g. call do_work is not valid in workshare. > So, it is ok to keep using x = x + 1 here if you initialize it > first at the start of the program. > >> + !$omp workshare >> + block >> + x = 1 >> + !$omp critical >> + block >> + x = 3 >> + end block >> + end block > And then there are cases like the above, please > just use different variables there (all initialized) or > say an array and access different elements in the different spots. > > Jakub > Thanks, attached is what I finally committed. Chung-Lin [-- Attachment #2: 0001-openmp-Fortran-strictly-structured-blocks-support.patch --] [-- Type: text/plain, Size: 19691 bytes --] From 2e4659199e814b7ee0f6bd925fd2c0a7610da856 Mon Sep 17 00:00:00 2001 From: Chung-Lin Tang <cltang@codesourcery.com> Date: Thu, 21 Oct 2021 14:56:20 +0800 Subject: [PATCH] openmp: Fortran strictly-structured blocks support This implements strictly-structured blocks support for Fortran, as specified in OpenMP 5.2. This now allows using a Fortran BLOCK construct as the body of most OpenMP constructs, with a "!$omp end ..." ending directive optional for that form. gcc/fortran/ChangeLog: * decl.c (gfc_match_end): Add COMP_OMP_STRICTLY_STRUCTURED_BLOCK case together with COMP_BLOCK. * parse.c (parse_omp_structured_block): Change return type to 'gfc_statement', add handling for strictly-structured block case, adjust recursive calls to parse_omp_structured_block. (parse_executable): Adjust calls to parse_omp_structured_block. * parse.h (enum gfc_compile_state): Add COMP_OMP_STRICTLY_STRUCTURED_BLOCK. * trans-openmp.c (gfc_trans_omp_workshare): Add EXEC_BLOCK case handling. gcc/testsuite/ChangeLog: * gfortran.dg/gomp/cancel-1.f90: Adjust testcase. * gfortran.dg/gomp/nesting-3.f90: Adjust testcase. * gfortran.dg/gomp/strictly-structured-block-1.f90: New test. * gfortran.dg/gomp/strictly-structured-block-2.f90: New test. * gfortran.dg/gomp/strictly-structured-block-3.f90: New test. libgomp/ChangeLog: * libgomp.texi (Support of strictly structured blocks in Fortran): Adjust to 'Y'. * testsuite/libgomp.fortran/task-reduction-16.f90: Adjust testcase. --- gcc/fortran/decl.c | 1 + gcc/fortran/parse.c | 69 +++++- gcc/fortran/parse.h | 2 +- gcc/fortran/trans-openmp.c | 6 +- gcc/testsuite/gfortran.dg/gomp/cancel-1.f90 | 3 + gcc/testsuite/gfortran.dg/gomp/nesting-3.f90 | 20 +- .../gomp/strictly-structured-block-1.f90 | 214 ++++++++++++++++++ .../gomp/strictly-structured-block-2.f90 | 139 ++++++++++++ .../gomp/strictly-structured-block-3.f90 | 52 +++++ libgomp/libgomp.texi | 2 +- .../libgomp.fortran/task-reduction-16.f90 | 1 + 11 files changed, 484 insertions(+), 25 deletions(-) create mode 100644 gcc/testsuite/gfortran.dg/gomp/strictly-structured-block-1.f90 create mode 100644 gcc/testsuite/gfortran.dg/gomp/strictly-structured-block-2.f90 create mode 100644 gcc/testsuite/gfortran.dg/gomp/strictly-structured-block-3.f90 diff --git a/gcc/fortran/decl.c b/gcc/fortran/decl.c index 6784b07ae9e..6043e100fbb 100644 --- a/gcc/fortran/decl.c +++ b/gcc/fortran/decl.c @@ -8429,6 +8429,7 @@ gfc_match_end (gfc_statement *st) break; case COMP_BLOCK: + case COMP_OMP_STRICTLY_STRUCTURED_BLOCK: *st = ST_END_BLOCK; target = " block"; eos_ok = 0; diff --git a/gcc/fortran/parse.c b/gcc/fortran/parse.c index 2a454be79b0..b1e73ee6801 100644 --- a/gcc/fortran/parse.c +++ b/gcc/fortran/parse.c @@ -5459,7 +5459,7 @@ parse_oacc_loop (gfc_statement acc_st) /* Parse the statements of an OpenMP structured block. */ -static void +static gfc_statement parse_omp_structured_block (gfc_statement omp_st, bool workshare_stmts_only) { gfc_statement st, omp_end_st; @@ -5546,6 +5546,32 @@ parse_omp_structured_block (gfc_statement omp_st, bool workshare_stmts_only) gcc_unreachable (); } + bool block_construct = false; + gfc_namespace *my_ns = NULL; + gfc_namespace *my_parent = NULL; + + st = next_statement (); + + if (st == ST_BLOCK) + { + /* Adjust state to a strictly-structured block, now that we found that + the body starts with a BLOCK construct. */ + s.state = COMP_OMP_STRICTLY_STRUCTURED_BLOCK; + + block_construct = true; + gfc_notify_std (GFC_STD_F2008, "BLOCK construct at %C"); + + my_ns = gfc_build_block_ns (gfc_current_ns); + gfc_current_ns = my_ns; + my_parent = my_ns->parent; + + new_st.op = EXEC_BLOCK; + new_st.ext.block.ns = my_ns; + new_st.ext.block.assoc = NULL; + accept_statement (ST_BLOCK); + st = parse_spec (ST_NONE); + } + do { if (workshare_stmts_only) @@ -5562,7 +5588,6 @@ parse_omp_structured_block (gfc_statement omp_st, bool workshare_stmts_only) restrictions apply recursively. */ bool cycle = true; - st = next_statement (); for (;;) { switch (st) @@ -5588,13 +5613,13 @@ parse_omp_structured_block (gfc_statement omp_st, bool workshare_stmts_only) case ST_OMP_PARALLEL_MASKED: case ST_OMP_PARALLEL_MASTER: case ST_OMP_PARALLEL_SECTIONS: - parse_omp_structured_block (st, false); - break; + st = parse_omp_structured_block (st, false); + continue; case ST_OMP_PARALLEL_WORKSHARE: case ST_OMP_CRITICAL: - parse_omp_structured_block (st, true); - break; + st = parse_omp_structured_block (st, true); + continue; case ST_OMP_PARALLEL_DO: case ST_OMP_PARALLEL_DO_SIMD: @@ -5617,7 +5642,7 @@ parse_omp_structured_block (gfc_statement omp_st, bool workshare_stmts_only) } } else - st = parse_executable (ST_NONE); + st = parse_executable (st); if (st == ST_NONE) unexpected_eof (); else if (st == ST_OMP_SECTION @@ -5627,9 +5652,27 @@ parse_omp_structured_block (gfc_statement omp_st, bool workshare_stmts_only) np = new_level (np); np->op = cp->op; np->block = NULL; + st = next_statement (); + } + else if (block_construct && st == ST_END_BLOCK) + { + accept_statement (st); + gfc_current_ns = my_parent; + pop_state (); + + st = next_statement (); + if (st == omp_end_st) + { + accept_statement (st); + st = next_statement (); + } + return st; } else if (st != omp_end_st) - unexpected_statement (st); + { + unexpected_statement (st); + st = next_statement (); + } } while (st != omp_end_st); @@ -5665,6 +5708,8 @@ parse_omp_structured_block (gfc_statement omp_st, bool workshare_stmts_only) gfc_commit_symbols (); gfc_warning_check (); pop_state (); + st = next_statement (); + return st; } @@ -5805,13 +5850,13 @@ parse_executable (gfc_statement st) case ST_OMP_TEAMS: case ST_OMP_TASK: case ST_OMP_TASKGROUP: - parse_omp_structured_block (st, false); - break; + st = parse_omp_structured_block (st, false); + continue; case ST_OMP_WORKSHARE: case ST_OMP_PARALLEL_WORKSHARE: - parse_omp_structured_block (st, true); - break; + st = parse_omp_structured_block (st, true); + continue; case ST_OMP_DISTRIBUTE: case ST_OMP_DISTRIBUTE_PARALLEL_DO: diff --git a/gcc/fortran/parse.h b/gcc/fortran/parse.h index 55f02299304..66b275de89b 100644 --- a/gcc/fortran/parse.h +++ b/gcc/fortran/parse.h @@ -31,7 +31,7 @@ enum gfc_compile_state COMP_STRUCTURE, COMP_UNION, COMP_MAP, COMP_DO, COMP_SELECT, COMP_FORALL, COMP_WHERE, COMP_CONTAINS, COMP_ENUM, COMP_SELECT_TYPE, COMP_SELECT_RANK, COMP_OMP_STRUCTURED_BLOCK, COMP_CRITICAL, - COMP_DO_CONCURRENT + COMP_DO_CONCURRENT, COMP_OMP_STRICTLY_STRUCTURED_BLOCK }; /* Stack element for the current compilation state. These structures diff --git a/gcc/fortran/trans-openmp.c b/gcc/fortran/trans-openmp.c index aaeb950fb72..e81c5588c53 100644 --- a/gcc/fortran/trans-openmp.c +++ b/gcc/fortran/trans-openmp.c @@ -7000,7 +7000,11 @@ gfc_trans_omp_workshare (gfc_code *code, gfc_omp_clauses *clauses) res = gfc_trans_omp_directive (code); ompws_flags = saved_ompws_flags; break; - + + case EXEC_BLOCK: + res = gfc_trans_block_construct (code); + break; + default: gfc_internal_error ("gfc_trans_omp_workshare(): Bad statement code"); } diff --git a/gcc/testsuite/gfortran.dg/gomp/cancel-1.f90 b/gcc/testsuite/gfortran.dg/gomp/cancel-1.f90 index d60dd72bd4c..1bfddc7b9db 100644 --- a/gcc/testsuite/gfortran.dg/gomp/cancel-1.f90 +++ b/gcc/testsuite/gfortran.dg/gomp/cancel-1.f90 @@ -265,6 +265,7 @@ subroutine f2 end do !$omp end do !$omp sections + !$omp section block !$omp cancel parallel ! { dg-error "not closely nested inside" } !$omp cancel do ! { dg-error "not closely nested inside" } @@ -417,6 +418,7 @@ subroutine f2 !$omp end ordered end do !$omp sections + !$omp section block !$omp cancel parallel ! { dg-error "not closely nested inside" } !$omp cancel do ! { dg-error "not closely nested inside" } @@ -515,6 +517,7 @@ subroutine f3 end do !$omp end do nowait !$omp sections + !$omp section block !$omp cancel sections ! { dg-warning "nowait" } end block diff --git a/gcc/testsuite/gfortran.dg/gomp/nesting-3.f90 b/gcc/testsuite/gfortran.dg/gomp/nesting-3.f90 index cd2e39ae082..5d0d20079a8 100644 --- a/gcc/testsuite/gfortran.dg/gomp/nesting-3.f90 +++ b/gcc/testsuite/gfortran.dg/gomp/nesting-3.f90 @@ -7,7 +7,7 @@ subroutine f1 block; end block end do !$omp sections ! { dg-error "may not be closely nested" } - block; end block + call do_work !$omp section block; end block !$omp end sections @@ -33,7 +33,7 @@ subroutine f1 !$omp end sections !$omp sections !$omp sections ! { dg-error "may not be closely nested" } - block; end block + call do_work !$omp section block; end block !$omp end sections @@ -72,7 +72,7 @@ subroutine f1 !$omp sections !$omp section !$omp sections ! { dg-error "may not be closely nested" } - block; end block + call do_work !$omp section block; end block !$omp end sections @@ -105,7 +105,7 @@ subroutine f1 block; end block end do !$omp sections ! { dg-error "may not be closely nested" } - block; end block + call do_work !$omp section block; end block !$omp end sections @@ -129,7 +129,7 @@ subroutine f1 block; end block end do !$omp sections ! { dg-error "may not be closely nested" } - block; end block + call do_work !$omp section block; end block !$omp end sections @@ -150,7 +150,7 @@ subroutine f1 block; end block end do !$omp sections ! { dg-error "may not be closely nested" } - block; end block + call do_work !$omp section block; end block !$omp end sections @@ -171,7 +171,7 @@ subroutine f1 block; end block end do !$omp sections ! { dg-error "may not be closely nested" } - block; end block + call do_work !$omp section block; end block !$omp end sections @@ -195,7 +195,7 @@ subroutine f1 block; end block end do !$omp sections - block; end block + call do_work !$omp section block; end block !$omp end sections @@ -224,7 +224,7 @@ subroutine f1 block; end block end do !$omp sections - block; end block + call do_work !$omp section block; end block !$omp end sections @@ -257,7 +257,7 @@ subroutine f2 block; end block end do !$omp sections ! { dg-error "may not be closely nested" } - block; end block + call do_work !$omp section block; end block !$omp end sections diff --git a/gcc/testsuite/gfortran.dg/gomp/strictly-structured-block-1.f90 b/gcc/testsuite/gfortran.dg/gomp/strictly-structured-block-1.f90 new file mode 100644 index 00000000000..00a018c6145 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/gomp/strictly-structured-block-1.f90 @@ -0,0 +1,214 @@ +! { dg-do compile } +! { dg-options "-fopenmp" } + +program main + integer :: x, i, n + + x = 0 + n = 10 + + !$omp parallel + block + x = x + 1 + end block + + !$omp parallel + block + x = x + 1 + end block + !$omp end parallel + + !$omp teams + block + x = x + 1 + end block + + !$omp teams + block + x = x + 1 + end block + !$omp end teams + + !$omp masked + block + x = x + 1 + end block + + !$omp masked + block + x = x + 1 + end block + !$omp end masked + + !$omp scope + block + x = x + 1 + end block + + !$omp scope + block + x = x + 1 + end block + !$omp end scope + + !$omp single + block + x = x + 1 + end block + + !$omp single + block + x = x + 1 + end block + !$omp end single + + !$omp workshare + block + x = x + 1 + end block + + !$omp workshare + block + x = x + 1 + end block + !$omp end workshare + + !$omp task + block + x = x + 1 + end block + + !$omp task + block + x = x + 1 + end block + !$omp end task + + !$omp target data map(x) + block + x = x + 1 + end block + + !$omp target data map(x) + block + x = x + 1 + end block + !$omp end target data + + !$omp target + block + x = x + 1 + end block + + !$omp target + block + x = x + 1 + end block + !$omp end target + + !$omp parallel workshare + block + x = x + 1 + end block + + !$omp parallel workshare + block + x = x + 1 + end block + !$omp end parallel workshare + + !$omp parallel masked + block + x = x + 1 + end block + + !$omp parallel masked + block + x = x + 1 + end block + !$omp end parallel masked + + !$omp target parallel + block + x = x + 1 + end block + + !$omp target parallel + block + x = x + 1 + end block + !$omp end target parallel + + !$omp target teams + block + x = x + 1 + end block + + !$omp target teams + block + x = x + 1 + end block + !$omp end target teams + + !$omp critical + block + x = x + 1 + end block + + !$omp critical + block + x = x + 1 + end block + !$omp end critical + + !$omp taskgroup + block + x = x + 1 + end block + + !$omp taskgroup + block + x = x + 1 + end block + !$omp end taskgroup + + !$omp do ordered + do i = 1, n + !$omp ordered + block + x = x + 1 + end block + end do + + !$omp do ordered + do i = 1, n + !$omp ordered + block + x = x + 1 + end block + !$omp end ordered + end do + + !$omp master + block + x = x + 1 + end block + + !$omp master + block + x = x + 1 + end block + !$omp end master + + !$omp parallel master + block + x = x + 1 + end block + + !$omp parallel master + block + x = x + 1 + end block + !$omp end parallel master + +end program diff --git a/gcc/testsuite/gfortran.dg/gomp/strictly-structured-block-2.f90 b/gcc/testsuite/gfortran.dg/gomp/strictly-structured-block-2.f90 new file mode 100644 index 00000000000..a99616980c0 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/gomp/strictly-structured-block-2.f90 @@ -0,0 +1,139 @@ +! { dg-do compile } +! { dg-options "-fopenmp" } + +program main + integer :: x, i, n + + x = 0 + n = 10 + + !$omp parallel + block + x = x + 1 + end block + x = x + 1 + !$omp end parallel ! { dg-error "Unexpected !.OMP END PARALLEL statement" } + + !$omp teams + block + x = x + 1 + end block + x = x + 1 + !$omp end teams ! { dg-error "Unexpected !.OMP END TEAMS statement" } + + !$omp masked + block + x = x + 1 + end block + x = x + 1 + !$omp end masked ! { dg-error "Unexpected !.OMP END MASKED statement" } + + !$omp scope + block + x = x + 1 + end block + x = x + 1 + !$omp end scope ! { dg-error "Unexpected !.OMP END SCOPE statement" } + + !$omp single + block + x = x + 1 + end block + x = x + 1 + !$omp end single ! { dg-error "Unexpected !.OMP END SINGLE statement" } + + !$omp workshare + block + x = x + 1 + end block + x = x + 1 + !$omp end workshare ! { dg-error "Unexpected !.OMP END WORKSHARE statement" } + + !$omp task + block + x = x + 1 + end block + x = x + 1 + !$omp end task ! { dg-error "Unexpected !.OMP END TASK statement" } + + !$omp target data map(x) + block + x = x + 1 + end block + x = x + 1 + !$omp end target data ! { dg-error "Unexpected !.OMP END TARGET DATA statement" } + + !$omp target + block + x = x + 1 + end block + x = x + 1 + !$omp end target ! { dg-error "Unexpected !.OMP END TARGET statement" } + + !$omp parallel workshare + block + x = x + 1 + end block + x = x + 1 + !$omp end parallel workshare ! { dg-error "Unexpected !.OMP END PARALLEL WORKSHARE statement" } + + !$omp parallel masked + block + x = x + 1 + end block + x = x + 1 + !$omp end parallel masked ! { dg-error "Unexpected !.OMP END PARALLEL MASKED statement" } + + !$omp target parallel + block + x = x + 1 + end block + x = x + 1 + !$omp end target parallel ! { dg-error "Unexpected !.OMP END TARGET PARALLEL statement" } + + !$omp target teams + block + x = x + 1 + end block + x = x + 1 + !$omp end target teams ! { dg-error "Unexpected !.OMP END TARGET TEAMS statement" } + + !$omp critical + block + x = x + 1 + end block + x = x + 1 + !$omp end critical ! { dg-error "Unexpected !.OMP END CRITICAL statement" } + + !$omp taskgroup + block + x = x + 1 + end block + x = x + 1 + !$omp end taskgroup ! { dg-error "Unexpected !.OMP END TASKGROUP statement" } + + !$omp do ordered + do i = 1, n + !$omp ordered + block + x = x + 1 + end block + x = x + 1 + !$omp end ordered ! { dg-error "Unexpected !.OMP END ORDERED statement" } + end do + + !$omp master + block + x = x + 1 + end block + x = x + 1 + !$omp end master ! { dg-error "Unexpected !.OMP END MASTER statement" } + + !$omp parallel master + block + x = x + 1 + end block + x = x + 1 + !$omp end parallel master ! { dg-error "Unexpected !.OMP END PARALLEL MASTER statement" } + +end program diff --git a/gcc/testsuite/gfortran.dg/gomp/strictly-structured-block-3.f90 b/gcc/testsuite/gfortran.dg/gomp/strictly-structured-block-3.f90 new file mode 100644 index 00000000000..f9c76d64120 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/gomp/strictly-structured-block-3.f90 @@ -0,0 +1,52 @@ +! { dg-do compile } +! { dg-options "-fopenmp" } + +program main + integer :: x, y + + x = 0 + y = 0 + + !$omp parallel + !$omp parallel + block + x = x + 1 + end block + !$omp end parallel + !$omp end parallel + + !$omp workshare + block + x = 1 + !$omp critical + block + y = 3 + end block + end block + + !$omp sections + block + !$omp section + block + x = 1 + end block + x = x + 2 + !$omp section + x = x + 4 + end block + + !$omp sections + !$omp section + block + end block + x = 1 + !$omp end sections + + !$omp sections + block + block + end block + x = 1 + end block + +end program main diff --git a/libgomp/libgomp.texi b/libgomp/libgomp.texi index e9fa8ba0bf7..6306e97696e 100644 --- a/libgomp/libgomp.texi +++ b/libgomp/libgomp.texi @@ -337,7 +337,7 @@ The OpenMP 4.5 specification is fully supported. @multitable @columnfractions .60 .10 .25 @headitem Description @tab Status @tab Comments -@item Support of strictly structured blocks in Fortran @tab N @tab +@item Support of strictly structured blocks in Fortran @tab Y @tab @item Support of structured block sequences in C/C++ @tab Y @tab @item @code{unconstrained} and @code{reproducible} modifiers on @code{order} clause @tab Y @tab diff --git a/libgomp/testsuite/libgomp.fortran/task-reduction-16.f90 b/libgomp/testsuite/libgomp.fortran/task-reduction-16.f90 index c6b39e0b391..5b8617a6f5d 100644 --- a/libgomp/testsuite/libgomp.fortran/task-reduction-16.f90 +++ b/libgomp/testsuite/libgomp.fortran/task-reduction-16.f90 @@ -20,6 +20,7 @@ contains !$omp scope reduction (task, iand: c) !$omp barrier !$omp sections + !$omp section block a = a + 1; b(0) = b(0) * 2; call bar (2); b(2) = b(2) * 3 c(1) = iand(c(1), not(ishft(1_8, 2))) -- 2.17.1 ^ permalink raw reply [flat|nested] 12+ messages in thread
* [committed] testsuite: Fix up gfortran.dg/gomp/strictly*.f90 testcases 2021-10-21 7:00 ` Chung-Lin Tang @ 2021-10-21 9:19 ` Jakub Jelinek 0 siblings, 0 replies; 12+ messages in thread From: Jakub Jelinek @ 2021-10-21 9:19 UTC (permalink / raw) To: Chung-Lin Tang; +Cc: Tobias Burnus, gcc-patches Hi! I meant it in the other testcases too: While these testcases are dg-do compile only, I think it is better not to give users bad examples and avoid unnecessary data races in testcases (unless it is exactly what we want to test). Perhaps one day we'll do some analysis and warn about data races... Tested on x86_64-linux, committed to trunk. 2021-10-21 Jakub Jelinek <jakub@redhat.com> * gfortran.dg/gomp/strictly-structured-block-1.f90: Use call do_work instead of x = x + 1 in places where the latter could be a data race. * gfortran.dg/gomp/strictly-structured-block-2.f90: Likewise. * gfortran.dg/gomp/strictly-structured-block-3.f90: Likewise. --- gcc/testsuite/gfortran.dg/gomp/strictly-structured-block-1.f90.jj 2021-10-21 10:23:27.544833287 +0200 +++ gcc/testsuite/gfortran.dg/gomp/strictly-structured-block-1.f90 2021-10-21 11:03:41.146041455 +0200 @@ -9,23 +9,23 @@ program main !$omp parallel block - x = x + 1 + call do_work end block !$omp parallel block - x = x + 1 + call do_work end block !$omp end parallel !$omp teams block - x = x + 1 + call do_work end block !$omp teams block - x = x + 1 + call do_work end block !$omp end teams @@ -42,12 +42,12 @@ program main !$omp scope block - x = x + 1 + call do_work end block !$omp scope block - x = x + 1 + call do_work end block !$omp end scope @@ -75,12 +75,12 @@ program main !$omp task block - x = x + 1 + call do_work end block !$omp task block - x = x + 1 + call do_work end block !$omp end task @@ -130,23 +130,23 @@ program main !$omp target parallel block - x = x + 1 + call do_work end block !$omp target parallel block - x = x + 1 + call do_work end block !$omp end target parallel !$omp target teams block - x = x + 1 + call do_work end block !$omp target teams block - x = x + 1 + call do_work end block !$omp end target teams @@ -176,7 +176,7 @@ program main do i = 1, n !$omp ordered block - x = x + 1 + call do_work end block end do @@ -184,7 +184,7 @@ program main do i = 1, n !$omp ordered block - x = x + 1 + call do_work end block !$omp end ordered end do --- gcc/testsuite/gfortran.dg/gomp/strictly-structured-block-2.f90.jj 2021-10-21 10:23:27.544833287 +0200 +++ gcc/testsuite/gfortran.dg/gomp/strictly-structured-block-2.f90 2021-10-21 11:05:04.326876447 +0200 @@ -9,16 +9,16 @@ program main !$omp parallel block - x = x + 1 + call do_work end block - x = x + 1 + call do_work !$omp end parallel ! { dg-error "Unexpected !.OMP END PARALLEL statement" } !$omp teams block - x = x + 1 + call do_work end block - x = x + 1 + call do_work !$omp end teams ! { dg-error "Unexpected !.OMP END TEAMS statement" } !$omp masked @@ -30,9 +30,9 @@ program main !$omp scope block - x = x + 1 + call do_work end block - x = x + 1 + call do_work !$omp end scope ! { dg-error "Unexpected !.OMP END SCOPE statement" } !$omp single @@ -51,9 +51,9 @@ program main !$omp task block - x = x + 1 + call do_work end block - x = x + 1 + call do_work !$omp end task ! { dg-error "Unexpected !.OMP END TASK statement" } !$omp target data map(x) @@ -86,16 +86,16 @@ program main !$omp target parallel block - x = x + 1 + call do_work end block - x = x + 1 + call do_work !$omp end target parallel ! { dg-error "Unexpected !.OMP END TARGET PARALLEL statement" } !$omp target teams block - x = x + 1 + call do_work end block - x = x + 1 + call do_work !$omp end target teams ! { dg-error "Unexpected !.OMP END TARGET TEAMS statement" } !$omp critical @@ -116,9 +116,9 @@ program main do i = 1, n !$omp ordered block - x = x + 1 + call do_work end block - x = x + 1 + call do_work !$omp end ordered ! { dg-error "Unexpected !.OMP END ORDERED statement" } end do --- gcc/testsuite/gfortran.dg/gomp/strictly-structured-block-3.f90.jj 2021-10-21 10:23:27.544833287 +0200 +++ gcc/testsuite/gfortran.dg/gomp/strictly-structured-block-3.f90 2021-10-21 11:07:21.441956054 +0200 @@ -10,7 +10,7 @@ program main !$omp parallel !$omp parallel block - x = x + 1 + call do_work end block !$omp end parallel !$omp end parallel @@ -32,7 +32,7 @@ program main end block x = x + 2 !$omp section - x = x + 4 + call do_work end block !$omp sections Jakub ^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2021-10-21 9:19 UTC | newest] Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2021-10-07 13:59 [PATCH, OpenMP 5.1, Fortran] Strictly-structured block support for OpenMP directives Chung-Lin Tang 2021-10-07 16:33 ` Tobias Burnus 2021-10-07 17:09 ` Jakub Jelinek 2021-10-08 16:14 ` [PATCH] openmp: Add support for OpenMP 5.1 structured-block-sequences Jakub Jelinek 2021-10-14 10:20 ` [PATCH, OpenMP 5.1, Fortran] Strictly-structured block support for OpenMP directives Jakub Jelinek 2021-10-14 11:19 ` Jakub Jelinek 2021-10-15 18:44 ` Chung-Lin Tang 2021-10-15 19:02 ` Jakub Jelinek 2021-10-20 12:30 ` [PATCH, v2, OpenMP 5.2, " Chung-Lin Tang 2021-10-20 16:15 ` Jakub Jelinek 2021-10-21 7:00 ` Chung-Lin Tang 2021-10-21 9:19 ` [committed] testsuite: Fix up gfortran.dg/gomp/strictly*.f90 testcases Jakub Jelinek
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).