OpenMP: Use enumerators for names of trait-sets and traits

This patch introduces enumerators to represent trait-set names and
trait names, which makes it easier to use tables to control other
behavior and for switch statements to dispatch on the tags.  The tags
are stored in the same place in the TREE_LIST structure (OMP_TSS_ID or
OMP_TS_ID) and are encoded there as integer constants.

gcc/ChangeLog
	* omp-selectors.h: New file.
	* omp-general.h: Include omp-selectors.h.
	(OMP_TSS_CODE, OMP_TSS_NAME): New.
	(OMP_TS_CODE, OMP_TS_NAME): New.
	(make_trait_set_selector, make_trait_selector): Adjust declarations.
	(omp_construct_traits_to_codes): Likewise.
	(omp_context_selector_set_compare): Likewise.
	(omp_get_context_selector): Likewise.
	(omp_get_context_selector_list): New.
	* omp-general.cc (omp_construct_traits_to_codes): Pass length in
	as argument instead of returning it.  Make it table-driven.
	(omp_tss_map): New.
	(kind_properties, vendor_properties, extension_properties): New.
	(atomic_default_mem_order_properties): New.
	(omp_ts_map): New.
	(omp_check_context_selector): Simplify lookup and dispatch logic.
	(omp_mark_declare_variant): Ignore variants with unknown construct
	selectors.  Adjust for new representation.
	(make_trait_set_selector, make_trait_selector): Adjust for new
	representations.
	(omp_context_selector_matches): Simplify dispatch logic.  Avoid
	fixed-sized buffers and adjust call to omp_construct_traits_to_codes.
	(omp_context_selector_props_compare): Adjust for new representations
	and simplify dispatch logic.
	(omp_context_selector_set_compare): Likewise.
	(omp_context_selector_compare): Likewise.
	(omp_get_context_selector): Adjust for new representations, and split
	out...
	(omp_get_context_selector_list): New function.
	(omp_lookup_tss_code): New.
	(omp_lookup_ts_code): New.
	(omp_context_compute_score): Adjust for new representations.  Avoid
	fixed-sized buffers and magic numbers.  Adjust call to
	omp_construct_traits_to_codes.
	* gimplify.cc (omp_construct_selector_matches): Avoid use of
	fixed-size buffer.  Adjust call to omp_construct_traits_to_codes.

gcc/c/ChangeLog
	* c-parser.cc (omp_construct_selectors): Delete.
	(omp_device_selectors): Delete.
	(omp_implementation_selectors): Delete.
	(omp_user_selectors): Delete.
	(c_parser_omp_context_selector): Adjust for new representations
	and simplify dispatch logic.  Uniformly warn instead of sometimes
	error when an unknown selector is found.  Adjust error messages
	for extraneous/incorrect score.
	(c_parser_omp_context_selector_specification): Likewise.
	(c_finish_omp_declare_variant): Adjust for new representations.

gcc/cp/ChangeLog
	* decl.cc (omp_declare_variant_finalize_one): Adjust for new
	representations.
	* parser.cc (omp_construct_selectors): Delete.
	(omp_device_selectors): Delete.
	(omp_implementation_selectors): Delete.
	(omp_user_selectors): Delete.
	(cp_parser_omp_context_selector): Adjust for new representations
	and simplify dispatch logic.  Uniformly warn instead of sometimes
	error when an unknown selector is found.  Adjust error messages
	for extraneous/incorrect score.
	(cp_parser_omp_context_selector_specification): Likewise.
	* pt.cc (tsubst_attribute): Adjust for new representations.

gcc/fortran/ChangeLog
	* gfortran.h: Include omp-selectors.h.
	(enum gfc_omp_trait_property_kind): Delete, and replace all
	references with equivalent omp_tp_type enumerators.
	(struct gfc_omp_trait_property): Update for omp_tp_type.
	(struct gfc_omp_selector): Replace string name with new enumerator.
	(struct gfc_omp_set_selector): Likewise.
	* openmp.cc (gfc_free_omp_trait_property_list): Update for
	omp_tp_type.
	(omp_construct_selectors): Delete.
	(omp_device_selectors): Delete.
	(omp_implementation_selectors): Delete.
	(omp_user_selectors): Delete.
	(gfc_ignore_trait_property_extension): New.
	(gfc_ignore_trait_property_extension_list): New.
	(gfc_match_omp_selector): Adjust for new representations and simplify
	dispatch logic.  Uniformly warn instead of sometimes error when an
	unknown selector is found.
	(gfc_match_omp_context_selector): Adjust for new representations.
	Adjust error messages for extraneous/incorrect score.
	(gfc_match_omp_context_selector_specification): Likewise.
	* trans-openmp.cc (gfc_trans_omp_declare_variant): Adjust for
	new representations.

gcc/testsuite/
	* c-c++-common/gomp/declare-variant-1.c: Expect warning on
	unknown selectors.
	* c-c++-common/gomp/declare-variant-2.c: Likewise.  Also adjust
	messages for score errors.
	* c-c++-common/gomp/declare-variant-no-score.c: New.
	* gfortran.dg/gomp/declare-variant-1.f90: Expect warning on
	unknown selectors.
	* gfortran.dg/gomp/declare-variant-2.f90: Likewise.  Also adjust
	messages for score errors.
	* gfortran.dg/gomp/declare-variant-no-score.f90: New.
This commit is contained in:
Sandra Loosemore 2023-12-18 23:16:53 +00:00
parent 9b8fdcbf21
commit 9f9b3d6732
17 changed files with 920 additions and 719 deletions

View file

