https://gcc.gnu.org/g:cfcdfd136fb23355d24d59605cbe3b3979abcd2c
commit cfcdfd136fb23355d24d59605cbe3b3979abcd2c Author: Julian Brown <jul...@codesourcery.com> Date: Tue Sep 3 08:54:28 2019 -0700 Reference reduction localization gcc/ * gimplify.cc (privatize_reduction): New struct. (localize_reductions_r, localize_reductions): New functions. (gimplify_omp_for): Call localize_reductions. (gimplify_omp_workshare): Likewise. * omp-low.cc (lower_oacc_reductions): Handle localized reductions. Create fewer temp vars. * tree-core.h (omp_clause_code): Add OMP_CLAUSE_REDUCTION_PRIVATE_DECL documentation. * tree.cc (omp_clause_num_ops): Bump number of ops for OMP_CLAUSE_REDUCTION to 6. (walk_tree_1): Adjust accordingly. * tree.h (OMP_CLAUSE_REDUCTION_PRIVATE_DECL): Add macro. Diff: --- gcc/ChangeLog.omp | 26 ++++++++++++++ gcc/gimplify.cc | 102 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ gcc/omp-low.cc | 45 +++++++----------------- gcc/tree-core.h | 4 ++- gcc/tree.cc | 2 +- gcc/tree.h | 2 ++ 6 files changed, 146 insertions(+), 35 deletions(-) diff --git a/gcc/ChangeLog.omp b/gcc/ChangeLog.omp index 1a936376617..93231368ff4 100644 --- a/gcc/ChangeLog.omp +++ b/gcc/ChangeLog.omp @@ -1,3 +1,29 @@ +2019-09-06 Julian Brown <jul...@codesourcery.com> + + * gimplify.cc (gimplify_omp_for): Use for_stmt in call to + localize_reductions. + +2019-09-06 Julian Brown <jul...@codesourcery.com> + + * gimplify.cc (gimplify_omp_workshare): Use OMP_CLAUSES, OMP_BODY + instead of OMP_TARGET_CLAUSES, OMP_TARGET_BODY. + +2019-09-05 Cesar Philippidis <ce...@codesourcery.com> + Julian Brown <jul...@codesourcery.com> + + * gimplify.cc (privatize_reduction): New struct. + (localize_reductions_r, localize_reductions): New functions. + (gimplify_omp_for): Call localize_reductions. + (gimplify_omp_workshare): Likewise. + * omp-low.cc (lower_oacc_reductions): Handle localized reductions. + Create fewer temp vars. + * tree-core.h (omp_clause_code): Add OMP_CLAUSE_REDUCTION_PRIVATE_DECL + documentation. + * tree.cc (omp_clause_num_ops): Bump number of ops for + OMP_CLAUSE_REDUCTION to 6. + (walk_tree_1): Adjust accordingly. + * tree.h (OMP_CLAUSE_REDUCTION_PRIVATE_DECL): Add macro. + 2018-09-05 Cesar Philippidis <ce...@codesourcery.com> Chung-Lin Tang <clt...@codesourcery.com> diff --git a/gcc/gimplify.cc b/gcc/gimplify.cc index 086bcc259f5..a96698ab007 100644 --- a/gcc/gimplify.cc +++ b/gcc/gimplify.cc @@ -263,6 +263,11 @@ struct gimplify_omp_ctx int defaultmap[5]; }; +struct privatize_reduction +{ + tree ref_var, local_var; +}; + static struct gimplify_ctx *gimplify_ctxp; static struct gimplify_omp_ctx *gimplify_omp_ctxp; static bool in_omp_construct; @@ -15092,6 +15097,80 @@ find_standalone_omp_ordered (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 clauses, tree body) +{ + 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 (!lang_hooks.decls.omp_privatize_by_reference (var)) + { + OMP_CLAUSE_REDUCTION_PRIVATE_DECL (c) = NULL; + continue; + } + + type = TREE_TYPE (TREE_TYPE (var)); + new_var = create_tmp_var (type, IDENTIFIER_POINTER (DECL_NAME (var))); + + pr.ref_var = var; + pr.local_var = new_var; + + walk_tree (&body, 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 @@ -15331,6 +15410,24 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p) gcc_unreachable (); } + if (ort == ORT_ACC) + { + gimplify_omp_ctx *outer = gimplify_omp_ctxp; + + while (outer + && outer->region_type != ORT_ACC_PARALLEL + && outer->region_type != ORT_ACC_KERNELS) + outer = outer->outer_context; + + /* FIXME: Reductions only work in parallel regions at present. We avoid + doing the reduction localization transformation in kernels regions + here, because the code to remove reductions in kernels regions cannot + handle that. */ + if (outer && outer->region_type == ORT_ACC_PARALLEL) + localize_reductions (OMP_FOR_CLAUSES (for_stmt), + OMP_FOR_BODY (for_stmt)); + } + /* 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) @@ -16939,6 +17036,11 @@ gimplify_omp_workshare (tree *expr_p, gimple_seq *pre_p) || (ort & ORT_HOST_TEAMS) == ORT_HOST_TEAMS) { push_gimplify_context (); + + /* FIXME: Reductions are not supported in kernels regions yet. */ + if (/*ort == ORT_ACC_KERNELS ||*/ ort == ORT_ACC_PARALLEL) + localize_reductions (OMP_CLAUSES (expr), OMP_BODY (expr)); + 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.cc b/gcc/omp-low.cc index a6da27934de..9ac7abaaa5a 100644 --- a/gcc/omp-low.cc +++ b/gcc/omp-low.cc @@ -7619,9 +7619,9 @@ lower_oacc_reductions (location_t loc, tree clauses, tree level, bool inner, gcc_checking_assert (!is_oacc_kernels_decomposed_part (ctx)); tree orig = OMP_CLAUSE_DECL (c); - tree var = maybe_lookup_decl (orig, ctx); + tree var; tree ref_to_res = NULL_TREE; - tree incoming, outgoing, v1, v2, v3; + tree incoming, outgoing; bool is_private = false; bool is_fpp = false; @@ -7634,6 +7634,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; @@ -7742,37 +7745,13 @@ lower_oacc_reductions (location_t loc, tree clauses, tree level, bool inner, if (!ref_to_res) ref_to_res = integer_zero_node; - if (omp_privatize_by_reference (orig)) + if (omp_privatize_by_reference (outgoing)) { - 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_CONSTANT (incoming)) incoming = build_simple_mem_ref (incoming); } - else - /* Note that 'var' might be a mem ref. */ - v1 = v2 = v3 = var; /* Determine position in reduction buffer, which may be used by target. The parser has ensured that this is not a @@ -7806,21 +7785,21 @@ 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), - unshare_expr (v1), level, op, off); + unshare_expr (var), 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), - unshare_expr (v2), level, op, off); + unshare_expr (var), level, op, off); tree teardown_call = build_call_expr_internal_loc (loc, IFN_GOACC_REDUCTION, TREE_TYPE (var), 6, teardown_code, - ref_to_res, unshare_expr (v3), + ref_to_res, unshare_expr (var), level, op, off); - gimplify_assign (unshare_expr (v1), setup_call, &before_fork); - gimplify_assign (unshare_expr (v2), init_call, &after_fork); - gimplify_assign (unshare_expr (v3), fini_call, &before_join); + gimplify_assign (unshare_expr (var), setup_call, &before_fork); + gimplify_assign (unshare_expr (var), init_call, &after_fork); + gimplify_assign (unshare_expr (var), fini_call, &before_join); gimplify_assign (unshare_expr (outgoing), teardown_call, &after_join); } diff --git a/gcc/tree-core.h b/gcc/tree-core.h index 9fa74342919..3f337a37f21 100644 --- a/gcc/tree-core.h +++ b/gcc/tree-core.h @@ -268,7 +268,9 @@ 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. */ + reductions. + Operand 5: OMP_CLAUSE_REDUCTION_PRIVATE_DECL: A private VAR_DECL of + the original DECL associated with the reduction clause. */ OMP_CLAUSE_REDUCTION, /* OpenMP clause: task_reduction (operator:variable_list). */ diff --git a/gcc/tree.cc b/gcc/tree.cc index 83f3bf306af..d6a33e4fd49 100644 --- a/gcc/tree.cc +++ b/gcc/tree.cc @@ -244,7 +244,7 @@ unsigned const char omp_clause_num_ops[] = 1, /* OMP_CLAUSE_SHARED */ 1, /* OMP_CLAUSE_FIRSTPRIVATE */ 2, /* OMP_CLAUSE_LASTPRIVATE */ - 5, /* OMP_CLAUSE_REDUCTION */ + 6, /* OMP_CLAUSE_REDUCTION */ 5, /* OMP_CLAUSE_TASK_REDUCTION */ 5, /* OMP_CLAUSE_IN_REDUCTION */ 1, /* OMP_CLAUSE_COPYIN */ diff --git a/gcc/tree.h b/gcc/tree.h index ee2aae332a4..1ae97c1318c 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -1913,6 +1913,8 @@ class auto_suppress_location_wrappers #define OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER(NODE) \ OMP_CLAUSE_OPERAND (OMP_CLAUSE_RANGE_CHECK (NODE, OMP_CLAUSE_REDUCTION, \ OMP_CLAUSE_IN_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. */