[PATCH, v2, OpenMP 5.2, Fortran] Strictly-structured block support for OpenMP directives

2021-10-20 Thread Chung-Lin Tang

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  

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.
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 (

Re: [PATCH, v2, OpenMP 5.2, Fortran] Strictly-structured block support for OpenMP directives

2021-10-20 Thread Jakub Jelinek via Fortran
On Wed, Oct 20, 2021 at 08:30:34PM +0800, Chung-Lin Tang wrote:
> 2021-10-20  Chung-Lin Tang  
> 
> 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



Re: [PATCH][WIP] Add install-dvi Makefile targets

2021-10-20 Thread Eric Gallager via Fortran
On Tue, Oct 19, 2021 at 1:41 AM Thomas Koenig  wrote:
>
> Hi Eric,
>
> > Hi, I have updated this patch and tested it with more languages now; I
> > can now confirm that it works with ada, d, and fortran now. The only
> > languages that remain untested now are go (since I'm building on
> > darwin and go doesn't build on darwin anyways, as per bug 46986) and
> > jit (which I ran into a bug about that I brought up on IRC, and will
> > probably need to file on bugzilla). OK to install?
>
> Fortran parts look good.
>
> Best regards
>
> Thomas

OK, thanks... so... at this point, who do I still need approval from
for the rest of it, then? Should I be cc-ing the build system
maintainers? The maintainers for all the rest of the subdirectories
I'm touching? Global reviewers? Someone else?
Thanks,
Eric Gallager


[PATCH] Fortran: Fixes and additional tests for shape/ubound/size [PR94070]

2021-10-20 Thread Sandra Loosemore
This patch started out as some additional testcases for the SHAPE, 
UBOUND, and SIZE intrinsic extensions for assumed-rank arrays added by 
TS29113; I realized a while ago that I had not added test coverage for 
polymorphic arguments.  My guess that this was a likely trouble spot was 
correct as the new test cases did not work.  :-(


The one that was most concerning was an ICE when calling the SHAPE 
intrinsic with an assumed-rank class type argument, as reported in 
PR94070.  (I think this ICE is similar to the one reported in PR102641 
that Tobias thinks is a problem with the scalarizer.)  In this case, 
SHAPE was calling a library function and trying to copy the array 
contents to a temporary, which is really stupid because SHAPE only needs 
to look at the descriptor and not the array contents.  I thought we 
could handle this inline the same as UBOUND and LBOUND, by extending 
gfc_trans_intrinsic_bound, and avoid the library function entirely.


Then, I found some other existing problems in gfc_trans_intrinsic_bound; 
the conditional it was building to test for the extent-zero special 
cases for LBOUND and UBOUND was completely wrong, and the compile-time 
test for the assumed-rank/assumed-size case was wrong too.  So I ended 
up rewriting large parts of that function.


I also fixed a bug in the SIZE intrinsic where it was not taking the 
class types into account.  (SIZE is already being handled inline in a 
separate place, otherwise I might've merged it into 
gfc_trans_intrinsic_bound as well.)


While I was at it I also added 3 more testcases for these functions to 
test for correct behavior with bind(c).  All 6 new tests PASS now, and 
there are no other regressions.


OK to commit?

-Sandra
commit c74d3f5ae059b74a552428d6f1602885ca239094
Author: Sandra Loosemore 
Date:   Tue Oct 19 21:11:15 2021 -0700

Fortran: Fixes and additional tests for shape/ubound/size [PR94070]

This patch reimplements the SHAPE intrinsic to be inlined similarly to
LBOUND and UBOUND, instead of as a library call, to avoid an
unnecessary array copy.  Various bugs are also fixed.

gcc/fortran/
	PR fortran/94070

	* expr.c (gfc_simplify_expr): Handle GFC_ISYM_SHAPE along with
	GFC_ISYM_LBOUND and GFC_ISYM_UBOUND.
	* trans-array.c (gfc_conv_ss_startstride): Likewise.
	(set_loop_bounds): Likewise.
	(gfc_tree_array_size): Handle class arrays.
	* trans-intrinsic.c (gfc_trans_intrinsic_bound): Extend to
	handle SHAPE.  Correct logic for zero-size special cases and
	detecting assumed-rank arrays associated with an assumed-size
	argument.
	(gfc_conv_intrinsic_shape): Deleted.
	(gfc_conv_intrinsic_function): Handle GFC_ISYM_SHAPE like
	GFC_ISYM_LBOUND and GFC_ISYM_UBOUND.
	(gfc_add_intrinsic_ss_code): Likewise.
	(gfc_walk_intrinsic_bound): Likewise.

gcc/testsuite/gfortran.dg/
	PR fortran/94070

	* c-interop/shape-bindc.f90: New test.
	* c-interop/shape-poly.f90: New test.
	* c-interop/size-bindc.f90: New test.
	* c-interop/size-poly.f90: New test.
	* c-interop/ubound-bindc.f90: New test.
	* c-interop/ubound-poly.f90: New test.

diff --git a/gcc/fortran/expr.c b/gcc/fortran/expr.c
index 66f24c6..b19d3a2 100644
--- a/gcc/fortran/expr.c
+++ b/gcc/fortran/expr.c
@@ -2205,7 +2205,8 @@ gfc_simplify_expr (gfc_expr *p, int type)
 	  (p->value.function.isym->id == GFC_ISYM_LBOUND
 	   || p->value.function.isym->id == GFC_ISYM_UBOUND
 	   || p->value.function.isym->id == GFC_ISYM_LCOBOUND
-	   || p->value.function.isym->id == GFC_ISYM_UCOBOUND))
+	   || p->value.function.isym->id == GFC_ISYM_UCOBOUND
+	   || p->value.function.isym->id == GFC_ISYM_SHAPE))
 	ap = ap->next;
 
   for ( ; ap; ap = ap->next)
