xref: /dragonfly/contrib/gcc-8.0/gcc/omp-low.c (revision 58e805e6)
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, &copyin_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 (&copyout);
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 			      &copyin_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