aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorPaul-Antoine Arras <parras@baylibre.com>2025-03-13 17:16:41 +0100
committerPaul-Antoine Arras <parras@baylibre.com>2025-03-21 19:24:16 +0100
commit99e2906ae255fc7b8edb008d7cd47b28b078a809 (patch)
treeaa20eea780d8962d8be0da6122795911e7376390 /gcc
parentf45d14b495d603b8d5fbdffe6fced03cb3e2fc10 (diff)
downloadgcc-99e2906ae255fc7b8edb008d7cd47b28b078a809.zip
gcc-99e2906ae255fc7b8edb008d7cd47b28b078a809.tar.gz
gcc-99e2906ae255fc7b8edb008d7cd47b28b078a809.tar.bz2
OpenMP: 'interop' construct - add ME support + target-independent libgomp
This patch partially enables use of the OpenMP interop construct by adding middle end support, mostly in the omplower pass, and in the target-independent part of the libgomp runtime. It follows up on previous patches for C, C++ and Fortran front ends support. The full interop feature requires another patch to enable foreign runtime support in libgomp plugins. gcc/ChangeLog: * builtin-types.def (BT_FN_VOID_INT_INT_PTR_PTR_PTR_INT_PTR_INT_PTR_UINT_PTR): New. * gimple-low.cc (lower_stmt): Handle GIMPLE_OMP_INTEROP. * gimple-pretty-print.cc (dump_gimple_omp_interop): New function. (pp_gimple_stmt_1): Handle GIMPLE_OMP_INTEROP. * gimple.cc (gimple_build_omp_interop): New function. (gimple_copy): Handle GIMPLE_OMP_INTEROP. * gimple.def (GIMPLE_OMP_INTEROP): Define. * gimple.h (gimple_build_omp_interop): Declare. (gimple_omp_interop_clauses): New function. (gimple_omp_interop_clauses_ptr): Likewise. (gimple_omp_interop_set_clauses): Likewise. (gimple_return_set_retval): Handle GIMPLE_OMP_INTEROP. * gimplify.cc (gimplify_scan_omp_clauses): Handle OMP_CLAUSE_INIT, OMP_CLAUSE_USE and OMP_CLAUSE_DESTROY. (gimplify_omp_interop): New function. (gimplify_expr): Replace sorry with call to gimplify_omp_interop. * omp-builtins.def (BUILT_IN_GOMP_INTEROP): Define. * omp-low.cc (scan_sharing_clauses): Handle OMP_CLAUSE_INIT, OMP_CLAUSE_USE and OMP_CLAUSE_DESTROY. (scan_omp_1_stmt): Handle GIMPLE_OMP_INTEROP. (lower_omp_interop_action_clauses): New function. (lower_omp_interop): Likewise. (lower_omp_1): Handle GIMPLE_OMP_INTEROP. gcc/c/ChangeLog: * c-parser.cc (c_parser_omp_clause_destroy): Make addressable. (c_parser_omp_clause_init): Make addressable. gcc/cp/ChangeLog: * parser.cc (cp_parser_omp_clause_init): Make addressable. gcc/fortran/ChangeLog: * trans-openmp.cc (gfc_trans_omp_clauses): Make OMP_CLAUSE_DESTROY and OMP_CLAUSE_INIT addressable. * types.def (BT_FN_VOID_INT_INT_PTR_PTR_PTR_INT_PTR_INT_PTR_UINT_PTR): New. include/ChangeLog: * gomp-constants.h (GOMP_DEVICE_DEFAULT_OMP_61, GOMP_INTEROP_TARGET, GOMP_INTEROP_TARGETSYNC, GOMP_INTEROP_FLAG_NOWAIT): Define. libgomp/ChangeLog: * icv-device.c (omp_set_default_device): Check GOMP_DEVICE_DEFAULT_OMP_61. * libgomp-plugin.h (struct interop_obj_t): New. (enum gomp_interop_flag): New. (GOMP_OFFLOAD_interop): Declare. (GOMP_OFFLOAD_get_interop_int): Declare. (GOMP_OFFLOAD_get_interop_ptr): Declare. (GOMP_OFFLOAD_get_interop_str): Declare. (GOMP_OFFLOAD_get_interop_type_desc): Declare. * libgomp.h (_LIBGOMP_OMP_LOCK_DEFINED): Define. (struct gomp_device_descr): Add interop_func, get_interop_int_func, get_interop_ptr_func, get_interop_str_func, get_interop_type_desc_func. * libgomp.map: Add GOMP_interop. * libgomp_g.h (GOMP_interop): Declare. * target.c (resolve_device): Handle GOMP_DEVICE_DEFAULT_OMP_61. (omp_get_interop_int): Replace stub with actual implementation. (omp_get_interop_ptr): Likewise. (omp_get_interop_str): Likewise. (omp_get_interop_type_desc): Likewise. (struct interop_data_t): Define. (gomp_interop_internal): New function. (GOMP_interop): Likewise. (gomp_load_plugin_for_device): Load symbols for get_interop_int, get_interop_ptr, get_interop_str and get_interop_type_desc. * testsuite/libgomp.c-c++-common/interop-1.c: New test. gcc/testsuite/ChangeLog: * c-c++-common/gomp/interop-1.c: Remove dg-prune-output "sorry". * c-c++-common/gomp/interop-2.c: Likewise. * c-c++-common/gomp/interop-3.c: Likewise. * c-c++-common/gomp/interop-4.c: Remove dg-message "not supported". * g++.dg/gomp/interop-5.C: Likewise. * gfortran.dg/gomp/interop-4.f90: Likewise. * c-c++-common/gomp/interop-5.c: New test. * gfortran.dg/gomp/interop-5.f90: New test. Co-authored-by: Tobias Burnus <tburnus@baylibre.com>
Diffstat (limited to 'gcc')
-rw-r--r--gcc/builtin-types.def3
-rw-r--r--gcc/c/c-parser.cc6
-rw-r--r--gcc/cp/parser.cc1
-rw-r--r--gcc/fortran/trans-openmp.cc20
-rw-r--r--gcc/fortran/types.def3
-rw-r--r--gcc/gimple-low.cc1
-rw-r--r--gcc/gimple-pretty-print.cc23
-rw-r--r--gcc/gimple.cc18
-rw-r--r--gcc/gimple.def4
-rw-r--r--gcc/gimple.h33
-rw-r--r--gcc/gimplify.cc22
-rw-r--r--gcc/omp-builtins.def3
-rw-r--r--gcc/omp-low.cc233
-rw-r--r--gcc/testsuite/c-c++-common/gomp/interop-1.c2
-rw-r--r--gcc/testsuite/c-c++-common/gomp/interop-2.c2
-rw-r--r--gcc/testsuite/c-c++-common/gomp/interop-3.c2
-rw-r--r--gcc/testsuite/c-c++-common/gomp/interop-4.c12
-rw-r--r--gcc/testsuite/c-c++-common/gomp/interop-5.c68
-rw-r--r--gcc/testsuite/g++.dg/gomp/interop-5.C12
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/interop-4.f9010
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/interop-5.f9021
21 files changed, 467 insertions, 32 deletions
diff --git a/gcc/builtin-types.def b/gcc/builtin-types.def
index 9b7cc99..9583d30 100644
--- a/gcc/builtin-types.def
+++ b/gcc/builtin-types.def
@@ -1015,6 +1015,9 @@ DEF_FUNCTION_TYPE_11 (BT_FN_VOID_OMPFN_PTR_OMPCPYFN_LONG_LONG_UINT_LONG_INT_ULL_
BT_PTR_FN_VOID_PTR_PTR, BT_LONG, BT_LONG,
BT_UINT, BT_LONG, BT_INT,
BT_ULONGLONG, BT_ULONGLONG, BT_ULONGLONG)
+DEF_FUNCTION_TYPE_11 (BT_FN_VOID_INT_INT_PTR_PTR_PTR_INT_PTR_INT_PTR_UINT_PTR,
+ BT_VOID, BT_INT, BT_INT, BT_PTR, BT_PTR, BT_PTR, BT_INT,
+ BT_PTR, BT_INT, BT_PTR, BT_UINT, BT_PTR)
DEF_FUNCTION_TYPE_VAR_0 (BT_FN_VOID_VAR, BT_VOID)
DEF_FUNCTION_TYPE_VAR_0 (BT_FN_INT_VAR, BT_INT)
diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc
index d49d5c5..cfb1f60 100644
--- a/gcc/c/c-parser.cc
+++ b/gcc/c/c-parser.cc
@@ -20519,7 +20519,10 @@ c_parser_omp_clause_detach (c_parser *parser, tree list)
static tree
c_parser_omp_clause_destroy (c_parser *parser, tree list)
{
- return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_DESTROY, list);
+ tree nl = c_parser_omp_var_list_parens (parser, OMP_CLAUSE_DESTROY, list);
+ for (tree c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
+ TREE_ADDRESSABLE (OMP_CLAUSE_DECL (c)) = 1;
+ return nl;
}
/* OpenMP 5.1:
@@ -20901,6 +20904,7 @@ c_parser_omp_clause_init (c_parser *parser, tree list)
for (tree c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
{
+ TREE_ADDRESSABLE (OMP_CLAUSE_DECL (c)) = 1;
if (target)
OMP_CLAUSE_INIT_TARGET (c) = 1;
if (targetsync)
diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index 2fb1dc5..57a4610 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -43183,6 +43183,7 @@ cp_parser_omp_clause_init (cp_parser *parser, tree list)
NULL, false);
for (tree c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
{
+ TREE_ADDRESSABLE (OMP_CLAUSE_DECL (c)) = 1;
if (target)
OMP_CLAUSE_INIT_TARGET (c) = 1;
if (targetsync)
diff --git a/gcc/fortran/trans-openmp.cc b/gcc/fortran/trans-openmp.cc
index d1c05d0..bf8c341 100644
--- a/gcc/fortran/trans-openmp.cc
+++ b/gcc/fortran/trans-openmp.cc
@@ -2790,9 +2790,6 @@ gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses,
case OMP_LIST_USE:
clause_code = OMP_CLAUSE_USE;
goto add_clause;
- case OMP_LIST_DESTROY:
- clause_code = OMP_CLAUSE_DESTROY;
- goto add_clause;
case OMP_LIST_INTEROP:
clause_code = OMP_CLAUSE_INTEROP;
goto add_clause;
@@ -2803,6 +2800,22 @@ gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses,
declare_simd);
break;
+ case OMP_LIST_DESTROY:
+ for (; n != NULL; n = n->next)
+ if (n->sym->attr.referenced)
+ {
+ tree t = gfc_trans_omp_variable (n->sym, declare_simd);
+ if (t != error_mark_node)
+ {
+ tree node
+ = build_omp_clause (input_location, OMP_CLAUSE_DESTROY);
+ OMP_CLAUSE_DECL (node) = t;
+ TREE_ADDRESSABLE (OMP_CLAUSE_DECL (node)) = 1;
+ omp_clauses = gfc_trans_add_clause (node, omp_clauses);
+ }
+ }
+ break;
+
case OMP_LIST_INIT:
{
tree pref_type = NULL_TREE;
@@ -2816,6 +2829,7 @@ gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses,
tree node = build_omp_clause (input_location,
OMP_CLAUSE_INIT);
OMP_CLAUSE_DECL (node) = t;
+ TREE_ADDRESSABLE (OMP_CLAUSE_DECL (node)) = 1;
if (n->u.init.target)
OMP_CLAUSE_INIT_TARGET (node) = 1;
if (n->u.init.targetsync)
diff --git a/gcc/fortran/types.def b/gcc/fortran/types.def
index 6447cee..dd9b8df 100644
--- a/gcc/fortran/types.def
+++ b/gcc/fortran/types.def
@@ -266,6 +266,9 @@ DEF_FUNCTION_TYPE_11 (BT_FN_VOID_OMPFN_PTR_OMPCPYFN_LONG_LONG_UINT_LONG_INT_ULL_
BT_PTR_FN_VOID_PTR_PTR, BT_LONG, BT_LONG,
BT_UINT, BT_LONG, BT_INT,
BT_ULONGLONG, BT_ULONGLONG, BT_ULONGLONG)
+DEF_FUNCTION_TYPE_11 (BT_FN_VOID_INT_INT_PTR_PTR_PTR_INT_PTR_INT_PTR_UINT_PTR,
+ BT_VOID, BT_INT, BT_INT, BT_PTR, BT_PTR, BT_PTR, BT_INT,
+ BT_PTR, BT_INT, BT_PTR, BT_UINT, BT_PTR)
DEF_FUNCTION_TYPE_VAR_0 (BT_FN_VOID_VAR, BT_VOID)
diff --git a/gcc/gimple-low.cc b/gcc/gimple-low.cc
index 26b415c..b612970 100644
--- a/gcc/gimple-low.cc
+++ b/gcc/gimple-low.cc
@@ -747,6 +747,7 @@ lower_stmt (gimple_stmt_iterator *gsi, struct lower_data *data)
case GIMPLE_OMP_FOR:
case GIMPLE_OMP_SCOPE:
case GIMPLE_OMP_DISPATCH:
+ case GIMPLE_OMP_INTEROP:
case GIMPLE_OMP_SECTIONS:
case GIMPLE_OMP_SECTIONS_SWITCH:
case GIMPLE_OMP_SECTION:
diff --git a/gcc/gimple-pretty-print.cc b/gcc/gimple-pretty-print.cc
index d1531fc..4e20b4c 100644
--- a/gcc/gimple-pretty-print.cc
+++ b/gcc/gimple-pretty-print.cc
@@ -1755,6 +1755,25 @@ dump_gimple_omp_dispatch (pretty_printer *buffer, const gimple *gs, int spc,
}
}
+/* Dump a GIMPLE_OMP_INTEROP tuple on the pretty_printer BUFFER. */
+
+static void
+dump_gimple_omp_interop (pretty_printer *buffer, const gimple *gs, int spc,
+ dump_flags_t flags)
+{
+ if (flags & TDF_RAW)
+ {
+ dump_gimple_fmt (buffer, spc, flags, "%G <CLAUSES <", gs);
+ dump_omp_clauses (buffer, gimple_omp_interop_clauses (gs), spc, flags);
+ dump_gimple_fmt (buffer, spc, flags, " >");
+ }
+ else
+ {
+ pp_string (buffer, "#pragma omp interop");
+ dump_omp_clauses (buffer, gimple_omp_interop_clauses (gs), spc, flags);
+ }
+}
+
/* Dump a GIMPLE_OMP_TARGET tuple on the pretty_printer PP. */
static void
@@ -2838,6 +2857,10 @@ pp_gimple_stmt_1 (pretty_printer *pp, const gimple *gs, int spc,
dump_gimple_omp_dispatch(pp, gs, spc, flags);
break;
+ case GIMPLE_OMP_INTEROP:
+ dump_gimple_omp_interop (pp, gs, spc, flags);
+ break;
+
case GIMPLE_OMP_MASTER:
case GIMPLE_OMP_SECTION:
case GIMPLE_OMP_STRUCTURED_BLOCK:
diff --git a/gcc/gimple.cc b/gcc/gimple.cc
index 9a58a3a..9acfa38 100644
--- a/gcc/gimple.cc
+++ b/gcc/gimple.cc
@@ -1278,6 +1278,19 @@ gimple_build_omp_dispatch (gimple_seq body, tree clauses)
return p;
}
+/* Build a GIMPLE_OMP_INTEROP statement.
+
+ CLAUSES are any of the OMP interop construct's clauses. */
+
+gimple *
+gimple_build_omp_interop (tree clauses)
+{
+ gimple *p = gimple_alloc (GIMPLE_OMP_INTEROP, 0);
+ gimple_omp_interop_set_clauses (p, clauses);
+
+ return p;
+}
+
/* Build a GIMPLE_OMP_TARGET statement.
BODY is the sequence of statements that will be executed.
@@ -2205,6 +2218,11 @@ gimple_copy (gimple *stmt)
gimple_omp_dispatch_set_clauses (copy, t);
goto copy_omp_body;
+ case GIMPLE_OMP_INTEROP:
+ t = unshare_expr (gimple_omp_interop_clauses (stmt));
+ gimple_omp_interop_set_clauses (copy, t);
+ break;
+
case GIMPLE_OMP_TARGET:
{
gomp_target *omp_target_stmt = as_a <gomp_target *> (stmt);
diff --git a/gcc/gimple.def b/gcc/gimple.def
index 609c711..54248a8 100644
--- a/gcc/gimple.def
+++ b/gcc/gimple.def
@@ -355,6 +355,10 @@ DEFGSCODE(GIMPLE_OMP_SCOPE, "gimple_omp_scope", GSS_OMP_SINGLE_LAYOUT)
CLAUSES is an OMP_CLAUSE chain holding the associated clauses. */
DEFGSCODE(GIMPLE_OMP_DISPATCH, "gimple_omp_dispatch", GSS_OMP_SINGLE_LAYOUT)
+/* GIMPLE_OMP_INTEROP <CLAUSES> represents #pragma omp interop
+ CLAUSES is an OMP_CLAUSE chain holding the associated clauses. */
+DEFGSCODE(GIMPLE_OMP_INTEROP, "gimple_omp_interop", GSS_OMP_SINGLE_LAYOUT)
+
/* OMP_SECTION <BODY> represents #pragma omp section.
BODY is the sequence of statements in the section body. */
DEFGSCODE(GIMPLE_OMP_SECTION, "gimple_omp_section", GSS_OMP)
diff --git a/gcc/gimple.h b/gcc/gimple.h
index ecbd54c..112e5ae 100644
--- a/gcc/gimple.h
+++ b/gcc/gimple.h
@@ -745,7 +745,8 @@ struct GTY((tag("GSS_OMP_CONTINUE")))
};
/* GIMPLE_OMP_SINGLE, GIMPLE_OMP_ORDERED, GIMPLE_OMP_TASKGROUP,
- GIMPLE_OMP_SCAN, GIMPLE_OMP_MASKED, GIMPLE_OMP_SCOPE, GIMPLE_OMP_DISPATCH. */
+ GIMPLE_OMP_SCAN, GIMPLE_OMP_MASKED, GIMPLE_OMP_SCOPE, GIMPLE_OMP_DISPATCH,
+ GIMPLE_OMP_INTEROP. */
struct GTY((tag("GSS_OMP_SINGLE_LAYOUT")))
gimple_statement_omp_single_layout : public gimple_statement_omp
@@ -1595,6 +1596,7 @@ gimple *gimple_build_omp_section (gimple_seq);
gimple *gimple_build_omp_structured_block (gimple_seq);
gimple *gimple_build_omp_scope (gimple_seq, tree);
gimple *gimple_build_omp_dispatch (gimple_seq, tree);
+gimple *gimple_build_omp_interop (tree);
gimple *gimple_build_omp_master (gimple_seq);
gimple *gimple_build_omp_masked (gimple_seq, tree);
gimple *gimple_build_omp_taskgroup (gimple_seq, tree);
@@ -5468,6 +5470,34 @@ gimple_omp_dispatch_set_clauses (gimple *gs, tree clauses)
static_cast<gimple_statement_omp_single_layout *> (gs)->clauses = clauses;
}
+/* Return the clauses associated with OMP_INTEROP statement GS. */
+
+inline tree
+gimple_omp_interop_clauses (const gimple *gs)
+{
+ GIMPLE_CHECK (gs, GIMPLE_OMP_INTEROP);
+ return static_cast<const gimple_statement_omp_single_layout *> (gs)->clauses;
+}
+
+/* Return a pointer to the clauses associated with OMP_INTEROP statement GS. */
+
+inline tree *
+gimple_omp_interop_clauses_ptr (gimple *gs)
+{
+ GIMPLE_CHECK (gs, GIMPLE_OMP_INTEROP);
+ return &static_cast<gimple_statement_omp_single_layout *> (gs)->clauses;
+}
+
+/* Set CLAUSES to be the clauses associated with OMP interop statement
+ GS. */
+
+inline void
+gimple_omp_interop_set_clauses (gimple *gs, tree clauses)
+{
+ GIMPLE_CHECK (gs, GIMPLE_OMP_INTEROP);
+ static_cast<gimple_statement_omp_single_layout *> (gs)->clauses = clauses;
+}
+
/* Return the kind of the OMP_FOR statemement G. */
inline int
@@ -6802,6 +6832,7 @@ gimple_return_set_retval (greturn *gs, tree retval)
case GIMPLE_OMP_TEAMS: \
case GIMPLE_OMP_SCOPE: \
case GIMPLE_OMP_DISPATCH: \
+ case GIMPLE_OMP_INTEROP: \
case GIMPLE_OMP_SECTION: \
case GIMPLE_OMP_STRUCTURED_BLOCK: \
case GIMPLE_OMP_MASTER: \
diff --git a/gcc/gimplify.cc b/gcc/gimplify.cc
index 5bdd970..244c4ba 100644
--- a/gcc/gimplify.cc
+++ b/gcc/gimplify.cc
@@ -13853,6 +13853,9 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
case OMP_CLAUSE_IF_PRESENT:
case OMP_CLAUSE_FINALIZE:
case OMP_CLAUSE_INTEROP:
+ case OMP_CLAUSE_INIT:
+ case OMP_CLAUSE_USE:
+ case OMP_CLAUSE_DESTROY:
break;
case OMP_CLAUSE_ORDER:
@@ -18480,6 +18483,21 @@ gimplify_omp_ordered (tree expr, gimple_seq body)
return gimple_build_omp_ordered (body, OMP_ORDERED_CLAUSES (expr));
}
+/* Gimplify an OMP_INTEROP statement. */
+
+static enum gimplify_status
+gimplify_omp_interop (tree *expr_p, gimple_seq *pre_p)
+{
+ tree expr = *expr_p;
+
+ gimplify_scan_omp_clauses (&OMP_INTEROP_CLAUSES (expr), pre_p, ORT_TASK,
+ OMP_INTEROP);
+ gimple *stmt = gimple_build_omp_interop (OMP_INTEROP_CLAUSES (expr));
+ gimplify_seq_add_stmt (pre_p, stmt);
+ *expr_p = NULL_TREE;
+ return GS_ALL_DONE;
+}
+
/* Callback for walk_tree to find an IFN_GOMP_DISPATCH. */
static tree
@@ -19953,9 +19971,7 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
}
case OMP_INTEROP:
- sorry_at (EXPR_LOCATION (*expr_p),
- "%<#pragma omp interop%> not yet supported");
- ret = GS_ERROR;
+ ret = gimplify_omp_interop (expr_p, pre_p);
break;
case OMP_ATOMIC:
case OMP_ATOMIC_READ:
diff --git a/gcc/omp-builtins.def b/gcc/omp-builtins.def
index 96de707..f73fb7b 100644
--- a/gcc/omp-builtins.def
+++ b/gcc/omp-builtins.def
@@ -402,6 +402,9 @@ DEF_GOMP_BUILTIN (BUILT_IN_GOMP_DOACROSS_ULL_POST, "GOMP_doacross_ull_post",
BT_FN_VOID_PTR, ATTR_NOTHROW_LEAF_LIST)
DEF_GOMP_BUILTIN (BUILT_IN_GOMP_DOACROSS_ULL_WAIT, "GOMP_doacross_ull_wait",
BT_FN_VOID_ULL_VAR, ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_INTEROP, "GOMP_interop",
+ BT_FN_VOID_INT_INT_PTR_PTR_PTR_INT_PTR_INT_PTR_UINT_PTR,
+ ATTR_NOTHROW_LIST)
DEF_GOMP_BUILTIN (BUILT_IN_GOMP_PARALLEL, "GOMP_parallel",
BT_FN_VOID_OMPFN_PTR_UINT_UINT, ATTR_NOTHROW_LIST)
DEF_GOMP_BUILTIN (BUILT_IN_GOMP_PARALLEL_REDUCTIONS,
diff --git a/gcc/omp-low.cc b/gcc/omp-low.cc
index c36ae38..e369df6 100644
--- a/gcc/omp-low.cc
+++ b/gcc/omp-low.cc
@@ -1790,6 +1790,11 @@ scan_sharing_clauses (tree clauses, omp_context *ctx)
install_var_local (decl, ctx);
break;
+ case OMP_CLAUSE_INIT:
+ case OMP_CLAUSE_USE:
+ case OMP_CLAUSE_DESTROY:
+ break;
+
case OMP_CLAUSE__CACHE_:
case OMP_CLAUSE_NOHOST:
default:
@@ -1986,6 +1991,9 @@ scan_sharing_clauses (tree clauses, omp_context *ctx)
case OMP_CLAUSE_FINALIZE:
case OMP_CLAUSE_FILTER:
case OMP_CLAUSE__CONDTEMP_:
+ case OMP_CLAUSE_INIT:
+ case OMP_CLAUSE_USE:
+ case OMP_CLAUSE_DESTROY:
break;
case OMP_CLAUSE__CACHE_:
@@ -4211,6 +4219,10 @@ scan_omp_1_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
scan_omp (gimple_omp_body_ptr (stmt), ctx);
break;
+ case GIMPLE_OMP_INTEROP:
+ ctx = new_omp_context (stmt, ctx);
+ break;
+
case GIMPLE_OMP_SECTIONS:
scan_omp_sections (as_a <gomp_sections *> (stmt), ctx);
break;
@@ -14331,6 +14343,222 @@ lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
}
}
+/* Generate code to implement the action-clauses (destroy, init, use) of an
+ OpenMP interop construct. */
+
+static void
+lower_omp_interop_action_clauses (gimple_seq *seq, vec<tree> &objs,
+ vec<tree> *interop_types = NULL,
+ vec<tree> *prefer_types = NULL)
+{
+ if (objs.length () == 0)
+ return;
+
+ enum omp_clause_code action = OMP_CLAUSE_CODE (objs[0]);
+ if (action == OMP_CLAUSE_INIT)
+ gcc_checking_assert (objs.length () == interop_types->length ()
+ && objs.length () == prefer_types->length ());
+ else
+ gcc_assert (prefer_types == NULL && interop_types == NULL);
+
+ tree ret_objs = NULL_TREE, ret_interop_types = NULL_TREE,
+ ret_prefer_types = NULL_TREE;
+
+ /* Build an array of interop objects. */
+
+ tree type_obj_pref = build_array_type_nelts (ptr_type_node, objs.length ());
+ ret_objs = create_tmp_var (type_obj_pref, "interopobjs");
+
+ bool have_pref_type = false;
+ if (action == OMP_CLAUSE_INIT)
+ {
+ for (tree pref_type : prefer_types)
+ if (pref_type != NULL_TREE)
+ {
+ have_pref_type = true;
+ break;
+ }
+ tree type_tgtsync
+ = build_array_type_nelts (integer_type_node, objs.length ());
+ ret_interop_types = create_tmp_var (type_tgtsync, "tgt_tgtsync");
+ if (have_pref_type)
+ ret_prefer_types = create_tmp_var (type_obj_pref, "pref_type");
+ else
+ {
+ ret_prefer_types = null_pointer_node;
+ prefer_types->truncate (0);
+ }
+ }
+
+ for (size_t i = 0; !objs.is_empty (); i++)
+ {
+ tree offset = build_int_cst (integer_type_node, i);
+ tree init = build4 (ARRAY_REF, ptr_type_node, ret_objs, offset, NULL_TREE,
+ NULL_TREE);
+ tree obj = OMP_CLAUSE_DECL (objs.pop ());
+ if (TREE_CODE (TREE_TYPE (obj)) == REFERENCE_TYPE)
+ obj = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (obj)), obj);
+ if (action != OMP_CLAUSE_USE
+ && TREE_CODE (TREE_TYPE (obj)) != POINTER_TYPE)
+ /* For modifying actions, we need a pointer. */
+ obj = build_fold_addr_expr (obj);
+ else if (action == OMP_CLAUSE_USE
+ && TREE_CODE (TREE_TYPE (obj)) == POINTER_TYPE)
+ /* For use action, we need the value. */
+ obj = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (obj)), obj);
+ init = build2 (MODIFY_EXPR, ptr_type_node, init,
+ fold_convert (ptr_type_node, obj));
+ gimplify_and_add (init, seq);
+
+ if (action == OMP_CLAUSE_INIT)
+ {
+ init = build4 (ARRAY_REF, integer_type_node, ret_interop_types,
+ offset, NULL_TREE, NULL_TREE);
+ init = build2 (MODIFY_EXPR, integer_type_node, init,
+ interop_types->pop ());
+ gimplify_and_add (init, seq);
+
+ if (have_pref_type)
+ {
+ tree prefer_type = prefer_types->pop ();
+ tree pref = (prefer_type == NULL_TREE
+ ? null_pointer_node
+ : build_fold_addr_expr (prefer_type));
+ init = build4 (ARRAY_REF, ptr_type_node, ret_prefer_types, offset,
+ NULL_TREE, NULL_TREE);
+ init = build2 (MODIFY_EXPR, ptr_type_node, init, pref);
+ gimplify_and_add (init, seq);
+ }
+ }
+ }
+ if (action == OMP_CLAUSE_INIT)
+ {
+ if (have_pref_type)
+ ret_prefer_types = build_fold_addr_expr (ret_prefer_types);
+ ret_interop_types = build_fold_addr_expr (ret_interop_types);
+ }
+ ret_objs = build_fold_addr_expr (ret_objs);
+
+ gcc_assert (objs.is_empty ()
+ && (!interop_types || interop_types->is_empty ())
+ && (!prefer_types || prefer_types->is_empty ()));
+
+ objs.safe_push (ret_objs);
+ if (action == OMP_CLAUSE_INIT)
+ {
+ interop_types->safe_push (ret_interop_types);
+ prefer_types->safe_push (ret_prefer_types);
+ }
+}
+
+/* Lower code for an OpenMP interop directive. */
+
+static void
+lower_omp_interop (gimple_stmt_iterator *gsi_p, omp_context *ctx)
+{
+ push_gimplify_context ();
+
+ tree block = make_node (BLOCK);
+ gbind *bind = gimple_build_bind (NULL, NULL, block);
+ gimple_seq bind_body = NULL;
+
+ /* Emit call to GOMP_interop:
+ void
+ GOMP_interop (int device_num, int n_init, omp_interop_t **init,
+ const void *target_targetsync, const void *prefer_type,
+ int n_use, omp_interop_t *use, int n_destroy,
+ omp_interop_t **destroy, unsigned int flags,
+ void **depend) */
+
+ tree flags = NULL_TREE;
+ tree depend = null_pointer_node;
+ tree device_num = NULL_TREE;
+
+ auto_vec<tree> init_objs, use_objs, destroy_objs, prefer_type,
+ target_targetsync;
+ gimple_seq dep_ilist = NULL, dep_olist = NULL;
+ tree clauses = gimple_omp_interop_clauses (gsi_stmt (*gsi_p));
+ for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
+ {
+ switch (OMP_CLAUSE_CODE (c))
+ {
+ case OMP_CLAUSE_INIT:
+ {
+ init_objs.safe_push (c);
+ int target_targetsync_bits = 0;
+ if (OMP_CLAUSE_INIT_TARGET (c))
+ target_targetsync_bits |= GOMP_INTEROP_TARGET;
+ if (OMP_CLAUSE_INIT_TARGETSYNC (c))
+ target_targetsync_bits |= GOMP_INTEROP_TARGETSYNC;
+ tree t = build_int_cst (integer_type_node, target_targetsync_bits);
+ target_targetsync.safe_push (t);
+ prefer_type.safe_push (OMP_CLAUSE_INIT_PREFER_TYPE (c));
+ }
+ break;
+ case OMP_CLAUSE_USE:
+ use_objs.safe_push (c);
+ break;
+ case OMP_CLAUSE_DESTROY:
+ destroy_objs.safe_push (c);
+ break;
+ case OMP_CLAUSE_NOWAIT:
+ flags = build_int_cst (integer_type_node, GOMP_INTEROP_FLAG_NOWAIT);
+ break;
+ case OMP_CLAUSE_DEPEND:
+ {
+ tree *cp = gimple_omp_interop_clauses_ptr (gsi_stmt (*gsi_p));
+ lower_depend_clauses (cp, &dep_ilist, &dep_olist);
+ depend = OMP_CLAUSE_DECL (*cp);
+ }
+ break;
+ case OMP_CLAUSE_DEVICE:
+ device_num = OMP_CLAUSE_DEVICE_ID (c);
+ break;
+ default:
+ gcc_unreachable ();
+ }
+ }
+
+ if (flags == NULL_TREE)
+ flags = build_int_cst (integer_type_node, 0);
+
+ if (device_num == NULL_TREE)
+ device_num = build_int_cst (integer_type_node, GOMP_DEVICE_DEFAULT_OMP_61);
+
+ tree n_init = build_int_cst (integer_type_node, init_objs.length ());
+ tree n_use = build_int_cst (integer_type_node, use_objs.length ());
+ tree n_destroy = build_int_cst (integer_type_node, destroy_objs.length ());
+
+ lower_omp_interop_action_clauses (&bind_body, init_objs, &target_targetsync,
+ &prefer_type);
+ lower_omp_interop_action_clauses (&bind_body, use_objs);
+ lower_omp_interop_action_clauses (&bind_body, destroy_objs);
+
+ gimple_seq_add_seq (&bind_body, dep_ilist);
+ tree fn = builtin_decl_explicit (BUILT_IN_GOMP_INTEROP);
+ tree init_arg = init_objs.length () ? init_objs.pop () : null_pointer_node;
+ tree target_targetsync_arg = target_targetsync.length ()
+ ? target_targetsync.pop ()
+ : null_pointer_node;
+ tree prefer_type_arg
+ = prefer_type.length () ? prefer_type.pop () : null_pointer_node;
+ tree use_arg = use_objs.length () ? use_objs.pop () : null_pointer_node;
+ tree destroy_arg
+ = destroy_objs.length () ? destroy_objs.pop () : null_pointer_node;
+ gcall *call
+ = gimple_build_call (fn, 11, device_num, n_init, init_arg,
+ target_targetsync_arg, prefer_type_arg, n_use, use_arg,
+ n_destroy, destroy_arg, flags, depend);
+ gimple_seq_add_stmt (&bind_body, call);
+ gimple_seq_add_seq (&bind_body, dep_olist);
+
+ gsi_replace (gsi_p, bind, true);
+ gimple_bind_set_body (bind, bind_body);
+ pop_gimplify_context (bind);
+ gimple_bind_append_vars (bind, ctx->block_vars);
+ BLOCK_VARS (block) = ctx->block_vars;
+}
+
/* Expand code for an OpenMP teams directive. */
static void
@@ -14614,6 +14842,11 @@ lower_omp_1 (gimple_stmt_iterator *gsi_p, omp_context *ctx)
gcc_assert (ctx);
lower_omp_dispatch (gsi_p, ctx);
break;
+ case GIMPLE_OMP_INTEROP:
+ ctx = maybe_lookup_ctx (stmt);
+ gcc_assert (ctx);
+ lower_omp_interop (gsi_p, ctx);
+ break;
case GIMPLE_OMP_SINGLE:
ctx = maybe_lookup_ctx (stmt);
gcc_assert (ctx);
diff --git a/gcc/testsuite/c-c++-common/gomp/interop-1.c b/gcc/testsuite/c-c++-common/gomp/interop-1.c
index de3a4ba..d68611b 100644
--- a/gcc/testsuite/c-c++-common/gomp/interop-1.c
+++ b/gcc/testsuite/c-c++-common/gomp/interop-1.c
@@ -2,8 +2,6 @@
/* { dg-additional-options "-std=c23" { target c } } */
/* C++11 and C23 because of 'constexpr'. */
-/* { dg-prune-output "sorry, unimplemented: '#pragma omp interop' not yet supported" } */
-
/* The following definitions are in omp_lib, which cannot be included
in gcc/testsuite/ */
diff --git a/gcc/testsuite/c-c++-common/gomp/interop-2.c b/gcc/testsuite/c-c++-common/gomp/interop-2.c
index 57fd688d..af81cc6 100644
--- a/gcc/testsuite/c-c++-common/gomp/interop-2.c
+++ b/gcc/testsuite/c-c++-common/gomp/interop-2.c
@@ -2,8 +2,6 @@
/* { dg-additional-options "-std=c23" { target c } } */
/* C++11 and C23 because of 'constexpr'. */
-/* { dg-prune-output "sorry, unimplemented: '#pragma omp interop' not yet supported" } */
-
/* The following definitions are in omp_lib, which cannot be included
in gcc/testsuite/ */
diff --git a/gcc/testsuite/c-c++-common/gomp/interop-3.c b/gcc/testsuite/c-c++-common/gomp/interop-3.c
index 42478bf..51d26dd 100644
--- a/gcc/testsuite/c-c++-common/gomp/interop-3.c
+++ b/gcc/testsuite/c-c++-common/gomp/interop-3.c
@@ -1,5 +1,3 @@
-/* { dg-prune-output "sorry, unimplemented: '#pragma omp interop' not yet supported" } */
-
/* The following definitions are in omp_lib, which cannot be included
in gcc/testsuite/ */
diff --git a/gcc/testsuite/c-c++-common/gomp/interop-4.c b/gcc/testsuite/c-c++-common/gomp/interop-4.c
index 1f9c987..bb0bf31 100644
--- a/gcc/testsuite/c-c++-common/gomp/interop-4.c
+++ b/gcc/testsuite/c-c++-common/gomp/interop-4.c
@@ -33,18 +33,18 @@ f()
omp_interop_t obj1, obj2, obj3, obj4, obj5, obj6, obj7;
int x[6];
- #pragma omp interop init ( obj1, obj2) use (obj3) destroy(obj4) init(obj5) destroy(obj6) use(obj7) /* { dg-message "'#pragma omp interop' not yet supported" } */
+ #pragma omp interop init ( obj1, obj2) use (obj3) destroy(obj4) init(obj5) destroy(obj6) use(obj7)
/* { dg-final { scan-tree-dump-times "#pragma omp interop use\\(obj7\\) destroy\\(obj6\\) init\\(obj5\\) destroy\\(obj4\\) use\\(obj3\\) init\\(obj2\\) init\\(obj1\\)\[\r\n\]" 1 "original" } } */
- #pragma omp interop nowait init (targetsync : obj1, obj2) use (obj3) destroy(obj4) init(target, targetsync : obj5) destroy(obj6) use(obj7) depend(inout: x) /* { dg-message "'#pragma omp interop' not yet supported" } */
+ #pragma omp interop nowait init (targetsync : obj1, obj2) use (obj3) destroy(obj4) init(target, targetsync : obj5) destroy(obj6) use(obj7) depend(inout: x)
/* { dg-final { scan-tree-dump-times "#pragma omp interop depend\\(inout:x\\) use\\(obj7\\) destroy\\(obj6\\) init\\(target, targetsync: obj5\\) destroy\\(obj4\\) use\\(obj3\\) init\\(targetsync: obj2\\) init\\(targetsync: obj1\\) nowait\[\r\n\]" 1 "original" } } */
- #pragma omp interop init ( obj1, obj2) init (target: obj3) init(targetsync : obj4) init(target,targetsync: obj5) /* { dg-message "'#pragma omp interop' not yet supported" } */
+ #pragma omp interop init ( obj1, obj2) init (target: obj3) init(targetsync : obj4) init(target,targetsync: obj5)
/* { dg-final { scan-tree-dump-times "#pragma omp interop init\\(target, targetsync: obj5\\) init\\(targetsync: obj4\\) init\\(target: obj3\\) init\\(obj2\\) init\\(obj1\\)\[\r\n\]" 1 "original" } } */
/* -------------------------------------------- */
- #pragma omp interop init (target, prefer_type(omp_ifr_cuda, omp_ifr_cuda+1, "hsa", "myPrivateInterop", omp_ifr_cuda-2) : obj1, obj2) init (target: obj3) init(prefer_type(omp_ifr_hip, "sycl", omp_ifr_opencl), targetsync : obj4, obj7) init(target,prefer_type("level_zero", omp_ifr_level_zero+0),targetsync: obj5) /* { dg-message "'#pragma omp interop' not yet supported" } */
+ #pragma omp interop init (target, prefer_type(omp_ifr_cuda, omp_ifr_cuda+1, "hsa", "myPrivateInterop", omp_ifr_cuda-2) : obj1, obj2) init (target: obj3) init(prefer_type(omp_ifr_hip, "sycl", omp_ifr_opencl), targetsync : obj4, obj7) init(target,prefer_type("level_zero", omp_ifr_level_zero+0),targetsync: obj5)
/*
{ dg-warning "unknown foreign runtime identifier 'myPrivateInterop' \\\[-Wopenmp\\\]" "" { target *-*-* } .-2 }
{ dg-warning "unknown foreign runtime identifier '-1' \\\[-Wopenmp\\\]" "" { target *-*-* } .-3 }
@@ -55,7 +55,7 @@ f()
/* -------------------------------------------- */
- #pragma omp interop init ( target, prefer_type( {fr("hip"), attr("ompx_gnu_prio:1", "ompx_gnu_debug")}, {attr("ompx_gnu_nicest"), attr("ompx_something")}) : obj1, obj2) init ( prefer_type( {fr("cuda")}, {fr(omp_ifr_cuda_driver), attr("ompx_nix")}, {fr("best")}), targetsync : obj3, obj4) nowait use(obj5) /* { dg-message "'#pragma omp interop' not yet supported" } */
+ #pragma omp interop init ( target, prefer_type( {fr("hip"), attr("ompx_gnu_prio:1", "ompx_gnu_debug")}, {attr("ompx_gnu_nicest"), attr("ompx_something")}) : obj1, obj2) init ( prefer_type( {fr("cuda")}, {fr(omp_ifr_cuda_driver), attr("ompx_nix")}, {fr("best")}), targetsync : obj3, obj4) nowait use(obj5)
/*
{ dg-warning "unknown foreign runtime identifier 'best' \\\[-Wopenmp\\\]" "" { target *-*-* } .-2 }
@@ -69,7 +69,7 @@ g (int *y)
{
omp_interop_t io1, io2, io3, io4, io5;
- [[omp::directive (interop,init(prefer_type({fr("level_zero")}, {fr(omp_ifr_sycl),attr("ompx_in_order"),attr("ompx_queue:in_order")}), targetsync : io1, io2),use(io3),destroy(io4,io5),depend(inout:y),nowait)]]; /* { dg-message "'#pragma omp interop' not yet supported" } */
+ [[omp::directive (interop,init(prefer_type({fr("level_zero")}, {fr(omp_ifr_sycl),attr("ompx_in_order"),attr("ompx_queue:in_order")}), targetsync : io1, io2),use(io3),destroy(io4,io5),depend(inout:y),nowait)]];
/* { dg-final { scan-tree-dump-times "#pragma omp interop nowait depend\\(inout:y\\) destroy\\(io5\\) destroy\\(io4\\) use\\(io3\\) init\\(prefer_type\\(\{fr\\(\"level_zero\"\\)\}, \{fr\\(\"sycl\"\\),attr\\(\"ompx_in_order\"\\),attr\\(\"ompx_queue:in_order\"\\)\}\\), targetsync: io2\\) init\\(prefer_type\\(\{fr\\(\"level_zero\"\\)\}, \{fr\\(\"sycl\"\\),attr\\(\"ompx_in_order\"\\),attr\\(\"ompx_queue:in_order\"\\)\}\\), targetsync: io1\\)\[\r\n\]" 1 "original" } } */
}
diff --git a/gcc/testsuite/c-c++-common/gomp/interop-5.c b/gcc/testsuite/c-c++-common/gomp/interop-5.c
new file mode 100644
index 0000000..0b9bd09
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/interop-5.c
@@ -0,0 +1,68 @@
+/* { dg-additional-options "-fdump-tree-omplower" } */
+
+/* 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;
+
+typedef enum omp_interop_fr_t
+{
+ omp_ifr_cuda = 1,
+ omp_ifr_cuda_driver = 2,
+ omp_ifr_opencl = 3,
+ omp_ifr_sycl = 4,
+ omp_ifr_hip = 5,
+ omp_ifr_level_zero = 6,
+ omp_ifr_hsa = 7,
+ omp_ifr_last = omp_ifr_hsa
+} omp_interop_fr_t;
+
+void
+f()
+{
+ omp_interop_t obj1, obj2, obj3, obj4, obj5, obj6, obj7;
+ int x[6];
+
+ #pragma omp interop init (targetsync: obj1, obj2) use (obj3) destroy(obj4) init(target: obj5) destroy(obj6) use(obj7)
+ /* { dg-final { scan-tree-dump-times "void \\* interopobjs\.\[0-9\]+.3.;\[\r\n\ ]*int tgt_tgtsync\\.\[0-9\]+.3.;\[\r\n\ ]*void \\* interopobjs\\.\[0-9\]+.2.;\[\r\n\ ]*omp_interop_t obj3\\.\[0-9\]+;\[\r\n\ ]*void \\* obj3\\.\[0-9\]+;\[\r\n\ ]*omp_interop_t obj7\\.\[0-9\]+;\[\r\n\ ]*void \\* obj7\\.\[0-9\]+;\[\r\n\ ]*void \\* interopobjs\\.\[0-9\]+.2.;\[\r\n\ ]*interopobjs\.\[0-9\]+.0. = &obj1;\[\r\n \]*tgt_tgtsync\.\[0-9\]+.0. = 2;\[\r\n \]*interopobjs\.\[0-9\]+.1. = &obj2;\[\r\n \]*tgt_tgtsync\.\[0-9\]+.1. = 2;\[\r\n \]*interopobjs\.\[0-9\]+.2. = &obj5;\[\r\n \]*tgt_tgtsync\.\[0-9\]+.2. = 1;\[\r\n \]*obj3\.\[0-9\]+ = obj3;\[\r\n \]*obj3\.\[0-9\]+ = \\(void \\*\\) obj3\.\[0-9\]+;\[\r\n \]*interopobjs\.\[0-9\]+.0. = obj3\.\[0-9\]+;\[\r\n \]*obj7\.\[0-9\]+ = obj7;\[\r\n \]*obj7\.\[0-9\]+ = \\(void \\*\\) obj7\.\[0-9\]+;\[\r\n \]*interopobjs\.\[0-9\]+.1. = obj7\.\[0-9\]+;\[\r\n \]*interopobjs\.\[0-9\]+.0. = &obj4;\[\r\n \]*interopobjs\.\[0-9\]+.1. = &obj6;\[\r\n \]*__builtin_GOMP_interop \\(-5, 3, &interopobjs\.\[0-9\]+, &tgt_tgtsync\.\[0-9\]+, 0B, 2, &interopobjs\.\[0-9\]+, 2, &interopobjs\.\[0-9\]+, 0, 0B\\);" 1 "omplower" { target c } } } */
+ /* { dg-final { scan-tree-dump-times "void \\* interopobjs\.\[0-9\]+.3.;\[\r\n\ ]*int tgt_tgtsync\\.\[0-9\]+.3.;\[\r\n\ ]*void \\* interopobjs\\.\[0-9\]+.2.;\[\r\n\ ]*omp_interop_t obj3\\.\[0-9\]+;\[\r\n\ ]*void \\* obj3\\.\[0-9\]+;\[\r\n\ ]*omp_interop_t obj7\\.\[0-9\]+;\[\r\n\ ]*void \\* obj7\\.\[0-9\]+;\[\r\n\ ]*void \\* interopobjs\\.\[0-9\]+.2.;\[\r\n\ ]*omp_interop_t obj6\\.\[0-9\]+;\[\r\n\ ]*interopobjs\.\[0-9\]+.0. = &obj1;\[\r\n \]*tgt_tgtsync\.\[0-9\]+.0. = 2;\[\r\n \]*interopobjs\.\[0-9\]+.1. = &obj2;\[\r\n \]*tgt_tgtsync\.\[0-9\]+.1. = 2;\[\r\n \]*interopobjs\.\[0-9\]+.2. = &obj5;\[\r\n \]*tgt_tgtsync\.\[0-9\]+.2. = 1;\[\r\n \]*obj3\.\[0-9\]+ = obj3;\[\r\n \]*obj3\.\[0-9\]+ = \\(void \\*\\) obj3\.\[0-9\]+;\[\r\n \]*interopobjs\.\[0-9\]+.0. = obj3\.\[0-9\]+;\[\r\n \]*obj7\.\[0-9\]+ = obj7;\[\r\n \]*obj7\.\[0-9\]+ = \\(void \\*\\) obj7\.\[0-9\]+;\[\r\n \]*interopobjs\.\[0-9\]+.1. = obj7\.\[0-9\]+;\[\r\n \]*interopobjs\.\[0-9\]+.0. = &obj4;\[\r\n \]*obj6\.\[0-9\]+ = obj6;\[\r\n \]*interopobjs\.\[0-9\]+.1. = &obj6\.\[0-9\]+;\[\r\n \]*__builtin_GOMP_interop \\(-5, 3, &interopobjs\.\[0-9\]+, &tgt_tgtsync\.\[0-9\]+, 0B, 2, &interopobjs\.\[0-9\]+, 2, &interopobjs\.\[0-9\]+, 0, 0B\\);" 1 "omplower" { target c++ } } } */
+
+ #pragma omp interop nowait init (targetsync : obj1, obj2) use (obj3) destroy(obj4) init(target, targetsync : obj5) destroy(obj6) use(obj7) depend(inout: x)
+ /* { dg-final { scan-tree-dump-times "void \\* D\\.\[0-9\]+.3.;\[\r\n\ ]*void \\* interopobjs\\.\[0-9\]+.3.;\[\r\n\ ]*int tgt_tgtsync\\.\[0-9\]+.3.;\[\r\n\ ]*void \\* interopobjs\\.\[0-9\]+.2.;\[\r\n\ ]*omp_interop_t obj3\\.\[0-9\]+;\[\r\n\ ]*void \\* obj3\\.\[0-9\]+;\[\r\n\ ]*omp_interop_t obj7\\.\[0-9\]+;\[\r\n\ ]*void \\* obj7\\.\[0-9\]+;\[\r\n\ ]*void \\* interopobjs\\.\[0-9\]+.2.;\[\r\n\ ]*interopobjs\.\[0-9\]+.0. = &obj1;\[\r\n\ ]*tgt_tgtsync\.\[0-9\]+.0. = 2;\[\r\n\ ]*interopobjs\.\[0-9\]+.1. = &obj2;\[\r\n\ ]*tgt_tgtsync\.\[0-9\]+.1. = 2;\[\r\n\ ]*interopobjs\.\[0-9\]+.2. = &obj5;\[\r\n\ ]*tgt_tgtsync\.\[0-9\]+.2. = 3;\[\r\n\ ]*obj3\.\[0-9\]+ = obj3;\[\r\n\ ]*obj3\.\[0-9\]+ = \\(void \\*\\) obj3\.\[0-9\]+;\[\r\n\ ]*interopobjs\.\[0-9\]+.0. = obj3\.\[0-9\]+;\[\r\n\ ]*obj7\.\[0-9\]+ = obj7;\[\r\n\ ]*obj7\.\[0-9\]+ = \\(void \\*\\) obj7\.\[0-9\]+;\[\r\n\ ]*interopobjs\.\[0-9\]+.1. = obj7\.\[0-9\]+;\[\r\n\ ]*interopobjs\.\[0-9\]+.0. = &obj4;\[\r\n\ ]*interopobjs\.\[0-9\]+.1. = &obj6;\[\r\n\ ]*D\.\[0-9\]+.0. = 1B;\[\r\n\ ]*D\.\[0-9\]+.1. = 1B;\[\r\n\ ]*D\.\[0-9\]+.2. = &x;\[\r\n\ ]*__builtin_GOMP_interop \\(-5, 3, &interopobjs\.\[0-9\]+, &tgt_tgtsync\.\[0-9\]+, 0B, 2, &interopobjs\.\[0-9\]+, 2, &interopobjs\.\[0-9\]+, 1, &D\.\[0-9\]+\\);" 1 "omplower" { target c } } } */
+ /* { dg-final { scan-tree-dump-times "void \\* D\\.\[0-9\]+.3.;\[\r\n\ ]*void \\* interopobjs\\.\[0-9\]+.3.;\[\r\n\ ]*int tgt_tgtsync\\.\[0-9\]+.3.;\[\r\n\ ]*void \\* interopobjs\\.\[0-9\]+.2.;\[\r\n\ ]*omp_interop_t obj3\\.\[0-9\]+;\[\r\n\ ]*void \\* obj3\\.\[0-9\]+;\[\r\n\ ]*omp_interop_t obj7\\.\[0-9\]+;\[\r\n\ ]*void \\* obj7\\.\[0-9\]+;\[\r\n\ ]*void \\* interopobjs\\.\[0-9\]+.2.;\[\r\n\ ]*omp_interop_t obj6\\.\[0-9\]+;\[\r\n\ ]*interopobjs\.\[0-9\]+.0. = &obj1;\[\r\n\ ]*tgt_tgtsync\.\[0-9\]+.0. = 2;\[\r\n\ ]*interopobjs\.\[0-9\]+.1. = &obj2;\[\r\n\ ]*tgt_tgtsync\.\[0-9\]+.1. = 2;\[\r\n\ ]*interopobjs\.\[0-9\]+.2. = &obj5;\[\r\n\ ]*tgt_tgtsync\.\[0-9\]+.2. = 3;\[\r\n\ ]*obj3\.\[0-9\]+ = obj3;\[\r\n\ ]*obj3\.\[0-9\]+ = \\(void \\*\\) obj3\.\[0-9\]+;\[\r\n\ ]*interopobjs\.\[0-9\]+.0. = obj3\.\[0-9\]+;\[\r\n\ ]*obj7\.\[0-9\]+ = obj7;\[\r\n\ ]*obj7\.\[0-9\]+ = \\(void \\*\\) obj7\.\[0-9\]+;\[\r\n\ ]*interopobjs\.\[0-9\]+.1. = obj7\.\[0-9\]+;\[\r\n\ ]*interopobjs\.\[0-9\]+.0. = &obj4;\[\r\n\ ]*obj6\.\[0-9\]+ = obj6;\[\r\n\ ]*interopobjs\.\[0-9\]+.1. = &obj6\.\[0-9\]+;\[\r\n\ ]*D\.\[0-9\]+.0. = 1B;\[\r\n\ ]*D\.\[0-9\]+.1. = 1B;\[\r\n\ ]*D\.\[0-9\]+.2. = &x;\[\r\n\ ]*__builtin_GOMP_interop \\(-5, 3, &interopobjs\.\[0-9\]+, &tgt_tgtsync\.\[0-9\]+, 0B, 2, &interopobjs\.\[0-9\]+, 2, &interopobjs\.\[0-9\]+, 1, &D\.\[0-9\]+\\);" 1 "omplower" { target c++ } } } */
+
+ #pragma omp interop init (target: obj1, obj2) init (target: obj3) init(targetsync : obj4) init(target,targetsync: obj5)
+ /* { dg-final { scan-tree-dump-times "void \\* interopobjs\\.\[0-9\]+.5.;\[\r\n\ ]*int tgt_tgtsync\\.\[0-9\]+.5.;\[\r\n\ ]*interopobjs\.\[0-9\]+.0. = &obj1;\[\r\n \]*tgt_tgtsync\.\[0-9\]+.0. = 1;\[\r\n \]*interopobjs\.\[0-9\]+.1. = &obj2;\[\r\n \]*tgt_tgtsync\.\[0-9\]+.1. = 1;\[\r\n \]*interopobjs\.\[0-9\]+.2. = &obj3;\[\r\n \]*tgt_tgtsync\.\[0-9\]+.2. = 1;\[\r\n \]*interopobjs\.\[0-9\]+.3. = &obj4;\[\r\n \]*tgt_tgtsync\.\[0-9\]+.3. = 2;\[\r\n \]*interopobjs\.\[0-9\]+.4. = &obj5;\[\r\n \]*tgt_tgtsync\.\[0-9\]+.4. = 3;\[\r\n\ ]*__builtin_GOMP_interop \\(-5, 5, &interopobjs\.\[0-9\]+, &tgt_tgtsync\.\[0-9\]+, 0B, 0, 0B, 0, 0B, 0, 0B\\);" 1 "omplower" } } */
+
+ /* -------------------------------------------- */
+
+ #pragma omp interop init (target, prefer_type(omp_ifr_cuda, omp_ifr_cuda+1, "hsa") : obj1, obj2) init (target: obj3) init(prefer_type(omp_ifr_hip, "sycl", omp_ifr_opencl), targetsync : obj4, obj7) init(target,prefer_type("level_zero", omp_ifr_level_zero+0),targetsync: obj5)
+ /* { dg-final { scan-tree-dump-times "void \\* interopobjs\\.\[0-9\]+.6.;\[\r\n\ ]*int tgt_tgtsync\\.\[0-9\]+.6.;\[\r\n\ ]*void \\* pref_type\.\[0-9\]+.6.;\[\r\n\ ]*interopobjs\.\[0-9\]+.0. = &obj1;\[\r\n \]*tgt_tgtsync\.\[0-9\]+.0. = 1;\[\r\n \]*pref_type\.\[0-9\]+.0. = .*;\[\r\n \]*interopobjs\.\[0-9\]+.1. = &obj2;\[\r\n \]*tgt_tgtsync\.\[0-9\]+.1. = 1;\[\r\n \]*pref_type\.\[0-9\]+.1. = .*;\[\r\n \]*interopobjs\.\[0-9\]+.2. = &obj3;\[\r\n \]*tgt_tgtsync\.\[0-9\]+.2. = 1;\[\r\n \]*pref_type\.\[0-9\]+.2. = 0B;\[\r\n \]*interopobjs\.\[0-9\]+.3. = &obj4;\[\r\n \]*tgt_tgtsync\.\[0-9\]+.3. = 2;\[\r\n \]*pref_type\.\[0-9\]+.3. = .*;\[\r\n \]*interopobjs\.\[0-9\]+.4. = &obj7;\[\r\n \]*tgt_tgtsync\.\[0-9\]+.4. = 2;\[\r\n \]*pref_type\.\[0-9\]+.4. = .*;\[\r\n \]*interopobjs\.\[0-9\]+.5. = &obj5;\[\r\n \]*tgt_tgtsync\.\[0-9\]+.5. = 3;\[\r\n \]*pref_type\.\[0-9\]+.5. = .*;\[\r\n\ ]*__builtin_GOMP_interop \\(-5, 6, &interopobjs\.\[0-9\]+, &tgt_tgtsync\.\[0-9\]+, &pref_type\.\[0-9\]+, 0, 0B, 0, 0B, 0, 0B\\);" 1 "omplower" } } */
+
+
+ /* -------------------------------------------- */
+
+ #pragma omp interop init ( target, prefer_type( {fr("hip"), attr("ompx_gnu_prio:1", "ompx_gnu_debug")}, {attr("ompx_gnu_nicest"), attr("ompx_something")}) : obj1) destroy(obj3) nowait use(obj5)
+ /* { dg-final { scan-tree-dump-times "void \\* interopobjs\\.\[0-9\]+.1.;\[\r\n\ ]*int tgt_tgtsync\\.\[0-9\]+.1.;\[\r\n\ ]*void \\* pref_type\.\[0-9\]+.1.;\[\r\n\ ]*void \\* interopobjs\.\[0-9\]+.1.;\[\r\n\ ]*omp_interop_t obj5\.\[0-9\]+;\[\r\n\ ]*void \\* obj5\.\[0-9\]+;\[\r\n\ ]*void \\* interopobjs\.\[0-9\]+.1.;\[\r\n\ ]*interopobjs\.\[0-9\]+.0. = &obj1;\[\r\n\ ]*tgt_tgtsync\.\[0-9\]+.0. = 1;\[\r\n\ ]*pref_type\.\[0-9\]+.0. = .*;\[\r\n\ ]*obj5\.\[0-9\]+ = obj5;\[\r\n\ ]*obj5\.\[0-9\]+ = \\(void \\*\\) obj5\.\[0-9\]+;\[\r\n\ ]*interopobjs\.\[0-9\]+.0. = obj5\.\[0-9\]+;\[\r\n\ ]*interopobjs\.\[0-9\]+.0. = &obj3;\[\r\n\ ]*__builtin_GOMP_interop \\(-5, 1, &interopobjs\.\[0-9\]+, &tgt_tgtsync\.\[0-9\]+, &pref_type\.\[0-9\]+, 1, &interopobjs\.\[0-9\]+, 1, &interopobjs\.\[0-9\]+, 1, 0B\\);" 1 "omplower" } } */
+
+}
+
+void
+g (int *y)
+{
+ omp_interop_t io1, io2, io3, io4, io5;
+
+ [[omp::directive (interop,init(prefer_type({fr("level_zero")}, {fr(omp_ifr_sycl),attr("ompx_in_order"),attr("ompx_queue:in_order")}), targetsync : io1, io2),use(io3),destroy(io4,io5),depend(inout:y),nowait)]];
+ /* { dg-final { scan-tree-dump-times "void \\* D\.\[0-9\]+.3.;\[\r\n\ ]*void \\* interopobjs\.\[0-9\]+.2.;\[\r\n\ ]*int tgt_tgtsync\.\[0-9\]+.2.;\[\r\n\ ]*void \\* pref_type\.\[0-9\]+.2.;\[\r\n\ ]*void \\* interopobjs\.\[0-9\]+.1.;\[\r\n\ ]*void \\* io3\.\[0-9\]+;\[\r\n\ ]*void \\* interopobjs\.\[0-9\]+.2.;\[\r\n\ ]*interopobjs\.\[0-9\]+.0. = &io1;\[\r\n\ ]*tgt_tgtsync\.\[0-9\]+.0. = 2;\[\r\n\ ]*pref_type\.\[0-9\]+.0. = .*;\[\r\n\ ]*interopobjs\.\[0-9\]+.1. = &io2;\[\r\n\ ]*tgt_tgtsync\.\[0-9\]+.1. = 2;\[\r\n\ ]*pref_type\.\[0-9\]+.1. = .*;\[\r\n\ ]*io3\.\[0-9\]+ = \\(void \\*\\) io3;\[\r\n\ ]*interopobjs\.\[0-9\]+.0. = io3\.\[0-9\]+;\[\r\n\ ]*interopobjs\.\[0-9\]+.0. = &io4;\[\r\n\ ]*interopobjs\.\[0-9\]+.1. = &io5;\[\r\n\ ]*D\.\[0-9\]+.0. = 1B;\[\r\n\ ]*D\.\[0-9\]+.1. = 1B;\[\r\n\ ]*D\.\[0-9\]+.2. = &y;\[\r\n\ ]*__builtin_GOMP_interop \\(-5, 2, &interopobjs\.\[0-9\]+, &tgt_tgtsync\.\[0-9\]+, &pref_type\.\[0-9\]+, 1, &interopobjs\.\[0-9\]+, 2, &interopobjs\.\[0-9\]+, 1, &D\.\[0-9\]+\\);" 1 "omplower" { target c } } } */
+ /* { dg-final { scan-tree-dump-times "void \\* D\.\[0-9\]+.3.;\[\r\n\ ]*void \\* interopobjs\.\[0-9\]+.2.;\[\r\n\ ]*int tgt_tgtsync\.\[0-9\]+.2.;\[\r\n\ ]*void \\* pref_type\.\[0-9\]+.2.;\[\r\n\ ]*void \\* interopobjs\.\[0-9\]+.1.;\[\r\n\ ]*void \\* io3\.\[0-9\]+;\[\r\n\ ]*void \\* interopobjs\.\[0-9\]+.2.;\[\r\n\ ]*omp_interop_t io4\.\[0-9\]+;\[\r\n\ ]*omp_interop_t io5\.\[0-9\]+;\[\r\n\ ]*interopobjs\.\[0-9\]+.0. = &io1;\[\r\n\ ]*tgt_tgtsync\.\[0-9\]+.0. = 2;\[\r\n\ ]*pref_type\.\[0-9\]+.0. = .*;\[\r\n\ ]*interopobjs\.\[0-9\]+.1. = &io2;\[\r\n\ ]*tgt_tgtsync\.\[0-9\]+.1. = 2;\[\r\n\ ]*pref_type\.\[0-9\]+.1. = .*;\[\r\n\ ]*io3\.\[0-9\]+ = \\(void \\*\\) io3;\[\r\n\ ]*interopobjs\.\[0-9\]+.0. = io3\.\[0-9\]+;\[\r\n\ ]*io4\.\[0-9\]+ = io4;\[\r\n\ ]*interopobjs\.\[0-9\]+.0. = &io4\.\[0-9\]+;\[\r\n\ ]*io5\.\[0-9\]+ = io5;\[\r\n\ ]*interopobjs\.\[0-9\]+.1. = &io5\.\[0-9\]+;\[\r\n\ ]*D\.\[0-9\]+.0. = 1B;\[\r\n\ ]*D\.\[0-9\]+.1. = 1B;\[\r\n\ ]*D\.\[0-9\]+.2. = &y;\[\r\n\ ]*__builtin_GOMP_interop \\(-5, 2, &interopobjs\.\[0-9\]+, &tgt_tgtsync\.\[0-9\]+, &pref_type\.\[0-9\]+, 1, &interopobjs\.\[0-9\]+, 2, &interopobjs\.\[0-9\]+, 1, &D\.\[0-9\]+\\);" 1 "omplower" { target c++ } } } */
+}
diff --git a/gcc/testsuite/g++.dg/gomp/interop-5.C b/gcc/testsuite/g++.dg/gomp/interop-5.C
index 5109dc4..89396cf 100644
--- a/gcc/testsuite/g++.dg/gomp/interop-5.C
+++ b/gcc/testsuite/g++.dg/gomp/interop-5.C
@@ -1,8 +1,6 @@
/* { dg-do compile { target c++11 } } */
/* { dg-additional-options "-fdump-tree-original" } */
-/* { dg-prune-output "sorry, unimplemented: '#pragma omp interop' not yet supported" } */
-
/* The following definitions are in omp_lib, which cannot be included
in gcc/testsuite/ */
@@ -43,13 +41,13 @@ f ()
constexpr T3 ifr_level_zero = (T3) (omp_ifr_sycl + 2);
constexpr T3 ifr_invalid = (T3) 99;
- #pragma omp interop init ( obj1, obj2) use (obj3) destroy(obj4) init(obj5) destroy(obj6) use(obj7) /* { dg-message "'#pragma omp interop' not yet supported" } */
+ #pragma omp interop init ( obj1, obj2) use (obj3) destroy(obj4) init(obj5) destroy(obj6) use(obj7)
/* { dg-final { scan-tree-dump-times "#pragma omp interop use\\(obj7\\) destroy\\(obj6\\) init\\(obj5\\) destroy\\(obj4\\) use\\(obj3\\) init\\(obj2\\) init\\(obj1\\)\[\r\n\]" 2 "original" } } */
- #pragma omp interop nowait init (targetsync : obj1, obj2) use (obj3) destroy(obj4) init(target, targetsync : obj5) destroy(obj6) use(obj7) depend(inout: x) /* { dg-message "'#pragma omp interop' not yet supported" } */
+ #pragma omp interop nowait init (targetsync : obj1, obj2) use (obj3) destroy(obj4) init(target, targetsync : obj5) destroy(obj6) use(obj7) depend(inout: x)
/* { dg-final { scan-tree-dump-times "#pragma omp interop depend\\(inout:x\\) use\\(obj7\\) destroy\\(obj6\\) init\\(target, targetsync: obj5\\) destroy\\(obj4\\) use\\(obj3\\) init\\(targetsync: obj2\\) init\\(targetsync: obj1\\) nowait\[\r\n\]" 2 "original" } } */
- #pragma omp interop init ( obj1, obj2) init (target: obj3) init(targetsync : obj4) init(target,targetsync: obj5) /* { dg-message "'#pragma omp interop' not yet supported" } */
+ #pragma omp interop init ( obj1, obj2) init (target: obj3) init(targetsync : obj4) init(target,targetsync: obj5)
/* { dg-final { scan-tree-dump-times "#pragma omp interop init\\(target, targetsync: obj5\\) init\\(targetsync: obj4\\) init\\(target: obj3\\) init\\(obj2\\) init\\(obj1\\)\[\r\n\]" 2 "original" } } */
/* -------------------------------------------- */
@@ -64,7 +62,7 @@ f ()
{ dg-final { scan-tree-dump-times "#pragma omp interop init\\(prefer_type\\(\{fr\\(\"<unknown>\"\\)\}, \{fr\\(\"<unknown>\"\\)\}, \{fr\\(\"cuda\"\\)\}, \{fr\\(\"cuda_driver\"\\)\}, \{fr\\(\"hsa\"\\)\}, \{fr\\(\"<unknown>\"\\)\}, \{fr\\(\"<unknown>\"\\)\}\\), target: obj2\\) init\\(prefer_type\\(\{fr\\(\"<unknown>\"\\)\}, \{fr\\(\"<unknown>\"\\)\}, \{fr\\(\"cuda\"\\)\}, \{fr\\(\"cuda_driver\"\\)\}, \{fr\\(\"hsa\"\\)\}, \{fr\\(\"<unknown>\"\\)\}, \{fr\\(\"<unknown>\"\\)\}\\), target: obj1\\)\[\r\n\]" 2 "original" } }
*/
- #pragma omp interop init (target, prefer_type(ifr_cuda, ifr_cuda+1, "hsa", "myPrivateInterop", ifr_cuda-2) : obj1, obj2) init (target: obj3) init(prefer_type(ifr_hip, "sycl", ifr_opencl), targetsync : obj4, obj7) init(target,prefer_type("level_zero", ifr_level_zero+0),targetsync: obj5) /* { dg-message "'#pragma omp interop' not yet supported" } */
+ #pragma omp interop init (target, prefer_type(ifr_cuda, ifr_cuda+1, "hsa", "myPrivateInterop", ifr_cuda-2) : obj1, obj2) init (target: obj3) init(prefer_type(ifr_hip, "sycl", ifr_opencl), targetsync : obj4, obj7) init(target,prefer_type("level_zero", ifr_level_zero+0),targetsync: obj5)
/*
{ dg-warning "unknown foreign runtime identifier 'myPrivateInterop' \\\[-Wopenmp\\\]" "" { target *-*-* } .-2 }
{ dg-warning "unknown foreign runtime identifier '-1' \\\[-Wopenmp\\\]" "" { target *-*-* } .-3 }
@@ -74,7 +72,7 @@ f ()
/* -------------------------------------------- */
- #pragma omp interop init ( target, prefer_type( {fr("hip"), attr("ompx_gnu_prio:1", "ompx_gnu_debug")}, {attr("ompx_gnu_nicest"), attr("ompx_something")}) : obj1, obj2) init ( prefer_type( {fr("cuda")}, {fr(ifr_cuda_driver), attr("ompx_nix")}, {fr("best")}), targetsync : obj3, obj4) nowait use(obj5) /* { dg-message "'#pragma omp interop' not yet supported" } */
+ #pragma omp interop init ( target, prefer_type( {fr("hip"), attr("ompx_gnu_prio:1", "ompx_gnu_debug")}, {attr("ompx_gnu_nicest"), attr("ompx_something")}) : obj1, obj2) init ( prefer_type( {fr("cuda")}, {fr(ifr_cuda_driver), attr("ompx_nix")}, {fr("best")}), targetsync : obj3, obj4) nowait use(obj5)
/*
{ dg-warning "unknown foreign runtime identifier 'best' \\\[-Wopenmp\\\]" "" { target *-*-* } .-2 }
diff --git a/gcc/testsuite/gfortran.dg/gomp/interop-4.f90 b/gcc/testsuite/gfortran.dg/gomp/interop-4.f90
index 8783f4c..43c28d6 100644
--- a/gcc/testsuite/gfortran.dg/gomp/interop-4.f90
+++ b/gcc/testsuite/gfortran.dg/gomp/interop-4.f90
@@ -26,18 +26,18 @@ implicit none
integer(omp_interop_kind) :: obj1, obj2, obj3, obj4, obj5, obj6, obj7
integer :: x(6)
-!$omp interop init ( obj1, obj2) use (obj3) destroy(obj4) init(obj5) destroy(obj6) use(obj7) ! { dg-message "'#pragma omp interop' not yet supported" }
+!$omp interop init ( obj1, obj2) use (obj3) destroy(obj4) init(obj5) destroy(obj6) use(obj7)
! { dg-final { scan-tree-dump-times "#pragma omp interop init\\(obj1\\) init\\(obj2\\) init\\(obj5\\) use\\(obj3\\) use\\(obj7\\) destroy\\(obj4\\) destroy\\(obj6\\)\[\r\n\]" 1 "original" } }
-!$omp interop nowait init (targetsync : obj1, obj2) use (obj3) destroy(obj4) init(target, targetsync : obj5) destroy(obj6) use(obj7) depend(inout: x) ! { dg-message "'#pragma omp interop' not yet supported" }
+!$omp interop nowait init (targetsync : obj1, obj2) use (obj3) destroy(obj4) init(target, targetsync : obj5) destroy(obj6) use(obj7) depend(inout: x)
! { dg-final { scan-tree-dump-times "#pragma omp interop depend\\(inout:x\\) init\\(targetsync: obj1\\) init\\(targetsync: obj2\\) init\\(target, targetsync: obj5\\) use\\(obj3\\) use\\(obj7\\) destroy\\(obj4\\) destroy\\(obj6\\) nowait\[\r\n\]" 1 "original" } }
-!$omp interop init ( obj1, obj2) init (target: obj3) init(targetsync : obj4) init(target,targetsync: obj5) ! { dg-message "'#pragma omp interop' not yet supported" }
+!$omp interop init ( obj1, obj2) init (target: obj3) init(targetsync : obj4) init(target,targetsync: obj5)
! { dg-final { scan-tree-dump-times "#pragma omp interop init\\(obj1\\) init\\(obj2\\) init\\(target: obj3\\) init\\(targetsync: obj4\\) init\\(target, targetsync: obj5\\)\[\r\n\]" 1 "original" } }
! --------------------------------------------
-!$omp interop init (target, prefer_type(omp_ifr_cuda, omp_ifr_cuda+1, "hsa", "myPrivateInterop", omp_ifr_cuda-2) : obj1, obj2) init (target: obj3) init(prefer_type(omp_ifr_hip, "sycl", omp_ifr_opencl), targetsync : obj4, obj7) init(target,prefer_type("level_zero", omp_ifr_level_zero+0),targetsync: obj5) ! { dg-message "'#pragma omp interop' not yet supported" }
+!$omp interop init (target, prefer_type(omp_ifr_cuda, omp_ifr_cuda+1, "hsa", "myPrivateInterop", omp_ifr_cuda-2) : obj1, obj2) init (target: obj3) init(prefer_type(omp_ifr_hip, "sycl", omp_ifr_opencl), targetsync : obj4, obj7) init(target,prefer_type("level_zero", omp_ifr_level_zero+0),targetsync: obj5)
!
! { dg-warning "Unknown foreign runtime identifier 'myPrivateInterop' at \\(1\\) \\\[-Wopenmp\\\]" "" { target *-*-* } .-2 }
! { dg-warning "Unknown foreign runtime identifier '-1' at \\(1\\) \\\[-Wopenmp\\\]" "" { target *-*-* } .-3 }
@@ -47,7 +47,7 @@ integer :: x(6)
! --------------------------------------------
-!$omp interop init ( target, prefer_type( {fr(1_"hip"), attr("ompx_gnu_prio:1", 1_"ompx_gnu_debug")}, {attr("ompx_gnu_nicest"), attr("ompx_something")}) : obj1, obj2) init ( prefer_type( {fr("cuda")}, {fr(omp_ifr_cuda_driver), attr("ompx_nix")}, {fr("best")}), targetsync : obj3, obj4) nowait use(obj5) ! { dg-message "'#pragma omp interop' not yet supported" }
+!$omp interop init ( target, prefer_type( {fr(1_"hip"), attr("ompx_gnu_prio:1", 1_"ompx_gnu_debug")}, {attr("ompx_gnu_nicest"), attr("ompx_something")}) : obj1, obj2) init ( prefer_type( {fr("cuda")}, {fr(omp_ifr_cuda_driver), attr("ompx_nix")}, {fr("best")}), targetsync : obj3, obj4) nowait use(obj5)
!
! ! { dg-warning "Unknown foreign runtime identifier 'best' at \\(1\\) \\\[-Wopenmp\\\]" "" { target *-*-* } .-2 }
!
diff --git a/gcc/testsuite/gfortran.dg/gomp/interop-5.f90 b/gcc/testsuite/gfortran.dg/gomp/interop-5.f90
new file mode 100644
index 0000000..a6a2d71
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/interop-5.f90
@@ -0,0 +1,21 @@
+! { dg-additional-options "-fdump-tree-omplower" }
+
+subroutine sub1 (a1, a2, a3, a4)
+ use omp_lib, only: omp_interop_kind
+ integer(omp_interop_kind) :: a1 ! by ref
+ integer(omp_interop_kind), optional :: a2 ! as pointer
+ integer(omp_interop_kind), allocatable :: a3 ! ref to pointer
+ integer(omp_interop_kind), value :: a4
+ integer(omp_interop_kind) :: b
+
+ !$omp interop init(target : a1, a2, a3, a4, b)
+ ! { dg-final { scan-tree-dump-times "void \\* interopobjs\.\[0-9\]+\\\[5\\\];\[\r\n ]*integer\\(kind=4\\) tgt_tgtsync\.\[0-9\]+\\\[5\\\];\[\r\n ]*integer\\(kind=8\\) \\* & a3\.\[0-9\]+;\[\r\n ]*integer\\(kind=8\\) \\* D\.\[0-9\]+;\[\r\n ]*integer\\(kind=8\\) \\* a2\.\[0-9\]+;\[\r\n ]*integer\\(kind=8\\) & a1\.\[0-9\]+;\[\r\n ]*interopobjs\.\[0-9\]+\\\[0\\\] = &b;\[\r\n ]*tgt_tgtsync\.\[0-9\]+\\\[0\\\] = 1;\[\r\n ]*interopobjs\.\[0-9\]+\\\[1\\\] = &a4;\[\r\n ]*tgt_tgtsync\.\[0-9\]+\\\[1\\\] = 1;\[\r\n ]*a3\.\[0-9\]+ = a3;\[\r\n ]*D\.\[0-9\]+ = \\*a3\.\[0-9\]+;\[\r\n ]*interopobjs\.\[0-9\]+\\\[2\\\] = D\.\[0-9\]+;\[\r\n ]*tgt_tgtsync\.\[0-9\]+\\\[2\\\] = 1;\[\r\n ]*a2\.\[0-9\]+ = a2;\[\r\n ]*interopobjs\.\[0-9\]+\\\[3\\\] = a2\.\[0-9\]+;\[\r\n ]*tgt_tgtsync\.\[0-9\]+\\\[3\\\] = 1;\[\r\n ]*a1\.\[0-9\]+ = a1;\[\r\n ]*interopobjs\.\[0-9\]+\\\[4\\\] = a1\.\[0-9\]+;\[\r\n ]*tgt_tgtsync\.\[0-9\]+\\\[4\\\] = 1;\[\r\n ]*__builtin_GOMP_interop \\(-5, 5, &interopobjs\.\[0-9\]+, &tgt_tgtsync\.\[0-9\]+, 0B, 0, 0B, 0, 0B, 0, 0B\\);" 1 "omplower" } }
+
+ !$omp interop use(a1, a2, a3, a4, b)
+ ! { dg-final { scan-tree-dump-times "void \\* interopobjs\.\[0-9\]+\\\[5\\\];\[\r\n ]*integer\\(kind=8\\) b\.\[0-9\]+;\[\r\n ]*void \\* b\.\[0-9\]+;\[\r\n ]*integer\\(kind=8\\) a4\.\[0-9\]+;\[\r\n ]*void \\* a4\.\[0-9\]+;\[\r\n ]*integer\\(kind=8\\) \\* & a3\.\[0-9\]+;\[\r\n ]*integer\\(kind=8\\) \\* D\.\[0-9\]+;\[\r\n ]*integer\\(kind=8\\) D\.\[0-9\]+;\[\r\n ]*void \\* D\.\[0-9\]+;\[\r\n ]*integer\\(kind=8\\) \\* a2\.\[0-9\]+;\[\r\n ]*integer\\(kind=8\\) D\.\[0-9\]+;\[\r\n ]*void \\* D\.\[0-9\]+;\[\r\n ]*integer\\(kind=8\\) & a1\.\[0-9\]+;\[\r\n ]*integer\\(kind=8\\) D\.\[0-9\]+;\[\r\n ]*void \\* D\.\[0-9\]+;\[\r\n ]*b\.\[0-9\]+ = b;\[\r\n ]*b\.\[0-9\]+ = \\(void \\*\\) b\.\[0-9\]+;\[\r\n ]*interopobjs\.\[0-9\]+\\\[0\\\] = b\.\[0-9\]+;\[\r\n ]*a4\.\[0-9\]+ = a4;\[\r\n ]*a4\.\[0-9\]+ = \\(void \\*\\) a4\.\[0-9\]+;\[\r\n ]*interopobjs\.\[0-9\]+\\\[1\\\] = a4\.\[0-9\]+;\[\r\n ]*a3\.\[0-9\]+ = a3;\[\r\n ]*D\.\[0-9\]+ = \\*a3\.\[0-9\]+;\[\r\n ]*D\.\[0-9\]+ = \\*D\.\[0-9\]+;\[\r\n ]*D\.\[0-9\]+ = \\(void \\*\\) D\.\[0-9\]+;\[\r\n ]*interopobjs\.\[0-9\]+\\\[2\\\] = D\.\[0-9\]+;\[\r\n ]*a2\.\[0-9\]+ = a2;\[\r\n ]*D\.\[0-9\]+ = \\*a2\.\[0-9\]+;\[\r\n ]*D\.\[0-9\]+ = \\(void \\*\\) D\.\[0-9\]+;\[\r\n ]*interopobjs\.\[0-9\]+\\\[3\\\] = D\.\[0-9\]+;\[\r\n ]*a1\.\[0-9\]+ = a1;\[\r\n ]*D\.\[0-9\]+ = \\*a1\.\[0-9\]+;\[\r\n ]*D\.\[0-9\]+ = \\(void \\*\\) D\.\[0-9\]+;\[\r\n ]*interopobjs\.\[0-9\]+\\\[4\\\] = D\.\[0-9\]+;\[\r\n ]*__builtin_GOMP_interop \\(-5, 0, 0B, 0B, 0B, 5, &interopobjs\.\[0-9\]+, 0, 0B, 0, 0B\\);" 1 "omplower" } }
+
+ !$omp interop destroy(a1, a2, a3, a4, b)
+ ! { dg-final { scan-tree-dump-times "void \\* interopobjs\.\[0-9\]+\\\[5\\\];\[\r\n ]*integer\\(kind=8\\) \\* & a3\.\[0-9\]+;\[\r\n ]*integer\\(kind=8\\) \\* D\.\[0-9\]+;\[\r\n ]*integer\\(kind=8\\) \\* a2\.\[0-9\]+;\[\r\n ]*integer\\(kind=8\\) & a1\.\[0-9\]+;\[\r\n ]*interopobjs\.\[0-9\]+\\\[0\\\] = &b;\[\r\n ]*interopobjs\.\[0-9\]+\\\[1\\\] = &a4;\[\r\n ]*a3\.\[0-9\]+ = a3;\[\r\n ]*D\.\[0-9\]+ = \\*a3\.\[0-9\]+;\[\r\n ]*interopobjs\.\[0-9\]+\\\[2\\\] = D\.\[0-9\]+;\[\r\n ]*a2\.\[0-9\]+ = a2;\[\r\n ]*interopobjs\.\[0-9\]+\\\[3\\\] = a2\.\[0-9\]+;\[\r\n ]*a1\.\[0-9\]+ = a1;\[\r\n ]*interopobjs\.\[0-9\]+\\\[4\\\] = a1\.\[0-9\]+;\[\r\n ]*__builtin_GOMP_interop \\(-5, 0, 0B, 0B, 0B, 0, 0B, 5, &interopobjs\.\[0-9\]+, 0, 0B\\);" 1 "omplower" } }
+end subroutine
+
+