public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [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).