From 512429a885e87bef51057a001681b7d8d106e807 Mon Sep 17 00:00:00 2001 From: Richard Biener Date: Thu, 1 Apr 2021 11:51:33 +0200 Subject: tree-optimization/99863 - clear vector CTOR TREE_SIDE_EFFECTS When we gimplify a vector CTOR the original CONSTRUCTOR tree remains but we fail to recompute flags such as TREE_SIDE_EFFECTS. This causes later GENERIC folding of them in vector lowering to give up since the match.pd machinery is careful about TREE_SIDE_EFFECTS. Fixing this makes vector lowering produce much less garbage and thus following the IL for PR99793 easier. 2021-04-01 Richard Biener PR tree-optimization/99863 * gimplify.c (gimplify_init_constructor): Recompute vector constructor flags. --- gcc/gimplify.c | 1 + 1 file changed, 1 insertion(+) (limited to 'gcc/gimplify.c') diff --git a/gcc/gimplify.c b/gcc/gimplify.c index 6da6698..1f417a5 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -5231,6 +5231,7 @@ gimplify_init_constructor (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, TREE_TYPE (ce->value))) TREE_STATIC (ctor) = 0; } + recompute_constructor_flags (ctor); if (!is_gimple_reg (TREE_OPERAND (*expr_p, 0))) TREE_OPERAND (*expr_p, 1) = get_formal_tmp_var (ctor, pre_p); } -- cgit v1.1 From 598359f627dec765eb74e31d9e96901a68bbfb97 Mon Sep 17 00:00:00 2001 From: Martin Liska Date: Mon, 12 Apr 2021 10:49:41 +0200 Subject: ASAN: do not unpoison in OpenMP context gcc/ChangeLog: PR sanitizer/99877 * gimplify.c (gimplify_expr): Right now, we unpoison all variables before a goto . We should not do it if we are in a omp context. gcc/testsuite/ChangeLog: PR sanitizer/99877 * g++.dg/asan/pr99877.C: New test. --- gcc/gimplify.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'gcc/gimplify.c') diff --git a/gcc/gimplify.c b/gcc/gimplify.c index 1f417a5..b65106b 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -14328,7 +14328,8 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, Doing so would prevent us from reporting a false positives. */ if (asan_poisoned_variables && asan_used_labels != NULL - && asan_used_labels->contains (label)) + && asan_used_labels->contains (label) + && !gimplify_omp_ctxp) asan_poison_variables (asan_poisoned_variables, false, pre_p); break; -- cgit v1.1 From 5747baa984d96241e4e2608da3c3e0160e32410b Mon Sep 17 00:00:00 2001 From: Eric Botcazou Date: Wed, 5 May 2021 12:07:24 +0200 Subject: Generate debug info for local dynamic record types In Ada you can embed VLAs in local record types and thus end up with dynamic offsets in record types, which are not well described in DWARF because 1) the temporaries generated for them by the gimplifier are naturally marked DECL_IGNORED_P and 2) when the types are referenced in nested subprograms, the DWARF back-end does not correctly handle the rewritten references. gcc/ * dwarf2out.c (loc_list_from_tree_1) : During early DWARF, do not expand the VALUE_EXPR of variables put in the non-local frame. * gimplify.c (gimplify_type_sizes) : If the type is not to be ignored for debug info, ensure its variable offsets are not. gcc/testsuite/ * gnat.dg/debug8.adb: Minor tweak. * gnat.dg/debug11.adb: Likewise. * gnat.dg/debug16.adb: Likewise. * gnat.dg/debug17.adb: New test. * gnat.dg/specs/debug1.ads: Minor tweak. --- gcc/gimplify.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) (limited to 'gcc/gimplify.c') diff --git a/gcc/gimplify.c b/gcc/gimplify.c index b65106b..e790f08 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -15141,11 +15141,15 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, void gimplify_type_sizes (tree type, gimple_seq *list_p) { - tree field, t; - if (type == NULL || type == error_mark_node) return; + const bool ignored_p + = TYPE_NAME (type) + && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL + && DECL_IGNORED_P (TYPE_NAME (type)); + tree t; + /* We first do the main variant, then copy into any other variants. */ type = TYPE_MAIN_VARIANT (type); @@ -15179,9 +15183,7 @@ gimplify_type_sizes (tree type, gimple_seq *list_p) /* Ensure VLA bounds aren't removed, for -O0 they should be variables with assigned stack slots, for -O1+ -g they should be tracked by VTA. */ - if (!(TYPE_NAME (type) - && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL - && DECL_IGNORED_P (TYPE_NAME (type))) + if (!ignored_p && TYPE_DOMAIN (type) && INTEGRAL_TYPE_P (TYPE_DOMAIN (type))) { @@ -15197,10 +15199,16 @@ gimplify_type_sizes (tree type, gimple_seq *list_p) case RECORD_TYPE: case UNION_TYPE: case QUAL_UNION_TYPE: - for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field)) + for (tree field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field)) if (TREE_CODE (field) == FIELD_DECL) { gimplify_one_sizepos (&DECL_FIELD_OFFSET (field), list_p); + /* Likewise, ensure variable offsets aren't removed. */ + if (!ignored_p + && (t = DECL_FIELD_OFFSET (field)) + && VAR_P (t) + && DECL_ARTIFICIAL (t)) + DECL_IGNORED_P (t) = 0; gimplify_one_sizepos (&DECL_SIZE (field), list_p); gimplify_one_sizepos (&DECL_SIZE_UNIT (field), list_p); gimplify_type_sizes (TREE_TYPE (field), list_p); -- cgit v1.1 From 780e5d4a2bac6eb7566c966a265961c99449cb55 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Wed, 19 May 2021 09:21:09 +0200 Subject: openmp: Handle lastprivate on combined target correctly [PR99928] This patch deals with 2 issues: 1) the gimplifier couldn't differentiate between #pragma omp parallel master #pragma omp taskloop simd and #pragma omp parallel master taskloop simd when there is a significant difference for clause handling between the two; as master construct doesn't have any clauses, we don't currently represent it during gimplification by an gimplification omp context at all, so this patch makes sure we don't set OMP_PARALLEL_COMBINED on parallel master when not combined further. If we ever add a separate master context during gimplification, we'd use ORT_COMBINED_MASTER vs. ORT_MASTER (or MASKED probably). 2) lastprivate when combined with target should be map(tofrom:) on the target, this change handles it only when not combined with firstprivate though, that will need further work (similarly to linear or reduction). 2021-05-19 Jakub Jelinek PR middle-end/99928 gcc/ * tree.h (OMP_MASTER_COMBINED): Define. * gimplify.c (gimplify_scan_omp_clauses): Rewrite lastprivate handling for outer combined/composite constructs to a loop. Handle lastprivate on combined target. (gimplify_expr): Formatting fix. gcc/c/ * c-parser.c (c_parser_omp_master): Set OMP_MASTER_COMBINED on master when combined with taskloop. (c_parser_omp_parallel): Don't set OMP_PARALLEL_COMBINED on parallel master when not combined with taskloop. gcc/cp/ * parser.c (cp_parser_omp_master): Set OMP_MASTER_COMBINED on master when combined with taskloop. (cp_parser_omp_parallel): Don't set OMP_PARALLEL_COMBINED on parallel master when not combined with taskloop. gcc/testsuite/ * c-c++-common/gomp/pr99928-2.c: Remove all xfails. * c-c++-common/gomp/pr99928-12.c: New test. --- gcc/gimplify.c | 103 +++++++++++++++++++++------------------------------------ 1 file changed, 38 insertions(+), 65 deletions(-) (limited to 'gcc/gimplify.c') diff --git a/gcc/gimplify.c b/gcc/gimplify.c index e790f08..2730f22 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -8642,75 +8642,48 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p, } if (OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c)) flags |= GOVD_LASTPRIVATE_CONDITIONAL; - if (outer_ctx - && (outer_ctx->region_type == ORT_COMBINED_PARALLEL - || ((outer_ctx->region_type & ORT_COMBINED_TEAMS) - == ORT_COMBINED_TEAMS)) - && splay_tree_lookup (outer_ctx->variables, - (splay_tree_key) decl) == NULL) - { - omp_add_variable (outer_ctx, decl, GOVD_SHARED | GOVD_SEEN); - if (outer_ctx->outer_context) - omp_notice_variable (outer_ctx->outer_context, decl, true); - } - else if (outer_ctx - && (outer_ctx->region_type & ORT_TASK) != 0 - && outer_ctx->combined_loop - && splay_tree_lookup (outer_ctx->variables, - (splay_tree_key) decl) == NULL) - { - omp_add_variable (outer_ctx, decl, GOVD_LASTPRIVATE | GOVD_SEEN); - if (outer_ctx->outer_context) - omp_notice_variable (outer_ctx->outer_context, decl, true); - } - else if (outer_ctx - && (outer_ctx->region_type == ORT_WORKSHARE - || outer_ctx->region_type == ORT_ACC) - && outer_ctx->combined_loop - && splay_tree_lookup (outer_ctx->variables, - (splay_tree_key) decl) == NULL - && !omp_check_private (outer_ctx, decl, false)) - { - omp_add_variable (outer_ctx, decl, GOVD_LASTPRIVATE | GOVD_SEEN); - if (outer_ctx->outer_context - && (outer_ctx->outer_context->region_type - == ORT_COMBINED_PARALLEL) - && splay_tree_lookup (outer_ctx->outer_context->variables, + struct gimplify_omp_ctx *octx; + for (octx = outer_ctx; octx; octx = octx->outer_context) + { + if ((octx->region_type == ORT_COMBINED_PARALLEL + || ((octx->region_type & ORT_COMBINED_TEAMS) + == ORT_COMBINED_TEAMS)) + && splay_tree_lookup (octx->variables, (splay_tree_key) decl) == NULL) { - struct gimplify_omp_ctx *octx = outer_ctx->outer_context; omp_add_variable (octx, decl, GOVD_SHARED | GOVD_SEEN); - if (octx->outer_context) - { - octx = octx->outer_context; - if (octx->region_type == ORT_WORKSHARE - && octx->combined_loop - && splay_tree_lookup (octx->variables, - (splay_tree_key) decl) == NULL - && !omp_check_private (octx, decl, false)) - { - omp_add_variable (octx, decl, - GOVD_LASTPRIVATE | GOVD_SEEN); - octx = octx->outer_context; - if (octx - && ((octx->region_type & ORT_COMBINED_TEAMS) - == ORT_COMBINED_TEAMS) - && (splay_tree_lookup (octx->variables, - (splay_tree_key) decl) - == NULL)) - { - omp_add_variable (octx, decl, - GOVD_SHARED | GOVD_SEEN); - octx = octx->outer_context; - } - } - if (octx) - omp_notice_variable (octx, decl, true); - } + continue; } - else if (outer_ctx->outer_context) - omp_notice_variable (outer_ctx->outer_context, decl, true); + if ((octx->region_type & ORT_TASK) != 0 + && octx->combined_loop + && splay_tree_lookup (octx->variables, + (splay_tree_key) decl) == NULL) + { + omp_add_variable (octx, decl, GOVD_LASTPRIVATE | GOVD_SEEN); + continue; + } + if ((octx->region_type == ORT_WORKSHARE + || octx->region_type == ORT_ACC) + && octx->combined_loop + && splay_tree_lookup (octx->variables, + (splay_tree_key) decl) == NULL + && !omp_check_private (octx, decl, false)) + { + omp_add_variable (octx, decl, GOVD_LASTPRIVATE | GOVD_SEEN); + continue; + } + if (octx->region_type == ORT_COMBINED_TARGET + && splay_tree_lookup (octx->variables, + (splay_tree_key) decl) == NULL) + { + omp_add_variable (octx, decl, GOVD_MAP | GOVD_SEEN); + octx = octx->outer_context; + break; + } + break; } + if (octx && octx != outer_ctx) + omp_notice_variable (octx, decl, true); goto do_add; case OMP_CLAUSE_REDUCTION: if (OMP_CLAUSE_REDUCTION_TASK (c)) @@ -14643,7 +14616,7 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, g = gimple_build_omp_section (body); break; case OMP_MASTER: - g = gimple_build_omp_master (body); + g = gimple_build_omp_master (body); break; case OMP_ORDERED: g = gimplify_omp_ordered (*expr_p, body); -- cgit v1.1 From 94fa4c67b95c12482b6087d8eef2d72f7b7ea254 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Thu, 20 May 2021 09:17:40 +0200 Subject: openmp: Handle explicit linear clause properly in combined constructs with target [PR99928] linear clause should have the effect of firstprivate+lastprivate (or for IVs not declared in the construct lastprivate) on outer constructs and eventually map(tofrom:) on target when combined with it. 2021-05-20 Jakub Jelinek PR middle-end/99928 * gimplify.c (gimplify_scan_omp_clauses) : For explicit linear clause when combined with target, make it map(tofrom:) instead of no clause or firstprivate. * c-c++-common/gomp/pr99928-4.c: Remove all xfails. * c-c++-common/gomp/pr99928-5.c: Likewise. --- gcc/gimplify.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'gcc/gimplify.c') diff --git a/gcc/gimplify.c b/gcc/gimplify.c index 2730f22..719a4e1 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -8884,9 +8884,8 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p, else if (octx && octx->region_type == ORT_COMBINED_TARGET) { - flags &= ~GOVD_LASTPRIVATE; - if (flags == GOVD_SEEN) - break; + if (flags & GOVD_LASTPRIVATE) + flags = GOVD_SEEN | GOVD_MAP; } else break; -- cgit v1.1 From 0c6e792dd5c96a48c873b73c2d5b1ee4fc4b6b8e Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Fri, 21 May 2021 21:13:06 +0200 Subject: openmp: Fix up handling of implicit lastprivate on outer constructs for implicit linear and lastprivate IVs [PR99928] This patch fixes the handling of lastprivate propagation to outer combined/composite leaf constructs from implicit linear or lastprivate clauses on simd IVs and adds missing testsuite coverage for explicit and implicit lastprivate on simd IVs. 2021-05-21 Jakub Jelinek PR middle-end/99928 * gimplify.c (omp_lastprivate_for_combined_outer_constructs): New function. (gimplify_scan_omp_clauses) : Use it. (gimplify_omp_for): Likewise. * c-c++-common/gomp/pr99928-6.c: Remove all xfails. * c-c++-common/gomp/pr99928-13.c: New test. * c-c++-common/gomp/pr99928-14.c: New test. --- gcc/gimplify.c | 270 ++++++++++++++++----------------------------------------- 1 file changed, 73 insertions(+), 197 deletions(-) (limited to 'gcc/gimplify.c') diff --git a/gcc/gimplify.c b/gcc/gimplify.c index 719a4e1..28bf1b0 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -8533,6 +8533,73 @@ omp_target_reorder_clauses (tree *list_p) } } +/* DECL is supposed to have lastprivate semantics in the outer contexts + of combined/composite constructs, starting with OCTX. + Add needed lastprivate, shared or map clause if no data sharing or + mapping clause are present. IMPLICIT_P is true if it is an implicit + clause (IV on simd), in which case the lastprivate will not be + copied to some constructs. */ + +static void +omp_lastprivate_for_combined_outer_constructs (struct gimplify_omp_ctx *octx, + tree decl, bool implicit_p) +{ + struct gimplify_omp_ctx *orig_octx = octx; + for (; octx; octx = octx->outer_context) + { + if ((octx->region_type == ORT_COMBINED_PARALLEL + || (octx->region_type & ORT_COMBINED_TEAMS) == ORT_COMBINED_TEAMS) + && splay_tree_lookup (octx->variables, + (splay_tree_key) decl) == NULL) + { + omp_add_variable (octx, decl, GOVD_SHARED | GOVD_SEEN); + continue; + } + if ((octx->region_type & ORT_TASK) != 0 + && octx->combined_loop + && splay_tree_lookup (octx->variables, + (splay_tree_key) decl) == NULL) + { + omp_add_variable (octx, decl, GOVD_LASTPRIVATE | GOVD_SEEN); + continue; + } + if (implicit_p + && octx->region_type == ORT_WORKSHARE + && octx->combined_loop + && splay_tree_lookup (octx->variables, + (splay_tree_key) decl) == NULL + && octx->outer_context + && octx->outer_context->region_type == ORT_COMBINED_PARALLEL + && splay_tree_lookup (octx->outer_context->variables, + (splay_tree_key) decl) == NULL) + { + octx = octx->outer_context; + omp_add_variable (octx, decl, GOVD_LASTPRIVATE | GOVD_SEEN); + continue; + } + if ((octx->region_type == ORT_WORKSHARE || octx->region_type == ORT_ACC) + && octx->combined_loop + && splay_tree_lookup (octx->variables, + (splay_tree_key) decl) == NULL + && !omp_check_private (octx, decl, false)) + { + omp_add_variable (octx, decl, GOVD_LASTPRIVATE | GOVD_SEEN); + continue; + } + if (octx->region_type == ORT_COMBINED_TARGET + && splay_tree_lookup (octx->variables, + (splay_tree_key) decl) == NULL) + { + omp_add_variable (octx, decl, GOVD_MAP | GOVD_SEEN); + octx = octx->outer_context; + break; + } + break; + } + if (octx && (implicit_p || octx != orig_octx)) + omp_notice_variable (octx, decl, true); +} + /* Scan the OMP clauses in *LIST_P, installing mappings into a new and previous omp contexts. */ @@ -8642,48 +8709,8 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p, } if (OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c)) flags |= GOVD_LASTPRIVATE_CONDITIONAL; - struct gimplify_omp_ctx *octx; - for (octx = outer_ctx; octx; octx = octx->outer_context) - { - if ((octx->region_type == ORT_COMBINED_PARALLEL - || ((octx->region_type & ORT_COMBINED_TEAMS) - == ORT_COMBINED_TEAMS)) - && splay_tree_lookup (octx->variables, - (splay_tree_key) decl) == NULL) - { - omp_add_variable (octx, decl, GOVD_SHARED | GOVD_SEEN); - continue; - } - if ((octx->region_type & ORT_TASK) != 0 - && octx->combined_loop - && splay_tree_lookup (octx->variables, - (splay_tree_key) decl) == NULL) - { - omp_add_variable (octx, decl, GOVD_LASTPRIVATE | GOVD_SEEN); - continue; - } - if ((octx->region_type == ORT_WORKSHARE - || octx->region_type == ORT_ACC) - && octx->combined_loop - && splay_tree_lookup (octx->variables, - (splay_tree_key) decl) == NULL - && !omp_check_private (octx, decl, false)) - { - omp_add_variable (octx, decl, GOVD_LASTPRIVATE | GOVD_SEEN); - continue; - } - if (octx->region_type == ORT_COMBINED_TARGET - && splay_tree_lookup (octx->variables, - (splay_tree_key) decl) == NULL) - { - omp_add_variable (octx, decl, GOVD_MAP | GOVD_SEEN); - octx = octx->outer_context; - break; - } - break; - } - if (octx && octx != outer_ctx) - omp_notice_variable (octx, decl, true); + omp_lastprivate_for_combined_outer_constructs (outer_ctx, decl, + false); goto do_add; case OMP_CLAUSE_REDUCTION: if (OMP_CLAUSE_REDUCTION_TASK (c)) @@ -11853,80 +11880,8 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p) OMP_FOR_CLAUSES (for_stmt) = c; omp_add_variable (gimplify_omp_ctxp, decl, flags); if (outer && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c)) - { - if (outer->region_type == ORT_WORKSHARE - && outer->combined_loop) - { - if (outer->outer_context - && (outer->outer_context->region_type - == ORT_COMBINED_PARALLEL)) - outer = outer->outer_context; - else if (omp_check_private (outer, decl, false)) - outer = NULL; - } - else if (((outer->region_type & ORT_TASKLOOP) - == ORT_TASKLOOP) - && outer->combined_loop - && !omp_check_private (gimplify_omp_ctxp, - decl, false)) - ; - else if (outer->region_type != ORT_COMBINED_PARALLEL) - { - omp_notice_variable (outer, decl, true); - outer = NULL; - } - if (outer) - { - n = splay_tree_lookup (outer->variables, - (splay_tree_key)decl); - if (n == NULL || (n->value & GOVD_DATA_SHARE_CLASS) == 0) - { - omp_add_variable (outer, decl, - GOVD_LASTPRIVATE | GOVD_SEEN); - if (outer->region_type == ORT_COMBINED_PARALLEL - && outer->outer_context - && (outer->outer_context->region_type - == ORT_WORKSHARE) - && outer->outer_context->combined_loop) - { - outer = outer->outer_context; - n = splay_tree_lookup (outer->variables, - (splay_tree_key)decl); - if (omp_check_private (outer, decl, false)) - outer = NULL; - else if (n == NULL - || ((n->value & GOVD_DATA_SHARE_CLASS) - == 0)) - omp_add_variable (outer, decl, - GOVD_LASTPRIVATE - | GOVD_SEEN); - else - outer = NULL; - } - if (outer && outer->outer_context - && ((outer->outer_context->region_type - & ORT_COMBINED_TEAMS) == ORT_COMBINED_TEAMS - || (((outer->region_type & ORT_TASKLOOP) - == ORT_TASKLOOP) - && (outer->outer_context->region_type - == ORT_COMBINED_PARALLEL)))) - { - outer = outer->outer_context; - n = splay_tree_lookup (outer->variables, - (splay_tree_key)decl); - if (n == NULL - || (n->value & GOVD_DATA_SHARE_CLASS) == 0) - omp_add_variable (outer, decl, - GOVD_SHARED | GOVD_SEEN); - else - outer = NULL; - } - if (outer && outer->outer_context) - omp_notice_variable (outer->outer_context, decl, - true); - } - } - } + omp_lastprivate_for_combined_outer_constructs (outer, decl, + true); } else { @@ -11945,87 +11900,8 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p) struct gimplify_omp_ctx *outer = gimplify_omp_ctxp->outer_context; if (outer && lastprivate) - { - if (outer->region_type == ORT_WORKSHARE - && outer->combined_loop) - { - n = splay_tree_lookup (outer->variables, - (splay_tree_key)decl); - if (n != NULL && (n->value & GOVD_LOCAL) != 0) - { - lastprivate = false; - outer = NULL; - } - else if (outer->outer_context - && (outer->outer_context->region_type - == ORT_COMBINED_PARALLEL)) - outer = outer->outer_context; - else if (omp_check_private (outer, decl, false)) - outer = NULL; - } - else if (((outer->region_type & ORT_TASKLOOP) - == ORT_TASKLOOP) - && outer->combined_loop - && !omp_check_private (gimplify_omp_ctxp, - decl, false)) - ; - else if (outer->region_type != ORT_COMBINED_PARALLEL) - { - omp_notice_variable (outer, decl, true); - outer = NULL; - } - if (outer) - { - n = splay_tree_lookup (outer->variables, - (splay_tree_key)decl); - if (n == NULL || (n->value & GOVD_DATA_SHARE_CLASS) == 0) - { - omp_add_variable (outer, decl, - GOVD_LASTPRIVATE | GOVD_SEEN); - if (outer->region_type == ORT_COMBINED_PARALLEL - && outer->outer_context - && (outer->outer_context->region_type - == ORT_WORKSHARE) - && outer->outer_context->combined_loop) - { - outer = outer->outer_context; - n = splay_tree_lookup (outer->variables, - (splay_tree_key)decl); - if (omp_check_private (outer, decl, false)) - outer = NULL; - else if (n == NULL - || ((n->value & GOVD_DATA_SHARE_CLASS) - == 0)) - omp_add_variable (outer, decl, - GOVD_LASTPRIVATE - | GOVD_SEEN); - else - outer = NULL; - } - if (outer && outer->outer_context - && ((outer->outer_context->region_type - & ORT_COMBINED_TEAMS) == ORT_COMBINED_TEAMS - || (((outer->region_type & ORT_TASKLOOP) - == ORT_TASKLOOP) - && (outer->outer_context->region_type - == ORT_COMBINED_PARALLEL)))) - { - outer = outer->outer_context; - n = splay_tree_lookup (outer->variables, - (splay_tree_key)decl); - if (n == NULL - || (n->value & GOVD_DATA_SHARE_CLASS) == 0) - omp_add_variable (outer, decl, - GOVD_SHARED | GOVD_SEEN); - else - outer = NULL; - } - if (outer && outer->outer_context) - omp_notice_variable (outer->outer_context, decl, - true); - } - } - } + omp_lastprivate_for_combined_outer_constructs (outer, decl, + true); c = build_omp_clause (input_location, lastprivate ? OMP_CLAUSE_LASTPRIVATE -- cgit v1.1 From b5c1c7a96bc8d7062d2c35675f48131667498182 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Fri, 21 May 2021 21:16:21 +0200 Subject: openmp: Fix up firstprivate+lastprivate clause handling [PR99928] The C/C++ clause splitting happens very early during construct parsing, but only the FEs later on handle possible instantiations, non-static member handling and array section lowering. In the OpenMP 5.0/5.1 rules, whether firstprivate is added to combined target depends on whether it isn't also mentioned in lastprivate or map clauses, but unfortunately I think such checks are much better done only when the FEs perform all the above mentioned changes. So, this patch arranges for the firstprivate clause to be copied or moved to combined target construct (as before), but sets flags on that clause, which tell the FE *finish_omp_clauses and the gimplifier it has been added only conditionally and let the FEs and gimplifier DTRT for these. 2021-05-21 Jakub Jelinek PR middle-end/99928 gcc/ * tree.h (OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT_TARGET): Define. * gimplify.c (enum gimplify_omp_var_data): Fix up GOVD_MAP_HAS_ATTACHMENTS value, add GOVD_FIRSTPRIVATE_IMPLICIT. (omp_lastprivate_for_combined_outer_constructs): If combined target has GOVD_FIRSTPRIVATE_IMPLICIT set for the decl, change it to GOVD_MAP | GOVD_SEEN. (gimplify_scan_omp_clauses): Set GOVD_FIRSTPRIVATE_IMPLICIT for firstprivate clauses with OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT. (gimplify_adjust_omp_clauses): For firstprivate clauses with OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT either clear that bit and OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT_TARGET too, or remove it and let it be replaced by implicit map clause. gcc/c-family/ * c-omp.c (c_omp_split_clauses): Set OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT on firstprivate clause copy going to target construct, and for target simd set also OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT_TARGET bit. gcc/c/ * c-typeck.c (c_finish_omp_clauses): Move firstprivate clauses with OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT to the end of the chain. Don't error if a decl is mentioned both in map clause and in such firstprivate clause unless OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT_TARGET is also set. gcc/cp/ * semantics.c (finish_omp_clauses): Move firstprivate clauses with OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT to the end of the chain. Don't error if a decl is mentioned both in map clause and in such firstprivate clause unless OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT_TARGET is also set. gcc/testsuite/ * c-c++-common/gomp/pr99928-3.c: Remove all xfails. * c-c++-common/gomp/pr99928-15.c: New test. --- gcc/gimplify.c | 45 ++++++++++++++++++++++++++++++++++++++------- 1 file changed, 38 insertions(+), 7 deletions(-) (limited to 'gcc/gimplify.c') diff --git a/gcc/gimplify.c b/gcc/gimplify.c index 28bf1b0..b62ea0e 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -126,7 +126,10 @@ enum gimplify_omp_var_data /* Flag for GOVD_MAP: (struct) vars that have pointer attachments for fields. */ - GOVD_MAP_HAS_ATTACHMENTS = 8388608, + GOVD_MAP_HAS_ATTACHMENTS = 0x4000000, + + /* Flag for GOVD_FIRSTPRIVATE: OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT. */ + GOVD_FIRSTPRIVATE_IMPLICIT = 0x8000000, GOVD_DATA_SHARE_CLASS = (GOVD_SHARED | GOVD_PRIVATE | GOVD_FIRSTPRIVATE | GOVD_LASTPRIVATE | GOVD_REDUCTION | GOVD_LINEAR @@ -8586,13 +8589,24 @@ omp_lastprivate_for_combined_outer_constructs (struct gimplify_omp_ctx *octx, omp_add_variable (octx, decl, GOVD_LASTPRIVATE | GOVD_SEEN); continue; } - if (octx->region_type == ORT_COMBINED_TARGET - && splay_tree_lookup (octx->variables, - (splay_tree_key) decl) == NULL) + if (octx->region_type == ORT_COMBINED_TARGET) { - omp_add_variable (octx, decl, GOVD_MAP | GOVD_SEEN); - octx = octx->outer_context; - break; + splay_tree_node n = splay_tree_lookup (octx->variables, + (splay_tree_key) decl); + if (n == NULL) + { + omp_add_variable (octx, decl, GOVD_MAP | GOVD_SEEN); + octx = octx->outer_context; + } + else if (!implicit_p + && (n->value & GOVD_FIRSTPRIVATE_IMPLICIT)) + { + n->value &= ~(GOVD_FIRSTPRIVATE + | GOVD_FIRSTPRIVATE_IMPLICIT + | GOVD_EXPLICIT); + omp_add_variable (octx, decl, GOVD_MAP | GOVD_SEEN); + octx = octx->outer_context; + } } break; } @@ -8673,6 +8687,11 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p, case OMP_CLAUSE_FIRSTPRIVATE: flags = GOVD_FIRSTPRIVATE | GOVD_EXPLICIT; check_non_private = "firstprivate"; + if (OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c)) + { + gcc_assert (code == OMP_TARGET); + flags |= GOVD_FIRSTPRIVATE_IMPLICIT; + } goto do_add; case OMP_CLAUSE_LASTPRIVATE: if (OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c)) @@ -10532,6 +10551,18 @@ gimplify_adjust_omp_clauses (gimple_seq *pre_p, gimple_seq body, tree *list_p, remove = true; break; } + if (OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c)) + { + decl = OMP_CLAUSE_DECL (c); + n = splay_tree_lookup (ctx->variables, (splay_tree_key) decl); + if ((n->value & GOVD_MAP) != 0) + { + remove = true; + break; + } + OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT_TARGET (c) = 0; + OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c) = 0; + } /* FALLTHRU */ case OMP_CLAUSE_PRIVATE: case OMP_CLAUSE_SHARED: -- cgit v1.1 From fd97aeb494cdcffe0d21e7f15ab4593662e065bd Mon Sep 17 00:00:00 2001 From: Eric Botcazou Date: Tue, 25 May 2021 18:30:29 +0200 Subject: Remove stalled TREE_READONLY flag on automatic variable gcc/ * gimplify.c (gimplify_decl_expr): Clear TREE_READONLY on the DECL when really creating an initialization statement for it. --- gcc/gimplify.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'gcc/gimplify.c') diff --git a/gcc/gimplify.c b/gcc/gimplify.c index b62ea0e..ed825a9 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -1828,6 +1828,9 @@ gimplify_decl_expr (tree *stmt_p, gimple_seq *seq_p) init = build2 (INIT_EXPR, void_type_node, decl, init); gimplify_and_add (init, seq_p); ggc_free (init); + /* Clear TREE_READONLY if we really have an initialization. */ + if (!DECL_INITIAL (decl)) + TREE_READONLY (decl) = 0; } else /* We must still examine initializers for static variables -- cgit v1.1 From a0d371a25148d113f7c3657f36fbf7dcb5e1f63d Mon Sep 17 00:00:00 2001 From: Eric Botcazou Date: Wed, 26 May 2021 09:51:36 +0200 Subject: Fix C++ libgomp regressions This is only a stopgap fix. gcc/ * gimplify.c (gimplify_decl_expr): Do not clear TREE_READONLY on a DECL which is a reference for OMP. --- gcc/gimplify.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'gcc/gimplify.c') diff --git a/gcc/gimplify.c b/gcc/gimplify.c index ed825a9..54bf59a 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -1829,7 +1829,7 @@ gimplify_decl_expr (tree *stmt_p, gimple_seq *seq_p) gimplify_and_add (init, seq_p); ggc_free (init); /* Clear TREE_READONLY if we really have an initialization. */ - if (!DECL_INITIAL (decl)) + if (!DECL_INITIAL (decl) && !omp_is_reference (decl)) TREE_READONLY (decl) = 0; } else -- cgit v1.1 From 9a5de4d5af1c10a8c097de30ee4c71457216e975 Mon Sep 17 00:00:00 2001 From: Tobias Burnus Date: Fri, 28 May 2021 10:01:19 +0200 Subject: OpenMP: Add iterator support to Fortran's depend; add affinity clause gcc/c-family/ChangeLog: * c-pragma.h (enum pragma_omp_clause): Add PRAGMA_OMP_CLAUSE_AFFINITY. gcc/c/ChangeLog: * c-parser.c (c_parser_omp_clause_affinity): New. (c_parser_omp_clause_name, c_parser_omp_variable_list, c_parser_omp_all_clauses, OMP_TASK_CLAUSE_MASK): Handle affinity clause. * c-typeck.c (handle_omp_array_sections_1, handle_omp_array_sections, c_finish_omp_clauses): Likewise. gcc/cp/ChangeLog: * parser.c (cp_parser_omp_clause_affinity): New. (cp_parser_omp_clause_name, cp_parser_omp_var_list_no_open, cp_parser_omp_all_clauses, OMP_TASK_CLAUSE_MASK): Handle affinity clause. * semantics.c (handle_omp_array_sections_1, handle_omp_array_sections, finish_omp_clauses): Likewise. gcc/fortran/ChangeLog: * dump-parse-tree.c (show_iterator): New. (show_omp_namelist): Handle iterators. (show_omp_clauses): Handle affinity. * gfortran.h (gfc_free_omp_namelist): New union with 'udr' and new 'ns'. * match.c (gfc_free_omp_namelist): Add are to choose union element. * openmp.c (gfc_free_omp_clauses, gfc_match_omp_detach, gfc_match_omp_clause_reduction, gfc_match_omp_flush): Update call to gfc_free_omp_namelist. (gfc_match_omp_variable_list): Likewise; permit preceeding whitespace. (enum omp_mask1): Add OMP_CLAUSE_AFFINITY. (gfc_match_iterator): New. (gfc_match_omp_clauses): Use it; update call to gfc_free_omp_namelist. (OMP_TASK_CLAUSES): Add OMP_CLAUSE_AFFINITY. (gfc_match_omp_taskwait): Match depend clause. (resolve_omp_clauses): Handle affinity; update for udr/union change. (gfc_resolve_omp_directive): Resolve clauses of taskwait. * st.c (gfc_free_statement): Update gfc_free_omp_namelist call. * trans-openmp.c (gfc_trans_omp_array_reduction_or_udr): Likewise (handle_iterator): New. (gfc_trans_omp_clauses): Handle iterators for depend/affinity clause. (gfc_trans_omp_taskwait): Handle depend clause. (gfc_trans_omp_directive): Update call. gcc/ChangeLog: * gimplify.c (gimplify_omp_affinity): New. (gimplify_scan_omp_clauses): Call it; remove affinity clause afterwards. * tree-core.h (enum omp_clause_code): Add OMP_CLAUSE_AFFINITY. * tree-pretty-print.c (dump_omp_clause): Handle OMP_CLAUSE_AFFINITY. * tree.c (omp_clause_num_ops, omp_clause_code_name): Add clause. (walk_tree_1): Handle OMP_CLAUSE_AFFINITY. libgomp/ChangeLog: * testsuite/libgomp.fortran/depend-iterator-2.f90: New test. gcc/testsuite/ChangeLog: * c-c++-common/gomp/affinity-1.c: New test. * c-c++-common/gomp/affinity-2.c: New test. * c-c++-common/gomp/affinity-3.c: New test. * c-c++-common/gomp/affinity-4.c: New test. * c-c++-common/gomp/affinity-5.c: New test. * c-c++-common/gomp/affinity-6.c: New test. * c-c++-common/gomp/affinity-7.c: New test. * gfortran.dg/gomp/affinity-clause-1.f90: New test. * gfortran.dg/gomp/affinity-clause-2.f90: New test. * gfortran.dg/gomp/affinity-clause-3.f90: New test. * gfortran.dg/gomp/affinity-clause-4.f90: New test. * gfortran.dg/gomp/affinity-clause-5.f90: New test. * gfortran.dg/gomp/affinity-clause-6.f90: New test. * gfortran.dg/gomp/depend-iterator-1.f90: New test. * gfortran.dg/gomp/depend-iterator-2.f90: New test. * gfortran.dg/gomp/depend-iterator-3.f90: New test. * gfortran.dg/gomp/taskwait.f90: New test. --- gcc/gimplify.c | 129 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 129 insertions(+) (limited to 'gcc/gimplify.c') diff --git a/gcc/gimplify.c b/gcc/gimplify.c index 54bf59a..d60fc95 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -7841,6 +7841,131 @@ find_decl_expr (tree *tp, int *walk_subtrees, void *data) return NULL_TREE; } + +/* Gimplify the affinity clause but effectively ignore it. + Generate: + var = begin; + if ((step > 1) ? var <= end : var > end) + locatator_var_expr; */ + +static void +gimplify_omp_affinity (tree *list_p, gimple_seq *pre_p) +{ + tree last_iter = NULL_TREE; + tree last_bind = NULL_TREE; + tree label = NULL_TREE; + tree *last_body = NULL; + for (tree c = *list_p; c; c = OMP_CLAUSE_CHAIN (c)) + if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_AFFINITY) + { + tree t = OMP_CLAUSE_DECL (c); + if (TREE_CODE (t) == TREE_LIST + && TREE_PURPOSE (t) + && TREE_CODE (TREE_PURPOSE (t)) == TREE_VEC) + { + if (TREE_VALUE (t) == null_pointer_node) + continue; + if (TREE_PURPOSE (t) != last_iter) + { + if (last_bind) + { + append_to_statement_list (label, last_body); + gimplify_and_add (last_bind, pre_p); + last_bind = NULL_TREE; + } + for (tree it = TREE_PURPOSE (t); it; it = TREE_CHAIN (it)) + { + if (gimplify_expr (&TREE_VEC_ELT (it, 1), pre_p, NULL, + is_gimple_val, fb_rvalue) == GS_ERROR + || gimplify_expr (&TREE_VEC_ELT (it, 2), pre_p, NULL, + is_gimple_val, fb_rvalue) == GS_ERROR + || gimplify_expr (&TREE_VEC_ELT (it, 3), pre_p, NULL, + is_gimple_val, fb_rvalue) == GS_ERROR + || (gimplify_expr (&TREE_VEC_ELT (it, 4), pre_p, NULL, + is_gimple_val, fb_rvalue) + == GS_ERROR)) + return; + } + last_iter = TREE_PURPOSE (t); + tree block = TREE_VEC_ELT (TREE_PURPOSE (t), 5); + last_bind = build3 (BIND_EXPR, void_type_node, BLOCK_VARS (block), + NULL, block); + last_body = &BIND_EXPR_BODY (last_bind); + tree cond = NULL_TREE; + location_t loc = OMP_CLAUSE_LOCATION (c); + for (tree it = TREE_PURPOSE (t); it; it = TREE_CHAIN (it)) + { + tree var = TREE_VEC_ELT (it, 0); + tree begin = TREE_VEC_ELT (it, 1); + tree end = TREE_VEC_ELT (it, 2); + tree step = TREE_VEC_ELT (it, 3); + loc = DECL_SOURCE_LOCATION (var); + tree tem = build2_loc (loc, MODIFY_EXPR, void_type_node, + var, begin); + append_to_statement_list_force (tem, last_body); + + tree cond1 = fold_build2_loc (loc, GT_EXPR, boolean_type_node, + step, build_zero_cst (TREE_TYPE (step))); + tree cond2 = fold_build2_loc (loc, LE_EXPR, boolean_type_node, + var, end); + tree cond3 = fold_build2_loc (loc, GT_EXPR, boolean_type_node, + var, end); + cond1 = fold_build3_loc (loc, COND_EXPR, boolean_type_node, + cond1, cond2, cond3); + if (cond) + cond = fold_build2_loc (loc, TRUTH_AND_EXPR, + boolean_type_node, cond, cond1); + else + cond = cond1; + } + tree cont_label = create_artificial_label (loc); + label = build1 (LABEL_EXPR, void_type_node, cont_label); + tree tem = fold_build3_loc (loc, COND_EXPR, void_type_node, cond, + void_node, + build_and_jump (&cont_label)); + append_to_statement_list_force (tem, last_body); + } + if (TREE_CODE (TREE_VALUE (t)) == COMPOUND_EXPR) + { + append_to_statement_list (TREE_OPERAND (TREE_VALUE (t), 0), + last_body); + TREE_VALUE (t) = TREE_OPERAND (TREE_VALUE (t), 1); + } + if (error_operand_p (TREE_VALUE (t))) + return; + append_to_statement_list_force (TREE_VALUE (t), last_body); + TREE_VALUE (t) = null_pointer_node; + } + else + { + if (last_bind) + { + append_to_statement_list (label, last_body); + gimplify_and_add (last_bind, pre_p); + last_bind = NULL_TREE; + } + if (TREE_CODE (OMP_CLAUSE_DECL (c)) == COMPOUND_EXPR) + { + gimplify_expr (&TREE_OPERAND (OMP_CLAUSE_DECL (c), 0), pre_p, + NULL, is_gimple_val, fb_rvalue); + OMP_CLAUSE_DECL (c) = TREE_OPERAND (OMP_CLAUSE_DECL (c), 1); + } + if (error_operand_p (OMP_CLAUSE_DECL (c))) + return; + if (gimplify_expr (&OMP_CLAUSE_DECL (c), pre_p, NULL, + is_gimple_val, fb_rvalue) == GS_ERROR) + return; + gimplify_and_add (OMP_CLAUSE_DECL (c), pre_p); + } + } + if (last_bind) + { + append_to_statement_list (label, last_body); + gimplify_and_add (last_bind, pre_p); + } + return; +} + /* If *LIST_P contains any OpenMP depend clauses with iterators, lower all the depend clauses by populating corresponding depend array. Returns 0 if there are no such depend clauses, or @@ -9527,6 +9652,10 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p, goto do_add; + case OMP_CLAUSE_AFFINITY: + gimplify_omp_affinity (list_p, pre_p); + remove = true; + break; case OMP_CLAUSE_DEPEND: if (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK) { -- cgit v1.1 From 5d21c0cbda0c4b109366f51534f328145da4c21f Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Sat, 29 May 2021 10:05:38 +0200 Subject: openmp: Add shared to parallel for linear on parallel master taskloop simd [PR99928] I forgot to add default(none) and defaultmap(none) wherever possible on the testcases to make sure none of the required clauses are added implicitly (because in that case it doesn't work with these none arguments of those default* clauses or works differently with other default* settings. And that revealed we didn't add shared on parallel for linear clause on parallel master taskloop simd, so this patch fixes that too. 2021-05-29 Jakub Jelinek PR middle-end/99928 * gimplify.c (gimplify_scan_omp_clauses): For taskloop simd combined with parallel, make sure to add shared clause to parallel for explicit linear clause. * c-c++-common/gomp/pr99928-1.c: Add default(none) to constructs combined with parallel, teams or taskloop and defaultmap(none) to constructs combined with target. * c-c++-common/gomp/pr99928-2.c: Likewise. * c-c++-common/gomp/pr99928-3.c: Likewise. * c-c++-common/gomp/pr99928-4.c: Likewise. * c-c++-common/gomp/pr99928-5.c: Likewise. * c-c++-common/gomp/pr99928-6.c: Likewise. * c-c++-common/gomp/pr99928-7.c: Likewise. * c-c++-common/gomp/pr99928-8.c: Likewise. * c-c++-common/gomp/pr99928-9.c: Likewise. * c-c++-common/gomp/pr99928-10.c: Likewise. * c-c++-common/gomp/pr99928-13.c: Likewise. * c-c++-common/gomp/pr99928-14.c: Likewise. --- gcc/gimplify.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'gcc/gimplify.c') diff --git a/gcc/gimplify.c b/gcc/gimplify.c index d60fc95..3ca29ce 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -9014,6 +9014,7 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p, lastprivate and perhaps firstprivate too on the parallel. Similarly for #pragma omp for simd. */ struct gimplify_omp_ctx *octx = outer_ctx; + bool taskloop_seen = false; decl = NULL_TREE; do { @@ -9045,11 +9046,12 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p, else if (octx && (octx->region_type & ORT_TASK) != 0 && octx->combined_loop) - ; + taskloop_seen = true; else if (octx && octx->region_type == ORT_COMBINED_PARALLEL - && ctx->region_type == ORT_WORKSHARE - && octx == outer_ctx) + && ((ctx->region_type == ORT_WORKSHARE + && octx == outer_ctx) + || taskloop_seen)) flags = GOVD_SEEN | GOVD_SHARED; else if (octx && ((octx->region_type & ORT_COMBINED_TEAMS) -- cgit v1.1 From 34aae6b561871d6d8b10c810f303cb6f18b5fdd0 Mon Sep 17 00:00:00 2001 From: Andrew Pinski Date: Mon, 31 May 2021 12:25:28 +0000 Subject: Use is_empty_type instead of zero-sized type. Instead of only removing assignments of zero-sized types, assignments of all empty types should be removed during gimplification. This moves to use is_empty_type which will be used in other places too. OK? Bootstrapped and tested on aarch64-linux-gnu with no regressions. Thanks, Andrew Pinski gcc/ChangeLog: * gimplify.c (zero_sized_field_decl): Delete (zero_sized_type): Delete (gimplify_init_ctor_eval): Use is_empty_type instead of zero_sized_field_decl. (gimplify_modify_expr): Use is_empty_type instead of zero_sized_type. --- gcc/gimplify.c | 34 +++++++--------------------------- 1 file changed, 7 insertions(+), 27 deletions(-) (limited to 'gcc/gimplify.c') diff --git a/gcc/gimplify.c b/gcc/gimplify.c index 3ca29ce..39f5b97 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -4644,28 +4644,6 @@ gimplify_init_ctor_eval_range (tree object, tree lower, tree upper, gimplify_seq_add_stmt (pre_p, gimple_build_label (loop_exit_label)); } -/* Return true if FDECL is accessing a field that is zero sized. */ - -static bool -zero_sized_field_decl (const_tree fdecl) -{ - if (TREE_CODE (fdecl) == FIELD_DECL && DECL_SIZE (fdecl) - && integer_zerop (DECL_SIZE (fdecl))) - return true; - return false; -} - -/* Return true if TYPE is zero sized. */ - -static bool -zero_sized_type (const_tree type) -{ - if (AGGREGATE_TYPE_P (type) && TYPE_SIZE (type) - && integer_zerop (TYPE_SIZE (type))) - return true; - return false; -} - /* A subroutine of gimplify_init_constructor. Generate individual MODIFY_EXPRs for a CONSTRUCTOR. OBJECT is the LHS against which the assignments should happen. ELTS is the CONSTRUCTOR_ELTS of the @@ -4699,11 +4677,13 @@ gimplify_init_ctor_eval (tree object, vec *elts, gcc_assert (purpose); /* Skip zero-sized fields, unless value has side-effects. This can - happen with calls to functions returning a zero-sized type, which + happen with calls to functions returning a empty type, which we shouldn't discard. As a number of downstream passes don't - expect sets of zero-sized fields, we rely on the gimplification of + expect sets of empty type fields, we rely on the gimplification of the MODIFY_EXPR we make below to drop the assignment statement. */ - if (! TREE_SIDE_EFFECTS (value) && zero_sized_field_decl (purpose)) + if (!TREE_SIDE_EFFECTS (value) + && TREE_CODE (purpose) == FIELD_DECL + && is_empty_type (TREE_TYPE (purpose))) continue; /* If we have a RANGE_EXPR, we have to build a loop to assign the @@ -5781,11 +5761,11 @@ gimplify_modify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, if (ret != GS_UNHANDLED) return ret; - /* For zero sized types only gimplify the left hand side and right hand + /* For empty types only gimplify the left hand side and right hand side as statements and throw away the assignment. Do this after gimplify_modify_expr_rhs so we handle TARGET_EXPRs of addressable types properly. */ - if (zero_sized_type (TREE_TYPE (*from_p)) + if (is_empty_type (TREE_TYPE (*from_p)) && !want_value /* Don't do this for calls that return addressable types, expand_call relies on those having a lhs. */ -- cgit v1.1 From 7aefef31365b9c3d32a0edb6ea0d3b8864d7e91a Mon Sep 17 00:00:00 2001 From: Andrew Stubbs Date: Fri, 25 Sep 2020 16:22:47 +0100 Subject: OpenACC: Separate enter/exit data ABIs Move the OpenACC enter and exit data directives from using a single builtin to having one each. For most purposes it was easy to tell which was which, from the clauses given, but it's overhead we can easily avoid, and there may be future uses where that isn't possible. gcc/ * omp-builtins.def (BUILT_IN_GOACC_ENTER_EXIT_DATA): Split into... (BUILT_IN_GOACC_ENTER_DATA, BUILT_IN_GOACC_EXIT_DATA): ... these. * gimple.h (enum gf_mask): Split 'GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA' into 'GF_OMP_TARGET_KIND_OACC_ENTER_DATA' and 'GF_OMP_TARGET_KIND_OACC_EXIT_DATA'. (is_gimple_omp_oacc): Update. * gimple-pretty-print.c (dump_gimple_omp_target): Likewise. * gimplify.c (gimplify_omp_target_update): Likewise. * omp-expand.c (expand_omp_target, build_omp_regions_1) (omp_make_gimple_edges): Likewise. * omp-low.c (check_omp_nesting_restrictions, lower_omp_target): Likewise. gcc/testsuite/ * c-c++-common/goacc-gomp/nesting-fail-1.c: Adjust patterns. * c-c++-common/goacc/finalize-1.c: Likewise. * c-c++-common/goacc/mdc-1.c: Likewise. * c-c++-common/goacc/nesting-fail-1.c: Likewise. * c-c++-common/goacc/struct-enter-exit-data-1.c: Likewise. * gfortran.dg/goacc/attach-descriptor.f90: Likewise. * gfortran.dg/goacc/finalize-1.f: Likewise. * gfortran.dg/goacc/mapping-tests-3.f90: Likewise. libgomp/ * libgomp.map (GOACC_2.0.2): New symbol version. * libgomp_g.h (GOACC_enter_data, GOACC_exit_data) New prototypes. * oacc-mem.c (GOACC_enter_data, GOACC_exit_data) New functions. Co-Authored-By: Thomas Schwinge --- gcc/gimplify.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'gcc/gimplify.c') diff --git a/gcc/gimplify.c b/gcc/gimplify.c index 39f5b97..c96d611 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -13383,8 +13383,11 @@ gimplify_omp_target_update (tree *expr_p, gimple_seq *pre_p) switch (TREE_CODE (expr)) { case OACC_ENTER_DATA: + kind = GF_OMP_TARGET_KIND_OACC_ENTER_DATA; + ort = ORT_ACC; + break; case OACC_EXIT_DATA: - kind = GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA; + kind = GF_OMP_TARGET_KIND_OACC_EXIT_DATA; ort = ORT_ACC; break; case OACC_UPDATE: -- cgit v1.1 From 1de31913d20a467b78904c0e96efd5fbd6facd2c Mon Sep 17 00:00:00 2001 From: Tobias Burnus Date: Tue, 15 Jun 2021 16:06:38 +0200 Subject: Fortran/OpenMP: Extend defaultmap clause for OpenMP 5 [PR92568] PR fortran/92568 gcc/fortran/ChangeLog: * dump-parse-tree.c (show_omp_clauses): Update for defaultmap. * f95-lang.c (LANG_HOOKS_OMP_ALLOCATABLE_P, LANG_HOOKS_OMP_SCALAR_TARGET_P): New. * gfortran.h (enum gfc_omp_defaultmap, enum gfc_omp_defaultmap_category): New. * openmp.c (gfc_match_omp_clauses): Update defaultmap matching. * trans-decl.c (gfc_finish_decl_attrs): Set GFC_DECL_SCALAR_TARGET. * trans-openmp.c (gfc_omp_allocatable_p, gfc_omp_scalar_target_p): New. (gfc_omp_scalar_p): Take 'ptr_alloc_ok' argument. (gfc_trans_omp_clauses, gfc_split_omp_clauses): Update for defaultmap changes. * trans.h (gfc_omp_scalar_p): Update prototype. (gfc_omp_allocatable_p, gfc_omp_scalar_target_p): New. (struct lang_decl): Add scalar_target. (GFC_DECL_SCALAR_TARGET, GFC_DECL_GET_SCALAR_TARGET): New. gcc/ChangeLog: * gimplify.c (enum gimplify_defaultmap_kind): Add GDMK_SCALAR_TARGET. (struct gimplify_omp_ctx): Extend defaultmap array by one. (new_omp_context): Init defaultmap[GDMK_SCALAR_TARGET]. (omp_notice_variable): Update type classification for Fortran. (gimplify_scan_omp_clauses): Update calls for new argument; handle GDMK_SCALAR_TARGET; for Fortran, GDMK_POINTER avoid GOVD_MAP_0LEN_ARRAY. * langhooks-def.h (lhd_omp_scalar_p): Add 'ptr_ok' argument. * langhooks.c (lhd_omp_scalar_p): Likewise. (LANG_HOOKS_OMP_ALLOCATABLE_P, LANG_HOOKS_OMP_SCALAR_TARGET_P): New. (LANG_HOOKS_DECLS): Add them. * langhooks.h (struct lang_hooks_for_decls): Add new hooks, update omp_scalar_p pointer type to include the new bool argument. libgomp/ChangeLog: * testsuite/libgomp.fortran/defaultmap-8.f90: New test. gcc/testsuite/ChangeLog: * gfortran.dg/gomp/pr99928-1.f90: Uncomment 'defaultmap(none)'. * gfortran.dg/gomp/pr99928-2.f90: Uncomment 'defaultmap(none)'. * gfortran.dg/gomp/pr99928-3.f90: Uncomment 'defaultmap(none)'. * gfortran.dg/gomp/pr99928-4.f90: Uncomment 'defaultmap(none)'. * gfortran.dg/gomp/pr99928-5.f90: Uncomment 'defaultmap(none)'. * gfortran.dg/gomp/pr99928-6.f90: Uncomment 'defaultmap(none)'. * gfortran.dg/gomp/pr99928-8.f90: Uncomment 'defaultmap(none)'. * gfortran.dg/gomp/defaultmap-1.f90: New test. * gfortran.dg/gomp/defaultmap-2.f90: New test. * gfortran.dg/gomp/defaultmap-3.f90: New test. * gfortran.dg/gomp/defaultmap-4.f90: New test. * gfortran.dg/gomp/defaultmap-5.f90: New test. * gfortran.dg/gomp/defaultmap-6.f90: New test. * gfortran.dg/gomp/defaultmap-7.f90: New test. --- gcc/gimplify.c | 35 +++++++++++++++++++++++++---------- 1 file changed, 25 insertions(+), 10 deletions(-) (limited to 'gcc/gimplify.c') diff --git a/gcc/gimplify.c b/gcc/gimplify.c index c96d611..2606998 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -212,6 +212,7 @@ struct gimplify_ctx enum gimplify_defaultmap_kind { GDMK_SCALAR, + GDMK_SCALAR_TARGET, /* w/ Fortran's target attr, implicit mapping, only. */ GDMK_AGGREGATE, GDMK_ALLOCATABLE, GDMK_POINTER @@ -236,7 +237,7 @@ struct gimplify_omp_ctx bool order_concurrent; bool has_depend; bool in_for_exprs; - int defaultmap[4]; + int defaultmap[5]; }; static struct gimplify_ctx *gimplify_ctxp; @@ -461,6 +462,7 @@ new_omp_context (enum omp_region_type region_type) else c->default_kind = OMP_CLAUSE_DEFAULT_UNSPECIFIED; c->defaultmap[GDMK_SCALAR] = GOVD_MAP; + c->defaultmap[GDMK_SCALAR_TARGET] = GOVD_MAP; c->defaultmap[GDMK_AGGREGATE] = GOVD_MAP; c->defaultmap[GDMK_ALLOCATABLE] = GOVD_MAP; c->defaultmap[GDMK_POINTER] = GOVD_MAP; @@ -7503,13 +7505,17 @@ omp_notice_variable (struct gimplify_omp_ctx *ctx, tree decl, bool in_code) { int gdmk; enum omp_clause_defaultmap_kind kind; - if (TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE - || (TREE_CODE (TREE_TYPE (decl)) == REFERENCE_TYPE - && (TREE_CODE (TREE_TYPE (TREE_TYPE (decl))) - == POINTER_TYPE))) - gdmk = GDMK_POINTER; - else if (lang_hooks.decls.omp_scalar_p (decl)) + if (lang_hooks.decls.omp_allocatable_p (decl)) + gdmk = GDMK_ALLOCATABLE; + else if (lang_hooks.decls.omp_scalar_target_p (decl)) + gdmk = GDMK_SCALAR_TARGET; + else if (lang_hooks.decls.omp_scalar_p (decl, false)) gdmk = GDMK_SCALAR; + else if (TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE + || (TREE_CODE (TREE_TYPE (decl)) == REFERENCE_TYPE + && (TREE_CODE (TREE_TYPE (TREE_TYPE (decl))) + == POINTER_TYPE))) + gdmk = GDMK_POINTER; else gdmk = GDMK_AGGREGATE; kind = lang_hooks.decls.omp_predetermined_mapping (decl); @@ -8746,6 +8752,8 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p, if (!lang_GNU_Fortran ()) ctx->defaultmap[GDMK_POINTER] = GOVD_MAP | GOVD_MAP_0LEN_ARRAY; ctx->defaultmap[GDMK_SCALAR] = GOVD_FIRSTPRIVATE; + ctx->defaultmap[GDMK_SCALAR_TARGET] = (lang_GNU_Fortran () + ? GOVD_MAP : GOVD_FIRSTPRIVATE); } if (!lang_GNU_Fortran ()) switch (code) @@ -8827,7 +8835,7 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p, if (error_operand_p (decl)) goto do_add; if (OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c) - && !lang_hooks.decls.omp_scalar_p (decl)) + && !lang_hooks.decls.omp_scalar_p (decl, true)) { error_at (OMP_CLAUSE_LOCATION (c), "non-scalar variable %qD in conditional " @@ -10025,7 +10033,8 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p, gdmkmax = GDMK_POINTER; break; case OMP_CLAUSE_DEFAULTMAP_CATEGORY_SCALAR: - gdmkmin = gdmkmax = GDMK_SCALAR; + gdmkmin = GDMK_SCALAR; + gdmkmax = GDMK_SCALAR_TARGET; break; case OMP_CLAUSE_DEFAULTMAP_CATEGORY_AGGREGATE: gdmkmin = gdmkmax = GDMK_AGGREGATE; @@ -10066,12 +10075,18 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p, case GDMK_SCALAR: ctx->defaultmap[gdmk] = GOVD_FIRSTPRIVATE; break; + case GDMK_SCALAR_TARGET: + ctx->defaultmap[gdmk] = (lang_GNU_Fortran () + ? GOVD_MAP : GOVD_FIRSTPRIVATE); + break; case GDMK_AGGREGATE: case GDMK_ALLOCATABLE: ctx->defaultmap[gdmk] = GOVD_MAP; break; case GDMK_POINTER: - ctx->defaultmap[gdmk] = GOVD_MAP | GOVD_MAP_0LEN_ARRAY; + ctx->defaultmap[gdmk] = GOVD_MAP; + if (!lang_GNU_Fortran ()) + ctx->defaultmap[gdmk] |= GOVD_MAP_0LEN_ARRAY; break; default: gcc_unreachable (); -- cgit v1.1 From 644c2cc5f2c09506a7bfef293a7f90efa8d7e5fa Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Mon, 21 Jun 2021 13:30:42 +0200 Subject: inline-asm: Fix ICE with bitfields in "m" operands [PR100785] Bitfields, while they live in memory, aren't something inline-asm can easily operate on. For C and "=m" or "+m", we were diagnosing bitfields in the past in the FE, where c_mark_addressable had: case COMPONENT_REF: if (DECL_C_BIT_FIELD (TREE_OPERAND (x, 1))) { error ("cannot take address of bit-field %qD", TREE_OPERAND (x, 1)); return false; } but that check got moved in GCC 6 to build_unary_op instead and now we emit an error during expansion and ICE afterwards (i.e. error-recovery). For "m" it used to be diagnosed in c_mark_addressable too, but since GCC 6 it is ice-on-invalid. For C++, this was never diagnosed in the FE, but used to be diagnosed in the gimplifier and/or during expansion before 4.8. The following patch does multiple things: 1) diagnoses it in the FEs 2) stops emitting a redundant diagnostic in the gimplifier using the usual way, if we already see error_mark_node, we assume error has been emitted already and only diagnose if it wasn't error_mark_node; this helps diagnosing the same bug with multiple different errors 3) simplifies during expansion the inline asm if any errors have been reported (similarly how e.g. vregs pass if it detects errors on inline-asm either deletes them or simplifies to bare minimum - just labels), so that we don't have error-recovery ICEs there 2021-06-11 Jakub Jelinek PR inline-asm/100785 gcc/ * gimplify.c (gimplify_asm_expr): Don't diagnose errors if output or input operands were already error_mark_node. * cfgexpand.c (expand_asm_stmt): If errors are emitted, remove all inputs, outputs and clobbers from the asm and set template to "". gcc/c/ * c-typeck.c (c_mark_addressable): Diagnose trying to make bit-fields addressable. gcc/cp/ * typeck.c (cxx_mark_addressable): Diagnose trying to make bit-fields addressable. gcc/testsuite/ * c-c++-common/pr100785.c: New test. * gcc.dg/pr48552-1.c: Don't expect invalid lvalue errors. * gcc.dg/pr48552-2.c: Likewise. --- gcc/gimplify.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'gcc/gimplify.c') diff --git a/gcc/gimplify.c b/gcc/gimplify.c index 2606998..41bae9c 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -6323,12 +6323,14 @@ gimplify_asm_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p) if (!allows_reg && allows_mem) mark_addressable (TREE_VALUE (link)); + tree orig = TREE_VALUE (link); tret = gimplify_expr (&TREE_VALUE (link), pre_p, post_p, is_inout ? is_gimple_min_lval : is_gimple_lvalue, fb_lvalue | fb_mayfail); if (tret == GS_ERROR) { - error ("invalid lvalue in % output %d", i); + if (orig != error_mark_node) + error ("invalid lvalue in % output %d", i); ret = tret; } @@ -6523,8 +6525,9 @@ gimplify_asm_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p) mark_addressable (TREE_VALUE (link)); if (tret == GS_ERROR) { - error_at (EXPR_LOC_OR_LOC (TREE_VALUE (link), input_location), - "memory input %d is not directly addressable", i); + if (inputv != error_mark_node) + error_at (EXPR_LOC_OR_LOC (TREE_VALUE (link), input_location), + "memory input %d is not directly addressable", i); ret = tret; } } -- cgit v1.1 From b4e21c80462682c4e6e5e487fe87107b27f8b4bd Mon Sep 17 00:00:00 2001 From: Richard Biener Date: Tue, 22 Jun 2021 12:13:44 +0200 Subject: middle-end/101156 - remove not working optimization in gimplification This removes a premature and not working optimization from the gimplifier. When gimplification is requested not to produce a SSA name we try to avoid generating a copy when we did so anyway but instead replace the LHS of its definition. But that only works in case there are no uses of the SSA name already which is something we cannot easily check, so the following removes said optimization. Statistics on the whole bootstrap shows we hit this optimization only for libiberty/cp-demangle.c and overall we have 21652112 gimplifications where just 240 copies are elided. Preserving the optimization would require scanning the original expression and the pre and post sequences for SSA names and uses, that seems excessive to avoid these 240 copies. 2021-06-22 Richard Biener PR middle-end/101156 * gimplify.c (gimplify_expr): Remove premature incorrect optimization. * gcc.dg/pr101156.c: New testcase. --- gcc/gimplify.c | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) (limited to 'gcc/gimplify.c') diff --git a/gcc/gimplify.c b/gcc/gimplify.c index 41bae9c..21e7a6c 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -15128,24 +15128,11 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, bool (*gimple_test_f) (tree), fallback_t fallback, bool allow_ssa) { - bool was_ssa_name_p = TREE_CODE (*expr_p) == SSA_NAME; enum gimplify_status ret = gimplify_expr (expr_p, pre_p, post_p, gimple_test_f, fallback); if (! allow_ssa && TREE_CODE (*expr_p) == SSA_NAME) - { - tree name = *expr_p; - if (was_ssa_name_p) - *expr_p = get_initialized_tmp_var (*expr_p, pre_p, NULL, false); - else - { - /* Avoid the extra copy if possible. */ - *expr_p = create_tmp_reg (TREE_TYPE (name)); - if (!gimple_nop_p (SSA_NAME_DEF_STMT (name))) - gimple_set_lhs (SSA_NAME_DEF_STMT (name), *expr_p); - release_ssa_name (name); - } - } + *expr_p = get_initialized_tmp_var (*expr_p, pre_p, NULL, false); return ret; } -- cgit v1.1 From 7619d33471c10fe3d149dcbb701d99ed3dd23528 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Thu, 24 Jun 2021 11:25:34 +0200 Subject: openmp: in_reduction clause support on target construct This patch adds support for in_reduction clause on target construct, though for now only for synchronous targets (without nowait clause). The encountering thread in that case runs the target task and blocks until the target region ends, so it is implemented by remapping it before entering the target, initializing the private copy if not yet initialized for the current thread and then using the remapped addresses for the mapping addresses. For nowait combined with in_reduction the patch contains a hack where the nowait clause is ignored. To implement it correctly, I think we would need to create a new private variable for the in_reduction and initialize it before doing the async target and adjust the map addresses to that private variable and then pass a function pointer to the library routine with code where the callback would remap the address to the current threads private variable and use in_reduction combiner to combine the private variable we've created into the thread's copy. The library would then need to make sure that the routine is called in some thread participating in the parallel (and not in an unshackeled thread). 2021-06-24 Jakub Jelinek gcc/ * tree.h (OMP_CLAUSE_MAP_IN_REDUCTION): Document meaning for OpenMP. * gimplify.c (gimplify_scan_omp_clauses): For OpenMP map clauses with OMP_CLAUSE_MAP_IN_REDUCTION flag partially defer gimplification of non-decl OMP_CLAUSE_DECL. For OMP_CLAUSE_IN_REDUCTION on OMP_TARGET user outer_ctx instead of ctx for placeholders and initializer/combiner gimplification. * omp-low.c (scan_sharing_clauses): Handle OMP_CLAUSE_MAP_IN_REDUCTION on target constructs. (lower_rec_input_clauses): Likewise. (lower_omp_target): Likewise. * omp-expand.c (expand_omp_target): Temporarily ignore nowait clause on target if in_reduction is present. gcc/c-family/ * c-common.h (enum c_omp_region_type): Add C_ORT_TARGET and C_ORT_OMP_TARGET. * c-omp.c (c_omp_split_clauses): For OMP_CLAUSE_IN_REDUCTION on combined target constructs also add map (always, tofrom:) clause. gcc/c/ * c-parser.c (omp_split_clauses): Pass C_ORT_OMP_TARGET instead of C_ORT_OMP for clauses on target construct. (OMP_TARGET_CLAUSE_MASK): Add in_reduction clause. (c_parser_omp_target): For non-combined target add map (always, tofrom:) clauses for OMP_CLAUSE_IN_REDUCTION. Pass C_ORT_OMP_TARGET to c_finish_omp_clauses. * c-typeck.c (handle_omp_array_sections): Adjust ort handling for addition of C_ORT_OMP_TARGET and simplify, mapping clauses are never present on C_ORT_*DECLARE_SIMD. (c_finish_omp_clauses): Likewise. Handle OMP_CLAUSE_IN_REDUCTION on C_ORT_OMP_TARGET, set OMP_CLAUSE_MAP_IN_REDUCTION on corresponding map clauses. gcc/cp/ * parser.c (cp_omp_split_clauses): Pass C_ORT_OMP_TARGET instead of C_ORT_OMP for clauses on target construct. (OMP_TARGET_CLAUSE_MASK): Add in_reduction clause. (cp_parser_omp_target): For non-combined target add map (always, tofrom:) clauses for OMP_CLAUSE_IN_REDUCTION. Pass C_ORT_OMP_TARGET to finish_omp_clauses. * semantics.c (handle_omp_array_sections_1): Adjust ort handling for addition of C_ORT_OMP_TARGET and simplify, mapping clauses are never present on C_ORT_*DECLARE_SIMD. (handle_omp_array_sections): Likewise. (finish_omp_clauses): Likewise. Handle OMP_CLAUSE_IN_REDUCTION on C_ORT_OMP_TARGET, set OMP_CLAUSE_MAP_IN_REDUCTION on corresponding map clauses. * pt.c (tsubst_expr): Pass C_ORT_OMP_TARGET instead of C_ORT_OMP for clauses on target construct. gcc/testsuite/ * c-c++-common/gomp/target-in-reduction-1.c: New test. * c-c++-common/gomp/clauses-1.c: Add in_reduction clauses on target or combined target constructs. libgomp/ * testsuite/libgomp.c-c++-common/target-in-reduction-1.c: New test. * testsuite/libgomp.c-c++-common/target-in-reduction-2.c: New test. * testsuite/libgomp.c++/target-in-reduction-1.C: New test. * testsuite/libgomp.c++/target-in-reduction-2.C: New test. --- gcc/gimplify.c | 126 +++++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 119 insertions(+), 7 deletions(-) (limited to 'gcc/gimplify.c') diff --git a/gcc/gimplify.c b/gcc/gimplify.c index 21e7a6c..4be2feb 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -9566,8 +9566,116 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p, OMP_CLAUSE_SET_MAP_KIND (c, k); } - if (gimplify_expr (pd, pre_p, NULL, is_gimple_lvalue, fb_lvalue) - == GS_ERROR) + if (code == OMP_TARGET && OMP_CLAUSE_MAP_IN_REDUCTION (c)) + { + /* Don't gimplify *pd fully at this point, as the base + will need to be adjusted during omp lowering. */ + auto_vec expr_stack; + tree *p = pd; + while (handled_component_p (*p) + || TREE_CODE (*p) == INDIRECT_REF + || TREE_CODE (*p) == ADDR_EXPR + || TREE_CODE (*p) == MEM_REF + || TREE_CODE (*p) == NON_LVALUE_EXPR) + { + expr_stack.safe_push (*p); + p = &TREE_OPERAND (*p, 0); + } + for (int i = expr_stack.length () - 1; i >= 0; i--) + { + tree t = expr_stack[i]; + if (TREE_CODE (t) == ARRAY_REF + || TREE_CODE (t) == ARRAY_RANGE_REF) + { + if (TREE_OPERAND (t, 2) == NULL_TREE) + { + tree low = unshare_expr (array_ref_low_bound (t)); + if (!is_gimple_min_invariant (low)) + { + TREE_OPERAND (t, 2) = low; + if (gimplify_expr (&TREE_OPERAND (t, 2), + pre_p, NULL, + is_gimple_reg, + fb_rvalue) == GS_ERROR) + remove = true; + } + } + else if (gimplify_expr (&TREE_OPERAND (t, 2), pre_p, + NULL, is_gimple_reg, + fb_rvalue) == GS_ERROR) + remove = true; + if (TREE_OPERAND (t, 3) == NULL_TREE) + { + tree elmt_size = array_ref_element_size (t); + if (!is_gimple_min_invariant (elmt_size)) + { + elmt_size = unshare_expr (elmt_size); + tree elmt_type + = TREE_TYPE (TREE_TYPE (TREE_OPERAND (t, + 0))); + tree factor + = size_int (TYPE_ALIGN_UNIT (elmt_type)); + elmt_size + = size_binop (EXACT_DIV_EXPR, elmt_size, + factor); + TREE_OPERAND (t, 3) = elmt_size; + if (gimplify_expr (&TREE_OPERAND (t, 3), + pre_p, NULL, + is_gimple_reg, + fb_rvalue) == GS_ERROR) + remove = true; + } + } + else if (gimplify_expr (&TREE_OPERAND (t, 3), pre_p, + NULL, is_gimple_reg, + fb_rvalue) == GS_ERROR) + remove = true; + } + else if (TREE_CODE (t) == COMPONENT_REF) + { + if (TREE_OPERAND (t, 2) == NULL_TREE) + { + tree offset = component_ref_field_offset (t); + if (!is_gimple_min_invariant (offset)) + { + offset = unshare_expr (offset); + tree field = TREE_OPERAND (t, 1); + tree factor + = size_int (DECL_OFFSET_ALIGN (field) + / BITS_PER_UNIT); + offset = size_binop (EXACT_DIV_EXPR, offset, + factor); + TREE_OPERAND (t, 2) = offset; + if (gimplify_expr (&TREE_OPERAND (t, 2), + pre_p, NULL, + is_gimple_reg, + fb_rvalue) == GS_ERROR) + remove = true; + } + } + else if (gimplify_expr (&TREE_OPERAND (t, 2), pre_p, + NULL, is_gimple_reg, + fb_rvalue) == GS_ERROR) + remove = true; + } + } + for (; expr_stack.length () > 0; ) + { + tree t = expr_stack.pop (); + + if (TREE_CODE (t) == ARRAY_REF + || TREE_CODE (t) == ARRAY_RANGE_REF) + { + if (!is_gimple_min_invariant (TREE_OPERAND (t, 1)) + && gimplify_expr (&TREE_OPERAND (t, 1), pre_p, + NULL, is_gimple_val, + fb_rvalue) == GS_ERROR) + remove = true; + } + } + } + else if (gimplify_expr (pd, pre_p, NULL, is_gimple_lvalue, + fb_lvalue) == GS_ERROR) { remove = true; break; @@ -9764,17 +9872,21 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p, || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_TASK_REDUCTION) && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)) { - omp_add_variable (ctx, OMP_CLAUSE_REDUCTION_PLACEHOLDER (c), - GOVD_LOCAL | GOVD_SEEN); - if (OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c) + struct gimplify_omp_ctx *pctx + = code == OMP_TARGET ? outer_ctx : ctx; + if (pctx) + omp_add_variable (pctx, OMP_CLAUSE_REDUCTION_PLACEHOLDER (c), + GOVD_LOCAL | GOVD_SEEN); + if (pctx + && OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c) && walk_tree (&OMP_CLAUSE_REDUCTION_INIT (c), find_decl_expr, OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c), NULL) == NULL_TREE) - omp_add_variable (ctx, + omp_add_variable (pctx, OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c), GOVD_LOCAL | GOVD_SEEN); - gimplify_omp_ctxp = ctx; + gimplify_omp_ctxp = pctx; push_gimplify_context (); OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL; -- cgit v1.1 From e9e2bad7251477db92ab9ebcdc010f9282dd9890 Mon Sep 17 00:00:00 2001 From: Martin Sebor Date: Thu, 24 Jun 2021 19:22:06 -0600 Subject: middle-end: add support for per-location warning groups. gcc/ChangeLog: * builtins.c (warn_string_no_nul): Replace uses of TREE_NO_WARNING, gimple_no_warning_p and gimple_set_no_warning with warning_suppressed_p, and suppress_warning. (c_strlen): Same. (maybe_warn_for_bound): Same. (warn_for_access): Same. (check_access): Same. (expand_builtin_strncmp): Same. (fold_builtin_varargs): Same. * calls.c (maybe_warn_nonstring_arg): Same. (maybe_warn_rdwr_sizes): Same. * cfgexpand.c (expand_call_stmt): Same. * cgraphunit.c (check_global_declaration): Same. * fold-const.c (fold_undefer_overflow_warnings): Same. (fold_truth_not_expr): Same. (fold_unary_loc): Same. (fold_checksum_tree): Same. * gimple-array-bounds.cc (array_bounds_checker::check_array_ref): Same. (array_bounds_checker::check_mem_ref): Same. (array_bounds_checker::check_addr_expr): Same. (array_bounds_checker::check_array_bounds): Same. * gimple-expr.c (copy_var_decl): Same. * gimple-fold.c (gimple_fold_builtin_strcpy): Same. (gimple_fold_builtin_strncat): Same. (gimple_fold_builtin_stxcpy_chk): Same. (gimple_fold_builtin_stpcpy): Same. (gimple_fold_builtin_sprintf): Same. (fold_stmt_1): Same. * gimple-ssa-isolate-paths.c (diag_returned_locals): Same. * gimple-ssa-nonnull-compare.c (do_warn_nonnull_compare): Same. * gimple-ssa-sprintf.c (handle_printf_call): Same. * gimple-ssa-store-merging.c (imm_store_chain_info::output_merged_store): Same. * gimple-ssa-warn-restrict.c (maybe_diag_overlap): Same. * gimple-ssa-warn-restrict.h: Adjust declarations. (maybe_diag_access_bounds): Replace uses of TREE_NO_WARNING, gimple_no_warning_p and gimple_set_no_warning with warning_suppressed_p, and suppress_warning. (check_call): Same. (check_bounds_or_overlap): Same. * gimple.c (gimple_build_call_from_tree): Same. * gimplify.c (gimplify_return_expr): Same. (gimplify_cond_expr): Same. (gimplify_modify_expr_complex_part): Same. (gimplify_modify_expr): Same. (gimple_push_cleanup): Same. (gimplify_expr): Same. * omp-expand.c (expand_omp_for_generic): Same. (expand_omp_taskloop_for_outer): Same. * omp-low.c (lower_rec_input_clauses): Same. (lower_lastprivate_clauses): Same. (lower_send_clauses): Same. (lower_omp_target): Same. * tree-cfg.c (pass_warn_function_return::execute): Same. * tree-complex.c (create_one_component_var): Same. * tree-inline.c (remap_gimple_op_r): Same. (copy_tree_body_r): Same. (declare_return_variable): Same. (expand_call_inline): Same. * tree-nested.c (lookup_field_for_decl): Same. * tree-sra.c (create_access_replacement): Same. (generate_subtree_copies): Same. * tree-ssa-ccp.c (pass_post_ipa_warn::execute): Same. * tree-ssa-forwprop.c (combine_cond_expr_cond): Same. * tree-ssa-loop-ch.c (ch_base::copy_headers): Same. * tree-ssa-loop-im.c (execute_sm): Same. * tree-ssa-phiopt.c (cond_store_replacement): Same. * tree-ssa-strlen.c (maybe_warn_overflow): Same. (handle_builtin_strcpy): Same. (maybe_diag_stxncpy_trunc): Same. (handle_builtin_stxncpy_strncat): Same. (handle_builtin_strcat): Same. * tree-ssa-uninit.c (get_no_uninit_warning): Same. (set_no_uninit_warning): Same. (uninit_undefined_value_p): Same. (warn_uninit): Same. (maybe_warn_operand): Same. * tree-vrp.c (compare_values_warnv): Same. * vr-values.c (vr_values::extract_range_for_var_from_comparison_expr): Same. (test_for_singularity): Same. * gimple.h (warning_suppressed_p): New function. (suppress_warning): Same. (copy_no_warning): Same. (gimple_set_block): Call gimple_set_location. (gimple_set_location): Call copy_warning. --- gcc/gimplify.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'gcc/gimplify.c') diff --git a/gcc/gimplify.c b/gcc/gimplify.c index 4be2feb..75a4a9d 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -1601,7 +1601,7 @@ gimplify_return_expr (tree stmt, gimple_seq *pre_p) { maybe_add_early_return_predict_stmt (pre_p); greturn *ret = gimple_build_return (ret_expr); - gimple_set_no_warning (ret, TREE_NO_WARNING (stmt)); + copy_warning (ret, stmt); gimplify_seq_add_stmt (pre_p, ret); return GS_ALL_DONE; } @@ -1663,7 +1663,7 @@ gimplify_return_expr (tree stmt, gimple_seq *pre_p) we can wind up warning about an uninitialized value for this. Due to how this variable is constructed and initialized, this is never true. Give up and never warn. */ - TREE_NO_WARNING (result) = 1; + suppress_warning (result, OPT_Wuninitialized); gimplify_ctxp->return_temp = result; } @@ -1677,7 +1677,7 @@ gimplify_return_expr (tree stmt, gimple_seq *pre_p) maybe_add_early_return_predict_stmt (pre_p); ret = gimple_build_return (result); - gimple_set_no_warning (ret, TREE_NO_WARNING (stmt)); + copy_warning (ret, stmt); gimplify_seq_add_stmt (pre_p, ret); return GS_ALL_DONE; @@ -4252,7 +4252,8 @@ gimplify_cond_expr (tree *expr_p, gimple_seq *pre_p, fallback_t fallback) &arm2); cond_stmt = gimple_build_cond (pred_code, arm1, arm2, label_true, label_false); - gimple_set_no_warning (cond_stmt, TREE_NO_WARNING (COND_EXPR_COND (expr))); + gimple_set_location (cond_stmt, EXPR_LOCATION (expr)); + copy_warning (cond_stmt, COND_EXPR_COND (expr)); gimplify_seq_add_stmt (&seq, cond_stmt); gimple_stmt_iterator gsi = gsi_last (seq); maybe_fold_stmt (&gsi); @@ -5682,7 +5683,7 @@ gimplify_modify_expr_complex_part (tree *expr_p, gimple_seq *pre_p, ocode = code == REALPART_EXPR ? IMAGPART_EXPR : REALPART_EXPR; other = build1 (ocode, TREE_TYPE (rhs), lhs); - TREE_NO_WARNING (other) = 1; + suppress_warning (other); other = get_formal_tmp_var (other, pre_p); realpart = code == REALPART_EXPR ? rhs : other; @@ -5967,7 +5968,7 @@ gimplify_modify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, assign = gimple_build_assign (*to_p, *from_p); gimple_set_location (assign, EXPR_LOCATION (*expr_p)); if (COMPARISON_CLASS_P (*from_p)) - gimple_set_no_warning (assign, TREE_NO_WARNING (*from_p)); + copy_warning (assign, *from_p); } if (gimplify_ctxp->into_ssa && is_gimple_reg (*to_p)) @@ -6729,7 +6730,7 @@ gimple_push_cleanup (tree var, tree cleanup, bool eh_only, gimple_seq *pre_p, /* Because of this manipulation, and the EH edges that jump threading cannot redirect, the temporary (VAR) will appear to be used uninitialized. Don't warn. */ - TREE_NO_WARNING (var) = 1; + suppress_warning (var, OPT_Wuninitialized); } } else @@ -14624,7 +14625,7 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, gimplify_and_add (EH_FILTER_FAILURE (*expr_p), &failure); ehf = gimple_build_eh_filter (EH_FILTER_TYPES (*expr_p), failure); - gimple_set_no_warning (ehf, TREE_NO_WARNING (*expr_p)); + copy_warning (ehf, *expr_p); gimplify_seq_add_stmt (pre_p, ehf); ret = GS_ALL_DONE; break; -- cgit v1.1 From f6dde32b9d487dd6e343d0a1e1d1f60783f5e735 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Thu, 15 Jul 2021 10:17:06 +0200 Subject: gimplify: Fix endless recursion on volatile empty type reads/writes [PR101437] Andrew's recent change to optimize away during gimplification not just assignments of zero sized types, but also assignments of empty types, caused infinite recursion in the gimplifier. If such assignment is optimized away, we gimplify separately the to_p and from_p operands and throw away the result. When gimplifying the operand that is volatile, we run into the gimplifier code below, which has different handling for types with non-BLKmode mode, tries to gimplify those as vol.N = expr, and for BLKmode just throws those away. Zero sized types will always have BLKmode and so are fine, but for the non-BLKmode ones like struct S in the testcase, the vol.N = expr gimplification will reach again the gimplify_modify_expr code, see it is assignment of empty type and will gimplify again vol.N separately (non-volatile, so ok) and expr, on which it will recurse again. The following patch breaks that infinite recursion by ignoring bare volatile loads from empty types. If a volatile load or store for aggregates are supposed to be member-wise loads or stores, then there are no non-padding members in the empty types that should be copied and so it is probably ok. 2021-07-15 Jakub Jelinek PR middle-end/101437 * gimplify.c (gimplify_expr): Throw away volatile reads from empty types even if they have non-BLKmode TYPE_MODE. * gcc.c-torture/compile/pr101437.c: New test. --- gcc/gimplify.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'gcc/gimplify.c') diff --git a/gcc/gimplify.c b/gcc/gimplify.c index 75a4a9d..93a2121 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -15060,7 +15060,8 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, *expr_p = NULL; } else if (COMPLETE_TYPE_P (TREE_TYPE (*expr_p)) - && TYPE_MODE (TREE_TYPE (*expr_p)) != BLKmode) + && TYPE_MODE (TREE_TYPE (*expr_p)) != BLKmode + && !is_empty_type (TREE_TYPE (*expr_p))) { /* Historically, the compiler has treated a bare reference to a non-BLKmode volatile lvalue as forcing a load. */ -- cgit v1.1 From b136b7a78774107943fe94051c42b5a968a3ad3f Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Wed, 21 Jul 2021 09:45:02 +0200 Subject: openmp: Fix up omp_check_private [PR101535] The target data construct shouldn't affect omp_check_private, unless the decl there is privatized (use_device_* clauses). The routine had some code for that, but it just did continue; in a loop that looped only if the region type is one of selected 4 kinds, so effectively resulted in return false; instead of looping again. And not diagnosing lastprivate (or reduction etc.) on a variable that is private to containing parallel results in ICEs later on, as there is no original list item to which store the last result. The target construct is unclear as it has an implicit parallel region and it is not obvious if the data privatization clauses on the construct shall be treated as data privatization on the implicit parallel or just on the target. For now treat those as privatization on the implicit parallel, but treat map clauses as shared on the implicit parallel. 2021-07-21 Jakub Jelinek PR middle-end/101535 * gimplify.c (omp_check_private): Properly skip ORT_TARGET_DATA contexts in which decl isn't privatized and for ORT_TARGET return false if decl is mapped. * c-c++-common/gomp/pr101535-1.c: New test. * c-c++-common/gomp/pr101535-2.c: New test. --- gcc/gimplify.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) (limited to 'gcc/gimplify.c') diff --git a/gcc/gimplify.c b/gcc/gimplify.c index 93a2121..5d43f76 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -7798,7 +7798,13 @@ omp_check_private (struct gimplify_omp_ctx *ctx, tree decl, bool copyprivate) if ((ctx->region_type & (ORT_TARGET | ORT_TARGET_DATA)) != 0 && (n == NULL || (n->value & GOVD_DATA_SHARE_CLASS) == 0)) - continue; + { + if ((ctx->region_type & ORT_TARGET_DATA) != 0 + || n == NULL + || (n->value & GOVD_MAP) == 0) + continue; + return false; + } if (n != NULL) { @@ -7807,11 +7813,16 @@ omp_check_private (struct gimplify_omp_ctx *ctx, tree decl, bool copyprivate) return false; return (n->value & GOVD_SHARED) == 0; } + + if (ctx->region_type == ORT_WORKSHARE + || ctx->region_type == ORT_TASKGROUP + || ctx->region_type == ORT_SIMD + || ctx->region_type == ORT_ACC) + continue; + + break; } - while (ctx->region_type == ORT_WORKSHARE - || ctx->region_type == ORT_TASKGROUP - || ctx->region_type == ORT_SIMD - || ctx->region_type == ORT_ACC); + while (1); return false; } -- cgit v1.1 From a61f6afbee370785cf091fe46e2e022748528307 Mon Sep 17 00:00:00 2001 From: Thomas Schwinge Date: Wed, 21 Jul 2021 18:30:00 +0200 Subject: OpenACC 'nohost' clause Do not "compile a version of this procedure for the host". gcc/ * tree-core.h (omp_clause_code): Add 'OMP_CLAUSE_NOHOST'. * tree.c (omp_clause_num_ops, omp_clause_code_name, walk_tree_1): Handle it. * tree-pretty-print.c (dump_omp_clause): Likewise. * omp-general.c (oacc_verify_routine_clauses): Likewise. * gimplify.c (gimplify_scan_omp_clauses) (gimplify_adjust_omp_clauses): Likewise. * tree-nested.c (convert_nonlocal_omp_clauses) (convert_local_omp_clauses): Likewise. * omp-low.c (scan_sharing_clauses): Likewise. * omp-offload.c (execute_oacc_device_lower): Update. gcc/c-family/ * c-pragma.h (pragma_omp_clause): Add 'PRAGMA_OACC_CLAUSE_NOHOST'. gcc/c/ * c-parser.c (c_parser_omp_clause_name): Handle 'nohost'. (c_parser_oacc_all_clauses): Handle 'PRAGMA_OACC_CLAUSE_NOHOST'. (OACC_ROUTINE_CLAUSE_MASK): Add 'PRAGMA_OACC_CLAUSE_NOHOST'. * c-typeck.c (c_finish_omp_clauses): Handle 'OMP_CLAUSE_NOHOST'. gcc/cp/ * parser.c (cp_parser_omp_clause_name): Handle 'nohost'. (cp_parser_oacc_all_clauses): Handle 'PRAGMA_OACC_CLAUSE_NOHOST'. (OACC_ROUTINE_CLAUSE_MASK): Add 'PRAGMA_OACC_CLAUSE_NOHOST'. * pt.c (tsubst_omp_clauses): Handle 'OMP_CLAUSE_NOHOST'. * semantics.c (finish_omp_clauses): Likewise. gcc/fortran/ * dump-parse-tree.c (show_attr): Update. * gfortran.h (symbol_attribute): Add 'oacc_routine_nohost' member. (gfc_omp_clauses): Add 'nohost' member. * module.c (ab_attribute): Add 'AB_OACC_ROUTINE_NOHOST'. (attr_bits, mio_symbol_attribute): Update. * openmp.c (omp_mask2): Add 'OMP_CLAUSE_NOHOST'. (gfc_match_omp_clauses): Handle 'OMP_CLAUSE_NOHOST'. (OACC_ROUTINE_CLAUSES): Add 'OMP_CLAUSE_NOHOST'. (gfc_match_oacc_routine): Update. * trans-decl.c (add_attributes_to_decl): Update. * trans-openmp.c (gfc_trans_omp_clauses): Likewise. gcc/testsuite/ * c-c++-common/goacc/classify-routine-nohost.c: New file. * c-c++-common/goacc/classify-routine.c: Update. * c-c++-common/goacc/routine-2.c: Likewise. * c-c++-common/goacc/routine-nohost-1.c: New file. * c-c++-common/goacc/routine-nohost-2.c: Likewise. * g++.dg/goacc/template.C: Update. * gfortran.dg/goacc/classify-routine-nohost.f95: New file. * gfortran.dg/goacc/classify-routine.f95: Update. * gfortran.dg/goacc/pure-elemental-procedures-2.f90: Likewise. * gfortran.dg/goacc/routine-6.f90: Likewise. * gfortran.dg/goacc/routine-intrinsic-2.f: Likewise. * gfortran.dg/goacc/routine-module-1.f90: Likewise. * gfortran.dg/goacc/routine-module-2.f90: Likewise. * gfortran.dg/goacc/routine-module-3.f90: Likewise. * gfortran.dg/goacc/routine-module-mod-1.f90: Likewise. * gfortran.dg/goacc/routine-multiple-directives-1.f90: Likewise. * gfortran.dg/goacc/routine-multiple-directives-2.f90: Likewise. libgomp/ * testsuite/libgomp.oacc-c-c++-common/routine-nohost-1.c: New file. * testsuite/libgomp.oacc-c-c++-common/routine-nohost-2.c: Likewise. * testsuite/libgomp.oacc-c-c++-common/routine-nohost-2_2.c: Likewise. * testsuite/libgomp.oacc-fortran/routine-nohost-1.f90: Likewise. Co-Authored-By: Joseph Myers Co-Authored-By: Cesar Philippidis --- gcc/gimplify.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'gcc/gimplify.c') diff --git a/gcc/gimplify.c b/gcc/gimplify.c index 5d43f76..21ff32e 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -10310,6 +10310,7 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p, } break; + case OMP_CLAUSE_NOHOST: default: gcc_unreachable (); } @@ -11247,6 +11248,7 @@ gimplify_adjust_omp_clauses (gimple_seq *pre_p, gimple_seq body, tree *list_p, case OMP_CLAUSE_EXCLUSIVE: break; + case OMP_CLAUSE_NOHOST: default: gcc_unreachable (); } -- cgit v1.1 From d0befed793b94f3f407be44e6f69f81a02f5f073 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Thu, 12 Aug 2021 22:41:17 +0200 Subject: openmp: Add support for OpenMP 5.1 masked construct This construct has been introduced as a replacement for master construct, but unlike that construct is slightly more general, has an optional clause which allows to choose which thread will be the one running the region, it can be some other thread than the master (primary) thread with number 0, or it could be no threads or multiple threads (then of course one needs to be careful about data races). It is way too early to deprecate the master construct though, we don't even have OpenMP 5.0 fully implemented, it has been deprecated in 5.1, will be also in 5.2 and removed in 6.0. But even then it will likely be a good idea to just -Wdeprecated warn about it and still accept it. The patch also contains something I should have done much earlier, for clauses that accept some integral expression where we only care about the value, forces during gimplification that value into either a min invariant (as before), SSA_NAME or a fresh temporary, but never e.g. a user VAR_DECL, so that for those clauses we don't need to worry about adjusting it. 2021-08-12 Jakub Jelinek gcc/ * tree.def (OMP_MASKED): New tree code. * tree-core.h (enum omp_clause_code): Add OMP_CLAUSE_FILTER. * tree.h (OMP_MASKED_BODY, OMP_MASKED_CLAUSES, OMP_MASKED_COMBINED, OMP_CLAUSE_FILTER_EXPR): Define. * tree.c (omp_clause_num_ops): Add OMP_CLAUSE_FILTER entry. (omp_clause_code_name): Likewise. (walk_tree_1): Handle OMP_CLAUSE_FILTER. * tree-nested.c (convert_nonlocal_omp_clauses, convert_local_omp_clauses): Handle OMP_CLAUSE_FILTER. (convert_nonlocal_reference_stmt, convert_local_reference_stmt, convert_gimple_call): Handle GIMPLE_OMP_MASTER. * tree-pretty-print.c (dump_omp_clause): Handle OMP_CLAUSE_FILTER. (dump_generic_node): Handle OMP_MASTER. * gimple.def (GIMPLE_OMP_MASKED): New gimple code. * gimple.c (gimple_build_omp_masked): New function. (gimple_copy): Handle GIMPLE_OMP_MASKED. * gimple.h (gimple_build_omp_masked): Declare. (gimple_has_substatements): Handle GIMPLE_OMP_MASKED. (gimple_omp_masked_clauses, gimple_omp_masked_clauses_ptr, gimple_omp_masked_set_clauses): New inline functions. (CASE_GIMPLE_OMP): Add GIMPLE_OMP_MASKED. * gimple-pretty-print.c (dump_gimple_omp_masked): New function. (pp_gimple_stmt_1): Handle GIMPLE_OMP_MASKED. * gimple-walk.c (walk_gimple_stmt): Likewise. * gimple-low.c (lower_stmt): Likewise. * gimplify.c (is_gimple_stmt): Handle OMP_MASTER. (gimplify_scan_omp_clauses): Handle OMP_CLAUSE_FILTER. For clauses that take one expression rather than decl or constant, force gimplification of that into a SSA_NAME or temporary unless min invariant. (gimplify_adjust_omp_clauses): Handle OMP_CLAUSE_FILTER. (gimplify_expr): Handle OMP_MASKED. * tree-inline.c (remap_gimple_stmt): Handle GIMPLE_OMP_MASKED. (estimate_num_insns): Likewise. * omp-low.c (scan_sharing_clauses): Handle OMP_CLAUSE_FILTER. (check_omp_nesting_restrictions): Handle GIMPLE_OMP_MASKED. Adjust diagnostics for existence of masked construct. (scan_omp_1_stmt, lower_omp_master, lower_omp_1, diagnose_sb_1, diagnose_sb_2): Handle GIMPLE_OMP_MASKED. * omp-expand.c (expand_omp_synch, expand_omp, omp_make_gimple_edges): Likewise. gcc/c-family/ * c-pragma.h (enum pragma_kind): Add PRAGMA_OMP_MASKED. (enum pragma_omp_clause): Add PRAGMA_OMP_CLAUSE_FILTER. * c-pragma.c (omp_pragmas_simd): Add masked construct. * c-common.h (enum c_omp_clause_split): Add C_OMP_CLAUSE_SPLIT_MASKED enumerator. (c_finish_omp_masked): Declare. * c-omp.c (c_finish_omp_masked): New function. (c_omp_split_clauses): Handle combined masked constructs. gcc/c/ * c-parser.c (c_parser_omp_clause_name): Parse filter clause name. (c_parser_omp_clause_filter): New function. (c_parser_omp_all_clauses): Handle PRAGMA_OMP_CLAUSE_FILTER. (OMP_MASKED_CLAUSE_MASK): Define. (c_parser_omp_masked): New function. (c_parser_omp_parallel): Handle parallel masked. (c_parser_omp_construct): Handle PRAGMA_OMP_MASKED. * c-typeck.c (c_finish_omp_clauses): Handle OMP_CLAUSE_FILTER. gcc/cp/ * parser.c (cp_parser_omp_clause_name): Parse filter clause name. (cp_parser_omp_clause_filter): New function. (cp_parser_omp_all_clauses): Handle PRAGMA_OMP_CLAUSE_FILTER. (OMP_MASKED_CLAUSE_MASK): Define. (cp_parser_omp_masked): New function. (cp_parser_omp_parallel): Handle parallel masked. (cp_parser_omp_construct, cp_parser_pragma): Handle PRAGMA_OMP_MASKED. * semantics.c (finish_omp_clauses): Handle OMP_CLAUSE_FILTER. * pt.c (tsubst_omp_clauses): Likewise. (tsubst_expr): Handle OMP_MASKED. gcc/testsuite/ * c-c++-common/gomp/clauses-1.c (bar): Add tests for combined masked constructs with clauses. * c-c++-common/gomp/clauses-5.c (foo): Add testcase for filter clause. * c-c++-common/gomp/clause-dups-1.c (f1): Likewise. * c-c++-common/gomp/masked-1.c: New test. * c-c++-common/gomp/masked-2.c: New test. * c-c++-common/gomp/masked-combined-1.c: New test. * c-c++-common/gomp/masked-combined-2.c: New test. * c-c++-common/goacc/uninit-if-clause.c: Remove xfails. * g++.dg/gomp/block-11.C: New test. * g++.dg/gomp/tpl-masked-1.C: New test. * g++.dg/gomp/attrs-1.C (bar): Add tests for masked construct and combined masked constructs with clauses in attribute syntax. * g++.dg/gomp/attrs-2.C (bar): Likewise. * gcc.dg/gomp/nesting-1.c (f1, f2): Add tests for masked construct nesting. * gfortran.dg/goacc/host_data-tree.f95: Allow also SSA_NAMEs in if clause. * gfortran.dg/goacc/kernels-tree.f95: Likewise. libgomp/ * testsuite/libgomp.c-c++-common/masked-1.c: New test. --- gcc/gimplify.c | 31 ++++++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) (limited to 'gcc/gimplify.c') diff --git a/gcc/gimplify.c b/gcc/gimplify.c index 21ff32e..eadbf83 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -5632,6 +5632,7 @@ is_gimple_stmt (tree t) case OMP_SECTION: case OMP_SINGLE: case OMP_MASTER: + case OMP_MASKED: case OMP_TASKGROUP: case OMP_ORDERED: case OMP_CRITICAL: @@ -10102,6 +10103,7 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p, case OMP_CLAUSE_PRIORITY: case OMP_CLAUSE_GRAINSIZE: case OMP_CLAUSE_NUM_TASKS: + case OMP_CLAUSE_FILTER: case OMP_CLAUSE_HINT: case OMP_CLAUSE_ASYNC: case OMP_CLAUSE_WAIT: @@ -10110,9 +10112,20 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p, case OMP_CLAUSE_VECTOR_LENGTH: case OMP_CLAUSE_WORKER: case OMP_CLAUSE_VECTOR: - if (gimplify_expr (&OMP_CLAUSE_OPERAND (c, 0), pre_p, NULL, - is_gimple_val, fb_rvalue) == GS_ERROR) - remove = true; + if (OMP_CLAUSE_OPERAND (c, 0) + && !is_gimple_min_invariant (OMP_CLAUSE_OPERAND (c, 0))) + { + if (error_operand_p (OMP_CLAUSE_OPERAND (c, 0))) + { + remove = true; + break; + } + /* All these clauses care about value, not a particular decl, + so try to force it into a SSA_NAME or fresh temporary. */ + OMP_CLAUSE_OPERAND (c, 0) + = get_initialized_tmp_var (OMP_CLAUSE_OPERAND (c, 0), + pre_p, NULL, true); + } break; case OMP_CLAUSE_GANG: @@ -11222,6 +11235,7 @@ gimplify_adjust_omp_clauses (gimple_seq *pre_p, gimple_seq body, tree *list_p, case OMP_CLAUSE_NOGROUP: case OMP_CLAUSE_THREADS: case OMP_CLAUSE_SIMD: + case OMP_CLAUSE_FILTER: case OMP_CLAUSE_HINT: case OMP_CLAUSE_DEFAULTMAP: case OMP_CLAUSE_ORDER: @@ -14766,6 +14780,7 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, case OMP_SECTION: case OMP_MASTER: + case OMP_MASKED: case OMP_ORDERED: case OMP_CRITICAL: case OMP_SCAN: @@ -14788,6 +14803,15 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, case OMP_ORDERED: g = gimplify_omp_ordered (*expr_p, body); break; + case OMP_MASKED: + gimplify_scan_omp_clauses (&OMP_MASKED_CLAUSES (*expr_p), + pre_p, ORT_WORKSHARE, OMP_MASKED); + gimplify_adjust_omp_clauses (pre_p, body, + &OMP_MASKED_CLAUSES (*expr_p), + OMP_MASKED); + g = gimple_build_omp_masked (body, + OMP_MASKED_CLAUSES (*expr_p)); + break; case OMP_CRITICAL: gimplify_scan_omp_clauses (&OMP_CRITICAL_CLAUSES (*expr_p), pre_p, ORT_WORKSHARE, OMP_CRITICAL); @@ -15161,6 +15185,7 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, && code != OMP_FOR && code != OACC_LOOP && code != OMP_MASTER + && code != OMP_MASKED && code != OMP_TASKGROUP && code != OMP_ORDERED && code != OMP_PARALLEL -- cgit v1.1 From e45483c7c4badc4bf2d6ced22360ce1ab172967f Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Tue, 17 Aug 2021 09:30:09 +0200 Subject: openmp: Implement OpenMP 5.1 scope construct This patch implements the OpenMP 5.1 scope construct, which is similar to worksharing constructs in many regards, but isn't one of them. The body of the construct is encountered by all threads though, it can be nested in itself or intermixed with taskgroup and worksharing etc. constructs can appear inside of it (but it can't be nested in worksharing etc. constructs). The main purpose of the construct is to allow reductions (normal and task ones) without the need to close the parallel and reopen another one. If it doesn't have task reductions, it can be implemented without any new library support, with nowait it just does the privatizations at the start if any and reductions before the end of the body, with without nowait emits a normal GOMP_barrier{,_cancel} at the end too. For task reductions, we need to ensure only one thread initializes the task reduction library data structures and other threads copy from that, so a new GOMP_scope_start routine is added to the library for that. It acts as if the start of the scope construct is a nowait worksharing construct (that is ok, it can't be nested in other worksharing constructs and all threads need to encounter the start in the same order) which does the task reduction initialization, but as the body can have other scope constructs and/or worksharing constructs, that is all where we use this dummy worksharing construct. With task reductions, the construct must not have nowait and ends with a GOMP_barrier{,_cancel}, followed by task reductions followed by GOMP_workshare_task_reduction_unregister. Only C/C++ FE support is done. 2021-08-17 Jakub Jelinek gcc/ * tree.def (OMP_SCOPE): New tree code. * tree.h (OMP_SCOPE_BODY, OMP_SCOPE_CLAUSES): Define. * tree-nested.c (convert_nonlocal_reference_stmt, convert_local_reference_stmt, convert_gimple_call): Handle GIMPLE_OMP_SCOPE. * tree-pretty-print.c (dump_generic_node): Handle OMP_SCOPE. * gimple.def (GIMPLE_OMP_SCOPE): New gimple code. * gimple.c (gimple_build_omp_scope): New function. (gimple_copy): Handle GIMPLE_OMP_SCOPE. * gimple.h (gimple_build_omp_scope): Declare. (gimple_has_substatements): Handle GIMPLE_OMP_SCOPE. (gimple_omp_scope_clauses, gimple_omp_scope_clauses_ptr, gimple_omp_scope_set_clauses): New inline functions. (CASE_GIMPLE_OMP): Add GIMPLE_OMP_SCOPE. * gimple-pretty-print.c (dump_gimple_omp_scope): New function. (pp_gimple_stmt_1): Handle GIMPLE_OMP_SCOPE. * gimple-walk.c (walk_gimple_stmt): Likewise. * gimple-low.c (lower_stmt): Likewise. * gimplify.c (is_gimple_stmt): Handle OMP_MASTER. (gimplify_scan_omp_clauses): For task reductions, handle OMP_SCOPE like ORT_WORKSHARE constructs. Adjust diagnostics for % allowing task reductions. Reject inscan reductions on scope. (omp_find_stores_stmt): Handle GIMPLE_OMP_SCOPE. (gimplify_omp_workshare, gimplify_expr): Handle OMP_SCOPE. * tree-inline.c (remap_gimple_stmt): Handle GIMPLE_OMP_SCOPE. (estimate_num_insns): Likewise. * omp-low.c (build_outer_var_ref): Look through GIMPLE_OMP_SCOPE contexts if var isn't privatized there. (check_omp_nesting_restrictions): Handle GIMPLE_OMP_SCOPE. (scan_omp_1_stmt): Likewise. (maybe_add_implicit_barrier_cancel): Look through outer scope constructs. (lower_omp_scope): New function. (lower_omp_task_reductions): Handle OMP_SCOPE. (lower_omp_1): Handle GIMPLE_OMP_SCOPE. (diagnose_sb_1, diagnose_sb_2): Likewise. * omp-expand.c (expand_omp_single): Support also GIMPLE_OMP_SCOPE. (expand_omp): Handle GIMPLE_OMP_SCOPE. (omp_make_gimple_edges): Likewise. * omp-builtins.def (BUILT_IN_GOMP_SCOPE_START): New built-in. gcc/c-family/ * c-pragma.h (enum pragma_kind): Add PRAGMA_OMP_SCOPE. * c-pragma.c (omp_pragmas): Add scope construct. * c-omp.c (omp_directives): Uncomment scope directive entry. gcc/c/ * c-parser.c (OMP_SCOPE_CLAUSE_MASK): Define. (c_parser_omp_scope): New function. (c_parser_omp_construct): Handle PRAGMA_OMP_SCOPE. gcc/cp/ * parser.c (OMP_SCOPE_CLAUSE_MASK): Define. (cp_parser_omp_scope): New function. (cp_parser_omp_construct, cp_parser_pragma): Handle PRAGMA_OMP_SCOPE. * pt.c (tsubst_expr): Handle OMP_SCOPE. gcc/testsuite/ * c-c++-common/gomp/nesting-2.c (foo): Add scope and masked construct tests. * c-c++-common/gomp/scan-1.c (f3): Add scope construct test.. * c-c++-common/gomp/cancel-1.c (f2): Add scope and masked construct tests. * c-c++-common/gomp/reduction-task-2.c (bar): Add scope construct test. Adjust diagnostics for the addition of scope. * c-c++-common/gomp/loop-1.c (f5): Add master, masked and scope construct tests. * c-c++-common/gomp/clause-dups-1.c (f1): Add scope construct test. * gcc.dg/gomp/nesting-1.c (f1, f2, f3): Add scope construct tests. * c-c++-common/gomp/scope-1.c: New test. * c-c++-common/gomp/scope-2.c: New test. * g++.dg/gomp/attrs-1.C (bar): Add scope construct tests. * g++.dg/gomp/attrs-2.C (bar): Likewise. * gfortran.dg/gomp/reduction4.f90: Adjust expected diagnostics. * gfortran.dg/gomp/reduction7.f90: Likewise. libgomp/ * Makefile.am (libgomp_la_SOURCES): Add scope.c * Makefile.in: Regenerated. * libgomp_g.h (GOMP_scope_start): Declare. * libgomp.map: Add GOMP_scope_start@@GOMP_5.1. * scope.c: New file. * testsuite/libgomp.c-c++-common/scope-1.c: New test. * testsuite/libgomp.c-c++-common/task-reduction-16.c: New test. --- gcc/gimplify.c | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) (limited to 'gcc/gimplify.c') diff --git a/gcc/gimplify.c b/gcc/gimplify.c index eadbf83..070d0e4 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -5628,6 +5628,7 @@ is_gimple_stmt (tree t) case OMP_LOOP: case OACC_LOOP: case OMP_SCAN: + case OMP_SCOPE: case OMP_SECTIONS: case OMP_SECTION: case OMP_SINGLE: @@ -8866,7 +8867,7 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p, case OMP_CLAUSE_REDUCTION: if (OMP_CLAUSE_REDUCTION_TASK (c)) { - if (region_type == ORT_WORKSHARE) + if (region_type == ORT_WORKSHARE || code == OMP_SCOPE) { if (nowait == -1) nowait = omp_find_clause (*list_p, @@ -8885,8 +8886,8 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p, { error_at (OMP_CLAUSE_LOCATION (c), "invalid % reduction modifier on construct " - "other than %, %qs or %", - lang_GNU_Fortran () ? "do" : "for"); + "other than %, %qs, % or " + "%", lang_GNU_Fortran () ? "do" : "for"); OMP_CLAUSE_REDUCTION_TASK (c) = 0; } } @@ -8917,6 +8918,12 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p, "%qs construct", "taskloop"); OMP_CLAUSE_REDUCTION_INSCAN (c) = 0; break; + case OMP_SCOPE: + error_at (OMP_CLAUSE_LOCATION (c), + "% % clause on " + "%qs construct", "scope"); + OMP_CLAUSE_REDUCTION_INSCAN (c) = 0; + break; default: break; } @@ -10453,6 +10460,7 @@ omp_find_stores_stmt (gimple_stmt_iterator *gsi_p, case GIMPLE_OMP_TASK: case GIMPLE_OMP_SECTIONS: case GIMPLE_OMP_SINGLE: + case GIMPLE_OMP_SCOPE: case GIMPLE_OMP_TARGET: case GIMPLE_OMP_TEAMS: case GIMPLE_OMP_CRITICAL: @@ -13375,6 +13383,9 @@ gimplify_omp_workshare (tree *expr_p, gimple_seq *pre_p) case OMP_SINGLE: ort = ORT_WORKSHARE; break; + case OMP_SCOPE: + ort = ORT_TASKGROUP; + break; case OMP_TARGET: ort = OMP_TARGET_COMBINED (expr) ? ORT_COMBINED_TARGET : ORT_TARGET; break; @@ -13487,6 +13498,9 @@ gimplify_omp_workshare (tree *expr_p, gimple_seq *pre_p) case OMP_SINGLE: stmt = gimple_build_omp_single (body, OMP_CLAUSES (expr)); break; + case OMP_SCOPE: + stmt = gimple_build_omp_scope (body, OMP_CLAUSES (expr)); + break; case OMP_TARGET: stmt = gimple_build_omp_target (body, GF_OMP_TARGET_KIND_REGION, OMP_CLAUSES (expr)); @@ -14759,6 +14773,7 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, case OACC_KERNELS: case OACC_PARALLEL: case OACC_SERIAL: + case OMP_SCOPE: case OMP_SECTIONS: case OMP_SINGLE: case OMP_TARGET: @@ -15192,7 +15207,8 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, && code != OMP_SCAN && code != OMP_SECTIONS && code != OMP_SECTION - && code != OMP_SINGLE); + && code != OMP_SINGLE + && code != OMP_SCOPE); } #endif -- cgit v1.1 From 03be3cfeef7b3811acb6c4a8da2fc5c1e25d3e4c Mon Sep 17 00:00:00 2001 From: Marcel Vollweiler Date: Tue, 31 Aug 2021 06:09:40 -0700 Subject: Add support for device-modifiers for 'omp target device'. 'device_num' and 'ancestor' are now parsed on target device constructs for C, C++, and Fortran (see OpenMP specification 5.0, p. 170). When 'ancestor' is used, then 'sorry, not supported' is output. Moreover, the restrictions for 'ancestor' are implemented (see OpenMP specification 5.0, p. 174f). gcc/c/ChangeLog: * c-parser.c (c_parser_omp_clause_device): Parse device-modifiers 'device_num' and 'ancestor' in 'target device' clauses. gcc/cp/ChangeLog: * parser.c (cp_parser_omp_clause_device): Parse device-modifiers 'device_num' and 'ancestor' in 'target device' clauses. * semantics.c (finish_omp_clauses): Error handling. Constant device ids must evaluate to '1' if 'ancestor' is used. gcc/fortran/ChangeLog: * gfortran.h: Add variable for 'ancestor' in struct gfc_omp_clauses. * openmp.c (gfc_match_omp_clauses): Parse device-modifiers 'device_num' and 'ancestor' in 'target device' clauses. * trans-openmp.c (gfc_trans_omp_clauses): Set OMP_CLAUSE_DEVICE_ANCESTOR. gcc/ChangeLog: * gimplify.c (gimplify_scan_omp_clauses): Error handling. 'ancestor' only allowed on target constructs and only with particular other clauses. * omp-expand.c (expand_omp_target): Output of 'sorry, not supported' if 'ancestor' is used. * omp-low.c (check_omp_nesting_restrictions): Error handling. No nested OpenMP structs when 'ancestor' is used. (scan_omp_1_stmt): No usage of OpenMP runtime routines in a target region when 'ancestor' is used. * tree-pretty-print.c (dump_omp_clause): Append 'ancestor'. * tree.h (OMP_CLAUSE_DEVICE_ANCESTOR): Define macro. gcc/testsuite/ChangeLog: * c-c++-common/gomp/target-device-1.c: New test. * c-c++-common/gomp/target-device-2.c: New test. * c-c++-common/gomp/target-device-ancestor-1.c: New test. * c-c++-common/gomp/target-device-ancestor-2.c: New test. * c-c++-common/gomp/target-device-ancestor-3.c: New test. * c-c++-common/gomp/target-device-ancestor-4.c: New test. * gfortran.dg/gomp/target-device-1.f90: New test. * gfortran.dg/gomp/target-device-2.f90: New test. * gfortran.dg/gomp/target-device-ancestor-1.f90: New test. * gfortran.dg/gomp/target-device-ancestor-2.f90: New test. * gfortran.dg/gomp/target-device-ancestor-3.f90: New test. * gfortran.dg/gomp/target-device-ancestor-4.f90: New test. --- gcc/gimplify.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) (limited to 'gcc/gimplify.c') diff --git a/gcc/gimplify.c b/gcc/gimplify.c index 070d0e4..400b6f0 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -10107,6 +10107,38 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p, case OMP_CLAUSE_THREAD_LIMIT: case OMP_CLAUSE_DIST_SCHEDULE: case OMP_CLAUSE_DEVICE: + if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEVICE + && OMP_CLAUSE_DEVICE_ANCESTOR (c)) + { + if (code != OMP_TARGET) + { + error_at (OMP_CLAUSE_LOCATION (c), + "% clause with % is only " + "allowed on % construct"); + remove = true; + break; + } + + tree clauses = *orig_list_p; + for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses)) + if (OMP_CLAUSE_CODE (clauses) != OMP_CLAUSE_DEVICE + && OMP_CLAUSE_CODE (clauses) != OMP_CLAUSE_FIRSTPRIVATE + && OMP_CLAUSE_CODE (clauses) != OMP_CLAUSE_PRIVATE + && OMP_CLAUSE_CODE (clauses) != OMP_CLAUSE_DEFAULTMAP + && OMP_CLAUSE_CODE (clauses) != OMP_CLAUSE_MAP + ) + { + error_at (OMP_CLAUSE_LOCATION (c), + "with %, only the %, " + "%, %, %, " + "and % clauses may appear on the " + "construct"); + remove = true; + break; + } + } + /* Fall through. */ + case OMP_CLAUSE_PRIORITY: case OMP_CLAUSE_GRAINSIZE: case OMP_CLAUSE_NUM_TASKS: -- cgit v1.1 From 22e6b3270068faab64778c016f4b04f787120661 Mon Sep 17 00:00:00 2001 From: Thomas Schwinge Date: Wed, 29 May 2019 18:59:46 +0200 Subject: [OMP] Standardize on 'omp_privatize_by_reference' ... instead of 'omp_is_reference' vs. 'lang_hooks.decls.omp_privatize_by_reference'. gcc/ * omp-general.h (omp_is_reference): Rename to... (omp_privatize_by_reference): ... this. Adjust all users... * omp-general.c: ... here, ... * gimplify.c: ... here, ... * omp-expand.c: ... here, ... * omp-low.c: ... here. --- gcc/gimplify.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'gcc/gimplify.c') diff --git a/gcc/gimplify.c b/gcc/gimplify.c index 400b6f0..99d1c7fc 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -1831,7 +1831,8 @@ gimplify_decl_expr (tree *stmt_p, gimple_seq *seq_p) gimplify_and_add (init, seq_p); ggc_free (init); /* Clear TREE_READONLY if we really have an initialization. */ - if (!DECL_INITIAL (decl) && !omp_is_reference (decl)) + if (!DECL_INITIAL (decl) + && !omp_privatize_by_reference (decl)) TREE_READONLY (decl) = 0; } else @@ -7064,7 +7065,7 @@ omp_add_variable (struct gimplify_omp_ctx *ctx, tree decl, unsigned int flags) omp_notice_variable (ctx, TYPE_SIZE_UNIT (TREE_TYPE (decl)), true); } else if ((flags & (GOVD_MAP | GOVD_LOCAL)) == 0 - && lang_hooks.decls.omp_privatize_by_reference (decl)) + && omp_privatize_by_reference (decl)) { omp_firstprivatize_type_sizes (ctx, TREE_TYPE (decl)); @@ -7322,7 +7323,7 @@ oacc_default_clause (struct gimplify_omp_ctx *ctx, tree decl, unsigned flags) bool declared = is_oacc_declared (decl); tree type = TREE_TYPE (decl); - if (lang_hooks.decls.omp_privatize_by_reference (decl)) + if (omp_privatize_by_reference (decl)) type = TREE_TYPE (type); /* For Fortran COMMON blocks, only used variables in those blocks are @@ -7586,7 +7587,7 @@ omp_notice_variable (struct gimplify_omp_ctx *ctx, tree decl, bool in_code) tree type = TREE_TYPE (decl); if (gimplify_omp_ctxp->target_firstprivatize_array_bases - && lang_hooks.decls.omp_privatize_by_reference (decl)) + && omp_privatize_by_reference (decl)) type = TREE_TYPE (type); if (!lang_hooks.types.omp_mappable_type (type)) { @@ -7660,7 +7661,7 @@ omp_notice_variable (struct gimplify_omp_ctx *ctx, tree decl, bool in_code) n2 = splay_tree_lookup (ctx->variables, (splay_tree_key) t); n2->value |= GOVD_SEEN; } - else if (lang_hooks.decls.omp_privatize_by_reference (decl) + else if (omp_privatize_by_reference (decl) && TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (decl))) && (TREE_CODE (TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (decl)))) != INTEGER_CST)) @@ -7785,7 +7786,7 @@ omp_check_private (struct gimplify_omp_ctx *ctx, tree decl, bool copyprivate) if (copyprivate) return true; - if (lang_hooks.decls.omp_privatize_by_reference (decl)) + if (omp_privatize_by_reference (decl)) return false; /* Treat C++ privatized non-static data members outside @@ -10405,7 +10406,7 @@ omp_shared_to_firstprivate_optimizable_decl_p (tree decl) HOST_WIDE_INT len = int_size_in_bytes (type); if (len == -1 || len > 4 * POINTER_SIZE / BITS_PER_UNIT) return false; - if (lang_hooks.decls.omp_privatize_by_reference (decl)) + if (omp_privatize_by_reference (decl)) return false; return true; } @@ -10730,7 +10731,7 @@ gimplify_adjust_omp_clauses_1 (splay_tree_node n, void *data) OMP_CLAUSE_CHAIN (clause) = nc; } else if (gimplify_omp_ctxp->target_firstprivatize_array_bases - && lang_hooks.decls.omp_privatize_by_reference (decl)) + && omp_privatize_by_reference (decl)) { OMP_CLAUSE_DECL (clause) = build_simple_mem_ref (decl); OMP_CLAUSE_SIZE (clause) -- cgit v1.1 From a25e0b5e6ac8a77a71c229e0a7b744603365b0e9 Mon Sep 17 00:00:00 2001 From: qing zhao Date: Thu, 9 Sep 2021 15:44:49 -0700 Subject: Add -ftrivial-auto-var-init option and uninitialized variable attribute. Initialize automatic variables with either a pattern or with zeroes to increase the security and predictability of a program by preventing uninitialized memory disclosure and use. GCC still considers an automatic variable that doesn't have an explicit initializer as uninitialized, -Wuninitialized will still report warning messages on such automatic variables. With this option, GCC will also initialize any padding of automatic variables that have structure or union types to zeroes. You can control this behavior for a specific variable by using the variable attribute "uninitialized" to control runtime overhead. gcc/ChangeLog: 2021-09-09 qing zhao * builtins.c (expand_builtin_memset): Make external visible. * builtins.h (expand_builtin_memset): Declare extern. * common.opt (ftrivial-auto-var-init=): New option. * doc/extend.texi: Document the uninitialized attribute. * doc/invoke.texi: Document -ftrivial-auto-var-init. * flag-types.h (enum auto_init_type): New enumerated type auto_init_type. * gimple-fold.c (clear_padding_type): Add one new parameter. (clear_padding_union): Likewise. (clear_padding_emit_loop): Likewise. (clear_type_padding_in_mask): Likewise. (gimple_fold_builtin_clear_padding): Handle this new parameter. * gimplify.c (gimple_add_init_for_auto_var): New function. (gimple_add_padding_init_for_auto_var): New function. (is_var_need_auto_init): New function. (gimplify_decl_expr): Add initialization to automatic variables per users' requests. (gimplify_call_expr): Add one new parameter for call to __builtin_clear_padding. (gimplify_init_constructor): Add padding initialization in the end. * internal-fn.c (INIT_PATTERN_VALUE): New macro. (expand_DEFERRED_INIT): New function. * internal-fn.def (DEFERRED_INIT): New internal function. * tree-cfg.c (verify_gimple_call): Verify calls to .DEFERRED_INIT. * tree-sra.c (generate_subtree_deferred_init): New function. (scan_function): Avoid setting cannot_scalarize_away_bitmap for calls to .DEFERRED_INIT. (sra_modify_deferred_init): New function. (sra_modify_function_body): Handle calls to DEFERRED_INIT specially. * tree-ssa-structalias.c (find_func_aliases_for_call): Likewise. * tree-ssa-uninit.c (warn_uninit): Handle calls to DEFERRED_INIT specially. (check_defs): Likewise. (warn_uninitialized_vars): Likewise. * tree-ssa.c (ssa_undefined_value_p): Likewise. * tree.c (build_common_builtin_nodes): Build tree node for BUILT_IN_CLEAR_PADDING when needed. gcc/c-family/ChangeLog: 2021-09-09 qing zhao * c-attribs.c (handle_uninitialized_attribute): New function. (c_common_attribute_table): Add "uninitialized" attribute. gcc/testsuite/ChangeLog: 2021-09-09 qing zhao * c-c++-common/auto-init-1.c: New test. * c-c++-common/auto-init-10.c: New test. * c-c++-common/auto-init-11.c: New test. * c-c++-common/auto-init-12.c: New test. * c-c++-common/auto-init-13.c: New test. * c-c++-common/auto-init-14.c: New test. * c-c++-common/auto-init-15.c: New test. * c-c++-common/auto-init-16.c: New test. * c-c++-common/auto-init-2.c: New test. * c-c++-common/auto-init-3.c: New test. * c-c++-common/auto-init-4.c: New test. * c-c++-common/auto-init-5.c: New test. * c-c++-common/auto-init-6.c: New test. * c-c++-common/auto-init-7.c: New test. * c-c++-common/auto-init-8.c: New test. * c-c++-common/auto-init-9.c: New test. * c-c++-common/auto-init-esra.c: New test. * c-c++-common/auto-init-padding-1.c: New test. * c-c++-common/auto-init-padding-2.c: New test. * c-c++-common/auto-init-padding-3.c: New test. * g++.dg/auto-init-uninit-pred-1_a.C: New test. * g++.dg/auto-init-uninit-pred-2_a.C: New test. * g++.dg/auto-init-uninit-pred-3_a.C: New test. * g++.dg/auto-init-uninit-pred-4.C: New test. * gcc.dg/auto-init-sra-1.c: New test. * gcc.dg/auto-init-sra-2.c: New test. * gcc.dg/auto-init-uninit-1.c: New test. * gcc.dg/auto-init-uninit-12.c: New test. * gcc.dg/auto-init-uninit-13.c: New test. * gcc.dg/auto-init-uninit-14.c: New test. * gcc.dg/auto-init-uninit-15.c: New test. * gcc.dg/auto-init-uninit-16.c: New test. * gcc.dg/auto-init-uninit-17.c: New test. * gcc.dg/auto-init-uninit-18.c: New test. * gcc.dg/auto-init-uninit-19.c: New test. * gcc.dg/auto-init-uninit-2.c: New test. * gcc.dg/auto-init-uninit-20.c: New test. * gcc.dg/auto-init-uninit-21.c: New test. * gcc.dg/auto-init-uninit-22.c: New test. * gcc.dg/auto-init-uninit-23.c: New test. * gcc.dg/auto-init-uninit-24.c: New test. * gcc.dg/auto-init-uninit-25.c: New test. * gcc.dg/auto-init-uninit-26.c: New test. * gcc.dg/auto-init-uninit-3.c: New test. * gcc.dg/auto-init-uninit-34.c: New test. * gcc.dg/auto-init-uninit-36.c: New test. * gcc.dg/auto-init-uninit-37.c: New test. * gcc.dg/auto-init-uninit-4.c: New test. * gcc.dg/auto-init-uninit-5.c: New test. * gcc.dg/auto-init-uninit-6.c: New test. * gcc.dg/auto-init-uninit-8.c: New test. * gcc.dg/auto-init-uninit-9.c: New test. * gcc.dg/auto-init-uninit-A.c: New test. * gcc.dg/auto-init-uninit-B.c: New test. * gcc.dg/auto-init-uninit-C.c: New test. * gcc.dg/auto-init-uninit-H.c: New test. * gcc.dg/auto-init-uninit-I.c: New test. * gcc.target/aarch64/auto-init-1.c: New test. * gcc.target/aarch64/auto-init-2.c: New test. * gcc.target/aarch64/auto-init-3.c: New test. * gcc.target/aarch64/auto-init-4.c: New test. * gcc.target/aarch64/auto-init-5.c: New test. * gcc.target/aarch64/auto-init-6.c: New test. * gcc.target/aarch64/auto-init-7.c: New test. * gcc.target/aarch64/auto-init-8.c: New test. * gcc.target/aarch64/auto-init-padding-1.c: New test. * gcc.target/aarch64/auto-init-padding-10.c: New test. * gcc.target/aarch64/auto-init-padding-11.c: New test. * gcc.target/aarch64/auto-init-padding-12.c: New test. * gcc.target/aarch64/auto-init-padding-2.c: New test. * gcc.target/aarch64/auto-init-padding-3.c: New test. * gcc.target/aarch64/auto-init-padding-4.c: New test. * gcc.target/aarch64/auto-init-padding-5.c: New test. * gcc.target/aarch64/auto-init-padding-6.c: New test. * gcc.target/aarch64/auto-init-padding-7.c: New test. * gcc.target/aarch64/auto-init-padding-8.c: New test. * gcc.target/aarch64/auto-init-padding-9.c: New test. * gcc.target/i386/auto-init-1.c: New test. * gcc.target/i386/auto-init-2.c: New test. * gcc.target/i386/auto-init-21.c: New test. * gcc.target/i386/auto-init-22.c: New test. * gcc.target/i386/auto-init-23.c: New test. * gcc.target/i386/auto-init-24.c: New test. * gcc.target/i386/auto-init-3.c: New test. * gcc.target/i386/auto-init-4.c: New test. * gcc.target/i386/auto-init-5.c: New test. * gcc.target/i386/auto-init-6.c: New test. * gcc.target/i386/auto-init-7.c: New test. * gcc.target/i386/auto-init-8.c: New test. * gcc.target/i386/auto-init-padding-1.c: New test. * gcc.target/i386/auto-init-padding-10.c: New test. * gcc.target/i386/auto-init-padding-11.c: New test. * gcc.target/i386/auto-init-padding-12.c: New test. * gcc.target/i386/auto-init-padding-2.c: New test. * gcc.target/i386/auto-init-padding-3.c: New test. * gcc.target/i386/auto-init-padding-4.c: New test. * gcc.target/i386/auto-init-padding-5.c: New test. * gcc.target/i386/auto-init-padding-6.c: New test. * gcc.target/i386/auto-init-padding-7.c: New test. * gcc.target/i386/auto-init-padding-8.c: New test. * gcc.target/i386/auto-init-padding-9.c: New test. --- gcc/gimplify.c | 151 +++++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 142 insertions(+), 9 deletions(-) (limited to 'gcc/gimplify.c') diff --git a/gcc/gimplify.c b/gcc/gimplify.c index 99d1c7fc..3314f76 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -1743,6 +1743,94 @@ force_labels_r (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED) return NULL_TREE; } +/* Generate an initialization to automatic variable DECL based on INIT_TYPE. + Build a call to internal const function DEFERRED_INIT: + 1st argument: SIZE of the DECL; + 2nd argument: INIT_TYPE; + 3rd argument: IS_VLA, 0 NO, 1 YES; + + as LHS = DEFERRED_INIT (SIZE of the DECL, INIT_TYPE, IS_VLA) + if IS_VLA is false, the LHS is the DECL itself, + if IS_VLA is true, the LHS is a MEM_REF whose address is the pointer + to this DECL. */ +static void +gimple_add_init_for_auto_var (tree decl, + enum auto_init_type init_type, + bool is_vla, + gimple_seq *seq_p) +{ + gcc_assert (auto_var_p (decl)); + gcc_assert (init_type > AUTO_INIT_UNINITIALIZED); + location_t loc = EXPR_LOCATION (decl); + tree decl_size = TYPE_SIZE_UNIT (TREE_TYPE (decl)); + + tree init_type_node + = build_int_cst (integer_type_node, (int) init_type); + tree is_vla_node + = build_int_cst (integer_type_node, (int) is_vla); + + tree call = build_call_expr_internal_loc (loc, IFN_DEFERRED_INIT, + TREE_TYPE (decl), 3, + decl_size, init_type_node, + is_vla_node); + + gimplify_assign (decl, call, seq_p); +} + +/* Generate padding initialization for automatic vairable DECL. + C guarantees that brace-init with fewer initializers than members + aggregate will initialize the rest of the aggregate as-if it were + static initialization. In turn static initialization guarantees + that padding is initialized to zero. So, we always initialize paddings + to zeroes regardless INIT_TYPE. + To do the padding initialization, we insert a call to + __BUILTIN_CLEAR_PADDING (&decl, 0, for_auto_init = true). + Note, we add an additional dummy argument for __BUILTIN_CLEAR_PADDING, + 'for_auto_init' to distinguish whether this call is for automatic + variable initialization or not. + */ +static void +gimple_add_padding_init_for_auto_var (tree decl, bool is_vla, + gimple_seq *seq_p) +{ + tree addr_of_decl = NULL_TREE; + bool for_auto_init = true; + tree fn = builtin_decl_explicit (BUILT_IN_CLEAR_PADDING); + + if (is_vla) + { + /* The temporary address variable for this vla should be + created in gimplify_vla_decl. */ + gcc_assert (DECL_HAS_VALUE_EXPR_P (decl)); + gcc_assert (TREE_CODE (DECL_VALUE_EXPR (decl)) == INDIRECT_REF); + addr_of_decl = TREE_OPERAND (DECL_VALUE_EXPR (decl), 0); + } + else + { + mark_addressable (decl); + addr_of_decl = build_fold_addr_expr (decl); + } + + gimple *call = gimple_build_call (fn, + 3, addr_of_decl, + build_zero_cst (TREE_TYPE (addr_of_decl)), + build_int_cst (integer_type_node, + (int) for_auto_init)); + gimplify_seq_add_stmt (seq_p, call); +} + +/* Return true if the DECL need to be automaticly initialized by the + compiler. */ +static bool +is_var_need_auto_init (tree decl) +{ + if (auto_var_p (decl) + && (flag_auto_var_init > AUTO_INIT_UNINITIALIZED) + && (!lookup_attribute ("uninitialized", DECL_ATTRIBUTES (decl)))) + return true; + return false; +} + /* Gimplify a DECL_EXPR node *STMT_P by making any necessary allocation and initialization explicit. */ @@ -1840,6 +1928,26 @@ gimplify_decl_expr (tree *stmt_p, gimple_seq *seq_p) as they may contain a label address. */ walk_tree (&init, force_labels_r, NULL, NULL); } + /* When there is no explicit initializer, if the user requested, + We should insert an artifical initializer for this automatic + variable. */ + else if (is_var_need_auto_init (decl)) + { + gimple_add_init_for_auto_var (decl, + flag_auto_var_init, + is_vla, + seq_p); + /* The expanding of a call to the above .DEFERRED_INIT will apply + block initialization to the whole space covered by this variable. + As a result, all the paddings will be initialized to zeroes + for zero initialization and 0xFE byte-repeatable patterns for + pattern initialization. + In order to make the paddings as zeroes for pattern init, We + should add a call to __builtin_clear_padding to clear the + paddings to zero in compatiple with CLANG. */ + if (flag_auto_var_init == AUTO_INIT_PATTERN) + gimple_add_padding_init_for_auto_var (decl, is_vla, seq_p); + } } return GS_ALL_DONE; @@ -3411,11 +3519,15 @@ gimplify_call_expr (tree *expr_p, gimple_seq *pre_p, bool want_value) { /* Remember the original type of the argument in an internal dummy second argument, as in GIMPLE pointer conversions are - useless. */ + useless. also mark this call as not for automatic initialization + in the internal dummy third argument. */ p = CALL_EXPR_ARG (*expr_p, 0); + bool for_auto_init = false; *expr_p - = build_call_expr_loc (EXPR_LOCATION (*expr_p), fndecl, 2, p, - build_zero_cst (TREE_TYPE (p))); + = build_call_expr_loc (EXPR_LOCATION (*expr_p), fndecl, 3, p, + build_zero_cst (TREE_TYPE (p)), + build_int_cst (integer_type_node, + (int) for_auto_init)); return GS_OK; } break; @@ -4872,6 +4984,9 @@ gimplify_init_constructor (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, tree object, ctor, type; enum gimplify_status ret; vec *elts; + bool cleared = false; + bool is_empty_ctor = false; + bool is_init_expr = (TREE_CODE (*expr_p) == INIT_EXPR); gcc_assert (TREE_CODE (TREE_OPERAND (*expr_p, 1)) == CONSTRUCTOR); @@ -4914,7 +5029,7 @@ gimplify_init_constructor (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, struct gimplify_init_ctor_preeval_data preeval_data; HOST_WIDE_INT num_ctor_elements, num_nonzero_elements; HOST_WIDE_INT num_unique_nonzero_elements; - bool cleared, complete_p, valid_const_initializer; + bool complete_p, valid_const_initializer; /* Aggregate types must lower constructors to initialization of individual elements. The exception is that a CONSTRUCTOR node @@ -4923,6 +5038,7 @@ gimplify_init_constructor (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, { if (notify_temp_creation) return GS_OK; + is_empty_ctor = true; break; } @@ -5248,13 +5364,28 @@ gimplify_init_constructor (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, if (want_value) { *expr_p = object; - return GS_OK; + ret = GS_OK; } else { *expr_p = NULL; - return GS_ALL_DONE; - } + ret = GS_ALL_DONE; + } + + /* If the user requests to initialize automatic variables, we + should initialize paddings inside the variable. Add a call to + __BUILTIN_CLEAR_PADDING (&object, 0, for_auto_init = true) to + initialize paddings of object always to zero regardless of + INIT_TYPE. Note, we will not insert this call if the aggregate + variable has be completely cleared already or it's initialized + with an empty constructor. */ + if (is_init_expr + && ((AGGREGATE_TYPE_P (type) && !cleared && !is_empty_ctor) + || !AGGREGATE_TYPE_P (type)) + && is_var_need_auto_init (object)) + gimple_add_padding_init_for_auto_var (object, false, pre_p); + + return ret; } /* Given a pointer value OP0, return a simplified version of an @@ -5395,10 +5526,12 @@ gimplify_modify_expr_rhs (tree *expr_p, tree *from_p, tree *to_p, crack at this before we break it down. */ if (ret != GS_UNHANDLED) break; + /* If we're initializing from a CONSTRUCTOR, break this into individual MODIFY_EXPRs. */ - return gimplify_init_constructor (expr_p, pre_p, post_p, want_value, - false); + ret = gimplify_init_constructor (expr_p, pre_p, post_p, want_value, + false); + return ret; case COND_EXPR: /* If we're assigning to a non-register type, push the assignment -- cgit v1.1 From 1dae802b685937b1dc52e49d0641c75f3186ba14 Mon Sep 17 00:00:00 2001 From: Richard Biener Date: Fri, 10 Sep 2021 10:17:24 +0200 Subject: middle-end/102269 - avoid auto-init of empty types This avoids initializing empty types for which we'll eventually leave a .DEFERRED_INIT call without a LHS. 2021-09-10 Richard Biener PR middle-end/102269 * gimplify.c (is_var_need_auto_init): Empty types do not need initialization. * gcc.dg/pr102269.c: New testcase. --- gcc/gimplify.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'gcc/gimplify.c') diff --git a/gcc/gimplify.c b/gcc/gimplify.c index 3314f76..8820f87 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -1826,7 +1826,8 @@ is_var_need_auto_init (tree decl) { if (auto_var_p (decl) && (flag_auto_var_init > AUTO_INIT_UNINITIALIZED) - && (!lookup_attribute ("uninitialized", DECL_ATTRIBUTES (decl)))) + && (!lookup_attribute ("uninitialized", DECL_ATTRIBUTES (decl))) + && !is_empty_type (TREE_TYPE (decl))) return true; return false; } -- cgit v1.1 From 8122fbff770bcff183a9c3c72e8092c0ca32150b Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Fri, 10 Sep 2021 20:41:33 +0200 Subject: openmp: Implement OpenMP 5.1 atomics, so far for C only This patch implements OpenMP 5.1 atomics (with clarifications from upcoming 5.2). The most important changes are that it is now possible to write (for C/C++, for Fortran it was possible before already) min/max atomics and more importantly compare and exchange in various forms. Also, acq_rel is now allowed on read/write and acq_rel/acquire are allowed on update, and there are new compare, weak and fail clauses. 2021-09-10 Jakub Jelinek gcc/ * tree-core.h (enum omp_memory_order): Add OMP_MEMORY_ORDER_MASK, OMP_FAIL_MEMORY_ORDER_UNSPECIFIED, OMP_FAIL_MEMORY_ORDER_RELAXED, OMP_FAIL_MEMORY_ORDER_ACQUIRE, OMP_FAIL_MEMORY_ORDER_RELEASE, OMP_FAIL_MEMORY_ORDER_ACQ_REL, OMP_FAIL_MEMORY_ORDER_SEQ_CST and OMP_FAIL_MEMORY_ORDER_MASK enumerators. (OMP_FAIL_MEMORY_ORDER_SHIFT): Define. * gimple-pretty-print.c (dump_gimple_omp_atomic_load, dump_gimple_omp_atomic_store): Print [weak] for weak atomic load/store. * gimple.h (enum gf_mask): Change GF_OMP_ATOMIC_MEMORY_ORDER to 6-bit mask, adjust GF_OMP_ATOMIC_NEED_VALUE value and add GF_OMP_ATOMIC_WEAK. (gimple_omp_atomic_weak_p, gimple_omp_atomic_set_weak): New inline functions. * tree.h (OMP_ATOMIC_WEAK): Define. * tree-pretty-print.c (dump_omp_atomic_memory_order): Adjust for fail memory order being encoded in the same enum and also print fail clause if present. (dump_generic_node): Print weak clause if OMP_ATOMIC_WEAK. * gimplify.c (goa_stabilize_expr): Add target_expr and rhs arguments, handle pre_p == NULL case as a test mode that only returns value but doesn't change gimplify nor change anything otherwise, adjust recursive calls, add MODIFY_EXPR, ADDR_EXPR, COND_EXPR, TARGET_EXPR and CALL_EXPR handling, adjust COMPOUND_EXPR handling for __builtin_clear_padding calls, for !rhs gimplify as lvalue rather than rvalue. (gimplify_omp_atomic): Adjust goa_stabilize_expr caller. Handle COND_EXPR rhs. Set weak flag on gimple load/store for OMP_ATOMIC_WEAK. * omp-expand.c (omp_memory_order_to_fail_memmodel): New function. (omp_memory_order_to_memmodel): Adjust for fail clause encoded in the same enum. (expand_omp_atomic_cas): New function. (expand_omp_atomic_pipeline): Use omp_memory_order_to_fail_memmodel function. (expand_omp_atomic): Attempt to optimize atomic compare and exchange using expand_omp_atomic_cas. gcc/c-family/ * c-common.h (c_finish_omp_atomic): Add r and weak arguments. * c-omp.c: Include gimple-fold.h. (c_finish_omp_atomic): Add r and weak arguments. Add support for OpenMP 5.1 atomics. gcc/c/ * c-parser.c (c_parser_conditional_expression): If omp_atomic_lhs and cond.value is >, < or == with omp_atomic_lhs as one of the operands, don't call build_conditional_expr, instead build a COND_EXPR directly. (c_parser_binary_expression): Avoid calling parser_build_binary_op if omp_atomic_lhs even in more cases for >, < or ==. (c_parser_omp_atomic): Update function comment for OpenMP 5.1 atomics, parse OpenMP 5.1 atomics and fail, compare and weak clauses, allow acq_rel on atomic read/write and acq_rel/acquire clauses on update. * c-typeck.c (build_binary_op): For flag_openmp only handle MIN_EXPR/MAX_EXPR. gcc/cp/ * parser.c (cp_parser_omp_atomic): Allow acq_rel on atomic read/write and acq_rel/acquire clauses on update. * semantics.c (finish_omp_atomic): Adjust c_finish_omp_atomic caller. gcc/testsuite/ * c-c++-common/gomp/atomic-17.c (foo): Add tests for atomic read, write or update with acq_rel clause and atomic update with acquire clause. * c-c++-common/gomp/atomic-18.c (foo): Adjust expected diagnostics wording, remove tests moved to atomic-17.c. * c-c++-common/gomp/atomic-21.c: Expect only 2 omp atomic release and 2 omp atomic acq_rel directives instead of 4 omp atomic release. * c-c++-common/gomp/atomic-25.c: New test. * c-c++-common/gomp/atomic-26.c: New test. * c-c++-common/gomp/atomic-27.c: New test. * c-c++-common/gomp/atomic-28.c: New test. * c-c++-common/gomp/atomic-29.c: New test. * c-c++-common/gomp/atomic-30.c: New test. * c-c++-common/goacc-gomp/atomic.c: Expect 1 omp atomic release and 1 omp atomic_acq_rel instead of 2 omp atomic release directives. * gcc.dg/gomp/atomic-5.c: Adjust expected error diagnostic wording. * g++.dg/gomp/atomic-18.C:Expect 4 omp atomic release and 1 omp atomic_acq_rel instead of 5 omp atomic release directives. libgomp/ * testsuite/libgomp.c-c++-common/atomic-19.c: New test. * testsuite/libgomp.c-c++-common/atomic-20.c: New test. * testsuite/libgomp.c-c++-common/atomic-21.c: New test. --- gcc/gimplify.c | 161 ++++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 138 insertions(+), 23 deletions(-) (limited to 'gcc/gimplify.c') diff --git a/gcc/gimplify.c b/gcc/gimplify.c index 8820f87..66dfd25 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -13859,14 +13859,15 @@ goa_lhs_expr_p (tree expr, tree addr) static int goa_stabilize_expr (tree *expr_p, gimple_seq *pre_p, tree lhs_addr, - tree lhs_var) + tree lhs_var, tree &target_expr, bool rhs) { tree expr = *expr_p; int saw_lhs; if (goa_lhs_expr_p (expr, lhs_addr)) { - *expr_p = lhs_var; + if (pre_p) + *expr_p = lhs_var; return 1; } if (is_gimple_val (expr)) @@ -13878,11 +13879,11 @@ goa_stabilize_expr (tree *expr_p, gimple_seq *pre_p, tree lhs_addr, case tcc_binary: case tcc_comparison: saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 1), pre_p, lhs_addr, - lhs_var); + lhs_var, target_expr, true); /* FALLTHRU */ case tcc_unary: saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 0), pre_p, lhs_addr, - lhs_var); + lhs_var, target_expr, true); break; case tcc_expression: switch (TREE_CODE (expr)) @@ -13894,36 +13895,131 @@ goa_stabilize_expr (tree *expr_p, gimple_seq *pre_p, tree lhs_addr, case TRUTH_XOR_EXPR: case BIT_INSERT_EXPR: saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 1), pre_p, - lhs_addr, lhs_var); + lhs_addr, lhs_var, target_expr, true); /* FALLTHRU */ case TRUTH_NOT_EXPR: saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 0), pre_p, - lhs_addr, lhs_var); + lhs_addr, lhs_var, target_expr, true); + break; + case MODIFY_EXPR: + saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 1), pre_p, + lhs_addr, lhs_var, target_expr, true); + /* FALLTHRU */ + case ADDR_EXPR: + saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 0), pre_p, + lhs_addr, lhs_var, target_expr, false); break; case COMPOUND_EXPR: + /* Special-case __builtin_clear_padding call before + __builtin_memcmp. */ + if (TREE_CODE (TREE_OPERAND (expr, 0)) == CALL_EXPR) + { + tree fndecl = get_callee_fndecl (TREE_OPERAND (expr, 0)); + if (fndecl + && fndecl_built_in_p (fndecl, BUILT_IN_CLEAR_PADDING) + && VOID_TYPE_P (TREE_TYPE (TREE_OPERAND (expr, 0)))) + { + saw_lhs = goa_stabilize_expr (&TREE_OPERAND (expr, 0), pre_p, + lhs_addr, lhs_var, + target_expr, true); + if (!saw_lhs) + { + expr = TREE_OPERAND (expr, 1); + if (!pre_p) + return goa_stabilize_expr (&expr, pre_p, lhs_addr, + lhs_var, target_expr, true); + *expr_p = expr; + return goa_stabilize_expr (expr_p, pre_p, lhs_addr, + lhs_var, target_expr, true); + } + else + { + saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 1), + pre_p, lhs_addr, lhs_var, + target_expr, rhs); + break; + } + } + } /* Break out any preevaluations from cp_build_modify_expr. */ for (; TREE_CODE (expr) == COMPOUND_EXPR; expr = TREE_OPERAND (expr, 1)) - gimplify_stmt (&TREE_OPERAND (expr, 0), pre_p); + if (pre_p) + gimplify_stmt (&TREE_OPERAND (expr, 0), pre_p); + if (!pre_p) + return goa_stabilize_expr (&expr, pre_p, lhs_addr, lhs_var, + target_expr, rhs); *expr_p = expr; - return goa_stabilize_expr (expr_p, pre_p, lhs_addr, lhs_var); + return goa_stabilize_expr (expr_p, pre_p, lhs_addr, lhs_var, + target_expr, rhs); + case COND_EXPR: + if (!goa_stabilize_expr (&TREE_OPERAND (expr, 0), NULL, lhs_addr, + lhs_var, target_expr, true)) + break; + saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 0), pre_p, + lhs_addr, lhs_var, target_expr, true); + saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 1), pre_p, + lhs_addr, lhs_var, target_expr, true); + saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 2), pre_p, + lhs_addr, lhs_var, target_expr, true); + break; + case TARGET_EXPR: + if (TARGET_EXPR_INITIAL (expr)) + { + if (expr == target_expr) + saw_lhs = 1; + else + { + saw_lhs = goa_stabilize_expr (&TARGET_EXPR_INITIAL (expr), + pre_p, lhs_addr, lhs_var, + target_expr, true); + if (saw_lhs && target_expr == NULL_TREE && pre_p) + target_expr = expr; + } + } + break; default: break; } break; case tcc_reference: - if (TREE_CODE (expr) == BIT_FIELD_REF) + if (TREE_CODE (expr) == BIT_FIELD_REF + || TREE_CODE (expr) == VIEW_CONVERT_EXPR) saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 0), pre_p, - lhs_addr, lhs_var); + lhs_addr, lhs_var, target_expr, true); + break; + case tcc_vl_exp: + if (TREE_CODE (expr) == CALL_EXPR) + { + if (tree fndecl = get_callee_fndecl (expr)) + if (fndecl_built_in_p (fndecl, BUILT_IN_CLEAR_PADDING) + || fndecl_built_in_p (fndecl, BUILT_IN_MEMCMP)) + { + int nargs = call_expr_nargs (expr); + for (int i = 0; i < nargs; i++) + saw_lhs |= goa_stabilize_expr (&CALL_EXPR_ARG (expr, i), + pre_p, lhs_addr, lhs_var, + target_expr, true); + } + if (saw_lhs == 0 && VOID_TYPE_P (TREE_TYPE (expr))) + { + if (pre_p) + gimplify_stmt (&expr, pre_p); + return 0; + } + } break; default: break; } - if (saw_lhs == 0) + if (saw_lhs == 0 && pre_p) { enum gimplify_status gs; - gs = gimplify_expr (expr_p, pre_p, NULL, is_gimple_val, fb_rvalue); + if (rhs) + gs = gimplify_expr (expr_p, pre_p, NULL, is_gimple_val, fb_rvalue); + else + gs = gimplify_expr (expr_p, pre_p, NULL, is_gimple_lvalue, fb_lvalue); if (gs != GS_ALL_DONE) saw_lhs = -1; } @@ -13943,9 +14039,12 @@ gimplify_omp_atomic (tree *expr_p, gimple_seq *pre_p) tree tmp_load; gomp_atomic_load *loadstmt; gomp_atomic_store *storestmt; + tree target_expr = NULL_TREE; tmp_load = create_tmp_reg (type); - if (rhs && goa_stabilize_expr (&rhs, pre_p, addr, tmp_load) < 0) + if (rhs + && goa_stabilize_expr (&rhs, pre_p, addr, tmp_load, target_expr, + true) < 0) return GS_ERROR; if (gimplify_expr (&addr, pre_p, NULL, is_gimple_val, fb_rvalue) @@ -13959,11 +14058,14 @@ gimplify_omp_atomic (tree *expr_p, gimple_seq *pre_p) { /* BIT_INSERT_EXPR is not valid for non-integral bitfield representatives. Use BIT_FIELD_REF on the lhs instead. */ - if (TREE_CODE (rhs) == BIT_INSERT_EXPR + tree rhsarg = rhs; + if (TREE_CODE (rhs) == COND_EXPR) + rhsarg = TREE_OPERAND (rhs, 1); + if (TREE_CODE (rhsarg) == BIT_INSERT_EXPR && !INTEGRAL_TYPE_P (TREE_TYPE (tmp_load))) { - tree bitpos = TREE_OPERAND (rhs, 2); - tree op1 = TREE_OPERAND (rhs, 1); + tree bitpos = TREE_OPERAND (rhsarg, 2); + tree op1 = TREE_OPERAND (rhsarg, 1); tree bitsize; tree tmp_store = tmp_load; if (TREE_CODE (*expr_p) == OMP_ATOMIC_CAPTURE_OLD) @@ -13972,17 +14074,25 @@ gimplify_omp_atomic (tree *expr_p, gimple_seq *pre_p) bitsize = bitsize_int (TYPE_PRECISION (TREE_TYPE (op1))); else bitsize = TYPE_SIZE (TREE_TYPE (op1)); - gcc_assert (TREE_OPERAND (rhs, 0) == tmp_load); - tree t = build2_loc (EXPR_LOCATION (rhs), + gcc_assert (TREE_OPERAND (rhsarg, 0) == tmp_load); + tree t = build2_loc (EXPR_LOCATION (rhsarg), MODIFY_EXPR, void_type_node, - build3_loc (EXPR_LOCATION (rhs), BIT_FIELD_REF, - TREE_TYPE (op1), tmp_store, bitsize, - bitpos), op1); + build3_loc (EXPR_LOCATION (rhsarg), + BIT_FIELD_REF, TREE_TYPE (op1), + tmp_store, bitsize, bitpos), op1); + if (TREE_CODE (rhs) == COND_EXPR) + t = build3_loc (EXPR_LOCATION (rhs), COND_EXPR, void_type_node, + TREE_OPERAND (rhs, 0), t, void_node); gimplify_and_add (t, pre_p); rhs = tmp_store; } - if (gimplify_expr (&rhs, pre_p, NULL, is_gimple_val, fb_rvalue) - != GS_ALL_DONE) + bool save_allow_rhs_cond_expr = gimplify_ctxp->allow_rhs_cond_expr; + if (TREE_CODE (rhs) == COND_EXPR) + gimplify_ctxp->allow_rhs_cond_expr = true; + enum gimplify_status gs = gimplify_expr (&rhs, pre_p, NULL, + is_gimple_val, fb_rvalue); + gimplify_ctxp->allow_rhs_cond_expr = save_allow_rhs_cond_expr; + if (gs != GS_ALL_DONE) return GS_ERROR; } @@ -13990,6 +14100,11 @@ gimplify_omp_atomic (tree *expr_p, gimple_seq *pre_p) rhs = tmp_load; storestmt = gimple_build_omp_atomic_store (rhs, OMP_ATOMIC_MEMORY_ORDER (*expr_p)); + if (TREE_CODE (*expr_p) != OMP_ATOMIC_READ && OMP_ATOMIC_WEAK (*expr_p)) + { + gimple_omp_atomic_set_weak (loadstmt); + gimple_omp_atomic_set_weak (storestmt); + } gimplify_seq_add_stmt (pre_p, storestmt); switch (TREE_CODE (*expr_p)) { -- cgit v1.1