@ -24370,16 +24370,6 @@ c_parser_omp_declare_simd (c_parser *parser, enum pragma_context context)
}
}
static const char *const omp_construct_selectors[] = {
"simd", "target", "teams", "parallel", "for", NULL };
static const char *const omp_device_selectors[] = {
"kind", "isa", "arch", NULL };
static const char *const omp_implementation_selectors[] = {
"vendor", "extension", "atomic_default_mem_order", "unified_address",
"unified_shared_memory", "dynamic_allocators", "reverse_offload", NULL };
static const char *const omp_user_selectors[] = {
"condition", NULL };
/* OpenMP 5.0:
trait-selector:
@ -24392,7 +24382,8 @@ static const char *const omp_user_selectors[] = {
trait-selector-set SET. */
static tree
c_parser_omp_context_selector (c_parser *parser, tree set, tree parms)
c_parser_omp_context_selector (c_parser *parser, enum omp_tss_code set,
tree parms)
{
tree ret = NULL_TREE;
do
@ -24406,80 +24397,41 @@ c_parser_omp_context_selector (c_parser *parser, tree set, tree parms)
c_parser_error (parser, "expected trait selector name");
return error_mark_node;
}
enum omp_ts_code sel
= omp_lookup_ts_code (set, IDENTIFIER_POINTER (selector));
tree properties = NULL_TREE;
tree scoreval = NULL_TREE;
const char *const *selectors = NULL;
bool allow_score = true;
bool allow_user = false;
int property_limit = 0;
enum { CTX_PROPERTY_NONE, CTX_PROPERTY_USER, CTX_PROPERTY_NAME_LIST,
CTX_PROPERTY_ID, CTX_PROPERTY_EXPR,
CTX_PROPERTY_SIMD } property_kind = CTX_PROPERTY_NONE;
switch (IDENTIFIER_POINTER (set)[0])
if (sel == OMP_TRAIT_INVALID)
{
case 'c': /* construct */
selectors = omp_construct_selectors;
allow_score = false;
property_limit = 1;
property_kind = CTX_PROPERTY_SIMD;
break;
case 'd': /* device */
selectors = omp_device_selectors;
allow_score = false;
allow_user = true;
property_limit = 3;
property_kind = CTX_PROPERTY_NAME_LIST;
break;
case 'i': /* implementation */
selectors = omp_implementation_selectors;
allow_user = true;
property_limit = 3;
property_kind = CTX_PROPERTY_NAME_LIST;
break;
case 'u': /* user */
selectors = omp_user_selectors;
property_limit = 1;
property_kind = CTX_PROPERTY_EXPR;
break;
default:
gcc_unreachable ();
}
for (int i = 0; ; i++)
{
if (selectors[i] == NULL)
/* Per the spec, "Implementations can ignore specified selectors
that are not those described in this section"; however, we
must record such selectors because they cause match failures. */
warning_at (c_parser_peek_token (parser)->location, OPT_Wopenmp,
"unknown selector %qs for context selector set %qs",
IDENTIFIER_POINTER (selector), omp_tss_map[set]);
c_parser_consume_token (parser);
ret = make_trait_selector (sel, NULL_TREE, NULL_TREE, ret);
if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
c_parser_balanced_token_sequence (parser);
if (c_parser_next_token_is (parser, CPP_COMMA))
{
if (allow_user)
{
property_kind = CTX_PROPERTY_USER;
break;
}
else
{
error_at (c_parser_peek_token (parser)->location,
"selector %qs not allowed for context selector "
"set %qs", IDENTIFIER_POINTER (selector),
IDENTIFIER_POINTER (set));
c_parser_consume_token (parser);
return error_mark_node;
}
c_parser_consume_token (parser);
continue;
}
if (i == property_limit)
property_kind = CTX_PROPERTY_NONE;
if (strcmp (selectors[i], IDENTIFIER_POINTER (selector)) == 0)
else
break;
}
if (property_kind == CTX_PROPERTY_NAME_LIST
&& IDENTIFIER_POINTER (set)[0] == 'i'
&& strcmp (IDENTIFIER_POINTER (selector),
"atomic_default_mem_order") == 0)
property_kind = CTX_PROPERTY_ID;
c_parser_consume_token (parser);
tree properties = NULL_TREE;
tree scoreval = NULL_TREE;
enum omp_tp_type property_kind = omp_ts_map[sel].tp_type;
bool allow_score = omp_ts_map[sel].allow_score;
tree t;
if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
{
if (property_kind == CTX_PROPERTY_NONE)
if (property_kind == OMP_TRAIT_PROPERTY_NONE)
{
error_at (c_parser_peek_token (parser)->location,
"selector %qs does not accept any properties",
@ -24491,8 +24443,7 @@ c_parser_omp_context_selector (c_parser *parser, tree set, tree parms)
parens.require_open (parser);
c_token *token = c_parser_peek_token (parser);
if (allow_score
&& c_parser_next_token_is (parser, CPP_NAME)
if (c_parser_next_token_is (parser, CPP_NAME)
&& strcmp (IDENTIFIER_POINTER (token->value), "score") == 0
&& c_parser_peek_2nd_token (parser)->type == CPP_OPEN_PAREN)
{
@ -24503,17 +24454,22 @@ c_parser_omp_context_selector (c_parser *parser, tree set, tree parms)
tree score = c_parser_expr_no_commas (parser, NULL).value;
parens2.skip_until_found_close (parser);
c_parser_require (parser, CPP_COLON, "expected %<:%>");
if (score != error_mark_node)
if (!allow_score)
error_at (token->location,
"%<score%> cannot be specified in traits "
"in the %qs trait-selector-set",
omp_tss_map[set]);
else if (score != error_mark_node)
{
mark_exp_read (score);
score = c_fully_fold (score, false, NULL);
if (!INTEGRAL_TYPE_P (TREE_TYPE (score))
|| TREE_CODE (score) != INTEGER_CST)
error_at (token->location, "score argument must be "
"constant integer expression");
error_at (token->location, "%<score%> argument must "
"be constant integer expression");
else if (tree_int_cst_sgn (score) < 0)
error_at (token->location, "score argument must be "
"non-negative");
error_at (token->location, "%<score%> argument must "
"be non-negative");
else
scoreval = score;
}
@ -24522,38 +24478,7 @@ c_parser_omp_context_selector (c_parser *parser, tree set, tree parms)
switch (property_kind)
{
tree t;
case CTX_PROPERTY_USER:
do
{
t = c_parser_expr_no_commas (parser, NULL).value;
if (TREE_CODE (t) == STRING_CST)
properties = make_trait_property (NULL_TREE, t,
properties);
else if (t != error_mark_node)
{
mark_exp_read (t);
t = c_fully_fold (t, false, NULL);
if (!INTEGRAL_TYPE_P (TREE_TYPE (t))
|| !tree_fits_shwi_p (t))
error_at (token->location, "property must be "
"constant integer expression or string "
"literal");
else
properties = make_trait_property (NULL_TREE, t,
properties);
}
else
return error_mark_node;
if (c_parser_next_token_is (parser, CPP_COMMA))
c_parser_consume_token (parser);
else
break;
}
while (1);
break;
case CTX_PROPERTY_ID:
case OMP_TRAIT_PROPERTY_ID:
if (c_parser_next_token_is (parser, CPP_KEYWORD)
|| c_parser_next_token_is (parser, CPP_NAME))
{
@ -24568,7 +24493,7 @@ c_parser_omp_context_selector (c_parser *parser, tree set, tree parms)
return error_mark_node;
}
break;
case CTX_PROPERTY_NAME_LIST:
case OMP_TRAIT_PROPERTY_NAME_LIST:
do
{
tree prop = OMP_TP_NAMELIST_NODE;
@ -24598,12 +24523,14 @@ c_parser_omp_context_selector (c_parser *parser, tree set, tree parms)
}
while (1);
break;
case CTX_PROPERTY_EXPR:
case OMP_TRAIT_PROPERTY_EXPR:
t = c_parser_expr_no_commas (parser, NULL).value;
if (t != error_mark_node)
{
mark_exp_read (t);
t = c_fully_fold (t, false, NULL);
/* FIXME: this is bogus, both device_num and
condition selectors allow arbitrary expressions. */
if (!INTEGRAL_TYPE_P (TREE_TYPE (t))
|| !tree_fits_shwi_p (t))
error_at (token->location, "property must be "
@ -24615,23 +24542,37 @@ c_parser_omp_context_selector (c_parser *parser, tree set, tree parms)
else
return error_mark_node;
break;
case CTX_PROPERTY_SIMD:
if (parms == NULL_TREE)
case OMP_TRAIT_PROPERTY_CLAUSE_LIST:
if (sel == OMP_TRAIT_CONSTRUCT_SIMD)
{
error_at (token->location, "properties for %<simd%> "
"selector may not be specified in "
"%<metadirective%>");
if (parms == NULL_TREE)
{
error_at (token->location, "properties for %<simd%> "
"selector may not be specified in "
"%<metadirective%>");
return error_mark_node;
}
tree c;
c = c_parser_omp_all_clauses (parser,
OMP_DECLARE_SIMD_CLAUSE_MASK,
"simd", true, 2);
c = c_omp_declare_simd_clauses_to_numbers (parms
== error_mark_node
? NULL_TREE : parms,
c);
properties = c;
}
else if (sel == OMP_TRAIT_IMPLEMENTATION_REQUIRES)
{
/* FIXME: The "requires" selector was added in OpenMP 5.1.
Currently only the now-deprecated syntax
from OpenMP 5.0 is supported. */
sorry_at (token->location,
"%<requires%> selector is not supported yet");
return error_mark_node;
}
tree c;
c = c_parser_omp_all_clauses (parser,
OMP_DECLARE_SIMD_CLAUSE_MASK,
"simd", true, 2);
c = c_omp_declare_simd_clauses_to_numbers (parms
== error_mark_node
? NULL_TREE : parms,
c);
properties = c;
else
gcc_unreachable ();
break;
default:
gcc_unreachable ();
@ -24640,15 +24581,15 @@ c_parser_omp_context_selector (c_parser *parser, tree set, tree parms)
parens.skip_until_found_close (parser);
properties = nreverse (properties);
}
else if (property_kind == CTX_PROPERTY_NAME_LIST
|| property_kind == CTX_PROPERTY_ID
|| property_kind == CTX_PROPERTY_EXPR)
else if (property_kind != OMP_TRAIT_PROPERTY_NONE
&& property_kind != OMP_TRAIT_PROPERTY_CLAUSE_LIST
&& property_kind != OMP_TRAIT_PROPERTY_EXTENSION)
{
c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>");
return error_mark_node;
}
ret = make_trait_selector (selector, scoreval, properties, ret);
ret = make_trait_selector (sel, scoreval, properties, ret);
if (c_parser_next_token_is (parser, CPP_COMMA))
c_parser_consume_token (parser);
@ -24682,35 +24623,14 @@ c_parser_omp_context_selector_specification (c_parser *parser, tree parms)
const char *setp = "";
if (c_parser_next_token_is (parser, CPP_NAME))
setp = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
switch (setp[0])
enum omp_tss_code set = omp_lookup_tss_code (setp);
if (set == OMP_TRAIT_SET_INVALID)
{
case 'c':
if (strcmp (setp, "construct") == 0)
setp = NULL;
break;
case 'd':
if (strcmp (setp, "device") == 0)
setp = NULL;
break;
case 'i':
if (strcmp (setp, "implementation") == 0)
setp = NULL;
break;
case 'u':
if (strcmp (setp, "user") == 0)
setp = NULL;
break;
default:
break;
}
if (setp)
{
c_parser_error (parser, "expected %<construct%>, %<device%>, "
"%<implementation%> or %<user%>");
c_parser_error (parser, "expected context selector set name");
return error_mark_node;
}
tree set = c_parser_peek_token (parser)->value;
c_parser_consume_token (parser);
if (!c_parser_require (parser, CPP_EQ, "expected %<=%>"))
@ -24807,7 +24727,8 @@ c_finish_omp_declare_variant (c_parser *parser, tree fndecl, tree parms)
error_at (token->location, "variant %qD is not a function", variant);
variant = error_mark_node;
}
else if (omp_get_context_selector (ctx, "construct", "simd") == NULL_TREE
else if (!omp_get_context_selector (ctx, OMP_TRAIT_SET_CONSTRUCT,
OMP_TRAIT_CONSTRUCT_SIMD)
&& !comptypes (TREE_TYPE (fndecl), TREE_TYPE (variant)))
{
error_at (token->location, "variant %qD and base %qD have "
@ -24828,7 +24749,8 @@ c_finish_omp_declare_variant (c_parser *parser, tree fndecl, tree parms)
if (variant != error_mark_node)
{
C_DECL_USED (variant) = 1;
tree construct = omp_get_context_selector (ctx, "construct", NULL);
tree construct
= omp_get_context_selector_list (ctx, OMP_TRAIT_SET_CONSTRUCT);
omp_mark_declare_variant (match_loc, variant, construct);
if (omp_context_selector_matches (ctx))
{

View file

@ -8097,12 +8097,13 @@ omp_declare_variant_finalize_one (tree decl, tree attr)
}
tree ctx = TREE_VALUE (TREE_VALUE (attr));
tree simd = omp_get_context_selector (ctx, "construct", "simd");
tree simd = omp_get_context_selector (ctx, OMP_TRAIT_SET_CONSTRUCT,
OMP_TRAIT_CONSTRUCT_SIMD);
if (simd)
{
TREE_VALUE (simd)
= c_omp_declare_simd_clauses_to_numbers (DECL_ARGUMENTS (decl),
TREE_VALUE (simd));
OMP_TS_PROPERTIES (simd));
/* FIXME, adjusting simd args unimplemented. */
return true;
}
@ -8195,7 +8196,8 @@ omp_declare_variant_finalize_one (tree decl, tree attr)
}
else
{
tree construct = omp_get_context_selector (ctx, "construct", NULL);
tree construct
= omp_get_context_selector_list (ctx, OMP_TRAIT_SET_CONSTRUCT);
omp_mark_declare_variant (match_loc, variant, construct);
if (!omp_context_selector_matches (ctx))
return true;

View file

@ -47416,16 +47416,6 @@ cp_parser_omp_declare_simd (cp_parser *parser, cp_token *pragma_tok,
}
}
static const char *const omp_construct_selectors[] = {
"simd", "target", "teams", "parallel", "for", NULL };
static const char *const omp_device_selectors[] = {
"kind", "isa", "arch", NULL };
static const char *const omp_implementation_selectors[] = {
"vendor", "extension", "atomic_default_mem_order", "unified_address",
"unified_shared_memory", "dynamic_allocators", "reverse_offload", NULL };
static const char *const omp_user_selectors[] = {
"condition", NULL };
/* OpenMP 5.0:
trait-selector:
@ -47438,7 +47428,8 @@ static const char *const omp_user_selectors[] = {
trait-selector-set SET. */
static tree
cp_parser_omp_context_selector (cp_parser *parser, tree set, bool has_parms_p)
cp_parser_omp_context_selector (cp_parser *parser, enum omp_tss_code set,
bool has_parms_p)
{
tree ret = NULL_TREE;
do
@ -47453,78 +47444,44 @@ cp_parser_omp_context_selector (cp_parser *parser, tree set, bool has_parms_p)
return error_mark_node;
}
tree properties = NULL_TREE;
tree scoreval = NULL_TREE;
const char *const *selectors = NULL;
bool allow_score = true;
bool allow_user = false;
int property_limit = 0;
enum { CTX_PROPERTY_NONE, CTX_PROPERTY_USER, CTX_PROPERTY_NAME_LIST,
CTX_PROPERTY_ID, CTX_PROPERTY_EXPR,
CTX_PROPERTY_SIMD } property_kind = CTX_PROPERTY_NONE;
switch (IDENTIFIER_POINTER (set)[0])
enum omp_ts_code sel
= omp_lookup_ts_code (set, IDENTIFIER_POINTER (selector));
if (sel == OMP_TRAIT_INVALID)
{
case 'c': /* construct */
selectors = omp_construct_selectors;
allow_score = false;
property_limit = 1;
property_kind = CTX_PROPERTY_SIMD;
break;
case 'd': /* device */
selectors = omp_device_selectors;
allow_score = false;
allow_user = true;
property_limit = 3;
property_kind = CTX_PROPERTY_NAME_LIST;
break;
case 'i': /* implementation */
selectors = omp_implementation_selectors;
allow_user = true;
property_limit = 3;
property_kind = CTX_PROPERTY_NAME_LIST;
break;
case 'u': /* user */
selectors = omp_user_selectors;
property_limit = 1;
property_kind = CTX_PROPERTY_EXPR;
break;
default:
gcc_unreachable ();
}
for (int i = 0; ; i++)
{
if (selectors[i] == NULL)
/* Per the spec, "Implementations can ignore specified selectors
that are not those described in this section"; however, we
must record such selectors because they cause match failures. */
warning_at (cp_lexer_peek_token (parser->lexer)->location,
OPT_Wopenmp,
"unknown selector %qs for context selector set %qs",
IDENTIFIER_POINTER (selector), omp_tss_map[set]);
cp_lexer_consume_token (parser->lexer);
ret = make_trait_selector (sel, NULL_TREE, NULL_TREE, ret);
if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
for (size_t n = cp_parser_skip_balanced_tokens (parser, 1) - 1;
n; --n)
cp_lexer_consume_token (parser->lexer);
if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
{
if (allow_user)
{
property_kind = CTX_PROPERTY_USER;
break;
}
else
{
error ("selector %qs not allowed for context selector "
"set %qs", IDENTIFIER_POINTER (selector),
IDENTIFIER_POINTER (set));
cp_lexer_consume_token (parser->lexer);
return error_mark_node;
}
cp_lexer_consume_token (parser->lexer);
continue;
}
if (i == property_limit)
property_kind = CTX_PROPERTY_NONE;
if (strcmp (selectors[i], IDENTIFIER_POINTER (selector)) == 0)
else
break;
}
if (property_kind == CTX_PROPERTY_NAME_LIST
&& IDENTIFIER_POINTER (set)[0] == 'i'
&& strcmp (IDENTIFIER_POINTER (selector),
"atomic_default_mem_order") == 0)
property_kind = CTX_PROPERTY_ID;
cp_lexer_consume_token (parser->lexer);
tree properties = NULL_TREE;
tree scoreval = NULL_TREE;
enum omp_tp_type property_kind = omp_ts_map[sel].tp_type;
bool allow_score = omp_ts_map[sel].allow_score;
tree t;
if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
{
if (property_kind == CTX_PROPERTY_NONE)
if (property_kind == OMP_TRAIT_PROPERTY_NONE)
{
error ("selector %qs does not accept any properties",
IDENTIFIER_POINTER (selector));
@ -47535,8 +47492,7 @@ cp_parser_omp_context_selector (cp_parser *parser, tree set, bool has_parms_p)
parens.consume_open (parser);
cp_token *token = cp_lexer_peek_token (parser->lexer);
if (allow_score
&& cp_lexer_next_token_is (parser->lexer, CPP_NAME)
if (cp_lexer_next_token_is (parser->lexer, CPP_NAME)
&& strcmp (IDENTIFIER_POINTER (token->u.value), "score") == 0
&& cp_lexer_nth_token_is (parser->lexer, 2, CPP_OPEN_PAREN))
{
@ -47557,18 +47513,23 @@ cp_parser_omp_context_selector (cp_parser *parser, tree set, bool has_parms_p)
cp_parser_skip_to_closing_parenthesis (parser, true,
false, true);
cp_parser_require (parser, CPP_COLON, RT_COLON);
if (score != error_mark_node)
if (!allow_score)
error_at (token->location,
"%<score%> cannot be specified in traits "
"in the %qs trait-selector-set",
omp_tss_map[set]);
else if (score != error_mark_node)
{
score = fold_non_dependent_expr (score);
if (value_dependent_expression_p (score))
scoreval = score;
else if (!INTEGRAL_TYPE_P (TREE_TYPE (score))
|| TREE_CODE (score) != INTEGER_CST)
error_at (token->location, "score argument must be "
"constant integer expression");
error_at (token->location, "%<score%> argument must "
"be constant integer expression");
else if (tree_int_cst_sgn (score) < 0)
error_at (token->location, "score argument must be "
"non-negative");
error_at (token->location, "%<score%> argument must "
"be non-negative");
else
scoreval = score;
}
@ -47581,38 +47542,7 @@ cp_parser_omp_context_selector (cp_parser *parser, tree set, bool has_parms_p)
switch (property_kind)
{
tree t;
case CTX_PROPERTY_USER:
do
{
t = cp_parser_constant_expression (parser);
if (t != error_mark_node)
{
t = fold_non_dependent_expr (t);
if (TREE_CODE (t) == STRING_CST)
properties = make_trait_property (NULL_TREE, t,
properties);
else if (!value_dependent_expression_p (t)
&& (!INTEGRAL_TYPE_P (TREE_TYPE (t))
|| !tree_fits_shwi_p (t)))
error_at (token->location, "property must be "
"constant integer expression or string "
"literal");
else
properties = make_trait_property (NULL_TREE, t,
properties);
}
else
return error_mark_node;
if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
cp_lexer_consume_token (parser->lexer);
else
break;
}
while (1);
break;
case CTX_PROPERTY_ID:
case OMP_TRAIT_PROPERTY_ID:
if (cp_lexer_next_token_is (parser->lexer, CPP_KEYWORD)
|| cp_lexer_next_token_is (parser->lexer, CPP_NAME))
{
@ -47627,7 +47557,7 @@ cp_parser_omp_context_selector (cp_parser *parser, tree set, bool has_parms_p)
return error_mark_node;
}
break;
case CTX_PROPERTY_NAME_LIST:
case OMP_TRAIT_PROPERTY_NAME_LIST:
do
{
tree prop = OMP_TP_NAMELIST_NODE;
@ -47658,7 +47588,9 @@ cp_parser_omp_context_selector (cp_parser *parser, tree set, bool has_parms_p)
}
while (1);
break;
case CTX_PROPERTY_EXPR:
case OMP_TRAIT_PROPERTY_EXPR:
/* FIXME: this is bogus, the expression need
not be constant. */
t = cp_parser_constant_expression (parser);
if (t != error_mark_node)
{
@ -47675,18 +47607,32 @@ cp_parser_omp_context_selector (cp_parser *parser, tree set, bool has_parms_p)
else
return error_mark_node;
break;
case CTX_PROPERTY_SIMD:
if (!has_parms_p)
case OMP_TRAIT_PROPERTY_CLAUSE_LIST:
if (sel == OMP_TRAIT_CONSTRUCT_SIMD)
{
error_at (token->location, "properties for %<simd%> "
"selector may not be specified in "
"%<metadirective%>");
if (!has_parms_p)
{
error_at (token->location, "properties for %<simd%> "
"selector may not be specified in "
"%<metadirective%>");
return error_mark_node;
}
properties
= cp_parser_omp_all_clauses (parser,
OMP_DECLARE_SIMD_CLAUSE_MASK,
"simd", NULL, true, 2);
}
else if (sel == OMP_TRAIT_IMPLEMENTATION_REQUIRES)
{
/* FIXME: The "requires" selector was added in OpenMP 5.1.
Currently only the now-deprecated syntax
from OpenMP 5.0 is supported. */
sorry_at (token->location,
"%<requires%> selector is not supported yet");
return error_mark_node;
}
properties
= cp_parser_omp_all_clauses (parser,
OMP_DECLARE_SIMD_CLAUSE_MASK,
"simd", NULL, true, 2);
else
gcc_unreachable ();
break;
default:
gcc_unreachable ();
@ -47697,15 +47643,15 @@ cp_parser_omp_context_selector (cp_parser *parser, tree set, bool has_parms_p)
properties = nreverse (properties);
}
else if (property_kind == CTX_PROPERTY_NAME_LIST
|| property_kind == CTX_PROPERTY_ID
|| property_kind == CTX_PROPERTY_EXPR)
else if (property_kind != OMP_TRAIT_PROPERTY_NONE
&& property_kind != OMP_TRAIT_PROPERTY_CLAUSE_LIST
&& property_kind != OMP_TRAIT_PROPERTY_EXTENSION)
{
cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN);
return error_mark_node;
}
ret = make_trait_selector (selector, scoreval, properties, ret);
ret = make_trait_selector (sel, scoreval, properties, ret);
if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
cp_lexer_consume_token (parser->lexer);
@ -47741,35 +47687,14 @@ cp_parser_omp_context_selector_specification (cp_parser *parser,
if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
setp
= IDENTIFIER_POINTER (cp_lexer_peek_token (parser->lexer)->u.value);
switch (setp[0])
enum omp_tss_code set = omp_lookup_tss_code (setp);
if (set == OMP_TRAIT_SET_INVALID)
{
case 'c':
if (strcmp (setp, "construct") == 0)
setp = NULL;
break;
case 'd':
if (strcmp (setp, "device") == 0)
setp = NULL;
break;
case 'i':
if (strcmp (setp, "implementation") == 0)
setp = NULL;
break;
case 'u':
if (strcmp (setp, "user") == 0)
setp = NULL;
break;
default:
break;
}
if (setp)
{
cp_parser_error (parser, "expected %<construct%>, %<device%>, "
"%<implementation%> or %<user%>");
cp_parser_error (parser, "expected context selector set name");
return error_mark_node;
}
tree set = cp_lexer_peek_token (parser->lexer)->u.value;
cp_lexer_consume_token (parser->lexer);
if (!cp_parser_require (parser, CPP_EQ, RT_EQ))

View file

@ -11888,18 +11888,20 @@ tsubst_attribute (tree t, tree *decl_p, tree args,
tree chain = TREE_CHAIN (val);
location_t match_loc = cp_expr_loc_or_input_loc (TREE_PURPOSE (chain));
tree ctx = copy_list (TREE_VALUE (val));
tree simd = get_identifier ("simd");
tree condition = get_identifier ("condition");
for (tree tss = ctx; tss; tss = TREE_CHAIN (tss))
{
const char *set = IDENTIFIER_POINTER (OMP_TSS_ID (tss));
enum omp_tss_code set = OMP_TSS_CODE (tss);
tree selectors = NULL_TREE;
for (tree ts = OMP_TSS_TRAIT_SELECTORS (tss); ts;
ts = TREE_CHAIN (ts))
{
tree properties = NULL_TREE;
tree scoreval = NULL_TREE;
if (OMP_TS_ID (ts) == simd && set[0] == 'c')
/* FIXME: The body of this loop should really be dispatching
according to omp_ts_map[OMP_TS_CODE (TS)].tp_type instead
of having hard-wired knowledge of specific selectors. */
if (OMP_TS_CODE (ts) == OMP_TRAIT_CONSTRUCT_SIMD
&& set == OMP_TRAIT_SET_CONSTRUCT)
{
tree clauses = OMP_TS_PROPERTIES (ts);
clauses = tsubst_omp_clauses (clauses,
@ -11944,7 +11946,8 @@ tsubst_attribute (tree t, tree *decl_p, tree args,
else if (OMP_TP_VALUE (p))
{
bool allow_string
= (OMP_TS_ID (ts) != condition || set[0] != 'u');
= (OMP_TS_CODE (ts) != OMP_TRAIT_USER_CONDITION
|| set != OMP_TRAIT_SET_USER);
tree v = OMP_TP_VALUE (p);
if (TREE_CODE (v) == STRING_CST && allow_string)
continue;
@ -11968,7 +11971,7 @@ tsubst_attribute (tree t, tree *decl_p, tree args,
OMP_TP_VALUE (p) = v;
}
}
selectors = make_trait_selector (OMP_TS_ID (ts), scoreval,
selectors = make_trait_selector (OMP_TS_CODE (ts), scoreval,
properties, selectors);
}
OMP_TSS_TRAIT_SELECTORS (tss) = nreverse (selectors);

View file

@ -1647,21 +1647,13 @@ typedef struct gfc_omp_declare_simd
gfc_omp_declare_simd;
#define gfc_get_omp_declare_simd() XCNEW (gfc_omp_declare_simd)
enum gfc_omp_trait_property_kind
{
CTX_PROPERTY_NONE,
CTX_PROPERTY_USER,
CTX_PROPERTY_NAME_LIST,
CTX_PROPERTY_ID,
CTX_PROPERTY_EXPR,
CTX_PROPERTY_SIMD
};
/* For OpenMP trait selector enum types and tables. */
#include "omp-selectors.h"
typedef struct gfc_omp_trait_property
{
struct gfc_omp_trait_property *next;
enum gfc_omp_trait_property_kind property_kind;
enum omp_tp_type property_kind;
bool is_name : 1;
union
@ -1677,8 +1669,7 @@ typedef struct gfc_omp_trait_property
typedef struct gfc_omp_selector
{
struct gfc_omp_selector *next;
char *trait_selector_name;
enum omp_ts_code code;
gfc_expr *score;
struct gfc_omp_trait_property *properties;
} gfc_omp_selector;
@ -1687,8 +1678,7 @@ typedef struct gfc_omp_selector
typedef struct gfc_omp_set_selector
{
struct gfc_omp_set_selector *next;
const char *trait_set_selector_name;
enum omp_tss_code code;
struct gfc_omp_selector *trait_selectors;
} gfc_omp_set_selector;
#define gfc_get_omp_set_selector() XCNEW (gfc_omp_set_selector)

View file

@ -269,14 +269,14 @@ gfc_free_omp_trait_property_list (gfc_omp_trait_property *list)
list = list->next;
switch (current->property_kind)
{
case CTX_PROPERTY_ID:
case OMP_TRAIT_PROPERTY_ID:
free (current->name);
break;
case CTX_PROPERTY_NAME_LIST:
case OMP_TRAIT_PROPERTY_NAME_LIST:
if (current->is_name)
free (current->name);
break;
case CTX_PROPERTY_SIMD:
case OMP_TRAIT_PROPERTY_CLAUSE_LIST:
gfc_free_omp_clauses (current->clauses);
break;
default:
@ -5584,17 +5584,55 @@ cleanup:
return MATCH_ERROR;
}
/* Skip over and ignore trait-property-extensions.
static const char *const omp_construct_selectors[] = {
"simd", "target", "teams", "parallel", "do", NULL };
static const char *const omp_device_selectors[] = {
"kind", "isa", "arch", NULL };
static const char *const omp_implementation_selectors[] = {
"vendor", "extension", "atomic_default_mem_order", "unified_address",
"unified_shared_memory", "dynamic_allocators", "reverse_offload", NULL };
static const char *const omp_user_selectors[] = {
"condition", NULL };
trait-property-extension :
trait-property-name
identifier (trait-property-extension[, trait-property-extension[, ...]])
constant integer expression
*/
static match gfc_ignore_trait_property_extension_list (void);
static match
gfc_ignore_trait_property_extension (void)
{
char buf[GFC_MAX_SYMBOL_LEN + 1];
gfc_expr *expr;
/* Identifier form of trait-property name, possibly followed by
a list of (recursive) trait-property-extensions. */
if (gfc_match_name (buf) == MATCH_YES)
{
if (gfc_match (" (") == MATCH_YES)
return gfc_ignore_trait_property_extension_list ();
return MATCH_YES;
}
/* Literal constant. */
if (gfc_match_literal_constant (&expr, 0) == MATCH_YES)
return MATCH_YES;
/* FIXME: constant integer expressions. */
gfc_error ("Expected trait-property-extension at %C");
return MATCH_ERROR;
}
static match
gfc_ignore_trait_property_extension_list (void)
{
while (1)
{
if (gfc_ignore_trait_property_extension () != MATCH_YES)
return MATCH_ERROR;
if (gfc_match (" ,") == MATCH_YES)
continue;
if (gfc_match (" )") == MATCH_YES)
return MATCH_YES;
gfc_error ("expected %<)%> at %C");
return MATCH_ERROR;
}
}
/* OpenMP 5.0:
@ -5618,83 +5656,52 @@ gfc_match_omp_context_selector (gfc_omp_set_selector *oss)
}
gfc_omp_selector *os = gfc_get_omp_selector ();
os->trait_selector_name = XNEWVEC (char, strlen (selector) + 1);
strcpy (os->trait_selector_name, selector);
if (oss->code == OMP_TRAIT_SET_CONSTRUCT
&& !strcmp (selector, "do"))
os->code = OMP_TRAIT_CONSTRUCT_FOR;
else if (oss->code == OMP_TRAIT_SET_CONSTRUCT
&& !strcmp (selector, "for"))
os->code = OMP_TRAIT_INVALID;
else
os->code = omp_lookup_ts_code (oss->code, selector);
os->next = oss->trait_selectors;
oss->trait_selectors = os;
const char *const *selectors = NULL;
bool allow_score = true;
bool allow_user = false;
int property_limit = 0;
enum gfc_omp_trait_property_kind property_kind = CTX_PROPERTY_NONE;
switch (oss->trait_set_selector_name[0])
if (os->code == OMP_TRAIT_INVALID)
{
case 'c': /* construct */
selectors = omp_construct_selectors;
allow_score = false;
property_limit = 1;
property_kind = CTX_PROPERTY_SIMD;
gfc_warning (OPT_Wopenmp,
"unknown selector %qs for context selector set %qs "
"at %C",
selector, omp_tss_map[oss->code]);
if (gfc_match (" (") == MATCH_YES
&& gfc_ignore_trait_property_extension_list () != MATCH_YES)
return MATCH_ERROR;
if (gfc_match (" ,") == MATCH_YES)
continue;
break;
case 'd': /* device */
selectors = omp_device_selectors;
allow_score = false;
allow_user = true;
property_limit = 3;
property_kind = CTX_PROPERTY_NAME_LIST;
break;
case 'i': /* implementation */
selectors = omp_implementation_selectors;
allow_user = true;
property_limit = 3;
property_kind = CTX_PROPERTY_NAME_LIST;
break;
case 'u': /* user */
selectors = omp_user_selectors;
property_limit = 1;
property_kind = CTX_PROPERTY_EXPR;
break;
default:
gcc_unreachable ();
}
for (int i = 0; ; i++)
{
if (selectors[i] == NULL)
{
if (allow_user)
{
property_kind = CTX_PROPERTY_USER;
break;
}
else
{
gfc_error ("selector %qs not allowed for context selector "
"set %qs at %C",
selector, oss->trait_set_selector_name);
return MATCH_ERROR;
}
}
if (i == property_limit)
property_kind = CTX_PROPERTY_NONE;
if (strcmp (selectors[i], selector) == 0)
break;
}
if (property_kind == CTX_PROPERTY_NAME_LIST
&& oss->trait_set_selector_name[0] == 'i'
&& strcmp (selector, "atomic_default_mem_order") == 0)
property_kind = CTX_PROPERTY_ID;
enum omp_tp_type property_kind = omp_ts_map[os->code].tp_type;
bool allow_score = omp_ts_map[os->code].allow_score;
if (gfc_match (" (") == MATCH_YES)
{
if (property_kind == CTX_PROPERTY_NONE)
if (property_kind == OMP_TRAIT_PROPERTY_NONE)
{
gfc_error ("selector %qs does not accept any properties at %C",
selector);
return MATCH_ERROR;
}
if (allow_score && gfc_match (" score") == MATCH_YES)
if (gfc_match (" score") == MATCH_YES)
{
if (!allow_score)
{
gfc_error ("%<score%> cannot be specified in traits "
"in the %qs trait-selector-set at %C",
omp_tss_map[oss->code]);
return MATCH_ERROR;
}
if (gfc_match (" (") != MATCH_YES)
{
gfc_error ("expected %<(%> at %C");
@ -5705,7 +5712,7 @@ gfc_match_omp_context_selector (gfc_omp_set_selector *oss)
|| os->score->ts.type != BT_INTEGER
|| os->score->rank != 0)
{
gfc_error ("score argument must be constant integer "
gfc_error ("%<score%> argument must be constant integer "
"expression at %C");
return MATCH_ERROR;
}
@ -5713,7 +5720,7 @@ gfc_match_omp_context_selector (gfc_omp_set_selector *oss)
if (os->score->expr_type == EXPR_CONSTANT
&& mpz_sgn (os->score->value.integer) < 0)
{
gfc_error ("score argument must be non-negative at %C");
gfc_error ("%<score%> argument must be non-negative at %C");
return MATCH_ERROR;
}
@ -5737,22 +5744,7 @@ gfc_match_omp_context_selector (gfc_omp_set_selector *oss)
switch (property_kind)
{
case CTX_PROPERTY_USER:
do
{
if (gfc_match_expr (&otp->expr) != MATCH_YES)
{
gfc_error ("property must be constant integer "
"expression or string literal at %C");
return MATCH_ERROR;
}
if (gfc_match (" ,") != MATCH_YES)
break;
}
while (1);
break;
case CTX_PROPERTY_ID:
case OMP_TRAIT_PROPERTY_ID:
{
char buf[GFC_MAX_SYMBOL_LEN + 1];
if (gfc_match_name (buf) == MATCH_YES)
@ -5767,7 +5759,7 @@ gfc_match_omp_context_selector (gfc_omp_set_selector *oss)
}
}
break;
case CTX_PROPERTY_NAME_LIST:
case OMP_TRAIT_PROPERTY_NAME_LIST:
do
{
char buf[GFC_MAX_SYMBOL_LEN + 1];
@ -5798,7 +5790,7 @@ gfc_match_omp_context_selector (gfc_omp_set_selector *oss)
}
while (1);
break;
case CTX_PROPERTY_EXPR:
case OMP_TRAIT_PROPERTY_EXPR:
if (gfc_match_expr (&otp->expr) != MATCH_YES)
{
gfc_error ("expected expression at %C");
@ -5814,16 +5806,29 @@ gfc_match_omp_context_selector (gfc_omp_set_selector *oss)
return MATCH_ERROR;
}
break;
case CTX_PROPERTY_SIMD:
case OMP_TRAIT_PROPERTY_CLAUSE_LIST:
{
if (gfc_match_omp_clauses (&otp->clauses,
OMP_DECLARE_SIMD_CLAUSES,
true, false, false, true)
!= MATCH_YES)
if (os->code == OMP_TRAIT_CONSTRUCT_SIMD)
{
gfc_error ("expected simd clause at %C");
if (gfc_match_omp_clauses (&otp->clauses,
OMP_DECLARE_SIMD_CLAUSES,
true, false, false, true)
!= MATCH_YES)
{
gfc_error ("expected simd clause at %C");
return MATCH_ERROR;
}
}
else if (os->code == OMP_TRAIT_IMPLEMENTATION_REQUIRES)
{
/* FIXME: The "requires" selector was added in OpenMP 5.1.
Currently only the now-deprecated syntax
from OpenMP 5.0 is supported. */
sorry ("%<requires%> selector is not supported yet");
return MATCH_ERROR;
}
else
gcc_unreachable ();
break;
}
default:
@ -5836,9 +5841,9 @@ gfc_match_omp_context_selector (gfc_omp_set_selector *oss)
return MATCH_ERROR;
}
}
else if (property_kind == CTX_PROPERTY_NAME_LIST
|| property_kind == CTX_PROPERTY_ID
|| property_kind == CTX_PROPERTY_EXPR)
else if (property_kind != OMP_TRAIT_PROPERTY_NONE
&& property_kind != OMP_TRAIT_PROPERTY_CLAUSE_LIST
&& property_kind != OMP_TRAIT_PROPERTY_EXTENSION)
{
if (gfc_match (" (") != MATCH_YES)
{
@ -5874,22 +5879,16 @@ gfc_match_omp_context_selector_specification (gfc_omp_declare_variant *odv)
do
{
match m;
const char *selector_sets[] = { "construct", "device",
"implementation", "user" };
const int selector_set_count = ARRAY_SIZE (selector_sets);
int i;
char buf[GFC_MAX_SYMBOL_LEN + 1];
enum omp_tss_code set = OMP_TRAIT_SET_INVALID;
m = gfc_match_name (buf);
if (m == MATCH_YES)
for (i = 0; i < selector_set_count; i++)
if (strcmp (buf, selector_sets[i]) == 0)
break;
set = omp_lookup_tss_code (buf);
if (m != MATCH_YES || i == selector_set_count)
if (set == OMP_TRAIT_SET_INVALID)
{
gfc_error ("expected %<construct%>, %<device%>, %<implementation%> "
"or %<user%> at %C");
gfc_error ("expected context selector set name at %C");
return MATCH_ERROR;
}
@ -5909,7 +5908,7 @@ gfc_match_omp_context_selector_specification (gfc_omp_declare_variant *odv)
gfc_omp_set_selector *oss = gfc_get_omp_set_selector ();
oss->next = odv->set_selectors;
oss->trait_set_selector_name = selector_sets[i];
oss->code = set;
odv->set_selectors = oss;
if (gfc_match_omp_context_selector (oss) != MATCH_YES)

View file

@ -8401,18 +8401,32 @@ gfc_trans_omp_declare_variant (gfc_namespace *ns)
{
tree selectors = NULL_TREE;
gfc_omp_selector *os;
enum omp_tss_code set = oss->code;
gcc_assert (set != OMP_TRAIT_SET_INVALID);
for (os = oss->trait_selectors; os; os = os->next)
{
tree scoreval = NULL_TREE;
tree properties = NULL_TREE;
gfc_omp_trait_property *otp;
enum omp_ts_code sel = os->code;
/* Per the spec, "Implementations can ignore specified
selectors that are not those described in this section";
however, we must record such selectors because they
cause match failures. */
if (sel == OMP_TRAIT_INVALID)
{
selectors = make_trait_selector (sel, NULL_TREE, NULL_TREE,
selectors);
continue;
}
for (otp = os->properties; otp; otp = otp->next)
{
switch (otp->property_kind)
{
case CTX_PROPERTY_USER:
case CTX_PROPERTY_EXPR:
case OMP_TRAIT_PROPERTY_EXPR:
{
gfc_se se;
gfc_init_se (&se, NULL);
@ -8421,12 +8435,12 @@ gfc_trans_omp_declare_variant (gfc_namespace *ns)
properties);
}
break;
case CTX_PROPERTY_ID:
case OMP_TRAIT_PROPERTY_ID:
properties
= make_trait_property (get_identifier (otp->name),
NULL_TREE, properties);
break;
case CTX_PROPERTY_NAME_LIST:
case OMP_TRAIT_PROPERTY_NAME_LIST:
{
tree prop = OMP_TP_NAMELIST_NODE;
tree value = NULL_TREE;
@ -8439,7 +8453,7 @@ gfc_trans_omp_declare_variant (gfc_namespace *ns)
properties);
}
break;
case CTX_PROPERTY_SIMD:
case OMP_TRAIT_PROPERTY_CLAUSE_LIST:
properties = gfc_trans_omp_clauses (NULL, otp->clauses,
odv->where, true);
break;
@ -8456,13 +8470,10 @@ gfc_trans_omp_declare_variant (gfc_namespace *ns)
scoreval = se.expr;
}
tree ts_name = get_identifier (os->trait_selector_name);
selectors = make_trait_selector (ts_name, scoreval,
selectors = make_trait_selector (sel, scoreval,
properties, selectors);
}
tree tss_name = get_identifier (oss->trait_set_selector_name);
set_selectors = make_trait_set_selector (tss_name, selectors,
set_selectors = make_trait_set_selector (set, selectors,
set_selectors);
}
@ -8491,8 +8502,10 @@ gfc_trans_omp_declare_variant (gfc_namespace *ns)
variant_proc_name, &odv->where);
variant_proc_sym = NULL;
}
else if (omp_get_context_selector (set_selectors, "construct",
"simd") == NULL_TREE)
else if (omp_get_context_selector (set_selectors,
OMP_TRAIT_SET_CONSTRUCT,
OMP_TRAIT_CONSTRUCT_SIMD)
== NULL_TREE)
{
char err[256];
if (!gfc_compare_interfaces (ns->proc_name, variant_proc_sym,
@ -8509,8 +8522,9 @@ gfc_trans_omp_declare_variant (gfc_namespace *ns)
if (variant_proc_sym != NULL)
{
gfc_set_sym_referenced (variant_proc_sym);
tree construct = omp_get_context_selector (set_selectors,
"construct", NULL);
tree construct
= omp_get_context_selector_list (set_selectors,
OMP_TRAIT_SET_CONSTRUCT);
omp_mark_declare_variant (gfc_get_location (&odv->where),
gfc_get_symbol_decl (variant_proc_sym),
construct);

View file

@ -14480,12 +14480,17 @@ omp_construct_selector_matches (enum tree_code *constructs, int nconstructs,
if (tree attr = lookup_attribute ("omp declare variant variant",
DECL_ATTRIBUTES (current_function_decl)))
{
enum tree_code variant_constructs[5];
int variant_nconstructs = 0;
if (!target_seen)
variant_nconstructs
= omp_construct_traits_to_codes (TREE_VALUE (attr),
variant_constructs);
tree selectors = TREE_VALUE (attr);
int variant_nconstructs = list_length (selectors);
enum tree_code *variant_constructs = NULL;
if (!target_seen && variant_nconstructs)
{
variant_constructs
= (enum tree_code *) alloca (variant_nconstructs
* sizeof (enum tree_code));
omp_construct_traits_to_codes (selectors, variant_nconstructs,
variant_constructs);
}
for (int i = 0; i < variant_nconstructs; i++)
{
++cnt;

View file

@ -1015,32 +1015,29 @@ omp_max_simt_vf (void)
return 0;
}
/* Store the construct selectors as tree codes from last to first,
return their number. */
/* Store the construct selectors as tree codes from last to first.
CTX is a list of trait selectors, nconstructs must be equal to its
length, and the array CONSTRUCTS holds the output. */
int
omp_construct_traits_to_codes (tree ctx, enum tree_code *constructs)
void
omp_construct_traits_to_codes (tree ctx, int nconstructs,
enum tree_code *constructs)
{
int nconstructs = list_length (ctx);
int i = nconstructs - 1;
/* Order must match the OMP_TRAIT_CONSTRUCT_* enumerators in
enum omp_ts_code. */
static enum tree_code code_map[]
= { OMP_TARGET, OMP_TEAMS, OMP_PARALLEL, OMP_FOR, OMP_SIMD };
for (tree ts = ctx; ts; ts = TREE_CHAIN (ts), i--)
{
const char *sel = IDENTIFIER_POINTER (OMP_TS_ID (ts));
if (!strcmp (sel, "target"))
constructs[i] = OMP_TARGET;
else if (!strcmp (sel, "teams"))
constructs[i] = OMP_TEAMS;
else if (!strcmp (sel, "parallel"))
constructs[i] = OMP_PARALLEL;
else if (!strcmp (sel, "for") || !strcmp (sel, "do"))
constructs[i] = OMP_FOR;
else if (!strcmp (sel, "simd"))
constructs[i] = OMP_SIMD;
else
gcc_unreachable ();
enum omp_ts_code sel = OMP_TS_CODE (ts);
int j = (int)sel - (int)OMP_TRAIT_CONSTRUCT_TARGET;
gcc_assert (j >= 0 && (unsigned int) j < ARRAY_SIZE (code_map));
constructs[i] = code_map[j];
}
gcc_assert (i == -1);
return nconstructs;
}
/* Return true if PROP is possibly present in one of the offloading target's
@ -1116,6 +1113,124 @@ omp_maybe_offloaded (void)
return false;
}
/* Lookup tables for context selectors. */
const char *omp_tss_map[] =
{
"construct",
"device",
"target_device",
"implementation",
"user",
NULL
};
/* Arrays of property candidates must be null-terminated. */
static const char *const kind_properties[] =
{ "host", "nohost", "cpu", "gpu", "fpga", "any", NULL };
static const char *const vendor_properties[] =
{ "amd", "arm", "bsc", "cray", "fujitsu", "gnu", "ibm", "intel",
"llvm", "nvidia", "pgi", "ti", "unknown", NULL };
static const char *const extension_properties[] =
{ NULL };
static const char *const atomic_default_mem_order_properties[] =
{ "seq_cst", "relaxed", "acq_rel", NULL };
struct omp_ts_info omp_ts_map[] =
{
{ "kind",
(1 << OMP_TRAIT_SET_DEVICE) | (1 << OMP_TRAIT_SET_TARGET_DEVICE),
OMP_TRAIT_PROPERTY_NAME_LIST, false,
kind_properties
},
{ "isa",
(1 << OMP_TRAIT_SET_DEVICE) | (1 << OMP_TRAIT_SET_TARGET_DEVICE),
OMP_TRAIT_PROPERTY_NAME_LIST, false,
NULL
},
{ "arch",
(1 << OMP_TRAIT_SET_DEVICE) | (1 << OMP_TRAIT_SET_TARGET_DEVICE),
OMP_TRAIT_PROPERTY_NAME_LIST, false,
NULL
},
{ "device_num",
(1 << OMP_TRAIT_SET_TARGET_DEVICE),
OMP_TRAIT_PROPERTY_EXPR, false,
NULL
},
{ "vendor",
(1 << OMP_TRAIT_SET_IMPLEMENTATION),
OMP_TRAIT_PROPERTY_NAME_LIST, true,
vendor_properties,
},
{ "extension",
(1 << OMP_TRAIT_SET_IMPLEMENTATION),
OMP_TRAIT_PROPERTY_NAME_LIST, true,
extension_properties,
},
{ "atomic_default_mem_order",
(1 << OMP_TRAIT_SET_IMPLEMENTATION),
OMP_TRAIT_PROPERTY_ID, true,
atomic_default_mem_order_properties,
},
{ "requires",
(1 << OMP_TRAIT_SET_IMPLEMENTATION),
OMP_TRAIT_PROPERTY_CLAUSE_LIST, true,
NULL
},
{ "unified_address",
(1 << OMP_TRAIT_SET_IMPLEMENTATION),
OMP_TRAIT_PROPERTY_NONE, true,
NULL
},
{ "unified_shared_memory",
(1 << OMP_TRAIT_SET_IMPLEMENTATION),
OMP_TRAIT_PROPERTY_NONE, true,
NULL
},
{ "dynamic_allocators",
(1 << OMP_TRAIT_SET_IMPLEMENTATION),
OMP_TRAIT_PROPERTY_NONE, true,
NULL
},
{ "reverse_offload",
(1 << OMP_TRAIT_SET_IMPLEMENTATION),
OMP_TRAIT_PROPERTY_NONE, true,
NULL
},
{ "condition",
(1 << OMP_TRAIT_SET_USER),
OMP_TRAIT_PROPERTY_EXPR, true,
NULL
},
{ "target",
(1 << OMP_TRAIT_SET_CONSTRUCT),
OMP_TRAIT_PROPERTY_NONE, false,
NULL
},
{ "teams",
(1 << OMP_TRAIT_SET_CONSTRUCT),
OMP_TRAIT_PROPERTY_NONE, false,
NULL
},
{ "parallel",
(1 << OMP_TRAIT_SET_CONSTRUCT),
OMP_TRAIT_PROPERTY_NONE, false,
NULL
},
{ "for",
(1 << OMP_TRAIT_SET_CONSTRUCT),
OMP_TRAIT_PROPERTY_NONE, false,
NULL
},
{ "simd",
(1 << OMP_TRAIT_SET_CONSTRUCT),
OMP_TRAIT_PROPERTY_CLAUSE_LIST, false,
NULL
},
{ NULL, 0, OMP_TRAIT_PROPERTY_NONE, false, NULL } /* OMP_TRAIT_LAST */
};
/* Return a name from PROP, a property in selectors accepting
name lists. */
@ -1147,124 +1262,119 @@ omp_context_name_list_prop (tree prop)
tree
omp_check_context_selector (location_t loc, tree ctx)
{
/* Each trait-set-selector-name can only be specified once.
There are just 4 set names. */
for (tree t1 = ctx; t1; t1 = TREE_CHAIN (t1))
for (tree t2 = TREE_CHAIN (t1); t2; t2 = TREE_CHAIN (t2))
if (OMP_TSS_ID (t1) == OMP_TSS_ID (t2))
{
error_at (loc, "selector set %qs specified more than once",
IDENTIFIER_POINTER (OMP_TSS_ID (t1)));
return error_mark_node;
}
bool tss_seen[OMP_TRAIT_SET_LAST], ts_seen[OMP_TRAIT_LAST];
memset (tss_seen, 0, sizeof (tss_seen));
for (tree tss = ctx; tss; tss = TREE_CHAIN (tss))
{
/* Each trait-selector-name can only be specified once. */
if (list_length (OMP_TSS_TRAIT_SELECTORS (tss)) < 5)
enum omp_tss_code tss_code = OMP_TSS_CODE (tss);
/* We can parse this, but not handle it yet. */
if (tss_code == OMP_TRAIT_SET_TARGET_DEVICE)
sorry_at (loc, "%<target_device%> selector set is not supported yet");
/* Each trait-set-selector-name can only be specified once. */
if (tss_seen[tss_code])
{
for (tree ts1 = OMP_TSS_TRAIT_SELECTORS (tss); ts1;
ts1 = TREE_CHAIN (ts1))
for (tree ts2 = TREE_CHAIN (ts1); ts2; ts2 = TREE_CHAIN (ts2))
if (OMP_TS_ID (ts1) == OMP_TS_ID (ts2))
{
error_at (loc,
"selector %qs specified more than once in set %qs",
IDENTIFIER_POINTER (OMP_TS_ID (ts1)),
IDENTIFIER_POINTER (OMP_TSS_ID (tss)));
return error_mark_node;
}
error_at (loc, "selector set %qs specified more than once",
OMP_TSS_NAME (tss));
return error_mark_node;
}
else
tss_seen[tss_code] = true;
memset (ts_seen, 0, sizeof (ts_seen));
for (tree ts = OMP_TSS_TRAIT_SELECTORS (tss); ts; ts = TREE_CHAIN (ts))
{
hash_set<tree> pset;
for (tree ts = OMP_TSS_TRAIT_SELECTORS (tss); ts;
ts = TREE_CHAIN (ts))
if (pset.add (OMP_TS_ID (ts)))
enum omp_ts_code ts_code = OMP_TS_CODE (ts);
/* Ignore unknown traits. */
if (ts_code == OMP_TRAIT_INVALID)
continue;
/* Each trait-selector-name can only be specified once. */
if (ts_seen[ts_code])
{
error_at (loc,
"selector %qs specified more than once in set %qs",
OMP_TS_NAME (ts),
OMP_TSS_NAME (tss));
return error_mark_node;
}
else
ts_seen[ts_code] = true;
if (omp_ts_map[ts_code].valid_properties == NULL)
continue;
for (tree p = OMP_TS_PROPERTIES (ts); p; p = TREE_CHAIN (p))
for (unsigned j = 0; ; j++)
{
error_at (loc,
"selector %qs specified more than once in set %qs",
IDENTIFIER_POINTER (OMP_TS_ID (ts)),
IDENTIFIER_POINTER (OMP_TSS_ID (tss)));
return error_mark_node;
const char *candidate
= omp_ts_map[ts_code].valid_properties[j];
if (candidate == NULL)
{
/* We've reached the end of the candidate array. */
if (ts_code == OMP_TRAIT_IMPLEMENTATION_ADMO)
/* FIXME: not sure why this is an error vs warnings
for the others, + incorrect/unknown wording? */
{
error_at (loc,
"incorrect property %qs of %qs selector",
IDENTIFIER_POINTER (OMP_TP_NAME (p)),
"atomic_default_mem_order");
return error_mark_node;
}
if (OMP_TP_NAME (p) == OMP_TP_NAMELIST_NODE
&& (TREE_CODE (OMP_TP_VALUE (p)) == STRING_CST))
warning_at (loc, OPT_Wopenmp,
"unknown property %qE of %qs selector",
OMP_TP_VALUE (p),
OMP_TS_NAME (ts));
else if (OMP_TP_NAME (p) == OMP_TP_NAMELIST_NODE)
warning_at (loc, OPT_Wopenmp,
"unknown property %qs of %qs selector",
omp_context_name_list_prop (p),
OMP_TS_NAME (ts));
else if (OMP_TP_NAME (p))
warning_at (loc, OPT_Wopenmp,
"unknown property %qs of %qs selector",
IDENTIFIER_POINTER (OMP_TP_NAME (p)),
OMP_TS_NAME (ts));
break;
}
else if (OMP_TP_NAME (p) == OMP_TP_NAMELIST_NODE)
/* Property-list traits. */
{
const char *str = omp_context_name_list_prop (p);
if (str && !strcmp (str, candidate))
break;
}
else if (!strcmp (IDENTIFIER_POINTER (OMP_TP_NAME (p)),
candidate))
/* Identifier traits. */
break;
}
}
static const char *const kind[] = {
"host", "nohost", "cpu", "gpu", "fpga", "any", NULL };
static const char *const vendor[] = {
"amd", "arm", "bsc", "cray", "fujitsu", "gnu", "ibm", "intel",
"llvm", "nvidia", "pgi", "ti", "unknown", NULL };
static const char *const extension[] = { NULL };
static const char *const atomic_default_mem_order[] = {
"seq_cst", "relaxed", "acq_rel", NULL };
struct known_properties { const char *set; const char *selector;
const char *const *props; };
known_properties props[] = {
{ "device", "kind", kind },
{ "implementation", "vendor", vendor },
{ "implementation", "extension", extension },
{ "implementation", "atomic_default_mem_order",
atomic_default_mem_order } };
for (tree ts = OMP_TSS_TRAIT_SELECTORS (tss); ts; ts = TREE_CHAIN (ts))
for (unsigned i = 0; i < ARRAY_SIZE (props); i++)
if (!strcmp (IDENTIFIER_POINTER (OMP_TS_ID (ts)),
props[i].selector)
&& !strcmp (IDENTIFIER_POINTER (OMP_TSS_ID (tss)),
props[i].set))
for (tree p = OMP_TS_PROPERTIES (ts); p; p = TREE_CHAIN (p))
for (unsigned j = 0; ; j++)
{
if (props[i].props[j] == NULL)
{
if (props[i].props == atomic_default_mem_order)
{
error_at (loc,
"incorrect property %qs of %qs selector",
IDENTIFIER_POINTER (TREE_PURPOSE (p)),
"atomic_default_mem_order");
return error_mark_node;
}
else if (OMP_TP_NAME (p) == OMP_TP_NAMELIST_NODE
&& (TREE_CODE (OMP_TP_VALUE (p)) == STRING_CST))
warning_at (loc, 0,
"unknown property %qE of %qs selector",
OMP_TP_VALUE (p),
props[i].selector);
else if (OMP_TP_NAME (p) == OMP_TP_NAMELIST_NODE)
warning_at (loc, 0,
"unknown property %qs of %qs selector",
omp_context_name_list_prop (p),
props[i].selector);
else if (OMP_TP_NAME (p))
warning_at (loc, OPT_Wopenmp,
"unknown property %qs of %qs selector",
IDENTIFIER_POINTER (OMP_TP_NAME (p)),
props[i].selector);
break;
}
else if (OMP_TP_NAME (p) == OMP_TP_NAMELIST_NODE)
/* Property-list traits. */
{
const char *str = omp_context_name_list_prop (p);
if (str && !strcmp (str, props[i].props[j]))
break;
}
else if (!strcmp (IDENTIFIER_POINTER (OMP_TP_NAME (p)),
props[i].props[j]))
break;
}
}
return ctx;
}
/* Register VARIANT as variant of some base function marked with
#pragma omp declare variant. CONSTRUCT is corresponding construct
selector set. */
#pragma omp declare variant. CONSTRUCT is corresponding list of
trait-selectors for the construct selector set. This is stashed as the
value of the "omp declare variant variant" attribute on VARIANT. */
void
omp_mark_declare_variant (location_t loc, tree variant, tree construct)
{
/* Ignore this variant if it contains unknown construct selectors.
It will never match, and the front ends have already issued a warning
about it. */
for (tree c = construct; c; c = TREE_CHAIN (c))
if (OMP_TS_CODE (c) == OMP_TRAIT_INVALID)
return;
tree attr = lookup_attribute ("omp declare variant variant",
DECL_ATTRIBUTES (variant));
if (attr == NULL_TREE)
@ -1277,7 +1387,8 @@ omp_mark_declare_variant (location_t loc, tree variant, tree construct)
}
if ((TREE_VALUE (attr) != NULL_TREE) != (construct != NULL_TREE)
|| (construct != NULL_TREE
&& omp_context_selector_set_compare ("construct", TREE_VALUE (attr),
&& omp_context_selector_set_compare (OMP_TRAIT_SET_CONSTRUCT,
TREE_VALUE (attr),
construct)))
error_at (loc, "%qD used as a variant with incompatible %<construct%> "
"selector sets", variant);
@ -1287,18 +1398,21 @@ omp_mark_declare_variant (location_t loc, tree variant, tree construct)
/* Constructors for context selectors. */
tree
make_trait_set_selector (tree name, tree selectors, tree chain)
make_trait_set_selector (enum omp_tss_code code, tree selectors, tree chain)
{
return tree_cons (name, selectors, chain);
return tree_cons (build_int_cst (integer_type_node, code),
selectors, chain);
}
tree
make_trait_selector (tree name, tree score, tree properties, tree chain)
make_trait_selector (enum omp_ts_code code, tree score, tree properties,
tree chain)
{
if (score == NULL_TREE)
return tree_cons (name, properties, chain);
return tree_cons (build_int_cst (integer_type_node, code),
properties, chain);
else
return tree_cons (name,
return tree_cons (build_int_cst (integer_type_node, code),
tree_cons (OMP_TS_SCORE_NODE, score, properties),
chain);
}
@ -1321,8 +1435,16 @@ omp_context_selector_matches (tree ctx)
int ret = 1;
for (tree tss = ctx; tss; tss = TREE_CHAIN (tss))
{
char set = IDENTIFIER_POINTER (OMP_TSS_ID (tss))[0];
if (set == 'c')
enum omp_tss_code set = OMP_TSS_CODE (tss);
tree selectors = OMP_TSS_TRAIT_SELECTORS (tss);
/* Immediately reject the match if there are any ignored
selectors present. */
for (tree ts = selectors; ts; ts = TREE_CHAIN (ts))
if (OMP_TS_CODE (ts) == OMP_TRAIT_INVALID)
return 0;
if (set == OMP_TRAIT_SET_CONSTRUCT)
{
/* For now, ignore the construct set. While something can be
determined already during parsing, we don't know until end of TU
@ -1337,10 +1459,20 @@ omp_context_selector_matches (tree ctx)
continue;
}
enum tree_code constructs[5];
int nconstructs
= omp_construct_traits_to_codes (OMP_TSS_TRAIT_SELECTORS (tss),
int nconstructs = list_length (selectors);
enum tree_code *constructs = NULL;
if (nconstructs)
{
/* Even though this alloca appears in a loop over selector
sets, it does not repeatedly grow the stack, because
there can be only one construct selector set specified.
This is enforced by omp_check_context_selector. */
constructs
= (enum tree_code *) alloca (nconstructs
* sizeof (enum tree_code));
omp_construct_traits_to_codes (selectors, nconstructs,
constructs);
}
if (cfun && (cfun->curr_properties & PROP_gimple_any) != 0)
{
@ -1371,13 +1503,13 @@ omp_context_selector_matches (tree ctx)
ret = -1;
continue;
}
for (tree ts = OMP_TSS_TRAIT_SELECTORS (tss); ts; ts = TREE_CHAIN (ts))
for (tree ts = selectors; ts; ts = TREE_CHAIN (ts))
{
const char *sel = IDENTIFIER_POINTER (OMP_TS_ID (ts));
switch (*sel)
enum omp_ts_code sel = OMP_TS_CODE (ts);
switch (sel)
{
case 'v':
if (set == 'i' && !strcmp (sel, "vendor"))
case OMP_TRAIT_IMPLEMENTATION_VENDOR:
if (set == OMP_TRAIT_SET_IMPLEMENTATION)
for (tree p = OMP_TS_PROPERTIES (ts); p; p = TREE_CHAIN (p))
{
const char *prop = omp_context_name_list_prop (p);
@ -1388,13 +1520,13 @@ omp_context_selector_matches (tree ctx)
return 0;
}
break;
case 'e':
if (set == 'i' && !strcmp (sel, "extension"))
case OMP_TRAIT_IMPLEMENTATION_EXTENSION:
if (set == OMP_TRAIT_SET_IMPLEMENTATION)
/* We don't support any extensions right now. */
return 0;
break;
case 'a':
if (set == 'i' && !strcmp (sel, "atomic_default_mem_order"))
case OMP_TRAIT_IMPLEMENTATION_ADMO:
if (set == OMP_TRAIT_SET_IMPLEMENTATION)
{
if (cfun && (cfun->curr_properties & PROP_gimple_any) != 0)
break;
@ -1426,7 +1558,9 @@ omp_context_selector_matches (tree ctx)
&& omo != OMP_MEMORY_ORDER_ACQ_REL)
return 0;
}
if (set == 'd' && !strcmp (sel, "arch"))
break;
case OMP_TRAIT_DEVICE_ARCH:
if (set == OMP_TRAIT_SET_DEVICE)
for (tree p = OMP_TS_PROPERTIES (ts); p; p = TREE_CHAIN (p))
{
const char *arch = omp_context_name_list_prop (p);
@ -1463,8 +1597,8 @@ omp_context_selector_matches (tree ctx)
ret = -1;
}
break;
case 'u':
if (set == 'i' && !strcmp (sel, "unified_address"))
case OMP_TRAIT_IMPLEMENTATION_UNIFIED_ADDRESS:
if (set == OMP_TRAIT_SET_IMPLEMENTATION)
{
if (cfun && (cfun->curr_properties & PROP_gimple_any) != 0)
break;
@ -1476,9 +1610,10 @@ omp_context_selector_matches (tree ctx)
else
return 0;
}
break;
}
if (set == 'i' && !strcmp (sel, "unified_shared_memory"))
break;
case OMP_TRAIT_IMPLEMENTATION_UNIFIED_SHARED_MEMORY:
if (set == OMP_TRAIT_SET_IMPLEMENTATION)
{
if (cfun && (cfun->curr_properties & PROP_gimple_any) != 0)
break;
@ -1491,11 +1626,10 @@ omp_context_selector_matches (tree ctx)
else
return 0;
}
break;
}
break;
case 'd':
if (set == 'i' && !strcmp (sel, "dynamic_allocators"))
case OMP_TRAIT_IMPLEMENTATION_DYNAMIC_ALLOCATORS:
if (set == OMP_TRAIT_SET_IMPLEMENTATION)
{
if (cfun && (cfun->curr_properties & PROP_gimple_any) != 0)
break;
@ -1508,11 +1642,10 @@ omp_context_selector_matches (tree ctx)
else
return 0;
}
break;
}
break;
case 'r':
if (set == 'i' && !strcmp (sel, "reverse_offload"))
case OMP_TRAIT_IMPLEMENTATION_REVERSE_OFFLOAD:
if (set == OMP_TRAIT_SET_IMPLEMENTATION)
{
if (cfun && (cfun->curr_properties & PROP_gimple_any) != 0)
break;
@ -1524,11 +1657,10 @@ omp_context_selector_matches (tree ctx)
else
return 0;
}
break;
}
break;
case 'k':
if (set == 'd' && !strcmp (sel, "kind"))
case OMP_TRAIT_DEVICE_KIND:
if (set == OMP_TRAIT_SET_DEVICE)
for (tree p = OMP_TS_PROPERTIES (ts); p; p = TREE_CHAIN (p))
{
const char *prop = omp_context_name_list_prop (p);
@ -1588,8 +1720,8 @@ omp_context_selector_matches (tree ctx)
ret = -1;
}
break;
case 'i':
if (set == 'd' && !strcmp (sel, "isa"))
case OMP_TRAIT_DEVICE_ISA:
if (set == OMP_TRAIT_SET_DEVICE)
for (tree p = OMP_TS_PROPERTIES (ts); p; p = TREE_CHAIN (p))
{
const char *isa = omp_context_name_list_prop (p);
@ -1641,8 +1773,8 @@ omp_context_selector_matches (tree ctx)
ret = -1;
}
break;
case 'c':
if (set == 'u' && !strcmp (sel, "condition"))
case OMP_TRAIT_USER_CONDITION:
if (set == OMP_TRAIT_SET_USER)
for (tree p = OMP_TS_PROPERTIES (ts); p; p = TREE_CHAIN (p))
if (OMP_TP_NAME (p) == NULL_TREE)
{
@ -1784,7 +1916,8 @@ omp_construct_simd_compare (tree clauses1, tree clauses2)
Unlike set names or selector names, properties can have duplicates. */
static int
omp_context_selector_props_compare (const char *set, const char *sel,
omp_context_selector_props_compare (enum omp_tss_code set,
enum omp_ts_code sel,
tree ctx1, tree ctx2)
{
int ret = 0;
@ -1797,7 +1930,8 @@ omp_context_selector_props_compare (const char *set, const char *sel,
{
if (OMP_TP_NAME (p1) == NULL_TREE)
{
if (set[0] == 'u' && strcmp (sel, "condition") == 0)
if (set == OMP_TRAIT_SET_USER
&& sel == OMP_TRAIT_USER_CONDITION)
{
if (integer_zerop (OMP_TP_VALUE (p1))
!= integer_zerop (OMP_TP_VALUE (p2)))
@ -1844,8 +1978,18 @@ omp_context_selector_props_compare (const char *set, const char *sel,
2 if neither context is a subset of another one. */
int
omp_context_selector_set_compare (const char *set, tree ctx1, tree ctx2)
omp_context_selector_set_compare (enum omp_tss_code set, tree ctx1, tree ctx2)
{
/* If either list includes an ignored selector trait, neither can
be a subset of the other. */
for (tree ts = ctx1; ts; ts = TREE_CHAIN (ts))
if (OMP_TS_CODE (ts) == OMP_TRAIT_INVALID)
return 2;
for (tree ts = ctx2; ts; ts = TREE_CHAIN (ts))
if (OMP_TS_CODE (ts) == OMP_TRAIT_INVALID)
return 2;
bool swapped = false;
int ret = 0;
int len1 = list_length (ctx1);
@ -1857,18 +2001,18 @@ omp_context_selector_set_compare (const char *set, tree ctx1, tree ctx2)
std::swap (ctx1, ctx2);
std::swap (len1, len2);
}
if (set[0] == 'c')
if (set == OMP_TRAIT_SET_CONSTRUCT)
{
tree ts1;
tree ts2 = ctx2;
tree simd = get_identifier ("simd");
/* Handle construct set specially. In this case the order
of the selector matters too. */
for (ts1 = ctx1; ts1; ts1 = TREE_CHAIN (ts1))
if (OMP_TS_ID (ts1) == OMP_TS_ID (ts2))
if (OMP_TS_CODE (ts1) == OMP_TS_CODE (ts2))
{
int r = 0;
if (OMP_TS_ID (ts1) == simd)
if (OMP_TS_CODE (ts1) == OMP_TRAIT_CONSTRUCT_SIMD)
r = omp_construct_simd_compare (OMP_TS_PROPERTIES (ts1),
OMP_TS_PROPERTIES (ts2));
if (r == 2 || (ret && r && (ret < 0) != (r < 0)))
@ -1900,17 +2044,17 @@ omp_context_selector_set_compare (const char *set, tree ctx1, tree ctx2)
}
for (tree ts1 = ctx1; ts1; ts1 = TREE_CHAIN (ts1))
{
enum omp_ts_code sel = OMP_TS_CODE (ts1);
tree ts2;
for (ts2 = ctx2; ts2; ts2 = TREE_CHAIN (ts2))
if (OMP_TS_ID (ts1) == OMP_TS_ID (ts2))
if (sel == OMP_TS_CODE (ts2))
{
tree score1 = OMP_TS_SCORE (ts1);
tree score2 = OMP_TS_SCORE (ts2);
if (score1 && score2 && !simple_cst_equal (score1, score2))
return 2;
const char *sel = IDENTIFIER_POINTER (OMP_TS_ID (ts1));
int r = omp_context_selector_props_compare (set, sel,
int r = omp_context_selector_props_compare (set, OMP_TS_CODE (ts1),
OMP_TS_PROPERTIES (ts1),
OMP_TS_PROPERTIES (ts2));
if (r == 2 || (ret && r && (ret < 0) != (r < 0)))
@ -1956,11 +2100,11 @@ omp_context_selector_compare (tree ctx1, tree ctx2)
}
for (tree tss1 = ctx1; tss1; tss1 = TREE_CHAIN (tss1))
{
enum omp_tss_code set = OMP_TSS_CODE (tss1);
tree tss2;
for (tss2 = ctx2; tss2; tss2 = TREE_CHAIN (tss2))
if (OMP_TSS_ID (tss1) == OMP_TSS_ID (tss2))
if (set == OMP_TSS_CODE (tss2))
{
const char *set = IDENTIFIER_POINTER (OMP_TSS_ID (tss1));
int r
= omp_context_selector_set_compare
(set, OMP_TSS_TRAIT_SELECTORS (tss1),
@ -1987,26 +2131,51 @@ omp_context_selector_compare (tree ctx1, tree ctx2)
}
/* From context selector CTX, return trait-selector with name SEL in
trait-selector-set with name SET if any, or NULL_TREE if not found.
If SEL is NULL, return the list of trait-selectors in SET. */
trait-selector-set with name SET if any, or NULL_TREE if not found. */
tree
omp_get_context_selector (tree ctx, const char *set, const char *sel)
omp_get_context_selector (tree ctx, enum omp_tss_code set,
enum omp_ts_code sel)
{
tree setid = get_identifier (set);
tree selid = sel ? get_identifier (sel) : NULL_TREE;
for (tree tss = ctx; tss; tss = TREE_CHAIN (tss))
if (OMP_TSS_ID (tss) == setid)
{
if (sel == NULL)
return OMP_TSS_TRAIT_SELECTORS (tss);
for (tree ts = OMP_TSS_TRAIT_SELECTORS (tss); ts; ts = TREE_CHAIN (ts))
if (OMP_TS_ID (ts) == selid)
return ts;
}
if (OMP_TSS_CODE (tss) == set)
for (tree ts = OMP_TSS_TRAIT_SELECTORS (tss); ts; ts = TREE_CHAIN (ts))
if (OMP_TS_CODE (ts) == sel)
return ts;
return NULL_TREE;
}
/* Similar, but returns the whole trait-selector list for SET in CTX. */
tree
omp_get_context_selector_list (tree ctx, enum omp_tss_code set)
{
for (tree tss = ctx; tss; tss = TREE_CHAIN (tss))
if (OMP_TSS_CODE (tss) == set)
return OMP_TSS_TRAIT_SELECTORS (tss);
return NULL_TREE;
}
/* Map string S onto a trait selector set code. */
enum omp_tss_code
omp_lookup_tss_code (const char * s)
{
for (int i = 0; i < OMP_TRAIT_SET_LAST; i++)
if (strcmp (s, omp_tss_map[i]) == 0)
return (enum omp_tss_code) i;
return OMP_TRAIT_SET_INVALID;
}
/* Map string S onto a trait selector code for set SET. */
enum omp_ts_code
omp_lookup_ts_code (enum omp_tss_code set, const char *s)
{
unsigned int mask = 1 << set;
for (int i = 0; i < OMP_TRAIT_LAST; i++)
if ((mask & omp_ts_map[i].tss_mask) != 0
&& strcmp (s, omp_ts_map[i].name) == 0)
return (enum omp_ts_code) i;
return OMP_TRAIT_INVALID;
}
/* Needs to be a GC-friendly widest_int variant, but precision is
desirable to be the same on all targets. */
typedef generic_wide_int <fixed_wide_int_storage <1024> > score_wide_int;
@ -2019,14 +2188,18 @@ typedef generic_wide_int <fixed_wide_int_storage <1024> > score_wide_int;
static bool
omp_context_compute_score (tree ctx, score_wide_int *score, bool declare_simd)
{
tree construct = omp_get_context_selector (ctx, "construct", NULL);
bool has_kind = omp_get_context_selector (ctx, "device", "kind");
bool has_arch = omp_get_context_selector (ctx, "device", "arch");
bool has_isa = omp_get_context_selector (ctx, "device", "isa");
tree selectors
= omp_get_context_selector_list (ctx, OMP_TRAIT_SET_CONSTRUCT);
bool has_kind = omp_get_context_selector (ctx, OMP_TRAIT_SET_DEVICE,
OMP_TRAIT_DEVICE_KIND);
bool has_arch = omp_get_context_selector (ctx, OMP_TRAIT_SET_DEVICE,
OMP_TRAIT_DEVICE_ARCH);
bool has_isa = omp_get_context_selector (ctx, OMP_TRAIT_SET_DEVICE,
OMP_TRAIT_DEVICE_ISA);
bool ret = false;
*score = 1;
for (tree tss = ctx; tss; tss = TREE_CHAIN (tss))
if (OMP_TSS_TRAIT_SELECTORS (tss) != construct)
if (OMP_TSS_TRAIT_SELECTORS (tss) != selectors)
for (tree ts = OMP_TSS_TRAIT_SELECTORS (tss); ts; ts = TREE_CHAIN (ts))
{
tree s = OMP_TS_SCORE (ts);
@ -2035,13 +2208,19 @@ omp_context_compute_score (tree ctx, score_wide_int *score, bool declare_simd)
TYPE_SIGN (TREE_TYPE (s)));
}
if (construct || has_kind || has_arch || has_isa)
if (selectors || has_kind || has_arch || has_isa)
{
int scores[12];
enum tree_code constructs[5];
int nconstructs = 0;
if (construct)
nconstructs = omp_construct_traits_to_codes (construct, constructs);
int nconstructs = list_length (selectors);
enum tree_code *constructs = NULL;
if (nconstructs)
{
constructs
= (enum tree_code *) alloca (nconstructs
* sizeof (enum tree_code));
omp_construct_traits_to_codes (selectors, nconstructs, constructs);
}
int *scores
= (int *) alloca ((2 * nconstructs + 2) * sizeof (int));
if (omp_construct_selector_matches (constructs, nconstructs, scores)
== 2)
ret = true;

View file

@ -24,6 +24,7 @@ along with GCC; see the file COPYING3. If not see
#include "gomp-constants.h"
#include "omp-api.h"
#include "omp-selectors.h"
/* Flags for an OpenACC loop. */
@ -135,8 +136,18 @@ struct omp_for_data
#define OMP_TP_VALUE(NODE) \
TREE_VALUE (NODE)
extern tree make_trait_set_selector (tree, tree, tree);
extern tree make_trait_selector (tree, tree, tree, tree);
#define OMP_TSS_CODE(t) \
((enum omp_tss_code) TREE_INT_CST_LOW (OMP_TSS_ID (t)))
#define OMP_TSS_NAME(t) \
(omp_tss_map[OMP_TSS_CODE (t)])
#define OMP_TS_CODE(t) \
((enum omp_ts_code) TREE_INT_CST_LOW (OMP_TS_ID (t)))
#define OMP_TS_NAME(t) \
(omp_ts_map[OMP_TS_CODE (t)].name)
extern tree make_trait_set_selector (enum omp_tss_code, tree, tree);
extern tree make_trait_selector (enum omp_ts_code, tree, tree, tree);
extern tree make_trait_property (tree, tree, tree);
extern tree omp_find_clause (tree clauses, enum omp_clause_code kind);
@ -153,13 +164,15 @@ extern gimple *omp_build_barrier (tree lhs);
extern tree find_combined_omp_for (tree *, int *, void *);
extern poly_uint64 omp_max_vf (void);
extern int omp_max_simt_vf (void);
extern int omp_construct_traits_to_codes (tree, enum tree_code *);
extern void omp_construct_traits_to_codes (tree, int, enum tree_code *);
extern tree omp_check_context_selector (location_t loc, tree ctx);
extern void omp_mark_declare_variant (location_t loc, tree variant,
tree construct);
extern int omp_context_selector_matches (tree);
extern int omp_context_selector_set_compare (const char *, tree, tree);
extern tree omp_get_context_selector (tree, const char *, const char *);
extern int omp_context_selector_set_compare (enum omp_tss_code, tree, tree);
extern tree omp_get_context_selector (tree, enum omp_tss_code,
enum omp_ts_code);
extern tree omp_get_context_selector_list (tree, enum omp_tss_code);
extern tree omp_resolve_declare_variant (tree);
extern tree oacc_launch_pack (unsigned code, tree device, unsigned op);
extern tree oacc_replace_fn_attrib_attr (tree attribs, tree dims);

93
gcc/omp-selectors.h Normal file
View file

@ -0,0 +1,93 @@
/* Data structures for OpenMP context selectors. This is in a separate file
from omp-general.h so that it may also be used in the Fortran parser
without reference to tree data structures.
Copyright (C) 2023 Free Software Foundation, Inc.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
#ifndef GCC_OMP_SELECTORS_H
#define GCC_OMP_SELECTORS_H
/* Trait set selector keywords. */
enum omp_tss_code {
OMP_TRAIT_SET_CONSTRUCT,
OMP_TRAIT_SET_DEVICE,
OMP_TRAIT_SET_TARGET_DEVICE,
OMP_TRAIT_SET_IMPLEMENTATION,
OMP_TRAIT_SET_USER,
OMP_TRAIT_SET_LAST,
OMP_TRAIT_SET_INVALID = -1
};
/* Trait selector keywords. */
enum omp_ts_code {
OMP_TRAIT_DEVICE_KIND,
OMP_TRAIT_DEVICE_ISA,
OMP_TRAIT_DEVICE_ARCH,
OMP_TRAIT_DEVICE_NUM,
OMP_TRAIT_IMPLEMENTATION_VENDOR,
OMP_TRAIT_IMPLEMENTATION_EXTENSION,
OMP_TRAIT_IMPLEMENTATION_ADMO,
OMP_TRAIT_IMPLEMENTATION_REQUIRES,
OMP_TRAIT_IMPLEMENTATION_UNIFIED_ADDRESS,
OMP_TRAIT_IMPLEMENTATION_UNIFIED_SHARED_MEMORY,
OMP_TRAIT_IMPLEMENTATION_DYNAMIC_ALLOCATORS,
OMP_TRAIT_IMPLEMENTATION_REVERSE_OFFLOAD,
OMP_TRAIT_USER_CONDITION,
OMP_TRAIT_CONSTRUCT_TARGET,
OMP_TRAIT_CONSTRUCT_TEAMS,
OMP_TRAIT_CONSTRUCT_PARALLEL,
OMP_TRAIT_CONSTRUCT_FOR,
OMP_TRAIT_CONSTRUCT_SIMD,
OMP_TRAIT_LAST,
OMP_TRAIT_INVALID = -1
};
/* All trait property forms. */
enum omp_tp_type {
OMP_TRAIT_PROPERTY_NONE,
OMP_TRAIT_PROPERTY_ID,
OMP_TRAIT_PROPERTY_NAME_LIST,
OMP_TRAIT_PROPERTY_EXPR,
OMP_TRAIT_PROPERTY_CLAUSE_LIST,
OMP_TRAIT_PROPERTY_EXTENSION
};
/* Map trait set selector name keywords onto strings. */
extern const char *omp_tss_map [];
/* Map trait selector keywords onto strings, allowed contexts, and
allowed property names for OMP_TRAIT_PROPERTY_NAME_LIST and
OMP_TRAIT_PROPERTY_ID properties. If valid_properties is null,
it means that any required checking has to be done explicitly
somewhere instead of being driven by the table. Otherwise it's a
null-terminated array of strings. */
struct omp_ts_info {
const char *name;
unsigned int tss_mask;
enum omp_tp_type tp_type;
bool allow_score;
const char * const *valid_properties;
};
extern struct omp_ts_info omp_ts_map[];
extern enum omp_tss_code omp_lookup_tss_code (const char *);
extern enum omp_ts_code omp_lookup_ts_code (enum omp_tss_code, const char *);
#endif /* GCC_OMP_SELECTORS_H */

View file

@ -9,6 +9,7 @@ int bar (int, int, int *);
match (device={arch(x86_64,powerpc64),isa(avx512f,popcntb)}, \
implementation={atomic_default_mem_order(seq_cst),made_up_selector("foo", 13, "bar")}, \
user={condition(3-3)})
/* { dg-warning "unknown selector 'made_up_selector'" "" { target *-*-* } .-2 } */
int baz (int, int, int *);
int

View file

@ -14,13 +14,13 @@ void f6 (void);
void f7 (void);
#pragma omp declare variant (f1) match /* { dg-error "expected '\\(' before end of line" } */
void f8 (void);
#pragma omp declare variant (f1) match( /* { dg-error "expected 'construct', 'device', 'implementation' or 'user' before end of line" } */
#pragma omp declare variant (f1) match( /* { dg-error "expected context selector set name before end of line" } */
void f9 (void);
#pragma omp declare variant (f1) match() /* { dg-error "expected 'construct', 'device', 'implementation' or 'user' before '\\)' token" } */
#pragma omp declare variant (f1) match() /* { dg-error "expected context selector set name before '\\)' token" } */
void f10 (void);
#pragma omp declare variant (f1) match(foo) /* { dg-error "expected 'construct', 'device', 'implementation' or 'user' before 'foo'" } */
#pragma omp declare variant (f1) match(foo) /* { dg-error "expected context selector set name before 'foo'" } */
void f11 (void);
#pragma omp declare variant (f1) match(something={something}) /* { dg-error "expected 'construct', 'device', 'implementation' or 'user' before 'something'" } */
#pragma omp declare variant (f1) match(something={something}) /* { dg-error "expected context selector set name before 'something'" } */
void f12 (void);
#pragma omp declare variant (f1) match(user) /* { dg-error "expected '=' before '\\)' token" } */
void f13 (void);
@ -42,10 +42,10 @@ void f20 (void);
void f21 (void); /* { dg-error "cannot appear in a constant-expression" "" { target c++98_only } .-1 } */
#pragma omp declare variant (f1) match(user={condition(1, 2, 3)}) /* { dg-error "expected '\\)' before ',' token" } */
void f22 (void);
#pragma omp declare variant (f1) match(construct={master}) /* { dg-error "selector 'master' not allowed for context selector set 'construct'" } */
#pragma omp declare variant (f1) match(construct={master}) /* { dg-warning "unknown selector 'master' for context selector set 'construct'" } */
void f23 (void);
#pragma omp declare variant (f1) match(construct={teams,parallel,master,for}) /* { dg-error "selector 'master' not allowed for context selector set 'construct'" } */
void f24 (void); /* { dg-error "expected '\\\}' before ',' token" "" { target c } .-1 } */
#pragma omp declare variant (f1) match(construct={teams,parallel,master,for}) /* { dg-warning "unknown selector 'master' for context selector set 'construct'" } */
void f24 (void);
#pragma omp declare variant (f1) match(construct={parallel(1 /* { dg-error "selector 'parallel' does not accept any properties" } */
void f25 (void); /* { dg-error "expected '\\\}' before end of line" "" { target c++ } .-1 } */
/* { dg-error "expected '\\\}' before '\\(' token" "" { target c } .-2 } */
@ -79,11 +79,11 @@ void f38 (void); /* { dg-warning "unknown property 'foobar' of 'kind' sele
void f39 (void);
#pragma omp declare variant (f1) match(device={arch(17)}) /* { dg-error "expected identifier or string literal before numeric constant" } */
void f40 (void);
#pragma omp declare variant (f1) match(device={foobar(3)})
#pragma omp declare variant (f1) match(device={foobar(3)}) /* { dg-warning "unknown selector 'foobar' for context selector set 'device'" } */
void f41 (void);
#pragma omp declare variant (f1) match(device={arch(x86_64)},device={isa(avx512vl)}) /* { dg-error "selector set 'device' specified more than once" } */
void f42 (void);
#pragma omp declare variant (f1) match(implementation={foobar(3)})
#pragma omp declare variant (f1) match(implementation={foobar(3)}) /* { dg-warning "unknown selector 'foobar' for context selector set 'implementation'" } */
void f43 (void);
#pragma omp declare variant (f1) match(implementation={vendor}) /* { dg-error "expected '\\(' before '\\\}' token" } */
void f44 (void);
@ -115,11 +115,11 @@ void f55 (void);
void f56 (void);
#pragma omp declare variant (f1) match(implementation={atomic_default_mem_order(relaxed)},implementation={atomic_default_mem_order(relaxed)}) /* { dg-error "selector set 'implementation' specified more than once" } */
void f57 (void);
#pragma omp declare variant (f1) match(user={foobar(3)}) /* { dg-error "selector 'foobar' not allowed for context selector set 'user'" } */
void f58 (void); /* { dg-error "expected '\\\}' before '\\(' token" "" { target c } .-1 } */
#pragma omp declare variant (f1) match(construct={foobar(3)}) /* { dg-error "selector 'foobar' not allowed for context selector set 'construct'" } */
void f59 (void); /* { dg-error "expected '\\\}' before '\\(' token" "" { target c } .-1 } */
#pragma omp declare variant (f1) match(construct={parallel},foobar={bar}) /* { dg-error "expected 'construct', 'device', 'implementation' or 'user' before 'foobar'" } */
#pragma omp declare variant (f1) match(user={foobar(3)}) /* { dg-warning "unknown selector 'foobar' for context selector set 'user'" } */
void f58 (void);
#pragma omp declare variant (f1) match(construct={foobar(3)}) /* { dg-warning "unknown selector 'foobar' for context selector set 'construct'" } */
void f59 (void);
#pragma omp declare variant (f1) match(construct={parallel},foobar={bar}) /* { dg-error "expected context selector set name before 'foobar'" } */
void f60 (void);
#pragma omp declare variant (f1) match(construct={parallel,parallel}) /* { dg-error "selector 'parallel' specified more than once in set 'construct'" } */
void f61 (void);
@ -127,34 +127,34 @@ void f61 (void);
void f62 (void);
#pragma omp declare variant (f1) match(construct={target,teams,teams}) /* { dg-error "selector 'teams' specified more than once in set 'construct'" } */
void f63 (void);
#pragma omp declare variant (f1) match(construct={single}) /* { dg-error "selector 'single' not allowed for context selector set 'construct'" } */
#pragma omp declare variant (f1) match(construct={single}) /* { dg-warning "unknown selector 'single' for context selector set 'construct'" } */
void f64 (void);
#pragma omp declare variant (f1) match(construct={taskgroup}) /* { dg-error "selector 'taskgroup' not allowed for context selector set 'construct'" } */
#pragma omp declare variant (f1) match(construct={taskgroup}) /* { dg-warning "unknown selector 'taskgroup' for context selector set 'construct'" } */
void f65 (void);
#pragma omp declare variant (f1) match(construct={do}) /* { dg-error "selector 'do' not allowed for context selector set 'construct'" } */
#pragma omp declare variant (f1) match(construct={do}) /* { dg-warning "unknown selector 'do' for context selector set 'construct'" } */
void f66 (void);
#pragma omp declare variant (f1) match(construct={threadprivate}) /* { dg-error "selector 'threadprivate' not allowed for context selector set 'construct'" } */
#pragma omp declare variant (f1) match(construct={threadprivate}) /* { dg-warning "unknown selector 'threadprivate' for context selector set 'construct'" } */
void f67 (void);
#pragma omp declare variant (f1) match(construct={critical}) /* { dg-error "selector 'critical' not allowed for context selector set 'construct'" } */
#pragma omp declare variant (f1) match(construct={critical}) /* { dg-warning "unknown selector 'critical' for context selector set 'construct'" } */
void f68 (void);
#pragma omp declare variant (f1) match(construct={task}) /* { dg-error "selector 'task' not allowed for context selector set 'construct'" } */
#pragma omp declare variant (f1) match(construct={task}) /* { dg-warning "unknown selector 'task' for context selector set 'construct'" } */
void f69 (void);
#pragma omp declare variant (f1) match(construct={taskloop}) /* { dg-error "selector 'taskloop' not allowed for context selector set 'construct'" } */
#pragma omp declare variant (f1) match(construct={taskloop}) /* { dg-warning "unknown selector 'taskloop' for context selector set 'construct'" } */
void f70 (void);
#pragma omp declare variant (f1) match(construct={sections}) /* { dg-error "selector 'sections' not allowed for context selector set 'construct'" } */
#pragma omp declare variant (f1) match(construct={sections}) /* { dg-warning "unknown selector 'sections' for context selector set 'construct'" } */
void f71 (void);
#pragma omp declare variant (f1) match(construct={section}) /* { dg-error "selector 'section' not allowed for context selector set 'construct'" } */
#pragma omp declare variant (f1) match(construct={section}) /* { dg-warning "unknown selector 'section' for context selector set 'construct'" } */
void f72 (void);
#pragma omp declare variant (f1) match(construct={workshare}) /* { dg-error "selector 'workshare' not allowed for context selector set 'construct'" } */
#pragma omp declare variant (f1) match(construct={workshare}) /* { dg-warning "unknown selector 'workshare' for context selector set 'construct'" } */
void f73 (void);
#pragma omp declare variant (f1) match(construct={requires}) /* { dg-error "selector 'requires' not allowed for context selector set 'construct'" } */
#pragma omp declare variant (f1) match(construct={requires}) /* { dg-warning "unknown selector 'requires' for context selector set 'construct'" } */
void f74 (void);
void f75a (void);
#pragma omp declare variant (f75a),match(construct={parallel})
void f75 (void);
#pragma omp declare variant (f1) match(implementation={atomic_default_mem_order("relaxed")}) /* { dg-error "expected identifier before string constant" } */
void f76 (void);
#pragma omp declare variant (f1) match(user={condition(score(&f76):1)}) /* { dg-error "score argument must be constant integer expression" "" { target { ! c++98_only } } } */
#pragma omp declare variant (f1) match(user={condition(score(&f76):1)}) /* { dg-error ".score. argument must be constant integer expression" "" { target { ! c++98_only } } } */
void f77 (void); /* { dg-error "cannot appear in a constant-expression" "" { target c++98_only } .-1 } */
#pragma omp declare variant (f1) match(user={condition(score(-130):1)}) /* { dg-error "score argument must be non-negative" } */
#pragma omp declare variant (f1) match(user={condition(score(-130):1)}) /* { dg-error ".score. argument must be non-negative" } */
void f78 (void);

View file

@ -0,0 +1,24 @@
/* { dg-do compile { target x86_64-*-* } } */
/* { dg-additional-options "-foffload=disable" } */
void f01 (void);
#pragma omp declare variant (f01) \
match (device={kind (score(5) : host)})
/* { dg-error ".score. cannot be specified in traits in the .device. trait-selector-set" "" { target *-*-*} .-1 } */
void f02 (void);
void f03 (void);
#pragma omp declare variant (f03) \
match (device={kind (host), arch (score(6) : x86_64), isa (avx512f)})
/* { dg-error ".score. cannot be specified in traits in the .device. trait-selector-set" "" { target *-*-*} .-1 } */
void f04 (void);
void f05 (void);
#pragma omp declare variant (f05) \
match (device={kind (host), arch (score(6) : x86_64), \
isa (score(7): avx512f)})
/* { dg-error ".score. cannot be specified in traits in the .device. trait-selector-set" "" { target *-*-*} .-2 } */
/* { dg-error ".score. cannot be specified in traits in the .device. trait-selector-set" "" { target *-*-*} .-2 } */
void f06 (void);

View file

@ -25,6 +25,7 @@ module main
!$omp & match (device={arch(x86_64,powerpc64),isa(avx512f,popcntb)}, &
!$omp & implementation={atomic_default_mem_order(seq_cst),made_up_selector("foo", 13, "bar")}, &
!$omp & user={condition(3-3)})
! { dg-warning "unknown selector 'made_up_selector'" "" { target *-*-* } .-2 }
end function
subroutine quux

View file

@ -27,16 +27,16 @@ contains
!$omp declare variant (f1) match ! { dg-error "expected '\\(' at .1." }
end subroutine
subroutine f9 ()
!$omp declare variant (f1) match( ! { dg-error "expected 'construct', 'device', 'implementation' or 'user' at .1." }
!$omp declare variant (f1) match( ! { dg-error "expected context selector set name at .1." }
end subroutine
subroutine f10 ()
!$omp declare variant (f1) match() ! { dg-error "expected 'construct', 'device', 'implementation' or 'user' at .1." }
!$omp declare variant (f1) match() ! { dg-error "expected context selector set name at .1." }
end subroutine
subroutine f11 ()
!$omp declare variant (f1) match(foo) ! { dg-error "expected 'construct', 'device', 'implementation' or 'user' at .1." }
!$omp declare variant (f1) match(foo) ! { dg-error "expected context selector set name at .1." }
end subroutine
subroutine f12 ()
!$omp declare variant (f1) match(something={something}) ! { dg-error "expected 'construct', 'device', 'implementation' or 'user' at .1." }
!$omp declare variant (f1) match(something={something}) ! { dg-error "expected context selector set name at .1." }
end subroutine
subroutine f13 ()
!$omp declare variant (f1) match(user) ! { dg-error "expected '=' at .1." }
@ -69,10 +69,10 @@ contains
!$omp declare variant (f1) match(user={condition(1, 2, 3)}) ! { dg-error "expected '\\)' at .1." }
end subroutine
subroutine f23 ()
!$omp declare variant (f1) match(construct={master}) ! { dg-error "selector 'master' not allowed for context selector set 'construct' at .1." }
!$omp declare variant (f1) match(construct={master}) ! { dg-warning "unknown selector 'master' for context selector set 'construct'" }
end subroutine
subroutine f24 ()
!$omp declare variant (f1) match(construct={teams,parallel,master,do}) ! { dg-error "selector 'master' not allowed for context selector set 'construct' at .1." }
!$omp declare variant (f1) match(construct={teams,parallel,master,do}) ! { dg-warning "unknown selector 'master' for context selector set 'construct'" }
end subroutine
subroutine f25 ()
!$omp declare variant (f1) match(construct={parallel(1 ! { dg-error "selector 'parallel' does not accept any properties at .1." }
@ -105,10 +105,10 @@ contains
!$omp declare variant (f1) match(device={arch(17)}) ! { dg-error "expected identifier or string literal at .1." }
end subroutine
subroutine f41 ()
!$omp declare variant (f1) match(device={foobar(3)})
!$omp declare variant (f1) match(device={foobar(3)}) ! { dg-warning "unknown selector 'foobar' for context selector set 'device' at .1." }
end subroutine
subroutine f43 ()
!$omp declare variant (f1) match(implementation={foobar(3)})
!$omp declare variant (f1) match(implementation={foobar(3)}) ! { dg-warning "unknown selector 'foobar' for context selector set 'implementation' at .1." }
end subroutine
subroutine f44 ()
!$omp declare variant (f1) match(implementation={vendor}) ! { dg-error "expected '\\(' at .1." }
@ -141,46 +141,46 @@ contains
!$omp declare variant (f1) match(implementation={atomic_default_mem_order(relaxed,seq_cst)}) ! { dg-error "expected '\\)' at .1." }
end subroutine
subroutine f58 ()
!$omp declare variant (f1) match(user={foobar(3)}) ! { dg-error "selector 'foobar' not allowed for context selector set 'user' at .1." }
!$omp declare variant (f1) match(user={foobar(3)}) ! { dg-warning "unknown selector 'foobar' for context selector set 'user' at .1." }
end subroutine
subroutine f59 ()
!$omp declare variant (f1) match(construct={foobar(3)}) ! { dg-error "selector 'foobar' not allowed for context selector set 'construct' at .1." }
!$omp declare variant (f1) match(construct={foobar(3)}) ! { dg-warning "unknown selector 'foobar' for context selector set 'construct' at .1." }
end subroutine
subroutine f60 ()
!$omp declare variant (f1) match(construct={parallel},foobar={bar}) ! { dg-error "expected 'construct', 'device', 'implementation' or 'user' at .1." }
!$omp declare variant (f1) match(construct={parallel},foobar={bar}) ! { dg-error "expected context selector set name at .1." }
end subroutine
subroutine f64 ()
!$omp declare variant (f1) match(construct={single}) ! { dg-error "selector 'single' not allowed for context selector set 'construct' at .1." }
!$omp declare variant (f1) match(construct={single}) ! { dg-warning "unknown selector 'single' for context selector set 'construct' at .1." }
end subroutine
subroutine f65 ()
!$omp declare variant (f1) match(construct={taskgroup}) ! { dg-error "selector 'taskgroup' not allowed for context selector set 'construct' at .1." }
!$omp declare variant (f1) match(construct={taskgroup}) ! { dg-warning "unknown selector 'taskgroup' for context selector set 'construct' at .1." }
end subroutine
subroutine f66 ()
!$omp declare variant (f1) match(construct={for}) ! { dg-error "selector 'for' not allowed for context selector set 'construct' at .1." }
!$omp declare variant (f1) match(construct={for}) ! { dg-warning "unknown selector 'for' for context selector set 'construct' at .1." }
end subroutine
subroutine f67 ()
!$omp declare variant (f1) match(construct={threadprivate}) ! { dg-error "selector 'threadprivate' not allowed for context selector set 'construct' at .1." }
!$omp declare variant (f1) match(construct={threadprivate}) ! { dg-warning "unknown selector 'threadprivate' for context selector set 'construct' at .1." }
end subroutine
subroutine f68 ()
!$omp declare variant (f1) match(construct={critical}) ! { dg-error "selector 'critical' not allowed for context selector set 'construct' at .1." }
!$omp declare variant (f1) match(construct={critical}) ! { dg-warning "unknown selector 'critical' for context selector set 'construct' at .1." }
end subroutine
subroutine f69 ()
!$omp declare variant (f1) match(construct={task}) ! { dg-error "selector 'task' not allowed for context selector set 'construct' at .1." }
!$omp declare variant (f1) match(construct={task}) ! { dg-warning "unknown selector 'task' for context selector set 'construct' at .1." }
end subroutine
subroutine f70 ()
!$omp declare variant (f1) match(construct={taskloop}) ! { dg-error "selector 'taskloop' not allowed for context selector set 'construct' at .1." }
!$omp declare variant (f1) match(construct={taskloop}) ! { dg-warning "unknown selector 'taskloop' for context selector set 'construct' at .1." }
end subroutine
subroutine f71 ()
!$omp declare variant (f1) match(construct={sections}) ! { dg-error "selector 'sections' not allowed for context selector set 'construct' at .1." }
!$omp declare variant (f1) match(construct={sections}) ! { dg-warning "unknown selector 'sections' for context selector set 'construct' at .1." }
end subroutine
subroutine f72 ()
!$omp declare variant (f1) match(construct={section}) ! { dg-error "selector 'section' not allowed for context selector set 'construct' at .1." }
!$omp declare variant (f1) match(construct={section}) ! { dg-warning "unknown selector 'section' for context selector set 'construct' at .1." }
end subroutine
subroutine f73 ()
!$omp declare variant (f1) match(construct={workshare}) ! { dg-error "selector 'workshare' not allowed for context selector set 'construct' at .1." }
!$omp declare variant (f1) match(construct={workshare}) ! { dg-warning "unknown selector 'workshare' for context selector set 'construct' at .1." }
end subroutine
subroutine f74 ()
!$omp declare variant (f1) match(construct={requires}) ! { dg-error "selector 'requires' not allowed for context selector set 'construct' at .1." }
!$omp declare variant (f1) match(construct={requires}) ! { dg-warning "unknown selector 'requires' for context selector set 'construct' at .1." }
end subroutine
subroutine f75 ()
!$omp declare variant (f1),match(construct={parallel}) ! { dg-error "expected 'match' at .1." }
@ -189,9 +189,9 @@ contains
!$omp declare variant (f1) match(implementation={atomic_default_mem_order("relaxed")}) ! { dg-error "expected identifier at .1." }
end subroutine
subroutine f77 ()
!$omp declare variant (f1) match(user={condition(score(f76):1)}) ! { dg-error "score argument must be constant integer expression at .1." }
!$omp declare variant (f1) match(user={condition(score(f76):1)}) ! { dg-error ".score. argument must be constant integer expression at .1." }
end subroutine
subroutine f78 ()
!$omp declare variant (f1) match(user={condition(score(-130):1)}) ! { dg-error "score argument must be non-negative" }
!$omp declare variant (f1) match(user={condition(score(-130):1)}) ! { dg-error ".score. argument must be non-negative" }
end subroutine
end module

View file

@ -0,0 +1,30 @@
! { dg-do compile { target x86_64-*-* } }
! { dg-additional-options "-foffload=disable" }
program main
contains
subroutine f01 ()
end subroutine
subroutine f02 ()
!$omp declare variant (f01) &
!$omp& match (device={kind (score(5) : host)})
! { dg-error ".score. cannot be specified in traits in the .device. trait-selector-set" "" { target *-*-*} .-1 }
end subroutine
subroutine f03 ()
end subroutine
subroutine f04 ()
!$omp declare variant (f03) &
!$omp& match (device={kind (host), arch (score(6) : x86_64), isa (avx512f)})
! { dg-error ".score. cannot be specified in traits in the .device. trait-selector-set" "" { target *-*-*} .-1 }
end subroutine
subroutine f05 ()
end subroutine
subroutine f06 ()
!$omp declare variant (f05) &
!$omp& match (device={kind (host), arch (score(6) : x86_64), &
!$omp& isa (score(7): avx512f)})
! { dg-error ".score. cannot be specified in traits in the .device. trait-selector-set" "" { target *-*-*} .-2 }
end subroutine
end program