aboutsummaryrefslogtreecommitdiff
path: root/gcc/fortran
diff options
context:
space:
mode:
authorTobias Burnus <tobias@codesourcery.com>2022-07-04 21:50:23 +0200
committerTobias Burnus <tobias@codesourcery.com>2022-07-04 21:50:23 +0200
commitc3297044f0055880dd23ffbf641aa3a5860197e1 (patch)
tree528d5fb4cc80e005f3eb7ac7c9f06f394fc94bb5 /gcc/fortran
parentce8dbe7d834b9264d7a5cd74d3ce6c750d28b3af (diff)
downloadgcc-c3297044f0055880dd23ffbf641aa3a5860197e1.zip
gcc-c3297044f0055880dd23ffbf641aa3a5860197e1.tar.gz
gcc-c3297044f0055880dd23ffbf641aa3a5860197e1.tar.bz2
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>
Diffstat (limited to 'gcc/fortran')
-rw-r--r--gcc/fortran/dump-parse-tree.cc6
-rw-r--r--gcc/fortran/gfortran.h6
-rw-r--r--gcc/fortran/module.cc6
-rw-r--r--gcc/fortran/openmp.cc163
-rw-r--r--gcc/fortran/trans-openmp.cc5
5 files changed, 157 insertions, 29 deletions
diff --git a/gcc/fortran/dump-parse-tree.cc b/gcc/fortran/dump-parse-tree.cc
index 85c0b98..5352008 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 463d969..696aadd 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 85aa153..5ddabdc 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 51b429a..bd4ff25 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 c6a584d..de27ed5 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)