[PATCH] fortran: Fix up initializers of param(0) PARAMETERs [PR103691]

2022-03-25 Thread Jakub Jelinek via Fortran
Hi!

On the gfortran.dg/pr103691.f90 testcase the Fortran ICE emits
  static real(kind=4) a[0] = {[0 ... -1]=2.0e+0};
That is an invalid RANGE_EXPR where the maximum is smaller than the minimum.

The following patch fixes that.  If TYPE_MAX_VALUE is smaller than
TYPE_MIN_VALUE, the array is empty and so doesn't need any initializer,
if the two are equal, we don't need to bother with a RANGE_EXPR and
can just use that INTEGER_CST as the index and finally for the 2+ values
in the range it uses a RANGE_EXPR as before.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

2022-03-25  Jakub Jelinek  

PR fortran/103691
* trans-array.cc (gfc_conv_array_initializer): If TYPE_MAX_VALUE is
smaller than TYPE_MIN_VALUE (i.e. empty array), throw the initializer
on the floor, if TYPE_MIN_VALUE is equal to TYPE_MAX_VALUE, use just
the TYPE_MIN_VALUE as index instead of RANGE_EXPR.

--- gcc/fortran/trans-array.cc.jj   2022-02-04 14:36:55.113603791 +0100
+++ gcc/fortran/trans-array.cc  2022-03-24 16:14:58.334498775 +0100
@@ -6267,10 +6267,17 @@ gfc_conv_array_initializer (tree type, g
   else
gfc_conv_structure (&se, expr, 1);
 
-  CONSTRUCTOR_APPEND_ELT (v, build2 (RANGE_EXPR, gfc_array_index_type,
-TYPE_MIN_VALUE (TYPE_DOMAIN (type)),
-TYPE_MAX_VALUE (TYPE_DOMAIN (type))),
- se.expr);
+  if (tree_int_cst_lt (TYPE_MAX_VALUE (TYPE_DOMAIN (type)),
+  TYPE_MIN_VALUE (TYPE_DOMAIN (type
+   break;
+  else if (tree_int_cst_equal (TYPE_MIN_VALUE (TYPE_DOMAIN (type)),
+  TYPE_MAX_VALUE (TYPE_DOMAIN (type
+   range = TYPE_MIN_VALUE (TYPE_DOMAIN (type));
+  else
+   range = build2 (RANGE_EXPR, gfc_array_index_type,
+   TYPE_MIN_VALUE (TYPE_DOMAIN (type)),
+   TYPE_MAX_VALUE (TYPE_DOMAIN (type)));
+  CONSTRUCTOR_APPEND_ELT (v, range, se.expr);
   break;
 
 case EXPR_ARRAY:

Jakub



Re: [PATCH] fortran: Fix up initializers of param(0) PARAMETERs [PR103691]

2022-03-25 Thread Tobias Burnus

On 25.03.22 09:57, Jakub Jelinek via Fortran wrote:

On the gfortran.dg/pr103691.f90 testcase the Fortran ICE emits
   static real(kind=4) a[0] = {[0 ... -1]=2.0e+0};
That is an invalid RANGE_EXPR where the maximum is smaller than the minimum.

The following patch fixes that.  If TYPE_MAX_VALUE is smaller than
TYPE_MIN_VALUE, the array is empty and so doesn't need any initializer,
if the two are equal, we don't need to bother with a RANGE_EXPR and
can just use that INTEGER_CST as the index and finally for the 2+ values
in the range it uses a RANGE_EXPR as before.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?


LGTM – thanks for taking care of Fortran patches and regressions.


2022-03-25  Jakub Jelinek  

  PR fortran/103691
  * trans-array.cc (gfc_conv_array_initializer): If TYPE_MAX_VALUE is
  smaller than TYPE_MIN_VALUE (i.e. empty array), throw the initializer
  on the floor, if TYPE_MIN_VALUE is equal to TYPE_MAX_VALUE, use just
  the TYPE_MIN_VALUE as index instead of RANGE_EXPR.


I am not sure whether "throw the initializer on the floor" is the best wording
for a changelog. I think I prefer a wording like "ignore the initializer" or
another less idiomatic expression. And I think a ';' before the second 'if'
also increases readability.

Tobias


--- gcc/fortran/trans-array.cc.jj 2022-02-04 14:36:55.113603791 +0100
+++ gcc/fortran/trans-array.cc2022-03-24 16:14:58.334498775 +0100
@@ -6267,10 +6267,17 @@ gfc_conv_array_initializer (tree type, g
else
  gfc_conv_structure (&se, expr, 1);

-  CONSTRUCTOR_APPEND_ELT (v, build2 (RANGE_EXPR, gfc_array_index_type,
-  TYPE_MIN_VALUE (TYPE_DOMAIN (type)),
-  TYPE_MAX_VALUE (TYPE_DOMAIN (type))),
-   se.expr);
+  if (tree_int_cst_lt (TYPE_MAX_VALUE (TYPE_DOMAIN (type)),
+TYPE_MIN_VALUE (TYPE_DOMAIN (type
+ break;
+  else if (tree_int_cst_equal (TYPE_MIN_VALUE (TYPE_DOMAIN (type)),
+TYPE_MAX_VALUE (TYPE_DOMAIN (type
+ range = TYPE_MIN_VALUE (TYPE_DOMAIN (type));
+  else
+ range = build2 (RANGE_EXPR, gfc_array_index_type,
+ TYPE_MIN_VALUE (TYPE_DOMAIN (type)),
+ TYPE_MAX_VALUE (TYPE_DOMAIN (type)));
+  CONSTRUCTOR_APPEND_ELT (v, range, se.expr);
break;

  case EXPR_ARRAY:

  Jakub


-
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: Fix up initializers of param(0) PARAMETERs [PR103691]

2022-03-25 Thread Richard Biener via Fortran
On Fri, Mar 25, 2022 at 11:13 AM Tobias Burnus  wrote:
>
> On 25.03.22 09:57, Jakub Jelinek via Fortran wrote:
> > On the gfortran.dg/pr103691.f90 testcase the Fortran ICE emits
> >static real(kind=4) a[0] = {[0 ... -1]=2.0e+0};
> > That is an invalid RANGE_EXPR where the maximum is smaller than the minimum.
> >
> > The following patch fixes that.  If TYPE_MAX_VALUE is smaller than
> > TYPE_MIN_VALUE, the array is empty and so doesn't need any initializer,
> > if the two are equal, we don't need to bother with a RANGE_EXPR and
> > can just use that INTEGER_CST as the index and finally for the 2+ values
> > in the range it uses a RANGE_EXPR as before.
> >
> > Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
>
> LGTM – thanks for taking care of Fortran patches and regressions.
>
> > 2022-03-25  Jakub Jelinek  
> >
> >   PR fortran/103691
> >   * trans-array.cc (gfc_conv_array_initializer): If TYPE_MAX_VALUE is
> >   smaller than TYPE_MIN_VALUE (i.e. empty array), throw the initializer
> >   on the floor, if TYPE_MIN_VALUE is equal to TYPE_MAX_VALUE, use just
> >   the TYPE_MIN_VALUE as index instead of RANGE_EXPR.
>
> I am not sure whether "throw the initializer on the floor" is the best wording
> for a changelog. I think I prefer a wording like "ignore the initializer" or
> another less idiomatic expression. And I think a ';' before the second 'if'
> also increases readability.

Can there be side-effects in those initializer elements in Fortran?

Richard.

> Tobias
>
> > --- gcc/fortran/trans-array.cc.jj 2022-02-04 14:36:55.113603791 +0100
> > +++ gcc/fortran/trans-array.cc2022-03-24 16:14:58.334498775 +0100
> > @@ -6267,10 +6267,17 @@ gfc_conv_array_initializer (tree type, g
> > else
> >   gfc_conv_structure (&se, expr, 1);
> >
> > -  CONSTRUCTOR_APPEND_ELT (v, build2 (RANGE_EXPR, gfc_array_index_type,
> > -  TYPE_MIN_VALUE (TYPE_DOMAIN (type)),
> > -  TYPE_MAX_VALUE (TYPE_DOMAIN (type))),
> > -   se.expr);
> > +  if (tree_int_cst_lt (TYPE_MAX_VALUE (TYPE_DOMAIN (type)),
> > +TYPE_MIN_VALUE (TYPE_DOMAIN (type
> > + break;
> > +  else if (tree_int_cst_equal (TYPE_MIN_VALUE (TYPE_DOMAIN (type)),
> > +TYPE_MAX_VALUE (TYPE_DOMAIN (type
> > + range = TYPE_MIN_VALUE (TYPE_DOMAIN (type));
> > +  else
> > + range = build2 (RANGE_EXPR, gfc_array_index_type,
> > + TYPE_MIN_VALUE (TYPE_DOMAIN (type)),
> > + TYPE_MAX_VALUE (TYPE_DOMAIN (type)));
> > +  CONSTRUCTOR_APPEND_ELT (v, range, se.expr);
> > break;
> >
> >   case EXPR_ARRAY:
> >
> >   Jakub
> >
> -
> 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: Fix up initializers of param(0) PARAMETERs [PR103691]

2022-03-25 Thread Jakub Jelinek via Fortran
On Fri, Mar 25, 2022 at 12:16:40PM +0100, Richard Biener wrote:
> On Fri, Mar 25, 2022 at 11:13 AM Tobias Burnus  
> wrote:
> >
> > On 25.03.22 09:57, Jakub Jelinek via Fortran wrote:
> > > On the gfortran.dg/pr103691.f90 testcase the Fortran ICE emits
> > >static real(kind=4) a[0] = {[0 ... -1]=2.0e+0};
> > > That is an invalid RANGE_EXPR where the maximum is smaller than the 
> > > minimum.
> > >
> > > The following patch fixes that.  If TYPE_MAX_VALUE is smaller than
> > > TYPE_MIN_VALUE, the array is empty and so doesn't need any initializer,
> > > if the two are equal, we don't need to bother with a RANGE_EXPR and
> > > can just use that INTEGER_CST as the index and finally for the 2+ values
> > > in the range it uses a RANGE_EXPR as before.
> > >
> > > Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
> >
> > LGTM – thanks for taking care of Fortran patches and regressions.
> >
> > > 2022-03-25  Jakub Jelinek  
> > >
> > >   PR fortran/103691
> > >   * trans-array.cc (gfc_conv_array_initializer): If TYPE_MAX_VALUE is
> > >   smaller than TYPE_MIN_VALUE (i.e. empty array), throw the 
> > > initializer
> > >   on the floor, if TYPE_MIN_VALUE is equal to TYPE_MAX_VALUE, use just
> > >   the TYPE_MIN_VALUE as index instead of RANGE_EXPR.
> >
> > I am not sure whether "throw the initializer on the floor" is the best 
> > wording
> > for a changelog. I think I prefer a wording like "ignore the initializer" or
> > another less idiomatic expression. And I think a ';' before the second 'if'
> > also increases readability.
> 
> Can there be side-effects in those initializer elements in Fortran?

For PARAMETERs certainly not, those need to be constant.
Even otherwise, this is in a routine that does
  /* Create a constructor from the list of elements.  */
  tmp = build_constructor (type, v);
  TREE_CONSTANT (tmp) = 1;
  return tmp;
at the end so I wouldn't expect side-effects anywhere.

Also, I think typically in the Fortran FE side-effects would go into
se.pre and se.post sequences, not into se.expr, and this routine
doesn't emit those se.pre/se.post sequences anywhere, so presumably it
assumes they don't exist.

What is the behavior with a RANGE_EXPR when one has { [0..10] = ++i; },
is that applying the side-effects 11 times or once ?


Jakub



Re: [PATCH] fortran: Fix up initializers of param(0) PARAMETERs [PR103691]

2022-03-25 Thread Richard Biener via Fortran
On Fri, Mar 25, 2022 at 12:34 PM Jakub Jelinek  wrote:
>
> On Fri, Mar 25, 2022 at 12:16:40PM +0100, Richard Biener wrote:
> > On Fri, Mar 25, 2022 at 11:13 AM Tobias Burnus  
> > wrote:
> > >
> > > On 25.03.22 09:57, Jakub Jelinek via Fortran wrote:
> > > > On the gfortran.dg/pr103691.f90 testcase the Fortran ICE emits
> > > >static real(kind=4) a[0] = {[0 ... -1]=2.0e+0};
> > > > That is an invalid RANGE_EXPR where the maximum is smaller than the 
> > > > minimum.
> > > >
> > > > The following patch fixes that.  If TYPE_MAX_VALUE is smaller than
> > > > TYPE_MIN_VALUE, the array is empty and so doesn't need any initializer,
> > > > if the two are equal, we don't need to bother with a RANGE_EXPR and
> > > > can just use that INTEGER_CST as the index and finally for the 2+ values
> > > > in the range it uses a RANGE_EXPR as before.
> > > >
> > > > Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
> > >
> > > LGTM – thanks for taking care of Fortran patches and regressions.
> > >
> > > > 2022-03-25  Jakub Jelinek  
> > > >
> > > >   PR fortran/103691
> > > >   * trans-array.cc (gfc_conv_array_initializer): If TYPE_MAX_VALUE 
> > > > is
> > > >   smaller than TYPE_MIN_VALUE (i.e. empty array), throw the 
> > > > initializer
> > > >   on the floor, if TYPE_MIN_VALUE is equal to TYPE_MAX_VALUE, use 
> > > > just
> > > >   the TYPE_MIN_VALUE as index instead of RANGE_EXPR.
> > >
> > > I am not sure whether "throw the initializer on the floor" is the best 
> > > wording
> > > for a changelog. I think I prefer a wording like "ignore the initializer" 
> > > or
> > > another less idiomatic expression. And I think a ';' before the second 
> > > 'if'
> > > also increases readability.
> >
> > Can there be side-effects in those initializer elements in Fortran?
>
> For PARAMETERs certainly not, those need to be constant.
> Even otherwise, this is in a routine that does
>   /* Create a constructor from the list of elements.  */
>   tmp = build_constructor (type, v);
>   TREE_CONSTANT (tmp) = 1;
>   return tmp;
> at the end so I wouldn't expect side-effects anywhere.

Ah, didn't see that.

> Also, I think typically in the Fortran FE side-effects would go into
> se.pre and se.post sequences, not into se.expr, and this routine
> doesn't emit those se.pre/se.post sequences anywhere, so presumably it
> assumes they don't exist.
>
> What is the behavior with a RANGE_EXPR when one has { [0..10] = ++i; },
> is that applying the side-effects 11 times or once ?

11 times is what is documented.

Richard.

>
>
> Jakub
>


Re: [PATCH] fortran: Fix up initializers of param(0) PARAMETERs [PR103691]

2022-03-25 Thread Jakub Jelinek via Fortran
On Fri, Mar 25, 2022 at 01:13:06PM +0100, Richard Biener wrote:
> > Also, I think typically in the Fortran FE side-effects would go into
> > se.pre and se.post sequences, not into se.expr, and this routine
> > doesn't emit those se.pre/se.post sequences anywhere, so presumably it
> > assumes they don't exist.
> >
> > What is the behavior with a RANGE_EXPR when one has { [0..10] = ++i; },
> > is that applying the side-effects 11 times or once ?
> 
> 11 times is what is documented.

Then [0..-1] = ++i should be 0 times the side-effect.

Jakub



[PATCH] Fortran: Fix clause splitting for OMP masked taskloop directive

2022-03-25 Thread Sandra Loosemore
I ran into this bug in the handling of clauses on the combined "masked 
taskloop" OMP directive when I was working on something else.  The fix 
turned out to be a 1-liner.  OK for trunk?


-Sandracommit 17c4fa0bd97c070945004095a06fb7d9e91869e3
Author: Sandra Loosemore 
Date:   Wed Mar 23 18:45:25 2022 -0700

Fortran: Fix clause splitting for OMP masked taskloop directive

This patch fixes an obvious coding goof that caused all clauses for
the combined OMP masked taskloop directive to be discarded.

	gcc/fortran/
	* trans-openmp.cc (gfc_split_omp_clauses): Fix mask for
	EXEC_OMP_MASKED_TASKLOOP.

	gcc/testsuite/
	* gfortran.dg/gomp/masked-taskloop.f90: New.

diff --git a/gcc/fortran/trans-openmp.cc b/gcc/fortran/trans-openmp.cc
index 101924f..25dde82 100644
--- a/gcc/fortran/trans-openmp.cc
+++ b/gcc/fortran/trans-openmp.cc
@@ -5998,7 +5998,7 @@ gfc_split_omp_clauses (gfc_code *code,
   innermost = GFC_OMP_SPLIT_DO;
   break;
 case EXEC_OMP_MASKED_TASKLOOP:
-  mask = GFC_OMP_SPLIT_MASKED | GFC_OMP_SPLIT_TASKLOOP;
+  mask = GFC_OMP_MASK_MASKED | GFC_OMP_MASK_TASKLOOP;
   innermost = GFC_OMP_SPLIT_TASKLOOP;
   break;
 case EXEC_OMP_MASTER_TASKLOOP:
diff --git a/gcc/testsuite/gfortran.dg/gomp/masked-taskloop.f90 b/gcc/testsuite/gfortran.dg/gomp/masked-taskloop.f90
new file mode 100644
index 000..6fb7111
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/masked-taskloop.f90
@@ -0,0 +1,19 @@
+! { dg-do compile }
+! { dg-additional-options "-fopenmp -fdump-tree-original" }
+
+! There was a bug in the clause splitting for the "masked taskloop"
+! combined directive that caused it to lose all the clauses.
+
+subroutine s1 (a1, a2)
+  integer :: a1, a2
+  integer :: i, j
+
+  !$omp masked taskloop collapse(2) grainsize(4)
+  do i = 1, a1
+do j = 1, a2
+end do
+  end do
+
+end subroutine
+
+! { dg-final { scan-tree-dump "omp taskloop collapse\\(2\\) grainsize\\(4\\)" "original" } }


[PATCH] Fortran: Add location info to OpenMP tree nodes

2022-03-25 Thread Sandra Loosemore
I've got another patch forthcoming (stage 1 material) that adds some new 
diagnostics for non-rectangular loops during gimplification of OMP 
nodes.  When I was working on that, I discovered that the Fortran front 
end wasn't attaching location information to the tree nodes 
corresponding to the various OMP directives, so the new errors weren't 
coming out with location info either.  I went through trans-openmp.cc 
and fixed all the places where make_node was being called to explicitly 
set the location.


I don't have a test case specifically for this change, but my test cases 
for the new diagnostics in the non-rectangular loops patch do exercise 
it.  Is this OK for trunk now, or for stage 1 when we get there?


-Sandracommit 4c745003d0b39d0e92032b62421df4920753783a
Author: Sandra Loosemore 
Date:   Thu Mar 24 21:02:34 2022 -0700

Fortran: Add location info to OpenMP tree nodes

	 gcc/fortran/
	 * trans-openmp.cc (gfc_trans_omp_critical): Set location on OMP
	 tree node.
	 (gfc_trans_omp_do): Likewise.
	 (gfc_trans_omp_masked): Likewise.
	 (gfc_trans_omp_do_simd): Likewise.
	 (gfc_trans_omp_scope): Likewise.
	 (gfc_trans_omp_taskgroup): Likewise.
	 (gfc_trans_omp_taskwait): Likewise.
	 (gfc_trans_omp_distribute): Likewise.
	 (gfc_trans_omp_taskloop): Likewise.
	 (gfc_trans_omp_master_masked_taskloop): Likewise.

diff --git a/gcc/fortran/trans-openmp.cc b/gcc/fortran/trans-openmp.cc
index 25dde82..ba3ff71 100644
--- a/gcc/fortran/trans-openmp.cc
+++ b/gcc/fortran/trans-openmp.cc
@@ -5012,6 +5012,7 @@ gfc_trans_omp_critical (gfc_code *code)
 name = get_identifier (code->ext.omp_clauses->critical_name);
   gfc_start_block (&block);
   stmt = make_node (OMP_CRITICAL);
+  SET_EXPR_LOCATION (stmt, gfc_get_location (&code->loc));
   TREE_TYPE (stmt) = void_type_node;
   OMP_CRITICAL_BODY (stmt) = gfc_trans_code (code->block->next);
   OMP_CRITICAL_NAME (stmt) = name;
@@ -5044,6 +5045,7 @@ gfc_trans_omp_do (gfc_code *code, gfc_exec_op op, stmtblock_t *pblock,
   unsigned ix;
   vec *saved_doacross_steps = doacross_steps;
   gfc_expr_list *tile = do_clauses ? do_clauses->tile_list : clauses->tile_list;
+  gfc_code *orig_code = code;
 
   /* Both collapsed and tiled loops are lowered the same way.  In
  OpenACC, those clauses are not compatible, so prioritize the tile
@@ -5398,6 +5400,7 @@ gfc_trans_omp_do (gfc_code *code, gfc_exec_op op, stmtblock_t *pblock,
 default: gcc_unreachable ();
 }
 
+  SET_EXPR_LOCATION (stmt, gfc_get_location (&orig_code->loc));
   TREE_TYPE (stmt) = void_type_node;
   OMP_FOR_BODY (stmt) = gfc_finish_block (&body);
   OMP_FOR_CLAUSES (stmt) = omp_clauses;
@@ -5670,6 +5673,7 @@ gfc_trans_omp_masked (gfc_code *code, gfc_omp_clauses *clauses)
   gfc_start_block (&block);
   tree omp_clauses = gfc_trans_omp_clauses (&block, clauses, code->loc);
   tree stmt = make_node (OMP_MASKED);
+  SET_EXPR_LOCATION (stmt, gfc_get_location (&code->loc));
   TREE_TYPE (stmt) = void_type_node;
   OMP_MASKED_BODY (stmt) = body;
   OMP_MASKED_CLAUSES (stmt) = omp_clauses;
@@ -6444,6 +6448,7 @@ gfc_trans_omp_do_simd (gfc_code *code, stmtblock_t *pblock,
   if (flag_openmp)
 {
   stmt = make_node (OMP_FOR);
+  SET_EXPR_LOCATION (stmt, gfc_get_location (&code->loc));
   TREE_TYPE (stmt) = void_type_node;
   OMP_FOR_BODY (stmt) = body;
   OMP_FOR_CLAUSES (stmt) = omp_do_clauses;
@@ -6616,6 +6621,7 @@ gfc_trans_omp_scope (gfc_code *code)
   tree omp_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
 	code->loc);
   tree stmt = make_node (OMP_SCOPE);
+  SET_EXPR_LOCATION (stmt, gfc_get_location (&code->loc));
   TREE_TYPE (stmt) = void_type_node;
   OMP_SCOPE_BODY (stmt) = body;
   OMP_SCOPE_CLAUSES (stmt) = omp_clauses;
@@ -6691,6 +6697,7 @@ gfc_trans_omp_taskgroup (gfc_code *code)
   gfc_start_block (&block);
   tree body = gfc_trans_code (code->block->next);
   tree stmt = make_node (OMP_TASKGROUP);
+  SET_EXPR_LOCATION (stmt, gfc_get_location (&code->loc));
   TREE_TYPE (stmt) = void_type_node;
   OMP_TASKGROUP_BODY (stmt) = body;
   OMP_TASKGROUP_CLAUSES (stmt) = gfc_trans_omp_clauses (&block,
@@ -6711,6 +6718,7 @@ gfc_trans_omp_taskwait (gfc_code *code)
   stmtblock_t block;
   gfc_start_block (&block);
   tree stmt = make_node (OMP_TASK);
+  SET_EXPR_LOCATION (stmt, gfc_get_location (&code->loc));
   TREE_TYPE (stmt) = void_type_node;
   OMP_TASK_BODY (stmt) = NULL_TREE;
   OMP_TASK_CLAUSES (stmt) = gfc_trans_omp_clauses (&block,
@@ -6788,6 +6796,7 @@ gfc_trans_omp_distribute (gfc_code *code, gfc_omp_clauses *clausesa)
   if (flag_openmp)
 {
   tree distribute = make_node (OMP_DISTRIBUTE);
+  SET_EXPR_LOCATION (distribute, gfc_get_location (&code->loc));
   TREE_TYPE (distribute) = void_type_node;
   OMP_FOR_BODY (distribute) = stmt;
   OMP_FOR_CLAUSES (distribute) = omp_clauses;
@@ -7008,6 +7017,7 @@ gfc_trans_omp_taskloop (gfc_code *code, gfc_exec_op op)
   if (

[PATCH, stage 1] Fortran: Add support for OMP non-rectangular loops

2022-03-25 Thread Sandra Loosemore
This patch adds Fortran support for OMP 5.1 "canonical loop nest form" 
and non-rectangular loops.  The C/C++ and middle-end support is already 
present except for some missing constraint checks in the gimplifier, 
which I've added here.  There's still a TODO with respect to the 
not-yet-implemented TILE construct.


Is this OK for stage 1 when the time comes?

-Sandracommit c46a79a9841b90fb0cde564e4147932290d91832
Author: Sandra Loosemore 
Date:   Fri Mar 25 14:14:37 2022 -0700

Fortran: Add support for OMP non-rectangular loops.

This patch adds support for OMP 5.1 "canonical loop nest form" to the
Fortran front end, marks non-rectangular loops for processing
by the middle end, and implements missing checks in the gimplifier
for additional prohibitions on non-rectangular loops.

Note that the OMP spec also prohibits non-rectangular loops with the TILE
construct; that construct hasn't been implemented yet, so that error will
need to be filled in later.

	gcc/fortran/
	* gfortran.h (struct gfc_omp_clauses): Add non_rectangular bit.
	* openmp.cc (is_outer_iteration_variable): New function.
	(expr_is_invariant): New function.
	(bound_expr_is_canonical): New function.
	(resolve_omp_do): Replace existing non-rectangularity error with
	check for canonical form and setting non_rectangular bit.
	* trans-openmp.cc (gfc_trans_omp_do): Transfer non_rectangular
	flag to generated tree structure.

	gcc/
	* gimplify.cc (gimplify_omp_for): Update messages for SCHEDULED
	and ORDERED clause conflict errors.  Add check for GRAINSIZE and
	NUM_TASKS on TASKLOOP.

	gcc/testsuite/
	* c-c++-common/gomp/loop-6.c (f3): New function to test TASKLOOP
	diagnostics.
	* gfortran.dg/gomp/collapse1.f90: Update expected messages.
	* gfortran.dg/gomp/pr85313.f90: Remove dg-error on non-rectangular
	loops that are now accepted.
	* gfortran.dg/gomp/non-rectangular-loop.f90: New file.
	* gfortran.dg/gomp/canonical-loop-1.f90: New file.
	* gfortran.dg/gomp/canonical-loop-2.f90: New file.

diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h
index 7bf1d5a..1bce283 100644
--- a/gcc/fortran/gfortran.h
+++ b/gcc/fortran/gfortran.h
@@ -1533,6 +1533,7 @@ typedef struct gfc_omp_clauses
   unsigned simd:1, threads:1, depend_source:1, destroy:1, order_concurrent:1;
   unsigned order_unconstrained:1, order_reproducible:1, capture:1;
   unsigned grainsize_strict:1, num_tasks_strict:1, compare:1, weak:1;
+  unsigned non_rectangular:1;
   ENUM_BITFIELD (gfc_omp_sched_kind) sched_kind:3;
   ENUM_BITFIELD (gfc_omp_device_type) device_type:2;
   ENUM_BITFIELD (gfc_omp_memorder) memorder:3;
diff --git a/gcc/fortran/openmp.cc b/gcc/fortran/openmp.cc
index 7141481..4d3fcc8 100644
--- a/gcc/fortran/openmp.cc
+++ b/gcc/fortran/openmp.cc
@@ -8446,6 +8446,105 @@ gfc_resolve_omp_local_vars (gfc_namespace *ns)
 gfc_traverse_ns (ns, handle_local_var);
 }
 
+/* CODE is an OMP loop construct.  Return true if VAR matches an iteration
+   variable outer to level DEPTH.  */
+static bool
+is_outer_iteration_variable (gfc_code *code, int depth, gfc_symbol *var)
+{
+  int i;
+  gfc_code *do_code = code->block->next;
+
+  for (i = 1; i < depth; i++)
+{
+  gfc_symbol *ivar = do_code->ext.iterator->var->symtree->n.sym;
+  if (var == ivar)
+	return true;
+  do_code = do_code->block->next;
+}
+  return false;
+}
+
+/* CODE is an OMP loop construct.  Return true if EXPR does not reference
+   any iteration variables outer to level DEPTH.  */
+static bool
+expr_is_invariant (gfc_code *code, int depth, gfc_expr *expr)
+{
+  int i;
+  gfc_code *do_code = code->block->next;
+
+  for (i = 1; i < depth; i++)
+{
+  gfc_symbol *ivar = do_code->ext.iterator->var->symtree->n.sym;
+  if (gfc_find_sym_in_expr (ivar, expr))
+	return false;
+  do_code = do_code->block->next;
+}
+  return true;
+}
+
+/* CODE is an OMP loop construct.  Return true if EXPR matches one of the
+   canonical forms for a bound expression.  It may include references to
+   an iteration variable outer to level DEPTH; set OUTER_VARP if so.  */
+static bool
+bound_expr_is_canonical (gfc_code *code, int depth, gfc_expr *expr,
+			 gfc_symbol **outer_varp)
+{
+  gfc_expr *expr2 = NULL;
+
+  /* Rectangular case.  */
+  if (depth == 0 || expr_is_invariant (code, depth, expr))
+return true;
+
+  /* Any simple variable that didn't pass expr_is_invariant must be
+ an outer_var.  */
+  if (expr->expr_type == EXPR_VARIABLE && expr->rank == 0)
+{
+  *outer_varp = expr->symtree->n.sym;
+  return true;
+}
+
+  /* All other permitted forms are binary operators.  */
+  if (expr->expr_type != EXPR_OP)
+return false;
+
+  /* Check for plus/minus a loop invariant expr.  */
+  if (expr->value.op.op == INTRINSIC_PLUS
+  || expr->value.op.op == INTRINSIC_MINUS)
+{
+  if (expr_is_invariant (code, depth, expr->value.