* [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).