https://gcc.gnu.org/g:3e3966d78461a4cfadfde079812e3d98335095b0
commit 3e3966d78461a4cfadfde079812e3d98335095b0 Author: Kwok Cheung Yeung <kcye...@baylibre.com> Date: Wed Nov 27 21:51:34 2024 +0000 openmp: Add support for iterators in 'target update' clauses (C/C++) This adds support for iterators in 'to' and 'from' clauses in the 'target update' OpenMP directive. gcc/c/ * c-parser.cc (c_parser_omp_clause_from_to): Parse 'iterator' modifier. * c-typeck.cc (c_finish_omp_clauses): Finish iterators for to/from clauses. gcc/cp/ * parser.cc (cp_parser_omp_clause_from_to): Parse 'iterator' modifier. * semantics.cc (finish_omp_clauses): Finish iterators for to/from clauses. gcc/ * gimplify.cc (gimplify_scan_omp_clauses): Add argument for iterator loop sequence. Gimplify the clause decl and size into the iterator loop if iterators are used. (gimplify_omp_workshare): Add argument for iterator loops sequence in call to gimplify_scan_omp_clauses. (gimplify_omp_target_update): Call remove_unused_omp_iterator_vars and build_omp_iterators_loops. Add loop sequence as argument when calling gimplify_scan_omp_clauses, gimplify_adjust_omp_clauses and building the Gimple statement. * tree-pretty-print.cc (dump_omp_clause): Call dump_omp_iterators for to/from clauses with iterators. * tree.cc (omp_clause_num_ops): Add extra operand for OMP_CLAUSE_FROM and OMP_CLAUSE_TO. * tree.h (OMP_CLAUSE_HAS_ITERATORS): Add check for OMP_CLAUSE_TO and OMP_CLAUSE_FROM. (OMP_CLAUSE_ITERATORS): Likewise. gcc/testsuite/ * c-c++-common/gomp/target-update-iterators-1.c: New. * c-c++-common/gomp/target-update-iterators-2.c: New. * c-c++-common/gomp/target-update-iterators-3.c: New. libgomp/ * target.c (gomp_update): Call gomp_merge_iterator_maps. Free allocated variables. * testsuite/libgomp.c-c++-common/target-update-iterators-1.c: New. * testsuite/libgomp.c-c++-common/target-update-iterators-2.c: New. * testsuite/libgomp.c-c++-common/target-update-iterators-3.c: New. Diff: --- gcc/ChangeLog.omp | 19 ++++++ gcc/c/ChangeLog.omp | 6 ++ gcc/c/c-parser.cc | 55 ++++++++++++++---- gcc/c/c-typeck.cc | 5 +- gcc/cp/ChangeLog.omp | 6 ++ gcc/cp/parser.cc | 56 ++++++++++++++++-- gcc/cp/semantics.cc | 5 +- gcc/gimplify.cc | 37 +++++++----- gcc/testsuite/ChangeLog.omp | 6 ++ .../c-c++-common/gomp/target-update-iterators-1.c | 20 +++++++ .../c-c++-common/gomp/target-update-iterators-2.c | 23 ++++++++ .../c-c++-common/gomp/target-update-iterators-3.c | 17 ++++++ gcc/tree-pretty-print.cc | 10 ++++ gcc/tree.cc | 4 +- gcc/tree.h | 6 +- libgomp/ChangeLog.omp | 8 +++ libgomp/target.c | 14 +++++ .../target-update-iterators-1.c | 65 +++++++++++++++++++++ .../target-update-iterators-2.c | 58 +++++++++++++++++++ .../target-update-iterators-3.c | 67 ++++++++++++++++++++++ 20 files changed, 449 insertions(+), 38 deletions(-) diff --git a/gcc/ChangeLog.omp b/gcc/ChangeLog.omp index 0d31c77933e0..2ba1ef83f204 100644 --- a/gcc/ChangeLog.omp +++ b/gcc/ChangeLog.omp @@ -1,3 +1,22 @@ +2025-04-17 Kwok Cheung Yeung <kcye...@baylibre.com> + + * gimplify.cc (gimplify_scan_omp_clauses): Add argument for iterator + loop sequence. Gimplify the clause decl and size into the iterator + loop if iterators are used. + (gimplify_omp_workshare): Add argument for iterator loops sequence + in call to gimplify_scan_omp_clauses. + (gimplify_omp_target_update): Call remove_unused_omp_iterator_vars and + build_omp_iterators_loops. Add loop sequence as argument when calling + gimplify_scan_omp_clauses, gimplify_adjust_omp_clauses and building + the Gimple statement. + * tree-pretty-print.cc (dump_omp_clause): Call dump_omp_iterators + for to/from clauses with iterators. + * tree.cc (omp_clause_num_ops): Add extra operand for OMP_CLAUSE_FROM + and OMP_CLAUSE_TO. + * tree.h (OMP_CLAUSE_HAS_ITERATORS): Add check for OMP_CLAUSE_TO and + OMP_CLAUSE_FROM. + (OMP_CLAUSE_ITERATORS): Likewise. + 2025-04-17 Kwok Cheung Yeung <kcye...@baylibre.com> * gimple-pretty-print.cc (dump_gimple_omp_target): Print expanded diff --git a/gcc/c/ChangeLog.omp b/gcc/c/ChangeLog.omp index cc3a28c836db..af995a398571 100644 --- a/gcc/c/ChangeLog.omp +++ b/gcc/c/ChangeLog.omp @@ -1,3 +1,9 @@ +2025-04-17 Kwok Cheung Yeung <kcye...@baylibre.com> + + * c-parser.cc (c_parser_omp_clause_from_to): Parse 'iterator' modifier. + * c-typeck.cc (c_finish_omp_clauses): Finish iterators for to/from + clauses. + 2025-04-17 Kwok Cheung Yeung <kcye...@baylibre.com> * c-parser.cc (c_parser_omp_clause_map): Parse 'iterator' modifier. diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc index e0aafc405545..55636680718e 100644 --- a/gcc/c/c-parser.cc +++ b/gcc/c/c-parser.cc @@ -19944,8 +19944,11 @@ c_parser_omp_clause_device_type (c_parser *parser, tree list) to ( variable-list ) OpenMP 5.1: - from ( [present :] variable-list ) - to ( [present :] variable-list ) */ + from ( [motion-modifier[,] [motion-modifier[,]...]:] variable-list ) + to ( [motion-modifier[,] [motion-modifier[,]...]:] variable-list ) + + motion-modifier: + present | iterator (iterators-definition) */ static tree c_parser_omp_clause_from_to (c_parser *parser, enum omp_clause_code kind, @@ -19957,20 +19960,27 @@ c_parser_omp_clause_from_to (c_parser *parser, enum omp_clause_code kind, return list; int pos = 1, colon_pos = 0; + int iterator_length = 0; while (c_parser_peek_nth_token_raw (parser, pos)->type == CPP_NAME) { - if (c_parser_peek_nth_token_raw (parser, pos + 1)->type == CPP_COMMA) - pos += 2; - else if (c_parser_peek_nth_token_raw (parser, pos + 1)->type - == CPP_OPEN_PAREN) + const char *identifier = + IDENTIFIER_POINTER (c_parser_peek_nth_token_raw (parser, pos)->value); + if (c_parser_peek_nth_token_raw (parser, pos + 1)->type + == CPP_OPEN_PAREN) { unsigned int npos = pos + 2; if (c_parser_check_balanced_raw_token_sequence (parser, &npos) - && (c_parser_peek_nth_token_raw (parser, npos)->type - == CPP_CLOSE_PAREN)) - pos = npos + 1; + && (c_parser_peek_nth_token_raw (parser, npos)->type + == CPP_CLOSE_PAREN)) + { + if (strcmp (identifier, "iterator") == 0) + iterator_length = npos - pos + 1; + pos = npos; + } } + if (c_parser_peek_nth_token_raw (parser, pos + 1)->type == CPP_COMMA) + pos += 2; else pos++; if (c_parser_peek_nth_token_raw (parser, pos)->type == CPP_COLON) @@ -19983,6 +19993,7 @@ c_parser_omp_clause_from_to (c_parser *parser, enum omp_clause_code kind, int present_modifier = false; int mapper_modifier = false; tree mapper_name = NULL_TREE; + tree iterators = NULL_TREE; for (int pos = 1; pos < colon_pos; ++pos) { @@ -20004,6 +20015,17 @@ c_parser_omp_clause_from_to (c_parser *parser, enum omp_clause_code kind, present_modifier++; c_parser_consume_token (parser); } + else if (strcmp ("iterator", p) == 0) + { + if (iterators) + { + c_parser_error (parser, "too many %<iterator%> modifiers"); + parens.skip_until_found_close (parser); + return list; + } + iterators = c_parser_omp_iterators (parser); + pos += iterator_length - 1; + } else if (strcmp ("mapper", p) == 0) { c_parser_consume_token (parser); @@ -20060,7 +20082,7 @@ c_parser_omp_clause_from_to (c_parser *parser, enum omp_clause_code kind, else { c_parser_error (parser, "%<to%> or %<from%> clause with modifier " - "other than %<present%> or %<mapper%>"); + "other than %<iterator%>, %<mapper%> or %<present%>"); parens.skip_until_found_close (parser); return list; } @@ -20097,6 +20119,19 @@ c_parser_omp_clause_from_to (c_parser *parser, enum omp_clause_code kind, OMP_CLAUSE_CHAIN (last_new) = name; } + if (iterators) + { + tree block = pop_scope (); + if (iterators == error_mark_node) + iterators = NULL_TREE; + else + TREE_VEC_ELT (iterators, 5) = block; + } + + if (iterators) + for (tree c = nl; c != list; c = OMP_CLAUSE_CHAIN (c)) + OMP_CLAUSE_ITERATORS (c) = iterators; + return nl; } diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc index c75322e732e3..e6ec927c6bc2 100644 --- a/gcc/c/c-typeck.cc +++ b/gcc/c/c-typeck.cc @@ -16192,6 +16192,9 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort) if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_GRID_DIM || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_GRID_STRIDE) break; + /* FALLTHRU */ + case OMP_CLAUSE_TO: + case OMP_CLAUSE_FROM: if (OMP_CLAUSE_ITERATORS (c) && c_omp_finish_iterators (OMP_CLAUSE_ITERATORS (c))) { @@ -16199,8 +16202,6 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort) break; } /* FALLTHRU */ - case OMP_CLAUSE_TO: - case OMP_CLAUSE_FROM: case OMP_CLAUSE__CACHE_: { using namespace omp_addr_tokenizer; diff --git a/gcc/cp/ChangeLog.omp b/gcc/cp/ChangeLog.omp index cbc4eb230486..80d2c3b5069e 100644 --- a/gcc/cp/ChangeLog.omp +++ b/gcc/cp/ChangeLog.omp @@ -1,3 +1,9 @@ +2025-04-17 Kwok Cheung Yeung <kcye...@baylibre.com> + + * parser.cc (cp_parser_omp_clause_from_to): Parse 'iterator' modifier. + * semantics.cc (finish_omp_clauses): Finish iterators for to/from + clauses. + 2025-04-17 Kwok Cheung Yeung <kcye...@baylibre.com> * parser.cc (cp_parser_omp_clause_map): Parse 'iterator' modifier. diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc index 1e9b7469b743..a13b0a9dc025 100644 --- a/gcc/cp/parser.cc +++ b/gcc/cp/parser.cc @@ -42417,8 +42417,11 @@ cp_parser_omp_clause_doacross (cp_parser *parser, tree list, location_t loc) to ( variable-list ) OpenMP 5.1: - from ( [present :] variable-list ) - to ( [present :] variable-list ) */ + from ( [motion-modifier[,] [motion-modifier[,]...]:] variable-list ) + to ( [motion-modifier[,] [motion-modifier[,]...]:] variable-list ) + + motion-modifier: + present | iterator (iterators-definition) */ static tree cp_parser_omp_clause_from_to (cp_parser *parser, enum omp_clause_code kind, @@ -42429,14 +42432,25 @@ cp_parser_omp_clause_from_to (cp_parser *parser, enum omp_clause_code kind, int pos = 1; int colon_pos = 0; + int iterator_length = 0; while (cp_lexer_peek_nth_token (parser->lexer, pos)->type == CPP_NAME) { + const char *identifier = + IDENTIFIER_POINTER (cp_lexer_peek_nth_token (parser->lexer, + pos)->u.value); + if (cp_lexer_nth_token_is (parser->lexer, pos + 1, CPP_OPEN_PAREN)) + { + int n = cp_parser_skip_balanced_tokens (parser, pos + 1); + if (n != pos + 1) + { + if (strcmp (identifier, "iterator") == 0) + iterator_length = n - pos; + pos = n - 1; + } + } if (cp_lexer_peek_nth_token (parser->lexer, pos + 1)->type == CPP_COMMA) pos += 2; - else if (cp_lexer_peek_nth_token (parser->lexer, pos + 1)->type - == CPP_OPEN_PAREN) - pos = cp_parser_skip_balanced_tokens (parser, pos + 1); else pos++; if (cp_lexer_peek_nth_token (parser->lexer, pos)->type == CPP_COLON) @@ -42449,6 +42463,7 @@ cp_parser_omp_clause_from_to (cp_parser *parser, enum omp_clause_code kind, bool present_modifier = false; bool mapper_modifier = false; tree mapper_name = NULL_TREE; + tree iterators = NULL_TREE; for (int pos = 1; pos < colon_pos; ++pos) { @@ -42473,6 +42488,21 @@ cp_parser_omp_clause_from_to (cp_parser *parser, enum omp_clause_code kind, present_modifier = true; cp_lexer_consume_token (parser->lexer); } + else if (strcmp ("iterator", p) == 0) + { + if (iterators) + { + cp_parser_error (parser, "too many %<iterator%> modifiers"); + cp_parser_skip_to_closing_parenthesis (parser, + /*recovering=*/true, + /*or_comma=*/false, + /*consume_paren=*/true); + return list; + } + begin_scope (sk_omp, NULL); + iterators = cp_parser_omp_iterators (parser); + pos += iterator_length - 1; + } else if (strcmp ("mapper", p) == 0) { cp_lexer_consume_token (parser->lexer); @@ -42535,7 +42565,8 @@ cp_parser_omp_clause_from_to (cp_parser *parser, enum omp_clause_code kind, else { cp_parser_error (parser, "%<to%> or %<from%> clause with " - "modifier other than %<present%> or %<mapper%>"); + "modifier other than %<iterator%>, " + "%<mapper%> or %<present%>"); cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, /*or_comma=*/false, @@ -42574,6 +42605,19 @@ cp_parser_omp_clause_from_to (cp_parser *parser, enum omp_clause_code kind, OMP_CLAUSE_CHAIN (last_new) = name; } + if (iterators) + { + tree block = poplevel (1, 1, 0); + if (iterators == error_mark_node) + iterators = NULL_TREE; + else + TREE_VEC_ELT (iterators, 5) = block; + } + + if (iterators) + for (tree c = nl; c != list; c = OMP_CLAUSE_CHAIN (c)) + OMP_CLAUSE_ITERATORS (c) = iterators; + return nl; } diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc index 42a61574e9d2..dc102f15cf7c 100644 --- a/gcc/cp/semantics.cc +++ b/gcc/cp/semantics.cc @@ -8956,6 +8956,9 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_GRID_DIM || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_GRID_STRIDE) break; + /* FALLTHRU */ + case OMP_CLAUSE_TO: + case OMP_CLAUSE_FROM: if (OMP_CLAUSE_ITERATORS (c) && cp_omp_finish_iterators (OMP_CLAUSE_ITERATORS (c))) { @@ -8963,8 +8966,6 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) break; } /* FALLTHRU */ - case OMP_CLAUSE_TO: - case OMP_CLAUSE_FROM: case OMP_CLAUSE__CACHE_: { using namespace omp_addr_tokenizer; diff --git a/gcc/gimplify.cc b/gcc/gimplify.cc index 78678c14b93e..cd687fc9f6ef 100644 --- a/gcc/gimplify.cc +++ b/gcc/gimplify.cc @@ -13644,7 +13644,8 @@ omp_instantiate_implicit_mappers (splay_tree_node n, void *data) static void gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p, enum omp_region_type region_type, - enum tree_code code) + enum tree_code code, + gimple_seq *loops_seq_p = NULL) { using namespace omp_addr_tokenizer; struct gimplify_omp_ctx *ctx, *outer_ctx; @@ -14412,23 +14413,24 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p, if (OMP_CLAUSE_SIZE (c) == NULL_TREE) OMP_CLAUSE_SIZE (c) = DECL_P (decl) ? DECL_SIZE_UNIT (decl) : TYPE_SIZE_UNIT (TREE_TYPE (decl)); - if (gimplify_expr (&OMP_CLAUSE_SIZE (c), pre_p, - NULL, is_gimple_val, fb_rvalue) == GS_ERROR) + gimple_seq *seq_p; + seq_p = enter_omp_iterator_loop_context (c, loops_seq_p, pre_p); + if (gimplify_expr (&OMP_CLAUSE_SIZE (c), seq_p, NULL, + is_gimple_val, fb_rvalue) == GS_ERROR) { remove = true; + exit_omp_iterator_loop_context (c); break; } if (!DECL_P (decl)) { - if (gimplify_expr (&OMP_CLAUSE_DECL (c), pre_p, - NULL, is_gimple_lvalue, fb_lvalue) - == GS_ERROR) - { - remove = true; - break; - } + if (gimplify_expr (&OMP_CLAUSE_DECL (c), seq_p, NULL, + is_gimple_lvalue, fb_lvalue) == GS_ERROR) + remove = true; + exit_omp_iterator_loop_context (c); break; } + exit_omp_iterator_loop_context (c); goto do_notice; case OMP_CLAUSE__MAPPER_BINDING_: @@ -19156,7 +19158,7 @@ gimplify_omp_workshare (tree *expr_p, gimple_seq *pre_p) if ((ort & ORT_ACC) == 0) in_omp_construct = false; gimplify_scan_omp_clauses (&OMP_CLAUSES (expr), pre_p, ort, - TREE_CODE (expr)); + TREE_CODE (expr), &iterator_loops_seq); if (TREE_CODE (expr) == OMP_TARGET) optimize_target_teams (expr, pre_p); if ((ort & (ORT_TARGET | ORT_TARGET_DATA)) != 0 @@ -19404,10 +19406,16 @@ gimplify_omp_target_update (tree *expr_p, gimple_seq *pre_p) default: gcc_unreachable (); } + + gimple_seq iterator_loops_seq = NULL; + remove_unused_omp_iterator_vars (&OMP_STANDALONE_CLAUSES (expr)); + build_omp_iterators_loops (&OMP_STANDALONE_CLAUSES (expr), + &iterator_loops_seq); + gimplify_scan_omp_clauses (&OMP_STANDALONE_CLAUSES (expr), pre_p, - ort, TREE_CODE (expr)); + ort, TREE_CODE (expr), &iterator_loops_seq); gimplify_adjust_omp_clauses (pre_p, NULL, &OMP_STANDALONE_CLAUSES (expr), - TREE_CODE (expr)); + TREE_CODE (expr), &iterator_loops_seq); if (TREE_CODE (expr) == OACC_UPDATE && omp_find_clause (OMP_STANDALONE_CLAUSES (expr), OMP_CLAUSE_IF_PRESENT)) @@ -19471,7 +19479,8 @@ gimplify_omp_target_update (tree *expr_p, gimple_seq *pre_p) gcc_unreachable (); } } - stmt = gimple_build_omp_target (NULL, kind, OMP_STANDALONE_CLAUSES (expr)); + stmt = gimple_build_omp_target (NULL, kind, OMP_STANDALONE_CLAUSES (expr), + iterator_loops_seq); gimplify_seq_add_stmt (pre_p, stmt); *expr_p = NULL_TREE; diff --git a/gcc/testsuite/ChangeLog.omp b/gcc/testsuite/ChangeLog.omp index bb5456a70eef..55b0ec12dcb3 100644 --- a/gcc/testsuite/ChangeLog.omp +++ b/gcc/testsuite/ChangeLog.omp @@ -1,3 +1,9 @@ +2025-04-17 Kwok Cheung Yeung <kcye...@baylibre.com> + + * c-c++-common/gomp/target-update-iterators-1.c: New. + * c-c++-common/gomp/target-update-iterators-2.c: New. + * c-c++-common/gomp/target-update-iterators-3.c: New. + 2025-04-17 Kwok Cheung Yeung <kcye...@baylibre.com> * c-c++-common/gomp/map-6.c (foo): Amend expected error message. diff --git a/gcc/testsuite/c-c++-common/gomp/target-update-iterators-1.c b/gcc/testsuite/c-c++-common/gomp/target-update-iterators-1.c new file mode 100644 index 000000000000..64602d45d494 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/target-update-iterators-1.c @@ -0,0 +1,20 @@ +/* { dg-do compile } */ +/* { dg-options "-fopenmp" } */ + +#define DIM1 17 +#define DIM2 39 + +void f (int **x, float **y) +{ + #pragma omp target update to (iterator(i=0:DIM1): x[i][:DIM2]) + + #pragma omp target update to (iterator(i=0:DIM1): x[i][:DIM2], y[i][:DIM2]) + + #pragma omp target update to (iterator(i=0:DIM1), present: x[i][:DIM2]) + + #pragma omp target update to (iterator(i=0:DIM1), iterator(j=0:DIM2): x[i][j]) /* { dg-error "too many 'iterator' modifiers" } */ + /* { dg-error ".#pragma omp target update. must contain at least one .from. or .to. clauses" "" { target *-*-* } .-1 } */ + + #pragma omp target update to (iterator(i=0:DIM1), something: x[i][j]) /* { dg-error ".to. or .from. clause with modifier other than .iterator., .mapper. or .present. before .something." } */ + /* { dg-error ".#pragma omp target update. must contain at least one .from. or .to. clauses" "" { target *-*-* } .-1 } */ +} diff --git a/gcc/testsuite/c-c++-common/gomp/target-update-iterators-2.c b/gcc/testsuite/c-c++-common/gomp/target-update-iterators-2.c new file mode 100644 index 000000000000..ae0a222485a0 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/target-update-iterators-2.c @@ -0,0 +1,23 @@ +/* { dg-do compile } */ +/* { dg-options "-fopenmp -fdump-tree-gimple" } */ + +void f (int *x, float *y, double *z) +{ + #pragma omp target update to(iterator(i=0:10): x) /* { dg-warning "iterator variable .i. not used in clause expression" }*/ + ; + + #pragma omp target update from(iterator(i2=0:10, j2=0:20): x[i2]) /* { dg-warning "iterator variable .j2. not used in clause expression" }*/ + ; + + #pragma omp target update to(iterator(i3=0:10, j3=0:20, k3=0:30): x[i3+j3], y[j3+k3], z[k3+i3]) + /* { dg-warning "iterator variable .i3. not used in clause expression" "" { target *-*-* } .-1 } */ + /* { dg-warning "iterator variable .j3. not used in clause expression" "" { target *-*-* } .-2 } */ + /* { dg-warning "iterator variable .k3. not used in clause expression" "" { target *-*-* } .-3 } */ + ; +} + +/* { dg-final { scan-tree-dump "update to\\\(x " "gimple" } } */ +/* { dg-final { scan-tree-dump "update from\\\(iterator\\\(int i2=0:10:1, loop_label=" "gimple" } } */ +/* { dg-final { scan-tree-dump "to\\\(iterator\\\(int i3=0:10:1, int k3=0:30:1, loop_label=" "gimple" } } */ +/* { dg-final { scan-tree-dump "to\\\(iterator\\\(int j3=0:20:1, int k3=0:30:1, loop_label=" "gimple" } } */ +/* { dg-final { scan-tree-dump "to\\\(iterator\\\(int i3=0:10:1, int j3=0:20:1, loop_label=" "gimple" } } */ diff --git a/gcc/testsuite/c-c++-common/gomp/target-update-iterators-3.c b/gcc/testsuite/c-c++-common/gomp/target-update-iterators-3.c new file mode 100644 index 000000000000..ef55216876f6 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/target-update-iterators-3.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-options "-fopenmp -fdump-tree-gimple" } */ + +#define DIM1 10 +#define DIM2 20 +#define DIM3 30 + +void f (int ***x, float ***y, double **z) +{ + #pragma omp target update to (iterator(i=0:DIM1, j=0:DIM2): x[i][j][:DIM3], y[i][j][:DIM3]) + #pragma omp target update from (iterator(i=0:DIM1): z[i][:DIM2]) +} + +/* { dg-final { scan-tree-dump-times "if \\(i <= 9\\) goto <D\.\[0-9\]+>; else goto <D\.\[0-9\]+>;" 2 "gimple" } } */ +/* { dg-final { scan-tree-dump-times "if \\(j <= 19\\) goto <D\.\[0-9\]+>; else goto <D\.\[0-9\]+>;" 1 "gimple" } } */ +/* { dg-final { scan-tree-dump-times "to\\(iterator\\(int i=0:10:1, int j=0:20:1, loop_label=<D\.\[0-9\]+>, elems=omp_iter_data\.\[0-9\]+, index=D\.\[0-9\]+\\):\\*D\.\[0-9\]+" 2 "gimple" } } */ +/* { dg-final { scan-tree-dump-times "from\\(iterator\\(int i=0:10:1, loop_label=<D\.\[0-9\]+>, elems=omp_iter_data\.\[0-9\]+, index=D\.\[0-9\]+\\):\\*D\.\[0-9\]+" 1 "gimple" } } */ diff --git a/gcc/tree-pretty-print.cc b/gcc/tree-pretty-print.cc index 5a0c4fc43fc7..cbdcd3bc0a1a 100644 --- a/gcc/tree-pretty-print.cc +++ b/gcc/tree-pretty-print.cc @@ -1270,6 +1270,11 @@ dump_omp_clause (pretty_printer *pp, tree clause, int spc, dump_flags_t flags) pp_string (pp, "from("); if (OMP_CLAUSE_MOTION_PRESENT (clause)) pp_string (pp, "present:"); + if (OMP_CLAUSE_ITERATORS (clause)) + { + dump_omp_iterators (pp, OMP_CLAUSE_ITERATORS (clause), spc, flags); + pp_colon (pp); + } dump_generic_node (pp, OMP_CLAUSE_DECL (clause), spc, flags, false); goto print_clause_size; @@ -1278,6 +1283,11 @@ dump_omp_clause (pretty_printer *pp, tree clause, int spc, dump_flags_t flags) pp_string (pp, "to("); if (OMP_CLAUSE_MOTION_PRESENT (clause)) pp_string (pp, "present:"); + if (OMP_CLAUSE_ITERATORS (clause)) + { + dump_omp_iterators (pp, OMP_CLAUSE_ITERATORS (clause), spc, flags); + pp_colon (pp); + } dump_generic_node (pp, OMP_CLAUSE_DECL (clause), spc, flags, false); goto print_clause_size; diff --git a/gcc/tree.cc b/gcc/tree.cc index 5de1c3aa3815..d3dfd8b1d507 100644 --- a/gcc/tree.cc +++ b/gcc/tree.cc @@ -264,8 +264,8 @@ unsigned const char omp_clause_num_ops[] = 1, /* OMP_CLAUSE_IS_DEVICE_PTR */ 1, /* OMP_CLAUSE_INCLUSIVE */ 1, /* OMP_CLAUSE_EXCLUSIVE */ - 2, /* OMP_CLAUSE_FROM */ - 2, /* OMP_CLAUSE_TO */ + 3, /* OMP_CLAUSE_FROM */ + 3, /* OMP_CLAUSE_TO */ 3, /* OMP_CLAUSE_MAP */ 1, /* OMP_CLAUSE_HAS_DEVICE_ADDR */ 1, /* OMP_CLAUSE_DOACROSS */ diff --git a/gcc/tree.h b/gcc/tree.h index 5dec4c0a8c62..e6268c1eb076 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -1635,11 +1635,13 @@ class auto_suppress_location_wrappers #define OMP_CLAUSE_LOCATION(NODE) (OMP_CLAUSE_CHECK (NODE))->omp_clause.locus #define OMP_CLAUSE_HAS_ITERATORS(NODE) \ - (OMP_CLAUSE_CODE (NODE) == OMP_CLAUSE_MAP \ + ((OMP_CLAUSE_CODE (NODE) == OMP_CLAUSE_FROM \ + || OMP_CLAUSE_CODE (NODE) == OMP_CLAUSE_TO \ + || OMP_CLAUSE_CODE (NODE) == OMP_CLAUSE_MAP) \ && OMP_CLAUSE_ITERATORS (NODE)) #define OMP_CLAUSE_ITERATORS(NODE) \ OMP_CLAUSE_OPERAND (OMP_CLAUSE_RANGE_CHECK (OMP_CLAUSE_CHECK (NODE), \ - OMP_CLAUSE_MAP, \ + OMP_CLAUSE_FROM, \ OMP_CLAUSE_MAP), 2) /* True on OMP_FOR and other OpenMP/OpenACC looping constructs if the loop nest diff --git a/libgomp/ChangeLog.omp b/libgomp/ChangeLog.omp index c93ae3b4fd5e..ca16b1e11a0b 100644 --- a/libgomp/ChangeLog.omp +++ b/libgomp/ChangeLog.omp @@ -1,3 +1,11 @@ +2025-04-17 Kwok Cheung Yeung <kcye...@baylibre.com> + + * target.c (gomp_update): Call gomp_merge_iterator_maps. Free + allocated variables. + * testsuite/libgomp.c-c++-common/target-update-iterators-1.c: New. + * testsuite/libgomp.c-c++-common/target-update-iterators-2.c: New. + * testsuite/libgomp.c-c++-common/target-update-iterators-3.c: New. + 2025-04-17 Kwok Cheung Yeung <kcye...@baylibre.com> * target.c (kind_to_name): New. diff --git a/libgomp/target.c b/libgomp/target.c index c0532ba1a673..aadb43731711 100644 --- a/libgomp/target.c +++ b/libgomp/target.c @@ -2449,6 +2449,8 @@ gomp_update (struct gomp_device_descr *devicep, size_t mapnum, void **hostaddrs, size_t i; struct splay_tree_key_s cur_node; const int typemask = short_mapkind ? 0xff : 0x7; + bool iterators_p = false; + size_t *iterator_count = NULL; if (!devicep) return; @@ -2456,6 +2458,10 @@ gomp_update (struct gomp_device_descr *devicep, size_t mapnum, void **hostaddrs, if (mapnum == 0) return; + if (short_mapkind) + iterators_p = gomp_merge_iterator_maps (&mapnum, &hostaddrs, &sizes, + &kinds, &iterator_count); + gomp_mutex_lock (&devicep->lock); if (devicep->state == GOMP_DEVICE_FINALIZED) { @@ -2593,6 +2599,14 @@ gomp_update (struct gomp_device_descr *devicep, size_t mapnum, void **hostaddrs, } } gomp_mutex_unlock (&devicep->lock); + + if (iterators_p) + { + free (hostaddrs); + free (sizes); + free (kinds); + free (iterator_count); + } } static struct gomp_offload_icv_list * diff --git a/libgomp/testsuite/libgomp.c-c++-common/target-update-iterators-1.c b/libgomp/testsuite/libgomp.c-c++-common/target-update-iterators-1.c new file mode 100644 index 000000000000..5a4cad5c2195 --- /dev/null +++ b/libgomp/testsuite/libgomp.c-c++-common/target-update-iterators-1.c @@ -0,0 +1,65 @@ +/* { dg-do run } */ + +/* Test target enter data and target update to the target using map + iterators. */ + +#include <stdlib.h> + +#define DIM1 8 +#define DIM2 15 + +int mkarray (int *x[]) +{ + int expected = 0; + for (int i = 0; i < DIM1; i++) + { + x[i] = (int *) malloc (DIM2 * sizeof (int)); + for (int j = 0; j < DIM2; j++) + { + x[i][j] = rand (); + expected += x[i][j]; + } + } + + return expected; +} + +int main (void) +{ + int *x[DIM1]; + int sum; + int expected = mkarray (x); + + #pragma omp target enter data map(to: x[:DIM1]) + #pragma omp target enter data map(iterator(i=0:DIM1), to: x[i][:DIM2]) + #pragma omp target map(from: sum) + { + sum = 0; + for (int i = 0; i < DIM1; i++) + for (int j = 0; j < DIM2; j++) + sum += x[i][j]; + } + + if (sum != expected) + return 1; + + expected = 0; + for (int i = 0; i < DIM1; i++) + for (int j = 0; j < DIM2; j++) + { + x[i][j] *= rand (); + expected += x[i][j]; + } + + #pragma omp target update to(iterator(i=0:DIM1): x[i][:DIM2]) + + #pragma omp target map(from: sum) + { + sum = 0; + for (int i = 0; i < DIM1; i++) + for (int j = 0; j < DIM2; j++) + sum += x[i][j]; + } + + return sum != expected; +} diff --git a/libgomp/testsuite/libgomp.c-c++-common/target-update-iterators-2.c b/libgomp/testsuite/libgomp.c-c++-common/target-update-iterators-2.c new file mode 100644 index 000000000000..93438d01c97e --- /dev/null +++ b/libgomp/testsuite/libgomp.c-c++-common/target-update-iterators-2.c @@ -0,0 +1,58 @@ +/* { dg-do run } */ +/* { dg-require-effective-target offload_device_nonshared_as } */ + +/* Test target enter data and target update from the target using map + iterators. */ + +#include <stdlib.h> + +#define DIM1 8 +#define DIM2 15 + +void mkarray (int *x[]) +{ + for (int i = 0; i < DIM1; i++) + { + x[i] = (int *) malloc (DIM2 * sizeof (int)); + for (int j = 0; j < DIM2; j++) + x[i][j] = 0; + } +} + +int main (void) +{ + int *x[DIM1]; + int sum, expected; + + mkarray (x); + + #pragma omp target enter data map(alloc: x[:DIM1]) + #pragma omp target enter data map(iterator(i=0:DIM1), to: x[i][:DIM2]) + #pragma omp target map(from: expected) + { + expected = 0; + for (int i = 0; i < DIM1; i++) + for (int j = 0; j < DIM2; j++) + { + x[i][j] = (i + 1) * (j + 2); + expected += x[i][j]; + } + } + + /* Host copy of x should remain unchanged. */ + sum = 0; + for (int i = 0; i < DIM1; i++) + for (int j = 0; j < DIM2; j++) + sum += x[i][j]; + if (sum != 0) + return 1; + + #pragma omp target update from(iterator(i=0:DIM1): x[i][:DIM2]) + + /* Host copy should now be updated. */ + sum = 0; + for (int i = 0; i < DIM1; i++) + for (int j = 0; j < DIM2; j++) + sum += x[i][j]; + return sum - expected; +} diff --git a/libgomp/testsuite/libgomp.c-c++-common/target-update-iterators-3.c b/libgomp/testsuite/libgomp.c-c++-common/target-update-iterators-3.c new file mode 100644 index 000000000000..a70b21c4b75a --- /dev/null +++ b/libgomp/testsuite/libgomp.c-c++-common/target-update-iterators-3.c @@ -0,0 +1,67 @@ +/* { dg-do run } */ +/* { dg-require-effective-target offload_device_nonshared_as } */ + +/* Test target enter data and target update to the target using map + iterators with a function. */ + +#include <stdlib.h> + +#define DIM1 8 +#define DIM2 15 + +void mkarray (int *x[]) +{ + for (int i = 0; i < DIM1; i++) + { + x[i] = (int *) malloc (DIM2 * sizeof (int)); + for (int j = 0; j < DIM2; j++) + x[i][j] = rand (); + } +} + +int f (int i) +{ + return i * 2; +} + +int main (void) +{ + int *x[DIM1], x_new[DIM1][DIM2]; + int sum, expected; + + mkarray (x); + + #pragma omp target enter data map(alloc: x[:DIM1]) + #pragma omp target enter data map(iterator(i=0:DIM1), to: x[i][:DIM2]) + + /* Update x on host. */ + for (int i = 0; i < DIM1; i++) + for (int j = 0; j < DIM2; j++) + { + x_new[i][j] = x[i][j]; + x[i][j] = (i + 1) * (j + 2); + } + + /* Update a subset of x on target. */ + #pragma omp target update to(iterator(i=0:DIM1/2): x[f (i)][:DIM2]) + + #pragma omp target map(from: sum) + { + sum = 0; + for (int i = 0; i < DIM1; i++) + for (int j = 0; j < DIM2; j++) + sum += x[i][j]; + } + + /* Calculate expected value on host. */ + for (int i = 0; i < DIM1/2; i++) + for (int j = 0; j < DIM2; j++) + x_new[f (i)][j] = x[f (i)][j]; + + expected = 0; + for (int i = 0; i < DIM1; i++) + for (int j = 0; j < DIM2; j++) + expected += x_new[i][j]; + + return sum - expected; +}