From 00294b189cf3285b17b4ca4135341e2614783553 Mon Sep 17 00:00:00 2001 From: Richard Biener Date: Thu, 9 Jan 2020 10:41:38 +0000 Subject: re PR tree-optimization/93054 (ICE in gimple_set_lhs, at gimple.c:1820) 2020-01-09 Richard Biener PR middle-end/93054 * gimplify.c (gimplify_expr): Deal with NOP definitions. * gcc.dg/pr93054.c: New testcase. From-SVN: r280039 --- 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 73fb2e7..4243d3a 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -14622,7 +14622,8 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, { /* Avoid the extra copy if possible. */ *expr_p = create_tmp_reg (TREE_TYPE (name)); - gimple_set_lhs (SSA_NAME_DEF_STMT (name), *expr_p); + if (!gimple_nop_p (SSA_NAME_DEF_STMT (name))) + gimple_set_lhs (SSA_NAME_DEF_STMT (name), *expr_p); release_ssa_name (name); } } -- cgit v1.1 From 640b23d7ff5f3fad005dcbfb04a36e27000fc150 Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Fri, 10 Jan 2020 13:46:57 -0500 Subject: PR c++/93173 - incorrect tree sharing. My patch for 93033 wasn't sufficient to handle all the possible sharing introduced by split_nonconstant_init, and it occurred to me that it would make sense to use the same unsharing technique as unshare_body, namely copy_if_shared. PR c++/93033 gcc/ * gimplify.c (copy_if_shared): No longer static. * gimplify.h: Declare it. gcc/cp/ * cp-gimplify.c (cp_gimplify_init_expr, cp_gimplify_expr): Use copy_if_shared after cp_genericize_tree. * typeck2.c (split_nonconstant_init): Don't unshare here. From-SVN: r280126 --- 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 4243d3a..00d264f 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -937,7 +937,7 @@ copy_if_shared_r (tree *tp, int *walk_subtrees, void *data) /* Unshare most of the shared trees rooted at *TP. DATA is passed to the copy_if_shared_r callback unmodified. */ -static inline void +void copy_if_shared (tree *tp, void *data) { walk_tree (tp, copy_if_shared_r, data, NULL); -- cgit v1.1 From b3b75e664a619dae98571a0b3ac8034f5fa7c2be Mon Sep 17 00:00:00 2001 From: Thomas Schwinge Date: Fri, 10 Jan 2020 23:23:44 +0100 Subject: Further changes for the OpenACC 'if_present' clause on the 'host_data' construct gcc/ * tree.h (OMP_CLAUSE_USE_DEVICE_PTR_IF_PRESENT): New definition. * tree-core.h: Document it. * gimplify.c (gimplify_omp_workshare): Set it. * omp-low.c (lower_omp_target): Use it. * tree-pretty-print.c (dump_omp_clause): Print it. gcc/testsuite/ * c-c++-common/goacc/host_data-1.c: Extend. * gfortran.dg/goacc/host_data-tree.f95: Likewise. gcc/ * omp-low.c (lower_omp_target) : Assert that for OpenACC we always have 'GOMP_MAP_USE_DEVICE_PTR'. libgomp/ * target.c (gomp_map_vars_internal) : Clean up/elaborate code paths. From-SVN: r280149 --- gcc/gimplify.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) (limited to 'gcc/gimplify.c') diff --git a/gcc/gimplify.c b/gcc/gimplify.c index 00d264f..fe7236d 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -12802,14 +12802,21 @@ gimplify_omp_workshare (tree *expr_p, gimple_seq *pre_p) stmt = gimple_build_omp_target (body, GF_OMP_TARGET_KIND_OACC_DATA, OMP_CLAUSES (expr)); break; - case OACC_KERNELS: - stmt = gimple_build_omp_target (body, GF_OMP_TARGET_KIND_OACC_KERNELS, - OMP_CLAUSES (expr)); - break; case OACC_HOST_DATA: + if (omp_find_clause (OMP_CLAUSES (expr), OMP_CLAUSE_IF_PRESENT)) + { + for (tree c = OMP_CLAUSES (expr); c; c = OMP_CLAUSE_CHAIN (c)) + if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_USE_DEVICE_PTR) + OMP_CLAUSE_USE_DEVICE_PTR_IF_PRESENT (c) = 1; + } + stmt = gimple_build_omp_target (body, GF_OMP_TARGET_KIND_OACC_HOST_DATA, OMP_CLAUSES (expr)); break; + case OACC_KERNELS: + stmt = gimple_build_omp_target (body, GF_OMP_TARGET_KIND_OACC_KERNELS, + OMP_CLAUSES (expr)); + break; case OACC_PARALLEL: stmt = gimple_build_omp_target (body, GF_OMP_TARGET_KIND_OACC_PARALLEL, OMP_CLAUSES (expr)); -- cgit v1.1 From 7c82dd6c02d44d9d2cd84dda137c00b1a3cd6c90 Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Fri, 10 Jan 2020 17:14:12 -0500 Subject: PR c++/33799 - destroy return value if local cleanup throws. This is a pretty rare situation since the C++11 change to make all destructors default to noexcept, but it is still possible to define throwing destructors, and if a destructor for a local variable throws during the return, we've already constructed the return value, so now we need to destroy it. I handled this somewhat like the new-expression cleanup; as in that case, this cleanup can't properly nest with the cleanups for local variables, so I introduce a cleanup region around the whole function and a flag variable to indicate whether the return value actually needs to be destroyed. Setting the flag requires giving a COMPOUND_EXPR as the operand of a RETURN_EXPR, so I adjust gimplify_return_expr to handle that. This doesn't currently work with deduced return type because we don't know the type when we're deciding whether to introduce the cleanup region. gcc/ * gimplify.c (gimplify_return_expr): Handle COMPOUND_EXPR. gcc/cp/ * cp-tree.h (current_retval_sentinel): New macro. * decl.c (start_preparsed_function): Set up cleanup for retval. * typeck.c (check_return_expr): Set current_retval_sentinel. --- gcc/gimplify.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'gcc/gimplify.c') diff --git a/gcc/gimplify.c b/gcc/gimplify.c index fe7236d..05d7922 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -1599,6 +1599,14 @@ gimplify_return_expr (tree stmt, gimple_seq *pre_p) if (VOID_TYPE_P (TREE_TYPE (TREE_TYPE (current_function_decl)))) result_decl = NULL_TREE; + else if (TREE_CODE (ret_expr) == COMPOUND_EXPR) + { + /* Used in C++ for handling EH cleanup of the return value if a local + cleanup throws. Assume the front-end knows what it's doing. */ + result_decl = DECL_RESULT (current_function_decl); + /* But crash if we end up trying to modify ret_expr below. */ + ret_expr = NULL_TREE; + } else { result_decl = TREE_OPERAND (ret_expr, 0); -- cgit v1.1 From 507de5ee23efdc8a16d6b0b6488e118055c711cd Mon Sep 17 00:00:00 2001 From: Richard Sandiford Date: Wed, 15 Jan 2020 16:52:18 +0000 Subject: gimplifier: handle POLY_INT_CST-sized TARGET_EXPRs If a TARGET_EXPR has poly-int size, the gimplifier would treat it like a VLA and use gimplify_vla_decl. gimplify_vla_decl in turn would use an alloca and expect all references to be gimplified via the DECL_VALUE_EXPR. This caused confusion later in gimplify_var_or_parm_decl_1 when we (correctly) had direct rather than indirect references. For completeness, the patch also fixes similar tests in the RETURN_EXPR handling and OpenMP depend clauses. 2020-01-17 Richard Sandiford gcc/ * gimplify.c (gimplify_return_expr): Use poly_int_tree_p rather than testing directly for INTEGER_CST. (gimplify_target_expr, gimplify_omp_depend): Likewise. gcc/testsuite/ * g++.target/aarch64/sve/acle/general-c++/gimplify_1.C: New test. --- gcc/gimplify.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'gcc/gimplify.c') diff --git a/gcc/gimplify.c b/gcc/gimplify.c index 05d7922..e50be57 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -1632,7 +1632,7 @@ gimplify_return_expr (tree stmt, gimple_seq *pre_p) result = NULL_TREE; else if (aggregate_value_p (result_decl, TREE_TYPE (current_function_decl))) { - if (TREE_CODE (DECL_SIZE (result_decl)) != INTEGER_CST) + if (!poly_int_tree_p (DECL_SIZE (result_decl))) { if (!TYPE_SIZES_GIMPLIFIED (TREE_TYPE (result_decl))) gimplify_type_sizes (TREE_TYPE (result_decl), pre_p); @@ -6714,7 +6714,7 @@ gimplify_target_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p) /* TARGET_EXPR temps aren't part of the enclosing block, so add it to the temps list. Handle also variable length TARGET_EXPRs. */ - if (TREE_CODE (DECL_SIZE (temp)) != INTEGER_CST) + if (!poly_int_tree_p (DECL_SIZE (temp))) { if (!TYPE_SIZES_GIMPLIFIED (TREE_TYPE (temp))) gimplify_type_sizes (TREE_TYPE (temp), pre_p); @@ -7921,7 +7921,7 @@ gimplify_omp_depend (tree *list_p, gimple_seq *pre_p) tree type = build_array_type (ptr_type_node, build_index_type (totalpx)); tree array = create_tmp_var_raw (type); TREE_ADDRESSABLE (array) = 1; - if (TREE_CODE (totalpx) != INTEGER_CST) + if (!poly_int_tree_p (totalpx)) { if (!TYPE_SIZES_GIMPLIFIED (TREE_TYPE (array))) gimplify_type_sizes (TREE_TYPE (array), pre_p); -- cgit v1.1 From cf785618ecc90e3f063b99572de48cb91aa5ab5d Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Thu, 6 Feb 2020 09:15:13 +0100 Subject: openmp: Notice reduction decl in outer contexts after adding it to shared [PR93515] If we call omp_add_variable, following omp_notice_variable will already find it on that construct and not go through outer constructs, the following patch fixes that. Note, this still doesn't follow OpenMP 5.0 semantics on target combined with other constructs with reduction/lastprivate/linear clauses, will handle that for GCC11. 2020-02-06 Jakub Jelinek PR libgomp/93515 * gimplify.c (gimplify_scan_omp_clauses) : If adding shared clause, call omp_notice_variable on outer context if any. --- gcc/gimplify.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'gcc/gimplify.c') diff --git a/gcc/gimplify.c b/gcc/gimplify.c index e50be57..aafef78 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -9464,9 +9464,13 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p, == POINTER_TYPE)))) omp_firstprivatize_variable (outer_ctx, decl); else - omp_add_variable (outer_ctx, decl, - GOVD_SEEN | GOVD_SHARED); - omp_notice_variable (outer_ctx, decl, true); + { + omp_add_variable (outer_ctx, decl, + GOVD_SEEN | GOVD_SHARED); + if (outer_ctx->outer_context) + omp_notice_variable (outer_ctx->outer_context, decl, + true); + } } } if (outer_ctx) -- cgit v1.1 From 9bc3b95dfefd37d860c5dc0004f8a53f6290fbb1 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Sun, 9 Feb 2020 08:17:10 +0100 Subject: openmp: Optimize DECL_IN_CONSTANT_POOL vars in target regions DECL_IN_CONSTANT_POOL are shared and thus don't really get emitted in the BLOCK where they are used, so for OpenMP target regions that have initializers gimplified into copying from them we actually map them at runtime from host to offload devices. This patch instead marks them as "omp declare target", so that they are on the target device from the beginning and don't need to be copied there. 2020-02-09 Jakub Jelinek * gimplify.c (gimplify_adjust_omp_clauses_1): Promote DECL_IN_CONSTANT_POOL variables into "omp declare target" to avoid copying them around between host and target. * testsuite/libgomp.c/target-38.c: New test. --- gcc/gimplify.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'gcc/gimplify.c') diff --git a/gcc/gimplify.c b/gcc/gimplify.c index aafef78..a6205d6 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -9906,6 +9906,22 @@ gimplify_adjust_omp_clauses_1 (splay_tree_node n, void *data) error ("%<_Atomic%> %qD in implicit % clause", decl); return 0; } + if (VAR_P (decl) + && DECL_IN_CONSTANT_POOL (decl) + && !lookup_attribute ("omp declare target", + DECL_ATTRIBUTES (decl))) + { + tree id = get_identifier ("omp declare target"); + DECL_ATTRIBUTES (decl) + = tree_cons (id, NULL_TREE, DECL_ATTRIBUTES (decl)); + varpool_node *node = varpool_node::get (decl); + if (node) + { + node->offloadable = 1; + if (ENABLE_OFFLOADING) + g->have_offload = true; + } + } } else if (flags & GOVD_SHARED) { -- cgit v1.1 From 1956773cc655dfcba8d310066d3f6585dd4b8972 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Thu, 27 Feb 2020 10:45:30 +0100 Subject: gimplify: Don't optimize register const vars to static [PR93949] The following testcase is rejected, while it was accepted in 3.4 and earlier (before tree-ssa merge). The problem is that we decide to promote the const variable to TREE_STATIC, but TREE_STATIC DECL_REGISTER VAR_DECLs may only be the global register vars and so assemble_variable/make_decl_rtl diagnoses it. Either we do what the following patch does, where we could consider register as a hint the user doesn't want such optimization, because if something is forced static, it is not "register" anymore and register static is not valid in C either, or we could clear DECL_REGISTER instead, but would still need to punt at least on DECL_HARD_REGISTER cases. 2020-02-27 Jakub Jelinek PR c/93949 * gimplify.c (gimplify_init_constructor): Don't promote readonly DECL_REGISTER variables to TREE_STATIC. * gcc.c-torture/compile/pr93949.c: New test. --- 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 a6205d6..ef531f3 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -4923,6 +4923,7 @@ gimplify_init_constructor (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, && num_nonzero_elements > 1 && TREE_READONLY (object) && VAR_P (object) + && !DECL_REGISTER (object) && (flag_merge_constants >= 2 || !TREE_ADDRESSABLE (object)) /* For ctors that have many repeated nonzero elements represented through RANGE_EXPRs, prefer initializing -- cgit v1.1 From 10ea09ee846eaa345161a3a3f519b3780d6101fa Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Thu, 26 Mar 2020 10:10:21 +0100 Subject: gimplify: Fix -fcompare-debug differences caused by gimplify_body [PR94281] The following testcase FAILs, because gimplify_body adds a GIMPLE_NOP only when there are no statements in the function and with -g there is a DEBUG_BEGIN_STMT, so it doesn't add it and due to -fno-tree-dce that never gets removed afterwards. Similarly, if the body seq after gimplification contains some DEBUG_BEGIN_STMTs plus a single gbind, then we could behave differently between -g0 and -g, by using that gbind as the body in the -g0 case and not in the -g case. This patch fixes that by ignoring DEBUG_BEGIN_STMTs (other debug stmts can't appear at this point yet thankfully) during decisions and if we pick the single gbind and there are DEBUG_BEGIN_STMTs next to it, it moves them into the gbind. While debugging this, I found also a bug in the gimple_seq_last_nondebug_stmt function, for a seq that has a single non-DEBUG_BEGIN_STMT statement followed by one or more DEBUG_BEGIN_STMTs it would return NULL rather than the first statement. 2020-03-26 Jakub Jelinek PR debug/94281 * gimple.h (gimple_seq_first_nondebug_stmt): New function. (gimple_seq_last_nondebug_stmt): Don't return NULL if seq contains a single non-debug stmt followed by one or more debug stmts. * gimplify.c (gimplify_body): Use gimple_seq_first_nondebug_stmt instead of gimple_seq_first_stmt, use gimple_seq_first_nondebug_stmt and gimple_seq_last_nondebug_stmt instead of gimple_seq_first and gimple_seq_last to check if outer_stmt gbind could be reused and if yes and it is surrounded by any debug stmts, move them into the gbind body. * g++.dg/debug/pr94281.C: New test. --- gcc/gimplify.c | 35 ++++++++++++++++++++++++++++++++--- 1 file changed, 32 insertions(+), 3 deletions(-) (limited to 'gcc/gimplify.c') diff --git a/gcc/gimplify.c b/gcc/gimplify.c index ef531f3..787435c 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -14849,7 +14849,7 @@ gimplify_body (tree fndecl, bool do_parms) /* Gimplify the function's body. */ seq = NULL; gimplify_stmt (&DECL_SAVED_TREE (fndecl), &seq); - outer_stmt = gimple_seq_first_stmt (seq); + outer_stmt = gimple_seq_first_nondebug_stmt (seq); if (!outer_stmt) { outer_stmt = gimple_build_nop (); @@ -14859,8 +14859,37 @@ gimplify_body (tree fndecl, bool do_parms) /* The body must contain exactly one statement, a GIMPLE_BIND. If this is not the case, wrap everything in a GIMPLE_BIND to make it so. */ if (gimple_code (outer_stmt) == GIMPLE_BIND - && gimple_seq_first (seq) == gimple_seq_last (seq)) - outer_bind = as_a (outer_stmt); + && (gimple_seq_first_nondebug_stmt (seq) + == gimple_seq_last_nondebug_stmt (seq))) + { + outer_bind = as_a (outer_stmt); + if (gimple_seq_first_stmt (seq) != outer_stmt + || gimple_seq_last_stmt (seq) != outer_stmt) + { + /* If there are debug stmts before or after outer_stmt, move them + inside of outer_bind body. */ + gimple_stmt_iterator gsi = gsi_for_stmt (outer_stmt, &seq); + gimple_seq second_seq = NULL; + if (gimple_seq_first_stmt (seq) != outer_stmt + && gimple_seq_last_stmt (seq) != outer_stmt) + { + second_seq = gsi_split_seq_after (gsi); + gsi_remove (&gsi, false); + } + else if (gimple_seq_first_stmt (seq) != outer_stmt) + gsi_remove (&gsi, false); + else + { + gsi_remove (&gsi, false); + second_seq = seq; + seq = NULL; + } + gimple_seq_add_seq_without_update (&seq, + gimple_bind_body (outer_bind)); + gimple_seq_add_seq_without_update (&seq, second_seq); + gimple_bind_set_body (outer_bind, seq); + } + } else outer_bind = gimple_build_bind (NULL_TREE, seq, NULL); -- cgit v1.1 From 3d947f1f27188e3a61ba7f42399b1c348469fe13 Mon Sep 17 00:00:00 2001 From: Richard Biener Date: Tue, 7 Apr 2020 16:29:37 +0200 Subject: middle-end/94479 - fix gimplification of address When gimplifying an address operand we may expose an indirect ref via DECL_VALUE_EXPR for example. This is dealt with in the code already but it fails to consider that INDIRECT_REFs get gimplified to MEM_REFs. Fixed which makes the ICE observed on x86_64-netbsd go away. 2020-04-07 Richard Biener PR middle-end/94479 * gimplify.c (gimplify_addr_expr): Also consider generated MEM_REFs. * gcc.dg/torture/pr94479.c: New testcase. --- gcc/gimplify.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'gcc/gimplify.c') diff --git a/gcc/gimplify.c b/gcc/gimplify.c index 787435c..8cdfae2 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -6181,7 +6181,9 @@ gimplify_addr_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p) /* For various reasons, the gimplification of the expression may have made a new INDIRECT_REF. */ - if (TREE_CODE (op0) == INDIRECT_REF) + if (TREE_CODE (op0) == INDIRECT_REF + || (TREE_CODE (op0) == MEM_REF + && integer_zerop (TREE_OPERAND (op0, 1)))) goto do_indirect_ref; mark_addressable (TREE_OPERAND (expr, 0)); -- cgit v1.1 From af557050fd011a03d21dc26b31959033061a0443 Mon Sep 17 00:00:00 2001 From: Tobias Burnus Date: Fri, 17 Apr 2020 19:08:55 +0200 Subject: [OpenMP] Fix 'omp exit data' for Fortran arrays (PR 94635) PR middle-end/94635 * gimplify.c (gimplify_scan_omp_clauses): Turn MAP_TO_PSET to MAP_DELETE. PR middle-end/94635 * testsuite/libgomp.fortran/target-enter-data-2.F90: New. --- gcc/gimplify.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'gcc/gimplify.c') diff --git a/gcc/gimplify.c b/gcc/gimplify.c index 8cdfae2..2f2c51b 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -8785,10 +8785,14 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p, 'exit data' - and in particular for 'delete:' - having an 'alloc:' does not make sense. Likewise, for 'update' only transferring the data itself is needed as the rest has been handled in previous - directives. */ - if ((code == OMP_TARGET_EXIT_DATA || code == OMP_TARGET_UPDATE) - && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER - || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_TO_PSET)) + directives. However, for 'exit data', the array descriptor needs + to be delete; hence, we turn the MAP_TO_PSET into a MAP_DELETE. */ + if (code == OMP_TARGET_EXIT_DATA + && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_TO_PSET) + OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_DELETE); + else if ((code == OMP_TARGET_EXIT_DATA || code == OMP_TARGET_UPDATE) + && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER + || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_TO_PSET)) remove = true; if (remove) -- cgit v1.1 From 2badc9885330b56dfabb49328c42de792bc67b1e Mon Sep 17 00:00:00 2001 From: Eric Botcazou Date: Tue, 5 May 2020 12:31:26 +0200 Subject: Do not put incomplete CONSTRUCTORs into static memory The CONSTRUCTOR_NO_CLEARING flag was invented to avoid generating a memset for CONSTRUCTORS that lack elements, but it turns out that the gimplifier can generate a memcpy for them instead, which is worse performance-wise, so this prevents it from doing that for them. * gimplify.c (gimplify_init_constructor): Do not put the constructor into static memory if it is not complete. --- 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 2f2c51b..7807e30 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -4995,8 +4995,8 @@ gimplify_init_constructor (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, all-zero initializers (which aren't big enough to merit clearing), and don't try to make bitwise copies of TREE_ADDRESSABLE types. */ - if (valid_const_initializer + && complete_p && !(cleared || num_nonzero_elements == 0) && !TREE_ADDRESSABLE (type)) { -- cgit v1.1 From eb72dc663e9070b281be83a80f6f838a3a878822 Mon Sep 17 00:00:00 2001 From: Richard Biener Date: Wed, 22 Apr 2020 10:40:51 +0200 Subject: extend DECL_GIMPLE_REG_P to all types This extends DECL_GIMPLE_REG_P to all types so we can clear TREE_ADDRESSABLE even for integers with partial defs, not just complex and vector variables. To make that transition easier the patch inverts DECL_GIMPLE_REG_P to DECL_NOT_GIMPLE_REG_P since that makes the default the current state for all other types besides complex and vectors. For the testcase in PR94703 we're able to expand the partial def'ed local integer to a register then, producing a single movl rather than going through the stack. On i?86 this execute FAILs gcc.dg/torture/pr71522.c because we now expand a round-trip through a long double automatic var to a register fld/fst which normalizes the value. For that during RTL expansion we're looking for problematic punnings of decls and avoid pseudos for those - I chose integer or BLKmode accesses on decls with modes where precision doesn't match bitsize which covers the XFmode case. 2020-05-07 Richard Biener PR middle-end/94703 * tree-core.h (tree_decl_common::gimple_reg_flag): Rename ... (tree_decl_common::not_gimple_reg_flag): ... to this. * tree.h (DECL_GIMPLE_REG_P): Rename ... (DECL_NOT_GIMPLE_REG_P): ... to this. * gimple-expr.c (copy_var_decl): Copy DECL_NOT_GIMPLE_REG_P. (create_tmp_reg): Simplify. (create_tmp_reg_fn): Likewise. (is_gimple_reg): Check DECL_NOT_GIMPLE_REG_P for all regs. * gimplify.c (create_tmp_from_val): Simplify. (gimplify_bind_expr): Likewise. (gimplify_compound_literal_expr): Likewise. (gimplify_function_tree): Likewise. (prepare_gimple_addressable): Set DECL_NOT_GIMPLE_REG_P. * asan.c (create_odr_indicator): Do not clear DECL_GIMPLE_REG_P. (asan_add_global): Copy it. * cgraphunit.c (cgraph_node::expand_thunk): Force args to be GIMPLE regs. * function.c (gimplify_parameters): Copy DECL_NOT_GIMPLE_REG_P. * ipa-param-manipulation.c (ipa_param_body_adjustments::common_initialization): Simplify. (ipa_param_body_adjustments::reset_debug_stmts): Copy DECL_NOT_GIMPLE_REG_P. * omp-low.c (lower_omp_for_scan): Do not set DECL_GIMPLE_REG_P. * sanopt.c (sanitize_rewrite_addressable_params): Likewise. * tree-cfg.c (make_blocks_1): Simplify. (verify_address): Do not verify DECL_GIMPLE_REG_P setting. * tree-eh.c (lower_eh_constructs_2): Simplify. * tree-inline.c (declare_return_variable): Adjust and generalize. (copy_decl_to_var): Copy DECL_NOT_GIMPLE_REG_P. (copy_result_decl_to_var): Likewise. * tree-into-ssa.c (pass_build_ssa::execute): Adjust comment. * tree-nested.c (create_tmp_var_for): Simplify. * tree-parloops.c (separate_decls_in_region_name): Copy DECL_NOT_GIMPLE_REG_P. * tree-sra.c (create_access_replacement): Adjust and generalize partial def support. * tree-ssa-forwprop.c (pass_forwprop::execute): Set DECL_NOT_GIMPLE_REG_P on decls we introduce partial defs on. * tree-ssa.c (maybe_optimize_var): Handle clearing of TREE_ADDRESSABLE and setting/clearing DECL_NOT_GIMPLE_REG_P independently. * lto-streamer-out.c (hash_tree): Hash DECL_NOT_GIMPLE_REG_P. * tree-streamer-out.c (pack_ts_decl_common_value_fields): Stream DECL_NOT_GIMPLE_REG_P. * tree-streamer-in.c (unpack_ts_decl_common_value_fields): Likewise. * cfgexpand.c (avoid_type_punning_on_regs): New. (discover_nonconstant_array_refs): Call avoid_type_punning_on_regs to avoid unsupported mode punning. lto/ * lto-common.c (compare_tree_sccs_1): Compare DECL_NOT_GIMPLE_REG_P. c/ * gimple-parser.c (c_parser_parse_ssa_name): Do not set DECL_GIMPLE_REG_P. cp/ * optimize.c (update_cloned_parm): Copy DECL_NOT_GIMPLE_REG_P. * gcc.dg/tree-ssa/pr94703.c: New testcase. --- gcc/gimplify.c | 46 ++-------------------------------------------- 1 file changed, 2 insertions(+), 44 deletions(-) (limited to 'gcc/gimplify.c') diff --git a/gcc/gimplify.c b/gcc/gimplify.c index 7807e30..1d532e6 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -559,9 +559,6 @@ create_tmp_from_val (tree val) /* Drop all qualifiers and address-space information from the value type. */ tree type = TYPE_MAIN_VARIANT (TREE_TYPE (val)); tree var = create_tmp_var (type, get_name (val)); - if (TREE_CODE (TREE_TYPE (var)) == COMPLEX_TYPE - || TREE_CODE (TREE_TYPE (var)) == VECTOR_TYPE) - DECL_GIMPLE_REG_P (var) = 1; return var; } @@ -1400,16 +1397,6 @@ gimplify_bind_expr (tree *expr_p, gimple_seq *pre_p) if (DECL_HARD_REGISTER (t) && !is_global_var (t) && cfun) cfun->has_local_explicit_reg_vars = true; } - - /* Preliminarily mark non-addressed complex variables as eligible - for promotion to gimple registers. We'll transform their uses - as we find them. */ - if ((TREE_CODE (TREE_TYPE (t)) == COMPLEX_TYPE - || TREE_CODE (TREE_TYPE (t)) == VECTOR_TYPE) - && !TREE_THIS_VOLATILE (t) - && (VAR_P (t) && !DECL_HARD_REGISTER (t)) - && !needs_to_live_in_memory (t)) - DECL_GIMPLE_REG_P (t) = 1; } bind_stmt = gimple_build_bind (BIND_EXPR_VARS (bind_expr), NULL, @@ -4308,7 +4295,7 @@ prepare_gimple_addressable (tree *expr_p, gimple_seq *seq_p) { /* Do not allow an SSA name as the temporary. */ tree var = get_initialized_tmp_var (*expr_p, seq_p, NULL, false); - DECL_GIMPLE_REG_P (var) = 0; + DECL_NOT_GIMPLE_REG_P (var) = 1; *expr_p = var; } } @@ -4774,15 +4761,6 @@ gimplify_compound_literal_expr (tree *expr_p, gimple_seq *pre_p, return GS_OK; } - /* Preliminarily mark non-addressed complex variables as eligible - for promotion to gimple registers. We'll transform their uses - as we find them. */ - if ((TREE_CODE (TREE_TYPE (decl)) == COMPLEX_TYPE - || TREE_CODE (TREE_TYPE (decl)) == VECTOR_TYPE) - && !TREE_THIS_VOLATILE (decl) - && !needs_to_live_in_memory (decl)) - DECL_GIMPLE_REG_P (decl) = 1; - /* If the decl is not addressable, then it is being used in some expression or on the right hand side of a statement, and it can be put into a readonly data section. */ @@ -5617,8 +5595,7 @@ is_gimple_stmt (tree t) /* Promote partial stores to COMPLEX variables to total stores. *EXPR_P is - a MODIFY_EXPR with a lhs of a REAL/IMAGPART_EXPR of a variable with - DECL_GIMPLE_REG_P set. + a MODIFY_EXPR with a lhs of a REAL/IMAGPART_EXPR of a gimple register. IMPORTANT NOTE: This promotion is performed by introducing a load of the other, unmodified part of the complex object just before the total store. @@ -14992,7 +14969,6 @@ flag_instrument_functions_exclude_p (tree fndecl) void gimplify_function_tree (tree fndecl) { - tree parm, ret; gimple_seq seq; gbind *bind; @@ -15007,24 +14983,6 @@ gimplify_function_tree (tree fndecl) if necessary. */ cfun->curr_properties |= PROP_gimple_lva; - for (parm = DECL_ARGUMENTS (fndecl); parm ; parm = DECL_CHAIN (parm)) - { - /* Preliminarily mark non-addressed complex variables as eligible - for promotion to gimple registers. We'll transform their uses - as we find them. */ - if ((TREE_CODE (TREE_TYPE (parm)) == COMPLEX_TYPE - || TREE_CODE (TREE_TYPE (parm)) == VECTOR_TYPE) - && !TREE_THIS_VOLATILE (parm) - && !needs_to_live_in_memory (parm)) - DECL_GIMPLE_REG_P (parm) = 1; - } - - ret = DECL_RESULT (fndecl); - if ((TREE_CODE (TREE_TYPE (ret)) == COMPLEX_TYPE - || TREE_CODE (TREE_TYPE (ret)) == VECTOR_TYPE) - && !needs_to_live_in_memory (ret)) - DECL_GIMPLE_REG_P (ret) = 1; - if (asan_sanitize_use_after_scope () && sanitize_flags_p (SANITIZE_ADDRESS)) asan_poisoned_variables = new hash_set (); bind = gimplify_body (fndecl, true); -- cgit v1.1 From 9f0f7da9aa98eec28b4e5e34ade0aa0028df161d Mon Sep 17 00:00:00 2001 From: Tobias Burnus Date: Fri, 15 May 2020 11:50:34 +0200 Subject: [OpenMP] Fix 'omp exit data' for Fortran arrays (PR 94635) gcc/ PR middle-end/94635 * gimplify.c (gimplify_scan_omp_clauses): For MAP_TO_PSET with OMP_TARGET_EXIT_DATA, use 'release:' unless the associated item is 'delete:'. gcc/testsuite PR middle-end/94635 * gfortran.dg/gomp/target-exit-data.f90: New. --- gcc/gimplify.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'gcc/gimplify.c') diff --git a/gcc/gimplify.c b/gcc/gimplify.c index 1d532e6..e104e76 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -8766,7 +8766,9 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p, to be delete; hence, we turn the MAP_TO_PSET into a MAP_DELETE. */ if (code == OMP_TARGET_EXIT_DATA && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_TO_PSET) - OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_DELETE); + OMP_CLAUSE_SET_MAP_KIND (c, OMP_CLAUSE_MAP_KIND (*prev_list_p) + == GOMP_MAP_DELETE + ? GOMP_MAP_DELETE : GOMP_MAP_RELEASE); else if ((code == OMP_TARGET_EXIT_DATA || code == OMP_TARGET_UPDATE) && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_TO_PSET)) -- cgit v1.1 From f1f862aec2c3b93dbd6adfc35b0e1b6034e59c21 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Tue, 26 May 2020 09:35:21 +0200 Subject: openmp: Ensure copy ctor for composite distribute parallel for class iterators is instantiated [PR95197] During gimplification omp_finish_clause langhook is called in several places to add the language specific info to the clause like what default/copy ctors, dtors and assignment operators should be used. Unfortunately, if it refers to some not yet instantiated method, during gimplification it is too late and the methods will not be instantiated anymore. For other cases, the genericizer has code to detect those and instantiate whatever is needed, this change adds the same for distribute parallel for class iterators where we under the hood need a copy constructor for the iterator to implement it. 2020-05-26 Jakub Jelinek PR c++/95197 * gimplify.c (find_combined_omp_for): Move to omp-general.c. * omp-general.h (find_combined_omp_for): Declare. * omp-general.c: Include tree-iterator.h. (find_combined_omp_for): New function, moved from gimplify.c. * cp-gimplify.c: Include omp-general.h. (cp_genericize_r) : For class iteration variables in composite distribute parallel for, instantiate copy ctor of their types. --- gcc/gimplify.c | 56 -------------------------------------------------------- 1 file changed, 56 deletions(-) (limited to 'gcc/gimplify.c') diff --git a/gcc/gimplify.c b/gcc/gimplify.c index e104e76..7f00d97 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -10963,62 +10963,6 @@ gimplify_omp_task (tree *expr_p, gimple_seq *pre_p) *expr_p = NULL_TREE; } -/* Helper function of gimplify_omp_for, find OMP_FOR resp. OMP_SIMD - with non-NULL OMP_FOR_INIT. Also, fill in pdata array, - pdata[0] non-NULL if there is anything non-trivial in between, pdata[1] - is address of OMP_PARALLEL in between if any, pdata[2] is address of - OMP_FOR in between if any and pdata[3] is address of the inner - OMP_FOR/OMP_SIMD. */ - -static tree -find_combined_omp_for (tree *tp, int *walk_subtrees, void *data) -{ - tree **pdata = (tree **) data; - *walk_subtrees = 0; - switch (TREE_CODE (*tp)) - { - case OMP_FOR: - if (OMP_FOR_INIT (*tp) != NULL_TREE) - { - pdata[3] = tp; - return *tp; - } - pdata[2] = tp; - *walk_subtrees = 1; - break; - case OMP_SIMD: - if (OMP_FOR_INIT (*tp) != NULL_TREE) - { - pdata[3] = tp; - return *tp; - } - break; - case BIND_EXPR: - if (BIND_EXPR_VARS (*tp) - || (BIND_EXPR_BLOCK (*tp) - && BLOCK_VARS (BIND_EXPR_BLOCK (*tp)))) - pdata[0] = tp; - *walk_subtrees = 1; - break; - case STATEMENT_LIST: - if (!tsi_one_before_end_p (tsi_start (*tp))) - pdata[0] = tp; - *walk_subtrees = 1; - break; - case TRY_FINALLY_EXPR: - pdata[0] = tp; - *walk_subtrees = 1; - break; - case OMP_PARALLEL: - pdata[1] = tp; - *walk_subtrees = 1; - break; - default: - break; - } - return NULL_TREE; -} - /* Gimplify the gross structure of an OMP_FOR statement. */ static enum gimplify_status -- cgit v1.1 From 93535a2b40367e6f68433295b37dc52c0e9c2c55 Mon Sep 17 00:00:00 2001 From: Tobias Burnus Date: Wed, 3 Jun 2020 12:28:25 +0200 Subject: [OpenMP] Fix mapping of artificial variables (PR94874) gcc/c-family/ChangeLog: * c-common.h (c_omp_predetermined_mapping): Declare. * c-omp.c (c_omp_predetermined_mapping): New. gcc/c/ChangeLog: * c-objc-common.h (LANG_HOOKS_OMP_PREDETERMINED_MAPPING): Redefine. gcc/cp/ChangeLog: * cp-gimplify.c (cxx_omp_predetermined_mapping): New. * cp-objcp-common.h (LANG_HOOKS_OMP_PREDETERMINED_MAPPING): Redfine. * cp-tree.h (cxx_omp_predetermined_mapping): Declare. gcc/fortran/ChangeLog: * f95-lang.c (LANG_HOOKS_OMP_PREDETERMINED_MAPPING): Redefine. * trans-openmp.c (gfc_omp_predetermined_mapping): New. * trans.h (gfc_omp_predetermined_mapping): Declare. gcc/ChangeLog: * gimplify.c (omp_notice_variable): Use new hook. * langhooks-def.h (lhd_omp_predetermined_mapping): Declare. (LANG_HOOKS_OMP_PREDETERMINED_MAPPING): Define (LANG_HOOKS_DECLS): Add it. * langhooks.c (lhd_omp_predetermined_sharing): Remove bogus unused attr. (lhd_omp_predetermined_mapping): New. * langhooks.h (struct lang_hooks_for_decls): Add new hook. gcc/testsuite/ChangeLog 2020-06-03 Thomas Schwinge Tobias Burnus PR middle-end/94874 * c-c++-common/gomp/pr94874.c: New. --- gcc/gimplify.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'gcc/gimplify.c') diff --git a/gcc/gimplify.c b/gcc/gimplify.c index 7f00d97..cb08b26 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -7432,6 +7432,7 @@ omp_notice_variable (struct gimplify_omp_ctx *ctx, tree decl, bool in_code) if (!is_declare_target) { 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))) @@ -7441,7 +7442,17 @@ omp_notice_variable (struct gimplify_omp_ctx *ctx, tree decl, bool in_code) gdmk = GDMK_SCALAR; else gdmk = GDMK_AGGREGATE; - if (ctx->defaultmap[gdmk] == 0) + kind = lang_hooks.decls.omp_predetermined_mapping (decl); + if (kind != OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED) + { + if (kind == OMP_CLAUSE_DEFAULTMAP_FIRSTPRIVATE) + nflags |= GOVD_FIRSTPRIVATE; + else if (kind == OMP_CLAUSE_DEFAULTMAP_TO) + nflags |= GOVD_MAP | GOVD_MAP_TO_ONLY; + else + gcc_unreachable (); + } + else if (ctx->defaultmap[gdmk] == 0) { tree d = lang_hooks.decls.omp_report_decl (decl); error ("%qE not specified in enclosing %", -- cgit v1.1 From 1afc4672561a41dfbf4e3f2c1f35f7a5b7a20339 Mon Sep 17 00:00:00 2001 From: Thomas Schwinge Date: Wed, 20 May 2020 10:56:55 +0200 Subject: [OpenACC 'exit data'] Strip 'GOMP_MAP_STRUCT' mappings These are not itself necessary for OpenACC 'exit data' directives, and are skipped over (now) in libgomp. We might as well not emit them to start with, in line with the equivalent OpenMP directive. We keep the no-op handling in libgomp for the reason of backward compatibility. gcc/ * gimplify.c (gimplify_adjust_omp_clauses): Remove 'GOMP_MAP_STRUCT' mapping from OpenACC 'exit data' directives. gcc/testsuite/ * c-c++-common/goacc/struct-enter-exit-data-1.c: New file. libgomp/ * oacc-mem.c (goacc_exit_data_internal) : Explain special handling. Co-Authored-By: Julian Brown --- 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 cb08b26..e14932f 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -10396,7 +10396,8 @@ gimplify_adjust_omp_clauses (gimple_seq *pre_p, gimple_seq body, tree *list_p, } } else if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_STRUCT - && code == OMP_TARGET_EXIT_DATA) + && (code == OMP_TARGET_EXIT_DATA + || code == OACC_EXIT_DATA)) remove = true; else if (DECL_SIZE (decl) && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST -- cgit v1.1 From 06712fc68dc9843d9af7c7ac10047f49d305ad76 Mon Sep 17 00:00:00 2001 From: Marco Elver Date: Wed, 10 Jun 2020 16:21:21 +0200 Subject: tsan: Add param to disable func-entry-exit instrumentation Adds param tsan-instrument-func-entry-exit, which controls if __tsan_func_{entry,exit} calls should be emitted or not. The default behaviour is to emit the calls. This may be required by alternative race detection runtimes. One such runtime is the Kernel Concurrency Sanitizer (KCSAN): https://github.com/google/ktsan/wiki/KCSAN After this change, GCC should satisfy all requirements for KCSAN: https://lore.kernel.org/lkml/20200515150338.190344-7-elver@google.com/ gcc/ChangeLog: * gimplify.c (gimplify_function_tree): Optimize and do not emit IFN_TSAN_FUNC_EXIT in a finally block if we do not need it. * params.opt: Add --param=tsan-instrument-func-entry-exit=. * tsan.c (instrument_memory_accesses): Make fentry_exit_instrument bool depend on new param. gcc/testsuite/ChangeLog: * c-c++-common/tsan/func_entry_exit.c: New test. * c-c++-common/tsan/func_entry_exit_disabled.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 e14932f..416fb60 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -15011,7 +15011,8 @@ gimplify_function_tree (tree fndecl) bind = new_bind; } - if (sanitize_flags_p (SANITIZE_THREAD)) + if (sanitize_flags_p (SANITIZE_THREAD) + && param_tsan_instrument_func_entry_exit) { gcall *call = gimple_build_call_internal (IFN_TSAN_FUNC_EXIT, 0); gimple *tf = gimple_build_try (seq, call, GIMPLE_TRY_FINALLY); -- cgit v1.1 From c7bac01ab41f019a66bc07fc704752f436707eb8 Mon Sep 17 00:00:00 2001 From: Eric Botcazou Date: Mon, 15 Jun 2020 19:56:00 +0200 Subject: Optimize assignment to volatile aggregate variable gimplify_modify_expr_rhs has an optimization whereby the assignment to an aggregate variable from a read-only object with a DECL_INITIAL is optimized into the direct assignment of the DECL_INITIAL, provided that no temporary is created in the process. The optimization is blocked if the read-only object is volatile, which is OK as per the semantics of volatile, but also if the target variable is volatile, on the grounds that the modified assignment might end up being done on a per field basis, which is also OK. But this latter restriction is enforced a priori and there are cases where the modified assignment would be OK, for example if there is only one field or the DECL_INITIAL is equivalent to the empty CONSTRUCTOR, i.e. all zeros. So, in the latter case, the patch changes gimplify_modify_expr_rhs to ask gimplify_init_constructor whether the assignment would be done as a block, which is easy because gimplify_init_constructor knows that it must create a temporary if the LHS is volatile and this would not be the case, so it's just a matter of completing the NOTIFY_TEMP_CREATION mechanism. gcc/ChangeLog * gimplify.c (gimplify_init_constructor) : Declare new ENSURE_SINGLE_ACCESS constant and move variables down. If it is true and all elements are zero, then always clear. Return GS_ERROR if a temporary would be created for it and NOTIFY_TEMP_CREATION set. (gimplify_modify_expr_rhs) : If the target is volatile but the type is aggregate non-addressable, ask gimplify_init_constructor whether it can generate a single access to the target. gcc/testsuite/ChangeLog * gnat.dg/aggr30.ads, gnat.dg/aggr30.adb: New test. --- gcc/gimplify.c | 53 ++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 36 insertions(+), 17 deletions(-) (limited to 'gcc/gimplify.c') diff --git a/gcc/gimplify.c b/gcc/gimplify.c index 416fb60..9851edf 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -4865,10 +4865,6 @@ gimplify_init_constructor (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, case QUAL_UNION_TYPE: case ARRAY_TYPE: { - 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; /* Use readonly data for initializers of this or smaller size regardless of the num_nonzero_elements / num_unique_nonzero_elements ratio. */ @@ -4876,6 +4872,17 @@ gimplify_init_constructor (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, /* If num_nonzero_elements / num_unique_nonzero_elements ratio is smaller than this, use readonly data. */ const int unique_nonzero_ratio = 8; + /* True if a single access of the object must be ensured. This is the + case if the target is volatile, the type is non-addressable and more + than one field need to be assigned. */ + const bool ensure_single_access + = TREE_THIS_VOLATILE (object) + && !TREE_ADDRESSABLE (type) + && vec_safe_length (elts) > 1; + 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; /* Aggregate types must lower constructors to initialization of individual elements. The exception is that a CONSTRUCTOR node @@ -4914,6 +4921,7 @@ gimplify_init_constructor (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, { if (notify_temp_creation) return GS_ERROR; + DECL_INITIAL (object) = ctor; TREE_STATIC (object) = 1; if (!DECL_NAME (object)) @@ -4961,6 +4969,10 @@ gimplify_init_constructor (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, /* If there are "lots" of zeros, it's more efficient to clear the memory and then set the nonzero elements. */ cleared = true; + else if (ensure_single_access && num_nonzero_elements == 0) + /* If a single access to the target must be ensured and all elements + are zero, then it's optimal to clear whatever their number. */ + cleared = true; else cleared = false; @@ -5029,13 +5041,14 @@ gimplify_init_constructor (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, } } - /* If the target is volatile, we have non-zero elements and more than - one field to assign, initialize the target from a temporary. */ - if (TREE_THIS_VOLATILE (object) - && !TREE_ADDRESSABLE (type) - && (num_nonzero_elements > 0 || !cleared) - && vec_safe_length (elts) > 1) + /* If a single access to the target must be ensured and there are + nonzero elements or the zero elements are not assigned en masse, + initialize the target from a temporary. */ + if (ensure_single_access && (num_nonzero_elements > 0 || !cleared)) { + if (notify_temp_creation) + return GS_ERROR; + tree temp = create_tmp_var (TYPE_MAIN_VARIANT (type)); TREE_OPERAND (*expr_p, 0) = temp; *expr_p = build2 (COMPOUND_EXPR, TREE_TYPE (*expr_p), @@ -5243,14 +5256,20 @@ gimplify_modify_expr_rhs (tree *expr_p, tree *from_p, tree *to_p, { case VAR_DECL: /* If we're assigning from a read-only variable initialized with - a constructor, do the direct assignment from the constructor, - but only if neither source nor target are volatile since this - latter assignment might end up being done on a per-field basis. */ - if (DECL_INITIAL (*from_p) - && TREE_READONLY (*from_p) + a constructor and not volatile, do the direct assignment from + the constructor, but only if the target is not volatile either + since this latter assignment might end up being done on a per + field basis. However, if the target is volatile and the type + is aggregate and non-addressable, gimplify_init_constructor + knows that it needs to ensure a single access to the target + and it will return GS_OK only in this case. */ + if (TREE_READONLY (*from_p) + && DECL_INITIAL (*from_p) + && TREE_CODE (DECL_INITIAL (*from_p)) == CONSTRUCTOR && !TREE_THIS_VOLATILE (*from_p) - && !TREE_THIS_VOLATILE (*to_p) - && TREE_CODE (DECL_INITIAL (*from_p)) == CONSTRUCTOR) + && (!TREE_THIS_VOLATILE (*to_p) + || (AGGREGATE_TYPE_P (TREE_TYPE (*to_p)) + && !TREE_ADDRESSABLE (TREE_TYPE (*to_p))))) { tree old_from = *from_p; enum gimplify_status subret; -- cgit v1.1 From 1160ec9a141faf1c4c0496c7412c8febeb623962 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Tue, 16 Jun 2020 16:31:13 +0200 Subject: openmp: Initial part of OpenMP 5.0 non-rectangular loop support OpenMP 5.0 adds support for non-rectangular loop collapses, e.g. triangular and more complex. This patch deals just with the diagnostics so that they aren't rejected immediately as before. As the spec generally requires as before that the iteration variable initializer and bound in the comparison as invariant vs. the outermost loop, and just add some exceptional forms that can violate that, we need to avoid folding the expressions until we can detect them and in order to avoid folding it later on, I chose to use a TREE_VEC in those expressions to hold the var_outer * expr1 + expr2 triplet, the patch adds pretty-printing of that, gimplification etc. and just sorry_at during omp expansion for now. The next step will be to implement the different cases of that one by one. 2020-06-16 Jakub Jelinek gcc/ * tree.h (OMP_FOR_NON_RECTANGULAR): Define. * gimplify.c (gimplify_omp_for): Diagnose schedule, ordered or dist_schedule clause on non-rectangular loops. Handle gimplification of non-rectangular lb/b expressions. When changing iteration variable, adjust also non-rectangular lb/b expressions referencing that. * omp-general.h (struct omp_for_data_loop): Add m1, m2 and outer members. (struct omp_for_data): Add non_rect member. * omp-general.c (omp_extract_for_data): Handle non-rectangular loops. Fill in non_rect, m1, m2 and outer. * omp-low.c (lower_omp_for): Handle non-rectangular lb/b expressions. * omp-expand.c (expand_omp_for): Emit sorry_at for unsupported non-rectangular loop cases and assert for cases that can't be non-rectangular. * tree-pretty-print.c (dump_mem_ref): Formatting fix. (dump_omp_loop_non_rect_expr): New function. (dump_generic_node): Handle non-rectangular OpenMP loops. * tree-pretty-print.h (dump_omp_loop_non_rect_expr): Declare. * gimple-pretty-print.c (dump_gimple_omp_for): Handle non-rectangular OpenMP loops. gcc/c-family/ * c-common.h (c_omp_check_loop_iv_exprs): Add an int argument. * c-omp.c (struct c_omp_check_loop_iv_data): Add maybe_nonrect and idx members. (c_omp_is_loop_iterator): New function. (c_omp_check_loop_iv_r): Use it. Add support for silent scanning if outer loop iterator is present. Perform duplicate checking through hash_set in the function rather than expecting caller to do that. Pass NULL instead of d->ppset to walk_tree_1. (c_omp_check_nonrect_loop_iv): New function. (c_omp_check_loop_iv): Use it. Fill in new members, allow non-rectangular loop forms, diagnose multiple associated loops with the same iterator. Pass NULL instead of &pset to walk_tree_1. (c_omp_check_loop_iv_exprs): Likewise. gcc/c/ * c-parser.c (c_parser_expr_no_commas): Save, clear and restore c_in_omp_for. (c_parser_omp_for_loop): Set c_in_omp_for around some calls to avoid premature c_fully_fold. Defer explicit c_fully_fold calls to after c_finish_omp_for. * c-tree.h (c_in_omp_for): Declare. * c-typeck.c (c_in_omp_for): Define. (build_modify_expr): Avoid c_fully_fold if c_in_omp_for. (digest_init): Likewise. (build_binary_op): Likewise. gcc/cp/ * semantics.c (handle_omp_for_class_iterator): Adjust c_omp_check_loop_iv_exprs caller. (finish_omp_for): Likewise. Don't call fold_build_cleanup_point_expr before calling c_finish_omp_for and c_omp_check_loop_iv, move it after those calls. * pt.c (tsubst_omp_for_iterator): Handle non-rectangular loops. gcc/testsuite/ * c-c++-common/gomp/loop-6.c: New test. * gcc.dg/gomp/loop-1.c: Don't expect diagnostics on valid non-rectangular loops. * gcc.dg/gomp/loop-2.c: New test. * g++.dg/gomp/loop-1.C: Don't expect diagnostics on valid non-rectangular loops. * g++.dg/gomp/loop-2.C: Likewise. * g++.dg/gomp/loop-5.C: New test. * g++.dg/gomp/loop-6.C: New test. --- gcc/gimplify.c | 82 +++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 78 insertions(+), 4 deletions(-) (limited to 'gcc/gimplify.c') diff --git a/gcc/gimplify.c b/gcc/gimplify.c index 9851edf..dd10119 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -11182,7 +11182,26 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p) switch (TREE_CODE (for_stmt)) { case OMP_FOR: + if (OMP_FOR_NON_RECTANGULAR (inner_for_stmt ? inner_for_stmt : for_stmt)) + { + if (omp_find_clause (OMP_FOR_CLAUSES (for_stmt), + OMP_CLAUSE_SCHEDULE)) + error_at (EXPR_LOCATION (for_stmt), + "%qs clause may not appear on non-rectangular %qs", + "schedule", "for"); + if (omp_find_clause (OMP_FOR_CLAUSES (for_stmt), OMP_CLAUSE_ORDERED)) + error_at (EXPR_LOCATION (for_stmt), + "%qs clause may not appear on non-rectangular %qs", + "ordered", "for"); + } + break; case OMP_DISTRIBUTE: + if (OMP_FOR_NON_RECTANGULAR (inner_for_stmt ? inner_for_stmt : for_stmt) + && omp_find_clause (OMP_FOR_CLAUSES (for_stmt), + OMP_CLAUSE_DIST_SCHEDULE)) + error_at (EXPR_LOCATION (for_stmt), + "%qs clause may not appear on non-rectangular %qs", + "dist_schedule", "distribute"); break; case OACC_LOOP: ort = ORT_ACC; @@ -11757,8 +11776,18 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p) else var = decl; - tret = gimplify_expr (&TREE_OPERAND (t, 1), &for_pre_body, NULL, - is_gimple_val, fb_rvalue, false); + if (TREE_CODE (TREE_OPERAND (t, 1)) == TREE_VEC) + { + tree lb = TREE_OPERAND (t, 1); + tret = gimplify_expr (&TREE_VEC_ELT (lb, 1), &for_pre_body, NULL, + is_gimple_val, fb_rvalue, false); + ret = MIN (ret, tret); + tret = gimplify_expr (&TREE_VEC_ELT (lb, 2), &for_pre_body, NULL, + is_gimple_val, fb_rvalue, false); + } + else + tret = gimplify_expr (&TREE_OPERAND (t, 1), &for_pre_body, NULL, + is_gimple_val, fb_rvalue, false); ret = MIN (ret, tret); if (ret == GS_ERROR) return ret; @@ -11768,8 +11797,18 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p) gcc_assert (COMPARISON_CLASS_P (t)); gcc_assert (TREE_OPERAND (t, 0) == decl); - tret = gimplify_expr (&TREE_OPERAND (t, 1), &for_pre_body, NULL, - is_gimple_val, fb_rvalue, false); + if (TREE_CODE (TREE_OPERAND (t, 1)) == TREE_VEC) + { + tree ub = TREE_OPERAND (t, 1); + tret = gimplify_expr (&TREE_VEC_ELT (ub, 1), &for_pre_body, NULL, + is_gimple_val, fb_rvalue, false); + ret = MIN (ret, tret); + tret = gimplify_expr (&TREE_VEC_ELT (ub, 2), &for_pre_body, NULL, + is_gimple_val, fb_rvalue, false); + } + else + tret = gimplify_expr (&TREE_OPERAND (t, 1), &for_pre_body, NULL, + is_gimple_val, fb_rvalue, false); ret = MIN (ret, tret); /* Handle OMP_FOR_INCR. */ @@ -11911,6 +11950,20 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p) pop_gimplify_context (bind); } } + if (OMP_FOR_NON_RECTANGULAR (for_stmt) && var != decl) + for (int j = i + 1; j < TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)); j++) + { + t = TREE_VEC_ELT (OMP_FOR_INIT (for_stmt), j); + gcc_assert (TREE_CODE (t) == MODIFY_EXPR); + if (TREE_CODE (TREE_OPERAND (t, 1)) == TREE_VEC + && TREE_VEC_ELT (TREE_OPERAND (t, 1), 0) == decl) + TREE_VEC_ELT (TREE_OPERAND (t, 1), 0) = var; + t = TREE_VEC_ELT (OMP_FOR_COND (for_stmt), j); + gcc_assert (COMPARISON_CLASS_P (t)); + if (TREE_CODE (TREE_OPERAND (t, 1)) == TREE_VEC + && TREE_VEC_ELT (TREE_OPERAND (t, 1), 0) == decl) + TREE_VEC_ELT (TREE_OPERAND (t, 1), 0) = var; + } } BITMAP_FREE (has_decl_expr); @@ -11955,6 +12008,27 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p) t = TREE_VEC_ELT (OMP_FOR_INCR (for_stmt), i); TREE_OPERAND (t, 1) = copy_node (TREE_OPERAND (t, 1)); TREE_OPERAND (TREE_OPERAND (t, 1), 0) = var; + if (OMP_FOR_NON_RECTANGULAR (for_stmt)) + for (int j = i + 1; + j < TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)); j++) + { + t = TREE_VEC_ELT (OMP_FOR_INIT (for_stmt), j); + gcc_assert (TREE_CODE (t) == MODIFY_EXPR); + if (TREE_CODE (TREE_OPERAND (t, 1)) == TREE_VEC + && TREE_VEC_ELT (TREE_OPERAND (t, 1), 0) == decl) + { + TREE_OPERAND (t, 1) = copy_node (TREE_OPERAND (t, 1)); + TREE_VEC_ELT (TREE_OPERAND (t, 1), 0) = var; + } + t = TREE_VEC_ELT (OMP_FOR_COND (for_stmt), j); + gcc_assert (COMPARISON_CLASS_P (t)); + if (TREE_CODE (TREE_OPERAND (t, 1)) == TREE_VEC + && TREE_VEC_ELT (TREE_OPERAND (t, 1), 0) == decl) + { + TREE_OPERAND (t, 1) = copy_node (TREE_OPERAND (t, 1)); + TREE_VEC_ELT (TREE_OPERAND (t, 1), 0) = var; + } + } } gimplify_adjust_omp_clauses (pre_p, for_body, -- cgit v1.1