diff options
Diffstat (limited to 'gcc/gimplify.c')
-rw-r--r-- | gcc/gimplify.c | 51 |
1 files changed, 43 insertions, 8 deletions
diff --git a/gcc/gimplify.c b/gcc/gimplify.c index 05ae2f1..fdf6b69 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -7227,15 +7227,28 @@ oacc_default_clause (struct gimplify_omp_ctx *ctx, tree decl, unsigned flags) { const char *rkind; bool on_device = false; + bool is_private = false; bool declared = is_oacc_declared (decl); tree type = TREE_TYPE (decl); if (lang_hooks.decls.omp_privatize_by_reference (decl)) type = TREE_TYPE (type); + /* For Fortran COMMON blocks, only used variables in those blocks are + transfered and remapped. The block itself will have a private clause to + avoid transfering the data twice. + The hook evaluates to false by default. For a variable in Fortran's COMMON + or EQUIVALENCE block, returns 'true' (as we have shared=false) - as only + the variables in such a COMMON/EQUIVALENCE block shall be privatized not + the whole block. For C++ and Fortran, it can also be true under certain + other conditions, if DECL_HAS_VALUE_EXPR. */ + if (RECORD_OR_UNION_TYPE_P (type)) + is_private = lang_hooks.decls.omp_disregard_value_expr (decl, false); + if ((ctx->region_type & (ORT_ACC_PARALLEL | ORT_ACC_KERNELS)) != 0 && is_global_var (decl) - && device_resident_p (decl)) + && device_resident_p (decl) + && !is_private) { on_device = true; flags |= GOVD_MAP_TO_ONLY; @@ -7246,7 +7259,9 @@ oacc_default_clause (struct gimplify_omp_ctx *ctx, tree decl, unsigned flags) case ORT_ACC_KERNELS: rkind = "kernels"; - if (AGGREGATE_TYPE_P (type)) + if (is_private) + flags |= GOVD_FIRSTPRIVATE; + else if (AGGREGATE_TYPE_P (type)) { /* Aggregates default to 'present_or_copy', or 'present'. */ if (ctx->default_kind != OMP_CLAUSE_DEFAULT_PRESENT) @@ -7263,7 +7278,9 @@ oacc_default_clause (struct gimplify_omp_ctx *ctx, tree decl, unsigned flags) case ORT_ACC_PARALLEL: rkind = "parallel"; - if (on_device || declared) + if (is_private) + flags |= GOVD_FIRSTPRIVATE; + else if (on_device || declared) flags |= GOVD_MAP; else if (AGGREGATE_TYPE_P (type)) { @@ -7327,10 +7344,18 @@ omp_notice_variable (struct gimplify_omp_ctx *ctx, tree decl, bool in_code) if (DECL_HAS_VALUE_EXPR_P (decl)) { - tree value = get_base_address (DECL_VALUE_EXPR (decl)); + if (ctx->region_type & ORT_ACC) + /* For OpenACC, defer expansion of value to avoid transfering + privatized common block data instead of im-/explicitly transfered + variables which are in common blocks. */ + ; + else + { + tree value = get_base_address (DECL_VALUE_EXPR (decl)); - if (value && DECL_P (value) && DECL_THREAD_LOCAL_P (value)) - return omp_notice_threadprivate_variable (ctx, decl, value); + if (value && DECL_P (value) && DECL_THREAD_LOCAL_P (value)) + return omp_notice_threadprivate_variable (ctx, decl, value); + } } if (gimplify_omp_ctxp->outer_context == NULL @@ -7361,7 +7386,13 @@ omp_notice_variable (struct gimplify_omp_ctx *ctx, tree decl, bool in_code) n = splay_tree_lookup (ctx->variables, (splay_tree_key)decl); if ((ctx->region_type & ORT_TARGET) != 0) { - ret = lang_hooks.decls.omp_disregard_value_expr (decl, true); + if (ctx->region_type & ORT_ACC) + /* For OpenACC, as remarked above, defer expansion. */ + shared = false; + else + shared = true; + + ret = lang_hooks.decls.omp_disregard_value_expr (decl, shared); if (n == NULL) { unsigned nflags = flags; @@ -7528,7 +7559,11 @@ omp_notice_variable (struct gimplify_omp_ctx *ctx, tree decl, bool in_code) } } - shared = ((flags | n->value) & GOVD_SHARED) != 0; + if (ctx->region_type & ORT_ACC) + /* For OpenACC, as remarked above, defer expansion. */ + shared = false; + else + shared = ((flags | n->value) & GOVD_SHARED) != 0; ret = lang_hooks.decls.omp_disregard_value_expr (decl, shared); /* If nothing changed, there's nothing left to do. */ |