diff --git a/gcc/c-family/c-pragma.h b/gcc/c-family/c-pragma.h index c95a602a47568c325e21207579f47cd0eb62d350..df5625d5f4f01823012690cae741a62e9ca39f7e 100644 --- a/gcc/c-family/c-pragma.h +++ b/gcc/c-family/c-pragma.h @@ -134,6 +134,7 @@ enum pragma_omp_clause { PRAGMA_OMP_CLAUSE_INDIRECT, PRAGMA_OMP_CLAUSE_INIT, PRAGMA_OMP_CLAUSE_IS_DEVICE_PTR, + PRAGMA_OMP_CLAUSE_INTEROP, PRAGMA_OMP_CLAUSE_LASTPRIVATE, PRAGMA_OMP_CLAUSE_LINEAR, PRAGMA_OMP_CLAUSE_LINK, diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc index ca4a6b39b2765a9484a7f1cbfcccf2db7ba13f8c..f3ed61047477ca5816bf825ae92049ede9e0c5d4 100644 --- a/gcc/c/c-parser.cc +++ b/gcc/c/c-parser.cc @@ -15786,6 +15786,8 @@ c_parser_omp_clause_name (c_parser *parser) result = PRAGMA_OMP_CLAUSE_INIT; else if (!strcmp ("is_device_ptr", p)) result = PRAGMA_OMP_CLAUSE_IS_DEVICE_PTR; + else if (!strcmp ("interop", p)) + result = PRAGMA_OMP_CLAUSE_INTEROP; break; case 'l': if (!strcmp ("lastprivate", p)) @@ -20569,6 +20571,16 @@ c_parser_omp_clause_use (c_parser *parser, tree list) return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_USE, list); } +/* OpenMP 6.0: + interop ( variable-list ) */ + +static tree +c_parser_omp_clause_interop (c_parser *parser, tree list) +{ + check_no_duplicate_clause (list, OMP_CLAUSE_INTEROP, "interop"); + return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_INTEROP, list); +} + /* Parse all OpenACC clauses. The set clauses allowed by the directive is a bitmask in MASK. Return the list of clauses found. */ @@ -21076,6 +21088,10 @@ c_parser_omp_all_clauses (c_parser *parser, omp_clause_mask mask, clauses = c_parser_omp_clause_use (parser, clauses); c_name = "use"; break; + case PRAGMA_OMP_CLAUSE_INTEROP: + clauses = c_parser_omp_clause_interop (parser, clauses); + c_name = "interop"; + break; case PRAGMA_OMP_CLAUSE_MAP: clauses = c_parser_omp_clause_map (parser, clauses); c_name = "map"; @@ -25078,6 +25094,7 @@ c_parser_omp_dispatch_body (c_parser *parser) | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOVARIANTS) \ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOCONTEXT) \ + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_INTEROP) \ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IS_DEVICE_PTR) \ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT)) diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc index f6f63ca7980ebe25fea8ef8af84f498c94e8e3e7..970fe68434b78df72a979c9f42d79c0616744108 100644 --- a/gcc/c/c-typeck.cc +++ b/gcc/c/c-typeck.cc @@ -17091,16 +17091,27 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort) error_at (OMP_CLAUSE_LOCATION (c), "%qD appears more than once in action clauses", t); remove = true; + break; } - else if (/* ort == C_ORT_OMP_INTEROP [uncomment for depobj init] */ + bitmap_set_bit (&generic_head, DECL_UID (t)); + /* FALLTHRU */ + case OMP_CLAUSE_INTEROP: + if (/* ort == C_ORT_OMP_INTEROP [uncomment for depobj init] */ !c_omp_interop_t_p (TREE_TYPE (OMP_CLAUSE_DECL (c)))) - error_at (OMP_CLAUSE_LOCATION (c), - "%qD must be of %<omp_interop_t%>", OMP_CLAUSE_DECL (c)); - else if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_USE + { + error_at (OMP_CLAUSE_LOCATION (c), + "%qD must be of %<omp_interop_t%>", + OMP_CLAUSE_DECL (c)); + remove = true; + } + else if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_INIT + || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DESTROY) && TREE_READONLY (OMP_CLAUSE_DECL (c))) - error_at (OMP_CLAUSE_LOCATION (c), + { + error_at (OMP_CLAUSE_LOCATION (c), "%qD shall not be const", OMP_CLAUSE_DECL (c)); - bitmap_set_bit (&generic_head, DECL_UID (t)); + remove = true; + } pc = &OMP_CLAUSE_CHAIN (c); break; default: diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc index fa9945b07da6b394fae70c834507feed112f86dd..f449ebde744a7114892da5afa5aff5682d2ecb43 100644 --- a/gcc/cp/parser.cc +++ b/gcc/cp/parser.cc @@ -38335,6 +38335,8 @@ cp_parser_omp_clause_name (cp_parser *parser) result = PRAGMA_OMP_CLAUSE_INDIRECT; else if (!strcmp ("init", p)) result = PRAGMA_OMP_CLAUSE_INIT; + else if (!strcmp ("interop", p)) + result = PRAGMA_OMP_CLAUSE_INTEROP; else if (!strcmp ("is_device_ptr", p)) result = PRAGMA_OMP_CLAUSE_IS_DEVICE_PTR; break; @@ -43336,6 +43338,13 @@ cp_parser_omp_all_clauses (cp_parser *parser, omp_clause_mask mask, clauses = cp_parser_omp_var_list (parser, OMP_CLAUSE_USE, clauses); c_name = "use"; break; + case PRAGMA_OMP_CLAUSE_INTEROP: + check_no_duplicate_clause (clauses, OMP_CLAUSE_INTEROP, "interop", + token->location); + clauses = cp_parser_omp_var_list (parser, OMP_CLAUSE_INTEROP, + clauses); + c_name = "interop"; + break; case PRAGMA_OMP_CLAUSE_DETACH: clauses = cp_parser_omp_clause_detach (parser, clauses); c_name = "detach"; @@ -49728,6 +49737,7 @@ cp_parser_omp_dispatch_body (cp_parser *parser) | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOVARIANTS) \ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOCONTEXT) \ + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_INTEROP) \ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IS_DEVICE_PTR) \ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT)) diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc index 74d0d86f560148cb78b4dbd8592d3a12e2e43014..5b7918805a38e1c0c919c1e1ccc7be6ee6ec676e 100644 --- a/gcc/cp/pt.cc +++ b/gcc/cp/pt.cc @@ -17893,6 +17893,7 @@ tsubst_omp_clauses (tree clauses, enum c_omp_region_type ort, /* FALLTHRU */ case OMP_CLAUSE_DESTROY: case OMP_CLAUSE_USE: + case OMP_CLAUSE_INTEROP: OMP_CLAUSE_OPERAND (nc, 0) = tsubst_stmt (OMP_CLAUSE_OPERAND (oc, 0), args, complain, in_decl); break; diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc index 328de3965c9e5aa31b38289726f716df853b182f..d58dd022463193cace488bc60287247adda8505e 100644 --- a/gcc/cp/semantics.cc +++ b/gcc/cp/semantics.cc @@ -9448,20 +9448,31 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) error_at (OMP_CLAUSE_LOCATION (c), "%qD appears more than once in action clauses", t); remove = true; + break; } + bitmap_set_bit (&generic_head, DECL_UID (t)); + /* FALLTHRU */ + case OMP_CLAUSE_INTEROP: if (!processing_template_decl) { - if (/* ort == C_ORT_OMP_INTEROP [uncomment for depobj init] */ - !c_omp_interop_t_p (TREE_TYPE (OMP_CLAUSE_DECL (c)))) - error_at (OMP_CLAUSE_LOCATION (c), - "%qD must be of %<omp_interop_t%>", - OMP_CLAUSE_DECL (c)); - else if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_USE + if (/* (ort == C_ORT_OMP_INTEROP [uncomment for depobj init] + || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_INTEROP) && */ + !c_omp_interop_t_p (TREE_TYPE (OMP_CLAUSE_DECL (c)))) + { + error_at (OMP_CLAUSE_LOCATION (c), + "%qD must be of %<omp_interop_t%>", + OMP_CLAUSE_DECL (c)); + remove = true; + } + else if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_INIT + || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DESTROY) && TREE_READONLY (OMP_CLAUSE_DECL (c))) - error_at (OMP_CLAUSE_LOCATION (c), - "%qD shall not be const", OMP_CLAUSE_DECL (c)); + { + error_at (OMP_CLAUSE_LOCATION (c), + "%qD shall not be const", OMP_CLAUSE_DECL (c)); + remove = true; + } } - bitmap_set_bit (&generic_head, DECL_UID (t)); pc = &OMP_CLAUSE_CHAIN (c); break; default: diff --git a/gcc/gimplify.cc b/gcc/gimplify.cc index d6612a845de809022cc3e58b806f4c5d6e510371..7b2466a2e34f0bdba6b0da6918ee791821e7a1c2 100644 --- a/gcc/gimplify.cc +++ b/gcc/gimplify.cc @@ -4071,6 +4071,20 @@ gimplify_call_expr (tree *expr_p, gimple_seq *pre_p, bool want_value) vars there. */ bool returns_twice = call_expr_flags (*expr_p) & ECF_RETURNS_TWICE; + tree dispatch_interop = NULL_TREE; + if (flag_openmp + && gimplify_omp_ctxp != NULL + && gimplify_omp_ctxp->code == OMP_DISPATCH + && gimplify_omp_ctxp->clauses + && (dispatch_interop = omp_find_clause (gimplify_omp_ctxp->clauses, + OMP_CLAUSE_INTEROP)) != NULL_TREE) + /* FIXME: When implementing 'append_args, use the 'device_num' of + the argument. */ + error_at (OMP_CLAUSE_LOCATION (dispatch_interop), + "number of list items in %<interop%> clause exceeds number of " + "%<append_args%> items for %<declare variant%> candidate %qD", + fndecl); + /* Gimplify the function arguments. */ if (nargs > 0) { @@ -13400,6 +13414,7 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p, case OMP_CLAUSE_BIND: case OMP_CLAUSE_IF_PRESENT: case OMP_CLAUSE_FINALIZE: + case OMP_CLAUSE_INTEROP: break; case OMP_CLAUSE_ORDER: diff --git a/gcc/testsuite/c-c++-common/gomp/dispatch-11.c b/gcc/testsuite/c-c++-common/gomp/dispatch-11.c new file mode 100644 index 0000000000000000000000000000000000000000..7f1d8062f25c8083a1aa42bd7b2ebc471a744ac3 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/dispatch-11.c @@ -0,0 +1,84 @@ +/* { dg-additional-options "-fdump-tree-original" } */ + +/* The following definitions are in omp_lib, which cannot be included + in gcc/testsuite/ */ + +#if __cplusplus >= 201103L +# define __GOMP_UINTPTR_T_ENUM : __UINTPTR_TYPE__ +#else +# define __GOMP_UINTPTR_T_ENUM +#endif + +typedef enum omp_interop_t __GOMP_UINTPTR_T_ENUM +{ + omp_interop_none = 0, + __omp_interop_t_max__ = __UINTPTR_MAX__ +} omp_interop_t; + + +float repl1(); +#pragma omp declare variant(repl1) match(construct={dispatch}) +float base1(); + +void repl2(int *, int *); +#pragma omp declare variant(repl2) match(construct={dispatch}) adjust_args(need_device_ptr : y) +void base2(int *x, int *y); + + +float +dupl (int *a, int *b) +{ + omp_interop_t obj1, obj2; + float x; + + #pragma omp dispatch interop ( obj1 ) interop(obj2) /* { dg-error "too many 'interop' clauses" } */ + x = base1 (); + /* { dg-error "number of list items in 'interop' clause exceeds number of 'append_args' items for 'declare variant' candidate 'repl1'" "" { target c } .-2 } */ + /* { dg-error "number of list items in 'interop' clause exceeds number of 'append_args' items for 'declare variant' candidate 'float repl1\\(\\)'" "" { target c++ } .-3 } */ + + #pragma omp dispatch interop ( obj1) nocontext(1) interop (obj2 ) /* { dg-error "too many 'interop' clauses" } */ + base2 (a, b); + /* { dg-error "number of list items in 'interop' clause exceeds number of 'append_args' items for 'declare variant' candidate 'base2'" "" { target c } .-2 } */ + /* { dg-error "number of list items in 'interop' clause exceeds number of 'append_args' items for 'declare variant' candidate 'void base2\\(int\\*, int\\*\\)'" "" { target c++ } .-3 } */ + return x; +} + + +float +test (int *a, int *b) +{ + omp_interop_t obj1, obj2; + float x, y; + + #pragma omp dispatch interop ( obj1 ) + x = base1 (); + /* { dg-error "number of list items in 'interop' clause exceeds number of 'append_args' items for 'declare variant' candidate 'repl1'" "" { target c } .-2 } */ + /* { dg-error "number of list items in 'interop' clause exceeds number of 'append_args' items for 'declare variant' candidate 'float repl1\\(\\)'" "" { target c++ } .-3 } */ + + #pragma omp dispatch interop ( obj1, obj1 ) /* Twice the same - should be fine. */ + x = base1 (); + /* { dg-error "number of list items in 'interop' clause exceeds number of 'append_args' items for 'declare variant' candidate 'repl1'" "" { target c } .-2 } */ + /* { dg-error "number of list items in 'interop' clause exceeds number of 'append_args' items for 'declare variant' candidate 'float repl1\\(\\)'" "" { target c++ } .-3 } */ + + #pragma omp dispatch novariants(1) interop(obj2, obj1) + y = base1 (); + /* { dg-error "number of list items in 'interop' clause exceeds number of 'append_args' items for 'declare variant' candidate 'base1'" "" { target c } .-2 } */ + /* { dg-error "number of list items in 'interop' clause exceeds number of 'append_args' items for 'declare variant' candidate 'float base1\\(\\)'" "" { target c++ } .-3 } */ + + #pragma omp dispatch interop(obj2, obj1) + base2 (a, b); + /* { dg-error "number of list items in 'interop' clause exceeds number of 'append_args' items for 'declare variant' candidate 'repl2'" "" { target c } .-2 } */ + /* { dg-error "number of list items in 'interop' clause exceeds number of 'append_args' items for 'declare variant' candidate 'void repl2\\(int\\*, int\\*\\)'" "" { target c++ } .-3 } */ + + #pragma omp dispatch interop(obj2) nocontext(1) + base2 (a, b); + /* { dg-error "number of list items in 'interop' clause exceeds number of 'append_args' items for 'declare variant' candidate 'base2'" "" { target c } .-2 } */ + /* { dg-error "number of list items in 'interop' clause exceeds number of 'append_args' items for 'declare variant' candidate 'void base2\\(int\\*, int\\*\\)'" "" { target c++ } .-3 } */ + return x + y; +} + +/* { dg-final { scan-tree-dump-times "#pragma omp dispatch interop\\(obj1\\)\[\\n\\r\]" 1 "original" } } */ +/* { dg-final { scan-tree-dump-times "#pragma omp dispatch interop\\(obj1\\) interop\\(obj1\\)\[\\n\\r\]" 1 "original" } } */ +/* { dg-final { scan-tree-dump-times "#pragma omp dispatch interop\\(obj1\\) interop\\(obj2\\) novariants\\(1\\)\[\\n\\r\]" 1 "original" } } */ +/* { dg-final { scan-tree-dump-times "#pragma omp dispatch interop\\(obj1\\) interop\\(obj2\\)\[\\n\\r\]" 1 "original" } } */ +/* { dg-final { scan-tree-dump-times "#pragma omp dispatch nocontext\\(1\\) interop\\(obj2\\)\[\\n\\r\]" 1 "original" } } */ diff --git a/gcc/testsuite/c-c++-common/gomp/dispatch-12.c b/gcc/testsuite/c-c++-common/gomp/dispatch-12.c new file mode 100644 index 0000000000000000000000000000000000000000..ea190c74e84f97139269abbd4a12dfefb7539eab --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/dispatch-12.c @@ -0,0 +1,53 @@ +/* The following definitions are in omp_lib, which cannot be included + in gcc/testsuite/ */ + +#if __cplusplus >= 201103L +# define __GOMP_UINTPTR_T_ENUM : __UINTPTR_TYPE__ +#else +# define __GOMP_UINTPTR_T_ENUM +#endif + +typedef enum omp_interop_t __GOMP_UINTPTR_T_ENUM +{ + omp_interop_none = 0, + __omp_interop_t_max__ = __UINTPTR_MAX__ +} omp_interop_t; + + +void repl1(); +#pragma omp declare variant(repl1) match(construct={dispatch}) +void base1(); + +void +test () +{ + const omp_interop_t obj1 = omp_interop_none; + omp_interop_t obj2[2]; + const omp_interop_t *obj3; + short x; + + #pragma omp dispatch interop ( obj1, obj2, obj1 ) /* { dg-error "'obj2' must be of 'omp_interop_t'" } */ + base1 (); + /* { dg-error "number of list items in 'interop' clause exceeds number of 'append_args' items for 'declare variant' candidate 'repl1'" "" { target c } .-2 } */ + /* { dg-error "number of list items in 'interop' clause exceeds number of 'append_args' items for 'declare variant' candidate 'void repl1\\(\\)'" "" { target c++ } .-3 } */ + + #pragma omp dispatch interop ( obj3 ) /* { dg-error "'obj3' must be of 'omp_interop_t'" } */ + base1 (); + /* { dg-error "number of list items in 'interop' clause exceeds number of 'append_args' items for 'declare variant' candidate 'repl1'" "" { target c } .-2 } */ + /* { dg-error "number of list items in 'interop' clause exceeds number of 'append_args' items for 'declare variant' candidate 'void repl1\\(\\)'" "" { target c++ } .-3 } */ + + #pragma omp dispatch interop ( obj1 ) + base1 (); + /* { dg-error "number of list items in 'interop' clause exceeds number of 'append_args' items for 'declare variant' candidate 'repl1'" "" { target c } .-2 } */ + /* { dg-error "number of list items in 'interop' clause exceeds number of 'append_args' items for 'declare variant' candidate 'void repl1\\(\\)'" "" { target c++ } .-3 } */ + + #pragma omp dispatch interop ( obj2 ) /* { dg-error "'obj2' must be of 'omp_interop_t'" } */ + base1 (); + /* { dg-error "number of list items in 'interop' clause exceeds number of 'append_args' items for 'declare variant' candidate 'repl1'" "" { target c } .-2 } */ + /* { dg-error "number of list items in 'interop' clause exceeds number of 'append_args' items for 'declare variant' candidate 'void repl1\\(\\)'" "" { target c++ } .-3 } */ + + #pragma omp dispatch interop ( x ) /* { dg-error "'x' must be of 'omp_interop_t'" } */ + base1 (); + /* { dg-error "number of list items in 'interop' clause exceeds number of 'append_args' items for 'declare variant' candidate 'repl1'" "" { target c } .-2 } */ + /* { dg-error "number of list items in 'interop' clause exceeds number of 'append_args' items for 'declare variant' candidate 'void repl1\\(\\)'" "" { target c++ } .-3 } */ +} diff --git a/gcc/tree-core.h b/gcc/tree-core.h index 620d0ad92e1827257839ce2cc08decc14e69227a..1776c154d94e12e6efaf846d1b60c3170d469605 100644 --- a/gcc/tree-core.h +++ b/gcc/tree-core.h @@ -387,6 +387,9 @@ enum omp_clause_code { /* OpenMP clause: use (variable-list ). */ OMP_CLAUSE_USE, + /* OpenMP clause: interop (variable-list). */ + OMP_CLAUSE_INTEROP, + /* OpenACC clause: gang [(gang-argument-list)]. Where gang-argument-list: [gang-argument-list, ] gang-argument diff --git a/gcc/tree-pretty-print.cc b/gcc/tree-pretty-print.cc index c50aa04c833d86d7a11c8e3becc746f7de53175c..cacef9457e65b0be275ca32327326ee6301112e1 100644 --- a/gcc/tree-pretty-print.cc +++ b/gcc/tree-pretty-print.cc @@ -1578,7 +1578,11 @@ dump_omp_clause (pretty_printer *pp, tree clause, int spc, dump_flags_t flags) spc, flags, false); pp_right_paren (pp); break; - + case OMP_CLAUSE_INTEROP: + pp_string (pp, "interop("); + dump_generic_node (pp, OMP_CLAUSE_DECL (clause), spc, flags, false); + pp_right_paren (pp); + break; case OMP_CLAUSE_IF_PRESENT: pp_string (pp, "if_present"); break; diff --git a/gcc/tree.cc b/gcc/tree.cc index 40ebfa130deb786e108775d01fcb4628fff017c7..6350dd427796b4dc8086c26f498b9fa1c15cc5f3 100644 --- a/gcc/tree.cc +++ b/gcc/tree.cc @@ -274,6 +274,7 @@ unsigned const char omp_clause_num_ops[] = 1, /* OMP_CLAUSE_DESTROY */ 2, /* OMP_CLAUSE_INIT */ 1, /* OMP_CLAUSE_USE */ + 1, /* OMP_CLAUSE_INTEROP */ 2, /* OMP_CLAUSE_GANG */ 1, /* OMP_CLAUSE_ASYNC */ 1, /* OMP_CLAUSE_WAIT */ @@ -375,6 +376,7 @@ const char * const omp_clause_code_name[] = "destroy", "init", "use", + "interop", "gang", "async", "wait",