diff options
author | Frederik Harwath <frederik@codesourcery.com> | 2023-03-24 18:20:08 +0100 |
---|---|---|
committer | Frederik Harwath <frederik@codesourcery.com> | 2023-03-27 12:44:13 +0200 |
commit | 09f39bb11413d05c4cd87991bf223e1c006c3707 (patch) | |
tree | 3df80f75157cf2370d63065917b6d1529b207e0b /gcc | |
parent | 8e2248956953741ac458bf0bd1927e25d3a7fcda (diff) | |
download | gcc-09f39bb11413d05c4cd87991bf223e1c006c3707.zip gcc-09f39bb11413d05c4cd87991bf223e1c006c3707.tar.gz gcc-09f39bb11413d05c4cd87991bf223e1c006c3707.tar.bz2 |
openmp: Add C/C++ support for loop transformations on inner loops
Add the parsing of loop transformations on inner loops of a loop-nest.
gcc/c/ChangeLog:
* c-parser.cc (c_parser_omp_nested_loop_transform_clauses):
Add argument for the level of loop-nest at which the clauses
appear, ...
(c_parser_omp_tile): ... adjust use here,
(c_parser_omp_unroll): ... and here,
(c_parser_omp_for_loop): ... and here. Stop treating loop
transformations like intervening code, parse them, and adjust
the loop-nest depth if necessary for tiling.
gcc/cp/ChangeLog:
* parser.cc (cp_parser_is_pragma): New function.
(cp_parser_omp_nested_loop_transform_clauses):
Add argument for the level of loop-nest at which the clauses
appear, ...
(cp_parser_omp_tile): ... adjust use here,
(cp_parser_omp_unroll): ... and here,
(cp_parser_omp_for_loop): ... and here. Stop treating loop
gcc/testsuite/ChangeLog:
* c-c++-common/gomp/loop-transforms/unroll-inner-1.c: New test.
* c-c++-common/gomp/loop-transforms/unroll-inner-2.c: New test.
libgomp/ChangeLog
* testsuite/libgomp.c++/loop-transforms/tile-1.C: Deleted, replaced by
matrix-* tests.
* testsuite/libgomp.c-c++-common/loop-transforms/matrix-1.h:
New header file for new tests.
* testsuite/libgomp.c-c++-common/loop-transforms/matrix-constant-iter.h:
Likewise.
* testsuite/libgomp.c-c++-common/loop-transforms/matrix-helper.h:
Likewise.
* testsuite/libgomp.c-c++-common/loop-transforms/matrix-no-directive-1.c:
New test.
* testsuite/libgomp.c-c++-common/loop-transforms/matrix-no-directive-unroll-full-1.c:
New test.
* testsuite/libgomp.c-c++-common/loop-transforms/matrix-omp-distribute-parallel-for-1.c:
New test.
* testsuite/libgomp.c-c++-common/loop-transforms/matrix-omp-for-1.c:
New test.
* testsuite/libgomp.c-c++-common/loop-transforms/matrix-omp-parallel-for-1.c:
New test.
* testsuite/libgomp.c-c++-common/loop-transforms/matrix-omp-parallel-masked-taskloop-1.c:
New test.
* testsuite/libgomp.c-c++-common/loop-transforms/matrix-omp-parallel-masked-taskloop-simd-1.c:
New test.
* testsuite/libgomp.c-c++-common/loop-transforms/matrix-omp-target-parallel-for-1.c:
New test.
* testsuite/libgomp.c-c++-common/loop-transforms/matrix-omp-target-teams-distribute-parallel-for-1.c:
New test.
* testsuite/libgomp.c-c++-common/loop-transforms/matrix-omp-taskloop-1.c:
New test.
* testsuite/libgomp.c-c++-common/loop-transforms/matrix-omp-teams-distribute-parallel-for-1.c:
New test.
* testsuite/libgomp.c-c++-common/loop-transforms/matrix-simd-1.c:
New test.
* testsuite/libgomp.c-c++-common/loop-transforms/matrix-transform-variants-1.h:
New test.
* testsuite/libgomp.c-c++-common/loop-transforms/unroll-non-rect-1.c:
New test.
Diffstat (limited to 'gcc')
7 files changed, 208 insertions, 25 deletions
diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc index 4b1f47e..a21ff8f 100644 --- a/gcc/c/c-parser.cc +++ b/gcc/c/c-parser.cc @@ -19859,7 +19859,7 @@ c_parser_omp_scan_loop_body (c_parser *parser, bool open_brace_parsed) } static int c_parser_omp_nested_loop_transform_clauses (c_parser *, tree &, int, - const char *); + int, const char *); /* Parse the restricted form of loop statements allowed by OpenACC and OpenMP. The real trick here is to determine the loop control variable early @@ -19914,7 +19914,7 @@ c_parser_omp_for_loop (location_t loc, c_parser *parser, enum tree_code code, ordered = collapse; } - c_parser_omp_nested_loop_transform_clauses (parser, clauses, collapse, + c_parser_omp_nested_loop_transform_clauses (parser, clauses, 0, collapse, "loop collapse"); /* Find the depth of the loop nest affected by "omp tile" @@ -20103,6 +20103,22 @@ c_parser_omp_for_loop (location_t loc, c_parser *parser, enum tree_code code, else if (bracecount && c_parser_next_token_is (parser, CPP_SEMICOLON)) c_parser_consume_token (parser); + else if (c_parser_peek_token (parser)->pragma_kind + == PRAGMA_OMP_UNROLL + || c_parser_peek_token (parser)->pragma_kind + == PRAGMA_OMP_TILE) + { + int depth = c_parser_omp_nested_loop_transform_clauses ( + parser, clauses, i + 1, count - i - 1, "loop collapse"); + if (i + 1 + depth > count) + { + count = i + 1 + depth; + declv = grow_tree_vec (declv, count); + initv = grow_tree_vec (initv, count); + condv = grow_tree_vec (condv, count); + incrv = grow_tree_vec (incrv, count); + } + } else { c_parser_error (parser, "not enough perfectly nested loops"); @@ -20114,7 +20130,7 @@ c_parser_omp_for_loop (location_t loc, c_parser *parser, enum tree_code code, fail = true; count = 0; break; - } + } } while (1); @@ -23767,9 +23783,9 @@ c_parser_omp_loop_transform_clause (c_parser *parser) } /* Parse zero or more OpenMP loop transformation directives that - follow another directive that requires a canonical loop nest and - append all to CLAUSES. Return the nesting depth - of the transformed loop nest. + follow another directive that requires a canonical loop nest, + append all to CLAUSES and record the LEVEL at which the clauses + appear in the loop nest in each clause. REQUIRED_DEPTH is the nesting depth of the loop nest required by the preceding directive. OUTER_DESCR is a description of the @@ -23779,7 +23795,7 @@ c_parser_omp_loop_transform_clause (c_parser *parser) static int c_parser_omp_nested_loop_transform_clauses (c_parser *parser, tree &clauses, - int required_depth, + int level, int required_depth, const char *outer_descr) { tree c = NULL_TREE; @@ -23840,6 +23856,7 @@ c_parser_omp_nested_loop_transform_clauses (c_parser *parser, tree &clauses, if (!transformed_depth) transformed_depth = last_depth; + OMP_CLAUSE_TRANSFORM_LEVEL (c) = build_int_cst (unsigned_type_node, level); if (!clauses) clauses = c; else if (last_c) @@ -23873,7 +23890,7 @@ c_parser_omp_tile (location_t loc, c_parser *parser, bool *if_p) return error_mark_node; int required_depth = list_length (OMP_CLAUSE_TILE_SIZES (clauses)); - c_parser_omp_nested_loop_transform_clauses (parser, clauses, required_depth, + c_parser_omp_nested_loop_transform_clauses (parser, clauses, 0, required_depth, "outer transformation"); block = c_begin_compound_stmt (true); @@ -23893,7 +23910,7 @@ c_parser_omp_unroll (location_t loc, c_parser *parser, bool *if_p) tree clauses = c_parser_omp_all_clauses (parser, mask, p_name, false); int required_depth = 1; - c_parser_omp_nested_loop_transform_clauses (parser, clauses, required_depth, + c_parser_omp_nested_loop_transform_clauses (parser, clauses, 0, required_depth, "outer transformation"); if (!clauses) diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc index 66568ac..ed68f75 100644 --- a/gcc/cp/parser.cc +++ b/gcc/cp/parser.cc @@ -43008,7 +43008,8 @@ cp_parser_omp_scan_loop_body (cp_parser *parser) } static int cp_parser_omp_nested_loop_transform_clauses (cp_parser *, tree &, - int, const char *); + int, int, + const char *); /* Parse the restricted form of the for statement allowed by OpenMP. */ @@ -43060,7 +43061,7 @@ cp_parser_omp_for_loop (cp_parser *parser, enum tree_code code, tree clauses, gcc_assert (oacc_tiling || (collapse >= 1 && ordered >= 0)); count = ordered ? ordered : collapse; - cp_parser_omp_nested_loop_transform_clauses (parser, clauses, count, + cp_parser_omp_nested_loop_transform_clauses (parser, clauses, 0, count, "loop collapse"); /* Find the depth of the loop nest affected by "omp tile" @@ -43330,19 +43331,42 @@ cp_parser_omp_for_loop (cp_parser *parser, enum tree_code code, tree clauses, cp_parser_parse_tentatively (parser); for (;;) { - if (cp_lexer_next_token_is_keyword (parser->lexer, RID_FOR)) + cp_token *tok = cp_lexer_peek_token (parser->lexer); + if (cp_parser_is_keyword (tok, RID_FOR)) break; - else if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE)) + else if (tok->type == CPP_OPEN_BRACE) { cp_lexer_consume_token (parser->lexer); bracecount++; } - else if (bracecount - && cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON)) + else if (bracecount && tok->type == CPP_SEMICOLON) cp_lexer_consume_token (parser->lexer); + else if (cp_parser_pragma_kind (tok) == PRAGMA_OMP_UNROLL + || cp_parser_pragma_kind (tok) == PRAGMA_OMP_TILE) + { + int depth = cp_parser_omp_nested_loop_transform_clauses ( + parser, clauses, i + 1, count - i - 1, "loop collapse"); + + /* Adjust the loop nest depth to the requirements of the + loop transformations. The collapse will be reduced + to value requested by the "collapse" and "ordered" + clauses after the execution of the loop transformations + in the middle end. */ + if (i + 1 + depth > count) + { + count = i + 1 + depth; + if (declv) + declv = grow_tree_vec (declv, count); + initv = grow_tree_vec (initv, count); + condv = grow_tree_vec (condv, count); + incrv = grow_tree_vec (incrv, count); + if (orig_declv) + declv = grow_tree_vec (orig_declv, count); + } + } else { - loc = cp_lexer_peek_token (parser->lexer)->location; + loc = tok->location; error_at (loc, "not enough for loops to collapse"); collapse_err = true; cp_parser_abort_tentative_parse (parser); @@ -43401,6 +43425,27 @@ cp_parser_omp_for_loop (cp_parser *parser, enum tree_code code, tree clauses, } else if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON)) cp_lexer_consume_token (parser->lexer); + else if (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) + { + int depth = + cp_parser_omp_nested_loop_transform_clauses (parser, clauses, + i + 1, count - i -1, + "loop collapse"); + if (i + 1 + depth > count) + { + count = i + 1 + depth; + if (declv) + declv = grow_tree_vec (declv, count); + initv = grow_tree_vec (initv, count); + condv = grow_tree_vec (condv, count); + incrv = grow_tree_vec (incrv, count); + if (orig_declv) + declv = grow_tree_vec (orig_declv, count); + } + } else { if (!collapse_err) @@ -45147,7 +45192,6 @@ cp_parser_omp_target (cp_parser *parser, cp_token *pragma_tok, return true; } - /* OpenMP 5.1: Parse sizes list for "omp tile sizes" sizes ( size-expr-list ) */ static tree @@ -45191,6 +45235,7 @@ cp_parser_omp_tile_sizes (cp_parser *parser, location_t loc) gcc_assert (sizes); tree c = build_omp_clause (loc, OMP_CLAUSE_TILE); + OMP_CLAUSE_TRANSFORM_LEVEL (c) = build_int_cst (unsigned_type_node, 0); OMP_CLAUSE_TILE_SIZES (c) = sizes; OMP_CLAUSE_TRANSFORM_LEVEL (c) = build_int_cst (unsigned_type_node, 0); @@ -45214,8 +45259,9 @@ cp_parser_omp_tile (cp_parser *parser, cp_token *tok, bool *if_p) return error_mark_node; int required_depth = list_length (OMP_CLAUSE_TILE_SIZES (clauses)); - cp_parser_omp_nested_loop_transform_clauses ( - parser, clauses, required_depth, "outer transformation"); + cp_parser_omp_nested_loop_transform_clauses (parser, clauses, 0, + required_depth, + "outer transformation"); block = begin_omp_structured_block (); clauses = finish_omp_clauses (clauses, C_ORT_OMP); @@ -45282,8 +45328,9 @@ cp_parser_omp_loop_transform_clause (cp_parser *parser) } /* Parse zero or more OpenMP loop transformation directives that - follow another directive that requires a canonical loop nest and - append all to CLAUSES. Return the nesting depth + follow another directive that requires a canonical loop nest, + append all to CLAUSES, and require the level at which the clause + appears in the loop nest in each clause. Return the nesting depth of the transformed loop nest. REQUIRED_DEPTH is the nesting depth of the loop nest required by @@ -45294,7 +45341,7 @@ cp_parser_omp_loop_transform_clause (cp_parser *parser) static int cp_parser_omp_nested_loop_transform_clauses (cp_parser *parser, tree &clauses, - int required_depth, + int level, int required_depth, const char *outer_descr) { tree c = NULL_TREE; @@ -45338,7 +45385,8 @@ cp_parser_omp_nested_loop_transform_clauses (cp_parser *parser, tree &clauses, default: gcc_unreachable (); } - OMP_CLAUSE_TRANSFORM_LEVEL (c) = build_int_cst (unsigned_type_node, 0); + OMP_CLAUSE_TRANSFORM_LEVEL (c) + = build_int_cst (unsigned_type_node, level); if (depth < last_depth) { @@ -45393,8 +45441,9 @@ cp_parser_omp_unroll (cp_parser *parser, cp_token *tok, bool *if_p) } int required_depth = 1; - cp_parser_omp_nested_loop_transform_clauses ( - parser, clauses, required_depth, "outer transformation"); + cp_parser_omp_nested_loop_transform_clauses (parser, clauses, 0, + required_depth, + "outer transformation"); block = begin_omp_structured_block (); ret = cp_parser_omp_for_loop (parser, OMP_LOOP_TRANS, clauses, NULL, if_p); diff --git a/gcc/testsuite/c-c++-common/gomp/loop-transforms/imperfect-loop-nest.c b/gcc/testsuite/c-c++-common/gomp/loop-transforms/imperfect-loop-nest.c new file mode 100644 index 0000000..57e72df --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/loop-transforms/imperfect-loop-nest.c @@ -0,0 +1,12 @@ +void test () +{ +#pragma omp tile sizes (2,4,6) + for (unsigned i = 0; i < 10; i++) + for (unsigned j = 0; j < 10; j++) + { + float intervening_decl = 0; /* { dg-bogus "not enough for loops to collapse" "TODO C/C++ imperfect loop nest handling" { xfail c++ } } */ + /* { dg-bogus "not enough perfectly nested loops" "TODO C/C++ imperfect loop nest handling" { xfail c } .-1 } */ +#pragma omp unroll partial(2) + for (unsigned k = 0; k < 10; k++); + } +} diff --git a/gcc/testsuite/c-c++-common/gomp/loop-transforms/unroll-inner-1.c b/gcc/testsuite/c-c++-common/gomp/loop-transforms/unroll-inner-1.c new file mode 100644 index 0000000..c365d94 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/loop-transforms/unroll-inner-1.c @@ -0,0 +1,15 @@ +/* { dg-additional-options "-std=c++11" { target c++} } */ + +extern void dummy (int); + +void +test () +{ + +#pragma omp target parallel for collapse(2) + for (int i = -300; i != 100; ++i) + #pragma omp unroll partial + for (int j = 0; j != 100; ++j) + dummy (i); +} + diff --git a/gcc/testsuite/c-c++-common/gomp/loop-transforms/unroll-inner-2.c b/gcc/testsuite/c-c++-common/gomp/loop-transforms/unroll-inner-2.c new file mode 100644 index 0000000..3f8fbf2 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/loop-transforms/unroll-inner-2.c @@ -0,0 +1,31 @@ +/* { dg-additional-options "-std=c++11" { target c++} } */ + +extern void dummy (int); + +void +test () +{ + +#pragma omp target parallel for collapse(2) + for (int i = -300; i != 100; ++i) +#pragma omp tile sizes(2) + for (int j = 0; j != 100; ++j) + dummy (i); + +#pragma omp target parallel for collapse(2) + for (int i = -300; i != 100; ++i) +#pragma omp tile sizes(2, 3) + for (int j = 0; j != 100; ++j) + dummy (i); /* { dg-error {not enough for loops to collapse} "" { target c++ } } */ +/* { dg-error {'i' was not declared in this scope} "" { target c++ } .-1 } */ +/* { dg-error {not enough perfectly nested loops before 'dummy'} "" { target c } .-2 } */ + +#pragma omp target parallel for collapse(2) + for (int i = -300; i != 100; ++i) +#pragma omp 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/c-c++-common/gomp/loop-transforms/unroll-non-rect-1.c b/gcc/testsuite/c-c++-common/gomp/loop-transforms/unroll-non-rect-1.c new file mode 100644 index 0000000..40e7f8e4 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/loop-transforms/unroll-non-rect-1.c @@ -0,0 +1,37 @@ +extern void dummy (int); + +void +test1 () +{ +#pragma omp target parallel for collapse(2) + for (int i = -300; i != 100; ++i) +#pragma omp unroll partial(2) + for (int j = i * 2; j <= i * 4 + 1; ++j) + dummy (i); + +#pragma omp target parallel for collapse(3) + for (int i = -300; i != 100; ++i) + for (int j = i; j != i * 2; ++j) + #pragma omp unroll partial + for (int k = 2; k != 100; ++k) + dummy (i); + +#pragma omp unroll full + for (int i = -300; i != 100; ++i) + for (int j = i; j != i * 2; ++j) + for (int k = 2; k != 100; ++k) + dummy (i); + + for (int i = -300; i != 100; ++i) +#pragma omp unroll full + for (int j = i; j != i + 10; ++j) + for (int k = 2; k != 100; ++k) + dummy (i); + + for (int i = -300; i != 100; ++i) +#pragma omp unroll full + for (int j = i; j != i + 10; ++j) + for (int k = j; k != 100; ++k) + dummy (i); +} + diff --git a/gcc/testsuite/c-c++-common/gomp/loop-transforms/unroll-non-rect-2.c b/gcc/testsuite/c-c++-common/gomp/loop-transforms/unroll-non-rect-2.c new file mode 100644 index 0000000..7696e5d --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/loop-transforms/unroll-non-rect-2.c @@ -0,0 +1,22 @@ +extern void dummy (int); + +void +test1 () +{ +#pragma omp target parallel for collapse(2) /* { dg-error {invalid OpenMP non-rectangular loop step; \'\(1 - 0\) \* 1\' is not a multiple of loop 2 step \'5\'} "" { target c } } */ + for (int i = -300; i != 100; ++i) /* { dg-error {invalid OpenMP non-rectangular loop step; \'\(1 - 0\) \* 1\' is not a multiple of loop 2 step \'5\'} "" { target c++ } } */ +#pragma omp unroll partial + for (int j = 2; j != i; ++j) + dummy (i); +} + +void +test2 () +{ + int i,j; +#pragma omp target parallel for collapse(2) + for (i = -300; i != 100; ++i) + #pragma omp unroll partial + for (j = 2; j != i; ++j) + dummy (i); +} |