diff options
author | Jakub Jelinek <jakub@redhat.com> | 2018-07-10 09:12:37 +0200 |
---|---|---|
committer | Jakub Jelinek <jakub@gcc.gnu.org> | 2018-07-10 09:12:37 +0200 |
commit | 0b27c3eda934bfc946d64fb72203001c5bee46a1 (patch) | |
tree | f53906c4b6e36f6adb263e98f301f5e3fd465d11 /gcc | |
parent | c0cb9a9da0a7e257297deb25193cc9f113ee672a (diff) | |
download | gcc-0b27c3eda934bfc946d64fb72203001c5bee46a1.zip gcc-0b27c3eda934bfc946d64fb72203001c5bee46a1.tar.gz gcc-0b27c3eda934bfc946d64fb72203001c5bee46a1.tar.bz2 |
re PR c++/86443 (ICEs on #pragma omp distribute parallel for with class iterators)
PR c++/86443
* gimplify.c (find_combined_omp_for): Add DATA argument, in addition
to finding the inner OMP_FOR/OMP_SIMD stmt find non-trivial wrappers,
BLOCKs with BLOCK_VARs, OMP_PARALLEL in between, OMP_FOR in between.
(gimplify_omp_for): For composite loops, move outer
OMP_{DISTRIBUTE,TASKLOOP,FOR,PARALLEL} right around innermost
OMP_FOR/OMP_SIMD if there are any non-trivial wrappers. For class
iterators add any needed clauses. Allow OMP_FOR_ORIG_DECLS to contain
TREE_LIST for both the original class iterator and the "last" helper
var. Gimplify OMP_FOR_PRE_BODY before the outermost composite
loop, remember has_decl_expr from outer composite loops for the
innermost OMP_SIMD in TREE_PRIVATE bit on OMP_FOR_INIT.
gcc/c-family/
* c-omp.c (c_omp_check_loop_iv_r, c_omp_check_loop_iv): Allow declv
to contain TREE_LIST for both the original class iterator and the
"last" helper var.
gcc/cp/
* semantics.c (handle_omp_for_class_iterator): Remove lastp argument,
instead of setting *lastp turn orig_declv elt into a TREE_LIST.
(finish_omp_for): Adjust handle_omp_for_class_iterator caller.
* pt.c (tsubst_omp_for_iterator): Allow OMP_FOR_ORIG_DECLS to contain
TREE_LIST for both the original class iterator and the "last" helper
var.
libgomp/
* testsuite/libgomp.c++/for-15.C: New test.
From-SVN: r262534
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 15 | ||||
-rw-r--r-- | gcc/c-family/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/c-family/c-omp.c | 8 | ||||
-rw-r--r-- | gcc/cp/ChangeLog | 10 | ||||
-rw-r--r-- | gcc/cp/pt.c | 7 | ||||
-rw-r--r-- | gcc/cp/semantics.c | 8 | ||||
-rw-r--r-- | gcc/gimplify.c | 185 |
7 files changed, 210 insertions, 30 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index dda22d8..3230cf3 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,18 @@ +2018-07-10 Jakub Jelinek <jakub@redhat.com> + + PR c++/86443 + * gimplify.c (find_combined_omp_for): Add DATA argument, in addition + to finding the inner OMP_FOR/OMP_SIMD stmt find non-trivial wrappers, + BLOCKs with BLOCK_VARs, OMP_PARALLEL in between, OMP_FOR in between. + (gimplify_omp_for): For composite loops, move outer + OMP_{DISTRIBUTE,TASKLOOP,FOR,PARALLEL} right around innermost + OMP_FOR/OMP_SIMD if there are any non-trivial wrappers. For class + iterators add any needed clauses. Allow OMP_FOR_ORIG_DECLS to contain + TREE_LIST for both the original class iterator and the "last" helper + var. Gimplify OMP_FOR_PRE_BODY before the outermost composite + loop, remember has_decl_expr from outer composite loops for the + innermost OMP_SIMD in TREE_PRIVATE bit on OMP_FOR_INIT. + 2018-07-09 Martin Sebor <msebor@redhat.com> PR middle-end/77357 diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index bf4e7e9..a459f06 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,10 @@ +2018-07-10 Jakub Jelinek <jakub@redhat.com> + + PR c++/86443 + * c-omp.c (c_omp_check_loop_iv_r, c_omp_check_loop_iv): Allow declv + to contain TREE_LIST for both the original class iterator and the + "last" helper var. + 2018-07-07 Eric Botcazou <ebotcazou@adacore.com> * c-ada-spec.c (to_ada_name): Remove index parameter. diff --git a/gcc/c-family/c-omp.c b/gcc/c-family/c-omp.c index d8695f5..8984937 100644 --- a/gcc/c-family/c-omp.c +++ b/gcc/c-family/c-omp.c @@ -827,7 +827,9 @@ c_omp_check_loop_iv_r (tree *tp, int *walk_subtrees, void *data) { int i; for (i = 0; i < TREE_VEC_LENGTH (d->declv); i++) - if (*tp == TREE_VEC_ELT (d->declv, i)) + if (*tp == TREE_VEC_ELT (d->declv, i) + || (TREE_CODE (TREE_VEC_ELT (d->declv, i)) == TREE_LIST + && *tp == TREE_PURPOSE (TREE_VEC_ELT (d->declv, i)))) { location_t loc = d->expr_loc; if (loc == UNKNOWN_LOCATION) @@ -894,7 +896,9 @@ c_omp_check_loop_iv (tree stmt, tree declv, walk_tree_lh lh) expression then involves the subtraction and always refers to the original value. The C++ FE needs to warn on those earlier. */ - if (decl == TREE_VEC_ELT (declv, i)) + if (decl == TREE_VEC_ELT (declv, i) + || (TREE_CODE (TREE_VEC_ELT (declv, i)) == TREE_LIST + && decl == TREE_PURPOSE (TREE_VEC_ELT (declv, i)))) { data.expr_loc = EXPR_LOCATION (cond); data.kind = 1; diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 82cb481..86d4a34 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,13 @@ +2018-07-10 Jakub Jelinek <jakub@redhat.com> + + PR c++/86443 + * semantics.c (handle_omp_for_class_iterator): Remove lastp argument, + instead of setting *lastp turn orig_declv elt into a TREE_LIST. + (finish_omp_for): Adjust handle_omp_for_class_iterator caller. + * pt.c (tsubst_omp_for_iterator): Allow OMP_FOR_ORIG_DECLS to contain + TREE_LIST for both the original class iterator and the "last" helper + var. + 2018-07-09 Paolo Carlini <paolo.carlini@oracle.com> * decl.c (grokdeclarator): Use rich_location::add_range in three diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 3780f34..eae9e14 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -16267,7 +16267,12 @@ tsubst_omp_for_iterator (tree t, int i, tree declv, tree orig_declv, if (orig_declv && OMP_FOR_ORIG_DECLS (t)) { tree o = TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (t), i); - TREE_VEC_ELT (orig_declv, i) = RECUR (o); + if (TREE_CODE (o) == TREE_LIST) + TREE_VEC_ELT (orig_declv, i) + = tree_cons (RECUR (TREE_PURPOSE (o)), + RECUR (TREE_VALUE (o)), NULL_TREE); + else + TREE_VEC_ELT (orig_declv, i) = RECUR (o); } decl = TREE_OPERAND (init, 0); diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index c779137..ef73d07 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -7679,7 +7679,7 @@ static bool handle_omp_for_class_iterator (int i, location_t locus, enum tree_code code, tree declv, tree orig_declv, tree initv, tree condv, tree incrv, tree *body, - tree *pre_body, tree &clauses, tree *lastp, + tree *pre_body, tree &clauses, int collapse, int ordered) { tree diff, iter_init, iter_incr = NULL, last; @@ -7983,7 +7983,8 @@ handle_omp_for_class_iterator (int i, location_t locus, enum tree_code code, TREE_VEC_ELT (initv, i) = init; TREE_VEC_ELT (condv, i) = cond; TREE_VEC_ELT (incrv, i) = incr; - *lastp = last; + TREE_VEC_ELT (orig_declv, i) + = tree_cons (TREE_VEC_ELT (orig_declv, i), last, NULL_TREE); return false; } @@ -8002,7 +8003,6 @@ finish_omp_for (location_t locus, enum tree_code code, tree declv, { tree omp_for = NULL, orig_incr = NULL; tree decl = NULL, init, cond, incr; - tree last = NULL_TREE; location_t elocus; int i; int collapse = 1; @@ -8169,7 +8169,7 @@ finish_omp_for (location_t locus, enum tree_code code, tree declv, } if (handle_omp_for_class_iterator (i, locus, code, declv, orig_declv, initv, condv, incrv, &body, - &pre_body, clauses, &last, + &pre_body, clauses, collapse, ordered)) return NULL; continue; diff --git a/gcc/gimplify.c b/gcc/gimplify.c index c86ad1a..6b76d17 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -9532,24 +9532,53 @@ gimplify_omp_task (tree *expr_p, gimple_seq *pre_p) } /* Helper function of gimplify_omp_for, find OMP_FOR resp. OMP_SIMD - with non-NULL OMP_FOR_INIT. */ + with non-NULL OMP_FOR_INIT. Also, fill in pdata array, + pdata[0] non-NULL if there is anything non-trivial in between, pdata[1] + is address of OMP_PARALLEL in between if any, pdata[2] is address of + OMP_FOR in between if any and pdata[3] is address of the inner + OMP_FOR/OMP_SIMD. */ static tree -find_combined_omp_for (tree *tp, int *walk_subtrees, void *) +find_combined_omp_for (tree *tp, int *walk_subtrees, void *data) { + tree **pdata = (tree **) data; *walk_subtrees = 0; switch (TREE_CODE (*tp)) { case OMP_FOR: + if (OMP_FOR_INIT (*tp) != NULL_TREE) + { + pdata[3] = tp; + return *tp; + } + pdata[2] = tp; *walk_subtrees = 1; - /* FALLTHRU */ + break; case OMP_SIMD: if (OMP_FOR_INIT (*tp) != NULL_TREE) - return *tp; + { + pdata[3] = tp; + return *tp; + } break; case BIND_EXPR: + if (BIND_EXPR_VARS (*tp) + || (BIND_EXPR_BLOCK (*tp) + && BLOCK_VARS (BIND_EXPR_BLOCK (*tp)))) + pdata[0] = tp; + *walk_subtrees = 1; + break; case STATEMENT_LIST: + if (!tsi_one_before_end_p (tsi_start (*tp))) + pdata[0] = tp; + *walk_subtrees = 1; + break; + case TRY_FINALLY_EXPR: + pdata[0] = tp; + *walk_subtrees = 1; + break; case OMP_PARALLEL: + pdata[1] = tp; *walk_subtrees = 1; break; default: @@ -9574,6 +9603,115 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p) orig_for_stmt = for_stmt = *expr_p; + if (OMP_FOR_INIT (for_stmt) == NULL_TREE) + { + tree *data[4] = { NULL, NULL, NULL, NULL }; + gcc_assert (TREE_CODE (for_stmt) != OACC_LOOP); + inner_for_stmt = walk_tree (&OMP_FOR_BODY (for_stmt), + find_combined_omp_for, data, NULL); + if (inner_for_stmt == NULL_TREE) + { + gcc_assert (seen_error ()); + *expr_p = NULL_TREE; + return GS_ERROR; + } + if (data[2] && OMP_FOR_PRE_BODY (*data[2])) + { + append_to_statement_list_force (OMP_FOR_PRE_BODY (*data[2]), + &OMP_FOR_PRE_BODY (for_stmt)); + OMP_FOR_PRE_BODY (*data[2]) = NULL_TREE; + } + if (OMP_FOR_PRE_BODY (inner_for_stmt)) + { + append_to_statement_list_force (OMP_FOR_PRE_BODY (inner_for_stmt), + &OMP_FOR_PRE_BODY (for_stmt)); + OMP_FOR_PRE_BODY (inner_for_stmt) = NULL_TREE; + } + + if (data[0]) + { + /* We have some statements or variable declarations in between + the composite construct directives. Move them around the + inner_for_stmt. */ + data[0] = expr_p; + for (i = 0; i < 3; i++) + if (data[i]) + { + tree t = *data[i]; + if (i < 2 && data[i + 1] == &OMP_BODY (t)) + data[i + 1] = data[i]; + *data[i] = OMP_BODY (t); + tree body = build3 (BIND_EXPR, void_type_node, NULL_TREE, + NULL_TREE, make_node (BLOCK)); + OMP_BODY (t) = body; + append_to_statement_list_force (inner_for_stmt, + &BIND_EXPR_BODY (body)); + *data[3] = t; + data[3] = tsi_stmt_ptr (tsi_start (BIND_EXPR_BODY (body))); + gcc_assert (*data[3] == inner_for_stmt); + } + return GS_OK; + } + + for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (inner_for_stmt)); i++) + if (OMP_FOR_ORIG_DECLS (inner_for_stmt) + && TREE_CODE (TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (inner_for_stmt), + i)) == TREE_LIST) + { + tree orig = TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (inner_for_stmt), i); + /* Class iterators aren't allowed on OMP_SIMD, so the only + case we need to solve is distribute parallel for. */ + gcc_assert (TREE_CODE (inner_for_stmt) == OMP_FOR + && TREE_CODE (for_stmt) == OMP_DISTRIBUTE + && data[1]); + tree orig_decl = TREE_PURPOSE (orig); + tree last = TREE_VALUE (orig); + tree *pc; + for (pc = &OMP_FOR_CLAUSES (inner_for_stmt); + *pc; pc = &OMP_CLAUSE_CHAIN (*pc)) + if ((OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_PRIVATE + || OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_LASTPRIVATE) + && OMP_CLAUSE_DECL (*pc) == orig_decl) + break; + if (*pc == NULL_TREE) + ; + else if (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_PRIVATE) + { + /* private clause will appear only on inner_for_stmt. + Change it into firstprivate, and add private clause + on for_stmt. */ + tree c = copy_node (*pc); + OMP_CLAUSE_CHAIN (c) = OMP_FOR_CLAUSES (for_stmt); + OMP_FOR_CLAUSES (for_stmt) = c; + OMP_CLAUSE_CODE (*pc) = OMP_CLAUSE_FIRSTPRIVATE; + lang_hooks.decls.omp_finish_clause (*pc, pre_p); + } + else + { + /* lastprivate clause will appear on both inner_for_stmt + and for_stmt. Add firstprivate clause to + inner_for_stmt. */ + tree c = build_omp_clause (OMP_CLAUSE_LOCATION (*pc), + OMP_CLAUSE_FIRSTPRIVATE); + OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (*pc); + OMP_CLAUSE_CHAIN (c) = *pc; + *pc = c; + lang_hooks.decls.omp_finish_clause (*pc, pre_p); + } + tree c = build_omp_clause (UNKNOWN_LOCATION, + OMP_CLAUSE_FIRSTPRIVATE); + OMP_CLAUSE_DECL (c) = last; + OMP_CLAUSE_CHAIN (c) = OMP_PARALLEL_CLAUSES (*data[1]); + OMP_PARALLEL_CLAUSES (*data[1]) = c; + c = build_omp_clause (UNKNOWN_LOCATION, + *pc ? OMP_CLAUSE_SHARED + : OMP_CLAUSE_FIRSTPRIVATE); + OMP_CLAUSE_DECL (c) = orig_decl; + OMP_CLAUSE_CHAIN (c) = OMP_PARALLEL_CLAUSES (*data[1]); + OMP_PARALLEL_CLAUSES (*data[1]) = c; + } + } + switch (TREE_CODE (for_stmt)) { case OMP_FOR: @@ -9611,19 +9749,6 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p) } } - if (OMP_FOR_INIT (for_stmt) == NULL_TREE) - { - gcc_assert (TREE_CODE (for_stmt) != OACC_LOOP); - inner_for_stmt = walk_tree (&OMP_FOR_BODY (for_stmt), - find_combined_omp_for, NULL, NULL); - if (inner_for_stmt == NULL_TREE) - { - gcc_assert (seen_error ()); - *expr_p = NULL_TREE; - return GS_ERROR; - } - } - if (TREE_CODE (for_stmt) != OMP_TASKLOOP) gimplify_scan_omp_clauses (&OMP_FOR_CLAUSES (for_stmt), pre_p, ort, TREE_CODE (for_stmt)); @@ -9633,7 +9758,9 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p) /* Handle OMP_FOR_INIT. */ for_pre_body = NULL; - if (ort == ORT_SIMD && OMP_FOR_PRE_BODY (for_stmt)) + if ((ort == ORT_SIMD + || (inner_for_stmt && TREE_CODE (inner_for_stmt) == OMP_SIMD)) + && OMP_FOR_PRE_BODY (for_stmt)) { has_decl_expr = BITMAP_ALLOC (NULL); if (TREE_CODE (OMP_FOR_PRE_BODY (for_stmt)) == DECL_EXPR @@ -9774,8 +9901,12 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p) if (is_doacross) { if (TREE_CODE (for_stmt) == OMP_FOR && OMP_FOR_ORIG_DECLS (for_stmt)) - gimplify_omp_ctxp->loop_iter_var.quick_push - (TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (for_stmt), i)); + { + tree orig_decl = TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (for_stmt), i); + if (TREE_CODE (orig_decl) == TREE_LIST) + orig_decl = TREE_PURPOSE (orig_decl); + gimplify_omp_ctxp->loop_iter_var.quick_push (orig_decl); + } else gimplify_omp_ctxp->loop_iter_var.quick_push (decl); gimplify_omp_ctxp->loop_iter_var.quick_push (decl); @@ -9785,7 +9916,12 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p) tree c = NULL_TREE; tree c2 = NULL_TREE; if (orig_for_stmt != for_stmt) - /* Do this only on innermost construct for combined ones. */; + { + /* Preserve this information until we gimplify the inner simd. */ + if (has_decl_expr + && bitmap_bit_p (has_decl_expr, DECL_UID (decl))) + TREE_PRIVATE (t) = 1; + } else if (ort == ORT_SIMD) { splay_tree_node n = splay_tree_lookup (gimplify_omp_ctxp->variables, @@ -9800,8 +9936,9 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p) c = build_omp_clause (input_location, OMP_CLAUSE_LINEAR); OMP_CLAUSE_LINEAR_NO_COPYIN (c) = 1; unsigned int flags = GOVD_LINEAR | GOVD_EXPLICIT | GOVD_SEEN; - if (has_decl_expr - && bitmap_bit_p (has_decl_expr, DECL_UID (decl))) + if ((has_decl_expr + && bitmap_bit_p (has_decl_expr, DECL_UID (decl))) + || TREE_PRIVATE (t)) { OMP_CLAUSE_LINEAR_NO_COPYOUT (c) = 1; flags |= GOVD_LINEAR_LASTPRIVATE_NO_OUTER; @@ -9923,6 +10060,8 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p) bool lastprivate = (!has_decl_expr || !bitmap_bit_p (has_decl_expr, DECL_UID (decl))); + if (TREE_PRIVATE (t)) + lastprivate = false; struct gimplify_omp_ctx *outer = gimplify_omp_ctxp->outer_context; if (outer && lastprivate) |