public inbox for fortran@gcc.gnu.org
 help / color / mirror / Atom feed
* [Patch] OpenMP/Fortran: Add support for OpenMP 5.2 linear clause syntax
@ 2022-07-04 14:10 Tobias Burnus
  2022-07-04 14:53 ` Jakub Jelinek
  0 siblings, 1 reply; 6+ messages in thread
From: Tobias Burnus @ 2022-07-04 14:10 UTC (permalink / raw)
  To: gcc-patches, fortran, Jakub Jelinek

[-- Attachment #1: Type: text/plain, Size: 824 bytes --]

This patch adds support for the OpenMP 5.2 syntax for the linear clause,
following the C/C++ patch. The testcases are modified versions from the
C/C++ ones, plus one added one for duplicated modifiers.

At least to me it is not quite clear when
   linear ( var : ref)
refers to a variable 'ref' and when to the linear-modifier 'ref'; the
spec does not seem to be very clear about it. I made an attempt, based
on the C/C++ code – but I am not positive I handle it correctly.

Tested on x86-64-gnu-linux.
OK? Or are there comments?

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

[-- Attachment #2: linear.diff --]
[-- Type: text/x-patch, Size: 25826 bytes --]

OpenMP/Fortran: Add support for OpenMP 5.2 linear clause syntax

Fortran part to C/C++
commit r13-1002-g03b71406323ddc065b1d7837d8b43b17e4b048b5

gcc/fortran/ChangeLog:

	* gfortran.h (gfc_omp_namelist): Update by creating 'linear' struct,
	move 'linear_op' as 'op' to id and add 'old_modifier' to it.
	* dump-parse-tree.cc (show_omp_namelist): Update accordingly.
	* module.cc (mio_omp_declare_simd): Likewise.
	* trans-openmp.cc (gfc_trans_omp_clauses): Likewise.
	* openmp.cc (resolve_omp_clauses): Likewise; accept new-style
	'val' modifier with do/simd.
	(gfc_match_omp_clauses): Handle OpenMP 5.2 linear clause syntax.

libgomp/ChangeLog:

	* libgomp.texi (OpenMP 5.2): Mark linear-clause change as 'Y'.

gcc/testsuite/ChangeLog:

	* gfortran.dg/gomp/linear-2.f90: New test.
	* gfortran.dg/gomp/linear-3.f90: New test.
	* gfortran.dg/gomp/linear-4.f90: New test.
	* gfortran.dg/gomp/linear-5.f90: New test.
	* gfortran.dg/gomp/linear-6.f90: New test.
	* gfortran.dg/gomp/linear-7.f90: New test.

 gcc/fortran/dump-parse-tree.cc              |   6 +-
 gcc/fortran/gfortran.h                      |   6 +-
 gcc/fortran/module.cc                       |   6 +-
 gcc/fortran/openmp.cc                       | 232 +++++++++++++++++++++++++---
 gcc/fortran/trans-openmp.cc                 |   5 +-
 gcc/testsuite/gfortran.dg/gomp/linear-2.f90 | 112 ++++++++++++++
 gcc/testsuite/gfortran.dg/gomp/linear-3.f90 |  39 +++++
 gcc/testsuite/gfortran.dg/gomp/linear-4.f90 | 102 ++++++++++++
 gcc/testsuite/gfortran.dg/gomp/linear-5.f90 |  43 ++++++
 gcc/testsuite/gfortran.dg/gomp/linear-6.f90 |  54 +++++++
 gcc/testsuite/gfortran.dg/gomp/linear-7.f90 |  27 ++++
 libgomp/libgomp.texi                        |   2 +-
 12 files changed, 604 insertions(+), 30 deletions(-)

diff --git a/gcc/fortran/dump-parse-tree.cc b/gcc/fortran/dump-parse-tree.cc
index 85c0b98f615..5352008a63d 100644
--- a/gcc/fortran/dump-parse-tree.cc
+++ b/gcc/fortran/dump-parse-tree.cc
@@ -1421,8 +1421,8 @@ show_omp_namelist (int list_type, gfc_omp_namelist *n)
 	  case OMP_MAP_RELEASE: fputs ("release:", dumpfile); break;
 	  default: break;
 	  }
-      else if (list_type == OMP_LIST_LINEAR)
-	switch (n->u.linear_op)
+      else if (list_type == OMP_LIST_LINEAR && n->u.linear.old_modifier)
+	switch (n->u.linear.op)
 	  {
 	  case OMP_LINEAR_REF: fputs ("ref(", dumpfile); break;
 	  case OMP_LINEAR_VAL: fputs ("val(", dumpfile); break;
@@ -1430,7 +1430,7 @@ show_omp_namelist (int list_type, gfc_omp_namelist *n)
 	  default: break;
 	  }
       fprintf (dumpfile, "%s", n->sym ? n->sym->name : "omp_all_memory");
-      if (list_type == OMP_LIST_LINEAR && n->u.linear_op != OMP_LINEAR_DEFAULT)
+      if (list_type == OMP_LIST_LINEAR && n->u.linear.op != OMP_LINEAR_DEFAULT)
 	fputc (')', dumpfile);
       if (n->expr)
 	{
diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h
index 463d9692236..696aadd7db6 100644
--- a/gcc/fortran/gfortran.h
+++ b/gcc/fortran/gfortran.h
@@ -1345,7 +1345,11 @@ typedef struct gfc_omp_namelist
       gfc_omp_reduction_op reduction_op;
       gfc_omp_depend_op depend_op;
       gfc_omp_map_op map_op;
-      gfc_omp_linear_op linear_op;
+      struct
+	{
+	  ENUM_BITFIELD (gfc_omp_linear_op) op:4;
+	  bool old_modifier;
+	} linear;
       struct gfc_common_head *common;
       bool lastprivate_conditional;
     } u;
diff --git a/gcc/fortran/module.cc b/gcc/fortran/module.cc
index 85aa153bd77..5ddabdcff4d 100644
--- a/gcc/fortran/module.cc
+++ b/gcc/fortran/module.cc
@@ -4383,10 +4383,10 @@ mio_omp_declare_simd (gfc_namespace *ns, gfc_omp_declare_simd **odsp)
 	    }
 	  for (n = ods->clauses->lists[OMP_LIST_LINEAR]; n; n = n->next)
 	    {
-	      if (n->u.linear_op == OMP_LINEAR_DEFAULT)
+	      if (n->u.linear.op == OMP_LINEAR_DEFAULT)
 		mio_name (4, omp_declare_simd_clauses);
 	      else
-		mio_name (32 + n->u.linear_op, omp_declare_simd_clauses);
+		mio_name (32 + n->u.linear.op, omp_declare_simd_clauses);
 	      mio_symbol_ref (&n->sym);
 	      mio_expr (&n->expr);
 	    }
@@ -4438,7 +4438,7 @@ mio_omp_declare_simd (gfc_namespace *ns, gfc_omp_declare_simd **odsp)
 	    case 34:
 	    case 35:
 	      *ptrs[1] = n = gfc_get_omp_namelist ();
-	      n->u.linear_op = (enum gfc_omp_linear_op) (t - 32);
+	      n->u.linear.op = (enum gfc_omp_linear_op) (t - 32);
 	      t = 4;
 	      goto finish_namelist;
 	    }
diff --git a/gcc/fortran/openmp.cc b/gcc/fortran/openmp.cc
index 51b429a597c..d3940cc51d0 100644
--- a/gcc/fortran/openmp.cc
+++ b/gcc/fortran/openmp.cc
@@ -2324,6 +2324,7 @@ gfc_match_omp_clauses (gfc_omp_clauses **cp, const omp_mask mask,
 	  if ((mask & OMP_CLAUSE_LINEAR)
 	      && gfc_match ("linear (") == MATCH_YES)
 	    {
+	      bool old_linear_modifier = false;
 	      gfc_omp_linear_op linear_op = OMP_LINEAR_DEFAULT;
 	      gfc_expr *step = NULL;
 
@@ -2331,17 +2332,26 @@ gfc_match_omp_clauses (gfc_omp_clauses **cp, const omp_mask mask,
 					       &c->lists[OMP_LIST_LINEAR],
 					       false, NULL, &head)
 		  == MATCH_YES)
-		linear_op = OMP_LINEAR_REF;
+		{
+		  linear_op = OMP_LINEAR_REF;
+		  old_linear_modifier = true;
+		}
 	      else if (gfc_match_omp_variable_list (" val (",
 						    &c->lists[OMP_LIST_LINEAR],
 						    false, NULL, &head)
 		       == MATCH_YES)
-		linear_op = OMP_LINEAR_VAL;
+		{
+		  linear_op = OMP_LINEAR_VAL;
+		  old_linear_modifier = true;
+		}
 	      else if (gfc_match_omp_variable_list (" uval (",
 						    &c->lists[OMP_LIST_LINEAR],
 						    false, NULL, &head)
 		       == MATCH_YES)
-		linear_op = OMP_LINEAR_UVAL;
+		{
+		  linear_op = OMP_LINEAR_UVAL;
+		  old_linear_modifier = true;
+		}
 	      else if (gfc_match_omp_variable_list ("",
 						    &c->lists[OMP_LIST_LINEAR],
 						    false, &end_colon, &head)
@@ -2364,14 +2374,183 @@ gfc_match_omp_clauses (gfc_omp_clauses **cp, const omp_mask mask,
 		      break;
 		    }
 		}
-	      if (end_colon && gfc_match (" %e )", &step) != MATCH_YES)
+	      gfc_gobble_whitespace ();
+	      if (old_linear_modifier && end_colon)
 		{
-		  gfc_free_omp_namelist (*head, false);
-		  gfc_current_locus = old_loc;
-		  *head = NULL;
-		  break;
+		  if (gfc_match (" %e )", &step) != MATCH_YES)
+		    {
+		      gfc_free_omp_namelist (*head, false);
+		      gfc_current_locus = old_loc;
+		      *head = NULL;
+		      goto error;
+		    }
+		}
+	      else if (end_colon)
+		{
+		  gfc_symtree *st;
+		  bool has_modifiers = false;
+		  bool duplicate_step = false;
+		  bool duplicate_mod = false;
+		  while (true)
+		    {
+		      old_loc = gfc_current_locus;
+		      if (gfc_match ("val )") == MATCH_YES)
+			{
+			  if (!has_modifiers)
+			    {
+			      gfc_find_sym_tree ("val", NULL, true, &st);
+			      bool has_val = (st
+					      && !st->n.sym->attr.function
+					      && !st->n.sym->attr.dimension);
+			      locus loc = gfc_current_locus;
+			      gfc_current_locus = old_loc;
+			      if (has_val
+				  && gfc_match (" %e ) ", &step) == MATCH_YES)
+				break;
+			      gfc_current_locus = loc;
+			    }
+			  if (linear_op != OMP_LINEAR_DEFAULT)
+			    {
+			      duplicate_mod = true;
+			      break;
+			    }
+			  linear_op = OMP_LINEAR_VAL;
+			  has_modifiers = true;
+			  break;
+			}
+		      else if (gfc_match ("val , ") == MATCH_YES)
+			{
+			  if (linear_op != OMP_LINEAR_DEFAULT)
+			    {
+			      duplicate_mod = true;
+			      break;
+			    }
+			  linear_op = OMP_LINEAR_VAL;
+			  has_modifiers = true;
+			  continue;
+			}
+		      else if (gfc_match ("uval )") == MATCH_YES)
+			{
+			  if (!has_modifiers)
+			    {
+			      gfc_find_sym_tree ("uval", NULL, true, &st);
+			      bool has_uval = (st
+					       && !st->n.sym->attr.function
+					       && !st->n.sym->attr.dimension);
+			      locus loc = gfc_current_locus;
+			      gfc_current_locus = old_loc;
+			      if (has_uval
+				  && gfc_match (" %e ) ", &step) == MATCH_YES)
+				break;
+			      gfc_current_locus = loc;
+			    }
+			  if (linear_op != OMP_LINEAR_DEFAULT)
+			    {
+			      duplicate_mod = true;
+			      break;
+			    }
+			  linear_op = OMP_LINEAR_UVAL;
+			  has_modifiers = true;
+			  break;
+			}
+		      else if (gfc_match ("uval , ") == MATCH_YES)
+			{
+			  if (linear_op != OMP_LINEAR_DEFAULT)
+			    {
+			      duplicate_mod = true;
+			      break;
+			    }
+			  linear_op = OMP_LINEAR_UVAL;
+			  has_modifiers = true;
+			  continue;
+			}
+		      else if (gfc_match ("ref )") == MATCH_YES)
+			{
+			  if (!has_modifiers)
+			    {
+			      gfc_find_sym_tree ("ref", NULL, true, &st);
+			      bool has_ref = (st
+					      && !st->n.sym->attr.function
+					      && !st->n.sym->attr.dimension);
+			      locus loc = gfc_current_locus;
+			      gfc_current_locus = old_loc;
+			      if (has_ref
+				  && gfc_match (" %e ) ", &step) == MATCH_YES)
+				break;
+			      gfc_current_locus = loc;
+			    }
+			  if (linear_op != OMP_LINEAR_DEFAULT)
+			    {
+			      duplicate_mod = true;
+			      break;
+			    }
+			  linear_op = OMP_LINEAR_REF;
+			  has_modifiers = true;
+			  break;
+			}
+		      else if (gfc_match ("ref , ") == MATCH_YES)
+			{
+			  if (linear_op != OMP_LINEAR_DEFAULT)
+			    {
+			      duplicate_mod = true;
+			      break;
+			    }
+			  linear_op = OMP_LINEAR_REF;
+			  has_modifiers = true;
+			  continue;
+			}
+		      else if (gfc_match ("step ( ") == MATCH_YES)
+			{
+			  if (!has_modifiers)
+			    {
+			      gfc_find_sym_tree ("step", NULL, true, &st);
+			      bool has_step
+				= (st && (st->n.sym->attr.function
+					  || st->n.sym->attr.dimension));
+			      locus loc = gfc_current_locus;
+			      gfc_current_locus = old_loc;
+			      if (has_step
+				  && gfc_match ("%e ) ", &step) == MATCH_YES)
+				break;
+			      gfc_current_locus = loc;
+			    }
+			  if (step)
+			    {
+			      duplicate_step = true;
+			      break;
+			    }
+			  has_modifiers = true;
+			  if (gfc_match ("%e ) ", &step) == MATCH_YES)
+			    {
+			      if (gfc_match (", ") == MATCH_YES)
+				continue;
+			      if (gfc_match (")") == MATCH_YES)
+				break;
+			    }
+			  gfc_free_omp_namelist (*head, false);
+			  *head = NULL;
+			  goto error;
+			}
+		      else if (!has_modifiers
+			       && gfc_match ("%e )", &step) == MATCH_YES)
+			break;
+		      else
+			{
+			  gfc_free_omp_namelist (*head, false);
+			  *head = NULL;
+			  goto error;
+			}
+		    }
+		  if (duplicate_mod || duplicate_step)
+		    {
+		      gfc_error ("Multiple %qs modifiers specified at %C",
+				 duplicate_mod ? "linear" : "step");
+		      gfc_free_omp_namelist (*head, false);
+		      *head = NULL;
+		      goto error;
+		    }
 		}
-	      else if (!end_colon)
+	      else
 		{
 		  step = gfc_get_constant_expr (BT_INTEGER,
 						gfc_default_integer_kind,
@@ -2379,9 +2558,12 @@ gfc_match_omp_clauses (gfc_omp_clauses **cp, const omp_mask mask,
 		  mpz_set_si (step->value.integer, 1);
 		}
 	      (*head)->expr = step;
-	      if (linear_op != OMP_LINEAR_DEFAULT)
+	      if (linear_op != OMP_LINEAR_DEFAULT || old_linear_modifier)
 		for (gfc_omp_namelist *n = *head; n; n = n->next)
-		  n->u.linear_op = linear_op;
+		  {
+		    n->u.linear.op = linear_op;
+		    n->u.linear.old_modifier = old_linear_modifier;
+		  }
 	      continue;
 	    }
 	  if ((mask & OMP_CLAUSE_LINK)
@@ -7439,28 +7621,38 @@ resolve_omp_clauses (gfc_code *code, gfc_omp_clauses *omp_clauses,
 		    break;
 		  case OMP_LIST_LINEAR:
 		    if (code
-			&& n->u.linear_op != OMP_LINEAR_DEFAULT
-			&& n->u.linear_op != linear_op)
+			&& n->u.linear.op != OMP_LINEAR_DEFAULT
+			&& n->u.linear.op != linear_op)
 		      {
-			gfc_error ("LINEAR clause modifier used on DO or SIMD"
-				   " construct at %L", &n->where);
-			linear_op = n->u.linear_op;
+			if (n->u.linear.old_modifier)
+			  {
+			    gfc_error ("LINEAR clause modifier used on DO or "
+				       "SIMD construct at %L", &n->where);
+			    linear_op = n->u.linear.op;
+			  }
+			else if (n->u.linear.op != OMP_LINEAR_VAL)
+			  {
+			    gfc_error ("LINEAR clause modifier other than VAL "
+				       "used on DO or SIMD construct at %L",
+				       &n->where);
+			    linear_op = n->u.linear.op;
+			  }
 		      }
 		    else if (omp_clauses->orderedc)
 		      gfc_error ("LINEAR clause specified together with "
 				 "ORDERED clause with argument at %L",
 				 &n->where);
-		    else if (n->u.linear_op != OMP_LINEAR_REF
+		    else if (n->u.linear.op != OMP_LINEAR_REF
 			     && n->sym->ts.type != BT_INTEGER)
 		      gfc_error ("LINEAR variable %qs must be INTEGER "
 				 "at %L", n->sym->name, &n->where);
-		    else if ((n->u.linear_op == OMP_LINEAR_REF
-			      || n->u.linear_op == OMP_LINEAR_UVAL)
+		    else if ((n->u.linear.op == OMP_LINEAR_REF
+			      || n->u.linear.op == OMP_LINEAR_UVAL)
 			     && n->sym->attr.value)
 		      gfc_error ("LINEAR dummy argument %qs with VALUE "
 				 "attribute with %s modifier at %L",
 				 n->sym->name,
-				 n->u.linear_op == OMP_LINEAR_REF
+				 n->u.linear.op == OMP_LINEAR_REF
 				 ? "REF" : "UVAL", &n->where);
 		    else if (n->expr)
 		      {
diff --git a/gcc/fortran/trans-openmp.cc b/gcc/fortran/trans-openmp.cc
index c6a584d36f2..de27ed52c02 100644
--- a/gcc/fortran/trans-openmp.cc
+++ b/gcc/fortran/trans-openmp.cc
@@ -2751,7 +2751,7 @@ gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses,
 						      OMP_CLAUSE_LINEAR);
 			OMP_CLAUSE_DECL (node) = t;
 			omp_clause_linear_kind kind;
-			switch (n->u.linear_op)
+			switch (n->u.linear.op)
 			  {
 			  case OMP_LINEAR_DEFAULT:
 			    kind = OMP_CLAUSE_LINEAR_DEFAULT;
@@ -2769,7 +2769,8 @@ gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses,
 			    gcc_unreachable ();
 			  }
 			OMP_CLAUSE_LINEAR_KIND (node) = kind;
-			OMP_CLAUSE_LINEAR_OLD_LINEAR_MODIFIER (node) = 1;
+			OMP_CLAUSE_LINEAR_OLD_LINEAR_MODIFIER (node)
+			  = n->u.linear.old_modifier;
 			if (last_step_expr && last_step == NULL_TREE)
 			  {
 			    if (!declare_simd)
diff --git a/gcc/testsuite/gfortran.dg/gomp/linear-2.f90 b/gcc/testsuite/gfortran.dg/gomp/linear-2.f90
new file mode 100644
index 00000000000..925d922ecfb
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/linear-2.f90
@@ -0,0 +1,112 @@
+! { dg-do compile }
+! { dg-options "-fopenmp -fdump-tree-original" }
+
+module m
+  implicit none (type, external)
+
+  integer i
+
+  interface
+    integer function bar (x, y, z)
+      integer, value :: x, y, z
+      !$omp declare simd linear (x : val, step (1)) linear (y : step (2))
+    end
+
+    integer function baz (x, y, z)
+      integer, value :: x, y, z
+      !$omp declare simd linear (x : step (1), val)
+    end
+
+    integer function qux (x, val)
+      integer, value :: x, val
+      !$omp declare simd linear (val (x) : val) uniform (val)
+    end
+
+    integer function corge (x, val)
+      integer, value :: x, val
+      !$omp declare simd linear (x : val, step (val)) uniform (val)
+    end
+
+    integer function grault (x)
+      integer, value :: x
+      !$omp declare simd linear (x : val)
+    end
+
+    integer function step (x)
+      integer, value :: x
+    end
+  end interface
+
+contains
+
+subroutine foo (x,y)
+  integer :: x, y
+  integer :: val
+
+  val = 1
+
+  !$omp simd linear (i: step (3))
+  do i = 0, 32, 3
+  end do
+
+  !$omp simd linear (i: val, step (3))
+  do i = 0, 32, 3
+  end do
+
+  !$omp simd linear (x: step (y + 1))
+  do i = 0, 9
+    x = x + y + 1
+  end do
+
+  !$omp simd linear (x: step (y + 1), val)
+  do i = 0, 9
+    x = x + y + 1
+  end do
+
+  !$omp parallel do linear (x: step (y + 1))
+  do i = 0, 9
+    x = x + y + 1
+  end do
+
+  !$omp parallel do linear (x: val, step (y + 1))
+  do i = 0, 9
+    x = x + y + 1
+  end do
+
+  !$omp parallel do simd linear (i: step (3))
+  do i = 0, 32, 3
+  end do
+
+  !$omp parallel do simd linear (i: step (3), val)
+  do i = 0, 32, 3
+  end do
+
+  !$omp parallel do simd linear (x: step (y + 1))
+  do i = 0, 9
+    x = x + y + 1
+  end do
+
+  !$omp parallel do simd linear (x: val, step (y + 1))
+  do i = 0, 9
+    x = x + y + 1
+  end do
+
+  !$omp parallel do simd linear (i: val + 0)
+  do i = 0, 9
+  end do
+
+  !$omp parallel do simd linear (i: step (1) * 1)
+  do i = 0, 9
+  end do
+end
+end module
+
+! { dg-final { scan-tree-dump-times "#pragma omp parallel" 8 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp for nowait" 6 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp for linear\\(x:D\\.\[0-9\]+\\) nowait" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp for linear\\(x:val,step\\(D\\.\[0-9\]+\\)\\) nowait" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp simd linear\\(count.\[0-9\]:1\\) linear\\(i:D\\.\[0-9\]+\\)" 2 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp simd linear\\(count.\[0-9\]:1\\) linear\\(i:val,step\\(3\\)\\)" 2 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp simd linear\\(i:1\\) linear\\(x:D\\.\[0-9\]+\\)" 2 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp simd linear\\(i:1\\) linear\\(x:val,step\\(D\\.\[0-9\]+\\)\\)" 2 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp simd linear\\(i:D\\.\[0-9\]+\\)" 2 "original" } }
diff --git a/gcc/testsuite/gfortran.dg/gomp/linear-3.f90 b/gcc/testsuite/gfortran.dg/gomp/linear-3.f90
new file mode 100644
index 00000000000..dee87b1a899
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/linear-3.f90
@@ -0,0 +1,39 @@
+! { dg-do compile }
+! { dg-options "-fopenmp" }
+
+module m2
+  implicit none (type, external)
+
+  integer :: val
+
+contains
+integer function step (x)
+  integer, value :: x
+end
+subroutine foo(x)
+  integer, value :: x
+  !$omp declare simd linear (val (x) : step (1))	! { dg-error "requires a constant integer linear-step expression or dummy argument" }
+end
+end module m2
+
+
+module m
+  implicit none (type, external)
+
+  integer :: val
+
+contains
+integer function step (x)
+  integer, value :: x
+  !$omp declare simd linear (val (x) : step (1))	! { dg-error "Failed to match clause" }
+end
+
+integer function bar (x, y, z)
+  integer, value :: x, y, z
+  !$omp declare simd linear (val (x) : val)		! { dg-error "requires a constant integer linear-step expression or dummy argument" }
+end
+
+integer function baz (x, y, z)
+  integer, value :: x, y, z
+end
+end module m
diff --git a/gcc/testsuite/gfortran.dg/gomp/linear-4.f90 b/gcc/testsuite/gfortran.dg/gomp/linear-4.f90
new file mode 100644
index 00000000000..f041bce7e35
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/linear-4.f90
@@ -0,0 +1,102 @@
+! { dg-do compile }
+! { dg-options "-fopenmp" }
+
+module m
+implicit none
+
+integer :: i
+
+interface
+  integer function bar (x,  y, z)
+    integer :: x, y
+    integer, value :: z
+    !!$omp declare simd linear (x : ref, step (1)) linear (y : step (2), uval)
+  end
+
+  integer function baz (x, y, z)
+    integer :: x
+    integer, value :: y, z
+    !!$omp declare simd linear (x : step (1), uval)
+  end
+
+  integer function qux (x, ref)
+    integer :: x
+    integer, value :: ref
+    !!$omp declare simd linear (ref (x) : ref) uniform (ref)
+  end
+
+  integer function corge (x, ref)
+    integer :: x
+    integer, value :: ref
+    !!$omp declare simd linear (x : ref, step (ref)) uniform (ref)
+  end
+
+  integer function grault (x)
+    integer :: x
+    !$omp declare simd linear (x : ref)
+  end
+
+  integer function waldo (x)
+    integer :: x
+    !$omp declare simd linear (x : uval)
+  end
+end interface
+
+contains
+
+integer function step (x)
+  integer, value :: x
+  step = x
+end
+
+subroutine foo (x, y)
+  integer :: x, y
+  !$omp simd linear (x: step (y + 1))
+  do i = 0, 9
+    x = x + y + 1
+  end do
+
+  !$omp simd linear (x: val, step (y + 1))
+  do i = 0, 9
+    x = x + y + 1
+  end do
+
+  !$omp parallel do linear (x: step (y + 1))
+  do i = 0, 9
+    x = x + y + 1
+  end do
+
+  !$omp parallel do linear (x: step (y + 1), val)
+  do i = 0, 9
+    x = x + y + 1
+  end do
+
+  !$omp parallel do simd linear (x: step (y + 1))
+  do i = 0, 9
+    x = x + y + 1
+  end do
+
+  !$omp parallel do simd linear (x: val, step (y + 1))
+  do i = 0, 9
+    x = x + y + 1
+  end do
+
+  !$omp parallel do simd linear (x: step (1) + 0)
+  do i = 0, 9
+    x = x + step (1) + 0
+  end do
+
+  block
+    integer, parameter :: ref = 1, uval = 2
+    !$omp parallel do simd linear (x: ref + 0)
+    do i = 0, 9
+      x = x + ref + 0
+    end do
+
+    !$omp parallel do simd linear (x: uval * 1)
+    do i = 0, 9
+      x = x + uval
+    end do
+  end block
+end
+end
diff --git a/gcc/testsuite/gfortran.dg/gomp/linear-5.f90 b/gcc/testsuite/gfortran.dg/gomp/linear-5.f90
new file mode 100644
index 00000000000..b00492d4b58
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/linear-5.f90
@@ -0,0 +1,43 @@
+! { dg-do compile }
+! { dg-options "-fopenmp" }
+
+module m
+implicit none
+integer :: i
+
+contains
+
+subroutine foo (x, y)
+  integer :: x, y
+
+  !$omp simd linear (x: step (y + 1), ref)		! { dg-error "LINEAR clause modifier other than VAL used on DO or SIMD construct" }
+  do i = 0, 10
+    x = x + y + 1
+  end do
+
+  !$omp simd linear (x: uval, step (y + 1))		! { dg-error "LINEAR clause modifier other than VAL used on DO or SIMD construct" }
+  do i = 0, 10
+    x = x + y + 1
+  end do
+
+  !$omp parallel do linear (x: ref, step (y + 1))	! { dg-error "LINEAR clause modifier other than VAL used on DO or SIMD construct" }
+  do i = 0, 10
+    x = x + y + 1
+  end do
+
+  !$omp parallel do linear (x: step (y + 1), uval)	! { dg-error "LINEAR clause modifier other than VAL used on DO or SIMD construct" }
+  do i = 0, 10
+    x = x + y + 1
+  end do
+
+  !$omp parallel do simd linear (x: step (y + 1), ref)	! { dg-error "LINEAR clause modifier other than VAL used on DO or SIMD construct" }
+  do i = 0, 10
+    x = x + y + 1
+  end do
+
+  !$omp parallel do simd linear (x: uval, step (y + 1))	! { dg-error "LINEAR clause modifier other than VAL used on DO or SIMD construct" }
+  do i = 0, 10
+    x = x + y + 1
+  end do
+end
+end
diff --git a/gcc/testsuite/gfortran.dg/gomp/linear-6.f90 b/gcc/testsuite/gfortran.dg/gomp/linear-6.f90
new file mode 100644
index 00000000000..57693ba6de1
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/linear-6.f90
@@ -0,0 +1,54 @@
+! { dg-do compile }
+! { dg-options "-fopenmp" }
+
+module m
+implicit none
+integer, parameter :: val = 1
+integer, parameter :: ref = 2
+integer, parameter :: uval = 3
+
+interface
+  integer function foo (x, y, z)
+    import
+    implicit none
+    integer, value :: x
+    integer :: y, z
+    !$omp declare simd linear (val (x) : step (1)) linear (ref (y) : step (2)) linear (uval (z) : step (3))
+
+! STEP is a function - thus:
+! { dg-error "'x' in LINEAR clause at .1. requires a constant integer linear-step expression or dummy argument specified in UNIFORM clause" "" { target *-*-* } .-3 }
+! { dg-error "'y' in LINEAR clause at .1. requires a constant integer linear-step expression or dummy argument specified in UNIFORM clause" "" { target *-*-* } .-4 }
+! { dg-error "'z' in LINEAR clause at .1. requires a constant integer linear-step expression or dummy argument specified in UNIFORM clause" "" { target *-*-* } .-5 }
+
+  end
+
+  integer function bar (x, y, z)
+    import
+    implicit none
+    integer, value :: x
+    integer :: y, z
+    !$omp declare simd linear (val (x) : val) linear (ref (y) : ref) linear (uval (z) : uval)
+  end
+
+  integer function baz (x, y, z)
+    import
+    implicit none
+    integer, value :: x
+    integer :: y, z
+    !$omp declare simd linear (val (x) : ref) linear (ref (y) : uval) linear (uval (z) : val)
+  end
+
+  integer function qux (x, y, z)
+    import
+    implicit none
+    integer, value :: x
+    integer :: y, z
+    !$omp declare simd linear (val (x) : uval) linear (ref (y) : val) linear (uval (z) : ref)
+  end
+end interface
+contains
+  integer function step (x)
+    integer, value :: x
+     step = x
+  end
+end module
diff --git a/gcc/testsuite/gfortran.dg/gomp/linear-7.f90 b/gcc/testsuite/gfortran.dg/gomp/linear-7.f90
new file mode 100644
index 00000000000..5e763a92ca6
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/linear-7.f90
@@ -0,0 +1,27 @@
+! { dg-do compile }
+! { dg-options "-fopenmp" }
+
+module m
+  implicit none (type, external)
+
+  integer i
+
+  interface
+    integer function s1 (x, y, z)
+      integer, value :: x, y, z
+      !$omp declare simd linear (x : val, step (1), val)  ! { dg-error "Multiple 'linear' modifiers specified" }
+    end
+
+    integer function s2 (x, y, z)
+      integer, value :: x, y, z
+      !$omp declare simd linear (x : val, step (1), step(2))  ! { dg-error "Multiple 'step' modifiers specified" }
+    end
+
+    integer function s3 (x, y, z)
+      integer, value :: x, y, z
+      !$omp declare simd linear (x : val, ref, step(2))  ! { dg-error "Multiple 'linear' modifiers specified" }
+    end
+
+  end interface
+
+end module
diff --git a/libgomp/libgomp.texi b/libgomp/libgomp.texi
index 39426ff7fbf..e88fe89a5b1 100644
--- a/libgomp/libgomp.texi
+++ b/libgomp/libgomp.texi
@@ -363,7 +363,7 @@ to address of matching mapped list item per 5.1, Sect. 2.21.7.2 @tab N @tab
 @item Clauses on @code{end} directive can be on directive @tab N @tab
 @item Deprecation of no-argument @code{destroy} clause on @code{depobj}
       @tab N @tab
-@item @code{linear} clause syntax changes and @code{step} modifier @tab P @tab only C/C++
+@item @code{linear} clause syntax changes and @code{step} modifier @tab Y @tab
 @item Deprecation of minus operator for reductions @tab N @tab
 @item Deprecation of separating @code{map} modifiers without comma @tab N @tab
 @item @code{declare mapper} with iterator and @code{present} modifiers

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2022-07-04 19:09 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-07-04 14:10 [Patch] OpenMP/Fortran: Add support for OpenMP 5.2 linear clause syntax Tobias Burnus
2022-07-04 14:53 ` Jakub Jelinek
2022-07-04 16:09   ` Tobias Burnus
2022-07-04 17:20     ` Jakub Jelinek
2022-07-04 18:29       ` Tobias Burnus
2022-07-04 19:08         ` 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).