diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/c-family/c-omp.cc | 2 | ||||
-rw-r--r-- | gcc/c/c-parser.cc | 397 | ||||
-rw-r--r-- | gcc/cp/decl.cc | 86 | ||||
-rw-r--r-- | gcc/cp/parser.cc | 287 | ||||
-rw-r--r-- | gcc/cp/pt.cc | 11 | ||||
-rw-r--r-- | gcc/gimplify.cc | 162 | ||||
-rw-r--r-- | gcc/testsuite/c-c++-common/gomp/append-args-1.c | 83 | ||||
-rw-r--r-- | gcc/testsuite/c-c++-common/gomp/append-args-2.c | 8 | ||||
-rw-r--r-- | gcc/testsuite/c-c++-common/gomp/append-args-3.c | 57 | ||||
-rw-r--r-- | gcc/testsuite/c-c++-common/gomp/declare-variant-2.c | 4 | ||||
-rw-r--r-- | gcc/testsuite/c-c++-common/gomp/dispatch-11.c | 58 | ||||
-rw-r--r-- | gcc/testsuite/c-c++-common/gomp/dispatch-12.c | 20 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/gomp/append-args-1.C | 134 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/gomp/append-args-2.C | 53 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/gomp/append-args-3.C | 100 |
15 files changed, 1197 insertions, 265 deletions
diff --git a/gcc/c-family/c-omp.cc b/gcc/c-family/c-omp.cc index 7e20e5a..5f2db14 100644 --- a/gcc/c-family/c-omp.cc +++ b/gcc/c-family/c-omp.cc @@ -669,6 +669,8 @@ c_finish_omp_atomic (location_t loc, enum tree_code code, bool c_omp_interop_t_p (tree type) { + if (type == error_mark_node) + return false; type = TYPE_MAIN_VARIANT (type); return (TREE_CODE (type) == ENUMERAL_TYPE && TYPE_NAME (type) diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc index d023580..42fa383 100644 --- a/gcc/c/c-parser.cc +++ b/gcc/c/c-parser.cc @@ -20630,6 +20630,73 @@ c_parser_omp_modifier_prefer_type (c_parser *parser) return res; } +/* OpenMP 5.1 + modifiers of the 'init' clause, used by the 'init' and the + 'append_args' clauses. + + Modifiers: + target + targetsync + prefer_type (preference-specification) + + Returns 'false' if an error has been issued. */ + +static bool +c_parser_omp_clause_init_modifiers (c_parser *parser, bool *target, + bool *targetsync, tree *prefer_type_tree) +{ + *target = false; + *targetsync = false; + *prefer_type_tree = NULL_TREE; + + do + { + c_token *tok = c_parser_peek_token (parser); + if (tok->type != CPP_NAME) + goto fail; + const char *p = IDENTIFIER_POINTER (tok->value); + if (strcmp ("targetsync", p) == 0) + { + if (*targetsync) + error_at (tok->location, "duplicate %<targetsync%> modifier"); + *targetsync = true; + c_parser_consume_token (parser); + } + else if (strcmp ("target", p) == 0) + { + if (*target) + error_at (tok->location, "duplicate %<target%> modifier"); + *target = true; + c_parser_consume_token (parser); + } + else if (strcmp ("prefer_type", p) == 0) + { + if (*prefer_type_tree != NULL_TREE) + error_at (tok->location, "duplicate %<prefer_type%> modifier"); + c_parser_consume_token (parser); + *prefer_type_tree = c_parser_omp_modifier_prefer_type (parser); + if (*prefer_type_tree == error_mark_node) + return false; + } + else + goto fail; + tok = c_parser_peek_token (parser); + if (tok->type == CPP_COMMA) + { + c_parser_consume_token (parser); + continue; + } + /* Unknown token - either done or an error; handle it in the caller. */ + return true; + } + while (true); + +fail: + c_parser_error (parser, "%<init%> clause with modifier other than " + "%<prefer_type%>, %<target%> or %<targetsync%>"); + return false; +} + /* OpenMP 5.1: init ( [init-modifier-list : ] variable-list ) @@ -20647,17 +20714,17 @@ c_parser_omp_clause_init (c_parser *parser, tree list) if (!parens.require_open (parser)) return list; - unsigned pos = 0, raw_pos = 1; + unsigned raw_pos = 1; while (c_parser_peek_nth_token_raw (parser, raw_pos)->type == CPP_NAME) { - pos++; raw_pos++; + raw_pos++; if (c_parser_peek_nth_token_raw (parser, raw_pos)->type == CPP_OPEN_PAREN) { raw_pos++; c_parser_check_balanced_raw_token_sequence (parser, &raw_pos); if (c_parser_peek_nth_token_raw (parser, raw_pos)->type != CPP_CLOSE_PAREN) { - pos = 0; + raw_pos = 0; break; } raw_pos++; @@ -20666,10 +20733,9 @@ c_parser_omp_clause_init (c_parser *parser, tree list) break; if (c_parser_peek_nth_token_raw (parser, raw_pos)->type != CPP_COMMA) { - pos = 0; + raw_pos = 0; break; } - pos++; raw_pos++; } @@ -20677,57 +20743,18 @@ c_parser_omp_clause_init (c_parser *parser, tree list) bool targetsync = false; tree prefer_type_tree = NULL_TREE; - for (unsigned pos2 = 0; pos2 < pos; ++pos2) + if (raw_pos > 1 + && (!c_parser_omp_clause_init_modifiers (parser, &target, &targetsync, + &prefer_type_tree) + || !c_parser_require (parser, CPP_COLON, "expected %<:%>"))) { - c_token *tok = c_parser_peek_token (parser); - if (tok->type == CPP_COMMA) - { - c_parser_consume_token (parser); - continue; - } - - const char *p = IDENTIFIER_POINTER (tok->value); - if (strcmp ("targetsync", p) == 0) - { - if (targetsync) - error_at (tok->location, "duplicate %<targetsync%> modifier"); - targetsync = true; - c_parser_consume_token (parser); - } - else if (strcmp ("target", p) == 0) - { - if (target) - error_at (tok->location, "duplicate %<target%> modifier"); - target = true; - c_parser_consume_token (parser); - } - else if (strcmp ("prefer_type", p) == 0) - { - if (prefer_type_tree != NULL_TREE) - error_at (tok->location, "duplicate %<prefer_type%> modifier"); - c_parser_consume_token (parser); - prefer_type_tree = c_parser_omp_modifier_prefer_type (parser); - if (prefer_type_tree == error_mark_node) - return list; - } - else - { - c_parser_error (parser, "%<init%> clause with modifier other than " - "%<prefer_type%>, %<target%> or " - "%<targetsync%>"); - parens.skip_until_found_close (parser); - return list; - } - } - if (pos) - { - c_token *tok = c_parser_peek_token (parser); - gcc_checking_assert (tok->type == CPP_COLON); - c_parser_consume_token (parser); + if (prefer_type_tree != error_mark_node) + parens.skip_until_found_close (parser); + return list; } tree nl = c_parser_omp_variable_list (parser, loc, OMP_CLAUSE_INIT, list, - false); + false); parens.skip_until_found_close (parser); for (tree c = nl; c != list; c = OMP_CLAUSE_CHAIN (c)) @@ -20758,7 +20785,13 @@ static tree c_parser_omp_clause_interop (c_parser *parser, tree list) { check_no_duplicate_clause (list, OMP_CLAUSE_INTEROP, "interop"); - return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_INTEROP, list); + tree nl = c_parser_omp_var_list_parens (parser, OMP_CLAUSE_INTEROP, list); + for (tree c = nl; c != list; c = OMP_CLAUSE_CHAIN (c)) + { + TREE_USED (OMP_CLAUSE_DECL (c)) = 1; + DECL_READ_P (OMP_CLAUSE_DECL (c)) = 1; + } + return nl; } /* Parse all OpenACC clauses. The set clauses allowed by the directive @@ -26322,7 +26355,7 @@ check_clauses: OpenMP 5.1 # pragma omp declare variant (identifier) match(context-selector) \ - adjust_args(adjust-op:argument-list) new-line + adjust_args(adjust-op:argument-list) append_args(interop-list) new-line */ #define OMP_DECLARE_SIMD_CLAUSE_MASK \ @@ -26786,10 +26819,15 @@ c_finish_omp_declare_variant (c_parser *parser, tree fndecl, tree parms) parens.require_close (parser); + tree append_args_tree = NULL_TREE; + tree append_args_last; vec<tree> adjust_args_list = vNULL; bool has_match = false, has_adjust_args = false; location_t adjust_args_loc = UNKNOWN_LOCATION; - tree need_device_ptr_list = make_node (TREE_LIST); + location_t append_args_loc = UNKNOWN_LOCATION; + location_t match_loc = UNKNOWN_LOCATION; + tree need_device_ptr_list = NULL_TREE; + tree ctx = error_mark_node; do { @@ -26798,26 +26836,36 @@ c_finish_omp_declare_variant (c_parser *parser, tree fndecl, tree parms) c_parser_consume_token (parser); const char *clause = ""; - location_t match_loc = c_parser_peek_token (parser)->location; + location_t loc = c_parser_peek_token (parser)->location; if (c_parser_next_token_is (parser, CPP_NAME)) clause = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value); enum clause { match, - adjust_args + adjust_args, + append_args } ccode; if (strcmp (clause, "match") == 0) - ccode = match; + { + ccode = match; + match_loc = loc; + } else if (strcmp (clause, "adjust_args") == 0) { ccode = adjust_args; - adjust_args_loc = match_loc; + adjust_args_loc = loc; + } + else if (strcmp (clause, "append_args") == 0) + { + ccode = append_args; + append_args_loc = loc; } else { - c_parser_error (parser, "expected %<match%> clause"); + c_parser_error (parser, "expected %<match%>, %<adjust_args%> or " + "%<append_args%> clause"); goto fail; } @@ -26834,8 +26882,7 @@ c_finish_omp_declare_variant (c_parser *parser, tree fndecl, tree parms) if (has_match) error_at (match_loc, "too many %<match%> clauses"); has_match = true; - tree ctx - = c_parser_omp_context_selector_specification (parser, parms); + ctx = c_parser_omp_context_selector_specification (parser, parms); if (ctx == error_mark_node) goto fail; ctx = omp_check_context_selector (match_loc, ctx); @@ -26862,40 +26909,6 @@ c_finish_omp_declare_variant (c_parser *parser, tree fndecl, tree parms) variant); variant = error_mark_node; } - else if (!omp_get_context_selector (ctx, OMP_TRAIT_SET_CONSTRUCT, - OMP_TRAIT_CONSTRUCT_SIMD)) - { - if (comptypes (TREE_TYPE (fndecl), TREE_TYPE (variant))) - { - if (TYPE_ARG_TYPES (TREE_TYPE (variant)) == NULL_TREE) - TYPE_ARG_TYPES (TREE_TYPE (variant)) - = TYPE_ARG_TYPES (TREE_TYPE (fndecl)); - } - else - { - error_at (token->location, - "variant %qD and base %qD have " - "incompatible types", - variant, fndecl); - variant = error_mark_node; - } - } - if (variant != error_mark_node) - { - C_DECL_USED (variant) = 1; - 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)) - { - tree attr = tree_cons (get_identifier ( - "omp declare variant base"), - build_tree_list (variant, ctx), - DECL_ATTRIBUTES (fndecl)); - DECL_ATTRIBUTES (fndecl) = attr; - } - } } } else if (ccode == adjust_args) @@ -26912,7 +26925,7 @@ c_finish_omp_declare_variant (c_parser *parser, tree fndecl, tree parms) c_parser_consume_token (parser); // need_device_ptr c_parser_consume_token (parser); // : - location_t loc = c_parser_peek_token (parser)->location; + loc = c_parser_peek_token (parser)->location; tree list = c_parser_omp_variable_list (parser, loc, OMP_CLAUSE_ERROR, NULL_TREE); @@ -26978,19 +26991,180 @@ c_finish_omp_declare_variant (c_parser *parser, tree fndecl, tree parms) goto fail; } } + else if (ccode == append_args) + { + if (append_args_tree) + error_at (append_args_loc, "too many %qs clauses", "append_args"); + do + { + location_t loc = c_parser_peek_token (parser)->location; + if (!c_parser_next_token_is (parser, CPP_NAME) + || strcmp ("interop", + IDENTIFIER_POINTER ( + c_parser_peek_token (parser)->value))) + { + error_at (loc, "expected %<interop%>"); + goto fail; + } + c_parser_consume_token (parser); + + if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + goto fail; + bool target = false; + bool targetsync = false; + tree prefer_type_tree = NULL_TREE; + if (!c_parser_omp_clause_init_modifiers (parser, &target, + &targetsync, + &prefer_type_tree) + || !c_parser_require (parser, CPP_CLOSE_PAREN, + "expected %<)%> or %<,%>")) + goto fail; + tree t = build_omp_clause (loc, OMP_CLAUSE_INIT); + if (append_args_tree) + OMP_CLAUSE_CHAIN (append_args_last) = t; + else + append_args_tree = append_args_last = t; + if (target) + OMP_CLAUSE_INIT_TARGET (t) = 1; + if (targetsync) + OMP_CLAUSE_INIT_TARGETSYNC (t) = 1; + if (prefer_type_tree) + OMP_CLAUSE_INIT_PREFER_TYPE (t) = prefer_type_tree; + if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN)) + break; + if (!c_parser_require (parser, CPP_COMMA, "expected %<)%> or %<,%>")) + goto fail; + } + while (true); + } parens.require_close (parser); } while (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL)); c_parser_skip_to_pragma_eol (parser); - if (has_adjust_args) + if ((ctx != error_mark_node && variant != error_mark_node) + && !omp_get_context_selector (ctx, OMP_TRAIT_SET_CONSTRUCT, + OMP_TRAIT_CONSTRUCT_SIMD)) + { + bool fail = false; + if (append_args_tree + && TYPE_ARG_TYPES (TREE_TYPE (fndecl)) != NULL_TREE + && TYPE_ARG_TYPES (TREE_TYPE (variant)) != NULL_TREE) + { + int nappend_args = 0; + int nbase_args = 0; + for (tree t = TYPE_ARG_TYPES (TREE_TYPE (fndecl)); + t && TREE_VALUE (t) != void_type_node; t = TREE_CHAIN (t)) + nbase_args++; + for (tree t = append_args_tree; t; t = TREE_CHAIN (t)) + nappend_args++; + + tree args, arg; + args = arg = TYPE_ARG_TYPES (TREE_TYPE (variant)); + for (int j = 0; j < nbase_args && arg; j++, arg = TREE_CHAIN (arg)) + args = arg; + for (int i = 0; i < nappend_args && arg; i++) + arg = TREE_CHAIN (arg); + tree saved_args; + if (nbase_args) + { + saved_args = TREE_CHAIN (args); + TREE_CHAIN (args) = arg; + } + else + { + saved_args = args; + TYPE_ARG_TYPES (TREE_TYPE (variant)) = arg; + } + if (!comptypes (TREE_TYPE (fndecl), TREE_TYPE (variant))) + fail = true; + if (nbase_args) + TREE_CHAIN (args) = saved_args; + else + TYPE_ARG_TYPES (TREE_TYPE (variant)) = saved_args; + arg = saved_args; + if (!fail) + for (int i = 0; i < nappend_args; i++, arg = TREE_CHAIN (arg)) + if (!arg || !c_omp_interop_t_p (TREE_VALUE (arg))) + { + error_at (DECL_SOURCE_LOCATION (variant), + "argument %d of %qD must be of %<omp_interop_t%>", + nbase_args + i + 1, variant); + inform (append_args_loc, "%<append_args%> specified here"); + break; + } + } + else + { + if (comptypes (TREE_TYPE (fndecl), TREE_TYPE (variant))) + { + if (TYPE_ARG_TYPES (TREE_TYPE (variant)) == NULL_TREE + && TYPE_ARG_TYPES (TREE_TYPE (fndecl)) != NULL_TREE) + { + if (!append_args_tree) + TYPE_ARG_TYPES (TREE_TYPE (variant)) + = TYPE_ARG_TYPES (TREE_TYPE (fndecl)); + else + { + tree new_args = NULL_TREE; + tree arg, last_arg = NULL_TREE; + for (arg = TYPE_ARG_TYPES (TREE_TYPE (fndecl)); + arg && arg != void_type_node; arg = TREE_CHAIN (arg)) + { + if (new_args == NULL_TREE) + new_args = last_arg = copy_node (arg); + else + { + TREE_CHAIN (last_arg) = copy_node (arg); + last_arg = TREE_CHAIN (last_arg); + } + } + for (tree t3 = append_args_tree; t3; t3 = TREE_CHAIN (t3)) + { + tree type = lookup_name (get_identifier ("omp_interop_t")); + type = type ? TREE_TYPE (type) : ptr_type_node; + last_arg = tree_cons (NULL_TREE, type, last_arg); + } + TREE_CHAIN (last_arg) = arg; + TYPE_ARG_TYPES (TREE_TYPE (variant)) = new_args; + } + } + } + else + fail = true; + } + if (fail) + { + error_at (token->location, + "variant %qD and base %qD have incompatible types", + variant, fndecl); + variant = error_mark_node; + } + } + if (ctx != error_mark_node && variant != error_mark_node) + { + C_DECL_USED (variant) = 1; + 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)) + { + tree attr = tree_cons (get_identifier ("omp declare variant base"), + build_tree_list (variant, ctx), + DECL_ATTRIBUTES (fndecl)); + DECL_ATTRIBUTES (fndecl) = attr; + } + } + + if (has_adjust_args || append_args_tree) { if (!has_match) { - error_at (adjust_args_loc, - "an %<adjust_args%> clause requires a %<match%> clause"); + error_at (has_adjust_args ? adjust_args_loc : append_args_loc, + "an %qs clause requires a %<match%> clause", + has_adjust_args ? "adjust_args" : "append_args"); } - else + else if (ctx != error_mark_node && variant != error_mark_node) { tree attr = lookup_attribute ("omp declare variant base", DECL_ATTRIBUTES (fndecl)); @@ -26999,23 +27173,24 @@ c_finish_omp_declare_variant (c_parser *parser, tree fndecl, tree parms) tree ctx = TREE_VALUE (TREE_VALUE (attr)); if (!omp_get_context_selector (ctx, OMP_TRAIT_SET_CONSTRUCT, OMP_TRAIT_CONSTRUCT_DISPATCH)) - error_at ( - adjust_args_loc, - "an %<adjust_args%> clause can only be specified if the " - "%<dispatch%> selector of the %<construct%> selector set " - "appears in the %<match%> clause"); + error_at (has_adjust_args ? adjust_args_loc : append_args_loc, + "an %qs clause can only be specified if the " + "%<dispatch%> selector of the %<construct%> selector " + "set appears in the %<match%> clause", + has_adjust_args ? "adjust_args" : "append_args"); } } } - if (TREE_CHAIN (need_device_ptr_list) != NULL_TREE - && variant != error_mark_node) + if ((ctx != error_mark_node && variant != error_mark_node) + && (need_device_ptr_list || append_args_tree)) { tree variant_decl = tree_strip_nop_conversions (variant); + tree t = build_tree_list (need_device_ptr_list, + NULL_TREE /* need_device_addr */); + TREE_CHAIN (t) = append_args_tree; DECL_ATTRIBUTES (variant_decl) - = tree_cons (get_identifier ("omp declare variant variant adjust_args"), - build_tree_list (need_device_ptr_list, - NULL_TREE /*need_device_addr */), + = tree_cons (get_identifier ("omp declare variant variant args"), t, DECL_ATTRIBUTES (variant_decl)); } } diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc index 2716ac5..9d25134 100644 --- a/gcc/cp/decl.cc +++ b/gcc/cp/decl.cc @@ -8473,6 +8473,39 @@ omp_declare_variant_finalize_one (tree decl, tree attr) else vec_safe_push (args, build_zero_cst (TREE_TYPE (parm))); + unsigned nappend_args = 0; + tree append_args_list = TREE_CHAIN (TREE_CHAIN (chain)); + if (append_args_list) + { + append_args_list = TREE_VALUE (append_args_list); + if (append_args_list) + append_args_list = TREE_CHAIN (append_args_list); + for (tree t = append_args_list; t; t = TREE_CHAIN (t)) + nappend_args++; + if (nappend_args) + { + tree type; + if ((type = lookup_qualified_name (current_scope (), + "omp_interop_t", + LOOK_want::NORMAL, + /*complain*/false)) == NULL_TREE + || !c_omp_interop_t_p (TREE_TYPE (type))) + { + variant = tree_strip_any_location_wrapper (variant); + if (TREE_CODE (variant) == OVERLOAD && OVL_SINGLE_P (variant)) + variant = OVL_FIRST (variant); + error_at (EXPR_LOC_OR_LOC (variant, DECL_SOURCE_LOCATION (variant)), + "argument %d of %qE must be of %<omp_interop_t%>", + args->length () + 1, variant); + inform (OMP_CLAUSE_LOCATION (append_args_list), + "%<append_args%> specified here"); + return true; + } + for (unsigned i = 0; i < nappend_args; i++) + vec_safe_push (args, build_zero_cst (TREE_TYPE (type))); + } + } + bool koenig_p = false; if (idk == CP_ID_KIND_UNQUALIFIED || idk == CP_ID_KIND_TEMPLATE_ID) { @@ -8522,8 +8555,57 @@ omp_declare_variant_finalize_one (tree decl, tree attr) if (variant) { + bool fail; const char *varname = IDENTIFIER_POINTER (DECL_NAME (variant)); - if (!comptypes (TREE_TYPE (decl), TREE_TYPE (variant), 0)) + if (!nappend_args) + fail = !comptypes (TREE_TYPE (decl), TREE_TYPE (variant), + COMPARE_STRICT); + else + { + unsigned nbase_args = 0; + for (tree t = TYPE_ARG_TYPES (TREE_TYPE (decl)); + t && TREE_VALUE (t) != void_type_node; t = TREE_CHAIN (t)) + nbase_args++; + tree vargs, varg; + vargs = varg = TYPE_ARG_TYPES (TREE_TYPE (variant)); + for (unsigned i = 0; i < nbase_args && varg; + i++, varg = TREE_CHAIN (varg)) + vargs = varg; + for (unsigned i = 0; i < nappend_args && varg; i++) + varg = TREE_CHAIN (varg); + tree saved_vargs; + if (nbase_args) + { + saved_vargs = TREE_CHAIN (vargs); + TREE_CHAIN (vargs) = varg; + } + else + { + saved_vargs = vargs; + TYPE_ARG_TYPES (TREE_TYPE (variant)) = varg; + } + /* Skip assert check that TYPE_CANONICAL is the same. */ + fail = !comptypes (TREE_TYPE (decl), TREE_TYPE (variant), + COMPARE_STRUCTURAL); + if (nbase_args) + TREE_CHAIN (vargs) = saved_vargs; + else + TYPE_ARG_TYPES (TREE_TYPE (variant)) = saved_vargs; + varg = saved_vargs; + if (!fail && !processing_template_decl) + for (unsigned i = 0; i < nappend_args; + i++, varg = TREE_CHAIN (varg)) + if (!varg || !c_omp_interop_t_p (TREE_VALUE (varg))) + { + error_at (DECL_SOURCE_LOCATION (variant), + "argument %d of %qD must be of %<omp_interop_t%>", + nbase_args + i + 1, variant); + inform (OMP_CLAUSE_LOCATION (append_args_list), + "%<append_args%> specified here"); + break; + } + } + if (fail) { error_at (varid_loc, "variant %qD and base %qD have incompatible " "types", variant, decl); @@ -8550,7 +8632,7 @@ omp_declare_variant_finalize_one (tree decl, tree attr) tree adjust_args_list = TREE_CHAIN (TREE_CHAIN (chain)); if (adjust_args_list != NULL_TREE) DECL_ATTRIBUTES (variant) = tree_cons ( - get_identifier ("omp declare variant variant adjust_args"), + get_identifier ("omp declare variant variant args"), TREE_VALUE (adjust_args_list), DECL_ATTRIBUTES (variant)); } } diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc index 4697450..3fcaa1f 100644 --- a/gcc/cp/parser.cc +++ b/gcc/cp/parser.cc @@ -42427,6 +42427,23 @@ cp_parser_omp_clause_proc_bind (cp_parser *parser, tree list, return list; } +/* OpenMP 5.1: + interop (var-list) */ + +static tree +cp_parser_omp_clause_interop (cp_parser *parser, tree list, + location_t location) +{ + check_no_duplicate_clause (list, OMP_CLAUSE_INTEROP, "interop", location); + tree nl = cp_parser_omp_var_list (parser, OMP_CLAUSE_INTEROP, list); + for (tree c = nl; c != list; c = OMP_CLAUSE_CHAIN (c)) + { + TREE_USED (OMP_CLAUSE_DECL (c)) = 1; + DECL_READ_P (OMP_CLAUSE_DECL (c)) = 1; + } + return nl; +} + /* OpenMP 5.0: device_type ( host | nohost | any ) */ @@ -42781,6 +42798,73 @@ cp_parser_omp_modifier_prefer_type (cp_parser *parser) return res; } +/* OpenMP 5.1 + modifiers of the 'init' clause, used by the 'init' and the + 'append_args' clauses. + + Modifiers: + target + targetsync + prefer_type (preference-specification) + + Returns 'false' if an error has been issued. */ + +static bool +cp_parser_omp_clause_init_modifiers (cp_parser *parser, bool *target, + bool *targetsync, tree *prefer_type_tree) +{ + *target = false; + *targetsync = false; + *prefer_type_tree = NULL_TREE; + + do + { + cp_token *tok = cp_lexer_peek_token (parser->lexer); + if (tok->type != CPP_NAME) + goto fail; + const char *p = IDENTIFIER_POINTER (tok->u.value); + if (strcmp ("targetsync", p) == 0) + { + if (*targetsync) + error_at (tok->location, "duplicate %<targetsync%> modifier"); + *targetsync = true; + cp_lexer_consume_token (parser->lexer); + } + else if (strcmp ("target", p) == 0) + { + if (*target) + error_at (tok->location, "duplicate %<target%> modifier"); + *target = true; + cp_lexer_consume_token (parser->lexer); + } + else if (strcmp ("prefer_type", p) == 0) + { + if (*prefer_type_tree != NULL_TREE) + error_at (tok->location, "duplicate %<prefer_type%> modifier"); + cp_lexer_consume_token (parser->lexer); + *prefer_type_tree = cp_parser_omp_modifier_prefer_type (parser); + if (*prefer_type_tree == error_mark_node) + return false; + } + else + goto fail; + tok = cp_lexer_peek_token (parser->lexer); + if (tok->type == CPP_COMMA) + { + cp_lexer_consume_token (parser->lexer); + continue; + } + /* Unknown token - either done or an error; handle it in the caller. */ + return true; + } + while (true); + +fail: + cp_parser_error (parser, "%<init%> clause with modifier other than " + "%<prefer_type%>, %<target%> or %<targetsync%>"); + return false; +} + /* OpenMP 5.1: init ( [init-modifier-list : ] variable-list ) @@ -42795,17 +42879,17 @@ cp_parser_omp_clause_init (cp_parser *parser, tree list) if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN)) return list; - unsigned pos = 0, raw_pos = 1; + unsigned raw_pos = 1; while (cp_lexer_peek_nth_token (parser->lexer, raw_pos)->type == CPP_NAME) { - pos++; raw_pos++; + raw_pos++; if (cp_lexer_peek_nth_token (parser->lexer, raw_pos)->type == CPP_OPEN_PAREN) { unsigned n = cp_parser_skip_balanced_tokens (parser, raw_pos); if (n == raw_pos) { - pos = 0; + raw_pos = 0; break; } raw_pos = n; @@ -42814,10 +42898,9 @@ cp_parser_omp_clause_init (cp_parser *parser, tree list) break; if (cp_lexer_peek_nth_token (parser->lexer, raw_pos)->type != CPP_COMMA) { - pos = 0; + raw_pos = 0; break; } - pos++; raw_pos++; } @@ -42825,54 +42908,17 @@ cp_parser_omp_clause_init (cp_parser *parser, tree list) bool targetsync = false; tree prefer_type_tree = NULL_TREE; - for (unsigned pos2 = 0; pos2 < pos; ++pos2) + if (raw_pos > 1 + && (!cp_parser_omp_clause_init_modifiers (parser, &target, &targetsync, + &prefer_type_tree) + || !cp_parser_require (parser, CPP_COLON, RT_COLON))) { - cp_token *tok = cp_lexer_peek_token (parser->lexer); - if (tok->type == CPP_COMMA) - { - cp_lexer_consume_token (parser->lexer); - continue; - } - const char *p = IDENTIFIER_POINTER (tok->u.value); - if (strcmp ("targetsync", p) == 0) - { - if (targetsync) - error_at (tok->location, "duplicate %<targetsync%> modifier"); - targetsync = true; - cp_lexer_consume_token (parser->lexer); - } - else if (strcmp ("target", p) == 0) - { - if (target) - error_at (tok->location, "duplicate %<target%> modifier"); - target = true; - cp_lexer_consume_token (parser->lexer); - } - else if (strcmp ("prefer_type", p) == 0) - { - if (prefer_type_tree != NULL_TREE) - error_at (tok->location, "duplicate %<prefer_type%> modifier"); - cp_lexer_consume_token (parser->lexer); - prefer_type_tree = cp_parser_omp_modifier_prefer_type (parser); - if (prefer_type_tree == error_mark_node) - return error_mark_node; - } - else - { - cp_parser_error (parser, "%<init%> clause with modifier other than " - "%<prefer_type%>, %<target%> or " - "%<targetsync%>"); - cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, - /*or_comma=*/false, - /*consume_paren=*/true); - return list; - } - } - if (pos) - { - gcc_checking_assert (cp_lexer_peek_token (parser->lexer)->type - == CPP_COLON); - cp_lexer_consume_token (parser->lexer); + if (prefer_type_tree == error_mark_node) + return error_mark_node; + cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, + /*or_comma=*/false, + /*consume_paren=*/true); + return list; } tree nl = cp_parser_omp_var_list_no_open (parser, OMP_CLAUSE_INIT, list, @@ -42880,11 +42926,11 @@ cp_parser_omp_clause_init (cp_parser *parser, tree list) for (tree c = nl; c != list; c = OMP_CLAUSE_CHAIN (c)) { if (target) - OMP_CLAUSE_INIT_TARGET (c) = 1; + OMP_CLAUSE_INIT_TARGET (c) = 1; if (targetsync) - OMP_CLAUSE_INIT_TARGETSYNC (c) = 1; + OMP_CLAUSE_INIT_TARGETSYNC (c) = 1; if (prefer_type_tree) - OMP_CLAUSE_INIT_PREFER_TYPE (c) = prefer_type_tree; + OMP_CLAUSE_INIT_PREFER_TYPE (c) = prefer_type_tree; } return nl; } @@ -43536,10 +43582,8 @@ cp_parser_omp_all_clauses (cp_parser *parser, omp_clause_mask mask, c_name = "use"; break; case PRAGMA_OMP_CLAUSE_INTEROP: - check_no_duplicate_clause (clauses, OMP_CLAUSE_INTEROP, "interop", - token->location); - clauses = cp_parser_omp_var_list (parser, OMP_CLAUSE_INTEROP, - clauses); + clauses = cp_parser_omp_clause_interop (parser, clauses, + token->location); c_name = "interop"; break; case PRAGMA_OMP_CLAUSE_DETACH: @@ -50086,10 +50130,14 @@ cp_finish_omp_declare_variant (cp_parser *parser, cp_token *pragma_tok, location_t finish_loc = get_finish (varid.get_location ()); location_t varid_loc = make_location (caret_loc, start_loc, finish_loc); + tree append_args_tree = NULL_TREE; + tree append_args_last; vec<tree> adjust_args_list = vNULL; bool has_match = false, has_adjust_args = false; location_t adjust_args_loc = UNKNOWN_LOCATION; - tree need_device_ptr_list = make_node (TREE_LIST); + location_t append_args_loc = UNKNOWN_LOCATION; + tree need_device_ptr_list = NULL_TREE; + tree ctx = NULL_TREE; do { @@ -50106,7 +50154,8 @@ cp_finish_omp_declare_variant (cp_parser *parser, cp_token *pragma_tok, enum clause { match, - adjust_args + adjust_args, + append_args } ccode; if (strcmp (clause, "match") == 0) @@ -50116,9 +50165,15 @@ cp_finish_omp_declare_variant (cp_parser *parser, cp_token *pragma_tok, ccode = adjust_args; adjust_args_loc = match_loc; } + else if (strcmp (clause, "append_args") == 0) + { + ccode = append_args; + append_args_loc = match_loc; + } else { - cp_parser_error (parser, "expected %<match%> clause"); + cp_parser_error (parser, "expected %<match%>, %<adjust_args%> or " + "%<append_args%> clause"); goto fail; } @@ -50132,8 +50187,7 @@ cp_finish_omp_declare_variant (cp_parser *parser, cp_token *pragma_tok, if (has_match) error_at (match_loc, "too many %<match%> clauses"); has_match = true; - tree ctx - = cp_parser_omp_context_selector_specification (parser, true); + ctx = cp_parser_omp_context_selector_specification (parser, true); if (ctx == error_mark_node) goto fail; ctx = omp_check_context_selector (match_loc, ctx); @@ -50239,40 +50293,95 @@ cp_finish_omp_declare_variant (cp_parser *parser, cp_token *pragma_tok, goto fail; } } + else if (ccode == append_args) + { + if (append_args_tree) + error_at (append_args_loc, "too many %qs clauses", "append_args"); + do + { + location_t loc = cp_lexer_peek_token (parser->lexer)->location; + if (!cp_lexer_next_token_is (parser->lexer, CPP_NAME) + || strcmp ("interop", + IDENTIFIER_POINTER ( + cp_lexer_peek_token (parser->lexer)->u.value))) + { + error_at (loc, "expected %<interop%>"); + goto fail; + } + cp_lexer_consume_token (parser->lexer); // : + + if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN)) + goto fail; + bool target = false; + bool targetsync = false; + tree prefer_type_tree = NULL_TREE; + if (!cp_parser_omp_clause_init_modifiers (parser, &target, + &targetsync, + &prefer_type_tree)) + goto fail; + tree t = build_omp_clause (loc, OMP_CLAUSE_INIT); + if (append_args_tree) + OMP_CLAUSE_CHAIN (append_args_last) = t; + else + append_args_tree = append_args_last = t; + if (target) + OMP_CLAUSE_INIT_TARGET (t) = 1; + if (targetsync) + OMP_CLAUSE_INIT_TARGETSYNC (t) = 1; + if (prefer_type_tree) + OMP_CLAUSE_INIT_PREFER_TYPE (t) = prefer_type_tree; + if (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_PAREN)) + { + cp_parser_error (parser, "expected %<)%> or %<,%>"); + goto fail; + } + cp_lexer_consume_token (parser->lexer); // ')' + if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_PAREN)) + { + cp_lexer_consume_token (parser->lexer); // ',' + break; + } + if (cp_lexer_next_token_is_not (parser->lexer, CPP_COMMA)) + { + cp_parser_error (parser, "expected %<)%> or %<,%>"); + goto fail; + } + cp_lexer_consume_token (parser->lexer); // ',' + } + while (true); + } } while (cp_lexer_next_token_is_not (parser->lexer, CPP_PRAGMA_EOL)); - if (has_adjust_args) + if ((ctx != error_mark_node && variant != error_mark_node) + && (has_adjust_args || append_args_tree)) { if (!has_match) { - error_at (adjust_args_loc, - "an %<adjust_args%> clause requires a %<match%> clause"); + error_at (has_adjust_args ? adjust_args_loc : append_args_loc, + "an %qs clause requires a %<match%> clause", + has_adjust_args ? "adjust_args" : "append_args"); } else { - tree ctx = TREE_VALUE (TREE_VALUE (attrs)); + gcc_assert (TREE_PURPOSE (attrs) + == get_identifier ("omp declare variant base")); + gcc_assert (TREE_PURPOSE (TREE_VALUE (attrs)) == variant); + ctx = TREE_VALUE (TREE_VALUE (attrs)); if (!omp_get_context_selector (ctx, OMP_TRAIT_SET_CONSTRUCT, OMP_TRAIT_CONSTRUCT_DISPATCH)) - error_at ( - adjust_args_loc, - "an %<adjust_args%> clause can only be specified if the " - "%<dispatch%> selector of the construct selector set appears " - "in the %<match%> clause"); - else if (TREE_CHAIN (need_device_ptr_list) != NULL_TREE) - { - // We might not have a DECL for the variant yet. So we store the - // need_device_ptr list in the base function attribute, after loc - // nodes. - gcc_assert (TREE_PURPOSE (attrs) - == get_identifier ("omp declare variant base")); - gcc_assert (TREE_PURPOSE (TREE_VALUE (attrs)) == variant); - TREE_VALUE (attrs) = chainon ( - TREE_VALUE (attrs), - build_tree_list ( - NULL_TREE, - build_tree_list (need_device_ptr_list, - NULL_TREE /*need_device_addr */))); - } + error_at (has_adjust_args ? adjust_args_loc : append_args_loc, + "an %qs clause can only be specified if the %<dispatch%> " + "selector of the construct selector set appears " + "in the %<match%> clause", + has_adjust_args ? "adjust_args" : "append_args"); + // We might not have a DECL for the variant yet. So we store the + // need_device_ptr list in the base function attribute, after loc + // nodes. + tree t = build_tree_list (need_device_ptr_list, + NULL_TREE /* need_device_addr */); + TREE_CHAIN (t) = append_args_tree; + TREE_VALUE (attrs) = chainon (TREE_VALUE (attrs), + build_tree_list ( NULL_TREE, t)); } } @@ -51319,7 +51428,7 @@ cp_parser_omp_declare_reduction (cp_parser *parser, cp_token *pragma_tok, OpenMP 5.1 #pragma omp declare variant (identifier) match (context-selector) \ - adjust_args (adjust-op:argument-list) */ + adjust_args (adjust-op:argument-list) append_args(interop-list) */ static bool cp_parser_omp_declare (cp_parser *parser, cp_token *pragma_tok, diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc index 8a91c9c..648ecea 100644 --- a/gcc/cp/pt.cc +++ b/gcc/cp/pt.cc @@ -12094,6 +12094,15 @@ 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 append_args_list = TREE_CHAIN (TREE_CHAIN (chain)); + if (append_args_list) + { + append_args_list = TREE_VALUE (append_args_list); + if (append_args_list) + TREE_CHAIN (append_args_list) + = tsubst_omp_clauses (TREE_CHAIN (append_args_list), + C_ORT_OMP_DECLARE_SIMD, args, complain, in_decl); + } for (tree tss = ctx; tss; tss = TREE_CHAIN (tss)) { enum omp_tss_code set = OMP_TSS_CODE (tss); @@ -17916,7 +17925,7 @@ tsubst_omp_clauses (tree clauses, enum c_omp_region_type ort, complain, in_decl); break; case OMP_CLAUSE_INIT: - if (ort == C_ORT_OMP_INTEROP + if ((ort == C_ORT_OMP_INTEROP || ort == C_ORT_OMP_DECLARE_SIMD) && OMP_CLAUSE_INIT_PREFER_TYPE (nc) && TREE_CODE (OMP_CLAUSE_INIT_PREFER_TYPE (nc)) == TREE_LIST && (OMP_CLAUSE_CHAIN (nc) == NULL_TREE diff --git a/gcc/gimplify.cc b/gcc/gimplify.cc index bf1c590..b1ef23b 100644 --- a/gcc/gimplify.cc +++ b/gcc/gimplify.cc @@ -4096,24 +4096,126 @@ gimplify_call_expr (tree *expr_p, gimple_seq *pre_p, bool want_value) vars there. */ bool returns_twice = call_expr_flags (*expr_p) & ECF_RETURNS_TWICE; + tree dispatch_device_num = NULL_TREE; tree dispatch_interop = NULL_TREE; + tree dispatch_append_args = NULL_TREE; + tree dispatch_adjust_args_list = NULL_TREE; if (flag_openmp && gimplify_omp_ctxp != NULL && gimplify_omp_ctxp->code == OMP_DISPATCH - && gimplify_omp_ctxp->clauses - && (dispatch_interop = omp_find_clause (gimplify_omp_ctxp->clauses, - OMP_CLAUSE_INTEROP)) != NULL_TREE) - /* FIXME: When implementing 'append_args, use the 'device_num' of - the argument. */ - error_at (OMP_CLAUSE_LOCATION (dispatch_interop), - "number of list items in %<interop%> clause exceeds number of " - "%<append_args%> items for %<declare variant%> candidate %qD", - fndecl); + && !gimplify_omp_ctxp->in_call_args + && EXPR_P (CALL_EXPR_FN (*expr_p)) + && DECL_P (TREE_OPERAND (CALL_EXPR_FN (*expr_p), 0))) + { + tree fndecl = TREE_OPERAND (CALL_EXPR_FN (*expr_p), 0); + dispatch_adjust_args_list + = lookup_attribute ("omp declare variant variant args", + DECL_ATTRIBUTES (fndecl)); + if (dispatch_adjust_args_list) + { + dispatch_adjust_args_list = TREE_VALUE (dispatch_adjust_args_list); + dispatch_append_args = TREE_CHAIN (dispatch_adjust_args_list); + if (TREE_PURPOSE (dispatch_adjust_args_list) == NULL_TREE + && TREE_VALUE (dispatch_adjust_args_list) == NULL_TREE) + dispatch_adjust_args_list = NULL_TREE; + } + dispatch_device_num = omp_find_clause (gimplify_omp_ctxp->clauses, + OMP_CLAUSE_DEVICE); + if (dispatch_device_num) + dispatch_device_num = OMP_CLAUSE_DEVICE_ID (dispatch_device_num); + if (gimplify_omp_ctxp->clauses) + dispatch_interop = omp_find_clause (gimplify_omp_ctxp->clauses, + OMP_CLAUSE_INTEROP); + /* Already processed? */ + if (dispatch_interop + && OMP_CLAUSE_DECL (dispatch_interop) == NULL_TREE) + dispatch_interop = dispatch_append_args = NULL_TREE; + + int nappend = 0, ninterop = 0; + for (tree t = dispatch_append_args; t; t = TREE_CHAIN (t)) + nappend++; + if (dispatch_interop) + { + for (tree t = dispatch_interop; t; t = TREE_CHAIN (t)) + if (OMP_CLAUSE_CODE (t) == OMP_CLAUSE_INTEROP) + ninterop++; + if (nappend < ninterop) + { + error_at (OMP_CLAUSE_LOCATION (dispatch_interop), + "number of list items in %<interop%> clause (%d) " + "exceeds the number of %<append_args%> items (%d) for " + "%<declare variant%> candidate %qD", + ninterop, nappend, fndecl); + inform (dispatch_append_args + ? OMP_CLAUSE_LOCATION (dispatch_append_args) + : DECL_SOURCE_LOCATION (fndecl), + "%<declare variant%> candidate %qD declared here", + fndecl); + } + /* FIXME: obtain the device_number from 1st 'interop' clause item. */ + } + if (dispatch_append_args && (nappend != ninterop || !dispatch_device_num)) + { + sorry_at (OMP_CLAUSE_LOCATION (dispatch_append_args), + "%<append_args%> clause not yet supported for %qD", fndecl); + inform (gimplify_omp_ctxp->location, + "required by %<dispatch%> construct"); + } + else if (dispatch_append_args) + { + // Append interop objects + int last_arg = 0; + for (tree t = TYPE_ARG_TYPES (TREE_TYPE (fndecl)); + t && TREE_VALUE(t) != void_type_node; t = TREE_CHAIN (t)) + last_arg++; + last_arg = last_arg - nappend; + + int nvariadic = nargs - last_arg; + nargs = last_arg + nappend + nvariadic; + tree *buffer = XALLOCAVEC (tree, nargs); + int i; + for (i = 0; i < last_arg; i++) + buffer[i] = CALL_EXPR_ARG (*expr_p, i); + int j = nappend; + for (tree t = dispatch_interop; + t; t = TREE_CHAIN (t)) + if (OMP_CLAUSE_CODE (t) == OMP_CLAUSE_INTEROP) + buffer[i + --j] = OMP_CLAUSE_DECL (t); + i += nappend; + for (j = last_arg; j < last_arg + nvariadic; j++) + buffer[i++] = CALL_EXPR_ARG (*expr_p, j); + tree call = *expr_p; + *expr_p = build_call_array_loc (loc, TREE_TYPE (call), + CALL_EXPR_FN (call), + nargs, buffer); + + /* Copy all CALL_EXPR flags. */ + CALL_EXPR_STATIC_CHAIN (*expr_p) = CALL_EXPR_STATIC_CHAIN (call); + CALL_EXPR_TAILCALL (*expr_p) = CALL_EXPR_TAILCALL (call); + CALL_EXPR_RETURN_SLOT_OPT (*expr_p) + = CALL_EXPR_RETURN_SLOT_OPT (call); + CALL_FROM_THUNK_P (*expr_p) = CALL_FROM_THUNK_P (call); + SET_EXPR_LOCATION (*expr_p, EXPR_LOCATION (call)); + CALL_EXPR_VA_ARG_PACK (*expr_p) = CALL_EXPR_VA_ARG_PACK (call); + + /* Mark as already processed. */ + if (dispatch_interop) + OMP_CLAUSE_DECL (dispatch_interop) = NULL_TREE; + else + { + tree t = build_omp_clause (loc, OMP_CLAUSE_INTEROP); + TREE_CHAIN (t) = gimplify_omp_ctxp->clauses; + gimplify_omp_ctxp->clauses = t; + } + + /* Re-run. */ + return GS_OK; + } + } /* Gimplify the function arguments. */ if (nargs > 0) { - tree device_num = NULL_TREE; for (i = (PUSH_ARGS_REVERSED ? nargs - 1 : 0); PUSH_ARGS_REVERSED ? i >= 0 : i < nargs; PUSH_ARGS_REVERSED ? i-- : i++) @@ -4125,18 +4227,7 @@ gimplify_call_expr (tree *expr_p, gimple_seq *pre_p, bool want_value) if ((i != 1) || !builtin_va_start_p) { tree *arg_p = &CALL_EXPR_ARG (*expr_p, i); - tree adjust_args_list; - if (flag_openmp && gimplify_omp_ctxp != NULL - && gimplify_omp_ctxp->code == OMP_DISPATCH - && !gimplify_omp_ctxp->in_call_args - && !integer_zerop (*arg_p) - && EXPR_P (CALL_EXPR_FN (*expr_p)) - && DECL_P (TREE_OPERAND (CALL_EXPR_FN (*expr_p), 0)) - && (adjust_args_list = lookup_attribute ( - "omp declare variant variant adjust_args", - DECL_ATTRIBUTES ( - TREE_OPERAND (CALL_EXPR_FN (*expr_p), 0)))) - != NULL_TREE) + if (dispatch_adjust_args_list && !integer_zerop (*arg_p)) { tree arg_types = TYPE_ARG_TYPES ( TREE_TYPE (TREE_OPERAND (CALL_EXPR_FN (*expr_p), 0))); @@ -4150,10 +4241,10 @@ gimplify_call_expr (tree *expr_p, gimple_seq *pre_p, bool want_value) bool need_device_addr = false; for (int need_addr = 0; need_addr <= 1; need_addr++) for (tree arg = need_addr - ? TREE_VALUE (TREE_VALUE ( - adjust_args_list)) - : TREE_PURPOSE (TREE_VALUE ( - adjust_args_list)); + ? TREE_VALUE ( + dispatch_adjust_args_list) + : TREE_PURPOSE ( + dispatch_adjust_args_list); arg != NULL; arg = TREE_CHAIN (arg)) { if (TREE_VALUE (arg) @@ -4204,6 +4295,7 @@ gimplify_call_expr (tree *expr_p, gimple_seq *pre_p, bool want_value) "%<need_device_addr%>", OMP_CLAUSE_DECL (c)); is_device_ptr = true; + break; } else if (decl1 == decl2) { @@ -4217,36 +4309,36 @@ gimplify_call_expr (tree *expr_p, gimple_seq *pre_p, bool want_value) "%<need_device_ptr%>", OMP_CLAUSE_DECL (c)); has_device_addr = true; + break; } } } - else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEVICE) - device_num = OMP_CLAUSE_OPERAND (c, 0); } if ((need_device_ptr && !is_device_ptr) || (need_device_addr && !has_device_addr)) { - if (device_num == NULL_TREE) + if (dispatch_device_num == NULL_TREE) { // device_num = omp_get_default_device () tree fn = builtin_decl_explicit ( BUILT_IN_OMP_GET_DEFAULT_DEVICE); gcall *call = gimple_build_call (fn, 0); - device_num = create_tmp_var ( + dispatch_device_num = create_tmp_var ( gimple_call_return_type (call)); - gimple_call_set_lhs (call, device_num); + gimple_call_set_lhs (call, + dispatch_device_num); gimplify_seq_add_stmt (pre_p, call); } // mapped_arg = omp_get_mapped_ptr (arg, - // device_num) + // device_num) tree fn = builtin_decl_explicit ( BUILT_IN_OMP_GET_MAPPED_PTR); gimplify_arg (arg_p, pre_p, loc); - gimplify_arg (&device_num, pre_p, loc); - call - = gimple_build_call (fn, 2, *arg_p, device_num); + gimplify_arg (&dispatch_device_num, pre_p, loc); + call = gimple_build_call (fn, 2, *arg_p, + dispatch_device_num); tree mapped_arg = create_tmp_var ( gimple_call_return_type (call)); gimple_call_set_lhs (call, mapped_arg); diff --git a/gcc/testsuite/c-c++-common/gomp/append-args-1.c b/gcc/testsuite/c-c++-common/gomp/append-args-1.c new file mode 100644 index 0000000..1325f37 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/append-args-1.c @@ -0,0 +1,83 @@ +/* The following definitions are in omp_lib, which cannot be included + in gcc/testsuite/ */ + +#if __cplusplus >= 201103L +# define __GOMP_UINTPTR_T_ENUM : __UINTPTR_TYPE__ +#else +# define __GOMP_UINTPTR_T_ENUM +#endif + +typedef enum omp_interop_t __GOMP_UINTPTR_T_ENUM +{ + omp_interop_none = 0, + __omp_interop_t_max__ = __UINTPTR_MAX__ +} omp_interop_t; + +float repl0(short, short); +#pragma omp declare variant(repl0) match(construct={dispatch}) append_args(interop(target), interop(targetsync)) +float base0(); +/* { dg-error "argument 1 of 'repl0' must be of 'omp_interop_t'" "" { target c } .-3 } */ +/* { dg-error "argument 1 of 'float repl0\\(short int, short int\\)' must be of 'omp_interop_t'" "" { target c++ } .-4 } */ +/* { dg-note "'append_args' specified here" "" { target *-*-* } .-4 } */ + +float repl1(omp_interop_t, omp_interop_t); +#pragma omp declare variant(repl1) match(construct={dispatch}) append_args(interop(target), interop(targetsync)) +float base1(); +/* { dg-message "sorry, unimplemented: 'append_args' clause not yet supported for 'repl1'" "" { target c } .-2 } */ +/* { dg-message "sorry, unimplemented: 'append_args' clause not yet supported for 'float repl1\\(omp_interop_t, omp_interop_t\\)'" "" { target c++ } .-3 } */ + +void repl2(int *, int *, omp_interop_t, omp_interop_t); +#pragma omp declare variant(repl2) match(construct={dispatch}) adjust_args(need_device_ptr : y) \ + append_args(interop(target, targetsync, prefer_type(1)), \ + interop(prefer_type({fr(3), attr("ompx_nop")},{fr(2)},{attr("ompx_all")}))) +void base2(int *x, int *y); +/* { dg-message "sorry, unimplemented: 'append_args' clause not yet supported for 'repl2'" "" { target c } .-3 } */ +/* { dg-message "sorry, unimplemented: 'append_args' clause not yet supported for 'void repl2\\(int\\*, int\\*, omp_interop_t, omp_interop_t\\)'" "" { target c++ } .-4 } */ + +void repl3(int, omp_interop_t, ...); +#pragma omp declare variant(repl3) match(construct={dispatch}) \ + append_args(interop(prefer_type("cuda", "hsa"))) +void base3(int, ...); +/* { dg-message "sorry, unimplemented: 'append_args' clause not yet supported for 'repl3'" "" { target c } .-2 } */ +/* { dg-message "sorry, unimplemented: 'append_args' clause not yet supported for 'void repl3\\(int, omp_interop_t, \\.\\.\\.\\)'" "" { target c++ } .-3 } */ +/* { dg-note "'declare variant' candidate 'repl3' declared here" "" { target c } .-4 } */ +/* { dg-note "'declare variant' candidate 'void repl3\\(int, omp_interop_t, \\.\\.\\.\\)' declared here" "" { target c++ } .-5 } */ + +float repl4(short, short, omp_interop_t, short); +#pragma omp declare variant(repl4) match(construct={dispatch}) append_args(interop(target)) append_args(interop(targetsync)) /* { dg-error "too many 'append_args' clauses" } */ +float base4(short, short); +/* { dg-error "argument 4 of 'repl4' must be of 'omp_interop_t'" "" { target c } .-3 } */ +/* { dg-error "argument 4 of 'float repl4\\(short int, short int, omp_interop_t, short int\\)' must be of 'omp_interop_t'" "" { target c++ } .-4 } */ +/* { dg-note "'append_args' specified here" "" { target *-*-* } .-4 } */ + + +float +test (int *a, int *b) +{ + omp_interop_t obj1, obj2; + float x; + + #pragma omp dispatch interop ( obj1 ) + x = base1 (); + /* { dg-note "required by 'dispatch' construct" "" { target *-*-* } .-2 } */ + + #pragma omp dispatch interop ( obj1 ) + base2 (a, b); + /* { dg-note "required by 'dispatch' construct" "" { target *-*-* } .-2 } */ + + #pragma omp dispatch + base3 (5, 1, 2, 3); + /* { dg-note "required by 'dispatch' construct" "" { target *-*-* } .-2 } */ + + #pragma omp dispatch interop (obj2) + base3 (5, 1, 2, 3); + /* { dg-note "required by 'dispatch' construct" "" { target *-*-* } .-2 } */ + + #pragma omp dispatch interop (obj2, obj1) + base3 (5, 1, 2, 3); + /* { dg-error "number of list items in 'interop' clause \\(2\\) exceeds the number of 'append_args' items \\(1\\) for 'declare variant' candidate 'repl3'" "" { target c } .-2 } */ + /* { dg-error "number of list items in 'interop' clause \\(2\\) exceeds the number of 'append_args' items \\(1\\) for 'declare variant' candidate 'void repl3\\(int, omp_interop_t, \\.\\.\\.\\)'" "" { target c++ } .-3 } */ + /* { dg-note "required by 'dispatch' construct" "" { target *-*-* } .-4 } */ + + return x; +} diff --git a/gcc/testsuite/c-c++-common/gomp/append-args-2.c b/gcc/testsuite/c-c++-common/gomp/append-args-2.c new file mode 100644 index 0000000..0e14675 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/append-args-2.c @@ -0,0 +1,8 @@ +/* omp_interop_t undefined (on purpose). */ + +float repl0(short, short); +#pragma omp declare variant(repl0) match(construct={dispatch}) append_args(interop(target), interop(targetsync)) +float base0(); +/* { dg-error "argument 1 of 'repl0' must be of 'omp_interop_t'" "" { target c } .-3 } */ +/* { dg-error "argument 1 of 'repl0' must be of 'omp_interop_t'" "" { target c++ } .-4 } */ +/* { dg-note "'append_args' specified here" "" { target *-*-* } .-4 } */ diff --git a/gcc/testsuite/c-c++-common/gomp/append-args-3.c b/gcc/testsuite/c-c++-common/gomp/append-args-3.c new file mode 100644 index 0000000..20fe3c0 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/append-args-3.c @@ -0,0 +1,57 @@ +/* { dg-additional-options "-fdump-tree-gimple -Wall" } */ + +#if __cplusplus >= 201103L +# define __GOMP_UINTPTR_T_ENUM : __UINTPTR_TYPE__ +#else +# define __GOMP_UINTPTR_T_ENUM +#endif + +typedef enum omp_interop_t __GOMP_UINTPTR_T_ENUM +{ + omp_interop_none = 0, + __omp_interop_t_max__ = __UINTPTR_MAX__ +} omp_interop_t; + + +void g(int, const char *, omp_interop_t, omp_interop_t); +#pragma omp declare variant(g) match(construct={dispatch}) append_args(interop(target),interop(targetsync)) +void f(int x, const char *y); + +void foo() +{ + omp_interop_t obj1; /* { dg-note "'obj1' was declared here" } */ + omp_interop_t obj2 = omp_interop_none; + #pragma omp dispatch device(9) novariants(1) + f(2, "abc"); + #pragma omp dispatch device(5) interop(obj1,obj2) + f(3, "cde"); /* { dg-warning "'obj1' is used uninitialized \\\[-Wuninitialized\\\]" } */ +} + + +void varvar(int, int, omp_interop_t, omp_interop_t, ...); +#pragma omp declare variant(varvar) match(construct={dispatch}) append_args(interop(target),interop(targetsync)) +void varbase(int x, int y, ...); + +void bar() +{ + omp_interop_t obj3 = omp_interop_none; + omp_interop_t obj4; /* { dg-note "'obj4' was declared here" } */ + #pragma omp dispatch device(3) nocontext(1) + varbase(10, 11, 101, 202, 303); + #pragma omp dispatch device(7) interop(obj3,obj4) + varbase(20, 21, 111, 222, 333); /* { dg-warning "'obj4' is used uninitialized \\\[-Wuninitialized\\\]" } */ +} + +/* { dg-final { scan-tree-dump-times "D\.\[0-9\]+ = __builtin_omp_get_default_device \\(\\);" 4 "gimple" } } */ + +/* { dg-final { scan-tree-dump-times "__builtin_omp_set_default_device \\(9\\);" 1 "gimple" } } */ +/* { dg-final { scan-tree-dump-times "__builtin_omp_set_default_device \\(5\\);" 1 "gimple" } } */ +/* { dg-final { scan-tree-dump-times "__builtin_omp_set_default_device \\(3\\);" 1 "gimple" } } */ +/* { dg-final { scan-tree-dump-times "__builtin_omp_set_default_device \\(7\\);" 1 "gimple" } } */ + +/* { dg-final { scan-tree-dump-times "__builtin_omp_set_default_device \\(D\.\[0-9\]+\\);" 4 "gimple" } } */ + +/* { dg-final { scan-tree-dump-times "f \\(2, \"abc\"\\);" 1 "gimple" } } */ +/* { dg-final { scan-tree-dump-times "g \\(3, \"cde\", obj1, obj2\\);" 1 "gimple" } } */ +/* { dg-final { scan-tree-dump-times "varbase \\(10, 11, 101, 202, 303\\);" 1 "gimple" } } */ +/* { dg-final { scan-tree-dump-times "varvar \\(20, 21, obj3, obj4, 111, 222, 333\\);" 1 "gimple" } } */ diff --git a/gcc/testsuite/c-c++-common/gomp/declare-variant-2.c b/gcc/testsuite/c-c++-common/gomp/declare-variant-2.c index 9f209f4..026998e 100644 --- a/gcc/testsuite/c-c++-common/gomp/declare-variant-2.c +++ b/gcc/testsuite/c-c++-common/gomp/declare-variant-2.c @@ -8,9 +8,9 @@ void f3 (void); void f4 (void); #pragma omp declare variant match(user={condition(0)}) /* { dg-error "expected '\\(' before 'match'" } */ void f5 (void); -#pragma omp declare variant (f1) /* { dg-error "expected 'match' clause before end of line" } */ +#pragma omp declare variant (f1) /* { dg-error "expected 'match', 'adjust_args' or 'append_args' clause before end of line" } */ void f6 (void); -#pragma omp declare variant (f1) simd /* { dg-error "expected 'match' clause before 'simd'" } */ +#pragma omp declare variant (f1) simd /* { dg-error "expected 'match', 'adjust_args' or 'append_args' clause before 'simd'" } */ void f7 (void); #pragma omp declare variant (f1) match /* { dg-error "expected '\\(' before end of line" } */ void f8 (void); diff --git a/gcc/testsuite/c-c++-common/gomp/dispatch-11.c b/gcc/testsuite/c-c++-common/gomp/dispatch-11.c index 7f1d806..e2372eb 100644 --- a/gcc/testsuite/c-c++-common/gomp/dispatch-11.c +++ b/gcc/testsuite/c-c++-common/gomp/dispatch-11.c @@ -24,6 +24,10 @@ void repl2(int *, int *); #pragma omp declare variant(repl2) match(construct={dispatch}) adjust_args(need_device_ptr : y) void base2(int *x, int *y); +void repl3(int *, int *, omp_interop_t); +#pragma omp declare variant(repl3) match(construct={dispatch}) adjust_args(need_device_ptr : y) append_args(interop(target)) +void base3(int *x, int *y); + float dupl (int *a, int *b) @@ -33,47 +37,69 @@ dupl (int *a, int *b) #pragma omp dispatch interop ( obj1 ) interop(obj2) /* { dg-error "too many 'interop' clauses" } */ x = base1 (); - /* { dg-error "number of list items in 'interop' clause exceeds number of 'append_args' items for 'declare variant' candidate 'repl1'" "" { target c } .-2 } */ - /* { dg-error "number of list items in 'interop' clause exceeds number of 'append_args' items for 'declare variant' candidate 'float repl1\\(\\)'" "" { target c++ } .-3 } */ + /* { dg-error "number of list items in 'interop' clause \\(2\\) exceeds the number of 'append_args' items \\(0\\) for 'declare variant' candidate 'repl1'" "" { target c } .-2 } */ + /* { dg-error "number of list items in 'interop' clause \\(2\\) exceeds the number of 'append_args' items \\(0\\) for 'declare variant' candidate 'float repl1\\(\\)'" "" { target c++ } .-3 } */ #pragma omp dispatch interop ( obj1) nocontext(1) interop (obj2 ) /* { dg-error "too many 'interop' clauses" } */ base2 (a, b); - /* { dg-error "number of list items in 'interop' clause exceeds number of 'append_args' items for 'declare variant' candidate 'base2'" "" { target c } .-2 } */ - /* { dg-error "number of list items in 'interop' clause exceeds number of 'append_args' items for 'declare variant' candidate 'void base2\\(int\\*, int\\*\\)'" "" { target c++ } .-3 } */ + /* { dg-error "number of list items in 'interop' clause \\(2\\) exceeds the number of 'append_args' items \\(0\\) for 'declare variant' candidate 'base2'" "" { target c } .-2 } */ + /* { dg-error "number of list items in 'interop' clause \\(2\\) exceeds the number of 'append_args' items \\(0\\) for 'declare variant' candidate 'void base2\\(int\\*, int\\*\\)'" "" { target c++ } .-3 } */ return x; } +/* { dg-note "'declare variant' candidate 'repl1' declared here" "" { target c } 19 } */ +/* { dg-note "'declare variant' candidate 'float repl1\\(\\)' declared here" "" { target c++ } 19 } */ +/* { dg-note "'declare variant' candidate 'base1' declared here" "" { target c } 21 } */ +/* { dg-note "'declare variant' candidate 'float base1\\(\\)' declared here" "" { target c++ } 21 } */ +/* { dg-note "'declare variant' candidate 'repl2' declared here" "" { target c } 23 } */ +/* { dg-note "'declare variant' candidate 'void repl2\\(int\\*, int\\*\\)' declared here" "" { target c++ } 23 } */ +/* { dg-note "'declare variant' candidate 'base2' declared here" "" { target c } 25 } */ +/* { dg-note "'declare variant' candidate 'void base2\\(int\\*, int\\*\\)' declared here" "" { target c++ } 25 } */ +/* { dg-note "'declare variant' candidate 'repl3' declared here" "" { target c } 28 } */ +/* { dg-note "'declare variant' candidate 'void repl3\\(int\\*, int\\*, omp_interop_t\\)' declared here" "" { target c++ } 28 } */ float test (int *a, int *b) { - omp_interop_t obj1, obj2; + omp_interop_t obj1, obj2, obj3; float x, y; #pragma omp dispatch interop ( obj1 ) x = base1 (); - /* { dg-error "number of list items in 'interop' clause exceeds number of 'append_args' items for 'declare variant' candidate 'repl1'" "" { target c } .-2 } */ - /* { dg-error "number of list items in 'interop' clause exceeds number of 'append_args' items for 'declare variant' candidate 'float repl1\\(\\)'" "" { target c++ } .-3 } */ + /* { dg-error "number of list items in 'interop' clause \\(1\\) exceeds the number of 'append_args' items \\(0\\) for 'declare variant' candidate 'repl1'" "" { target c } .-2 } */ + /* { dg-error "number of list items in 'interop' clause \\(1\\) exceeds the number of 'append_args' items \\(0\\) for 'declare variant' candidate 'float repl1\\(\\)'" "" { target c++ } .-3 } */ #pragma omp dispatch interop ( obj1, obj1 ) /* Twice the same - should be fine. */ x = base1 (); - /* { dg-error "number of list items in 'interop' clause exceeds number of 'append_args' items for 'declare variant' candidate 'repl1'" "" { target c } .-2 } */ - /* { dg-error "number of list items in 'interop' clause exceeds number of 'append_args' items for 'declare variant' candidate 'float repl1\\(\\)'" "" { target c++ } .-3 } */ + /* { dg-error "number of list items in 'interop' clause \\(2\\) exceeds the number of 'append_args' items \\(0\\) for 'declare variant' candidate 'repl1'" "" { target c } .-2 } */ + /* { dg-error "number of list items in 'interop' clause \\(2\\) exceeds the number of 'append_args' items \\(0\\) for 'declare variant' candidate 'float repl1\\(\\)'" "" { target c++ } .-3 } */ #pragma omp dispatch novariants(1) interop(obj2, obj1) y = base1 (); - /* { dg-error "number of list items in 'interop' clause exceeds number of 'append_args' items for 'declare variant' candidate 'base1'" "" { target c } .-2 } */ - /* { dg-error "number of list items in 'interop' clause exceeds number of 'append_args' items for 'declare variant' candidate 'float base1\\(\\)'" "" { target c++ } .-3 } */ + /* { dg-error "number of list items in 'interop' clause \\(2\\) exceeds the number of 'append_args' items \\(0\\) for 'declare variant' candidate 'base1'" "" { target c } .-2 } */ + /* { dg-error "number of list items in 'interop' clause \\(2\\) exceeds the number of 'append_args' items \\(0\\) for 'declare variant' candidate 'float base1\\(\\)'" "" { target c++ } .-3 } */ #pragma omp dispatch interop(obj2, obj1) base2 (a, b); - /* { dg-error "number of list items in 'interop' clause exceeds number of 'append_args' items for 'declare variant' candidate 'repl2'" "" { target c } .-2 } */ - /* { dg-error "number of list items in 'interop' clause exceeds number of 'append_args' items for 'declare variant' candidate 'void repl2\\(int\\*, int\\*\\)'" "" { target c++ } .-3 } */ + /* { dg-error "number of list items in 'interop' clause \\(2\\) exceeds the number of 'append_args' items \\(0\\) for 'declare variant' candidate 'repl2'" "" { target c } .-2 } */ + /* { dg-error "number of list items in 'interop' clause \\(2\\) exceeds the number of 'append_args' items \\(0\\) for 'declare variant' candidate 'void repl2\\(int\\*, int\\*\\)'" "" { target c++ } .-3 } */ #pragma omp dispatch interop(obj2) nocontext(1) base2 (a, b); - /* { dg-error "number of list items in 'interop' clause exceeds number of 'append_args' items for 'declare variant' candidate 'base2'" "" { target c } .-2 } */ - /* { dg-error "number of list items in 'interop' clause exceeds number of 'append_args' items for 'declare variant' candidate 'void base2\\(int\\*, int\\*\\)'" "" { target c++ } .-3 } */ + /* { dg-error "number of list items in 'interop' clause \\(1\\) exceeds the number of 'append_args' items \\(0\\) for 'declare variant' candidate 'base2'" "" { target c } .-2 } */ + /* { dg-error "number of list items in 'interop' clause \\(1\\) exceeds the number of 'append_args' items \\(0\\) for 'declare variant' candidate 'void base2\\(int\\*, int\\*\\)'" "" { target c++ } .-3 } */ + + #pragma omp dispatch interop(obj3, obj2) + base3 (a, b); + /* { dg-error "number of list items in 'interop' clause \\(2\\) exceeds the number of 'append_args' items \\(1\\) for 'declare variant' candidate 'repl3'" "" { target c } .-2 } */ + /* { dg-error "number of list items in 'interop' clause \\(2\\) exceeds the number of 'append_args' items \\(1\\) for 'declare variant' candidate 'void repl3\\(int\\*, int\\*, omp_interop_t\\)'" "" { target c++ } .-3 } */ + /* { dg-note "required by 'dispatch' construct" "" { target *-*-* } .-4 } */ + + #pragma omp dispatch interop(obj3) + base3 (a, b); + /* { dg-message "sorry, unimplemented: 'append_args' clause not yet supported for 'repl3'" "" { target c } 28 } */ + /* { dg-message "sorry, unimplemented: 'append_args' clause not yet supported for 'void repl3\\(int\\*, int\\*, omp_interop_t\\)'" "" { target c++ } 28 } */ + /* { dg-note "required by 'dispatch' construct" "" { target *-*-* } .-4 } */ return x + y; } @@ -82,3 +108,5 @@ test (int *a, int *b) /* { dg-final { scan-tree-dump-times "#pragma omp dispatch interop\\(obj1\\) interop\\(obj2\\) novariants\\(1\\)\[\\n\\r\]" 1 "original" } } */ /* { dg-final { scan-tree-dump-times "#pragma omp dispatch interop\\(obj1\\) interop\\(obj2\\)\[\\n\\r\]" 1 "original" } } */ /* { dg-final { scan-tree-dump-times "#pragma omp dispatch nocontext\\(1\\) interop\\(obj2\\)\[\\n\\r\]" 1 "original" } } */ +/* { dg-final { scan-tree-dump-times "#pragma omp dispatch interop\\(obj2\\) interop\\(obj3\\)\[\\n\\r\]" 1 "original" } } */ +/* { dg-final { scan-tree-dump-times "#pragma omp dispatch interop\\(obj3\\)\[\\n\\r\]" 1 "original" } } */ diff --git a/gcc/testsuite/c-c++-common/gomp/dispatch-12.c b/gcc/testsuite/c-c++-common/gomp/dispatch-12.c index ea190c7..0b8fdfa 100644 --- a/gcc/testsuite/c-c++-common/gomp/dispatch-12.c +++ b/gcc/testsuite/c-c++-common/gomp/dispatch-12.c @@ -28,26 +28,26 @@ test () #pragma omp dispatch interop ( obj1, obj2, obj1 ) /* { dg-error "'obj2' must be of 'omp_interop_t'" } */ base1 (); - /* { dg-error "number of list items in 'interop' clause exceeds number of 'append_args' items for 'declare variant' candidate 'repl1'" "" { target c } .-2 } */ - /* { dg-error "number of list items in 'interop' clause exceeds number of 'append_args' items for 'declare variant' candidate 'void repl1\\(\\)'" "" { target c++ } .-3 } */ + /* { dg-error "number of list items in 'interop' clause \\(3\\) exceeds the number of 'append_args' items \\(0\\) for 'declare variant' candidate 'repl1'" "" { target c } .-2 } */ + /* { dg-error "number of list items in 'interop' clause \\(3\\) exceeds the number of 'append_args' items \\(0\\) for 'declare variant' candidate 'void repl1\\(\\)'" "" { target c++ } .-3 } */ #pragma omp dispatch interop ( obj3 ) /* { dg-error "'obj3' must be of 'omp_interop_t'" } */ base1 (); - /* { dg-error "number of list items in 'interop' clause exceeds number of 'append_args' items for 'declare variant' candidate 'repl1'" "" { target c } .-2 } */ - /* { dg-error "number of list items in 'interop' clause exceeds number of 'append_args' items for 'declare variant' candidate 'void repl1\\(\\)'" "" { target c++ } .-3 } */ + /* { dg-error "number of list items in 'interop' clause \\(1\\) exceeds the number of 'append_args' items \\(0\\) for 'declare variant' candidate 'repl1'" "" { target c } .-2 } */ + /* { dg-error "number of list items in 'interop' clause \\(1\\) exceeds the number of 'append_args' items \\(0\\) for 'declare variant' candidate 'void repl1\\(\\)'" "" { target c++ } .-3 } */ #pragma omp dispatch interop ( obj1 ) base1 (); - /* { dg-error "number of list items in 'interop' clause exceeds number of 'append_args' items for 'declare variant' candidate 'repl1'" "" { target c } .-2 } */ - /* { dg-error "number of list items in 'interop' clause exceeds number of 'append_args' items for 'declare variant' candidate 'void repl1\\(\\)'" "" { target c++ } .-3 } */ + /* { dg-error "number of list items in 'interop' clause \\(1\\) exceeds the number of 'append_args' items \\(0\\) for 'declare variant' candidate 'repl1'" "" { target c } .-2 } */ + /* { dg-error "number of list items in 'interop' clause \\(1\\) exceeds the number of 'append_args' items \\(0\\) for 'declare variant' candidate 'void repl1\\(\\)'" "" { target c++ } .-3 } */ #pragma omp dispatch interop ( obj2 ) /* { dg-error "'obj2' must be of 'omp_interop_t'" } */ base1 (); - /* { dg-error "number of list items in 'interop' clause exceeds number of 'append_args' items for 'declare variant' candidate 'repl1'" "" { target c } .-2 } */ - /* { dg-error "number of list items in 'interop' clause exceeds number of 'append_args' items for 'declare variant' candidate 'void repl1\\(\\)'" "" { target c++ } .-3 } */ + /* { dg-error "number of list items in 'interop' clause \\(1\\) exceeds the number of 'append_args' items \\(0\\) for 'declare variant' candidate 'repl1'" "" { target c } .-2 } */ + /* { dg-error "number of list items in 'interop' clause \\(1\\) exceeds the number of 'append_args' items \\(0\\) for 'declare variant' candidate 'void repl1\\(\\)'" "" { target c++ } .-3 } */ #pragma omp dispatch interop ( x ) /* { dg-error "'x' must be of 'omp_interop_t'" } */ base1 (); - /* { dg-error "number of list items in 'interop' clause exceeds number of 'append_args' items for 'declare variant' candidate 'repl1'" "" { target c } .-2 } */ - /* { dg-error "number of list items in 'interop' clause exceeds number of 'append_args' items for 'declare variant' candidate 'void repl1\\(\\)'" "" { target c++ } .-3 } */ + /* { dg-error "number of list items in 'interop' clause \\(1\\) exceeds the number of 'append_args' items \\(0\\) for 'declare variant' candidate 'repl1'" "" { target c } .-2 } */ + /* { dg-error "number of list items in 'interop' clause \\(1\\) exceeds the number of 'append_args' items \\(0\\) for 'declare variant' candidate 'void repl1\\(\\)'" "" { target c++ } .-3 } */ } diff --git a/gcc/testsuite/g++.dg/gomp/append-args-1.C b/gcc/testsuite/g++.dg/gomp/append-args-1.C new file mode 100644 index 0000000..d4f9a70 --- /dev/null +++ b/gcc/testsuite/g++.dg/gomp/append-args-1.C @@ -0,0 +1,134 @@ +/* The following definitions are in omp_lib, which cannot be included +gcc/testsuite/g++.dg/gomp/append-args-1.C in gcc/testsuite/ */ + +#if __cplusplus >= 201103L +# define __GOMP_UINTPTR_T_ENUM : __UINTPTR_TYPE__ +#else +# define __GOMP_UINTPTR_T_ENUM +#endif + +typedef enum omp_interop_t __GOMP_UINTPTR_T_ENUM +{ + omp_interop_none = 0, + __omp_interop_t_max__ = __UINTPTR_MAX__ +} omp_interop_t; + +template<typename T, typename T2> +float repl1(T, T2, T2); +#pragma omp declare variant(repl1) match(construct={dispatch}) append_args(interop(target,prefer_type(1,5,4)), interop(targetsync)) +template<typename T> +float base1(T); + +/* { dg-message "sorry, unimplemented: 'append_args' clause not yet supported for 'float repl1\\(T, T2, T2\\) \\\[with T = short int; T2 = omp_interop_t\\\]'" "" { target *-*-* } .-4 } */ +/* { dg-message "sorry, unimplemented: 'append_args' clause not yet supported for 'float repl1\\(T, T2, T2\\) \\\[with T = omp_interop_t; T2 = omp_interop_t\\\]'" "" { target *-*-* } .-5 } */ +/* { dg-message "sorry, unimplemented: 'append_args' clause not yet supported for 'float repl1\\(T, T2, T2\\) \\\[with T = float; T2 = omp_interop_t\\\]'" "" { target *-*-* } .-6 } */ + + + +template<typename T, typename T2, typename T3> +void repl3inval(T, T2, float); +#pragma omp declare variant(repl3inval) match(construct={dispatch}) adjust_args(nothing : y) \ + append_args(interop(prefer_type({fr(3), attr("ompx_nop")},{fr(2)},{attr("ompx_all")}),target,targetsync)) +template<typename T, typename T2> +void base2inval(T x, T2 y); + +/* { dg-error "no matching function for call to 'repl3inval\\(int\\*, omp_interop_t, omp_interop_t\\)'" "" { target *-*-* } .-5 } */ +/* { dg-note "there is 1 candidate" "" { target *-*-* } .-6 } */ +/* { dg-note "candidate 1: 'template<class T, class T2, class T3> void repl3inval\\(T, T2, float\\)'" "" { target *-*-* } .-8 } */ +/* { dg-note "template argument deduction/substitution failed:" "" { target *-*-* } .-9 } */ +/* { dg-note "couldn't deduce template parameter 'T3'" "" { target *-*-* } .-9 } */ + + +template<typename T> +void repl99(T); +#pragma omp declare variant(repl99) match(construct={dispatch}) \ + append_args(interop(target, targetsync, prefer_type("cuda"))) +void base99(); + +/* { dg-message "sorry, unimplemented: 'append_args' clause not yet supported for 'void repl99\\(T\\) \\\[with T = omp_interop_t\\\]'" "" { target *-*-* } .-3 } */ + + + +template<typename T, typename T2, typename T3> +void repl2(T, T2, T3, T3); +#pragma omp declare variant(repl2) match(construct={dispatch}) adjust_args(need_device_ptr : y) \ + append_args(interop(target, targetsync, prefer_type(1)), \ + interop(prefer_type({fr(3), attr("ompx_nop")},{fr(2)},{attr("ompx_all")}))) +template<typename T, typename T2> +void base2(T x, T2 y); + +/* { dg-message "sorry, unimplemented: 'append_args' clause not yet supported for 'void repl2\\(T, T2, T3, T3\\) \\\[with T = int\\*; T2 = int\\*; T3 = omp_interop_t\\\]'" "" { target *-*-* } .-5 } */ +/* { dg-message "sorry, unimplemented: 'append_args' clause not yet supported for 'void repl2\\(T, T2, T3, T3\\) \\\[with T = int\\*; T2 = omp_interop_t; T3 = omp_interop_t\\\]'" "" { target *-*-* } .-6 } */ + + +template<typename T,typename T3> +void tooFewRepl(T, T, T3); +#pragma omp declare variant(tooFewRepl) match(construct={dispatch}) \ + append_args(interop(target, targetsync, prefer_type(1)), \ + interop(prefer_type({fr(3), attr("ompx_nop")},{fr(2)},{attr("ompx_all")}))) +template<typename T, typename T2> +void tooFewBase(T x, T2 y); + +/* { dg-error "no matching function for call to 'tooFewRepl\\(int\\*, int\\*, omp_interop_t, omp_interop_t\\)'" "" { target *-*-* } .-6 } */ +/* { dg-note "there is 1 candidate" "" { target *-*-* } .-7 } */ +/* { dg-note "candidate 1: 'template<class T, class T3> void tooFewRepl\\(T, T, T3\\)'" "" { target *-*-* } .-9 } */ +/* { dg-note "candidate expects 3 arguments, 4 provided" "" { target *-*-* } .-10 } */ + + + +template<typename T, typename T2> +void repl3(T, T2, ...); +#pragma omp declare variant(repl3) match(construct={dispatch}) \ + append_args(interop(prefer_type("cuda", "hsa"))) +template<typename T> +void base3(T, ...); + +/* { dg-message "sorry, unimplemented: 'append_args' clause not yet supported for 'void repl3\\(T, T2, \.\.\.\\) \\\[with T = int\\*; T2 = omp_interop_t\\\]'" "" { target *-*-* } .-4 } */ + + + +float +test (int *a, int *b) +{ + omp_interop_t obj1, obj2; + float x, y; + + #pragma omp dispatch interop ( obj1, obj2 ) + x = base1<short> (5); + /* { dg-note "required by 'dispatch' construct" "" { target *-*-* } .-2 } */ + + #pragma omp dispatch + base2inval<int *, omp_interop_t> (a, omp_interop_none); + + #pragma omp dispatch + base99 (); + /* { dg-note "required by 'dispatch' construct" "" { target *-*-* } .-2 } */ + + #pragma omp dispatch interop ( obj1 ) + base2<int *, omp_interop_t> (b, omp_interop_none); + /* { dg-note "required by 'dispatch' construct" "" { target *-*-* } .-2 } */ + + #pragma omp dispatch interop ( obj1 ) + base2<int *, int *> (b, a); + /* { dg-note "required by 'dispatch' construct" "" { target *-*-* } .-2 } */ + + #pragma omp dispatch interop ( obj1 ) + x = base1<omp_interop_t> (omp_interop_none); + /* { dg-note "required by 'dispatch' construct" "" { target *-*-* } .-2 } */ + + #pragma omp dispatch interop ( obj1 ) + x = base1<float> (1.0f); + /* { dg-note "required by 'dispatch' construct" "" { target *-*-* } .-2 } */ + + #pragma omp dispatch + tooFewBase<int*,int*>(a,b); + + #pragma omp dispatch nocontext(1) + base3<int*>(a, 1, 2, "abc"); + + #pragma omp dispatch + base3<int*>(a, 1, 2, "abc"); + /* { dg-note "required by 'dispatch' construct" "" { target *-*-* } .-2 } */ + + return x; +} diff --git a/gcc/testsuite/g++.dg/gomp/append-args-2.C b/gcc/testsuite/g++.dg/gomp/append-args-2.C new file mode 100644 index 0000000..33cd268 --- /dev/null +++ b/gcc/testsuite/g++.dg/gomp/append-args-2.C @@ -0,0 +1,53 @@ +/* omp_interop_t is undefined (on purpose) */ + + +template<typename T, typename T2> +float repl1(T, T2, T2); /* { dg-error "argument 2 of 'repl1' must be of 'omp_interop_t'" } */ +#pragma omp declare variant(repl1) match(construct={dispatch}) append_args(interop(target,prefer_type(1,5,4)), interop(targetsync)) /* { dg-note "'append_args' specified here" } */ +template<typename T> +float base1(T); + + + +template<typename T, typename T2, typename T3> +void repl3inval(T, T2, float); /* { dg-error "argument 3 of 'repl3inval' must be of 'omp_interop_t'" } */ +#pragma omp declare variant(repl3inval) match(construct={dispatch}) adjust_args(nothing : y) \ + append_args(interop(prefer_type({fr(3), attr("ompx_nop")},{fr(2)},{attr("ompx_all")}),target,targetsync)) /* { dg-note "'append_args' specified here" } */ +template<typename T, typename T2> +void base2inval(T x, T2 y); + + + +template<typename T> +void repl99(T); /* { dg-error "argument 1 of 'repl99' must be of 'omp_interop_t'" } */ +#pragma omp declare variant(repl99) match(construct={dispatch}) \ + append_args(interop(target, targetsync, prefer_type("cuda"))) /* { dg-note "'append_args' specified here" } */ +void base99(); + + + +template<typename T, typename T2, typename T3> +void repl2(T, T2, T3, T3); /* { dg-error "argument 3 of 'repl2' must be of 'omp_interop_t'" } */ +#pragma omp declare variant(repl2) match(construct={dispatch}) adjust_args(need_device_ptr : y) \ + append_args(interop(target, targetsync, prefer_type(1)), /* { dg-note "'append_args' specified here" } */ \ + interop(prefer_type({fr(3), attr("ompx_nop")},{fr(2)},{attr("ompx_all")}))) +template<typename T, typename T2> +void base2(T x, T2 y); + + +template<typename T,typename T3> +void tooFewRepl(T, T, T3); /* { dg-error "argument 3 of 'tooFewRepl' must be of 'omp_interop_t'" } */ +#pragma omp declare variant(tooFewRepl) match(construct={dispatch}) \ + append_args(interop(target, targetsync, prefer_type(1)), /* { dg-note "'append_args' specified here" } */ \ + interop(prefer_type({fr(3), attr("ompx_nop")},{fr(2)},{attr("ompx_all")}))) +template<typename T, typename T2> +void tooFewBase(T x, T2 y); + + + +template<typename T, typename T2> +void repl3(T, T2, ...); /* { dg-error "argument 2 of 'repl3' must be of 'omp_interop_t'" } */ +#pragma omp declare variant(repl3) match(construct={dispatch}) \ + append_args(interop(prefer_type("cuda", "hsa"))) /* { dg-note "'append_args' specified here" } */ +template<typename T> +void base3(T, ...); diff --git a/gcc/testsuite/g++.dg/gomp/append-args-3.C b/gcc/testsuite/g++.dg/gomp/append-args-3.C new file mode 100644 index 0000000..324825d --- /dev/null +++ b/gcc/testsuite/g++.dg/gomp/append-args-3.C @@ -0,0 +1,100 @@ +/* { dg-additional-options "-fdump-tree-gimple -Wall" } */ + +#if __cplusplus >= 201103L +# define __GOMP_UINTPTR_T_ENUM : __UINTPTR_TYPE__ +#else +# define __GOMP_UINTPTR_T_ENUM +#endif + +typedef enum omp_interop_t __GOMP_UINTPTR_T_ENUM +{ + omp_interop_none = 0, + __omp_interop_t_max__ = __UINTPTR_MAX__ +} omp_interop_t; + + +template<typename T, typename T2, typename T3> +void g(T, T2, T3, T3); +#pragma omp declare variant(g) match(construct={dispatch}) append_args(interop(target),interop(targetsync)) +template<typename T, typename T2> +void f(T x, T2 y); + +void foo() +{ + omp_interop_t obj1; /* { dg-note "'obj1' was declared here" } */ + omp_interop_t obj2 = omp_interop_none; + #pragma omp dispatch device(9) novariants(1) + f<int, const char *>(2, (const char*)"abc"); + #pragma omp dispatch device(5) interop(obj1,obj2) + f<int, const char *>(3, (const char*)"cde"); /* { dg-warning "'obj1' is used uninitialized \\\[-Wuninitialized\\\]" } */ + + #pragma omp dispatch device(9) novariants(1) + f<int, omp_interop_t>(2, omp_interop_none); + #pragma omp dispatch device(5) interop(obj1,obj2) + f<int, omp_interop_t>(3, omp_interop_none); +} + + +template<typename Ta, typename Tb, typename Tc> +void varvar(Ta, Tb, Tc, Tc, ...); +#pragma omp declare variant(varvar) match(construct={dispatch}) append_args(interop(target),interop(targetsync)) +template<typename Ta, typename Tb> +void varbase(Ta x, Tb y, ...); + +void bar() +{ + omp_interop_t obj3 = omp_interop_none; + omp_interop_t obj4; /* { dg-note "'obj4' was declared here" } */ + #pragma omp dispatch device(3) nocontext(1) + varbase<int, int>(10, 11, 101, 202, 303); + #pragma omp dispatch device(7) interop(obj3,obj4) + varbase<int, int>(20, 21, 111, 222, 333); /* { dg-warning "'obj4' is used uninitialized \\\[-Wuninitialized\\\]" } */ + + #pragma omp dispatch device(3) nocontext(1) + varbase<int, omp_interop_t>(10, omp_interop_none, 101, 202, 303); + #pragma omp dispatch device(7) interop(obj3,obj4) + varbase<int, omp_interop_t>(20, omp_interop_none, 111, 222, 333); +} + + + +template<typename T> +void nargVar(T, T); +#pragma omp declare variant(nargVar) match(construct={dispatch}) append_args(interop(target),interop(targetsync)) +void nargsBase(); + +void foobar() +{ + omp_interop_t obj5 = omp_interop_none; + omp_interop_t obj6 = omp_interop_none; + #pragma omp dispatch device(1) nocontext(1) + nargsBase(); + #pragma omp dispatch device(2) interop(obj5,obj6) + nargsBase(); +} + +/* { dg-final { scan-tree-dump-times "D\.\[0-9\]+ = __builtin_omp_get_default_device \\(\\);" 10 "gimple" } } */ + +/* { dg-final { scan-tree-dump-times "__builtin_omp_set_default_device \\(9\\);" 2 "gimple" } } */ +/* { dg-final { scan-tree-dump-times "__builtin_omp_set_default_device \\(5\\);" 2 "gimple" } } */ +/* { dg-final { scan-tree-dump-times "__builtin_omp_set_default_device \\(3\\);" 2 "gimple" } } */ +/* { dg-final { scan-tree-dump-times "__builtin_omp_set_default_device \\(7\\);" 2 "gimple" } } */ + +/* { dg-final { scan-tree-dump-times "__builtin_omp_set_default_device \\(1\\);" 1 "gimple" } } */ +/* { dg-final { scan-tree-dump-times "__builtin_omp_set_default_device \\(2\\);" 1 "gimple" } } */ + +/* { dg-final { scan-tree-dump-times "__builtin_omp_set_default_device \\(D\.\[0-9\]+\\);" 10 "gimple" } } */ + + +/* { dg-final { scan-tree-dump-times "f<int, const char\\*> \\(2, \"abc\"\\);" 1 "gimple" } } */ +/* { dg-final { scan-tree-dump-times "g<int, const char\\*, omp_interop_t> \\(3, \"cde\", obj1, obj2\\);" 1 "gimple" } } */ +/* { dg-final { scan-tree-dump-times "f<int, omp_interop_t> \\(2, 0\\);" 1 "gimple" } } */ +/* { dg-final { scan-tree-dump-times "g<int, omp_interop_t, omp_interop_t> \\(3, 0, obj1, obj2\\);" 1 "gimple" } } */ + +/* { dg-final { scan-tree-dump-times "varbase<int, int> \\(10, 11, 101, 202, 303\\);" 1 "gimple" } } */ +/* { dg-final { scan-tree-dump-times "varvar<int, int, omp_interop_t> \\(20, 21, obj3, obj4, 111, 222, 333\\);" 1 "gimple" } } */ +/* { dg-final { scan-tree-dump-times "varbase<int, omp_interop_t> \\(10, 0, 101, 202, 303\\);" 1 "gimple" } } */ +/* { dg-final { scan-tree-dump-times "varvar<int, omp_interop_t, omp_interop_t> \\(20, 0, obj3, obj4, 111, 222, 333\\);" 1 "gimple" } } */ + +/* { dg-final { scan-tree-dump-times "nargsBase \\(\\);" 1 "gimple" } } */ +/* { dg-final { scan-tree-dump-times "nargVar<omp_interop_t> \\(obj5, obj6\\);" 1 "gimple" } } */ |