diff options
27 files changed, 770 insertions, 290 deletions
diff --git a/gcc/c-family/c-omp.cc b/gcc/c-family/c-omp.cc index 66d17a2..56bc4b1 100644 --- a/gcc/c-family/c-omp.cc +++ b/gcc/c-family/c-omp.cc @@ -714,8 +714,17 @@ c_finish_omp_depobj (location_t loc, tree depobj, if (clause) { - gcc_assert (TREE_CODE (clause) == OMP_CLAUSE - && OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_DEPEND); + gcc_assert (TREE_CODE (clause) == OMP_CLAUSE); + if (OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_DOACROSS) + { + error_at (OMP_CLAUSE_LOCATION (clause), + "%<depend(%s)%> is only allowed in %<omp ordered%>", + OMP_CLAUSE_DOACROSS_KIND (clause) + == OMP_CLAUSE_DOACROSS_SOURCE + ? "source" : "sink"); + return; + } + gcc_assert (OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_DEPEND); if (OMP_CLAUSE_CHAIN (clause)) error_at (OMP_CLAUSE_LOCATION (clause), "more than one locator in %<depend%> clause on %<depobj%> " @@ -727,13 +736,6 @@ c_finish_omp_depobj (location_t loc, tree depobj, "%<depobj%> dependence type specified in %<depend%> " "clause on %<depobj%> construct"); return; - case OMP_CLAUSE_DEPEND_SOURCE: - case OMP_CLAUSE_DEPEND_SINK: - error_at (OMP_CLAUSE_LOCATION (clause), - "%<depend(%s)%> is only allowed in %<omp ordered%>", - OMP_CLAUSE_DEPEND_KIND (clause) == OMP_CLAUSE_DEPEND_SOURCE - ? "source" : "sink"); - return; case OMP_CLAUSE_DEPEND_IN: case OMP_CLAUSE_DEPEND_OUT: case OMP_CLAUSE_DEPEND_INOUT: @@ -765,7 +767,7 @@ c_finish_omp_depobj (location_t loc, tree depobj, } } else - gcc_assert (kind != OMP_CLAUSE_DEPEND_SOURCE); + gcc_assert (kind != OMP_CLAUSE_DEPEND_INVALID); if (depobj == error_mark_node) return; diff --git a/gcc/c-family/c-pragma.h b/gcc/c-family/c-pragma.h index de806a6..c894a25 100644 --- a/gcc/c-family/c-pragma.h +++ b/gcc/c-family/c-pragma.h @@ -108,6 +108,7 @@ enum pragma_omp_clause { PRAGMA_OMP_CLAUSE_DEVICE, PRAGMA_OMP_CLAUSE_DEVICE_TYPE, PRAGMA_OMP_CLAUSE_DIST_SCHEDULE, + PRAGMA_OMP_CLAUSE_DOACROSS, PRAGMA_OMP_CLAUSE_ENTER, PRAGMA_OMP_CLAUSE_FILTER, PRAGMA_OMP_CLAUSE_FINAL, diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc index e0188cc..65d73a6 100644 --- a/gcc/c/c-parser.cc +++ b/gcc/c/c-parser.cc @@ -12823,6 +12823,8 @@ c_parser_omp_clause_name (c_parser *parser) result = PRAGMA_OMP_CLAUSE_DEVICE_TYPE; else if (!strcmp ("dist_schedule", p)) result = PRAGMA_OMP_CLAUSE_DIST_SCHEDULE; + else if (!strcmp ("doacross", p)) + result = PRAGMA_OMP_CLAUSE_DOACROSS; break; case 'e': if (!strcmp ("enter", p)) @@ -15971,8 +15973,8 @@ c_parser_omp_clause_simdlen (c_parser *parser, tree list) */ static tree -c_parser_omp_clause_depend_sink (c_parser *parser, location_t clause_loc, - tree list) +c_parser_omp_clause_doacross_sink (c_parser *parser, location_t clause_loc, + tree list, bool depend_p) { tree vec = NULL; if (c_parser_next_token_is_not (parser, CPP_NAME) @@ -15982,6 +15984,31 @@ c_parser_omp_clause_depend_sink (c_parser *parser, location_t clause_loc, return list; } + if (!depend_p) + { + const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value); + if (strcmp (p, "omp_cur_iteration") == 0 + && c_parser_peek_2nd_token (parser)->type == CPP_MINUS + && c_parser_peek_nth_token (parser, 3)->type == CPP_NUMBER + && c_parser_peek_nth_token (parser, 4)->type == CPP_CLOSE_PAREN) + { + tree val = c_parser_peek_nth_token (parser, 3)->value; + if (integer_onep (val) + && comptypes (TREE_TYPE (val), integer_type_node)) + { + c_parser_consume_token (parser); + c_parser_consume_token (parser); + c_parser_consume_token (parser); + tree u = build_omp_clause (clause_loc, OMP_CLAUSE_DOACROSS); + OMP_CLAUSE_DOACROSS_KIND (u) = OMP_CLAUSE_DOACROSS_SINK; + OMP_CLAUSE_CHAIN (u) = list; + return u; + } + } + } + + + while (c_parser_next_token_is (parser, CPP_NAME) && c_parser_peek_token (parser)->id_kind == C_ID_ID) { @@ -16027,7 +16054,7 @@ c_parser_omp_clause_depend_sink (c_parser *parser, location_t clause_loc, { vec = tree_cons (addend, t, vec); if (neg) - OMP_CLAUSE_DEPEND_SINK_NEGATIVE (vec) = 1; + OMP_CLAUSE_DOACROSS_SINK_NEGATIVE (vec) = 1; } if (c_parser_next_token_is_not (parser, CPP_COMMA) @@ -16041,8 +16068,9 @@ c_parser_omp_clause_depend_sink (c_parser *parser, location_t clause_loc, if (vec == NULL_TREE) return list; - tree u = build_omp_clause (clause_loc, OMP_CLAUSE_DEPEND); - OMP_CLAUSE_DEPEND_KIND (u) = OMP_CLAUSE_DEPEND_SINK; + tree u = build_omp_clause (clause_loc, OMP_CLAUSE_DOACROSS); + OMP_CLAUSE_DOACROSS_KIND (u) = OMP_CLAUSE_DOACROSS_SINK; + OMP_CLAUSE_DOACROSS_DEPEND (u) = depend_p; OMP_CLAUSE_DECL (u) = nreverse (vec); OMP_CLAUSE_CHAIN (u) = list; return u; @@ -16234,6 +16262,7 @@ c_parser_omp_clause_depend (c_parser *parser, tree list) { location_t clause_loc = c_parser_peek_token (parser)->location; enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_LAST; + enum omp_clause_doacross_kind dkind = OMP_CLAUSE_DOACROSS_LAST; tree nl, c, iterators = NULL_TREE; matching_parens parens; @@ -16265,9 +16294,9 @@ c_parser_omp_clause_depend (c_parser *parser, tree list) else if (strcmp ("depobj", p) == 0) kind = OMP_CLAUSE_DEPEND_DEPOBJ; else if (strcmp ("sink", p) == 0) - kind = OMP_CLAUSE_DEPEND_SINK; + dkind = OMP_CLAUSE_DOACROSS_SINK; else if (strcmp ("source", p) == 0) - kind = OMP_CLAUSE_DEPEND_SOURCE; + dkind = OMP_CLAUSE_DOACROSS_SOURCE; else goto invalid_kind; break; @@ -16277,18 +16306,20 @@ c_parser_omp_clause_depend (c_parser *parser, tree list) c_parser_consume_token (parser); if (iterators - && (kind == OMP_CLAUSE_DEPEND_SOURCE || kind == OMP_CLAUSE_DEPEND_SINK)) + && (dkind == OMP_CLAUSE_DOACROSS_SOURCE + || dkind == OMP_CLAUSE_DOACROSS_SINK)) { pop_scope (); error_at (clause_loc, "%<iterator%> modifier incompatible with %qs", - kind == OMP_CLAUSE_DEPEND_SOURCE ? "source" : "sink"); + dkind == OMP_CLAUSE_DOACROSS_SOURCE ? "source" : "sink"); iterators = NULL_TREE; } - if (kind == OMP_CLAUSE_DEPEND_SOURCE) + if (dkind == OMP_CLAUSE_DOACROSS_SOURCE) { - c = build_omp_clause (clause_loc, OMP_CLAUSE_DEPEND); - OMP_CLAUSE_DEPEND_KIND (c) = kind; + c = build_omp_clause (clause_loc, OMP_CLAUSE_DOACROSS); + OMP_CLAUSE_DOACROSS_KIND (c) = dkind; + OMP_CLAUSE_DOACROSS_DEPEND (c) = 1; OMP_CLAUSE_DECL (c) = NULL_TREE; OMP_CLAUSE_CHAIN (c) = list; parens.skip_until_found_close (parser); @@ -16298,8 +16329,8 @@ c_parser_omp_clause_depend (c_parser *parser, tree list) if (!c_parser_require (parser, CPP_COLON, "expected %<:%>")) goto resync_fail; - if (kind == OMP_CLAUSE_DEPEND_SINK) - nl = c_parser_omp_clause_depend_sink (parser, clause_loc, list); + if (dkind == OMP_CLAUSE_DOACROSS_SINK) + nl = c_parser_omp_clause_doacross_sink (parser, clause_loc, list, true); else { nl = c_parser_omp_variable_list (parser, clause_loc, @@ -16335,6 +16366,65 @@ c_parser_omp_clause_depend (c_parser *parser, tree list) return list; } +/* OpenMP 5.2: + doacross ( source : ) + doacross ( source : omp_cur_iteration ) + + doacross ( sink : vec ) + doacross ( sink : omp_cur_iteration - logical_iteration ) */ + +static tree +c_parser_omp_clause_doacross (c_parser *parser, tree list) +{ + location_t clause_loc = c_parser_peek_token (parser)->location; + enum omp_clause_doacross_kind kind = OMP_CLAUSE_DOACROSS_LAST; + tree nl; + const char *p; + + matching_parens parens; + if (!parens.require_open (parser)) + return list; + + if (c_parser_next_token_is_not (parser, CPP_NAME)) + goto invalid_kind; + + p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value); + if (strcmp ("sink", p) == 0) + kind = OMP_CLAUSE_DOACROSS_SINK; + else if (strcmp ("source", p) == 0) + kind = OMP_CLAUSE_DOACROSS_SOURCE; + else + goto invalid_kind; + + c_parser_consume_token (parser); + + if (!c_parser_require (parser, CPP_COLON, "expected %<:%>")) + goto resync_fail; + + if (kind == OMP_CLAUSE_DOACROSS_SOURCE) + { + if (c_parser_next_token_is (parser, CPP_NAME) + && strcmp (IDENTIFIER_POINTER (c_parser_peek_token (parser)->value), + "omp_cur_iteration") == 0) + c_parser_consume_token (parser); + nl = build_omp_clause (clause_loc, OMP_CLAUSE_DOACROSS); + OMP_CLAUSE_DOACROSS_KIND (nl) = OMP_CLAUSE_DOACROSS_SOURCE; + OMP_CLAUSE_DECL (nl) = NULL_TREE; + OMP_CLAUSE_CHAIN (nl) = list; + } + else + nl = c_parser_omp_clause_doacross_sink (parser, clause_loc, list, false); + + parens.skip_until_found_close (parser); + return nl; + + invalid_kind: + c_parser_error (parser, "invalid doacross kind"); + resync_fail: + parens.skip_until_found_close (parser); + return list; +} + /* OpenMP 4.0: map ( map-kind: variable-list ) map ( variable-list ) @@ -17252,6 +17342,10 @@ c_parser_omp_all_clauses (c_parser *parser, omp_clause_mask mask, clauses = c_parser_omp_clause_depend (parser, clauses); c_name = "depend"; break; + case PRAGMA_OMP_CLAUSE_DOACROSS: + clauses = c_parser_omp_clause_doacross (parser, clauses); + c_name = "doacross"; + break; case PRAGMA_OMP_CLAUSE_MAP: clauses = c_parser_omp_clause_map (parser, clauses); c_name = "map"; @@ -19196,7 +19290,7 @@ c_parser_omp_depobj (c_parser *parser) parens.skip_until_found_close (parser); tree clause = NULL_TREE; - enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_SOURCE; + enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_INVALID; location_t c_loc = c_parser_peek_token (parser)->location; if (c_parser_next_token_is (parser, CPP_NAME)) { @@ -19235,7 +19329,7 @@ c_parser_omp_depobj (c_parser *parser) else if (!strcmp ("inoutset", p2)) kind = OMP_CLAUSE_DEPEND_INOUTSET; } - if (kind == OMP_CLAUSE_DEPEND_SOURCE) + if (kind == OMP_CLAUSE_DEPEND_INVALID) { clause = error_mark_node; error_at (c2_loc, "expected %<in%>, %<out%>, %<inout%>, " @@ -19247,7 +19341,7 @@ c_parser_omp_depobj (c_parser *parser) clause = error_mark_node; } } - if (!clause && kind == OMP_CLAUSE_DEPEND_SOURCE) + if (!clause && kind == OMP_CLAUSE_DEPEND_INVALID) { clause = error_mark_node; error_at (c_loc, "expected %<depend%>, %<destroy%> or %<update%> clause"); @@ -19446,19 +19540,6 @@ c_parser_omp_for_loop (location_t loc, c_parser *parser, enum tree_code code, = build_int_cst (NULL_TREE, collapse); ordered = collapse; } - if (ordered) - { - for (tree *pc = &clauses; *pc; ) - if (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_LINEAR) - { - error_at (OMP_CLAUSE_LOCATION (*pc), - "%<linear%> clause may not be specified together " - "with %<ordered%> clause with a parameter"); - *pc = OMP_CLAUSE_CHAIN (*pc); - } - else - pc = &OMP_CLAUSE_CHAIN (*pc); - } gcc_assert (tiling || (collapse >= 1 && ordered >= 0)); count = ordered ? ordered : collapse; @@ -19896,15 +19977,6 @@ c_parser_omp_simd (location_t loc, c_parser *parser, { omp_split_clauses (loc, OMP_SIMD, mask, clauses, cclauses); clauses = cclauses[C_OMP_CLAUSE_SPLIT_SIMD]; - tree c = omp_find_clause (cclauses[C_OMP_CLAUSE_SPLIT_FOR], - OMP_CLAUSE_ORDERED); - if (c && OMP_CLAUSE_ORDERED_EXPR (c)) - { - error_at (OMP_CLAUSE_LOCATION (c), - "%<ordered%> clause with parameter may not be specified " - "on %qs construct", p_name); - OMP_CLAUSE_ORDERED_EXPR (c) = NULL_TREE; - } } block = c_begin_compound_stmt (true); @@ -20143,14 +20215,18 @@ c_parser_omp_masked (location_t loc, c_parser *parser, # pragma omp ordered ordered-clauses new-line structured-block - # pragma omp ordered depend-clauses new-line */ + # pragma omp ordered depend-clauses new-line + + OpenMP 5.2 + # pragma omp ordered doacross-clauses new-line */ #define OMP_ORDERED_CLAUSE_MASK \ ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_THREADS) \ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SIMD)) #define OMP_ORDERED_DEPEND_CLAUSE_MASK \ - (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) + ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \ + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DOACROSS)) static bool c_parser_omp_ordered (c_parser *parser, enum pragma_context context, @@ -20170,7 +20246,7 @@ c_parser_omp_ordered (c_parser *parser, enum pragma_context context, { const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value); - if (!strcmp ("depend", p)) + if (!strcmp ("depend", p) || !strcmp ("doacross", p)) { if (!flag_openmp) /* flag_openmp_simd */ { @@ -20180,8 +20256,8 @@ c_parser_omp_ordered (c_parser *parser, enum pragma_context context, if (context == pragma_stmt) { error_at (loc, - "%<#pragma omp ordered%> with %<depend%> clause may " - "only be used in compound statements"); + "%<#pragma omp ordered%> with %qs clause may " + "only be used in compound statements", p); c_parser_skip_to_pragma_eol (parser, false); return true; } diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc index 5cb1336..9ada5d2 100644 --- a/gcc/c/c-typeck.cc +++ b/gcc/c/c-typeck.cc @@ -14843,15 +14843,11 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort) } break; - case OMP_CLAUSE_DEPEND: + case OMP_CLAUSE_DOACROSS: t = OMP_CLAUSE_DECL (c); if (t == NULL_TREE) - { - gcc_assert (OMP_CLAUSE_DEPEND_KIND (c) - == OMP_CLAUSE_DEPEND_SOURCE); - break; - } - if (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK) + break; + if (OMP_CLAUSE_DOACROSS_KIND (c) == OMP_CLAUSE_DOACROSS_SINK) { gcc_assert (TREE_CODE (t) == TREE_LIST); for (; t; t = TREE_CHAIN (t)) @@ -14879,7 +14875,8 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort) } break; } - /* FALLTHRU */ + gcc_unreachable (); + case OMP_CLAUSE_DEPEND: case OMP_CLAUSE_AFFINITY: t = OMP_CLAUSE_DECL (c); if (TREE_CODE (t) == TREE_LIST diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc index 13435d2..076ad62 100644 --- a/gcc/cp/parser.cc +++ b/gcc/cp/parser.cc @@ -11994,14 +11994,18 @@ cp_parser_handle_statement_omp_attributes (cp_parser *parser, tree attrs) if (dir->id == PRAGMA_OMP_ORDERED) { /* ordered is C_OMP_DIR_CONSTRUCT only if it doesn't contain - depend clause. */ - if (directive[1] && strcmp (directive[1], "depend") == 0) + depend/doacross clause. */ + if (directive[1] + && (strcmp (directive[1], "depend") == 0 + || strcmp (directive[1], "doacross") == 0)) kind = C_OMP_DIR_STANDALONE; else if (first + 2 < last && first[1].type == CPP_COMMA && first[2].type == CPP_NAME - && strcmp (IDENTIFIER_POINTER (first[2].u.value), - "depend") == 0) + && (strcmp (IDENTIFIER_POINTER (first[2].u.value), + "depend") == 0 + || strcmp (IDENTIFIER_POINTER (first[2].u.value), + "doacross") == 0)) kind = C_OMP_DIR_STANDALONE; } else if (dir->id == PRAGMA_OMP_ERROR) @@ -36602,6 +36606,8 @@ cp_parser_omp_clause_name (cp_parser *parser) result = PRAGMA_OMP_CLAUSE_DEVICE_TYPE; else if (!strcmp ("dist_schedule", p)) result = PRAGMA_OMP_CLAUSE_DIST_SCHEDULE; + else if (!strcmp ("doacross", p)) + result = PRAGMA_OMP_CLAUSE_DOACROSS; break; case 'e': if (!strcmp ("enter", p)) @@ -39329,8 +39335,8 @@ cp_parser_omp_clause_simdlen (cp_parser *parser, tree list, */ static tree -cp_parser_omp_clause_depend_sink (cp_parser *parser, location_t clause_loc, - tree list) +cp_parser_omp_clause_doacross_sink (cp_parser *parser, location_t clause_loc, + tree list, bool depend_p) { tree vec = NULL; @@ -39340,6 +39346,29 @@ cp_parser_omp_clause_depend_sink (cp_parser *parser, location_t clause_loc, return list; } + if (!depend_p) + { + tree id = cp_lexer_peek_token (parser->lexer)->u.value; + if (strcmp (IDENTIFIER_POINTER (id), "omp_cur_iteration") == 0 + && cp_lexer_nth_token_is (parser->lexer, 2, CPP_MINUS) + && cp_lexer_nth_token_is (parser->lexer, 3, CPP_NUMBER) + && cp_lexer_nth_token_is (parser->lexer, 4, CPP_CLOSE_PAREN)) + { + tree val = cp_lexer_peek_nth_token (parser->lexer, 3)->u.value; + if (integer_onep (val) + && same_type_p (TREE_TYPE (val), integer_type_node)) + { + cp_lexer_consume_token (parser->lexer); + cp_lexer_consume_token (parser->lexer); + cp_lexer_consume_token (parser->lexer); + tree u = build_omp_clause (clause_loc, OMP_CLAUSE_DOACROSS); + OMP_CLAUSE_DOACROSS_KIND (u) = OMP_CLAUSE_DOACROSS_SINK; + OMP_CLAUSE_CHAIN (u) = list; + return u; + } + } + } + while (cp_lexer_next_token_is (parser->lexer, CPP_NAME)) { location_t id_loc = cp_lexer_peek_token (parser->lexer)->location; @@ -39387,7 +39416,7 @@ cp_parser_omp_clause_depend_sink (cp_parser *parser, location_t clause_loc, { vec = tree_cons (addend, t, vec); if (neg) - OMP_CLAUSE_DEPEND_SINK_NEGATIVE (vec) = 1; + OMP_CLAUSE_DOACROSS_SINK_NEGATIVE (vec) = 1; } if (cp_lexer_next_token_is_not (parser->lexer, CPP_COMMA) @@ -39399,8 +39428,9 @@ cp_parser_omp_clause_depend_sink (cp_parser *parser, location_t clause_loc, if (vec) { - tree u = build_omp_clause (clause_loc, OMP_CLAUSE_DEPEND); - OMP_CLAUSE_DEPEND_KIND (u) = OMP_CLAUSE_DEPEND_SINK; + tree u = build_omp_clause (clause_loc, OMP_CLAUSE_DOACROSS); + OMP_CLAUSE_DOACROSS_KIND (u) = OMP_CLAUSE_DOACROSS_SINK; + OMP_CLAUSE_DOACROSS_DEPEND (u) = depend_p; OMP_CLAUSE_DECL (u) = nreverse (vec); OMP_CLAUSE_CHAIN (u) = list; return u; @@ -39649,6 +39679,7 @@ cp_parser_omp_clause_depend (cp_parser *parser, tree list, location_t loc) { tree nlist, c, iterators = NULL_TREE; enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_LAST; + enum omp_clause_doacross_kind dkind = OMP_CLAUSE_DOACROSS_LAST; matching_parens parens; if (!parens.require_open (parser)) @@ -39682,9 +39713,9 @@ cp_parser_omp_clause_depend (cp_parser *parser, tree list, location_t loc) else if (strcmp ("depobj", p) == 0) kind = OMP_CLAUSE_DEPEND_DEPOBJ; else if (strcmp ("sink", p) == 0) - kind = OMP_CLAUSE_DEPEND_SINK; + dkind = OMP_CLAUSE_DOACROSS_SINK; else if (strcmp ("source", p) == 0) - kind = OMP_CLAUSE_DEPEND_SOURCE; + dkind = OMP_CLAUSE_DOACROSS_SOURCE; else goto invalid_kind; break; @@ -39694,18 +39725,20 @@ cp_parser_omp_clause_depend (cp_parser *parser, tree list, location_t loc) cp_lexer_consume_token (parser->lexer); if (iterators - && (kind == OMP_CLAUSE_DEPEND_SOURCE || kind == OMP_CLAUSE_DEPEND_SINK)) + && (dkind == OMP_CLAUSE_DOACROSS_SOURCE + || dkind == OMP_CLAUSE_DOACROSS_SINK)) { poplevel (0, 1, 0); error_at (loc, "%<iterator%> modifier incompatible with %qs", - kind == OMP_CLAUSE_DEPEND_SOURCE ? "source" : "sink"); + dkind == OMP_CLAUSE_DOACROSS_SOURCE ? "source" : "sink"); iterators = NULL_TREE; } - if (kind == OMP_CLAUSE_DEPEND_SOURCE) + if (dkind == OMP_CLAUSE_DOACROSS_SOURCE) { - c = build_omp_clause (loc, OMP_CLAUSE_DEPEND); - OMP_CLAUSE_DEPEND_KIND (c) = kind; + c = build_omp_clause (loc, OMP_CLAUSE_DOACROSS); + OMP_CLAUSE_DOACROSS_KIND (c) = dkind; + OMP_CLAUSE_DOACROSS_DEPEND (c) = 1; OMP_CLAUSE_DECL (c) = NULL_TREE; OMP_CLAUSE_CHAIN (c) = list; if (!parens.require_close (parser)) @@ -39718,9 +39751,9 @@ cp_parser_omp_clause_depend (cp_parser *parser, tree list, location_t loc) if (!cp_parser_require (parser, CPP_COLON, RT_COLON)) goto resync_fail; - if (kind == OMP_CLAUSE_DEPEND_SINK) + if (dkind == OMP_CLAUSE_DOACROSS_SINK) { - nlist = cp_parser_omp_clause_depend_sink (parser, loc, list); + nlist = cp_parser_omp_clause_doacross_sink (parser, loc, list, true); if (!parens.require_close (parser)) cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, /*or_comma=*/false, @@ -39761,6 +39794,73 @@ cp_parser_omp_clause_depend (cp_parser *parser, tree list, location_t loc) return list; } +/* OpenMP 5.2: + doacross ( source : ) + doacross ( source : omp_cur_iteration ) + + doacross ( sink : vec ) + doacross ( sink : omp_cur_iteration - logical_iteration ) */ + +static tree +cp_parser_omp_clause_doacross (cp_parser *parser, tree list, location_t loc) +{ + tree nlist; + enum omp_clause_doacross_kind kind = OMP_CLAUSE_DOACROSS_LAST; + + matching_parens parens; + if (!parens.require_open (parser)) + return list; + + if (cp_lexer_next_token_is_not (parser->lexer, CPP_NAME)) + { + invalid_kind: + cp_parser_error (parser, "invalid doacross kind"); + resync_fail: + cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, + /*or_comma=*/false, + /*consume_paren=*/true); + return list; + } + + tree id = cp_lexer_peek_token (parser->lexer)->u.value; + const char *p = IDENTIFIER_POINTER (id); + + if (strcmp ("sink", p) == 0) + kind = OMP_CLAUSE_DOACROSS_SINK; + else if (strcmp ("source", p) == 0) + kind = OMP_CLAUSE_DOACROSS_SOURCE; + else + goto invalid_kind; + + cp_lexer_consume_token (parser->lexer); + + if (!cp_parser_require (parser, CPP_COLON, RT_COLON)) + goto resync_fail; + + if (kind == OMP_CLAUSE_DOACROSS_SOURCE) + { + if (cp_lexer_next_token_is (parser->lexer, CPP_NAME)) + { + id = cp_lexer_peek_token (parser->lexer)->u.value; + p = IDENTIFIER_POINTER (id); + if (strcmp (p, "omp_cur_iteration") == 0) + cp_lexer_consume_token (parser->lexer); + } + nlist = build_omp_clause (loc, OMP_CLAUSE_DOACROSS); + OMP_CLAUSE_DOACROSS_KIND (nlist) = OMP_CLAUSE_DOACROSS_SOURCE; + OMP_CLAUSE_DECL (nlist) = NULL_TREE; + OMP_CLAUSE_CHAIN (nlist) = list; + } + else + nlist = cp_parser_omp_clause_doacross_sink (parser, loc, list, false); + + if (!parens.require_close (parser)) + cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, + /*or_comma=*/false, + /*consume_paren=*/true); + return nlist; +} + /* OpenMP 4.0: map ( map-kind : variable-list ) map ( variable-list ) @@ -40703,6 +40803,11 @@ cp_parser_omp_all_clauses (cp_parser *parser, omp_clause_mask mask, token->location); c_name = "depend"; break; + case PRAGMA_OMP_CLAUSE_DOACROSS: + clauses = cp_parser_omp_clause_doacross (parser, clauses, + token->location); + c_name = "doacross"; + break; case PRAGMA_OMP_CLAUSE_DETACH: clauses = cp_parser_omp_clause_detach (parser, clauses); c_name = "detach"; @@ -41941,7 +42046,7 @@ cp_parser_omp_depobj (cp_parser *parser, cp_token *pragma_tok) /*consume_paren=*/true); tree clause = NULL_TREE; - enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_SOURCE; + enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_INVALID; location_t c_loc = cp_lexer_peek_token (parser->lexer)->location; /* For now only in C++ attributes, do it always for OpenMP 5.1. */ if (parser->lexer->in_omp_attribute_pragma @@ -41989,7 +42094,7 @@ cp_parser_omp_depobj (cp_parser *parser, cp_token *pragma_tok) else if (!strcmp ("inoutset", p2)) kind = OMP_CLAUSE_DEPEND_INOUTSET; } - if (kind == OMP_CLAUSE_DEPEND_SOURCE) + if (kind == OMP_CLAUSE_DEPEND_INVALID) { clause = error_mark_node; error_at (c2_loc, "expected %<in%>, %<out%>, %<inout%>, " @@ -42005,7 +42110,7 @@ cp_parser_omp_depobj (cp_parser *parser, cp_token *pragma_tok) clause = error_mark_node; } } - if (!clause && kind == OMP_CLAUSE_DEPEND_SOURCE) + if (!clause && kind == OMP_CLAUSE_DEPEND_INVALID) { clause = error_mark_node; error_at (c_loc, "expected %<depend%>, %<destroy%> or %<update%> clause"); @@ -42837,19 +42942,6 @@ cp_parser_omp_for_loop (cp_parser *parser, enum tree_code code, tree clauses, = build_int_cst (NULL_TREE, collapse); ordered = collapse; } - if (ordered) - { - for (tree *pc = &clauses; *pc; ) - if (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_LINEAR) - { - error_at (OMP_CLAUSE_LOCATION (*pc), - "%<linear%> clause may not be specified together " - "with %<ordered%> clause with a parameter"); - *pc = OMP_CLAUSE_CHAIN (*pc); - } - else - pc = &OMP_CLAUSE_CHAIN (*pc); - } gcc_assert (tiling || (collapse >= 1 && ordered >= 0)); count = ordered ? ordered : collapse; @@ -43301,15 +43393,6 @@ cp_parser_omp_simd (cp_parser *parser, cp_token *pragma_tok, { cp_omp_split_clauses (loc, OMP_SIMD, mask, clauses, cclauses); clauses = cclauses[C_OMP_CLAUSE_SPLIT_SIMD]; - tree c = omp_find_clause (cclauses[C_OMP_CLAUSE_SPLIT_FOR], - OMP_CLAUSE_ORDERED); - if (c && OMP_CLAUSE_ORDERED_EXPR (c)) - { - error_at (OMP_CLAUSE_LOCATION (c), - "%<ordered%> clause with parameter may not be specified " - "on %qs construct", p_name); - OMP_CLAUSE_ORDERED_EXPR (c) = NULL_TREE; - } } keep_next_level (true); @@ -43571,7 +43654,8 @@ cp_parser_omp_masked (cp_parser *parser, cp_token *pragma_tok, | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SIMD)) #define OMP_ORDERED_DEPEND_CLAUSE_MASK \ - (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) + ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \ + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DOACROSS)) static bool cp_parser_omp_ordered (cp_parser *parser, cp_token *pragma_tok, @@ -43590,7 +43674,7 @@ cp_parser_omp_ordered (cp_parser *parser, cp_token *pragma_tok, tree id = cp_lexer_peek_nth_token (parser->lexer, n)->u.value; const char *p = IDENTIFIER_POINTER (id); - if (strcmp (p, "depend") == 0) + if (strcmp (p, "depend") == 0 || strcmp (p, "doacross") == 0) { if (!flag_openmp) /* flag_openmp_simd */ { @@ -43600,8 +43684,8 @@ cp_parser_omp_ordered (cp_parser *parser, cp_token *pragma_tok, if (context == pragma_stmt) { error_at (pragma_tok->location, "%<#pragma omp ordered%> with " - "%<depend%> clause may only be used in compound " - "statements"); + "%qs clause may only be used in compound " + "statements", p); cp_parser_skip_to_pragma_eol (parser, pragma_tok); return true; } diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc index fe7e809..cd0d892 100644 --- a/gcc/cp/pt.cc +++ b/gcc/cp/pt.cc @@ -17830,8 +17830,8 @@ tsubst_omp_clause_decl (tree decl, tree args, tsubst_flags_t complain, } /* Handle an OpenMP array section represented as a TREE_LIST (or - OMP_CLAUSE_DEPEND_KIND). An OMP_CLAUSE_DEPEND (with a depend - kind of OMP_CLAUSE_DEPEND_SINK) can also be represented as a + OMP_CLAUSE_DOACROSS_KIND). An OMP_CLAUSE_DOACROSS (with a depend + kind of OMP_CLAUSE_DOACROSS_SINK) can also be represented as a TREE_LIST. We can handle it exactly the same as an array section (purpose, value, and a chain), even though the nomenclature (low_bound, length, etc) is different. */ @@ -17849,8 +17849,8 @@ tsubst_omp_clause_decl (tree decl, tree args, tsubst_flags_t complain, && TREE_CHAIN (decl) == chain) return decl; tree ret = tree_cons (low_bound, length, chain); - OMP_CLAUSE_DEPEND_SINK_NEGATIVE (ret) - = OMP_CLAUSE_DEPEND_SINK_NEGATIVE (decl); + OMP_CLAUSE_DOACROSS_SINK_NEGATIVE (ret) + = OMP_CLAUSE_DOACROSS_SINK_NEGATIVE (decl); return ret; } tree ret = tsubst_expr (decl, args, complain, in_decl, @@ -17898,6 +17898,7 @@ tsubst_omp_clauses (tree clauses, enum c_omp_region_type ort, case OMP_CLAUSE_COPYPRIVATE: case OMP_CLAUSE_UNIFORM: case OMP_CLAUSE_DEPEND: + case OMP_CLAUSE_DOACROSS: case OMP_CLAUSE_AFFINITY: case OMP_CLAUSE_FROM: case OMP_CLAUSE_TO: @@ -19414,7 +19415,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl, r = RECUR (OMP_DEPOBJ_DEPOBJ (t)); if (OMP_DEPOBJ_CLAUSES (t) && OMP_DEPOBJ_CLAUSES (t) != error_mark_node) { - enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_SOURCE; + enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_INVALID; if (TREE_CODE (OMP_DEPOBJ_CLAUSES (t)) == OMP_CLAUSE) { tmp = tsubst_omp_clauses (OMP_DEPOBJ_CLAUSES (t), C_ORT_OMP, @@ -19432,7 +19433,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl, } else finish_omp_depobj (EXPR_LOCATION (t), r, - OMP_CLAUSE_DEPEND_SOURCE, + OMP_CLAUSE_DEPEND_INVALID, OMP_DEPOBJ_CLAUSES (t)); break; diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc index ae7c8ea..7b2c495 100644 --- a/gcc/cp/semantics.cc +++ b/gcc/cp/semantics.cc @@ -6477,13 +6477,13 @@ finish_omp_declare_simd_methods (tree t) } } -/* Adjust sink depend clause to take into account pointer offsets. +/* Adjust sink depend/doacross clause to take into account pointer offsets. Return TRUE if there was a problem processing the offset, and the whole clause should be removed. */ static bool -cp_finish_omp_clause_depend_sink (tree sink_clause) +cp_finish_omp_clause_doacross_sink (tree sink_clause) { tree t = OMP_CLAUSE_DECL (sink_clause); gcc_assert (TREE_CODE (t) == TREE_LIST); @@ -7795,21 +7795,18 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) } goto handle_field_decl; - case OMP_CLAUSE_DEPEND: + case OMP_CLAUSE_DOACROSS: t = OMP_CLAUSE_DECL (c); if (t == NULL_TREE) + break; + if (OMP_CLAUSE_DOACROSS_KIND (c) == OMP_CLAUSE_DOACROSS_SINK) { - gcc_assert (OMP_CLAUSE_DEPEND_KIND (c) - == OMP_CLAUSE_DEPEND_SOURCE); - break; - } - if (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK) - { - if (cp_finish_omp_clause_depend_sink (c)) + if (cp_finish_omp_clause_doacross_sink (c)) remove = true; break; } - /* FALLTHRU */ + gcc_unreachable (); + case OMP_CLAUSE_DEPEND: case OMP_CLAUSE_AFFINITY: t = OMP_CLAUSE_DECL (c); if (TREE_CODE (t) == TREE_LIST diff --git a/gcc/fortran/trans-openmp.cc b/gcc/fortran/trans-openmp.cc index de27ed5..82c1079 100644 --- a/gcc/fortran/trans-openmp.cc +++ b/gcc/fortran/trans-openmp.cc @@ -2897,7 +2897,7 @@ gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses, } vec = tree_cons (addend, t, vec); if (neg) - OMP_CLAUSE_DEPEND_SINK_NEGATIVE (vec) = 1; + OMP_CLAUSE_DOACROSS_SINK_NEGATIVE (vec) = 1; } if (n->next == NULL || n->next->u.depend_op != OMP_DEPEND_SINK) @@ -2908,8 +2908,9 @@ gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses, continue; tree node = build_omp_clause (input_location, - OMP_CLAUSE_DEPEND); - OMP_CLAUSE_DEPEND_KIND (node) = OMP_CLAUSE_DEPEND_SINK; + OMP_CLAUSE_DOACROSS); + OMP_CLAUSE_DOACROSS_KIND (node) = OMP_CLAUSE_DOACROSS_SINK; + OMP_CLAUSE_DOACROSS_DEPEND (node) = 1; OMP_CLAUSE_DECL (node) = nreverse (vec); omp_clauses = gfc_trans_add_clause (node, omp_clauses); continue; @@ -4254,8 +4255,9 @@ gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses, if (clauses->depend_source) { - c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_DEPEND); - OMP_CLAUSE_DEPEND_KIND (c) = OMP_CLAUSE_DEPEND_SOURCE; + c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_DOACROSS); + OMP_CLAUSE_DOACROSS_KIND (c) = OMP_CLAUSE_DOACROSS_SOURCE; + OMP_CLAUSE_DOACROSS_DEPEND (c) = 1; omp_clauses = gfc_trans_add_clause (c, omp_clauses); } diff --git a/gcc/gimplify.cc b/gcc/gimplify.cc index b828ddb..988fc93 100644 --- a/gcc/gimplify.cc +++ b/gcc/gimplify.cc @@ -8319,9 +8319,6 @@ gimplify_omp_depend (tree *list_p, gimple_seq *pre_p) case OMP_CLAUSE_DEPEND_INOUTSET: i = 4; break; - case OMP_CLAUSE_DEPEND_SOURCE: - case OMP_CLAUSE_DEPEND_SINK: - continue; default: gcc_unreachable (); } @@ -8560,9 +8557,6 @@ gimplify_omp_depend (tree *list_p, gimple_seq *pre_p) case OMP_CLAUSE_DEPEND_INOUTSET: i = 4; break; - case OMP_CLAUSE_DEPEND_SOURCE: - case OMP_CLAUSE_DEPEND_SINK: - continue; default: gcc_unreachable (); } @@ -10406,8 +10400,8 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p, gimplify_omp_affinity (list_p, pre_p); remove = true; break; - case OMP_CLAUSE_DEPEND: - if (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK) + case OMP_CLAUSE_DOACROSS: + if (OMP_CLAUSE_DOACROSS_KIND (c) == OMP_CLAUSE_DOACROSS_SINK) { tree deps = OMP_CLAUSE_DECL (c); while (deps && TREE_CODE (deps) == TREE_LIST) @@ -10418,10 +10412,12 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p, pre_p, NULL, is_gimple_val, fb_rvalue); deps = TREE_CHAIN (deps); } - break; } - else if (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SOURCE) - break; + else + gcc_assert (OMP_CLAUSE_DOACROSS_KIND (c) + == OMP_CLAUSE_DOACROSS_SOURCE); + break; + case OMP_CLAUSE_DEPEND: if (handled_depend_iterators == -1) handled_depend_iterators = gimplify_omp_depend (list_p, pre_p); if (handled_depend_iterators) @@ -11946,6 +11942,7 @@ gimplify_adjust_omp_clauses (gimple_seq *pre_p, gimple_seq body, tree *list_p, case OMP_CLAUSE_SAFELEN: case OMP_CLAUSE_SIMDLEN: case OMP_CLAUSE_DEPEND: + case OMP_CLAUSE_DOACROSS: case OMP_CLAUSE_PRIORITY: case OMP_CLAUSE_GRAINSIZE: case OMP_CLAUSE_NUM_TASKS: @@ -12429,6 +12426,29 @@ gimplify_omp_taskloop_expr (tree type, tree *tp, gimple_seq *pre_p, OMP_FOR_CLAUSES (orig_for_stmt) = c; } +/* Helper function of gimplify_omp_for, find OMP_ORDERED with + OMP_CLAUSE_DOACROSS clause inside of OMP_FOR's body. */ + +static tree +find_standalone_omp_ordered (tree *tp, int *walk_subtrees, void *) +{ + switch (TREE_CODE (*tp)) + { + case OMP_ORDERED: + if (omp_find_clause (OMP_ORDERED_CLAUSES (*tp), OMP_CLAUSE_DOACROSS)) + return *tp; + break; + case OMP_SIMD: + case OMP_PARALLEL: + case OMP_TARGET: + *walk_subtrees = 0; + break; + default: + break; + } + return NULL_TREE; +} + /* Gimplify the gross structure of an OMP_FOR statement. */ static enum gimplify_status @@ -12804,12 +12824,24 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p) tree c = omp_find_clause (OMP_FOR_CLAUSES (for_stmt), OMP_CLAUSE_ORDERED); bool is_doacross = false; - if (c && OMP_CLAUSE_ORDERED_EXPR (c)) + if (c && walk_tree_without_duplicates (&OMP_FOR_BODY (for_stmt), + find_standalone_omp_ordered, NULL)) { + OMP_CLAUSE_ORDERED_DOACROSS (c) = 1; is_doacross = true; - gimplify_omp_ctxp->loop_iter_var.create (TREE_VEC_LENGTH - (OMP_FOR_INIT (for_stmt)) - * 2); + int len = TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)); + gimplify_omp_ctxp->loop_iter_var.create (len * 2); + for (tree *pc = &OMP_FOR_CLAUSES (for_stmt); *pc; ) + if (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_LINEAR) + { + error_at (OMP_CLAUSE_LOCATION (*pc), + "%<linear%> clause may not be specified together " + "with %<ordered%> clause if stand-alone %<ordered%> " + "construct is nested in it"); + *pc = OMP_CLAUSE_CHAIN (*pc); + } + else + pc = &OMP_CLAUSE_CHAIN (*pc); } int collapse = 1, tile = 0; c = omp_find_clause (OMP_FOR_CLAUSES (for_stmt), OMP_CLAUSE_COLLAPSE); @@ -14882,21 +14914,22 @@ gimplify_omp_ordered (tree expr, gimple_seq body) if (gimplify_omp_ctxp) { for (c = OMP_ORDERED_CLAUSES (expr); c; c = OMP_CLAUSE_CHAIN (c)) - if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND - && gimplify_omp_ctxp->loop_iter_var.is_empty () - && (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK - || OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SOURCE)) + if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DOACROSS + && gimplify_omp_ctxp->loop_iter_var.is_empty ()) { error_at (OMP_CLAUSE_LOCATION (c), - "%<ordered%> construct with %<depend%> clause must be " - "closely nested inside a loop with %<ordered%> clause " - "with a parameter"); + "%<ordered%> construct with %qs clause must be " + "closely nested inside a loop with %<ordered%> clause", + OMP_CLAUSE_DOACROSS_DEPEND (c) ? "depend" : "doacross"); failures++; } - else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND - && OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK) + else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DOACROSS + && OMP_CLAUSE_DOACROSS_KIND (c) == OMP_CLAUSE_DOACROSS_SINK) { bool fail = false; + sink_c = c; + if (OMP_CLAUSE_DECL (c) == NULL_TREE) + continue; /* omp_cur_iteration - 1 */ for (decls = OMP_CLAUSE_DECL (c), i = 0; decls && TREE_CODE (decls) == TREE_LIST; decls = TREE_CHAIN (decls), ++i) @@ -14919,21 +14952,24 @@ gimplify_omp_ordered (tree expr, gimple_seq body) if (!fail && i != gimplify_omp_ctxp->loop_iter_var.length () / 2) { error_at (OMP_CLAUSE_LOCATION (c), - "number of variables in %<depend%> clause with " + "number of variables in %qs clause with " "%<sink%> modifier does not match number of " - "iteration variables"); + "iteration variables", + OMP_CLAUSE_DOACROSS_DEPEND (c) + ? "depend" : "doacross"); failures++; } - sink_c = c; } - else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND - && OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SOURCE) + else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DOACROSS + && OMP_CLAUSE_DOACROSS_KIND (c) == OMP_CLAUSE_DOACROSS_SOURCE) { if (source_c) { error_at (OMP_CLAUSE_LOCATION (c), - "more than one %<depend%> clause with %<source%> " - "modifier on an %<ordered%> construct"); + "more than one %qs clause with %<source%> " + "modifier on an %<ordered%> construct", + OMP_CLAUSE_DOACROSS_DEPEND (source_c) + ? "depend" : "doacross"); failures++; } else @@ -14943,9 +14979,11 @@ gimplify_omp_ordered (tree expr, gimple_seq body) if (source_c && sink_c) { error_at (OMP_CLAUSE_LOCATION (source_c), - "%<depend%> clause with %<source%> modifier specified " - "together with %<depend%> clauses with %<sink%> modifier " - "on the same construct"); + "%qs clause with %<source%> modifier specified " + "together with %qs clauses with %<sink%> modifier " + "on the same construct", + OMP_CLAUSE_DOACROSS_DEPEND (source_c) ? "depend" : "doacross", + OMP_CLAUSE_DOACROSS_DEPEND (sink_c) ? "depend" : "doacross"); failures++; } diff --git a/gcc/lto-streamer-out.cc b/gcc/lto-streamer-out.cc index 471f35c..1bc3f55 100644 --- a/gcc/lto-streamer-out.cc +++ b/gcc/lto-streamer-out.cc @@ -1553,6 +1553,9 @@ hash_tree (struct streamer_tree_cache_d *cache, hash_map<tree, hashval_t> *map, case OMP_CLAUSE_DEPEND: val = OMP_CLAUSE_DEPEND_KIND (t); break; + case OMP_CLAUSE_DOACROSS: + val = OMP_CLAUSE_DOACROSS_KIND (t); + break; case OMP_CLAUSE_MAP: val = OMP_CLAUSE_MAP_KIND (t); break; diff --git a/gcc/omp-expand.cc b/gcc/omp-expand.cc index fcaf4f6..55c513d 100644 --- a/gcc/omp-expand.cc +++ b/gcc/omp-expand.cc @@ -3298,6 +3298,11 @@ expand_omp_ordered_sink (gimple_stmt_iterator *gsi, struct omp_for_data *fd, gimple_stmt_iterator gsi2 = *gsi; bool warned_step = false; + if (deps == NULL) + { + sorry_at (loc, "%<doacross(sink:omp_cur_iteration-1)%> not supported yet"); + return; + } for (i = 0; i < fd->ordered; i++) { tree step = NULL_TREE; @@ -3321,9 +3326,11 @@ expand_omp_ordered_sink (gimple_stmt_iterator *gsi, struct omp_for_data *fd, break; forward = tree_int_cst_sgn (step) != -1; } - if (forward ^ OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps)) - warning_at (loc, 0, "%<depend%> clause with %<sink%> modifier " - "waiting for lexically later iteration"); + if (forward ^ OMP_CLAUSE_DOACROSS_SINK_NEGATIVE (deps)) + warning_at (loc, 0, "%qs clause with %<sink%> modifier " + "waiting for lexically later iteration", + OMP_CLAUSE_DOACROSS_DEPEND (c) + ? "depend" : "doacross"); break; } deps = TREE_CHAIN (deps); @@ -3377,13 +3384,13 @@ expand_omp_ordered_sink (gimple_stmt_iterator *gsi, struct omp_for_data *fd, tree co = fold_convert_loc (loc, itype, off); if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v))) { - if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps)) + if (OMP_CLAUSE_DOACROSS_SINK_NEGATIVE (deps)) co = fold_build1_loc (loc, NEGATE_EXPR, itype, co); a = fold_build2_loc (loc, POINTER_PLUS_EXPR, TREE_TYPE (fd->loops[i].v), fd->loops[i].v, co); } - else if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps)) + else if (OMP_CLAUSE_DOACROSS_SINK_NEGATIVE (deps)) a = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (fd->loops[i].v), fd->loops[i].v, co); else @@ -3392,13 +3399,13 @@ expand_omp_ordered_sink (gimple_stmt_iterator *gsi, struct omp_for_data *fd, if (step) { tree t1, t2; - if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps)) + if (OMP_CLAUSE_DOACROSS_SINK_NEGATIVE (deps)) t1 = fold_build2_loc (loc, GE_EXPR, boolean_type_node, a, fd->loops[i].n1); else t1 = fold_build2_loc (loc, LT_EXPR, boolean_type_node, a, fd->loops[i].n2); - if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps)) + if (OMP_CLAUSE_DOACROSS_SINK_NEGATIVE (deps)) t2 = fold_build2_loc (loc, LT_EXPR, boolean_type_node, a, fd->loops[i].n2); else @@ -3420,14 +3427,14 @@ expand_omp_ordered_sink (gimple_stmt_iterator *gsi, struct omp_for_data *fd, } else if (fd->loops[i].cond_code == LT_EXPR) { - if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps)) + if (OMP_CLAUSE_DOACROSS_SINK_NEGATIVE (deps)) t = fold_build2_loc (loc, GE_EXPR, boolean_type_node, a, fd->loops[i].n1); else t = fold_build2_loc (loc, LT_EXPR, boolean_type_node, a, fd->loops[i].n2); } - else if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps)) + else if (OMP_CLAUSE_DOACROSS_SINK_NEGATIVE (deps)) t = fold_build2_loc (loc, GT_EXPR, boolean_type_node, a, fd->loops[i].n2); else @@ -3459,9 +3466,11 @@ expand_omp_ordered_sink (gimple_stmt_iterator *gsi, struct omp_for_data *fd, build_int_cst (itype, 0)); if (integer_zerop (t) && !warned_step) { - warning_at (loc, 0, "%<depend%> clause with %<sink%> modifier " + warning_at (loc, 0, "%qs clause with %<sink%> modifier " "refers to iteration never in the iteration " - "space"); + "space", + OMP_CLAUSE_DOACROSS_DEPEND (c) + ? "depend" : "doacross"); warned_step = true; } cond = fold_build2_loc (loc, BIT_AND_EXPR, boolean_type_node, @@ -3486,7 +3495,7 @@ expand_omp_ordered_sink (gimple_stmt_iterator *gsi, struct omp_for_data *fd, s)); else off = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, off, s); - if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps)) + if (OMP_CLAUSE_DOACROSS_SINK_NEGATIVE (deps)) off = fold_build1_loc (loc, NEGATE_EXPR, itype, off); off = fold_convert_loc (loc, fd->iter_type, off); if (i <= fd->collapse - 1 && fd->collapse > 1) @@ -3559,13 +3568,13 @@ expand_omp_ordered_source_sink (struct omp_region *region, tree c; for (c = gimple_omp_ordered_clauses (ord_stmt); c; c = OMP_CLAUSE_CHAIN (c)) - if (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SOURCE) + if (OMP_CLAUSE_DOACROSS_KIND (c) == OMP_CLAUSE_DOACROSS_SOURCE) break; if (c) expand_omp_ordered_source (&gsi, fd, counts, loc); for (c = gimple_omp_ordered_clauses (ord_stmt); c; c = OMP_CLAUSE_CHAIN (c)) - if (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK) + if (OMP_CLAUSE_DOACROSS_KIND (c) == OMP_CLAUSE_DOACROSS_SINK) expand_omp_ordered_sink (&gsi, fd, counts, c, loc); gsi_remove (&gsi, true); } @@ -10479,7 +10488,7 @@ expand_omp (struct omp_region *region) gomp_ordered *ord_stmt = as_a <gomp_ordered *> (last_stmt (region->entry)); if (omp_find_clause (gimple_omp_ordered_clauses (ord_stmt), - OMP_CLAUSE_DEPEND)) + OMP_CLAUSE_DOACROSS)) { /* We'll expand these when expanding corresponding worksharing region with ordered(n) clause. */ @@ -10609,7 +10618,7 @@ build_omp_regions_1 (basic_block bb, struct omp_region *parent, else if (code == GIMPLE_OMP_ORDERED && omp_find_clause (gimple_omp_ordered_clauses (as_a <gomp_ordered *> (stmt)), - OMP_CLAUSE_DEPEND)) + OMP_CLAUSE_DOACROSS)) /* #pragma omp ordered depend is also just a stand-alone directive. */ region = NULL; @@ -10835,7 +10844,7 @@ omp_make_gimple_edges (basic_block bb, struct omp_region **region, fallthru = true; if (omp_find_clause (gimple_omp_ordered_clauses (as_a <gomp_ordered *> (last)), - OMP_CLAUSE_DEPEND)) + OMP_CLAUSE_DOACROSS)) cur_region = cur_region->outer; break; diff --git a/gcc/omp-general.cc b/gcc/omp-general.cc index 33792ad..0b4ec82 100644 --- a/gcc/omp-general.cc +++ b/gcc/omp-general.cc @@ -241,8 +241,13 @@ omp_extract_for_data (gomp_for *for_stmt, struct omp_for_data *fd, break; case OMP_CLAUSE_ORDERED: fd->have_ordered = true; - if (OMP_CLAUSE_ORDERED_EXPR (t)) - fd->ordered = tree_to_shwi (OMP_CLAUSE_ORDERED_EXPR (t)); + if (OMP_CLAUSE_ORDERED_DOACROSS (t)) + { + if (OMP_CLAUSE_ORDERED_EXPR (t)) + fd->ordered = tree_to_shwi (OMP_CLAUSE_ORDERED_EXPR (t)); + else + fd->ordered = -1; + } break; case OMP_CLAUSE_SCHEDULE: gcc_assert (!distribute && !taskloop); @@ -301,6 +306,9 @@ omp_extract_for_data (gomp_for *for_stmt, struct omp_for_data *fd, break; } + if (fd->ordered == -1) + fd->ordered = fd->collapse; + /* For order(reproducible:concurrent) schedule ({dynamic,guided,runtime}) we have either the option to expensively remember at runtime how we've distributed work from first loop and reuse that in following loops with diff --git a/gcc/omp-low.cc b/gcc/omp-low.cc index e9e4bd0..b32336b 100644 --- a/gcc/omp-low.cc +++ b/gcc/omp-low.cc @@ -3636,14 +3636,13 @@ check_omp_nesting_restrictions (gimple *stmt, omp_context *ctx) break; case GIMPLE_OMP_TASK: for (c = gimple_omp_task_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c)) - if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND - && (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SOURCE - || OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK)) + if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DOACROSS) { - enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_KIND (c); + enum omp_clause_doacross_kind kind = OMP_CLAUSE_DOACROSS_KIND (c); error_at (OMP_CLAUSE_LOCATION (c), - "%<depend(%s)%> is only allowed in %<omp ordered%>", - kind == OMP_CLAUSE_DEPEND_SOURCE ? "source" : "sink"); + "%<%s(%s)%> is only allowed in %<omp ordered%>", + OMP_CLAUSE_DOACROSS_DEPEND (c) ? "depend" : "doacross", + kind == OMP_CLAUSE_DOACROSS_SOURCE ? "source" : "sink"); return false; } break; @@ -3651,43 +3650,30 @@ check_omp_nesting_restrictions (gimple *stmt, omp_context *ctx) for (c = gimple_omp_ordered_clauses (as_a <gomp_ordered *> (stmt)); c; c = OMP_CLAUSE_CHAIN (c)) { - if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND) + if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DOACROSS) { - gcc_assert (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_THREADS - || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SIMD); - continue; - } - enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_KIND (c); - if (kind == OMP_CLAUSE_DEPEND_SOURCE - || kind == OMP_CLAUSE_DEPEND_SINK) - { - tree oclause; - /* Look for containing ordered(N) loop. */ - if (ctx == NULL - || gimple_code (ctx->stmt) != GIMPLE_OMP_FOR - || (oclause - = omp_find_clause (gimple_omp_for_clauses (ctx->stmt), - OMP_CLAUSE_ORDERED)) == NULL_TREE) - { - error_at (OMP_CLAUSE_LOCATION (c), - "%<ordered%> construct with %<depend%> clause " - "must be closely nested inside an %<ordered%> " - "loop"); - return false; - } - else if (OMP_CLAUSE_ORDERED_EXPR (oclause) == NULL_TREE) + if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND) { error_at (OMP_CLAUSE_LOCATION (c), - "%<ordered%> construct with %<depend%> clause " - "must be closely nested inside a loop with " - "%<ordered%> clause with a parameter"); + "invalid depend kind in omp %<ordered%> %<depend%>"); return false; } + gcc_assert (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_THREADS + || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SIMD); + continue; } - else + + tree oclause; + /* Look for containing ordered(N) loop. */ + if (ctx == NULL + || gimple_code (ctx->stmt) != GIMPLE_OMP_FOR + || (oclause + = omp_find_clause (gimple_omp_for_clauses (ctx->stmt), + OMP_CLAUSE_ORDERED)) == NULL_TREE) { error_at (OMP_CLAUSE_LOCATION (c), - "invalid depend kind in omp %<ordered%> %<depend%>"); + "%<ordered%> construct with %<depend%> clause " + "must be closely nested inside an %<ordered%> loop"); return false; } } @@ -3732,14 +3718,37 @@ check_omp_nesting_restrictions (gimple *stmt, omp_context *ctx) "a loop region with an %<ordered%> clause"); return false; } - if (OMP_CLAUSE_ORDERED_EXPR (o) != NULL_TREE - && omp_find_clause (c, OMP_CLAUSE_DEPEND) == NULL_TREE) + if (omp_find_clause (c, OMP_CLAUSE_DOACROSS) == NULL_TREE) { - error_at (gimple_location (stmt), - "%<ordered%> region without %<depend%> clause may " - "not be closely nested inside a loop region with " - "an %<ordered%> clause with a parameter"); - return false; + if (OMP_CLAUSE_ORDERED_DOACROSS (o)) + { + error_at (gimple_location (stmt), + "%<ordered%> construct without %<doacross%> or " + "%<depend%> clauses must not have the same " + "binding region as %<ordered%> construct with " + "those clauses"); + return false; + } + else if (OMP_CLAUSE_ORDERED_EXPR (o)) + { + tree co + = omp_find_clause (gimple_omp_for_clauses (ctx->stmt), + OMP_CLAUSE_COLLAPSE); + HOST_WIDE_INT + o_n = tree_to_shwi (OMP_CLAUSE_ORDERED_EXPR (o)); + HOST_WIDE_INT c_n = 1; + if (co) + c_n = tree_to_shwi (OMP_CLAUSE_COLLAPSE_EXPR (co)); + if (o_n != c_n) + { + error_at (gimple_location (stmt), + "%<ordered%> construct without %<doacross%> " + "or %<depend%> clauses binds to loop where " + "%<collapse%> argument %wd is different from " + "%<ordered%> argument %wd", c_n, o_n); + return false; + } + } } return true; case GIMPLE_OMP_TARGET: @@ -3793,14 +3802,12 @@ check_omp_nesting_restrictions (gimple *stmt, omp_context *ctx) break; case GIMPLE_OMP_TARGET: for (c = gimple_omp_target_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c)) - if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND - && (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SOURCE - || OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK)) + if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DOACROSS) { - enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_KIND (c); + enum omp_clause_doacross_kind kind = OMP_CLAUSE_DOACROSS_KIND (c); error_at (OMP_CLAUSE_LOCATION (c), "%<depend(%s)%> is only allowed in %<omp ordered%>", - kind == OMP_CLAUSE_DEPEND_SOURCE ? "source" : "sink"); + kind == OMP_CLAUSE_DOACROSS_SOURCE ? "source" : "sink"); return false; } if (is_gimple_omp_offloaded (stmt) @@ -9740,8 +9747,8 @@ lower_omp_ordered_clauses (gimple_stmt_iterator *gsi_p, gomp_ordered *ord_stmt, tree *list_p = gimple_omp_ordered_clauses_ptr (ord_stmt); tree c = gimple_omp_ordered_clauses (ord_stmt); - if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND - && OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK) + if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DOACROSS + && OMP_CLAUSE_DOACROSS_KIND (c) == OMP_CLAUSE_DOACROSS_SINK) { /* Merge depend clauses from multiple adjacent #pragma omp ordered depend(sink:...) constructs @@ -9763,8 +9770,8 @@ lower_omp_ordered_clauses (gimple_stmt_iterator *gsi_p, gomp_ordered *ord_stmt, gomp_ordered *ord_stmt2 = as_a <gomp_ordered *> (stmt); c = gimple_omp_ordered_clauses (ord_stmt2); if (c == NULL_TREE - || OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND - || OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_SINK) + || OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DOACROSS + || OMP_CLAUSE_DOACROSS_KIND (c) != OMP_CLAUSE_DOACROSS_SINK) break; while (*list_p) list_p = &OMP_CLAUSE_CHAIN (*list_p); @@ -9831,8 +9838,8 @@ lower_omp_ordered_clauses (gimple_stmt_iterator *gsi_p, gomp_ordered *ord_stmt, { bool remove = false; - gcc_assert (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND); - if (OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_SINK) + gcc_assert (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DOACROSS); + if (OMP_CLAUSE_DOACROSS_KIND (c) != OMP_CLAUSE_DOACROSS_SINK) goto next_ordered_clause; tree vec; @@ -9983,7 +9990,7 @@ lower_omp_ordered (gimple_stmt_iterator *gsi_p, omp_context *ctx) OMP_CLAUSE_THREADS); if (omp_find_clause (gimple_omp_ordered_clauses (ord_stmt), - OMP_CLAUSE_DEPEND)) + OMP_CLAUSE_DOACROSS)) { /* FIXME: This is needs to be moved to the expansion to verify various conditions only testable on cfg with dominators computed, and also @@ -12359,9 +12366,6 @@ lower_depend_clauses (tree *pclauses, gimple_seq *iseq, gimple_seq *oseq) case OMP_CLAUSE_DEPEND_INOUTSET: cnt[4]++; break; - case OMP_CLAUSE_DEPEND_SOURCE: - case OMP_CLAUSE_DEPEND_SINK: - /* FALLTHRU */ default: gcc_unreachable (); } diff --git a/gcc/testsuite/c-c++-common/gomp/doacross-2.c b/gcc/testsuite/c-c++-common/gomp/doacross-2.c index cc45487..44c5c21 100644 --- a/gcc/testsuite/c-c++-common/gomp/doacross-2.c +++ b/gcc/testsuite/c-c++-common/gomp/doacross-2.c @@ -7,13 +7,13 @@ foo (void) #pragma omp for ordered(1) for (i = 0; i < 64; i++) { - #pragma omp ordered /* { dg-error "'ordered' region without 'depend' clause may not be closely nested inside a loop region with an 'ordered' clause with a parameter" } */ + #pragma omp ordered ; } #pragma omp for ordered(1) for (i = 0; i < 64; i++) { - #pragma omp ordered threads /* { dg-error "'ordered' region without 'depend' clause may not be closely nested inside a loop region with an 'ordered' clause with a parameter" } */ + #pragma omp ordered threads ; } } @@ -25,14 +25,20 @@ bar (void) #pragma omp for ordered for (i = 0; i < 64; i++) { - #pragma omp ordered depend(source) /* { dg-error "'ordered' construct with 'depend' clause must be closely nested inside a loop with 'ordered' clause with a parameter" } */ - #pragma omp ordered depend(sink: i - 1) /* { dg-error "'ordered' construct with 'depend' clause must be closely nested inside a loop with 'ordered' clause with a parameter" } */ + #pragma omp ordered depend(source) + #pragma omp ordered depend(sink: i - 1) + } + #pragma omp for ordered + for (i = 0; i < 64; i++) + { + #pragma omp ordered doacross(source:) + #pragma omp ordered doacross(sink: i - 1) } #pragma omp for for (i = 0; i < 64; i++) { - #pragma omp ordered depend(source) /* { dg-error "'ordered' construct with 'depend' clause must be closely nested inside a loop with 'ordered' clause with a parameter" } */ - #pragma omp ordered depend(sink: i - 1) /* { dg-error "'ordered' construct with 'depend' clause must be closely nested inside a loop with 'ordered' clause with a parameter" } */ + #pragma omp ordered depend(source) /* { dg-error "'ordered' construct with 'depend' clause must be closely nested inside a loop with 'ordered' clause" } */ + #pragma omp ordered depend(sink: i - 1) /* { dg-error "'ordered' construct with 'depend' clause must be closely nested inside a loop with 'ordered' clause" } */ } #pragma omp for for (i = 0; i < 64; i++) diff --git a/gcc/testsuite/c-c++-common/gomp/doacross-5.c b/gcc/testsuite/c-c++-common/gomp/doacross-5.c new file mode 100644 index 0000000..9dd6dbf4 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/doacross-5.c @@ -0,0 +1,94 @@ +void +foo (int n) +{ + int i; + #pragma omp for ordered + for (i = 0; i < 8; i += n) + { + #pragma omp ordered doacross(source:) + #pragma omp ordered doacross(sink: i - 2) + } +} + +void +bar (int n) +{ + int i, j; + #pragma omp for collapse(2) ordered(2) + for (i = 0; i < 8; i += n) + for (j = 0; j < 8; j += n) + { + #pragma omp ordered doacross(source:omp_cur_iteration) + #pragma omp ordered doacross(sink: i - 2, j + 2) + } +} + +void +baz (void) +{ + int i, j; + #pragma omp for ordered(1) + for (i = 0; i < 64; i++) + { + #pragma omp ordered /* { dg-error "'ordered' construct without 'doacross' or 'depend' clauses must not have the same binding region as 'ordered' construct with those clauses" } */ + ; + #pragma omp ordered doacross(source:) + #pragma omp ordered doacross(sink: i - 1) + } + #pragma omp for ordered + for (i = 0; i < 64; i++) + { + #pragma omp ordered doacross(source: omp_cur_iteration ) + #pragma omp ordered doacross(sink: i - 1) + #pragma omp ordered threads /* { dg-error "'ordered' construct without 'doacross' or 'depend' clauses must not have the same binding region as 'ordered' construct with those clauses" } */ + ; + } + #pragma omp for ordered(2) + for (i = 0; i < 8; i++) + for (j = 0; j < 8; j++) + { + #pragma omp ordered /* { dg-error "'ordered' construct without 'doacross' or 'depend' clauses binds to loop where 'collapse' argument 1 is different from 'ordered' argument 2" } */ + ; + } + #pragma omp for ordered(2) collapse(1) + for (i = 0; i < 8; i++) + for (j = 0; j < 8; j++) + { + #pragma omp ordered threads /* { dg-error "'ordered' construct without 'doacross' or 'depend' clauses binds to loop where 'collapse' argument 1 is different from 'ordered' argument 2" } */ + ; + } +} + +void +qux (void) +{ + int i, j = 0; + #pragma omp for ordered linear(j) + for (i = 0; i < 64; i++) + { + ++j; + #pragma omp ordered + ; + } + #pragma omp for ordered linear(j) /* { dg-error "'linear' clause may not be specified together with 'ordered' clause if stand-alone 'ordered' construct is nested in it" } */ + for (i = 0; i < 64; i++) + { + ++j; + #pragma omp ordered doacross(source:) + #pragma omp ordered doacross(sink:i-1) + } + #pragma omp for ordered(1) linear(j) + for (i = 0; i < 64; i++) + { + ++j; + #pragma omp ordered + ; + } + #pragma omp for ordered(1) linear(j) /* { dg-error "'linear' clause may not be specified together with 'ordered' clause if stand-alone 'ordered' construct is nested in it" } */ + for (i = 0; i < 64; i++) + { + ++j; + #pragma omp ordered doacross(source:) + #pragma omp ordered doacross(sink:i-1) + } +} diff --git a/gcc/testsuite/c-c++-common/gomp/doacross-6.c b/gcc/testsuite/c-c++-common/gomp/doacross-6.c new file mode 100644 index 0000000..d126ad1 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/doacross-6.c @@ -0,0 +1,74 @@ +void +foo (int n) +{ + int i; + #pragma omp for ordered + for (i = 0; i < 8; i += n) + { + #pragma omp ordered doacross(source) /* { dg-error "expected ':' before '\\\)' token" } */ + } + #pragma omp for ordered + for (i = 0; i < 8; i += n) + { + #pragma omp ordered doacross(source:omp_current_iteration) /* { dg-error "expected '\\\)' before 'omp_current_iteration'" } */ + } + #pragma omp for ordered + for (i = 0; i < 8; i += n) + { + #pragma omp ordered doacross(source:i - 2) /* { dg-error "expected '\\\)' before 'i'" } */ + } + #pragma omp for ordered + for (i = 0; i < 8; i += n) + { + #pragma omp ordered doacross(sink) /* { dg-error "expected ':' before '\\\)' token" } */ + } +} + +void +bar (int n) +{ + int i; + #pragma omp for ordered + for (i = 0; i < 8; i += n) + { + #pragma omp ordered doacross(sink:omp_current_iteration - 1) /* { dg-error "'omp_current_iteration' undeclared \\\(first use in this function\\\)" "" { target c } } */ + } /* { dg-error "'omp_current_iteration' has not been declared" "" { target c++ } .-1 } */ + #pragma omp for ordered + for (i = 0; i < 8; i += n) + { + #pragma omp ordered doacross(sink:omp_cur_iteration) /* { dg-error "'omp_cur_iteration' undeclared \\\(first use in this function\\\)" "" { target c } } */ + } /* { dg-error "'omp_cur_iteration' has not been declared" "" { target c++ } .-1 } */ +} + +void +baz (int n) +{ + int i; + #pragma omp for ordered + for (i = 0; i < 8; i += n) + { + #pragma omp ordered doacross(sink:omp_cur_iteration + 1) /* { dg-error "'omp_cur_iteration' undeclared \\\(first use in this function\\\)" "" { target c } } */ + } /* { dg-error "'omp_cur_iteration' has not been declared" "" { target c++ } .-1 } */ +} + +void +qux (int n) +{ + int i; + #pragma omp for ordered + for (i = 0; i < 8; i += n) + { + #pragma omp ordered doacross(sink:omp_cur_iteration - (2 - 1)) /* { dg-error "'omp_cur_iteration' undeclared \\\(first use in this function\\\)" "" { target c } } */ + } /* { dg-error "expected integer before '\\\(' token" "" { target *-*-* } .-1 } */ +} /* { dg-error "'omp_cur_iteration' has not been declared" "" { target c++ } .-2 } */ + /* { dg-error "expected '\\\)' before '\\\(' token" "" { target c++ } .-3 } */ +void +corge (int n) +{ + int i; + #pragma omp for ordered + for (i = 0; i < 8; i += n) + { + #pragma omp ordered doacross(sink:omp_cur_iteration - 1LL) /* { dg-error "'omp_cur_iteration' undeclared \\\(first use in this function\\\)" "" { target c } } */ + } /* { dg-error "'omp_cur_iteration' has not been declared" "" { target c++ } .-1 } */ +} diff --git a/gcc/testsuite/c-c++-common/gomp/nesting-2.c b/gcc/testsuite/c-c++-common/gomp/nesting-2.c index 420cfd3..6ce560d 100644 --- a/gcc/testsuite/c-c++-common/gomp/nesting-2.c +++ b/gcc/testsuite/c-c++-common/gomp/nesting-2.c @@ -160,7 +160,14 @@ foo (void) for (i = 0; i < 64; i++) #pragma omp parallel { - #pragma omp ordered depend(source) /* { dg-error ".ordered. construct with .depend. clause must be closely nested inside a loop with .ordered. clause with a parameter" } */ - #pragma omp ordered depend(sink: i - 1) /* { dg-error ".ordered. construct with .depend. clause must be closely nested inside a loop with .ordered. clause with a parameter" } */ + #pragma omp ordered depend(source) /* { dg-error ".ordered. construct with .depend. clause must be closely nested inside a loop with .ordered. clause" } */ + #pragma omp ordered depend(sink: i - 1) /* { dg-error ".ordered. construct with .depend. clause must be closely nested inside a loop with .ordered. clause" } */ + } + #pragma omp for ordered(1) + for (i = 0; i < 64; i++) + #pragma omp parallel + { + #pragma omp ordered doacross(source:) /* { dg-error ".ordered. construct with .doacross. clause must be closely nested inside a loop with .ordered. clause" } */ + #pragma omp ordered doacross(sink: i - 1) /* { dg-error ".ordered. construct with .doacross. clause must be closely nested inside a loop with .ordered. clause" } */ } } diff --git a/gcc/testsuite/c-c++-common/gomp/ordered-3.c b/gcc/testsuite/c-c++-common/gomp/ordered-3.c index e7fd738..b007ca7 100644 --- a/gcc/testsuite/c-c++-common/gomp/ordered-3.c +++ b/gcc/testsuite/c-c++-common/gomp/ordered-3.c @@ -47,29 +47,53 @@ foo (void) #pragma omp ordered threads, simd, threads, simd /* { dg-error "too many .threads. clauses" } */ ; /* { dg-error "too many .simd. clauses" "" { target *-*-* } .-1 } */ } - #pragma omp for simd ordered(1) /* { dg-error ".ordered. clause with parameter may not be specified on .#pragma omp for simd. construct" } */ + #pragma omp for simd ordered(1) for (i = 0; i < 64; i++) { - #pragma omp ordered depend(sink: i - 1) /* { dg-error "clause must be closely nested inside a loop with .ordered. clause with a parameter" } */ - #pragma omp ordered depend(source) /* { dg-error "clause must be closely nested inside a loop with .ordered. clause with a parameter" } */ + #pragma omp ordered depend(sink: i - 1) /* { dg-error "clause must be closely nested inside a loop with .ordered. clause" } */ + #pragma omp ordered depend(source) /* { dg-error "clause must be closely nested inside a loop with .ordered. clause" } */ } - #pragma omp parallel for simd ordered(1) /* { dg-error ".ordered. clause with parameter may not be specified on .#pragma omp parallel for simd. construct" } */ + #pragma omp for simd ordered(1) for (i = 0; i < 64; i++) { - #pragma omp ordered depend(sink: i - 1) /* { dg-error "clause must be closely nested inside a loop with .ordered. clause with a parameter" } */ - #pragma omp ordered depend(source) /* { dg-error "clause must be closely nested inside a loop with .ordered. clause with a parameter" } */ + #pragma omp ordered doacross(sink: i - 1) /* { dg-error "clause must be closely nested inside a loop with .ordered. clause" } */ + #pragma omp ordered doacross(source:omp_cur_iteration) /* { dg-error "clause must be closely nested inside a loop with .ordered. clause" } */ + } + #pragma omp parallel for simd ordered(1) + for (i = 0; i < 64; i++) + { + #pragma omp ordered depend(sink: i - 1) /* { dg-error "clause must be closely nested inside a loop with .ordered. clause" } */ + #pragma omp ordered depend(source) /* { dg-error "clause must be closely nested inside a loop with .ordered. clause" } */ + } + #pragma omp parallel for simd ordered(1) + for (i = 0; i < 64; i++) + { + #pragma omp ordered doacross(sink: i - 1) /* { dg-error "clause must be closely nested inside a loop with .ordered. clause" } */ + #pragma omp ordered doacross(source:) /* { dg-error "clause must be closely nested inside a loop with .ordered. clause" } */ + } + #pragma omp parallel for ordered + for (i = 0; i < 64; i++) + { + #pragma omp ordered depend(sink: i - 1) + #pragma omp ordered depend(source) } #pragma omp parallel for ordered for (i = 0; i < 64; i++) { - #pragma omp ordered depend(sink: i - 1) /* { dg-error "clause must be closely nested inside a loop with .ordered. clause with a parameter" } */ - #pragma omp ordered depend(source) /* { dg-error "clause must be closely nested inside a loop with .ordered. clause with a parameter" } */ + #pragma omp ordered doacross(sink: i - 1) + #pragma omp ordered doacross(source:) + } + #pragma omp parallel for + for (i = 0; i < 64; i++) + { + #pragma omp ordered depend(sink: i - 1) /* { dg-error "clause must be closely nested inside a loop with .ordered. clause" } */ + #pragma omp ordered depend(source) /* { dg-error "clause must be closely nested inside a loop with .ordered. clause" } */ } #pragma omp parallel for for (i = 0; i < 64; i++) { - #pragma omp ordered depend(sink: i - 1) /* { dg-error "clause must be closely nested inside a loop with .ordered. clause with a parameter" } */ - #pragma omp ordered depend(source) /* { dg-error "clause must be closely nested inside a loop with .ordered. clause with a parameter" } */ + #pragma omp ordered doacross(sink: i - 1) /* { dg-error "clause must be closely nested inside a loop with .ordered. clause" } */ + #pragma omp ordered doacross(source:) /* { dg-error "clause must be closely nested inside a loop with .ordered. clause" } */ } } diff --git a/gcc/testsuite/c-c++-common/gomp/sink-3.c b/gcc/testsuite/c-c++-common/gomp/sink-3.c index 588aea2..3f7ba5e 100644 --- a/gcc/testsuite/c-c++-common/gomp/sink-3.c +++ b/gcc/testsuite/c-c++-common/gomp/sink-3.c @@ -14,7 +14,7 @@ foo () for (i=0; i < 100; ++i) { #pragma omp ordered depend(sink:poo-1,paa+1) /* { dg-error "poo.*declared.*paa.*declared" } */ - bar(&i); /* { dg-error "may not be closely nested" "" { target *-*-* } .-1 } */ + bar(&i); /* { dg-error "must not have the same binding region" "" { target *-*-* } .-1 } */ #pragma omp ordered depend(source) } } diff --git a/gcc/testsuite/gfortran.dg/gomp/nesting-2.f90 b/gcc/testsuite/gfortran.dg/gomp/nesting-2.f90 index 2eccdf9..d8014d6 100644 --- a/gcc/testsuite/gfortran.dg/gomp/nesting-2.f90 +++ b/gcc/testsuite/gfortran.dg/gomp/nesting-2.f90 @@ -158,8 +158,8 @@ subroutine foo !$omp do ordered(1) do i = 0, 63 !$omp parallel - !$omp ordered depend(source) ! { dg-error ".ordered. construct with .depend. clause must be closely nested inside a loop with .ordered. clause with a parameter" } - !$omp ordered depend(sink: i - 1) ! { dg-error ".ordered. construct with .depend. clause must be closely nested inside a loop with .ordered. clause with a parameter" } + !$omp ordered depend(source) ! { dg-error ".ordered. construct with .depend. clause must be closely nested inside a loop with .ordered. clause" } + !$omp ordered depend(sink: i - 1) ! { dg-error ".ordered. construct with .depend. clause must be closely nested inside a loop with .ordered. clause" } !$omp end parallel end do end diff --git a/gcc/tree-core.h b/gcc/tree-core.h index 86a07c2..80c2bcb 100644 --- a/gcc/tree-core.h +++ b/gcc/tree-core.h @@ -345,6 +345,9 @@ enum omp_clause_code { /* OpenMP clause: has_device_addr (variable-list). */ OMP_CLAUSE_HAS_DEVICE_ADDR, + /* OpenMP clause: doacross ({source,sink}:vec). */ + OMP_CLAUSE_DOACROSS, + /* Internal structure to hold OpenACC cache directive's variable-list. #pragma acc cache (variable-list). */ OMP_CLAUSE__CACHE_, @@ -1525,12 +1528,18 @@ enum omp_clause_depend_kind OMP_CLAUSE_DEPEND_INOUT, OMP_CLAUSE_DEPEND_MUTEXINOUTSET, OMP_CLAUSE_DEPEND_INOUTSET, - OMP_CLAUSE_DEPEND_SOURCE, - OMP_CLAUSE_DEPEND_SINK, OMP_CLAUSE_DEPEND_DEPOBJ, + OMP_CLAUSE_DEPEND_INVALID, OMP_CLAUSE_DEPEND_LAST }; +enum omp_clause_doacross_kind +{ + OMP_CLAUSE_DOACROSS_SOURCE, + OMP_CLAUSE_DOACROSS_SINK, + OMP_CLAUSE_DOACROSS_LAST +}; + enum omp_clause_proc_bind_kind { /* Numbers should match omp_proc_bind_t enum in omp.h. */ @@ -1620,6 +1629,7 @@ struct GTY(()) tree_omp_clause { enum omp_clause_default_kind default_kind; enum omp_clause_schedule_kind schedule_kind; enum omp_clause_depend_kind depend_kind; + enum omp_clause_doacross_kind doacross_kind; /* See include/gomp-constants.h for enum gomp_map_kind's values. */ unsigned int map_kind; enum omp_clause_proc_bind_kind proc_bind_kind; diff --git a/gcc/tree-nested.cc b/gcc/tree-nested.cc index 9952809..ea7d57a 100644 --- a/gcc/tree-nested.cc +++ b/gcc/tree-nested.cc @@ -1368,6 +1368,7 @@ convert_nonlocal_omp_clauses (tree *pclauses, struct walk_stmt_info *wi) case OMP_CLAUSE_IF: case OMP_CLAUSE_NUM_THREADS: case OMP_CLAUSE_DEPEND: + case OMP_CLAUSE_DOACROSS: case OMP_CLAUSE_DEVICE: case OMP_CLAUSE_NUM_TEAMS: case OMP_CLAUSE_THREAD_LIMIT: @@ -2157,6 +2158,7 @@ convert_local_omp_clauses (tree *pclauses, struct walk_stmt_info *wi) case OMP_CLAUSE_IF: case OMP_CLAUSE_NUM_THREADS: case OMP_CLAUSE_DEPEND: + case OMP_CLAUSE_DOACROSS: case OMP_CLAUSE_DEVICE: case OMP_CLAUSE_NUM_TEAMS: case OMP_CLAUSE_THREAD_LIMIT: diff --git a/gcc/tree-pretty-print.cc b/gcc/tree-pretty-print.cc index 47371d8..33b12c7 100644 --- a/gcc/tree-pretty-print.cc +++ b/gcc/tree-pretty-print.cc @@ -831,34 +831,9 @@ dump_omp_clause (pretty_printer *pp, tree clause, int spc, dump_flags_t flags) case OMP_CLAUSE_DEPEND_INOUTSET: name = "inoutset"; break; - case OMP_CLAUSE_DEPEND_SOURCE: - pp_string (pp, "source)"); - return; case OMP_CLAUSE_DEPEND_LAST: name = "__internal__"; break; - case OMP_CLAUSE_DEPEND_SINK: - pp_string (pp, "sink:"); - for (tree t = OMP_CLAUSE_DECL (clause); t; t = TREE_CHAIN (t)) - if (TREE_CODE (t) == TREE_LIST) - { - dump_generic_node (pp, TREE_VALUE (t), spc, flags, false); - if (TREE_PURPOSE (t) != integer_zero_node) - { - if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (t)) - pp_minus (pp); - else - pp_plus (pp); - dump_generic_node (pp, TREE_PURPOSE (t), spc, flags, - false); - } - if (TREE_CHAIN (t)) - pp_comma (pp); - } - else - gcc_unreachable (); - pp_right_paren (pp); - return; default: gcc_unreachable (); } @@ -885,6 +860,49 @@ dump_omp_clause (pretty_printer *pp, tree clause, int spc, dump_flags_t flags) } break; + case OMP_CLAUSE_DOACROSS: + pp_string (pp, OMP_CLAUSE_DOACROSS_DEPEND (clause) + ? "depend(" : "doacross("); + switch (OMP_CLAUSE_DOACROSS_KIND (clause)) + { + case OMP_CLAUSE_DOACROSS_SOURCE: + if (OMP_CLAUSE_DOACROSS_DEPEND (clause)) + pp_string (pp, "source)"); + else + pp_string (pp, "source:)"); + break; + case OMP_CLAUSE_DOACROSS_SINK: + pp_string (pp, "sink:"); + if (OMP_CLAUSE_DECL (clause) == NULL_TREE) + { + pp_string (pp, "omp_cur_iteration-1)"); + break; + } + for (tree t = OMP_CLAUSE_DECL (clause); t; t = TREE_CHAIN (t)) + if (TREE_CODE (t) == TREE_LIST) + { + dump_generic_node (pp, TREE_VALUE (t), spc, flags, false); + if (TREE_PURPOSE (t) != integer_zero_node) + { + if (OMP_CLAUSE_DOACROSS_SINK_NEGATIVE (t)) + pp_minus (pp); + else + pp_plus (pp); + dump_generic_node (pp, TREE_PURPOSE (t), spc, flags, + false); + } + if (TREE_CHAIN (t)) + pp_comma (pp); + } + else + gcc_unreachable (); + pp_right_paren (pp); + break; + default: + gcc_unreachable (); + } + break; + case OMP_CLAUSE_MAP: pp_string (pp, "map("); switch (OMP_CLAUSE_MAP_KIND (clause)) diff --git a/gcc/tree-streamer-in.cc b/gcc/tree-streamer-in.cc index 196f19c..219cf5e 100644 --- a/gcc/tree-streamer-in.cc +++ b/gcc/tree-streamer-in.cc @@ -453,6 +453,11 @@ unpack_ts_omp_clause_value_fields (class data_in *data_in, OMP_CLAUSE_DEPEND_KIND (expr) = bp_unpack_enum (bp, omp_clause_depend_kind, OMP_CLAUSE_DEPEND_LAST); break; + case OMP_CLAUSE_DOACROSS: + OMP_CLAUSE_DOACROSS_KIND (expr) + = bp_unpack_enum (bp, omp_clause_doacross_kind, + OMP_CLAUSE_DOACROSS_LAST); + break; case OMP_CLAUSE_MAP: OMP_CLAUSE_SET_MAP_KIND (expr, bp_unpack_enum (bp, gomp_map_kind, GOMP_MAP_LAST)); diff --git a/gcc/tree-streamer-out.cc b/gcc/tree-streamer-out.cc index d39dc15..9b114dc 100644 --- a/gcc/tree-streamer-out.cc +++ b/gcc/tree-streamer-out.cc @@ -419,6 +419,10 @@ pack_ts_omp_clause_value_fields (struct output_block *ob, bp_pack_enum (bp, omp_clause_depend_kind, OMP_CLAUSE_DEPEND_LAST, OMP_CLAUSE_DEPEND_KIND (expr)); break; + case OMP_CLAUSE_DOACROSS: + bp_pack_enum (bp, omp_clause_doacross_kind, OMP_CLAUSE_DOACROSS_LAST, + OMP_CLAUSE_DOACROSS_KIND (expr)); + break; case OMP_CLAUSE_MAP: bp_pack_enum (bp, gomp_map_kind, GOMP_MAP_LAST, OMP_CLAUSE_MAP_KIND (expr)); diff --git a/gcc/tree.cc b/gcc/tree.cc index 0179c0f..2f488e4 100644 --- a/gcc/tree.cc +++ b/gcc/tree.cc @@ -294,6 +294,7 @@ unsigned const char omp_clause_num_ops[] = 2, /* OMP_CLAUSE_TO */ 2, /* OMP_CLAUSE_MAP */ 1, /* OMP_CLAUSE_HAS_DEVICE_ADDR */ + 1, /* OMP_CLAUSE_DOACROSS */ 2, /* OMP_CLAUSE__CACHE_ */ 2, /* OMP_CLAUSE_GANG */ 1, /* OMP_CLAUSE_ASYNC */ @@ -384,6 +385,7 @@ const char * const omp_clause_code_name[] = "to", "map", "has_device_addr", + "doacross", "_cache_", "gang", "async", @@ -1722,9 +1722,16 @@ class auto_suppress_location_wrappers #define OMP_CLAUSE_DEPEND_KIND(NODE) \ (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_DEPEND)->omp_clause.subcode.depend_kind) -#define OMP_CLAUSE_DEPEND_SINK_NEGATIVE(NODE) \ +#define OMP_CLAUSE_DOACROSS_KIND(NODE) \ + (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_DOACROSS)->omp_clause.subcode.doacross_kind) + +#define OMP_CLAUSE_DOACROSS_SINK_NEGATIVE(NODE) \ TREE_PUBLIC (TREE_LIST_CHECK (NODE)) +/* True if DOACROSS clause is spelled as DEPEND. */ +#define OMP_CLAUSE_DOACROSS_DEPEND(NODE) \ + TREE_PROTECTED (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_DOACROSS)) + #define OMP_CLAUSE_MAP_KIND(NODE) \ ((enum gomp_map_kind) OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_MAP)->omp_clause.subcode.map_kind) #define OMP_CLAUSE_SET_MAP_KIND(NODE, MAP_KIND) \ @@ -1786,6 +1793,11 @@ class auto_suppress_location_wrappers #define OMP_CLAUSE_ORDERED_EXPR(NODE) \ OMP_CLAUSE_OPERAND (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_ORDERED), 0) +/* True on an OMP_CLAUSE_ORDERED if stand-alone ordered construct is nested + inside of work-sharing loop the clause is on. */ +#define OMP_CLAUSE_ORDERED_DOACROSS(NODE) \ + (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_ORDERED)->base.public_flag) + /* True for unconstrained modifier on order(concurrent) clause. */ #define OMP_CLAUSE_ORDER_UNCONSTRAINED(NODE) \ (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_ORDER)->base.public_flag) |