* [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
* Re: [Patch] OpenMP/Fortran: Add support for OpenMP 5.2 linear clause syntax
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
0 siblings, 1 reply; 6+ messages in thread
From: Jakub Jelinek @ 2022-07-04 14:53 UTC (permalink / raw)
To: Tobias Burnus; +Cc: gcc-patches, fortran
On Mon, Jul 04, 2022 at 04:10:03PM +0200, Tobias Burnus wrote:
> 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
See OpenMP 5.2 [59:31-34]:
A modifier that is an expression must neither lexically match the name of a simple modifier
defined for the clause that is an OpenMP keyword nor modifier-name parenthesized-tokens,
where modifier-name is the modifier-name of a complex modifier defined for the clause and
parenthesized-tokens is a token sequence that starts with ( and ends with ).
So, ref can't be step expression because it lexically matches the name of a
simple modifier, so linear (var : ref) is equivalent to old style linear (ref (var):1)
while e.g. linear (var : ref + 0) is equivalent to linear (var : step (ref + 0))
> + 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)
> + {
So, if you see val ) even right after colon (when !old_linear_modifiers), it is
always linear modifier, so the if (!has_modifiers) looks wrong.
> + 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 ("uval )") == MATCH_YES)
> + {
Likewise.
> + if (!has_modifiers)
> + else if (gfc_match ("ref )") == MATCH_YES)
> + {
And again.
> + if (!has_modifiers)
> + else if (gfc_match ("step ( ") == MATCH_YES)
> + {
step ( could start both valid step expression and be a valid modifier.
But that decision shouldn't be based on whether there is a step symtree or
not, but whether it is step ( whatever ) ) or step ( whatever ) ,
(in that case it should be parsed as the complex modifier with expression
in it), otherwise it is parsed as step expression.
The whatever above means some tokens with balanced parentheses.
I doubt the Fortran FE has something like that right now.
You can certainly try to match "step ( %e ) )" or "step ( %e ) , " first,
those would handle the case of valid complex modifier.
But, I think if there is
interface
integer function step (x, y, z)
integer :: x, y, z
end function step
end interface
then
linear (v : step (x, y, z))
should be rejected, not accepted as valid
linear (v : step (step (x, y, z)))
I think I should add:
int step (int x, int y, int z) { return x + y + z; }
int
foo (int x)
{
int i;
#pragma omp parallel for linear (x : step (step (1, 2, 3)))
for (i = 0; i < 64; i++)
x += 6;
return x;
}
int
bar (int x)
{
int i;
#pragma omp parallel for linear (x : step (1, 2, 3)) /* { dg-error "expected" } */
for (i = 0; i < 64; i++)
x += 6;
return x;
}
as another testcase (where foo used to be invalid before and bar used to be
valid).
Jakub
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [Patch] OpenMP/Fortran: Add support for OpenMP 5.2 linear clause syntax
2022-07-04 14:53 ` Jakub Jelinek
@ 2022-07-04 16:09 ` Tobias Burnus
2022-07-04 17:20 ` Jakub Jelinek
0 siblings, 1 reply; 6+ messages in thread
From: Tobias Burnus @ 2022-07-04 16:09 UTC (permalink / raw)
To: Jakub Jelinek; +Cc: gcc-patches, fortran
[-- Attachment #1: Type: text/plain, Size: 2194 bytes --]
Hi Jakub,
thanks for the comment & spec referral. I have now updated the patch –
and included the new C/Fortran testcase.
On 04.07.22 16:53, Jakub Jelinek via Fortran wrote:
> See OpenMP 5.2 [59:31-34]:
> A modifier that is an expression must neither lexically match the name of a simple modifier
> defined for the clause that is an OpenMP keyword nor modifier-name parenthesized-tokens,
> where modifier-name is the modifier-name of a complex modifier defined for the clause and
> parenthesized-tokens is a token sequence that starts with ( and ends with ).
>
> So, ref can't be step expression because it lexically matches the name of a
> simple modifier, so linear (var : ref) is equivalent to old style linear (ref (var):1)
> while e.g. linear (var : ref + 0) is equivalent to linear (var : step (ref + 0))
I see.
> You can certainly try to match "step ( %e ) )" or "step ( %e ) , " first,
> those would handle the case of valid complex modifier.
Done so + plus some more massage in order to support the following,
added as C/Fortran testcase:
> But, I think if there is
> interface
> integer function step (x, y, z)
> integer :: x, y, z
> end function step
> end interface
> then
> linear (v : step (x, y, z))
> should be rejected, not accepted as valid
> linear (v : step (step (x, y, z)))
>
> I think I should add:
> int step (int x, int y, int z) { return x + y + z; }
>
> int
> foo (int x)
> {
> int i;
> #pragma omp parallel for linear (x : step (step (1, 2, 3)))
> for (i = 0; i < 64; i++)
> x += 6;
> return x;
> }
>
> int
> bar (int x)
> {
> int i;
> #pragma omp parallel for linear (x : step (1, 2, 3)) /* { dg-error "expected" } */
> for (i = 0; i < 64; i++)
> x += 6;
> return x;
> }
> as another testcase (where foo used to be invalid before and bar used to be
> valid).
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-v2.diff --]
[-- Type: text/x-patch, Size: 26288 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:
* c-c++-common/gomp/linear-4.c: New test.
* 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.
* gfortran.dg/gomp/linear-8.f90: New test.
Co-authored-by: Jakub Jelinek <jakub@redhat.com>
gcc/fortran/dump-parse-tree.cc | 6 +-
gcc/fortran/gfortran.h | 6 +-
gcc/fortran/module.cc | 6 +-
gcc/fortran/openmp.cc | 192 +++++++++++++++++++++++++---
gcc/fortran/trans-openmp.cc | 5 +-
gcc/testsuite/c-c++-common/gomp/linear-4.c | 24 ++++
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 ++++
gcc/testsuite/gfortran.dg/gomp/linear-8.f90 | 34 +++++
libgomp/libgomp.texi | 2 +-
14 files changed, 622 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..f2c0202e440 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,143 @@ 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)
+ else if (end_colon)
+ {
+ bool has_error = false;
+ bool has_modifiers = false;
+ bool has_step = false;
+ bool duplicate_step = false;
+ bool duplicate_mod = false;
+ while (true)
+ {
+ old_loc = gfc_current_locus;
+ if (gfc_match ("val )") == MATCH_YES)
+ {
+ 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 (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 (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 ( %e ) )", &step) == MATCH_YES)
+ {
+ if (has_step)
+ {
+ duplicate_step = true;
+ break;
+ }
+ has_modifiers = has_step = true;
+ break;
+ }
+ else if (gfc_match ("step ( %e ) , ", &step) == MATCH_YES)
+ {
+ if (has_step)
+ {
+ duplicate_step = true;
+ break;
+ }
+ has_modifiers = has_step = true;
+ continue;
+ }
+ else if (!has_modifiers
+ && gfc_match ("%e )", &step) == MATCH_YES)
+ {
+ if ((step->expr_type == EXPR_FUNCTION
+ || step->expr_type == EXPR_VARIABLE)
+ && strcmp (step->symtree->name, "step") == 0)
+ {
+ gfc_current_locus = old_loc;
+ gfc_match ("step (");
+ has_error = true;
+ }
+ break;
+ }
+ has_error = true;
+ break;
+ }
+ if (duplicate_mod || duplicate_step)
+ {
+ gfc_error ("Multiple %qs modifiers specified at %C",
+ duplicate_mod ? "linear" : "step");
+ has_error = true;
+ }
+ if (has_error)
+ {
+ gfc_free_omp_namelist (*head, false);
+ *head = NULL;
+ goto error;
+ }
+ }
+ else
{
step = gfc_get_constant_expr (BT_INTEGER,
gfc_default_integer_kind,
@@ -2379,9 +2518,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 +7581,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/c-c++-common/gomp/linear-4.c b/gcc/testsuite/c-c++-common/gomp/linear-4.c
new file mode 100644
index 00000000000..1e595213c38
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/linear-4.c
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+/* { dg-options "-fopenmp" } */
+
+int step (int x, int y, int z) { return x + y + z; }
+
+int
+foo (int x)
+{
+ int i;
+ #pragma omp parallel for linear (x : step (step (1, 2, 3)))
+ for (i = 0; i < 64; i++)
+ x += 6;
+ return x;
+}
+
+int
+bar (int x)
+{
+ int i;
+ #pragma omp parallel for linear (x : step (1, 2, 3)) /* { dg-error "expected" } */
+ for (i = 0; i < 64; i++)
+ x += 6;
+ return x;
+}
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..05f007fd5c2
--- /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:3\\)" 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..51c41b3aad9
--- /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/gcc/testsuite/gfortran.dg/gomp/linear-8.f90 b/gcc/testsuite/gfortran.dg/gomp/linear-8.f90
new file mode 100644
index 00000000000..3274a5bd1e4
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/linear-8.f90
@@ -0,0 +1,34 @@
+! { dg-do compile }
+! { dg-options "-fopenmp" }
+
+module m
+ implicit none (type, external)
+
+ interface
+ integer function step (x, y, z)
+ integer :: x, y, z
+ end function step
+ end interface
+
+contains
+
+integer function foo (x)
+ integer, value :: x
+ integer :: i
+ !$omp parallel do linear (x : step (step (1, 2, 3)))
+ do i = 0, 63
+ x = x + 6
+ end do
+ foo = x
+end
+
+integer function bar (x)
+ integer, value :: x
+ integer :: i
+ !$omp parallel do linear (x : step (1, 2, 3)) ! { dg-error "40: Invalid character in name" }
+ do i = 0, 63
+ x = x + 6
+ end do
+ bar = x
+end
+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
* Re: [Patch] OpenMP/Fortran: Add support for OpenMP 5.2 linear clause syntax
2022-07-04 16:09 ` Tobias Burnus
@ 2022-07-04 17:20 ` Jakub Jelinek
2022-07-04 18:29 ` Tobias Burnus
0 siblings, 1 reply; 6+ messages in thread
From: Jakub Jelinek @ 2022-07-04 17:20 UTC (permalink / raw)
To: Tobias Burnus; +Cc: gcc-patches, fortran
On Mon, Jul 04, 2022 at 06:09:31PM +0200, Tobias Burnus wrote:
> thanks for the comment & spec referral. I have now updated the patch –
> and included the new C/Fortran testcase.
Thanks.
> + while (true)
> + {
> + old_loc = gfc_current_locus;
> + if (gfc_match ("val )") == MATCH_YES)
> + {
> + 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;
> + }
Perhaps you could avoid some code duplication by doing it like:
bool close_paren = gfc_match ("val )") == MATCH_YES;
if (close_paren || gfc_match ("val , ") == MATCH_YES)
{
if (linear_op != OMP_LINEAR_DEFAULT)
{
duplicate_mod = true;
break;
}
linear_op = OMP_LINEAR_VAL;
has_modifiers = true;
if (close_paren)
break;
else
continue;
}
and similarly for uval and ref.
> + else if (!has_modifiers
> + && gfc_match ("%e )", &step) == MATCH_YES)
> + {
> + if ((step->expr_type == EXPR_FUNCTION
> + || step->expr_type == EXPR_VARIABLE)
> + && strcmp (step->symtree->name, "step") == 0)
> + {
> + gfc_current_locus = old_loc;
> + gfc_match ("step (");
> + has_error = true;
> + }
I think the above should accept even
linear (v : step (1) + 0) or linear (v : step (1, 2, 3) * 1)
which is desirable, because step then will be some other operation (hope
folding isn't performed yet).
> --- /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)
Are all these !! intentional?
The test then doesn't test much.
Or is that a FIXME?
Jakub
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [Patch] OpenMP/Fortran: Add support for OpenMP 5.2 linear clause syntax
2022-07-04 17:20 ` Jakub Jelinek
@ 2022-07-04 18:29 ` Tobias Burnus
2022-07-04 19:08 ` Jakub Jelinek
0 siblings, 1 reply; 6+ messages in thread
From: Tobias Burnus @ 2022-07-04 18:29 UTC (permalink / raw)
To: Jakub Jelinek; +Cc: gcc-patches, fortran
[-- Attachment #1: Type: text/plain, Size: 1834 bytes --]
On 04.07.22 19:20, Jakub Jelinek wrote:
> Perhaps you could avoid some code duplication by doing it like:
> bool close_paren = gfc_match ("val )") == MATCH_YES;
> if (close_paren || gfc_match ("val , ") == MATCH_YES)
Done!
Good idea! I was thinking of things like ...peek_char() but that takes
the next char and not the last one; but your method works.
>> + else if (!has_modifiers
>> + && gfc_match ("%e )", &step) == MATCH_YES)
>> + {
>> + if ((step->expr_type == EXPR_FUNCTION
>> + || step->expr_type == EXPR_VARIABLE)
>> + && strcmp (step->symtree->name, "step") == 0)
>> + {
>> + gfc_current_locus = old_loc;
>> + gfc_match ("step (");
>> + has_error = true;
>> + }
> I think the above should accept even
> linear (v : step (1) + 0) or linear (v : step (1, 2, 3) * 1)
> which is desirable, because step then will be some other operation (hope
> folding isn't performed yet).
Well, it does. In that case expr_type == EXPR_OP. I added the latter to
the C/C++ and the Fortran testcase.
>> + !!$omp declare simd linear (x : ref, step (1)) linear (y : step (2), uval)
> Are all these !! intentional?
No – just a missed undo after debugging. It worked/works after changing
it back to '!'.
Revised version attached.
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-v3.diff --]
[-- Type: text/x-patch, Size: 26096 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:
* c-c++-common/gomp/linear-4.c: New test.
* 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.
* gfortran.dg/gomp/linear-8.f90: New test.
Co-authored-by: Jakub Jelinek <jakub@redhat.com>
gcc/fortran/dump-parse-tree.cc | 6 +-
gcc/fortran/gfortran.h | 6 +-
gcc/fortran/module.cc | 6 +-
gcc/fortran/openmp.cc | 163 ++++++++++++++++++++++++----
gcc/fortran/trans-openmp.cc | 5 +-
gcc/testsuite/c-c++-common/gomp/linear-4.c | 34 ++++++
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 +++++
gcc/testsuite/gfortran.dg/gomp/linear-8.f90 | 44 ++++++++
libgomp/libgomp.texi | 2 +-
14 files changed, 613 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..bd4ff259fe0 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,114 @@ 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)
+ else if (end_colon)
+ {
+ bool has_error = false;
+ bool has_modifiers = false;
+ bool has_step = false;
+ bool duplicate_step = false;
+ bool duplicate_mod = false;
+ while (true)
+ {
+ old_loc = gfc_current_locus;
+ bool close_paren = gfc_match ("val )") == MATCH_YES;
+ if (close_paren || gfc_match ("val , ") == MATCH_YES)
+ {
+ if (linear_op != OMP_LINEAR_DEFAULT)
+ {
+ duplicate_mod = true;
+ break;
+ }
+ linear_op = OMP_LINEAR_VAL;
+ has_modifiers = true;
+ if (close_paren)
+ break;
+ continue;
+ }
+ close_paren = gfc_match ("uval )") == MATCH_YES;
+ if (close_paren || gfc_match ("uval , ") == MATCH_YES)
+ {
+ if (linear_op != OMP_LINEAR_DEFAULT)
+ {
+ duplicate_mod = true;
+ break;
+ }
+ linear_op = OMP_LINEAR_UVAL;
+ has_modifiers = true;
+ if (close_paren)
+ break;
+ continue;
+ }
+ close_paren = gfc_match ("ref )") == MATCH_YES;
+ if (close_paren || gfc_match ("ref , ") == MATCH_YES)
+ {
+ if (linear_op != OMP_LINEAR_DEFAULT)
+ {
+ duplicate_mod = true;
+ break;
+ }
+ linear_op = OMP_LINEAR_REF;
+ has_modifiers = true;
+ if (close_paren)
+ break;
+ continue;
+ }
+ close_paren = (gfc_match ("step ( %e ) )", &step)
+ == MATCH_YES);
+ if (close_paren
+ || gfc_match ("step ( %e ) , ", &step) == MATCH_YES)
+ {
+ if (has_step)
+ {
+ duplicate_step = true;
+ break;
+ }
+ has_modifiers = has_step = true;
+ if (close_paren)
+ break;
+ continue;
+ }
+ if (!has_modifiers
+ && gfc_match ("%e )", &step) == MATCH_YES)
+ {
+ if ((step->expr_type == EXPR_FUNCTION
+ || step->expr_type == EXPR_VARIABLE)
+ && strcmp (step->symtree->name, "step") == 0)
+ {
+ gfc_current_locus = old_loc;
+ gfc_match ("step (");
+ has_error = true;
+ }
+ break;
+ }
+ has_error = true;
+ break;
+ }
+ if (duplicate_mod || duplicate_step)
+ {
+ gfc_error ("Multiple %qs modifiers specified at %C",
+ duplicate_mod ? "linear" : "step");
+ has_error = true;
+ }
+ if (has_error)
+ {
+ gfc_free_omp_namelist (*head, false);
+ *head = NULL;
+ goto error;
+ }
+ }
+ else
{
step = gfc_get_constant_expr (BT_INTEGER,
gfc_default_integer_kind,
@@ -2379,9 +2489,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 +7552,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/c-c++-common/gomp/linear-4.c b/gcc/testsuite/c-c++-common/gomp/linear-4.c
new file mode 100644
index 00000000000..59c22b8f86b
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/linear-4.c
@@ -0,0 +1,34 @@
+/* { dg-do compile } */
+/* { dg-options "-fopenmp" } */
+
+int step (int x, int y, int z) { return x + y + z; }
+
+int
+foo (int x)
+{
+ int i;
+ #pragma omp parallel for linear (x : step (step (1, 2, 3)))
+ for (i = 0; i < 64; i++)
+ x += 6;
+ return x;
+}
+
+int
+bar (int x)
+{
+ int i;
+ #pragma omp parallel for linear (x : step (1, 2, 3)) /* { dg-error "expected" } */
+ for (i = 0; i < 64; i++)
+ x += 6;
+ return x;
+}
+
+int
+bar2 (int x)
+{
+ int i;
+ #pragma omp parallel for linear (x : step (1, 2, 3) * 1)
+ for (i = 0; i < 64; i++)
+ x += 6;
+ return x;
+}
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..05f007fd5c2
--- /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:3\\)" 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..ac532f81000
--- /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/gcc/testsuite/gfortran.dg/gomp/linear-8.f90 b/gcc/testsuite/gfortran.dg/gomp/linear-8.f90
new file mode 100644
index 00000000000..d23dd84b3ed
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/linear-8.f90
@@ -0,0 +1,44 @@
+! { dg-do compile }
+! { dg-options "-fopenmp" }
+
+module m
+ implicit none (type, external)
+
+ interface
+ integer function step (x, y, z)
+ integer :: x, y, z
+ end function step
+ end interface
+
+contains
+
+integer function foo (x)
+ integer, value :: x
+ integer :: i
+ !$omp parallel do linear (x : step (step (1, 2, 3)))
+ do i = 0, 63
+ x = x + 6
+ end do
+ foo = x
+end
+
+integer function bar (x)
+ integer, value :: x
+ integer :: i
+ !$omp parallel do linear (x : step (1, 2, 3)) ! { dg-error "40: Invalid character in name" }
+ do i = 0, 63
+ x = x + 6
+ end do
+ bar = x
+end
+
+integer function bar2 (x)
+ integer, value :: x
+ integer :: i
+ !$omp parallel do linear (x : step (1, 2, 3) * 1)
+ do i = 0, 63
+ x = x + 6
+ end do
+ bar2 = x
+end
+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
* Re: [Patch] OpenMP/Fortran: Add support for OpenMP 5.2 linear clause syntax
2022-07-04 18:29 ` Tobias Burnus
@ 2022-07-04 19:08 ` Jakub Jelinek
0 siblings, 0 replies; 6+ messages in thread
From: Jakub Jelinek @ 2022-07-04 19:08 UTC (permalink / raw)
To: Tobias Burnus; +Cc: gcc-patches, fortran
On Mon, Jul 04, 2022 at 08:29:37PM +0200, Tobias Burnus wrote:
> 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:
>
> * c-c++-common/gomp/linear-4.c: New test.
> * 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.
> * gfortran.dg/gomp/linear-8.f90: New test.
Ok, thanks.
Jakub
^ 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).