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>
This commit is contained in:
parent
f45d14b495
commit
99e2906ae2
29 changed files with 775 additions and 66 deletions
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
33
gcc/gimple.h
33
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: \
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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,
|
||||
|
|
233
gcc/omp-low.cc
233
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);
|
||||
|
|
|
@ -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/ */
|
||||
|
||||
|
|
|
@ -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/ */
|
||||
|
||||
|
|
|
@ -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/ */
|
||||
|
||||
|
|
|
@ -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" } } */
|
||||
}
|
||||
|
|
68
gcc/testsuite/c-c++-common/gomp/interop-5.c
Normal file
68
gcc/testsuite/c-c++-common/gomp/interop-5.c
Normal file
|
@ -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++ } } } */
|
||||
}
|
|
@ -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 }
|
||||
|
||||
|
|
|
@ -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 }
|
||||
!
|
||||
|
|
21
gcc/testsuite/gfortran.dg/gomp/interop-5.f90
Normal file
21
gcc/testsuite/gfortran.dg/gomp/interop-5.f90
Normal file
|
@ -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
|
||||
|
||||
|
|
@ -280,10 +280,14 @@ enum gomp_map_kind
|
|||
omp_invalid_device) to -3 (so that for dev_num >= -2U we can
|
||||
subtract 1). -4 is then what we use for omp_invalid_device,
|
||||
which unlike the other non-conforming device numbers results
|
||||
in fatal error regardless of OMP_TARGET_OFFLOAD. */
|
||||
in fatal error regardless of OMP_TARGET_OFFLOAD.
|
||||
Furthermore, OpenMP 6.1 exposes the default device to the user; hence,
|
||||
GOMP_DEVICE_DEFAULT_OMP_61 can be used for it,
|
||||
with and without remapped device numbers. */
|
||||
#define GOMP_DEVICE_ICV -1
|
||||
#define GOMP_DEVICE_HOST_FALLBACK -2
|
||||
#define GOMP_DEVICE_INVALID -4
|
||||
#define GOMP_DEVICE_DEFAULT_OMP_61 -5
|
||||
|
||||
/* GOMP_task/GOMP_taskloop* flags argument. */
|
||||
#define GOMP_TASK_FLAG_UNTIED (1 << 0)
|
||||
|
@ -406,6 +410,13 @@ enum gomp_map_kind
|
|||
#define GOMP_INTEROP_IFR_SEPARATOR ((char)(-__INT8_MAX__-1))
|
||||
#define GOMP_INTEROP_IFR_UNKNOWN ((char)(-__INT8_MAX__))
|
||||
|
||||
/* GOMP_interop target_targetsync argument. */
|
||||
#define GOMP_INTEROP_TARGET (1 << 0)
|
||||
#define GOMP_INTEROP_TARGETSYNC (1 << 1)
|
||||
|
||||
/* GOMP_interop flags argument. */
|
||||
#define GOMP_INTEROP_FLAG_NOWAIT (1 << 0)
|
||||
|
||||
/* HSA specific data structures. */
|
||||
|
||||
/* Identifiers of device-specific target arguments. */
|
||||
|
|
|
@ -32,8 +32,11 @@
|
|||
void
|
||||
omp_set_default_device (int device_num)
|
||||
{
|
||||
struct gomp_task_icv *icv = gomp_icv (true);
|
||||
icv->default_device_var = device_num;
|
||||
if (device_num != GOMP_DEVICE_DEFAULT_OMP_61)
|
||||
{
|
||||
struct gomp_task_icv *icv = gomp_icv (true);
|
||||
icv->default_device_var = device_num;
|
||||
}
|
||||
}
|
||||
|
||||
ialias (omp_set_default_device)
|
||||
|
|
|
@ -33,6 +33,14 @@
|
|||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef _LIBGOMP_PLUGIN_INCLUDE
|
||||
/* Include 'omp.h' for the interop definitions. */
|
||||
#define _LIBGOMP_OMP_LOCK_DEFINED 1
|
||||
typedef struct omp_lock_t omp_lock_t;
|
||||
typedef struct omp_nest_lock_t omp_nest_lock_t;
|
||||
#include "omp.h.in"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
@ -101,6 +109,25 @@ struct addr_pair
|
|||
uintptr_t end;
|
||||
};
|
||||
|
||||
|
||||
#ifdef _LIBGOMP_OMP_LOCK_DEFINED
|
||||
/* Only define when omp.h.in was included, as in plugin/ and in libgomp.h. */
|
||||
struct interop_obj_t
|
||||
{
|
||||
void *stream;
|
||||
void *device_data;
|
||||
omp_interop_fr_t fr;
|
||||
int device_num;
|
||||
};
|
||||
|
||||
enum gomp_interop_flag
|
||||
{
|
||||
gomp_interop_flag_init,
|
||||
gomp_interop_flag_use,
|
||||
gomp_interop_flag_destroy
|
||||
};
|
||||
#endif
|
||||
|
||||
/* This following symbol is used to name the target side variable struct that
|
||||
holds the designated ICVs of the target device. The symbol needs to be
|
||||
available to libgomp code and the offload plugin (which in the latter case
|
||||
|
@ -181,6 +208,23 @@ extern int GOMP_OFFLOAD_openacc_cuda_set_stream (struct goacc_asyncqueue *,
|
|||
extern union goacc_property_value
|
||||
GOMP_OFFLOAD_openacc_get_property (int, enum goacc_property);
|
||||
|
||||
#ifdef _LIBGOMP_OMP_LOCK_DEFINED
|
||||
/* Only define when omp.h.in was included, as in plugin/ and in libgomp.h. */
|
||||
extern void GOMP_OFFLOAD_interop (struct interop_obj_t *, int,
|
||||
enum gomp_interop_flag, bool, const char *);
|
||||
extern intptr_t GOMP_OFFLOAD_get_interop_int (struct interop_obj_t *,
|
||||
omp_interop_property_t,
|
||||
omp_interop_rc_t *);
|
||||
extern void *GOMP_OFFLOAD_get_interop_ptr (struct interop_obj_t *,
|
||||
omp_interop_property_t,
|
||||
omp_interop_rc_t *);
|
||||
extern const char *GOMP_OFFLOAD_get_interop_str (struct interop_obj_t *obj,
|
||||
omp_interop_property_t,
|
||||
omp_interop_rc_t *);
|
||||
extern const char *GOMP_OFFLOAD_get_interop_type_desc (struct interop_obj_t *,
|
||||
omp_interop_property_t);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -43,7 +43,14 @@
|
|||
|
||||
#include "config.h"
|
||||
#include <stdint.h>
|
||||
|
||||
/* Include omp.h by parts. */
|
||||
#include "omp-lock.h"
|
||||
#define _LIBGOMP_OMP_LOCK_DEFINED 1
|
||||
#include "omp.h.in"
|
||||
|
||||
#include "libgomp-plugin.h"
|
||||
|
||||
#include "gomp-constants.h"
|
||||
|
||||
#ifdef HAVE_PTHREAD_H
|
||||
|
@ -1419,6 +1426,11 @@ struct gomp_device_descr
|
|||
__typeof (GOMP_OFFLOAD_can_run) *can_run_func;
|
||||
__typeof (GOMP_OFFLOAD_run) *run_func;
|
||||
__typeof (GOMP_OFFLOAD_async_run) *async_run_func;
|
||||
__typeof (GOMP_OFFLOAD_interop) *interop_func;
|
||||
__typeof (GOMP_OFFLOAD_get_interop_int) *get_interop_int_func;
|
||||
__typeof (GOMP_OFFLOAD_get_interop_ptr) *get_interop_ptr_func;
|
||||
__typeof (GOMP_OFFLOAD_get_interop_str) *get_interop_str_func;
|
||||
__typeof (GOMP_OFFLOAD_get_interop_type_desc) *get_interop_type_desc_func;
|
||||
|
||||
/* Splay tree containing information about mapped memory regions. */
|
||||
struct splay_tree_s mem_map;
|
||||
|
@ -1501,11 +1513,6 @@ gomp_work_share_init_done (void)
|
|||
/* Now that we're back to default visibility, include the globals. */
|
||||
#include "libgomp_g.h"
|
||||
|
||||
/* Include omp.h by parts. */
|
||||
#include "omp-lock.h"
|
||||
#define _LIBGOMP_OMP_LOCK_DEFINED 1
|
||||
#include "omp.h.in"
|
||||
|
||||
#if !defined (HAVE_ATTRIBUTE_VISIBILITY) \
|
||||
|| !defined (HAVE_ATTRIBUTE_ALIAS) \
|
||||
|| !defined (HAVE_AS_SYMVER_DIRECTIVE) \
|
||||
|
|
|
@ -430,6 +430,7 @@ GOMP_5.1.2 {
|
|||
|
||||
GOMP_5.1.3 {
|
||||
global:
|
||||
GOMP_interop;
|
||||
omp_get_num_interop_properties;
|
||||
omp_get_interop_int;
|
||||
omp_get_interop_ptr;
|
||||
|
|
|
@ -358,6 +358,10 @@ extern void GOMP_target_enter_exit_data (int, size_t, void **, size_t *,
|
|||
extern void GOMP_teams (unsigned int, unsigned int);
|
||||
extern bool GOMP_teams4 (unsigned int, unsigned int, unsigned int, bool);
|
||||
extern void *GOMP_target_map_indirect_ptr (void *);
|
||||
struct interop_obj_t;
|
||||
extern void GOMP_interop (int, int, struct interop_obj_t ***, const int *,
|
||||
const char **, int, struct interop_obj_t **, int,
|
||||
struct interop_obj_t ***, unsigned, void **);
|
||||
|
||||
/* teams.c */
|
||||
|
||||
|
|
213
libgomp/target.c
213
libgomp/target.c
|
@ -146,7 +146,8 @@ resolve_device (int device_id, bool remapped)
|
|||
called, which must be done before using default_device_var. */
|
||||
int num_devices = gomp_get_num_devices ();
|
||||
|
||||
if (remapped && device_id == GOMP_DEVICE_ICV)
|
||||
if ((remapped && device_id == GOMP_DEVICE_ICV)
|
||||
|| device_id == GOMP_DEVICE_DEFAULT_OMP_61)
|
||||
{
|
||||
struct gomp_task_icv *icv = gomp_icv (false);
|
||||
device_id = icv->default_device_var;
|
||||
|
@ -5136,45 +5137,78 @@ omp_get_num_interop_properties (const omp_interop_t interop
|
|||
}
|
||||
|
||||
omp_intptr_t
|
||||
omp_get_interop_int (const omp_interop_t interop __attribute__ ((unused)),
|
||||
omp_get_interop_int (const omp_interop_t interop,
|
||||
omp_interop_property_t property_id,
|
||||
omp_interop_rc_t *ret_code)
|
||||
{
|
||||
if (ret_code == NULL)
|
||||
return 0;
|
||||
struct interop_obj_t *obj = (struct interop_obj_t *) interop;
|
||||
struct gomp_device_descr *devicep;
|
||||
|
||||
if (property_id < omp_ipr_first || property_id >= 0)
|
||||
*ret_code = omp_irc_out_of_range;
|
||||
else
|
||||
*ret_code = omp_irc_empty; /* Assume omp_interop_none. */
|
||||
return 0;
|
||||
{
|
||||
if (ret_code)
|
||||
*ret_code = omp_irc_out_of_range;
|
||||
return 0;
|
||||
}
|
||||
if (obj == NULL
|
||||
|| (devicep = resolve_device (obj->device_num, false)) == NULL
|
||||
|| devicep->get_interop_int_func == NULL)
|
||||
{
|
||||
if (ret_code)
|
||||
*ret_code = omp_irc_empty; /* Assume omp_interop_none. */
|
||||
return 0;
|
||||
}
|
||||
return devicep->get_interop_int_func (obj, property_id, ret_code);
|
||||
}
|
||||
|
||||
void *
|
||||
omp_get_interop_ptr (const omp_interop_t interop __attribute__ ((unused)),
|
||||
omp_get_interop_ptr (const omp_interop_t interop,
|
||||
omp_interop_property_t property_id,
|
||||
omp_interop_rc_t *ret_code)
|
||||
{
|
||||
if (ret_code == NULL)
|
||||
return NULL;
|
||||
struct interop_obj_t *obj = (struct interop_obj_t *) interop;
|
||||
struct gomp_device_descr *devicep;
|
||||
|
||||
if (property_id < omp_ipr_first || property_id >= 0)
|
||||
*ret_code = omp_irc_out_of_range;
|
||||
else
|
||||
*ret_code = omp_irc_empty; /* Assume omp_interop_none. */
|
||||
return NULL;
|
||||
{
|
||||
if (ret_code)
|
||||
*ret_code = omp_irc_out_of_range;
|
||||
return 0;
|
||||
}
|
||||
if (obj == NULL
|
||||
|| (devicep = resolve_device (obj->device_num, false)) == NULL
|
||||
|| devicep->get_interop_int_func == NULL)
|
||||
{
|
||||
if (ret_code)
|
||||
*ret_code = omp_irc_empty; /* Assume omp_interop_none. */
|
||||
return 0;
|
||||
}
|
||||
return devicep->get_interop_ptr_func (obj, property_id, ret_code);
|
||||
}
|
||||
|
||||
const char *
|
||||
omp_get_interop_str (const omp_interop_t interop __attribute__ ((unused)),
|
||||
omp_get_interop_str (const omp_interop_t interop,
|
||||
omp_interop_property_t property_id,
|
||||
omp_interop_rc_t *ret_code)
|
||||
{
|
||||
if (ret_code == NULL)
|
||||
return NULL;
|
||||
struct interop_obj_t *obj = (struct interop_obj_t *) interop;
|
||||
struct gomp_device_descr *devicep;
|
||||
|
||||
if (property_id < omp_ipr_first || property_id >= 0)
|
||||
*ret_code = omp_irc_out_of_range;
|
||||
else
|
||||
*ret_code = omp_irc_empty; /* Assume omp_interop_none. */
|
||||
return NULL;
|
||||
{
|
||||
if (ret_code)
|
||||
*ret_code = omp_irc_out_of_range;
|
||||
return 0;
|
||||
}
|
||||
if (obj == NULL
|
||||
|| (devicep = resolve_device (obj->device_num, false)) == NULL
|
||||
|| devicep->get_interop_int_func == NULL)
|
||||
{
|
||||
if (ret_code)
|
||||
*ret_code = omp_irc_empty; /* Assume omp_interop_none. */
|
||||
return 0;
|
||||
}
|
||||
return devicep->get_interop_str_func (obj, property_id, ret_code);
|
||||
}
|
||||
|
||||
const char *
|
||||
|
@ -5194,18 +5228,24 @@ omp_get_interop_type_desc (const omp_interop_t interop,
|
|||
omp_interop_property_t property_id)
|
||||
{
|
||||
static const char *desc[omp_ipr_fr_id - omp_ipr_device_num + 1]
|
||||
= {"omp_interop_t", /* fr_id */
|
||||
"const char*", /* fr_name */
|
||||
= {"omp_interop_t", /* fr_id */
|
||||
"const char *", /* fr_name */
|
||||
"int", /* vendor */
|
||||
"const char *", /* vendor_name */
|
||||
"int"}; /* device_num */
|
||||
|
||||
struct interop_obj_t *obj = (struct interop_obj_t *) interop;
|
||||
struct gomp_device_descr *devicep;
|
||||
|
||||
if (property_id > omp_ipr_fr_id || property_id < omp_ipr_first)
|
||||
return NULL;
|
||||
if (interop == omp_interop_none)
|
||||
if (obj == NULL
|
||||
|| (devicep = resolve_device (obj->device_num, false)) == NULL
|
||||
|| devicep->get_interop_int_func == NULL)
|
||||
return NULL;
|
||||
if (property_id >= omp_ipr_device_num)
|
||||
return desc[omp_ipr_fr_id - property_id];
|
||||
return NULL; /* FIXME: Call plugin. */
|
||||
return devicep->get_interop_type_desc_func (obj, property_id);
|
||||
}
|
||||
|
||||
const char *
|
||||
|
@ -5236,6 +5276,119 @@ ialias (omp_get_interop_name)
|
|||
ialias (omp_get_interop_type_desc)
|
||||
ialias (omp_get_interop_rc_desc)
|
||||
|
||||
struct interop_data_t
|
||||
{
|
||||
int device_num, n_init, n_use, n_destroy;
|
||||
struct interop_obj_t ***init;
|
||||
struct interop_obj_t **use;
|
||||
struct interop_obj_t ***destroy;
|
||||
const int *target_targetsync;
|
||||
const char **prefer_type;
|
||||
};
|
||||
|
||||
static void
|
||||
gomp_interop_internal (void *data)
|
||||
{
|
||||
struct interop_data_t *args = (struct interop_data_t *) data;
|
||||
struct gomp_device_descr *devicep;
|
||||
|
||||
/* Destroy objects to free resources. */
|
||||
for (int i = 0; i < args->n_destroy; i++)
|
||||
{
|
||||
struct interop_obj_t **obj = args->destroy[i];
|
||||
if (*obj == NULL /* omp_interop_none */)
|
||||
continue;
|
||||
devicep = resolve_device ((*obj)->device_num, false);
|
||||
if (devicep != NULL && devicep->interop_func)
|
||||
devicep->interop_func (*obj, devicep->target_id,
|
||||
gomp_interop_flag_destroy, false, NULL);
|
||||
free (*obj);
|
||||
*obj = NULL;
|
||||
}
|
||||
|
||||
/* Init streams next to give 'use' more time for completion. */
|
||||
if (args->n_init)
|
||||
{
|
||||
devicep = resolve_device (args->device_num, false);
|
||||
for (int i = 0; i < args->n_init; i++)
|
||||
{
|
||||
struct interop_obj_t **obj = args->init[i];
|
||||
bool targetsync
|
||||
= (args->target_targetsync[i] & GOMP_INTEROP_TARGETSYNC);
|
||||
const char *prefer_type
|
||||
= (args->prefer_type ? args->prefer_type[i] : NULL);
|
||||
if (devicep == NULL || !devicep->interop_func)
|
||||
{
|
||||
*obj = NULL;
|
||||
continue;
|
||||
}
|
||||
*obj =
|
||||
(struct interop_obj_t *) calloc (1, sizeof (struct interop_obj_t));
|
||||
devicep->interop_func (*obj, devicep->target_id,
|
||||
gomp_interop_flag_init, targetsync,
|
||||
prefer_type);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < args->n_use; i++)
|
||||
{
|
||||
struct interop_obj_t *obj = args->use[i];
|
||||
if (obj == NULL)
|
||||
continue;
|
||||
devicep = resolve_device (obj->device_num, false);
|
||||
if (devicep != NULL && devicep->interop_func)
|
||||
devicep->interop_func (obj, devicep->target_id,
|
||||
gomp_interop_flag_use, false, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/* Process the OpenMP interop directive. 'init' and 'destroy' take an array
|
||||
of 'omp_interop_t *', 'use' an array of 'omp_interop_t', where
|
||||
'omp_interop_t' is internally 'struct interop_obj_t *';
|
||||
'flags' is used for the 'nowait' clause. */
|
||||
|
||||
void
|
||||
GOMP_interop (int device_num, int n_init, struct interop_obj_t ***init,
|
||||
const int *target_targetsync, const char **prefer_type, int n_use,
|
||||
struct interop_obj_t **use, int n_destroy,
|
||||
struct interop_obj_t ***destroy, unsigned int flags,
|
||||
void **depend)
|
||||
{
|
||||
struct interop_data_t args;
|
||||
args.device_num = device_num;
|
||||
args.n_init = n_init;
|
||||
args.n_use = n_use;
|
||||
args.n_destroy = n_destroy;
|
||||
args.init = init;
|
||||
args.target_targetsync = target_targetsync;
|
||||
args.prefer_type = prefer_type;
|
||||
args.use = use;
|
||||
args.destroy = destroy;
|
||||
|
||||
/* No need to create a task for 'init' as that should be fast. */
|
||||
bool use_task = false;
|
||||
if (flags & GOMP_INTEROP_FLAG_NOWAIT)
|
||||
{
|
||||
for (int i = 0; i < n_use && !use_task; i++)
|
||||
if (args.use[i])
|
||||
use_task |= args.use[i]->stream != NULL;
|
||||
for (int i = 0; i < n_destroy && !use_task; i++)
|
||||
if (*args.destroy[i])
|
||||
use_task |= (*args.destroy[i])->stream != NULL;
|
||||
}
|
||||
|
||||
if (use_task)
|
||||
GOMP_task (gomp_interop_internal, &args, NULL, sizeof (args),
|
||||
__alignof__ (args), true, depend ? GOMP_TASK_FLAG_DEPEND : 0,
|
||||
depend, 0, NULL);
|
||||
else
|
||||
{
|
||||
gomp_interop_internal (&args);
|
||||
if (depend)
|
||||
GOMP_taskwait_depend (depend);
|
||||
}
|
||||
}
|
||||
|
||||
static const char *
|
||||
gomp_get_uid_for_device (struct gomp_device_descr *devicep, int device_num)
|
||||
{
|
||||
|
@ -5344,6 +5497,14 @@ gomp_load_plugin_for_device (struct gomp_device_descr *device,
|
|||
DLSYM (host2dev);
|
||||
DLSYM_OPT (memcpy2d, memcpy2d);
|
||||
DLSYM_OPT (memcpy3d, memcpy3d);
|
||||
if (DLSYM_OPT (interop, interop))
|
||||
{
|
||||
DLSYM (get_interop_int);
|
||||
DLSYM (get_interop_ptr);
|
||||
DLSYM (get_interop_str);
|
||||
DLSYM (get_interop_type_desc);
|
||||
}
|
||||
|
||||
device->capabilities = device->get_caps_func ();
|
||||
if (device->capabilities & GOMP_OFFLOAD_CAP_OPENMP_400)
|
||||
{
|
||||
|
|
43
libgomp/testsuite/libgomp.c-c++-common/interop-1.c
Normal file
43
libgomp/testsuite/libgomp.c-c++-common/interop-1.c
Normal file
|
@ -0,0 +1,43 @@
|
|||
/* { dg-do run } */
|
||||
|
||||
#include <omp.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
int dev = omp_get_num_devices ();
|
||||
int x[6];
|
||||
omp_interop_t obj1 = omp_interop_none;
|
||||
#pragma omp interop init(targetsync : obj1) depend(in : x) device(dev)
|
||||
if (obj1 != omp_interop_none)
|
||||
abort ();
|
||||
|
||||
#pragma omp interop use(obj1)
|
||||
#pragma omp interop destroy(obj1) depend(out : x)
|
||||
if (obj1 != omp_interop_none)
|
||||
abort ();
|
||||
|
||||
omp_set_default_device (dev);
|
||||
omp_interop_t obj2;
|
||||
|
||||
#pragma omp interop init( \
|
||||
target, targetsync, \
|
||||
prefer_type({fr("hip"), attr("ompx_gnu_prio:1", "ompx_gnu_debug")}, \
|
||||
{attr("ompx_gnu_nicest"), attr("ompx_something")}) : obj1, \
|
||||
obj2) nowait
|
||||
if (obj1 != omp_interop_none || obj2 != omp_interop_none)
|
||||
abort ();
|
||||
#pragma omp interop use(obj1, obj2) nowait
|
||||
|
||||
omp_interop_t obj3 = __omp_interop_t_max__;
|
||||
|
||||
#pragma omp interop init(target : obj3) use(obj2) destroy(obj1) nowait
|
||||
if (obj1 != omp_interop_none || obj3 != omp_interop_none)
|
||||
abort ();
|
||||
#pragma omp interop destroy(obj3, obj2) nowait
|
||||
if (obj2 != omp_interop_none || obj3 != omp_interop_none)
|
||||
abort ();
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Add table
Reference in a new issue