aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorFrederik Harwath <frederik@codesourcery.com>2023-03-24 18:20:08 +0100
committerFrederik Harwath <frederik@codesourcery.com>2023-03-27 12:44:13 +0200
commit09f39bb11413d05c4cd87991bf223e1c006c3707 (patch)
tree3df80f75157cf2370d63065917b6d1529b207e0b /gcc
parent8e2248956953741ac458bf0bd1927e25d3a7fcda (diff)
downloadgcc-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')
-rw-r--r--gcc/c/c-parser.cc35
-rw-r--r--gcc/cp/parser.cc81
-rw-r--r--gcc/testsuite/c-c++-common/gomp/loop-transforms/imperfect-loop-nest.c12
-rw-r--r--gcc/testsuite/c-c++-common/gomp/loop-transforms/unroll-inner-1.c15
-rw-r--r--gcc/testsuite/c-c++-common/gomp/loop-transforms/unroll-inner-2.c31
-rw-r--r--gcc/testsuite/c-c++-common/gomp/loop-transforms/unroll-non-rect-1.c37
-rw-r--r--gcc/testsuite/c-c++-common/gomp/loop-transforms/unroll-non-rect-2.c22
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);
+}