138fd1498Szrj /* Lowering pass for OMP directives. Converts OMP directives into explicit
238fd1498Szrj calls to the runtime library (libgomp), data marshalling to implement data
338fd1498Szrj sharing and copying clauses, offloading to accelerators, and more.
438fd1498Szrj
538fd1498Szrj Contributed by Diego Novillo <dnovillo@redhat.com>
638fd1498Szrj
738fd1498Szrj Copyright (C) 2005-2018 Free Software Foundation, Inc.
838fd1498Szrj
938fd1498Szrj This file is part of GCC.
1038fd1498Szrj
1138fd1498Szrj GCC is free software; you can redistribute it and/or modify it under
1238fd1498Szrj the terms of the GNU General Public License as published by the Free
1338fd1498Szrj Software Foundation; either version 3, or (at your option) any later
1438fd1498Szrj version.
1538fd1498Szrj
1638fd1498Szrj GCC is distributed in the hope that it will be useful, but WITHOUT ANY
1738fd1498Szrj WARRANTY; without even the implied warranty of MERCHANTABILITY or
1838fd1498Szrj FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
1938fd1498Szrj for more details.
2038fd1498Szrj
2138fd1498Szrj You should have received a copy of the GNU General Public License
2238fd1498Szrj along with GCC; see the file COPYING3. If not see
2338fd1498Szrj <http://www.gnu.org/licenses/>. */
2438fd1498Szrj
2538fd1498Szrj #include "config.h"
2638fd1498Szrj #include "system.h"
2738fd1498Szrj #include "coretypes.h"
2838fd1498Szrj #include "backend.h"
2938fd1498Szrj #include "target.h"
3038fd1498Szrj #include "tree.h"
3138fd1498Szrj #include "gimple.h"
3238fd1498Szrj #include "tree-pass.h"
3338fd1498Szrj #include "ssa.h"
3438fd1498Szrj #include "cgraph.h"
3538fd1498Szrj #include "pretty-print.h"
3638fd1498Szrj #include "diagnostic-core.h"
3738fd1498Szrj #include "fold-const.h"
3838fd1498Szrj #include "stor-layout.h"
3938fd1498Szrj #include "internal-fn.h"
4038fd1498Szrj #include "gimple-fold.h"
4138fd1498Szrj #include "gimplify.h"
4238fd1498Szrj #include "gimple-iterator.h"
4338fd1498Szrj #include "gimplify-me.h"
4438fd1498Szrj #include "gimple-walk.h"
4538fd1498Szrj #include "tree-iterator.h"
4638fd1498Szrj #include "tree-inline.h"
4738fd1498Szrj #include "langhooks.h"
4838fd1498Szrj #include "tree-dfa.h"
4938fd1498Szrj #include "tree-ssa.h"
5038fd1498Szrj #include "splay-tree.h"
5138fd1498Szrj #include "omp-general.h"
5238fd1498Szrj #include "omp-low.h"
5338fd1498Szrj #include "omp-grid.h"
5438fd1498Szrj #include "gimple-low.h"
5538fd1498Szrj #include "symbol-summary.h"
5638fd1498Szrj #include "tree-nested.h"
5738fd1498Szrj #include "context.h"
5838fd1498Szrj #include "gomp-constants.h"
5938fd1498Szrj #include "gimple-pretty-print.h"
6038fd1498Szrj #include "hsa-common.h"
6138fd1498Szrj #include "stringpool.h"
6238fd1498Szrj #include "attribs.h"
6338fd1498Szrj
6438fd1498Szrj /* Lowering of OMP parallel and workshare constructs proceeds in two
6538fd1498Szrj phases. The first phase scans the function looking for OMP statements
6638fd1498Szrj and then for variables that must be replaced to satisfy data sharing
6738fd1498Szrj clauses. The second phase expands code for the constructs, as well as
6838fd1498Szrj re-gimplifying things when variables have been replaced with complex
6938fd1498Szrj expressions.
7038fd1498Szrj
7138fd1498Szrj Final code generation is done by pass_expand_omp. The flowgraph is
7238fd1498Szrj scanned for regions which are then moved to a new
7338fd1498Szrj function, to be invoked by the thread library, or offloaded. */
7438fd1498Szrj
7538fd1498Szrj /* Context structure. Used to store information about each parallel
7638fd1498Szrj directive in the code. */
7738fd1498Szrj
7838fd1498Szrj struct omp_context
7938fd1498Szrj {
8038fd1498Szrj /* This field must be at the beginning, as we do "inheritance": Some
8138fd1498Szrj callback functions for tree-inline.c (e.g., omp_copy_decl)
8238fd1498Szrj receive a copy_body_data pointer that is up-casted to an
8338fd1498Szrj omp_context pointer. */
8438fd1498Szrj copy_body_data cb;
8538fd1498Szrj
8638fd1498Szrj /* The tree of contexts corresponding to the encountered constructs. */
8738fd1498Szrj struct omp_context *outer;
8838fd1498Szrj gimple *stmt;
8938fd1498Szrj
9038fd1498Szrj /* Map variables to fields in a structure that allows communication
9138fd1498Szrj between sending and receiving threads. */
9238fd1498Szrj splay_tree field_map;
9338fd1498Szrj tree record_type;
9438fd1498Szrj tree sender_decl;
9538fd1498Szrj tree receiver_decl;
9638fd1498Szrj
9738fd1498Szrj /* These are used just by task contexts, if task firstprivate fn is
9838fd1498Szrj needed. srecord_type is used to communicate from the thread
9938fd1498Szrj that encountered the task construct to task firstprivate fn,
10038fd1498Szrj record_type is allocated by GOMP_task, initialized by task firstprivate
10138fd1498Szrj fn and passed to the task body fn. */
10238fd1498Szrj splay_tree sfield_map;
10338fd1498Szrj tree srecord_type;
10438fd1498Szrj
10538fd1498Szrj /* A chain of variables to add to the top-level block surrounding the
10638fd1498Szrj construct. In the case of a parallel, this is in the child function. */
10738fd1498Szrj tree block_vars;
10838fd1498Szrj
10938fd1498Szrj /* Label to which GOMP_cancel{,llation_point} and explicit and implicit
11038fd1498Szrj barriers should jump to during omplower pass. */
11138fd1498Szrj tree cancel_label;
11238fd1498Szrj
11338fd1498Szrj /* The sibling GIMPLE_OMP_FOR simd with _simt_ clause or NULL
11438fd1498Szrj otherwise. */
11538fd1498Szrj gimple *simt_stmt;
11638fd1498Szrj
11738fd1498Szrj /* Nesting depth of this context. Used to beautify error messages re
11838fd1498Szrj invalid gotos. The outermost ctx is depth 1, with depth 0 being
11938fd1498Szrj reserved for the main body of the function. */
12038fd1498Szrj int depth;
12138fd1498Szrj
12238fd1498Szrj /* True if this parallel directive is nested within another. */
12338fd1498Szrj bool is_nested;
12438fd1498Szrj
12538fd1498Szrj /* True if this construct can be cancelled. */
12638fd1498Szrj bool cancellable;
12738fd1498Szrj };
12838fd1498Szrj
12938fd1498Szrj static splay_tree all_contexts;
13038fd1498Szrj static int taskreg_nesting_level;
13138fd1498Szrj static int target_nesting_level;
13238fd1498Szrj static bitmap task_shared_vars;
13338fd1498Szrj static vec<omp_context *> taskreg_contexts;
13438fd1498Szrj
13538fd1498Szrj static void scan_omp (gimple_seq *, omp_context *);
13638fd1498Szrj static tree scan_omp_1_op (tree *, int *, void *);
13738fd1498Szrj
13838fd1498Szrj #define WALK_SUBSTMTS \
13938fd1498Szrj case GIMPLE_BIND: \
14038fd1498Szrj case GIMPLE_TRY: \
14138fd1498Szrj case GIMPLE_CATCH: \
14238fd1498Szrj case GIMPLE_EH_FILTER: \
14338fd1498Szrj case GIMPLE_TRANSACTION: \
14438fd1498Szrj /* The sub-statements for these should be walked. */ \
14538fd1498Szrj *handled_ops_p = false; \
14638fd1498Szrj break;
14738fd1498Szrj
14838fd1498Szrj /* Return true if CTX corresponds to an oacc parallel region. */
14938fd1498Szrj
15038fd1498Szrj static bool
is_oacc_parallel(omp_context * ctx)15138fd1498Szrj is_oacc_parallel (omp_context *ctx)
15238fd1498Szrj {
15338fd1498Szrj enum gimple_code outer_type = gimple_code (ctx->stmt);
15438fd1498Szrj return ((outer_type == GIMPLE_OMP_TARGET)
15538fd1498Szrj && (gimple_omp_target_kind (ctx->stmt)
15638fd1498Szrj == GF_OMP_TARGET_KIND_OACC_PARALLEL));
15738fd1498Szrj }
15838fd1498Szrj
15938fd1498Szrj /* Return true if CTX corresponds to an oacc kernels region. */
16038fd1498Szrj
16138fd1498Szrj static bool
is_oacc_kernels(omp_context * ctx)16238fd1498Szrj is_oacc_kernels (omp_context *ctx)
16338fd1498Szrj {
16438fd1498Szrj enum gimple_code outer_type = gimple_code (ctx->stmt);
16538fd1498Szrj return ((outer_type == GIMPLE_OMP_TARGET)
16638fd1498Szrj && (gimple_omp_target_kind (ctx->stmt)
16738fd1498Szrj == GF_OMP_TARGET_KIND_OACC_KERNELS));
16838fd1498Szrj }
16938fd1498Szrj
17038fd1498Szrj /* If DECL is the artificial dummy VAR_DECL created for non-static
17138fd1498Szrj data member privatization, return the underlying "this" parameter,
17238fd1498Szrj otherwise return NULL. */
17338fd1498Szrj
17438fd1498Szrj tree
omp_member_access_dummy_var(tree decl)17538fd1498Szrj omp_member_access_dummy_var (tree decl)
17638fd1498Szrj {
17738fd1498Szrj if (!VAR_P (decl)
17838fd1498Szrj || !DECL_ARTIFICIAL (decl)
17938fd1498Szrj || !DECL_IGNORED_P (decl)
18038fd1498Szrj || !DECL_HAS_VALUE_EXPR_P (decl)
18138fd1498Szrj || !lang_hooks.decls.omp_disregard_value_expr (decl, false))
18238fd1498Szrj return NULL_TREE;
18338fd1498Szrj
18438fd1498Szrj tree v = DECL_VALUE_EXPR (decl);
18538fd1498Szrj if (TREE_CODE (v) != COMPONENT_REF)
18638fd1498Szrj return NULL_TREE;
18738fd1498Szrj
18838fd1498Szrj while (1)
18938fd1498Szrj switch (TREE_CODE (v))
19038fd1498Szrj {
19138fd1498Szrj case COMPONENT_REF:
19238fd1498Szrj case MEM_REF:
19338fd1498Szrj case INDIRECT_REF:
19438fd1498Szrj CASE_CONVERT:
19538fd1498Szrj case POINTER_PLUS_EXPR:
19638fd1498Szrj v = TREE_OPERAND (v, 0);
19738fd1498Szrj continue;
19838fd1498Szrj case PARM_DECL:
19938fd1498Szrj if (DECL_CONTEXT (v) == current_function_decl
20038fd1498Szrj && DECL_ARTIFICIAL (v)
20138fd1498Szrj && TREE_CODE (TREE_TYPE (v)) == POINTER_TYPE)
20238fd1498Szrj return v;
20338fd1498Szrj return NULL_TREE;
20438fd1498Szrj default:
20538fd1498Szrj return NULL_TREE;
20638fd1498Szrj }
20738fd1498Szrj }
20838fd1498Szrj
20938fd1498Szrj /* Helper for unshare_and_remap, called through walk_tree. */
21038fd1498Szrj
21138fd1498Szrj static tree
unshare_and_remap_1(tree * tp,int * walk_subtrees,void * data)21238fd1498Szrj unshare_and_remap_1 (tree *tp, int *walk_subtrees, void *data)
21338fd1498Szrj {
21438fd1498Szrj tree *pair = (tree *) data;
21538fd1498Szrj if (*tp == pair[0])
21638fd1498Szrj {
21738fd1498Szrj *tp = unshare_expr (pair[1]);
21838fd1498Szrj *walk_subtrees = 0;
21938fd1498Szrj }
22038fd1498Szrj else if (IS_TYPE_OR_DECL_P (*tp))
22138fd1498Szrj *walk_subtrees = 0;
22238fd1498Szrj return NULL_TREE;
22338fd1498Szrj }
22438fd1498Szrj
22538fd1498Szrj /* Return unshare_expr (X) with all occurrences of FROM
22638fd1498Szrj replaced with TO. */
22738fd1498Szrj
22838fd1498Szrj static tree
unshare_and_remap(tree x,tree from,tree to)22938fd1498Szrj unshare_and_remap (tree x, tree from, tree to)
23038fd1498Szrj {
23138fd1498Szrj tree pair[2] = { from, to };
23238fd1498Szrj x = unshare_expr (x);
23338fd1498Szrj walk_tree (&x, unshare_and_remap_1, pair, NULL);
23438fd1498Szrj return x;
23538fd1498Szrj }
23638fd1498Szrj
23738fd1498Szrj /* Convenience function for calling scan_omp_1_op on tree operands. */
23838fd1498Szrj
23938fd1498Szrj static inline tree
scan_omp_op(tree * tp,omp_context * ctx)24038fd1498Szrj scan_omp_op (tree *tp, omp_context *ctx)
24138fd1498Szrj {
24238fd1498Szrj struct walk_stmt_info wi;
24338fd1498Szrj
24438fd1498Szrj memset (&wi, 0, sizeof (wi));
24538fd1498Szrj wi.info = ctx;
24638fd1498Szrj wi.want_locations = true;
24738fd1498Szrj
24838fd1498Szrj return walk_tree (tp, scan_omp_1_op, &wi, NULL);
24938fd1498Szrj }
25038fd1498Szrj
25138fd1498Szrj static void lower_omp (gimple_seq *, omp_context *);
25238fd1498Szrj static tree lookup_decl_in_outer_ctx (tree, omp_context *);
25338fd1498Szrj static tree maybe_lookup_decl_in_outer_ctx (tree, omp_context *);
25438fd1498Szrj
25538fd1498Szrj /* Return true if CTX is for an omp parallel. */
25638fd1498Szrj
25738fd1498Szrj static inline bool
is_parallel_ctx(omp_context * ctx)25838fd1498Szrj is_parallel_ctx (omp_context *ctx)
25938fd1498Szrj {
26038fd1498Szrj return gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL;
26138fd1498Szrj }
26238fd1498Szrj
26338fd1498Szrj
26438fd1498Szrj /* Return true if CTX is for an omp task. */
26538fd1498Szrj
26638fd1498Szrj static inline bool
is_task_ctx(omp_context * ctx)26738fd1498Szrj is_task_ctx (omp_context *ctx)
26838fd1498Szrj {
26938fd1498Szrj return gimple_code (ctx->stmt) == GIMPLE_OMP_TASK;
27038fd1498Szrj }
27138fd1498Szrj
27238fd1498Szrj
27338fd1498Szrj /* Return true if CTX is for an omp taskloop. */
27438fd1498Szrj
27538fd1498Szrj static inline bool
is_taskloop_ctx(omp_context * ctx)27638fd1498Szrj is_taskloop_ctx (omp_context *ctx)
27738fd1498Szrj {
27838fd1498Szrj return gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
27938fd1498Szrj && gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_TASKLOOP;
28038fd1498Szrj }
28138fd1498Szrj
28238fd1498Szrj
28338fd1498Szrj /* Return true if CTX is for an omp parallel or omp task. */
28438fd1498Szrj
28538fd1498Szrj static inline bool
is_taskreg_ctx(omp_context * ctx)28638fd1498Szrj is_taskreg_ctx (omp_context *ctx)
28738fd1498Szrj {
28838fd1498Szrj return is_parallel_ctx (ctx) || is_task_ctx (ctx);
28938fd1498Szrj }
29038fd1498Szrj
29138fd1498Szrj /* Return true if EXPR is variable sized. */
29238fd1498Szrj
29338fd1498Szrj static inline bool
is_variable_sized(const_tree expr)29438fd1498Szrj is_variable_sized (const_tree expr)
29538fd1498Szrj {
29638fd1498Szrj return !TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (expr)));
29738fd1498Szrj }
29838fd1498Szrj
29938fd1498Szrj /* Lookup variables. The "maybe" form
30038fd1498Szrj allows for the variable form to not have been entered, otherwise we
30138fd1498Szrj assert that the variable must have been entered. */
30238fd1498Szrj
30338fd1498Szrj static inline tree
lookup_decl(tree var,omp_context * ctx)30438fd1498Szrj lookup_decl (tree var, omp_context *ctx)
30538fd1498Szrj {
30638fd1498Szrj tree *n = ctx->cb.decl_map->get (var);
30738fd1498Szrj return *n;
30838fd1498Szrj }
30938fd1498Szrj
31038fd1498Szrj static inline tree
maybe_lookup_decl(const_tree var,omp_context * ctx)31138fd1498Szrj maybe_lookup_decl (const_tree var, omp_context *ctx)
31238fd1498Szrj {
31338fd1498Szrj tree *n = ctx->cb.decl_map->get (const_cast<tree> (var));
31438fd1498Szrj return n ? *n : NULL_TREE;
31538fd1498Szrj }
31638fd1498Szrj
31738fd1498Szrj static inline tree
lookup_field(tree var,omp_context * ctx)31838fd1498Szrj lookup_field (tree var, omp_context *ctx)
31938fd1498Szrj {
32038fd1498Szrj splay_tree_node n;
32138fd1498Szrj n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
32238fd1498Szrj return (tree) n->value;
32338fd1498Szrj }
32438fd1498Szrj
32538fd1498Szrj static inline tree
lookup_sfield(splay_tree_key key,omp_context * ctx)32638fd1498Szrj lookup_sfield (splay_tree_key key, omp_context *ctx)
32738fd1498Szrj {
32838fd1498Szrj splay_tree_node n;
32938fd1498Szrj n = splay_tree_lookup (ctx->sfield_map
33038fd1498Szrj ? ctx->sfield_map : ctx->field_map, key);
33138fd1498Szrj return (tree) n->value;
33238fd1498Szrj }
33338fd1498Szrj
33438fd1498Szrj static inline tree
lookup_sfield(tree var,omp_context * ctx)33538fd1498Szrj lookup_sfield (tree var, omp_context *ctx)
33638fd1498Szrj {
33738fd1498Szrj return lookup_sfield ((splay_tree_key) var, ctx);
33838fd1498Szrj }
33938fd1498Szrj
34038fd1498Szrj static inline tree
maybe_lookup_field(splay_tree_key key,omp_context * ctx)34138fd1498Szrj maybe_lookup_field (splay_tree_key key, omp_context *ctx)
34238fd1498Szrj {
34338fd1498Szrj splay_tree_node n;
34438fd1498Szrj n = splay_tree_lookup (ctx->field_map, key);
34538fd1498Szrj return n ? (tree) n->value : NULL_TREE;
34638fd1498Szrj }
34738fd1498Szrj
34838fd1498Szrj static inline tree
maybe_lookup_field(tree var,omp_context * ctx)34938fd1498Szrj maybe_lookup_field (tree var, omp_context *ctx)
35038fd1498Szrj {
35138fd1498Szrj return maybe_lookup_field ((splay_tree_key) var, ctx);
35238fd1498Szrj }
35338fd1498Szrj
35438fd1498Szrj /* Return true if DECL should be copied by pointer. SHARED_CTX is
35538fd1498Szrj the parallel context if DECL is to be shared. */
35638fd1498Szrj
35738fd1498Szrj static bool
use_pointer_for_field(tree decl,omp_context * shared_ctx)35838fd1498Szrj use_pointer_for_field (tree decl, omp_context *shared_ctx)
35938fd1498Szrj {
36038fd1498Szrj if (AGGREGATE_TYPE_P (TREE_TYPE (decl))
36138fd1498Szrj || TYPE_ATOMIC (TREE_TYPE (decl)))
36238fd1498Szrj return true;
36338fd1498Szrj
36438fd1498Szrj /* We can only use copy-in/copy-out semantics for shared variables
36538fd1498Szrj when we know the value is not accessible from an outer scope. */
36638fd1498Szrj if (shared_ctx)
36738fd1498Szrj {
36838fd1498Szrj gcc_assert (!is_gimple_omp_oacc (shared_ctx->stmt));
36938fd1498Szrj
37038fd1498Szrj /* ??? Trivially accessible from anywhere. But why would we even
37138fd1498Szrj be passing an address in this case? Should we simply assert
37238fd1498Szrj this to be false, or should we have a cleanup pass that removes
37338fd1498Szrj these from the list of mappings? */
37438fd1498Szrj if (TREE_STATIC (decl) || DECL_EXTERNAL (decl))
37538fd1498Szrj return true;
37638fd1498Szrj
37738fd1498Szrj /* For variables with DECL_HAS_VALUE_EXPR_P set, we cannot tell
37838fd1498Szrj without analyzing the expression whether or not its location
37938fd1498Szrj is accessible to anyone else. In the case of nested parallel
38038fd1498Szrj regions it certainly may be. */
38138fd1498Szrj if (TREE_CODE (decl) != RESULT_DECL && DECL_HAS_VALUE_EXPR_P (decl))
38238fd1498Szrj return true;
38338fd1498Szrj
38438fd1498Szrj /* Do not use copy-in/copy-out for variables that have their
38538fd1498Szrj address taken. */
38638fd1498Szrj if (TREE_ADDRESSABLE (decl))
38738fd1498Szrj return true;
38838fd1498Szrj
38938fd1498Szrj /* lower_send_shared_vars only uses copy-in, but not copy-out
39038fd1498Szrj for these. */
39138fd1498Szrj if (TREE_READONLY (decl)
39238fd1498Szrj || ((TREE_CODE (decl) == RESULT_DECL
39338fd1498Szrj || TREE_CODE (decl) == PARM_DECL)
39438fd1498Szrj && DECL_BY_REFERENCE (decl)))
39538fd1498Szrj return false;
39638fd1498Szrj
39738fd1498Szrj /* Disallow copy-in/out in nested parallel if
39838fd1498Szrj decl is shared in outer parallel, otherwise
39938fd1498Szrj each thread could store the shared variable
40038fd1498Szrj in its own copy-in location, making the
40138fd1498Szrj variable no longer really shared. */
40238fd1498Szrj if (shared_ctx->is_nested)
40338fd1498Szrj {
40438fd1498Szrj omp_context *up;
40538fd1498Szrj
40638fd1498Szrj for (up = shared_ctx->outer; up; up = up->outer)
40738fd1498Szrj if (is_taskreg_ctx (up) && maybe_lookup_decl (decl, up))
40838fd1498Szrj break;
40938fd1498Szrj
41038fd1498Szrj if (up)
41138fd1498Szrj {
41238fd1498Szrj tree c;
41338fd1498Szrj
41438fd1498Szrj for (c = gimple_omp_taskreg_clauses (up->stmt);
41538fd1498Szrj c; c = OMP_CLAUSE_CHAIN (c))
41638fd1498Szrj if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
41738fd1498Szrj && OMP_CLAUSE_DECL (c) == decl)
41838fd1498Szrj break;
41938fd1498Szrj
42038fd1498Szrj if (c)
42138fd1498Szrj goto maybe_mark_addressable_and_ret;
42238fd1498Szrj }
42338fd1498Szrj }
42438fd1498Szrj
42538fd1498Szrj /* For tasks avoid using copy-in/out. As tasks can be
42638fd1498Szrj deferred or executed in different thread, when GOMP_task
42738fd1498Szrj returns, the task hasn't necessarily terminated. */
42838fd1498Szrj if (is_task_ctx (shared_ctx))
42938fd1498Szrj {
43038fd1498Szrj tree outer;
43138fd1498Szrj maybe_mark_addressable_and_ret:
43238fd1498Szrj outer = maybe_lookup_decl_in_outer_ctx (decl, shared_ctx);
43338fd1498Szrj if (is_gimple_reg (outer) && !omp_member_access_dummy_var (outer))
43438fd1498Szrj {
43538fd1498Szrj /* Taking address of OUTER in lower_send_shared_vars
43638fd1498Szrj might need regimplification of everything that uses the
43738fd1498Szrj variable. */
43838fd1498Szrj if (!task_shared_vars)
43938fd1498Szrj task_shared_vars = BITMAP_ALLOC (NULL);
44038fd1498Szrj bitmap_set_bit (task_shared_vars, DECL_UID (outer));
44138fd1498Szrj TREE_ADDRESSABLE (outer) = 1;
44238fd1498Szrj }
44338fd1498Szrj return true;
44438fd1498Szrj }
44538fd1498Szrj }
44638fd1498Szrj
44738fd1498Szrj return false;
44838fd1498Szrj }
44938fd1498Szrj
45038fd1498Szrj /* Construct a new automatic decl similar to VAR. */
45138fd1498Szrj
45238fd1498Szrj static tree
omp_copy_decl_2(tree var,tree name,tree type,omp_context * ctx)45338fd1498Szrj omp_copy_decl_2 (tree var, tree name, tree type, omp_context *ctx)
45438fd1498Szrj {
45538fd1498Szrj tree copy = copy_var_decl (var, name, type);
45638fd1498Szrj
45738fd1498Szrj DECL_CONTEXT (copy) = current_function_decl;
45838fd1498Szrj DECL_CHAIN (copy) = ctx->block_vars;
45938fd1498Szrj /* If VAR is listed in task_shared_vars, it means it wasn't
46038fd1498Szrj originally addressable and is just because task needs to take
46138fd1498Szrj it's address. But we don't need to take address of privatizations
46238fd1498Szrj from that var. */
46338fd1498Szrj if (TREE_ADDRESSABLE (var)
46438fd1498Szrj && task_shared_vars
46538fd1498Szrj && bitmap_bit_p (task_shared_vars, DECL_UID (var)))
46638fd1498Szrj TREE_ADDRESSABLE (copy) = 0;
46738fd1498Szrj ctx->block_vars = copy;
46838fd1498Szrj
46938fd1498Szrj return copy;
47038fd1498Szrj }
47138fd1498Szrj
47238fd1498Szrj static tree
omp_copy_decl_1(tree var,omp_context * ctx)47338fd1498Szrj omp_copy_decl_1 (tree var, omp_context *ctx)
47438fd1498Szrj {
47538fd1498Szrj return omp_copy_decl_2 (var, DECL_NAME (var), TREE_TYPE (var), ctx);
47638fd1498Szrj }
47738fd1498Szrj
47838fd1498Szrj /* Build COMPONENT_REF and set TREE_THIS_VOLATILE and TREE_READONLY on it
47938fd1498Szrj as appropriate. */
48038fd1498Szrj static tree
omp_build_component_ref(tree obj,tree field)48138fd1498Szrj omp_build_component_ref (tree obj, tree field)
48238fd1498Szrj {
48338fd1498Szrj tree ret = build3 (COMPONENT_REF, TREE_TYPE (field), obj, field, NULL);
48438fd1498Szrj if (TREE_THIS_VOLATILE (field))
48538fd1498Szrj TREE_THIS_VOLATILE (ret) |= 1;
48638fd1498Szrj if (TREE_READONLY (field))
48738fd1498Szrj TREE_READONLY (ret) |= 1;
48838fd1498Szrj return ret;
48938fd1498Szrj }
49038fd1498Szrj
49138fd1498Szrj /* Build tree nodes to access the field for VAR on the receiver side. */
49238fd1498Szrj
49338fd1498Szrj static tree
build_receiver_ref(tree var,bool by_ref,omp_context * ctx)49438fd1498Szrj build_receiver_ref (tree var, bool by_ref, omp_context *ctx)
49538fd1498Szrj {
49638fd1498Szrj tree x, field = lookup_field (var, ctx);
49738fd1498Szrj
49838fd1498Szrj /* If the receiver record type was remapped in the child function,
49938fd1498Szrj remap the field into the new record type. */
50038fd1498Szrj x = maybe_lookup_field (field, ctx);
50138fd1498Szrj if (x != NULL)
50238fd1498Szrj field = x;
50338fd1498Szrj
50438fd1498Szrj x = build_simple_mem_ref (ctx->receiver_decl);
50538fd1498Szrj TREE_THIS_NOTRAP (x) = 1;
50638fd1498Szrj x = omp_build_component_ref (x, field);
50738fd1498Szrj if (by_ref)
50838fd1498Szrj {
50938fd1498Szrj x = build_simple_mem_ref (x);
51038fd1498Szrj TREE_THIS_NOTRAP (x) = 1;
51138fd1498Szrj }
51238fd1498Szrj
51338fd1498Szrj return x;
51438fd1498Szrj }
51538fd1498Szrj
51638fd1498Szrj /* Build tree nodes to access VAR in the scope outer to CTX. In the case
51738fd1498Szrj of a parallel, this is a component reference; for workshare constructs
51838fd1498Szrj this is some variable. */
51938fd1498Szrj
52038fd1498Szrj static tree
52138fd1498Szrj build_outer_var_ref (tree var, omp_context *ctx,
52238fd1498Szrj enum omp_clause_code code = OMP_CLAUSE_ERROR)
52338fd1498Szrj {
52438fd1498Szrj tree x;
52538fd1498Szrj
52638fd1498Szrj if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx)))
52738fd1498Szrj x = var;
52838fd1498Szrj else if (is_variable_sized (var))
52938fd1498Szrj {
53038fd1498Szrj x = TREE_OPERAND (DECL_VALUE_EXPR (var), 0);
53138fd1498Szrj x = build_outer_var_ref (x, ctx, code);
53238fd1498Szrj x = build_simple_mem_ref (x);
53338fd1498Szrj }
53438fd1498Szrj else if (is_taskreg_ctx (ctx))
53538fd1498Szrj {
53638fd1498Szrj bool by_ref = use_pointer_for_field (var, NULL);
53738fd1498Szrj x = build_receiver_ref (var, by_ref, ctx);
53838fd1498Szrj }
53938fd1498Szrj else if ((gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
54038fd1498Szrj && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
54138fd1498Szrj || (code == OMP_CLAUSE_PRIVATE
54238fd1498Szrj && (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
54338fd1498Szrj || gimple_code (ctx->stmt) == GIMPLE_OMP_SECTIONS
54438fd1498Szrj || gimple_code (ctx->stmt) == GIMPLE_OMP_SINGLE)))
54538fd1498Szrj {
54638fd1498Szrj /* #pragma omp simd isn't a worksharing construct, and can reference
54738fd1498Szrj even private vars in its linear etc. clauses.
54838fd1498Szrj Similarly for OMP_CLAUSE_PRIVATE with outer ref, that can refer
54938fd1498Szrj to private vars in all worksharing constructs. */
55038fd1498Szrj x = NULL_TREE;
55138fd1498Szrj if (ctx->outer && is_taskreg_ctx (ctx))
55238fd1498Szrj x = lookup_decl (var, ctx->outer);
55338fd1498Szrj else if (ctx->outer)
55438fd1498Szrj x = maybe_lookup_decl_in_outer_ctx (var, ctx);
55538fd1498Szrj if (x == NULL_TREE)
55638fd1498Szrj x = var;
55738fd1498Szrj }
55838fd1498Szrj else if (code == OMP_CLAUSE_LASTPRIVATE && is_taskloop_ctx (ctx))
55938fd1498Szrj {
56038fd1498Szrj gcc_assert (ctx->outer);
56138fd1498Szrj splay_tree_node n
56238fd1498Szrj = splay_tree_lookup (ctx->outer->field_map,
56338fd1498Szrj (splay_tree_key) &DECL_UID (var));
56438fd1498Szrj if (n == NULL)
56538fd1498Szrj {
56638fd1498Szrj if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx->outer)))
56738fd1498Szrj x = var;
56838fd1498Szrj else
56938fd1498Szrj x = lookup_decl (var, ctx->outer);
57038fd1498Szrj }
57138fd1498Szrj else
57238fd1498Szrj {
57338fd1498Szrj tree field = (tree) n->value;
57438fd1498Szrj /* If the receiver record type was remapped in the child function,
57538fd1498Szrj remap the field into the new record type. */
57638fd1498Szrj x = maybe_lookup_field (field, ctx->outer);
57738fd1498Szrj if (x != NULL)
57838fd1498Szrj field = x;
57938fd1498Szrj
58038fd1498Szrj x = build_simple_mem_ref (ctx->outer->receiver_decl);
58138fd1498Szrj x = omp_build_component_ref (x, field);
58238fd1498Szrj if (use_pointer_for_field (var, ctx->outer))
58338fd1498Szrj x = build_simple_mem_ref (x);
58438fd1498Szrj }
58538fd1498Szrj }
58638fd1498Szrj else if (ctx->outer)
58738fd1498Szrj {
58838fd1498Szrj omp_context *outer = ctx->outer;
58938fd1498Szrj if (gimple_code (outer->stmt) == GIMPLE_OMP_GRID_BODY)
59038fd1498Szrj {
59138fd1498Szrj outer = outer->outer;
59238fd1498Szrj gcc_assert (outer
59338fd1498Szrj && gimple_code (outer->stmt) != GIMPLE_OMP_GRID_BODY);
59438fd1498Szrj }
59538fd1498Szrj x = lookup_decl (var, outer);
59638fd1498Szrj }
59738fd1498Szrj else if (omp_is_reference (var))
59838fd1498Szrj /* This can happen with orphaned constructs. If var is reference, it is
59938fd1498Szrj possible it is shared and as such valid. */
60038fd1498Szrj x = var;
60138fd1498Szrj else if (omp_member_access_dummy_var (var))
60238fd1498Szrj x = var;
60338fd1498Szrj else
60438fd1498Szrj gcc_unreachable ();
60538fd1498Szrj
60638fd1498Szrj if (x == var)
60738fd1498Szrj {
60838fd1498Szrj tree t = omp_member_access_dummy_var (var);
60938fd1498Szrj if (t)
61038fd1498Szrj {
61138fd1498Szrj x = DECL_VALUE_EXPR (var);
61238fd1498Szrj tree o = maybe_lookup_decl_in_outer_ctx (t, ctx);
61338fd1498Szrj if (o != t)
61438fd1498Szrj x = unshare_and_remap (x, t, o);
61538fd1498Szrj else
61638fd1498Szrj x = unshare_expr (x);
61738fd1498Szrj }
61838fd1498Szrj }
61938fd1498Szrj
62038fd1498Szrj if (omp_is_reference (var))
62138fd1498Szrj x = build_simple_mem_ref (x);
62238fd1498Szrj
62338fd1498Szrj return x;
62438fd1498Szrj }
62538fd1498Szrj
62638fd1498Szrj /* Build tree nodes to access the field for VAR on the sender side. */
62738fd1498Szrj
62838fd1498Szrj static tree
build_sender_ref(splay_tree_key key,omp_context * ctx)62938fd1498Szrj build_sender_ref (splay_tree_key key, omp_context *ctx)
63038fd1498Szrj {
63138fd1498Szrj tree field = lookup_sfield (key, ctx);
63238fd1498Szrj return omp_build_component_ref (ctx->sender_decl, field);
63338fd1498Szrj }
63438fd1498Szrj
63538fd1498Szrj static tree
build_sender_ref(tree var,omp_context * ctx)63638fd1498Szrj build_sender_ref (tree var, omp_context *ctx)
63738fd1498Szrj {
63838fd1498Szrj return build_sender_ref ((splay_tree_key) var, ctx);
63938fd1498Szrj }
64038fd1498Szrj
64138fd1498Szrj /* Add a new field for VAR inside the structure CTX->SENDER_DECL. If
64238fd1498Szrj BASE_POINTERS_RESTRICT, declare the field with restrict. */
64338fd1498Szrj
64438fd1498Szrj static void
64538fd1498Szrj install_var_field (tree var, bool by_ref, int mask, omp_context *ctx,
64638fd1498Szrj bool base_pointers_restrict = false)
64738fd1498Szrj {
64838fd1498Szrj tree field, type, sfield = NULL_TREE;
64938fd1498Szrj splay_tree_key key = (splay_tree_key) var;
65038fd1498Szrj
65138fd1498Szrj if ((mask & 8) != 0)
65238fd1498Szrj {
65338fd1498Szrj key = (splay_tree_key) &DECL_UID (var);
65438fd1498Szrj gcc_checking_assert (key != (splay_tree_key) var);
65538fd1498Szrj }
65638fd1498Szrj gcc_assert ((mask & 1) == 0
65738fd1498Szrj || !splay_tree_lookup (ctx->field_map, key));
65838fd1498Szrj gcc_assert ((mask & 2) == 0 || !ctx->sfield_map
65938fd1498Szrj || !splay_tree_lookup (ctx->sfield_map, key));
66038fd1498Szrj gcc_assert ((mask & 3) == 3
66138fd1498Szrj || !is_gimple_omp_oacc (ctx->stmt));
66238fd1498Szrj
66338fd1498Szrj type = TREE_TYPE (var);
66438fd1498Szrj /* Prevent redeclaring the var in the split-off function with a restrict
66538fd1498Szrj pointer type. Note that we only clear type itself, restrict qualifiers in
66638fd1498Szrj the pointed-to type will be ignored by points-to analysis. */
66738fd1498Szrj if (POINTER_TYPE_P (type)
66838fd1498Szrj && TYPE_RESTRICT (type))
66938fd1498Szrj type = build_qualified_type (type, TYPE_QUALS (type) & ~TYPE_QUAL_RESTRICT);
67038fd1498Szrj
67138fd1498Szrj if (mask & 4)
67238fd1498Szrj {
67338fd1498Szrj gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
67438fd1498Szrj type = build_pointer_type (build_pointer_type (type));
67538fd1498Szrj }
67638fd1498Szrj else if (by_ref)
67738fd1498Szrj {
67838fd1498Szrj type = build_pointer_type (type);
67938fd1498Szrj if (base_pointers_restrict)
68038fd1498Szrj type = build_qualified_type (type, TYPE_QUAL_RESTRICT);
68138fd1498Szrj }
68238fd1498Szrj else if ((mask & 3) == 1 && omp_is_reference (var))
68338fd1498Szrj type = TREE_TYPE (type);
68438fd1498Szrj
68538fd1498Szrj field = build_decl (DECL_SOURCE_LOCATION (var),
68638fd1498Szrj FIELD_DECL, DECL_NAME (var), type);
68738fd1498Szrj
68838fd1498Szrj /* Remember what variable this field was created for. This does have a
68938fd1498Szrj side effect of making dwarf2out ignore this member, so for helpful
69038fd1498Szrj debugging we clear it later in delete_omp_context. */
69138fd1498Szrj DECL_ABSTRACT_ORIGIN (field) = var;
69238fd1498Szrj if (type == TREE_TYPE (var))
69338fd1498Szrj {
69438fd1498Szrj SET_DECL_ALIGN (field, DECL_ALIGN (var));
69538fd1498Szrj DECL_USER_ALIGN (field) = DECL_USER_ALIGN (var);
69638fd1498Szrj TREE_THIS_VOLATILE (field) = TREE_THIS_VOLATILE (var);
69738fd1498Szrj }
69838fd1498Szrj else
69938fd1498Szrj SET_DECL_ALIGN (field, TYPE_ALIGN (type));
70038fd1498Szrj
70138fd1498Szrj if ((mask & 3) == 3)
70238fd1498Szrj {
70338fd1498Szrj insert_field_into_struct (ctx->record_type, field);
70438fd1498Szrj if (ctx->srecord_type)
70538fd1498Szrj {
70638fd1498Szrj sfield = build_decl (DECL_SOURCE_LOCATION (var),
70738fd1498Szrj FIELD_DECL, DECL_NAME (var), type);
70838fd1498Szrj DECL_ABSTRACT_ORIGIN (sfield) = var;
70938fd1498Szrj SET_DECL_ALIGN (sfield, DECL_ALIGN (field));
71038fd1498Szrj DECL_USER_ALIGN (sfield) = DECL_USER_ALIGN (field);
71138fd1498Szrj TREE_THIS_VOLATILE (sfield) = TREE_THIS_VOLATILE (field);
71238fd1498Szrj insert_field_into_struct (ctx->srecord_type, sfield);
71338fd1498Szrj }
71438fd1498Szrj }
71538fd1498Szrj else
71638fd1498Szrj {
71738fd1498Szrj if (ctx->srecord_type == NULL_TREE)
71838fd1498Szrj {
71938fd1498Szrj tree t;
72038fd1498Szrj
72138fd1498Szrj ctx->srecord_type = lang_hooks.types.make_type (RECORD_TYPE);
72238fd1498Szrj ctx->sfield_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
72338fd1498Szrj for (t = TYPE_FIELDS (ctx->record_type); t ; t = TREE_CHAIN (t))
72438fd1498Szrj {
72538fd1498Szrj sfield = build_decl (DECL_SOURCE_LOCATION (t),
72638fd1498Szrj FIELD_DECL, DECL_NAME (t), TREE_TYPE (t));
72738fd1498Szrj DECL_ABSTRACT_ORIGIN (sfield) = DECL_ABSTRACT_ORIGIN (t);
72838fd1498Szrj insert_field_into_struct (ctx->srecord_type, sfield);
72938fd1498Szrj splay_tree_insert (ctx->sfield_map,
73038fd1498Szrj (splay_tree_key) DECL_ABSTRACT_ORIGIN (t),
73138fd1498Szrj (splay_tree_value) sfield);
73238fd1498Szrj }
73338fd1498Szrj }
73438fd1498Szrj sfield = field;
73538fd1498Szrj insert_field_into_struct ((mask & 1) ? ctx->record_type
73638fd1498Szrj : ctx->srecord_type, field);
73738fd1498Szrj }
73838fd1498Szrj
73938fd1498Szrj if (mask & 1)
74038fd1498Szrj splay_tree_insert (ctx->field_map, key, (splay_tree_value) field);
74138fd1498Szrj if ((mask & 2) && ctx->sfield_map)
74238fd1498Szrj splay_tree_insert (ctx->sfield_map, key, (splay_tree_value) sfield);
74338fd1498Szrj }
74438fd1498Szrj
74538fd1498Szrj static tree
install_var_local(tree var,omp_context * ctx)74638fd1498Szrj install_var_local (tree var, omp_context *ctx)
74738fd1498Szrj {
74838fd1498Szrj tree new_var = omp_copy_decl_1 (var, ctx);
74938fd1498Szrj insert_decl_map (&ctx->cb, var, new_var);
75038fd1498Szrj return new_var;
75138fd1498Szrj }
75238fd1498Szrj
75338fd1498Szrj /* Adjust the replacement for DECL in CTX for the new context. This means
75438fd1498Szrj copying the DECL_VALUE_EXPR, and fixing up the type. */
75538fd1498Szrj
75638fd1498Szrj static void
fixup_remapped_decl(tree decl,omp_context * ctx,bool private_debug)75738fd1498Szrj fixup_remapped_decl (tree decl, omp_context *ctx, bool private_debug)
75838fd1498Szrj {
75938fd1498Szrj tree new_decl, size;
76038fd1498Szrj
76138fd1498Szrj new_decl = lookup_decl (decl, ctx);
76238fd1498Szrj
76338fd1498Szrj TREE_TYPE (new_decl) = remap_type (TREE_TYPE (decl), &ctx->cb);
76438fd1498Szrj
76538fd1498Szrj if ((!TREE_CONSTANT (DECL_SIZE (new_decl)) || private_debug)
76638fd1498Szrj && DECL_HAS_VALUE_EXPR_P (decl))
76738fd1498Szrj {
76838fd1498Szrj tree ve = DECL_VALUE_EXPR (decl);
76938fd1498Szrj walk_tree (&ve, copy_tree_body_r, &ctx->cb, NULL);
77038fd1498Szrj SET_DECL_VALUE_EXPR (new_decl, ve);
77138fd1498Szrj DECL_HAS_VALUE_EXPR_P (new_decl) = 1;
77238fd1498Szrj }
77338fd1498Szrj
77438fd1498Szrj if (!TREE_CONSTANT (DECL_SIZE (new_decl)))
77538fd1498Szrj {
77638fd1498Szrj size = remap_decl (DECL_SIZE (decl), &ctx->cb);
77738fd1498Szrj if (size == error_mark_node)
77838fd1498Szrj size = TYPE_SIZE (TREE_TYPE (new_decl));
77938fd1498Szrj DECL_SIZE (new_decl) = size;
78038fd1498Szrj
78138fd1498Szrj size = remap_decl (DECL_SIZE_UNIT (decl), &ctx->cb);
78238fd1498Szrj if (size == error_mark_node)
78338fd1498Szrj size = TYPE_SIZE_UNIT (TREE_TYPE (new_decl));
78438fd1498Szrj DECL_SIZE_UNIT (new_decl) = size;
78538fd1498Szrj }
78638fd1498Szrj }
78738fd1498Szrj
78838fd1498Szrj /* The callback for remap_decl. Search all containing contexts for a
78938fd1498Szrj mapping of the variable; this avoids having to duplicate the splay
79038fd1498Szrj tree ahead of time. We know a mapping doesn't already exist in the
79138fd1498Szrj given context. Create new mappings to implement default semantics. */
79238fd1498Szrj
79338fd1498Szrj static tree
omp_copy_decl(tree var,copy_body_data * cb)79438fd1498Szrj omp_copy_decl (tree var, copy_body_data *cb)
79538fd1498Szrj {
79638fd1498Szrj omp_context *ctx = (omp_context *) cb;
79738fd1498Szrj tree new_var;
79838fd1498Szrj
79938fd1498Szrj if (TREE_CODE (var) == LABEL_DECL)
80038fd1498Szrj {
80138fd1498Szrj if (FORCED_LABEL (var) || DECL_NONLOCAL (var))
80238fd1498Szrj return var;
80338fd1498Szrj new_var = create_artificial_label (DECL_SOURCE_LOCATION (var));
80438fd1498Szrj DECL_CONTEXT (new_var) = current_function_decl;
80538fd1498Szrj insert_decl_map (&ctx->cb, var, new_var);
80638fd1498Szrj return new_var;
80738fd1498Szrj }
80838fd1498Szrj
80938fd1498Szrj while (!is_taskreg_ctx (ctx))
81038fd1498Szrj {
81138fd1498Szrj ctx = ctx->outer;
81238fd1498Szrj if (ctx == NULL)
81338fd1498Szrj return var;
81438fd1498Szrj new_var = maybe_lookup_decl (var, ctx);
81538fd1498Szrj if (new_var)
81638fd1498Szrj return new_var;
81738fd1498Szrj }
81838fd1498Szrj
81938fd1498Szrj if (is_global_var (var) || decl_function_context (var) != ctx->cb.src_fn)
82038fd1498Szrj return var;
82138fd1498Szrj
82238fd1498Szrj return error_mark_node;
82338fd1498Szrj }
82438fd1498Szrj
82538fd1498Szrj /* Create a new context, with OUTER_CTX being the surrounding context. */
82638fd1498Szrj
82738fd1498Szrj static omp_context *
new_omp_context(gimple * stmt,omp_context * outer_ctx)82838fd1498Szrj new_omp_context (gimple *stmt, omp_context *outer_ctx)
82938fd1498Szrj {
83038fd1498Szrj omp_context *ctx = XCNEW (omp_context);
83138fd1498Szrj
83238fd1498Szrj splay_tree_insert (all_contexts, (splay_tree_key) stmt,
83338fd1498Szrj (splay_tree_value) ctx);
83438fd1498Szrj ctx->stmt = stmt;
83538fd1498Szrj
83638fd1498Szrj if (outer_ctx)
83738fd1498Szrj {
83838fd1498Szrj ctx->outer = outer_ctx;
83938fd1498Szrj ctx->cb = outer_ctx->cb;
84038fd1498Szrj ctx->cb.block = NULL;
84138fd1498Szrj ctx->depth = outer_ctx->depth + 1;
84238fd1498Szrj }
84338fd1498Szrj else
84438fd1498Szrj {
84538fd1498Szrj ctx->cb.src_fn = current_function_decl;
84638fd1498Szrj ctx->cb.dst_fn = current_function_decl;
84738fd1498Szrj ctx->cb.src_node = cgraph_node::get (current_function_decl);
84838fd1498Szrj gcc_checking_assert (ctx->cb.src_node);
84938fd1498Szrj ctx->cb.dst_node = ctx->cb.src_node;
85038fd1498Szrj ctx->cb.src_cfun = cfun;
85138fd1498Szrj ctx->cb.copy_decl = omp_copy_decl;
85238fd1498Szrj ctx->cb.eh_lp_nr = 0;
85338fd1498Szrj ctx->cb.transform_call_graph_edges = CB_CGE_MOVE;
85438fd1498Szrj ctx->depth = 1;
85538fd1498Szrj }
85638fd1498Szrj
85738fd1498Szrj ctx->cb.decl_map = new hash_map<tree, tree>;
85838fd1498Szrj
85938fd1498Szrj return ctx;
86038fd1498Szrj }
86138fd1498Szrj
86238fd1498Szrj static gimple_seq maybe_catch_exception (gimple_seq);
86338fd1498Szrj
86438fd1498Szrj /* Finalize task copyfn. */
86538fd1498Szrj
86638fd1498Szrj static void
finalize_task_copyfn(gomp_task * task_stmt)86738fd1498Szrj finalize_task_copyfn (gomp_task *task_stmt)
86838fd1498Szrj {
86938fd1498Szrj struct function *child_cfun;
87038fd1498Szrj tree child_fn;
87138fd1498Szrj gimple_seq seq = NULL, new_seq;
87238fd1498Szrj gbind *bind;
87338fd1498Szrj
87438fd1498Szrj child_fn = gimple_omp_task_copy_fn (task_stmt);
87538fd1498Szrj if (child_fn == NULL_TREE)
87638fd1498Szrj return;
87738fd1498Szrj
87838fd1498Szrj child_cfun = DECL_STRUCT_FUNCTION (child_fn);
87938fd1498Szrj DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
88038fd1498Szrj
88138fd1498Szrj push_cfun (child_cfun);
88238fd1498Szrj bind = gimplify_body (child_fn, false);
88338fd1498Szrj gimple_seq_add_stmt (&seq, bind);
88438fd1498Szrj new_seq = maybe_catch_exception (seq);
88538fd1498Szrj if (new_seq != seq)
88638fd1498Szrj {
88738fd1498Szrj bind = gimple_build_bind (NULL, new_seq, NULL);
88838fd1498Szrj seq = NULL;
88938fd1498Szrj gimple_seq_add_stmt (&seq, bind);
89038fd1498Szrj }
89138fd1498Szrj gimple_set_body (child_fn, seq);
89238fd1498Szrj pop_cfun ();
89338fd1498Szrj
89438fd1498Szrj /* Inform the callgraph about the new function. */
89538fd1498Szrj cgraph_node *node = cgraph_node::get_create (child_fn);
89638fd1498Szrj node->parallelized_function = 1;
89738fd1498Szrj cgraph_node::add_new_function (child_fn, false);
89838fd1498Szrj }
89938fd1498Szrj
90038fd1498Szrj /* Destroy a omp_context data structures. Called through the splay tree
90138fd1498Szrj value delete callback. */
90238fd1498Szrj
90338fd1498Szrj static void
delete_omp_context(splay_tree_value value)90438fd1498Szrj delete_omp_context (splay_tree_value value)
90538fd1498Szrj {
90638fd1498Szrj omp_context *ctx = (omp_context *) value;
90738fd1498Szrj
90838fd1498Szrj delete ctx->cb.decl_map;
90938fd1498Szrj
91038fd1498Szrj if (ctx->field_map)
91138fd1498Szrj splay_tree_delete (ctx->field_map);
91238fd1498Szrj if (ctx->sfield_map)
91338fd1498Szrj splay_tree_delete (ctx->sfield_map);
91438fd1498Szrj
91538fd1498Szrj /* We hijacked DECL_ABSTRACT_ORIGIN earlier. We need to clear it before
91638fd1498Szrj it produces corrupt debug information. */
91738fd1498Szrj if (ctx->record_type)
91838fd1498Szrj {
91938fd1498Szrj tree t;
92038fd1498Szrj for (t = TYPE_FIELDS (ctx->record_type); t ; t = DECL_CHAIN (t))
92138fd1498Szrj DECL_ABSTRACT_ORIGIN (t) = NULL;
92238fd1498Szrj }
92338fd1498Szrj if (ctx->srecord_type)
92438fd1498Szrj {
92538fd1498Szrj tree t;
92638fd1498Szrj for (t = TYPE_FIELDS (ctx->srecord_type); t ; t = DECL_CHAIN (t))
92738fd1498Szrj DECL_ABSTRACT_ORIGIN (t) = NULL;
92838fd1498Szrj }
92938fd1498Szrj
93038fd1498Szrj if (is_task_ctx (ctx))
93138fd1498Szrj finalize_task_copyfn (as_a <gomp_task *> (ctx->stmt));
93238fd1498Szrj
93338fd1498Szrj XDELETE (ctx);
93438fd1498Szrj }
93538fd1498Szrj
93638fd1498Szrj /* Fix up RECEIVER_DECL with a type that has been remapped to the child
93738fd1498Szrj context. */
93838fd1498Szrj
93938fd1498Szrj static void
fixup_child_record_type(omp_context * ctx)94038fd1498Szrj fixup_child_record_type (omp_context *ctx)
94138fd1498Szrj {
94238fd1498Szrj tree f, type = ctx->record_type;
94338fd1498Szrj
94438fd1498Szrj if (!ctx->receiver_decl)
94538fd1498Szrj return;
94638fd1498Szrj /* ??? It isn't sufficient to just call remap_type here, because
94738fd1498Szrj variably_modified_type_p doesn't work the way we expect for
94838fd1498Szrj record types. Testing each field for whether it needs remapping
94938fd1498Szrj and creating a new record by hand works, however. */
95038fd1498Szrj for (f = TYPE_FIELDS (type); f ; f = DECL_CHAIN (f))
95138fd1498Szrj if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
95238fd1498Szrj break;
95338fd1498Szrj if (f)
95438fd1498Szrj {
95538fd1498Szrj tree name, new_fields = NULL;
95638fd1498Szrj
95738fd1498Szrj type = lang_hooks.types.make_type (RECORD_TYPE);
95838fd1498Szrj name = DECL_NAME (TYPE_NAME (ctx->record_type));
95938fd1498Szrj name = build_decl (DECL_SOURCE_LOCATION (ctx->receiver_decl),
96038fd1498Szrj TYPE_DECL, name, type);
96138fd1498Szrj TYPE_NAME (type) = name;
96238fd1498Szrj
96338fd1498Szrj for (f = TYPE_FIELDS (ctx->record_type); f ; f = DECL_CHAIN (f))
96438fd1498Szrj {
96538fd1498Szrj tree new_f = copy_node (f);
96638fd1498Szrj DECL_CONTEXT (new_f) = type;
96738fd1498Szrj TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &ctx->cb);
96838fd1498Szrj DECL_CHAIN (new_f) = new_fields;
96938fd1498Szrj walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &ctx->cb, NULL);
97038fd1498Szrj walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r,
97138fd1498Szrj &ctx->cb, NULL);
97238fd1498Szrj walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
97338fd1498Szrj &ctx->cb, NULL);
97438fd1498Szrj new_fields = new_f;
97538fd1498Szrj
97638fd1498Szrj /* Arrange to be able to look up the receiver field
97738fd1498Szrj given the sender field. */
97838fd1498Szrj splay_tree_insert (ctx->field_map, (splay_tree_key) f,
97938fd1498Szrj (splay_tree_value) new_f);
98038fd1498Szrj }
98138fd1498Szrj TYPE_FIELDS (type) = nreverse (new_fields);
98238fd1498Szrj layout_type (type);
98338fd1498Szrj }
98438fd1498Szrj
98538fd1498Szrj /* In a target region we never modify any of the pointers in *.omp_data_i,
98638fd1498Szrj so attempt to help the optimizers. */
98738fd1498Szrj if (is_gimple_omp_offloaded (ctx->stmt))
98838fd1498Szrj type = build_qualified_type (type, TYPE_QUAL_CONST);
98938fd1498Szrj
99038fd1498Szrj TREE_TYPE (ctx->receiver_decl)
99138fd1498Szrj = build_qualified_type (build_reference_type (type), TYPE_QUAL_RESTRICT);
99238fd1498Szrj }
99338fd1498Szrj
99438fd1498Szrj /* Instantiate decls as necessary in CTX to satisfy the data sharing
99538fd1498Szrj specified by CLAUSES. If BASE_POINTERS_RESTRICT, install var field with
99638fd1498Szrj restrict. */
99738fd1498Szrj
99838fd1498Szrj static void
99938fd1498Szrj scan_sharing_clauses (tree clauses, omp_context *ctx,
100038fd1498Szrj bool base_pointers_restrict = false)
100138fd1498Szrj {
100238fd1498Szrj tree c, decl;
100338fd1498Szrj bool scan_array_reductions = false;
100438fd1498Szrj
100538fd1498Szrj for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
100638fd1498Szrj {
100738fd1498Szrj bool by_ref;
100838fd1498Szrj
100938fd1498Szrj switch (OMP_CLAUSE_CODE (c))
101038fd1498Szrj {
101138fd1498Szrj case OMP_CLAUSE_PRIVATE:
101238fd1498Szrj decl = OMP_CLAUSE_DECL (c);
101338fd1498Szrj if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
101438fd1498Szrj goto do_private;
101538fd1498Szrj else if (!is_variable_sized (decl))
101638fd1498Szrj install_var_local (decl, ctx);
101738fd1498Szrj break;
101838fd1498Szrj
101938fd1498Szrj case OMP_CLAUSE_SHARED:
102038fd1498Szrj decl = OMP_CLAUSE_DECL (c);
102138fd1498Szrj /* Ignore shared directives in teams construct. */
102238fd1498Szrj if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
102338fd1498Szrj {
102438fd1498Szrj /* Global variables don't need to be copied,
102538fd1498Szrj the receiver side will use them directly. */
102638fd1498Szrj tree odecl = maybe_lookup_decl_in_outer_ctx (decl, ctx);
102738fd1498Szrj if (is_global_var (odecl))
102838fd1498Szrj break;
102938fd1498Szrj insert_decl_map (&ctx->cb, decl, odecl);
103038fd1498Szrj break;
103138fd1498Szrj }
103238fd1498Szrj gcc_assert (is_taskreg_ctx (ctx));
103338fd1498Szrj gcc_assert (!COMPLETE_TYPE_P (TREE_TYPE (decl))
103438fd1498Szrj || !is_variable_sized (decl));
103538fd1498Szrj /* Global variables don't need to be copied,
103638fd1498Szrj the receiver side will use them directly. */
103738fd1498Szrj if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
103838fd1498Szrj break;
103938fd1498Szrj if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
104038fd1498Szrj {
104138fd1498Szrj use_pointer_for_field (decl, ctx);
104238fd1498Szrj break;
104338fd1498Szrj }
104438fd1498Szrj by_ref = use_pointer_for_field (decl, NULL);
104538fd1498Szrj if ((! TREE_READONLY (decl) && !OMP_CLAUSE_SHARED_READONLY (c))
104638fd1498Szrj || TREE_ADDRESSABLE (decl)
104738fd1498Szrj || by_ref
104838fd1498Szrj || omp_is_reference (decl))
104938fd1498Szrj {
105038fd1498Szrj by_ref = use_pointer_for_field (decl, ctx);
105138fd1498Szrj install_var_field (decl, by_ref, 3, ctx);
105238fd1498Szrj install_var_local (decl, ctx);
105338fd1498Szrj break;
105438fd1498Szrj }
105538fd1498Szrj /* We don't need to copy const scalar vars back. */
105638fd1498Szrj OMP_CLAUSE_SET_CODE (c, OMP_CLAUSE_FIRSTPRIVATE);
105738fd1498Szrj goto do_private;
105838fd1498Szrj
105938fd1498Szrj case OMP_CLAUSE_REDUCTION:
106038fd1498Szrj decl = OMP_CLAUSE_DECL (c);
106138fd1498Szrj if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
106238fd1498Szrj && TREE_CODE (decl) == MEM_REF)
106338fd1498Szrj {
106438fd1498Szrj tree t = TREE_OPERAND (decl, 0);
106538fd1498Szrj if (TREE_CODE (t) == POINTER_PLUS_EXPR)
106638fd1498Szrj t = TREE_OPERAND (t, 0);
106738fd1498Szrj if (TREE_CODE (t) == INDIRECT_REF
106838fd1498Szrj || TREE_CODE (t) == ADDR_EXPR)
106938fd1498Szrj t = TREE_OPERAND (t, 0);
107038fd1498Szrj install_var_local (t, ctx);
107138fd1498Szrj if (is_taskreg_ctx (ctx)
107238fd1498Szrj && !is_global_var (maybe_lookup_decl_in_outer_ctx (t, ctx))
107338fd1498Szrj && !is_variable_sized (t))
107438fd1498Szrj {
107538fd1498Szrj by_ref = use_pointer_for_field (t, ctx);
107638fd1498Szrj install_var_field (t, by_ref, 3, ctx);
107738fd1498Szrj }
107838fd1498Szrj break;
107938fd1498Szrj }
108038fd1498Szrj goto do_private;
108138fd1498Szrj
108238fd1498Szrj case OMP_CLAUSE_LASTPRIVATE:
108338fd1498Szrj /* Let the corresponding firstprivate clause create
108438fd1498Szrj the variable. */
108538fd1498Szrj if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
108638fd1498Szrj break;
108738fd1498Szrj /* FALLTHRU */
108838fd1498Szrj
108938fd1498Szrj case OMP_CLAUSE_FIRSTPRIVATE:
109038fd1498Szrj case OMP_CLAUSE_LINEAR:
109138fd1498Szrj decl = OMP_CLAUSE_DECL (c);
109238fd1498Szrj do_private:
109338fd1498Szrj if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE
109438fd1498Szrj || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IS_DEVICE_PTR)
109538fd1498Szrj && is_gimple_omp_offloaded (ctx->stmt))
109638fd1498Szrj {
109738fd1498Szrj if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
109838fd1498Szrj install_var_field (decl, !omp_is_reference (decl), 3, ctx);
109938fd1498Szrj else if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
110038fd1498Szrj install_var_field (decl, true, 3, ctx);
110138fd1498Szrj else
110238fd1498Szrj install_var_field (decl, false, 3, ctx);
110338fd1498Szrj }
110438fd1498Szrj if (is_variable_sized (decl))
110538fd1498Szrj {
110638fd1498Szrj if (is_task_ctx (ctx))
110738fd1498Szrj install_var_field (decl, false, 1, ctx);
110838fd1498Szrj break;
110938fd1498Szrj }
111038fd1498Szrj else if (is_taskreg_ctx (ctx))
111138fd1498Szrj {
111238fd1498Szrj bool global
111338fd1498Szrj = is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx));
111438fd1498Szrj by_ref = use_pointer_for_field (decl, NULL);
111538fd1498Szrj
111638fd1498Szrj if (is_task_ctx (ctx)
111738fd1498Szrj && (global || by_ref || omp_is_reference (decl)))
111838fd1498Szrj {
111938fd1498Szrj install_var_field (decl, false, 1, ctx);
112038fd1498Szrj if (!global)
112138fd1498Szrj install_var_field (decl, by_ref, 2, ctx);
112238fd1498Szrj }
112338fd1498Szrj else if (!global)
112438fd1498Szrj install_var_field (decl, by_ref, 3, ctx);
112538fd1498Szrj }
112638fd1498Szrj install_var_local (decl, ctx);
112738fd1498Szrj break;
112838fd1498Szrj
112938fd1498Szrj case OMP_CLAUSE_USE_DEVICE_PTR:
113038fd1498Szrj decl = OMP_CLAUSE_DECL (c);
113138fd1498Szrj if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
113238fd1498Szrj install_var_field (decl, true, 3, ctx);
113338fd1498Szrj else
113438fd1498Szrj install_var_field (decl, false, 3, ctx);
113538fd1498Szrj if (DECL_SIZE (decl)
113638fd1498Szrj && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
113738fd1498Szrj {
113838fd1498Szrj tree decl2 = DECL_VALUE_EXPR (decl);
113938fd1498Szrj gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
114038fd1498Szrj decl2 = TREE_OPERAND (decl2, 0);
114138fd1498Szrj gcc_assert (DECL_P (decl2));
114238fd1498Szrj install_var_local (decl2, ctx);
114338fd1498Szrj }
114438fd1498Szrj install_var_local (decl, ctx);
114538fd1498Szrj break;
114638fd1498Szrj
114738fd1498Szrj case OMP_CLAUSE_IS_DEVICE_PTR:
114838fd1498Szrj decl = OMP_CLAUSE_DECL (c);
114938fd1498Szrj goto do_private;
115038fd1498Szrj
115138fd1498Szrj case OMP_CLAUSE__LOOPTEMP_:
115238fd1498Szrj gcc_assert (is_taskreg_ctx (ctx));
115338fd1498Szrj decl = OMP_CLAUSE_DECL (c);
115438fd1498Szrj install_var_field (decl, false, 3, ctx);
115538fd1498Szrj install_var_local (decl, ctx);
115638fd1498Szrj break;
115738fd1498Szrj
115838fd1498Szrj case OMP_CLAUSE_COPYPRIVATE:
115938fd1498Szrj case OMP_CLAUSE_COPYIN:
116038fd1498Szrj decl = OMP_CLAUSE_DECL (c);
116138fd1498Szrj by_ref = use_pointer_for_field (decl, NULL);
116238fd1498Szrj install_var_field (decl, by_ref, 3, ctx);
116338fd1498Szrj break;
116438fd1498Szrj
116538fd1498Szrj case OMP_CLAUSE_FINAL:
116638fd1498Szrj case OMP_CLAUSE_IF:
116738fd1498Szrj case OMP_CLAUSE_NUM_THREADS:
116838fd1498Szrj case OMP_CLAUSE_NUM_TEAMS:
116938fd1498Szrj case OMP_CLAUSE_THREAD_LIMIT:
117038fd1498Szrj case OMP_CLAUSE_DEVICE:
117138fd1498Szrj case OMP_CLAUSE_SCHEDULE:
117238fd1498Szrj case OMP_CLAUSE_DIST_SCHEDULE:
117338fd1498Szrj case OMP_CLAUSE_DEPEND:
117438fd1498Szrj case OMP_CLAUSE_PRIORITY:
117538fd1498Szrj case OMP_CLAUSE_GRAINSIZE:
117638fd1498Szrj case OMP_CLAUSE_NUM_TASKS:
117738fd1498Szrj case OMP_CLAUSE_NUM_GANGS:
117838fd1498Szrj case OMP_CLAUSE_NUM_WORKERS:
117938fd1498Szrj case OMP_CLAUSE_VECTOR_LENGTH:
118038fd1498Szrj if (ctx->outer)
118138fd1498Szrj scan_omp_op (&OMP_CLAUSE_OPERAND (c, 0), ctx->outer);
118238fd1498Szrj break;
118338fd1498Szrj
118438fd1498Szrj case OMP_CLAUSE_TO:
118538fd1498Szrj case OMP_CLAUSE_FROM:
118638fd1498Szrj case OMP_CLAUSE_MAP:
118738fd1498Szrj if (ctx->outer)
118838fd1498Szrj scan_omp_op (&OMP_CLAUSE_SIZE (c), ctx->outer);
118938fd1498Szrj decl = OMP_CLAUSE_DECL (c);
119038fd1498Szrj /* Global variables with "omp declare target" attribute
119138fd1498Szrj don't need to be copied, the receiver side will use them
119238fd1498Szrj directly. However, global variables with "omp declare target link"
1193*58e805e6Szrj attribute need to be copied. Or when ALWAYS modifier is used. */
119438fd1498Szrj if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
119538fd1498Szrj && DECL_P (decl)
119638fd1498Szrj && ((OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_FIRSTPRIVATE_POINTER
119738fd1498Szrj && (OMP_CLAUSE_MAP_KIND (c)
119838fd1498Szrj != GOMP_MAP_FIRSTPRIVATE_REFERENCE))
119938fd1498Szrj || TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1200*58e805e6Szrj && OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_ALWAYS_TO
1201*58e805e6Szrj && OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_ALWAYS_FROM
1202*58e805e6Szrj && OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_ALWAYS_TOFROM
120338fd1498Szrj && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
120438fd1498Szrj && varpool_node::get_create (decl)->offloadable
120538fd1498Szrj && !lookup_attribute ("omp declare target link",
120638fd1498Szrj DECL_ATTRIBUTES (decl)))
120738fd1498Szrj break;
120838fd1498Szrj if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
120938fd1498Szrj && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER)
121038fd1498Szrj {
121138fd1498Szrj /* Ignore GOMP_MAP_POINTER kind for arrays in regions that are
121238fd1498Szrj not offloaded; there is nothing to map for those. */
121338fd1498Szrj if (!is_gimple_omp_offloaded (ctx->stmt)
121438fd1498Szrj && !POINTER_TYPE_P (TREE_TYPE (decl))
121538fd1498Szrj && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
121638fd1498Szrj break;
121738fd1498Szrj }
121838fd1498Szrj if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
121938fd1498Szrj && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
122038fd1498Szrj || (OMP_CLAUSE_MAP_KIND (c)
122138fd1498Szrj == GOMP_MAP_FIRSTPRIVATE_REFERENCE)))
122238fd1498Szrj {
122338fd1498Szrj if (TREE_CODE (decl) == COMPONENT_REF
122438fd1498Szrj || (TREE_CODE (decl) == INDIRECT_REF
122538fd1498Szrj && TREE_CODE (TREE_OPERAND (decl, 0)) == COMPONENT_REF
122638fd1498Szrj && (TREE_CODE (TREE_TYPE (TREE_OPERAND (decl, 0)))
122738fd1498Szrj == REFERENCE_TYPE)))
122838fd1498Szrj break;
122938fd1498Szrj if (DECL_SIZE (decl)
123038fd1498Szrj && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
123138fd1498Szrj {
123238fd1498Szrj tree decl2 = DECL_VALUE_EXPR (decl);
123338fd1498Szrj gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
123438fd1498Szrj decl2 = TREE_OPERAND (decl2, 0);
123538fd1498Szrj gcc_assert (DECL_P (decl2));
123638fd1498Szrj install_var_local (decl2, ctx);
123738fd1498Szrj }
123838fd1498Szrj install_var_local (decl, ctx);
123938fd1498Szrj break;
124038fd1498Szrj }
124138fd1498Szrj if (DECL_P (decl))
124238fd1498Szrj {
124338fd1498Szrj if (DECL_SIZE (decl)
124438fd1498Szrj && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
124538fd1498Szrj {
124638fd1498Szrj tree decl2 = DECL_VALUE_EXPR (decl);
124738fd1498Szrj gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
124838fd1498Szrj decl2 = TREE_OPERAND (decl2, 0);
124938fd1498Szrj gcc_assert (DECL_P (decl2));
125038fd1498Szrj install_var_field (decl2, true, 3, ctx);
125138fd1498Szrj install_var_local (decl2, ctx);
125238fd1498Szrj install_var_local (decl, ctx);
125338fd1498Szrj }
125438fd1498Szrj else
125538fd1498Szrj {
125638fd1498Szrj if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
125738fd1498Szrj && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
125838fd1498Szrj && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
125938fd1498Szrj && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
126038fd1498Szrj install_var_field (decl, true, 7, ctx);
126138fd1498Szrj else
126238fd1498Szrj install_var_field (decl, true, 3, ctx,
126338fd1498Szrj base_pointers_restrict);
126438fd1498Szrj if (is_gimple_omp_offloaded (ctx->stmt)
126538fd1498Szrj && !OMP_CLAUSE_MAP_IN_REDUCTION (c))
126638fd1498Szrj install_var_local (decl, ctx);
126738fd1498Szrj }
126838fd1498Szrj }
126938fd1498Szrj else
127038fd1498Szrj {
127138fd1498Szrj tree base = get_base_address (decl);
127238fd1498Szrj tree nc = OMP_CLAUSE_CHAIN (c);
127338fd1498Szrj if (DECL_P (base)
127438fd1498Szrj && nc != NULL_TREE
127538fd1498Szrj && OMP_CLAUSE_CODE (nc) == OMP_CLAUSE_MAP
127638fd1498Szrj && OMP_CLAUSE_DECL (nc) == base
127738fd1498Szrj && OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_POINTER
127838fd1498Szrj && integer_zerop (OMP_CLAUSE_SIZE (nc)))
127938fd1498Szrj {
128038fd1498Szrj OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c) = 1;
128138fd1498Szrj OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (nc) = 1;
128238fd1498Szrj }
128338fd1498Szrj else
128438fd1498Szrj {
128538fd1498Szrj if (ctx->outer)
128638fd1498Szrj {
128738fd1498Szrj scan_omp_op (&OMP_CLAUSE_DECL (c), ctx->outer);
128838fd1498Szrj decl = OMP_CLAUSE_DECL (c);
128938fd1498Szrj }
129038fd1498Szrj gcc_assert (!splay_tree_lookup (ctx->field_map,
129138fd1498Szrj (splay_tree_key) decl));
129238fd1498Szrj tree field
129338fd1498Szrj = build_decl (OMP_CLAUSE_LOCATION (c),
129438fd1498Szrj FIELD_DECL, NULL_TREE, ptr_type_node);
129538fd1498Szrj SET_DECL_ALIGN (field, TYPE_ALIGN (ptr_type_node));
129638fd1498Szrj insert_field_into_struct (ctx->record_type, field);
129738fd1498Szrj splay_tree_insert (ctx->field_map, (splay_tree_key) decl,
129838fd1498Szrj (splay_tree_value) field);
129938fd1498Szrj }
130038fd1498Szrj }
130138fd1498Szrj break;
130238fd1498Szrj
130338fd1498Szrj case OMP_CLAUSE__GRIDDIM_:
130438fd1498Szrj if (ctx->outer)
130538fd1498Szrj {
130638fd1498Szrj scan_omp_op (&OMP_CLAUSE__GRIDDIM__SIZE (c), ctx->outer);
130738fd1498Szrj scan_omp_op (&OMP_CLAUSE__GRIDDIM__GROUP (c), ctx->outer);
130838fd1498Szrj }
130938fd1498Szrj break;
131038fd1498Szrj
131138fd1498Szrj case OMP_CLAUSE_NOWAIT:
131238fd1498Szrj case OMP_CLAUSE_ORDERED:
131338fd1498Szrj case OMP_CLAUSE_COLLAPSE:
131438fd1498Szrj case OMP_CLAUSE_UNTIED:
131538fd1498Szrj case OMP_CLAUSE_MERGEABLE:
131638fd1498Szrj case OMP_CLAUSE_PROC_BIND:
131738fd1498Szrj case OMP_CLAUSE_SAFELEN:
131838fd1498Szrj case OMP_CLAUSE_SIMDLEN:
131938fd1498Szrj case OMP_CLAUSE_THREADS:
132038fd1498Szrj case OMP_CLAUSE_SIMD:
132138fd1498Szrj case OMP_CLAUSE_NOGROUP:
132238fd1498Szrj case OMP_CLAUSE_DEFAULTMAP:
132338fd1498Szrj case OMP_CLAUSE_ASYNC:
132438fd1498Szrj case OMP_CLAUSE_WAIT:
132538fd1498Szrj case OMP_CLAUSE_GANG:
132638fd1498Szrj case OMP_CLAUSE_WORKER:
132738fd1498Szrj case OMP_CLAUSE_VECTOR:
132838fd1498Szrj case OMP_CLAUSE_INDEPENDENT:
132938fd1498Szrj case OMP_CLAUSE_AUTO:
133038fd1498Szrj case OMP_CLAUSE_SEQ:
133138fd1498Szrj case OMP_CLAUSE_TILE:
133238fd1498Szrj case OMP_CLAUSE__SIMT_:
133338fd1498Szrj case OMP_CLAUSE_DEFAULT:
133438fd1498Szrj break;
133538fd1498Szrj
133638fd1498Szrj case OMP_CLAUSE_ALIGNED:
133738fd1498Szrj decl = OMP_CLAUSE_DECL (c);
133838fd1498Szrj if (is_global_var (decl)
133938fd1498Szrj && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
134038fd1498Szrj install_var_local (decl, ctx);
134138fd1498Szrj break;
134238fd1498Szrj
134338fd1498Szrj case OMP_CLAUSE__CACHE_:
134438fd1498Szrj default:
134538fd1498Szrj gcc_unreachable ();
134638fd1498Szrj }
134738fd1498Szrj }
134838fd1498Szrj
134938fd1498Szrj for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
135038fd1498Szrj {
135138fd1498Szrj switch (OMP_CLAUSE_CODE (c))
135238fd1498Szrj {
135338fd1498Szrj case OMP_CLAUSE_LASTPRIVATE:
135438fd1498Szrj /* Let the corresponding firstprivate clause create
135538fd1498Szrj the variable. */
135638fd1498Szrj if (OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
135738fd1498Szrj scan_array_reductions = true;
135838fd1498Szrj if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
135938fd1498Szrj break;
136038fd1498Szrj /* FALLTHRU */
136138fd1498Szrj
136238fd1498Szrj case OMP_CLAUSE_FIRSTPRIVATE:
136338fd1498Szrj case OMP_CLAUSE_PRIVATE:
136438fd1498Szrj case OMP_CLAUSE_LINEAR:
136538fd1498Szrj case OMP_CLAUSE_IS_DEVICE_PTR:
136638fd1498Szrj decl = OMP_CLAUSE_DECL (c);
136738fd1498Szrj if (is_variable_sized (decl))
136838fd1498Szrj {
136938fd1498Szrj if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE
137038fd1498Szrj || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IS_DEVICE_PTR)
137138fd1498Szrj && is_gimple_omp_offloaded (ctx->stmt))
137238fd1498Szrj {
137338fd1498Szrj tree decl2 = DECL_VALUE_EXPR (decl);
137438fd1498Szrj gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
137538fd1498Szrj decl2 = TREE_OPERAND (decl2, 0);
137638fd1498Szrj gcc_assert (DECL_P (decl2));
137738fd1498Szrj install_var_local (decl2, ctx);
137838fd1498Szrj fixup_remapped_decl (decl2, ctx, false);
137938fd1498Szrj }
138038fd1498Szrj install_var_local (decl, ctx);
138138fd1498Szrj }
138238fd1498Szrj fixup_remapped_decl (decl, ctx,
138338fd1498Szrj OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE
138438fd1498Szrj && OMP_CLAUSE_PRIVATE_DEBUG (c));
138538fd1498Szrj if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
138638fd1498Szrj && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
138738fd1498Szrj scan_array_reductions = true;
138838fd1498Szrj break;
138938fd1498Szrj
139038fd1498Szrj case OMP_CLAUSE_REDUCTION:
139138fd1498Szrj decl = OMP_CLAUSE_DECL (c);
139238fd1498Szrj if (TREE_CODE (decl) != MEM_REF)
139338fd1498Szrj {
139438fd1498Szrj if (is_variable_sized (decl))
139538fd1498Szrj install_var_local (decl, ctx);
139638fd1498Szrj fixup_remapped_decl (decl, ctx, false);
139738fd1498Szrj }
139838fd1498Szrj if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
139938fd1498Szrj scan_array_reductions = true;
140038fd1498Szrj break;
140138fd1498Szrj
140238fd1498Szrj case OMP_CLAUSE_SHARED:
140338fd1498Szrj /* Ignore shared directives in teams construct. */
140438fd1498Szrj if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
140538fd1498Szrj break;
140638fd1498Szrj decl = OMP_CLAUSE_DECL (c);
140738fd1498Szrj if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
140838fd1498Szrj break;
140938fd1498Szrj if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
141038fd1498Szrj {
141138fd1498Szrj if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl,
141238fd1498Szrj ctx->outer)))
141338fd1498Szrj break;
141438fd1498Szrj bool by_ref = use_pointer_for_field (decl, ctx);
141538fd1498Szrj install_var_field (decl, by_ref, 11, ctx);
141638fd1498Szrj break;
141738fd1498Szrj }
141838fd1498Szrj fixup_remapped_decl (decl, ctx, false);
141938fd1498Szrj break;
142038fd1498Szrj
142138fd1498Szrj case OMP_CLAUSE_MAP:
142238fd1498Szrj if (!is_gimple_omp_offloaded (ctx->stmt))
142338fd1498Szrj break;
142438fd1498Szrj decl = OMP_CLAUSE_DECL (c);
142538fd1498Szrj if (DECL_P (decl)
142638fd1498Szrj && ((OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_FIRSTPRIVATE_POINTER
142738fd1498Szrj && (OMP_CLAUSE_MAP_KIND (c)
142838fd1498Szrj != GOMP_MAP_FIRSTPRIVATE_REFERENCE))
142938fd1498Szrj || TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
143038fd1498Szrj && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
143138fd1498Szrj && varpool_node::get_create (decl)->offloadable)
143238fd1498Szrj break;
143338fd1498Szrj if (DECL_P (decl))
143438fd1498Szrj {
143538fd1498Szrj if ((OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
143638fd1498Szrj || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER)
143738fd1498Szrj && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
143838fd1498Szrj && !COMPLETE_TYPE_P (TREE_TYPE (decl)))
143938fd1498Szrj {
144038fd1498Szrj tree new_decl = lookup_decl (decl, ctx);
144138fd1498Szrj TREE_TYPE (new_decl)
144238fd1498Szrj = remap_type (TREE_TYPE (decl), &ctx->cb);
144338fd1498Szrj }
144438fd1498Szrj else if (DECL_SIZE (decl)
144538fd1498Szrj && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
144638fd1498Szrj {
144738fd1498Szrj tree decl2 = DECL_VALUE_EXPR (decl);
144838fd1498Szrj gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
144938fd1498Szrj decl2 = TREE_OPERAND (decl2, 0);
145038fd1498Szrj gcc_assert (DECL_P (decl2));
145138fd1498Szrj fixup_remapped_decl (decl2, ctx, false);
145238fd1498Szrj fixup_remapped_decl (decl, ctx, true);
145338fd1498Szrj }
145438fd1498Szrj else
145538fd1498Szrj fixup_remapped_decl (decl, ctx, false);
145638fd1498Szrj }
145738fd1498Szrj break;
145838fd1498Szrj
145938fd1498Szrj case OMP_CLAUSE_COPYPRIVATE:
146038fd1498Szrj case OMP_CLAUSE_COPYIN:
146138fd1498Szrj case OMP_CLAUSE_DEFAULT:
146238fd1498Szrj case OMP_CLAUSE_IF:
146338fd1498Szrj case OMP_CLAUSE_NUM_THREADS:
146438fd1498Szrj case OMP_CLAUSE_NUM_TEAMS:
146538fd1498Szrj case OMP_CLAUSE_THREAD_LIMIT:
146638fd1498Szrj case OMP_CLAUSE_DEVICE:
146738fd1498Szrj case OMP_CLAUSE_SCHEDULE:
146838fd1498Szrj case OMP_CLAUSE_DIST_SCHEDULE:
146938fd1498Szrj case OMP_CLAUSE_NOWAIT:
147038fd1498Szrj case OMP_CLAUSE_ORDERED:
147138fd1498Szrj case OMP_CLAUSE_COLLAPSE:
147238fd1498Szrj case OMP_CLAUSE_UNTIED:
147338fd1498Szrj case OMP_CLAUSE_FINAL:
147438fd1498Szrj case OMP_CLAUSE_MERGEABLE:
147538fd1498Szrj case OMP_CLAUSE_PROC_BIND:
147638fd1498Szrj case OMP_CLAUSE_SAFELEN:
147738fd1498Szrj case OMP_CLAUSE_SIMDLEN:
147838fd1498Szrj case OMP_CLAUSE_ALIGNED:
147938fd1498Szrj case OMP_CLAUSE_DEPEND:
148038fd1498Szrj case OMP_CLAUSE__LOOPTEMP_:
148138fd1498Szrj case OMP_CLAUSE_TO:
148238fd1498Szrj case OMP_CLAUSE_FROM:
148338fd1498Szrj case OMP_CLAUSE_PRIORITY:
148438fd1498Szrj case OMP_CLAUSE_GRAINSIZE:
148538fd1498Szrj case OMP_CLAUSE_NUM_TASKS:
148638fd1498Szrj case OMP_CLAUSE_THREADS:
148738fd1498Szrj case OMP_CLAUSE_SIMD:
148838fd1498Szrj case OMP_CLAUSE_NOGROUP:
148938fd1498Szrj case OMP_CLAUSE_DEFAULTMAP:
149038fd1498Szrj case OMP_CLAUSE_USE_DEVICE_PTR:
149138fd1498Szrj case OMP_CLAUSE_ASYNC:
149238fd1498Szrj case OMP_CLAUSE_WAIT:
149338fd1498Szrj case OMP_CLAUSE_NUM_GANGS:
149438fd1498Szrj case OMP_CLAUSE_NUM_WORKERS:
149538fd1498Szrj case OMP_CLAUSE_VECTOR_LENGTH:
149638fd1498Szrj case OMP_CLAUSE_GANG:
149738fd1498Szrj case OMP_CLAUSE_WORKER:
149838fd1498Szrj case OMP_CLAUSE_VECTOR:
149938fd1498Szrj case OMP_CLAUSE_INDEPENDENT:
150038fd1498Szrj case OMP_CLAUSE_AUTO:
150138fd1498Szrj case OMP_CLAUSE_SEQ:
150238fd1498Szrj case OMP_CLAUSE_TILE:
150338fd1498Szrj case OMP_CLAUSE__GRIDDIM_:
150438fd1498Szrj case OMP_CLAUSE__SIMT_:
150538fd1498Szrj break;
150638fd1498Szrj
150738fd1498Szrj case OMP_CLAUSE__CACHE_:
150838fd1498Szrj default:
150938fd1498Szrj gcc_unreachable ();
151038fd1498Szrj }
151138fd1498Szrj }
151238fd1498Szrj
151338fd1498Szrj gcc_checking_assert (!scan_array_reductions
151438fd1498Szrj || !is_gimple_omp_oacc (ctx->stmt));
151538fd1498Szrj if (scan_array_reductions)
151638fd1498Szrj {
151738fd1498Szrj for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
151838fd1498Szrj if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
151938fd1498Szrj && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
152038fd1498Szrj {
152138fd1498Szrj scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c), ctx);
152238fd1498Szrj scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
152338fd1498Szrj }
152438fd1498Szrj else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
152538fd1498Szrj && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
152638fd1498Szrj scan_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
152738fd1498Szrj else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
152838fd1498Szrj && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
152938fd1498Szrj scan_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
153038fd1498Szrj }
153138fd1498Szrj }
153238fd1498Szrj
153338fd1498Szrj /* Create a new name for omp child function. Returns an identifier. */
153438fd1498Szrj
153538fd1498Szrj static tree
create_omp_child_function_name(bool task_copy)153638fd1498Szrj create_omp_child_function_name (bool task_copy)
153738fd1498Szrj {
153838fd1498Szrj return clone_function_name (current_function_decl,
153938fd1498Szrj task_copy ? "_omp_cpyfn" : "_omp_fn");
154038fd1498Szrj }
154138fd1498Szrj
154238fd1498Szrj /* Return true if CTX may belong to offloaded code: either if current function
154338fd1498Szrj is offloaded, or any enclosing context corresponds to a target region. */
154438fd1498Szrj
154538fd1498Szrj static bool
omp_maybe_offloaded_ctx(omp_context * ctx)154638fd1498Szrj omp_maybe_offloaded_ctx (omp_context *ctx)
154738fd1498Szrj {
154838fd1498Szrj if (cgraph_node::get (current_function_decl)->offloadable)
154938fd1498Szrj return true;
155038fd1498Szrj for (; ctx; ctx = ctx->outer)
155138fd1498Szrj if (is_gimple_omp_offloaded (ctx->stmt))
155238fd1498Szrj return true;
155338fd1498Szrj return false;
155438fd1498Szrj }
155538fd1498Szrj
155638fd1498Szrj /* Build a decl for the omp child function. It'll not contain a body
155738fd1498Szrj yet, just the bare decl. */
155838fd1498Szrj
155938fd1498Szrj static void
create_omp_child_function(omp_context * ctx,bool task_copy)156038fd1498Szrj create_omp_child_function (omp_context *ctx, bool task_copy)
156138fd1498Szrj {
156238fd1498Szrj tree decl, type, name, t;
156338fd1498Szrj
156438fd1498Szrj name = create_omp_child_function_name (task_copy);
156538fd1498Szrj if (task_copy)
156638fd1498Szrj type = build_function_type_list (void_type_node, ptr_type_node,
156738fd1498Szrj ptr_type_node, NULL_TREE);
156838fd1498Szrj else
156938fd1498Szrj type = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
157038fd1498Szrj
157138fd1498Szrj decl = build_decl (gimple_location (ctx->stmt), FUNCTION_DECL, name, type);
157238fd1498Szrj
157338fd1498Szrj gcc_checking_assert (!is_gimple_omp_oacc (ctx->stmt)
157438fd1498Szrj || !task_copy);
157538fd1498Szrj if (!task_copy)
157638fd1498Szrj ctx->cb.dst_fn = decl;
157738fd1498Szrj else
157838fd1498Szrj gimple_omp_task_set_copy_fn (ctx->stmt, decl);
157938fd1498Szrj
158038fd1498Szrj TREE_STATIC (decl) = 1;
158138fd1498Szrj TREE_USED (decl) = 1;
158238fd1498Szrj DECL_ARTIFICIAL (decl) = 1;
158338fd1498Szrj DECL_IGNORED_P (decl) = 0;
158438fd1498Szrj TREE_PUBLIC (decl) = 0;
158538fd1498Szrj DECL_UNINLINABLE (decl) = 1;
158638fd1498Szrj DECL_EXTERNAL (decl) = 0;
158738fd1498Szrj DECL_CONTEXT (decl) = NULL_TREE;
158838fd1498Szrj DECL_INITIAL (decl) = make_node (BLOCK);
158938fd1498Szrj BLOCK_SUPERCONTEXT (DECL_INITIAL (decl)) = decl;
159038fd1498Szrj DECL_ATTRIBUTES (decl) = DECL_ATTRIBUTES (current_function_decl);
159138fd1498Szrj /* Remove omp declare simd attribute from the new attributes. */
159238fd1498Szrj if (tree a = lookup_attribute ("omp declare simd", DECL_ATTRIBUTES (decl)))
159338fd1498Szrj {
159438fd1498Szrj while (tree a2 = lookup_attribute ("omp declare simd", TREE_CHAIN (a)))
159538fd1498Szrj a = a2;
159638fd1498Szrj a = TREE_CHAIN (a);
159738fd1498Szrj for (tree *p = &DECL_ATTRIBUTES (decl); *p != a;)
159838fd1498Szrj if (is_attribute_p ("omp declare simd", get_attribute_name (*p)))
159938fd1498Szrj *p = TREE_CHAIN (*p);
160038fd1498Szrj else
160138fd1498Szrj {
160238fd1498Szrj tree chain = TREE_CHAIN (*p);
160338fd1498Szrj *p = copy_node (*p);
160438fd1498Szrj p = &TREE_CHAIN (*p);
160538fd1498Szrj *p = chain;
160638fd1498Szrj }
160738fd1498Szrj }
160838fd1498Szrj DECL_FUNCTION_SPECIFIC_OPTIMIZATION (decl)
160938fd1498Szrj = DECL_FUNCTION_SPECIFIC_OPTIMIZATION (current_function_decl);
161038fd1498Szrj DECL_FUNCTION_SPECIFIC_TARGET (decl)
161138fd1498Szrj = DECL_FUNCTION_SPECIFIC_TARGET (current_function_decl);
161238fd1498Szrj DECL_FUNCTION_VERSIONED (decl)
161338fd1498Szrj = DECL_FUNCTION_VERSIONED (current_function_decl);
161438fd1498Szrj
161538fd1498Szrj if (omp_maybe_offloaded_ctx (ctx))
161638fd1498Szrj {
161738fd1498Szrj cgraph_node::get_create (decl)->offloadable = 1;
161838fd1498Szrj if (ENABLE_OFFLOADING)
161938fd1498Szrj g->have_offload = true;
162038fd1498Szrj }
162138fd1498Szrj
162238fd1498Szrj if (cgraph_node::get_create (decl)->offloadable
162338fd1498Szrj && !lookup_attribute ("omp declare target",
162438fd1498Szrj DECL_ATTRIBUTES (current_function_decl)))
162538fd1498Szrj {
162638fd1498Szrj const char *target_attr = (is_gimple_omp_offloaded (ctx->stmt)
162738fd1498Szrj ? "omp target entrypoint"
162838fd1498Szrj : "omp declare target");
162938fd1498Szrj DECL_ATTRIBUTES (decl)
163038fd1498Szrj = tree_cons (get_identifier (target_attr),
163138fd1498Szrj NULL_TREE, DECL_ATTRIBUTES (decl));
163238fd1498Szrj }
163338fd1498Szrj
163438fd1498Szrj t = build_decl (DECL_SOURCE_LOCATION (decl),
163538fd1498Szrj RESULT_DECL, NULL_TREE, void_type_node);
163638fd1498Szrj DECL_ARTIFICIAL (t) = 1;
163738fd1498Szrj DECL_IGNORED_P (t) = 1;
163838fd1498Szrj DECL_CONTEXT (t) = decl;
163938fd1498Szrj DECL_RESULT (decl) = t;
164038fd1498Szrj
164138fd1498Szrj tree data_name = get_identifier (".omp_data_i");
164238fd1498Szrj t = build_decl (DECL_SOURCE_LOCATION (decl), PARM_DECL, data_name,
164338fd1498Szrj ptr_type_node);
164438fd1498Szrj DECL_ARTIFICIAL (t) = 1;
164538fd1498Szrj DECL_NAMELESS (t) = 1;
164638fd1498Szrj DECL_ARG_TYPE (t) = ptr_type_node;
164738fd1498Szrj DECL_CONTEXT (t) = current_function_decl;
164838fd1498Szrj TREE_USED (t) = 1;
164938fd1498Szrj TREE_READONLY (t) = 1;
165038fd1498Szrj DECL_ARGUMENTS (decl) = t;
165138fd1498Szrj if (!task_copy)
165238fd1498Szrj ctx->receiver_decl = t;
165338fd1498Szrj else
165438fd1498Szrj {
165538fd1498Szrj t = build_decl (DECL_SOURCE_LOCATION (decl),
165638fd1498Szrj PARM_DECL, get_identifier (".omp_data_o"),
165738fd1498Szrj ptr_type_node);
165838fd1498Szrj DECL_ARTIFICIAL (t) = 1;
165938fd1498Szrj DECL_NAMELESS (t) = 1;
166038fd1498Szrj DECL_ARG_TYPE (t) = ptr_type_node;
166138fd1498Szrj DECL_CONTEXT (t) = current_function_decl;
166238fd1498Szrj TREE_USED (t) = 1;
166338fd1498Szrj TREE_ADDRESSABLE (t) = 1;
166438fd1498Szrj DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
166538fd1498Szrj DECL_ARGUMENTS (decl) = t;
166638fd1498Szrj }
166738fd1498Szrj
166838fd1498Szrj /* Allocate memory for the function structure. The call to
166938fd1498Szrj allocate_struct_function clobbers CFUN, so we need to restore
167038fd1498Szrj it afterward. */
167138fd1498Szrj push_struct_function (decl);
167238fd1498Szrj cfun->function_end_locus = gimple_location (ctx->stmt);
167338fd1498Szrj init_tree_ssa (cfun);
167438fd1498Szrj pop_cfun ();
167538fd1498Szrj }
167638fd1498Szrj
167738fd1498Szrj /* Callback for walk_gimple_seq. Check if combined parallel
167838fd1498Szrj contains gimple_omp_for_combined_into_p OMP_FOR. */
167938fd1498Szrj
168038fd1498Szrj tree
omp_find_combined_for(gimple_stmt_iterator * gsi_p,bool * handled_ops_p,struct walk_stmt_info * wi)168138fd1498Szrj omp_find_combined_for (gimple_stmt_iterator *gsi_p,
168238fd1498Szrj bool *handled_ops_p,
168338fd1498Szrj struct walk_stmt_info *wi)
168438fd1498Szrj {
168538fd1498Szrj gimple *stmt = gsi_stmt (*gsi_p);
168638fd1498Szrj
168738fd1498Szrj *handled_ops_p = true;
168838fd1498Szrj switch (gimple_code (stmt))
168938fd1498Szrj {
169038fd1498Szrj WALK_SUBSTMTS;
169138fd1498Szrj
169238fd1498Szrj case GIMPLE_OMP_FOR:
169338fd1498Szrj if (gimple_omp_for_combined_into_p (stmt)
169438fd1498Szrj && gimple_omp_for_kind (stmt)
169538fd1498Szrj == *(const enum gf_mask *) (wi->info))
169638fd1498Szrj {
169738fd1498Szrj wi->info = stmt;
169838fd1498Szrj return integer_zero_node;
169938fd1498Szrj }
170038fd1498Szrj break;
170138fd1498Szrj default:
170238fd1498Szrj break;
170338fd1498Szrj }
170438fd1498Szrj return NULL;
170538fd1498Szrj }
170638fd1498Szrj
170738fd1498Szrj /* Add _LOOPTEMP_ clauses on OpenMP parallel or task. */
170838fd1498Szrj
170938fd1498Szrj static void
add_taskreg_looptemp_clauses(enum gf_mask msk,gimple * stmt,omp_context * outer_ctx)171038fd1498Szrj add_taskreg_looptemp_clauses (enum gf_mask msk, gimple *stmt,
171138fd1498Szrj omp_context *outer_ctx)
171238fd1498Szrj {
171338fd1498Szrj struct walk_stmt_info wi;
171438fd1498Szrj
171538fd1498Szrj memset (&wi, 0, sizeof (wi));
171638fd1498Szrj wi.val_only = true;
171738fd1498Szrj wi.info = (void *) &msk;
171838fd1498Szrj walk_gimple_seq (gimple_omp_body (stmt), omp_find_combined_for, NULL, &wi);
171938fd1498Szrj if (wi.info != (void *) &msk)
172038fd1498Szrj {
172138fd1498Szrj gomp_for *for_stmt = as_a <gomp_for *> ((gimple *) wi.info);
172238fd1498Szrj struct omp_for_data fd;
172338fd1498Szrj omp_extract_for_data (for_stmt, &fd, NULL);
172438fd1498Szrj /* We need two temporaries with fd.loop.v type (istart/iend)
172538fd1498Szrj and then (fd.collapse - 1) temporaries with the same
172638fd1498Szrj type for count2 ... countN-1 vars if not constant. */
172738fd1498Szrj size_t count = 2, i;
172838fd1498Szrj tree type = fd.iter_type;
172938fd1498Szrj if (fd.collapse > 1
173038fd1498Szrj && TREE_CODE (fd.loop.n2) != INTEGER_CST)
173138fd1498Szrj {
173238fd1498Szrj count += fd.collapse - 1;
173338fd1498Szrj /* If there are lastprivate clauses on the inner
173438fd1498Szrj GIMPLE_OMP_FOR, add one more temporaries for the total number
173538fd1498Szrj of iterations (product of count1 ... countN-1). */
173638fd1498Szrj if (omp_find_clause (gimple_omp_for_clauses (for_stmt),
173738fd1498Szrj OMP_CLAUSE_LASTPRIVATE))
173838fd1498Szrj count++;
173938fd1498Szrj else if (msk == GF_OMP_FOR_KIND_FOR
174038fd1498Szrj && omp_find_clause (gimple_omp_parallel_clauses (stmt),
174138fd1498Szrj OMP_CLAUSE_LASTPRIVATE))
174238fd1498Szrj count++;
174338fd1498Szrj }
174438fd1498Szrj for (i = 0; i < count; i++)
174538fd1498Szrj {
174638fd1498Szrj tree temp = create_tmp_var (type);
174738fd1498Szrj tree c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__LOOPTEMP_);
174838fd1498Szrj insert_decl_map (&outer_ctx->cb, temp, temp);
174938fd1498Szrj OMP_CLAUSE_DECL (c) = temp;
175038fd1498Szrj OMP_CLAUSE_CHAIN (c) = gimple_omp_taskreg_clauses (stmt);
175138fd1498Szrj gimple_omp_taskreg_set_clauses (stmt, c);
175238fd1498Szrj }
175338fd1498Szrj }
175438fd1498Szrj }
175538fd1498Szrj
175638fd1498Szrj /* Scan an OpenMP parallel directive. */
175738fd1498Szrj
175838fd1498Szrj static void
scan_omp_parallel(gimple_stmt_iterator * gsi,omp_context * outer_ctx)175938fd1498Szrj scan_omp_parallel (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
176038fd1498Szrj {
176138fd1498Szrj omp_context *ctx;
176238fd1498Szrj tree name;
176338fd1498Szrj gomp_parallel *stmt = as_a <gomp_parallel *> (gsi_stmt (*gsi));
176438fd1498Szrj
176538fd1498Szrj /* Ignore parallel directives with empty bodies, unless there
176638fd1498Szrj are copyin clauses. */
176738fd1498Szrj if (optimize > 0
176838fd1498Szrj && empty_body_p (gimple_omp_body (stmt))
176938fd1498Szrj && omp_find_clause (gimple_omp_parallel_clauses (stmt),
177038fd1498Szrj OMP_CLAUSE_COPYIN) == NULL)
177138fd1498Szrj {
177238fd1498Szrj gsi_replace (gsi, gimple_build_nop (), false);
177338fd1498Szrj return;
177438fd1498Szrj }
177538fd1498Szrj
177638fd1498Szrj if (gimple_omp_parallel_combined_p (stmt))
177738fd1498Szrj add_taskreg_looptemp_clauses (GF_OMP_FOR_KIND_FOR, stmt, outer_ctx);
177838fd1498Szrj
177938fd1498Szrj ctx = new_omp_context (stmt, outer_ctx);
178038fd1498Szrj taskreg_contexts.safe_push (ctx);
178138fd1498Szrj if (taskreg_nesting_level > 1)
178238fd1498Szrj ctx->is_nested = true;
178338fd1498Szrj ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
178438fd1498Szrj ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
178538fd1498Szrj name = create_tmp_var_name (".omp_data_s");
178638fd1498Szrj name = build_decl (gimple_location (stmt),
178738fd1498Szrj TYPE_DECL, name, ctx->record_type);
178838fd1498Szrj DECL_ARTIFICIAL (name) = 1;
178938fd1498Szrj DECL_NAMELESS (name) = 1;
179038fd1498Szrj TYPE_NAME (ctx->record_type) = name;
179138fd1498Szrj TYPE_ARTIFICIAL (ctx->record_type) = 1;
179238fd1498Szrj if (!gimple_omp_parallel_grid_phony (stmt))
179338fd1498Szrj {
179438fd1498Szrj create_omp_child_function (ctx, false);
179538fd1498Szrj gimple_omp_parallel_set_child_fn (stmt, ctx->cb.dst_fn);
179638fd1498Szrj }
179738fd1498Szrj
179838fd1498Szrj scan_sharing_clauses (gimple_omp_parallel_clauses (stmt), ctx);
179938fd1498Szrj scan_omp (gimple_omp_body_ptr (stmt), ctx);
180038fd1498Szrj
180138fd1498Szrj if (TYPE_FIELDS (ctx->record_type) == NULL)
180238fd1498Szrj ctx->record_type = ctx->receiver_decl = NULL;
180338fd1498Szrj }
180438fd1498Szrj
180538fd1498Szrj /* Scan an OpenMP task directive. */
180638fd1498Szrj
180738fd1498Szrj static void
scan_omp_task(gimple_stmt_iterator * gsi,omp_context * outer_ctx)180838fd1498Szrj scan_omp_task (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
180938fd1498Szrj {
181038fd1498Szrj omp_context *ctx;
181138fd1498Szrj tree name, t;
181238fd1498Szrj gomp_task *stmt = as_a <gomp_task *> (gsi_stmt (*gsi));
181338fd1498Szrj
181438fd1498Szrj /* Ignore task directives with empty bodies, unless they have depend
181538fd1498Szrj clause. */
181638fd1498Szrj if (optimize > 0
181738fd1498Szrj && empty_body_p (gimple_omp_body (stmt))
181838fd1498Szrj && !omp_find_clause (gimple_omp_task_clauses (stmt), OMP_CLAUSE_DEPEND))
181938fd1498Szrj {
182038fd1498Szrj gsi_replace (gsi, gimple_build_nop (), false);
182138fd1498Szrj return;
182238fd1498Szrj }
182338fd1498Szrj
182438fd1498Szrj if (gimple_omp_task_taskloop_p (stmt))
182538fd1498Szrj add_taskreg_looptemp_clauses (GF_OMP_FOR_KIND_TASKLOOP, stmt, outer_ctx);
182638fd1498Szrj
182738fd1498Szrj ctx = new_omp_context (stmt, outer_ctx);
182838fd1498Szrj taskreg_contexts.safe_push (ctx);
182938fd1498Szrj if (taskreg_nesting_level > 1)
183038fd1498Szrj ctx->is_nested = true;
183138fd1498Szrj ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
183238fd1498Szrj ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
183338fd1498Szrj name = create_tmp_var_name (".omp_data_s");
183438fd1498Szrj name = build_decl (gimple_location (stmt),
183538fd1498Szrj TYPE_DECL, name, ctx->record_type);
183638fd1498Szrj DECL_ARTIFICIAL (name) = 1;
183738fd1498Szrj DECL_NAMELESS (name) = 1;
183838fd1498Szrj TYPE_NAME (ctx->record_type) = name;
183938fd1498Szrj TYPE_ARTIFICIAL (ctx->record_type) = 1;
184038fd1498Szrj create_omp_child_function (ctx, false);
184138fd1498Szrj gimple_omp_task_set_child_fn (stmt, ctx->cb.dst_fn);
184238fd1498Szrj
184338fd1498Szrj scan_sharing_clauses (gimple_omp_task_clauses (stmt), ctx);
184438fd1498Szrj
184538fd1498Szrj if (ctx->srecord_type)
184638fd1498Szrj {
184738fd1498Szrj name = create_tmp_var_name (".omp_data_a");
184838fd1498Szrj name = build_decl (gimple_location (stmt),
184938fd1498Szrj TYPE_DECL, name, ctx->srecord_type);
185038fd1498Szrj DECL_ARTIFICIAL (name) = 1;
185138fd1498Szrj DECL_NAMELESS (name) = 1;
185238fd1498Szrj TYPE_NAME (ctx->srecord_type) = name;
185338fd1498Szrj TYPE_ARTIFICIAL (ctx->srecord_type) = 1;
185438fd1498Szrj create_omp_child_function (ctx, true);
185538fd1498Szrj }
185638fd1498Szrj
185738fd1498Szrj scan_omp (gimple_omp_body_ptr (stmt), ctx);
185838fd1498Szrj
185938fd1498Szrj if (TYPE_FIELDS (ctx->record_type) == NULL)
186038fd1498Szrj {
186138fd1498Szrj ctx->record_type = ctx->receiver_decl = NULL;
186238fd1498Szrj t = build_int_cst (long_integer_type_node, 0);
186338fd1498Szrj gimple_omp_task_set_arg_size (stmt, t);
186438fd1498Szrj t = build_int_cst (long_integer_type_node, 1);
186538fd1498Szrj gimple_omp_task_set_arg_align (stmt, t);
186638fd1498Szrj }
186738fd1498Szrj }
186838fd1498Szrj
186938fd1498Szrj /* Helper function for finish_taskreg_scan, called through walk_tree.
187038fd1498Szrj If maybe_lookup_decl_in_outer_context returns non-NULL for some
187138fd1498Szrj tree, replace it in the expression. */
187238fd1498Szrj
187338fd1498Szrj static tree
finish_taskreg_remap(tree * tp,int * walk_subtrees,void * data)187438fd1498Szrj finish_taskreg_remap (tree *tp, int *walk_subtrees, void *data)
187538fd1498Szrj {
187638fd1498Szrj if (VAR_P (*tp))
187738fd1498Szrj {
187838fd1498Szrj omp_context *ctx = (omp_context *) data;
187938fd1498Szrj tree t = maybe_lookup_decl_in_outer_ctx (*tp, ctx);
188038fd1498Szrj if (t != *tp)
188138fd1498Szrj {
188238fd1498Szrj if (DECL_HAS_VALUE_EXPR_P (t))
188338fd1498Szrj t = unshare_expr (DECL_VALUE_EXPR (t));
188438fd1498Szrj *tp = t;
188538fd1498Szrj }
188638fd1498Szrj *walk_subtrees = 0;
188738fd1498Szrj }
188838fd1498Szrj else if (IS_TYPE_OR_DECL_P (*tp))
188938fd1498Szrj *walk_subtrees = 0;
189038fd1498Szrj return NULL_TREE;
189138fd1498Szrj }
189238fd1498Szrj
189338fd1498Szrj /* If any decls have been made addressable during scan_omp,
189438fd1498Szrj adjust their fields if needed, and layout record types
189538fd1498Szrj of parallel/task constructs. */
189638fd1498Szrj
189738fd1498Szrj static void
finish_taskreg_scan(omp_context * ctx)189838fd1498Szrj finish_taskreg_scan (omp_context *ctx)
189938fd1498Szrj {
190038fd1498Szrj if (ctx->record_type == NULL_TREE)
190138fd1498Szrj return;
190238fd1498Szrj
190338fd1498Szrj /* If any task_shared_vars were needed, verify all
190438fd1498Szrj OMP_CLAUSE_SHARED clauses on GIMPLE_OMP_{PARALLEL,TASK}
190538fd1498Szrj statements if use_pointer_for_field hasn't changed
190638fd1498Szrj because of that. If it did, update field types now. */
190738fd1498Szrj if (task_shared_vars)
190838fd1498Szrj {
190938fd1498Szrj tree c;
191038fd1498Szrj
191138fd1498Szrj for (c = gimple_omp_taskreg_clauses (ctx->stmt);
191238fd1498Szrj c; c = OMP_CLAUSE_CHAIN (c))
191338fd1498Szrj if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
191438fd1498Szrj && !OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
191538fd1498Szrj {
191638fd1498Szrj tree decl = OMP_CLAUSE_DECL (c);
191738fd1498Szrj
191838fd1498Szrj /* Global variables don't need to be copied,
191938fd1498Szrj the receiver side will use them directly. */
192038fd1498Szrj if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
192138fd1498Szrj continue;
192238fd1498Szrj if (!bitmap_bit_p (task_shared_vars, DECL_UID (decl))
192338fd1498Szrj || !use_pointer_for_field (decl, ctx))
192438fd1498Szrj continue;
192538fd1498Szrj tree field = lookup_field (decl, ctx);
192638fd1498Szrj if (TREE_CODE (TREE_TYPE (field)) == POINTER_TYPE
192738fd1498Szrj && TREE_TYPE (TREE_TYPE (field)) == TREE_TYPE (decl))
192838fd1498Szrj continue;
192938fd1498Szrj TREE_TYPE (field) = build_pointer_type (TREE_TYPE (decl));
193038fd1498Szrj TREE_THIS_VOLATILE (field) = 0;
193138fd1498Szrj DECL_USER_ALIGN (field) = 0;
193238fd1498Szrj SET_DECL_ALIGN (field, TYPE_ALIGN (TREE_TYPE (field)));
193338fd1498Szrj if (TYPE_ALIGN (ctx->record_type) < DECL_ALIGN (field))
193438fd1498Szrj SET_TYPE_ALIGN (ctx->record_type, DECL_ALIGN (field));
193538fd1498Szrj if (ctx->srecord_type)
193638fd1498Szrj {
193738fd1498Szrj tree sfield = lookup_sfield (decl, ctx);
193838fd1498Szrj TREE_TYPE (sfield) = TREE_TYPE (field);
193938fd1498Szrj TREE_THIS_VOLATILE (sfield) = 0;
194038fd1498Szrj DECL_USER_ALIGN (sfield) = 0;
194138fd1498Szrj SET_DECL_ALIGN (sfield, DECL_ALIGN (field));
194238fd1498Szrj if (TYPE_ALIGN (ctx->srecord_type) < DECL_ALIGN (sfield))
194338fd1498Szrj SET_TYPE_ALIGN (ctx->srecord_type, DECL_ALIGN (sfield));
194438fd1498Szrj }
194538fd1498Szrj }
194638fd1498Szrj }
194738fd1498Szrj
194838fd1498Szrj if (gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL)
194938fd1498Szrj {
195038fd1498Szrj layout_type (ctx->record_type);
195138fd1498Szrj fixup_child_record_type (ctx);
195238fd1498Szrj }
195338fd1498Szrj else
195438fd1498Szrj {
195538fd1498Szrj location_t loc = gimple_location (ctx->stmt);
195638fd1498Szrj tree *p, vla_fields = NULL_TREE, *q = &vla_fields;
195738fd1498Szrj /* Move VLA fields to the end. */
195838fd1498Szrj p = &TYPE_FIELDS (ctx->record_type);
195938fd1498Szrj while (*p)
196038fd1498Szrj if (!TYPE_SIZE_UNIT (TREE_TYPE (*p))
196138fd1498Szrj || ! TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (*p))))
196238fd1498Szrj {
196338fd1498Szrj *q = *p;
196438fd1498Szrj *p = TREE_CHAIN (*p);
196538fd1498Szrj TREE_CHAIN (*q) = NULL_TREE;
196638fd1498Szrj q = &TREE_CHAIN (*q);
196738fd1498Szrj }
196838fd1498Szrj else
196938fd1498Szrj p = &DECL_CHAIN (*p);
197038fd1498Szrj *p = vla_fields;
197138fd1498Szrj if (gimple_omp_task_taskloop_p (ctx->stmt))
197238fd1498Szrj {
197338fd1498Szrj /* Move fields corresponding to first and second _looptemp_
197438fd1498Szrj clause first. There are filled by GOMP_taskloop
197538fd1498Szrj and thus need to be in specific positions. */
197638fd1498Szrj tree c1 = gimple_omp_task_clauses (ctx->stmt);
197738fd1498Szrj c1 = omp_find_clause (c1, OMP_CLAUSE__LOOPTEMP_);
197838fd1498Szrj tree c2 = omp_find_clause (OMP_CLAUSE_CHAIN (c1),
197938fd1498Szrj OMP_CLAUSE__LOOPTEMP_);
198038fd1498Szrj tree f1 = lookup_field (OMP_CLAUSE_DECL (c1), ctx);
198138fd1498Szrj tree f2 = lookup_field (OMP_CLAUSE_DECL (c2), ctx);
198238fd1498Szrj p = &TYPE_FIELDS (ctx->record_type);
198338fd1498Szrj while (*p)
198438fd1498Szrj if (*p == f1 || *p == f2)
198538fd1498Szrj *p = DECL_CHAIN (*p);
198638fd1498Szrj else
198738fd1498Szrj p = &DECL_CHAIN (*p);
198838fd1498Szrj DECL_CHAIN (f1) = f2;
198938fd1498Szrj DECL_CHAIN (f2) = TYPE_FIELDS (ctx->record_type);
199038fd1498Szrj TYPE_FIELDS (ctx->record_type) = f1;
199138fd1498Szrj if (ctx->srecord_type)
199238fd1498Szrj {
199338fd1498Szrj f1 = lookup_sfield (OMP_CLAUSE_DECL (c1), ctx);
199438fd1498Szrj f2 = lookup_sfield (OMP_CLAUSE_DECL (c2), ctx);
199538fd1498Szrj p = &TYPE_FIELDS (ctx->srecord_type);
199638fd1498Szrj while (*p)
199738fd1498Szrj if (*p == f1 || *p == f2)
199838fd1498Szrj *p = DECL_CHAIN (*p);
199938fd1498Szrj else
200038fd1498Szrj p = &DECL_CHAIN (*p);
200138fd1498Szrj DECL_CHAIN (f1) = f2;
200238fd1498Szrj DECL_CHAIN (f2) = TYPE_FIELDS (ctx->srecord_type);
200338fd1498Szrj TYPE_FIELDS (ctx->srecord_type) = f1;
200438fd1498Szrj }
200538fd1498Szrj }
200638fd1498Szrj layout_type (ctx->record_type);
200738fd1498Szrj fixup_child_record_type (ctx);
200838fd1498Szrj if (ctx->srecord_type)
200938fd1498Szrj layout_type (ctx->srecord_type);
201038fd1498Szrj tree t = fold_convert_loc (loc, long_integer_type_node,
201138fd1498Szrj TYPE_SIZE_UNIT (ctx->record_type));
201238fd1498Szrj if (TREE_CODE (t) != INTEGER_CST)
201338fd1498Szrj {
201438fd1498Szrj t = unshare_expr (t);
201538fd1498Szrj walk_tree (&t, finish_taskreg_remap, ctx, NULL);
201638fd1498Szrj }
201738fd1498Szrj gimple_omp_task_set_arg_size (ctx->stmt, t);
201838fd1498Szrj t = build_int_cst (long_integer_type_node,
201938fd1498Szrj TYPE_ALIGN_UNIT (ctx->record_type));
202038fd1498Szrj gimple_omp_task_set_arg_align (ctx->stmt, t);
202138fd1498Szrj }
202238fd1498Szrj }
202338fd1498Szrj
202438fd1498Szrj /* Find the enclosing offload context. */
202538fd1498Szrj
202638fd1498Szrj static omp_context *
enclosing_target_ctx(omp_context * ctx)202738fd1498Szrj enclosing_target_ctx (omp_context *ctx)
202838fd1498Szrj {
202938fd1498Szrj for (; ctx; ctx = ctx->outer)
203038fd1498Szrj if (gimple_code (ctx->stmt) == GIMPLE_OMP_TARGET)
203138fd1498Szrj break;
203238fd1498Szrj
203338fd1498Szrj return ctx;
203438fd1498Szrj }
203538fd1498Szrj
203638fd1498Szrj /* Return true if ctx is part of an oacc kernels region. */
203738fd1498Szrj
203838fd1498Szrj static bool
ctx_in_oacc_kernels_region(omp_context * ctx)203938fd1498Szrj ctx_in_oacc_kernels_region (omp_context *ctx)
204038fd1498Szrj {
204138fd1498Szrj for (;ctx != NULL; ctx = ctx->outer)
204238fd1498Szrj {
204338fd1498Szrj gimple *stmt = ctx->stmt;
204438fd1498Szrj if (gimple_code (stmt) == GIMPLE_OMP_TARGET
204538fd1498Szrj && gimple_omp_target_kind (stmt) == GF_OMP_TARGET_KIND_OACC_KERNELS)
204638fd1498Szrj return true;
204738fd1498Szrj }
204838fd1498Szrj
204938fd1498Szrj return false;
205038fd1498Szrj }
205138fd1498Szrj
205238fd1498Szrj /* Check the parallelism clauses inside a kernels regions.
205338fd1498Szrj Until kernels handling moves to use the same loop indirection
205438fd1498Szrj scheme as parallel, we need to do this checking early. */
205538fd1498Szrj
205638fd1498Szrj static unsigned
check_oacc_kernel_gwv(gomp_for * stmt,omp_context * ctx)205738fd1498Szrj check_oacc_kernel_gwv (gomp_for *stmt, omp_context *ctx)
205838fd1498Szrj {
205938fd1498Szrj bool checking = true;
206038fd1498Szrj unsigned outer_mask = 0;
206138fd1498Szrj unsigned this_mask = 0;
206238fd1498Szrj bool has_seq = false, has_auto = false;
206338fd1498Szrj
206438fd1498Szrj if (ctx->outer)
206538fd1498Szrj outer_mask = check_oacc_kernel_gwv (NULL, ctx->outer);
206638fd1498Szrj if (!stmt)
206738fd1498Szrj {
206838fd1498Szrj checking = false;
206938fd1498Szrj if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR)
207038fd1498Szrj return outer_mask;
207138fd1498Szrj stmt = as_a <gomp_for *> (ctx->stmt);
207238fd1498Szrj }
207338fd1498Szrj
207438fd1498Szrj for (tree c = gimple_omp_for_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c))
207538fd1498Szrj {
207638fd1498Szrj switch (OMP_CLAUSE_CODE (c))
207738fd1498Szrj {
207838fd1498Szrj case OMP_CLAUSE_GANG:
207938fd1498Szrj this_mask |= GOMP_DIM_MASK (GOMP_DIM_GANG);
208038fd1498Szrj break;
208138fd1498Szrj case OMP_CLAUSE_WORKER:
208238fd1498Szrj this_mask |= GOMP_DIM_MASK (GOMP_DIM_WORKER);
208338fd1498Szrj break;
208438fd1498Szrj case OMP_CLAUSE_VECTOR:
208538fd1498Szrj this_mask |= GOMP_DIM_MASK (GOMP_DIM_VECTOR);
208638fd1498Szrj break;
208738fd1498Szrj case OMP_CLAUSE_SEQ:
208838fd1498Szrj has_seq = true;
208938fd1498Szrj break;
209038fd1498Szrj case OMP_CLAUSE_AUTO:
209138fd1498Szrj has_auto = true;
209238fd1498Szrj break;
209338fd1498Szrj default:
209438fd1498Szrj break;
209538fd1498Szrj }
209638fd1498Szrj }
209738fd1498Szrj
209838fd1498Szrj if (checking)
209938fd1498Szrj {
210038fd1498Szrj if (has_seq && (this_mask || has_auto))
210138fd1498Szrj error_at (gimple_location (stmt), "%<seq%> overrides other"
210238fd1498Szrj " OpenACC loop specifiers");
210338fd1498Szrj else if (has_auto && this_mask)
210438fd1498Szrj error_at (gimple_location (stmt), "%<auto%> conflicts with other"
210538fd1498Szrj " OpenACC loop specifiers");
210638fd1498Szrj
210738fd1498Szrj if (this_mask & outer_mask)
210838fd1498Szrj error_at (gimple_location (stmt), "inner loop uses same"
210938fd1498Szrj " OpenACC parallelism as containing loop");
211038fd1498Szrj }
211138fd1498Szrj
211238fd1498Szrj return outer_mask | this_mask;
211338fd1498Szrj }
211438fd1498Szrj
211538fd1498Szrj /* Scan a GIMPLE_OMP_FOR. */
211638fd1498Szrj
211738fd1498Szrj static omp_context *
scan_omp_for(gomp_for * stmt,omp_context * outer_ctx)211838fd1498Szrj scan_omp_for (gomp_for *stmt, omp_context *outer_ctx)
211938fd1498Szrj {
212038fd1498Szrj omp_context *ctx;
212138fd1498Szrj size_t i;
212238fd1498Szrj tree clauses = gimple_omp_for_clauses (stmt);
212338fd1498Szrj
212438fd1498Szrj ctx = new_omp_context (stmt, outer_ctx);
212538fd1498Szrj
212638fd1498Szrj if (is_gimple_omp_oacc (stmt))
212738fd1498Szrj {
212838fd1498Szrj omp_context *tgt = enclosing_target_ctx (outer_ctx);
212938fd1498Szrj
213038fd1498Szrj if (!tgt || is_oacc_parallel (tgt))
213138fd1498Szrj for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
213238fd1498Szrj {
213338fd1498Szrj char const *check = NULL;
213438fd1498Szrj
213538fd1498Szrj switch (OMP_CLAUSE_CODE (c))
213638fd1498Szrj {
213738fd1498Szrj case OMP_CLAUSE_GANG:
213838fd1498Szrj check = "gang";
213938fd1498Szrj break;
214038fd1498Szrj
214138fd1498Szrj case OMP_CLAUSE_WORKER:
214238fd1498Szrj check = "worker";
214338fd1498Szrj break;
214438fd1498Szrj
214538fd1498Szrj case OMP_CLAUSE_VECTOR:
214638fd1498Szrj check = "vector";
214738fd1498Szrj break;
214838fd1498Szrj
214938fd1498Szrj default:
215038fd1498Szrj break;
215138fd1498Szrj }
215238fd1498Szrj
215338fd1498Szrj if (check && OMP_CLAUSE_OPERAND (c, 0))
215438fd1498Szrj error_at (gimple_location (stmt),
215538fd1498Szrj "argument not permitted on %qs clause in"
215638fd1498Szrj " OpenACC %<parallel%>", check);
215738fd1498Szrj }
215838fd1498Szrj
215938fd1498Szrj if (tgt && is_oacc_kernels (tgt))
216038fd1498Szrj {
216138fd1498Szrj /* Strip out reductions, as they are not handled yet. */
216238fd1498Szrj tree *prev_ptr = &clauses;
216338fd1498Szrj
216438fd1498Szrj while (tree probe = *prev_ptr)
216538fd1498Szrj {
216638fd1498Szrj tree *next_ptr = &OMP_CLAUSE_CHAIN (probe);
216738fd1498Szrj
216838fd1498Szrj if (OMP_CLAUSE_CODE (probe) == OMP_CLAUSE_REDUCTION)
216938fd1498Szrj *prev_ptr = *next_ptr;
217038fd1498Szrj else
217138fd1498Szrj prev_ptr = next_ptr;
217238fd1498Szrj }
217338fd1498Szrj
217438fd1498Szrj gimple_omp_for_set_clauses (stmt, clauses);
217538fd1498Szrj check_oacc_kernel_gwv (stmt, ctx);
217638fd1498Szrj }
217738fd1498Szrj }
217838fd1498Szrj
217938fd1498Szrj scan_sharing_clauses (clauses, ctx);
218038fd1498Szrj
218138fd1498Szrj scan_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
218238fd1498Szrj for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
218338fd1498Szrj {
218438fd1498Szrj scan_omp_op (gimple_omp_for_index_ptr (stmt, i), ctx);
218538fd1498Szrj scan_omp_op (gimple_omp_for_initial_ptr (stmt, i), ctx);
218638fd1498Szrj scan_omp_op (gimple_omp_for_final_ptr (stmt, i), ctx);
218738fd1498Szrj scan_omp_op (gimple_omp_for_incr_ptr (stmt, i), ctx);
218838fd1498Szrj }
218938fd1498Szrj scan_omp (gimple_omp_body_ptr (stmt), ctx);
219038fd1498Szrj return ctx;
219138fd1498Szrj }
219238fd1498Szrj
219338fd1498Szrj /* Duplicate #pragma omp simd, one for SIMT, another one for SIMD. */
219438fd1498Szrj
219538fd1498Szrj static void
scan_omp_simd(gimple_stmt_iterator * gsi,gomp_for * stmt,omp_context * outer_ctx)219638fd1498Szrj scan_omp_simd (gimple_stmt_iterator *gsi, gomp_for *stmt,
219738fd1498Szrj omp_context *outer_ctx)
219838fd1498Szrj {
219938fd1498Szrj gbind *bind = gimple_build_bind (NULL, NULL, NULL);
220038fd1498Szrj gsi_replace (gsi, bind, false);
220138fd1498Szrj gimple_seq seq = NULL;
220238fd1498Szrj gimple *g = gimple_build_call_internal (IFN_GOMP_USE_SIMT, 0);
220338fd1498Szrj tree cond = create_tmp_var_raw (integer_type_node);
220438fd1498Szrj DECL_CONTEXT (cond) = current_function_decl;
220538fd1498Szrj DECL_SEEN_IN_BIND_EXPR_P (cond) = 1;
220638fd1498Szrj gimple_bind_set_vars (bind, cond);
220738fd1498Szrj gimple_call_set_lhs (g, cond);
220838fd1498Szrj gimple_seq_add_stmt (&seq, g);
220938fd1498Szrj tree lab1 = create_artificial_label (UNKNOWN_LOCATION);
221038fd1498Szrj tree lab2 = create_artificial_label (UNKNOWN_LOCATION);
221138fd1498Szrj tree lab3 = create_artificial_label (UNKNOWN_LOCATION);
221238fd1498Szrj g = gimple_build_cond (NE_EXPR, cond, integer_zero_node, lab1, lab2);
221338fd1498Szrj gimple_seq_add_stmt (&seq, g);
221438fd1498Szrj g = gimple_build_label (lab1);
221538fd1498Szrj gimple_seq_add_stmt (&seq, g);
221638fd1498Szrj gimple_seq new_seq = copy_gimple_seq_and_replace_locals (stmt);
221738fd1498Szrj gomp_for *new_stmt = as_a <gomp_for *> (new_seq);
221838fd1498Szrj tree clause = build_omp_clause (gimple_location (stmt), OMP_CLAUSE__SIMT_);
221938fd1498Szrj OMP_CLAUSE_CHAIN (clause) = gimple_omp_for_clauses (new_stmt);
222038fd1498Szrj gimple_omp_for_set_clauses (new_stmt, clause);
222138fd1498Szrj gimple_seq_add_stmt (&seq, new_stmt);
222238fd1498Szrj g = gimple_build_goto (lab3);
222338fd1498Szrj gimple_seq_add_stmt (&seq, g);
222438fd1498Szrj g = gimple_build_label (lab2);
222538fd1498Szrj gimple_seq_add_stmt (&seq, g);
222638fd1498Szrj gimple_seq_add_stmt (&seq, stmt);
222738fd1498Szrj g = gimple_build_label (lab3);
222838fd1498Szrj gimple_seq_add_stmt (&seq, g);
222938fd1498Szrj gimple_bind_set_body (bind, seq);
223038fd1498Szrj update_stmt (bind);
223138fd1498Szrj scan_omp_for (new_stmt, outer_ctx);
223238fd1498Szrj scan_omp_for (stmt, outer_ctx)->simt_stmt = new_stmt;
223338fd1498Szrj }
223438fd1498Szrj
223538fd1498Szrj /* Scan an OpenMP sections directive. */
223638fd1498Szrj
223738fd1498Szrj static void
scan_omp_sections(gomp_sections * stmt,omp_context * outer_ctx)223838fd1498Szrj scan_omp_sections (gomp_sections *stmt, omp_context *outer_ctx)
223938fd1498Szrj {
224038fd1498Szrj omp_context *ctx;
224138fd1498Szrj
224238fd1498Szrj ctx = new_omp_context (stmt, outer_ctx);
224338fd1498Szrj scan_sharing_clauses (gimple_omp_sections_clauses (stmt), ctx);
224438fd1498Szrj scan_omp (gimple_omp_body_ptr (stmt), ctx);
224538fd1498Szrj }
224638fd1498Szrj
224738fd1498Szrj /* Scan an OpenMP single directive. */
224838fd1498Szrj
224938fd1498Szrj static void
scan_omp_single(gomp_single * stmt,omp_context * outer_ctx)225038fd1498Szrj scan_omp_single (gomp_single *stmt, omp_context *outer_ctx)
225138fd1498Szrj {
225238fd1498Szrj omp_context *ctx;
225338fd1498Szrj tree name;
225438fd1498Szrj
225538fd1498Szrj ctx = new_omp_context (stmt, outer_ctx);
225638fd1498Szrj ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
225738fd1498Szrj ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
225838fd1498Szrj name = create_tmp_var_name (".omp_copy_s");
225938fd1498Szrj name = build_decl (gimple_location (stmt),
226038fd1498Szrj TYPE_DECL, name, ctx->record_type);
226138fd1498Szrj TYPE_NAME (ctx->record_type) = name;
226238fd1498Szrj
226338fd1498Szrj scan_sharing_clauses (gimple_omp_single_clauses (stmt), ctx);
226438fd1498Szrj scan_omp (gimple_omp_body_ptr (stmt), ctx);
226538fd1498Szrj
226638fd1498Szrj if (TYPE_FIELDS (ctx->record_type) == NULL)
226738fd1498Szrj ctx->record_type = NULL;
226838fd1498Szrj else
226938fd1498Szrj layout_type (ctx->record_type);
227038fd1498Szrj }
227138fd1498Szrj
227238fd1498Szrj /* Return true if the CLAUSES of an omp target guarantee that the base pointers
227338fd1498Szrj used in the corresponding offloaded function are restrict. */
227438fd1498Szrj
227538fd1498Szrj static bool
omp_target_base_pointers_restrict_p(tree clauses)227638fd1498Szrj omp_target_base_pointers_restrict_p (tree clauses)
227738fd1498Szrj {
227838fd1498Szrj /* The analysis relies on the GOMP_MAP_FORCE_* mapping kinds, which are only
227938fd1498Szrj used by OpenACC. */
228038fd1498Szrj if (flag_openacc == 0)
228138fd1498Szrj return false;
228238fd1498Szrj
228338fd1498Szrj /* I. Basic example:
228438fd1498Szrj
228538fd1498Szrj void foo (void)
228638fd1498Szrj {
228738fd1498Szrj unsigned int a[2], b[2];
228838fd1498Szrj
228938fd1498Szrj #pragma acc kernels \
229038fd1498Szrj copyout (a) \
229138fd1498Szrj copyout (b)
229238fd1498Szrj {
229338fd1498Szrj a[0] = 0;
229438fd1498Szrj b[0] = 1;
229538fd1498Szrj }
229638fd1498Szrj }
229738fd1498Szrj
229838fd1498Szrj After gimplification, we have:
229938fd1498Szrj
230038fd1498Szrj #pragma omp target oacc_kernels \
230138fd1498Szrj map(force_from:a [len: 8]) \
230238fd1498Szrj map(force_from:b [len: 8])
230338fd1498Szrj {
230438fd1498Szrj a[0] = 0;
230538fd1498Szrj b[0] = 1;
230638fd1498Szrj }
230738fd1498Szrj
230838fd1498Szrj Because both mappings have the force prefix, we know that they will be
230938fd1498Szrj allocated when calling the corresponding offloaded function, which means we
231038fd1498Szrj can mark the base pointers for a and b in the offloaded function as
231138fd1498Szrj restrict. */
231238fd1498Szrj
231338fd1498Szrj tree c;
231438fd1498Szrj for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
231538fd1498Szrj {
231638fd1498Szrj if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP)
231738fd1498Szrj return false;
231838fd1498Szrj
231938fd1498Szrj switch (OMP_CLAUSE_MAP_KIND (c))
232038fd1498Szrj {
232138fd1498Szrj case GOMP_MAP_FORCE_ALLOC:
232238fd1498Szrj case GOMP_MAP_FORCE_TO:
232338fd1498Szrj case GOMP_MAP_FORCE_FROM:
232438fd1498Szrj case GOMP_MAP_FORCE_TOFROM:
232538fd1498Szrj break;
232638fd1498Szrj default:
232738fd1498Szrj return false;
232838fd1498Szrj }
232938fd1498Szrj }
233038fd1498Szrj
233138fd1498Szrj return true;
233238fd1498Szrj }
233338fd1498Szrj
233438fd1498Szrj /* Scan a GIMPLE_OMP_TARGET. */
233538fd1498Szrj
233638fd1498Szrj static void
scan_omp_target(gomp_target * stmt,omp_context * outer_ctx)233738fd1498Szrj scan_omp_target (gomp_target *stmt, omp_context *outer_ctx)
233838fd1498Szrj {
233938fd1498Szrj omp_context *ctx;
234038fd1498Szrj tree name;
234138fd1498Szrj bool offloaded = is_gimple_omp_offloaded (stmt);
234238fd1498Szrj tree clauses = gimple_omp_target_clauses (stmt);
234338fd1498Szrj
234438fd1498Szrj ctx = new_omp_context (stmt, outer_ctx);
234538fd1498Szrj ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
234638fd1498Szrj ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
234738fd1498Szrj name = create_tmp_var_name (".omp_data_t");
234838fd1498Szrj name = build_decl (gimple_location (stmt),
234938fd1498Szrj TYPE_DECL, name, ctx->record_type);
235038fd1498Szrj DECL_ARTIFICIAL (name) = 1;
235138fd1498Szrj DECL_NAMELESS (name) = 1;
235238fd1498Szrj TYPE_NAME (ctx->record_type) = name;
235338fd1498Szrj TYPE_ARTIFICIAL (ctx->record_type) = 1;
235438fd1498Szrj
235538fd1498Szrj bool base_pointers_restrict = false;
235638fd1498Szrj if (offloaded)
235738fd1498Szrj {
235838fd1498Szrj create_omp_child_function (ctx, false);
235938fd1498Szrj gimple_omp_target_set_child_fn (stmt, ctx->cb.dst_fn);
236038fd1498Szrj
236138fd1498Szrj base_pointers_restrict = omp_target_base_pointers_restrict_p (clauses);
236238fd1498Szrj if (base_pointers_restrict
236338fd1498Szrj && dump_file && (dump_flags & TDF_DETAILS))
236438fd1498Szrj fprintf (dump_file,
236538fd1498Szrj "Base pointers in offloaded function are restrict\n");
236638fd1498Szrj }
236738fd1498Szrj
236838fd1498Szrj scan_sharing_clauses (clauses, ctx, base_pointers_restrict);
236938fd1498Szrj scan_omp (gimple_omp_body_ptr (stmt), ctx);
237038fd1498Szrj
237138fd1498Szrj if (TYPE_FIELDS (ctx->record_type) == NULL)
237238fd1498Szrj ctx->record_type = ctx->receiver_decl = NULL;
237338fd1498Szrj else
237438fd1498Szrj {
237538fd1498Szrj TYPE_FIELDS (ctx->record_type)
237638fd1498Szrj = nreverse (TYPE_FIELDS (ctx->record_type));
237738fd1498Szrj if (flag_checking)
237838fd1498Szrj {
237938fd1498Szrj unsigned int align = DECL_ALIGN (TYPE_FIELDS (ctx->record_type));
238038fd1498Szrj for (tree field = TYPE_FIELDS (ctx->record_type);
238138fd1498Szrj field;
238238fd1498Szrj field = DECL_CHAIN (field))
238338fd1498Szrj gcc_assert (DECL_ALIGN (field) == align);
238438fd1498Szrj }
238538fd1498Szrj layout_type (ctx->record_type);
238638fd1498Szrj if (offloaded)
238738fd1498Szrj fixup_child_record_type (ctx);
238838fd1498Szrj }
238938fd1498Szrj }
239038fd1498Szrj
239138fd1498Szrj /* Scan an OpenMP teams directive. */
239238fd1498Szrj
239338fd1498Szrj static void
scan_omp_teams(gomp_teams * stmt,omp_context * outer_ctx)239438fd1498Szrj scan_omp_teams (gomp_teams *stmt, omp_context *outer_ctx)
239538fd1498Szrj {
239638fd1498Szrj omp_context *ctx = new_omp_context (stmt, outer_ctx);
239738fd1498Szrj scan_sharing_clauses (gimple_omp_teams_clauses (stmt), ctx);
239838fd1498Szrj scan_omp (gimple_omp_body_ptr (stmt), ctx);
239938fd1498Szrj }
240038fd1498Szrj
240138fd1498Szrj /* Check nesting restrictions. */
240238fd1498Szrj static bool
check_omp_nesting_restrictions(gimple * stmt,omp_context * ctx)240338fd1498Szrj check_omp_nesting_restrictions (gimple *stmt, omp_context *ctx)
240438fd1498Szrj {
240538fd1498Szrj tree c;
240638fd1498Szrj
240738fd1498Szrj if (ctx && gimple_code (ctx->stmt) == GIMPLE_OMP_GRID_BODY)
240838fd1498Szrj /* GRID_BODY is an artificial construct, nesting rules will be checked in
240938fd1498Szrj the original copy of its contents. */
241038fd1498Szrj return true;
241138fd1498Szrj
241238fd1498Szrj /* No nesting of non-OpenACC STMT (that is, an OpenMP one, or a GOMP builtin)
241338fd1498Szrj inside an OpenACC CTX. */
241438fd1498Szrj if (!(is_gimple_omp (stmt)
241538fd1498Szrj && is_gimple_omp_oacc (stmt))
241638fd1498Szrj /* Except for atomic codes that we share with OpenMP. */
241738fd1498Szrj && !(gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD
241838fd1498Szrj || gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE))
241938fd1498Szrj {
242038fd1498Szrj if (oacc_get_fn_attrib (cfun->decl) != NULL)
242138fd1498Szrj {
242238fd1498Szrj error_at (gimple_location (stmt),
242338fd1498Szrj "non-OpenACC construct inside of OpenACC routine");
242438fd1498Szrj return false;
242538fd1498Szrj }
242638fd1498Szrj else
242738fd1498Szrj for (omp_context *octx = ctx; octx != NULL; octx = octx->outer)
242838fd1498Szrj if (is_gimple_omp (octx->stmt)
242938fd1498Szrj && is_gimple_omp_oacc (octx->stmt))
243038fd1498Szrj {
243138fd1498Szrj error_at (gimple_location (stmt),
243238fd1498Szrj "non-OpenACC construct inside of OpenACC region");
243338fd1498Szrj return false;
243438fd1498Szrj }
243538fd1498Szrj }
243638fd1498Szrj
243738fd1498Szrj if (ctx != NULL)
243838fd1498Szrj {
243938fd1498Szrj if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
244038fd1498Szrj && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
244138fd1498Szrj {
244238fd1498Szrj c = NULL_TREE;
244338fd1498Szrj if (gimple_code (stmt) == GIMPLE_OMP_ORDERED)
244438fd1498Szrj {
244538fd1498Szrj c = gimple_omp_ordered_clauses (as_a <gomp_ordered *> (stmt));
244638fd1498Szrj if (omp_find_clause (c, OMP_CLAUSE_SIMD))
244738fd1498Szrj {
244838fd1498Szrj if (omp_find_clause (c, OMP_CLAUSE_THREADS)
244938fd1498Szrj && (ctx->outer == NULL
245038fd1498Szrj || !gimple_omp_for_combined_into_p (ctx->stmt)
245138fd1498Szrj || gimple_code (ctx->outer->stmt) != GIMPLE_OMP_FOR
245238fd1498Szrj || (gimple_omp_for_kind (ctx->outer->stmt)
245338fd1498Szrj != GF_OMP_FOR_KIND_FOR)
245438fd1498Szrj || !gimple_omp_for_combined_p (ctx->outer->stmt)))
245538fd1498Szrj {
245638fd1498Szrj error_at (gimple_location (stmt),
245738fd1498Szrj "%<ordered simd threads%> must be closely "
245838fd1498Szrj "nested inside of %<for simd%> region");
245938fd1498Szrj return false;
246038fd1498Szrj }
246138fd1498Szrj return true;
246238fd1498Szrj }
246338fd1498Szrj }
246438fd1498Szrj error_at (gimple_location (stmt),
246538fd1498Szrj "OpenMP constructs other than %<#pragma omp ordered simd%>"
246638fd1498Szrj " may not be nested inside %<simd%> region");
246738fd1498Szrj return false;
246838fd1498Szrj }
246938fd1498Szrj else if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
247038fd1498Szrj {
247138fd1498Szrj if ((gimple_code (stmt) != GIMPLE_OMP_FOR
247238fd1498Szrj || ((gimple_omp_for_kind (stmt) != GF_OMP_FOR_KIND_DISTRIBUTE)
247338fd1498Szrj && (gimple_omp_for_kind (stmt) != GF_OMP_FOR_KIND_GRID_LOOP)))
247438fd1498Szrj && gimple_code (stmt) != GIMPLE_OMP_PARALLEL)
247538fd1498Szrj {
247638fd1498Szrj error_at (gimple_location (stmt),
247738fd1498Szrj "only %<distribute%> or %<parallel%> regions are "
247838fd1498Szrj "allowed to be strictly nested inside %<teams%> "
247938fd1498Szrj "region");
248038fd1498Szrj return false;
248138fd1498Szrj }
248238fd1498Szrj }
248338fd1498Szrj }
248438fd1498Szrj switch (gimple_code (stmt))
248538fd1498Szrj {
248638fd1498Szrj case GIMPLE_OMP_FOR:
248738fd1498Szrj if (gimple_omp_for_kind (stmt) & GF_OMP_FOR_SIMD)
248838fd1498Szrj return true;
248938fd1498Szrj if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
249038fd1498Szrj {
249138fd1498Szrj if (ctx != NULL && gimple_code (ctx->stmt) != GIMPLE_OMP_TEAMS)
249238fd1498Szrj {
249338fd1498Szrj error_at (gimple_location (stmt),
249438fd1498Szrj "%<distribute%> region must be strictly nested "
249538fd1498Szrj "inside %<teams%> construct");
249638fd1498Szrj return false;
249738fd1498Szrj }
249838fd1498Szrj return true;
249938fd1498Szrj }
250038fd1498Szrj /* We split taskloop into task and nested taskloop in it. */
250138fd1498Szrj if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_TASKLOOP)
250238fd1498Szrj return true;
250338fd1498Szrj if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_OACC_LOOP)
250438fd1498Szrj {
250538fd1498Szrj bool ok = false;
250638fd1498Szrj
250738fd1498Szrj if (ctx)
250838fd1498Szrj switch (gimple_code (ctx->stmt))
250938fd1498Szrj {
251038fd1498Szrj case GIMPLE_OMP_FOR:
251138fd1498Szrj ok = (gimple_omp_for_kind (ctx->stmt)
251238fd1498Szrj == GF_OMP_FOR_KIND_OACC_LOOP);
251338fd1498Szrj break;
251438fd1498Szrj
251538fd1498Szrj case GIMPLE_OMP_TARGET:
251638fd1498Szrj switch (gimple_omp_target_kind (ctx->stmt))
251738fd1498Szrj {
251838fd1498Szrj case GF_OMP_TARGET_KIND_OACC_PARALLEL:
251938fd1498Szrj case GF_OMP_TARGET_KIND_OACC_KERNELS:
252038fd1498Szrj ok = true;
252138fd1498Szrj break;
252238fd1498Szrj
252338fd1498Szrj default:
252438fd1498Szrj break;
252538fd1498Szrj }
252638fd1498Szrj
252738fd1498Szrj default:
252838fd1498Szrj break;
252938fd1498Szrj }
253038fd1498Szrj else if (oacc_get_fn_attrib (current_function_decl))
253138fd1498Szrj ok = true;
253238fd1498Szrj if (!ok)
253338fd1498Szrj {
253438fd1498Szrj error_at (gimple_location (stmt),
253538fd1498Szrj "OpenACC loop directive must be associated with"
253638fd1498Szrj " an OpenACC compute region");
253738fd1498Szrj return false;
253838fd1498Szrj }
253938fd1498Szrj }
254038fd1498Szrj /* FALLTHRU */
254138fd1498Szrj case GIMPLE_CALL:
254238fd1498Szrj if (is_gimple_call (stmt)
254338fd1498Szrj && (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
254438fd1498Szrj == BUILT_IN_GOMP_CANCEL
254538fd1498Szrj || DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
254638fd1498Szrj == BUILT_IN_GOMP_CANCELLATION_POINT))
254738fd1498Szrj {
254838fd1498Szrj const char *bad = NULL;
254938fd1498Szrj const char *kind = NULL;
255038fd1498Szrj const char *construct
255138fd1498Szrj = (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
255238fd1498Szrj == BUILT_IN_GOMP_CANCEL)
255338fd1498Szrj ? "#pragma omp cancel"
255438fd1498Szrj : "#pragma omp cancellation point";
255538fd1498Szrj if (ctx == NULL)
255638fd1498Szrj {
255738fd1498Szrj error_at (gimple_location (stmt), "orphaned %qs construct",
255838fd1498Szrj construct);
255938fd1498Szrj return false;
256038fd1498Szrj }
256138fd1498Szrj switch (tree_fits_shwi_p (gimple_call_arg (stmt, 0))
256238fd1498Szrj ? tree_to_shwi (gimple_call_arg (stmt, 0))
256338fd1498Szrj : 0)
256438fd1498Szrj {
256538fd1498Szrj case 1:
256638fd1498Szrj if (gimple_code (ctx->stmt) != GIMPLE_OMP_PARALLEL)
256738fd1498Szrj bad = "#pragma omp parallel";
256838fd1498Szrj else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
256938fd1498Szrj == BUILT_IN_GOMP_CANCEL
257038fd1498Szrj && !integer_zerop (gimple_call_arg (stmt, 1)))
257138fd1498Szrj ctx->cancellable = true;
257238fd1498Szrj kind = "parallel";
257338fd1498Szrj break;
257438fd1498Szrj case 2:
257538fd1498Szrj if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
257638fd1498Szrj || gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR)
257738fd1498Szrj bad = "#pragma omp for";
257838fd1498Szrj else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
257938fd1498Szrj == BUILT_IN_GOMP_CANCEL
258038fd1498Szrj && !integer_zerop (gimple_call_arg (stmt, 1)))
258138fd1498Szrj {
258238fd1498Szrj ctx->cancellable = true;
258338fd1498Szrj if (omp_find_clause (gimple_omp_for_clauses (ctx->stmt),
258438fd1498Szrj OMP_CLAUSE_NOWAIT))
258538fd1498Szrj warning_at (gimple_location (stmt), 0,
258638fd1498Szrj "%<#pragma omp cancel for%> inside "
258738fd1498Szrj "%<nowait%> for construct");
258838fd1498Szrj if (omp_find_clause (gimple_omp_for_clauses (ctx->stmt),
258938fd1498Szrj OMP_CLAUSE_ORDERED))
259038fd1498Szrj warning_at (gimple_location (stmt), 0,
259138fd1498Szrj "%<#pragma omp cancel for%> inside "
259238fd1498Szrj "%<ordered%> for construct");
259338fd1498Szrj }
259438fd1498Szrj kind = "for";
259538fd1498Szrj break;
259638fd1498Szrj case 4:
259738fd1498Szrj if (gimple_code (ctx->stmt) != GIMPLE_OMP_SECTIONS
259838fd1498Szrj && gimple_code (ctx->stmt) != GIMPLE_OMP_SECTION)
259938fd1498Szrj bad = "#pragma omp sections";
260038fd1498Szrj else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
260138fd1498Szrj == BUILT_IN_GOMP_CANCEL
260238fd1498Szrj && !integer_zerop (gimple_call_arg (stmt, 1)))
260338fd1498Szrj {
260438fd1498Szrj if (gimple_code (ctx->stmt) == GIMPLE_OMP_SECTIONS)
260538fd1498Szrj {
260638fd1498Szrj ctx->cancellable = true;
260738fd1498Szrj if (omp_find_clause (gimple_omp_sections_clauses
260838fd1498Szrj (ctx->stmt),
260938fd1498Szrj OMP_CLAUSE_NOWAIT))
261038fd1498Szrj warning_at (gimple_location (stmt), 0,
261138fd1498Szrj "%<#pragma omp cancel sections%> inside "
261238fd1498Szrj "%<nowait%> sections construct");
261338fd1498Szrj }
261438fd1498Szrj else
261538fd1498Szrj {
261638fd1498Szrj gcc_assert (ctx->outer
261738fd1498Szrj && gimple_code (ctx->outer->stmt)
261838fd1498Szrj == GIMPLE_OMP_SECTIONS);
261938fd1498Szrj ctx->outer->cancellable = true;
262038fd1498Szrj if (omp_find_clause (gimple_omp_sections_clauses
262138fd1498Szrj (ctx->outer->stmt),
262238fd1498Szrj OMP_CLAUSE_NOWAIT))
262338fd1498Szrj warning_at (gimple_location (stmt), 0,
262438fd1498Szrj "%<#pragma omp cancel sections%> inside "
262538fd1498Szrj "%<nowait%> sections construct");
262638fd1498Szrj }
262738fd1498Szrj }
262838fd1498Szrj kind = "sections";
262938fd1498Szrj break;
263038fd1498Szrj case 8:
263138fd1498Szrj if (gimple_code (ctx->stmt) != GIMPLE_OMP_TASK)
263238fd1498Szrj bad = "#pragma omp task";
263338fd1498Szrj else
263438fd1498Szrj {
263538fd1498Szrj for (omp_context *octx = ctx->outer;
263638fd1498Szrj octx; octx = octx->outer)
263738fd1498Szrj {
263838fd1498Szrj switch (gimple_code (octx->stmt))
263938fd1498Szrj {
264038fd1498Szrj case GIMPLE_OMP_TASKGROUP:
264138fd1498Szrj break;
264238fd1498Szrj case GIMPLE_OMP_TARGET:
264338fd1498Szrj if (gimple_omp_target_kind (octx->stmt)
264438fd1498Szrj != GF_OMP_TARGET_KIND_REGION)
264538fd1498Szrj continue;
264638fd1498Szrj /* FALLTHRU */
264738fd1498Szrj case GIMPLE_OMP_PARALLEL:
264838fd1498Szrj case GIMPLE_OMP_TEAMS:
264938fd1498Szrj error_at (gimple_location (stmt),
265038fd1498Szrj "%<%s taskgroup%> construct not closely "
265138fd1498Szrj "nested inside of %<taskgroup%> region",
265238fd1498Szrj construct);
265338fd1498Szrj return false;
265438fd1498Szrj default:
265538fd1498Szrj continue;
265638fd1498Szrj }
265738fd1498Szrj break;
265838fd1498Szrj }
265938fd1498Szrj ctx->cancellable = true;
266038fd1498Szrj }
266138fd1498Szrj kind = "taskgroup";
266238fd1498Szrj break;
266338fd1498Szrj default:
266438fd1498Szrj error_at (gimple_location (stmt), "invalid arguments");
266538fd1498Szrj return false;
266638fd1498Szrj }
266738fd1498Szrj if (bad)
266838fd1498Szrj {
266938fd1498Szrj error_at (gimple_location (stmt),
267038fd1498Szrj "%<%s %s%> construct not closely nested inside of %qs",
267138fd1498Szrj construct, kind, bad);
267238fd1498Szrj return false;
267338fd1498Szrj }
267438fd1498Szrj }
267538fd1498Szrj /* FALLTHRU */
267638fd1498Szrj case GIMPLE_OMP_SECTIONS:
267738fd1498Szrj case GIMPLE_OMP_SINGLE:
267838fd1498Szrj for (; ctx != NULL; ctx = ctx->outer)
267938fd1498Szrj switch (gimple_code (ctx->stmt))
268038fd1498Szrj {
268138fd1498Szrj case GIMPLE_OMP_FOR:
268238fd1498Szrj if (gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR
268338fd1498Szrj && gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_TASKLOOP)
268438fd1498Szrj break;
268538fd1498Szrj /* FALLTHRU */
268638fd1498Szrj case GIMPLE_OMP_SECTIONS:
268738fd1498Szrj case GIMPLE_OMP_SINGLE:
268838fd1498Szrj case GIMPLE_OMP_ORDERED:
268938fd1498Szrj case GIMPLE_OMP_MASTER:
269038fd1498Szrj case GIMPLE_OMP_TASK:
269138fd1498Szrj case GIMPLE_OMP_CRITICAL:
269238fd1498Szrj if (is_gimple_call (stmt))
269338fd1498Szrj {
269438fd1498Szrj if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
269538fd1498Szrj != BUILT_IN_GOMP_BARRIER)
269638fd1498Szrj return true;
269738fd1498Szrj error_at (gimple_location (stmt),
269838fd1498Szrj "barrier region may not be closely nested inside "
269938fd1498Szrj "of work-sharing, %<critical%>, %<ordered%>, "
270038fd1498Szrj "%<master%>, explicit %<task%> or %<taskloop%> "
270138fd1498Szrj "region");
270238fd1498Szrj return false;
270338fd1498Szrj }
270438fd1498Szrj error_at (gimple_location (stmt),
270538fd1498Szrj "work-sharing region may not be closely nested inside "
270638fd1498Szrj "of work-sharing, %<critical%>, %<ordered%>, "
270738fd1498Szrj "%<master%>, explicit %<task%> or %<taskloop%> region");
270838fd1498Szrj return false;
270938fd1498Szrj case GIMPLE_OMP_PARALLEL:
271038fd1498Szrj case GIMPLE_OMP_TEAMS:
271138fd1498Szrj return true;
271238fd1498Szrj case GIMPLE_OMP_TARGET:
271338fd1498Szrj if (gimple_omp_target_kind (ctx->stmt)
271438fd1498Szrj == GF_OMP_TARGET_KIND_REGION)
271538fd1498Szrj return true;
271638fd1498Szrj break;
271738fd1498Szrj default:
271838fd1498Szrj break;
271938fd1498Szrj }
272038fd1498Szrj break;
272138fd1498Szrj case GIMPLE_OMP_MASTER:
272238fd1498Szrj for (; ctx != NULL; ctx = ctx->outer)
272338fd1498Szrj switch (gimple_code (ctx->stmt))
272438fd1498Szrj {
272538fd1498Szrj case GIMPLE_OMP_FOR:
272638fd1498Szrj if (gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR
272738fd1498Szrj && gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_TASKLOOP)
272838fd1498Szrj break;
272938fd1498Szrj /* FALLTHRU */
273038fd1498Szrj case GIMPLE_OMP_SECTIONS:
273138fd1498Szrj case GIMPLE_OMP_SINGLE:
273238fd1498Szrj case GIMPLE_OMP_TASK:
273338fd1498Szrj error_at (gimple_location (stmt),
273438fd1498Szrj "%<master%> region may not be closely nested inside "
273538fd1498Szrj "of work-sharing, explicit %<task%> or %<taskloop%> "
273638fd1498Szrj "region");
273738fd1498Szrj return false;
273838fd1498Szrj case GIMPLE_OMP_PARALLEL:
273938fd1498Szrj case GIMPLE_OMP_TEAMS:
274038fd1498Szrj return true;
274138fd1498Szrj case GIMPLE_OMP_TARGET:
274238fd1498Szrj if (gimple_omp_target_kind (ctx->stmt)
274338fd1498Szrj == GF_OMP_TARGET_KIND_REGION)
274438fd1498Szrj return true;
274538fd1498Szrj break;
274638fd1498Szrj default:
274738fd1498Szrj break;
274838fd1498Szrj }
274938fd1498Szrj break;
275038fd1498Szrj case GIMPLE_OMP_TASK:
275138fd1498Szrj for (c = gimple_omp_task_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c))
275238fd1498Szrj if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
275338fd1498Szrj && (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SOURCE
275438fd1498Szrj || OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK))
275538fd1498Szrj {
275638fd1498Szrj enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_KIND (c);
275738fd1498Szrj error_at (OMP_CLAUSE_LOCATION (c),
275838fd1498Szrj "%<depend(%s)%> is only allowed in %<omp ordered%>",
275938fd1498Szrj kind == OMP_CLAUSE_DEPEND_SOURCE ? "source" : "sink");
276038fd1498Szrj return false;
276138fd1498Szrj }
276238fd1498Szrj break;
276338fd1498Szrj case GIMPLE_OMP_ORDERED:
276438fd1498Szrj for (c = gimple_omp_ordered_clauses (as_a <gomp_ordered *> (stmt));
276538fd1498Szrj c; c = OMP_CLAUSE_CHAIN (c))
276638fd1498Szrj {
276738fd1498Szrj if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND)
276838fd1498Szrj {
276938fd1498Szrj gcc_assert (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_THREADS
277038fd1498Szrj || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SIMD);
277138fd1498Szrj continue;
277238fd1498Szrj }
277338fd1498Szrj enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_KIND (c);
277438fd1498Szrj if (kind == OMP_CLAUSE_DEPEND_SOURCE
277538fd1498Szrj || kind == OMP_CLAUSE_DEPEND_SINK)
277638fd1498Szrj {
277738fd1498Szrj tree oclause;
277838fd1498Szrj /* Look for containing ordered(N) loop. */
277938fd1498Szrj if (ctx == NULL
278038fd1498Szrj || gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
278138fd1498Szrj || (oclause
278238fd1498Szrj = omp_find_clause (gimple_omp_for_clauses (ctx->stmt),
278338fd1498Szrj OMP_CLAUSE_ORDERED)) == NULL_TREE)
278438fd1498Szrj {
278538fd1498Szrj error_at (OMP_CLAUSE_LOCATION (c),
278638fd1498Szrj "%<ordered%> construct with %<depend%> clause "
278738fd1498Szrj "must be closely nested inside an %<ordered%> "
278838fd1498Szrj "loop");
278938fd1498Szrj return false;
279038fd1498Szrj }
279138fd1498Szrj else if (OMP_CLAUSE_ORDERED_EXPR (oclause) == NULL_TREE)
279238fd1498Szrj {
279338fd1498Szrj error_at (OMP_CLAUSE_LOCATION (c),
279438fd1498Szrj "%<ordered%> construct with %<depend%> clause "
279538fd1498Szrj "must be closely nested inside a loop with "
279638fd1498Szrj "%<ordered%> clause with a parameter");
279738fd1498Szrj return false;
279838fd1498Szrj }
279938fd1498Szrj }
280038fd1498Szrj else
280138fd1498Szrj {
280238fd1498Szrj error_at (OMP_CLAUSE_LOCATION (c),
280338fd1498Szrj "invalid depend kind in omp %<ordered%> %<depend%>");
280438fd1498Szrj return false;
280538fd1498Szrj }
280638fd1498Szrj }
280738fd1498Szrj c = gimple_omp_ordered_clauses (as_a <gomp_ordered *> (stmt));
280838fd1498Szrj if (omp_find_clause (c, OMP_CLAUSE_SIMD))
280938fd1498Szrj {
281038fd1498Szrj /* ordered simd must be closely nested inside of simd region,
281138fd1498Szrj and simd region must not encounter constructs other than
281238fd1498Szrj ordered simd, therefore ordered simd may be either orphaned,
281338fd1498Szrj or ctx->stmt must be simd. The latter case is handled already
281438fd1498Szrj earlier. */
281538fd1498Szrj if (ctx != NULL)
281638fd1498Szrj {
281738fd1498Szrj error_at (gimple_location (stmt),
281838fd1498Szrj "%<ordered%> %<simd%> must be closely nested inside "
281938fd1498Szrj "%<simd%> region");
282038fd1498Szrj return false;
282138fd1498Szrj }
282238fd1498Szrj }
282338fd1498Szrj for (; ctx != NULL; ctx = ctx->outer)
282438fd1498Szrj switch (gimple_code (ctx->stmt))
282538fd1498Szrj {
282638fd1498Szrj case GIMPLE_OMP_CRITICAL:
282738fd1498Szrj case GIMPLE_OMP_TASK:
282838fd1498Szrj case GIMPLE_OMP_ORDERED:
282938fd1498Szrj ordered_in_taskloop:
283038fd1498Szrj error_at (gimple_location (stmt),
283138fd1498Szrj "%<ordered%> region may not be closely nested inside "
283238fd1498Szrj "of %<critical%>, %<ordered%>, explicit %<task%> or "
283338fd1498Szrj "%<taskloop%> region");
283438fd1498Szrj return false;
283538fd1498Szrj case GIMPLE_OMP_FOR:
283638fd1498Szrj if (gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_TASKLOOP)
283738fd1498Szrj goto ordered_in_taskloop;
2838*58e805e6Szrj tree o;
2839*58e805e6Szrj o = omp_find_clause (gimple_omp_for_clauses (ctx->stmt),
2840*58e805e6Szrj OMP_CLAUSE_ORDERED);
2841*58e805e6Szrj if (o == NULL)
284238fd1498Szrj {
284338fd1498Szrj error_at (gimple_location (stmt),
284438fd1498Szrj "%<ordered%> region must be closely nested inside "
284538fd1498Szrj "a loop region with an %<ordered%> clause");
284638fd1498Szrj return false;
284738fd1498Szrj }
2848*58e805e6Szrj if (OMP_CLAUSE_ORDERED_EXPR (o) != NULL_TREE
2849*58e805e6Szrj && omp_find_clause (c, OMP_CLAUSE_DEPEND) == NULL_TREE)
2850*58e805e6Szrj {
2851*58e805e6Szrj error_at (gimple_location (stmt),
2852*58e805e6Szrj "%<ordered%> region without %<depend%> clause may "
2853*58e805e6Szrj "not be closely nested inside a loop region with "
2854*58e805e6Szrj "an %<ordered%> clause with a parameter");
2855*58e805e6Szrj return false;
2856*58e805e6Szrj }
285738fd1498Szrj return true;
285838fd1498Szrj case GIMPLE_OMP_TARGET:
285938fd1498Szrj if (gimple_omp_target_kind (ctx->stmt)
286038fd1498Szrj != GF_OMP_TARGET_KIND_REGION)
286138fd1498Szrj break;
286238fd1498Szrj /* FALLTHRU */
286338fd1498Szrj case GIMPLE_OMP_PARALLEL:
286438fd1498Szrj case GIMPLE_OMP_TEAMS:
286538fd1498Szrj error_at (gimple_location (stmt),
286638fd1498Szrj "%<ordered%> region must be closely nested inside "
286738fd1498Szrj "a loop region with an %<ordered%> clause");
286838fd1498Szrj return false;
286938fd1498Szrj default:
287038fd1498Szrj break;
287138fd1498Szrj }
287238fd1498Szrj break;
287338fd1498Szrj case GIMPLE_OMP_CRITICAL:
287438fd1498Szrj {
287538fd1498Szrj tree this_stmt_name
287638fd1498Szrj = gimple_omp_critical_name (as_a <gomp_critical *> (stmt));
287738fd1498Szrj for (; ctx != NULL; ctx = ctx->outer)
287838fd1498Szrj if (gomp_critical *other_crit
287938fd1498Szrj = dyn_cast <gomp_critical *> (ctx->stmt))
288038fd1498Szrj if (this_stmt_name == gimple_omp_critical_name (other_crit))
288138fd1498Szrj {
288238fd1498Szrj error_at (gimple_location (stmt),
288338fd1498Szrj "%<critical%> region may not be nested inside "
288438fd1498Szrj "a %<critical%> region with the same name");
288538fd1498Szrj return false;
288638fd1498Szrj }
288738fd1498Szrj }
288838fd1498Szrj break;
288938fd1498Szrj case GIMPLE_OMP_TEAMS:
289038fd1498Szrj if (ctx == NULL
289138fd1498Szrj || gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET
289238fd1498Szrj || gimple_omp_target_kind (ctx->stmt) != GF_OMP_TARGET_KIND_REGION)
289338fd1498Szrj {
289438fd1498Szrj error_at (gimple_location (stmt),
289538fd1498Szrj "%<teams%> construct not closely nested inside of "
289638fd1498Szrj "%<target%> construct");
289738fd1498Szrj return false;
289838fd1498Szrj }
289938fd1498Szrj break;
290038fd1498Szrj case GIMPLE_OMP_TARGET:
290138fd1498Szrj for (c = gimple_omp_target_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c))
290238fd1498Szrj if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
290338fd1498Szrj && (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SOURCE
290438fd1498Szrj || OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK))
290538fd1498Szrj {
290638fd1498Szrj enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_KIND (c);
290738fd1498Szrj error_at (OMP_CLAUSE_LOCATION (c),
290838fd1498Szrj "%<depend(%s)%> is only allowed in %<omp ordered%>",
290938fd1498Szrj kind == OMP_CLAUSE_DEPEND_SOURCE ? "source" : "sink");
291038fd1498Szrj return false;
291138fd1498Szrj }
291238fd1498Szrj if (is_gimple_omp_offloaded (stmt)
291338fd1498Szrj && oacc_get_fn_attrib (cfun->decl) != NULL)
291438fd1498Szrj {
291538fd1498Szrj error_at (gimple_location (stmt),
291638fd1498Szrj "OpenACC region inside of OpenACC routine, nested "
291738fd1498Szrj "parallelism not supported yet");
291838fd1498Szrj return false;
291938fd1498Szrj }
292038fd1498Szrj for (; ctx != NULL; ctx = ctx->outer)
292138fd1498Szrj {
292238fd1498Szrj if (gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET)
292338fd1498Szrj {
292438fd1498Szrj if (is_gimple_omp (stmt)
292538fd1498Szrj && is_gimple_omp_oacc (stmt)
292638fd1498Szrj && is_gimple_omp (ctx->stmt))
292738fd1498Szrj {
292838fd1498Szrj error_at (gimple_location (stmt),
292938fd1498Szrj "OpenACC construct inside of non-OpenACC region");
293038fd1498Szrj return false;
293138fd1498Szrj }
293238fd1498Szrj continue;
293338fd1498Szrj }
293438fd1498Szrj
293538fd1498Szrj const char *stmt_name, *ctx_stmt_name;
293638fd1498Szrj switch (gimple_omp_target_kind (stmt))
293738fd1498Szrj {
293838fd1498Szrj case GF_OMP_TARGET_KIND_REGION: stmt_name = "target"; break;
293938fd1498Szrj case GF_OMP_TARGET_KIND_DATA: stmt_name = "target data"; break;
294038fd1498Szrj case GF_OMP_TARGET_KIND_UPDATE: stmt_name = "target update"; break;
294138fd1498Szrj case GF_OMP_TARGET_KIND_ENTER_DATA:
294238fd1498Szrj stmt_name = "target enter data"; break;
294338fd1498Szrj case GF_OMP_TARGET_KIND_EXIT_DATA:
294438fd1498Szrj stmt_name = "target exit data"; break;
294538fd1498Szrj case GF_OMP_TARGET_KIND_OACC_PARALLEL: stmt_name = "parallel"; break;
294638fd1498Szrj case GF_OMP_TARGET_KIND_OACC_KERNELS: stmt_name = "kernels"; break;
294738fd1498Szrj case GF_OMP_TARGET_KIND_OACC_DATA: stmt_name = "data"; break;
294838fd1498Szrj case GF_OMP_TARGET_KIND_OACC_UPDATE: stmt_name = "update"; break;
294938fd1498Szrj case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
295038fd1498Szrj stmt_name = "enter/exit data"; break;
295138fd1498Szrj case GF_OMP_TARGET_KIND_OACC_HOST_DATA: stmt_name = "host_data";
295238fd1498Szrj break;
295338fd1498Szrj default: gcc_unreachable ();
295438fd1498Szrj }
295538fd1498Szrj switch (gimple_omp_target_kind (ctx->stmt))
295638fd1498Szrj {
295738fd1498Szrj case GF_OMP_TARGET_KIND_REGION: ctx_stmt_name = "target"; break;
295838fd1498Szrj case GF_OMP_TARGET_KIND_DATA: ctx_stmt_name = "target data"; break;
295938fd1498Szrj case GF_OMP_TARGET_KIND_OACC_PARALLEL:
296038fd1498Szrj ctx_stmt_name = "parallel"; break;
296138fd1498Szrj case GF_OMP_TARGET_KIND_OACC_KERNELS:
296238fd1498Szrj ctx_stmt_name = "kernels"; break;
296338fd1498Szrj case GF_OMP_TARGET_KIND_OACC_DATA: ctx_stmt_name = "data"; break;
296438fd1498Szrj case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
296538fd1498Szrj ctx_stmt_name = "host_data"; break;
296638fd1498Szrj default: gcc_unreachable ();
296738fd1498Szrj }
296838fd1498Szrj
296938fd1498Szrj /* OpenACC/OpenMP mismatch? */
297038fd1498Szrj if (is_gimple_omp_oacc (stmt)
297138fd1498Szrj != is_gimple_omp_oacc (ctx->stmt))
297238fd1498Szrj {
297338fd1498Szrj error_at (gimple_location (stmt),
297438fd1498Szrj "%s %qs construct inside of %s %qs region",
297538fd1498Szrj (is_gimple_omp_oacc (stmt)
297638fd1498Szrj ? "OpenACC" : "OpenMP"), stmt_name,
297738fd1498Szrj (is_gimple_omp_oacc (ctx->stmt)
297838fd1498Szrj ? "OpenACC" : "OpenMP"), ctx_stmt_name);
297938fd1498Szrj return false;
298038fd1498Szrj }
298138fd1498Szrj if (is_gimple_omp_offloaded (ctx->stmt))
298238fd1498Szrj {
298338fd1498Szrj /* No GIMPLE_OMP_TARGET inside offloaded OpenACC CTX. */
298438fd1498Szrj if (is_gimple_omp_oacc (ctx->stmt))
298538fd1498Szrj {
298638fd1498Szrj error_at (gimple_location (stmt),
298738fd1498Szrj "%qs construct inside of %qs region",
298838fd1498Szrj stmt_name, ctx_stmt_name);
298938fd1498Szrj return false;
299038fd1498Szrj }
299138fd1498Szrj else
299238fd1498Szrj {
299338fd1498Szrj warning_at (gimple_location (stmt), 0,
299438fd1498Szrj "%qs construct inside of %qs region",
299538fd1498Szrj stmt_name, ctx_stmt_name);
299638fd1498Szrj }
299738fd1498Szrj }
299838fd1498Szrj }
299938fd1498Szrj break;
300038fd1498Szrj default:
300138fd1498Szrj break;
300238fd1498Szrj }
300338fd1498Szrj return true;
300438fd1498Szrj }
300538fd1498Szrj
300638fd1498Szrj
300738fd1498Szrj /* Helper function scan_omp.
300838fd1498Szrj
300938fd1498Szrj Callback for walk_tree or operators in walk_gimple_stmt used to
301038fd1498Szrj scan for OMP directives in TP. */
301138fd1498Szrj
301238fd1498Szrj static tree
scan_omp_1_op(tree * tp,int * walk_subtrees,void * data)301338fd1498Szrj scan_omp_1_op (tree *tp, int *walk_subtrees, void *data)
301438fd1498Szrj {
301538fd1498Szrj struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
301638fd1498Szrj omp_context *ctx = (omp_context *) wi->info;
301738fd1498Szrj tree t = *tp;
301838fd1498Szrj
301938fd1498Szrj switch (TREE_CODE (t))
302038fd1498Szrj {
302138fd1498Szrj case VAR_DECL:
302238fd1498Szrj case PARM_DECL:
302338fd1498Szrj case LABEL_DECL:
302438fd1498Szrj case RESULT_DECL:
302538fd1498Szrj if (ctx)
302638fd1498Szrj {
302738fd1498Szrj tree repl = remap_decl (t, &ctx->cb);
302838fd1498Szrj gcc_checking_assert (TREE_CODE (repl) != ERROR_MARK);
302938fd1498Szrj *tp = repl;
303038fd1498Szrj }
303138fd1498Szrj break;
303238fd1498Szrj
303338fd1498Szrj default:
303438fd1498Szrj if (ctx && TYPE_P (t))
303538fd1498Szrj *tp = remap_type (t, &ctx->cb);
303638fd1498Szrj else if (!DECL_P (t))
303738fd1498Szrj {
303838fd1498Szrj *walk_subtrees = 1;
303938fd1498Szrj if (ctx)
304038fd1498Szrj {
304138fd1498Szrj tree tem = remap_type (TREE_TYPE (t), &ctx->cb);
304238fd1498Szrj if (tem != TREE_TYPE (t))
304338fd1498Szrj {
304438fd1498Szrj if (TREE_CODE (t) == INTEGER_CST)
304538fd1498Szrj *tp = wide_int_to_tree (tem, wi::to_wide (t));
304638fd1498Szrj else
304738fd1498Szrj TREE_TYPE (t) = tem;
304838fd1498Szrj }
304938fd1498Szrj }
305038fd1498Szrj }
305138fd1498Szrj break;
305238fd1498Szrj }
305338fd1498Szrj
305438fd1498Szrj return NULL_TREE;
305538fd1498Szrj }
305638fd1498Szrj
305738fd1498Szrj /* Return true if FNDECL is a setjmp or a longjmp. */
305838fd1498Szrj
305938fd1498Szrj static bool
setjmp_or_longjmp_p(const_tree fndecl)306038fd1498Szrj setjmp_or_longjmp_p (const_tree fndecl)
306138fd1498Szrj {
306238fd1498Szrj if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
306338fd1498Szrj && (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_SETJMP
306438fd1498Szrj || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_LONGJMP))
306538fd1498Szrj return true;
306638fd1498Szrj
306738fd1498Szrj tree declname = DECL_NAME (fndecl);
306838fd1498Szrj if (!declname)
306938fd1498Szrj return false;
307038fd1498Szrj const char *name = IDENTIFIER_POINTER (declname);
307138fd1498Szrj return !strcmp (name, "setjmp") || !strcmp (name, "longjmp");
307238fd1498Szrj }
307338fd1498Szrj
307438fd1498Szrj
307538fd1498Szrj /* Helper function for scan_omp.
307638fd1498Szrj
307738fd1498Szrj Callback for walk_gimple_stmt used to scan for OMP directives in
307838fd1498Szrj the current statement in GSI. */
307938fd1498Szrj
308038fd1498Szrj static tree
scan_omp_1_stmt(gimple_stmt_iterator * gsi,bool * handled_ops_p,struct walk_stmt_info * wi)308138fd1498Szrj scan_omp_1_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
308238fd1498Szrj struct walk_stmt_info *wi)
308338fd1498Szrj {
308438fd1498Szrj gimple *stmt = gsi_stmt (*gsi);
308538fd1498Szrj omp_context *ctx = (omp_context *) wi->info;
308638fd1498Szrj
308738fd1498Szrj if (gimple_has_location (stmt))
308838fd1498Szrj input_location = gimple_location (stmt);
308938fd1498Szrj
309038fd1498Szrj /* Check the nesting restrictions. */
309138fd1498Szrj bool remove = false;
309238fd1498Szrj if (is_gimple_omp (stmt))
309338fd1498Szrj remove = !check_omp_nesting_restrictions (stmt, ctx);
309438fd1498Szrj else if (is_gimple_call (stmt))
309538fd1498Szrj {
309638fd1498Szrj tree fndecl = gimple_call_fndecl (stmt);
309738fd1498Szrj if (fndecl)
309838fd1498Szrj {
309938fd1498Szrj if (setjmp_or_longjmp_p (fndecl)
310038fd1498Szrj && ctx
310138fd1498Szrj && gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
310238fd1498Szrj && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
310338fd1498Szrj {
310438fd1498Szrj remove = true;
310538fd1498Szrj error_at (gimple_location (stmt),
310638fd1498Szrj "setjmp/longjmp inside simd construct");
310738fd1498Szrj }
310838fd1498Szrj else if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
310938fd1498Szrj switch (DECL_FUNCTION_CODE (fndecl))
311038fd1498Szrj {
311138fd1498Szrj case BUILT_IN_GOMP_BARRIER:
311238fd1498Szrj case BUILT_IN_GOMP_CANCEL:
311338fd1498Szrj case BUILT_IN_GOMP_CANCELLATION_POINT:
311438fd1498Szrj case BUILT_IN_GOMP_TASKYIELD:
311538fd1498Szrj case BUILT_IN_GOMP_TASKWAIT:
311638fd1498Szrj case BUILT_IN_GOMP_TASKGROUP_START:
311738fd1498Szrj case BUILT_IN_GOMP_TASKGROUP_END:
311838fd1498Szrj remove = !check_omp_nesting_restrictions (stmt, ctx);
311938fd1498Szrj break;
312038fd1498Szrj default:
312138fd1498Szrj break;
312238fd1498Szrj }
312338fd1498Szrj }
312438fd1498Szrj }
312538fd1498Szrj if (remove)
312638fd1498Szrj {
312738fd1498Szrj stmt = gimple_build_nop ();
312838fd1498Szrj gsi_replace (gsi, stmt, false);
312938fd1498Szrj }
313038fd1498Szrj
313138fd1498Szrj *handled_ops_p = true;
313238fd1498Szrj
313338fd1498Szrj switch (gimple_code (stmt))
313438fd1498Szrj {
313538fd1498Szrj case GIMPLE_OMP_PARALLEL:
313638fd1498Szrj taskreg_nesting_level++;
313738fd1498Szrj scan_omp_parallel (gsi, ctx);
313838fd1498Szrj taskreg_nesting_level--;
313938fd1498Szrj break;
314038fd1498Szrj
314138fd1498Szrj case GIMPLE_OMP_TASK:
314238fd1498Szrj taskreg_nesting_level++;
314338fd1498Szrj scan_omp_task (gsi, ctx);
314438fd1498Szrj taskreg_nesting_level--;
314538fd1498Szrj break;
314638fd1498Szrj
314738fd1498Szrj case GIMPLE_OMP_FOR:
314838fd1498Szrj if (((gimple_omp_for_kind (as_a <gomp_for *> (stmt))
314938fd1498Szrj & GF_OMP_FOR_KIND_MASK) == GF_OMP_FOR_KIND_SIMD)
315038fd1498Szrj && omp_maybe_offloaded_ctx (ctx)
315138fd1498Szrj && omp_max_simt_vf ())
315238fd1498Szrj scan_omp_simd (gsi, as_a <gomp_for *> (stmt), ctx);
315338fd1498Szrj else
315438fd1498Szrj scan_omp_for (as_a <gomp_for *> (stmt), ctx);
315538fd1498Szrj break;
315638fd1498Szrj
315738fd1498Szrj case GIMPLE_OMP_SECTIONS:
315838fd1498Szrj scan_omp_sections (as_a <gomp_sections *> (stmt), ctx);
315938fd1498Szrj break;
316038fd1498Szrj
316138fd1498Szrj case GIMPLE_OMP_SINGLE:
316238fd1498Szrj scan_omp_single (as_a <gomp_single *> (stmt), ctx);
316338fd1498Szrj break;
316438fd1498Szrj
316538fd1498Szrj case GIMPLE_OMP_SECTION:
316638fd1498Szrj case GIMPLE_OMP_MASTER:
316738fd1498Szrj case GIMPLE_OMP_TASKGROUP:
316838fd1498Szrj case GIMPLE_OMP_ORDERED:
316938fd1498Szrj case GIMPLE_OMP_CRITICAL:
317038fd1498Szrj case GIMPLE_OMP_GRID_BODY:
317138fd1498Szrj ctx = new_omp_context (stmt, ctx);
317238fd1498Szrj scan_omp (gimple_omp_body_ptr (stmt), ctx);
317338fd1498Szrj break;
317438fd1498Szrj
317538fd1498Szrj case GIMPLE_OMP_TARGET:
317638fd1498Szrj scan_omp_target (as_a <gomp_target *> (stmt), ctx);
317738fd1498Szrj break;
317838fd1498Szrj
317938fd1498Szrj case GIMPLE_OMP_TEAMS:
318038fd1498Szrj scan_omp_teams (as_a <gomp_teams *> (stmt), ctx);
318138fd1498Szrj break;
318238fd1498Szrj
318338fd1498Szrj case GIMPLE_BIND:
318438fd1498Szrj {
318538fd1498Szrj tree var;
318638fd1498Szrj
318738fd1498Szrj *handled_ops_p = false;
318838fd1498Szrj if (ctx)
318938fd1498Szrj for (var = gimple_bind_vars (as_a <gbind *> (stmt));
319038fd1498Szrj var ;
319138fd1498Szrj var = DECL_CHAIN (var))
319238fd1498Szrj insert_decl_map (&ctx->cb, var, var);
319338fd1498Szrj }
319438fd1498Szrj break;
319538fd1498Szrj default:
319638fd1498Szrj *handled_ops_p = false;
319738fd1498Szrj break;
319838fd1498Szrj }
319938fd1498Szrj
320038fd1498Szrj return NULL_TREE;
320138fd1498Szrj }
320238fd1498Szrj
320338fd1498Szrj
320438fd1498Szrj /* Scan all the statements starting at the current statement. CTX
320538fd1498Szrj contains context information about the OMP directives and
320638fd1498Szrj clauses found during the scan. */
320738fd1498Szrj
320838fd1498Szrj static void
scan_omp(gimple_seq * body_p,omp_context * ctx)320938fd1498Szrj scan_omp (gimple_seq *body_p, omp_context *ctx)
321038fd1498Szrj {
321138fd1498Szrj location_t saved_location;
321238fd1498Szrj struct walk_stmt_info wi;
321338fd1498Szrj
321438fd1498Szrj memset (&wi, 0, sizeof (wi));
321538fd1498Szrj wi.info = ctx;
321638fd1498Szrj wi.want_locations = true;
321738fd1498Szrj
321838fd1498Szrj saved_location = input_location;
321938fd1498Szrj walk_gimple_seq_mod (body_p, scan_omp_1_stmt, scan_omp_1_op, &wi);
322038fd1498Szrj input_location = saved_location;
322138fd1498Szrj }
322238fd1498Szrj
322338fd1498Szrj /* Re-gimplification and code generation routines. */
322438fd1498Szrj
322538fd1498Szrj /* Remove omp_member_access_dummy_var variables from gimple_bind_vars
322638fd1498Szrj of BIND if in a method. */
322738fd1498Szrj
322838fd1498Szrj static void
maybe_remove_omp_member_access_dummy_vars(gbind * bind)322938fd1498Szrj maybe_remove_omp_member_access_dummy_vars (gbind *bind)
323038fd1498Szrj {
323138fd1498Szrj if (DECL_ARGUMENTS (current_function_decl)
323238fd1498Szrj && DECL_ARTIFICIAL (DECL_ARGUMENTS (current_function_decl))
323338fd1498Szrj && (TREE_CODE (TREE_TYPE (DECL_ARGUMENTS (current_function_decl)))
323438fd1498Szrj == POINTER_TYPE))
323538fd1498Szrj {
323638fd1498Szrj tree vars = gimple_bind_vars (bind);
323738fd1498Szrj for (tree *pvar = &vars; *pvar; )
323838fd1498Szrj if (omp_member_access_dummy_var (*pvar))
323938fd1498Szrj *pvar = DECL_CHAIN (*pvar);
324038fd1498Szrj else
324138fd1498Szrj pvar = &DECL_CHAIN (*pvar);
324238fd1498Szrj gimple_bind_set_vars (bind, vars);
324338fd1498Szrj }
324438fd1498Szrj }
324538fd1498Szrj
324638fd1498Szrj /* Remove omp_member_access_dummy_var variables from BLOCK_VARS of
324738fd1498Szrj block and its subblocks. */
324838fd1498Szrj
324938fd1498Szrj static void
remove_member_access_dummy_vars(tree block)325038fd1498Szrj remove_member_access_dummy_vars (tree block)
325138fd1498Szrj {
325238fd1498Szrj for (tree *pvar = &BLOCK_VARS (block); *pvar; )
325338fd1498Szrj if (omp_member_access_dummy_var (*pvar))
325438fd1498Szrj *pvar = DECL_CHAIN (*pvar);
325538fd1498Szrj else
325638fd1498Szrj pvar = &DECL_CHAIN (*pvar);
325738fd1498Szrj
325838fd1498Szrj for (block = BLOCK_SUBBLOCKS (block); block; block = BLOCK_CHAIN (block))
325938fd1498Szrj remove_member_access_dummy_vars (block);
326038fd1498Szrj }
326138fd1498Szrj
326238fd1498Szrj /* If a context was created for STMT when it was scanned, return it. */
326338fd1498Szrj
326438fd1498Szrj static omp_context *
maybe_lookup_ctx(gimple * stmt)326538fd1498Szrj maybe_lookup_ctx (gimple *stmt)
326638fd1498Szrj {
326738fd1498Szrj splay_tree_node n;
326838fd1498Szrj n = splay_tree_lookup (all_contexts, (splay_tree_key) stmt);
326938fd1498Szrj return n ? (omp_context *) n->value : NULL;
327038fd1498Szrj }
327138fd1498Szrj
327238fd1498Szrj
327338fd1498Szrj /* Find the mapping for DECL in CTX or the immediately enclosing
327438fd1498Szrj context that has a mapping for DECL.
327538fd1498Szrj
327638fd1498Szrj If CTX is a nested parallel directive, we may have to use the decl
327738fd1498Szrj mappings created in CTX's parent context. Suppose that we have the
327838fd1498Szrj following parallel nesting (variable UIDs showed for clarity):
327938fd1498Szrj
328038fd1498Szrj iD.1562 = 0;
328138fd1498Szrj #omp parallel shared(iD.1562) -> outer parallel
328238fd1498Szrj iD.1562 = iD.1562 + 1;
328338fd1498Szrj
328438fd1498Szrj #omp parallel shared (iD.1562) -> inner parallel
328538fd1498Szrj iD.1562 = iD.1562 - 1;
328638fd1498Szrj
328738fd1498Szrj Each parallel structure will create a distinct .omp_data_s structure
328838fd1498Szrj for copying iD.1562 in/out of the directive:
328938fd1498Szrj
329038fd1498Szrj outer parallel .omp_data_s.1.i -> iD.1562
329138fd1498Szrj inner parallel .omp_data_s.2.i -> iD.1562
329238fd1498Szrj
329338fd1498Szrj A shared variable mapping will produce a copy-out operation before
329438fd1498Szrj the parallel directive and a copy-in operation after it. So, in
329538fd1498Szrj this case we would have:
329638fd1498Szrj
329738fd1498Szrj iD.1562 = 0;
329838fd1498Szrj .omp_data_o.1.i = iD.1562;
329938fd1498Szrj #omp parallel shared(iD.1562) -> outer parallel
330038fd1498Szrj .omp_data_i.1 = &.omp_data_o.1
330138fd1498Szrj .omp_data_i.1->i = .omp_data_i.1->i + 1;
330238fd1498Szrj
330338fd1498Szrj .omp_data_o.2.i = iD.1562; -> **
330438fd1498Szrj #omp parallel shared(iD.1562) -> inner parallel
330538fd1498Szrj .omp_data_i.2 = &.omp_data_o.2
330638fd1498Szrj .omp_data_i.2->i = .omp_data_i.2->i - 1;
330738fd1498Szrj
330838fd1498Szrj
330938fd1498Szrj ** This is a problem. The symbol iD.1562 cannot be referenced
331038fd1498Szrj inside the body of the outer parallel region. But since we are
331138fd1498Szrj emitting this copy operation while expanding the inner parallel
331238fd1498Szrj directive, we need to access the CTX structure of the outer
331338fd1498Szrj parallel directive to get the correct mapping:
331438fd1498Szrj
331538fd1498Szrj .omp_data_o.2.i = .omp_data_i.1->i
331638fd1498Szrj
331738fd1498Szrj Since there may be other workshare or parallel directives enclosing
331838fd1498Szrj the parallel directive, it may be necessary to walk up the context
331938fd1498Szrj parent chain. This is not a problem in general because nested
332038fd1498Szrj parallelism happens only rarely. */
332138fd1498Szrj
332238fd1498Szrj static tree
lookup_decl_in_outer_ctx(tree decl,omp_context * ctx)332338fd1498Szrj lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
332438fd1498Szrj {
332538fd1498Szrj tree t;
332638fd1498Szrj omp_context *up;
332738fd1498Szrj
332838fd1498Szrj for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
332938fd1498Szrj t = maybe_lookup_decl (decl, up);
333038fd1498Szrj
333138fd1498Szrj gcc_assert (!ctx->is_nested || t || is_global_var (decl));
333238fd1498Szrj
333338fd1498Szrj return t ? t : decl;
333438fd1498Szrj }
333538fd1498Szrj
333638fd1498Szrj
333738fd1498Szrj /* Similar to lookup_decl_in_outer_ctx, but return DECL if not found
333838fd1498Szrj in outer contexts. */
333938fd1498Szrj
334038fd1498Szrj static tree
maybe_lookup_decl_in_outer_ctx(tree decl,omp_context * ctx)334138fd1498Szrj maybe_lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
334238fd1498Szrj {
334338fd1498Szrj tree t = NULL;
334438fd1498Szrj omp_context *up;
334538fd1498Szrj
334638fd1498Szrj for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
334738fd1498Szrj t = maybe_lookup_decl (decl, up);
334838fd1498Szrj
334938fd1498Szrj return t ? t : decl;
335038fd1498Szrj }
335138fd1498Szrj
335238fd1498Szrj
335338fd1498Szrj /* Construct the initialization value for reduction operation OP. */
335438fd1498Szrj
335538fd1498Szrj tree
omp_reduction_init_op(location_t loc,enum tree_code op,tree type)335638fd1498Szrj omp_reduction_init_op (location_t loc, enum tree_code op, tree type)
335738fd1498Szrj {
335838fd1498Szrj switch (op)
335938fd1498Szrj {
336038fd1498Szrj case PLUS_EXPR:
336138fd1498Szrj case MINUS_EXPR:
336238fd1498Szrj case BIT_IOR_EXPR:
336338fd1498Szrj case BIT_XOR_EXPR:
336438fd1498Szrj case TRUTH_OR_EXPR:
336538fd1498Szrj case TRUTH_ORIF_EXPR:
336638fd1498Szrj case TRUTH_XOR_EXPR:
336738fd1498Szrj case NE_EXPR:
336838fd1498Szrj return build_zero_cst (type);
336938fd1498Szrj
337038fd1498Szrj case MULT_EXPR:
337138fd1498Szrj case TRUTH_AND_EXPR:
337238fd1498Szrj case TRUTH_ANDIF_EXPR:
337338fd1498Szrj case EQ_EXPR:
337438fd1498Szrj return fold_convert_loc (loc, type, integer_one_node);
337538fd1498Szrj
337638fd1498Szrj case BIT_AND_EXPR:
337738fd1498Szrj return fold_convert_loc (loc, type, integer_minus_one_node);
337838fd1498Szrj
337938fd1498Szrj case MAX_EXPR:
338038fd1498Szrj if (SCALAR_FLOAT_TYPE_P (type))
338138fd1498Szrj {
338238fd1498Szrj REAL_VALUE_TYPE max, min;
338338fd1498Szrj if (HONOR_INFINITIES (type))
338438fd1498Szrj {
338538fd1498Szrj real_inf (&max);
338638fd1498Szrj real_arithmetic (&min, NEGATE_EXPR, &max, NULL);
338738fd1498Szrj }
338838fd1498Szrj else
338938fd1498Szrj real_maxval (&min, 1, TYPE_MODE (type));
339038fd1498Szrj return build_real (type, min);
339138fd1498Szrj }
339238fd1498Szrj else if (POINTER_TYPE_P (type))
339338fd1498Szrj {
339438fd1498Szrj wide_int min
339538fd1498Szrj = wi::min_value (TYPE_PRECISION (type), TYPE_SIGN (type));
339638fd1498Szrj return wide_int_to_tree (type, min);
339738fd1498Szrj }
339838fd1498Szrj else
339938fd1498Szrj {
340038fd1498Szrj gcc_assert (INTEGRAL_TYPE_P (type));
340138fd1498Szrj return TYPE_MIN_VALUE (type);
340238fd1498Szrj }
340338fd1498Szrj
340438fd1498Szrj case MIN_EXPR:
340538fd1498Szrj if (SCALAR_FLOAT_TYPE_P (type))
340638fd1498Szrj {
340738fd1498Szrj REAL_VALUE_TYPE max;
340838fd1498Szrj if (HONOR_INFINITIES (type))
340938fd1498Szrj real_inf (&max);
341038fd1498Szrj else
341138fd1498Szrj real_maxval (&max, 0, TYPE_MODE (type));
341238fd1498Szrj return build_real (type, max);
341338fd1498Szrj }
341438fd1498Szrj else if (POINTER_TYPE_P (type))
341538fd1498Szrj {
341638fd1498Szrj wide_int max
341738fd1498Szrj = wi::max_value (TYPE_PRECISION (type), TYPE_SIGN (type));
341838fd1498Szrj return wide_int_to_tree (type, max);
341938fd1498Szrj }
342038fd1498Szrj else
342138fd1498Szrj {
342238fd1498Szrj gcc_assert (INTEGRAL_TYPE_P (type));
342338fd1498Szrj return TYPE_MAX_VALUE (type);
342438fd1498Szrj }
342538fd1498Szrj
342638fd1498Szrj default:
342738fd1498Szrj gcc_unreachable ();
342838fd1498Szrj }
342938fd1498Szrj }
343038fd1498Szrj
343138fd1498Szrj /* Construct the initialization value for reduction CLAUSE. */
343238fd1498Szrj
343338fd1498Szrj tree
omp_reduction_init(tree clause,tree type)343438fd1498Szrj omp_reduction_init (tree clause, tree type)
343538fd1498Szrj {
343638fd1498Szrj return omp_reduction_init_op (OMP_CLAUSE_LOCATION (clause),
343738fd1498Szrj OMP_CLAUSE_REDUCTION_CODE (clause), type);
343838fd1498Szrj }
343938fd1498Szrj
344038fd1498Szrj /* Return alignment to be assumed for var in CLAUSE, which should be
344138fd1498Szrj OMP_CLAUSE_ALIGNED. */
344238fd1498Szrj
344338fd1498Szrj static tree
omp_clause_aligned_alignment(tree clause)344438fd1498Szrj omp_clause_aligned_alignment (tree clause)
344538fd1498Szrj {
344638fd1498Szrj if (OMP_CLAUSE_ALIGNED_ALIGNMENT (clause))
344738fd1498Szrj return OMP_CLAUSE_ALIGNED_ALIGNMENT (clause);
344838fd1498Szrj
344938fd1498Szrj /* Otherwise return implementation defined alignment. */
345038fd1498Szrj unsigned int al = 1;
345138fd1498Szrj opt_scalar_mode mode_iter;
345238fd1498Szrj auto_vector_sizes sizes;
345338fd1498Szrj targetm.vectorize.autovectorize_vector_sizes (&sizes);
345438fd1498Szrj poly_uint64 vs = 0;
345538fd1498Szrj for (unsigned int i = 0; i < sizes.length (); ++i)
345638fd1498Szrj vs = ordered_max (vs, sizes[i]);
345738fd1498Szrj static enum mode_class classes[]
345838fd1498Szrj = { MODE_INT, MODE_VECTOR_INT, MODE_FLOAT, MODE_VECTOR_FLOAT };
345938fd1498Szrj for (int i = 0; i < 4; i += 2)
346038fd1498Szrj /* The for loop above dictates that we only walk through scalar classes. */
346138fd1498Szrj FOR_EACH_MODE_IN_CLASS (mode_iter, classes[i])
346238fd1498Szrj {
346338fd1498Szrj scalar_mode mode = mode_iter.require ();
346438fd1498Szrj machine_mode vmode = targetm.vectorize.preferred_simd_mode (mode);
346538fd1498Szrj if (GET_MODE_CLASS (vmode) != classes[i + 1])
346638fd1498Szrj continue;
346738fd1498Szrj while (maybe_ne (vs, 0U)
346838fd1498Szrj && known_lt (GET_MODE_SIZE (vmode), vs)
346938fd1498Szrj && GET_MODE_2XWIDER_MODE (vmode).exists ())
347038fd1498Szrj vmode = GET_MODE_2XWIDER_MODE (vmode).require ();
347138fd1498Szrj
347238fd1498Szrj tree type = lang_hooks.types.type_for_mode (mode, 1);
347338fd1498Szrj if (type == NULL_TREE || TYPE_MODE (type) != mode)
347438fd1498Szrj continue;
347538fd1498Szrj poly_uint64 nelts = exact_div (GET_MODE_SIZE (vmode),
347638fd1498Szrj GET_MODE_SIZE (mode));
347738fd1498Szrj type = build_vector_type (type, nelts);
347838fd1498Szrj if (TYPE_MODE (type) != vmode)
347938fd1498Szrj continue;
348038fd1498Szrj if (TYPE_ALIGN_UNIT (type) > al)
348138fd1498Szrj al = TYPE_ALIGN_UNIT (type);
348238fd1498Szrj }
348338fd1498Szrj return build_int_cst (integer_type_node, al);
348438fd1498Szrj }
348538fd1498Szrj
348638fd1498Szrj
348738fd1498Szrj /* This structure is part of the interface between lower_rec_simd_input_clauses
348838fd1498Szrj and lower_rec_input_clauses. */
348938fd1498Szrj
349038fd1498Szrj struct omplow_simd_context {
omplow_simd_contextomplow_simd_context349138fd1498Szrj omplow_simd_context () { memset (this, 0, sizeof (*this)); }
349238fd1498Szrj tree idx;
349338fd1498Szrj tree lane;
349438fd1498Szrj vec<tree, va_heap> simt_eargs;
349538fd1498Szrj gimple_seq simt_dlist;
349638fd1498Szrj poly_uint64_pod max_vf;
349738fd1498Szrj bool is_simt;
349838fd1498Szrj };
349938fd1498Szrj
350038fd1498Szrj /* Helper function of lower_rec_input_clauses, used for #pragma omp simd
350138fd1498Szrj privatization. */
350238fd1498Szrj
350338fd1498Szrj static bool
lower_rec_simd_input_clauses(tree new_var,omp_context * ctx,omplow_simd_context * sctx,tree & ivar,tree & lvar)350438fd1498Szrj lower_rec_simd_input_clauses (tree new_var, omp_context *ctx,
350538fd1498Szrj omplow_simd_context *sctx, tree &ivar, tree &lvar)
350638fd1498Szrj {
350738fd1498Szrj if (known_eq (sctx->max_vf, 0U))
350838fd1498Szrj {
350938fd1498Szrj sctx->max_vf = sctx->is_simt ? omp_max_simt_vf () : omp_max_vf ();
351038fd1498Szrj if (maybe_gt (sctx->max_vf, 1U))
351138fd1498Szrj {
351238fd1498Szrj tree c = omp_find_clause (gimple_omp_for_clauses (ctx->stmt),
351338fd1498Szrj OMP_CLAUSE_SAFELEN);
351438fd1498Szrj if (c)
351538fd1498Szrj {
351638fd1498Szrj poly_uint64 safe_len;
351738fd1498Szrj if (!poly_int_tree_p (OMP_CLAUSE_SAFELEN_EXPR (c), &safe_len)
351838fd1498Szrj || maybe_lt (safe_len, 1U))
351938fd1498Szrj sctx->max_vf = 1;
352038fd1498Szrj else
352138fd1498Szrj sctx->max_vf = lower_bound (sctx->max_vf, safe_len);
352238fd1498Szrj }
352338fd1498Szrj }
352438fd1498Szrj if (maybe_gt (sctx->max_vf, 1U))
352538fd1498Szrj {
352638fd1498Szrj sctx->idx = create_tmp_var (unsigned_type_node);
352738fd1498Szrj sctx->lane = create_tmp_var (unsigned_type_node);
352838fd1498Szrj }
352938fd1498Szrj }
353038fd1498Szrj if (known_eq (sctx->max_vf, 1U))
353138fd1498Szrj return false;
353238fd1498Szrj
353338fd1498Szrj if (sctx->is_simt)
353438fd1498Szrj {
353538fd1498Szrj if (is_gimple_reg (new_var))
353638fd1498Szrj {
353738fd1498Szrj ivar = lvar = new_var;
353838fd1498Szrj return true;
353938fd1498Szrj }
354038fd1498Szrj tree type = TREE_TYPE (new_var), ptype = build_pointer_type (type);
354138fd1498Szrj ivar = lvar = create_tmp_var (type);
354238fd1498Szrj TREE_ADDRESSABLE (ivar) = 1;
354338fd1498Szrj DECL_ATTRIBUTES (ivar) = tree_cons (get_identifier ("omp simt private"),
354438fd1498Szrj NULL, DECL_ATTRIBUTES (ivar));
354538fd1498Szrj sctx->simt_eargs.safe_push (build1 (ADDR_EXPR, ptype, ivar));
354638fd1498Szrj tree clobber = build_constructor (type, NULL);
354738fd1498Szrj TREE_THIS_VOLATILE (clobber) = 1;
354838fd1498Szrj gimple *g = gimple_build_assign (ivar, clobber);
354938fd1498Szrj gimple_seq_add_stmt (&sctx->simt_dlist, g);
355038fd1498Szrj }
355138fd1498Szrj else
355238fd1498Szrj {
355338fd1498Szrj tree atype = build_array_type_nelts (TREE_TYPE (new_var), sctx->max_vf);
355438fd1498Szrj tree avar = create_tmp_var_raw (atype);
355538fd1498Szrj if (TREE_ADDRESSABLE (new_var))
355638fd1498Szrj TREE_ADDRESSABLE (avar) = 1;
355738fd1498Szrj DECL_ATTRIBUTES (avar)
355838fd1498Szrj = tree_cons (get_identifier ("omp simd array"), NULL,
355938fd1498Szrj DECL_ATTRIBUTES (avar));
356038fd1498Szrj gimple_add_tmp_var (avar);
356138fd1498Szrj ivar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, sctx->idx,
356238fd1498Szrj NULL_TREE, NULL_TREE);
356338fd1498Szrj lvar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, sctx->lane,
356438fd1498Szrj NULL_TREE, NULL_TREE);
356538fd1498Szrj }
356638fd1498Szrj if (DECL_P (new_var))
356738fd1498Szrj {
356838fd1498Szrj SET_DECL_VALUE_EXPR (new_var, lvar);
356938fd1498Szrj DECL_HAS_VALUE_EXPR_P (new_var) = 1;
357038fd1498Szrj }
357138fd1498Szrj return true;
357238fd1498Szrj }
357338fd1498Szrj
357438fd1498Szrj /* Helper function of lower_rec_input_clauses. For a reference
357538fd1498Szrj in simd reduction, add an underlying variable it will reference. */
357638fd1498Szrj
357738fd1498Szrj static void
handle_simd_reference(location_t loc,tree new_vard,gimple_seq * ilist)357838fd1498Szrj handle_simd_reference (location_t loc, tree new_vard, gimple_seq *ilist)
357938fd1498Szrj {
358038fd1498Szrj tree z = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_vard)));
358138fd1498Szrj if (TREE_CONSTANT (z))
358238fd1498Szrj {
358338fd1498Szrj z = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_vard)),
358438fd1498Szrj get_name (new_vard));
358538fd1498Szrj gimple_add_tmp_var (z);
358638fd1498Szrj TREE_ADDRESSABLE (z) = 1;
358738fd1498Szrj z = build_fold_addr_expr_loc (loc, z);
358838fd1498Szrj gimplify_assign (new_vard, z, ilist);
358938fd1498Szrj }
359038fd1498Szrj }
359138fd1498Szrj
359238fd1498Szrj /* Generate code to implement the input clauses, FIRSTPRIVATE and COPYIN,
359338fd1498Szrj from the receiver (aka child) side and initializers for REFERENCE_TYPE
359438fd1498Szrj private variables. Initialization statements go in ILIST, while calls
359538fd1498Szrj to destructors go in DLIST. */
359638fd1498Szrj
359738fd1498Szrj static void
lower_rec_input_clauses(tree clauses,gimple_seq * ilist,gimple_seq * dlist,omp_context * ctx,struct omp_for_data * fd)359838fd1498Szrj lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
359938fd1498Szrj omp_context *ctx, struct omp_for_data *fd)
360038fd1498Szrj {
360138fd1498Szrj tree c, dtor, copyin_seq, x, ptr;
360238fd1498Szrj bool copyin_by_ref = false;
360338fd1498Szrj bool lastprivate_firstprivate = false;
360438fd1498Szrj bool reduction_omp_orig_ref = false;
360538fd1498Szrj int pass;
360638fd1498Szrj bool is_simd = (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
360738fd1498Szrj && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD);
360838fd1498Szrj omplow_simd_context sctx = omplow_simd_context ();
360938fd1498Szrj tree simt_lane = NULL_TREE, simtrec = NULL_TREE;
361038fd1498Szrj tree ivar = NULL_TREE, lvar = NULL_TREE, uid = NULL_TREE;
361138fd1498Szrj gimple_seq llist[3] = { };
361238fd1498Szrj
361338fd1498Szrj copyin_seq = NULL;
361438fd1498Szrj sctx.is_simt = is_simd && omp_find_clause (clauses, OMP_CLAUSE__SIMT_);
361538fd1498Szrj
361638fd1498Szrj /* Set max_vf=1 (which will later enforce safelen=1) in simd loops
361738fd1498Szrj with data sharing clauses referencing variable sized vars. That
361838fd1498Szrj is unnecessarily hard to support and very unlikely to result in
361938fd1498Szrj vectorized code anyway. */
362038fd1498Szrj if (is_simd)
362138fd1498Szrj for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
362238fd1498Szrj switch (OMP_CLAUSE_CODE (c))
362338fd1498Szrj {
362438fd1498Szrj case OMP_CLAUSE_LINEAR:
362538fd1498Szrj if (OMP_CLAUSE_LINEAR_ARRAY (c))
362638fd1498Szrj sctx.max_vf = 1;
362738fd1498Szrj /* FALLTHRU */
362838fd1498Szrj case OMP_CLAUSE_PRIVATE:
362938fd1498Szrj case OMP_CLAUSE_FIRSTPRIVATE:
363038fd1498Szrj case OMP_CLAUSE_LASTPRIVATE:
363138fd1498Szrj if (is_variable_sized (OMP_CLAUSE_DECL (c)))
363238fd1498Szrj sctx.max_vf = 1;
363338fd1498Szrj break;
363438fd1498Szrj case OMP_CLAUSE_REDUCTION:
363538fd1498Szrj if (TREE_CODE (OMP_CLAUSE_DECL (c)) == MEM_REF
363638fd1498Szrj || is_variable_sized (OMP_CLAUSE_DECL (c)))
363738fd1498Szrj sctx.max_vf = 1;
363838fd1498Szrj break;
363938fd1498Szrj default:
364038fd1498Szrj continue;
364138fd1498Szrj }
364238fd1498Szrj
364338fd1498Szrj /* Add a placeholder for simduid. */
364438fd1498Szrj if (sctx.is_simt && maybe_ne (sctx.max_vf, 1U))
364538fd1498Szrj sctx.simt_eargs.safe_push (NULL_TREE);
364638fd1498Szrj
364738fd1498Szrj /* Do all the fixed sized types in the first pass, and the variable sized
364838fd1498Szrj types in the second pass. This makes sure that the scalar arguments to
364938fd1498Szrj the variable sized types are processed before we use them in the
365038fd1498Szrj variable sized operations. */
365138fd1498Szrj for (pass = 0; pass < 2; ++pass)
365238fd1498Szrj {
365338fd1498Szrj for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
365438fd1498Szrj {
365538fd1498Szrj enum omp_clause_code c_kind = OMP_CLAUSE_CODE (c);
365638fd1498Szrj tree var, new_var;
365738fd1498Szrj bool by_ref;
365838fd1498Szrj location_t clause_loc = OMP_CLAUSE_LOCATION (c);
365938fd1498Szrj
366038fd1498Szrj switch (c_kind)
366138fd1498Szrj {
366238fd1498Szrj case OMP_CLAUSE_PRIVATE:
366338fd1498Szrj if (OMP_CLAUSE_PRIVATE_DEBUG (c))
366438fd1498Szrj continue;
366538fd1498Szrj break;
366638fd1498Szrj case OMP_CLAUSE_SHARED:
366738fd1498Szrj /* Ignore shared directives in teams construct. */
366838fd1498Szrj if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
366938fd1498Szrj continue;
367038fd1498Szrj if (maybe_lookup_decl (OMP_CLAUSE_DECL (c), ctx) == NULL)
367138fd1498Szrj {
367238fd1498Szrj gcc_assert (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c)
367338fd1498Szrj || is_global_var (OMP_CLAUSE_DECL (c)));
367438fd1498Szrj continue;
367538fd1498Szrj }
367638fd1498Szrj case OMP_CLAUSE_FIRSTPRIVATE:
367738fd1498Szrj case OMP_CLAUSE_COPYIN:
367838fd1498Szrj break;
367938fd1498Szrj case OMP_CLAUSE_LINEAR:
368038fd1498Szrj if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c)
368138fd1498Szrj && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
368238fd1498Szrj lastprivate_firstprivate = true;
368338fd1498Szrj break;
368438fd1498Szrj case OMP_CLAUSE_REDUCTION:
368538fd1498Szrj if (OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c))
368638fd1498Szrj reduction_omp_orig_ref = true;
368738fd1498Szrj break;
368838fd1498Szrj case OMP_CLAUSE__LOOPTEMP_:
368938fd1498Szrj /* Handle _looptemp_ clauses only on parallel/task. */
369038fd1498Szrj if (fd)
369138fd1498Szrj continue;
369238fd1498Szrj break;
369338fd1498Szrj case OMP_CLAUSE_LASTPRIVATE:
369438fd1498Szrj if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
369538fd1498Szrj {
369638fd1498Szrj lastprivate_firstprivate = true;
369738fd1498Szrj if (pass != 0 || is_taskloop_ctx (ctx))
369838fd1498Szrj continue;
369938fd1498Szrj }
370038fd1498Szrj /* Even without corresponding firstprivate, if
370138fd1498Szrj decl is Fortran allocatable, it needs outer var
370238fd1498Szrj reference. */
370338fd1498Szrj else if (pass == 0
370438fd1498Szrj && lang_hooks.decls.omp_private_outer_ref
370538fd1498Szrj (OMP_CLAUSE_DECL (c)))
370638fd1498Szrj lastprivate_firstprivate = true;
370738fd1498Szrj break;
370838fd1498Szrj case OMP_CLAUSE_ALIGNED:
370938fd1498Szrj if (pass == 0)
371038fd1498Szrj continue;
371138fd1498Szrj var = OMP_CLAUSE_DECL (c);
371238fd1498Szrj if (TREE_CODE (TREE_TYPE (var)) == POINTER_TYPE
371338fd1498Szrj && !is_global_var (var))
371438fd1498Szrj {
371538fd1498Szrj new_var = maybe_lookup_decl (var, ctx);
371638fd1498Szrj if (new_var == NULL_TREE)
371738fd1498Szrj new_var = maybe_lookup_decl_in_outer_ctx (var, ctx);
371838fd1498Szrj x = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
371938fd1498Szrj tree alarg = omp_clause_aligned_alignment (c);
372038fd1498Szrj alarg = fold_convert_loc (clause_loc, size_type_node, alarg);
372138fd1498Szrj x = build_call_expr_loc (clause_loc, x, 2, new_var, alarg);
372238fd1498Szrj x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
372338fd1498Szrj x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
372438fd1498Szrj gimplify_and_add (x, ilist);
372538fd1498Szrj }
372638fd1498Szrj else if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE
372738fd1498Szrj && is_global_var (var))
372838fd1498Szrj {
372938fd1498Szrj tree ptype = build_pointer_type (TREE_TYPE (var)), t, t2;
373038fd1498Szrj new_var = lookup_decl (var, ctx);
373138fd1498Szrj t = maybe_lookup_decl_in_outer_ctx (var, ctx);
373238fd1498Szrj t = build_fold_addr_expr_loc (clause_loc, t);
373338fd1498Szrj t2 = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
373438fd1498Szrj tree alarg = omp_clause_aligned_alignment (c);
373538fd1498Szrj alarg = fold_convert_loc (clause_loc, size_type_node, alarg);
373638fd1498Szrj t = build_call_expr_loc (clause_loc, t2, 2, t, alarg);
373738fd1498Szrj t = fold_convert_loc (clause_loc, ptype, t);
373838fd1498Szrj x = create_tmp_var (ptype);
373938fd1498Szrj t = build2 (MODIFY_EXPR, ptype, x, t);
374038fd1498Szrj gimplify_and_add (t, ilist);
374138fd1498Szrj t = build_simple_mem_ref_loc (clause_loc, x);
374238fd1498Szrj SET_DECL_VALUE_EXPR (new_var, t);
374338fd1498Szrj DECL_HAS_VALUE_EXPR_P (new_var) = 1;
374438fd1498Szrj }
374538fd1498Szrj continue;
374638fd1498Szrj default:
374738fd1498Szrj continue;
374838fd1498Szrj }
374938fd1498Szrj
375038fd1498Szrj new_var = var = OMP_CLAUSE_DECL (c);
375138fd1498Szrj if (c_kind == OMP_CLAUSE_REDUCTION && TREE_CODE (var) == MEM_REF)
375238fd1498Szrj {
375338fd1498Szrj var = TREE_OPERAND (var, 0);
375438fd1498Szrj if (TREE_CODE (var) == POINTER_PLUS_EXPR)
375538fd1498Szrj var = TREE_OPERAND (var, 0);
375638fd1498Szrj if (TREE_CODE (var) == INDIRECT_REF
375738fd1498Szrj || TREE_CODE (var) == ADDR_EXPR)
375838fd1498Szrj var = TREE_OPERAND (var, 0);
375938fd1498Szrj if (is_variable_sized (var))
376038fd1498Szrj {
376138fd1498Szrj gcc_assert (DECL_HAS_VALUE_EXPR_P (var));
376238fd1498Szrj var = DECL_VALUE_EXPR (var);
376338fd1498Szrj gcc_assert (TREE_CODE (var) == INDIRECT_REF);
376438fd1498Szrj var = TREE_OPERAND (var, 0);
376538fd1498Szrj gcc_assert (DECL_P (var));
376638fd1498Szrj }
376738fd1498Szrj new_var = var;
376838fd1498Szrj }
376938fd1498Szrj if (c_kind != OMP_CLAUSE_COPYIN)
377038fd1498Szrj new_var = lookup_decl (var, ctx);
377138fd1498Szrj
377238fd1498Szrj if (c_kind == OMP_CLAUSE_SHARED || c_kind == OMP_CLAUSE_COPYIN)
377338fd1498Szrj {
377438fd1498Szrj if (pass != 0)
377538fd1498Szrj continue;
377638fd1498Szrj }
377738fd1498Szrj /* C/C++ array section reductions. */
377838fd1498Szrj else if (c_kind == OMP_CLAUSE_REDUCTION
377938fd1498Szrj && var != OMP_CLAUSE_DECL (c))
378038fd1498Szrj {
378138fd1498Szrj if (pass == 0)
378238fd1498Szrj continue;
378338fd1498Szrj
378438fd1498Szrj tree bias = TREE_OPERAND (OMP_CLAUSE_DECL (c), 1);
378538fd1498Szrj tree orig_var = TREE_OPERAND (OMP_CLAUSE_DECL (c), 0);
378638fd1498Szrj if (TREE_CODE (orig_var) == POINTER_PLUS_EXPR)
378738fd1498Szrj {
378838fd1498Szrj tree b = TREE_OPERAND (orig_var, 1);
378938fd1498Szrj b = maybe_lookup_decl (b, ctx);
379038fd1498Szrj if (b == NULL)
379138fd1498Szrj {
379238fd1498Szrj b = TREE_OPERAND (orig_var, 1);
379338fd1498Szrj b = maybe_lookup_decl_in_outer_ctx (b, ctx);
379438fd1498Szrj }
379538fd1498Szrj if (integer_zerop (bias))
379638fd1498Szrj bias = b;
379738fd1498Szrj else
379838fd1498Szrj {
379938fd1498Szrj bias = fold_convert_loc (clause_loc,
380038fd1498Szrj TREE_TYPE (b), bias);
380138fd1498Szrj bias = fold_build2_loc (clause_loc, PLUS_EXPR,
380238fd1498Szrj TREE_TYPE (b), b, bias);
380338fd1498Szrj }
380438fd1498Szrj orig_var = TREE_OPERAND (orig_var, 0);
380538fd1498Szrj }
380638fd1498Szrj if (TREE_CODE (orig_var) == INDIRECT_REF
380738fd1498Szrj || TREE_CODE (orig_var) == ADDR_EXPR)
380838fd1498Szrj orig_var = TREE_OPERAND (orig_var, 0);
380938fd1498Szrj tree d = OMP_CLAUSE_DECL (c);
381038fd1498Szrj tree type = TREE_TYPE (d);
381138fd1498Szrj gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
381238fd1498Szrj tree v = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
381338fd1498Szrj const char *name = get_name (orig_var);
381438fd1498Szrj if (TREE_CONSTANT (v))
381538fd1498Szrj {
381638fd1498Szrj x = create_tmp_var_raw (type, name);
381738fd1498Szrj gimple_add_tmp_var (x);
381838fd1498Szrj TREE_ADDRESSABLE (x) = 1;
381938fd1498Szrj x = build_fold_addr_expr_loc (clause_loc, x);
382038fd1498Szrj }
382138fd1498Szrj else
382238fd1498Szrj {
382338fd1498Szrj tree atmp
382438fd1498Szrj = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
382538fd1498Szrj tree t = maybe_lookup_decl (v, ctx);
382638fd1498Szrj if (t)
382738fd1498Szrj v = t;
382838fd1498Szrj else
382938fd1498Szrj v = maybe_lookup_decl_in_outer_ctx (v, ctx);
383038fd1498Szrj gimplify_expr (&v, ilist, NULL, is_gimple_val, fb_rvalue);
383138fd1498Szrj t = fold_build2_loc (clause_loc, PLUS_EXPR,
383238fd1498Szrj TREE_TYPE (v), v,
383338fd1498Szrj build_int_cst (TREE_TYPE (v), 1));
383438fd1498Szrj t = fold_build2_loc (clause_loc, MULT_EXPR,
383538fd1498Szrj TREE_TYPE (v), t,
383638fd1498Szrj TYPE_SIZE_UNIT (TREE_TYPE (type)));
383738fd1498Szrj tree al = size_int (TYPE_ALIGN (TREE_TYPE (type)));
383838fd1498Szrj x = build_call_expr_loc (clause_loc, atmp, 2, t, al);
383938fd1498Szrj }
384038fd1498Szrj
384138fd1498Szrj tree ptype = build_pointer_type (TREE_TYPE (type));
384238fd1498Szrj x = fold_convert_loc (clause_loc, ptype, x);
384338fd1498Szrj tree y = create_tmp_var (ptype, name);
384438fd1498Szrj gimplify_assign (y, x, ilist);
384538fd1498Szrj x = y;
384638fd1498Szrj tree yb = y;
384738fd1498Szrj
384838fd1498Szrj if (!integer_zerop (bias))
384938fd1498Szrj {
385038fd1498Szrj bias = fold_convert_loc (clause_loc, pointer_sized_int_node,
385138fd1498Szrj bias);
385238fd1498Szrj yb = fold_convert_loc (clause_loc, pointer_sized_int_node,
385338fd1498Szrj x);
385438fd1498Szrj yb = fold_build2_loc (clause_loc, MINUS_EXPR,
385538fd1498Szrj pointer_sized_int_node, yb, bias);
385638fd1498Szrj x = fold_convert_loc (clause_loc, TREE_TYPE (x), yb);
385738fd1498Szrj yb = create_tmp_var (ptype, name);
385838fd1498Szrj gimplify_assign (yb, x, ilist);
385938fd1498Szrj x = yb;
386038fd1498Szrj }
386138fd1498Szrj
386238fd1498Szrj d = TREE_OPERAND (d, 0);
386338fd1498Szrj if (TREE_CODE (d) == POINTER_PLUS_EXPR)
386438fd1498Szrj d = TREE_OPERAND (d, 0);
386538fd1498Szrj if (TREE_CODE (d) == ADDR_EXPR)
386638fd1498Szrj {
386738fd1498Szrj if (orig_var != var)
386838fd1498Szrj {
386938fd1498Szrj gcc_assert (is_variable_sized (orig_var));
387038fd1498Szrj x = fold_convert_loc (clause_loc, TREE_TYPE (new_var),
387138fd1498Szrj x);
387238fd1498Szrj gimplify_assign (new_var, x, ilist);
387338fd1498Szrj tree new_orig_var = lookup_decl (orig_var, ctx);
387438fd1498Szrj tree t = build_fold_indirect_ref (new_var);
387538fd1498Szrj DECL_IGNORED_P (new_var) = 0;
387638fd1498Szrj TREE_THIS_NOTRAP (t);
387738fd1498Szrj SET_DECL_VALUE_EXPR (new_orig_var, t);
387838fd1498Szrj DECL_HAS_VALUE_EXPR_P (new_orig_var) = 1;
387938fd1498Szrj }
388038fd1498Szrj else
388138fd1498Szrj {
388238fd1498Szrj x = build2 (MEM_REF, TREE_TYPE (new_var), x,
388338fd1498Szrj build_int_cst (ptype, 0));
388438fd1498Szrj SET_DECL_VALUE_EXPR (new_var, x);
388538fd1498Szrj DECL_HAS_VALUE_EXPR_P (new_var) = 1;
388638fd1498Szrj }
388738fd1498Szrj }
388838fd1498Szrj else
388938fd1498Szrj {
389038fd1498Szrj gcc_assert (orig_var == var);
389138fd1498Szrj if (TREE_CODE (d) == INDIRECT_REF)
389238fd1498Szrj {
389338fd1498Szrj x = create_tmp_var (ptype, name);
389438fd1498Szrj TREE_ADDRESSABLE (x) = 1;
389538fd1498Szrj gimplify_assign (x, yb, ilist);
389638fd1498Szrj x = build_fold_addr_expr_loc (clause_loc, x);
389738fd1498Szrj }
389838fd1498Szrj x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
389938fd1498Szrj gimplify_assign (new_var, x, ilist);
390038fd1498Szrj }
390138fd1498Szrj tree y1 = create_tmp_var (ptype, NULL);
390238fd1498Szrj gimplify_assign (y1, y, ilist);
390338fd1498Szrj tree i2 = NULL_TREE, y2 = NULL_TREE;
390438fd1498Szrj tree body2 = NULL_TREE, end2 = NULL_TREE;
390538fd1498Szrj tree y3 = NULL_TREE, y4 = NULL_TREE;
390638fd1498Szrj if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) || is_simd)
390738fd1498Szrj {
390838fd1498Szrj y2 = create_tmp_var (ptype, NULL);
390938fd1498Szrj gimplify_assign (y2, y, ilist);
391038fd1498Szrj tree ref = build_outer_var_ref (var, ctx);
391138fd1498Szrj /* For ref build_outer_var_ref already performs this. */
391238fd1498Szrj if (TREE_CODE (d) == INDIRECT_REF)
391338fd1498Szrj gcc_assert (omp_is_reference (var));
391438fd1498Szrj else if (TREE_CODE (d) == ADDR_EXPR)
391538fd1498Szrj ref = build_fold_addr_expr (ref);
391638fd1498Szrj else if (omp_is_reference (var))
391738fd1498Szrj ref = build_fold_addr_expr (ref);
391838fd1498Szrj ref = fold_convert_loc (clause_loc, ptype, ref);
391938fd1498Szrj if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)
392038fd1498Szrj && OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c))
392138fd1498Szrj {
392238fd1498Szrj y3 = create_tmp_var (ptype, NULL);
392338fd1498Szrj gimplify_assign (y3, unshare_expr (ref), ilist);
392438fd1498Szrj }
392538fd1498Szrj if (is_simd)
392638fd1498Szrj {
392738fd1498Szrj y4 = create_tmp_var (ptype, NULL);
392838fd1498Szrj gimplify_assign (y4, ref, dlist);
392938fd1498Szrj }
393038fd1498Szrj }
393138fd1498Szrj tree i = create_tmp_var (TREE_TYPE (v), NULL);
393238fd1498Szrj gimplify_assign (i, build_int_cst (TREE_TYPE (v), 0), ilist);
393338fd1498Szrj tree body = create_artificial_label (UNKNOWN_LOCATION);
393438fd1498Szrj tree end = create_artificial_label (UNKNOWN_LOCATION);
393538fd1498Szrj gimple_seq_add_stmt (ilist, gimple_build_label (body));
393638fd1498Szrj if (y2)
393738fd1498Szrj {
393838fd1498Szrj i2 = create_tmp_var (TREE_TYPE (v), NULL);
393938fd1498Szrj gimplify_assign (i2, build_int_cst (TREE_TYPE (v), 0), dlist);
394038fd1498Szrj body2 = create_artificial_label (UNKNOWN_LOCATION);
394138fd1498Szrj end2 = create_artificial_label (UNKNOWN_LOCATION);
394238fd1498Szrj gimple_seq_add_stmt (dlist, gimple_build_label (body2));
394338fd1498Szrj }
394438fd1498Szrj if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
394538fd1498Szrj {
394638fd1498Szrj tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
394738fd1498Szrj tree decl_placeholder
394838fd1498Szrj = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c);
394938fd1498Szrj SET_DECL_VALUE_EXPR (decl_placeholder,
395038fd1498Szrj build_simple_mem_ref (y1));
395138fd1498Szrj DECL_HAS_VALUE_EXPR_P (decl_placeholder) = 1;
395238fd1498Szrj SET_DECL_VALUE_EXPR (placeholder,
395338fd1498Szrj y3 ? build_simple_mem_ref (y3)
395438fd1498Szrj : error_mark_node);
395538fd1498Szrj DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
395638fd1498Szrj x = lang_hooks.decls.omp_clause_default_ctor
395738fd1498Szrj (c, build_simple_mem_ref (y1),
395838fd1498Szrj y3 ? build_simple_mem_ref (y3) : NULL_TREE);
395938fd1498Szrj if (x)
396038fd1498Szrj gimplify_and_add (x, ilist);
396138fd1498Szrj if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
396238fd1498Szrj {
396338fd1498Szrj gimple_seq tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
396438fd1498Szrj lower_omp (&tseq, ctx);
396538fd1498Szrj gimple_seq_add_seq (ilist, tseq);
396638fd1498Szrj }
396738fd1498Szrj OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
396838fd1498Szrj if (is_simd)
396938fd1498Szrj {
397038fd1498Szrj SET_DECL_VALUE_EXPR (decl_placeholder,
397138fd1498Szrj build_simple_mem_ref (y2));
397238fd1498Szrj SET_DECL_VALUE_EXPR (placeholder,
397338fd1498Szrj build_simple_mem_ref (y4));
397438fd1498Szrj gimple_seq tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
397538fd1498Szrj lower_omp (&tseq, ctx);
397638fd1498Szrj gimple_seq_add_seq (dlist, tseq);
397738fd1498Szrj OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
397838fd1498Szrj }
397938fd1498Szrj DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
398038fd1498Szrj DECL_HAS_VALUE_EXPR_P (decl_placeholder) = 0;
398138fd1498Szrj x = lang_hooks.decls.omp_clause_dtor
398238fd1498Szrj (c, build_simple_mem_ref (y2));
398338fd1498Szrj if (x)
398438fd1498Szrj {
398538fd1498Szrj gimple_seq tseq = NULL;
398638fd1498Szrj dtor = x;
398738fd1498Szrj gimplify_stmt (&dtor, &tseq);
398838fd1498Szrj gimple_seq_add_seq (dlist, tseq);
398938fd1498Szrj }
399038fd1498Szrj }
399138fd1498Szrj else
399238fd1498Szrj {
399338fd1498Szrj x = omp_reduction_init (c, TREE_TYPE (type));
399438fd1498Szrj enum tree_code code = OMP_CLAUSE_REDUCTION_CODE (c);
399538fd1498Szrj
399638fd1498Szrj /* reduction(-:var) sums up the partial results, so it
399738fd1498Szrj acts identically to reduction(+:var). */
399838fd1498Szrj if (code == MINUS_EXPR)
399938fd1498Szrj code = PLUS_EXPR;
400038fd1498Szrj
400138fd1498Szrj gimplify_assign (build_simple_mem_ref (y1), x, ilist);
400238fd1498Szrj if (is_simd)
400338fd1498Szrj {
400438fd1498Szrj x = build2 (code, TREE_TYPE (type),
400538fd1498Szrj build_simple_mem_ref (y4),
400638fd1498Szrj build_simple_mem_ref (y2));
400738fd1498Szrj gimplify_assign (build_simple_mem_ref (y4), x, dlist);
400838fd1498Szrj }
400938fd1498Szrj }
401038fd1498Szrj gimple *g
401138fd1498Szrj = gimple_build_assign (y1, POINTER_PLUS_EXPR, y1,
401238fd1498Szrj TYPE_SIZE_UNIT (TREE_TYPE (type)));
401338fd1498Szrj gimple_seq_add_stmt (ilist, g);
401438fd1498Szrj if (y3)
401538fd1498Szrj {
401638fd1498Szrj g = gimple_build_assign (y3, POINTER_PLUS_EXPR, y3,
401738fd1498Szrj TYPE_SIZE_UNIT (TREE_TYPE (type)));
401838fd1498Szrj gimple_seq_add_stmt (ilist, g);
401938fd1498Szrj }
402038fd1498Szrj g = gimple_build_assign (i, PLUS_EXPR, i,
402138fd1498Szrj build_int_cst (TREE_TYPE (i), 1));
402238fd1498Szrj gimple_seq_add_stmt (ilist, g);
402338fd1498Szrj g = gimple_build_cond (LE_EXPR, i, v, body, end);
402438fd1498Szrj gimple_seq_add_stmt (ilist, g);
402538fd1498Szrj gimple_seq_add_stmt (ilist, gimple_build_label (end));
402638fd1498Szrj if (y2)
402738fd1498Szrj {
402838fd1498Szrj g = gimple_build_assign (y2, POINTER_PLUS_EXPR, y2,
402938fd1498Szrj TYPE_SIZE_UNIT (TREE_TYPE (type)));
403038fd1498Szrj gimple_seq_add_stmt (dlist, g);
403138fd1498Szrj if (y4)
403238fd1498Szrj {
403338fd1498Szrj g = gimple_build_assign
403438fd1498Szrj (y4, POINTER_PLUS_EXPR, y4,
403538fd1498Szrj TYPE_SIZE_UNIT (TREE_TYPE (type)));
403638fd1498Szrj gimple_seq_add_stmt (dlist, g);
403738fd1498Szrj }
403838fd1498Szrj g = gimple_build_assign (i2, PLUS_EXPR, i2,
403938fd1498Szrj build_int_cst (TREE_TYPE (i2), 1));
404038fd1498Szrj gimple_seq_add_stmt (dlist, g);
404138fd1498Szrj g = gimple_build_cond (LE_EXPR, i2, v, body2, end2);
404238fd1498Szrj gimple_seq_add_stmt (dlist, g);
404338fd1498Szrj gimple_seq_add_stmt (dlist, gimple_build_label (end2));
404438fd1498Szrj }
404538fd1498Szrj continue;
404638fd1498Szrj }
404738fd1498Szrj else if (is_variable_sized (var))
404838fd1498Szrj {
404938fd1498Szrj /* For variable sized types, we need to allocate the
405038fd1498Szrj actual storage here. Call alloca and store the
405138fd1498Szrj result in the pointer decl that we created elsewhere. */
405238fd1498Szrj if (pass == 0)
405338fd1498Szrj continue;
405438fd1498Szrj
405538fd1498Szrj if (c_kind != OMP_CLAUSE_FIRSTPRIVATE || !is_task_ctx (ctx))
405638fd1498Szrj {
405738fd1498Szrj gcall *stmt;
405838fd1498Szrj tree tmp, atmp;
405938fd1498Szrj
406038fd1498Szrj ptr = DECL_VALUE_EXPR (new_var);
406138fd1498Szrj gcc_assert (TREE_CODE (ptr) == INDIRECT_REF);
406238fd1498Szrj ptr = TREE_OPERAND (ptr, 0);
406338fd1498Szrj gcc_assert (DECL_P (ptr));
406438fd1498Szrj x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
406538fd1498Szrj
406638fd1498Szrj /* void *tmp = __builtin_alloca */
406738fd1498Szrj atmp = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
406838fd1498Szrj stmt = gimple_build_call (atmp, 2, x,
406938fd1498Szrj size_int (DECL_ALIGN (var)));
407038fd1498Szrj tmp = create_tmp_var_raw (ptr_type_node);
407138fd1498Szrj gimple_add_tmp_var (tmp);
407238fd1498Szrj gimple_call_set_lhs (stmt, tmp);
407338fd1498Szrj
407438fd1498Szrj gimple_seq_add_stmt (ilist, stmt);
407538fd1498Szrj
407638fd1498Szrj x = fold_convert_loc (clause_loc, TREE_TYPE (ptr), tmp);
407738fd1498Szrj gimplify_assign (ptr, x, ilist);
407838fd1498Szrj }
407938fd1498Szrj }
408038fd1498Szrj else if (omp_is_reference (var))
408138fd1498Szrj {
408238fd1498Szrj /* For references that are being privatized for Fortran,
408338fd1498Szrj allocate new backing storage for the new pointer
408438fd1498Szrj variable. This allows us to avoid changing all the
408538fd1498Szrj code that expects a pointer to something that expects
408638fd1498Szrj a direct variable. */
408738fd1498Szrj if (pass == 0)
408838fd1498Szrj continue;
408938fd1498Szrj
409038fd1498Szrj x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
409138fd1498Szrj if (c_kind == OMP_CLAUSE_FIRSTPRIVATE && is_task_ctx (ctx))
409238fd1498Szrj {
409338fd1498Szrj x = build_receiver_ref (var, false, ctx);
409438fd1498Szrj x = build_fold_addr_expr_loc (clause_loc, x);
409538fd1498Szrj }
409638fd1498Szrj else if (TREE_CONSTANT (x))
409738fd1498Szrj {
409838fd1498Szrj /* For reduction in SIMD loop, defer adding the
409938fd1498Szrj initialization of the reference, because if we decide
410038fd1498Szrj to use SIMD array for it, the initilization could cause
410138fd1498Szrj expansion ICE. */
410238fd1498Szrj if (c_kind == OMP_CLAUSE_REDUCTION && is_simd)
410338fd1498Szrj x = NULL_TREE;
410438fd1498Szrj else
410538fd1498Szrj {
410638fd1498Szrj x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)),
410738fd1498Szrj get_name (var));
410838fd1498Szrj gimple_add_tmp_var (x);
410938fd1498Szrj TREE_ADDRESSABLE (x) = 1;
411038fd1498Szrj x = build_fold_addr_expr_loc (clause_loc, x);
411138fd1498Szrj }
411238fd1498Szrj }
411338fd1498Szrj else
411438fd1498Szrj {
411538fd1498Szrj tree atmp
411638fd1498Szrj = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
411738fd1498Szrj tree rtype = TREE_TYPE (TREE_TYPE (new_var));
411838fd1498Szrj tree al = size_int (TYPE_ALIGN (rtype));
411938fd1498Szrj x = build_call_expr_loc (clause_loc, atmp, 2, x, al);
412038fd1498Szrj }
412138fd1498Szrj
412238fd1498Szrj if (x)
412338fd1498Szrj {
412438fd1498Szrj x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
412538fd1498Szrj gimplify_assign (new_var, x, ilist);
412638fd1498Szrj }
412738fd1498Szrj
412838fd1498Szrj new_var = build_simple_mem_ref_loc (clause_loc, new_var);
412938fd1498Szrj }
413038fd1498Szrj else if (c_kind == OMP_CLAUSE_REDUCTION
413138fd1498Szrj && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
413238fd1498Szrj {
413338fd1498Szrj if (pass == 0)
413438fd1498Szrj continue;
413538fd1498Szrj }
413638fd1498Szrj else if (pass != 0)
413738fd1498Szrj continue;
413838fd1498Szrj
413938fd1498Szrj switch (OMP_CLAUSE_CODE (c))
414038fd1498Szrj {
414138fd1498Szrj case OMP_CLAUSE_SHARED:
414238fd1498Szrj /* Ignore shared directives in teams construct. */
414338fd1498Szrj if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
414438fd1498Szrj continue;
414538fd1498Szrj /* Shared global vars are just accessed directly. */
414638fd1498Szrj if (is_global_var (new_var))
414738fd1498Szrj break;
414838fd1498Szrj /* For taskloop firstprivate/lastprivate, represented
414938fd1498Szrj as firstprivate and shared clause on the task, new_var
415038fd1498Szrj is the firstprivate var. */
415138fd1498Szrj if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
415238fd1498Szrj break;
415338fd1498Szrj /* Set up the DECL_VALUE_EXPR for shared variables now. This
415438fd1498Szrj needs to be delayed until after fixup_child_record_type so
415538fd1498Szrj that we get the correct type during the dereference. */
415638fd1498Szrj by_ref = use_pointer_for_field (var, ctx);
415738fd1498Szrj x = build_receiver_ref (var, by_ref, ctx);
415838fd1498Szrj SET_DECL_VALUE_EXPR (new_var, x);
415938fd1498Szrj DECL_HAS_VALUE_EXPR_P (new_var) = 1;
416038fd1498Szrj
416138fd1498Szrj /* ??? If VAR is not passed by reference, and the variable
416238fd1498Szrj hasn't been initialized yet, then we'll get a warning for
416338fd1498Szrj the store into the omp_data_s structure. Ideally, we'd be
416438fd1498Szrj able to notice this and not store anything at all, but
416538fd1498Szrj we're generating code too early. Suppress the warning. */
416638fd1498Szrj if (!by_ref)
416738fd1498Szrj TREE_NO_WARNING (var) = 1;
416838fd1498Szrj break;
416938fd1498Szrj
417038fd1498Szrj case OMP_CLAUSE_LASTPRIVATE:
417138fd1498Szrj if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
417238fd1498Szrj break;
417338fd1498Szrj /* FALLTHRU */
417438fd1498Szrj
417538fd1498Szrj case OMP_CLAUSE_PRIVATE:
417638fd1498Szrj if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_PRIVATE)
417738fd1498Szrj x = build_outer_var_ref (var, ctx);
417838fd1498Szrj else if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
417938fd1498Szrj {
418038fd1498Szrj if (is_task_ctx (ctx))
418138fd1498Szrj x = build_receiver_ref (var, false, ctx);
418238fd1498Szrj else
418338fd1498Szrj x = build_outer_var_ref (var, ctx, OMP_CLAUSE_PRIVATE);
418438fd1498Szrj }
418538fd1498Szrj else
418638fd1498Szrj x = NULL;
418738fd1498Szrj do_private:
418838fd1498Szrj tree nx;
418938fd1498Szrj nx = lang_hooks.decls.omp_clause_default_ctor
419038fd1498Szrj (c, unshare_expr (new_var), x);
419138fd1498Szrj if (is_simd)
419238fd1498Szrj {
419338fd1498Szrj tree y = lang_hooks.decls.omp_clause_dtor (c, new_var);
419438fd1498Szrj if ((TREE_ADDRESSABLE (new_var) || nx || y
419538fd1498Szrj || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE)
419638fd1498Szrj && lower_rec_simd_input_clauses (new_var, ctx, &sctx,
419738fd1498Szrj ivar, lvar))
419838fd1498Szrj {
419938fd1498Szrj if (nx)
420038fd1498Szrj x = lang_hooks.decls.omp_clause_default_ctor
420138fd1498Szrj (c, unshare_expr (ivar), x);
420238fd1498Szrj if (nx && x)
420338fd1498Szrj gimplify_and_add (x, &llist[0]);
420438fd1498Szrj if (y)
420538fd1498Szrj {
420638fd1498Szrj y = lang_hooks.decls.omp_clause_dtor (c, ivar);
420738fd1498Szrj if (y)
420838fd1498Szrj {
420938fd1498Szrj gimple_seq tseq = NULL;
421038fd1498Szrj
421138fd1498Szrj dtor = y;
421238fd1498Szrj gimplify_stmt (&dtor, &tseq);
421338fd1498Szrj gimple_seq_add_seq (&llist[1], tseq);
421438fd1498Szrj }
421538fd1498Szrj }
421638fd1498Szrj break;
421738fd1498Szrj }
421838fd1498Szrj }
421938fd1498Szrj if (nx)
422038fd1498Szrj gimplify_and_add (nx, ilist);
422138fd1498Szrj /* FALLTHRU */
422238fd1498Szrj
422338fd1498Szrj do_dtor:
422438fd1498Szrj x = lang_hooks.decls.omp_clause_dtor (c, new_var);
422538fd1498Szrj if (x)
422638fd1498Szrj {
422738fd1498Szrj gimple_seq tseq = NULL;
422838fd1498Szrj
422938fd1498Szrj dtor = x;
423038fd1498Szrj gimplify_stmt (&dtor, &tseq);
423138fd1498Szrj gimple_seq_add_seq (dlist, tseq);
423238fd1498Szrj }
423338fd1498Szrj break;
423438fd1498Szrj
423538fd1498Szrj case OMP_CLAUSE_LINEAR:
423638fd1498Szrj if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c))
423738fd1498Szrj goto do_firstprivate;
423838fd1498Szrj if (OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
423938fd1498Szrj x = NULL;
424038fd1498Szrj else
424138fd1498Szrj x = build_outer_var_ref (var, ctx);
424238fd1498Szrj goto do_private;
424338fd1498Szrj
424438fd1498Szrj case OMP_CLAUSE_FIRSTPRIVATE:
424538fd1498Szrj if (is_task_ctx (ctx))
424638fd1498Szrj {
424738fd1498Szrj if (omp_is_reference (var) || is_variable_sized (var))
424838fd1498Szrj goto do_dtor;
424938fd1498Szrj else if (is_global_var (maybe_lookup_decl_in_outer_ctx (var,
425038fd1498Szrj ctx))
425138fd1498Szrj || use_pointer_for_field (var, NULL))
425238fd1498Szrj {
425338fd1498Szrj x = build_receiver_ref (var, false, ctx);
425438fd1498Szrj SET_DECL_VALUE_EXPR (new_var, x);
425538fd1498Szrj DECL_HAS_VALUE_EXPR_P (new_var) = 1;
425638fd1498Szrj goto do_dtor;
425738fd1498Szrj }
425838fd1498Szrj }
425938fd1498Szrj do_firstprivate:
426038fd1498Szrj x = build_outer_var_ref (var, ctx);
426138fd1498Szrj if (is_simd)
426238fd1498Szrj {
426338fd1498Szrj if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
426438fd1498Szrj && gimple_omp_for_combined_into_p (ctx->stmt))
426538fd1498Szrj {
426638fd1498Szrj tree t = OMP_CLAUSE_LINEAR_STEP (c);
426738fd1498Szrj tree stept = TREE_TYPE (t);
426838fd1498Szrj tree ct = omp_find_clause (clauses,
426938fd1498Szrj OMP_CLAUSE__LOOPTEMP_);
427038fd1498Szrj gcc_assert (ct);
427138fd1498Szrj tree l = OMP_CLAUSE_DECL (ct);
427238fd1498Szrj tree n1 = fd->loop.n1;
427338fd1498Szrj tree step = fd->loop.step;
427438fd1498Szrj tree itype = TREE_TYPE (l);
427538fd1498Szrj if (POINTER_TYPE_P (itype))
427638fd1498Szrj itype = signed_type_for (itype);
427738fd1498Szrj l = fold_build2 (MINUS_EXPR, itype, l, n1);
427838fd1498Szrj if (TYPE_UNSIGNED (itype)
427938fd1498Szrj && fd->loop.cond_code == GT_EXPR)
428038fd1498Szrj l = fold_build2 (TRUNC_DIV_EXPR, itype,
428138fd1498Szrj fold_build1 (NEGATE_EXPR, itype, l),
428238fd1498Szrj fold_build1 (NEGATE_EXPR,
428338fd1498Szrj itype, step));
428438fd1498Szrj else
428538fd1498Szrj l = fold_build2 (TRUNC_DIV_EXPR, itype, l, step);
428638fd1498Szrj t = fold_build2 (MULT_EXPR, stept,
428738fd1498Szrj fold_convert (stept, l), t);
428838fd1498Szrj
428938fd1498Szrj if (OMP_CLAUSE_LINEAR_ARRAY (c))
429038fd1498Szrj {
429138fd1498Szrj x = lang_hooks.decls.omp_clause_linear_ctor
429238fd1498Szrj (c, new_var, x, t);
429338fd1498Szrj gimplify_and_add (x, ilist);
429438fd1498Szrj goto do_dtor;
429538fd1498Szrj }
429638fd1498Szrj
429738fd1498Szrj if (POINTER_TYPE_P (TREE_TYPE (x)))
429838fd1498Szrj x = fold_build2 (POINTER_PLUS_EXPR,
429938fd1498Szrj TREE_TYPE (x), x, t);
430038fd1498Szrj else
430138fd1498Szrj x = fold_build2 (PLUS_EXPR, TREE_TYPE (x), x, t);
430238fd1498Szrj }
430338fd1498Szrj
430438fd1498Szrj if ((OMP_CLAUSE_CODE (c) != OMP_CLAUSE_LINEAR
430538fd1498Szrj || TREE_ADDRESSABLE (new_var))
430638fd1498Szrj && lower_rec_simd_input_clauses (new_var, ctx, &sctx,
430738fd1498Szrj ivar, lvar))
430838fd1498Szrj {
430938fd1498Szrj if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR)
431038fd1498Szrj {
431138fd1498Szrj tree iv = create_tmp_var (TREE_TYPE (new_var));
431238fd1498Szrj x = lang_hooks.decls.omp_clause_copy_ctor (c, iv, x);
431338fd1498Szrj gimplify_and_add (x, ilist);
431438fd1498Szrj gimple_stmt_iterator gsi
431538fd1498Szrj = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
431638fd1498Szrj gassign *g
431738fd1498Szrj = gimple_build_assign (unshare_expr (lvar), iv);
431838fd1498Szrj gsi_insert_before_without_update (&gsi, g,
431938fd1498Szrj GSI_SAME_STMT);
432038fd1498Szrj tree t = OMP_CLAUSE_LINEAR_STEP (c);
432138fd1498Szrj enum tree_code code = PLUS_EXPR;
432238fd1498Szrj if (POINTER_TYPE_P (TREE_TYPE (new_var)))
432338fd1498Szrj code = POINTER_PLUS_EXPR;
432438fd1498Szrj g = gimple_build_assign (iv, code, iv, t);
432538fd1498Szrj gsi_insert_before_without_update (&gsi, g,
432638fd1498Szrj GSI_SAME_STMT);
432738fd1498Szrj break;
432838fd1498Szrj }
432938fd1498Szrj x = lang_hooks.decls.omp_clause_copy_ctor
433038fd1498Szrj (c, unshare_expr (ivar), x);
433138fd1498Szrj gimplify_and_add (x, &llist[0]);
433238fd1498Szrj x = lang_hooks.decls.omp_clause_dtor (c, ivar);
433338fd1498Szrj if (x)
433438fd1498Szrj {
433538fd1498Szrj gimple_seq tseq = NULL;
433638fd1498Szrj
433738fd1498Szrj dtor = x;
433838fd1498Szrj gimplify_stmt (&dtor, &tseq);
433938fd1498Szrj gimple_seq_add_seq (&llist[1], tseq);
434038fd1498Szrj }
434138fd1498Szrj break;
434238fd1498Szrj }
434338fd1498Szrj }
434438fd1498Szrj x = lang_hooks.decls.omp_clause_copy_ctor
434538fd1498Szrj (c, unshare_expr (new_var), x);
434638fd1498Szrj gimplify_and_add (x, ilist);
434738fd1498Szrj goto do_dtor;
434838fd1498Szrj
434938fd1498Szrj case OMP_CLAUSE__LOOPTEMP_:
435038fd1498Szrj gcc_assert (is_taskreg_ctx (ctx));
435138fd1498Szrj x = build_outer_var_ref (var, ctx);
435238fd1498Szrj x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
435338fd1498Szrj gimplify_and_add (x, ilist);
435438fd1498Szrj break;
435538fd1498Szrj
435638fd1498Szrj case OMP_CLAUSE_COPYIN:
435738fd1498Szrj by_ref = use_pointer_for_field (var, NULL);
435838fd1498Szrj x = build_receiver_ref (var, by_ref, ctx);
435938fd1498Szrj x = lang_hooks.decls.omp_clause_assign_op (c, new_var, x);
436038fd1498Szrj append_to_statement_list (x, ©in_seq);
436138fd1498Szrj copyin_by_ref |= by_ref;
436238fd1498Szrj break;
436338fd1498Szrj
436438fd1498Szrj case OMP_CLAUSE_REDUCTION:
436538fd1498Szrj /* OpenACC reductions are initialized using the
436638fd1498Szrj GOACC_REDUCTION internal function. */
436738fd1498Szrj if (is_gimple_omp_oacc (ctx->stmt))
436838fd1498Szrj break;
436938fd1498Szrj if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
437038fd1498Szrj {
437138fd1498Szrj tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
437238fd1498Szrj gimple *tseq;
437338fd1498Szrj x = build_outer_var_ref (var, ctx);
437438fd1498Szrj
437538fd1498Szrj if (omp_is_reference (var)
437638fd1498Szrj && !useless_type_conversion_p (TREE_TYPE (placeholder),
437738fd1498Szrj TREE_TYPE (x)))
437838fd1498Szrj x = build_fold_addr_expr_loc (clause_loc, x);
437938fd1498Szrj SET_DECL_VALUE_EXPR (placeholder, x);
438038fd1498Szrj DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
438138fd1498Szrj tree new_vard = new_var;
438238fd1498Szrj if (omp_is_reference (var))
438338fd1498Szrj {
438438fd1498Szrj gcc_assert (TREE_CODE (new_var) == MEM_REF);
438538fd1498Szrj new_vard = TREE_OPERAND (new_var, 0);
438638fd1498Szrj gcc_assert (DECL_P (new_vard));
438738fd1498Szrj }
438838fd1498Szrj if (is_simd
438938fd1498Szrj && lower_rec_simd_input_clauses (new_var, ctx, &sctx,
439038fd1498Szrj ivar, lvar))
439138fd1498Szrj {
439238fd1498Szrj if (new_vard == new_var)
439338fd1498Szrj {
439438fd1498Szrj gcc_assert (DECL_VALUE_EXPR (new_var) == lvar);
439538fd1498Szrj SET_DECL_VALUE_EXPR (new_var, ivar);
439638fd1498Szrj }
439738fd1498Szrj else
439838fd1498Szrj {
439938fd1498Szrj SET_DECL_VALUE_EXPR (new_vard,
440038fd1498Szrj build_fold_addr_expr (ivar));
440138fd1498Szrj DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
440238fd1498Szrj }
440338fd1498Szrj x = lang_hooks.decls.omp_clause_default_ctor
440438fd1498Szrj (c, unshare_expr (ivar),
440538fd1498Szrj build_outer_var_ref (var, ctx));
440638fd1498Szrj if (x)
440738fd1498Szrj gimplify_and_add (x, &llist[0]);
440838fd1498Szrj if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
440938fd1498Szrj {
441038fd1498Szrj tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
441138fd1498Szrj lower_omp (&tseq, ctx);
441238fd1498Szrj gimple_seq_add_seq (&llist[0], tseq);
441338fd1498Szrj }
441438fd1498Szrj OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
441538fd1498Szrj tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
441638fd1498Szrj lower_omp (&tseq, ctx);
441738fd1498Szrj gimple_seq_add_seq (&llist[1], tseq);
441838fd1498Szrj OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
441938fd1498Szrj DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
442038fd1498Szrj if (new_vard == new_var)
442138fd1498Szrj SET_DECL_VALUE_EXPR (new_var, lvar);
442238fd1498Szrj else
442338fd1498Szrj SET_DECL_VALUE_EXPR (new_vard,
442438fd1498Szrj build_fold_addr_expr (lvar));
442538fd1498Szrj x = lang_hooks.decls.omp_clause_dtor (c, ivar);
442638fd1498Szrj if (x)
442738fd1498Szrj {
442838fd1498Szrj tseq = NULL;
442938fd1498Szrj dtor = x;
443038fd1498Szrj gimplify_stmt (&dtor, &tseq);
443138fd1498Szrj gimple_seq_add_seq (&llist[1], tseq);
443238fd1498Szrj }
443338fd1498Szrj break;
443438fd1498Szrj }
443538fd1498Szrj /* If this is a reference to constant size reduction var
443638fd1498Szrj with placeholder, we haven't emitted the initializer
443738fd1498Szrj for it because it is undesirable if SIMD arrays are used.
443838fd1498Szrj But if they aren't used, we need to emit the deferred
443938fd1498Szrj initialization now. */
444038fd1498Szrj else if (omp_is_reference (var) && is_simd)
444138fd1498Szrj handle_simd_reference (clause_loc, new_vard, ilist);
444238fd1498Szrj x = lang_hooks.decls.omp_clause_default_ctor
444338fd1498Szrj (c, unshare_expr (new_var),
444438fd1498Szrj build_outer_var_ref (var, ctx));
444538fd1498Szrj if (x)
444638fd1498Szrj gimplify_and_add (x, ilist);
444738fd1498Szrj if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
444838fd1498Szrj {
444938fd1498Szrj tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
445038fd1498Szrj lower_omp (&tseq, ctx);
445138fd1498Szrj gimple_seq_add_seq (ilist, tseq);
445238fd1498Szrj }
445338fd1498Szrj OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
445438fd1498Szrj if (is_simd)
445538fd1498Szrj {
445638fd1498Szrj tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
445738fd1498Szrj lower_omp (&tseq, ctx);
445838fd1498Szrj gimple_seq_add_seq (dlist, tseq);
445938fd1498Szrj OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
446038fd1498Szrj }
446138fd1498Szrj DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
446238fd1498Szrj goto do_dtor;
446338fd1498Szrj }
446438fd1498Szrj else
446538fd1498Szrj {
446638fd1498Szrj x = omp_reduction_init (c, TREE_TYPE (new_var));
446738fd1498Szrj gcc_assert (TREE_CODE (TREE_TYPE (new_var)) != ARRAY_TYPE);
446838fd1498Szrj enum tree_code code = OMP_CLAUSE_REDUCTION_CODE (c);
446938fd1498Szrj
447038fd1498Szrj /* reduction(-:var) sums up the partial results, so it
447138fd1498Szrj acts identically to reduction(+:var). */
447238fd1498Szrj if (code == MINUS_EXPR)
447338fd1498Szrj code = PLUS_EXPR;
447438fd1498Szrj
447538fd1498Szrj tree new_vard = new_var;
447638fd1498Szrj if (is_simd && omp_is_reference (var))
447738fd1498Szrj {
447838fd1498Szrj gcc_assert (TREE_CODE (new_var) == MEM_REF);
447938fd1498Szrj new_vard = TREE_OPERAND (new_var, 0);
448038fd1498Szrj gcc_assert (DECL_P (new_vard));
448138fd1498Szrj }
448238fd1498Szrj if (is_simd
448338fd1498Szrj && lower_rec_simd_input_clauses (new_var, ctx, &sctx,
448438fd1498Szrj ivar, lvar))
448538fd1498Szrj {
448638fd1498Szrj tree ref = build_outer_var_ref (var, ctx);
448738fd1498Szrj
448838fd1498Szrj gimplify_assign (unshare_expr (ivar), x, &llist[0]);
448938fd1498Szrj
449038fd1498Szrj if (sctx.is_simt)
449138fd1498Szrj {
449238fd1498Szrj if (!simt_lane)
449338fd1498Szrj simt_lane = create_tmp_var (unsigned_type_node);
449438fd1498Szrj x = build_call_expr_internal_loc
449538fd1498Szrj (UNKNOWN_LOCATION, IFN_GOMP_SIMT_XCHG_BFLY,
449638fd1498Szrj TREE_TYPE (ivar), 2, ivar, simt_lane);
449738fd1498Szrj x = build2 (code, TREE_TYPE (ivar), ivar, x);
449838fd1498Szrj gimplify_assign (ivar, x, &llist[2]);
449938fd1498Szrj }
450038fd1498Szrj x = build2 (code, TREE_TYPE (ref), ref, ivar);
450138fd1498Szrj ref = build_outer_var_ref (var, ctx);
450238fd1498Szrj gimplify_assign (ref, x, &llist[1]);
450338fd1498Szrj
450438fd1498Szrj if (new_vard != new_var)
450538fd1498Szrj {
450638fd1498Szrj SET_DECL_VALUE_EXPR (new_vard,
450738fd1498Szrj build_fold_addr_expr (lvar));
450838fd1498Szrj DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
450938fd1498Szrj }
451038fd1498Szrj }
451138fd1498Szrj else
451238fd1498Szrj {
451338fd1498Szrj if (omp_is_reference (var) && is_simd)
451438fd1498Szrj handle_simd_reference (clause_loc, new_vard, ilist);
451538fd1498Szrj gimplify_assign (new_var, x, ilist);
451638fd1498Szrj if (is_simd)
451738fd1498Szrj {
451838fd1498Szrj tree ref = build_outer_var_ref (var, ctx);
451938fd1498Szrj
452038fd1498Szrj x = build2 (code, TREE_TYPE (ref), ref, new_var);
452138fd1498Szrj ref = build_outer_var_ref (var, ctx);
452238fd1498Szrj gimplify_assign (ref, x, dlist);
452338fd1498Szrj }
452438fd1498Szrj }
452538fd1498Szrj }
452638fd1498Szrj break;
452738fd1498Szrj
452838fd1498Szrj default:
452938fd1498Szrj gcc_unreachable ();
453038fd1498Szrj }
453138fd1498Szrj }
453238fd1498Szrj }
453338fd1498Szrj
453438fd1498Szrj if (known_eq (sctx.max_vf, 1U))
453538fd1498Szrj sctx.is_simt = false;
453638fd1498Szrj
453738fd1498Szrj if (sctx.lane || sctx.is_simt)
453838fd1498Szrj {
453938fd1498Szrj uid = create_tmp_var (ptr_type_node, "simduid");
454038fd1498Szrj /* Don't want uninit warnings on simduid, it is always uninitialized,
454138fd1498Szrj but we use it not for the value, but for the DECL_UID only. */
454238fd1498Szrj TREE_NO_WARNING (uid) = 1;
454338fd1498Szrj c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__SIMDUID_);
454438fd1498Szrj OMP_CLAUSE__SIMDUID__DECL (c) = uid;
454538fd1498Szrj OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
454638fd1498Szrj gimple_omp_for_set_clauses (ctx->stmt, c);
454738fd1498Szrj }
454838fd1498Szrj /* Emit calls denoting privatized variables and initializing a pointer to
454938fd1498Szrj structure that holds private variables as fields after ompdevlow pass. */
455038fd1498Szrj if (sctx.is_simt)
455138fd1498Szrj {
455238fd1498Szrj sctx.simt_eargs[0] = uid;
455338fd1498Szrj gimple *g
455438fd1498Szrj = gimple_build_call_internal_vec (IFN_GOMP_SIMT_ENTER, sctx.simt_eargs);
455538fd1498Szrj gimple_call_set_lhs (g, uid);
455638fd1498Szrj gimple_seq_add_stmt (ilist, g);
455738fd1498Szrj sctx.simt_eargs.release ();
455838fd1498Szrj
455938fd1498Szrj simtrec = create_tmp_var (ptr_type_node, ".omp_simt");
456038fd1498Szrj g = gimple_build_call_internal (IFN_GOMP_SIMT_ENTER_ALLOC, 1, uid);
456138fd1498Szrj gimple_call_set_lhs (g, simtrec);
456238fd1498Szrj gimple_seq_add_stmt (ilist, g);
456338fd1498Szrj }
456438fd1498Szrj if (sctx.lane)
456538fd1498Szrj {
456638fd1498Szrj gimple *g
456738fd1498Szrj = gimple_build_call_internal (IFN_GOMP_SIMD_LANE, 1, uid);
456838fd1498Szrj gimple_call_set_lhs (g, sctx.lane);
456938fd1498Szrj gimple_stmt_iterator gsi = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
457038fd1498Szrj gsi_insert_before_without_update (&gsi, g, GSI_SAME_STMT);
457138fd1498Szrj g = gimple_build_assign (sctx.lane, INTEGER_CST,
457238fd1498Szrj build_int_cst (unsigned_type_node, 0));
457338fd1498Szrj gimple_seq_add_stmt (ilist, g);
457438fd1498Szrj /* Emit reductions across SIMT lanes in log_2(simt_vf) steps. */
457538fd1498Szrj if (llist[2])
457638fd1498Szrj {
457738fd1498Szrj tree simt_vf = create_tmp_var (unsigned_type_node);
457838fd1498Szrj g = gimple_build_call_internal (IFN_GOMP_SIMT_VF, 0);
457938fd1498Szrj gimple_call_set_lhs (g, simt_vf);
458038fd1498Szrj gimple_seq_add_stmt (dlist, g);
458138fd1498Szrj
458238fd1498Szrj tree t = build_int_cst (unsigned_type_node, 1);
458338fd1498Szrj g = gimple_build_assign (simt_lane, INTEGER_CST, t);
458438fd1498Szrj gimple_seq_add_stmt (dlist, g);
458538fd1498Szrj
458638fd1498Szrj t = build_int_cst (unsigned_type_node, 0);
458738fd1498Szrj g = gimple_build_assign (sctx.idx, INTEGER_CST, t);
458838fd1498Szrj gimple_seq_add_stmt (dlist, g);
458938fd1498Szrj
459038fd1498Szrj tree body = create_artificial_label (UNKNOWN_LOCATION);
459138fd1498Szrj tree header = create_artificial_label (UNKNOWN_LOCATION);
459238fd1498Szrj tree end = create_artificial_label (UNKNOWN_LOCATION);
459338fd1498Szrj gimple_seq_add_stmt (dlist, gimple_build_goto (header));
459438fd1498Szrj gimple_seq_add_stmt (dlist, gimple_build_label (body));
459538fd1498Szrj
459638fd1498Szrj gimple_seq_add_seq (dlist, llist[2]);
459738fd1498Szrj
459838fd1498Szrj g = gimple_build_assign (simt_lane, LSHIFT_EXPR, simt_lane, integer_one_node);
459938fd1498Szrj gimple_seq_add_stmt (dlist, g);
460038fd1498Szrj
460138fd1498Szrj gimple_seq_add_stmt (dlist, gimple_build_label (header));
460238fd1498Szrj g = gimple_build_cond (LT_EXPR, simt_lane, simt_vf, body, end);
460338fd1498Szrj gimple_seq_add_stmt (dlist, g);
460438fd1498Szrj
460538fd1498Szrj gimple_seq_add_stmt (dlist, gimple_build_label (end));
460638fd1498Szrj }
460738fd1498Szrj for (int i = 0; i < 2; i++)
460838fd1498Szrj if (llist[i])
460938fd1498Szrj {
461038fd1498Szrj tree vf = create_tmp_var (unsigned_type_node);
461138fd1498Szrj g = gimple_build_call_internal (IFN_GOMP_SIMD_VF, 1, uid);
461238fd1498Szrj gimple_call_set_lhs (g, vf);
461338fd1498Szrj gimple_seq *seq = i == 0 ? ilist : dlist;
461438fd1498Szrj gimple_seq_add_stmt (seq, g);
461538fd1498Szrj tree t = build_int_cst (unsigned_type_node, 0);
461638fd1498Szrj g = gimple_build_assign (sctx.idx, INTEGER_CST, t);
461738fd1498Szrj gimple_seq_add_stmt (seq, g);
461838fd1498Szrj tree body = create_artificial_label (UNKNOWN_LOCATION);
461938fd1498Szrj tree header = create_artificial_label (UNKNOWN_LOCATION);
462038fd1498Szrj tree end = create_artificial_label (UNKNOWN_LOCATION);
462138fd1498Szrj gimple_seq_add_stmt (seq, gimple_build_goto (header));
462238fd1498Szrj gimple_seq_add_stmt (seq, gimple_build_label (body));
462338fd1498Szrj gimple_seq_add_seq (seq, llist[i]);
462438fd1498Szrj t = build_int_cst (unsigned_type_node, 1);
462538fd1498Szrj g = gimple_build_assign (sctx.idx, PLUS_EXPR, sctx.idx, t);
462638fd1498Szrj gimple_seq_add_stmt (seq, g);
462738fd1498Szrj gimple_seq_add_stmt (seq, gimple_build_label (header));
462838fd1498Szrj g = gimple_build_cond (LT_EXPR, sctx.idx, vf, body, end);
462938fd1498Szrj gimple_seq_add_stmt (seq, g);
463038fd1498Szrj gimple_seq_add_stmt (seq, gimple_build_label (end));
463138fd1498Szrj }
463238fd1498Szrj }
463338fd1498Szrj if (sctx.is_simt)
463438fd1498Szrj {
463538fd1498Szrj gimple_seq_add_seq (dlist, sctx.simt_dlist);
463638fd1498Szrj gimple *g
463738fd1498Szrj = gimple_build_call_internal (IFN_GOMP_SIMT_EXIT, 1, simtrec);
463838fd1498Szrj gimple_seq_add_stmt (dlist, g);
463938fd1498Szrj }
464038fd1498Szrj
464138fd1498Szrj /* The copyin sequence is not to be executed by the main thread, since
464238fd1498Szrj that would result in self-copies. Perhaps not visible to scalars,
464338fd1498Szrj but it certainly is to C++ operator=. */
464438fd1498Szrj if (copyin_seq)
464538fd1498Szrj {
464638fd1498Szrj x = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM),
464738fd1498Szrj 0);
464838fd1498Szrj x = build2 (NE_EXPR, boolean_type_node, x,
464938fd1498Szrj build_int_cst (TREE_TYPE (x), 0));
465038fd1498Szrj x = build3 (COND_EXPR, void_type_node, x, copyin_seq, NULL);
465138fd1498Szrj gimplify_and_add (x, ilist);
465238fd1498Szrj }
465338fd1498Szrj
465438fd1498Szrj /* If any copyin variable is passed by reference, we must ensure the
465538fd1498Szrj master thread doesn't modify it before it is copied over in all
465638fd1498Szrj threads. Similarly for variables in both firstprivate and
465738fd1498Szrj lastprivate clauses we need to ensure the lastprivate copying
465838fd1498Szrj happens after firstprivate copying in all threads. And similarly
465938fd1498Szrj for UDRs if initializer expression refers to omp_orig. */
466038fd1498Szrj if (copyin_by_ref || lastprivate_firstprivate || reduction_omp_orig_ref)
466138fd1498Szrj {
466238fd1498Szrj /* Don't add any barrier for #pragma omp simd or
466338fd1498Szrj #pragma omp distribute. */
466438fd1498Szrj if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
466538fd1498Szrj || gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_FOR)
466638fd1498Szrj gimple_seq_add_stmt (ilist, omp_build_barrier (NULL_TREE));
466738fd1498Szrj }
466838fd1498Szrj
466938fd1498Szrj /* If max_vf is non-zero, then we can use only a vectorization factor
467038fd1498Szrj up to the max_vf we chose. So stick it into the safelen clause. */
467138fd1498Szrj if (maybe_ne (sctx.max_vf, 0U))
467238fd1498Szrj {
467338fd1498Szrj tree c = omp_find_clause (gimple_omp_for_clauses (ctx->stmt),
467438fd1498Szrj OMP_CLAUSE_SAFELEN);
467538fd1498Szrj poly_uint64 safe_len;
467638fd1498Szrj if (c == NULL_TREE
467738fd1498Szrj || (poly_int_tree_p (OMP_CLAUSE_SAFELEN_EXPR (c), &safe_len)
467838fd1498Szrj && maybe_gt (safe_len, sctx.max_vf)))
467938fd1498Szrj {
468038fd1498Szrj c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_SAFELEN);
468138fd1498Szrj OMP_CLAUSE_SAFELEN_EXPR (c) = build_int_cst (integer_type_node,
468238fd1498Szrj sctx.max_vf);
468338fd1498Szrj OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
468438fd1498Szrj gimple_omp_for_set_clauses (ctx->stmt, c);
468538fd1498Szrj }
468638fd1498Szrj }
468738fd1498Szrj }
468838fd1498Szrj
468938fd1498Szrj
469038fd1498Szrj /* Generate code to implement the LASTPRIVATE clauses. This is used for
469138fd1498Szrj both parallel and workshare constructs. PREDICATE may be NULL if it's
469238fd1498Szrj always true. */
469338fd1498Szrj
469438fd1498Szrj static void
lower_lastprivate_clauses(tree clauses,tree predicate,gimple_seq * stmt_list,omp_context * ctx)469538fd1498Szrj lower_lastprivate_clauses (tree clauses, tree predicate, gimple_seq *stmt_list,
469638fd1498Szrj omp_context *ctx)
469738fd1498Szrj {
469838fd1498Szrj tree x, c, label = NULL, orig_clauses = clauses;
469938fd1498Szrj bool par_clauses = false;
470038fd1498Szrj tree simduid = NULL, lastlane = NULL, simtcond = NULL, simtlast = NULL;
470138fd1498Szrj
470238fd1498Szrj /* Early exit if there are no lastprivate or linear clauses. */
470338fd1498Szrj for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
470438fd1498Szrj if (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LASTPRIVATE
470538fd1498Szrj || (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LINEAR
470638fd1498Szrj && !OMP_CLAUSE_LINEAR_NO_COPYOUT (clauses)))
470738fd1498Szrj break;
470838fd1498Szrj if (clauses == NULL)
470938fd1498Szrj {
471038fd1498Szrj /* If this was a workshare clause, see if it had been combined
471138fd1498Szrj with its parallel. In that case, look for the clauses on the
471238fd1498Szrj parallel statement itself. */
471338fd1498Szrj if (is_parallel_ctx (ctx))
471438fd1498Szrj return;
471538fd1498Szrj
471638fd1498Szrj ctx = ctx->outer;
471738fd1498Szrj if (ctx == NULL || !is_parallel_ctx (ctx))
471838fd1498Szrj return;
471938fd1498Szrj
472038fd1498Szrj clauses = omp_find_clause (gimple_omp_parallel_clauses (ctx->stmt),
472138fd1498Szrj OMP_CLAUSE_LASTPRIVATE);
472238fd1498Szrj if (clauses == NULL)
472338fd1498Szrj return;
472438fd1498Szrj par_clauses = true;
472538fd1498Szrj }
472638fd1498Szrj
472738fd1498Szrj bool maybe_simt = false;
472838fd1498Szrj if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
472938fd1498Szrj && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
473038fd1498Szrj {
473138fd1498Szrj maybe_simt = omp_find_clause (orig_clauses, OMP_CLAUSE__SIMT_);
473238fd1498Szrj simduid = omp_find_clause (orig_clauses, OMP_CLAUSE__SIMDUID_);
473338fd1498Szrj if (simduid)
473438fd1498Szrj simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
473538fd1498Szrj }
473638fd1498Szrj
473738fd1498Szrj if (predicate)
473838fd1498Szrj {
473938fd1498Szrj gcond *stmt;
474038fd1498Szrj tree label_true, arm1, arm2;
474138fd1498Szrj enum tree_code pred_code = TREE_CODE (predicate);
474238fd1498Szrj
474338fd1498Szrj label = create_artificial_label (UNKNOWN_LOCATION);
474438fd1498Szrj label_true = create_artificial_label (UNKNOWN_LOCATION);
474538fd1498Szrj if (TREE_CODE_CLASS (pred_code) == tcc_comparison)
474638fd1498Szrj {
474738fd1498Szrj arm1 = TREE_OPERAND (predicate, 0);
474838fd1498Szrj arm2 = TREE_OPERAND (predicate, 1);
474938fd1498Szrj gimplify_expr (&arm1, stmt_list, NULL, is_gimple_val, fb_rvalue);
475038fd1498Szrj gimplify_expr (&arm2, stmt_list, NULL, is_gimple_val, fb_rvalue);
475138fd1498Szrj }
475238fd1498Szrj else
475338fd1498Szrj {
475438fd1498Szrj arm1 = predicate;
475538fd1498Szrj gimplify_expr (&arm1, stmt_list, NULL, is_gimple_val, fb_rvalue);
475638fd1498Szrj arm2 = boolean_false_node;
475738fd1498Szrj pred_code = NE_EXPR;
475838fd1498Szrj }
475938fd1498Szrj if (maybe_simt)
476038fd1498Szrj {
476138fd1498Szrj c = build2 (pred_code, boolean_type_node, arm1, arm2);
476238fd1498Szrj c = fold_convert (integer_type_node, c);
476338fd1498Szrj simtcond = create_tmp_var (integer_type_node);
476438fd1498Szrj gimplify_assign (simtcond, c, stmt_list);
476538fd1498Szrj gcall *g = gimple_build_call_internal (IFN_GOMP_SIMT_VOTE_ANY,
476638fd1498Szrj 1, simtcond);
476738fd1498Szrj c = create_tmp_var (integer_type_node);
476838fd1498Szrj gimple_call_set_lhs (g, c);
476938fd1498Szrj gimple_seq_add_stmt (stmt_list, g);
477038fd1498Szrj stmt = gimple_build_cond (NE_EXPR, c, integer_zero_node,
477138fd1498Szrj label_true, label);
477238fd1498Szrj }
477338fd1498Szrj else
477438fd1498Szrj stmt = gimple_build_cond (pred_code, arm1, arm2, label_true, label);
477538fd1498Szrj gimple_seq_add_stmt (stmt_list, stmt);
477638fd1498Szrj gimple_seq_add_stmt (stmt_list, gimple_build_label (label_true));
477738fd1498Szrj }
477838fd1498Szrj
477938fd1498Szrj for (c = clauses; c ;)
478038fd1498Szrj {
478138fd1498Szrj tree var, new_var;
478238fd1498Szrj location_t clause_loc = OMP_CLAUSE_LOCATION (c);
478338fd1498Szrj
478438fd1498Szrj if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
478538fd1498Szrj || (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
478638fd1498Szrj && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c)))
478738fd1498Szrj {
478838fd1498Szrj var = OMP_CLAUSE_DECL (c);
478938fd1498Szrj if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
479038fd1498Szrj && OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c)
479138fd1498Szrj && is_taskloop_ctx (ctx))
479238fd1498Szrj {
479338fd1498Szrj gcc_checking_assert (ctx->outer && is_task_ctx (ctx->outer));
479438fd1498Szrj new_var = lookup_decl (var, ctx->outer);
479538fd1498Szrj }
479638fd1498Szrj else
479738fd1498Szrj {
479838fd1498Szrj new_var = lookup_decl (var, ctx);
479938fd1498Szrj /* Avoid uninitialized warnings for lastprivate and
480038fd1498Szrj for linear iterators. */
480138fd1498Szrj if (predicate
480238fd1498Szrj && (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
480338fd1498Szrj || OMP_CLAUSE_LINEAR_NO_COPYIN (c)))
480438fd1498Szrj TREE_NO_WARNING (new_var) = 1;
480538fd1498Szrj }
480638fd1498Szrj
480738fd1498Szrj if (!maybe_simt && simduid && DECL_HAS_VALUE_EXPR_P (new_var))
480838fd1498Szrj {
480938fd1498Szrj tree val = DECL_VALUE_EXPR (new_var);
481038fd1498Szrj if (TREE_CODE (val) == ARRAY_REF
481138fd1498Szrj && VAR_P (TREE_OPERAND (val, 0))
481238fd1498Szrj && lookup_attribute ("omp simd array",
481338fd1498Szrj DECL_ATTRIBUTES (TREE_OPERAND (val,
481438fd1498Szrj 0))))
481538fd1498Szrj {
481638fd1498Szrj if (lastlane == NULL)
481738fd1498Szrj {
481838fd1498Szrj lastlane = create_tmp_var (unsigned_type_node);
481938fd1498Szrj gcall *g
482038fd1498Szrj = gimple_build_call_internal (IFN_GOMP_SIMD_LAST_LANE,
482138fd1498Szrj 2, simduid,
482238fd1498Szrj TREE_OPERAND (val, 1));
482338fd1498Szrj gimple_call_set_lhs (g, lastlane);
482438fd1498Szrj gimple_seq_add_stmt (stmt_list, g);
482538fd1498Szrj }
482638fd1498Szrj new_var = build4 (ARRAY_REF, TREE_TYPE (val),
482738fd1498Szrj TREE_OPERAND (val, 0), lastlane,
482838fd1498Szrj NULL_TREE, NULL_TREE);
482938fd1498Szrj }
483038fd1498Szrj }
483138fd1498Szrj else if (maybe_simt)
483238fd1498Szrj {
483338fd1498Szrj tree val = (DECL_HAS_VALUE_EXPR_P (new_var)
483438fd1498Szrj ? DECL_VALUE_EXPR (new_var)
483538fd1498Szrj : new_var);
483638fd1498Szrj if (simtlast == NULL)
483738fd1498Szrj {
483838fd1498Szrj simtlast = create_tmp_var (unsigned_type_node);
483938fd1498Szrj gcall *g = gimple_build_call_internal
484038fd1498Szrj (IFN_GOMP_SIMT_LAST_LANE, 1, simtcond);
484138fd1498Szrj gimple_call_set_lhs (g, simtlast);
484238fd1498Szrj gimple_seq_add_stmt (stmt_list, g);
484338fd1498Szrj }
484438fd1498Szrj x = build_call_expr_internal_loc
484538fd1498Szrj (UNKNOWN_LOCATION, IFN_GOMP_SIMT_XCHG_IDX,
484638fd1498Szrj TREE_TYPE (val), 2, val, simtlast);
484738fd1498Szrj new_var = unshare_expr (new_var);
484838fd1498Szrj gimplify_assign (new_var, x, stmt_list);
484938fd1498Szrj new_var = unshare_expr (new_var);
485038fd1498Szrj }
485138fd1498Szrj
485238fd1498Szrj if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
485338fd1498Szrj && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
485438fd1498Szrj {
485538fd1498Szrj lower_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
485638fd1498Szrj gimple_seq_add_seq (stmt_list,
485738fd1498Szrj OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c));
485838fd1498Szrj OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c) = NULL;
485938fd1498Szrj }
486038fd1498Szrj else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
486138fd1498Szrj && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
486238fd1498Szrj {
486338fd1498Szrj lower_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
486438fd1498Szrj gimple_seq_add_seq (stmt_list,
486538fd1498Szrj OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c));
486638fd1498Szrj OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c) = NULL;
486738fd1498Szrj }
486838fd1498Szrj
486938fd1498Szrj x = NULL_TREE;
487038fd1498Szrj if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
487138fd1498Szrj && OMP_CLAUSE_LASTPRIVATE_TASKLOOP_IV (c))
487238fd1498Szrj {
487338fd1498Szrj gcc_checking_assert (is_taskloop_ctx (ctx));
487438fd1498Szrj tree ovar = maybe_lookup_decl_in_outer_ctx (var,
487538fd1498Szrj ctx->outer->outer);
487638fd1498Szrj if (is_global_var (ovar))
487738fd1498Szrj x = ovar;
487838fd1498Szrj }
487938fd1498Szrj if (!x)
488038fd1498Szrj x = build_outer_var_ref (var, ctx, OMP_CLAUSE_LASTPRIVATE);
488138fd1498Szrj if (omp_is_reference (var))
488238fd1498Szrj new_var = build_simple_mem_ref_loc (clause_loc, new_var);
488338fd1498Szrj x = lang_hooks.decls.omp_clause_assign_op (c, x, new_var);
488438fd1498Szrj gimplify_and_add (x, stmt_list);
488538fd1498Szrj }
488638fd1498Szrj c = OMP_CLAUSE_CHAIN (c);
488738fd1498Szrj if (c == NULL && !par_clauses)
488838fd1498Szrj {
488938fd1498Szrj /* If this was a workshare clause, see if it had been combined
489038fd1498Szrj with its parallel. In that case, continue looking for the
489138fd1498Szrj clauses also on the parallel statement itself. */
489238fd1498Szrj if (is_parallel_ctx (ctx))
489338fd1498Szrj break;
489438fd1498Szrj
489538fd1498Szrj ctx = ctx->outer;
489638fd1498Szrj if (ctx == NULL || !is_parallel_ctx (ctx))
489738fd1498Szrj break;
489838fd1498Szrj
489938fd1498Szrj c = omp_find_clause (gimple_omp_parallel_clauses (ctx->stmt),
490038fd1498Szrj OMP_CLAUSE_LASTPRIVATE);
490138fd1498Szrj par_clauses = true;
490238fd1498Szrj }
490338fd1498Szrj }
490438fd1498Szrj
490538fd1498Szrj if (label)
490638fd1498Szrj gimple_seq_add_stmt (stmt_list, gimple_build_label (label));
490738fd1498Szrj }
490838fd1498Szrj
490938fd1498Szrj /* Lower the OpenACC reductions of CLAUSES for compute axis LEVEL
491038fd1498Szrj (which might be a placeholder). INNER is true if this is an inner
491138fd1498Szrj axis of a multi-axis loop. FORK and JOIN are (optional) fork and
491238fd1498Szrj join markers. Generate the before-loop forking sequence in
491338fd1498Szrj FORK_SEQ and the after-loop joining sequence to JOIN_SEQ. The
491438fd1498Szrj general form of these sequences is
491538fd1498Szrj
491638fd1498Szrj GOACC_REDUCTION_SETUP
491738fd1498Szrj GOACC_FORK
491838fd1498Szrj GOACC_REDUCTION_INIT
491938fd1498Szrj ...
492038fd1498Szrj GOACC_REDUCTION_FINI
492138fd1498Szrj GOACC_JOIN
492238fd1498Szrj GOACC_REDUCTION_TEARDOWN. */
492338fd1498Szrj
492438fd1498Szrj static void
lower_oacc_reductions(location_t loc,tree clauses,tree level,bool inner,gcall * fork,gcall * join,gimple_seq * fork_seq,gimple_seq * join_seq,omp_context * ctx)492538fd1498Szrj lower_oacc_reductions (location_t loc, tree clauses, tree level, bool inner,
492638fd1498Szrj gcall *fork, gcall *join, gimple_seq *fork_seq,
492738fd1498Szrj gimple_seq *join_seq, omp_context *ctx)
492838fd1498Szrj {
492938fd1498Szrj gimple_seq before_fork = NULL;
493038fd1498Szrj gimple_seq after_fork = NULL;
493138fd1498Szrj gimple_seq before_join = NULL;
493238fd1498Szrj gimple_seq after_join = NULL;
493338fd1498Szrj tree init_code = NULL_TREE, fini_code = NULL_TREE,
493438fd1498Szrj setup_code = NULL_TREE, teardown_code = NULL_TREE;
493538fd1498Szrj unsigned offset = 0;
493638fd1498Szrj
493738fd1498Szrj for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
493838fd1498Szrj if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
493938fd1498Szrj {
494038fd1498Szrj tree orig = OMP_CLAUSE_DECL (c);
494138fd1498Szrj tree var = maybe_lookup_decl (orig, ctx);
494238fd1498Szrj tree ref_to_res = NULL_TREE;
494338fd1498Szrj tree incoming, outgoing, v1, v2, v3;
494438fd1498Szrj bool is_private = false;
494538fd1498Szrj
494638fd1498Szrj enum tree_code rcode = OMP_CLAUSE_REDUCTION_CODE (c);
494738fd1498Szrj if (rcode == MINUS_EXPR)
494838fd1498Szrj rcode = PLUS_EXPR;
494938fd1498Szrj else if (rcode == TRUTH_ANDIF_EXPR)
495038fd1498Szrj rcode = BIT_AND_EXPR;
495138fd1498Szrj else if (rcode == TRUTH_ORIF_EXPR)
495238fd1498Szrj rcode = BIT_IOR_EXPR;
495338fd1498Szrj tree op = build_int_cst (unsigned_type_node, rcode);
495438fd1498Szrj
495538fd1498Szrj if (!var)
495638fd1498Szrj var = orig;
495738fd1498Szrj
495838fd1498Szrj incoming = outgoing = var;
495938fd1498Szrj
496038fd1498Szrj if (!inner)
496138fd1498Szrj {
496238fd1498Szrj /* See if an outer construct also reduces this variable. */
496338fd1498Szrj omp_context *outer = ctx;
496438fd1498Szrj
496538fd1498Szrj while (omp_context *probe = outer->outer)
496638fd1498Szrj {
496738fd1498Szrj enum gimple_code type = gimple_code (probe->stmt);
496838fd1498Szrj tree cls;
496938fd1498Szrj
497038fd1498Szrj switch (type)
497138fd1498Szrj {
497238fd1498Szrj case GIMPLE_OMP_FOR:
497338fd1498Szrj cls = gimple_omp_for_clauses (probe->stmt);
497438fd1498Szrj break;
497538fd1498Szrj
497638fd1498Szrj case GIMPLE_OMP_TARGET:
497738fd1498Szrj if (gimple_omp_target_kind (probe->stmt)
497838fd1498Szrj != GF_OMP_TARGET_KIND_OACC_PARALLEL)
497938fd1498Szrj goto do_lookup;
498038fd1498Szrj
498138fd1498Szrj cls = gimple_omp_target_clauses (probe->stmt);
498238fd1498Szrj break;
498338fd1498Szrj
498438fd1498Szrj default:
498538fd1498Szrj goto do_lookup;
498638fd1498Szrj }
498738fd1498Szrj
498838fd1498Szrj outer = probe;
498938fd1498Szrj for (; cls; cls = OMP_CLAUSE_CHAIN (cls))
499038fd1498Szrj if (OMP_CLAUSE_CODE (cls) == OMP_CLAUSE_REDUCTION
499138fd1498Szrj && orig == OMP_CLAUSE_DECL (cls))
499238fd1498Szrj {
499338fd1498Szrj incoming = outgoing = lookup_decl (orig, probe);
499438fd1498Szrj goto has_outer_reduction;
499538fd1498Szrj }
499638fd1498Szrj else if ((OMP_CLAUSE_CODE (cls) == OMP_CLAUSE_FIRSTPRIVATE
499738fd1498Szrj || OMP_CLAUSE_CODE (cls) == OMP_CLAUSE_PRIVATE)
499838fd1498Szrj && orig == OMP_CLAUSE_DECL (cls))
499938fd1498Szrj {
500038fd1498Szrj is_private = true;
500138fd1498Szrj goto do_lookup;
500238fd1498Szrj }
500338fd1498Szrj }
500438fd1498Szrj
500538fd1498Szrj do_lookup:
500638fd1498Szrj /* This is the outermost construct with this reduction,
500738fd1498Szrj see if there's a mapping for it. */
500838fd1498Szrj if (gimple_code (outer->stmt) == GIMPLE_OMP_TARGET
500938fd1498Szrj && maybe_lookup_field (orig, outer) && !is_private)
501038fd1498Szrj {
501138fd1498Szrj ref_to_res = build_receiver_ref (orig, false, outer);
501238fd1498Szrj if (omp_is_reference (orig))
501338fd1498Szrj ref_to_res = build_simple_mem_ref (ref_to_res);
501438fd1498Szrj
501538fd1498Szrj tree type = TREE_TYPE (var);
501638fd1498Szrj if (POINTER_TYPE_P (type))
501738fd1498Szrj type = TREE_TYPE (type);
501838fd1498Szrj
501938fd1498Szrj outgoing = var;
502038fd1498Szrj incoming = omp_reduction_init_op (loc, rcode, type);
502138fd1498Szrj }
502238fd1498Szrj else
502338fd1498Szrj {
502438fd1498Szrj /* Try to look at enclosing contexts for reduction var,
502538fd1498Szrj use original if no mapping found. */
502638fd1498Szrj tree t = NULL_TREE;
502738fd1498Szrj omp_context *c = ctx->outer;
502838fd1498Szrj while (c && !t)
502938fd1498Szrj {
503038fd1498Szrj t = maybe_lookup_decl (orig, c);
503138fd1498Szrj c = c->outer;
503238fd1498Szrj }
503338fd1498Szrj incoming = outgoing = (t ? t : orig);
503438fd1498Szrj }
503538fd1498Szrj
503638fd1498Szrj has_outer_reduction:;
503738fd1498Szrj }
503838fd1498Szrj
503938fd1498Szrj if (!ref_to_res)
504038fd1498Szrj ref_to_res = integer_zero_node;
504138fd1498Szrj
504238fd1498Szrj if (omp_is_reference (orig))
504338fd1498Szrj {
504438fd1498Szrj tree type = TREE_TYPE (var);
504538fd1498Szrj const char *id = IDENTIFIER_POINTER (DECL_NAME (var));
504638fd1498Szrj
504738fd1498Szrj if (!inner)
504838fd1498Szrj {
504938fd1498Szrj tree x = create_tmp_var (TREE_TYPE (type), id);
505038fd1498Szrj gimplify_assign (var, build_fold_addr_expr (x), fork_seq);
505138fd1498Szrj }
505238fd1498Szrj
505338fd1498Szrj v1 = create_tmp_var (type, id);
505438fd1498Szrj v2 = create_tmp_var (type, id);
505538fd1498Szrj v3 = create_tmp_var (type, id);
505638fd1498Szrj
505738fd1498Szrj gimplify_assign (v1, var, fork_seq);
505838fd1498Szrj gimplify_assign (v2, var, fork_seq);
505938fd1498Szrj gimplify_assign (v3, var, fork_seq);
506038fd1498Szrj
506138fd1498Szrj var = build_simple_mem_ref (var);
506238fd1498Szrj v1 = build_simple_mem_ref (v1);
506338fd1498Szrj v2 = build_simple_mem_ref (v2);
506438fd1498Szrj v3 = build_simple_mem_ref (v3);
506538fd1498Szrj outgoing = build_simple_mem_ref (outgoing);
506638fd1498Szrj
506738fd1498Szrj if (!TREE_CONSTANT (incoming))
506838fd1498Szrj incoming = build_simple_mem_ref (incoming);
506938fd1498Szrj }
507038fd1498Szrj else
507138fd1498Szrj v1 = v2 = v3 = var;
507238fd1498Szrj
507338fd1498Szrj /* Determine position in reduction buffer, which may be used
507438fd1498Szrj by target. The parser has ensured that this is not a
507538fd1498Szrj variable-sized type. */
507638fd1498Szrj fixed_size_mode mode
507738fd1498Szrj = as_a <fixed_size_mode> (TYPE_MODE (TREE_TYPE (var)));
507838fd1498Szrj unsigned align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
507938fd1498Szrj offset = (offset + align - 1) & ~(align - 1);
508038fd1498Szrj tree off = build_int_cst (sizetype, offset);
508138fd1498Szrj offset += GET_MODE_SIZE (mode);
508238fd1498Szrj
508338fd1498Szrj if (!init_code)
508438fd1498Szrj {
508538fd1498Szrj init_code = build_int_cst (integer_type_node,
508638fd1498Szrj IFN_GOACC_REDUCTION_INIT);
508738fd1498Szrj fini_code = build_int_cst (integer_type_node,
508838fd1498Szrj IFN_GOACC_REDUCTION_FINI);
508938fd1498Szrj setup_code = build_int_cst (integer_type_node,
509038fd1498Szrj IFN_GOACC_REDUCTION_SETUP);
509138fd1498Szrj teardown_code = build_int_cst (integer_type_node,
509238fd1498Szrj IFN_GOACC_REDUCTION_TEARDOWN);
509338fd1498Szrj }
509438fd1498Szrj
509538fd1498Szrj tree setup_call
509638fd1498Szrj = build_call_expr_internal_loc (loc, IFN_GOACC_REDUCTION,
509738fd1498Szrj TREE_TYPE (var), 6, setup_code,
509838fd1498Szrj unshare_expr (ref_to_res),
509938fd1498Szrj incoming, level, op, off);
510038fd1498Szrj tree init_call
510138fd1498Szrj = build_call_expr_internal_loc (loc, IFN_GOACC_REDUCTION,
510238fd1498Szrj TREE_TYPE (var), 6, init_code,
510338fd1498Szrj unshare_expr (ref_to_res),
510438fd1498Szrj v1, level, op, off);
510538fd1498Szrj tree fini_call
510638fd1498Szrj = build_call_expr_internal_loc (loc, IFN_GOACC_REDUCTION,
510738fd1498Szrj TREE_TYPE (var), 6, fini_code,
510838fd1498Szrj unshare_expr (ref_to_res),
510938fd1498Szrj v2, level, op, off);
511038fd1498Szrj tree teardown_call
511138fd1498Szrj = build_call_expr_internal_loc (loc, IFN_GOACC_REDUCTION,
511238fd1498Szrj TREE_TYPE (var), 6, teardown_code,
511338fd1498Szrj ref_to_res, v3, level, op, off);
511438fd1498Szrj
511538fd1498Szrj gimplify_assign (v1, setup_call, &before_fork);
511638fd1498Szrj gimplify_assign (v2, init_call, &after_fork);
511738fd1498Szrj gimplify_assign (v3, fini_call, &before_join);
511838fd1498Szrj gimplify_assign (outgoing, teardown_call, &after_join);
511938fd1498Szrj }
512038fd1498Szrj
512138fd1498Szrj /* Now stitch things together. */
512238fd1498Szrj gimple_seq_add_seq (fork_seq, before_fork);
512338fd1498Szrj if (fork)
512438fd1498Szrj gimple_seq_add_stmt (fork_seq, fork);
512538fd1498Szrj gimple_seq_add_seq (fork_seq, after_fork);
512638fd1498Szrj
512738fd1498Szrj gimple_seq_add_seq (join_seq, before_join);
512838fd1498Szrj if (join)
512938fd1498Szrj gimple_seq_add_stmt (join_seq, join);
513038fd1498Szrj gimple_seq_add_seq (join_seq, after_join);
513138fd1498Szrj }
513238fd1498Szrj
513338fd1498Szrj /* Generate code to implement the REDUCTION clauses. */
513438fd1498Szrj
513538fd1498Szrj static void
lower_reduction_clauses(tree clauses,gimple_seq * stmt_seqp,omp_context * ctx)513638fd1498Szrj lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp, omp_context *ctx)
513738fd1498Szrj {
513838fd1498Szrj gimple_seq sub_seq = NULL;
513938fd1498Szrj gimple *stmt;
514038fd1498Szrj tree x, c;
514138fd1498Szrj int count = 0;
514238fd1498Szrj
514338fd1498Szrj /* OpenACC loop reductions are handled elsewhere. */
514438fd1498Szrj if (is_gimple_omp_oacc (ctx->stmt))
514538fd1498Szrj return;
514638fd1498Szrj
514738fd1498Szrj /* SIMD reductions are handled in lower_rec_input_clauses. */
514838fd1498Szrj if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
514938fd1498Szrj && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
515038fd1498Szrj return;
515138fd1498Szrj
515238fd1498Szrj /* First see if there is exactly one reduction clause. Use OMP_ATOMIC
515338fd1498Szrj update in that case, otherwise use a lock. */
515438fd1498Szrj for (c = clauses; c && count < 2; c = OMP_CLAUSE_CHAIN (c))
515538fd1498Szrj if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
515638fd1498Szrj {
515738fd1498Szrj if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)
515838fd1498Szrj || TREE_CODE (OMP_CLAUSE_DECL (c)) == MEM_REF)
515938fd1498Szrj {
516038fd1498Szrj /* Never use OMP_ATOMIC for array reductions or UDRs. */
516138fd1498Szrj count = -1;
516238fd1498Szrj break;
516338fd1498Szrj }
516438fd1498Szrj count++;
516538fd1498Szrj }
516638fd1498Szrj
516738fd1498Szrj if (count == 0)
516838fd1498Szrj return;
516938fd1498Szrj
517038fd1498Szrj for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
517138fd1498Szrj {
517238fd1498Szrj tree var, ref, new_var, orig_var;
517338fd1498Szrj enum tree_code code;
517438fd1498Szrj location_t clause_loc = OMP_CLAUSE_LOCATION (c);
517538fd1498Szrj
517638fd1498Szrj if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
517738fd1498Szrj continue;
517838fd1498Szrj
517938fd1498Szrj enum omp_clause_code ccode = OMP_CLAUSE_REDUCTION;
518038fd1498Szrj orig_var = var = OMP_CLAUSE_DECL (c);
518138fd1498Szrj if (TREE_CODE (var) == MEM_REF)
518238fd1498Szrj {
518338fd1498Szrj var = TREE_OPERAND (var, 0);
518438fd1498Szrj if (TREE_CODE (var) == POINTER_PLUS_EXPR)
518538fd1498Szrj var = TREE_OPERAND (var, 0);
518638fd1498Szrj if (TREE_CODE (var) == ADDR_EXPR)
518738fd1498Szrj var = TREE_OPERAND (var, 0);
518838fd1498Szrj else
518938fd1498Szrj {
519038fd1498Szrj /* If this is a pointer or referenced based array
519138fd1498Szrj section, the var could be private in the outer
519238fd1498Szrj context e.g. on orphaned loop construct. Pretend this
519338fd1498Szrj is private variable's outer reference. */
519438fd1498Szrj ccode = OMP_CLAUSE_PRIVATE;
519538fd1498Szrj if (TREE_CODE (var) == INDIRECT_REF)
519638fd1498Szrj var = TREE_OPERAND (var, 0);
519738fd1498Szrj }
519838fd1498Szrj orig_var = var;
519938fd1498Szrj if (is_variable_sized (var))
520038fd1498Szrj {
520138fd1498Szrj gcc_assert (DECL_HAS_VALUE_EXPR_P (var));
520238fd1498Szrj var = DECL_VALUE_EXPR (var);
520338fd1498Szrj gcc_assert (TREE_CODE (var) == INDIRECT_REF);
520438fd1498Szrj var = TREE_OPERAND (var, 0);
520538fd1498Szrj gcc_assert (DECL_P (var));
520638fd1498Szrj }
520738fd1498Szrj }
520838fd1498Szrj new_var = lookup_decl (var, ctx);
520938fd1498Szrj if (var == OMP_CLAUSE_DECL (c) && omp_is_reference (var))
521038fd1498Szrj new_var = build_simple_mem_ref_loc (clause_loc, new_var);
521138fd1498Szrj ref = build_outer_var_ref (var, ctx, ccode);
521238fd1498Szrj code = OMP_CLAUSE_REDUCTION_CODE (c);
521338fd1498Szrj
521438fd1498Szrj /* reduction(-:var) sums up the partial results, so it acts
521538fd1498Szrj identically to reduction(+:var). */
521638fd1498Szrj if (code == MINUS_EXPR)
521738fd1498Szrj code = PLUS_EXPR;
521838fd1498Szrj
521938fd1498Szrj if (count == 1)
522038fd1498Szrj {
522138fd1498Szrj tree addr = build_fold_addr_expr_loc (clause_loc, ref);
522238fd1498Szrj
522338fd1498Szrj addr = save_expr (addr);
522438fd1498Szrj ref = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (addr)), addr);
522538fd1498Szrj x = fold_build2_loc (clause_loc, code, TREE_TYPE (ref), ref, new_var);
522638fd1498Szrj x = build2 (OMP_ATOMIC, void_type_node, addr, x);
522738fd1498Szrj gimplify_and_add (x, stmt_seqp);
522838fd1498Szrj return;
522938fd1498Szrj }
523038fd1498Szrj else if (TREE_CODE (OMP_CLAUSE_DECL (c)) == MEM_REF)
523138fd1498Szrj {
523238fd1498Szrj tree d = OMP_CLAUSE_DECL (c);
523338fd1498Szrj tree type = TREE_TYPE (d);
523438fd1498Szrj tree v = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
523538fd1498Szrj tree i = create_tmp_var (TREE_TYPE (v), NULL);
523638fd1498Szrj tree ptype = build_pointer_type (TREE_TYPE (type));
523738fd1498Szrj tree bias = TREE_OPERAND (d, 1);
523838fd1498Szrj d = TREE_OPERAND (d, 0);
523938fd1498Szrj if (TREE_CODE (d) == POINTER_PLUS_EXPR)
524038fd1498Szrj {
524138fd1498Szrj tree b = TREE_OPERAND (d, 1);
524238fd1498Szrj b = maybe_lookup_decl (b, ctx);
524338fd1498Szrj if (b == NULL)
524438fd1498Szrj {
524538fd1498Szrj b = TREE_OPERAND (d, 1);
524638fd1498Szrj b = maybe_lookup_decl_in_outer_ctx (b, ctx);
524738fd1498Szrj }
524838fd1498Szrj if (integer_zerop (bias))
524938fd1498Szrj bias = b;
525038fd1498Szrj else
525138fd1498Szrj {
525238fd1498Szrj bias = fold_convert_loc (clause_loc, TREE_TYPE (b), bias);
525338fd1498Szrj bias = fold_build2_loc (clause_loc, PLUS_EXPR,
525438fd1498Szrj TREE_TYPE (b), b, bias);
525538fd1498Szrj }
525638fd1498Szrj d = TREE_OPERAND (d, 0);
525738fd1498Szrj }
525838fd1498Szrj /* For ref build_outer_var_ref already performs this, so
525938fd1498Szrj only new_var needs a dereference. */
526038fd1498Szrj if (TREE_CODE (d) == INDIRECT_REF)
526138fd1498Szrj {
526238fd1498Szrj new_var = build_simple_mem_ref_loc (clause_loc, new_var);
526338fd1498Szrj gcc_assert (omp_is_reference (var) && var == orig_var);
526438fd1498Szrj }
526538fd1498Szrj else if (TREE_CODE (d) == ADDR_EXPR)
526638fd1498Szrj {
526738fd1498Szrj if (orig_var == var)
526838fd1498Szrj {
526938fd1498Szrj new_var = build_fold_addr_expr (new_var);
527038fd1498Szrj ref = build_fold_addr_expr (ref);
527138fd1498Szrj }
527238fd1498Szrj }
527338fd1498Szrj else
527438fd1498Szrj {
527538fd1498Szrj gcc_assert (orig_var == var);
527638fd1498Szrj if (omp_is_reference (var))
527738fd1498Szrj ref = build_fold_addr_expr (ref);
527838fd1498Szrj }
527938fd1498Szrj if (DECL_P (v))
528038fd1498Szrj {
528138fd1498Szrj tree t = maybe_lookup_decl (v, ctx);
528238fd1498Szrj if (t)
528338fd1498Szrj v = t;
528438fd1498Szrj else
528538fd1498Szrj v = maybe_lookup_decl_in_outer_ctx (v, ctx);
528638fd1498Szrj gimplify_expr (&v, stmt_seqp, NULL, is_gimple_val, fb_rvalue);
528738fd1498Szrj }
528838fd1498Szrj if (!integer_zerop (bias))
528938fd1498Szrj {
529038fd1498Szrj bias = fold_convert_loc (clause_loc, sizetype, bias);
529138fd1498Szrj new_var = fold_build2_loc (clause_loc, POINTER_PLUS_EXPR,
529238fd1498Szrj TREE_TYPE (new_var), new_var,
529338fd1498Szrj unshare_expr (bias));
529438fd1498Szrj ref = fold_build2_loc (clause_loc, POINTER_PLUS_EXPR,
529538fd1498Szrj TREE_TYPE (ref), ref, bias);
529638fd1498Szrj }
529738fd1498Szrj new_var = fold_convert_loc (clause_loc, ptype, new_var);
529838fd1498Szrj ref = fold_convert_loc (clause_loc, ptype, ref);
529938fd1498Szrj tree m = create_tmp_var (ptype, NULL);
530038fd1498Szrj gimplify_assign (m, new_var, stmt_seqp);
530138fd1498Szrj new_var = m;
530238fd1498Szrj m = create_tmp_var (ptype, NULL);
530338fd1498Szrj gimplify_assign (m, ref, stmt_seqp);
530438fd1498Szrj ref = m;
530538fd1498Szrj gimplify_assign (i, build_int_cst (TREE_TYPE (v), 0), stmt_seqp);
530638fd1498Szrj tree body = create_artificial_label (UNKNOWN_LOCATION);
530738fd1498Szrj tree end = create_artificial_label (UNKNOWN_LOCATION);
530838fd1498Szrj gimple_seq_add_stmt (&sub_seq, gimple_build_label (body));
530938fd1498Szrj tree priv = build_simple_mem_ref_loc (clause_loc, new_var);
531038fd1498Szrj tree out = build_simple_mem_ref_loc (clause_loc, ref);
531138fd1498Szrj if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
531238fd1498Szrj {
531338fd1498Szrj tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
531438fd1498Szrj tree decl_placeholder
531538fd1498Szrj = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c);
531638fd1498Szrj SET_DECL_VALUE_EXPR (placeholder, out);
531738fd1498Szrj DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
531838fd1498Szrj SET_DECL_VALUE_EXPR (decl_placeholder, priv);
531938fd1498Szrj DECL_HAS_VALUE_EXPR_P (decl_placeholder) = 1;
532038fd1498Szrj lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
532138fd1498Szrj gimple_seq_add_seq (&sub_seq,
532238fd1498Szrj OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
532338fd1498Szrj OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
532438fd1498Szrj OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
532538fd1498Szrj OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c) = NULL;
532638fd1498Szrj }
532738fd1498Szrj else
532838fd1498Szrj {
532938fd1498Szrj x = build2 (code, TREE_TYPE (out), out, priv);
533038fd1498Szrj out = unshare_expr (out);
533138fd1498Szrj gimplify_assign (out, x, &sub_seq);
533238fd1498Szrj }
533338fd1498Szrj gimple *g = gimple_build_assign (new_var, POINTER_PLUS_EXPR, new_var,
533438fd1498Szrj TYPE_SIZE_UNIT (TREE_TYPE (type)));
533538fd1498Szrj gimple_seq_add_stmt (&sub_seq, g);
533638fd1498Szrj g = gimple_build_assign (ref, POINTER_PLUS_EXPR, ref,
533738fd1498Szrj TYPE_SIZE_UNIT (TREE_TYPE (type)));
533838fd1498Szrj gimple_seq_add_stmt (&sub_seq, g);
533938fd1498Szrj g = gimple_build_assign (i, PLUS_EXPR, i,
534038fd1498Szrj build_int_cst (TREE_TYPE (i), 1));
534138fd1498Szrj gimple_seq_add_stmt (&sub_seq, g);
534238fd1498Szrj g = gimple_build_cond (LE_EXPR, i, v, body, end);
534338fd1498Szrj gimple_seq_add_stmt (&sub_seq, g);
534438fd1498Szrj gimple_seq_add_stmt (&sub_seq, gimple_build_label (end));
534538fd1498Szrj }
534638fd1498Szrj else if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
534738fd1498Szrj {
534838fd1498Szrj tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
534938fd1498Szrj
535038fd1498Szrj if (omp_is_reference (var)
535138fd1498Szrj && !useless_type_conversion_p (TREE_TYPE (placeholder),
535238fd1498Szrj TREE_TYPE (ref)))
535338fd1498Szrj ref = build_fold_addr_expr_loc (clause_loc, ref);
535438fd1498Szrj SET_DECL_VALUE_EXPR (placeholder, ref);
535538fd1498Szrj DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
535638fd1498Szrj lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
535738fd1498Szrj gimple_seq_add_seq (&sub_seq, OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
535838fd1498Szrj OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
535938fd1498Szrj OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
536038fd1498Szrj }
536138fd1498Szrj else
536238fd1498Szrj {
536338fd1498Szrj x = build2 (code, TREE_TYPE (ref), ref, new_var);
536438fd1498Szrj ref = build_outer_var_ref (var, ctx);
536538fd1498Szrj gimplify_assign (ref, x, &sub_seq);
536638fd1498Szrj }
536738fd1498Szrj }
536838fd1498Szrj
536938fd1498Szrj stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START),
537038fd1498Szrj 0);
537138fd1498Szrj gimple_seq_add_stmt (stmt_seqp, stmt);
537238fd1498Szrj
537338fd1498Szrj gimple_seq_add_seq (stmt_seqp, sub_seq);
537438fd1498Szrj
537538fd1498Szrj stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END),
537638fd1498Szrj 0);
537738fd1498Szrj gimple_seq_add_stmt (stmt_seqp, stmt);
537838fd1498Szrj }
537938fd1498Szrj
538038fd1498Szrj
538138fd1498Szrj /* Generate code to implement the COPYPRIVATE clauses. */
538238fd1498Szrj
538338fd1498Szrj static void
lower_copyprivate_clauses(tree clauses,gimple_seq * slist,gimple_seq * rlist,omp_context * ctx)538438fd1498Szrj lower_copyprivate_clauses (tree clauses, gimple_seq *slist, gimple_seq *rlist,
538538fd1498Szrj omp_context *ctx)
538638fd1498Szrj {
538738fd1498Szrj tree c;
538838fd1498Szrj
538938fd1498Szrj for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
539038fd1498Szrj {
539138fd1498Szrj tree var, new_var, ref, x;
539238fd1498Szrj bool by_ref;
539338fd1498Szrj location_t clause_loc = OMP_CLAUSE_LOCATION (c);
539438fd1498Szrj
539538fd1498Szrj if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYPRIVATE)
539638fd1498Szrj continue;
539738fd1498Szrj
539838fd1498Szrj var = OMP_CLAUSE_DECL (c);
539938fd1498Szrj by_ref = use_pointer_for_field (var, NULL);
540038fd1498Szrj
540138fd1498Szrj ref = build_sender_ref (var, ctx);
540238fd1498Szrj x = new_var = lookup_decl_in_outer_ctx (var, ctx);
540338fd1498Szrj if (by_ref)
540438fd1498Szrj {
540538fd1498Szrj x = build_fold_addr_expr_loc (clause_loc, new_var);
540638fd1498Szrj x = fold_convert_loc (clause_loc, TREE_TYPE (ref), x);
540738fd1498Szrj }
540838fd1498Szrj gimplify_assign (ref, x, slist);
540938fd1498Szrj
541038fd1498Szrj ref = build_receiver_ref (var, false, ctx);
541138fd1498Szrj if (by_ref)
541238fd1498Szrj {
541338fd1498Szrj ref = fold_convert_loc (clause_loc,
541438fd1498Szrj build_pointer_type (TREE_TYPE (new_var)),
541538fd1498Szrj ref);
541638fd1498Szrj ref = build_fold_indirect_ref_loc (clause_loc, ref);
541738fd1498Szrj }
541838fd1498Szrj if (omp_is_reference (var))
541938fd1498Szrj {
542038fd1498Szrj ref = fold_convert_loc (clause_loc, TREE_TYPE (new_var), ref);
542138fd1498Szrj ref = build_simple_mem_ref_loc (clause_loc, ref);
542238fd1498Szrj new_var = build_simple_mem_ref_loc (clause_loc, new_var);
542338fd1498Szrj }
542438fd1498Szrj x = lang_hooks.decls.omp_clause_assign_op (c, new_var, ref);
542538fd1498Szrj gimplify_and_add (x, rlist);
542638fd1498Szrj }
542738fd1498Szrj }
542838fd1498Szrj
542938fd1498Szrj
543038fd1498Szrj /* Generate code to implement the clauses, FIRSTPRIVATE, COPYIN, LASTPRIVATE,
543138fd1498Szrj and REDUCTION from the sender (aka parent) side. */
543238fd1498Szrj
543338fd1498Szrj static void
lower_send_clauses(tree clauses,gimple_seq * ilist,gimple_seq * olist,omp_context * ctx)543438fd1498Szrj lower_send_clauses (tree clauses, gimple_seq *ilist, gimple_seq *olist,
543538fd1498Szrj omp_context *ctx)
543638fd1498Szrj {
543738fd1498Szrj tree c, t;
543838fd1498Szrj int ignored_looptemp = 0;
543938fd1498Szrj bool is_taskloop = false;
544038fd1498Szrj
544138fd1498Szrj /* For taskloop, ignore first two _looptemp_ clauses, those are initialized
544238fd1498Szrj by GOMP_taskloop. */
544338fd1498Szrj if (is_task_ctx (ctx) && gimple_omp_task_taskloop_p (ctx->stmt))
544438fd1498Szrj {
544538fd1498Szrj ignored_looptemp = 2;
544638fd1498Szrj is_taskloop = true;
544738fd1498Szrj }
544838fd1498Szrj
544938fd1498Szrj for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
545038fd1498Szrj {
545138fd1498Szrj tree val, ref, x, var;
545238fd1498Szrj bool by_ref, do_in = false, do_out = false;
545338fd1498Szrj location_t clause_loc = OMP_CLAUSE_LOCATION (c);
545438fd1498Szrj
545538fd1498Szrj switch (OMP_CLAUSE_CODE (c))
545638fd1498Szrj {
545738fd1498Szrj case OMP_CLAUSE_PRIVATE:
545838fd1498Szrj if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
545938fd1498Szrj break;
546038fd1498Szrj continue;
546138fd1498Szrj case OMP_CLAUSE_FIRSTPRIVATE:
546238fd1498Szrj case OMP_CLAUSE_COPYIN:
546338fd1498Szrj case OMP_CLAUSE_LASTPRIVATE:
546438fd1498Szrj case OMP_CLAUSE_REDUCTION:
546538fd1498Szrj break;
546638fd1498Szrj case OMP_CLAUSE_SHARED:
546738fd1498Szrj if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
546838fd1498Szrj break;
546938fd1498Szrj continue;
547038fd1498Szrj case OMP_CLAUSE__LOOPTEMP_:
547138fd1498Szrj if (ignored_looptemp)
547238fd1498Szrj {
547338fd1498Szrj ignored_looptemp--;
547438fd1498Szrj continue;
547538fd1498Szrj }
547638fd1498Szrj break;
547738fd1498Szrj default:
547838fd1498Szrj continue;
547938fd1498Szrj }
548038fd1498Szrj
548138fd1498Szrj val = OMP_CLAUSE_DECL (c);
548238fd1498Szrj if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
548338fd1498Szrj && TREE_CODE (val) == MEM_REF)
548438fd1498Szrj {
548538fd1498Szrj val = TREE_OPERAND (val, 0);
548638fd1498Szrj if (TREE_CODE (val) == POINTER_PLUS_EXPR)
548738fd1498Szrj val = TREE_OPERAND (val, 0);
548838fd1498Szrj if (TREE_CODE (val) == INDIRECT_REF
548938fd1498Szrj || TREE_CODE (val) == ADDR_EXPR)
549038fd1498Szrj val = TREE_OPERAND (val, 0);
549138fd1498Szrj if (is_variable_sized (val))
549238fd1498Szrj continue;
549338fd1498Szrj }
549438fd1498Szrj
549538fd1498Szrj /* For OMP_CLAUSE_SHARED_FIRSTPRIVATE, look beyond the
549638fd1498Szrj outer taskloop region. */
549738fd1498Szrj omp_context *ctx_for_o = ctx;
549838fd1498Szrj if (is_taskloop
549938fd1498Szrj && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
550038fd1498Szrj && OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
550138fd1498Szrj ctx_for_o = ctx->outer;
550238fd1498Szrj
550338fd1498Szrj var = lookup_decl_in_outer_ctx (val, ctx_for_o);
550438fd1498Szrj
550538fd1498Szrj if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYIN
550638fd1498Szrj && is_global_var (var))
550738fd1498Szrj continue;
550838fd1498Szrj
550938fd1498Szrj t = omp_member_access_dummy_var (var);
551038fd1498Szrj if (t)
551138fd1498Szrj {
551238fd1498Szrj var = DECL_VALUE_EXPR (var);
551338fd1498Szrj tree o = maybe_lookup_decl_in_outer_ctx (t, ctx_for_o);
551438fd1498Szrj if (o != t)
551538fd1498Szrj var = unshare_and_remap (var, t, o);
551638fd1498Szrj else
551738fd1498Szrj var = unshare_expr (var);
551838fd1498Szrj }
551938fd1498Szrj
552038fd1498Szrj if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED)
552138fd1498Szrj {
552238fd1498Szrj /* Handle taskloop firstprivate/lastprivate, where the
552338fd1498Szrj lastprivate on GIMPLE_OMP_TASK is represented as
552438fd1498Szrj OMP_CLAUSE_SHARED_FIRSTPRIVATE. */
552538fd1498Szrj tree f = lookup_sfield ((splay_tree_key) &DECL_UID (val), ctx);
552638fd1498Szrj x = omp_build_component_ref (ctx->sender_decl, f);
552738fd1498Szrj if (use_pointer_for_field (val, ctx))
552838fd1498Szrj var = build_fold_addr_expr (var);
552938fd1498Szrj gimplify_assign (x, var, ilist);
553038fd1498Szrj DECL_ABSTRACT_ORIGIN (f) = NULL;
553138fd1498Szrj continue;
553238fd1498Szrj }
553338fd1498Szrj
553438fd1498Szrj if ((OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION
553538fd1498Szrj || val == OMP_CLAUSE_DECL (c))
553638fd1498Szrj && is_variable_sized (val))
553738fd1498Szrj continue;
553838fd1498Szrj by_ref = use_pointer_for_field (val, NULL);
553938fd1498Szrj
554038fd1498Szrj switch (OMP_CLAUSE_CODE (c))
554138fd1498Szrj {
554238fd1498Szrj case OMP_CLAUSE_FIRSTPRIVATE:
554338fd1498Szrj if (OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c)
554438fd1498Szrj && !by_ref
554538fd1498Szrj && is_task_ctx (ctx))
554638fd1498Szrj TREE_NO_WARNING (var) = 1;
554738fd1498Szrj do_in = true;
554838fd1498Szrj break;
554938fd1498Szrj
555038fd1498Szrj case OMP_CLAUSE_PRIVATE:
555138fd1498Szrj case OMP_CLAUSE_COPYIN:
555238fd1498Szrj case OMP_CLAUSE__LOOPTEMP_:
555338fd1498Szrj do_in = true;
555438fd1498Szrj break;
555538fd1498Szrj
555638fd1498Szrj case OMP_CLAUSE_LASTPRIVATE:
555738fd1498Szrj if (by_ref || omp_is_reference (val))
555838fd1498Szrj {
555938fd1498Szrj if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
556038fd1498Szrj continue;
556138fd1498Szrj do_in = true;
556238fd1498Szrj }
556338fd1498Szrj else
556438fd1498Szrj {
556538fd1498Szrj do_out = true;
556638fd1498Szrj if (lang_hooks.decls.omp_private_outer_ref (val))
556738fd1498Szrj do_in = true;
556838fd1498Szrj }
556938fd1498Szrj break;
557038fd1498Szrj
557138fd1498Szrj case OMP_CLAUSE_REDUCTION:
557238fd1498Szrj do_in = true;
557338fd1498Szrj if (val == OMP_CLAUSE_DECL (c))
557438fd1498Szrj do_out = !(by_ref || omp_is_reference (val));
557538fd1498Szrj else
557638fd1498Szrj by_ref = TREE_CODE (TREE_TYPE (val)) == ARRAY_TYPE;
557738fd1498Szrj break;
557838fd1498Szrj
557938fd1498Szrj default:
558038fd1498Szrj gcc_unreachable ();
558138fd1498Szrj }
558238fd1498Szrj
558338fd1498Szrj if (do_in)
558438fd1498Szrj {
558538fd1498Szrj ref = build_sender_ref (val, ctx);
558638fd1498Szrj x = by_ref ? build_fold_addr_expr_loc (clause_loc, var) : var;
558738fd1498Szrj gimplify_assign (ref, x, ilist);
558838fd1498Szrj if (is_task_ctx (ctx))
558938fd1498Szrj DECL_ABSTRACT_ORIGIN (TREE_OPERAND (ref, 1)) = NULL;
559038fd1498Szrj }
559138fd1498Szrj
559238fd1498Szrj if (do_out)
559338fd1498Szrj {
559438fd1498Szrj ref = build_sender_ref (val, ctx);
559538fd1498Szrj gimplify_assign (var, ref, olist);
559638fd1498Szrj }
559738fd1498Szrj }
559838fd1498Szrj }
559938fd1498Szrj
560038fd1498Szrj /* Generate code to implement SHARED from the sender (aka parent)
560138fd1498Szrj side. This is trickier, since GIMPLE_OMP_PARALLEL_CLAUSES doesn't
560238fd1498Szrj list things that got automatically shared. */
560338fd1498Szrj
560438fd1498Szrj static void
lower_send_shared_vars(gimple_seq * ilist,gimple_seq * olist,omp_context * ctx)560538fd1498Szrj lower_send_shared_vars (gimple_seq *ilist, gimple_seq *olist, omp_context *ctx)
560638fd1498Szrj {
560738fd1498Szrj tree var, ovar, nvar, t, f, x, record_type;
560838fd1498Szrj
560938fd1498Szrj if (ctx->record_type == NULL)
561038fd1498Szrj return;
561138fd1498Szrj
561238fd1498Szrj record_type = ctx->srecord_type ? ctx->srecord_type : ctx->record_type;
561338fd1498Szrj for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
561438fd1498Szrj {
561538fd1498Szrj ovar = DECL_ABSTRACT_ORIGIN (f);
561638fd1498Szrj if (!ovar || TREE_CODE (ovar) == FIELD_DECL)
561738fd1498Szrj continue;
561838fd1498Szrj
561938fd1498Szrj nvar = maybe_lookup_decl (ovar, ctx);
562038fd1498Szrj if (!nvar || !DECL_HAS_VALUE_EXPR_P (nvar))
562138fd1498Szrj continue;
562238fd1498Szrj
562338fd1498Szrj /* If CTX is a nested parallel directive. Find the immediately
562438fd1498Szrj enclosing parallel or workshare construct that contains a
562538fd1498Szrj mapping for OVAR. */
562638fd1498Szrj var = lookup_decl_in_outer_ctx (ovar, ctx);
562738fd1498Szrj
562838fd1498Szrj t = omp_member_access_dummy_var (var);
562938fd1498Szrj if (t)
563038fd1498Szrj {
563138fd1498Szrj var = DECL_VALUE_EXPR (var);
563238fd1498Szrj tree o = maybe_lookup_decl_in_outer_ctx (t, ctx);
563338fd1498Szrj if (o != t)
563438fd1498Szrj var = unshare_and_remap (var, t, o);
563538fd1498Szrj else
563638fd1498Szrj var = unshare_expr (var);
563738fd1498Szrj }
563838fd1498Szrj
563938fd1498Szrj if (use_pointer_for_field (ovar, ctx))
564038fd1498Szrj {
564138fd1498Szrj x = build_sender_ref (ovar, ctx);
564238fd1498Szrj var = build_fold_addr_expr (var);
564338fd1498Szrj gimplify_assign (x, var, ilist);
564438fd1498Szrj }
564538fd1498Szrj else
564638fd1498Szrj {
564738fd1498Szrj x = build_sender_ref (ovar, ctx);
564838fd1498Szrj gimplify_assign (x, var, ilist);
564938fd1498Szrj
565038fd1498Szrj if (!TREE_READONLY (var)
565138fd1498Szrj /* We don't need to receive a new reference to a result
565238fd1498Szrj or parm decl. In fact we may not store to it as we will
565338fd1498Szrj invalidate any pending RSO and generate wrong gimple
565438fd1498Szrj during inlining. */
565538fd1498Szrj && !((TREE_CODE (var) == RESULT_DECL
565638fd1498Szrj || TREE_CODE (var) == PARM_DECL)
565738fd1498Szrj && DECL_BY_REFERENCE (var)))
565838fd1498Szrj {
565938fd1498Szrj x = build_sender_ref (ovar, ctx);
566038fd1498Szrj gimplify_assign (var, x, olist);
566138fd1498Szrj }
566238fd1498Szrj }
566338fd1498Szrj }
566438fd1498Szrj }
566538fd1498Szrj
566638fd1498Szrj /* Emit an OpenACC head marker call, encapulating the partitioning and
566738fd1498Szrj other information that must be processed by the target compiler.
566838fd1498Szrj Return the maximum number of dimensions the associated loop might
566938fd1498Szrj be partitioned over. */
567038fd1498Szrj
567138fd1498Szrj static unsigned
lower_oacc_head_mark(location_t loc,tree ddvar,tree clauses,gimple_seq * seq,omp_context * ctx)567238fd1498Szrj lower_oacc_head_mark (location_t loc, tree ddvar, tree clauses,
567338fd1498Szrj gimple_seq *seq, omp_context *ctx)
567438fd1498Szrj {
567538fd1498Szrj unsigned levels = 0;
567638fd1498Szrj unsigned tag = 0;
567738fd1498Szrj tree gang_static = NULL_TREE;
567838fd1498Szrj auto_vec<tree, 5> args;
567938fd1498Szrj
568038fd1498Szrj args.quick_push (build_int_cst
568138fd1498Szrj (integer_type_node, IFN_UNIQUE_OACC_HEAD_MARK));
568238fd1498Szrj args.quick_push (ddvar);
568338fd1498Szrj for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
568438fd1498Szrj {
568538fd1498Szrj switch (OMP_CLAUSE_CODE (c))
568638fd1498Szrj {
568738fd1498Szrj case OMP_CLAUSE_GANG:
568838fd1498Szrj tag |= OLF_DIM_GANG;
568938fd1498Szrj gang_static = OMP_CLAUSE_GANG_STATIC_EXPR (c);
569038fd1498Szrj /* static:* is represented by -1, and we can ignore it, as
569138fd1498Szrj scheduling is always static. */
569238fd1498Szrj if (gang_static && integer_minus_onep (gang_static))
569338fd1498Szrj gang_static = NULL_TREE;
569438fd1498Szrj levels++;
569538fd1498Szrj break;
569638fd1498Szrj
569738fd1498Szrj case OMP_CLAUSE_WORKER:
569838fd1498Szrj tag |= OLF_DIM_WORKER;
569938fd1498Szrj levels++;
570038fd1498Szrj break;
570138fd1498Szrj
570238fd1498Szrj case OMP_CLAUSE_VECTOR:
570338fd1498Szrj tag |= OLF_DIM_VECTOR;
570438fd1498Szrj levels++;
570538fd1498Szrj break;
570638fd1498Szrj
570738fd1498Szrj case OMP_CLAUSE_SEQ:
570838fd1498Szrj tag |= OLF_SEQ;
570938fd1498Szrj break;
571038fd1498Szrj
571138fd1498Szrj case OMP_CLAUSE_AUTO:
571238fd1498Szrj tag |= OLF_AUTO;
571338fd1498Szrj break;
571438fd1498Szrj
571538fd1498Szrj case OMP_CLAUSE_INDEPENDENT:
571638fd1498Szrj tag |= OLF_INDEPENDENT;
571738fd1498Szrj break;
571838fd1498Szrj
571938fd1498Szrj case OMP_CLAUSE_TILE:
572038fd1498Szrj tag |= OLF_TILE;
572138fd1498Szrj break;
572238fd1498Szrj
572338fd1498Szrj default:
572438fd1498Szrj continue;
572538fd1498Szrj }
572638fd1498Szrj }
572738fd1498Szrj
572838fd1498Szrj if (gang_static)
572938fd1498Szrj {
573038fd1498Szrj if (DECL_P (gang_static))
573138fd1498Szrj gang_static = build_outer_var_ref (gang_static, ctx);
573238fd1498Szrj tag |= OLF_GANG_STATIC;
573338fd1498Szrj }
573438fd1498Szrj
573538fd1498Szrj /* In a parallel region, loops are implicitly INDEPENDENT. */
573638fd1498Szrj omp_context *tgt = enclosing_target_ctx (ctx);
573738fd1498Szrj if (!tgt || is_oacc_parallel (tgt))
573838fd1498Szrj tag |= OLF_INDEPENDENT;
573938fd1498Szrj
574038fd1498Szrj if (tag & OLF_TILE)
574138fd1498Szrj /* Tiling could use all 3 levels. */
574238fd1498Szrj levels = 3;
574338fd1498Szrj else
574438fd1498Szrj {
574538fd1498Szrj /* A loop lacking SEQ, GANG, WORKER and/or VECTOR could be AUTO.
574638fd1498Szrj Ensure at least one level, or 2 for possible auto
574738fd1498Szrj partitioning */
574838fd1498Szrj bool maybe_auto = !(tag & (((GOMP_DIM_MASK (GOMP_DIM_MAX) - 1)
574938fd1498Szrj << OLF_DIM_BASE) | OLF_SEQ));
575038fd1498Szrj
575138fd1498Szrj if (levels < 1u + maybe_auto)
575238fd1498Szrj levels = 1u + maybe_auto;
575338fd1498Szrj }
575438fd1498Szrj
575538fd1498Szrj args.quick_push (build_int_cst (integer_type_node, levels));
575638fd1498Szrj args.quick_push (build_int_cst (integer_type_node, tag));
575738fd1498Szrj if (gang_static)
575838fd1498Szrj args.quick_push (gang_static);
575938fd1498Szrj
576038fd1498Szrj gcall *call = gimple_build_call_internal_vec (IFN_UNIQUE, args);
576138fd1498Szrj gimple_set_location (call, loc);
576238fd1498Szrj gimple_set_lhs (call, ddvar);
576338fd1498Szrj gimple_seq_add_stmt (seq, call);
576438fd1498Szrj
576538fd1498Szrj return levels;
576638fd1498Szrj }
576738fd1498Szrj
576838fd1498Szrj /* Emit an OpenACC lopp head or tail marker to SEQ. LEVEL is the
576938fd1498Szrj partitioning level of the enclosed region. */
577038fd1498Szrj
577138fd1498Szrj static void
lower_oacc_loop_marker(location_t loc,tree ddvar,bool head,tree tofollow,gimple_seq * seq)577238fd1498Szrj lower_oacc_loop_marker (location_t loc, tree ddvar, bool head,
577338fd1498Szrj tree tofollow, gimple_seq *seq)
577438fd1498Szrj {
577538fd1498Szrj int marker_kind = (head ? IFN_UNIQUE_OACC_HEAD_MARK
577638fd1498Szrj : IFN_UNIQUE_OACC_TAIL_MARK);
577738fd1498Szrj tree marker = build_int_cst (integer_type_node, marker_kind);
577838fd1498Szrj int nargs = 2 + (tofollow != NULL_TREE);
577938fd1498Szrj gcall *call = gimple_build_call_internal (IFN_UNIQUE, nargs,
578038fd1498Szrj marker, ddvar, tofollow);
578138fd1498Szrj gimple_set_location (call, loc);
578238fd1498Szrj gimple_set_lhs (call, ddvar);
578338fd1498Szrj gimple_seq_add_stmt (seq, call);
578438fd1498Szrj }
578538fd1498Szrj
578638fd1498Szrj /* Generate the before and after OpenACC loop sequences. CLAUSES are
578738fd1498Szrj the loop clauses, from which we extract reductions. Initialize
578838fd1498Szrj HEAD and TAIL. */
578938fd1498Szrj
579038fd1498Szrj static void
lower_oacc_head_tail(location_t loc,tree clauses,gimple_seq * head,gimple_seq * tail,omp_context * ctx)579138fd1498Szrj lower_oacc_head_tail (location_t loc, tree clauses,
579238fd1498Szrj gimple_seq *head, gimple_seq *tail, omp_context *ctx)
579338fd1498Szrj {
579438fd1498Szrj bool inner = false;
579538fd1498Szrj tree ddvar = create_tmp_var (integer_type_node, ".data_dep");
579638fd1498Szrj gimple_seq_add_stmt (head, gimple_build_assign (ddvar, integer_zero_node));
579738fd1498Szrj
579838fd1498Szrj unsigned count = lower_oacc_head_mark (loc, ddvar, clauses, head, ctx);
579938fd1498Szrj tree fork_kind = build_int_cst (unsigned_type_node, IFN_UNIQUE_OACC_FORK);
580038fd1498Szrj tree join_kind = build_int_cst (unsigned_type_node, IFN_UNIQUE_OACC_JOIN);
580138fd1498Szrj
580238fd1498Szrj gcc_assert (count);
580338fd1498Szrj for (unsigned done = 1; count; count--, done++)
580438fd1498Szrj {
580538fd1498Szrj gimple_seq fork_seq = NULL;
580638fd1498Szrj gimple_seq join_seq = NULL;
580738fd1498Szrj
580838fd1498Szrj tree place = build_int_cst (integer_type_node, -1);
580938fd1498Szrj gcall *fork = gimple_build_call_internal (IFN_UNIQUE, 3,
581038fd1498Szrj fork_kind, ddvar, place);
581138fd1498Szrj gimple_set_location (fork, loc);
581238fd1498Szrj gimple_set_lhs (fork, ddvar);
581338fd1498Szrj
581438fd1498Szrj gcall *join = gimple_build_call_internal (IFN_UNIQUE, 3,
581538fd1498Szrj join_kind, ddvar, place);
581638fd1498Szrj gimple_set_location (join, loc);
581738fd1498Szrj gimple_set_lhs (join, ddvar);
581838fd1498Szrj
581938fd1498Szrj /* Mark the beginning of this level sequence. */
582038fd1498Szrj if (inner)
582138fd1498Szrj lower_oacc_loop_marker (loc, ddvar, true,
582238fd1498Szrj build_int_cst (integer_type_node, count),
582338fd1498Szrj &fork_seq);
582438fd1498Szrj lower_oacc_loop_marker (loc, ddvar, false,
582538fd1498Szrj build_int_cst (integer_type_node, done),
582638fd1498Szrj &join_seq);
582738fd1498Szrj
582838fd1498Szrj lower_oacc_reductions (loc, clauses, place, inner,
582938fd1498Szrj fork, join, &fork_seq, &join_seq, ctx);
583038fd1498Szrj
583138fd1498Szrj /* Append this level to head. */
583238fd1498Szrj gimple_seq_add_seq (head, fork_seq);
583338fd1498Szrj /* Prepend it to tail. */
583438fd1498Szrj gimple_seq_add_seq (&join_seq, *tail);
583538fd1498Szrj *tail = join_seq;
583638fd1498Szrj
583738fd1498Szrj inner = true;
583838fd1498Szrj }
583938fd1498Szrj
584038fd1498Szrj /* Mark the end of the sequence. */
584138fd1498Szrj lower_oacc_loop_marker (loc, ddvar, true, NULL_TREE, head);
584238fd1498Szrj lower_oacc_loop_marker (loc, ddvar, false, NULL_TREE, tail);
584338fd1498Szrj }
584438fd1498Szrj
584538fd1498Szrj /* If exceptions are enabled, wrap the statements in BODY in a MUST_NOT_THROW
584638fd1498Szrj catch handler and return it. This prevents programs from violating the
584738fd1498Szrj structured block semantics with throws. */
584838fd1498Szrj
584938fd1498Szrj static gimple_seq
maybe_catch_exception(gimple_seq body)585038fd1498Szrj maybe_catch_exception (gimple_seq body)
585138fd1498Szrj {
585238fd1498Szrj gimple *g;
585338fd1498Szrj tree decl;
585438fd1498Szrj
585538fd1498Szrj if (!flag_exceptions)
585638fd1498Szrj return body;
585738fd1498Szrj
585838fd1498Szrj if (lang_hooks.eh_protect_cleanup_actions != NULL)
585938fd1498Szrj decl = lang_hooks.eh_protect_cleanup_actions ();
586038fd1498Szrj else
586138fd1498Szrj decl = builtin_decl_explicit (BUILT_IN_TRAP);
586238fd1498Szrj
586338fd1498Szrj g = gimple_build_eh_must_not_throw (decl);
586438fd1498Szrj g = gimple_build_try (body, gimple_seq_alloc_with_stmt (g),
586538fd1498Szrj GIMPLE_TRY_CATCH);
586638fd1498Szrj
586738fd1498Szrj return gimple_seq_alloc_with_stmt (g);
586838fd1498Szrj }
586938fd1498Szrj
587038fd1498Szrj
587138fd1498Szrj /* Routines to lower OMP directives into OMP-GIMPLE. */
587238fd1498Szrj
587338fd1498Szrj /* If ctx is a worksharing context inside of a cancellable parallel
587438fd1498Szrj region and it isn't nowait, add lhs to its GIMPLE_OMP_RETURN
587538fd1498Szrj and conditional branch to parallel's cancel_label to handle
587638fd1498Szrj cancellation in the implicit barrier. */
587738fd1498Szrj
587838fd1498Szrj static void
maybe_add_implicit_barrier_cancel(omp_context * ctx,gimple_seq * body)587938fd1498Szrj maybe_add_implicit_barrier_cancel (omp_context *ctx, gimple_seq *body)
588038fd1498Szrj {
588138fd1498Szrj gimple *omp_return = gimple_seq_last_stmt (*body);
588238fd1498Szrj gcc_assert (gimple_code (omp_return) == GIMPLE_OMP_RETURN);
588338fd1498Szrj if (gimple_omp_return_nowait_p (omp_return))
588438fd1498Szrj return;
588538fd1498Szrj if (ctx->outer
588638fd1498Szrj && gimple_code (ctx->outer->stmt) == GIMPLE_OMP_PARALLEL
588738fd1498Szrj && ctx->outer->cancellable)
588838fd1498Szrj {
588938fd1498Szrj tree fndecl = builtin_decl_explicit (BUILT_IN_GOMP_CANCEL);
589038fd1498Szrj tree c_bool_type = TREE_TYPE (TREE_TYPE (fndecl));
589138fd1498Szrj tree lhs = create_tmp_var (c_bool_type);
589238fd1498Szrj gimple_omp_return_set_lhs (omp_return, lhs);
589338fd1498Szrj tree fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
589438fd1498Szrj gimple *g = gimple_build_cond (NE_EXPR, lhs,
589538fd1498Szrj fold_convert (c_bool_type,
589638fd1498Szrj boolean_false_node),
589738fd1498Szrj ctx->outer->cancel_label, fallthru_label);
589838fd1498Szrj gimple_seq_add_stmt (body, g);
589938fd1498Szrj gimple_seq_add_stmt (body, gimple_build_label (fallthru_label));
590038fd1498Szrj }
590138fd1498Szrj }
590238fd1498Szrj
590338fd1498Szrj /* Lower the OpenMP sections directive in the current statement in GSI_P.
590438fd1498Szrj CTX is the enclosing OMP context for the current statement. */
590538fd1498Szrj
590638fd1498Szrj static void
lower_omp_sections(gimple_stmt_iterator * gsi_p,omp_context * ctx)590738fd1498Szrj lower_omp_sections (gimple_stmt_iterator *gsi_p, omp_context *ctx)
590838fd1498Szrj {
590938fd1498Szrj tree block, control;
591038fd1498Szrj gimple_stmt_iterator tgsi;
591138fd1498Szrj gomp_sections *stmt;
591238fd1498Szrj gimple *t;
591338fd1498Szrj gbind *new_stmt, *bind;
591438fd1498Szrj gimple_seq ilist, dlist, olist, new_body;
591538fd1498Szrj
591638fd1498Szrj stmt = as_a <gomp_sections *> (gsi_stmt (*gsi_p));
591738fd1498Szrj
591838fd1498Szrj push_gimplify_context ();
591938fd1498Szrj
592038fd1498Szrj dlist = NULL;
592138fd1498Szrj ilist = NULL;
592238fd1498Szrj lower_rec_input_clauses (gimple_omp_sections_clauses (stmt),
592338fd1498Szrj &ilist, &dlist, ctx, NULL);
592438fd1498Szrj
592538fd1498Szrj new_body = gimple_omp_body (stmt);
592638fd1498Szrj gimple_omp_set_body (stmt, NULL);
592738fd1498Szrj tgsi = gsi_start (new_body);
592838fd1498Szrj for (; !gsi_end_p (tgsi); gsi_next (&tgsi))
592938fd1498Szrj {
593038fd1498Szrj omp_context *sctx;
593138fd1498Szrj gimple *sec_start;
593238fd1498Szrj
593338fd1498Szrj sec_start = gsi_stmt (tgsi);
593438fd1498Szrj sctx = maybe_lookup_ctx (sec_start);
593538fd1498Szrj gcc_assert (sctx);
593638fd1498Szrj
593738fd1498Szrj lower_omp (gimple_omp_body_ptr (sec_start), sctx);
593838fd1498Szrj gsi_insert_seq_after (&tgsi, gimple_omp_body (sec_start),
593938fd1498Szrj GSI_CONTINUE_LINKING);
594038fd1498Szrj gimple_omp_set_body (sec_start, NULL);
594138fd1498Szrj
594238fd1498Szrj if (gsi_one_before_end_p (tgsi))
594338fd1498Szrj {
594438fd1498Szrj gimple_seq l = NULL;
594538fd1498Szrj lower_lastprivate_clauses (gimple_omp_sections_clauses (stmt), NULL,
594638fd1498Szrj &l, ctx);
594738fd1498Szrj gsi_insert_seq_after (&tgsi, l, GSI_CONTINUE_LINKING);
594838fd1498Szrj gimple_omp_section_set_last (sec_start);
594938fd1498Szrj }
595038fd1498Szrj
595138fd1498Szrj gsi_insert_after (&tgsi, gimple_build_omp_return (false),
595238fd1498Szrj GSI_CONTINUE_LINKING);
595338fd1498Szrj }
595438fd1498Szrj
595538fd1498Szrj block = make_node (BLOCK);
595638fd1498Szrj bind = gimple_build_bind (NULL, new_body, block);
595738fd1498Szrj
595838fd1498Szrj olist = NULL;
595938fd1498Szrj lower_reduction_clauses (gimple_omp_sections_clauses (stmt), &olist, ctx);
596038fd1498Szrj
596138fd1498Szrj block = make_node (BLOCK);
596238fd1498Szrj new_stmt = gimple_build_bind (NULL, NULL, block);
596338fd1498Szrj gsi_replace (gsi_p, new_stmt, true);
596438fd1498Szrj
596538fd1498Szrj pop_gimplify_context (new_stmt);
596638fd1498Szrj gimple_bind_append_vars (new_stmt, ctx->block_vars);
596738fd1498Szrj BLOCK_VARS (block) = gimple_bind_vars (bind);
596838fd1498Szrj if (BLOCK_VARS (block))
596938fd1498Szrj TREE_USED (block) = 1;
597038fd1498Szrj
597138fd1498Szrj new_body = NULL;
597238fd1498Szrj gimple_seq_add_seq (&new_body, ilist);
597338fd1498Szrj gimple_seq_add_stmt (&new_body, stmt);
597438fd1498Szrj gimple_seq_add_stmt (&new_body, gimple_build_omp_sections_switch ());
597538fd1498Szrj gimple_seq_add_stmt (&new_body, bind);
597638fd1498Szrj
597738fd1498Szrj control = create_tmp_var (unsigned_type_node, ".section");
597838fd1498Szrj t = gimple_build_omp_continue (control, control);
597938fd1498Szrj gimple_omp_sections_set_control (stmt, control);
598038fd1498Szrj gimple_seq_add_stmt (&new_body, t);
598138fd1498Szrj
598238fd1498Szrj gimple_seq_add_seq (&new_body, olist);
598338fd1498Szrj if (ctx->cancellable)
598438fd1498Szrj gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
598538fd1498Szrj gimple_seq_add_seq (&new_body, dlist);
598638fd1498Szrj
598738fd1498Szrj new_body = maybe_catch_exception (new_body);
598838fd1498Szrj
598938fd1498Szrj bool nowait = omp_find_clause (gimple_omp_sections_clauses (stmt),
599038fd1498Szrj OMP_CLAUSE_NOWAIT) != NULL_TREE;
599138fd1498Szrj t = gimple_build_omp_return (nowait);
599238fd1498Szrj gimple_seq_add_stmt (&new_body, t);
599338fd1498Szrj maybe_add_implicit_barrier_cancel (ctx, &new_body);
599438fd1498Szrj
599538fd1498Szrj gimple_bind_set_body (new_stmt, new_body);
599638fd1498Szrj }
599738fd1498Szrj
599838fd1498Szrj
599938fd1498Szrj /* A subroutine of lower_omp_single. Expand the simple form of
600038fd1498Szrj a GIMPLE_OMP_SINGLE, without a copyprivate clause:
600138fd1498Szrj
600238fd1498Szrj if (GOMP_single_start ())
600338fd1498Szrj BODY;
600438fd1498Szrj [ GOMP_barrier (); ] -> unless 'nowait' is present.
600538fd1498Szrj
600638fd1498Szrj FIXME. It may be better to delay expanding the logic of this until
600738fd1498Szrj pass_expand_omp. The expanded logic may make the job more difficult
600838fd1498Szrj to a synchronization analysis pass. */
600938fd1498Szrj
601038fd1498Szrj static void
lower_omp_single_simple(gomp_single * single_stmt,gimple_seq * pre_p)601138fd1498Szrj lower_omp_single_simple (gomp_single *single_stmt, gimple_seq *pre_p)
601238fd1498Szrj {
601338fd1498Szrj location_t loc = gimple_location (single_stmt);
601438fd1498Szrj tree tlabel = create_artificial_label (loc);
601538fd1498Szrj tree flabel = create_artificial_label (loc);
601638fd1498Szrj gimple *call, *cond;
601738fd1498Szrj tree lhs, decl;
601838fd1498Szrj
601938fd1498Szrj decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_START);
602038fd1498Szrj lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (decl)));
602138fd1498Szrj call = gimple_build_call (decl, 0);
602238fd1498Szrj gimple_call_set_lhs (call, lhs);
602338fd1498Szrj gimple_seq_add_stmt (pre_p, call);
602438fd1498Szrj
602538fd1498Szrj cond = gimple_build_cond (EQ_EXPR, lhs,
602638fd1498Szrj fold_convert_loc (loc, TREE_TYPE (lhs),
602738fd1498Szrj boolean_true_node),
602838fd1498Szrj tlabel, flabel);
602938fd1498Szrj gimple_seq_add_stmt (pre_p, cond);
603038fd1498Szrj gimple_seq_add_stmt (pre_p, gimple_build_label (tlabel));
603138fd1498Szrj gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
603238fd1498Szrj gimple_seq_add_stmt (pre_p, gimple_build_label (flabel));
603338fd1498Szrj }
603438fd1498Szrj
603538fd1498Szrj
603638fd1498Szrj /* A subroutine of lower_omp_single. Expand the simple form of
603738fd1498Szrj a GIMPLE_OMP_SINGLE, with a copyprivate clause:
603838fd1498Szrj
603938fd1498Szrj #pragma omp single copyprivate (a, b, c)
604038fd1498Szrj
604138fd1498Szrj Create a new structure to hold copies of 'a', 'b' and 'c' and emit:
604238fd1498Szrj
604338fd1498Szrj {
604438fd1498Szrj if ((copyout_p = GOMP_single_copy_start ()) == NULL)
604538fd1498Szrj {
604638fd1498Szrj BODY;
604738fd1498Szrj copyout.a = a;
604838fd1498Szrj copyout.b = b;
604938fd1498Szrj copyout.c = c;
605038fd1498Szrj GOMP_single_copy_end (©out);
605138fd1498Szrj }
605238fd1498Szrj else
605338fd1498Szrj {
605438fd1498Szrj a = copyout_p->a;
605538fd1498Szrj b = copyout_p->b;
605638fd1498Szrj c = copyout_p->c;
605738fd1498Szrj }
605838fd1498Szrj GOMP_barrier ();
605938fd1498Szrj }
606038fd1498Szrj
606138fd1498Szrj FIXME. It may be better to delay expanding the logic of this until
606238fd1498Szrj pass_expand_omp. The expanded logic may make the job more difficult
606338fd1498Szrj to a synchronization analysis pass. */
606438fd1498Szrj
606538fd1498Szrj static void
lower_omp_single_copy(gomp_single * single_stmt,gimple_seq * pre_p,omp_context * ctx)606638fd1498Szrj lower_omp_single_copy (gomp_single *single_stmt, gimple_seq *pre_p,
606738fd1498Szrj omp_context *ctx)
606838fd1498Szrj {
606938fd1498Szrj tree ptr_type, t, l0, l1, l2, bfn_decl;
607038fd1498Szrj gimple_seq copyin_seq;
607138fd1498Szrj location_t loc = gimple_location (single_stmt);
607238fd1498Szrj
607338fd1498Szrj ctx->sender_decl = create_tmp_var (ctx->record_type, ".omp_copy_o");
607438fd1498Szrj
607538fd1498Szrj ptr_type = build_pointer_type (ctx->record_type);
607638fd1498Szrj ctx->receiver_decl = create_tmp_var (ptr_type, ".omp_copy_i");
607738fd1498Szrj
607838fd1498Szrj l0 = create_artificial_label (loc);
607938fd1498Szrj l1 = create_artificial_label (loc);
608038fd1498Szrj l2 = create_artificial_label (loc);
608138fd1498Szrj
608238fd1498Szrj bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_START);
608338fd1498Szrj t = build_call_expr_loc (loc, bfn_decl, 0);
608438fd1498Szrj t = fold_convert_loc (loc, ptr_type, t);
608538fd1498Szrj gimplify_assign (ctx->receiver_decl, t, pre_p);
608638fd1498Szrj
608738fd1498Szrj t = build2 (EQ_EXPR, boolean_type_node, ctx->receiver_decl,
608838fd1498Szrj build_int_cst (ptr_type, 0));
608938fd1498Szrj t = build3 (COND_EXPR, void_type_node, t,
609038fd1498Szrj build_and_jump (&l0), build_and_jump (&l1));
609138fd1498Szrj gimplify_and_add (t, pre_p);
609238fd1498Szrj
609338fd1498Szrj gimple_seq_add_stmt (pre_p, gimple_build_label (l0));
609438fd1498Szrj
609538fd1498Szrj gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
609638fd1498Szrj
609738fd1498Szrj copyin_seq = NULL;
609838fd1498Szrj lower_copyprivate_clauses (gimple_omp_single_clauses (single_stmt), pre_p,
609938fd1498Szrj ©in_seq, ctx);
610038fd1498Szrj
610138fd1498Szrj t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
610238fd1498Szrj bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_END);
610338fd1498Szrj t = build_call_expr_loc (loc, bfn_decl, 1, t);
610438fd1498Szrj gimplify_and_add (t, pre_p);
610538fd1498Szrj
610638fd1498Szrj t = build_and_jump (&l2);
610738fd1498Szrj gimplify_and_add (t, pre_p);
610838fd1498Szrj
610938fd1498Szrj gimple_seq_add_stmt (pre_p, gimple_build_label (l1));
611038fd1498Szrj
611138fd1498Szrj gimple_seq_add_seq (pre_p, copyin_seq);
611238fd1498Szrj
611338fd1498Szrj gimple_seq_add_stmt (pre_p, gimple_build_label (l2));
611438fd1498Szrj }
611538fd1498Szrj
611638fd1498Szrj
611738fd1498Szrj /* Expand code for an OpenMP single directive. */
611838fd1498Szrj
611938fd1498Szrj static void
lower_omp_single(gimple_stmt_iterator * gsi_p,omp_context * ctx)612038fd1498Szrj lower_omp_single (gimple_stmt_iterator *gsi_p, omp_context *ctx)
612138fd1498Szrj {
612238fd1498Szrj tree block;
612338fd1498Szrj gomp_single *single_stmt = as_a <gomp_single *> (gsi_stmt (*gsi_p));
612438fd1498Szrj gbind *bind;
612538fd1498Szrj gimple_seq bind_body, bind_body_tail = NULL, dlist;
612638fd1498Szrj
612738fd1498Szrj push_gimplify_context ();
612838fd1498Szrj
612938fd1498Szrj block = make_node (BLOCK);
613038fd1498Szrj bind = gimple_build_bind (NULL, NULL, block);
613138fd1498Szrj gsi_replace (gsi_p, bind, true);
613238fd1498Szrj bind_body = NULL;
613338fd1498Szrj dlist = NULL;
613438fd1498Szrj lower_rec_input_clauses (gimple_omp_single_clauses (single_stmt),
613538fd1498Szrj &bind_body, &dlist, ctx, NULL);
613638fd1498Szrj lower_omp (gimple_omp_body_ptr (single_stmt), ctx);
613738fd1498Szrj
613838fd1498Szrj gimple_seq_add_stmt (&bind_body, single_stmt);
613938fd1498Szrj
614038fd1498Szrj if (ctx->record_type)
614138fd1498Szrj lower_omp_single_copy (single_stmt, &bind_body, ctx);
614238fd1498Szrj else
614338fd1498Szrj lower_omp_single_simple (single_stmt, &bind_body);
614438fd1498Szrj
614538fd1498Szrj gimple_omp_set_body (single_stmt, NULL);
614638fd1498Szrj
614738fd1498Szrj gimple_seq_add_seq (&bind_body, dlist);
614838fd1498Szrj
614938fd1498Szrj bind_body = maybe_catch_exception (bind_body);
615038fd1498Szrj
615138fd1498Szrj bool nowait = omp_find_clause (gimple_omp_single_clauses (single_stmt),
615238fd1498Szrj OMP_CLAUSE_NOWAIT) != NULL_TREE;
615338fd1498Szrj gimple *g = gimple_build_omp_return (nowait);
615438fd1498Szrj gimple_seq_add_stmt (&bind_body_tail, g);
615538fd1498Szrj maybe_add_implicit_barrier_cancel (ctx, &bind_body_tail);
615638fd1498Szrj if (ctx->record_type)
615738fd1498Szrj {
615838fd1498Szrj gimple_stmt_iterator gsi = gsi_start (bind_body_tail);
615938fd1498Szrj tree clobber = build_constructor (ctx->record_type, NULL);
616038fd1498Szrj TREE_THIS_VOLATILE (clobber) = 1;
616138fd1498Szrj gsi_insert_after (&gsi, gimple_build_assign (ctx->sender_decl,
616238fd1498Szrj clobber), GSI_SAME_STMT);
616338fd1498Szrj }
616438fd1498Szrj gimple_seq_add_seq (&bind_body, bind_body_tail);
616538fd1498Szrj gimple_bind_set_body (bind, bind_body);
616638fd1498Szrj
616738fd1498Szrj pop_gimplify_context (bind);
616838fd1498Szrj
616938fd1498Szrj gimple_bind_append_vars (bind, ctx->block_vars);
617038fd1498Szrj BLOCK_VARS (block) = ctx->block_vars;
617138fd1498Szrj if (BLOCK_VARS (block))
617238fd1498Szrj TREE_USED (block) = 1;
617338fd1498Szrj }
617438fd1498Szrj
617538fd1498Szrj
617638fd1498Szrj /* Expand code for an OpenMP master directive. */
617738fd1498Szrj
617838fd1498Szrj static void
lower_omp_master(gimple_stmt_iterator * gsi_p,omp_context * ctx)617938fd1498Szrj lower_omp_master (gimple_stmt_iterator *gsi_p, omp_context *ctx)
618038fd1498Szrj {
618138fd1498Szrj tree block, lab = NULL, x, bfn_decl;
618238fd1498Szrj gimple *stmt = gsi_stmt (*gsi_p);
618338fd1498Szrj gbind *bind;
618438fd1498Szrj location_t loc = gimple_location (stmt);
618538fd1498Szrj gimple_seq tseq;
618638fd1498Szrj
618738fd1498Szrj push_gimplify_context ();
618838fd1498Szrj
618938fd1498Szrj block = make_node (BLOCK);
619038fd1498Szrj bind = gimple_build_bind (NULL, NULL, block);
619138fd1498Szrj gsi_replace (gsi_p, bind, true);
619238fd1498Szrj gimple_bind_add_stmt (bind, stmt);
619338fd1498Szrj
619438fd1498Szrj bfn_decl = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
619538fd1498Szrj x = build_call_expr_loc (loc, bfn_decl, 0);
619638fd1498Szrj x = build2 (EQ_EXPR, boolean_type_node, x, integer_zero_node);
619738fd1498Szrj x = build3 (COND_EXPR, void_type_node, x, NULL, build_and_jump (&lab));
619838fd1498Szrj tseq = NULL;
619938fd1498Szrj gimplify_and_add (x, &tseq);
620038fd1498Szrj gimple_bind_add_seq (bind, tseq);
620138fd1498Szrj
620238fd1498Szrj lower_omp (gimple_omp_body_ptr (stmt), ctx);
620338fd1498Szrj gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
620438fd1498Szrj gimple_bind_add_seq (bind, gimple_omp_body (stmt));
620538fd1498Szrj gimple_omp_set_body (stmt, NULL);
620638fd1498Szrj
620738fd1498Szrj gimple_bind_add_stmt (bind, gimple_build_label (lab));
620838fd1498Szrj
620938fd1498Szrj gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
621038fd1498Szrj
621138fd1498Szrj pop_gimplify_context (bind);
621238fd1498Szrj
621338fd1498Szrj gimple_bind_append_vars (bind, ctx->block_vars);
621438fd1498Szrj BLOCK_VARS (block) = ctx->block_vars;
621538fd1498Szrj }
621638fd1498Szrj
621738fd1498Szrj
621838fd1498Szrj /* Expand code for an OpenMP taskgroup directive. */
621938fd1498Szrj
622038fd1498Szrj static void
lower_omp_taskgroup(gimple_stmt_iterator * gsi_p,omp_context * ctx)622138fd1498Szrj lower_omp_taskgroup (gimple_stmt_iterator *gsi_p, omp_context *ctx)
622238fd1498Szrj {
622338fd1498Szrj gimple *stmt = gsi_stmt (*gsi_p);
622438fd1498Szrj gcall *x;
622538fd1498Szrj gbind *bind;
622638fd1498Szrj tree block = make_node (BLOCK);
622738fd1498Szrj
622838fd1498Szrj bind = gimple_build_bind (NULL, NULL, block);
622938fd1498Szrj gsi_replace (gsi_p, bind, true);
623038fd1498Szrj gimple_bind_add_stmt (bind, stmt);
623138fd1498Szrj
623238fd1498Szrj x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_TASKGROUP_START),
623338fd1498Szrj 0);
623438fd1498Szrj gimple_bind_add_stmt (bind, x);
623538fd1498Szrj
623638fd1498Szrj lower_omp (gimple_omp_body_ptr (stmt), ctx);
623738fd1498Szrj gimple_bind_add_seq (bind, gimple_omp_body (stmt));
623838fd1498Szrj gimple_omp_set_body (stmt, NULL);
623938fd1498Szrj
624038fd1498Szrj gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
624138fd1498Szrj
624238fd1498Szrj gimple_bind_append_vars (bind, ctx->block_vars);
624338fd1498Szrj BLOCK_VARS (block) = ctx->block_vars;
624438fd1498Szrj }
624538fd1498Szrj
624638fd1498Szrj
624738fd1498Szrj /* Fold the OMP_ORDERED_CLAUSES for the OMP_ORDERED in STMT if possible. */
624838fd1498Szrj
624938fd1498Szrj static void
lower_omp_ordered_clauses(gimple_stmt_iterator * gsi_p,gomp_ordered * ord_stmt,omp_context * ctx)625038fd1498Szrj lower_omp_ordered_clauses (gimple_stmt_iterator *gsi_p, gomp_ordered *ord_stmt,
625138fd1498Szrj omp_context *ctx)
625238fd1498Szrj {
625338fd1498Szrj struct omp_for_data fd;
625438fd1498Szrj if (!ctx->outer || gimple_code (ctx->outer->stmt) != GIMPLE_OMP_FOR)
625538fd1498Szrj return;
625638fd1498Szrj
625738fd1498Szrj unsigned int len = gimple_omp_for_collapse (ctx->outer->stmt);
625838fd1498Szrj struct omp_for_data_loop *loops = XALLOCAVEC (struct omp_for_data_loop, len);
625938fd1498Szrj omp_extract_for_data (as_a <gomp_for *> (ctx->outer->stmt), &fd, loops);
626038fd1498Szrj if (!fd.ordered)
626138fd1498Szrj return;
626238fd1498Szrj
626338fd1498Szrj tree *list_p = gimple_omp_ordered_clauses_ptr (ord_stmt);
626438fd1498Szrj tree c = gimple_omp_ordered_clauses (ord_stmt);
626538fd1498Szrj if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
626638fd1498Szrj && OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK)
626738fd1498Szrj {
626838fd1498Szrj /* Merge depend clauses from multiple adjacent
626938fd1498Szrj #pragma omp ordered depend(sink:...) constructs
627038fd1498Szrj into one #pragma omp ordered depend(sink:...), so that
627138fd1498Szrj we can optimize them together. */
627238fd1498Szrj gimple_stmt_iterator gsi = *gsi_p;
627338fd1498Szrj gsi_next (&gsi);
627438fd1498Szrj while (!gsi_end_p (gsi))
627538fd1498Szrj {
627638fd1498Szrj gimple *stmt = gsi_stmt (gsi);
627738fd1498Szrj if (is_gimple_debug (stmt)
627838fd1498Szrj || gimple_code (stmt) == GIMPLE_NOP)
627938fd1498Szrj {
628038fd1498Szrj gsi_next (&gsi);
628138fd1498Szrj continue;
628238fd1498Szrj }
628338fd1498Szrj if (gimple_code (stmt) != GIMPLE_OMP_ORDERED)
628438fd1498Szrj break;
628538fd1498Szrj gomp_ordered *ord_stmt2 = as_a <gomp_ordered *> (stmt);
628638fd1498Szrj c = gimple_omp_ordered_clauses (ord_stmt2);
628738fd1498Szrj if (c == NULL_TREE
628838fd1498Szrj || OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND
628938fd1498Szrj || OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_SINK)
629038fd1498Szrj break;
629138fd1498Szrj while (*list_p)
629238fd1498Szrj list_p = &OMP_CLAUSE_CHAIN (*list_p);
629338fd1498Szrj *list_p = c;
629438fd1498Szrj gsi_remove (&gsi, true);
629538fd1498Szrj }
629638fd1498Szrj }
629738fd1498Szrj
629838fd1498Szrj /* Canonicalize sink dependence clauses into one folded clause if
629938fd1498Szrj possible.
630038fd1498Szrj
630138fd1498Szrj The basic algorithm is to create a sink vector whose first
630238fd1498Szrj element is the GCD of all the first elements, and whose remaining
630338fd1498Szrj elements are the minimum of the subsequent columns.
630438fd1498Szrj
630538fd1498Szrj We ignore dependence vectors whose first element is zero because
630638fd1498Szrj such dependencies are known to be executed by the same thread.
630738fd1498Szrj
630838fd1498Szrj We take into account the direction of the loop, so a minimum
630938fd1498Szrj becomes a maximum if the loop is iterating forwards. We also
631038fd1498Szrj ignore sink clauses where the loop direction is unknown, or where
631138fd1498Szrj the offsets are clearly invalid because they are not a multiple
631238fd1498Szrj of the loop increment.
631338fd1498Szrj
631438fd1498Szrj For example:
631538fd1498Szrj
631638fd1498Szrj #pragma omp for ordered(2)
631738fd1498Szrj for (i=0; i < N; ++i)
631838fd1498Szrj for (j=0; j < M; ++j)
631938fd1498Szrj {
632038fd1498Szrj #pragma omp ordered \
632138fd1498Szrj depend(sink:i-8,j-2) \
632238fd1498Szrj depend(sink:i,j-1) \ // Completely ignored because i+0.
632338fd1498Szrj depend(sink:i-4,j-3) \
632438fd1498Szrj depend(sink:i-6,j-4)
632538fd1498Szrj #pragma omp ordered depend(source)
632638fd1498Szrj }
632738fd1498Szrj
632838fd1498Szrj Folded clause is:
632938fd1498Szrj
633038fd1498Szrj depend(sink:-gcd(8,4,6),-min(2,3,4))
633138fd1498Szrj -or-
633238fd1498Szrj depend(sink:-2,-2)
633338fd1498Szrj */
633438fd1498Szrj
633538fd1498Szrj /* FIXME: Computing GCD's where the first element is zero is
633638fd1498Szrj non-trivial in the presence of collapsed loops. Do this later. */
633738fd1498Szrj if (fd.collapse > 1)
633838fd1498Szrj return;
633938fd1498Szrj
634038fd1498Szrj wide_int *folded_deps = XALLOCAVEC (wide_int, 2 * len - 1);
634138fd1498Szrj
634238fd1498Szrj /* wide_int is not a POD so it must be default-constructed. */
634338fd1498Szrj for (unsigned i = 0; i != 2 * len - 1; ++i)
634438fd1498Szrj new (static_cast<void*>(folded_deps + i)) wide_int ();
634538fd1498Szrj
634638fd1498Szrj tree folded_dep = NULL_TREE;
634738fd1498Szrj /* TRUE if the first dimension's offset is negative. */
634838fd1498Szrj bool neg_offset_p = false;
634938fd1498Szrj
635038fd1498Szrj list_p = gimple_omp_ordered_clauses_ptr (ord_stmt);
635138fd1498Szrj unsigned int i;
635238fd1498Szrj while ((c = *list_p) != NULL)
635338fd1498Szrj {
635438fd1498Szrj bool remove = false;
635538fd1498Szrj
635638fd1498Szrj gcc_assert (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND);
635738fd1498Szrj if (OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_SINK)
635838fd1498Szrj goto next_ordered_clause;
635938fd1498Szrj
636038fd1498Szrj tree vec;
636138fd1498Szrj for (vec = OMP_CLAUSE_DECL (c), i = 0;
636238fd1498Szrj vec && TREE_CODE (vec) == TREE_LIST;
636338fd1498Szrj vec = TREE_CHAIN (vec), ++i)
636438fd1498Szrj {
636538fd1498Szrj gcc_assert (i < len);
636638fd1498Szrj
636738fd1498Szrj /* omp_extract_for_data has canonicalized the condition. */
636838fd1498Szrj gcc_assert (fd.loops[i].cond_code == LT_EXPR
636938fd1498Szrj || fd.loops[i].cond_code == GT_EXPR);
637038fd1498Szrj bool forward = fd.loops[i].cond_code == LT_EXPR;
637138fd1498Szrj bool maybe_lexically_later = true;
637238fd1498Szrj
637338fd1498Szrj /* While the committee makes up its mind, bail if we have any
637438fd1498Szrj non-constant steps. */
637538fd1498Szrj if (TREE_CODE (fd.loops[i].step) != INTEGER_CST)
637638fd1498Szrj goto lower_omp_ordered_ret;
637738fd1498Szrj
637838fd1498Szrj tree itype = TREE_TYPE (TREE_VALUE (vec));
637938fd1498Szrj if (POINTER_TYPE_P (itype))
638038fd1498Szrj itype = sizetype;
638138fd1498Szrj wide_int offset = wide_int::from (wi::to_wide (TREE_PURPOSE (vec)),
638238fd1498Szrj TYPE_PRECISION (itype),
638338fd1498Szrj TYPE_SIGN (itype));
638438fd1498Szrj
638538fd1498Szrj /* Ignore invalid offsets that are not multiples of the step. */
638638fd1498Szrj if (!wi::multiple_of_p (wi::abs (offset),
638738fd1498Szrj wi::abs (wi::to_wide (fd.loops[i].step)),
638838fd1498Szrj UNSIGNED))
638938fd1498Szrj {
639038fd1498Szrj warning_at (OMP_CLAUSE_LOCATION (c), 0,
639138fd1498Szrj "ignoring sink clause with offset that is not "
639238fd1498Szrj "a multiple of the loop step");
639338fd1498Szrj remove = true;
639438fd1498Szrj goto next_ordered_clause;
639538fd1498Szrj }
639638fd1498Szrj
639738fd1498Szrj /* Calculate the first dimension. The first dimension of
639838fd1498Szrj the folded dependency vector is the GCD of the first
639938fd1498Szrj elements, while ignoring any first elements whose offset
640038fd1498Szrj is 0. */
640138fd1498Szrj if (i == 0)
640238fd1498Szrj {
640338fd1498Szrj /* Ignore dependence vectors whose first dimension is 0. */
640438fd1498Szrj if (offset == 0)
640538fd1498Szrj {
640638fd1498Szrj remove = true;
640738fd1498Szrj goto next_ordered_clause;
640838fd1498Szrj }
640938fd1498Szrj else
641038fd1498Szrj {
641138fd1498Szrj if (!TYPE_UNSIGNED (itype) && (forward ^ wi::neg_p (offset)))
641238fd1498Szrj {
641338fd1498Szrj error_at (OMP_CLAUSE_LOCATION (c),
641438fd1498Szrj "first offset must be in opposite direction "
641538fd1498Szrj "of loop iterations");
641638fd1498Szrj goto lower_omp_ordered_ret;
641738fd1498Szrj }
641838fd1498Szrj if (forward)
641938fd1498Szrj offset = -offset;
642038fd1498Szrj neg_offset_p = forward;
642138fd1498Szrj /* Initialize the first time around. */
642238fd1498Szrj if (folded_dep == NULL_TREE)
642338fd1498Szrj {
642438fd1498Szrj folded_dep = c;
642538fd1498Szrj folded_deps[0] = offset;
642638fd1498Szrj }
642738fd1498Szrj else
642838fd1498Szrj folded_deps[0] = wi::gcd (folded_deps[0],
642938fd1498Szrj offset, UNSIGNED);
643038fd1498Szrj }
643138fd1498Szrj }
643238fd1498Szrj /* Calculate minimum for the remaining dimensions. */
643338fd1498Szrj else
643438fd1498Szrj {
643538fd1498Szrj folded_deps[len + i - 1] = offset;
643638fd1498Szrj if (folded_dep == c)
643738fd1498Szrj folded_deps[i] = offset;
643838fd1498Szrj else if (maybe_lexically_later
643938fd1498Szrj && !wi::eq_p (folded_deps[i], offset))
644038fd1498Szrj {
644138fd1498Szrj if (forward ^ wi::gts_p (folded_deps[i], offset))
644238fd1498Szrj {
644338fd1498Szrj unsigned int j;
644438fd1498Szrj folded_dep = c;
644538fd1498Szrj for (j = 1; j <= i; j++)
644638fd1498Szrj folded_deps[j] = folded_deps[len + j - 1];
644738fd1498Szrj }
644838fd1498Szrj else
644938fd1498Szrj maybe_lexically_later = false;
645038fd1498Szrj }
645138fd1498Szrj }
645238fd1498Szrj }
645338fd1498Szrj gcc_assert (i == len);
645438fd1498Szrj
645538fd1498Szrj remove = true;
645638fd1498Szrj
645738fd1498Szrj next_ordered_clause:
645838fd1498Szrj if (remove)
645938fd1498Szrj *list_p = OMP_CLAUSE_CHAIN (c);
646038fd1498Szrj else
646138fd1498Szrj list_p = &OMP_CLAUSE_CHAIN (c);
646238fd1498Szrj }
646338fd1498Szrj
646438fd1498Szrj if (folded_dep)
646538fd1498Szrj {
646638fd1498Szrj if (neg_offset_p)
646738fd1498Szrj folded_deps[0] = -folded_deps[0];
646838fd1498Szrj
646938fd1498Szrj tree itype = TREE_TYPE (TREE_VALUE (OMP_CLAUSE_DECL (folded_dep)));
647038fd1498Szrj if (POINTER_TYPE_P (itype))
647138fd1498Szrj itype = sizetype;
647238fd1498Szrj
647338fd1498Szrj TREE_PURPOSE (OMP_CLAUSE_DECL (folded_dep))
647438fd1498Szrj = wide_int_to_tree (itype, folded_deps[0]);
647538fd1498Szrj OMP_CLAUSE_CHAIN (folded_dep) = gimple_omp_ordered_clauses (ord_stmt);
647638fd1498Szrj *gimple_omp_ordered_clauses_ptr (ord_stmt) = folded_dep;
647738fd1498Szrj }
647838fd1498Szrj
647938fd1498Szrj lower_omp_ordered_ret:
648038fd1498Szrj
648138fd1498Szrj /* Ordered without clauses is #pragma omp threads, while we want
648238fd1498Szrj a nop instead if we remove all clauses. */
648338fd1498Szrj if (gimple_omp_ordered_clauses (ord_stmt) == NULL_TREE)
648438fd1498Szrj gsi_replace (gsi_p, gimple_build_nop (), true);
648538fd1498Szrj }
648638fd1498Szrj
648738fd1498Szrj
648838fd1498Szrj /* Expand code for an OpenMP ordered directive. */
648938fd1498Szrj
649038fd1498Szrj static void
lower_omp_ordered(gimple_stmt_iterator * gsi_p,omp_context * ctx)649138fd1498Szrj lower_omp_ordered (gimple_stmt_iterator *gsi_p, omp_context *ctx)
649238fd1498Szrj {
649338fd1498Szrj tree block;
649438fd1498Szrj gimple *stmt = gsi_stmt (*gsi_p), *g;
649538fd1498Szrj gomp_ordered *ord_stmt = as_a <gomp_ordered *> (stmt);
649638fd1498Szrj gcall *x;
649738fd1498Szrj gbind *bind;
649838fd1498Szrj bool simd = omp_find_clause (gimple_omp_ordered_clauses (ord_stmt),
649938fd1498Szrj OMP_CLAUSE_SIMD);
650038fd1498Szrj /* FIXME: this should check presence of OMP_CLAUSE__SIMT_ on the enclosing
650138fd1498Szrj loop. */
650238fd1498Szrj bool maybe_simt
650338fd1498Szrj = simd && omp_maybe_offloaded_ctx (ctx) && omp_max_simt_vf () > 1;
650438fd1498Szrj bool threads = omp_find_clause (gimple_omp_ordered_clauses (ord_stmt),
650538fd1498Szrj OMP_CLAUSE_THREADS);
650638fd1498Szrj
650738fd1498Szrj if (omp_find_clause (gimple_omp_ordered_clauses (ord_stmt),
650838fd1498Szrj OMP_CLAUSE_DEPEND))
650938fd1498Szrj {
651038fd1498Szrj /* FIXME: This is needs to be moved to the expansion to verify various
651138fd1498Szrj conditions only testable on cfg with dominators computed, and also
651238fd1498Szrj all the depend clauses to be merged still might need to be available
651338fd1498Szrj for the runtime checks. */
651438fd1498Szrj if (0)
651538fd1498Szrj lower_omp_ordered_clauses (gsi_p, ord_stmt, ctx);
651638fd1498Szrj return;
651738fd1498Szrj }
651838fd1498Szrj
651938fd1498Szrj push_gimplify_context ();
652038fd1498Szrj
652138fd1498Szrj block = make_node (BLOCK);
652238fd1498Szrj bind = gimple_build_bind (NULL, NULL, block);
652338fd1498Szrj gsi_replace (gsi_p, bind, true);
652438fd1498Szrj gimple_bind_add_stmt (bind, stmt);
652538fd1498Szrj
652638fd1498Szrj if (simd)
652738fd1498Szrj {
652838fd1498Szrj x = gimple_build_call_internal (IFN_GOMP_SIMD_ORDERED_START, 1,
652938fd1498Szrj build_int_cst (NULL_TREE, threads));
653038fd1498Szrj cfun->has_simduid_loops = true;
653138fd1498Szrj }
653238fd1498Szrj else
653338fd1498Szrj x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_START),
653438fd1498Szrj 0);
653538fd1498Szrj gimple_bind_add_stmt (bind, x);
653638fd1498Szrj
653738fd1498Szrj tree counter = NULL_TREE, test = NULL_TREE, body = NULL_TREE;
653838fd1498Szrj if (maybe_simt)
653938fd1498Szrj {
654038fd1498Szrj counter = create_tmp_var (integer_type_node);
654138fd1498Szrj g = gimple_build_call_internal (IFN_GOMP_SIMT_LANE, 0);
654238fd1498Szrj gimple_call_set_lhs (g, counter);
654338fd1498Szrj gimple_bind_add_stmt (bind, g);
654438fd1498Szrj
654538fd1498Szrj body = create_artificial_label (UNKNOWN_LOCATION);
654638fd1498Szrj test = create_artificial_label (UNKNOWN_LOCATION);
654738fd1498Szrj gimple_bind_add_stmt (bind, gimple_build_label (body));
654838fd1498Szrj
654938fd1498Szrj tree simt_pred = create_tmp_var (integer_type_node);
655038fd1498Szrj g = gimple_build_call_internal (IFN_GOMP_SIMT_ORDERED_PRED, 1, counter);
655138fd1498Szrj gimple_call_set_lhs (g, simt_pred);
655238fd1498Szrj gimple_bind_add_stmt (bind, g);
655338fd1498Szrj
655438fd1498Szrj tree t = create_artificial_label (UNKNOWN_LOCATION);
655538fd1498Szrj g = gimple_build_cond (EQ_EXPR, simt_pred, integer_zero_node, t, test);
655638fd1498Szrj gimple_bind_add_stmt (bind, g);
655738fd1498Szrj
655838fd1498Szrj gimple_bind_add_stmt (bind, gimple_build_label (t));
655938fd1498Szrj }
656038fd1498Szrj lower_omp (gimple_omp_body_ptr (stmt), ctx);
656138fd1498Szrj gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
656238fd1498Szrj gimple_bind_add_seq (bind, gimple_omp_body (stmt));
656338fd1498Szrj gimple_omp_set_body (stmt, NULL);
656438fd1498Szrj
656538fd1498Szrj if (maybe_simt)
656638fd1498Szrj {
656738fd1498Szrj gimple_bind_add_stmt (bind, gimple_build_label (test));
656838fd1498Szrj g = gimple_build_assign (counter, MINUS_EXPR, counter, integer_one_node);
656938fd1498Szrj gimple_bind_add_stmt (bind, g);
657038fd1498Szrj
657138fd1498Szrj tree c = build2 (GE_EXPR, boolean_type_node, counter, integer_zero_node);
657238fd1498Szrj tree nonneg = create_tmp_var (integer_type_node);
657338fd1498Szrj gimple_seq tseq = NULL;
657438fd1498Szrj gimplify_assign (nonneg, fold_convert (integer_type_node, c), &tseq);
657538fd1498Szrj gimple_bind_add_seq (bind, tseq);
657638fd1498Szrj
657738fd1498Szrj g = gimple_build_call_internal (IFN_GOMP_SIMT_VOTE_ANY, 1, nonneg);
657838fd1498Szrj gimple_call_set_lhs (g, nonneg);
657938fd1498Szrj gimple_bind_add_stmt (bind, g);
658038fd1498Szrj
658138fd1498Szrj tree end = create_artificial_label (UNKNOWN_LOCATION);
658238fd1498Szrj g = gimple_build_cond (NE_EXPR, nonneg, integer_zero_node, body, end);
658338fd1498Szrj gimple_bind_add_stmt (bind, g);
658438fd1498Szrj
658538fd1498Szrj gimple_bind_add_stmt (bind, gimple_build_label (end));
658638fd1498Szrj }
658738fd1498Szrj if (simd)
658838fd1498Szrj x = gimple_build_call_internal (IFN_GOMP_SIMD_ORDERED_END, 1,
658938fd1498Szrj build_int_cst (NULL_TREE, threads));
659038fd1498Szrj else
659138fd1498Szrj x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_END),
659238fd1498Szrj 0);
659338fd1498Szrj gimple_bind_add_stmt (bind, x);
659438fd1498Szrj
659538fd1498Szrj gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
659638fd1498Szrj
659738fd1498Szrj pop_gimplify_context (bind);
659838fd1498Szrj
659938fd1498Szrj gimple_bind_append_vars (bind, ctx->block_vars);
660038fd1498Szrj BLOCK_VARS (block) = gimple_bind_vars (bind);
660138fd1498Szrj }
660238fd1498Szrj
660338fd1498Szrj
660438fd1498Szrj /* Gimplify a GIMPLE_OMP_CRITICAL statement. This is a relatively simple
660538fd1498Szrj substitution of a couple of function calls. But in the NAMED case,
660638fd1498Szrj requires that languages coordinate a symbol name. It is therefore
660738fd1498Szrj best put here in common code. */
660838fd1498Szrj
660938fd1498Szrj static GTY(()) hash_map<tree, tree> *critical_name_mutexes;
661038fd1498Szrj
661138fd1498Szrj static void
lower_omp_critical(gimple_stmt_iterator * gsi_p,omp_context * ctx)661238fd1498Szrj lower_omp_critical (gimple_stmt_iterator *gsi_p, omp_context *ctx)
661338fd1498Szrj {
661438fd1498Szrj tree block;
661538fd1498Szrj tree name, lock, unlock;
661638fd1498Szrj gomp_critical *stmt = as_a <gomp_critical *> (gsi_stmt (*gsi_p));
661738fd1498Szrj gbind *bind;
661838fd1498Szrj location_t loc = gimple_location (stmt);
661938fd1498Szrj gimple_seq tbody;
662038fd1498Szrj
662138fd1498Szrj name = gimple_omp_critical_name (stmt);
662238fd1498Szrj if (name)
662338fd1498Szrj {
662438fd1498Szrj tree decl;
662538fd1498Szrj
662638fd1498Szrj if (!critical_name_mutexes)
662738fd1498Szrj critical_name_mutexes = hash_map<tree, tree>::create_ggc (10);
662838fd1498Szrj
662938fd1498Szrj tree *n = critical_name_mutexes->get (name);
663038fd1498Szrj if (n == NULL)
663138fd1498Szrj {
663238fd1498Szrj char *new_str;
663338fd1498Szrj
663438fd1498Szrj decl = create_tmp_var_raw (ptr_type_node);
663538fd1498Szrj
663638fd1498Szrj new_str = ACONCAT ((".gomp_critical_user_",
663738fd1498Szrj IDENTIFIER_POINTER (name), NULL));
663838fd1498Szrj DECL_NAME (decl) = get_identifier (new_str);
663938fd1498Szrj TREE_PUBLIC (decl) = 1;
664038fd1498Szrj TREE_STATIC (decl) = 1;
664138fd1498Szrj DECL_COMMON (decl) = 1;
664238fd1498Szrj DECL_ARTIFICIAL (decl) = 1;
664338fd1498Szrj DECL_IGNORED_P (decl) = 1;
664438fd1498Szrj
664538fd1498Szrj varpool_node::finalize_decl (decl);
664638fd1498Szrj
664738fd1498Szrj critical_name_mutexes->put (name, decl);
664838fd1498Szrj }
664938fd1498Szrj else
665038fd1498Szrj decl = *n;
665138fd1498Szrj
665238fd1498Szrj /* If '#pragma omp critical' is inside offloaded region or
665338fd1498Szrj inside function marked as offloadable, the symbol must be
665438fd1498Szrj marked as offloadable too. */
665538fd1498Szrj omp_context *octx;
665638fd1498Szrj if (cgraph_node::get (current_function_decl)->offloadable)
665738fd1498Szrj varpool_node::get_create (decl)->offloadable = 1;
665838fd1498Szrj else
665938fd1498Szrj for (octx = ctx->outer; octx; octx = octx->outer)
666038fd1498Szrj if (is_gimple_omp_offloaded (octx->stmt))
666138fd1498Szrj {
666238fd1498Szrj varpool_node::get_create (decl)->offloadable = 1;
666338fd1498Szrj break;
666438fd1498Szrj }
666538fd1498Szrj
666638fd1498Szrj lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_START);
666738fd1498Szrj lock = build_call_expr_loc (loc, lock, 1,
666838fd1498Szrj build_fold_addr_expr_loc (loc, decl));
666938fd1498Szrj
667038fd1498Szrj unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_END);
667138fd1498Szrj unlock = build_call_expr_loc (loc, unlock, 1,
667238fd1498Szrj build_fold_addr_expr_loc (loc, decl));
667338fd1498Szrj }
667438fd1498Szrj else
667538fd1498Szrj {
667638fd1498Szrj lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_START);
667738fd1498Szrj lock = build_call_expr_loc (loc, lock, 0);
667838fd1498Szrj
667938fd1498Szrj unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_END);
668038fd1498Szrj unlock = build_call_expr_loc (loc, unlock, 0);
668138fd1498Szrj }
668238fd1498Szrj
668338fd1498Szrj push_gimplify_context ();
668438fd1498Szrj
668538fd1498Szrj block = make_node (BLOCK);
668638fd1498Szrj bind = gimple_build_bind (NULL, NULL, block);
668738fd1498Szrj gsi_replace (gsi_p, bind, true);
668838fd1498Szrj gimple_bind_add_stmt (bind, stmt);
668938fd1498Szrj
669038fd1498Szrj tbody = gimple_bind_body (bind);
669138fd1498Szrj gimplify_and_add (lock, &tbody);
669238fd1498Szrj gimple_bind_set_body (bind, tbody);
669338fd1498Szrj
669438fd1498Szrj lower_omp (gimple_omp_body_ptr (stmt), ctx);
669538fd1498Szrj gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
669638fd1498Szrj gimple_bind_add_seq (bind, gimple_omp_body (stmt));
669738fd1498Szrj gimple_omp_set_body (stmt, NULL);
669838fd1498Szrj
669938fd1498Szrj tbody = gimple_bind_body (bind);
670038fd1498Szrj gimplify_and_add (unlock, &tbody);
670138fd1498Szrj gimple_bind_set_body (bind, tbody);
670238fd1498Szrj
670338fd1498Szrj gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
670438fd1498Szrj
670538fd1498Szrj pop_gimplify_context (bind);
670638fd1498Szrj gimple_bind_append_vars (bind, ctx->block_vars);
670738fd1498Szrj BLOCK_VARS (block) = gimple_bind_vars (bind);
670838fd1498Szrj }
670938fd1498Szrj
671038fd1498Szrj /* A subroutine of lower_omp_for. Generate code to emit the predicate
671138fd1498Szrj for a lastprivate clause. Given a loop control predicate of (V
671238fd1498Szrj cond N2), we gate the clause on (!(V cond N2)). The lowered form
671338fd1498Szrj is appended to *DLIST, iterator initialization is appended to
671438fd1498Szrj *BODY_P. */
671538fd1498Szrj
671638fd1498Szrj static void
lower_omp_for_lastprivate(struct omp_for_data * fd,gimple_seq * body_p,gimple_seq * dlist,struct omp_context * ctx)671738fd1498Szrj lower_omp_for_lastprivate (struct omp_for_data *fd, gimple_seq *body_p,
671838fd1498Szrj gimple_seq *dlist, struct omp_context *ctx)
671938fd1498Szrj {
672038fd1498Szrj tree clauses, cond, vinit;
672138fd1498Szrj enum tree_code cond_code;
672238fd1498Szrj gimple_seq stmts;
672338fd1498Szrj
672438fd1498Szrj cond_code = fd->loop.cond_code;
672538fd1498Szrj cond_code = cond_code == LT_EXPR ? GE_EXPR : LE_EXPR;
672638fd1498Szrj
672738fd1498Szrj /* When possible, use a strict equality expression. This can let VRP
672838fd1498Szrj type optimizations deduce the value and remove a copy. */
672938fd1498Szrj if (tree_fits_shwi_p (fd->loop.step))
673038fd1498Szrj {
673138fd1498Szrj HOST_WIDE_INT step = tree_to_shwi (fd->loop.step);
673238fd1498Szrj if (step == 1 || step == -1)
673338fd1498Szrj cond_code = EQ_EXPR;
673438fd1498Szrj }
673538fd1498Szrj
673638fd1498Szrj if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_GRID_LOOP
673738fd1498Szrj || gimple_omp_for_grid_phony (fd->for_stmt))
673838fd1498Szrj cond = omp_grid_lastprivate_predicate (fd);
673938fd1498Szrj else
674038fd1498Szrj {
674138fd1498Szrj tree n2 = fd->loop.n2;
674238fd1498Szrj if (fd->collapse > 1
674338fd1498Szrj && TREE_CODE (n2) != INTEGER_CST
674438fd1498Szrj && gimple_omp_for_combined_into_p (fd->for_stmt))
674538fd1498Szrj {
674638fd1498Szrj struct omp_context *taskreg_ctx = NULL;
674738fd1498Szrj if (gimple_code (ctx->outer->stmt) == GIMPLE_OMP_FOR)
674838fd1498Szrj {
674938fd1498Szrj gomp_for *gfor = as_a <gomp_for *> (ctx->outer->stmt);
675038fd1498Szrj if (gimple_omp_for_kind (gfor) == GF_OMP_FOR_KIND_FOR
675138fd1498Szrj || gimple_omp_for_kind (gfor) == GF_OMP_FOR_KIND_DISTRIBUTE)
675238fd1498Szrj {
675338fd1498Szrj if (gimple_omp_for_combined_into_p (gfor))
675438fd1498Szrj {
675538fd1498Szrj gcc_assert (ctx->outer->outer
675638fd1498Szrj && is_parallel_ctx (ctx->outer->outer));
675738fd1498Szrj taskreg_ctx = ctx->outer->outer;
675838fd1498Szrj }
675938fd1498Szrj else
676038fd1498Szrj {
676138fd1498Szrj struct omp_for_data outer_fd;
676238fd1498Szrj omp_extract_for_data (gfor, &outer_fd, NULL);
676338fd1498Szrj n2 = fold_convert (TREE_TYPE (n2), outer_fd.loop.n2);
676438fd1498Szrj }
676538fd1498Szrj }
676638fd1498Szrj else if (gimple_omp_for_kind (gfor) == GF_OMP_FOR_KIND_TASKLOOP)
676738fd1498Szrj taskreg_ctx = ctx->outer->outer;
676838fd1498Szrj }
676938fd1498Szrj else if (is_taskreg_ctx (ctx->outer))
677038fd1498Szrj taskreg_ctx = ctx->outer;
677138fd1498Szrj if (taskreg_ctx)
677238fd1498Szrj {
677338fd1498Szrj int i;
677438fd1498Szrj tree taskreg_clauses
677538fd1498Szrj = gimple_omp_taskreg_clauses (taskreg_ctx->stmt);
677638fd1498Szrj tree innerc = omp_find_clause (taskreg_clauses,
677738fd1498Szrj OMP_CLAUSE__LOOPTEMP_);
677838fd1498Szrj gcc_assert (innerc);
677938fd1498Szrj for (i = 0; i < fd->collapse; i++)
678038fd1498Szrj {
678138fd1498Szrj innerc = omp_find_clause (OMP_CLAUSE_CHAIN (innerc),
678238fd1498Szrj OMP_CLAUSE__LOOPTEMP_);
678338fd1498Szrj gcc_assert (innerc);
678438fd1498Szrj }
678538fd1498Szrj innerc = omp_find_clause (OMP_CLAUSE_CHAIN (innerc),
678638fd1498Szrj OMP_CLAUSE__LOOPTEMP_);
678738fd1498Szrj if (innerc)
678838fd1498Szrj n2 = fold_convert (TREE_TYPE (n2),
678938fd1498Szrj lookup_decl (OMP_CLAUSE_DECL (innerc),
679038fd1498Szrj taskreg_ctx));
679138fd1498Szrj }
679238fd1498Szrj }
679338fd1498Szrj cond = build2 (cond_code, boolean_type_node, fd->loop.v, n2);
679438fd1498Szrj }
679538fd1498Szrj
679638fd1498Szrj clauses = gimple_omp_for_clauses (fd->for_stmt);
679738fd1498Szrj stmts = NULL;
679838fd1498Szrj lower_lastprivate_clauses (clauses, cond, &stmts, ctx);
679938fd1498Szrj if (!gimple_seq_empty_p (stmts))
680038fd1498Szrj {
680138fd1498Szrj gimple_seq_add_seq (&stmts, *dlist);
680238fd1498Szrj *dlist = stmts;
680338fd1498Szrj
680438fd1498Szrj /* Optimize: v = 0; is usually cheaper than v = some_other_constant. */
680538fd1498Szrj vinit = fd->loop.n1;
680638fd1498Szrj if (cond_code == EQ_EXPR
680738fd1498Szrj && tree_fits_shwi_p (fd->loop.n2)
680838fd1498Szrj && ! integer_zerop (fd->loop.n2))
680938fd1498Szrj vinit = build_int_cst (TREE_TYPE (fd->loop.v), 0);
681038fd1498Szrj else
681138fd1498Szrj vinit = unshare_expr (vinit);
681238fd1498Szrj
681338fd1498Szrj /* Initialize the iterator variable, so that threads that don't execute
681438fd1498Szrj any iterations don't execute the lastprivate clauses by accident. */
681538fd1498Szrj gimplify_assign (fd->loop.v, vinit, body_p);
681638fd1498Szrj }
681738fd1498Szrj }
681838fd1498Szrj
681938fd1498Szrj
682038fd1498Szrj /* Lower code for an OMP loop directive. */
682138fd1498Szrj
682238fd1498Szrj static void
lower_omp_for(gimple_stmt_iterator * gsi_p,omp_context * ctx)682338fd1498Szrj lower_omp_for (gimple_stmt_iterator *gsi_p, omp_context *ctx)
682438fd1498Szrj {
682538fd1498Szrj tree *rhs_p, block;
682638fd1498Szrj struct omp_for_data fd, *fdp = NULL;
682738fd1498Szrj gomp_for *stmt = as_a <gomp_for *> (gsi_stmt (*gsi_p));
682838fd1498Szrj gbind *new_stmt;
682938fd1498Szrj gimple_seq omp_for_body, body, dlist;
683038fd1498Szrj gimple_seq oacc_head = NULL, oacc_tail = NULL;
683138fd1498Szrj size_t i;
683238fd1498Szrj
683338fd1498Szrj push_gimplify_context ();
683438fd1498Szrj
683538fd1498Szrj lower_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
683638fd1498Szrj
683738fd1498Szrj block = make_node (BLOCK);
683838fd1498Szrj new_stmt = gimple_build_bind (NULL, NULL, block);
683938fd1498Szrj /* Replace at gsi right away, so that 'stmt' is no member
684038fd1498Szrj of a sequence anymore as we're going to add to a different
684138fd1498Szrj one below. */
684238fd1498Szrj gsi_replace (gsi_p, new_stmt, true);
684338fd1498Szrj
684438fd1498Szrj /* Move declaration of temporaries in the loop body before we make
684538fd1498Szrj it go away. */
684638fd1498Szrj omp_for_body = gimple_omp_body (stmt);
684738fd1498Szrj if (!gimple_seq_empty_p (omp_for_body)
684838fd1498Szrj && gimple_code (gimple_seq_first_stmt (omp_for_body)) == GIMPLE_BIND)
684938fd1498Szrj {
685038fd1498Szrj gbind *inner_bind
685138fd1498Szrj = as_a <gbind *> (gimple_seq_first_stmt (omp_for_body));
685238fd1498Szrj tree vars = gimple_bind_vars (inner_bind);
685338fd1498Szrj gimple_bind_append_vars (new_stmt, vars);
685438fd1498Szrj /* bind_vars/BLOCK_VARS are being moved to new_stmt/block, don't
685538fd1498Szrj keep them on the inner_bind and it's block. */
685638fd1498Szrj gimple_bind_set_vars (inner_bind, NULL_TREE);
685738fd1498Szrj if (gimple_bind_block (inner_bind))
685838fd1498Szrj BLOCK_VARS (gimple_bind_block (inner_bind)) = NULL_TREE;
685938fd1498Szrj }
686038fd1498Szrj
686138fd1498Szrj if (gimple_omp_for_combined_into_p (stmt))
686238fd1498Szrj {
686338fd1498Szrj omp_extract_for_data (stmt, &fd, NULL);
686438fd1498Szrj fdp = &fd;
686538fd1498Szrj
686638fd1498Szrj /* We need two temporaries with fd.loop.v type (istart/iend)
686738fd1498Szrj and then (fd.collapse - 1) temporaries with the same
686838fd1498Szrj type for count2 ... countN-1 vars if not constant. */
686938fd1498Szrj size_t count = 2;
687038fd1498Szrj tree type = fd.iter_type;
687138fd1498Szrj if (fd.collapse > 1
687238fd1498Szrj && TREE_CODE (fd.loop.n2) != INTEGER_CST)
687338fd1498Szrj count += fd.collapse - 1;
687438fd1498Szrj bool taskreg_for
687538fd1498Szrj = (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR
687638fd1498Szrj || gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_TASKLOOP);
687738fd1498Szrj tree outerc = NULL, *pc = gimple_omp_for_clauses_ptr (stmt);
687838fd1498Szrj tree simtc = NULL;
687938fd1498Szrj tree clauses = *pc;
688038fd1498Szrj if (taskreg_for)
688138fd1498Szrj outerc
688238fd1498Szrj = omp_find_clause (gimple_omp_taskreg_clauses (ctx->outer->stmt),
688338fd1498Szrj OMP_CLAUSE__LOOPTEMP_);
688438fd1498Szrj if (ctx->simt_stmt)
688538fd1498Szrj simtc = omp_find_clause (gimple_omp_for_clauses (ctx->simt_stmt),
688638fd1498Szrj OMP_CLAUSE__LOOPTEMP_);
688738fd1498Szrj for (i = 0; i < count; i++)
688838fd1498Szrj {
688938fd1498Szrj tree temp;
689038fd1498Szrj if (taskreg_for)
689138fd1498Szrj {
689238fd1498Szrj gcc_assert (outerc);
689338fd1498Szrj temp = lookup_decl (OMP_CLAUSE_DECL (outerc), ctx->outer);
689438fd1498Szrj outerc = omp_find_clause (OMP_CLAUSE_CHAIN (outerc),
689538fd1498Szrj OMP_CLAUSE__LOOPTEMP_);
689638fd1498Szrj }
689738fd1498Szrj else
689838fd1498Szrj {
689938fd1498Szrj /* If there are 2 adjacent SIMD stmts, one with _simt_
690038fd1498Szrj clause, another without, make sure they have the same
690138fd1498Szrj decls in _looptemp_ clauses, because the outer stmt
690238fd1498Szrj they are combined into will look up just one inner_stmt. */
690338fd1498Szrj if (ctx->simt_stmt)
690438fd1498Szrj temp = OMP_CLAUSE_DECL (simtc);
690538fd1498Szrj else
690638fd1498Szrj temp = create_tmp_var (type);
690738fd1498Szrj insert_decl_map (&ctx->outer->cb, temp, temp);
690838fd1498Szrj }
690938fd1498Szrj *pc = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__LOOPTEMP_);
691038fd1498Szrj OMP_CLAUSE_DECL (*pc) = temp;
691138fd1498Szrj pc = &OMP_CLAUSE_CHAIN (*pc);
691238fd1498Szrj if (ctx->simt_stmt)
691338fd1498Szrj simtc = omp_find_clause (OMP_CLAUSE_CHAIN (simtc),
691438fd1498Szrj OMP_CLAUSE__LOOPTEMP_);
691538fd1498Szrj }
691638fd1498Szrj *pc = clauses;
691738fd1498Szrj }
691838fd1498Szrj
691938fd1498Szrj /* The pre-body and input clauses go before the lowered GIMPLE_OMP_FOR. */
692038fd1498Szrj dlist = NULL;
692138fd1498Szrj body = NULL;
692238fd1498Szrj lower_rec_input_clauses (gimple_omp_for_clauses (stmt), &body, &dlist, ctx,
692338fd1498Szrj fdp);
692438fd1498Szrj gimple_seq_add_seq (&body, gimple_omp_for_pre_body (stmt));
692538fd1498Szrj
692638fd1498Szrj lower_omp (gimple_omp_body_ptr (stmt), ctx);
692738fd1498Szrj
692838fd1498Szrj /* Lower the header expressions. At this point, we can assume that
692938fd1498Szrj the header is of the form:
693038fd1498Szrj
693138fd1498Szrj #pragma omp for (V = VAL1; V {<|>|<=|>=} VAL2; V = V [+-] VAL3)
693238fd1498Szrj
693338fd1498Szrj We just need to make sure that VAL1, VAL2 and VAL3 are lowered
693438fd1498Szrj using the .omp_data_s mapping, if needed. */
693538fd1498Szrj for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
693638fd1498Szrj {
693738fd1498Szrj rhs_p = gimple_omp_for_initial_ptr (stmt, i);
693838fd1498Szrj if (!is_gimple_min_invariant (*rhs_p))
693938fd1498Szrj *rhs_p = get_formal_tmp_var (*rhs_p, &body);
694038fd1498Szrj else if (TREE_CODE (*rhs_p) == ADDR_EXPR)
694138fd1498Szrj recompute_tree_invariant_for_addr_expr (*rhs_p);
694238fd1498Szrj
694338fd1498Szrj rhs_p = gimple_omp_for_final_ptr (stmt, i);
694438fd1498Szrj if (!is_gimple_min_invariant (*rhs_p))
694538fd1498Szrj *rhs_p = get_formal_tmp_var (*rhs_p, &body);
694638fd1498Szrj else if (TREE_CODE (*rhs_p) == ADDR_EXPR)
694738fd1498Szrj recompute_tree_invariant_for_addr_expr (*rhs_p);
694838fd1498Szrj
694938fd1498Szrj rhs_p = &TREE_OPERAND (gimple_omp_for_incr (stmt, i), 1);
695038fd1498Szrj if (!is_gimple_min_invariant (*rhs_p))
695138fd1498Szrj *rhs_p = get_formal_tmp_var (*rhs_p, &body);
695238fd1498Szrj }
695338fd1498Szrj
695438fd1498Szrj /* Once lowered, extract the bounds and clauses. */
695538fd1498Szrj omp_extract_for_data (stmt, &fd, NULL);
695638fd1498Szrj
695738fd1498Szrj if (is_gimple_omp_oacc (ctx->stmt)
695838fd1498Szrj && !ctx_in_oacc_kernels_region (ctx))
695938fd1498Szrj lower_oacc_head_tail (gimple_location (stmt),
696038fd1498Szrj gimple_omp_for_clauses (stmt),
696138fd1498Szrj &oacc_head, &oacc_tail, ctx);
696238fd1498Szrj
696338fd1498Szrj /* Add OpenACC partitioning and reduction markers just before the loop. */
696438fd1498Szrj if (oacc_head)
696538fd1498Szrj gimple_seq_add_seq (&body, oacc_head);
696638fd1498Szrj
696738fd1498Szrj lower_omp_for_lastprivate (&fd, &body, &dlist, ctx);
696838fd1498Szrj
696938fd1498Szrj if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR)
697038fd1498Szrj for (tree c = gimple_omp_for_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c))
697138fd1498Szrj if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
697238fd1498Szrj && !OMP_CLAUSE_LINEAR_NO_COPYIN (c))
697338fd1498Szrj {
697438fd1498Szrj OMP_CLAUSE_DECL (c) = lookup_decl (OMP_CLAUSE_DECL (c), ctx);
697538fd1498Szrj if (DECL_P (OMP_CLAUSE_LINEAR_STEP (c)))
697638fd1498Szrj OMP_CLAUSE_LINEAR_STEP (c)
697738fd1498Szrj = maybe_lookup_decl_in_outer_ctx (OMP_CLAUSE_LINEAR_STEP (c),
697838fd1498Szrj ctx);
697938fd1498Szrj }
698038fd1498Szrj
698138fd1498Szrj bool phony_loop = (gimple_omp_for_kind (stmt) != GF_OMP_FOR_KIND_GRID_LOOP
698238fd1498Szrj && gimple_omp_for_grid_phony (stmt));
698338fd1498Szrj if (!phony_loop)
698438fd1498Szrj gimple_seq_add_stmt (&body, stmt);
698538fd1498Szrj gimple_seq_add_seq (&body, gimple_omp_body (stmt));
698638fd1498Szrj
698738fd1498Szrj if (!phony_loop)
698838fd1498Szrj gimple_seq_add_stmt (&body, gimple_build_omp_continue (fd.loop.v,
698938fd1498Szrj fd.loop.v));
699038fd1498Szrj
699138fd1498Szrj /* After the loop, add exit clauses. */
699238fd1498Szrj lower_reduction_clauses (gimple_omp_for_clauses (stmt), &body, ctx);
699338fd1498Szrj
699438fd1498Szrj if (ctx->cancellable)
699538fd1498Szrj gimple_seq_add_stmt (&body, gimple_build_label (ctx->cancel_label));
699638fd1498Szrj
699738fd1498Szrj gimple_seq_add_seq (&body, dlist);
699838fd1498Szrj
699938fd1498Szrj body = maybe_catch_exception (body);
700038fd1498Szrj
700138fd1498Szrj if (!phony_loop)
700238fd1498Szrj {
700338fd1498Szrj /* Region exit marker goes at the end of the loop body. */
700438fd1498Szrj gimple_seq_add_stmt (&body, gimple_build_omp_return (fd.have_nowait));
700538fd1498Szrj maybe_add_implicit_barrier_cancel (ctx, &body);
700638fd1498Szrj }
700738fd1498Szrj
700838fd1498Szrj /* Add OpenACC joining and reduction markers just after the loop. */
700938fd1498Szrj if (oacc_tail)
701038fd1498Szrj gimple_seq_add_seq (&body, oacc_tail);
701138fd1498Szrj
701238fd1498Szrj pop_gimplify_context (new_stmt);
701338fd1498Szrj
701438fd1498Szrj gimple_bind_append_vars (new_stmt, ctx->block_vars);
701538fd1498Szrj maybe_remove_omp_member_access_dummy_vars (new_stmt);
701638fd1498Szrj BLOCK_VARS (block) = gimple_bind_vars (new_stmt);
701738fd1498Szrj if (BLOCK_VARS (block))
701838fd1498Szrj TREE_USED (block) = 1;
701938fd1498Szrj
702038fd1498Szrj gimple_bind_set_body (new_stmt, body);
702138fd1498Szrj gimple_omp_set_body (stmt, NULL);
702238fd1498Szrj gimple_omp_for_set_pre_body (stmt, NULL);
702338fd1498Szrj }
702438fd1498Szrj
702538fd1498Szrj /* Callback for walk_stmts. Check if the current statement only contains
702638fd1498Szrj GIMPLE_OMP_FOR or GIMPLE_OMP_SECTIONS. */
702738fd1498Szrj
702838fd1498Szrj static tree
check_combined_parallel(gimple_stmt_iterator * gsi_p,bool * handled_ops_p,struct walk_stmt_info * wi)702938fd1498Szrj check_combined_parallel (gimple_stmt_iterator *gsi_p,
703038fd1498Szrj bool *handled_ops_p,
703138fd1498Szrj struct walk_stmt_info *wi)
703238fd1498Szrj {
703338fd1498Szrj int *info = (int *) wi->info;
703438fd1498Szrj gimple *stmt = gsi_stmt (*gsi_p);
703538fd1498Szrj
703638fd1498Szrj *handled_ops_p = true;
703738fd1498Szrj switch (gimple_code (stmt))
703838fd1498Szrj {
703938fd1498Szrj WALK_SUBSTMTS;
704038fd1498Szrj
704138fd1498Szrj case GIMPLE_DEBUG:
704238fd1498Szrj break;
704338fd1498Szrj case GIMPLE_OMP_FOR:
704438fd1498Szrj case GIMPLE_OMP_SECTIONS:
704538fd1498Szrj *info = *info == 0 ? 1 : -1;
704638fd1498Szrj break;
704738fd1498Szrj default:
704838fd1498Szrj *info = -1;
704938fd1498Szrj break;
705038fd1498Szrj }
705138fd1498Szrj return NULL;
705238fd1498Szrj }
705338fd1498Szrj
705438fd1498Szrj struct omp_taskcopy_context
705538fd1498Szrj {
705638fd1498Szrj /* This field must be at the beginning, as we do "inheritance": Some
705738fd1498Szrj callback functions for tree-inline.c (e.g., omp_copy_decl)
705838fd1498Szrj receive a copy_body_data pointer that is up-casted to an
705938fd1498Szrj omp_context pointer. */
706038fd1498Szrj copy_body_data cb;
706138fd1498Szrj omp_context *ctx;
706238fd1498Szrj };
706338fd1498Szrj
706438fd1498Szrj static tree
task_copyfn_copy_decl(tree var,copy_body_data * cb)706538fd1498Szrj task_copyfn_copy_decl (tree var, copy_body_data *cb)
706638fd1498Szrj {
706738fd1498Szrj struct omp_taskcopy_context *tcctx = (struct omp_taskcopy_context *) cb;
706838fd1498Szrj
706938fd1498Szrj if (splay_tree_lookup (tcctx->ctx->sfield_map, (splay_tree_key) var))
707038fd1498Szrj return create_tmp_var (TREE_TYPE (var));
707138fd1498Szrj
707238fd1498Szrj return var;
707338fd1498Szrj }
707438fd1498Szrj
707538fd1498Szrj static tree
task_copyfn_remap_type(struct omp_taskcopy_context * tcctx,tree orig_type)707638fd1498Szrj task_copyfn_remap_type (struct omp_taskcopy_context *tcctx, tree orig_type)
707738fd1498Szrj {
707838fd1498Szrj tree name, new_fields = NULL, type, f;
707938fd1498Szrj
708038fd1498Szrj type = lang_hooks.types.make_type (RECORD_TYPE);
708138fd1498Szrj name = DECL_NAME (TYPE_NAME (orig_type));
708238fd1498Szrj name = build_decl (gimple_location (tcctx->ctx->stmt),
708338fd1498Szrj TYPE_DECL, name, type);
708438fd1498Szrj TYPE_NAME (type) = name;
708538fd1498Szrj
708638fd1498Szrj for (f = TYPE_FIELDS (orig_type); f ; f = TREE_CHAIN (f))
708738fd1498Szrj {
708838fd1498Szrj tree new_f = copy_node (f);
708938fd1498Szrj DECL_CONTEXT (new_f) = type;
709038fd1498Szrj TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &tcctx->cb);
709138fd1498Szrj TREE_CHAIN (new_f) = new_fields;
709238fd1498Szrj walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &tcctx->cb, NULL);
709338fd1498Szrj walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r, &tcctx->cb, NULL);
709438fd1498Szrj walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
709538fd1498Szrj &tcctx->cb, NULL);
709638fd1498Szrj new_fields = new_f;
709738fd1498Szrj tcctx->cb.decl_map->put (f, new_f);
709838fd1498Szrj }
709938fd1498Szrj TYPE_FIELDS (type) = nreverse (new_fields);
710038fd1498Szrj layout_type (type);
710138fd1498Szrj return type;
710238fd1498Szrj }
710338fd1498Szrj
710438fd1498Szrj /* Create task copyfn. */
710538fd1498Szrj
710638fd1498Szrj static void
create_task_copyfn(gomp_task * task_stmt,omp_context * ctx)710738fd1498Szrj create_task_copyfn (gomp_task *task_stmt, omp_context *ctx)
710838fd1498Szrj {
710938fd1498Szrj struct function *child_cfun;
711038fd1498Szrj tree child_fn, t, c, src, dst, f, sf, arg, sarg, decl;
711138fd1498Szrj tree record_type, srecord_type, bind, list;
711238fd1498Szrj bool record_needs_remap = false, srecord_needs_remap = false;
711338fd1498Szrj splay_tree_node n;
711438fd1498Szrj struct omp_taskcopy_context tcctx;
711538fd1498Szrj location_t loc = gimple_location (task_stmt);
7116*58e805e6Szrj size_t looptempno = 0;
711738fd1498Szrj
711838fd1498Szrj child_fn = gimple_omp_task_copy_fn (task_stmt);
711938fd1498Szrj child_cfun = DECL_STRUCT_FUNCTION (child_fn);
712038fd1498Szrj gcc_assert (child_cfun->cfg == NULL);
712138fd1498Szrj DECL_SAVED_TREE (child_fn) = alloc_stmt_list ();
712238fd1498Szrj
712338fd1498Szrj /* Reset DECL_CONTEXT on function arguments. */
712438fd1498Szrj for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
712538fd1498Szrj DECL_CONTEXT (t) = child_fn;
712638fd1498Szrj
712738fd1498Szrj /* Populate the function. */
712838fd1498Szrj push_gimplify_context ();
712938fd1498Szrj push_cfun (child_cfun);
713038fd1498Szrj
713138fd1498Szrj bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
713238fd1498Szrj TREE_SIDE_EFFECTS (bind) = 1;
713338fd1498Szrj list = NULL;
713438fd1498Szrj DECL_SAVED_TREE (child_fn) = bind;
713538fd1498Szrj DECL_SOURCE_LOCATION (child_fn) = gimple_location (task_stmt);
713638fd1498Szrj
713738fd1498Szrj /* Remap src and dst argument types if needed. */
713838fd1498Szrj record_type = ctx->record_type;
713938fd1498Szrj srecord_type = ctx->srecord_type;
714038fd1498Szrj for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
714138fd1498Szrj if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
714238fd1498Szrj {
714338fd1498Szrj record_needs_remap = true;
714438fd1498Szrj break;
714538fd1498Szrj }
714638fd1498Szrj for (f = TYPE_FIELDS (srecord_type); f ; f = DECL_CHAIN (f))
714738fd1498Szrj if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
714838fd1498Szrj {
714938fd1498Szrj srecord_needs_remap = true;
715038fd1498Szrj break;
715138fd1498Szrj }
715238fd1498Szrj
715338fd1498Szrj if (record_needs_remap || srecord_needs_remap)
715438fd1498Szrj {
715538fd1498Szrj memset (&tcctx, '\0', sizeof (tcctx));
715638fd1498Szrj tcctx.cb.src_fn = ctx->cb.src_fn;
715738fd1498Szrj tcctx.cb.dst_fn = child_fn;
715838fd1498Szrj tcctx.cb.src_node = cgraph_node::get (tcctx.cb.src_fn);
715938fd1498Szrj gcc_checking_assert (tcctx.cb.src_node);
716038fd1498Szrj tcctx.cb.dst_node = tcctx.cb.src_node;
716138fd1498Szrj tcctx.cb.src_cfun = ctx->cb.src_cfun;
716238fd1498Szrj tcctx.cb.copy_decl = task_copyfn_copy_decl;
716338fd1498Szrj tcctx.cb.eh_lp_nr = 0;
716438fd1498Szrj tcctx.cb.transform_call_graph_edges = CB_CGE_MOVE;
716538fd1498Szrj tcctx.cb.decl_map = new hash_map<tree, tree>;
716638fd1498Szrj tcctx.ctx = ctx;
716738fd1498Szrj
716838fd1498Szrj if (record_needs_remap)
716938fd1498Szrj record_type = task_copyfn_remap_type (&tcctx, record_type);
717038fd1498Szrj if (srecord_needs_remap)
717138fd1498Szrj srecord_type = task_copyfn_remap_type (&tcctx, srecord_type);
717238fd1498Szrj }
717338fd1498Szrj else
717438fd1498Szrj tcctx.cb.decl_map = NULL;
717538fd1498Szrj
717638fd1498Szrj arg = DECL_ARGUMENTS (child_fn);
717738fd1498Szrj TREE_TYPE (arg) = build_pointer_type (record_type);
717838fd1498Szrj sarg = DECL_CHAIN (arg);
717938fd1498Szrj TREE_TYPE (sarg) = build_pointer_type (srecord_type);
718038fd1498Szrj
718138fd1498Szrj /* First pass: initialize temporaries used in record_type and srecord_type
718238fd1498Szrj sizes and field offsets. */
718338fd1498Szrj if (tcctx.cb.decl_map)
718438fd1498Szrj for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
718538fd1498Szrj if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
718638fd1498Szrj {
718738fd1498Szrj tree *p;
718838fd1498Szrj
718938fd1498Szrj decl = OMP_CLAUSE_DECL (c);
719038fd1498Szrj p = tcctx.cb.decl_map->get (decl);
719138fd1498Szrj if (p == NULL)
719238fd1498Szrj continue;
719338fd1498Szrj n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
719438fd1498Szrj sf = (tree) n->value;
719538fd1498Szrj sf = *tcctx.cb.decl_map->get (sf);
719638fd1498Szrj src = build_simple_mem_ref_loc (loc, sarg);
719738fd1498Szrj src = omp_build_component_ref (src, sf);
719838fd1498Szrj t = build2 (MODIFY_EXPR, TREE_TYPE (*p), *p, src);
719938fd1498Szrj append_to_statement_list (t, &list);
720038fd1498Szrj }
720138fd1498Szrj
720238fd1498Szrj /* Second pass: copy shared var pointers and copy construct non-VLA
720338fd1498Szrj firstprivate vars. */
720438fd1498Szrj for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
720538fd1498Szrj switch (OMP_CLAUSE_CODE (c))
720638fd1498Szrj {
720738fd1498Szrj splay_tree_key key;
720838fd1498Szrj case OMP_CLAUSE_SHARED:
720938fd1498Szrj decl = OMP_CLAUSE_DECL (c);
721038fd1498Szrj key = (splay_tree_key) decl;
721138fd1498Szrj if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
721238fd1498Szrj key = (splay_tree_key) &DECL_UID (decl);
721338fd1498Szrj n = splay_tree_lookup (ctx->field_map, key);
721438fd1498Szrj if (n == NULL)
721538fd1498Szrj break;
721638fd1498Szrj f = (tree) n->value;
721738fd1498Szrj if (tcctx.cb.decl_map)
721838fd1498Szrj f = *tcctx.cb.decl_map->get (f);
721938fd1498Szrj n = splay_tree_lookup (ctx->sfield_map, key);
722038fd1498Szrj sf = (tree) n->value;
722138fd1498Szrj if (tcctx.cb.decl_map)
722238fd1498Szrj sf = *tcctx.cb.decl_map->get (sf);
722338fd1498Szrj src = build_simple_mem_ref_loc (loc, sarg);
722438fd1498Szrj src = omp_build_component_ref (src, sf);
722538fd1498Szrj dst = build_simple_mem_ref_loc (loc, arg);
722638fd1498Szrj dst = omp_build_component_ref (dst, f);
722738fd1498Szrj t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
722838fd1498Szrj append_to_statement_list (t, &list);
722938fd1498Szrj break;
7230*58e805e6Szrj case OMP_CLAUSE__LOOPTEMP_:
7231*58e805e6Szrj /* Fields for first two _looptemp_ clauses are initialized by
7232*58e805e6Szrj GOMP_taskloop*, the rest are handled like firstprivate. */
7233*58e805e6Szrj if (looptempno < 2)
7234*58e805e6Szrj {
7235*58e805e6Szrj looptempno++;
7236*58e805e6Szrj break;
7237*58e805e6Szrj }
7238*58e805e6Szrj /* FALLTHRU */
723938fd1498Szrj case OMP_CLAUSE_FIRSTPRIVATE:
724038fd1498Szrj decl = OMP_CLAUSE_DECL (c);
724138fd1498Szrj if (is_variable_sized (decl))
724238fd1498Szrj break;
724338fd1498Szrj n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
724438fd1498Szrj if (n == NULL)
724538fd1498Szrj break;
724638fd1498Szrj f = (tree) n->value;
724738fd1498Szrj if (tcctx.cb.decl_map)
724838fd1498Szrj f = *tcctx.cb.decl_map->get (f);
724938fd1498Szrj n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
725038fd1498Szrj if (n != NULL)
725138fd1498Szrj {
725238fd1498Szrj sf = (tree) n->value;
725338fd1498Szrj if (tcctx.cb.decl_map)
725438fd1498Szrj sf = *tcctx.cb.decl_map->get (sf);
725538fd1498Szrj src = build_simple_mem_ref_loc (loc, sarg);
725638fd1498Szrj src = omp_build_component_ref (src, sf);
725738fd1498Szrj if (use_pointer_for_field (decl, NULL) || omp_is_reference (decl))
725838fd1498Szrj src = build_simple_mem_ref_loc (loc, src);
725938fd1498Szrj }
726038fd1498Szrj else
726138fd1498Szrj src = decl;
726238fd1498Szrj dst = build_simple_mem_ref_loc (loc, arg);
726338fd1498Szrj dst = omp_build_component_ref (dst, f);
7264*58e805e6Szrj if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE__LOOPTEMP_)
7265*58e805e6Szrj t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
7266*58e805e6Szrj else
726738fd1498Szrj t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
726838fd1498Szrj append_to_statement_list (t, &list);
726938fd1498Szrj break;
727038fd1498Szrj case OMP_CLAUSE_PRIVATE:
727138fd1498Szrj if (! OMP_CLAUSE_PRIVATE_OUTER_REF (c))
727238fd1498Szrj break;
727338fd1498Szrj decl = OMP_CLAUSE_DECL (c);
727438fd1498Szrj n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
727538fd1498Szrj f = (tree) n->value;
727638fd1498Szrj if (tcctx.cb.decl_map)
727738fd1498Szrj f = *tcctx.cb.decl_map->get (f);
727838fd1498Szrj n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
727938fd1498Szrj if (n != NULL)
728038fd1498Szrj {
728138fd1498Szrj sf = (tree) n->value;
728238fd1498Szrj if (tcctx.cb.decl_map)
728338fd1498Szrj sf = *tcctx.cb.decl_map->get (sf);
728438fd1498Szrj src = build_simple_mem_ref_loc (loc, sarg);
728538fd1498Szrj src = omp_build_component_ref (src, sf);
728638fd1498Szrj if (use_pointer_for_field (decl, NULL))
728738fd1498Szrj src = build_simple_mem_ref_loc (loc, src);
728838fd1498Szrj }
728938fd1498Szrj else
729038fd1498Szrj src = decl;
729138fd1498Szrj dst = build_simple_mem_ref_loc (loc, arg);
729238fd1498Szrj dst = omp_build_component_ref (dst, f);
729338fd1498Szrj t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
729438fd1498Szrj append_to_statement_list (t, &list);
729538fd1498Szrj break;
729638fd1498Szrj default:
729738fd1498Szrj break;
729838fd1498Szrj }
729938fd1498Szrj
730038fd1498Szrj /* Last pass: handle VLA firstprivates. */
730138fd1498Szrj if (tcctx.cb.decl_map)
730238fd1498Szrj for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
730338fd1498Szrj if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
730438fd1498Szrj {
730538fd1498Szrj tree ind, ptr, df;
730638fd1498Szrj
730738fd1498Szrj decl = OMP_CLAUSE_DECL (c);
730838fd1498Szrj if (!is_variable_sized (decl))
730938fd1498Szrj continue;
731038fd1498Szrj n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
731138fd1498Szrj if (n == NULL)
731238fd1498Szrj continue;
731338fd1498Szrj f = (tree) n->value;
731438fd1498Szrj f = *tcctx.cb.decl_map->get (f);
731538fd1498Szrj gcc_assert (DECL_HAS_VALUE_EXPR_P (decl));
731638fd1498Szrj ind = DECL_VALUE_EXPR (decl);
731738fd1498Szrj gcc_assert (TREE_CODE (ind) == INDIRECT_REF);
731838fd1498Szrj gcc_assert (DECL_P (TREE_OPERAND (ind, 0)));
731938fd1498Szrj n = splay_tree_lookup (ctx->sfield_map,
732038fd1498Szrj (splay_tree_key) TREE_OPERAND (ind, 0));
732138fd1498Szrj sf = (tree) n->value;
732238fd1498Szrj sf = *tcctx.cb.decl_map->get (sf);
732338fd1498Szrj src = build_simple_mem_ref_loc (loc, sarg);
732438fd1498Szrj src = omp_build_component_ref (src, sf);
732538fd1498Szrj src = build_simple_mem_ref_loc (loc, src);
732638fd1498Szrj dst = build_simple_mem_ref_loc (loc, arg);
732738fd1498Szrj dst = omp_build_component_ref (dst, f);
732838fd1498Szrj t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
732938fd1498Szrj append_to_statement_list (t, &list);
733038fd1498Szrj n = splay_tree_lookup (ctx->field_map,
733138fd1498Szrj (splay_tree_key) TREE_OPERAND (ind, 0));
733238fd1498Szrj df = (tree) n->value;
733338fd1498Szrj df = *tcctx.cb.decl_map->get (df);
733438fd1498Szrj ptr = build_simple_mem_ref_loc (loc, arg);
733538fd1498Szrj ptr = omp_build_component_ref (ptr, df);
733638fd1498Szrj t = build2 (MODIFY_EXPR, TREE_TYPE (ptr), ptr,
733738fd1498Szrj build_fold_addr_expr_loc (loc, dst));
733838fd1498Szrj append_to_statement_list (t, &list);
733938fd1498Szrj }
734038fd1498Szrj
734138fd1498Szrj t = build1 (RETURN_EXPR, void_type_node, NULL);
734238fd1498Szrj append_to_statement_list (t, &list);
734338fd1498Szrj
734438fd1498Szrj if (tcctx.cb.decl_map)
734538fd1498Szrj delete tcctx.cb.decl_map;
734638fd1498Szrj pop_gimplify_context (NULL);
734738fd1498Szrj BIND_EXPR_BODY (bind) = list;
734838fd1498Szrj pop_cfun ();
734938fd1498Szrj }
735038fd1498Szrj
735138fd1498Szrj static void
lower_depend_clauses(tree * pclauses,gimple_seq * iseq,gimple_seq * oseq)735238fd1498Szrj lower_depend_clauses (tree *pclauses, gimple_seq *iseq, gimple_seq *oseq)
735338fd1498Szrj {
735438fd1498Szrj tree c, clauses;
735538fd1498Szrj gimple *g;
735638fd1498Szrj size_t n_in = 0, n_out = 0, idx = 2, i;
735738fd1498Szrj
735838fd1498Szrj clauses = omp_find_clause (*pclauses, OMP_CLAUSE_DEPEND);
735938fd1498Szrj gcc_assert (clauses);
736038fd1498Szrj for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
736138fd1498Szrj if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
736238fd1498Szrj switch (OMP_CLAUSE_DEPEND_KIND (c))
736338fd1498Szrj {
736438fd1498Szrj case OMP_CLAUSE_DEPEND_IN:
736538fd1498Szrj n_in++;
736638fd1498Szrj break;
736738fd1498Szrj case OMP_CLAUSE_DEPEND_OUT:
736838fd1498Szrj case OMP_CLAUSE_DEPEND_INOUT:
736938fd1498Szrj n_out++;
737038fd1498Szrj break;
737138fd1498Szrj case OMP_CLAUSE_DEPEND_SOURCE:
737238fd1498Szrj case OMP_CLAUSE_DEPEND_SINK:
737338fd1498Szrj /* FALLTHRU */
737438fd1498Szrj default:
737538fd1498Szrj gcc_unreachable ();
737638fd1498Szrj }
737738fd1498Szrj tree type = build_array_type_nelts (ptr_type_node, n_in + n_out + 2);
737838fd1498Szrj tree array = create_tmp_var (type);
737938fd1498Szrj TREE_ADDRESSABLE (array) = 1;
738038fd1498Szrj tree r = build4 (ARRAY_REF, ptr_type_node, array, size_int (0), NULL_TREE,
738138fd1498Szrj NULL_TREE);
738238fd1498Szrj g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_in + n_out));
738338fd1498Szrj gimple_seq_add_stmt (iseq, g);
738438fd1498Szrj r = build4 (ARRAY_REF, ptr_type_node, array, size_int (1), NULL_TREE,
738538fd1498Szrj NULL_TREE);
738638fd1498Szrj g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_out));
738738fd1498Szrj gimple_seq_add_stmt (iseq, g);
738838fd1498Szrj for (i = 0; i < 2; i++)
738938fd1498Szrj {
739038fd1498Szrj if ((i ? n_in : n_out) == 0)
739138fd1498Szrj continue;
739238fd1498Szrj for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
739338fd1498Szrj if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
739438fd1498Szrj && ((OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_IN) ^ i))
739538fd1498Szrj {
739638fd1498Szrj tree t = OMP_CLAUSE_DECL (c);
739738fd1498Szrj t = fold_convert (ptr_type_node, t);
739838fd1498Szrj gimplify_expr (&t, iseq, NULL, is_gimple_val, fb_rvalue);
739938fd1498Szrj r = build4 (ARRAY_REF, ptr_type_node, array, size_int (idx++),
740038fd1498Szrj NULL_TREE, NULL_TREE);
740138fd1498Szrj g = gimple_build_assign (r, t);
740238fd1498Szrj gimple_seq_add_stmt (iseq, g);
740338fd1498Szrj }
740438fd1498Szrj }
740538fd1498Szrj c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_DEPEND);
740638fd1498Szrj OMP_CLAUSE_DECL (c) = build_fold_addr_expr (array);
740738fd1498Szrj OMP_CLAUSE_CHAIN (c) = *pclauses;
740838fd1498Szrj *pclauses = c;
740938fd1498Szrj tree clobber = build_constructor (type, NULL);
741038fd1498Szrj TREE_THIS_VOLATILE (clobber) = 1;
741138fd1498Szrj g = gimple_build_assign (array, clobber);
741238fd1498Szrj gimple_seq_add_stmt (oseq, g);
741338fd1498Szrj }
741438fd1498Szrj
741538fd1498Szrj /* Lower the OpenMP parallel or task directive in the current statement
741638fd1498Szrj in GSI_P. CTX holds context information for the directive. */
741738fd1498Szrj
741838fd1498Szrj static void
lower_omp_taskreg(gimple_stmt_iterator * gsi_p,omp_context * ctx)741938fd1498Szrj lower_omp_taskreg (gimple_stmt_iterator *gsi_p, omp_context *ctx)
742038fd1498Szrj {
742138fd1498Szrj tree clauses;
742238fd1498Szrj tree child_fn, t;
742338fd1498Szrj gimple *stmt = gsi_stmt (*gsi_p);
742438fd1498Szrj gbind *par_bind, *bind, *dep_bind = NULL;
742538fd1498Szrj gimple_seq par_body, olist, ilist, par_olist, par_rlist, par_ilist, new_body;
742638fd1498Szrj location_t loc = gimple_location (stmt);
742738fd1498Szrj
742838fd1498Szrj clauses = gimple_omp_taskreg_clauses (stmt);
742938fd1498Szrj par_bind
743038fd1498Szrj = as_a <gbind *> (gimple_seq_first_stmt (gimple_omp_body (stmt)));
743138fd1498Szrj par_body = gimple_bind_body (par_bind);
743238fd1498Szrj child_fn = ctx->cb.dst_fn;
743338fd1498Szrj if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
743438fd1498Szrj && !gimple_omp_parallel_combined_p (stmt))
743538fd1498Szrj {
743638fd1498Szrj struct walk_stmt_info wi;
743738fd1498Szrj int ws_num = 0;
743838fd1498Szrj
743938fd1498Szrj memset (&wi, 0, sizeof (wi));
744038fd1498Szrj wi.info = &ws_num;
744138fd1498Szrj wi.val_only = true;
744238fd1498Szrj walk_gimple_seq (par_body, check_combined_parallel, NULL, &wi);
744338fd1498Szrj if (ws_num == 1)
744438fd1498Szrj gimple_omp_parallel_set_combined_p (stmt, true);
744538fd1498Szrj }
744638fd1498Szrj gimple_seq dep_ilist = NULL;
744738fd1498Szrj gimple_seq dep_olist = NULL;
744838fd1498Szrj if (gimple_code (stmt) == GIMPLE_OMP_TASK
744938fd1498Szrj && omp_find_clause (clauses, OMP_CLAUSE_DEPEND))
745038fd1498Szrj {
745138fd1498Szrj push_gimplify_context ();
745238fd1498Szrj dep_bind = gimple_build_bind (NULL, NULL, make_node (BLOCK));
745338fd1498Szrj lower_depend_clauses (gimple_omp_task_clauses_ptr (stmt),
745438fd1498Szrj &dep_ilist, &dep_olist);
745538fd1498Szrj }
745638fd1498Szrj
745738fd1498Szrj if (ctx->srecord_type)
745838fd1498Szrj create_task_copyfn (as_a <gomp_task *> (stmt), ctx);
745938fd1498Szrj
746038fd1498Szrj push_gimplify_context ();
746138fd1498Szrj
746238fd1498Szrj par_olist = NULL;
746338fd1498Szrj par_ilist = NULL;
746438fd1498Szrj par_rlist = NULL;
746538fd1498Szrj bool phony_construct = gimple_code (stmt) == GIMPLE_OMP_PARALLEL
746638fd1498Szrj && gimple_omp_parallel_grid_phony (as_a <gomp_parallel *> (stmt));
746738fd1498Szrj if (phony_construct && ctx->record_type)
746838fd1498Szrj {
746938fd1498Szrj gcc_checking_assert (!ctx->receiver_decl);
747038fd1498Szrj ctx->receiver_decl = create_tmp_var
747138fd1498Szrj (build_reference_type (ctx->record_type), ".omp_rec");
747238fd1498Szrj }
747338fd1498Szrj lower_rec_input_clauses (clauses, &par_ilist, &par_olist, ctx, NULL);
747438fd1498Szrj lower_omp (&par_body, ctx);
747538fd1498Szrj if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL)
747638fd1498Szrj lower_reduction_clauses (clauses, &par_rlist, ctx);
747738fd1498Szrj
747838fd1498Szrj /* Declare all the variables created by mapping and the variables
747938fd1498Szrj declared in the scope of the parallel body. */
748038fd1498Szrj record_vars_into (ctx->block_vars, child_fn);
748138fd1498Szrj maybe_remove_omp_member_access_dummy_vars (par_bind);
748238fd1498Szrj record_vars_into (gimple_bind_vars (par_bind), child_fn);
748338fd1498Szrj
748438fd1498Szrj if (ctx->record_type)
748538fd1498Szrj {
748638fd1498Szrj ctx->sender_decl
748738fd1498Szrj = create_tmp_var (ctx->srecord_type ? ctx->srecord_type
748838fd1498Szrj : ctx->record_type, ".omp_data_o");
748938fd1498Szrj DECL_NAMELESS (ctx->sender_decl) = 1;
749038fd1498Szrj TREE_ADDRESSABLE (ctx->sender_decl) = 1;
749138fd1498Szrj gimple_omp_taskreg_set_data_arg (stmt, ctx->sender_decl);
749238fd1498Szrj }
749338fd1498Szrj
749438fd1498Szrj olist = NULL;
749538fd1498Szrj ilist = NULL;
749638fd1498Szrj lower_send_clauses (clauses, &ilist, &olist, ctx);
749738fd1498Szrj lower_send_shared_vars (&ilist, &olist, ctx);
749838fd1498Szrj
749938fd1498Szrj if (ctx->record_type)
750038fd1498Szrj {
750138fd1498Szrj tree clobber = build_constructor (TREE_TYPE (ctx->sender_decl), NULL);
750238fd1498Szrj TREE_THIS_VOLATILE (clobber) = 1;
750338fd1498Szrj gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
750438fd1498Szrj clobber));
750538fd1498Szrj }
750638fd1498Szrj
750738fd1498Szrj /* Once all the expansions are done, sequence all the different
750838fd1498Szrj fragments inside gimple_omp_body. */
750938fd1498Szrj
751038fd1498Szrj new_body = NULL;
751138fd1498Szrj
751238fd1498Szrj if (ctx->record_type)
751338fd1498Szrj {
751438fd1498Szrj t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
751538fd1498Szrj /* fixup_child_record_type might have changed receiver_decl's type. */
751638fd1498Szrj t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
751738fd1498Szrj gimple_seq_add_stmt (&new_body,
751838fd1498Szrj gimple_build_assign (ctx->receiver_decl, t));
751938fd1498Szrj }
752038fd1498Szrj
752138fd1498Szrj gimple_seq_add_seq (&new_body, par_ilist);
752238fd1498Szrj gimple_seq_add_seq (&new_body, par_body);
752338fd1498Szrj gimple_seq_add_seq (&new_body, par_rlist);
752438fd1498Szrj if (ctx->cancellable)
752538fd1498Szrj gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
752638fd1498Szrj gimple_seq_add_seq (&new_body, par_olist);
752738fd1498Szrj new_body = maybe_catch_exception (new_body);
752838fd1498Szrj if (gimple_code (stmt) == GIMPLE_OMP_TASK)
752938fd1498Szrj gimple_seq_add_stmt (&new_body,
753038fd1498Szrj gimple_build_omp_continue (integer_zero_node,
753138fd1498Szrj integer_zero_node));
753238fd1498Szrj if (!phony_construct)
753338fd1498Szrj {
753438fd1498Szrj gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
753538fd1498Szrj gimple_omp_set_body (stmt, new_body);
753638fd1498Szrj }
753738fd1498Szrj
753838fd1498Szrj bind = gimple_build_bind (NULL, NULL, gimple_bind_block (par_bind));
753938fd1498Szrj gsi_replace (gsi_p, dep_bind ? dep_bind : bind, true);
754038fd1498Szrj gimple_bind_add_seq (bind, ilist);
754138fd1498Szrj if (!phony_construct)
754238fd1498Szrj gimple_bind_add_stmt (bind, stmt);
754338fd1498Szrj else
754438fd1498Szrj gimple_bind_add_seq (bind, new_body);
754538fd1498Szrj gimple_bind_add_seq (bind, olist);
754638fd1498Szrj
754738fd1498Szrj pop_gimplify_context (NULL);
754838fd1498Szrj
754938fd1498Szrj if (dep_bind)
755038fd1498Szrj {
755138fd1498Szrj gimple_bind_add_seq (dep_bind, dep_ilist);
755238fd1498Szrj gimple_bind_add_stmt (dep_bind, bind);
755338fd1498Szrj gimple_bind_add_seq (dep_bind, dep_olist);
755438fd1498Szrj pop_gimplify_context (dep_bind);
755538fd1498Szrj }
755638fd1498Szrj }
755738fd1498Szrj
755838fd1498Szrj /* Lower the GIMPLE_OMP_TARGET in the current statement
755938fd1498Szrj in GSI_P. CTX holds context information for the directive. */
756038fd1498Szrj
756138fd1498Szrj static void
lower_omp_target(gimple_stmt_iterator * gsi_p,omp_context * ctx)756238fd1498Szrj lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
756338fd1498Szrj {
756438fd1498Szrj tree clauses;
756538fd1498Szrj tree child_fn, t, c;
756638fd1498Szrj gomp_target *stmt = as_a <gomp_target *> (gsi_stmt (*gsi_p));
756738fd1498Szrj gbind *tgt_bind, *bind, *dep_bind = NULL;
756838fd1498Szrj gimple_seq tgt_body, olist, ilist, fplist, new_body;
756938fd1498Szrj location_t loc = gimple_location (stmt);
757038fd1498Szrj bool offloaded, data_region;
757138fd1498Szrj unsigned int map_cnt = 0;
757238fd1498Szrj
757338fd1498Szrj offloaded = is_gimple_omp_offloaded (stmt);
757438fd1498Szrj switch (gimple_omp_target_kind (stmt))
757538fd1498Szrj {
757638fd1498Szrj case GF_OMP_TARGET_KIND_REGION:
757738fd1498Szrj case GF_OMP_TARGET_KIND_UPDATE:
757838fd1498Szrj case GF_OMP_TARGET_KIND_ENTER_DATA:
757938fd1498Szrj case GF_OMP_TARGET_KIND_EXIT_DATA:
758038fd1498Szrj case GF_OMP_TARGET_KIND_OACC_PARALLEL:
758138fd1498Szrj case GF_OMP_TARGET_KIND_OACC_KERNELS:
758238fd1498Szrj case GF_OMP_TARGET_KIND_OACC_UPDATE:
758338fd1498Szrj case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
758438fd1498Szrj case GF_OMP_TARGET_KIND_OACC_DECLARE:
758538fd1498Szrj data_region = false;
758638fd1498Szrj break;
758738fd1498Szrj case GF_OMP_TARGET_KIND_DATA:
758838fd1498Szrj case GF_OMP_TARGET_KIND_OACC_DATA:
758938fd1498Szrj case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
759038fd1498Szrj data_region = true;
759138fd1498Szrj break;
759238fd1498Szrj default:
759338fd1498Szrj gcc_unreachable ();
759438fd1498Szrj }
759538fd1498Szrj
759638fd1498Szrj clauses = gimple_omp_target_clauses (stmt);
759738fd1498Szrj
759838fd1498Szrj gimple_seq dep_ilist = NULL;
759938fd1498Szrj gimple_seq dep_olist = NULL;
760038fd1498Szrj if (omp_find_clause (clauses, OMP_CLAUSE_DEPEND))
760138fd1498Szrj {
760238fd1498Szrj push_gimplify_context ();
760338fd1498Szrj dep_bind = gimple_build_bind (NULL, NULL, make_node (BLOCK));
760438fd1498Szrj lower_depend_clauses (gimple_omp_target_clauses_ptr (stmt),
760538fd1498Szrj &dep_ilist, &dep_olist);
760638fd1498Szrj }
760738fd1498Szrj
760838fd1498Szrj tgt_bind = NULL;
760938fd1498Szrj tgt_body = NULL;
761038fd1498Szrj if (offloaded)
761138fd1498Szrj {
761238fd1498Szrj tgt_bind = gimple_seq_first_stmt_as_a_bind (gimple_omp_body (stmt));
761338fd1498Szrj tgt_body = gimple_bind_body (tgt_bind);
761438fd1498Szrj }
761538fd1498Szrj else if (data_region)
761638fd1498Szrj tgt_body = gimple_omp_body (stmt);
761738fd1498Szrj child_fn = ctx->cb.dst_fn;
761838fd1498Szrj
761938fd1498Szrj push_gimplify_context ();
762038fd1498Szrj fplist = NULL;
762138fd1498Szrj
762238fd1498Szrj for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
762338fd1498Szrj switch (OMP_CLAUSE_CODE (c))
762438fd1498Szrj {
762538fd1498Szrj tree var, x;
762638fd1498Szrj
762738fd1498Szrj default:
762838fd1498Szrj break;
762938fd1498Szrj case OMP_CLAUSE_MAP:
763038fd1498Szrj #if CHECKING_P
763138fd1498Szrj /* First check what we're prepared to handle in the following. */
763238fd1498Szrj switch (OMP_CLAUSE_MAP_KIND (c))
763338fd1498Szrj {
763438fd1498Szrj case GOMP_MAP_ALLOC:
763538fd1498Szrj case GOMP_MAP_TO:
763638fd1498Szrj case GOMP_MAP_FROM:
763738fd1498Szrj case GOMP_MAP_TOFROM:
763838fd1498Szrj case GOMP_MAP_POINTER:
763938fd1498Szrj case GOMP_MAP_TO_PSET:
764038fd1498Szrj case GOMP_MAP_DELETE:
764138fd1498Szrj case GOMP_MAP_RELEASE:
764238fd1498Szrj case GOMP_MAP_ALWAYS_TO:
764338fd1498Szrj case GOMP_MAP_ALWAYS_FROM:
764438fd1498Szrj case GOMP_MAP_ALWAYS_TOFROM:
764538fd1498Szrj case GOMP_MAP_FIRSTPRIVATE_POINTER:
764638fd1498Szrj case GOMP_MAP_FIRSTPRIVATE_REFERENCE:
764738fd1498Szrj case GOMP_MAP_STRUCT:
764838fd1498Szrj case GOMP_MAP_ALWAYS_POINTER:
764938fd1498Szrj break;
765038fd1498Szrj case GOMP_MAP_FORCE_ALLOC:
765138fd1498Szrj case GOMP_MAP_FORCE_TO:
765238fd1498Szrj case GOMP_MAP_FORCE_FROM:
765338fd1498Szrj case GOMP_MAP_FORCE_TOFROM:
765438fd1498Szrj case GOMP_MAP_FORCE_PRESENT:
765538fd1498Szrj case GOMP_MAP_FORCE_DEVICEPTR:
765638fd1498Szrj case GOMP_MAP_DEVICE_RESIDENT:
765738fd1498Szrj case GOMP_MAP_LINK:
765838fd1498Szrj gcc_assert (is_gimple_omp_oacc (stmt));
765938fd1498Szrj break;
766038fd1498Szrj default:
766138fd1498Szrj gcc_unreachable ();
766238fd1498Szrj }
766338fd1498Szrj #endif
766438fd1498Szrj /* FALLTHRU */
766538fd1498Szrj case OMP_CLAUSE_TO:
766638fd1498Szrj case OMP_CLAUSE_FROM:
766738fd1498Szrj oacc_firstprivate:
766838fd1498Szrj var = OMP_CLAUSE_DECL (c);
766938fd1498Szrj if (!DECL_P (var))
767038fd1498Szrj {
767138fd1498Szrj if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP
767238fd1498Szrj || (!OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
767338fd1498Szrj && (OMP_CLAUSE_MAP_KIND (c)
767438fd1498Szrj != GOMP_MAP_FIRSTPRIVATE_POINTER)))
767538fd1498Szrj map_cnt++;
767638fd1498Szrj continue;
767738fd1498Szrj }
767838fd1498Szrj
767938fd1498Szrj if (DECL_SIZE (var)
768038fd1498Szrj && TREE_CODE (DECL_SIZE (var)) != INTEGER_CST)
768138fd1498Szrj {
768238fd1498Szrj tree var2 = DECL_VALUE_EXPR (var);
768338fd1498Szrj gcc_assert (TREE_CODE (var2) == INDIRECT_REF);
768438fd1498Szrj var2 = TREE_OPERAND (var2, 0);
768538fd1498Szrj gcc_assert (DECL_P (var2));
768638fd1498Szrj var = var2;
768738fd1498Szrj }
768838fd1498Szrj
768938fd1498Szrj if (offloaded
769038fd1498Szrj && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
769138fd1498Szrj && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
769238fd1498Szrj || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_REFERENCE))
769338fd1498Szrj {
769438fd1498Szrj if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
769538fd1498Szrj {
769638fd1498Szrj if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx))
769738fd1498Szrj && varpool_node::get_create (var)->offloadable)
769838fd1498Szrj continue;
769938fd1498Szrj
770038fd1498Szrj tree type = build_pointer_type (TREE_TYPE (var));
770138fd1498Szrj tree new_var = lookup_decl (var, ctx);
770238fd1498Szrj x = create_tmp_var_raw (type, get_name (new_var));
770338fd1498Szrj gimple_add_tmp_var (x);
770438fd1498Szrj x = build_simple_mem_ref (x);
770538fd1498Szrj SET_DECL_VALUE_EXPR (new_var, x);
770638fd1498Szrj DECL_HAS_VALUE_EXPR_P (new_var) = 1;
770738fd1498Szrj }
770838fd1498Szrj continue;
770938fd1498Szrj }
771038fd1498Szrj
771138fd1498Szrj if (!maybe_lookup_field (var, ctx))
771238fd1498Szrj continue;
771338fd1498Szrj
771438fd1498Szrj /* Don't remap oacc parallel reduction variables, because the
771538fd1498Szrj intermediate result must be local to each gang. */
771638fd1498Szrj if (offloaded && !(OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
771738fd1498Szrj && OMP_CLAUSE_MAP_IN_REDUCTION (c)))
771838fd1498Szrj {
771938fd1498Szrj x = build_receiver_ref (var, true, ctx);
772038fd1498Szrj tree new_var = lookup_decl (var, ctx);
772138fd1498Szrj
772238fd1498Szrj if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
772338fd1498Szrj && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
772438fd1498Szrj && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
772538fd1498Szrj && TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
772638fd1498Szrj x = build_simple_mem_ref (x);
772738fd1498Szrj if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
772838fd1498Szrj {
772938fd1498Szrj gcc_assert (is_gimple_omp_oacc (ctx->stmt));
773038fd1498Szrj if (omp_is_reference (new_var))
773138fd1498Szrj {
773238fd1498Szrj /* Create a local object to hold the instance
773338fd1498Szrj value. */
773438fd1498Szrj tree type = TREE_TYPE (TREE_TYPE (new_var));
773538fd1498Szrj const char *id = IDENTIFIER_POINTER (DECL_NAME (new_var));
773638fd1498Szrj tree inst = create_tmp_var (type, id);
773738fd1498Szrj gimplify_assign (inst, fold_indirect_ref (x), &fplist);
773838fd1498Szrj x = build_fold_addr_expr (inst);
773938fd1498Szrj }
774038fd1498Szrj gimplify_assign (new_var, x, &fplist);
774138fd1498Szrj }
774238fd1498Szrj else if (DECL_P (new_var))
774338fd1498Szrj {
774438fd1498Szrj SET_DECL_VALUE_EXPR (new_var, x);
774538fd1498Szrj DECL_HAS_VALUE_EXPR_P (new_var) = 1;
774638fd1498Szrj }
774738fd1498Szrj else
774838fd1498Szrj gcc_unreachable ();
774938fd1498Szrj }
775038fd1498Szrj map_cnt++;
775138fd1498Szrj break;
775238fd1498Szrj
775338fd1498Szrj case OMP_CLAUSE_FIRSTPRIVATE:
775438fd1498Szrj if (is_oacc_parallel (ctx))
775538fd1498Szrj goto oacc_firstprivate;
775638fd1498Szrj map_cnt++;
775738fd1498Szrj var = OMP_CLAUSE_DECL (c);
775838fd1498Szrj if (!omp_is_reference (var)
775938fd1498Szrj && !is_gimple_reg_type (TREE_TYPE (var)))
776038fd1498Szrj {
776138fd1498Szrj tree new_var = lookup_decl (var, ctx);
776238fd1498Szrj if (is_variable_sized (var))
776338fd1498Szrj {
776438fd1498Szrj tree pvar = DECL_VALUE_EXPR (var);
776538fd1498Szrj gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
776638fd1498Szrj pvar = TREE_OPERAND (pvar, 0);
776738fd1498Szrj gcc_assert (DECL_P (pvar));
776838fd1498Szrj tree new_pvar = lookup_decl (pvar, ctx);
776938fd1498Szrj x = build_fold_indirect_ref (new_pvar);
777038fd1498Szrj TREE_THIS_NOTRAP (x) = 1;
777138fd1498Szrj }
777238fd1498Szrj else
777338fd1498Szrj x = build_receiver_ref (var, true, ctx);
777438fd1498Szrj SET_DECL_VALUE_EXPR (new_var, x);
777538fd1498Szrj DECL_HAS_VALUE_EXPR_P (new_var) = 1;
777638fd1498Szrj }
777738fd1498Szrj break;
777838fd1498Szrj
777938fd1498Szrj case OMP_CLAUSE_PRIVATE:
778038fd1498Szrj if (is_gimple_omp_oacc (ctx->stmt))
778138fd1498Szrj break;
778238fd1498Szrj var = OMP_CLAUSE_DECL (c);
778338fd1498Szrj if (is_variable_sized (var))
778438fd1498Szrj {
778538fd1498Szrj tree new_var = lookup_decl (var, ctx);
778638fd1498Szrj tree pvar = DECL_VALUE_EXPR (var);
778738fd1498Szrj gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
778838fd1498Szrj pvar = TREE_OPERAND (pvar, 0);
778938fd1498Szrj gcc_assert (DECL_P (pvar));
779038fd1498Szrj tree new_pvar = lookup_decl (pvar, ctx);
779138fd1498Szrj x = build_fold_indirect_ref (new_pvar);
779238fd1498Szrj TREE_THIS_NOTRAP (x) = 1;
779338fd1498Szrj SET_DECL_VALUE_EXPR (new_var, x);
779438fd1498Szrj DECL_HAS_VALUE_EXPR_P (new_var) = 1;
779538fd1498Szrj }
779638fd1498Szrj break;
779738fd1498Szrj
779838fd1498Szrj case OMP_CLAUSE_USE_DEVICE_PTR:
779938fd1498Szrj case OMP_CLAUSE_IS_DEVICE_PTR:
780038fd1498Szrj var = OMP_CLAUSE_DECL (c);
780138fd1498Szrj map_cnt++;
780238fd1498Szrj if (is_variable_sized (var))
780338fd1498Szrj {
780438fd1498Szrj tree new_var = lookup_decl (var, ctx);
780538fd1498Szrj tree pvar = DECL_VALUE_EXPR (var);
780638fd1498Szrj gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
780738fd1498Szrj pvar = TREE_OPERAND (pvar, 0);
780838fd1498Szrj gcc_assert (DECL_P (pvar));
780938fd1498Szrj tree new_pvar = lookup_decl (pvar, ctx);
781038fd1498Szrj x = build_fold_indirect_ref (new_pvar);
781138fd1498Szrj TREE_THIS_NOTRAP (x) = 1;
781238fd1498Szrj SET_DECL_VALUE_EXPR (new_var, x);
781338fd1498Szrj DECL_HAS_VALUE_EXPR_P (new_var) = 1;
781438fd1498Szrj }
781538fd1498Szrj else if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
781638fd1498Szrj {
781738fd1498Szrj tree new_var = lookup_decl (var, ctx);
781838fd1498Szrj tree type = build_pointer_type (TREE_TYPE (var));
781938fd1498Szrj x = create_tmp_var_raw (type, get_name (new_var));
782038fd1498Szrj gimple_add_tmp_var (x);
782138fd1498Szrj x = build_simple_mem_ref (x);
782238fd1498Szrj SET_DECL_VALUE_EXPR (new_var, x);
782338fd1498Szrj DECL_HAS_VALUE_EXPR_P (new_var) = 1;
782438fd1498Szrj }
782538fd1498Szrj else
782638fd1498Szrj {
782738fd1498Szrj tree new_var = lookup_decl (var, ctx);
782838fd1498Szrj x = create_tmp_var_raw (TREE_TYPE (new_var), get_name (new_var));
782938fd1498Szrj gimple_add_tmp_var (x);
783038fd1498Szrj SET_DECL_VALUE_EXPR (new_var, x);
783138fd1498Szrj DECL_HAS_VALUE_EXPR_P (new_var) = 1;
783238fd1498Szrj }
783338fd1498Szrj break;
783438fd1498Szrj }
783538fd1498Szrj
783638fd1498Szrj if (offloaded)
783738fd1498Szrj {
783838fd1498Szrj target_nesting_level++;
783938fd1498Szrj lower_omp (&tgt_body, ctx);
784038fd1498Szrj target_nesting_level--;
784138fd1498Szrj }
784238fd1498Szrj else if (data_region)
784338fd1498Szrj lower_omp (&tgt_body, ctx);
784438fd1498Szrj
784538fd1498Szrj if (offloaded)
784638fd1498Szrj {
784738fd1498Szrj /* Declare all the variables created by mapping and the variables
784838fd1498Szrj declared in the scope of the target body. */
784938fd1498Szrj record_vars_into (ctx->block_vars, child_fn);
785038fd1498Szrj maybe_remove_omp_member_access_dummy_vars (tgt_bind);
785138fd1498Szrj record_vars_into (gimple_bind_vars (tgt_bind), child_fn);
785238fd1498Szrj }
785338fd1498Szrj
785438fd1498Szrj olist = NULL;
785538fd1498Szrj ilist = NULL;
785638fd1498Szrj if (ctx->record_type)
785738fd1498Szrj {
785838fd1498Szrj ctx->sender_decl
785938fd1498Szrj = create_tmp_var (ctx->record_type, ".omp_data_arr");
786038fd1498Szrj DECL_NAMELESS (ctx->sender_decl) = 1;
786138fd1498Szrj TREE_ADDRESSABLE (ctx->sender_decl) = 1;
786238fd1498Szrj t = make_tree_vec (3);
786338fd1498Szrj TREE_VEC_ELT (t, 0) = ctx->sender_decl;
786438fd1498Szrj TREE_VEC_ELT (t, 1)
786538fd1498Szrj = create_tmp_var (build_array_type_nelts (size_type_node, map_cnt),
786638fd1498Szrj ".omp_data_sizes");
786738fd1498Szrj DECL_NAMELESS (TREE_VEC_ELT (t, 1)) = 1;
786838fd1498Szrj TREE_ADDRESSABLE (TREE_VEC_ELT (t, 1)) = 1;
786938fd1498Szrj TREE_STATIC (TREE_VEC_ELT (t, 1)) = 1;
787038fd1498Szrj tree tkind_type = short_unsigned_type_node;
787138fd1498Szrj int talign_shift = 8;
787238fd1498Szrj TREE_VEC_ELT (t, 2)
787338fd1498Szrj = create_tmp_var (build_array_type_nelts (tkind_type, map_cnt),
787438fd1498Szrj ".omp_data_kinds");
787538fd1498Szrj DECL_NAMELESS (TREE_VEC_ELT (t, 2)) = 1;
787638fd1498Szrj TREE_ADDRESSABLE (TREE_VEC_ELT (t, 2)) = 1;
787738fd1498Szrj TREE_STATIC (TREE_VEC_ELT (t, 2)) = 1;
787838fd1498Szrj gimple_omp_target_set_data_arg (stmt, t);
787938fd1498Szrj
788038fd1498Szrj vec<constructor_elt, va_gc> *vsize;
788138fd1498Szrj vec<constructor_elt, va_gc> *vkind;
788238fd1498Szrj vec_alloc (vsize, map_cnt);
788338fd1498Szrj vec_alloc (vkind, map_cnt);
788438fd1498Szrj unsigned int map_idx = 0;
788538fd1498Szrj
788638fd1498Szrj for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
788738fd1498Szrj switch (OMP_CLAUSE_CODE (c))
788838fd1498Szrj {
788938fd1498Szrj tree ovar, nc, s, purpose, var, x, type;
789038fd1498Szrj unsigned int talign;
789138fd1498Szrj
789238fd1498Szrj default:
789338fd1498Szrj break;
789438fd1498Szrj
789538fd1498Szrj case OMP_CLAUSE_MAP:
789638fd1498Szrj case OMP_CLAUSE_TO:
789738fd1498Szrj case OMP_CLAUSE_FROM:
789838fd1498Szrj oacc_firstprivate_map:
789938fd1498Szrj nc = c;
790038fd1498Szrj ovar = OMP_CLAUSE_DECL (c);
790138fd1498Szrj if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
790238fd1498Szrj && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
790338fd1498Szrj || (OMP_CLAUSE_MAP_KIND (c)
790438fd1498Szrj == GOMP_MAP_FIRSTPRIVATE_REFERENCE)))
790538fd1498Szrj break;
790638fd1498Szrj if (!DECL_P (ovar))
790738fd1498Szrj {
790838fd1498Szrj if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
790938fd1498Szrj && OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
791038fd1498Szrj {
791138fd1498Szrj gcc_checking_assert (OMP_CLAUSE_DECL (OMP_CLAUSE_CHAIN (c))
791238fd1498Szrj == get_base_address (ovar));
791338fd1498Szrj nc = OMP_CLAUSE_CHAIN (c);
791438fd1498Szrj ovar = OMP_CLAUSE_DECL (nc);
791538fd1498Szrj }
791638fd1498Szrj else
791738fd1498Szrj {
791838fd1498Szrj tree x = build_sender_ref (ovar, ctx);
791938fd1498Szrj tree v
792038fd1498Szrj = build_fold_addr_expr_with_type (ovar, ptr_type_node);
792138fd1498Szrj gimplify_assign (x, v, &ilist);
792238fd1498Szrj nc = NULL_TREE;
792338fd1498Szrj }
792438fd1498Szrj }
792538fd1498Szrj else
792638fd1498Szrj {
792738fd1498Szrj if (DECL_SIZE (ovar)
792838fd1498Szrj && TREE_CODE (DECL_SIZE (ovar)) != INTEGER_CST)
792938fd1498Szrj {
793038fd1498Szrj tree ovar2 = DECL_VALUE_EXPR (ovar);
793138fd1498Szrj gcc_assert (TREE_CODE (ovar2) == INDIRECT_REF);
793238fd1498Szrj ovar2 = TREE_OPERAND (ovar2, 0);
793338fd1498Szrj gcc_assert (DECL_P (ovar2));
793438fd1498Szrj ovar = ovar2;
793538fd1498Szrj }
793638fd1498Szrj if (!maybe_lookup_field (ovar, ctx))
793738fd1498Szrj continue;
793838fd1498Szrj }
793938fd1498Szrj
794038fd1498Szrj talign = TYPE_ALIGN_UNIT (TREE_TYPE (ovar));
794138fd1498Szrj if (DECL_P (ovar) && DECL_ALIGN_UNIT (ovar) > talign)
794238fd1498Szrj talign = DECL_ALIGN_UNIT (ovar);
794338fd1498Szrj if (nc)
794438fd1498Szrj {
794538fd1498Szrj var = lookup_decl_in_outer_ctx (ovar, ctx);
794638fd1498Szrj x = build_sender_ref (ovar, ctx);
794738fd1498Szrj
794838fd1498Szrj if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
794938fd1498Szrj && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
795038fd1498Szrj && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
795138fd1498Szrj && TREE_CODE (TREE_TYPE (ovar)) == ARRAY_TYPE)
795238fd1498Szrj {
795338fd1498Szrj gcc_assert (offloaded);
795438fd1498Szrj tree avar
795538fd1498Szrj = create_tmp_var (TREE_TYPE (TREE_TYPE (x)));
795638fd1498Szrj mark_addressable (avar);
795738fd1498Szrj gimplify_assign (avar, build_fold_addr_expr (var), &ilist);
795838fd1498Szrj talign = DECL_ALIGN_UNIT (avar);
795938fd1498Szrj avar = build_fold_addr_expr (avar);
796038fd1498Szrj gimplify_assign (x, avar, &ilist);
796138fd1498Szrj }
796238fd1498Szrj else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
796338fd1498Szrj {
796438fd1498Szrj gcc_assert (is_gimple_omp_oacc (ctx->stmt));
796538fd1498Szrj if (!omp_is_reference (var))
796638fd1498Szrj {
796738fd1498Szrj if (is_gimple_reg (var)
796838fd1498Szrj && OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c))
796938fd1498Szrj TREE_NO_WARNING (var) = 1;
797038fd1498Szrj var = build_fold_addr_expr (var);
797138fd1498Szrj }
797238fd1498Szrj else
797338fd1498Szrj talign = TYPE_ALIGN_UNIT (TREE_TYPE (TREE_TYPE (ovar)));
797438fd1498Szrj gimplify_assign (x, var, &ilist);
797538fd1498Szrj }
797638fd1498Szrj else if (is_gimple_reg (var))
797738fd1498Szrj {
797838fd1498Szrj gcc_assert (offloaded);
797938fd1498Szrj tree avar = create_tmp_var (TREE_TYPE (var));
798038fd1498Szrj mark_addressable (avar);
798138fd1498Szrj enum gomp_map_kind map_kind = OMP_CLAUSE_MAP_KIND (c);
798238fd1498Szrj if (GOMP_MAP_COPY_TO_P (map_kind)
798338fd1498Szrj || map_kind == GOMP_MAP_POINTER
798438fd1498Szrj || map_kind == GOMP_MAP_TO_PSET
798538fd1498Szrj || map_kind == GOMP_MAP_FORCE_DEVICEPTR)
798638fd1498Szrj {
798738fd1498Szrj /* If we need to initialize a temporary
798838fd1498Szrj with VAR because it is not addressable, and
798938fd1498Szrj the variable hasn't been initialized yet, then
799038fd1498Szrj we'll get a warning for the store to avar.
799138fd1498Szrj Don't warn in that case, the mapping might
799238fd1498Szrj be implicit. */
799338fd1498Szrj TREE_NO_WARNING (var) = 1;
799438fd1498Szrj gimplify_assign (avar, var, &ilist);
799538fd1498Szrj }
799638fd1498Szrj avar = build_fold_addr_expr (avar);
799738fd1498Szrj gimplify_assign (x, avar, &ilist);
799838fd1498Szrj if ((GOMP_MAP_COPY_FROM_P (map_kind)
799938fd1498Szrj || map_kind == GOMP_MAP_FORCE_DEVICEPTR)
800038fd1498Szrj && !TYPE_READONLY (TREE_TYPE (var)))
800138fd1498Szrj {
800238fd1498Szrj x = unshare_expr (x);
800338fd1498Szrj x = build_simple_mem_ref (x);
800438fd1498Szrj gimplify_assign (var, x, &olist);
800538fd1498Szrj }
800638fd1498Szrj }
800738fd1498Szrj else
800838fd1498Szrj {
800938fd1498Szrj var = build_fold_addr_expr (var);
801038fd1498Szrj gimplify_assign (x, var, &ilist);
801138fd1498Szrj }
801238fd1498Szrj }
801338fd1498Szrj s = NULL_TREE;
801438fd1498Szrj if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
801538fd1498Szrj {
801638fd1498Szrj gcc_checking_assert (is_gimple_omp_oacc (ctx->stmt));
801738fd1498Szrj s = TREE_TYPE (ovar);
801838fd1498Szrj if (TREE_CODE (s) == REFERENCE_TYPE)
801938fd1498Szrj s = TREE_TYPE (s);
802038fd1498Szrj s = TYPE_SIZE_UNIT (s);
802138fd1498Szrj }
802238fd1498Szrj else
802338fd1498Szrj s = OMP_CLAUSE_SIZE (c);
802438fd1498Szrj if (s == NULL_TREE)
802538fd1498Szrj s = TYPE_SIZE_UNIT (TREE_TYPE (ovar));
802638fd1498Szrj s = fold_convert (size_type_node, s);
802738fd1498Szrj purpose = size_int (map_idx++);
802838fd1498Szrj CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
802938fd1498Szrj if (TREE_CODE (s) != INTEGER_CST)
803038fd1498Szrj TREE_STATIC (TREE_VEC_ELT (t, 1)) = 0;
803138fd1498Szrj
803238fd1498Szrj unsigned HOST_WIDE_INT tkind, tkind_zero;
803338fd1498Szrj switch (OMP_CLAUSE_CODE (c))
803438fd1498Szrj {
803538fd1498Szrj case OMP_CLAUSE_MAP:
803638fd1498Szrj tkind = OMP_CLAUSE_MAP_KIND (c);
803738fd1498Szrj tkind_zero = tkind;
803838fd1498Szrj if (OMP_CLAUSE_MAP_MAYBE_ZERO_LENGTH_ARRAY_SECTION (c))
803938fd1498Szrj switch (tkind)
804038fd1498Szrj {
804138fd1498Szrj case GOMP_MAP_ALLOC:
804238fd1498Szrj case GOMP_MAP_TO:
804338fd1498Szrj case GOMP_MAP_FROM:
804438fd1498Szrj case GOMP_MAP_TOFROM:
804538fd1498Szrj case GOMP_MAP_ALWAYS_TO:
804638fd1498Szrj case GOMP_MAP_ALWAYS_FROM:
804738fd1498Szrj case GOMP_MAP_ALWAYS_TOFROM:
804838fd1498Szrj case GOMP_MAP_RELEASE:
804938fd1498Szrj case GOMP_MAP_FORCE_TO:
805038fd1498Szrj case GOMP_MAP_FORCE_FROM:
805138fd1498Szrj case GOMP_MAP_FORCE_TOFROM:
805238fd1498Szrj case GOMP_MAP_FORCE_PRESENT:
805338fd1498Szrj tkind_zero = GOMP_MAP_ZERO_LEN_ARRAY_SECTION;
805438fd1498Szrj break;
805538fd1498Szrj case GOMP_MAP_DELETE:
805638fd1498Szrj tkind_zero = GOMP_MAP_DELETE_ZERO_LEN_ARRAY_SECTION;
805738fd1498Szrj default:
805838fd1498Szrj break;
805938fd1498Szrj }
806038fd1498Szrj if (tkind_zero != tkind)
806138fd1498Szrj {
806238fd1498Szrj if (integer_zerop (s))
806338fd1498Szrj tkind = tkind_zero;
806438fd1498Szrj else if (integer_nonzerop (s))
806538fd1498Szrj tkind_zero = tkind;
806638fd1498Szrj }
806738fd1498Szrj break;
806838fd1498Szrj case OMP_CLAUSE_FIRSTPRIVATE:
806938fd1498Szrj gcc_checking_assert (is_gimple_omp_oacc (ctx->stmt));
807038fd1498Szrj tkind = GOMP_MAP_TO;
807138fd1498Szrj tkind_zero = tkind;
807238fd1498Szrj break;
807338fd1498Szrj case OMP_CLAUSE_TO:
807438fd1498Szrj tkind = GOMP_MAP_TO;
807538fd1498Szrj tkind_zero = tkind;
807638fd1498Szrj break;
807738fd1498Szrj case OMP_CLAUSE_FROM:
807838fd1498Szrj tkind = GOMP_MAP_FROM;
807938fd1498Szrj tkind_zero = tkind;
808038fd1498Szrj break;
808138fd1498Szrj default:
808238fd1498Szrj gcc_unreachable ();
808338fd1498Szrj }
808438fd1498Szrj gcc_checking_assert (tkind
808538fd1498Szrj < (HOST_WIDE_INT_C (1U) << talign_shift));
808638fd1498Szrj gcc_checking_assert (tkind_zero
808738fd1498Szrj < (HOST_WIDE_INT_C (1U) << talign_shift));
808838fd1498Szrj talign = ceil_log2 (talign);
808938fd1498Szrj tkind |= talign << talign_shift;
809038fd1498Szrj tkind_zero |= talign << talign_shift;
809138fd1498Szrj gcc_checking_assert (tkind
809238fd1498Szrj <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
809338fd1498Szrj gcc_checking_assert (tkind_zero
809438fd1498Szrj <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
809538fd1498Szrj if (tkind == tkind_zero)
809638fd1498Szrj x = build_int_cstu (tkind_type, tkind);
809738fd1498Szrj else
809838fd1498Szrj {
809938fd1498Szrj TREE_STATIC (TREE_VEC_ELT (t, 2)) = 0;
810038fd1498Szrj x = build3 (COND_EXPR, tkind_type,
810138fd1498Szrj fold_build2 (EQ_EXPR, boolean_type_node,
810238fd1498Szrj unshare_expr (s), size_zero_node),
810338fd1498Szrj build_int_cstu (tkind_type, tkind_zero),
810438fd1498Szrj build_int_cstu (tkind_type, tkind));
810538fd1498Szrj }
810638fd1498Szrj CONSTRUCTOR_APPEND_ELT (vkind, purpose, x);
810738fd1498Szrj if (nc && nc != c)
810838fd1498Szrj c = nc;
810938fd1498Szrj break;
811038fd1498Szrj
811138fd1498Szrj case OMP_CLAUSE_FIRSTPRIVATE:
811238fd1498Szrj if (is_oacc_parallel (ctx))
811338fd1498Szrj goto oacc_firstprivate_map;
811438fd1498Szrj ovar = OMP_CLAUSE_DECL (c);
811538fd1498Szrj if (omp_is_reference (ovar))
811638fd1498Szrj talign = TYPE_ALIGN_UNIT (TREE_TYPE (TREE_TYPE (ovar)));
811738fd1498Szrj else
811838fd1498Szrj talign = DECL_ALIGN_UNIT (ovar);
811938fd1498Szrj var = lookup_decl_in_outer_ctx (ovar, ctx);
812038fd1498Szrj x = build_sender_ref (ovar, ctx);
812138fd1498Szrj tkind = GOMP_MAP_FIRSTPRIVATE;
812238fd1498Szrj type = TREE_TYPE (ovar);
812338fd1498Szrj if (omp_is_reference (ovar))
812438fd1498Szrj type = TREE_TYPE (type);
812538fd1498Szrj if ((INTEGRAL_TYPE_P (type)
812638fd1498Szrj && TYPE_PRECISION (type) <= POINTER_SIZE)
812738fd1498Szrj || TREE_CODE (type) == POINTER_TYPE)
812838fd1498Szrj {
812938fd1498Szrj tkind = GOMP_MAP_FIRSTPRIVATE_INT;
813038fd1498Szrj tree t = var;
813138fd1498Szrj if (omp_is_reference (var))
813238fd1498Szrj t = build_simple_mem_ref (var);
813338fd1498Szrj else if (OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c))
813438fd1498Szrj TREE_NO_WARNING (var) = 1;
813538fd1498Szrj if (TREE_CODE (type) != POINTER_TYPE)
813638fd1498Szrj t = fold_convert (pointer_sized_int_node, t);
813738fd1498Szrj t = fold_convert (TREE_TYPE (x), t);
813838fd1498Szrj gimplify_assign (x, t, &ilist);
813938fd1498Szrj }
814038fd1498Szrj else if (omp_is_reference (var))
814138fd1498Szrj gimplify_assign (x, var, &ilist);
814238fd1498Szrj else if (is_gimple_reg (var))
814338fd1498Szrj {
814438fd1498Szrj tree avar = create_tmp_var (TREE_TYPE (var));
814538fd1498Szrj mark_addressable (avar);
814638fd1498Szrj if (OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c))
814738fd1498Szrj TREE_NO_WARNING (var) = 1;
814838fd1498Szrj gimplify_assign (avar, var, &ilist);
814938fd1498Szrj avar = build_fold_addr_expr (avar);
815038fd1498Szrj gimplify_assign (x, avar, &ilist);
815138fd1498Szrj }
815238fd1498Szrj else
815338fd1498Szrj {
815438fd1498Szrj var = build_fold_addr_expr (var);
815538fd1498Szrj gimplify_assign (x, var, &ilist);
815638fd1498Szrj }
815738fd1498Szrj if (tkind == GOMP_MAP_FIRSTPRIVATE_INT)
815838fd1498Szrj s = size_int (0);
815938fd1498Szrj else if (omp_is_reference (ovar))
816038fd1498Szrj s = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (ovar)));
816138fd1498Szrj else
816238fd1498Szrj s = TYPE_SIZE_UNIT (TREE_TYPE (ovar));
816338fd1498Szrj s = fold_convert (size_type_node, s);
816438fd1498Szrj purpose = size_int (map_idx++);
816538fd1498Szrj CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
816638fd1498Szrj if (TREE_CODE (s) != INTEGER_CST)
816738fd1498Szrj TREE_STATIC (TREE_VEC_ELT (t, 1)) = 0;
816838fd1498Szrj
816938fd1498Szrj gcc_checking_assert (tkind
817038fd1498Szrj < (HOST_WIDE_INT_C (1U) << talign_shift));
817138fd1498Szrj talign = ceil_log2 (talign);
817238fd1498Szrj tkind |= talign << talign_shift;
817338fd1498Szrj gcc_checking_assert (tkind
817438fd1498Szrj <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
817538fd1498Szrj CONSTRUCTOR_APPEND_ELT (vkind, purpose,
817638fd1498Szrj build_int_cstu (tkind_type, tkind));
817738fd1498Szrj break;
817838fd1498Szrj
817938fd1498Szrj case OMP_CLAUSE_USE_DEVICE_PTR:
818038fd1498Szrj case OMP_CLAUSE_IS_DEVICE_PTR:
818138fd1498Szrj ovar = OMP_CLAUSE_DECL (c);
818238fd1498Szrj var = lookup_decl_in_outer_ctx (ovar, ctx);
818338fd1498Szrj x = build_sender_ref (ovar, ctx);
818438fd1498Szrj if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_USE_DEVICE_PTR)
818538fd1498Szrj tkind = GOMP_MAP_USE_DEVICE_PTR;
818638fd1498Szrj else
818738fd1498Szrj tkind = GOMP_MAP_FIRSTPRIVATE_INT;
818838fd1498Szrj type = TREE_TYPE (ovar);
818938fd1498Szrj if (TREE_CODE (type) == ARRAY_TYPE)
819038fd1498Szrj var = build_fold_addr_expr (var);
819138fd1498Szrj else
819238fd1498Szrj {
819338fd1498Szrj if (omp_is_reference (ovar))
819438fd1498Szrj {
819538fd1498Szrj type = TREE_TYPE (type);
819638fd1498Szrj if (TREE_CODE (type) != ARRAY_TYPE)
819738fd1498Szrj var = build_simple_mem_ref (var);
819838fd1498Szrj var = fold_convert (TREE_TYPE (x), var);
819938fd1498Szrj }
820038fd1498Szrj }
820138fd1498Szrj gimplify_assign (x, var, &ilist);
820238fd1498Szrj s = size_int (0);
820338fd1498Szrj purpose = size_int (map_idx++);
820438fd1498Szrj CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
820538fd1498Szrj gcc_checking_assert (tkind
820638fd1498Szrj < (HOST_WIDE_INT_C (1U) << talign_shift));
820738fd1498Szrj gcc_checking_assert (tkind
820838fd1498Szrj <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
820938fd1498Szrj CONSTRUCTOR_APPEND_ELT (vkind, purpose,
821038fd1498Szrj build_int_cstu (tkind_type, tkind));
821138fd1498Szrj break;
821238fd1498Szrj }
821338fd1498Szrj
821438fd1498Szrj gcc_assert (map_idx == map_cnt);
821538fd1498Szrj
821638fd1498Szrj DECL_INITIAL (TREE_VEC_ELT (t, 1))
821738fd1498Szrj = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)), vsize);
821838fd1498Szrj DECL_INITIAL (TREE_VEC_ELT (t, 2))
821938fd1498Szrj = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 2)), vkind);
822038fd1498Szrj for (int i = 1; i <= 2; i++)
822138fd1498Szrj if (!TREE_STATIC (TREE_VEC_ELT (t, i)))
822238fd1498Szrj {
822338fd1498Szrj gimple_seq initlist = NULL;
822438fd1498Szrj force_gimple_operand (build1 (DECL_EXPR, void_type_node,
822538fd1498Szrj TREE_VEC_ELT (t, i)),
822638fd1498Szrj &initlist, true, NULL_TREE);
822738fd1498Szrj gimple_seq_add_seq (&ilist, initlist);
822838fd1498Szrj
822938fd1498Szrj tree clobber = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, i)),
823038fd1498Szrj NULL);
823138fd1498Szrj TREE_THIS_VOLATILE (clobber) = 1;
823238fd1498Szrj gimple_seq_add_stmt (&olist,
823338fd1498Szrj gimple_build_assign (TREE_VEC_ELT (t, i),
823438fd1498Szrj clobber));
823538fd1498Szrj }
823638fd1498Szrj
823738fd1498Szrj tree clobber = build_constructor (ctx->record_type, NULL);
823838fd1498Szrj TREE_THIS_VOLATILE (clobber) = 1;
823938fd1498Szrj gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
824038fd1498Szrj clobber));
824138fd1498Szrj }
824238fd1498Szrj
824338fd1498Szrj /* Once all the expansions are done, sequence all the different
824438fd1498Szrj fragments inside gimple_omp_body. */
824538fd1498Szrj
824638fd1498Szrj new_body = NULL;
824738fd1498Szrj
824838fd1498Szrj if (offloaded
824938fd1498Szrj && ctx->record_type)
825038fd1498Szrj {
825138fd1498Szrj t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
825238fd1498Szrj /* fixup_child_record_type might have changed receiver_decl's type. */
825338fd1498Szrj t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
825438fd1498Szrj gimple_seq_add_stmt (&new_body,
825538fd1498Szrj gimple_build_assign (ctx->receiver_decl, t));
825638fd1498Szrj }
825738fd1498Szrj gimple_seq_add_seq (&new_body, fplist);
825838fd1498Szrj
825938fd1498Szrj if (offloaded || data_region)
826038fd1498Szrj {
826138fd1498Szrj tree prev = NULL_TREE;
826238fd1498Szrj for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
826338fd1498Szrj switch (OMP_CLAUSE_CODE (c))
826438fd1498Szrj {
826538fd1498Szrj tree var, x;
826638fd1498Szrj default:
826738fd1498Szrj break;
826838fd1498Szrj case OMP_CLAUSE_FIRSTPRIVATE:
826938fd1498Szrj if (is_gimple_omp_oacc (ctx->stmt))
827038fd1498Szrj break;
827138fd1498Szrj var = OMP_CLAUSE_DECL (c);
827238fd1498Szrj if (omp_is_reference (var)
827338fd1498Szrj || is_gimple_reg_type (TREE_TYPE (var)))
827438fd1498Szrj {
827538fd1498Szrj tree new_var = lookup_decl (var, ctx);
827638fd1498Szrj tree type;
827738fd1498Szrj type = TREE_TYPE (var);
827838fd1498Szrj if (omp_is_reference (var))
827938fd1498Szrj type = TREE_TYPE (type);
828038fd1498Szrj if ((INTEGRAL_TYPE_P (type)
828138fd1498Szrj && TYPE_PRECISION (type) <= POINTER_SIZE)
828238fd1498Szrj || TREE_CODE (type) == POINTER_TYPE)
828338fd1498Szrj {
828438fd1498Szrj x = build_receiver_ref (var, false, ctx);
828538fd1498Szrj if (TREE_CODE (type) != POINTER_TYPE)
828638fd1498Szrj x = fold_convert (pointer_sized_int_node, x);
828738fd1498Szrj x = fold_convert (type, x);
828838fd1498Szrj gimplify_expr (&x, &new_body, NULL, is_gimple_val,
828938fd1498Szrj fb_rvalue);
829038fd1498Szrj if (omp_is_reference (var))
829138fd1498Szrj {
829238fd1498Szrj tree v = create_tmp_var_raw (type, get_name (var));
829338fd1498Szrj gimple_add_tmp_var (v);
829438fd1498Szrj TREE_ADDRESSABLE (v) = 1;
829538fd1498Szrj gimple_seq_add_stmt (&new_body,
829638fd1498Szrj gimple_build_assign (v, x));
829738fd1498Szrj x = build_fold_addr_expr (v);
829838fd1498Szrj }
829938fd1498Szrj gimple_seq_add_stmt (&new_body,
830038fd1498Szrj gimple_build_assign (new_var, x));
830138fd1498Szrj }
830238fd1498Szrj else
830338fd1498Szrj {
830438fd1498Szrj x = build_receiver_ref (var, !omp_is_reference (var), ctx);
830538fd1498Szrj gimplify_expr (&x, &new_body, NULL, is_gimple_val,
830638fd1498Szrj fb_rvalue);
830738fd1498Szrj gimple_seq_add_stmt (&new_body,
830838fd1498Szrj gimple_build_assign (new_var, x));
830938fd1498Szrj }
831038fd1498Szrj }
831138fd1498Szrj else if (is_variable_sized (var))
831238fd1498Szrj {
831338fd1498Szrj tree pvar = DECL_VALUE_EXPR (var);
831438fd1498Szrj gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
831538fd1498Szrj pvar = TREE_OPERAND (pvar, 0);
831638fd1498Szrj gcc_assert (DECL_P (pvar));
831738fd1498Szrj tree new_var = lookup_decl (pvar, ctx);
831838fd1498Szrj x = build_receiver_ref (var, false, ctx);
831938fd1498Szrj gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
832038fd1498Szrj gimple_seq_add_stmt (&new_body,
832138fd1498Szrj gimple_build_assign (new_var, x));
832238fd1498Szrj }
832338fd1498Szrj break;
832438fd1498Szrj case OMP_CLAUSE_PRIVATE:
832538fd1498Szrj if (is_gimple_omp_oacc (ctx->stmt))
832638fd1498Szrj break;
832738fd1498Szrj var = OMP_CLAUSE_DECL (c);
832838fd1498Szrj if (omp_is_reference (var))
832938fd1498Szrj {
833038fd1498Szrj location_t clause_loc = OMP_CLAUSE_LOCATION (c);
833138fd1498Szrj tree new_var = lookup_decl (var, ctx);
833238fd1498Szrj x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
833338fd1498Szrj if (TREE_CONSTANT (x))
833438fd1498Szrj {
833538fd1498Szrj x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)),
833638fd1498Szrj get_name (var));
833738fd1498Szrj gimple_add_tmp_var (x);
833838fd1498Szrj TREE_ADDRESSABLE (x) = 1;
833938fd1498Szrj x = build_fold_addr_expr_loc (clause_loc, x);
834038fd1498Szrj }
834138fd1498Szrj else
834238fd1498Szrj break;
834338fd1498Szrj
834438fd1498Szrj x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
834538fd1498Szrj gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
834638fd1498Szrj gimple_seq_add_stmt (&new_body,
834738fd1498Szrj gimple_build_assign (new_var, x));
834838fd1498Szrj }
834938fd1498Szrj break;
835038fd1498Szrj case OMP_CLAUSE_USE_DEVICE_PTR:
835138fd1498Szrj case OMP_CLAUSE_IS_DEVICE_PTR:
835238fd1498Szrj var = OMP_CLAUSE_DECL (c);
835338fd1498Szrj if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_USE_DEVICE_PTR)
835438fd1498Szrj x = build_sender_ref (var, ctx);
835538fd1498Szrj else
835638fd1498Szrj x = build_receiver_ref (var, false, ctx);
835738fd1498Szrj if (is_variable_sized (var))
835838fd1498Szrj {
835938fd1498Szrj tree pvar = DECL_VALUE_EXPR (var);
836038fd1498Szrj gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
836138fd1498Szrj pvar = TREE_OPERAND (pvar, 0);
836238fd1498Szrj gcc_assert (DECL_P (pvar));
836338fd1498Szrj tree new_var = lookup_decl (pvar, ctx);
836438fd1498Szrj gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
836538fd1498Szrj gimple_seq_add_stmt (&new_body,
836638fd1498Szrj gimple_build_assign (new_var, x));
836738fd1498Szrj }
836838fd1498Szrj else if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
836938fd1498Szrj {
837038fd1498Szrj tree new_var = lookup_decl (var, ctx);
837138fd1498Szrj new_var = DECL_VALUE_EXPR (new_var);
837238fd1498Szrj gcc_assert (TREE_CODE (new_var) == MEM_REF);
837338fd1498Szrj new_var = TREE_OPERAND (new_var, 0);
837438fd1498Szrj gcc_assert (DECL_P (new_var));
837538fd1498Szrj gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
837638fd1498Szrj gimple_seq_add_stmt (&new_body,
837738fd1498Szrj gimple_build_assign (new_var, x));
837838fd1498Szrj }
837938fd1498Szrj else
838038fd1498Szrj {
838138fd1498Szrj tree type = TREE_TYPE (var);
838238fd1498Szrj tree new_var = lookup_decl (var, ctx);
838338fd1498Szrj if (omp_is_reference (var))
838438fd1498Szrj {
838538fd1498Szrj type = TREE_TYPE (type);
838638fd1498Szrj if (TREE_CODE (type) != ARRAY_TYPE)
838738fd1498Szrj {
838838fd1498Szrj tree v = create_tmp_var_raw (type, get_name (var));
838938fd1498Szrj gimple_add_tmp_var (v);
839038fd1498Szrj TREE_ADDRESSABLE (v) = 1;
839138fd1498Szrj x = fold_convert (type, x);
839238fd1498Szrj gimplify_expr (&x, &new_body, NULL, is_gimple_val,
839338fd1498Szrj fb_rvalue);
839438fd1498Szrj gimple_seq_add_stmt (&new_body,
839538fd1498Szrj gimple_build_assign (v, x));
839638fd1498Szrj x = build_fold_addr_expr (v);
839738fd1498Szrj }
839838fd1498Szrj }
839938fd1498Szrj new_var = DECL_VALUE_EXPR (new_var);
840038fd1498Szrj x = fold_convert (TREE_TYPE (new_var), x);
840138fd1498Szrj gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
840238fd1498Szrj gimple_seq_add_stmt (&new_body,
840338fd1498Szrj gimple_build_assign (new_var, x));
840438fd1498Szrj }
840538fd1498Szrj break;
840638fd1498Szrj }
840738fd1498Szrj /* Handle GOMP_MAP_FIRSTPRIVATE_{POINTER,REFERENCE} in second pass,
840838fd1498Szrj so that firstprivate vars holding OMP_CLAUSE_SIZE if needed
840938fd1498Szrj are already handled. Similarly OMP_CLAUSE_PRIVATE for VLAs
841038fd1498Szrj or references to VLAs. */
841138fd1498Szrj for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
841238fd1498Szrj switch (OMP_CLAUSE_CODE (c))
841338fd1498Szrj {
841438fd1498Szrj tree var;
841538fd1498Szrj default:
841638fd1498Szrj break;
841738fd1498Szrj case OMP_CLAUSE_MAP:
841838fd1498Szrj if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
841938fd1498Szrj || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_REFERENCE)
842038fd1498Szrj {
842138fd1498Szrj location_t clause_loc = OMP_CLAUSE_LOCATION (c);
842238fd1498Szrj poly_int64 offset = 0;
842338fd1498Szrj gcc_assert (prev);
842438fd1498Szrj var = OMP_CLAUSE_DECL (c);
842538fd1498Szrj if (DECL_P (var)
842638fd1498Szrj && TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE
842738fd1498Szrj && is_global_var (maybe_lookup_decl_in_outer_ctx (var,
842838fd1498Szrj ctx))
842938fd1498Szrj && varpool_node::get_create (var)->offloadable)
843038fd1498Szrj break;
843138fd1498Szrj if (TREE_CODE (var) == INDIRECT_REF
843238fd1498Szrj && TREE_CODE (TREE_OPERAND (var, 0)) == COMPONENT_REF)
843338fd1498Szrj var = TREE_OPERAND (var, 0);
843438fd1498Szrj if (TREE_CODE (var) == COMPONENT_REF)
843538fd1498Szrj {
843638fd1498Szrj var = get_addr_base_and_unit_offset (var, &offset);
843738fd1498Szrj gcc_assert (var != NULL_TREE && DECL_P (var));
843838fd1498Szrj }
843938fd1498Szrj else if (DECL_SIZE (var)
844038fd1498Szrj && TREE_CODE (DECL_SIZE (var)) != INTEGER_CST)
844138fd1498Szrj {
844238fd1498Szrj tree var2 = DECL_VALUE_EXPR (var);
844338fd1498Szrj gcc_assert (TREE_CODE (var2) == INDIRECT_REF);
844438fd1498Szrj var2 = TREE_OPERAND (var2, 0);
844538fd1498Szrj gcc_assert (DECL_P (var2));
844638fd1498Szrj var = var2;
844738fd1498Szrj }
844838fd1498Szrj tree new_var = lookup_decl (var, ctx), x;
844938fd1498Szrj tree type = TREE_TYPE (new_var);
845038fd1498Szrj bool is_ref;
845138fd1498Szrj if (TREE_CODE (OMP_CLAUSE_DECL (c)) == INDIRECT_REF
845238fd1498Szrj && (TREE_CODE (TREE_OPERAND (OMP_CLAUSE_DECL (c), 0))
845338fd1498Szrj == COMPONENT_REF))
845438fd1498Szrj {
845538fd1498Szrj type = TREE_TYPE (TREE_OPERAND (OMP_CLAUSE_DECL (c), 0));
845638fd1498Szrj is_ref = true;
845738fd1498Szrj new_var = build2 (MEM_REF, type,
845838fd1498Szrj build_fold_addr_expr (new_var),
845938fd1498Szrj build_int_cst (build_pointer_type (type),
846038fd1498Szrj offset));
846138fd1498Szrj }
846238fd1498Szrj else if (TREE_CODE (OMP_CLAUSE_DECL (c)) == COMPONENT_REF)
846338fd1498Szrj {
846438fd1498Szrj type = TREE_TYPE (OMP_CLAUSE_DECL (c));
846538fd1498Szrj is_ref = TREE_CODE (type) == REFERENCE_TYPE;
846638fd1498Szrj new_var = build2 (MEM_REF, type,
846738fd1498Szrj build_fold_addr_expr (new_var),
846838fd1498Szrj build_int_cst (build_pointer_type (type),
846938fd1498Szrj offset));
847038fd1498Szrj }
847138fd1498Szrj else
847238fd1498Szrj is_ref = omp_is_reference (var);
847338fd1498Szrj if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_REFERENCE)
847438fd1498Szrj is_ref = false;
847538fd1498Szrj bool ref_to_array = false;
847638fd1498Szrj if (is_ref)
847738fd1498Szrj {
847838fd1498Szrj type = TREE_TYPE (type);
847938fd1498Szrj if (TREE_CODE (type) == ARRAY_TYPE)
848038fd1498Szrj {
848138fd1498Szrj type = build_pointer_type (type);
848238fd1498Szrj ref_to_array = true;
848338fd1498Szrj }
848438fd1498Szrj }
848538fd1498Szrj else if (TREE_CODE (type) == ARRAY_TYPE)
848638fd1498Szrj {
848738fd1498Szrj tree decl2 = DECL_VALUE_EXPR (new_var);
848838fd1498Szrj gcc_assert (TREE_CODE (decl2) == MEM_REF);
848938fd1498Szrj decl2 = TREE_OPERAND (decl2, 0);
849038fd1498Szrj gcc_assert (DECL_P (decl2));
849138fd1498Szrj new_var = decl2;
849238fd1498Szrj type = TREE_TYPE (new_var);
849338fd1498Szrj }
849438fd1498Szrj x = build_receiver_ref (OMP_CLAUSE_DECL (prev), false, ctx);
849538fd1498Szrj x = fold_convert_loc (clause_loc, type, x);
849638fd1498Szrj if (!integer_zerop (OMP_CLAUSE_SIZE (c)))
849738fd1498Szrj {
849838fd1498Szrj tree bias = OMP_CLAUSE_SIZE (c);
849938fd1498Szrj if (DECL_P (bias))
850038fd1498Szrj bias = lookup_decl (bias, ctx);
850138fd1498Szrj bias = fold_convert_loc (clause_loc, sizetype, bias);
850238fd1498Szrj bias = fold_build1_loc (clause_loc, NEGATE_EXPR, sizetype,
850338fd1498Szrj bias);
850438fd1498Szrj x = fold_build2_loc (clause_loc, POINTER_PLUS_EXPR,
850538fd1498Szrj TREE_TYPE (x), x, bias);
850638fd1498Szrj }
850738fd1498Szrj if (ref_to_array)
850838fd1498Szrj x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
850938fd1498Szrj gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
851038fd1498Szrj if (is_ref && !ref_to_array)
851138fd1498Szrj {
851238fd1498Szrj tree t = create_tmp_var_raw (type, get_name (var));
851338fd1498Szrj gimple_add_tmp_var (t);
851438fd1498Szrj TREE_ADDRESSABLE (t) = 1;
851538fd1498Szrj gimple_seq_add_stmt (&new_body,
851638fd1498Szrj gimple_build_assign (t, x));
851738fd1498Szrj x = build_fold_addr_expr_loc (clause_loc, t);
851838fd1498Szrj }
851938fd1498Szrj gimple_seq_add_stmt (&new_body,
852038fd1498Szrj gimple_build_assign (new_var, x));
852138fd1498Szrj prev = NULL_TREE;
852238fd1498Szrj }
852338fd1498Szrj else if (OMP_CLAUSE_CHAIN (c)
852438fd1498Szrj && OMP_CLAUSE_CODE (OMP_CLAUSE_CHAIN (c))
852538fd1498Szrj == OMP_CLAUSE_MAP
852638fd1498Szrj && (OMP_CLAUSE_MAP_KIND (OMP_CLAUSE_CHAIN (c))
852738fd1498Szrj == GOMP_MAP_FIRSTPRIVATE_POINTER
852838fd1498Szrj || (OMP_CLAUSE_MAP_KIND (OMP_CLAUSE_CHAIN (c))
852938fd1498Szrj == GOMP_MAP_FIRSTPRIVATE_REFERENCE)))
853038fd1498Szrj prev = c;
853138fd1498Szrj break;
853238fd1498Szrj case OMP_CLAUSE_PRIVATE:
853338fd1498Szrj var = OMP_CLAUSE_DECL (c);
853438fd1498Szrj if (is_variable_sized (var))
853538fd1498Szrj {
853638fd1498Szrj location_t clause_loc = OMP_CLAUSE_LOCATION (c);
853738fd1498Szrj tree new_var = lookup_decl (var, ctx);
853838fd1498Szrj tree pvar = DECL_VALUE_EXPR (var);
853938fd1498Szrj gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
854038fd1498Szrj pvar = TREE_OPERAND (pvar, 0);
854138fd1498Szrj gcc_assert (DECL_P (pvar));
854238fd1498Szrj tree new_pvar = lookup_decl (pvar, ctx);
854338fd1498Szrj tree atmp = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
854438fd1498Szrj tree al = size_int (DECL_ALIGN (var));
854538fd1498Szrj tree x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
854638fd1498Szrj x = build_call_expr_loc (clause_loc, atmp, 2, x, al);
854738fd1498Szrj x = fold_convert_loc (clause_loc, TREE_TYPE (new_pvar), x);
854838fd1498Szrj gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
854938fd1498Szrj gimple_seq_add_stmt (&new_body,
855038fd1498Szrj gimple_build_assign (new_pvar, x));
855138fd1498Szrj }
855238fd1498Szrj else if (omp_is_reference (var) && !is_gimple_omp_oacc (ctx->stmt))
855338fd1498Szrj {
855438fd1498Szrj location_t clause_loc = OMP_CLAUSE_LOCATION (c);
855538fd1498Szrj tree new_var = lookup_decl (var, ctx);
855638fd1498Szrj tree x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
855738fd1498Szrj if (TREE_CONSTANT (x))
855838fd1498Szrj break;
855938fd1498Szrj else
856038fd1498Szrj {
856138fd1498Szrj tree atmp
856238fd1498Szrj = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
856338fd1498Szrj tree rtype = TREE_TYPE (TREE_TYPE (new_var));
856438fd1498Szrj tree al = size_int (TYPE_ALIGN (rtype));
856538fd1498Szrj x = build_call_expr_loc (clause_loc, atmp, 2, x, al);
856638fd1498Szrj }
856738fd1498Szrj
856838fd1498Szrj x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
856938fd1498Szrj gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
857038fd1498Szrj gimple_seq_add_stmt (&new_body,
857138fd1498Szrj gimple_build_assign (new_var, x));
857238fd1498Szrj }
857338fd1498Szrj break;
857438fd1498Szrj }
857538fd1498Szrj
857638fd1498Szrj gimple_seq fork_seq = NULL;
857738fd1498Szrj gimple_seq join_seq = NULL;
857838fd1498Szrj
857938fd1498Szrj if (is_oacc_parallel (ctx))
858038fd1498Szrj {
858138fd1498Szrj /* If there are reductions on the offloaded region itself, treat
858238fd1498Szrj them as a dummy GANG loop. */
858338fd1498Szrj tree level = build_int_cst (integer_type_node, GOMP_DIM_GANG);
858438fd1498Szrj
858538fd1498Szrj lower_oacc_reductions (gimple_location (ctx->stmt), clauses, level,
858638fd1498Szrj false, NULL, NULL, &fork_seq, &join_seq, ctx);
858738fd1498Szrj }
858838fd1498Szrj
858938fd1498Szrj gimple_seq_add_seq (&new_body, fork_seq);
859038fd1498Szrj gimple_seq_add_seq (&new_body, tgt_body);
859138fd1498Szrj gimple_seq_add_seq (&new_body, join_seq);
859238fd1498Szrj
859338fd1498Szrj if (offloaded)
859438fd1498Szrj new_body = maybe_catch_exception (new_body);
859538fd1498Szrj
859638fd1498Szrj gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
859738fd1498Szrj gimple_omp_set_body (stmt, new_body);
859838fd1498Szrj }
859938fd1498Szrj
860038fd1498Szrj bind = gimple_build_bind (NULL, NULL,
860138fd1498Szrj tgt_bind ? gimple_bind_block (tgt_bind)
860238fd1498Szrj : NULL_TREE);
860338fd1498Szrj gsi_replace (gsi_p, dep_bind ? dep_bind : bind, true);
860438fd1498Szrj gimple_bind_add_seq (bind, ilist);
860538fd1498Szrj gimple_bind_add_stmt (bind, stmt);
860638fd1498Szrj gimple_bind_add_seq (bind, olist);
860738fd1498Szrj
860838fd1498Szrj pop_gimplify_context (NULL);
860938fd1498Szrj
861038fd1498Szrj if (dep_bind)
861138fd1498Szrj {
861238fd1498Szrj gimple_bind_add_seq (dep_bind, dep_ilist);
861338fd1498Szrj gimple_bind_add_stmt (dep_bind, bind);
861438fd1498Szrj gimple_bind_add_seq (dep_bind, dep_olist);
861538fd1498Szrj pop_gimplify_context (dep_bind);
861638fd1498Szrj }
861738fd1498Szrj }
861838fd1498Szrj
861938fd1498Szrj /* Expand code for an OpenMP teams directive. */
862038fd1498Szrj
862138fd1498Szrj static void
lower_omp_teams(gimple_stmt_iterator * gsi_p,omp_context * ctx)862238fd1498Szrj lower_omp_teams (gimple_stmt_iterator *gsi_p, omp_context *ctx)
862338fd1498Szrj {
862438fd1498Szrj gomp_teams *teams_stmt = as_a <gomp_teams *> (gsi_stmt (*gsi_p));
862538fd1498Szrj push_gimplify_context ();
862638fd1498Szrj
862738fd1498Szrj tree block = make_node (BLOCK);
862838fd1498Szrj gbind *bind = gimple_build_bind (NULL, NULL, block);
862938fd1498Szrj gsi_replace (gsi_p, bind, true);
863038fd1498Szrj gimple_seq bind_body = NULL;
863138fd1498Szrj gimple_seq dlist = NULL;
863238fd1498Szrj gimple_seq olist = NULL;
863338fd1498Szrj
863438fd1498Szrj tree num_teams = omp_find_clause (gimple_omp_teams_clauses (teams_stmt),
863538fd1498Szrj OMP_CLAUSE_NUM_TEAMS);
863638fd1498Szrj if (num_teams == NULL_TREE)
863738fd1498Szrj num_teams = build_int_cst (unsigned_type_node, 0);
863838fd1498Szrj else
863938fd1498Szrj {
864038fd1498Szrj num_teams = OMP_CLAUSE_NUM_TEAMS_EXPR (num_teams);
864138fd1498Szrj num_teams = fold_convert (unsigned_type_node, num_teams);
864238fd1498Szrj gimplify_expr (&num_teams, &bind_body, NULL, is_gimple_val, fb_rvalue);
864338fd1498Szrj }
864438fd1498Szrj tree thread_limit = omp_find_clause (gimple_omp_teams_clauses (teams_stmt),
864538fd1498Szrj OMP_CLAUSE_THREAD_LIMIT);
864638fd1498Szrj if (thread_limit == NULL_TREE)
864738fd1498Szrj thread_limit = build_int_cst (unsigned_type_node, 0);
864838fd1498Szrj else
864938fd1498Szrj {
865038fd1498Szrj thread_limit = OMP_CLAUSE_THREAD_LIMIT_EXPR (thread_limit);
865138fd1498Szrj thread_limit = fold_convert (unsigned_type_node, thread_limit);
865238fd1498Szrj gimplify_expr (&thread_limit, &bind_body, NULL, is_gimple_val,
865338fd1498Szrj fb_rvalue);
865438fd1498Szrj }
865538fd1498Szrj
865638fd1498Szrj lower_rec_input_clauses (gimple_omp_teams_clauses (teams_stmt),
865738fd1498Szrj &bind_body, &dlist, ctx, NULL);
865838fd1498Szrj lower_omp (gimple_omp_body_ptr (teams_stmt), ctx);
865938fd1498Szrj lower_reduction_clauses (gimple_omp_teams_clauses (teams_stmt), &olist, ctx);
866038fd1498Szrj if (!gimple_omp_teams_grid_phony (teams_stmt))
866138fd1498Szrj {
866238fd1498Szrj gimple_seq_add_stmt (&bind_body, teams_stmt);
866338fd1498Szrj location_t loc = gimple_location (teams_stmt);
866438fd1498Szrj tree decl = builtin_decl_explicit (BUILT_IN_GOMP_TEAMS);
866538fd1498Szrj gimple *call = gimple_build_call (decl, 2, num_teams, thread_limit);
866638fd1498Szrj gimple_set_location (call, loc);
866738fd1498Szrj gimple_seq_add_stmt (&bind_body, call);
866838fd1498Szrj }
866938fd1498Szrj
867038fd1498Szrj gimple_seq_add_seq (&bind_body, gimple_omp_body (teams_stmt));
867138fd1498Szrj gimple_omp_set_body (teams_stmt, NULL);
867238fd1498Szrj gimple_seq_add_seq (&bind_body, olist);
867338fd1498Szrj gimple_seq_add_seq (&bind_body, dlist);
867438fd1498Szrj if (!gimple_omp_teams_grid_phony (teams_stmt))
867538fd1498Szrj gimple_seq_add_stmt (&bind_body, gimple_build_omp_return (true));
867638fd1498Szrj gimple_bind_set_body (bind, bind_body);
867738fd1498Szrj
867838fd1498Szrj pop_gimplify_context (bind);
867938fd1498Szrj
868038fd1498Szrj gimple_bind_append_vars (bind, ctx->block_vars);
868138fd1498Szrj BLOCK_VARS (block) = ctx->block_vars;
868238fd1498Szrj if (BLOCK_VARS (block))
868338fd1498Szrj TREE_USED (block) = 1;
868438fd1498Szrj }
868538fd1498Szrj
868638fd1498Szrj /* Expand code within an artificial GIMPLE_OMP_GRID_BODY OMP construct. */
868738fd1498Szrj
868838fd1498Szrj static void
lower_omp_grid_body(gimple_stmt_iterator * gsi_p,omp_context * ctx)868938fd1498Szrj lower_omp_grid_body (gimple_stmt_iterator *gsi_p, omp_context *ctx)
869038fd1498Szrj {
869138fd1498Szrj gimple *stmt = gsi_stmt (*gsi_p);
869238fd1498Szrj lower_omp (gimple_omp_body_ptr (stmt), ctx);
869338fd1498Szrj gimple_seq_add_stmt (gimple_omp_body_ptr (stmt),
869438fd1498Szrj gimple_build_omp_return (false));
869538fd1498Szrj }
869638fd1498Szrj
869738fd1498Szrj
869838fd1498Szrj /* Callback for lower_omp_1. Return non-NULL if *tp needs to be
869938fd1498Szrj regimplified. If DATA is non-NULL, lower_omp_1 is outside
870038fd1498Szrj of OMP context, but with task_shared_vars set. */
870138fd1498Szrj
870238fd1498Szrj static tree
lower_omp_regimplify_p(tree * tp,int * walk_subtrees,void * data)870338fd1498Szrj lower_omp_regimplify_p (tree *tp, int *walk_subtrees,
870438fd1498Szrj void *data)
870538fd1498Szrj {
870638fd1498Szrj tree t = *tp;
870738fd1498Szrj
870838fd1498Szrj /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
870938fd1498Szrj if (VAR_P (t) && data == NULL && DECL_HAS_VALUE_EXPR_P (t))
871038fd1498Szrj return t;
871138fd1498Szrj
871238fd1498Szrj if (task_shared_vars
871338fd1498Szrj && DECL_P (t)
871438fd1498Szrj && bitmap_bit_p (task_shared_vars, DECL_UID (t)))
871538fd1498Szrj return t;
871638fd1498Szrj
871738fd1498Szrj /* If a global variable has been privatized, TREE_CONSTANT on
871838fd1498Szrj ADDR_EXPR might be wrong. */
871938fd1498Szrj if (data == NULL && TREE_CODE (t) == ADDR_EXPR)
872038fd1498Szrj recompute_tree_invariant_for_addr_expr (t);
872138fd1498Szrj
872238fd1498Szrj *walk_subtrees = !IS_TYPE_OR_DECL_P (t);
872338fd1498Szrj return NULL_TREE;
872438fd1498Szrj }
872538fd1498Szrj
872638fd1498Szrj /* Data to be communicated between lower_omp_regimplify_operands and
872738fd1498Szrj lower_omp_regimplify_operands_p. */
872838fd1498Szrj
872938fd1498Szrj struct lower_omp_regimplify_operands_data
873038fd1498Szrj {
873138fd1498Szrj omp_context *ctx;
873238fd1498Szrj vec<tree> *decls;
873338fd1498Szrj };
873438fd1498Szrj
873538fd1498Szrj /* Helper function for lower_omp_regimplify_operands. Find
873638fd1498Szrj omp_member_access_dummy_var vars and adjust temporarily their
873738fd1498Szrj DECL_VALUE_EXPRs if needed. */
873838fd1498Szrj
873938fd1498Szrj static tree
lower_omp_regimplify_operands_p(tree * tp,int * walk_subtrees,void * data)874038fd1498Szrj lower_omp_regimplify_operands_p (tree *tp, int *walk_subtrees,
874138fd1498Szrj void *data)
874238fd1498Szrj {
874338fd1498Szrj tree t = omp_member_access_dummy_var (*tp);
874438fd1498Szrj if (t)
874538fd1498Szrj {
874638fd1498Szrj struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
874738fd1498Szrj lower_omp_regimplify_operands_data *ldata
874838fd1498Szrj = (lower_omp_regimplify_operands_data *) wi->info;
874938fd1498Szrj tree o = maybe_lookup_decl (t, ldata->ctx);
875038fd1498Szrj if (o != t)
875138fd1498Szrj {
875238fd1498Szrj ldata->decls->safe_push (DECL_VALUE_EXPR (*tp));
875338fd1498Szrj ldata->decls->safe_push (*tp);
875438fd1498Szrj tree v = unshare_and_remap (DECL_VALUE_EXPR (*tp), t, o);
875538fd1498Szrj SET_DECL_VALUE_EXPR (*tp, v);
875638fd1498Szrj }
875738fd1498Szrj }
875838fd1498Szrj *walk_subtrees = !IS_TYPE_OR_DECL_P (*tp);
875938fd1498Szrj return NULL_TREE;
876038fd1498Szrj }
876138fd1498Szrj
876238fd1498Szrj /* Wrapper around gimple_regimplify_operands that adjusts DECL_VALUE_EXPRs
876338fd1498Szrj of omp_member_access_dummy_var vars during regimplification. */
876438fd1498Szrj
876538fd1498Szrj static void
lower_omp_regimplify_operands(omp_context * ctx,gimple * stmt,gimple_stmt_iterator * gsi_p)876638fd1498Szrj lower_omp_regimplify_operands (omp_context *ctx, gimple *stmt,
876738fd1498Szrj gimple_stmt_iterator *gsi_p)
876838fd1498Szrj {
876938fd1498Szrj auto_vec<tree, 10> decls;
877038fd1498Szrj if (ctx)
877138fd1498Szrj {
877238fd1498Szrj struct walk_stmt_info wi;
877338fd1498Szrj memset (&wi, '\0', sizeof (wi));
877438fd1498Szrj struct lower_omp_regimplify_operands_data data;
877538fd1498Szrj data.ctx = ctx;
877638fd1498Szrj data.decls = &decls;
877738fd1498Szrj wi.info = &data;
877838fd1498Szrj walk_gimple_op (stmt, lower_omp_regimplify_operands_p, &wi);
877938fd1498Szrj }
878038fd1498Szrj gimple_regimplify_operands (stmt, gsi_p);
878138fd1498Szrj while (!decls.is_empty ())
878238fd1498Szrj {
878338fd1498Szrj tree t = decls.pop ();
878438fd1498Szrj tree v = decls.pop ();
878538fd1498Szrj SET_DECL_VALUE_EXPR (t, v);
878638fd1498Szrj }
878738fd1498Szrj }
878838fd1498Szrj
878938fd1498Szrj static void
lower_omp_1(gimple_stmt_iterator * gsi_p,omp_context * ctx)879038fd1498Szrj lower_omp_1 (gimple_stmt_iterator *gsi_p, omp_context *ctx)
879138fd1498Szrj {
879238fd1498Szrj gimple *stmt = gsi_stmt (*gsi_p);
879338fd1498Szrj struct walk_stmt_info wi;
879438fd1498Szrj gcall *call_stmt;
879538fd1498Szrj
879638fd1498Szrj if (gimple_has_location (stmt))
879738fd1498Szrj input_location = gimple_location (stmt);
879838fd1498Szrj
879938fd1498Szrj if (task_shared_vars)
880038fd1498Szrj memset (&wi, '\0', sizeof (wi));
880138fd1498Szrj
880238fd1498Szrj /* If we have issued syntax errors, avoid doing any heavy lifting.
880338fd1498Szrj Just replace the OMP directives with a NOP to avoid
880438fd1498Szrj confusing RTL expansion. */
880538fd1498Szrj if (seen_error () && is_gimple_omp (stmt))
880638fd1498Szrj {
880738fd1498Szrj gsi_replace (gsi_p, gimple_build_nop (), true);
880838fd1498Szrj return;
880938fd1498Szrj }
881038fd1498Szrj
881138fd1498Szrj switch (gimple_code (stmt))
881238fd1498Szrj {
881338fd1498Szrj case GIMPLE_COND:
881438fd1498Szrj {
881538fd1498Szrj gcond *cond_stmt = as_a <gcond *> (stmt);
881638fd1498Szrj if ((ctx || task_shared_vars)
881738fd1498Szrj && (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
881838fd1498Szrj lower_omp_regimplify_p,
881938fd1498Szrj ctx ? NULL : &wi, NULL)
882038fd1498Szrj || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
882138fd1498Szrj lower_omp_regimplify_p,
882238fd1498Szrj ctx ? NULL : &wi, NULL)))
882338fd1498Szrj lower_omp_regimplify_operands (ctx, cond_stmt, gsi_p);
882438fd1498Szrj }
882538fd1498Szrj break;
882638fd1498Szrj case GIMPLE_CATCH:
882738fd1498Szrj lower_omp (gimple_catch_handler_ptr (as_a <gcatch *> (stmt)), ctx);
882838fd1498Szrj break;
882938fd1498Szrj case GIMPLE_EH_FILTER:
883038fd1498Szrj lower_omp (gimple_eh_filter_failure_ptr (stmt), ctx);
883138fd1498Szrj break;
883238fd1498Szrj case GIMPLE_TRY:
883338fd1498Szrj lower_omp (gimple_try_eval_ptr (stmt), ctx);
883438fd1498Szrj lower_omp (gimple_try_cleanup_ptr (stmt), ctx);
883538fd1498Szrj break;
883638fd1498Szrj case GIMPLE_TRANSACTION:
883738fd1498Szrj lower_omp (gimple_transaction_body_ptr (as_a <gtransaction *> (stmt)),
883838fd1498Szrj ctx);
883938fd1498Szrj break;
884038fd1498Szrj case GIMPLE_BIND:
884138fd1498Szrj lower_omp (gimple_bind_body_ptr (as_a <gbind *> (stmt)), ctx);
884238fd1498Szrj maybe_remove_omp_member_access_dummy_vars (as_a <gbind *> (stmt));
884338fd1498Szrj break;
884438fd1498Szrj case GIMPLE_OMP_PARALLEL:
884538fd1498Szrj case GIMPLE_OMP_TASK:
884638fd1498Szrj ctx = maybe_lookup_ctx (stmt);
884738fd1498Szrj gcc_assert (ctx);
884838fd1498Szrj if (ctx->cancellable)
884938fd1498Szrj ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
885038fd1498Szrj lower_omp_taskreg (gsi_p, ctx);
885138fd1498Szrj break;
885238fd1498Szrj case GIMPLE_OMP_FOR:
885338fd1498Szrj ctx = maybe_lookup_ctx (stmt);
885438fd1498Szrj gcc_assert (ctx);
885538fd1498Szrj if (ctx->cancellable)
885638fd1498Szrj ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
885738fd1498Szrj lower_omp_for (gsi_p, ctx);
885838fd1498Szrj break;
885938fd1498Szrj case GIMPLE_OMP_SECTIONS:
886038fd1498Szrj ctx = maybe_lookup_ctx (stmt);
886138fd1498Szrj gcc_assert (ctx);
886238fd1498Szrj if (ctx->cancellable)
886338fd1498Szrj ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
886438fd1498Szrj lower_omp_sections (gsi_p, ctx);
886538fd1498Szrj break;
886638fd1498Szrj case GIMPLE_OMP_SINGLE:
886738fd1498Szrj ctx = maybe_lookup_ctx (stmt);
886838fd1498Szrj gcc_assert (ctx);
886938fd1498Szrj lower_omp_single (gsi_p, ctx);
887038fd1498Szrj break;
887138fd1498Szrj case GIMPLE_OMP_MASTER:
887238fd1498Szrj ctx = maybe_lookup_ctx (stmt);
887338fd1498Szrj gcc_assert (ctx);
887438fd1498Szrj lower_omp_master (gsi_p, ctx);
887538fd1498Szrj break;
887638fd1498Szrj case GIMPLE_OMP_TASKGROUP:
887738fd1498Szrj ctx = maybe_lookup_ctx (stmt);
887838fd1498Szrj gcc_assert (ctx);
887938fd1498Szrj lower_omp_taskgroup (gsi_p, ctx);
888038fd1498Szrj break;
888138fd1498Szrj case GIMPLE_OMP_ORDERED:
888238fd1498Szrj ctx = maybe_lookup_ctx (stmt);
888338fd1498Szrj gcc_assert (ctx);
888438fd1498Szrj lower_omp_ordered (gsi_p, ctx);
888538fd1498Szrj break;
888638fd1498Szrj case GIMPLE_OMP_CRITICAL:
888738fd1498Szrj ctx = maybe_lookup_ctx (stmt);
888838fd1498Szrj gcc_assert (ctx);
888938fd1498Szrj lower_omp_critical (gsi_p, ctx);
889038fd1498Szrj break;
889138fd1498Szrj case GIMPLE_OMP_ATOMIC_LOAD:
889238fd1498Szrj if ((ctx || task_shared_vars)
889338fd1498Szrj && walk_tree (gimple_omp_atomic_load_rhs_ptr (
889438fd1498Szrj as_a <gomp_atomic_load *> (stmt)),
889538fd1498Szrj lower_omp_regimplify_p, ctx ? NULL : &wi, NULL))
889638fd1498Szrj lower_omp_regimplify_operands (ctx, stmt, gsi_p);
889738fd1498Szrj break;
889838fd1498Szrj case GIMPLE_OMP_TARGET:
889938fd1498Szrj ctx = maybe_lookup_ctx (stmt);
890038fd1498Szrj gcc_assert (ctx);
890138fd1498Szrj lower_omp_target (gsi_p, ctx);
890238fd1498Szrj break;
890338fd1498Szrj case GIMPLE_OMP_TEAMS:
890438fd1498Szrj ctx = maybe_lookup_ctx (stmt);
890538fd1498Szrj gcc_assert (ctx);
890638fd1498Szrj lower_omp_teams (gsi_p, ctx);
890738fd1498Szrj break;
890838fd1498Szrj case GIMPLE_OMP_GRID_BODY:
890938fd1498Szrj ctx = maybe_lookup_ctx (stmt);
891038fd1498Szrj gcc_assert (ctx);
891138fd1498Szrj lower_omp_grid_body (gsi_p, ctx);
891238fd1498Szrj break;
891338fd1498Szrj case GIMPLE_CALL:
891438fd1498Szrj tree fndecl;
891538fd1498Szrj call_stmt = as_a <gcall *> (stmt);
891638fd1498Szrj fndecl = gimple_call_fndecl (call_stmt);
891738fd1498Szrj if (fndecl
891838fd1498Szrj && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
891938fd1498Szrj switch (DECL_FUNCTION_CODE (fndecl))
892038fd1498Szrj {
892138fd1498Szrj case BUILT_IN_GOMP_BARRIER:
892238fd1498Szrj if (ctx == NULL)
892338fd1498Szrj break;
892438fd1498Szrj /* FALLTHRU */
892538fd1498Szrj case BUILT_IN_GOMP_CANCEL:
892638fd1498Szrj case BUILT_IN_GOMP_CANCELLATION_POINT:
892738fd1498Szrj omp_context *cctx;
892838fd1498Szrj cctx = ctx;
892938fd1498Szrj if (gimple_code (cctx->stmt) == GIMPLE_OMP_SECTION)
893038fd1498Szrj cctx = cctx->outer;
893138fd1498Szrj gcc_assert (gimple_call_lhs (call_stmt) == NULL_TREE);
893238fd1498Szrj if (!cctx->cancellable)
893338fd1498Szrj {
893438fd1498Szrj if (DECL_FUNCTION_CODE (fndecl)
893538fd1498Szrj == BUILT_IN_GOMP_CANCELLATION_POINT)
893638fd1498Szrj {
893738fd1498Szrj stmt = gimple_build_nop ();
893838fd1498Szrj gsi_replace (gsi_p, stmt, false);
893938fd1498Szrj }
894038fd1498Szrj break;
894138fd1498Szrj }
894238fd1498Szrj if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_GOMP_BARRIER)
894338fd1498Szrj {
894438fd1498Szrj fndecl = builtin_decl_explicit (BUILT_IN_GOMP_BARRIER_CANCEL);
894538fd1498Szrj gimple_call_set_fndecl (call_stmt, fndecl);
894638fd1498Szrj gimple_call_set_fntype (call_stmt, TREE_TYPE (fndecl));
894738fd1498Szrj }
894838fd1498Szrj tree lhs;
894938fd1498Szrj lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (fndecl)));
895038fd1498Szrj gimple_call_set_lhs (call_stmt, lhs);
895138fd1498Szrj tree fallthru_label;
895238fd1498Szrj fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
895338fd1498Szrj gimple *g;
895438fd1498Szrj g = gimple_build_label (fallthru_label);
895538fd1498Szrj gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
895638fd1498Szrj g = gimple_build_cond (NE_EXPR, lhs,
895738fd1498Szrj fold_convert (TREE_TYPE (lhs),
895838fd1498Szrj boolean_false_node),
895938fd1498Szrj cctx->cancel_label, fallthru_label);
896038fd1498Szrj gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
896138fd1498Szrj break;
896238fd1498Szrj default:
896338fd1498Szrj break;
896438fd1498Szrj }
896538fd1498Szrj /* FALLTHRU */
896638fd1498Szrj default:
896738fd1498Szrj if ((ctx || task_shared_vars)
896838fd1498Szrj && walk_gimple_op (stmt, lower_omp_regimplify_p,
896938fd1498Szrj ctx ? NULL : &wi))
897038fd1498Szrj {
897138fd1498Szrj /* Just remove clobbers, this should happen only if we have
897238fd1498Szrj "privatized" local addressable variables in SIMD regions,
897338fd1498Szrj the clobber isn't needed in that case and gimplifying address
897438fd1498Szrj of the ARRAY_REF into a pointer and creating MEM_REF based
897538fd1498Szrj clobber would create worse code than we get with the clobber
897638fd1498Szrj dropped. */
897738fd1498Szrj if (gimple_clobber_p (stmt))
897838fd1498Szrj {
897938fd1498Szrj gsi_replace (gsi_p, gimple_build_nop (), true);
898038fd1498Szrj break;
898138fd1498Szrj }
898238fd1498Szrj lower_omp_regimplify_operands (ctx, stmt, gsi_p);
898338fd1498Szrj }
898438fd1498Szrj break;
898538fd1498Szrj }
898638fd1498Szrj }
898738fd1498Szrj
898838fd1498Szrj static void
lower_omp(gimple_seq * body,omp_context * ctx)898938fd1498Szrj lower_omp (gimple_seq *body, omp_context *ctx)
899038fd1498Szrj {
899138fd1498Szrj location_t saved_location = input_location;
899238fd1498Szrj gimple_stmt_iterator gsi;
899338fd1498Szrj for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
899438fd1498Szrj lower_omp_1 (&gsi, ctx);
899538fd1498Szrj /* During gimplification, we haven't folded statments inside offloading
899638fd1498Szrj or taskreg regions (gimplify.c:maybe_fold_stmt); do that now. */
899738fd1498Szrj if (target_nesting_level || taskreg_nesting_level)
899838fd1498Szrj for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
899938fd1498Szrj fold_stmt (&gsi);
900038fd1498Szrj input_location = saved_location;
900138fd1498Szrj }
900238fd1498Szrj
900338fd1498Szrj /* Main entry point. */
900438fd1498Szrj
900538fd1498Szrj static unsigned int
execute_lower_omp(void)900638fd1498Szrj execute_lower_omp (void)
900738fd1498Szrj {
900838fd1498Szrj gimple_seq body;
900938fd1498Szrj int i;
901038fd1498Szrj omp_context *ctx;
901138fd1498Szrj
901238fd1498Szrj /* This pass always runs, to provide PROP_gimple_lomp.
901338fd1498Szrj But often, there is nothing to do. */
901438fd1498Szrj if (flag_openacc == 0 && flag_openmp == 0
901538fd1498Szrj && flag_openmp_simd == 0)
901638fd1498Szrj return 0;
901738fd1498Szrj
901838fd1498Szrj all_contexts = splay_tree_new (splay_tree_compare_pointers, 0,
901938fd1498Szrj delete_omp_context);
902038fd1498Szrj
902138fd1498Szrj body = gimple_body (current_function_decl);
902238fd1498Szrj
902338fd1498Szrj if (hsa_gen_requested_p ())
902438fd1498Szrj omp_grid_gridify_all_targets (&body);
902538fd1498Szrj
902638fd1498Szrj scan_omp (&body, NULL);
902738fd1498Szrj gcc_assert (taskreg_nesting_level == 0);
902838fd1498Szrj FOR_EACH_VEC_ELT (taskreg_contexts, i, ctx)
902938fd1498Szrj finish_taskreg_scan (ctx);
903038fd1498Szrj taskreg_contexts.release ();
903138fd1498Szrj
903238fd1498Szrj if (all_contexts->root)
903338fd1498Szrj {
903438fd1498Szrj if (task_shared_vars)
903538fd1498Szrj push_gimplify_context ();
903638fd1498Szrj lower_omp (&body, NULL);
903738fd1498Szrj if (task_shared_vars)
903838fd1498Szrj pop_gimplify_context (NULL);
903938fd1498Szrj }
904038fd1498Szrj
904138fd1498Szrj if (all_contexts)
904238fd1498Szrj {
904338fd1498Szrj splay_tree_delete (all_contexts);
904438fd1498Szrj all_contexts = NULL;
904538fd1498Szrj }
904638fd1498Szrj BITMAP_FREE (task_shared_vars);
904738fd1498Szrj
904838fd1498Szrj /* If current function is a method, remove artificial dummy VAR_DECL created
904938fd1498Szrj for non-static data member privatization, they aren't needed for
905038fd1498Szrj debuginfo nor anything else, have been already replaced everywhere in the
905138fd1498Szrj IL and cause problems with LTO. */
905238fd1498Szrj if (DECL_ARGUMENTS (current_function_decl)
905338fd1498Szrj && DECL_ARTIFICIAL (DECL_ARGUMENTS (current_function_decl))
905438fd1498Szrj && (TREE_CODE (TREE_TYPE (DECL_ARGUMENTS (current_function_decl)))
905538fd1498Szrj == POINTER_TYPE))
905638fd1498Szrj remove_member_access_dummy_vars (DECL_INITIAL (current_function_decl));
905738fd1498Szrj return 0;
905838fd1498Szrj }
905938fd1498Szrj
906038fd1498Szrj namespace {
906138fd1498Szrj
906238fd1498Szrj const pass_data pass_data_lower_omp =
906338fd1498Szrj {
906438fd1498Szrj GIMPLE_PASS, /* type */
906538fd1498Szrj "omplower", /* name */
906638fd1498Szrj OPTGROUP_OMP, /* optinfo_flags */
906738fd1498Szrj TV_NONE, /* tv_id */
906838fd1498Szrj PROP_gimple_any, /* properties_required */
906938fd1498Szrj PROP_gimple_lomp | PROP_gimple_lomp_dev, /* properties_provided */
907038fd1498Szrj 0, /* properties_destroyed */
907138fd1498Szrj 0, /* todo_flags_start */
907238fd1498Szrj 0, /* todo_flags_finish */
907338fd1498Szrj };
907438fd1498Szrj
907538fd1498Szrj class pass_lower_omp : public gimple_opt_pass
907638fd1498Szrj {
907738fd1498Szrj public:
pass_lower_omp(gcc::context * ctxt)907838fd1498Szrj pass_lower_omp (gcc::context *ctxt)
907938fd1498Szrj : gimple_opt_pass (pass_data_lower_omp, ctxt)
908038fd1498Szrj {}
908138fd1498Szrj
908238fd1498Szrj /* opt_pass methods: */
execute(function *)908338fd1498Szrj virtual unsigned int execute (function *) { return execute_lower_omp (); }
908438fd1498Szrj
908538fd1498Szrj }; // class pass_lower_omp
908638fd1498Szrj
908738fd1498Szrj } // anon namespace
908838fd1498Szrj
908938fd1498Szrj gimple_opt_pass *
make_pass_lower_omp(gcc::context * ctxt)909038fd1498Szrj make_pass_lower_omp (gcc::context *ctxt)
909138fd1498Szrj {
909238fd1498Szrj return new pass_lower_omp (ctxt);
909338fd1498Szrj }
909438fd1498Szrj
909538fd1498Szrj /* The following is a utility to diagnose structured block violations.
909638fd1498Szrj It is not part of the "omplower" pass, as that's invoked too late. It
909738fd1498Szrj should be invoked by the respective front ends after gimplification. */
909838fd1498Szrj
909938fd1498Szrj static splay_tree all_labels;
910038fd1498Szrj
910138fd1498Szrj /* Check for mismatched contexts and generate an error if needed. Return
910238fd1498Szrj true if an error is detected. */
910338fd1498Szrj
910438fd1498Szrj static bool
diagnose_sb_0(gimple_stmt_iterator * gsi_p,gimple * branch_ctx,gimple * label_ctx)910538fd1498Szrj diagnose_sb_0 (gimple_stmt_iterator *gsi_p,
910638fd1498Szrj gimple *branch_ctx, gimple *label_ctx)
910738fd1498Szrj {
910838fd1498Szrj gcc_checking_assert (!branch_ctx || is_gimple_omp (branch_ctx));
910938fd1498Szrj gcc_checking_assert (!label_ctx || is_gimple_omp (label_ctx));
911038fd1498Szrj
911138fd1498Szrj if (label_ctx == branch_ctx)
911238fd1498Szrj return false;
911338fd1498Szrj
911438fd1498Szrj const char* kind = NULL;
911538fd1498Szrj
911638fd1498Szrj if (flag_openacc)
911738fd1498Szrj {
911838fd1498Szrj if ((branch_ctx && is_gimple_omp_oacc (branch_ctx))
911938fd1498Szrj || (label_ctx && is_gimple_omp_oacc (label_ctx)))
912038fd1498Szrj {
912138fd1498Szrj gcc_checking_assert (kind == NULL);
912238fd1498Szrj kind = "OpenACC";
912338fd1498Szrj }
912438fd1498Szrj }
912538fd1498Szrj if (kind == NULL)
912638fd1498Szrj {
912738fd1498Szrj gcc_checking_assert (flag_openmp || flag_openmp_simd);
912838fd1498Szrj kind = "OpenMP";
912938fd1498Szrj }
913038fd1498Szrj
913138fd1498Szrj /* Previously we kept track of the label's entire context in diagnose_sb_[12]
913238fd1498Szrj so we could traverse it and issue a correct "exit" or "enter" error
913338fd1498Szrj message upon a structured block violation.
913438fd1498Szrj
913538fd1498Szrj We built the context by building a list with tree_cons'ing, but there is
913638fd1498Szrj no easy counterpart in gimple tuples. It seems like far too much work
913738fd1498Szrj for issuing exit/enter error messages. If someone really misses the
913838fd1498Szrj distinct error message... patches welcome. */
913938fd1498Szrj
914038fd1498Szrj #if 0
914138fd1498Szrj /* Try to avoid confusing the user by producing and error message
914238fd1498Szrj with correct "exit" or "enter" verbiage. We prefer "exit"
914338fd1498Szrj unless we can show that LABEL_CTX is nested within BRANCH_CTX. */
914438fd1498Szrj if (branch_ctx == NULL)
914538fd1498Szrj exit_p = false;
914638fd1498Szrj else
914738fd1498Szrj {
914838fd1498Szrj while (label_ctx)
914938fd1498Szrj {
915038fd1498Szrj if (TREE_VALUE (label_ctx) == branch_ctx)
915138fd1498Szrj {
915238fd1498Szrj exit_p = false;
915338fd1498Szrj break;
915438fd1498Szrj }
915538fd1498Szrj label_ctx = TREE_CHAIN (label_ctx);
915638fd1498Szrj }
915738fd1498Szrj }
915838fd1498Szrj
915938fd1498Szrj if (exit_p)
916038fd1498Szrj error ("invalid exit from %s structured block", kind);
916138fd1498Szrj else
916238fd1498Szrj error ("invalid entry to %s structured block", kind);
916338fd1498Szrj #endif
916438fd1498Szrj
916538fd1498Szrj /* If it's obvious we have an invalid entry, be specific about the error. */
916638fd1498Szrj if (branch_ctx == NULL)
916738fd1498Szrj error ("invalid entry to %s structured block", kind);
916838fd1498Szrj else
916938fd1498Szrj {
917038fd1498Szrj /* Otherwise, be vague and lazy, but efficient. */
917138fd1498Szrj error ("invalid branch to/from %s structured block", kind);
917238fd1498Szrj }
917338fd1498Szrj
917438fd1498Szrj gsi_replace (gsi_p, gimple_build_nop (), false);
917538fd1498Szrj return true;
917638fd1498Szrj }
917738fd1498Szrj
917838fd1498Szrj /* Pass 1: Create a minimal tree of structured blocks, and record
917938fd1498Szrj where each label is found. */
918038fd1498Szrj
918138fd1498Szrj static tree
diagnose_sb_1(gimple_stmt_iterator * gsi_p,bool * handled_ops_p,struct walk_stmt_info * wi)918238fd1498Szrj diagnose_sb_1 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
918338fd1498Szrj struct walk_stmt_info *wi)
918438fd1498Szrj {
918538fd1498Szrj gimple *context = (gimple *) wi->info;
918638fd1498Szrj gimple *inner_context;
918738fd1498Szrj gimple *stmt = gsi_stmt (*gsi_p);
918838fd1498Szrj
918938fd1498Szrj *handled_ops_p = true;
919038fd1498Szrj
919138fd1498Szrj switch (gimple_code (stmt))
919238fd1498Szrj {
919338fd1498Szrj WALK_SUBSTMTS;
919438fd1498Szrj
919538fd1498Szrj case GIMPLE_OMP_PARALLEL:
919638fd1498Szrj case GIMPLE_OMP_TASK:
919738fd1498Szrj case GIMPLE_OMP_SECTIONS:
919838fd1498Szrj case GIMPLE_OMP_SINGLE:
919938fd1498Szrj case GIMPLE_OMP_SECTION:
920038fd1498Szrj case GIMPLE_OMP_MASTER:
920138fd1498Szrj case GIMPLE_OMP_ORDERED:
920238fd1498Szrj case GIMPLE_OMP_CRITICAL:
920338fd1498Szrj case GIMPLE_OMP_TARGET:
920438fd1498Szrj case GIMPLE_OMP_TEAMS:
920538fd1498Szrj case GIMPLE_OMP_TASKGROUP:
920638fd1498Szrj /* The minimal context here is just the current OMP construct. */
920738fd1498Szrj inner_context = stmt;
920838fd1498Szrj wi->info = inner_context;
920938fd1498Szrj walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
921038fd1498Szrj wi->info = context;
921138fd1498Szrj break;
921238fd1498Szrj
921338fd1498Szrj case GIMPLE_OMP_FOR:
921438fd1498Szrj inner_context = stmt;
921538fd1498Szrj wi->info = inner_context;
921638fd1498Szrj /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
921738fd1498Szrj walk them. */
921838fd1498Szrj walk_gimple_seq (gimple_omp_for_pre_body (stmt),
921938fd1498Szrj diagnose_sb_1, NULL, wi);
922038fd1498Szrj walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
922138fd1498Szrj wi->info = context;
922238fd1498Szrj break;
922338fd1498Szrj
922438fd1498Szrj case GIMPLE_LABEL:
922538fd1498Szrj splay_tree_insert (all_labels,
922638fd1498Szrj (splay_tree_key) gimple_label_label (
922738fd1498Szrj as_a <glabel *> (stmt)),
922838fd1498Szrj (splay_tree_value) context);
922938fd1498Szrj break;
923038fd1498Szrj
923138fd1498Szrj default:
923238fd1498Szrj break;
923338fd1498Szrj }
923438fd1498Szrj
923538fd1498Szrj return NULL_TREE;
923638fd1498Szrj }
923738fd1498Szrj
923838fd1498Szrj /* Pass 2: Check each branch and see if its context differs from that of
923938fd1498Szrj the destination label's context. */
924038fd1498Szrj
924138fd1498Szrj static tree
diagnose_sb_2(gimple_stmt_iterator * gsi_p,bool * handled_ops_p,struct walk_stmt_info * wi)924238fd1498Szrj diagnose_sb_2 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
924338fd1498Szrj struct walk_stmt_info *wi)
924438fd1498Szrj {
924538fd1498Szrj gimple *context = (gimple *) wi->info;
924638fd1498Szrj splay_tree_node n;
924738fd1498Szrj gimple *stmt = gsi_stmt (*gsi_p);
924838fd1498Szrj
924938fd1498Szrj *handled_ops_p = true;
925038fd1498Szrj
925138fd1498Szrj switch (gimple_code (stmt))
925238fd1498Szrj {
925338fd1498Szrj WALK_SUBSTMTS;
925438fd1498Szrj
925538fd1498Szrj case GIMPLE_OMP_PARALLEL:
925638fd1498Szrj case GIMPLE_OMP_TASK:
925738fd1498Szrj case GIMPLE_OMP_SECTIONS:
925838fd1498Szrj case GIMPLE_OMP_SINGLE:
925938fd1498Szrj case GIMPLE_OMP_SECTION:
926038fd1498Szrj case GIMPLE_OMP_MASTER:
926138fd1498Szrj case GIMPLE_OMP_ORDERED:
926238fd1498Szrj case GIMPLE_OMP_CRITICAL:
926338fd1498Szrj case GIMPLE_OMP_TARGET:
926438fd1498Szrj case GIMPLE_OMP_TEAMS:
926538fd1498Szrj case GIMPLE_OMP_TASKGROUP:
926638fd1498Szrj wi->info = stmt;
926738fd1498Szrj walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
926838fd1498Szrj wi->info = context;
926938fd1498Szrj break;
927038fd1498Szrj
927138fd1498Szrj case GIMPLE_OMP_FOR:
927238fd1498Szrj wi->info = stmt;
927338fd1498Szrj /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
927438fd1498Szrj walk them. */
927538fd1498Szrj walk_gimple_seq_mod (gimple_omp_for_pre_body_ptr (stmt),
927638fd1498Szrj diagnose_sb_2, NULL, wi);
927738fd1498Szrj walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
927838fd1498Szrj wi->info = context;
927938fd1498Szrj break;
928038fd1498Szrj
928138fd1498Szrj case GIMPLE_COND:
928238fd1498Szrj {
928338fd1498Szrj gcond *cond_stmt = as_a <gcond *> (stmt);
928438fd1498Szrj tree lab = gimple_cond_true_label (cond_stmt);
928538fd1498Szrj if (lab)
928638fd1498Szrj {
928738fd1498Szrj n = splay_tree_lookup (all_labels,
928838fd1498Szrj (splay_tree_key) lab);
928938fd1498Szrj diagnose_sb_0 (gsi_p, context,
929038fd1498Szrj n ? (gimple *) n->value : NULL);
929138fd1498Szrj }
929238fd1498Szrj lab = gimple_cond_false_label (cond_stmt);
929338fd1498Szrj if (lab)
929438fd1498Szrj {
929538fd1498Szrj n = splay_tree_lookup (all_labels,
929638fd1498Szrj (splay_tree_key) lab);
929738fd1498Szrj diagnose_sb_0 (gsi_p, context,
929838fd1498Szrj n ? (gimple *) n->value : NULL);
929938fd1498Szrj }
930038fd1498Szrj }
930138fd1498Szrj break;
930238fd1498Szrj
930338fd1498Szrj case GIMPLE_GOTO:
930438fd1498Szrj {
930538fd1498Szrj tree lab = gimple_goto_dest (stmt);
930638fd1498Szrj if (TREE_CODE (lab) != LABEL_DECL)
930738fd1498Szrj break;
930838fd1498Szrj
930938fd1498Szrj n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
931038fd1498Szrj diagnose_sb_0 (gsi_p, context, n ? (gimple *) n->value : NULL);
931138fd1498Szrj }
931238fd1498Szrj break;
931338fd1498Szrj
931438fd1498Szrj case GIMPLE_SWITCH:
931538fd1498Szrj {
931638fd1498Szrj gswitch *switch_stmt = as_a <gswitch *> (stmt);
931738fd1498Szrj unsigned int i;
931838fd1498Szrj for (i = 0; i < gimple_switch_num_labels (switch_stmt); ++i)
931938fd1498Szrj {
932038fd1498Szrj tree lab = CASE_LABEL (gimple_switch_label (switch_stmt, i));
932138fd1498Szrj n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
932238fd1498Szrj if (n && diagnose_sb_0 (gsi_p, context, (gimple *) n->value))
932338fd1498Szrj break;
932438fd1498Szrj }
932538fd1498Szrj }
932638fd1498Szrj break;
932738fd1498Szrj
932838fd1498Szrj case GIMPLE_RETURN:
932938fd1498Szrj diagnose_sb_0 (gsi_p, context, NULL);
933038fd1498Szrj break;
933138fd1498Szrj
933238fd1498Szrj default:
933338fd1498Szrj break;
933438fd1498Szrj }
933538fd1498Szrj
933638fd1498Szrj return NULL_TREE;
933738fd1498Szrj }
933838fd1498Szrj
933938fd1498Szrj static unsigned int
diagnose_omp_structured_block_errors(void)934038fd1498Szrj diagnose_omp_structured_block_errors (void)
934138fd1498Szrj {
934238fd1498Szrj struct walk_stmt_info wi;
934338fd1498Szrj gimple_seq body = gimple_body (current_function_decl);
934438fd1498Szrj
934538fd1498Szrj all_labels = splay_tree_new (splay_tree_compare_pointers, 0, 0);
934638fd1498Szrj
934738fd1498Szrj memset (&wi, 0, sizeof (wi));
934838fd1498Szrj walk_gimple_seq (body, diagnose_sb_1, NULL, &wi);
934938fd1498Szrj
935038fd1498Szrj memset (&wi, 0, sizeof (wi));
935138fd1498Szrj wi.want_locations = true;
935238fd1498Szrj walk_gimple_seq_mod (&body, diagnose_sb_2, NULL, &wi);
935338fd1498Szrj
935438fd1498Szrj gimple_set_body (current_function_decl, body);
935538fd1498Szrj
935638fd1498Szrj splay_tree_delete (all_labels);
935738fd1498Szrj all_labels = NULL;
935838fd1498Szrj
935938fd1498Szrj return 0;
936038fd1498Szrj }
936138fd1498Szrj
936238fd1498Szrj namespace {
936338fd1498Szrj
936438fd1498Szrj const pass_data pass_data_diagnose_omp_blocks =
936538fd1498Szrj {
936638fd1498Szrj GIMPLE_PASS, /* type */
936738fd1498Szrj "*diagnose_omp_blocks", /* name */
936838fd1498Szrj OPTGROUP_OMP, /* optinfo_flags */
936938fd1498Szrj TV_NONE, /* tv_id */
937038fd1498Szrj PROP_gimple_any, /* properties_required */
937138fd1498Szrj 0, /* properties_provided */
937238fd1498Szrj 0, /* properties_destroyed */
937338fd1498Szrj 0, /* todo_flags_start */
937438fd1498Szrj 0, /* todo_flags_finish */
937538fd1498Szrj };
937638fd1498Szrj
937738fd1498Szrj class pass_diagnose_omp_blocks : public gimple_opt_pass
937838fd1498Szrj {
937938fd1498Szrj public:
pass_diagnose_omp_blocks(gcc::context * ctxt)938038fd1498Szrj pass_diagnose_omp_blocks (gcc::context *ctxt)
938138fd1498Szrj : gimple_opt_pass (pass_data_diagnose_omp_blocks, ctxt)
938238fd1498Szrj {}
938338fd1498Szrj
938438fd1498Szrj /* opt_pass methods: */
gate(function *)938538fd1498Szrj virtual bool gate (function *)
938638fd1498Szrj {
938738fd1498Szrj return flag_openacc || flag_openmp || flag_openmp_simd;
938838fd1498Szrj }
execute(function *)938938fd1498Szrj virtual unsigned int execute (function *)
939038fd1498Szrj {
939138fd1498Szrj return diagnose_omp_structured_block_errors ();
939238fd1498Szrj }
939338fd1498Szrj
939438fd1498Szrj }; // class pass_diagnose_omp_blocks
939538fd1498Szrj
939638fd1498Szrj } // anon namespace
939738fd1498Szrj
939838fd1498Szrj gimple_opt_pass *
make_pass_diagnose_omp_blocks(gcc::context * ctxt)939938fd1498Szrj make_pass_diagnose_omp_blocks (gcc::context *ctxt)
940038fd1498Szrj {
940138fd1498Szrj return new pass_diagnose_omp_blocks (ctxt);
940238fd1498Szrj }
940338fd1498Szrj
940438fd1498Szrj
940538fd1498Szrj #include "gt-omp-low.h"
9406