OpenMP: C++ front-end support for dispatch + adjust_args
This patch adds C++ support for the `dispatch` construct and the `adjust_args` clause. It relies on the c-family bits comprised in the corresponding C front end patch for pragmas and attributes. Additional C/C++ common testcases are provided in a subsequent patch in the series. gcc/cp/ChangeLog: * decl.cc (omp_declare_variant_finalize_one): Set adjust_args need_device_ptr attribute. * parser.cc (cp_parser_direct_declarator): Update call to cp_parser_late_return_type_opt. (cp_parser_late_return_type_opt): Add 'tree parms' parameter. Update call to cp_parser_late_parsing_omp_declare_simd. (cp_parser_omp_clause_name): Handle nocontext and novariants clauses. (cp_parser_omp_clause_novariants): New function. (cp_parser_omp_clause_nocontext): Likewise. (cp_parser_omp_all_clauses): Handle PRAGMA_OMP_CLAUSE_NOVARIANTS and PRAGMA_OMP_CLAUSE_NOCONTEXT. (cp_parser_omp_dispatch_body): New function, inspired from cp_parser_assignment_expression and cp_parser_postfix_expression. (OMP_DISPATCH_CLAUSE_MASK): Define. (cp_parser_omp_dispatch): New function. (cp_finish_omp_declare_variant): Add parameter. Handle adjust_args clause. (cp_parser_late_parsing_omp_declare_simd): Add parameter. Update calls to cp_finish_omp_declare_variant and cp_finish_omp_declare_variant. (cp_parser_omp_construct): Handle PRAGMA_OMP_DISPATCH. (cp_parser_pragma): Likewise. * semantics.cc (finish_omp_clauses): Handle OMP_CLAUSE_NOCONTEXT and OMP_CLAUSE_NOVARIANTS. * pt.cc (tsubst_omp_clauses): Handle OMP_CLAUSE_NOCONTEXT and OMP_CLAUSE_NOVARIANTS. (tsubst_stmt): Handle OMP_DISPATCH. (tsubst_expr): Handle IFN_GOMP_DISPATCH. gcc/testsuite/ChangeLog: * g++.dg/gomp/adjust-args-1.C: New test. * g++.dg/gomp/adjust-args-2.C: New test. * g++.dg/gomp/adjust-args-3.C: New test. * g++.dg/gomp/dispatch-1.C: New test. * g++.dg/gomp/dispatch-2.C: New test. * g++.dg/gomp/dispatch-3.C: New test. * g++.dg/gomp/dispatch-4.C: New test. * g++.dg/gomp/dispatch-5.C: New test. * g++.dg/gomp/dispatch-6.C: New test. * g++.dg/gomp/dispatch-7.C: New test.
This commit is contained in:
parent
d7d8d9dae9
commit
ed49709acd
14 changed files with 818 additions and 48 deletions
|
@ -8401,6 +8401,13 @@ omp_declare_variant_finalize_one (tree decl, tree attr)
|
|||
if (!omp_context_selector_matches (ctx))
|
||||
return true;
|
||||
TREE_PURPOSE (TREE_VALUE (attr)) = variant;
|
||||
|
||||
// Prepend adjust_args list to variant attributes
|
||||
tree adjust_args_list = TREE_CHAIN (TREE_CHAIN (chain));
|
||||
if (adjust_args_list != NULL_TREE)
|
||||
DECL_ATTRIBUTES (variant) = tree_cons (
|
||||
get_identifier ("omp declare variant variant adjust_args"),
|
||||
TREE_VALUE (adjust_args_list), DECL_ATTRIBUTES (variant));
|
||||
}
|
||||
}
|
||||
else if (!processing_template_decl)
|
||||
|
|
472
gcc/cp/parser.cc
472
gcc/cp/parser.cc
|
@ -19,6 +19,7 @@ along with GCC; see the file COPYING3. If not see
|
|||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include "config.h"
|
||||
#include "omp-selectors.h"
|
||||
#define INCLUDE_MEMORY
|
||||
#include "system.h"
|
||||
#include "coretypes.h"
|
||||
|
@ -2603,7 +2604,7 @@ static cp_ref_qualifier cp_parser_ref_qualifier_opt
|
|||
static tree cp_parser_tx_qualifier_opt
|
||||
(cp_parser *);
|
||||
static tree cp_parser_late_return_type_opt
|
||||
(cp_parser *, cp_declarator *, tree &);
|
||||
(cp_parser *, cp_declarator *, tree &, tree);
|
||||
static tree cp_parser_declarator_id
|
||||
(cp_parser *, bool);
|
||||
static tree cp_parser_type_id
|
||||
|
@ -2638,7 +2639,7 @@ static void cp_parser_ctor_initializer_opt_and_function_body
|
|||
(cp_parser *, bool);
|
||||
|
||||
static tree cp_parser_late_parsing_omp_declare_simd
|
||||
(cp_parser *, tree);
|
||||
(cp_parser *, tree, tree);
|
||||
|
||||
static tree cp_parser_late_parsing_oacc_routine
|
||||
(cp_parser *, tree);
|
||||
|
@ -24327,7 +24328,7 @@ cp_parser_direct_declarator (cp_parser* parser,
|
|||
tree requires_clause = NULL_TREE;
|
||||
late_return
|
||||
= cp_parser_late_return_type_opt (parser, declarator,
|
||||
requires_clause);
|
||||
requires_clause, params);
|
||||
|
||||
cp_finalize_omp_declare_simd (parser, &odsd);
|
||||
|
||||
|
@ -25192,8 +25193,8 @@ parsing_function_declarator ()
|
|||
function. */
|
||||
|
||||
static tree
|
||||
cp_parser_late_return_type_opt (cp_parser* parser, cp_declarator *declarator,
|
||||
tree& requires_clause)
|
||||
cp_parser_late_return_type_opt (cp_parser *parser, cp_declarator *declarator,
|
||||
tree &requires_clause, tree parms)
|
||||
{
|
||||
cp_token *token;
|
||||
tree type = NULL_TREE;
|
||||
|
@ -25229,8 +25230,8 @@ cp_parser_late_return_type_opt (cp_parser* parser, cp_declarator *declarator,
|
|||
|
||||
if (declare_simd_p)
|
||||
declarator->attributes
|
||||
= cp_parser_late_parsing_omp_declare_simd (parser,
|
||||
declarator->attributes);
|
||||
= cp_parser_late_parsing_omp_declare_simd (parser, declarator->attributes,
|
||||
parms);
|
||||
if (oacc_routine_p)
|
||||
declarator->attributes
|
||||
= cp_parser_late_parsing_oacc_routine (parser,
|
||||
|
@ -38349,6 +38350,8 @@ cp_parser_omp_clause_name (cp_parser *parser)
|
|||
case 'n':
|
||||
if (!strcmp ("no_create", p))
|
||||
result = PRAGMA_OACC_CLAUSE_NO_CREATE;
|
||||
else if (!strcmp ("nocontext", p))
|
||||
result = PRAGMA_OMP_CLAUSE_NOCONTEXT;
|
||||
else if (!strcmp ("nogroup", p))
|
||||
result = PRAGMA_OMP_CLAUSE_NOGROUP;
|
||||
else if (!strcmp ("nohost", p))
|
||||
|
@ -38357,6 +38360,8 @@ cp_parser_omp_clause_name (cp_parser *parser)
|
|||
result = PRAGMA_OMP_CLAUSE_NONTEMPORAL;
|
||||
else if (!strcmp ("notinbranch", p))
|
||||
result = PRAGMA_OMP_CLAUSE_NOTINBRANCH;
|
||||
else if (!strcmp ("novariants", p))
|
||||
result = PRAGMA_OMP_CLAUSE_NOVARIANTS;
|
||||
else if (!strcmp ("nowait", p))
|
||||
result = PRAGMA_OMP_CLAUSE_NOWAIT;
|
||||
else if (!strcmp ("num_gangs", p))
|
||||
|
@ -40803,6 +40808,56 @@ cp_parser_omp_clause_partial (cp_parser *parser, tree list, location_t loc)
|
|||
return c;
|
||||
}
|
||||
|
||||
/* OpenMP 5.1
|
||||
novariants ( scalar-expression ) */
|
||||
|
||||
static tree
|
||||
cp_parser_omp_clause_novariants (cp_parser *parser, tree list, location_t loc)
|
||||
{
|
||||
matching_parens parens;
|
||||
if (!parens.require_open (parser))
|
||||
return list;
|
||||
|
||||
tree t = cp_parser_assignment_expression (parser);
|
||||
if (t == error_mark_node || !parens.require_close (parser))
|
||||
cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
|
||||
/*or_comma=*/false,
|
||||
/*consume_paren=*/true);
|
||||
|
||||
check_no_duplicate_clause (list, OMP_CLAUSE_NOVARIANTS, "novariants", loc);
|
||||
|
||||
tree c = build_omp_clause (loc, OMP_CLAUSE_NOVARIANTS);
|
||||
OMP_CLAUSE_NOVARIANTS_EXPR (c) = t;
|
||||
OMP_CLAUSE_CHAIN (c) = list;
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
/* OpenMP 5.1
|
||||
nocontext ( scalar-expression ) */
|
||||
|
||||
static tree
|
||||
cp_parser_omp_clause_nocontext (cp_parser *parser, tree list, location_t loc)
|
||||
{
|
||||
matching_parens parens;
|
||||
if (!parens.require_open (parser))
|
||||
return list;
|
||||
|
||||
tree t = cp_parser_assignment_expression (parser);
|
||||
if (t == error_mark_node || !parens.require_close (parser))
|
||||
cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
|
||||
/*or_comma=*/false,
|
||||
/*consume_paren=*/true);
|
||||
|
||||
check_no_duplicate_clause (list, OMP_CLAUSE_NOCONTEXT, "nocontext", loc);
|
||||
|
||||
tree c = build_omp_clause (loc, OMP_CLAUSE_NOCONTEXT);
|
||||
OMP_CLAUSE_NOCONTEXT_EXPR (c) = t;
|
||||
OMP_CLAUSE_CHAIN (c) = list;
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
/* OpenMP 4.0:
|
||||
aligned ( variable-list )
|
||||
aligned ( variable-list : constant-expression ) */
|
||||
|
@ -42910,6 +42965,16 @@ cp_parser_omp_all_clauses (cp_parser *parser, omp_clause_mask mask,
|
|||
clauses = cp_parser_omp_clause_full (clauses, token->location);
|
||||
c_name = "full";
|
||||
break;
|
||||
case PRAGMA_OMP_CLAUSE_NOVARIANTS:
|
||||
clauses = cp_parser_omp_clause_novariants (parser, clauses,
|
||||
token->location);
|
||||
c_name = "novariants";
|
||||
break;
|
||||
case PRAGMA_OMP_CLAUSE_NOCONTEXT:
|
||||
clauses
|
||||
= cp_parser_omp_clause_nocontext (parser, clauses, token->location);
|
||||
c_name = "nocontext";
|
||||
break;
|
||||
default:
|
||||
cp_parser_error (parser, "expected an OpenMP clause");
|
||||
goto saw_error;
|
||||
|
@ -49151,12 +49216,160 @@ cp_parser_omp_assumes (cp_parser *parser, cp_token *pragma_tok)
|
|||
return false;
|
||||
}
|
||||
|
||||
/* Parse a function dispatch structured block:
|
||||
|
||||
lvalue-expression = target-call ( [expression-list] );
|
||||
or
|
||||
target-call ( [expression-list] );
|
||||
|
||||
Inspired from cp_parser_assignment_expression and
|
||||
cp_parser_postfix_expression.
|
||||
*/
|
||||
|
||||
static tree
|
||||
cp_parser_omp_dispatch_body (cp_parser *parser)
|
||||
{
|
||||
/* Parse the binary expressions (lvalue-expression or target-call). */
|
||||
cp_expr expr = cp_parser_binary_expression (parser, false, false, false,
|
||||
PREC_NOT_OPERATOR, NULL);
|
||||
if (TREE_CODE (STRIP_REFERENCE_REF (expr.get_value ())) == CALL_EXPR
|
||||
|| TREE_CODE (expr) == ERROR_MARK)
|
||||
return expr;
|
||||
|
||||
/* We have the lvalue, now deal with the assignment. */
|
||||
|
||||
if (!cp_parser_require (parser, CPP_EQ, RT_EQ))
|
||||
return error_mark_node;
|
||||
|
||||
/* Peek at the next token. */
|
||||
cp_token *token = cp_lexer_peek_token (parser->lexer);
|
||||
location_t loc = token->location;
|
||||
|
||||
/* Parse function call. */
|
||||
cp_expr rhs = cp_parser_postfix_expression (parser, false, false, false,
|
||||
false, nullptr);
|
||||
if (rhs == error_mark_node)
|
||||
return rhs;
|
||||
|
||||
if (TREE_CODE (STRIP_REFERENCE_REF (rhs.get_value ())) != CALL_EXPR)
|
||||
{
|
||||
error_at (EXPR_LOC_OR_LOC (rhs, rhs.get_location ()),
|
||||
"expected target-function call");
|
||||
return error_mark_node;
|
||||
}
|
||||
|
||||
/* Build the assignment expression. Its default
|
||||
location:
|
||||
LHS = RHS
|
||||
~~~~^~~~~
|
||||
is the location of the '=' token as the
|
||||
caret, ranging from the start of the lhs to the
|
||||
end of the rhs. */
|
||||
loc = make_location (loc, expr.get_start (), rhs.get_finish ());
|
||||
expr = build_x_modify_expr (loc, expr, NOP_EXPR, rhs, NULL_TREE,
|
||||
complain_flags (false));
|
||||
/* TODO: build_x_modify_expr doesn't honor the location,
|
||||
so we must set it here. */
|
||||
expr.set_location (loc);
|
||||
|
||||
return expr;
|
||||
}
|
||||
|
||||
/* OpenMP 5.1:
|
||||
# pragma omp dispatch dispatch-clause[optseq] new-line
|
||||
expression-stmt
|
||||
|
||||
LOC is the location of the #pragma.
|
||||
*/
|
||||
|
||||
#define OMP_DISPATCH_CLAUSE_MASK \
|
||||
((OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE) \
|
||||
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \
|
||||
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOVARIANTS) \
|
||||
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOCONTEXT) \
|
||||
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IS_DEVICE_PTR) \
|
||||
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT))
|
||||
|
||||
static tree
|
||||
cp_parser_omp_dispatch (cp_parser *parser, cp_token *pragma_tok)
|
||||
{
|
||||
location_t loc = cp_lexer_peek_token (parser->lexer)->location;
|
||||
tree stmt = make_node (OMP_DISPATCH);
|
||||
SET_EXPR_LOCATION (stmt, loc);
|
||||
TREE_TYPE (stmt) = void_type_node;
|
||||
|
||||
OMP_DISPATCH_CLAUSES (stmt)
|
||||
= cp_parser_omp_all_clauses (parser, OMP_DISPATCH_CLAUSE_MASK,
|
||||
"#pragma omp dispatch", pragma_tok);
|
||||
|
||||
// Extract depend clauses and create taskwait
|
||||
tree depend_clauses = NULL_TREE;
|
||||
tree *depend_clauses_ptr = &depend_clauses;
|
||||
for (tree c = OMP_DISPATCH_CLAUSES (stmt); c; c = OMP_CLAUSE_CHAIN (c))
|
||||
{
|
||||
if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
|
||||
{
|
||||
*depend_clauses_ptr = c;
|
||||
depend_clauses_ptr = &OMP_CLAUSE_CHAIN (c);
|
||||
}
|
||||
}
|
||||
if (depend_clauses != NULL_TREE)
|
||||
{
|
||||
tree stmt = make_node (OMP_TASK);
|
||||
TREE_TYPE (stmt) = void_node;
|
||||
OMP_TASK_CLAUSES (stmt) = depend_clauses;
|
||||
OMP_TASK_BODY (stmt) = NULL_TREE;
|
||||
SET_EXPR_LOCATION (stmt, loc);
|
||||
add_stmt (stmt);
|
||||
}
|
||||
|
||||
// Parse expression statement
|
||||
loc = cp_lexer_peek_token (parser->lexer)->location;
|
||||
tree dispatch_body = cp_parser_omp_dispatch_body (parser);
|
||||
if (dispatch_body == error_mark_node)
|
||||
{
|
||||
inform (loc,
|
||||
"%<#pragma omp dispatch%> must be followed by a direct function "
|
||||
"call with optional assignment");
|
||||
cp_parser_skip_to_end_of_block_or_statement (parser);
|
||||
return NULL_TREE;
|
||||
}
|
||||
|
||||
// Walk the tree to find the dispatch function call and wrap it into an IFN
|
||||
tree *dispatch_call;
|
||||
switch (TREE_CODE (STRIP_REFERENCE_REF (dispatch_body)))
|
||||
{
|
||||
case MODIFY_EXPR:
|
||||
dispatch_call = &TREE_OPERAND (dispatch_body, 1);
|
||||
break;
|
||||
case MODOP_EXPR:
|
||||
dispatch_call = &TREE_OPERAND (dispatch_body, 2);
|
||||
break;
|
||||
case CALL_EXPR:
|
||||
dispatch_call = &dispatch_body;
|
||||
break;
|
||||
default:
|
||||
gcc_unreachable ();
|
||||
}
|
||||
if (TREE_CODE (*dispatch_call) == FLOAT_EXPR
|
||||
|| TREE_CODE (*dispatch_call) == CONVERT_EXPR)
|
||||
dispatch_call = &TREE_OPERAND (*dispatch_call, 0);
|
||||
*dispatch_call = build_call_expr_internal_loc (loc, IFN_GOMP_DISPATCH,
|
||||
TREE_TYPE (*dispatch_call), 1,
|
||||
*dispatch_call);
|
||||
|
||||
cp_parser_consume_semicolon_at_end_of_statement (parser);
|
||||
OMP_DISPATCH_BODY (stmt) = dispatch_body;
|
||||
|
||||
return add_stmt (stmt);
|
||||
}
|
||||
|
||||
/* Finalize #pragma omp declare variant after a fndecl has been parsed, and put
|
||||
that into "omp declare variant base" attribute. */
|
||||
|
||||
static tree
|
||||
cp_finish_omp_declare_variant (cp_parser *parser, cp_token *pragma_tok,
|
||||
tree attrs)
|
||||
tree attrs, tree parms)
|
||||
{
|
||||
matching_parens parens;
|
||||
if (!parens.require_open (parser))
|
||||
|
@ -49214,44 +49427,196 @@ cp_finish_omp_declare_variant (cp_parser *parser, cp_token *pragma_tok,
|
|||
location_t finish_loc = get_finish (varid.get_location ());
|
||||
location_t varid_loc = make_location (caret_loc, start_loc, finish_loc);
|
||||
|
||||
if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA)
|
||||
&& cp_lexer_nth_token_is (parser->lexer, 2, CPP_NAME))
|
||||
cp_lexer_consume_token (parser->lexer);
|
||||
vec<tree> adjust_args_list = vNULL;
|
||||
bool has_match = false, has_adjust_args = false;
|
||||
location_t adjust_args_loc = UNKNOWN_LOCATION;
|
||||
tree need_device_ptr_list = make_node (TREE_LIST);
|
||||
|
||||
const char *clause = "";
|
||||
location_t match_loc = cp_lexer_peek_token (parser->lexer)->location;
|
||||
if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
|
||||
clause = IDENTIFIER_POINTER (cp_lexer_peek_token (parser->lexer)->u.value);
|
||||
if (strcmp (clause, "match"))
|
||||
do
|
||||
{
|
||||
cp_parser_error (parser, "expected %<match%>");
|
||||
goto fail;
|
||||
if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA)
|
||||
&& cp_lexer_nth_token_is (parser->lexer, 2, CPP_NAME))
|
||||
cp_lexer_consume_token (parser->lexer);
|
||||
|
||||
const char *clause = "";
|
||||
location_t match_loc = cp_lexer_peek_token (parser->lexer)->location;
|
||||
if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
|
||||
clause
|
||||
= IDENTIFIER_POINTER (cp_lexer_peek_token (parser->lexer)->u.value);
|
||||
|
||||
enum clause
|
||||
{
|
||||
match,
|
||||
adjust_args
|
||||
} ccode;
|
||||
|
||||
if (strcmp (clause, "match") == 0)
|
||||
ccode = match;
|
||||
else if (strcmp (clause, "adjust_args") == 0)
|
||||
{
|
||||
ccode = adjust_args;
|
||||
adjust_args_loc = match_loc;
|
||||
}
|
||||
else
|
||||
{
|
||||
cp_parser_error (parser, "expected %<match%> clause");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
cp_lexer_consume_token (parser->lexer);
|
||||
|
||||
if (!parens.require_open (parser))
|
||||
goto fail;
|
||||
|
||||
if (ccode == match)
|
||||
{
|
||||
if (has_match)
|
||||
error_at (match_loc, "too many %<match%> clauses");
|
||||
has_match = true;
|
||||
tree ctx
|
||||
= cp_parser_omp_context_selector_specification (parser, true);
|
||||
if (ctx == error_mark_node)
|
||||
goto fail;
|
||||
ctx = omp_check_context_selector (match_loc, ctx);
|
||||
if (ctx != error_mark_node && variant != error_mark_node)
|
||||
{
|
||||
tree match_loc_node
|
||||
= maybe_wrap_with_location (integer_zero_node, match_loc);
|
||||
tree loc_node
|
||||
= maybe_wrap_with_location (integer_zero_node, varid_loc);
|
||||
loc_node
|
||||
= tree_cons (match_loc_node,
|
||||
build_int_cst (integer_type_node, idk),
|
||||
build_tree_list (loc_node, integer_zero_node));
|
||||
attrs = tree_cons (get_identifier ("omp declare variant base"),
|
||||
tree_cons (variant, ctx, loc_node), attrs);
|
||||
if (processing_template_decl)
|
||||
ATTR_IS_DEPENDENT (attrs) = 1;
|
||||
}
|
||||
if (!parens.require_close (parser))
|
||||
goto fail;
|
||||
}
|
||||
else if (ccode == adjust_args)
|
||||
{
|
||||
has_adjust_args = true;
|
||||
cp_token *adjust_op_tok = cp_lexer_peek_token (parser->lexer);
|
||||
if (cp_lexer_next_token_is (parser->lexer, CPP_NAME)
|
||||
&& cp_lexer_nth_token_is (parser->lexer, 2, CPP_COLON))
|
||||
{
|
||||
const char *p = IDENTIFIER_POINTER (adjust_op_tok->u.value);
|
||||
if (strcmp (p, "need_device_ptr") == 0
|
||||
|| strcmp (p, "nothing") == 0)
|
||||
{
|
||||
cp_lexer_consume_token (parser->lexer); // need_device_ptr
|
||||
cp_lexer_consume_token (parser->lexer); // :
|
||||
location_t arg_loc
|
||||
= cp_lexer_peek_token (parser->lexer)->location;
|
||||
|
||||
tree arg;
|
||||
tree list
|
||||
= cp_parser_omp_var_list_no_open (parser, OMP_CLAUSE_ERROR,
|
||||
NULL_TREE, NULL);
|
||||
|
||||
for (tree c = list; c != NULL_TREE; c = TREE_CHAIN (c))
|
||||
{
|
||||
tree decl = TREE_PURPOSE (c);
|
||||
int idx;
|
||||
for (arg = parms, idx = 0; arg != NULL;
|
||||
arg = TREE_CHAIN (arg), idx++)
|
||||
if (TREE_VALUE (arg) == decl)
|
||||
break;
|
||||
if (arg == NULL_TREE)
|
||||
{
|
||||
error_at (arg_loc, "%qD is not a function argument",
|
||||
decl);
|
||||
continue;
|
||||
}
|
||||
arg = TREE_VALUE (arg);
|
||||
if (adjust_args_list.contains (arg))
|
||||
{
|
||||
// TODO fix location
|
||||
error_at (arg_loc, "%qD is specified more than once",
|
||||
decl);
|
||||
continue;
|
||||
}
|
||||
if (strcmp (p, "need_device_ptr") == 0)
|
||||
{
|
||||
bool is_ptr_or_template
|
||||
= TEMPLATE_PARM_P (TREE_TYPE (arg))
|
||||
|| POINTER_TYPE_P (TREE_TYPE (arg));
|
||||
if (!is_ptr_or_template)
|
||||
{
|
||||
error_at (arg_loc, "%qD is not a C pointer",
|
||||
decl);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
adjust_args_list.safe_push (arg);
|
||||
if (strcmp (p, "need_device_ptr") == 0)
|
||||
{
|
||||
need_device_ptr_list = chainon (
|
||||
need_device_ptr_list,
|
||||
build_tree_list (
|
||||
NULL_TREE,
|
||||
build_int_cst (
|
||||
integer_type_node,
|
||||
idx))); // Store 0-based argument index,
|
||||
// as in gimplify_call_expr
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
error_at (adjust_op_tok->location,
|
||||
"expected %<nothing%> or %<need_device_ptr%>");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
error_at (adjust_op_tok->location,
|
||||
"expected %<nothing%> or %<need_device_ptr%> followed "
|
||||
"by %<:%>");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
} while (cp_lexer_next_token_is_not (parser->lexer, CPP_PRAGMA_EOL));
|
||||
|
||||
if (has_adjust_args)
|
||||
{
|
||||
if (!has_match)
|
||||
{
|
||||
error_at (adjust_args_loc,
|
||||
"an %<adjust_args%> clause requires a %<match%> clause");
|
||||
}
|
||||
else
|
||||
{
|
||||
tree ctx = TREE_VALUE (TREE_VALUE (attrs));
|
||||
if (!omp_get_context_selector (ctx, OMP_TRAIT_SET_CONSTRUCT,
|
||||
OMP_TRAIT_CONSTRUCT_DISPATCH))
|
||||
error_at (
|
||||
adjust_args_loc,
|
||||
"an %<adjust_args%> clause can only be specified if the "
|
||||
"%<dispatch%> selector of the construct selector set appears "
|
||||
"in the %<match%> clause");
|
||||
else if (TREE_CHAIN (need_device_ptr_list) != NULL_TREE)
|
||||
{
|
||||
// We might not have a DECL for the variant yet. So we store the
|
||||
// need_device_ptr list in the base function attribute, after loc
|
||||
// nodes.
|
||||
gcc_assert (TREE_PURPOSE (attrs)
|
||||
== get_identifier ("omp declare variant base"));
|
||||
gcc_assert (TREE_PURPOSE (TREE_VALUE (attrs)) == variant);
|
||||
TREE_VALUE (attrs) = chainon (
|
||||
TREE_VALUE (attrs),
|
||||
build_tree_list (
|
||||
NULL_TREE,
|
||||
build_tree_list (need_device_ptr_list,
|
||||
NULL_TREE /*need_device_addr */)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cp_lexer_consume_token (parser->lexer);
|
||||
|
||||
if (!parens.require_open (parser))
|
||||
goto fail;
|
||||
|
||||
tree ctx = cp_parser_omp_context_selector_specification (parser, true);
|
||||
if (ctx == error_mark_node)
|
||||
goto fail;
|
||||
ctx = omp_check_context_selector (match_loc, ctx);
|
||||
if (ctx != error_mark_node && variant != error_mark_node)
|
||||
{
|
||||
tree match_loc_node = maybe_wrap_with_location (integer_zero_node,
|
||||
match_loc);
|
||||
tree loc_node = maybe_wrap_with_location (integer_zero_node, varid_loc);
|
||||
loc_node = tree_cons (match_loc_node,
|
||||
build_int_cst (integer_type_node, idk),
|
||||
build_tree_list (loc_node, integer_zero_node));
|
||||
attrs = tree_cons (get_identifier ("omp declare variant base"),
|
||||
tree_cons (variant, ctx, loc_node), attrs);
|
||||
if (processing_template_decl)
|
||||
ATTR_IS_DEPENDENT (attrs) = 1;
|
||||
}
|
||||
|
||||
parens.require_close (parser);
|
||||
cp_parser_skip_to_pragma_eol (parser, pragma_tok);
|
||||
return attrs;
|
||||
}
|
||||
|
@ -49261,7 +49626,8 @@ cp_finish_omp_declare_variant (cp_parser *parser, cp_token *pragma_tok,
|
|||
been parsed, and put that into "omp declare simd" attribute. */
|
||||
|
||||
static tree
|
||||
cp_parser_late_parsing_omp_declare_simd (cp_parser *parser, tree attrs)
|
||||
cp_parser_late_parsing_omp_declare_simd (cp_parser *parser, tree attrs,
|
||||
tree parms)
|
||||
{
|
||||
struct cp_token_cache *ce;
|
||||
cp_omp_declare_simd_data *data = parser->omp_declare_simd;
|
||||
|
@ -49305,7 +49671,7 @@ cp_parser_late_parsing_omp_declare_simd (cp_parser *parser, tree attrs)
|
|||
{
|
||||
gcc_assert (strcmp (kind, "variant") == 0);
|
||||
attrs
|
||||
= cp_finish_omp_declare_variant (parser, pragma_tok, attrs);
|
||||
= cp_finish_omp_declare_variant (parser, pragma_tok, attrs, parms);
|
||||
}
|
||||
cp_parser_pop_lexer (parser);
|
||||
}
|
||||
|
@ -49436,9 +49802,8 @@ cp_parser_late_parsing_omp_declare_simd (cp_parser *parser, tree attrs)
|
|||
else
|
||||
{
|
||||
gcc_assert (strcmp (kind, "variant") == 0);
|
||||
attrs
|
||||
= cp_finish_omp_declare_variant (parser, pragma_tok,
|
||||
attrs);
|
||||
attrs = cp_finish_omp_declare_variant (parser, pragma_tok,
|
||||
attrs, parms);
|
||||
}
|
||||
gcc_assert (parser->lexer != lexer);
|
||||
vec_safe_truncate (lexer->buffer, 0);
|
||||
|
@ -50291,7 +50656,11 @@ cp_parser_omp_declare_reduction (cp_parser *parser, cp_token *pragma_tok,
|
|||
#pragma omp declare target new-line
|
||||
|
||||
OpenMP 5.0
|
||||
#pragma omp declare variant (identifier) match (context-selector) */
|
||||
#pragma omp declare variant (identifier) match (context-selector)
|
||||
|
||||
OpenMP 5.1
|
||||
#pragma omp declare variant (identifier) match (context-selector) \
|
||||
adjust_args (adjust-op:argument-list) */
|
||||
|
||||
static bool
|
||||
cp_parser_omp_declare (cp_parser *parser, cp_token *pragma_tok,
|
||||
|
@ -51155,6 +51524,9 @@ cp_parser_omp_construct (cp_parser *parser, cp_token *pragma_tok, bool *if_p)
|
|||
case PRAGMA_OMP_UNROLL:
|
||||
stmt = cp_parser_omp_unroll (parser, pragma_tok, if_p);
|
||||
break;
|
||||
case PRAGMA_OMP_DISPATCH:
|
||||
stmt = cp_parser_omp_dispatch (parser, pragma_tok);
|
||||
break;
|
||||
default:
|
||||
gcc_unreachable ();
|
||||
}
|
||||
|
@ -51851,6 +52223,10 @@ cp_parser_pragma (cp_parser *parser, enum pragma_context context, bool *if_p)
|
|||
"%<#pragma omp sections%> construct");
|
||||
break;
|
||||
|
||||
case PRAGMA_OMP_DISPATCH:
|
||||
cp_parser_omp_dispatch (parser, pragma_tok);
|
||||
return true;
|
||||
|
||||
case PRAGMA_IVDEP:
|
||||
case PRAGMA_UNROLL:
|
||||
case PRAGMA_NOVECTOR:
|
||||
|
|
28
gcc/cp/pt.cc
28
gcc/cp/pt.cc
|
@ -17799,6 +17799,16 @@ tsubst_omp_clauses (tree clauses, enum c_omp_region_type ort,
|
|||
= tsubst_expr (OMP_CLAUSE_SIZES_LIST (oc), args, complain,
|
||||
in_decl);
|
||||
break;
|
||||
case OMP_CLAUSE_NOCONTEXT:
|
||||
OMP_CLAUSE_NOCONTEXT_EXPR (nc)
|
||||
= tsubst_expr (OMP_CLAUSE_NOCONTEXT_EXPR (oc), args, complain,
|
||||
in_decl);
|
||||
break;
|
||||
case OMP_CLAUSE_NOVARIANTS:
|
||||
OMP_CLAUSE_NOVARIANTS_EXPR (nc)
|
||||
= tsubst_expr (OMP_CLAUSE_NOVARIANTS_EXPR (oc), args, complain,
|
||||
in_decl);
|
||||
break;
|
||||
case OMP_CLAUSE_REDUCTION:
|
||||
case OMP_CLAUSE_IN_REDUCTION:
|
||||
case OMP_CLAUSE_TASK_REDUCTION:
|
||||
|
@ -19462,6 +19472,16 @@ tsubst_stmt (tree t, tree args, tsubst_flags_t complain, tree in_decl)
|
|||
add_stmt (t);
|
||||
break;
|
||||
|
||||
case OMP_DISPATCH:
|
||||
tmp = tsubst_omp_clauses (OMP_DISPATCH_CLAUSES (t), C_ORT_OMP, args,
|
||||
complain, in_decl);
|
||||
stmt = RECUR (OMP_DISPATCH_BODY (t));
|
||||
t = copy_node (t);
|
||||
OMP_DISPATCH_BODY (t) = stmt;
|
||||
OMP_DISPATCH_CLAUSES (t) = tmp;
|
||||
add_stmt (t);
|
||||
break;
|
||||
|
||||
case OMP_ATOMIC:
|
||||
gcc_assert (OMP_ATOMIC_DEPENDENT_P (t));
|
||||
tmp = NULL_TREE;
|
||||
|
@ -21205,6 +21225,14 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
|
|||
}
|
||||
break;
|
||||
|
||||
case IFN_GOMP_DISPATCH:
|
||||
ret = build_call_expr_internal_loc (EXPR_LOCATION (t),
|
||||
IFN_GOMP_DISPATCH,
|
||||
TREE_TYPE (call_args[0]), 1,
|
||||
call_args[0]);
|
||||
RETURN (ret);
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Unsupported internal function with arguments. */
|
||||
gcc_unreachable ();
|
||||
|
|
|
@ -7753,6 +7753,26 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
|
|||
OMP_CLAUSE_FINAL_EXPR (c) = t;
|
||||
break;
|
||||
|
||||
case OMP_CLAUSE_NOCONTEXT:
|
||||
t = OMP_CLAUSE_NOCONTEXT_EXPR (c);
|
||||
t = maybe_convert_cond (t);
|
||||
if (t == error_mark_node)
|
||||
remove = true;
|
||||
else if (!processing_template_decl)
|
||||
t = fold_build_cleanup_point_expr (TREE_TYPE (t), t);
|
||||
OMP_CLAUSE_NOCONTEXT_EXPR (c) = t;
|
||||
break;
|
||||
|
||||
case OMP_CLAUSE_NOVARIANTS:
|
||||
t = OMP_CLAUSE_NOVARIANTS_EXPR (c);
|
||||
t = maybe_convert_cond (t);
|
||||
if (t == error_mark_node)
|
||||
remove = true;
|
||||
else if (!processing_template_decl)
|
||||
t = fold_build_cleanup_point_expr (TREE_TYPE (t), t);
|
||||
OMP_CLAUSE_NOVARIANTS_EXPR (c) = t;
|
||||
break;
|
||||
|
||||
case OMP_CLAUSE_GANG:
|
||||
/* Operand 1 is the gang static: argument. */
|
||||
t = OMP_CLAUSE_OPERAND (c, 1);
|
||||
|
|
39
gcc/testsuite/g++.dg/gomp/adjust-args-1.C
Normal file
39
gcc/testsuite/g++.dg/gomp/adjust-args-1.C
Normal file
|
@ -0,0 +1,39 @@
|
|||
/* Test parsing of OMP clause adjust_args */
|
||||
/* { dg-do compile } */
|
||||
|
||||
int b;
|
||||
|
||||
int f0 (void *a);
|
||||
int g (void *a);
|
||||
int f1 (int);
|
||||
|
||||
#pragma omp declare variant (f0) match (construct={target}) adjust_args (nothing: a) /* { dg-error "an 'adjust_args' clause can only be specified if the 'dispatch' selector of the construct selector set appears in the 'match' clause" } */
|
||||
int f2 (void *a);
|
||||
#pragma omp declare variant (f0) match (construct={dispatch,target}) adjust_args (need_device_ptr: a) /* { dg-error "'int f0.void..' used as a variant with incompatible 'construct' selector sets" } */
|
||||
int f2a (void *a);
|
||||
#pragma omp declare variant (f0) match (construct={target,dispatch}) adjust_args (need_device_ptr: a) /* { dg-error "'int f0.void..' used as a variant with incompatible 'construct' selector sets" } */
|
||||
int f2b (void *a);
|
||||
#pragma omp declare variant (f0) match (construct={dispatch},device={arch(gcn)}) adjust_args (need_device_ptr: a) /* { dg-error "'int f0.void..' used as a variant with incompatible 'construct' selector sets" } */
|
||||
int f2c (void *a);
|
||||
#pragma omp declare variant (f1) match (construct={dispatch}) adjust_args (other: a) /* { dg-error "expected 'nothing' or 'need_device_ptr'" } */
|
||||
int f3 (int a);
|
||||
#pragma omp declare variant (f0) adjust_args (nothing: a) /* { dg-error "an 'adjust_args' clause requires a 'match' clause" } */
|
||||
int f4 (void *a);
|
||||
#pragma omp declare variant (f1) match (construct={dispatch}) adjust_args () /* { dg-error "expected 'nothing' or 'need_device_ptr' followed by ':'" } */
|
||||
int f5 (int a);
|
||||
#pragma omp declare variant (f1) match (construct={dispatch}) adjust_args (nothing) /* { dg-error "expected 'nothing' or 'need_device_ptr' followed by ':'" } */
|
||||
int f6 (int a);
|
||||
#pragma omp declare variant (f1) match (construct={dispatch}) adjust_args (nothing:) /* { dg-error "expected unqualified-id before '\\)' token" } */
|
||||
int f7 (int a);
|
||||
#pragma omp declare variant (f1) match (construct={dispatch}) adjust_args (nothing: z) /* { dg-error "'z' has not been declared" } */
|
||||
int f8 (int a);
|
||||
#pragma omp declare variant (f1) match (construct={dispatch}) adjust_args (need_device_ptr: a) /* { dg-error "'a' is not a C pointer" } */
|
||||
int f9 (int a);
|
||||
#pragma omp declare variant (f1) match (construct={dispatch}) adjust_args (nothing: a) adjust_args (nothing: a) /* { dg-error "'a' is specified more than once" } */
|
||||
int f10 (int a);
|
||||
#pragma omp declare variant (g) match (construct={dispatch}) adjust_args (nothing: a) adjust_args (need_device_ptr: a) /* { dg-error "'a' is specified more than once" } */
|
||||
int f11 (void *a);
|
||||
#pragma omp declare variant (g) match (construct={dispatch}) adjust_args (need_device_ptr: b) /* { dg-error "'b' is not a function argument" } */
|
||||
int f12 (void *a);
|
||||
#pragma omp declare variant (g) match (construct={dispatch}) adjust_args (need_device_ptr: this) /* { dg-error "expected unqualified-id before 'this'" } */
|
||||
int f13 (void *a);
|
51
gcc/testsuite/g++.dg/gomp/adjust-args-2.C
Normal file
51
gcc/testsuite/g++.dg/gomp/adjust-args-2.C
Normal file
|
@ -0,0 +1,51 @@
|
|||
struct S {
|
||||
int a;
|
||||
int g (const void *b);
|
||||
#pragma omp declare variant (g) match (construct={dispatch}) adjust_args (need_device_ptr: b)
|
||||
int f0(const void *b);
|
||||
int operator()() { return a; }
|
||||
bool operator!() { return !a; }
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
T f0(T a, T *b);
|
||||
|
||||
#pragma omp declare variant (f0) match (construct={dispatch}) adjust_args (need_device_ptr: a, b)
|
||||
template <typename T>
|
||||
T f1(T a, T *b);
|
||||
|
||||
namespace N {
|
||||
class C{
|
||||
public:
|
||||
void g(C *c);
|
||||
#pragma omp declare variant (g) match (construct={dispatch}) adjust_args (need_device_ptr: c)
|
||||
void f0(C *c);
|
||||
};
|
||||
void g(C *c);
|
||||
#pragma omp declare variant (g) match (construct={dispatch}) adjust_args (need_device_ptr: c)
|
||||
void f0(C *c);
|
||||
}
|
||||
|
||||
#pragma omp declare variant (g) match (construct={dispatch}) adjust_args (need_device_ptr: c)
|
||||
void f3(N::C *c);
|
||||
void f4(S *&s);
|
||||
#pragma omp declare variant (f4) match (construct={dispatch}) adjust_args (need_device_ptr: s)
|
||||
void f5(S *&s);
|
||||
|
||||
void test() {
|
||||
S s, *sp;
|
||||
N::C c;
|
||||
int *a, b;
|
||||
#pragma omp dispatch
|
||||
s.f0(a);
|
||||
#pragma omp dispatch
|
||||
f1(b, a);
|
||||
#pragma omp dispatch
|
||||
c.f0(&c);
|
||||
#pragma omp dispatch
|
||||
N::f0(&c);
|
||||
#pragma omp dispatch
|
||||
f3(&c);
|
||||
#pragma omp dispatch
|
||||
f5(sp);
|
||||
}
|
6
gcc/testsuite/g++.dg/gomp/adjust-args-3.C
Normal file
6
gcc/testsuite/g++.dg/gomp/adjust-args-3.C
Normal file
|
@ -0,0 +1,6 @@
|
|||
// Check that an adjust_args clause does not lead to an ICE when the match
|
||||
// clause is missing.
|
||||
|
||||
void f(int *, int *, int *);
|
||||
#pragma omp declare variant(f) adjust_args(need_device_ptr: xxx) /* { dg-error "an 'adjust_args' clause requires a 'match' clause" } */
|
||||
void g(int *xxx, int *yyy, int *zzz);
|
53
gcc/testsuite/g++.dg/gomp/dispatch-1.C
Normal file
53
gcc/testsuite/g++.dg/gomp/dispatch-1.C
Normal file
|
@ -0,0 +1,53 @@
|
|||
struct S {
|
||||
int a;
|
||||
void f0(double);
|
||||
int operator()() { return a; }
|
||||
bool operator!() { return !a; }
|
||||
};
|
||||
|
||||
int f0(int);
|
||||
template <typename T>
|
||||
T f1(T a, T b);
|
||||
void (*f2)(void);
|
||||
|
||||
namespace N {
|
||||
class C{};
|
||||
void f0(C);
|
||||
int a;
|
||||
}
|
||||
|
||||
int test() {
|
||||
int result;
|
||||
double d = 5.0;
|
||||
N::C c;
|
||||
S s;
|
||||
S* sp = &s;
|
||||
int &r = result;
|
||||
#pragma omp dispatch
|
||||
result = f0(5);
|
||||
#pragma omp dispatch
|
||||
r = f0(5);
|
||||
#pragma omp dispatch
|
||||
N::a = ::f0(5);
|
||||
#pragma omp dispatch
|
||||
sp->a = f1<int>(5, 10);
|
||||
#pragma omp dispatch
|
||||
s.a = f1(5, 10);
|
||||
#pragma omp dispatch
|
||||
f2();
|
||||
#pragma omp dispatch
|
||||
N::f0(c);
|
||||
#pragma omp dispatch
|
||||
f0(c);
|
||||
#pragma omp dispatch
|
||||
s.f0(d);
|
||||
#pragma omp dispatch
|
||||
sp->f0(d);
|
||||
#pragma omp dispatch
|
||||
sp->f0(d);
|
||||
#pragma omp dispatch
|
||||
s();
|
||||
#pragma omp dispatch
|
||||
!s;
|
||||
return result;
|
||||
}
|
62
gcc/testsuite/g++.dg/gomp/dispatch-2.C
Normal file
62
gcc/testsuite/g++.dg/gomp/dispatch-2.C
Normal file
|
@ -0,0 +1,62 @@
|
|||
/* Test parsing of #pragma omp dispatch */
|
||||
/* { dg-do compile } */
|
||||
|
||||
struct S {
|
||||
int a;
|
||||
int b;
|
||||
virtual int f (double);
|
||||
};
|
||||
|
||||
int f0 (int);
|
||||
|
||||
void f1 (void)
|
||||
{
|
||||
int a, b;
|
||||
double x;
|
||||
int arr[1];
|
||||
S s;
|
||||
|
||||
#pragma omp dispatch
|
||||
int c = f0 (a); /* { dg-error "expected primary-expression before 'int'" } */
|
||||
#pragma omp dispatch
|
||||
int f2 (int d); /* { dg-error "expected primary-expression before 'int'" } */
|
||||
#pragma omp dispatch
|
||||
a = b; /* { dg-error "expected target-function call" } */
|
||||
#pragma omp dispatch
|
||||
s.a = f0(a) + b; /* { dg-error "expected ';' before '\\+' token" } */
|
||||
#pragma omp dispatch
|
||||
b = !f0(a); /* { dg-error "expected primary-expression before '!' token" } */
|
||||
#pragma omp dispatch
|
||||
s.b += f0(s.a); /* { dg-error "expected '=' before '\\+=' token" } */
|
||||
#pragma omp dispatch
|
||||
#pragma omp threadprivate(a) /* { dg-error "'#pragma' is not allowed here" } */
|
||||
a = f0(b);
|
||||
#pragma omp dispatch
|
||||
a = s.f(x); /* { dg-error "'f' is a virtual function but only a direct call is allowed in a dispatch construct" } */
|
||||
|
||||
#pragma omp dispatch nocontext(s) /* { dg-error "could not convert 's' from 'S' to 'bool'" } */
|
||||
f0(a);
|
||||
#pragma omp dispatch nocontext(a, b) /* { dg-error "expected '\\)' before ','" } */
|
||||
f0(a);
|
||||
#pragma omp dispatch nocontext(a) nocontext(b) /* { dg-error "too many 'nocontext' clauses" } */
|
||||
f0(a);
|
||||
#pragma omp dispatch novariants(s) /* { dg-error "could not convert 's' from 'S' to 'bool'" } */
|
||||
f0(a);
|
||||
#pragma omp dispatch novariants(a, b) /* { dg-error "expected '\\)' before ','" } */
|
||||
f0(a);
|
||||
#pragma omp dispatch novariants(a) novariants(b) /* { dg-error "too many 'novariants' clauses" } */
|
||||
f0(a);
|
||||
#pragma omp dispatch nowait nowait /* { dg-error "too many 'nowait' clauses" } */
|
||||
f0(a);
|
||||
#pragma omp dispatch device(x) /* { dg-error "'device' id must be integral" } */
|
||||
f0(a);
|
||||
#pragma omp dispatch device(arr) /* { dg-error "'device' id must be integral" } */
|
||||
f0(a);
|
||||
#pragma omp dispatch is_device_ptr(x) /* { dg-error "'is_device_ptr' variable is neither a pointer, nor an array nor reference to pointer" } */
|
||||
f0(a);
|
||||
#pragma omp dispatch is_device_ptr(&x) /* { dg-error "expected unqualified-id before '&' token" } */
|
||||
f0(a);
|
||||
#pragma omp dispatch depend(inout: s.f) /* { dg-error "'s.S::f' is not lvalue expression nor array section in 'depend' clause" } */
|
||||
f0(a);
|
||||
|
||||
}
|
17
gcc/testsuite/g++.dg/gomp/dispatch-3.C
Normal file
17
gcc/testsuite/g++.dg/gomp/dispatch-3.C
Normal file
|
@ -0,0 +1,17 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-additional-options "-fdump-tree-original -fdump-tree-gimple" } */
|
||||
|
||||
/* Check that the right call to f is wrapped in a GOMP_DISPATCH internal function
|
||||
before translation and that it is stripped during gimplification. */
|
||||
|
||||
int &f(int);
|
||||
void g(int *x)
|
||||
{
|
||||
#pragma omp dispatch
|
||||
x[f(1)] = f(f(2));
|
||||
// ^ only this call to f is a dispatch call
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump "\.GOMP_DISPATCH \\(\\*f \\(\\*f \\(2\\)\\)\\)" "original" } } */
|
||||
/* { dg-final { scan-tree-dump-times "\.GOMP_DISPATCH" 1 "original" } } */
|
||||
/* { dg-final { scan-tree-dump-not "\.GOMP_DISPATCH" "gimple" } } */
|
22
gcc/testsuite/g++.dg/gomp/dispatch-4.C
Normal file
22
gcc/testsuite/g++.dg/gomp/dispatch-4.C
Normal file
|
@ -0,0 +1,22 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-additional-options "-fdump-tree-gimple" } */
|
||||
|
||||
/* Check that no host-to-device pointer conversion happens for a nullptr
|
||||
argument. */
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
int variant_fn(int *, int * = NULL);
|
||||
|
||||
#pragma omp declare variant(variant_fn) match(construct={dispatch}) adjust_args(need_device_ptr : x, y)
|
||||
int bar(int *x, int *y = NULL);
|
||||
|
||||
void sub(int *a, int *b)
|
||||
{
|
||||
int x;
|
||||
#pragma omp dispatch
|
||||
x = bar(a);
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "__builtin_omp_get_mapped_ptr" 1 "gimple" } } */
|
||||
/* { dg-final { scan-tree-dump-not "__builtin_omp_get_mapped_ptr \\(OB" "gimple" } } */
|
17
gcc/testsuite/g++.dg/gomp/dispatch-5.C
Normal file
17
gcc/testsuite/g++.dg/gomp/dispatch-5.C
Normal file
|
@ -0,0 +1,17 @@
|
|||
/* { dg-do compile } */
|
||||
|
||||
/* Check that the parser does not issue an error when a variant returns a
|
||||
reference. */
|
||||
|
||||
int& variant_fn();
|
||||
|
||||
#pragma omp declare variant(variant_fn) match(construct={target})
|
||||
int& bar();
|
||||
|
||||
void sub(int a)
|
||||
{
|
||||
#pragma omp dispatch
|
||||
bar();
|
||||
#pragma omp dispatch
|
||||
a = bar();
|
||||
}
|
29
gcc/testsuite/g++.dg/gomp/dispatch-6.C
Normal file
29
gcc/testsuite/g++.dg/gomp/dispatch-6.C
Normal file
|
@ -0,0 +1,29 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-additional-options "-fdump-tree-original" } */
|
||||
|
||||
/* Check that templates are properly handled. */
|
||||
|
||||
template<typename T>
|
||||
T templ_var_fn(T x);
|
||||
|
||||
#pragma omp declare variant(templ_var_fn) match(construct={dispatch}) adjust_args(need_device_ptr: x)
|
||||
template<typename T>
|
||||
T templ_base_fn(T x);
|
||||
|
||||
template<typename T, typename TB>
|
||||
void f(int *y, TB x)
|
||||
{
|
||||
#pragma omp dispatch nocontext (x)
|
||||
y = templ_base_fn<T> (y);
|
||||
#pragma omp dispatch novariants (x)
|
||||
y = templ_base_fn<T> (y);
|
||||
}
|
||||
|
||||
void bar()
|
||||
{
|
||||
int a;
|
||||
bool b = true;
|
||||
f<int*,bool> (&a, b);
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "y = \.GOMP_DISPATCH \\(templ_base_fn<int\\*> \\(y\\)\\)" 2 "original" } } */
|
43
gcc/testsuite/g++.dg/gomp/dispatch-7.C
Normal file
43
gcc/testsuite/g++.dg/gomp/dispatch-7.C
Normal file
|
@ -0,0 +1,43 @@
|
|||
// { dg-do compile { target c++11 } }
|
||||
|
||||
|
||||
template<typename T>
|
||||
T templ_var_fn(T x);
|
||||
|
||||
|
||||
template<typename T> [[omp::directive (declare variant(templ_var_fn) match(construct={dispatch}) adjust_args(need_device_ptr: x))]]
|
||||
T templ_base_fn(T x);
|
||||
|
||||
template<typename T, typename TB>
|
||||
void f(int *y, TB x)
|
||||
{
|
||||
[[omp::directive (dispatch nocontext (x))]]
|
||||
y = templ_base_fn<T> (y);
|
||||
[[omp::directive (dispatch novariants (x))]]
|
||||
y = templ_base_fn<T> (y);
|
||||
}
|
||||
|
||||
void bar()
|
||||
{
|
||||
int a;
|
||||
bool b = true;
|
||||
f<int*,bool> (&a, b);
|
||||
}
|
||||
|
||||
|
||||
void variant_fn(int *x, int *y, int *z);
|
||||
|
||||
[[omp::directive (declare variant(variant_fn) match(construct={dispatch}) adjust_args(need_device_ptr: x,y) adjust_args(nothing: z))]]
|
||||
void bar(int *x, int *y, int *z);
|
||||
|
||||
void sub(int *x, int *y, int *z)
|
||||
{
|
||||
[[omp::directive (dispatch is_device_ptr(y))]]
|
||||
bar(x, y, z);
|
||||
[[omp::directive (dispatch device(0))]]
|
||||
bar(x, y, z);
|
||||
[[omp::directive (dispatch nocontext(1) novariants(1))]]
|
||||
bar(x, y, z);
|
||||
[[omp::directive (dispatch depend(inout: x) nowait)]]
|
||||
bar(x, y, z);
|
||||
}
|
Loading…
Add table
Reference in a new issue