diff --git a/gcc/fortran/trans-array.c b/gcc/fortran/trans-array.c
index f8c087e..323edcb 100644
--- a/gcc/fortran/trans-array.c
+++ b/gcc/fortran/trans-array.c
@@ -4507,6 +4507,7 @@ gfc_conv_ss_startstride (gfc_loopinfo * loop)
 	case GFC_ISYM_UBOUND:
 	case GFC_ISYM_LCOBOUND:
 	case GFC_ISYM_UCOBOUND:
+	case GFC_ISYM_SHAPE:
 	case GFC_ISYM_THIS_IMAGE:
 	  loop->dimen = ss->dimen;
 	  goto done;
@@ -4558,12 +4559,14 @@ done:
 	/* Fall through to supply start and stride.  */
 	case GFC_ISYM_LBOUND:
 	case GFC_ISYM_UBOUND:
+	  /* This is the variant without DIM=...  */
+	  gcc_assert (expr->value.function.actual->next->expr == NULL);
+	  /* Fall through.  */
+
+	case GFC_ISYM_SHAPE:
 	  {
 		gfc_expr *arg;
 
-		/* This is the variant without DIM=...  */
-		gcc_assert (expr->value.function.actual->next->expr == NULL);
-
 		arg = expr->value.function.actual->expr;
 		if (arg->rank == -1)
 		  {
@@ -5350,10 +5353,13 @@ set_loop_bounds (gfc_loopinfo *loop)
 		gfc_expr *expr = loopspec[n]->info->expr;
 
 		/* The {l,u}bound of an assumed rank.  */
-		gcc_assert ((expr->value.function.isym->id == GFC_ISYM_LBOUND
-			 || expr->value.function.isym->id == G

Re: [PATCH] Fortran: Fixes and additional tests for shape/ubound/size [PR94070]

2021-10-20 Thread Tobias Burnus

Hi Sandra,

On 20.10.21 22:03, Sandra Loosemore wrote:

The one that was most concerning was an ICE when calling the SHAPE
intrinsic with an assumed-rank class type argument ... In this case,
SHAPE was calling a library function and trying to copy the array
contents to a temporary, which is really stupid because SHAPE only
needs to look at the descriptor and not the array contents.  I thought
we could handle this inline the same as UBOUND and LBOUND, by
extending gfc_trans_intrinsic_bound, and avoid the library function
entirely.

Then, I found some other existing problems in
gfc_trans_intrinsic_bound; the conditional it was building to test for
the extent-zero special cases for LBOUND and UBOUND was completely
wrong, and the compile-time test for the assumed-rank/assumed-size
case was wrong too.  So I ended up rewriting large parts of that
function.

I also fixed a bug in the SIZE intrinsic where it was not taking the
class types into account.  (SIZE is already being handled inline in a
separate place, otherwise I might've merged it into
gfc_trans_intrinsic_bound as well.)


Thanks for your efforts!

LGTM with the changelog path fix, without the gfc_tree_array_size
attribute change and with the indentation fix.

Namely:


gcc/testsuite/gfortran.dg/
PR fortran/94070

* c-interop/shape-bindc.f90: New test.

The ChangeLog file is in testsuite/ not in testsuite/gfortran.dg/.


@@ -8054,9 +8060,18 @@ gfc_tree_array_size (stmtblock_t *block, tree desc, 
gfc_expr *expr, tree dim)
return GFC_TYPE_ARRAY_SIZE (TREE_TYPE (desc));
  }
tree size, tmp, rank = NULL_TREE, cond = NULL_TREE;
-  symbol_attribute attr = gfc_expr_attr (expr);
+  symbol_attribute attr;
gfc_array_spec *as = gfc_get_full_arrayspec_from_expr (expr);
gcc_assert (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc)));
+
+  if (expr->ts.type == BT_CLASS)
+{
+  attr = CLASS_DATA (expr->symtree->n.sym)->attr;
+  attr.pointer = attr.class_pointer;
+}
+  else
+attr = gfc_expr_attr (expr);


Short version: Can you undo this change and verify that it still
fails? – Because I think that it works now due to the patch mentioned below.

At least it did pass here and an assert only pointed to testcases,
where I expected an issue.

 * * *

Long version:
I stumbled over this while reading the patch as I think it is wrong in the
general case. However, I belief it is fine for the particular use
(only allocatable + pointer with assumed-rank arrays). It does mishandle
"nonclass%class_comp" – but that is inaccessible if 'nonclass' is
assumed-rank (and the attributes are only used in that case).

Nonetheless, I fail to see when this fails - because I think that gfc_expr_attr
should yield the proper result (since Tue Oct 12, my 
eb92cd57a1ebe7cd7589bdbec34d9ae337752ead)

I think before before that patch, the problem was that expr was not 'var'
but 'var%_data' and gfc_expr then returned the attributes for gfc_expr,
which always had attr.pointer == 1 as the true 'pointer' attribute is in
attr.class_pointer and not in attr.pointer.

My bet is that you modified this before doing the "git pull" which pulled
in my patch above ...

For testing, I did turn your change into an assert and it only failed for
class_48.f90 and pr93792.f90. Those expose the issue I was concerned about:

(gdb) p gfc_debug_expr(expr)
test4:one % a % _data(FULL)

(gdb) p gfc_debug_expr(expr)
copy:self % x % _data(FULL)

(As said: nonissue in this case, but still feels wrong – and as the
workaround is longer be needed, it can also be removed.)

--- a/gcc/fortran/trans-intrinsic.c
+++ b/gcc/fortran/trans-intrinsic.c
...
+   /* Descriptors for assumed-size arrays have ubound = -1
+  in the last dimension.  */
+   cond1 = fold_build2_loc (input_location, EQ_EXPR,
+ logical_type_node, ubound, minus_one);

Here, indentation goes wrong.

Thanks,

Tobias

-
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


Re: [PATCH] Fortran: Fixes and additional tests for shape/ubound/size [PR94070]

2021-10-20 Thread Sandra Loosemore

On 10/20/21 3:41 PM, Tobias Burnus wrote:

Hi Sandra,

On 20.10.21 22:03, Sandra Loosemore wrote:
The one that was most concerning was an ICE when calling the SHAPE 
intrinsic with an assumed-rank class type argument ... In this case, 
SHAPE was calling a library function and trying to copy the array 
contents to a temporary, which is really stupid because SHAPE only 
needs to look at the descriptor and not the array contents.  I thought 
we could handle this inline the same as UBOUND and LBOUND, by 
extending gfc_trans_intrinsic_bound, and avoid the library function 
entirely.


Then, I found some other existing problems in 
gfc_trans_intrinsic_bound; the conditional it was building to test for 
the extent-zero special cases for LBOUND and UBOUND was completely 
wrong, and the compile-time test for the assumed-rank/assumed-size 
case was wrong too.  So I ended up rewriting large parts of that 
function.


I also fixed a bug in the SIZE intrinsic where it was not taking the 
class types into account.  (SIZE is already being handled inline in a 
separate place, otherwise I might've merged it into 
gfc_trans_intrinsic_bound as well.)


Thanks for your efforts!

LGTM with the changelog path fix, without the gfc_tree_array_size 
attribute change and with the indentation fix.


Thanks, committed now with those fixes.  You are right that I'd made 
that change to gfc_tree_array_size before I pulled your alternate fix 
for that, and didn't realize that my hack had become redundant.


-Sandra