This patch backports the reduction changes in trunk to gomp-4_0-branch. Prior to this patch, gomp-4_0-branch was having the gimplifier create a temporary variable for reference-typed reductions. That's no longer necessary with this patch.
Besides for the reference reduction changes, this patch also addresses some problems with reductions in acc parallel directives. Specifically, private and firstprivate reductions are reported as errors now, so that resolves PR70357. Thomas, there's still some divergence between trunk and gomp-4_0-branch in the various FEs. Those changes are too late for trunk right now. I'll take a closer look at them later, but maybe we should drop them in gomp-4_0-branch. I've applied this patch to gomp-4_0-branch. Cesar
2016-04-08 Cesar Philippidis <ce...@codesourcery.com> gcc/ PR tree-optimization/70357 * gimplify.c (gimplify_scan_omp_clauses): Remove stale acc reduction code. (gimplify_adjust_omp_clauses): Add or adjust data clauses for acc parallel reductions as necessary. Error on those that are private. (localize_reductions_r): Delete. (localize_reductions): Delete. (gimplify_omp_for): Don't call localize_reductions. (gimplify_omp_workshare): Likewise. * omp-low.c (build_outer_var_ref): Remove stale reduction-specific corner cases. (fixup_remapped_decl): Likewise. (scan_sharing_clauses): Don't install variables which are used in acc parallel reductions. (check_omp_nesting_restrictions): Remove stale reduction-specific corner cases. (scan_omp_1_stmt): Clean up whitespace. (lower_rec_input_clauses): Remove stale reduction-specific corner cases. (lower_oacc_reductions): Update it to handle parallel, reference and nested reductions. (lower_omp_target): Don't remap variables appearing in acc parallel reductions. * tree-core.h (enum omp_clause_code): Remove stale comments about the fifth reduction clause operand. * tree.c (omp_clause_num_ops): Set the number of reduction clause operands to 5. (walk_tree_1): Update error checking for the reduction clause. * tree.h (OMP_CLAUSE_MAP_IN_REDUCTION): New macro. diff --git a/gcc/gimplify.c b/gcc/gimplify.c index 5800fed..374d786 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -6542,12 +6542,9 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p, tree c, clauses = *list_p; hash_map<tree, tree> *struct_map_to_clause = NULL; tree *prev_list_p = NULL; - vec<tree> redvec; - bool processed_reductions = false; ctx = new_omp_context (region_type); outer_ctx = ctx->outer_context; - redvec.create (8); if (code == OMP_TARGET && !lang_GNU_Fortran ()) { ctx->target_map_pointers_as_0len_arrays = true; @@ -6696,10 +6693,6 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p, || TREE_CODE (decl) == INDIRECT_REF) decl = TREE_OPERAND (decl, 0); } - if ((region_type & ORT_ACC) && ((region_type & ORT_TARGET) != 0) - && (outer_ctx == NULL - || outer_ctx->region_type == ORT_ACC_DATA)) - redvec.safe_push (OMP_CLAUSE_DECL (c)); goto do_add_decl; case OMP_CLAUSE_LINEAR: if (gimplify_expr (&OMP_CLAUSE_LINEAR_STEP (c), pre_p, NULL, @@ -7553,46 +7546,6 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p, gcc_unreachable (); } - /* Add an implicit data-movement clause for an OpenACC parallel - reduction, if necessary. */ - if (OMP_CLAUSE_CHAIN (c) == NULL && !processed_reductions - && ((region_type & ORT_TARGET) != 0) - && (region_type & ORT_ACC)) - { - tree t; - - while (!redvec.is_empty ()) - { - tree decl = redvec.pop (); - bool mapped = false; - - for (t = clauses; t; t = OMP_CLAUSE_CHAIN (t)) - if (OMP_CLAUSE_CODE (t) == OMP_CLAUSE_MAP - && OMP_CLAUSE_DECL (t) == decl) - { - mapped = true; - if (OMP_CLAUSE_MAP_KIND (t) == GOMP_MAP_TOFROM - && OMP_CLAUSE_MAP_KIND (t) != GOMP_MAP_FORCE_TOFROM) - error_at (OMP_CLAUSE_LOCATION (t), - "incompatible data clause"); - break; - } - - if (!mapped) - { - /* Let gimplify_adjust_omp_clauses_1 create a new data - clause for the reduction. */ - - splay_tree_node n; - - n = splay_tree_lookup (ctx->variables, (splay_tree_key)decl); - n->value |= GOVD_MAP; - } - } - - processed_reductions = true; - } - if (remove) *list_p = OMP_CLAUSE_CHAIN (c); else @@ -8061,6 +8014,34 @@ gimplify_adjust_omp_clauses (gimple_seq *pre_p, gimple_seq body, tree *list_p, break; } decl = OMP_CLAUSE_DECL (c); + /* Data clasues associated with acc parallel reductions must be + compatible with present_or_copy. Warn and adjust the clause + if that is not the case. */ + if (ctx->region_type == ORT_ACC_PARALLEL) + { + tree t = DECL_P (decl) ? decl : TREE_OPERAND (decl, 0); + n = NULL; + + if (DECL_P (t)) + n = splay_tree_lookup (ctx->variables, (splay_tree_key) t); + + if (n && (n->value & GOVD_REDUCTION)) + { + enum gomp_map_kind kind = OMP_CLAUSE_MAP_KIND (c); + + OMP_CLAUSE_MAP_IN_REDUCTION (c) = 1; + if ((kind & GOMP_MAP_TOFROM) != GOMP_MAP_TOFROM + && kind != GOMP_MAP_FORCE_PRESENT + && kind != GOMP_MAP_POINTER) + { + warning_at (OMP_CLAUSE_LOCATION (c), 0, + "incompatible data clause with reduction " + "on %qE; promoting to present_or_copy", + DECL_NAME (t)); + OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_TOFROM); + } + } + } if (!DECL_P (decl)) { if ((ctx->region_type & ORT_TARGET) != 0 @@ -8192,6 +8173,33 @@ gimplify_adjust_omp_clauses (gimple_seq *pre_p, gimple_seq body, tree *list_p, case OMP_CLAUSE_REDUCTION: decl = OMP_CLAUSE_DECL (c); + /* OpenACC reductions need a present_or_copy data clause. + Add one if necessary. Error is the reduction is private. */ + if (ctx->region_type == ORT_ACC_PARALLEL) + { + n = splay_tree_lookup (ctx->variables, (splay_tree_key) decl); + if (n->value & (GOVD_PRIVATE | GOVD_FIRSTPRIVATE)) + error_at (OMP_CLAUSE_LOCATION (c), "invalid private " + "reduction on %qE", DECL_NAME (decl)); + else if ((n->value & GOVD_MAP) == 0) + { + tree next = OMP_CLAUSE_CHAIN (c); + tree nc = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_MAP); + OMP_CLAUSE_SET_MAP_KIND (nc, GOMP_MAP_TOFROM); + OMP_CLAUSE_DECL (nc) = decl; + OMP_CLAUSE_CHAIN (c) = nc; + lang_hooks.decls.omp_finish_clause (nc, pre_p); + while (1) + { + OMP_CLAUSE_MAP_IN_REDUCTION (nc) = 1; + if (OMP_CLAUSE_CHAIN (nc) == NULL) + break; + nc = OMP_CLAUSE_CHAIN (nc); + } + OMP_CLAUSE_CHAIN (nc) = next; + n->value |= GOVD_MAP; + } + } if (DECL_P (decl) && omp_shared_to_firstprivate_optimizable_decl_p (decl)) omp_mark_stores (gimplify_omp_ctxp->outer_context, decl); @@ -8497,87 +8505,6 @@ find_combined_omp_for (tree *tp, int *walk_subtrees, void *) return NULL_TREE; } -/* Helper function for localize_reductions. Replace all uses of REF_VAR with - LOCAL_VAR. */ - -static tree -localize_reductions_r (tree *tp, int *walk_subtrees, void *data) -{ - enum tree_code tc = TREE_CODE (*tp); - struct privatize_reduction *pr = (struct privatize_reduction *) data; - - if (TYPE_P (*tp)) - *walk_subtrees = 0; - - switch (tc) - { - case INDIRECT_REF: - case MEM_REF: - if (TREE_OPERAND (*tp, 0) == pr->ref_var) - *tp = pr->local_var; - - *walk_subtrees = 0; - break; - - case VAR_DECL: - case PARM_DECL: - case RESULT_DECL: - if (*tp == pr->ref_var) - *tp = pr->local_var; - - *walk_subtrees = 0; - break; - - default: - break; - } - - return NULL_TREE; -} - -/* OpenACC worker and vector loop state propagation requires reductions - to be inside local variables. This function replaces all reference-type - reductions variables associated with the loop with a local copy. It is - also used to create private copies of reduction variables for those - which are not associated with acc loops. */ - -static void -localize_reductions (tree *expr_p, bool target) -{ - tree clauses = target ? OMP_CLAUSES (*expr_p) : OMP_FOR_CLAUSES (*expr_p); - tree c, var, type, new_var; - struct privatize_reduction pr; - - for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c)) - if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION) - { - var = OMP_CLAUSE_DECL (c); - - if (!target && !lang_hooks.decls.omp_privatize_by_reference (var)) - { - OMP_CLAUSE_REDUCTION_PRIVATE_DECL (c) = NULL; - continue; - } - - if (lang_hooks.decls.omp_privatize_by_reference (var)) - type = TREE_TYPE (TREE_TYPE (var)); - else - type = TREE_TYPE (var); - new_var = create_tmp_var (type); - - pr.ref_var = var; - pr.local_var = new_var; - - /* Only replace var with new_var within the region associated the - current ACC construct, not in the clauses of this construct. */ - tree region = TREE_OPERAND (*expr_p, 0); - - walk_tree (®ion, localize_reductions_r, &pr, NULL); - - OMP_CLAUSE_REDUCTION_PRIVATE_DECL (c) = new_var; - } -} - /* Gimplify the gross structure of an OMP_FOR statement. */ static enum gimplify_status @@ -8617,29 +8544,6 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p) gcc_unreachable (); } - /* Strip out reductions, as they are not handled yet. */ - if (gimplify_omp_ctxp != NULL - && (gimplify_omp_ctxp->region_type == ORT_ACC_KERNELS - || (gimplify_omp_ctxp->outer_context != NULL - && (gimplify_omp_ctxp->outer_context->region_type - == ORT_ACC_KERNELS)))) - { - tree *prev_ptr = &OMP_FOR_CLAUSES (for_stmt); - - while (tree probe = *prev_ptr) - { - tree *next_ptr = &OMP_CLAUSE_CHAIN (probe); - - if (OMP_CLAUSE_CODE (probe) == OMP_CLAUSE_REDUCTION) - *prev_ptr = *next_ptr; - else - prev_ptr = next_ptr; - } - } - - if (ort == ORT_ACC) - localize_reductions (expr_p, false); - /* Set OMP_CLAUSE_LINEAR_NO_COPYIN flag on explicit linear clause for the IV. */ if (ort == ORT_SIMD && TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)) == 1) @@ -9714,10 +9618,6 @@ gimplify_omp_workshare (tree *expr_p, gimple_seq *pre_p) if ((ort & (ORT_TARGET | ORT_TARGET_DATA)) != 0) { push_gimplify_context (); - - if (ort & ORT_ACC) - localize_reductions (expr_p, true); - gimple *g = gimplify_and_return_first (OMP_BODY (expr), &body); if (gimple_code (g) == GIMPLE_BIND) pop_gimplify_context (g); diff --git a/gcc/omp-low.c b/gcc/omp-low.c index 9cb6425..276cf7a 100644 --- a/gcc/omp-low.c +++ b/gcc/omp-low.c @@ -83,7 +83,6 @@ along with GCC; see the file COPYING3. If not see #include "symbol-summary.h" #include "hsa.h" #include "params.h" -#include "set" #include "tree-ssa-propagate.h" /* Lowering of OMP parallel and workshare constructs proceeds in two @@ -1358,18 +1357,6 @@ build_outer_var_ref (tree var, omp_context *ctx, bool lastprivate = false) gcc_assert (outer && gimple_code (outer->stmt) != GIMPLE_OMP_GRID_BODY); } - /* OpenACC may have multiple outer contexts (one per loop). */ - if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR - && gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_OACC_LOOP) - { - do - { - x = maybe_lookup_decl (var, outer); - outer = outer->outer; - } - while (!x); - } - else x = lookup_decl (var, outer); } else if (is_reference (var)) @@ -1559,10 +1546,6 @@ fixup_remapped_decl (tree decl, omp_context *ctx, bool private_debug) new_decl = lookup_decl (decl, ctx); - /* Ignore these for now. */ - if (TREE_CODE (new_decl) == INDIRECT_REF) - return; - TREE_TYPE (new_decl) = remap_type (TREE_TYPE (decl), &ctx->cb); if ((!TREE_CONSTANT (DECL_SIZE (new_decl)) || private_debug) @@ -1993,6 +1976,7 @@ scan_sharing_clauses (tree clauses, omp_context *ctx, if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c)) break; /* FALLTHRU */ + case OMP_CLAUSE_FIRSTPRIVATE: case OMP_CLAUSE_LINEAR: decl = OMP_CLAUSE_DECL (c); @@ -2170,7 +2154,8 @@ scan_sharing_clauses (tree clauses, omp_context *ctx, else install_var_field (decl, true, 3, ctx, base_pointers_restrict); - if (is_gimple_omp_offloaded (ctx->stmt)) + if (is_gimple_omp_offloaded (ctx->stmt) + && !OMP_CLAUSE_MAP_IN_REDUCTION (c)) install_var_local (decl, ctx); } } @@ -2430,22 +2415,23 @@ scan_sharing_clauses (tree clauses, omp_context *ctx, } } - + gcc_checking_assert (!scan_array_reductions + || !is_gimple_omp_oacc (ctx->stmt)); if (scan_array_reductions) { - for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c)) - if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION - && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)) - { - scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c), ctx); - scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx); - } - else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE - && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c)) - scan_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx); - else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR - && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c)) - scan_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx); + for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c)) + if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION + && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)) + { + scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c), ctx); + scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx); + } + else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE + && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c)) + scan_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx); + else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR + && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c)) + scan_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx); } } @@ -3581,9 +3567,6 @@ check_omp_nesting_restrictions (gimple *stmt, omp_context *ctx) "region"); return false; } - if (is_gimple_omp_oacc (stmt) - && is_gimple_omp_oacc (ctx->stmt)) - return true; /* TODO */ error_at (gimple_location (stmt), "work-sharing region may not be closely nested inside " "of work-sharing, %<critical%>, %<ordered%>, " @@ -4058,7 +4041,6 @@ scan_omp_1_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p, insert_decl_map (&ctx->cb, var, var); } break; - default: *handled_ops_p = false; break; @@ -4896,7 +4878,7 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist, gimplify_assign (ptr, x, ilist); } } - else if (is_reference (var) && !is_oacc_parallel (ctx)) + else if (is_reference (var)) { /* For references that are being privatized for Fortran, allocate new backing storage for the new pointer @@ -5630,9 +5612,10 @@ lower_oacc_reductions (location_t loc, tree clauses, tree level, bool inner, if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION) { tree orig = OMP_CLAUSE_DECL (c); - tree var; + tree var = maybe_lookup_decl (orig, ctx); tree ref_to_res = NULL_TREE; - tree incoming, outgoing; + tree incoming, outgoing, v1, v2, v3; + bool is_private = false; enum tree_code rcode = OMP_CLAUSE_REDUCTION_CODE (c); if (rcode == MINUS_EXPR) @@ -5643,15 +5626,9 @@ lower_oacc_reductions (location_t loc, tree clauses, tree level, bool inner, rcode = BIT_IOR_EXPR; tree op = build_int_cst (unsigned_type_node, rcode); - var = OMP_CLAUSE_REDUCTION_PRIVATE_DECL (c); - if (!var) - var = maybe_lookup_decl (orig, ctx); if (!var) var = orig; - if (is_reference (var)) - var = build_simple_mem_ref (var); - incoming = outgoing = var; if (!inner) @@ -5684,79 +5661,80 @@ lower_oacc_reductions (location_t loc, tree clauses, tree level, bool inner, outer = probe; for (; cls; cls = OMP_CLAUSE_CHAIN (cls)) - { - if (OMP_CLAUSE_CODE (cls) == OMP_CLAUSE_REDUCTION - && orig == OMP_CLAUSE_DECL (cls)) - goto has_outer_reduction; - else if (OMP_CLAUSE_CODE (cls) == OMP_CLAUSE_PRIVATE - && orig == OMP_CLAUSE_DECL (cls) - && gimple_code (outer->stmt) != GIMPLE_OMP_TARGET) + if (OMP_CLAUSE_CODE (cls) == OMP_CLAUSE_REDUCTION + && orig == OMP_CLAUSE_DECL (cls)) + { + incoming = outgoing = lookup_decl (orig, probe); goto has_outer_reduction; - } + } + else if ((OMP_CLAUSE_CODE (cls) == OMP_CLAUSE_FIRSTPRIVATE + || OMP_CLAUSE_CODE (cls) == OMP_CLAUSE_PRIVATE) + && orig == OMP_CLAUSE_DECL (cls)) + { + is_private = true; + goto do_lookup; + } } do_lookup: /* This is the outermost construct with this reduction, see if there's a mapping for it. */ - if (gimple_code (outer->stmt) == GIMPLE_OMP_TARGET) + if (gimple_code (outer->stmt) == GIMPLE_OMP_TARGET + && maybe_lookup_field (orig, outer) && !is_private) { - bool is_private = false; - bool is_mapped = false; - - /* Check for a private or firstprivate mapping. */ - for (tree cls = gimple_omp_target_clauses (outer->stmt); - cls; cls = OMP_CLAUSE_CHAIN (cls)) - { - if ((OMP_CLAUSE_CODE (cls) == OMP_CLAUSE_PRIVATE - || OMP_CLAUSE_CODE (cls) == OMP_CLAUSE_FIRSTPRIVATE) - && OMP_CLAUSE_DECL (cls) == orig) - { - tree t = lookup_decl (orig, ctx->outer); - if (is_reference (t)) - incoming = outgoing = build_simple_mem_ref (t); - else - incoming = outgoing = t; - is_private = true; - break; - } - } - - /* Check for a data mapping. */ - if (!is_private && maybe_lookup_field (orig, outer)) - { - ref_to_res = build_receiver_ref (orig, false, outer); + ref_to_res = build_receiver_ref (orig, false, outer); + if (is_reference (orig)) + ref_to_res = build_simple_mem_ref (ref_to_res); - if (is_reference (orig)) - ref_to_res = build_simple_mem_ref (ref_to_res); - - incoming = omp_reduction_init_op (loc, rcode, - TREE_TYPE (var)); - outgoing = var; - is_mapped = true; - } + tree type = TREE_TYPE (var); + if (POINTER_TYPE_P (type)) + type = TREE_TYPE (type); - /* Update incoming and outgoing for reduction variables - local to the offloaded region. */ - if (!is_private && !is_mapped) - incoming = outgoing = orig; + outgoing = var; + incoming = omp_reduction_init_op (loc, rcode, type); } + else if (ctx->outer) + incoming = outgoing = lookup_decl (orig, ctx->outer); else incoming = outgoing = orig; - - has_outer_reduction: - /* We found a reduction variable used by another reduction. */ - if (gimple_code (outer->stmt) != GIMPLE_OMP_TARGET) - { - /* There may be no outer omp context if this reduction is - inside a routine. */ - incoming = outgoing = (ctx->outer == NULL) - ? orig : lookup_decl (orig, ctx->outer); - } + + has_outer_reduction:; } if (!ref_to_res) ref_to_res = integer_zero_node; + if (is_reference (orig)) + { + tree type = TREE_TYPE (var); + const char *id = IDENTIFIER_POINTER (DECL_NAME (var)); + + if (!inner) + { + tree x = create_tmp_var (TREE_TYPE (type), id); + gimplify_assign (var, build_fold_addr_expr (x), fork_seq); + } + + v1 = create_tmp_var (type, id); + v2 = create_tmp_var (type, id); + v3 = create_tmp_var (type, id); + + gimplify_assign (v1, var, fork_seq); + gimplify_assign (v2, var, fork_seq); + gimplify_assign (v3, var, fork_seq); + + var = build_simple_mem_ref (var); + v1 = build_simple_mem_ref (v1); + v2 = build_simple_mem_ref (v2); + v3 = build_simple_mem_ref (v3); + outgoing = build_simple_mem_ref (outgoing); + + if (TREE_CODE (incoming) != INTEGER_CST) + incoming = build_simple_mem_ref (incoming); + } + else + v1 = v2 = v3 = var; + /* Determine position in reduction buffer, which may be used by target. */ enum machine_mode mode = TYPE_MODE (TREE_TYPE (var)); @@ -5786,20 +5764,20 @@ lower_oacc_reductions (location_t loc, tree clauses, tree level, bool inner, = build_call_expr_internal_loc (loc, IFN_GOACC_REDUCTION, TREE_TYPE (var), 6, init_code, unshare_expr (ref_to_res), - var, level, op, off); + v1, level, op, off); tree fini_call = build_call_expr_internal_loc (loc, IFN_GOACC_REDUCTION, TREE_TYPE (var), 6, fini_code, unshare_expr (ref_to_res), - var, level, op, off); + v2, level, op, off); tree teardown_call = build_call_expr_internal_loc (loc, IFN_GOACC_REDUCTION, TREE_TYPE (var), 6, teardown_code, - ref_to_res, var, level, op, off); + ref_to_res, v3, level, op, off); - gimplify_assign (var, setup_call, &before_fork); - gimplify_assign (var, init_call, &after_fork); - gimplify_assign (var, fini_call, &before_join); + gimplify_assign (v1, setup_call, &before_fork); + gimplify_assign (v2, init_call, &after_fork); + gimplify_assign (v3, fini_call, &before_join); gimplify_assign (outgoing, teardown_call, &after_join); } @@ -12613,6 +12591,7 @@ expand_omp_atomic (struct omp_region *region) expand_omp_atomic_mutex (load_bb, store_bb, addr, loaded_val, stored_val); } + /* Encode an oacc launch argument. This matches the GOMP_LAUNCH_PACK macro on gomp-constants.h. We do not check for overflow. */ @@ -13871,7 +13850,6 @@ grid_expand_target_grid_body (struct omp_region *target) return; } - /* Expand the parallel region tree rooted at REGION. Expansion proceeds in depth-first order. Innermost regions are expanded first. This way, parallel regions that require a new function to @@ -16053,7 +16031,10 @@ lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx) if (!maybe_lookup_field (var, ctx)) continue; - if (offloaded) + /* Don't remap oacc parallel reduction variables, because the + intermediate result must be local to each gang. */ + if (offloaded && !(OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP + && OMP_CLAUSE_MAP_IN_REDUCTION (c))) { x = build_receiver_ref (var, true, ctx); tree new_var = lookup_decl (var, ctx); diff --git a/gcc/tree-core.h b/gcc/tree-core.h index aab89fa..b07ff30 100644 --- a/gcc/tree-core.h +++ b/gcc/tree-core.h @@ -260,9 +260,7 @@ enum omp_clause_code { placeholder used in OMP_CLAUSE_REDUCTION_{INIT,MERGE}. Operand 4: OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER: Another dummy VAR_DECL placeholder, used like the above for C/C++ array - reductions. - Operand 5: OMP_CLAUSE_REDUCTION_PRIVATE_DECL: A private VAR_DECL of - the original DECL associated with the reduction clause. */ + reductions. */ OMP_CLAUSE_REDUCTION, /* OpenMP clause: copyin (variable_list). */ diff --git a/gcc/tree.c b/gcc/tree.c index ab1f1e9..c897a68 100644 --- a/gcc/tree.c +++ b/gcc/tree.c @@ -266,7 +266,7 @@ unsigned const char omp_clause_num_ops[] = 1, /* OMP_CLAUSE_SHARED */ 1, /* OMP_CLAUSE_FIRSTPRIVATE */ 2, /* OMP_CLAUSE_LASTPRIVATE */ - 6, /* OMP_CLAUSE_REDUCTION */ + 5, /* OMP_CLAUSE_REDUCTION */ 1, /* OMP_CLAUSE_COPYIN */ 1, /* OMP_CLAUSE_COPYPRIVATE */ 3, /* OMP_CLAUSE_LINEAR */ @@ -11750,7 +11750,7 @@ walk_tree_1 (tree *tp, walk_tree_fn func, void *data, case OMP_CLAUSE_REDUCTION: { int i; - for (i = 0; i < 6; i++) + for (i = 0; i < 5; i++) WALK_SUBTREE (OMP_CLAUSE_OPERAND (*tp, i)); WALK_SUBTREE_TAIL (OMP_CLAUSE_CHAIN (*tp)); } diff --git a/gcc/tree.h b/gcc/tree.h index 6f99435..9450b41 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -1535,6 +1535,9 @@ extern void protected_set_expr_location (tree, location_t); treatment if OMP_CLAUSE_SIZE is zero. */ #define OMP_CLAUSE_MAP_MAYBE_ZERO_LENGTH_ARRAY_SECTION(NODE) \ TREE_PROTECTED (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_MAP)) +/* Nonzero if this map clause is for an ACC parallel reduction variable. */ +#define OMP_CLAUSE_MAP_IN_REDUCTION(NODE) \ + TREE_PRIVATE (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_MAP)) #define OMP_CLAUSE_PROC_BIND_KIND(NODE) \ (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_PROC_BIND)->omp_clause.subcode.proc_bind_kind) @@ -1563,8 +1566,6 @@ extern void protected_set_expr_location (tree, location_t); OMP_CLAUSE_OPERAND (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_REDUCTION), 3) #define OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER(NODE) \ OMP_CLAUSE_OPERAND (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_REDUCTION), 4) -#define OMP_CLAUSE_REDUCTION_PRIVATE_DECL(NODE) \ - OMP_CLAUSE_OPERAND (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_REDUCTION), 5) /* True if a REDUCTION clause may reference the original list item (omp_orig) in its OMP_CLAUSE_REDUCTION_{,GIMPLE_}INIT. */