gcc/cp/ChangeLog * parser.cc (cp_parser_omp_all_clauses): Allow comma before first clause. (cp_parser_see_omp_loop_nest): Accept C++ standard attributes before RID_FOR. (cp_parser_omp_loop_nest): Process C++ standard attributes like pragmas. Improve error handling for bad pragmas/attributes. Use cp_parser_see_omp_loop_nest instead of duplicating what it does. (cp_parser_omp_tile_sizes): Permit comma before the clause. (cp_parser_omp_tile): Assert that this isn't called for inner directive. (cp_parser_omp_unroll): Likewise.
gcc/testsuite/ChangeLog * g++.dg/gomp/loop-transforms/attrs-tile-1.C: New file. * g++.dg/gomp/loop-transforms/attrs-tile-2.C: New file. * g++.dg/gomp/loop-transforms/attrs-tile-3.C: New file. * g++.dg/gomp/loop-transforms/attrs-unroll-1.C: New file. * g++.dg/gomp/loop-transforms/attrs-unroll-2.C: New file. * g++.dg/gomp/loop-transforms/attrs-unroll-3.C: New file. * g++.dg/gomp/loop-transforms/attrs-unroll-inner-1.C: New file. * g++.dg/gomp/loop-transforms/attrs-unroll-inner-2.C: New file. * g++.dg/gomp/loop-transforms/attrs-unroll-inner-3.C: New file. --- gcc/cp/ChangeLog.omp | 15 ++ gcc/cp/parser.cc | 69 ++++--- gcc/testsuite/ChangeLog.omp | 12 ++ .../gomp/loop-transforms/attrs-tile-1.C | 164 +++++++++++++++++ .../gomp/loop-transforms/attrs-tile-2.C | 174 ++++++++++++++++++ .../gomp/loop-transforms/attrs-tile-3.C | 111 +++++++++++ .../gomp/loop-transforms/attrs-unroll-1.C | 135 ++++++++++++++ .../gomp/loop-transforms/attrs-unroll-2.C | 81 ++++++++ .../gomp/loop-transforms/attrs-unroll-3.C | 20 ++ .../loop-transforms/attrs-unroll-inner-1.C | 15 ++ .../loop-transforms/attrs-unroll-inner-2.C | 29 +++ .../loop-transforms/attrs-unroll-inner-3.C | 71 +++++++ 12 files changed, 872 insertions(+), 24 deletions(-) create mode 100644 gcc/testsuite/g++.dg/gomp/loop-transforms/attrs-tile-1.C create mode 100644 gcc/testsuite/g++.dg/gomp/loop-transforms/attrs-tile-2.C create mode 100644 gcc/testsuite/g++.dg/gomp/loop-transforms/attrs-tile-3.C create mode 100644 gcc/testsuite/g++.dg/gomp/loop-transforms/attrs-unroll-1.C create mode 100644 gcc/testsuite/g++.dg/gomp/loop-transforms/attrs-unroll-2.C create mode 100644 gcc/testsuite/g++.dg/gomp/loop-transforms/attrs-unroll-3.C create mode 100644 gcc/testsuite/g++.dg/gomp/loop-transforms/attrs-unroll-inner-1.C create mode 100644 gcc/testsuite/g++.dg/gomp/loop-transforms/attrs-unroll-inner-2.C create mode 100644 gcc/testsuite/g++.dg/gomp/loop-transforms/attrs-unroll-inner-3.C diff --git a/gcc/cp/ChangeLog.omp b/gcc/cp/ChangeLog.omp index 1b2d71422d8..fe5ef67a7ad 100644 --- a/gcc/cp/ChangeLog.omp +++ b/gcc/cp/ChangeLog.omp @@ -1,3 +1,18 @@ +2023-08-18 Sandra Loosemore <san...@codesourcery.com> + + * parser.cc (cp_parser_omp_all_clauses): Allow comma before first + clause. + (cp_parser_see_omp_loop_nest): Accept C++ standard attributes + before RID_FOR. + (cp_parser_omp_loop_nest): Process C++ standard attributes like + pragmas. Improve error handling for bad pragmas/attributes. + Use cp_parser_see_omp_loop_nest instead of duplicating what it + does. + (cp_parser_omp_tile_sizes): Permit comma before the clause. + (cp_parser_omp_tile): Assert that this isn't called for inner + directive. + (cp_parser_omp_unroll): Likewise. + 2023-08-18 Sandra Loosemore <san...@codesourcery.com> * parser.cc (cp_parser_omp_declare_mapper): Allow commas between diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc index 0ce2a7be608..4871f4511a9 100644 --- a/gcc/cp/parser.cc +++ b/gcc/cp/parser.cc @@ -42240,15 +42240,12 @@ cp_parser_omp_all_clauses (cp_parser *parser, omp_clause_mask mask, if (nested && cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_PAREN)) break; - if (!first || nested != 2) - { - if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA)) - cp_lexer_consume_token (parser->lexer); - else if (nested == 2) - error_at (cp_lexer_peek_token (parser->lexer)->location, - "clauses in %<simd%> trait should be separated " - "by %<,%>"); - } + if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA)) + cp_lexer_consume_token (parser->lexer); + else if (!first && nested == 2) + error_at (cp_lexer_peek_token (parser->lexer)->location, + "clauses in %<simd%> trait should be separated " + "by %<,%>"); token = cp_lexer_peek_token (parser->lexer); c_kind = cp_parser_omp_clause_name (parser); @@ -44803,6 +44800,11 @@ cp_parser_see_omp_loop_nest (cp_parser *parser, enum tree_code code, || (cp_parser_pragma_kind (cp_lexer_peek_token (parser->lexer)) == PRAGMA_OMP_TILE)) return true; + if (cp_lexer_nth_token_is_keyword + (parser->lexer, + cp_parser_skip_std_attribute_spec_seq (parser, 1), + RID_FOR)) + return true; if (error_p) cp_parser_error (parser, "loop nest expected"); } @@ -44868,6 +44870,11 @@ cp_parser_omp_loop_nest (cp_parser *parser, bool *if_p) the depth of the *next* loop, not the level of the loop body the transformation directive appears in. */ + /* Arrange for C++ standard attribute syntax to be parsed as regular + pragmas. */ + tree std_attrs = cp_parser_std_attribute_spec_seq (parser); + std_attrs = cp_parser_handle_statement_omp_attributes (parser, std_attrs); + if ((cp_parser_pragma_kind (cp_lexer_peek_token (parser->lexer)) == PRAGMA_OMP_UNROLL) || (cp_parser_pragma_kind (cp_lexer_peek_token (parser->lexer)) @@ -44893,19 +44900,29 @@ cp_parser_omp_loop_nest (cp_parser *parser, bool *if_p) omp_for_parse_state->orig_declv = grow_tree_vec (omp_for_parse_state->orig_declv, count); } - if (cp_parser_see_omp_loop_nest (parser, omp_for_parse_state->code, - true)) - return cp_parser_omp_loop_nest (parser, if_p); - else + } + + /* Diagnose errors if we don't have a "for" loop following the + optional loop transforms. Otherwise, consume the token. */ + if (!cp_lexer_next_token_is_keyword (parser->lexer, RID_FOR)) + { + omp_for_parse_state->fail = true; + cp_token *token = cp_lexer_peek_token (parser->lexer); + /* Don't call cp_parser_error here since it overrides the + provided message with a more confusing one if there was + a bad pragma or attribute directive. */ + error_at (token->location, "loop nest expected"); + /* See if we can recover by skipping over bad pragma(s). */ + while (token->type == CPP_PRAGMA) { - /* FIXME: Better error recovery here? */ - omp_for_parse_state->fail = true; - return NULL_TREE; + cp_parser_skip_to_pragma_eol (parser, token); + if (cp_parser_see_omp_loop_nest (parser, omp_for_parse_state->code, + false)) + return cp_parser_omp_loop_nest (parser, if_p); + token = cp_lexer_peek_token (parser->lexer); } + return NULL_TREE; } - - /* We have already matched the FOR token but not consumed it yet. */ - gcc_assert (cp_lexer_next_token_is_keyword (parser->lexer, RID_FOR)); loc = cp_lexer_consume_token (parser->lexer)->location; /* Forbid break/continue in the loop initializer, condition, and @@ -45161,11 +45178,8 @@ cp_parser_omp_loop_nest (cp_parser *parser, bool *if_p) moreloops = depth < omp_for_parse_state->count - 1; omp_for_parse_state->want_nested_loop = moreloops; if (moreloops - && (cp_lexer_next_token_is_keyword (parser->lexer, RID_FOR) - || (cp_parser_pragma_kind (cp_lexer_peek_token (parser->lexer)) - == PRAGMA_OMP_UNROLL) - || (cp_parser_pragma_kind (cp_lexer_peek_token (parser->lexer)) - == PRAGMA_OMP_TILE))) + && cp_parser_see_omp_loop_nest (parser, omp_for_parse_state->code, + false)) { omp_for_parse_state->depth++; add_stmt (cp_parser_omp_loop_nest (parser, if_p)); @@ -47323,6 +47337,9 @@ cp_parser_omp_tile_sizes (cp_parser *parser, location_t loc) tree sizes = NULL_TREE; cp_lexer *lexer = parser->lexer; + if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA)) + cp_lexer_consume_token (parser->lexer); + cp_token *tok = cp_lexer_peek_token (lexer); if (tok->type != CPP_NAME || strcmp ("sizes", IDENTIFIER_POINTER (tok->u.value))) @@ -47375,6 +47392,8 @@ cp_parser_omp_tile (cp_parser *parser, cp_token *tok, bool *if_p) tree block; tree ret = error_mark_node; + gcc_assert (!parser->omp_for_parse_state); + tree clauses = cp_parser_omp_tile_sizes (parser, tok->location); cp_parser_require_pragma_eol (parser, tok); @@ -47553,6 +47572,8 @@ cp_parser_omp_unroll (cp_parser *parser, cp_token *tok, bool *if_p) static const char *p_name = "#pragma omp unroll"; omp_clause_mask mask = OMP_UNROLL_CLAUSE_MASK; + gcc_assert (!parser->omp_for_parse_state); + tree clauses = cp_parser_omp_all_clauses (parser, mask, p_name, tok, true); if (!clauses) diff --git a/gcc/testsuite/ChangeLog.omp b/gcc/testsuite/ChangeLog.omp index a7d11777988..3008a8e52eb 100644 --- a/gcc/testsuite/ChangeLog.omp +++ b/gcc/testsuite/ChangeLog.omp @@ -1,3 +1,15 @@ +2023-08-18 Sandra Loosemore <san...@codesourcery.com> + + * g++.dg/gomp/loop-transforms/attrs-tile-1.C: New file. + * g++.dg/gomp/loop-transforms/attrs-tile-2.C: New file. + * g++.dg/gomp/loop-transforms/attrs-tile-3.C: New file. + * g++.dg/gomp/loop-transforms/attrs-unroll-1.C: New file. + * g++.dg/gomp/loop-transforms/attrs-unroll-2.C: New file. + * g++.dg/gomp/loop-transforms/attrs-unroll-3.C: New file. + * g++.dg/gomp/loop-transforms/attrs-unroll-inner-1.C: New file. + * g++.dg/gomp/loop-transforms/attrs-unroll-inner-2.C: New file. + * g++.dg/gomp/loop-transforms/attrs-unroll-inner-3.C: New file. + 2023-08-18 Sandra Loosemore <san...@codesourcery.com> * g++.dg/gomp/attrs-declare-mapper-3.C: New file. diff --git a/gcc/testsuite/g++.dg/gomp/loop-transforms/attrs-tile-1.C b/gcc/testsuite/g++.dg/gomp/loop-transforms/attrs-tile-1.C new file mode 100644 index 00000000000..0906ff3bbe8 --- /dev/null +++ b/gcc/testsuite/g++.dg/gomp/loop-transforms/attrs-tile-1.C @@ -0,0 +1,164 @@ +// { dg-do compile { target c++11 } } + +extern void dummy (int); + +void +test () +{ + [[omp::directive (tile sizes(1))]] + for (int i = 0; i < 100; ++i) + dummy (i); + + [[omp::directive (tile sizes(0))]] /* { dg-error {'tile sizes' argument needs positive integral constant} } */ + for (int i = 0; i < 100; ++i) + dummy (i); + + [[omp::directive (tile sizes(-1))]] /* { dg-error {'tile sizes' argument needs positive integral constant} } */ + for (int i = 0; i < 100; ++i) + dummy (i); + + [[omp::directive (tile sizes())]] /* { dg-error {expected primary-expression before} } */ + for (int i = 0; i < 100; ++i) + dummy (i); + + [[omp::directive (tile sizes)]] /* { dg-error {expected '\(' before end of line} } */ + for (int i = 0; i < 100; ++i) + dummy (i); + + [[omp::directive (tile sizes(1) sizes(1))]] /* { dg-error {expected end of line before 'sizes'} } */ + for (int i = 0; i < 100; ++i) + dummy (i); + + [[omp::directive (tile, sizes(1), sizes(1))]] /* { dg-error {expected end of line before ','} } */ + for (int i = 0; i < 100; ++i) + dummy (i); + + [[omp::sequence + (directive (tile sizes(1)), + directive (tile sizes(1)))]] + for (int i = 0; i < 100; ++i) + dummy (i); + + [[omp::sequence + (directive (tile sizes(1, 2)), + directive (tile sizes(1)))]] /* { dg-error {nesting depth left after this transformation too low for outer transformation} } */ + for (int i = 0; i < 100; ++i) + for (int j = 0; j < 100; ++j) + dummy (i); + + [[omp::sequence + (directive (tile sizes(1, 2)), + directive (tile sizes(1, 2)))]] + for (int i = 0; i < 100; ++i) + for (int j = 0; j < 100; ++j) + dummy (i); + + [[omp::sequence + (directive (tile sizes(5, 6)), + directive (tile sizes(1, 2, 3)))]] + for (int i = 0; i < 100; ++i) + for (int j = 0; j < 100; ++j) + for (int k = 0; k < 100; ++k) + dummy (i); + + [[omp::sequence + (directive (tile sizes(1)), + directive (unroll partia), /* { dg-error {expected an OpenMP clause before 'partia'} } */ + directive (tile sizes(1)))]] + for (int i = 0; i < 100; ++i) + dummy (i); + + [[omp::sequence + (directive (tile sizes(1)), + directive (unroll))]] /* { dg-error {'#pragma omp unroll' without 'partial' clause is invalid here; turns loop into non-loop} } */ + for (int i = 0; i < 100; ++i) + dummy (i); + + [[omp::sequence + (directive (tile sizes(1)), + directive (unroll full))]] /* { dg-error {'full' clause is invalid here; turns loop into non-loop} } */ + for (int i = 0; i < 100; ++i) + dummy (i); + + [[omp::sequence + (directive (tile sizes(1)), + directive (unroll partial), + directive (tile sizes(1)))]] + for (int i = 0; i < 100; ++i) + dummy (i); + + [[omp::sequence + (directive (tile sizes(8,8)), + directive (unroll partial), /* { dg-error {nesting depth left after this transformation too low for outer transformation} } */ + directive (tile sizes(1)))]] + for (int i = 0; i < 100; ++i) + dummy (i); + + [[omp::sequence + (directive (tile sizes(8,8)), + directive (unroll partial))]] /* { dg-error {nesting depth left after this transformation too low for outer transformation} } */ + for (int i = 0; i < 100; ++i) + dummy (i); + + [[omp::directive (tile sizes(1, 2))]] + for (int i = 0; i < 100; ++i) + for (int j = 0; j < 100; ++j) + dummy (i); + + [[omp::directive (tile sizes(1, 2))]] /* { dg-error {'tile' loop transformation may not appear on non-rectangular for} } */ + for (int i = 0; i < 100; ++i) + for (int j = i; j < 100; ++j) + dummy (i); + + [[omp::directive (tile sizes(1, 2))]] /* { dg-error {'tile' loop transformation may not appear on non-rectangular for} } */ + for (int i = 0; i < 100; ++i) + for (int j = 2; j < i; ++j) + dummy (i); + + [[omp::directive (tile sizes(1, 2, 3))]] + for (int i = 0; i < 100; ++i) /* { dg-error {not enough nested loops} } */ + for (int j = 0; j < 100; ++j) + dummy (i); + + [[omp::directive (tile sizes(1))]] + for (int i = 0; i < 100; ++i) + { + dummy (i); + for (int j = 0; j < 100; ++j) + dummy (i); + } + + [[omp::directive (tile sizes(1))]] + for (int i = 0; i < 100; ++i) + { + for (int j = 0; j < 100; ++j) + dummy (j); + dummy (i); + } + + [[omp::directive (tile sizes(1, 2))]] + for (int i = 0; i < 100; ++i) /* { dg-error {inner loops must be perfectly nested} } */ + { + dummy (i); + for (int j = 0; j < 100; ++j) + dummy (j); + } + + [[omp::directive (tile sizes(1, 2))]] + for (int i = 0; i < 100; ++i) /* { dg-error {inner loops must be perfectly nested} } */ + { + for (int j = 0; j < 100; ++j) + dummy (j); + dummy (i); + } + + int s; + [[omp::directive (tile sizes(s))]] /* { dg-error {'tile sizes' argument needs positive integral constant} "" { target { ! c++98_only } } } */ + /* { dg-error {the value of 's' is not usable in a constant expression} "" { target { c++ && { ! c++98_only } } } .-1 } */ + for (int i = 0; i < 100; ++i) + dummy (i); + + [[omp::directive (tile sizes(42.0))]] /* { dg-error {'tile sizes' argument needs integral type} } */ + for (int i = 0; i < 100; ++i) + dummy (i); +} diff --git a/gcc/testsuite/g++.dg/gomp/loop-transforms/attrs-tile-2.C b/gcc/testsuite/g++.dg/gomp/loop-transforms/attrs-tile-2.C new file mode 100644 index 00000000000..ab02924defa --- /dev/null +++ b/gcc/testsuite/g++.dg/gomp/loop-transforms/attrs-tile-2.C @@ -0,0 +1,174 @@ +// { dg-do compile { target c++11 } } + +extern void dummy (int); + +void +test () +{ + [[omp::sequence (directive (parallel for), + directive (tile sizes(1)))]] + for (int i = 0; i < 100; ++i) + dummy (i); + + [[omp::sequence (directive (parallel for), + directive (tile sizes(0)))]] /* { dg-error {'tile sizes' argument needs positive integral constant} } */ + for (int i = 0; i < 100; ++i) + dummy (i); + + [[omp::sequence (directive (parallel for), + directive (tile sizes(-1)))]] /* { dg-error {'tile sizes' argument needs positive integral constant} } */ + for (int i = 0; i < 100; ++i) + dummy (i); + + [[omp::sequence (directive (parallel for), + directive (tile sizes()))]] /* { dg-error {expected primary-expression before} } */ + for (int i = 0; i < 100; ++i) + dummy (i); + + [[omp::sequence (directive (parallel for), + directive (tile sizes(,)))]] /* { dg-error {expected primary-expression before} } */ + for (int i = 0; i < 100; ++i) + dummy (i); + + [[omp::sequence (directive (parallel for), + directive (tile sizes))]] /* { dg-error {expected '\(' before end of line} } */ + for (int i = 0; i < 100; ++i) + dummy (i); + + [[omp::sequence (directive (parallel for), + directive (tile sizes(1) sizes(1)))]] /* { dg-error {expected end of line before 'sizes'} } */ + for (int i = 0; i < 100; ++i) + dummy (i); + + [[omp::sequence (directive (parallel for), + directive (tile sizes(1)), + directive (tile sizes(1)))]] + for (int i = 0; i < 100; ++i) + dummy (i); + + [[omp::sequence (directive (parallel for), + directive (tile sizes(1, 2)), + directive (tile sizes(1)))]] /* { dg-error {nesting depth left after this transformation too low for outer transformation} } */ + for (int i = 0; i < 100; ++i) + for (int j = 0; j < 100; ++j) + dummy (i); + + [[omp::sequence (directive (parallel for), + directive (tile sizes(1, 2)), + directive (tile sizes(1, 2)))]] + for (int i = 0; i < 100; ++i) + for (int j = 0; j < 100; ++j) + dummy (i); + + [[omp::sequence (directive (parallel for), + directive (tile sizes(5, 6)), + directive (tile sizes(1, 2, 3)))]] + for (int i = 0; i < 100; ++i) + for (int j = 0; j < 100; ++j) + for (int k = 0; k < 100; ++k) + dummy (i); + + [[omp::sequence (directive (parallel for), + directive (tile sizes(1)), + directive (unroll partia), /* { dg-error {expected an OpenMP clause before 'partia'} } */ + directive (tile sizes(1)))]] + for (int i = 0; i < 100; ++i) + dummy (i); + + [[omp::sequence (directive (parallel for), + directive (tile sizes(1)), + directive (unroll))]] /* { dg-error {'#pragma omp unroll' without 'partial' clause is invalid here; turns loop into non-loop} } */ + for (int i = 0; i < 100; ++i) + dummy (i); + + [[omp::sequence (directive (parallel for), + directive (tile sizes(1)), + directive (unroll full))]] /* { dg-error {'full' clause is invalid here; turns loop into non-loop} } */ + for (int i = 0; i < 100; ++i) + dummy (i); + + [[omp::sequence (directive (parallel for), + directive (tile sizes(1)), + directive (unroll partial), + directive (tile sizes(1)))]] + for (int i = 0; i < 100; ++i) + dummy (i); + + [[omp::sequence (directive (parallel for), + directive (tile sizes(8,8)), + directive (unroll partial), /* { dg-error {nesting depth left after this transformation too low for outer transformation} } */ + directive (tile sizes(1)))]] + for (int i = 0; i < 100; ++i) + dummy (i); + + [[omp::sequence (directive (parallel for), + directive (tile sizes(8,8)), + directive (unroll partial))]] /* { dg-error {nesting depth left after this transformation too low for outer transformation} } */ + for (int i = 0; i < 100; ++i) + dummy (i); + + [[omp::sequence (directive (parallel for), + directive (tile sizes(1, 2)))]] + for (int i = 0; i < 100; ++i) + for (int j = 0; j < 100; ++j) + dummy (i); + + [[omp::sequence (directive (parallel for), + directive (tile sizes(1, 2)))]] /* { dg-error {'tile' loop transformation may not appear on non-rectangular for} } */ + for (int i = 0; i < 100; ++i) + for (int j = i; j < 100; ++j) + dummy (i); + + [[omp::sequence (directive (parallel for), + directive (tile sizes(1, 2)))]] /* { dg-error {'tile' loop transformation may not appear on non-rectangular for} } */ + for (int i = 0; i < 100; ++i) + for (int j = 2; j < i; ++j) + dummy (i); + + [[omp::sequence (directive (parallel for), + directive (tile sizes(1, 2, 3)))]] + for (int i = 0; i < 100; ++i) /* { dg-error {not enough nested loops} } */ + for (int j = 0; j < 100; ++j) + dummy (i); + + [[omp::sequence (directive (parallel for), + directive (tile sizes(1)))]] + for (int i = 0; i < 100; ++i) + { + dummy (i); + for (int j = 0; j < 100; ++j) + dummy (i); + } + + [[omp::sequence (directive (parallel for), + directive (tile sizes(1)))]] + for (int i = 0; i < 100; ++i) + { + for (int j = 0; j < 100; ++j) + dummy (j); + dummy (i); + } + + [[omp::sequence (directive (parallel for), + directive (tile sizes(1, 2)))]] + for (int i = 0; i < 100; ++i) /* { dg-error {inner loops must be perfectly nested} } */ + { + dummy (i); + for (int j = 0; j < 100; ++j) + dummy (j); + } + + [[omp::sequence (directive (parallel for), + directive (tile sizes(1, 2)))]] + for (int i = 0; i < 100; ++i) /* { dg-error {inner loops must be perfectly nested} } */ + { + for (int j = 0; j < 100; ++j) + dummy (j); + dummy (i); + } + + [[omp::sequence (directive (parallel for), + directive (tile sizes(1)))]] + for (int i = 0; i < 100; ++i) + dummy (i); +} diff --git a/gcc/testsuite/g++.dg/gomp/loop-transforms/attrs-tile-3.C b/gcc/testsuite/g++.dg/gomp/loop-transforms/attrs-tile-3.C new file mode 100644 index 00000000000..95a0115b014 --- /dev/null +++ b/gcc/testsuite/g++.dg/gomp/loop-transforms/attrs-tile-3.C @@ -0,0 +1,111 @@ +// { dg-do compile { target c++11 } } + +extern void dummy (int); + +void +test () +{ + [[omp::sequence (directive (for), + directive (tile sizes(1, 2)))]] /* { dg-error {'tile' loop transformation may not appear on non-rectangular for} } */ + for (int i = 0; i < 100; ++i) + for (int j = i; j < 100; ++j) + dummy (i); + + [[omp::sequence (directive (for), + directive (tile sizes(1, 2)))]] /* { dg-error {'tile' loop transformation may not appear on non-rectangular for} } */ + for (int i = 0; i < 100; ++i) + for (int j = 0; j < i; ++j) + dummy (i); + + + [[omp::sequence (directive (for collapse(1)), + directive (tile sizes(1)))]] + for (int i = 0; i < 100; ++i) + for (int j = 0; j < 100; ++j) + dummy (i); + + [[omp::sequence (directive (for collapse(2)), + directive (tile sizes(1)))]] /* { dg-error {nesting depth left after this transformation too low for loop collapse} } */ + for (int i = 0; i < 100; ++i) + for (int j = 0; j < 100; ++j) + dummy (i); + + [[omp::sequence (directive (for collapse(2)), + directive (tile sizes(1, 2)))]] + for (int i = 0; i < 100; ++i) + for (int j = 0; j < 100; ++j) + dummy (i); + + [[omp::sequence (directive (for collapse(3)), + directive (tile sizes(1, 2)))]] /* { dg-error {nesting depth left after this transformation too low for loop collapse} } */ + for (int i = 0; i < 100; ++i) /* { dg-error {not enough nested loops} } */ + for (int j = 0; j < 100; ++j) + dummy (i); + + [[omp::sequence (directive (for collapse(1)), + directive (tile sizes(1)), + directive (tile sizes(1)))]] + for (int i = 0; i < 100; ++i) + dummy (i); + + [[omp::sequence (directive (for collapse(2)), + directive (tile sizes(1, 2)), + directive (tile sizes(1)))]] /* { dg-error {nesting depth left after this transformation too low for outer transformation} } */ + for (int i = 0; i < 100; ++i) /* { dg-error {not enough nested loops} } */ + dummy (i); + + [[omp::sequence (directive (for collapse(2)), + directive (tile sizes(1, 2)), + directive (tile sizes(1, 2)))]] + for (int i = 0; i < 100; ++i) /* { dg-error {not enough nested loops} } */ + dummy (i); + + [[omp::sequence (directive (for collapse(2)), + directive (tile sizes(5, 6)), + directive (tile sizes(1, 2, 3)))]] + for (int i = 0; i < 100; ++i) /* { dg-error {not enough nested loops} } */ + dummy (i); + + [[omp::sequence (directive (for collapse(1)), + directive (tile sizes(1)), + directive (tile sizes(1)))]] + for (int i = 0; i < 100; ++i) + dummy (i); + + [[omp::sequence (directive (for collapse(2)), + directive (tile sizes(1, 2)), + directive (tile sizes(1)))]] /* { dg-error {nesting depth left after this transformation too low for outer transformation} } */ + for (int i = 0; i < 100; ++i) + for (int j = 0; j < 100; ++j) + dummy (i); + + [[omp::sequence (directive (for collapse(2)), + directive (tile sizes(1, 2)), + directive (tile sizes(1, 2)))]] + for (int i = 0; i < 100; ++i) + for (int j = 0; j < 100; ++j) + dummy (i); + + [[omp::sequence (directive (for collapse(2)), + directive (tile sizes(5, 6)), + directive (tile sizes(1, 2, 3)))]] + for (int i = 0; i < 100; ++i) + for (int j = 0; j < 100; ++j) + for (int k = 0; k < 100; ++k) + dummy (i); + + [[omp::sequence (directive (for collapse(3)), + directive (tile sizes(1, 2)), /* { dg-error {nesting depth left after this transformation too low for loop collapse} } */ + directive (tile sizes(1, 2)))]] + for (int i = 0; i < 100; ++i) /* { dg-error {not enough nested loops} } */ + for (int j = 0; j < 100; ++j) + dummy (i); + + [[omp::sequence (directive (for collapse(3)), + directive (tile sizes(5, 6)), /* { dg-error {nesting depth left after this transformation too low for loop collapse} } */ + directive (tile sizes(1, 2, 3)))]] + for (int i = 0; i < 100; ++i) + for (int j = 0; j < 100; ++j) + for (int k = 0; k < 100; ++k) + dummy (i); +} diff --git a/gcc/testsuite/g++.dg/gomp/loop-transforms/attrs-unroll-1.C b/gcc/testsuite/g++.dg/gomp/loop-transforms/attrs-unroll-1.C new file mode 100644 index 00000000000..5b93b9fa59e --- /dev/null +++ b/gcc/testsuite/g++.dg/gomp/loop-transforms/attrs-unroll-1.C @@ -0,0 +1,135 @@ +// { dg-do compile { target c++11 } } + +extern void dummy (int); + +void +test1 () +{ +[[omp::directive (unroll partial)]] + for (int i = 0; i < 100; ++i) + dummy (i); +} + +void +test2 () +{ +[[omp::directive (unroll partial(10))]] + for (int i = 0; i < 100; ++i) + dummy (i); +} + +void +test3 () +{ +[[omp::directive (unroll full)]] + for (int i = 0; i < 100; ++i) + dummy (i); +} + +void +test4 () +{ +[[omp::directive (unroll full)]] + for (int i = 0; i > 100; ++i) + dummy (i); +} + +void +test5 () +{ +[[omp::directive (unroll full)]] + for (int i = 1; i <= 100; ++i) + dummy (i); +} + +void +test6 () +{ +[[omp::directive (unroll full)]] + for (int i = 200; i >= 100; i--) + dummy (i); +} + +void +test7 () +{ +[[omp::directive (unroll full)]] + for (int i = -100; i > 100; ++i) + dummy (i); +} + +void +test8 () +{ +[[omp::directive (unroll full)]] + for (int i = 100; i > -200; --i) + dummy (i); +} + +void +test9 () +{ +[[omp::directive (unroll full)]] + for (int i = -300; i != 100; ++i) + dummy (i); +} + +void +test10 () +{ +[[omp::directive (unroll full)]] + for (int i = -300; i != 100; ++i) + dummy (i); +} + +void +test12 () +{ +[[omp::sequence (directive (unroll full), + directive (unroll partial), + directive (unroll partial))]] + for (int i = -300; i != 100; ++i) + dummy (i); +} + +void +test13 () +{ + for (int i = 0; i < 100; ++i) +[[omp::sequence (directive (unroll full), + directive (unroll partial), + directive (unroll partial))]] + for (int j = -300; j != 100; ++j) + dummy (i); +} + +void +test14 () +{ + [[omp::directive (for)]] + for (int i = 0; i < 100; ++i) + [[omp::sequence (directive (unroll full), + directive (unroll partial), + directive (unroll partial))]] + for (int j = -300; j != 100; ++j) + dummy (i); +} + +void +test15 () +{ + [[omp::directive (for)]] + for (int i = 0; i < 100; ++i) + { + + dummy (i); + + [[omp::sequence (directive (unroll full), + directive (unroll partial), + directive (unroll partial))]] + for (int j = -300; j != 100; ++j) + dummy (j); + + dummy (i); + } + } diff --git a/gcc/testsuite/g++.dg/gomp/loop-transforms/attrs-unroll-2.C b/gcc/testsuite/g++.dg/gomp/loop-transforms/attrs-unroll-2.C new file mode 100644 index 00000000000..1a45eadec64 --- /dev/null +++ b/gcc/testsuite/g++.dg/gomp/loop-transforms/attrs-unroll-2.C @@ -0,0 +1,81 @@ +/* { dg-prune-output "error: invalid controlling predicate" } */ +// { dg-do compile { target c++11 } } + +extern void dummy (int); + +void +test () +{ +[[omp::sequence (directive (unroll partial), + directive (unroll full))]] /* { dg-error {'full' clause is invalid here; turns loop into non-loop} } */ + for (int i = -300; i != 100; ++i) + dummy (i); + +[[omp::sequence (directive (for), + directive (unroll full), /* { dg-error {'full' clause is invalid here; turns loop into non-loop} } */ + directive (unroll partial))]] + for (int i = -300; i != 100; ++i) + dummy (i); + +[[omp::sequence (directive (for), + directive (unroll full), /* { dg-error {'full' clause is invalid here; turns loop into non-loop} } */ + directive (unroll full))]] + for (int i = -300; i != 100; ++i) + dummy (i); + +[[omp::sequence (directive (for), + directive (unroll partial partial))]] /* { dg-error {too many 'partial' clauses} } */ + for (int i = -300; i != 100; ++i) + dummy (i); + +[[omp::directive (unroll full full)]] /* { dg-error {too many 'full' clauses} } */ + for (int i = -300; i != 100; ++i) + dummy (i); + +[[omp::sequence (directive (unroll partial), + directive (unroll))]] /* { dg-error {'#pragma omp unroll' without 'partial' clause is invalid here; turns loop into non-loop} } */ + for (int i = -300; i != 100; ++i) + dummy (i); + +[[omp::sequence (directive (for), + directive (unroll))]] /* { dg-error {'#pragma omp unroll' without 'partial' clause is invalid here; turns loop into non-loop} } */ + for (int i = -300; i != 100; ++i) + dummy (i); + + int i; + +[[omp::sequence (directive (for), + directive (unroll foo))]] /* { dg-error {expected an OpenMP clause before 'foo'} } */ + for (int i = -300; i != 100; ++i) + dummy (i); + +[[omp::directive (unroll partial(i))]] + /* { dg-error {the value of 'i' is not usable in a constant expression} "" { target c++ } .-1 } */ + /* { dg-error {partial argument needs positive constant integer expression} "" { target *-*-* } .-2 } */ + for (int i = -300; i != 100; ++i) + dummy (i); + +[[omp::directive (unroll parti)]] /* { dg-error {expected an OpenMP clause before 'parti'} } */ + for (int i = -300; i != 100; ++i) + dummy (i); + +[[omp::sequence (directive (for), + directive (unroll partial(1)), + directive (unroll parti))]] /* { dg-error {expected an OpenMP clause before 'parti'} } */ + for (int i = -300; i != 100; ++i) + dummy (i); + +[[omp::sequence (directive (for), + directive (unroll partial(1)), + directive (unroll parti))]] /* { dg-error {expected an OpenMP clause before 'parti'} } */ + for (int i = -300; i != 100; ++i) + dummy (i); + +int sum = 0; +[[omp::sequence (directive (parallel for reduction(+ : sum) collapse(2)), + directive (unroll partial(1)))]] /* { dg-error {nesting depth left after this transformation too low for loop collapse} } */ + for (int i = 3; i < 10; ++i) + for (int j = -2; j < 7; ++j) + sum++; +} + diff --git a/gcc/testsuite/g++.dg/gomp/loop-transforms/attrs-unroll-3.C b/gcc/testsuite/g++.dg/gomp/loop-transforms/attrs-unroll-3.C new file mode 100644 index 00000000000..20c11c0f314 --- /dev/null +++ b/gcc/testsuite/g++.dg/gomp/loop-transforms/attrs-unroll-3.C @@ -0,0 +1,20 @@ +// { dg-do compile { target c++11 } } + +/* { dg-additional-options "-fdump-tree-omp_transform_loops" } + * { dg-additional-options "-fdump-tree-original" } */ + +extern void dummy (int); + +void +test1 () +{ + int i; + [[omp::directive (unroll full)]] + for (int i = 0; i < 10; i++) + dummy (i); +} + + /* Loop should be removed with 10 copies of the body remaining + * { dg-final { scan-tree-dump-times "dummy" 10 "omp_transform_loops" } } + * { dg-final { scan-tree-dump "#pragma omp loop_transform" "original" } } + * { dg-final { scan-tree-dump-not "#pragma omp" "omp_transform_loops" } } */ diff --git a/gcc/testsuite/g++.dg/gomp/loop-transforms/attrs-unroll-inner-1.C b/gcc/testsuite/g++.dg/gomp/loop-transforms/attrs-unroll-inner-1.C new file mode 100644 index 00000000000..234753ad017 --- /dev/null +++ b/gcc/testsuite/g++.dg/gomp/loop-transforms/attrs-unroll-inner-1.C @@ -0,0 +1,15 @@ +// { dg-do compile { target c++11 } } + +extern void dummy (int); + +void +test () +{ + + [[omp::directive (target parallel for collapse(2))]] + for (int i = -300; i != 100; ++i) + [[omp::directive (unroll, partial)]] + for (int j = 0; j != 100; ++j) + dummy (i); +} + diff --git a/gcc/testsuite/g++.dg/gomp/loop-transforms/attrs-unroll-inner-2.C b/gcc/testsuite/g++.dg/gomp/loop-transforms/attrs-unroll-inner-2.C new file mode 100644 index 00000000000..26cc665007d --- /dev/null +++ b/gcc/testsuite/g++.dg/gomp/loop-transforms/attrs-unroll-inner-2.C @@ -0,0 +1,29 @@ +// { dg-do compile { target c++11 } } + +extern void dummy (int); + +void +test () +{ + +#pragma omp target parallel for collapse(2) + for (int i = -300; i != 100; ++i) + [[omp::directive (tile sizes (2))]] + for (int j = 0; j != 100; ++j) + dummy (i); + + [[omp::directive (target parallel for collapse(2))]] + for (int i = -300; i != 100; ++i) /* { dg-error {not enough nested loops} } */ + [[omp::directive (tile sizes(2, 3))]] + for (int j = 0; j != 100; ++j) + dummy (i); + + [[omp::directive (target parallel for, collapse(2))]] + for (int i = -300; i != 100; ++i) + [[omp::directive (tile, sizes(2, 3))]] + for (int j = 0; j != 100; ++j) + for (int k = 0; k != 100; ++k) + dummy (i); +} + + diff --git a/gcc/testsuite/g++.dg/gomp/loop-transforms/attrs-unroll-inner-3.C b/gcc/testsuite/g++.dg/gomp/loop-transforms/attrs-unroll-inner-3.C new file mode 100644 index 00000000000..46970b84a24 --- /dev/null +++ b/gcc/testsuite/g++.dg/gomp/loop-transforms/attrs-unroll-inner-3.C @@ -0,0 +1,71 @@ +// { dg-do compile { target c++11 } } + +// Test that omp::sequence is handled properly in a loop nest, but that +// invalid attribute specifiers are rejected. + +extern void dummy (int); + +void +test1 () +{ + [[omp::directive (target parallel for collapse(2))]] + for (int i = -300; i != 100; ++i) + [[omp::sequence (directive (unroll, partial))]] // OK + for (int j = 0; j != 100; ++j) + dummy (i); +} + +void +test2 () +{ + [[omp::directive (target parallel for collapse(2))]] + for (int i = -300; i != 100; ++i) + [[omp::directive (masked)]] // { dg-error "loop nest expected" } + for (int j = 0; j != 100; ++j) + dummy (i); +} + +void +test3 () +{ + [[omp::directive (target parallel for collapse(2))]] + for (int i = -300; i != 100; ++i) + [[omp::directive (unroll, partial)]] // { dg-error "attributes on the same statement" } + [[omp::directive (masked)]] + for (int j = 0; j != 100; ++j) + dummy (i); +} + +void +test4 () +{ + [[omp::directive (target parallel for collapse(2))]] + for (int i = -300; i != 100; ++i) + [[omp::sequence (directive (unroll, partial), + directive (masked))]] // { dg-error "loop nest expected" } + for (int j = 0; j != 100; ++j) + dummy (i); +} + +void +test5 () +{ + [[omp::directive (target parallel for collapse(2))]] + for (int i = -300; i != 100; ++i) + [[omp::sequence (directive (masked), // { dg-error "loop nest expected" } + directive (unroll, partial))]] + for (int j = 0; j != 100; ++j) + dummy (i); +} + +void +test6 () +{ + [[omp::directive (target parallel for collapse(2))]] + for (int i = -300; i != 100; ++i) + [[omp::directive (unroll, partial), // { dg-error "attributes on the same statement" } + omp::directive (masked)]] + for (int j = 0; j != 100; ++j) + dummy (i); +} + -- 2.31.1