1 /* Lowering pass for OMP directives.  Converts OMP directives into explicit
2    calls to the runtime library (libgomp), data marshalling to implement data
3    sharing and copying clauses, offloading to accelerators, and more.
4 
5    Contributed by Diego Novillo <dnovillo@redhat.com>
6 
7    Copyright (C) 2005-2022 Free Software Foundation, Inc.
8 
9 This file is part of GCC.
10 
11 GCC is free software; you can redistribute it and/or modify it under
12 the terms of the GNU General Public License as published by the Free
13 Software Foundation; either version 3, or (at your option) any later
14 version.
15 
16 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
17 WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
19 for more details.
20 
21 You should have received a copy of the GNU General Public License
22 along with GCC; see the file COPYING3.  If not see
23 <http://www.gnu.org/licenses/>.  */
24 
25 #include "config.h"
26 #include "system.h"
27 #include "coretypes.h"
28 #include "backend.h"
29 #include "target.h"
30 #include "tree.h"
31 #include "gimple.h"
32 #include "tree-pass.h"
33 #include "ssa.h"
34 #include "cgraph.h"
35 #include "pretty-print.h"
36 #include "diagnostic-core.h"
37 #include "fold-const.h"
38 #include "stor-layout.h"
39 #include "internal-fn.h"
40 #include "gimple-fold.h"
41 #include "gimplify.h"
42 #include "gimple-iterator.h"
43 #include "gimplify-me.h"
44 #include "gimple-walk.h"
45 #include "tree-iterator.h"
46 #include "tree-inline.h"
47 #include "langhooks.h"
48 #include "tree-dfa.h"
49 #include "tree-ssa.h"
50 #include "splay-tree.h"
51 #include "omp-general.h"
52 #include "omp-low.h"
53 #include "gimple-low.h"
54 #include "alloc-pool.h"
55 #include "symbol-summary.h"
56 #include "tree-nested.h"
57 #include "context.h"
58 #include "gomp-constants.h"
59 #include "gimple-pretty-print.h"
60 #include "stringpool.h"
61 #include "attribs.h"
62 #include "omp-offload.h"
63 
64 /* Lowering of OMP parallel and workshare constructs proceeds in two
65    phases.  The first phase scans the function looking for OMP statements
66    and then for variables that must be replaced to satisfy data sharing
67    clauses.  The second phase expands code for the constructs, as well as
68    re-gimplifying things when variables have been replaced with complex
69    expressions.
70 
71    Final code generation is done by pass_expand_omp.  The flowgraph is
72    scanned for regions which are then moved to a new
73    function, to be invoked by the thread library, or offloaded.  */
74 
75 /* Context structure.  Used to store information about each parallel
76    directive in the code.  */
77 
78 struct omp_context
79 {
80   /* This field must be at the beginning, as we do "inheritance": Some
81      callback functions for tree-inline.cc (e.g., omp_copy_decl)
82      receive a copy_body_data pointer that is up-casted to an
83      omp_context pointer.  */
84   copy_body_data cb;
85 
86   /* The tree of contexts corresponding to the encountered constructs.  */
87   struct omp_context *outer;
88   gimple *stmt;
89 
90   /* Map variables to fields in a structure that allows communication
91      between sending and receiving threads.  */
92   splay_tree field_map;
93   tree record_type;
94   tree sender_decl;
95   tree receiver_decl;
96 
97   /* These are used just by task contexts, if task firstprivate fn is
98      needed.  srecord_type is used to communicate from the thread
99      that encountered the task construct to task firstprivate fn,
100      record_type is allocated by GOMP_task, initialized by task firstprivate
101      fn and passed to the task body fn.  */
102   splay_tree sfield_map;
103   tree srecord_type;
104 
105   /* A chain of variables to add to the top-level block surrounding the
106      construct.  In the case of a parallel, this is in the child function.  */
107   tree block_vars;
108 
109   /* Label to which GOMP_cancel{,llation_point} and explicit and implicit
110      barriers should jump to during omplower pass.  */
111   tree cancel_label;
112 
113   /* The sibling GIMPLE_OMP_FOR simd with _simt_ clause or NULL
114      otherwise.  */
115   gimple *simt_stmt;
116 
117   /* For task reductions registered in this context, a vector containing
118      the length of the private copies block (if constant, otherwise NULL)
119      and then offsets (if constant, otherwise NULL) for each entry.  */
120   vec<tree> task_reductions;
121 
122   /* A hash map from the reduction clauses to the registered array
123      elts.  */
124   hash_map<tree, unsigned> *task_reduction_map;
125 
126   /* And a hash map from the lastprivate(conditional:) variables to their
127      corresponding tracking loop iteration variables.  */
128   hash_map<tree, tree> *lastprivate_conditional_map;
129 
130   /* And a hash map from the allocate variables to their corresponding
131      allocators.  */
132   hash_map<tree, tree> *allocate_map;
133 
134   /* A tree_list of the reduction clauses in this context. This is
135     only used for checking the consistency of OpenACC reduction
136     clauses in scan_omp_for and is not guaranteed to contain a valid
137     value outside of this function. */
138   tree local_reduction_clauses;
139 
140   /* A tree_list of the reduction clauses in outer contexts. This is
141     only used for checking the consistency of OpenACC reduction
142     clauses in scan_omp_for and is not guaranteed to contain a valid
143     value outside of this function. */
144   tree outer_reduction_clauses;
145 
146   /* Nesting depth of this context.  Used to beautify error messages re
147      invalid gotos.  The outermost ctx is depth 1, with depth 0 being
148      reserved for the main body of the function.  */
149   int depth;
150 
151   /* True if this parallel directive is nested within another.  */
152   bool is_nested;
153 
154   /* True if this construct can be cancelled.  */
155   bool cancellable;
156 
157   /* True if lower_omp_1 should look up lastprivate conditional in parent
158      context.  */
159   bool combined_into_simd_safelen1;
160 
161   /* True if there is nested scan context with inclusive clause.  */
162   bool scan_inclusive;
163 
164   /* True if there is nested scan context with exclusive clause.  */
165   bool scan_exclusive;
166 
167   /* True in the second simd loop of for simd with inscan reductions.  */
168   bool for_simd_scan_phase;
169 
170   /* True if there is order(concurrent) clause on the construct.  */
171   bool order_concurrent;
172 
173   /* True if there is bind clause on the construct (i.e. a loop construct).  */
174   bool loop_p;
175 
176   /* Only used for omp target contexts.  True if a teams construct is
177      strictly nested in it.  */
178   bool teams_nested_p;
179 
180   /* Only used for omp target contexts.  True if an OpenMP construct other
181      than teams is strictly nested in it.  */
182   bool nonteams_nested_p;
183 
184   /* Candidates for adjusting OpenACC privatization level.  */
185   vec<tree> oacc_privatization_candidates;
186 };
187 
188 static splay_tree all_contexts;
189 static int taskreg_nesting_level;
190 static int target_nesting_level;
191 static bitmap make_addressable_vars;
192 static bitmap global_nonaddressable_vars;
193 static vec<omp_context *> taskreg_contexts;
194 static vec<gomp_task *> task_cpyfns;
195 
196 static void scan_omp (gimple_seq *, omp_context *);
197 static tree scan_omp_1_op (tree *, int *, void *);
198 
199 #define WALK_SUBSTMTS  \
200     case GIMPLE_BIND: \
201     case GIMPLE_TRY: \
202     case GIMPLE_CATCH: \
203     case GIMPLE_EH_FILTER: \
204     case GIMPLE_TRANSACTION: \
205       /* The sub-statements for these should be walked.  */ \
206       *handled_ops_p = false; \
207       break;
208 
209 /* Return whether CTX represents an OpenACC 'parallel' or 'serial' construct.
210    (This doesn't include OpenACC 'kernels' decomposed parts.)  */
211 
212 static bool
is_oacc_parallel_or_serial(omp_context * ctx)213 is_oacc_parallel_or_serial (omp_context *ctx)
214 {
215   enum gimple_code outer_type = gimple_code (ctx->stmt);
216   return ((outer_type == GIMPLE_OMP_TARGET)
217             && ((gimple_omp_target_kind (ctx->stmt)
218                  == GF_OMP_TARGET_KIND_OACC_PARALLEL)
219                 || (gimple_omp_target_kind (ctx->stmt)
220                       == GF_OMP_TARGET_KIND_OACC_SERIAL)));
221 }
222 
223 /* Return whether CTX represents an OpenACC 'kernels' construct.
224    (This doesn't include OpenACC 'kernels' decomposed parts.)  */
225 
226 static bool
is_oacc_kernels(omp_context * ctx)227 is_oacc_kernels (omp_context *ctx)
228 {
229   enum gimple_code outer_type = gimple_code (ctx->stmt);
230   return ((outer_type == GIMPLE_OMP_TARGET)
231             && (gimple_omp_target_kind (ctx->stmt)
232                 == GF_OMP_TARGET_KIND_OACC_KERNELS));
233 }
234 
235 /* Return whether CTX represents an OpenACC 'kernels' decomposed part.  */
236 
237 static bool
is_oacc_kernels_decomposed_part(omp_context * ctx)238 is_oacc_kernels_decomposed_part (omp_context *ctx)
239 {
240   enum gimple_code outer_type = gimple_code (ctx->stmt);
241   return ((outer_type == GIMPLE_OMP_TARGET)
242             && ((gimple_omp_target_kind (ctx->stmt)
243                  == GF_OMP_TARGET_KIND_OACC_PARALLEL_KERNELS_PARALLELIZED)
244                 || (gimple_omp_target_kind (ctx->stmt)
245                       == GF_OMP_TARGET_KIND_OACC_PARALLEL_KERNELS_GANG_SINGLE)
246                 || (gimple_omp_target_kind (ctx->stmt)
247                       == GF_OMP_TARGET_KIND_OACC_DATA_KERNELS)));
248 }
249 
250 /* Return true if STMT corresponds to an OpenMP target region.  */
251 static bool
is_omp_target(gimple * stmt)252 is_omp_target (gimple *stmt)
253 {
254   if (gimple_code (stmt) == GIMPLE_OMP_TARGET)
255     {
256       int kind = gimple_omp_target_kind (stmt);
257       return (kind == GF_OMP_TARGET_KIND_REGION
258                 || kind == GF_OMP_TARGET_KIND_DATA
259                 || kind == GF_OMP_TARGET_KIND_ENTER_DATA
260                 || kind == GF_OMP_TARGET_KIND_EXIT_DATA);
261     }
262   return false;
263 }
264 
265 /* If DECL is the artificial dummy VAR_DECL created for non-static
266    data member privatization, return the underlying "this" parameter,
267    otherwise return NULL.  */
268 
269 tree
omp_member_access_dummy_var(tree decl)270 omp_member_access_dummy_var (tree decl)
271 {
272   if (!VAR_P (decl)
273       || !DECL_ARTIFICIAL (decl)
274       || !DECL_IGNORED_P (decl)
275       || !DECL_HAS_VALUE_EXPR_P (decl)
276       || !lang_hooks.decls.omp_disregard_value_expr (decl, false))
277     return NULL_TREE;
278 
279   tree v = DECL_VALUE_EXPR (decl);
280   if (TREE_CODE (v) != COMPONENT_REF)
281     return NULL_TREE;
282 
283   while (1)
284     switch (TREE_CODE (v))
285       {
286       case COMPONENT_REF:
287       case MEM_REF:
288       case INDIRECT_REF:
289       CASE_CONVERT:
290       case POINTER_PLUS_EXPR:
291           v = TREE_OPERAND (v, 0);
292           continue;
293       case PARM_DECL:
294           if (DECL_CONTEXT (v) == current_function_decl
295               && DECL_ARTIFICIAL (v)
296               && TREE_CODE (TREE_TYPE (v)) == POINTER_TYPE)
297             return v;
298           return NULL_TREE;
299       default:
300           return NULL_TREE;
301       }
302 }
303 
304 /* Helper for unshare_and_remap, called through walk_tree.  */
305 
306 static tree
unshare_and_remap_1(tree * tp,int * walk_subtrees,void * data)307 unshare_and_remap_1 (tree *tp, int *walk_subtrees, void *data)
308 {
309   tree *pair = (tree *) data;
310   if (*tp == pair[0])
311     {
312       *tp = unshare_expr (pair[1]);
313       *walk_subtrees = 0;
314     }
315   else if (IS_TYPE_OR_DECL_P (*tp))
316     *walk_subtrees = 0;
317   return NULL_TREE;
318 }
319 
320 /* Return unshare_expr (X) with all occurrences of FROM
321    replaced with TO.  */
322 
323 static tree
unshare_and_remap(tree x,tree from,tree to)324 unshare_and_remap (tree x, tree from, tree to)
325 {
326   tree pair[2] = { from, to };
327   x = unshare_expr (x);
328   walk_tree (&x, unshare_and_remap_1, pair, NULL);
329   return x;
330 }
331 
332 /* Convenience function for calling scan_omp_1_op on tree operands.  */
333 
334 static inline tree
scan_omp_op(tree * tp,omp_context * ctx)335 scan_omp_op (tree *tp, omp_context *ctx)
336 {
337   struct walk_stmt_info wi;
338 
339   memset (&wi, 0, sizeof (wi));
340   wi.info = ctx;
341   wi.want_locations = true;
342 
343   return walk_tree (tp, scan_omp_1_op, &wi, NULL);
344 }
345 
346 static void lower_omp (gimple_seq *, omp_context *);
347 static tree lookup_decl_in_outer_ctx (tree, omp_context *);
348 static tree maybe_lookup_decl_in_outer_ctx (tree, omp_context *);
349 
350 /* Return true if CTX is for an omp parallel.  */
351 
352 static inline bool
is_parallel_ctx(omp_context * ctx)353 is_parallel_ctx (omp_context *ctx)
354 {
355   return gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL;
356 }
357 
358 
359 /* Return true if CTX is for an omp task.  */
360 
361 static inline bool
is_task_ctx(omp_context * ctx)362 is_task_ctx (omp_context *ctx)
363 {
364   return gimple_code (ctx->stmt) == GIMPLE_OMP_TASK;
365 }
366 
367 
368 /* Return true if CTX is for an omp taskloop.  */
369 
370 static inline bool
is_taskloop_ctx(omp_context * ctx)371 is_taskloop_ctx (omp_context *ctx)
372 {
373   return gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
374            && gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_TASKLOOP;
375 }
376 
377 
378 /* Return true if CTX is for a host omp teams.  */
379 
380 static inline bool
is_host_teams_ctx(omp_context * ctx)381 is_host_teams_ctx (omp_context *ctx)
382 {
383   return gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS
384            && gimple_omp_teams_host (as_a <gomp_teams *> (ctx->stmt));
385 }
386 
387 /* Return true if CTX is for an omp parallel or omp task or host omp teams
388    (the last one is strictly not a task region in OpenMP speak, but we
389    need to treat it similarly).  */
390 
391 static inline bool
is_taskreg_ctx(omp_context * ctx)392 is_taskreg_ctx (omp_context *ctx)
393 {
394   return is_parallel_ctx (ctx) || is_task_ctx (ctx) || is_host_teams_ctx (ctx);
395 }
396 
397 /* Return true if EXPR is variable sized.  */
398 
399 static inline bool
is_variable_sized(const_tree expr)400 is_variable_sized (const_tree expr)
401 {
402   return !TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (expr)));
403 }
404 
405 /* Lookup variables.  The "maybe" form
406    allows for the variable form to not have been entered, otherwise we
407    assert that the variable must have been entered.  */
408 
409 static inline tree
lookup_decl(tree var,omp_context * ctx)410 lookup_decl (tree var, omp_context *ctx)
411 {
412   tree *n = ctx->cb.decl_map->get (var);
413   return *n;
414 }
415 
416 static inline tree
maybe_lookup_decl(const_tree var,omp_context * ctx)417 maybe_lookup_decl (const_tree var, omp_context *ctx)
418 {
419   tree *n = ctx->cb.decl_map->get (const_cast<tree> (var));
420   return n ? *n : NULL_TREE;
421 }
422 
423 static inline tree
lookup_field(tree var,omp_context * ctx)424 lookup_field (tree var, omp_context *ctx)
425 {
426   splay_tree_node n;
427   n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
428   return (tree) n->value;
429 }
430 
431 static inline tree
lookup_sfield(splay_tree_key key,omp_context * ctx)432 lookup_sfield (splay_tree_key key, omp_context *ctx)
433 {
434   splay_tree_node n;
435   n = splay_tree_lookup (ctx->sfield_map
436                                ? ctx->sfield_map : ctx->field_map, key);
437   return (tree) n->value;
438 }
439 
440 static inline tree
lookup_sfield(tree var,omp_context * ctx)441 lookup_sfield (tree var, omp_context *ctx)
442 {
443   return lookup_sfield ((splay_tree_key) var, ctx);
444 }
445 
446 static inline tree
maybe_lookup_field(splay_tree_key key,omp_context * ctx)447 maybe_lookup_field (splay_tree_key key, omp_context *ctx)
448 {
449   splay_tree_node n;
450   n = splay_tree_lookup (ctx->field_map, key);
451   return n ? (tree) n->value : NULL_TREE;
452 }
453 
454 static inline tree
maybe_lookup_field(tree var,omp_context * ctx)455 maybe_lookup_field (tree var, omp_context *ctx)
456 {
457   return maybe_lookup_field ((splay_tree_key) var, ctx);
458 }
459 
460 /* Return true if DECL should be copied by pointer.  SHARED_CTX is
461    the parallel context if DECL is to be shared.  */
462 
463 static bool
use_pointer_for_field(tree decl,omp_context * shared_ctx)464 use_pointer_for_field (tree decl, omp_context *shared_ctx)
465 {
466   if (AGGREGATE_TYPE_P (TREE_TYPE (decl))
467       || TYPE_ATOMIC (TREE_TYPE (decl)))
468     return true;
469 
470   /* We can only use copy-in/copy-out semantics for shared variables
471      when we know the value is not accessible from an outer scope.  */
472   if (shared_ctx)
473     {
474       gcc_assert (!is_gimple_omp_oacc (shared_ctx->stmt));
475 
476       /* ??? Trivially accessible from anywhere.  But why would we even
477            be passing an address in this case?  Should we simply assert
478            this to be false, or should we have a cleanup pass that removes
479            these from the list of mappings?  */
480       if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, shared_ctx)))
481           return true;
482 
483       /* For variables with DECL_HAS_VALUE_EXPR_P set, we cannot tell
484            without analyzing the expression whether or not its location
485            is accessible to anyone else.  In the case of nested parallel
486            regions it certainly may be.  */
487       if (TREE_CODE (decl) != RESULT_DECL && DECL_HAS_VALUE_EXPR_P (decl))
488           return true;
489 
490       /* Do not use copy-in/copy-out for variables that have their
491            address taken.  */
492       if (is_global_var (decl))
493           {
494             /* For file scope vars, track whether we've seen them as
495                non-addressable initially and in that case, keep the same
496                answer for the duration of the pass, even when they are made
497                addressable later on e.g. through reduction expansion.  Global
498                variables which weren't addressable before the pass will not
499                have their privatized copies address taken.  See PR91216.  */
500             if (!TREE_ADDRESSABLE (decl))
501               {
502                 if (!global_nonaddressable_vars)
503                     global_nonaddressable_vars = BITMAP_ALLOC (NULL);
504                 bitmap_set_bit (global_nonaddressable_vars, DECL_UID (decl));
505               }
506             else if (!global_nonaddressable_vars
507                        || !bitmap_bit_p (global_nonaddressable_vars,
508                                              DECL_UID (decl)))
509               return true;
510           }
511       else if (TREE_ADDRESSABLE (decl))
512           return true;
513 
514       /* lower_send_shared_vars only uses copy-in, but not copy-out
515            for these.  */
516       if (TREE_READONLY (decl)
517             || ((TREE_CODE (decl) == RESULT_DECL
518                  || TREE_CODE (decl) == PARM_DECL)
519                 && DECL_BY_REFERENCE (decl)))
520           return false;
521 
522       /* Disallow copy-in/out in nested parallel if
523            decl is shared in outer parallel, otherwise
524            each thread could store the shared variable
525            in its own copy-in location, making the
526            variable no longer really shared.  */
527       if (shared_ctx->is_nested)
528           {
529             omp_context *up;
530 
531             for (up = shared_ctx->outer; up; up = up->outer)
532               if ((is_taskreg_ctx (up)
533                      || (gimple_code (up->stmt) == GIMPLE_OMP_TARGET
534                          && is_gimple_omp_offloaded (up->stmt)))
535                     && maybe_lookup_decl (decl, up))
536                 break;
537 
538             if (up)
539               {
540                 tree c;
541 
542                 if (gimple_code (up->stmt) == GIMPLE_OMP_TARGET)
543                     {
544                       for (c = gimple_omp_target_clauses (up->stmt);
545                            c; c = OMP_CLAUSE_CHAIN (c))
546                         if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
547                               && OMP_CLAUSE_DECL (c) == decl)
548                           break;
549                     }
550                 else
551                     for (c = gimple_omp_taskreg_clauses (up->stmt);
552                          c; c = OMP_CLAUSE_CHAIN (c))
553                       if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
554                           && OMP_CLAUSE_DECL (c) == decl)
555                         break;
556 
557                 if (c)
558                     goto maybe_mark_addressable_and_ret;
559               }
560           }
561 
562       /* For tasks avoid using copy-in/out.  As tasks can be
563            deferred or executed in different thread, when GOMP_task
564            returns, the task hasn't necessarily terminated.  */
565       if (is_task_ctx (shared_ctx))
566           {
567             tree outer;
568           maybe_mark_addressable_and_ret:
569             outer = maybe_lookup_decl_in_outer_ctx (decl, shared_ctx);
570             if (is_gimple_reg (outer) && !omp_member_access_dummy_var (outer))
571               {
572                 /* Taking address of OUTER in lower_send_shared_vars
573                      might need regimplification of everything that uses the
574                      variable.  */
575                 if (!make_addressable_vars)
576                     make_addressable_vars = BITMAP_ALLOC (NULL);
577                 bitmap_set_bit (make_addressable_vars, DECL_UID (outer));
578                 TREE_ADDRESSABLE (outer) = 1;
579               }
580             return true;
581           }
582     }
583 
584   return false;
585 }
586 
587 /* Construct a new automatic decl similar to VAR.  */
588 
589 static tree
omp_copy_decl_2(tree var,tree name,tree type,omp_context * ctx)590 omp_copy_decl_2 (tree var, tree name, tree type, omp_context *ctx)
591 {
592   tree copy = copy_var_decl (var, name, type);
593 
594   DECL_CONTEXT (copy) = current_function_decl;
595 
596   if (ctx)
597     {
598       DECL_CHAIN (copy) = ctx->block_vars;
599       ctx->block_vars = copy;
600     }
601   else
602     record_vars (copy);
603 
604   /* If VAR is listed in make_addressable_vars, it wasn't
605      originally addressable, but was only later made so.
606      We don't need to take address of privatizations
607      from that var.  */
608   if (TREE_ADDRESSABLE (var)
609       && ((make_addressable_vars
610              && bitmap_bit_p (make_addressable_vars, DECL_UID (var)))
611             || (global_nonaddressable_vars
612                 && bitmap_bit_p (global_nonaddressable_vars, DECL_UID (var)))))
613     TREE_ADDRESSABLE (copy) = 0;
614 
615   return copy;
616 }
617 
618 static tree
omp_copy_decl_1(tree var,omp_context * ctx)619 omp_copy_decl_1 (tree var, omp_context *ctx)
620 {
621   return omp_copy_decl_2 (var, DECL_NAME (var), TREE_TYPE (var), ctx);
622 }
623 
624 /* Build tree nodes to access the field for VAR on the receiver side.  */
625 
626 static tree
build_receiver_ref(tree var,bool by_ref,omp_context * ctx)627 build_receiver_ref (tree var, bool by_ref, omp_context *ctx)
628 {
629   tree x, field = lookup_field (var, ctx);
630 
631   /* If the receiver record type was remapped in the child function,
632      remap the field into the new record type.  */
633   x = maybe_lookup_field (field, ctx);
634   if (x != NULL)
635     field = x;
636 
637   x = build_simple_mem_ref (ctx->receiver_decl);
638   TREE_THIS_NOTRAP (x) = 1;
639   x = omp_build_component_ref (x, field);
640   if (by_ref)
641     {
642       x = build_simple_mem_ref (x);
643       TREE_THIS_NOTRAP (x) = 1;
644     }
645 
646   return x;
647 }
648 
649 /* Build tree nodes to access VAR in the scope outer to CTX.  In the case
650    of a parallel, this is a component reference; for workshare constructs
651    this is some variable.  */
652 
653 static tree
build_outer_var_ref(tree var,omp_context * ctx,enum omp_clause_code code=OMP_CLAUSE_ERROR)654 build_outer_var_ref (tree var, omp_context *ctx,
655                          enum omp_clause_code code = OMP_CLAUSE_ERROR)
656 {
657   tree x;
658   omp_context *outer = ctx->outer;
659   for (; outer; outer = outer->outer)
660     {
661       if (gimple_code (outer->stmt) == GIMPLE_OMP_TASKGROUP)
662           continue;
663       if (gimple_code (outer->stmt) == GIMPLE_OMP_SCOPE
664             && !maybe_lookup_decl (var, outer))
665           continue;
666       break;
667     }
668 
669   if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx)))
670     x = var;
671   else if (is_variable_sized (var))
672     {
673       x = TREE_OPERAND (DECL_VALUE_EXPR (var), 0);
674       x = build_outer_var_ref (x, ctx, code);
675       x = build_simple_mem_ref (x);
676     }
677   else if (is_taskreg_ctx (ctx))
678     {
679       bool by_ref = use_pointer_for_field (var, NULL);
680       x = build_receiver_ref (var, by_ref, ctx);
681     }
682   else if ((gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
683               && gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_SIMD)
684              || ctx->loop_p
685              || (code == OMP_CLAUSE_PRIVATE
686                  && (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
687                        || gimple_code (ctx->stmt) == GIMPLE_OMP_SECTIONS
688                        || gimple_code (ctx->stmt) == GIMPLE_OMP_SINGLE)))
689     {
690       /* #pragma omp simd isn't a worksharing construct, and can reference
691            even private vars in its linear etc. clauses.
692            Similarly for OMP_CLAUSE_PRIVATE with outer ref, that can refer
693            to private vars in all worksharing constructs.  */
694       x = NULL_TREE;
695       if (outer && is_taskreg_ctx (outer))
696           x = lookup_decl (var, outer);
697       else if (outer)
698           x = maybe_lookup_decl_in_outer_ctx (var, ctx);
699       if (x == NULL_TREE)
700           x = var;
701     }
702   else if (code == OMP_CLAUSE_LASTPRIVATE && is_taskloop_ctx (ctx))
703     {
704       gcc_assert (outer);
705       splay_tree_node n
706           = splay_tree_lookup (outer->field_map,
707                                    (splay_tree_key) &DECL_UID (var));
708       if (n == NULL)
709           {
710             if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, outer)))
711               x = var;
712             else
713               x = lookup_decl (var, outer);
714           }
715       else
716           {
717             tree field = (tree) n->value;
718             /* If the receiver record type was remapped in the child function,
719                remap the field into the new record type.  */
720             x = maybe_lookup_field (field, outer);
721             if (x != NULL)
722               field = x;
723 
724             x = build_simple_mem_ref (outer->receiver_decl);
725             x = omp_build_component_ref (x, field);
726             if (use_pointer_for_field (var, outer))
727               x = build_simple_mem_ref (x);
728           }
729     }
730   else if (outer)
731     x = lookup_decl (var, outer);
732   else if (omp_privatize_by_reference (var))
733     /* This can happen with orphaned constructs.  If var is reference, it is
734        possible it is shared and as such valid.  */
735     x = var;
736   else if (omp_member_access_dummy_var (var))
737     x = var;
738   else
739     gcc_unreachable ();
740 
741   if (x == var)
742     {
743       tree t = omp_member_access_dummy_var (var);
744       if (t)
745           {
746             x = DECL_VALUE_EXPR (var);
747             tree o = maybe_lookup_decl_in_outer_ctx (t, ctx);
748             if (o != t)
749               x = unshare_and_remap (x, t, o);
750             else
751               x = unshare_expr (x);
752           }
753     }
754 
755   if (omp_privatize_by_reference (var))
756     x = build_simple_mem_ref (x);
757 
758   return x;
759 }
760 
761 /* Build tree nodes to access the field for VAR on the sender side.  */
762 
763 static tree
build_sender_ref(splay_tree_key key,omp_context * ctx)764 build_sender_ref (splay_tree_key key, omp_context *ctx)
765 {
766   tree field = lookup_sfield (key, ctx);
767   return omp_build_component_ref (ctx->sender_decl, field);
768 }
769 
770 static tree
build_sender_ref(tree var,omp_context * ctx)771 build_sender_ref (tree var, omp_context *ctx)
772 {
773   return build_sender_ref ((splay_tree_key) var, ctx);
774 }
775 
776 /* Add a new field for VAR inside the structure CTX->SENDER_DECL.  If
777    BASE_POINTERS_RESTRICT, declare the field with restrict.  */
778 
779 static void
install_var_field(tree var,bool by_ref,int mask,omp_context * ctx)780 install_var_field (tree var, bool by_ref, int mask, omp_context *ctx)
781 {
782   tree field, type, sfield = NULL_TREE;
783   splay_tree_key key = (splay_tree_key) var;
784 
785   if ((mask & 16) != 0)
786     {
787       key = (splay_tree_key) &DECL_NAME (var);
788       gcc_checking_assert (key != (splay_tree_key) var);
789     }
790   if ((mask & 8) != 0)
791     {
792       key = (splay_tree_key) &DECL_UID (var);
793       gcc_checking_assert (key != (splay_tree_key) var);
794     }
795   gcc_assert ((mask & 1) == 0
796                 || !splay_tree_lookup (ctx->field_map, key));
797   gcc_assert ((mask & 2) == 0 || !ctx->sfield_map
798                 || !splay_tree_lookup (ctx->sfield_map, key));
799   gcc_assert ((mask & 3) == 3
800                 || !is_gimple_omp_oacc (ctx->stmt));
801 
802   type = TREE_TYPE (var);
803   if ((mask & 16) != 0)
804     type = lang_hooks.decls.omp_array_data (var, true);
805 
806   /* Prevent redeclaring the var in the split-off function with a restrict
807      pointer type.  Note that we only clear type itself, restrict qualifiers in
808      the pointed-to type will be ignored by points-to analysis.  */
809   if (POINTER_TYPE_P (type)
810       && TYPE_RESTRICT (type))
811     type = build_qualified_type (type, TYPE_QUALS (type) & ~TYPE_QUAL_RESTRICT);
812 
813   if (mask & 4)
814     {
815       gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
816       type = build_pointer_type (build_pointer_type (type));
817     }
818   else if (by_ref)
819     type = build_pointer_type (type);
820   else if ((mask & (32 | 3)) == 1
821              && omp_privatize_by_reference (var))
822     type = TREE_TYPE (type);
823 
824   field = build_decl (DECL_SOURCE_LOCATION (var),
825                           FIELD_DECL, DECL_NAME (var), type);
826 
827   /* Remember what variable this field was created for.  This does have a
828      side effect of making dwarf2out ignore this member, so for helpful
829      debugging we clear it later in delete_omp_context.  */
830   DECL_ABSTRACT_ORIGIN (field) = var;
831   if ((mask & 16) == 0 && type == TREE_TYPE (var))
832     {
833       SET_DECL_ALIGN (field, DECL_ALIGN (var));
834       DECL_USER_ALIGN (field) = DECL_USER_ALIGN (var);
835       TREE_THIS_VOLATILE (field) = TREE_THIS_VOLATILE (var);
836     }
837   else
838     SET_DECL_ALIGN (field, TYPE_ALIGN (type));
839 
840   if ((mask & 3) == 3)
841     {
842       insert_field_into_struct (ctx->record_type, field);
843       if (ctx->srecord_type)
844           {
845             sfield = build_decl (DECL_SOURCE_LOCATION (var),
846                                      FIELD_DECL, DECL_NAME (var), type);
847             DECL_ABSTRACT_ORIGIN (sfield) = var;
848             SET_DECL_ALIGN (sfield, DECL_ALIGN (field));
849             DECL_USER_ALIGN (sfield) = DECL_USER_ALIGN (field);
850             TREE_THIS_VOLATILE (sfield) = TREE_THIS_VOLATILE (field);
851             insert_field_into_struct (ctx->srecord_type, sfield);
852           }
853     }
854   else
855     {
856       if (ctx->srecord_type == NULL_TREE)
857           {
858             tree t;
859 
860             ctx->srecord_type = lang_hooks.types.make_type (RECORD_TYPE);
861             ctx->sfield_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
862             for (t = TYPE_FIELDS (ctx->record_type); t ; t = TREE_CHAIN (t))
863               {
864                 sfield = build_decl (DECL_SOURCE_LOCATION (t),
865                                            FIELD_DECL, DECL_NAME (t), TREE_TYPE (t));
866                 DECL_ABSTRACT_ORIGIN (sfield) = DECL_ABSTRACT_ORIGIN (t);
867                 insert_field_into_struct (ctx->srecord_type, sfield);
868                 splay_tree_insert (ctx->sfield_map,
869                                          (splay_tree_key) DECL_ABSTRACT_ORIGIN (t),
870                                          (splay_tree_value) sfield);
871               }
872           }
873       sfield = field;
874       insert_field_into_struct ((mask & 1) ? ctx->record_type
875                                         : ctx->srecord_type, field);
876     }
877 
878   if (mask & 1)
879     splay_tree_insert (ctx->field_map, key, (splay_tree_value) field);
880   if ((mask & 2) && ctx->sfield_map)
881     splay_tree_insert (ctx->sfield_map, key, (splay_tree_value) sfield);
882 }
883 
884 static tree
install_var_local(tree var,omp_context * ctx)885 install_var_local (tree var, omp_context *ctx)
886 {
887   tree new_var = omp_copy_decl_1 (var, ctx);
888   insert_decl_map (&ctx->cb, var, new_var);
889   return new_var;
890 }
891 
892 /* Adjust the replacement for DECL in CTX for the new context.  This means
893    copying the DECL_VALUE_EXPR, and fixing up the type.  */
894 
895 static void
fixup_remapped_decl(tree decl,omp_context * ctx,bool private_debug)896 fixup_remapped_decl (tree decl, omp_context *ctx, bool private_debug)
897 {
898   tree new_decl, size;
899 
900   new_decl = lookup_decl (decl, ctx);
901 
902   TREE_TYPE (new_decl) = remap_type (TREE_TYPE (decl), &ctx->cb);
903 
904   if ((!TREE_CONSTANT (DECL_SIZE (new_decl)) || private_debug)
905       && DECL_HAS_VALUE_EXPR_P (decl))
906     {
907       tree ve = DECL_VALUE_EXPR (decl);
908       walk_tree (&ve, copy_tree_body_r, &ctx->cb, NULL);
909       SET_DECL_VALUE_EXPR (new_decl, ve);
910       DECL_HAS_VALUE_EXPR_P (new_decl) = 1;
911     }
912 
913   if (!TREE_CONSTANT (DECL_SIZE (new_decl)))
914     {
915       size = remap_decl (DECL_SIZE (decl), &ctx->cb);
916       if (size == error_mark_node)
917           size = TYPE_SIZE (TREE_TYPE (new_decl));
918       DECL_SIZE (new_decl) = size;
919 
920       size = remap_decl (DECL_SIZE_UNIT (decl), &ctx->cb);
921       if (size == error_mark_node)
922           size = TYPE_SIZE_UNIT (TREE_TYPE (new_decl));
923       DECL_SIZE_UNIT (new_decl) = size;
924     }
925 }
926 
927 /* The callback for remap_decl.  Search all containing contexts for a
928    mapping of the variable; this avoids having to duplicate the splay
929    tree ahead of time.  We know a mapping doesn't already exist in the
930    given context.  Create new mappings to implement default semantics.  */
931 
932 static tree
omp_copy_decl(tree var,copy_body_data * cb)933 omp_copy_decl (tree var, copy_body_data *cb)
934 {
935   omp_context *ctx = (omp_context *) cb;
936   tree new_var;
937 
938   if (TREE_CODE (var) == LABEL_DECL)
939     {
940       if (FORCED_LABEL (var) || DECL_NONLOCAL (var))
941           return var;
942       new_var = create_artificial_label (DECL_SOURCE_LOCATION (var));
943       DECL_CONTEXT (new_var) = current_function_decl;
944       insert_decl_map (&ctx->cb, var, new_var);
945       return new_var;
946     }
947 
948   while (!is_taskreg_ctx (ctx))
949     {
950       ctx = ctx->outer;
951       if (ctx == NULL)
952           return var;
953       new_var = maybe_lookup_decl (var, ctx);
954       if (new_var)
955           return new_var;
956     }
957 
958   if (is_global_var (var) || decl_function_context (var) != ctx->cb.src_fn)
959     return var;
960 
961   return error_mark_node;
962 }
963 
964 /* Create a new context, with OUTER_CTX being the surrounding context.  */
965 
966 static omp_context *
new_omp_context(gimple * stmt,omp_context * outer_ctx)967 new_omp_context (gimple *stmt, omp_context *outer_ctx)
968 {
969   omp_context *ctx = XCNEW (omp_context);
970 
971   splay_tree_insert (all_contexts, (splay_tree_key) stmt,
972                          (splay_tree_value) ctx);
973   ctx->stmt = stmt;
974 
975   if (outer_ctx)
976     {
977       ctx->outer = outer_ctx;
978       ctx->cb = outer_ctx->cb;
979       ctx->cb.block = NULL;
980       ctx->depth = outer_ctx->depth + 1;
981     }
982   else
983     {
984       ctx->cb.src_fn = current_function_decl;
985       ctx->cb.dst_fn = current_function_decl;
986       ctx->cb.src_node = cgraph_node::get (current_function_decl);
987       gcc_checking_assert (ctx->cb.src_node);
988       ctx->cb.dst_node = ctx->cb.src_node;
989       ctx->cb.src_cfun = cfun;
990       ctx->cb.copy_decl = omp_copy_decl;
991       ctx->cb.eh_lp_nr = 0;
992       ctx->cb.transform_call_graph_edges = CB_CGE_MOVE;
993       ctx->cb.adjust_array_error_bounds = true;
994       ctx->cb.dont_remap_vla_if_no_change = true;
995       ctx->depth = 1;
996     }
997 
998   ctx->cb.decl_map = new hash_map<tree, tree>;
999 
1000   return ctx;
1001 }
1002 
1003 static gimple_seq maybe_catch_exception (gimple_seq);
1004 
1005 /* Finalize task copyfn.  */
1006 
1007 static void
finalize_task_copyfn(gomp_task * task_stmt)1008 finalize_task_copyfn (gomp_task *task_stmt)
1009 {
1010   struct function *child_cfun;
1011   tree child_fn;
1012   gimple_seq seq = NULL, new_seq;
1013   gbind *bind;
1014 
1015   child_fn = gimple_omp_task_copy_fn (task_stmt);
1016   if (child_fn == NULL_TREE)
1017     return;
1018 
1019   child_cfun = DECL_STRUCT_FUNCTION (child_fn);
1020   DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
1021 
1022   push_cfun (child_cfun);
1023   bind = gimplify_body (child_fn, false);
1024   gimple_seq_add_stmt (&seq, bind);
1025   new_seq = maybe_catch_exception (seq);
1026   if (new_seq != seq)
1027     {
1028       bind = gimple_build_bind (NULL, new_seq, NULL);
1029       seq = NULL;
1030       gimple_seq_add_stmt (&seq, bind);
1031     }
1032   gimple_set_body (child_fn, seq);
1033   pop_cfun ();
1034 
1035   /* Inform the callgraph about the new function.  */
1036   cgraph_node *node = cgraph_node::get_create (child_fn);
1037   node->parallelized_function = 1;
1038   cgraph_node::add_new_function (child_fn, false);
1039 }
1040 
1041 /* Destroy a omp_context data structures.  Called through the splay tree
1042    value delete callback.  */
1043 
1044 static void
delete_omp_context(splay_tree_value value)1045 delete_omp_context (splay_tree_value value)
1046 {
1047   omp_context *ctx = (omp_context *) value;
1048 
1049   delete ctx->cb.decl_map;
1050 
1051   if (ctx->field_map)
1052     splay_tree_delete (ctx->field_map);
1053   if (ctx->sfield_map)
1054     splay_tree_delete (ctx->sfield_map);
1055 
1056   /* We hijacked DECL_ABSTRACT_ORIGIN earlier.  We need to clear it before
1057      it produces corrupt debug information.  */
1058   if (ctx->record_type)
1059     {
1060       tree t;
1061       for (t = TYPE_FIELDS (ctx->record_type); t ; t = DECL_CHAIN (t))
1062           DECL_ABSTRACT_ORIGIN (t) = NULL;
1063     }
1064   if (ctx->srecord_type)
1065     {
1066       tree t;
1067       for (t = TYPE_FIELDS (ctx->srecord_type); t ; t = DECL_CHAIN (t))
1068           DECL_ABSTRACT_ORIGIN (t) = NULL;
1069     }
1070 
1071   if (ctx->task_reduction_map)
1072     {
1073       ctx->task_reductions.release ();
1074       delete ctx->task_reduction_map;
1075     }
1076 
1077   delete ctx->lastprivate_conditional_map;
1078   delete ctx->allocate_map;
1079 
1080   XDELETE (ctx);
1081 }
1082 
1083 /* Fix up RECEIVER_DECL with a type that has been remapped to the child
1084    context.  */
1085 
1086 static void
fixup_child_record_type(omp_context * ctx)1087 fixup_child_record_type (omp_context *ctx)
1088 {
1089   tree f, type = ctx->record_type;
1090 
1091   if (!ctx->receiver_decl)
1092     return;
1093   /* ??? It isn't sufficient to just call remap_type here, because
1094      variably_modified_type_p doesn't work the way we expect for
1095      record types.  Testing each field for whether it needs remapping
1096      and creating a new record by hand works, however.  */
1097   for (f = TYPE_FIELDS (type); f ; f = DECL_CHAIN (f))
1098     if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
1099       break;
1100   if (f)
1101     {
1102       tree name, new_fields = NULL;
1103 
1104       type = lang_hooks.types.make_type (RECORD_TYPE);
1105       name = DECL_NAME (TYPE_NAME (ctx->record_type));
1106       name = build_decl (DECL_SOURCE_LOCATION (ctx->receiver_decl),
1107                                TYPE_DECL, name, type);
1108       TYPE_NAME (type) = name;
1109 
1110       for (f = TYPE_FIELDS (ctx->record_type); f ; f = DECL_CHAIN (f))
1111           {
1112             tree new_f = copy_node (f);
1113             DECL_CONTEXT (new_f) = type;
1114             TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &ctx->cb);
1115             DECL_CHAIN (new_f) = new_fields;
1116             walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &ctx->cb, NULL);
1117             walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r,
1118                          &ctx->cb, NULL);
1119             walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
1120                          &ctx->cb, NULL);
1121             new_fields = new_f;
1122 
1123             /* Arrange to be able to look up the receiver field
1124                given the sender field.  */
1125             splay_tree_insert (ctx->field_map, (splay_tree_key) f,
1126                                    (splay_tree_value) new_f);
1127           }
1128       TYPE_FIELDS (type) = nreverse (new_fields);
1129       layout_type (type);
1130     }
1131 
1132   /* In a target region we never modify any of the pointers in *.omp_data_i,
1133      so attempt to help the optimizers.  */
1134   if (is_gimple_omp_offloaded (ctx->stmt))
1135     type = build_qualified_type (type, TYPE_QUAL_CONST);
1136 
1137   TREE_TYPE (ctx->receiver_decl)
1138     = build_qualified_type (build_reference_type (type), TYPE_QUAL_RESTRICT);
1139 }
1140 
1141 /* Instantiate decls as necessary in CTX to satisfy the data sharing
1142    specified by CLAUSES.  */
1143 
1144 static void
scan_sharing_clauses(tree clauses,omp_context * ctx)1145 scan_sharing_clauses (tree clauses, omp_context *ctx)
1146 {
1147   tree c, decl;
1148   bool scan_array_reductions = false;
1149 
1150   for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1151     if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_ALLOCATE
1152           && (OMP_CLAUSE_ALLOCATE_ALLOCATOR (c) == NULL_TREE
1153               /* omp_default_mem_alloc is 1 */
1154               || !integer_onep (OMP_CLAUSE_ALLOCATE_ALLOCATOR (c))
1155               || OMP_CLAUSE_ALLOCATE_ALIGN (c) != NULL_TREE))
1156       {
1157           if (ctx->allocate_map == NULL)
1158             ctx->allocate_map = new hash_map<tree, tree>;
1159           tree val = integer_zero_node;
1160           if (OMP_CLAUSE_ALLOCATE_ALLOCATOR (c))
1161             val = OMP_CLAUSE_ALLOCATE_ALLOCATOR (c);
1162           if (OMP_CLAUSE_ALLOCATE_ALIGN (c))
1163             val = build_tree_list (val, OMP_CLAUSE_ALLOCATE_ALIGN (c));
1164           ctx->allocate_map->put (OMP_CLAUSE_DECL (c), val);
1165       }
1166 
1167   for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1168     {
1169       bool by_ref;
1170 
1171       switch (OMP_CLAUSE_CODE (c))
1172           {
1173           case OMP_CLAUSE_PRIVATE:
1174             decl = OMP_CLAUSE_DECL (c);
1175             if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
1176               goto do_private;
1177             else if (!is_variable_sized (decl))
1178               install_var_local (decl, ctx);
1179             break;
1180 
1181           case OMP_CLAUSE_SHARED:
1182             decl = OMP_CLAUSE_DECL (c);
1183             if (ctx->allocate_map && ctx->allocate_map->get (decl))
1184               ctx->allocate_map->remove (decl);
1185             /* Ignore shared directives in teams construct inside of
1186                target construct.  */
1187             if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS
1188                 && !is_host_teams_ctx (ctx))
1189               {
1190                 /* Global variables don't need to be copied,
1191                      the receiver side will use them directly.  */
1192                 tree odecl = maybe_lookup_decl_in_outer_ctx (decl, ctx);
1193                 if (is_global_var (odecl))
1194                     break;
1195                 insert_decl_map (&ctx->cb, decl, odecl);
1196                 break;
1197               }
1198             gcc_assert (is_taskreg_ctx (ctx));
1199             gcc_assert (!COMPLETE_TYPE_P (TREE_TYPE (decl))
1200                           || !is_variable_sized (decl));
1201             /* Global variables don't need to be copied,
1202                the receiver side will use them directly.  */
1203             if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1204               break;
1205             if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
1206               {
1207                 use_pointer_for_field (decl, ctx);
1208                 break;
1209               }
1210             by_ref = use_pointer_for_field (decl, NULL);
1211             if ((! TREE_READONLY (decl) && !OMP_CLAUSE_SHARED_READONLY (c))
1212                 || TREE_ADDRESSABLE (decl)
1213                 || by_ref
1214                 || omp_privatize_by_reference (decl))
1215               {
1216                 by_ref = use_pointer_for_field (decl, ctx);
1217                 install_var_field (decl, by_ref, 3, ctx);
1218                 install_var_local (decl, ctx);
1219                 break;
1220               }
1221             /* We don't need to copy const scalar vars back.  */
1222             OMP_CLAUSE_SET_CODE (c, OMP_CLAUSE_FIRSTPRIVATE);
1223             goto do_private;
1224 
1225           case OMP_CLAUSE_REDUCTION:
1226             /* Collect 'reduction' clauses on OpenACC compute construct.  */
1227             if (is_gimple_omp_oacc (ctx->stmt)
1228                 && is_gimple_omp_offloaded (ctx->stmt))
1229               {
1230                 /* No 'reduction' clauses on OpenACC 'kernels'.  */
1231                 gcc_checking_assert (!is_oacc_kernels (ctx));
1232                 /* Likewise, on OpenACC 'kernels' decomposed parts.  */
1233                 gcc_checking_assert (!is_oacc_kernels_decomposed_part (ctx));
1234 
1235                 ctx->local_reduction_clauses
1236                     = tree_cons (NULL, c, ctx->local_reduction_clauses);
1237               }
1238             /* FALLTHRU */
1239 
1240           case OMP_CLAUSE_IN_REDUCTION:
1241             decl = OMP_CLAUSE_DECL (c);
1242             if (ctx->allocate_map
1243                 && ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1244                        && (OMP_CLAUSE_REDUCTION_INSCAN (c)
1245                            || OMP_CLAUSE_REDUCTION_TASK (c)))
1246                       || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IN_REDUCTION
1247                       || is_task_ctx (ctx)))
1248               {
1249                 /* For now.  */
1250                 if (ctx->allocate_map->get (decl))
1251                     ctx->allocate_map->remove (decl);
1252               }
1253             if (TREE_CODE (decl) == MEM_REF)
1254               {
1255                 tree t = TREE_OPERAND (decl, 0);
1256                 if (TREE_CODE (t) == POINTER_PLUS_EXPR)
1257                     t = TREE_OPERAND (t, 0);
1258                 if (TREE_CODE (t) == INDIRECT_REF
1259                       || TREE_CODE (t) == ADDR_EXPR)
1260                     t = TREE_OPERAND (t, 0);
1261                 if (is_omp_target (ctx->stmt))
1262                     {
1263                       if (is_variable_sized (t))
1264                         {
1265                           gcc_assert (DECL_HAS_VALUE_EXPR_P (t));
1266                           t = DECL_VALUE_EXPR (t);
1267                           gcc_assert (TREE_CODE (t) == INDIRECT_REF);
1268                           t = TREE_OPERAND (t, 0);
1269                           gcc_assert (DECL_P (t));
1270                         }
1271                       tree at = t;
1272                       if (ctx->outer)
1273                         scan_omp_op (&at, ctx->outer);
1274                       tree nt = omp_copy_decl_1 (at, ctx->outer);
1275                       splay_tree_insert (ctx->field_map,
1276                                              (splay_tree_key) &DECL_CONTEXT (t),
1277                                              (splay_tree_value) nt);
1278                       if (at != t)
1279                         splay_tree_insert (ctx->field_map,
1280                                                (splay_tree_key) &DECL_CONTEXT (at),
1281                                                (splay_tree_value) nt);
1282                       break;
1283                     }
1284                 install_var_local (t, ctx);
1285                 if (is_taskreg_ctx (ctx)
1286                       && (!is_global_var (maybe_lookup_decl_in_outer_ctx (t, ctx))
1287                           || (is_task_ctx (ctx)
1288                                 && (TREE_CODE (TREE_TYPE (t)) == POINTER_TYPE
1289                                     || (TREE_CODE (TREE_TYPE (t)) == REFERENCE_TYPE
1290                                           && (TREE_CODE (TREE_TYPE (TREE_TYPE (t)))
1291                                               == POINTER_TYPE)))))
1292                       && !is_variable_sized (t)
1293                       && (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION
1294                           || (!OMP_CLAUSE_REDUCTION_TASK (c)
1295                                 && !is_task_ctx (ctx))))
1296                     {
1297                       by_ref = use_pointer_for_field (t, NULL);
1298                       if (is_task_ctx (ctx)
1299                           && TREE_CODE (TREE_TYPE (t)) == REFERENCE_TYPE
1300                           && TREE_CODE (TREE_TYPE (TREE_TYPE (t))) == POINTER_TYPE)
1301                         {
1302                           install_var_field (t, false, 1, ctx);
1303                           install_var_field (t, by_ref, 2, ctx);
1304                         }
1305                       else
1306                         install_var_field (t, by_ref, 3, ctx);
1307                     }
1308                 break;
1309               }
1310             if (is_omp_target (ctx->stmt))
1311               {
1312                 tree at = decl;
1313                 if (ctx->outer)
1314                     scan_omp_op (&at, ctx->outer);
1315                 tree nt = omp_copy_decl_1 (at, ctx->outer);
1316                 splay_tree_insert (ctx->field_map,
1317                                          (splay_tree_key) &DECL_CONTEXT (decl),
1318                                          (splay_tree_value) nt);
1319                 if (at != decl)
1320                     splay_tree_insert (ctx->field_map,
1321                                            (splay_tree_key) &DECL_CONTEXT (at),
1322                                            (splay_tree_value) nt);
1323                 break;
1324               }
1325             if (is_task_ctx (ctx)
1326                 || (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1327                       && OMP_CLAUSE_REDUCTION_TASK (c)
1328                       && is_parallel_ctx (ctx)))
1329               {
1330                 /* Global variables don't need to be copied,
1331                      the receiver side will use them directly.  */
1332                 if (!is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1333                     {
1334                       by_ref = use_pointer_for_field (decl, ctx);
1335                       if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IN_REDUCTION)
1336                         install_var_field (decl, by_ref, 3, ctx);
1337                     }
1338                 install_var_local (decl, ctx);
1339                 break;
1340               }
1341             if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1342                 && OMP_CLAUSE_REDUCTION_TASK (c))
1343               {
1344                 install_var_local (decl, ctx);
1345                 break;
1346               }
1347             goto do_private;
1348 
1349           case OMP_CLAUSE_LASTPRIVATE:
1350             /* Let the corresponding firstprivate clause create
1351                the variable.  */
1352             if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1353               break;
1354             /* FALLTHRU */
1355 
1356           case OMP_CLAUSE_FIRSTPRIVATE:
1357           case OMP_CLAUSE_LINEAR:
1358             decl = OMP_CLAUSE_DECL (c);
1359           do_private:
1360             if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE
1361                  || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IS_DEVICE_PTR
1362                  || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_HAS_DEVICE_ADDR)
1363                 && is_gimple_omp_offloaded (ctx->stmt))
1364               {
1365                 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
1366                     {
1367                       by_ref = !omp_privatize_by_reference (decl);
1368                       install_var_field (decl, by_ref, 3, ctx);
1369                     }
1370                 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_HAS_DEVICE_ADDR)
1371                     {
1372                       if (TREE_CODE (decl) == INDIRECT_REF)
1373                         decl = TREE_OPERAND (decl, 0);
1374                       install_var_field (decl, true, 3, ctx);
1375                     }
1376                 else if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1377                       install_var_field (decl, true, 3, ctx);
1378                 else
1379                     install_var_field (decl, false, 3, ctx);
1380               }
1381             if (is_variable_sized (decl))
1382               {
1383                 if (is_task_ctx (ctx))
1384                     {
1385                       if (ctx->allocate_map
1386                           && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
1387                         {
1388                           /* For now.  */
1389                           if (ctx->allocate_map->get (decl))
1390                               ctx->allocate_map->remove (decl);
1391                         }
1392                       install_var_field (decl, false, 1, ctx);
1393                     }
1394                 break;
1395               }
1396             else if (is_taskreg_ctx (ctx))
1397               {
1398                 bool global
1399                     = is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx));
1400                 by_ref = use_pointer_for_field (decl, NULL);
1401 
1402                 if (is_task_ctx (ctx)
1403                       && (global || by_ref || omp_privatize_by_reference (decl)))
1404                     {
1405                       if (ctx->allocate_map
1406                           && ctx->allocate_map->get (decl))
1407                         install_var_field (decl, by_ref, 32 | 1, ctx);
1408                       else
1409                         install_var_field (decl, false, 1, ctx);
1410                       if (!global)
1411                         install_var_field (decl, by_ref, 2, ctx);
1412                     }
1413                 else if (!global)
1414                     install_var_field (decl, by_ref, 3, ctx);
1415               }
1416             install_var_local (decl, ctx);
1417             break;
1418 
1419           case OMP_CLAUSE_USE_DEVICE_PTR:
1420           case OMP_CLAUSE_USE_DEVICE_ADDR:
1421             decl = OMP_CLAUSE_DECL (c);
1422 
1423             /* Fortran array descriptors.  */
1424             if (lang_hooks.decls.omp_array_data (decl, true))
1425               install_var_field (decl, false, 19, ctx);
1426             else if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_USE_DEVICE_ADDR
1427                         && !omp_privatize_by_reference (decl)
1428                         && !omp_is_allocatable_or_ptr (decl))
1429                        || TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1430               install_var_field (decl, true, 11, ctx);
1431             else
1432               install_var_field (decl, false, 11, ctx);
1433             if (DECL_SIZE (decl)
1434                 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
1435               {
1436                 tree decl2 = DECL_VALUE_EXPR (decl);
1437                 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
1438                 decl2 = TREE_OPERAND (decl2, 0);
1439                 gcc_assert (DECL_P (decl2));
1440                 install_var_local (decl2, ctx);
1441               }
1442             install_var_local (decl, ctx);
1443             break;
1444 
1445           case OMP_CLAUSE_HAS_DEVICE_ADDR:
1446             decl = OMP_CLAUSE_DECL (c);
1447             while (TREE_CODE (decl) == INDIRECT_REF
1448                      || TREE_CODE (decl) == ARRAY_REF)
1449               decl = TREE_OPERAND (decl, 0);
1450             goto do_private;
1451 
1452           case OMP_CLAUSE_IS_DEVICE_PTR:
1453             decl = OMP_CLAUSE_DECL (c);
1454             goto do_private;
1455 
1456           case OMP_CLAUSE__LOOPTEMP_:
1457           case OMP_CLAUSE__REDUCTEMP_:
1458             gcc_assert (is_taskreg_ctx (ctx));
1459             decl = OMP_CLAUSE_DECL (c);
1460             install_var_field (decl, false, 3, ctx);
1461             install_var_local (decl, ctx);
1462             break;
1463 
1464           case OMP_CLAUSE_COPYPRIVATE:
1465           case OMP_CLAUSE_COPYIN:
1466             decl = OMP_CLAUSE_DECL (c);
1467             by_ref = use_pointer_for_field (decl, NULL);
1468             install_var_field (decl, by_ref, 3, ctx);
1469             break;
1470 
1471           case OMP_CLAUSE_FINAL:
1472           case OMP_CLAUSE_IF:
1473           case OMP_CLAUSE_NUM_THREADS:
1474           case OMP_CLAUSE_NUM_TEAMS:
1475           case OMP_CLAUSE_THREAD_LIMIT:
1476           case OMP_CLAUSE_DEVICE:
1477           case OMP_CLAUSE_SCHEDULE:
1478           case OMP_CLAUSE_DIST_SCHEDULE:
1479           case OMP_CLAUSE_DEPEND:
1480           case OMP_CLAUSE_PRIORITY:
1481           case OMP_CLAUSE_GRAINSIZE:
1482           case OMP_CLAUSE_NUM_TASKS:
1483           case OMP_CLAUSE_NUM_GANGS:
1484           case OMP_CLAUSE_NUM_WORKERS:
1485           case OMP_CLAUSE_VECTOR_LENGTH:
1486           case OMP_CLAUSE_DETACH:
1487           case OMP_CLAUSE_FILTER:
1488             if (ctx->outer)
1489               scan_omp_op (&OMP_CLAUSE_OPERAND (c, 0), ctx->outer);
1490             break;
1491 
1492           case OMP_CLAUSE_TO:
1493           case OMP_CLAUSE_FROM:
1494           case OMP_CLAUSE_MAP:
1495             if (ctx->outer)
1496               scan_omp_op (&OMP_CLAUSE_SIZE (c), ctx->outer);
1497             decl = OMP_CLAUSE_DECL (c);
1498             /* If requested, make 'decl' addressable.  */
1499             if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1500                 && OMP_CLAUSE_MAP_DECL_MAKE_ADDRESSABLE (c))
1501               {
1502                 gcc_checking_assert (DECL_P (decl));
1503 
1504                 bool decl_addressable = TREE_ADDRESSABLE (decl);
1505                 if (!decl_addressable)
1506                     {
1507                       if (!make_addressable_vars)
1508                         make_addressable_vars = BITMAP_ALLOC (NULL);
1509                       bitmap_set_bit (make_addressable_vars, DECL_UID (decl));
1510                       TREE_ADDRESSABLE (decl) = 1;
1511                     }
1512 
1513                 if (dump_enabled_p ())
1514                     {
1515                       location_t loc = OMP_CLAUSE_LOCATION (c);
1516                       const dump_user_location_t d_u_loc
1517                         = dump_user_location_t::from_location_t (loc);
1518                       /* PR100695 "Format decoder, quoting in 'dump_printf' etc." */
1519 #if __GNUC__ >= 10
1520 # pragma GCC diagnostic push
1521 # pragma GCC diagnostic ignored "-Wformat"
1522 #endif
1523                       if (!decl_addressable)
1524                         dump_printf_loc (MSG_NOTE, d_u_loc,
1525                                              "variable %<%T%>"
1526                                              " made addressable\n",
1527                                              decl);
1528                       else
1529                         dump_printf_loc (MSG_NOTE, d_u_loc,
1530                                              "variable %<%T%>"
1531                                              " already made addressable\n",
1532                                              decl);
1533 #if __GNUC__ >= 10
1534 # pragma GCC diagnostic pop
1535 #endif
1536                     }
1537 
1538                 /* Done.  */
1539                 OMP_CLAUSE_MAP_DECL_MAKE_ADDRESSABLE (c) = 0;
1540               }
1541             /* Global variables with "omp declare target" attribute
1542                don't need to be copied, the receiver side will use them
1543                directly.  However, global variables with "omp declare target link"
1544                attribute need to be copied.  Or when ALWAYS modifier is used.  */
1545             if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1546                 && DECL_P (decl)
1547                 && ((OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_FIRSTPRIVATE_POINTER
1548                        && (OMP_CLAUSE_MAP_KIND (c)
1549                            != GOMP_MAP_FIRSTPRIVATE_REFERENCE)
1550                        && OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_ATTACH
1551                        && OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_DETACH)
1552                       || TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1553                 && OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_ALWAYS_TO
1554                 && OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_ALWAYS_FROM
1555                 && OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_ALWAYS_TOFROM
1556                 && OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_TO_PSET
1557                 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
1558                 && varpool_node::get_create (decl)->offloadable
1559                 && !lookup_attribute ("omp declare target link",
1560                                             DECL_ATTRIBUTES (decl)))
1561               break;
1562             if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1563                 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER)
1564               {
1565                 /* Ignore GOMP_MAP_POINTER kind for arrays in regions that are
1566                      not offloaded; there is nothing to map for those.  */
1567                 if (!is_gimple_omp_offloaded (ctx->stmt)
1568                       && !POINTER_TYPE_P (TREE_TYPE (decl))
1569                       && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
1570                     break;
1571               }
1572             if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1573                 && DECL_P (decl)
1574                 && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH
1575                       || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_DETACH)
1576                 && is_omp_target (ctx->stmt))
1577               {
1578                 /* If this is an offloaded region, an attach operation should
1579                      only exist when the pointer variable is mapped in a prior
1580                      clause.  */
1581                 if (is_gimple_omp_offloaded (ctx->stmt))
1582                     gcc_assert
1583                       (maybe_lookup_decl (decl, ctx)
1584                        || (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
1585                            && lookup_attribute ("omp declare target",
1586                                                       DECL_ATTRIBUTES (decl))));
1587 
1588                 /* By itself, attach/detach is generated as part of pointer
1589                      variable mapping and should not create new variables in the
1590                      offloaded region, however sender refs for it must be created
1591                      for its address to be passed to the runtime.  */
1592                 tree field
1593                     = build_decl (OMP_CLAUSE_LOCATION (c),
1594                                     FIELD_DECL, NULL_TREE, ptr_type_node);
1595                 SET_DECL_ALIGN (field, TYPE_ALIGN (ptr_type_node));
1596                 insert_field_into_struct (ctx->record_type, field);
1597                 /* To not clash with a map of the pointer variable itself,
1598                      attach/detach maps have their field looked up by the *clause*
1599                      tree expression, not the decl.  */
1600                 gcc_assert (!splay_tree_lookup (ctx->field_map,
1601                                                         (splay_tree_key) c));
1602                 splay_tree_insert (ctx->field_map, (splay_tree_key) c,
1603                                          (splay_tree_value) field);
1604                 break;
1605               }
1606             if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1607                 && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
1608                       || (OMP_CLAUSE_MAP_KIND (c)
1609                           == GOMP_MAP_FIRSTPRIVATE_REFERENCE)))
1610               {
1611                 if (TREE_CODE (decl) == COMPONENT_REF
1612                       || (TREE_CODE (decl) == INDIRECT_REF
1613                           && TREE_CODE (TREE_OPERAND (decl, 0)) == COMPONENT_REF
1614                           && (TREE_CODE (TREE_TYPE (TREE_OPERAND (decl, 0)))
1615                                 == REFERENCE_TYPE)))
1616                     break;
1617                 if (DECL_SIZE (decl)
1618                       && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
1619                     {
1620                       tree decl2 = DECL_VALUE_EXPR (decl);
1621                       gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
1622                       decl2 = TREE_OPERAND (decl2, 0);
1623                       gcc_assert (DECL_P (decl2));
1624                       install_var_local (decl2, ctx);
1625                     }
1626                 install_var_local (decl, ctx);
1627                 break;
1628               }
1629             if (DECL_P (decl))
1630               {
1631                 if (DECL_SIZE (decl)
1632                       && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
1633                     {
1634                       tree decl2 = DECL_VALUE_EXPR (decl);
1635                       gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
1636                       decl2 = TREE_OPERAND (decl2, 0);
1637                       gcc_assert (DECL_P (decl2));
1638                       install_var_field (decl2, true, 3, ctx);
1639                       install_var_local (decl2, ctx);
1640                       install_var_local (decl, ctx);
1641                     }
1642                 else
1643                     {
1644                       if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1645                           && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
1646                           && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
1647                           && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1648                         install_var_field (decl, true, 7, ctx);
1649                       else
1650                         install_var_field (decl, true, 3, ctx);
1651                       if (is_gimple_omp_offloaded (ctx->stmt)
1652                           && !(is_gimple_omp_oacc (ctx->stmt)
1653                                  && OMP_CLAUSE_MAP_IN_REDUCTION (c)))
1654                         install_var_local (decl, ctx);
1655                     }
1656               }
1657             else
1658               {
1659                 tree base = get_base_address (decl);
1660                 tree nc = OMP_CLAUSE_CHAIN (c);
1661                 if (DECL_P (base)
1662                       && nc != NULL_TREE
1663                       && OMP_CLAUSE_CODE (nc) == OMP_CLAUSE_MAP
1664                       && OMP_CLAUSE_DECL (nc) == base
1665                       && OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_POINTER
1666                       && integer_zerop (OMP_CLAUSE_SIZE (nc)))
1667                     {
1668                       OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c) = 1;
1669                       OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (nc) = 1;
1670                     }
1671                 else
1672                     {
1673                       if (ctx->outer)
1674                         {
1675                           scan_omp_op (&OMP_CLAUSE_DECL (c), ctx->outer);
1676                           decl = OMP_CLAUSE_DECL (c);
1677                         }
1678                       gcc_assert (!splay_tree_lookup (ctx->field_map,
1679                                                               (splay_tree_key) decl));
1680                       tree field
1681                         = build_decl (OMP_CLAUSE_LOCATION (c),
1682                                           FIELD_DECL, NULL_TREE, ptr_type_node);
1683                       SET_DECL_ALIGN (field, TYPE_ALIGN (ptr_type_node));
1684                       insert_field_into_struct (ctx->record_type, field);
1685                       splay_tree_insert (ctx->field_map, (splay_tree_key) decl,
1686                                              (splay_tree_value) field);
1687                     }
1688               }
1689             break;
1690 
1691           case OMP_CLAUSE_ORDER:
1692             ctx->order_concurrent = true;
1693             break;
1694 
1695           case OMP_CLAUSE_BIND:
1696             ctx->loop_p = true;
1697             break;
1698 
1699           case OMP_CLAUSE_NOWAIT:
1700           case OMP_CLAUSE_ORDERED:
1701           case OMP_CLAUSE_COLLAPSE:
1702           case OMP_CLAUSE_UNTIED:
1703           case OMP_CLAUSE_MERGEABLE:
1704           case OMP_CLAUSE_PROC_BIND:
1705           case OMP_CLAUSE_SAFELEN:
1706           case OMP_CLAUSE_SIMDLEN:
1707           case OMP_CLAUSE_THREADS:
1708           case OMP_CLAUSE_SIMD:
1709           case OMP_CLAUSE_NOGROUP:
1710           case OMP_CLAUSE_DEFAULTMAP:
1711           case OMP_CLAUSE_ASYNC:
1712           case OMP_CLAUSE_WAIT:
1713           case OMP_CLAUSE_GANG:
1714           case OMP_CLAUSE_WORKER:
1715           case OMP_CLAUSE_VECTOR:
1716           case OMP_CLAUSE_INDEPENDENT:
1717           case OMP_CLAUSE_AUTO:
1718           case OMP_CLAUSE_SEQ:
1719           case OMP_CLAUSE_TILE:
1720           case OMP_CLAUSE__SIMT_:
1721           case OMP_CLAUSE_DEFAULT:
1722           case OMP_CLAUSE_NONTEMPORAL:
1723           case OMP_CLAUSE_IF_PRESENT:
1724           case OMP_CLAUSE_FINALIZE:
1725           case OMP_CLAUSE_TASK_REDUCTION:
1726           case OMP_CLAUSE_ALLOCATE:
1727             break;
1728 
1729           case OMP_CLAUSE_ALIGNED:
1730             decl = OMP_CLAUSE_DECL (c);
1731             if (is_global_var (decl)
1732                 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1733               install_var_local (decl, ctx);
1734             break;
1735 
1736           case OMP_CLAUSE__CONDTEMP_:
1737             decl = OMP_CLAUSE_DECL (c);
1738             if (is_parallel_ctx (ctx))
1739               {
1740                 install_var_field (decl, false, 3, ctx);
1741                 install_var_local (decl, ctx);
1742               }
1743             else if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
1744                        && gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_SIMD
1745                        && !OMP_CLAUSE__CONDTEMP__ITER (c))
1746               install_var_local (decl, ctx);
1747             break;
1748 
1749           case OMP_CLAUSE__CACHE_:
1750           case OMP_CLAUSE_NOHOST:
1751           default:
1752             gcc_unreachable ();
1753           }
1754     }
1755 
1756   for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1757     {
1758       switch (OMP_CLAUSE_CODE (c))
1759           {
1760           case OMP_CLAUSE_LASTPRIVATE:
1761             /* Let the corresponding firstprivate clause create
1762                the variable.  */
1763             if (OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
1764               scan_array_reductions = true;
1765             if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1766               break;
1767             /* FALLTHRU */
1768 
1769           case OMP_CLAUSE_FIRSTPRIVATE:
1770           case OMP_CLAUSE_PRIVATE:
1771           case OMP_CLAUSE_LINEAR:
1772           case OMP_CLAUSE_HAS_DEVICE_ADDR:
1773           case OMP_CLAUSE_IS_DEVICE_PTR:
1774             decl = OMP_CLAUSE_DECL (c);
1775             if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_HAS_DEVICE_ADDR)
1776               {
1777                 while (TREE_CODE (decl) == INDIRECT_REF
1778                          || TREE_CODE (decl) == ARRAY_REF)
1779                     decl = TREE_OPERAND (decl, 0);
1780               }
1781 
1782             if (is_variable_sized (decl))
1783               {
1784                 if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE
1785                        || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IS_DEVICE_PTR
1786                        || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_HAS_DEVICE_ADDR)
1787                       && is_gimple_omp_offloaded (ctx->stmt))
1788                     {
1789                       tree decl2 = DECL_VALUE_EXPR (decl);
1790                       gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
1791                       decl2 = TREE_OPERAND (decl2, 0);
1792                       gcc_assert (DECL_P (decl2));
1793                       install_var_local (decl2, ctx);
1794                       fixup_remapped_decl (decl2, ctx, false);
1795                     }
1796                 install_var_local (decl, ctx);
1797               }
1798             fixup_remapped_decl (decl, ctx,
1799                                      OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE
1800                                      && OMP_CLAUSE_PRIVATE_DEBUG (c));
1801             if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
1802                 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
1803               scan_array_reductions = true;
1804             break;
1805 
1806           case OMP_CLAUSE_REDUCTION:
1807           case OMP_CLAUSE_IN_REDUCTION:
1808             decl = OMP_CLAUSE_DECL (c);
1809             if (TREE_CODE (decl) != MEM_REF && !is_omp_target (ctx->stmt))
1810               {
1811                 if (is_variable_sized (decl))
1812                     install_var_local (decl, ctx);
1813                 fixup_remapped_decl (decl, ctx, false);
1814               }
1815             if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1816               scan_array_reductions = true;
1817             break;
1818 
1819           case OMP_CLAUSE_TASK_REDUCTION:
1820             if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1821               scan_array_reductions = true;
1822             break;
1823 
1824           case OMP_CLAUSE_SHARED:
1825             /* Ignore shared directives in teams construct inside of
1826                target construct.  */
1827             if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS
1828                 && !is_host_teams_ctx (ctx))
1829               break;
1830             decl = OMP_CLAUSE_DECL (c);
1831             if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1832               break;
1833             if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
1834               {
1835                 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl,
1836                                                                                  ctx->outer)))
1837                     break;
1838                 bool by_ref = use_pointer_for_field (decl, ctx);
1839                 install_var_field (decl, by_ref, 11, ctx);
1840                 break;
1841               }
1842             fixup_remapped_decl (decl, ctx, false);
1843             break;
1844 
1845           case OMP_CLAUSE_MAP:
1846             if (!is_gimple_omp_offloaded (ctx->stmt))
1847               break;
1848             decl = OMP_CLAUSE_DECL (c);
1849             if (DECL_P (decl)
1850                 && ((OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_FIRSTPRIVATE_POINTER
1851                        && (OMP_CLAUSE_MAP_KIND (c)
1852                            != GOMP_MAP_FIRSTPRIVATE_REFERENCE))
1853                       || TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1854                 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
1855                 && varpool_node::get_create (decl)->offloadable)
1856               break;
1857             if ((OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH
1858                  || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_DETACH)
1859                 && is_omp_target (ctx->stmt)
1860                 && !is_gimple_omp_offloaded (ctx->stmt))
1861               break;
1862             if (DECL_P (decl))
1863               {
1864                 if ((OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
1865                        || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER)
1866                       && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
1867                       && !COMPLETE_TYPE_P (TREE_TYPE (decl)))
1868                     {
1869                       tree new_decl = lookup_decl (decl, ctx);
1870                       TREE_TYPE (new_decl)
1871                         = remap_type (TREE_TYPE (decl), &ctx->cb);
1872                     }
1873                 else if (DECL_SIZE (decl)
1874                            && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
1875                     {
1876                       tree decl2 = DECL_VALUE_EXPR (decl);
1877                       gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
1878                       decl2 = TREE_OPERAND (decl2, 0);
1879                       gcc_assert (DECL_P (decl2));
1880                       fixup_remapped_decl (decl2, ctx, false);
1881                       fixup_remapped_decl (decl, ctx, true);
1882                     }
1883                 else
1884                     fixup_remapped_decl (decl, ctx, false);
1885               }
1886             break;
1887 
1888           case OMP_CLAUSE_COPYPRIVATE:
1889           case OMP_CLAUSE_COPYIN:
1890           case OMP_CLAUSE_DEFAULT:
1891           case OMP_CLAUSE_IF:
1892           case OMP_CLAUSE_NUM_THREADS:
1893           case OMP_CLAUSE_NUM_TEAMS:
1894           case OMP_CLAUSE_THREAD_LIMIT:
1895           case OMP_CLAUSE_DEVICE:
1896           case OMP_CLAUSE_SCHEDULE:
1897           case OMP_CLAUSE_DIST_SCHEDULE:
1898           case OMP_CLAUSE_NOWAIT:
1899           case OMP_CLAUSE_ORDERED:
1900           case OMP_CLAUSE_COLLAPSE:
1901           case OMP_CLAUSE_UNTIED:
1902           case OMP_CLAUSE_FINAL:
1903           case OMP_CLAUSE_MERGEABLE:
1904           case OMP_CLAUSE_PROC_BIND:
1905           case OMP_CLAUSE_SAFELEN:
1906           case OMP_CLAUSE_SIMDLEN:
1907           case OMP_CLAUSE_ALIGNED:
1908           case OMP_CLAUSE_DEPEND:
1909           case OMP_CLAUSE_DETACH:
1910           case OMP_CLAUSE_ALLOCATE:
1911           case OMP_CLAUSE__LOOPTEMP_:
1912           case OMP_CLAUSE__REDUCTEMP_:
1913           case OMP_CLAUSE_TO:
1914           case OMP_CLAUSE_FROM:
1915           case OMP_CLAUSE_PRIORITY:
1916           case OMP_CLAUSE_GRAINSIZE:
1917           case OMP_CLAUSE_NUM_TASKS:
1918           case OMP_CLAUSE_THREADS:
1919           case OMP_CLAUSE_SIMD:
1920           case OMP_CLAUSE_NOGROUP:
1921           case OMP_CLAUSE_DEFAULTMAP:
1922           case OMP_CLAUSE_ORDER:
1923           case OMP_CLAUSE_BIND:
1924           case OMP_CLAUSE_USE_DEVICE_PTR:
1925           case OMP_CLAUSE_USE_DEVICE_ADDR:
1926           case OMP_CLAUSE_NONTEMPORAL:
1927           case OMP_CLAUSE_ASYNC:
1928           case OMP_CLAUSE_WAIT:
1929           case OMP_CLAUSE_NUM_GANGS:
1930           case OMP_CLAUSE_NUM_WORKERS:
1931           case OMP_CLAUSE_VECTOR_LENGTH:
1932           case OMP_CLAUSE_GANG:
1933           case OMP_CLAUSE_WORKER:
1934           case OMP_CLAUSE_VECTOR:
1935           case OMP_CLAUSE_INDEPENDENT:
1936           case OMP_CLAUSE_AUTO:
1937           case OMP_CLAUSE_SEQ:
1938           case OMP_CLAUSE_TILE:
1939           case OMP_CLAUSE__SIMT_:
1940           case OMP_CLAUSE_IF_PRESENT:
1941           case OMP_CLAUSE_FINALIZE:
1942           case OMP_CLAUSE_FILTER:
1943           case OMP_CLAUSE__CONDTEMP_:
1944             break;
1945 
1946           case OMP_CLAUSE__CACHE_:
1947           case OMP_CLAUSE_NOHOST:
1948           default:
1949             gcc_unreachable ();
1950           }
1951     }
1952 
1953   gcc_checking_assert (!scan_array_reductions
1954                            || !is_gimple_omp_oacc (ctx->stmt));
1955   if (scan_array_reductions)
1956     {
1957       for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1958           if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1959                || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IN_REDUCTION
1960                || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_TASK_REDUCTION)
1961               && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1962             {
1963               omp_context *rctx = ctx;
1964               if (is_omp_target (ctx->stmt))
1965                 rctx = ctx->outer;
1966               scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c), rctx);
1967               scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), rctx);
1968             }
1969           else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
1970                      && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
1971             scan_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
1972           else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
1973                      && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
1974             scan_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
1975     }
1976 }
1977 
1978 /* Create a new name for omp child function.  Returns an identifier. */
1979 
1980 static tree
create_omp_child_function_name(bool task_copy)1981 create_omp_child_function_name (bool task_copy)
1982 {
1983   return clone_function_name_numbered (current_function_decl,
1984                                                task_copy ? "_omp_cpyfn" : "_omp_fn");
1985 }
1986 
1987 /* Return true if CTX may belong to offloaded code: either if current function
1988    is offloaded, or any enclosing context corresponds to a target region.  */
1989 
1990 static bool
omp_maybe_offloaded_ctx(omp_context * ctx)1991 omp_maybe_offloaded_ctx (omp_context *ctx)
1992 {
1993   if (cgraph_node::get (current_function_decl)->offloadable)
1994     return true;
1995   for (; ctx; ctx = ctx->outer)
1996     if (is_gimple_omp_offloaded (ctx->stmt))
1997       return true;
1998   return false;
1999 }
2000 
2001 /* Build a decl for the omp child function.  It'll not contain a body
2002    yet, just the bare decl.  */
2003 
2004 static void
create_omp_child_function(omp_context * ctx,bool task_copy)2005 create_omp_child_function (omp_context *ctx, bool task_copy)
2006 {
2007   tree decl, type, name, t;
2008 
2009   name = create_omp_child_function_name (task_copy);
2010   if (task_copy)
2011     type = build_function_type_list (void_type_node, ptr_type_node,
2012                                              ptr_type_node, NULL_TREE);
2013   else
2014     type = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
2015 
2016   decl = build_decl (gimple_location (ctx->stmt), FUNCTION_DECL, name, type);
2017 
2018   gcc_checking_assert (!is_gimple_omp_oacc (ctx->stmt)
2019                            || !task_copy);
2020   if (!task_copy)
2021     ctx->cb.dst_fn = decl;
2022   else
2023     gimple_omp_task_set_copy_fn (ctx->stmt, decl);
2024 
2025   TREE_STATIC (decl) = 1;
2026   TREE_USED (decl) = 1;
2027   DECL_ARTIFICIAL (decl) = 1;
2028   DECL_IGNORED_P (decl) = 0;
2029   TREE_PUBLIC (decl) = 0;
2030   DECL_UNINLINABLE (decl) = 1;
2031   DECL_EXTERNAL (decl) = 0;
2032   DECL_CONTEXT (decl) = NULL_TREE;
2033   DECL_INITIAL (decl) = make_node (BLOCK);
2034   BLOCK_SUPERCONTEXT (DECL_INITIAL (decl)) = decl;
2035   DECL_ATTRIBUTES (decl) = DECL_ATTRIBUTES (current_function_decl);
2036   /* Remove omp declare simd attribute from the new attributes.  */
2037   if (tree a = lookup_attribute ("omp declare simd", DECL_ATTRIBUTES (decl)))
2038     {
2039       while (tree a2 = lookup_attribute ("omp declare simd", TREE_CHAIN (a)))
2040           a = a2;
2041       a = TREE_CHAIN (a);
2042       for (tree *p = &DECL_ATTRIBUTES (decl); *p != a;)
2043           if (is_attribute_p ("omp declare simd", get_attribute_name (*p)))
2044             *p = TREE_CHAIN (*p);
2045           else
2046             {
2047               tree chain = TREE_CHAIN (*p);
2048               *p = copy_node (*p);
2049               p = &TREE_CHAIN (*p);
2050               *p = chain;
2051             }
2052     }
2053   DECL_FUNCTION_SPECIFIC_OPTIMIZATION (decl)
2054     = DECL_FUNCTION_SPECIFIC_OPTIMIZATION (current_function_decl);
2055   DECL_FUNCTION_SPECIFIC_TARGET (decl)
2056     = DECL_FUNCTION_SPECIFIC_TARGET (current_function_decl);
2057   DECL_FUNCTION_VERSIONED (decl)
2058     = DECL_FUNCTION_VERSIONED (current_function_decl);
2059 
2060   if (omp_maybe_offloaded_ctx (ctx))
2061     {
2062       cgraph_node::get_create (decl)->offloadable = 1;
2063       if (ENABLE_OFFLOADING)
2064           g->have_offload = true;
2065     }
2066 
2067   if (cgraph_node::get_create (decl)->offloadable)
2068     {
2069       const char *target_attr = (is_gimple_omp_offloaded (ctx->stmt)
2070                                          ? "omp target entrypoint"
2071                                          : "omp declare target");
2072       if (lookup_attribute ("omp declare target",
2073                                   DECL_ATTRIBUTES (current_function_decl)))
2074           {
2075             if (is_gimple_omp_offloaded (ctx->stmt))
2076               DECL_ATTRIBUTES (decl)
2077                 = remove_attribute ("omp declare target",
2078                                           copy_list (DECL_ATTRIBUTES (decl)));
2079             else
2080               target_attr = NULL;
2081           }
2082       if (target_attr)
2083           DECL_ATTRIBUTES (decl)
2084             = tree_cons (get_identifier (target_attr),
2085                            NULL_TREE, DECL_ATTRIBUTES (decl));
2086     }
2087 
2088   t = build_decl (DECL_SOURCE_LOCATION (decl),
2089                       RESULT_DECL, NULL_TREE, void_type_node);
2090   DECL_ARTIFICIAL (t) = 1;
2091   DECL_IGNORED_P (t) = 1;
2092   DECL_CONTEXT (t) = decl;
2093   DECL_RESULT (decl) = t;
2094 
2095   tree data_name = get_identifier (".omp_data_i");
2096   t = build_decl (DECL_SOURCE_LOCATION (decl), PARM_DECL, data_name,
2097                       ptr_type_node);
2098   DECL_ARTIFICIAL (t) = 1;
2099   DECL_NAMELESS (t) = 1;
2100   DECL_ARG_TYPE (t) = ptr_type_node;
2101   DECL_CONTEXT (t) = current_function_decl;
2102   TREE_USED (t) = 1;
2103   TREE_READONLY (t) = 1;
2104   DECL_ARGUMENTS (decl) = t;
2105   if (!task_copy)
2106     ctx->receiver_decl = t;
2107   else
2108     {
2109       t = build_decl (DECL_SOURCE_LOCATION (decl),
2110                           PARM_DECL, get_identifier (".omp_data_o"),
2111                           ptr_type_node);
2112       DECL_ARTIFICIAL (t) = 1;
2113       DECL_NAMELESS (t) = 1;
2114       DECL_ARG_TYPE (t) = ptr_type_node;
2115       DECL_CONTEXT (t) = current_function_decl;
2116       TREE_USED (t) = 1;
2117       TREE_ADDRESSABLE (t) = 1;
2118       DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2119       DECL_ARGUMENTS (decl) = t;
2120     }
2121 
2122   /* Allocate memory for the function structure.  The call to
2123      allocate_struct_function clobbers CFUN, so we need to restore
2124      it afterward.  */
2125   push_struct_function (decl);
2126   cfun->function_end_locus = gimple_location (ctx->stmt);
2127   init_tree_ssa (cfun);
2128   pop_cfun ();
2129 }
2130 
2131 /* Callback for walk_gimple_seq.  Check if combined parallel
2132    contains gimple_omp_for_combined_into_p OMP_FOR.  */
2133 
2134 tree
omp_find_combined_for(gimple_stmt_iterator * gsi_p,bool * handled_ops_p,struct walk_stmt_info * wi)2135 omp_find_combined_for (gimple_stmt_iterator *gsi_p,
2136                            bool *handled_ops_p,
2137                            struct walk_stmt_info *wi)
2138 {
2139   gimple *stmt = gsi_stmt (*gsi_p);
2140 
2141   *handled_ops_p = true;
2142   switch (gimple_code (stmt))
2143     {
2144     WALK_SUBSTMTS;
2145 
2146     case GIMPLE_OMP_FOR:
2147       if (gimple_omp_for_combined_into_p (stmt)
2148             && gimple_omp_for_kind (stmt)
2149                == *(const enum gf_mask *) (wi->info))
2150           {
2151             wi->info = stmt;
2152             return integer_zero_node;
2153           }
2154       break;
2155     default:
2156       break;
2157     }
2158   return NULL;
2159 }
2160 
2161 /* Add _LOOPTEMP_/_REDUCTEMP_ clauses on OpenMP parallel or task.  */
2162 
2163 static void
add_taskreg_looptemp_clauses(enum gf_mask msk,gimple * stmt,omp_context * outer_ctx)2164 add_taskreg_looptemp_clauses (enum gf_mask msk, gimple *stmt,
2165                                     omp_context *outer_ctx)
2166 {
2167   struct walk_stmt_info wi;
2168 
2169   memset (&wi, 0, sizeof (wi));
2170   wi.val_only = true;
2171   wi.info = (void *) &msk;
2172   walk_gimple_seq (gimple_omp_body (stmt), omp_find_combined_for, NULL, &wi);
2173   if (wi.info != (void *) &msk)
2174     {
2175       gomp_for *for_stmt = as_a <gomp_for *> ((gimple *) wi.info);
2176       struct omp_for_data fd;
2177       omp_extract_for_data (for_stmt, &fd, NULL);
2178       /* We need two temporaries with fd.loop.v type (istart/iend)
2179            and then (fd.collapse - 1) temporaries with the same
2180            type for count2 ... countN-1 vars if not constant.  */
2181       size_t count = 2, i;
2182       tree type = fd.iter_type;
2183       if (fd.collapse > 1
2184             && TREE_CODE (fd.loop.n2) != INTEGER_CST)
2185           {
2186             count += fd.collapse - 1;
2187             /* If there are lastprivate clauses on the inner
2188                GIMPLE_OMP_FOR, add one more temporaries for the total number
2189                of iterations (product of count1 ... countN-1).  */
2190             if (omp_find_clause (gimple_omp_for_clauses (for_stmt),
2191                                      OMP_CLAUSE_LASTPRIVATE)
2192                 || (msk == GF_OMP_FOR_KIND_FOR
2193                       && omp_find_clause (gimple_omp_parallel_clauses (stmt),
2194                                               OMP_CLAUSE_LASTPRIVATE)))
2195               {
2196                 tree temp = create_tmp_var (type);
2197                 tree c = build_omp_clause (UNKNOWN_LOCATION,
2198                                                    OMP_CLAUSE__LOOPTEMP_);
2199                 insert_decl_map (&outer_ctx->cb, temp, temp);
2200                 OMP_CLAUSE_DECL (c) = temp;
2201                 OMP_CLAUSE_CHAIN (c) = gimple_omp_taskreg_clauses (stmt);
2202                 gimple_omp_taskreg_set_clauses (stmt, c);
2203               }
2204             if (fd.non_rect
2205                 && fd.last_nonrect == fd.first_nonrect + 1)
2206               if (tree v = gimple_omp_for_index (for_stmt, fd.last_nonrect))
2207                 if (!TYPE_UNSIGNED (TREE_TYPE (v)))
2208                     {
2209                       v = gimple_omp_for_index (for_stmt, fd.first_nonrect);
2210                       tree type2 = TREE_TYPE (v);
2211                       count++;
2212                       for (i = 0; i < 3; i++)
2213                         {
2214                           tree temp = create_tmp_var (type2);
2215                           tree c = build_omp_clause (UNKNOWN_LOCATION,
2216                                                              OMP_CLAUSE__LOOPTEMP_);
2217                           insert_decl_map (&outer_ctx->cb, temp, temp);
2218                           OMP_CLAUSE_DECL (c) = temp;
2219                           OMP_CLAUSE_CHAIN (c) = gimple_omp_taskreg_clauses (stmt);
2220                           gimple_omp_taskreg_set_clauses (stmt, c);
2221                         }
2222                     }
2223           }
2224       for (i = 0; i < count; i++)
2225           {
2226             tree temp = create_tmp_var (type);
2227             tree c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__LOOPTEMP_);
2228             insert_decl_map (&outer_ctx->cb, temp, temp);
2229             OMP_CLAUSE_DECL (c) = temp;
2230             OMP_CLAUSE_CHAIN (c) = gimple_omp_taskreg_clauses (stmt);
2231             gimple_omp_taskreg_set_clauses (stmt, c);
2232           }
2233     }
2234   if (msk == GF_OMP_FOR_KIND_TASKLOOP
2235       && omp_find_clause (gimple_omp_task_clauses (stmt),
2236                                 OMP_CLAUSE_REDUCTION))
2237     {
2238       tree type = build_pointer_type (pointer_sized_int_node);
2239       tree temp = create_tmp_var (type);
2240       tree c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__REDUCTEMP_);
2241       insert_decl_map (&outer_ctx->cb, temp, temp);
2242       OMP_CLAUSE_DECL (c) = temp;
2243       OMP_CLAUSE_CHAIN (c) = gimple_omp_task_clauses (stmt);
2244       gimple_omp_task_set_clauses (stmt, c);
2245     }
2246 }
2247 
2248 /* Scan an OpenMP parallel directive.  */
2249 
2250 static void
scan_omp_parallel(gimple_stmt_iterator * gsi,omp_context * outer_ctx)2251 scan_omp_parallel (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
2252 {
2253   omp_context *ctx;
2254   tree name;
2255   gomp_parallel *stmt = as_a <gomp_parallel *> (gsi_stmt (*gsi));
2256 
2257   /* Ignore parallel directives with empty bodies, unless there
2258      are copyin clauses.  */
2259   if (optimize > 0
2260       && empty_body_p (gimple_omp_body (stmt))
2261       && omp_find_clause (gimple_omp_parallel_clauses (stmt),
2262                                 OMP_CLAUSE_COPYIN) == NULL)
2263     {
2264       gsi_replace (gsi, gimple_build_nop (), false);
2265       return;
2266     }
2267 
2268   if (gimple_omp_parallel_combined_p (stmt))
2269     add_taskreg_looptemp_clauses (GF_OMP_FOR_KIND_FOR, stmt, outer_ctx);
2270   for (tree c = omp_find_clause (gimple_omp_parallel_clauses (stmt),
2271                                          OMP_CLAUSE_REDUCTION);
2272        c; c = omp_find_clause (OMP_CLAUSE_CHAIN (c), OMP_CLAUSE_REDUCTION))
2273     if (OMP_CLAUSE_REDUCTION_TASK (c))
2274       {
2275           tree type = build_pointer_type (pointer_sized_int_node);
2276           tree temp = create_tmp_var (type);
2277           tree c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__REDUCTEMP_);
2278           if (outer_ctx)
2279             insert_decl_map (&outer_ctx->cb, temp, temp);
2280           OMP_CLAUSE_DECL (c) = temp;
2281           OMP_CLAUSE_CHAIN (c) = gimple_omp_parallel_clauses (stmt);
2282           gimple_omp_parallel_set_clauses (stmt, c);
2283           break;
2284       }
2285     else if (OMP_CLAUSE_CHAIN (c) == NULL_TREE)
2286       break;
2287 
2288   ctx = new_omp_context (stmt, outer_ctx);
2289   taskreg_contexts.safe_push (ctx);
2290   if (taskreg_nesting_level > 1)
2291     ctx->is_nested = true;
2292   ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2293   ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2294   name = create_tmp_var_name (".omp_data_s");
2295   name = build_decl (gimple_location (stmt),
2296                          TYPE_DECL, name, ctx->record_type);
2297   DECL_ARTIFICIAL (name) = 1;
2298   DECL_NAMELESS (name) = 1;
2299   TYPE_NAME (ctx->record_type) = name;
2300   TYPE_ARTIFICIAL (ctx->record_type) = 1;
2301   create_omp_child_function (ctx, false);
2302   gimple_omp_parallel_set_child_fn (stmt, ctx->cb.dst_fn);
2303 
2304   scan_sharing_clauses (gimple_omp_parallel_clauses (stmt), ctx);
2305   scan_omp (gimple_omp_body_ptr (stmt), ctx);
2306 
2307   if (TYPE_FIELDS (ctx->record_type) == NULL)
2308     ctx->record_type = ctx->receiver_decl = NULL;
2309 }
2310 
2311 /* Scan an OpenMP task directive.  */
2312 
2313 static void
scan_omp_task(gimple_stmt_iterator * gsi,omp_context * outer_ctx)2314 scan_omp_task (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
2315 {
2316   omp_context *ctx;
2317   tree name, t;
2318   gomp_task *stmt = as_a <gomp_task *> (gsi_stmt (*gsi));
2319 
2320   /* Ignore task directives with empty bodies, unless they have depend
2321      clause.  */
2322   if (optimize > 0
2323       && gimple_omp_body (stmt)
2324       && empty_body_p (gimple_omp_body (stmt))
2325       && !omp_find_clause (gimple_omp_task_clauses (stmt), OMP_CLAUSE_DEPEND))
2326     {
2327       gsi_replace (gsi, gimple_build_nop (), false);
2328       return;
2329     }
2330 
2331   if (gimple_omp_task_taskloop_p (stmt))
2332     add_taskreg_looptemp_clauses (GF_OMP_FOR_KIND_TASKLOOP, stmt, outer_ctx);
2333 
2334   ctx = new_omp_context (stmt, outer_ctx);
2335 
2336   if (gimple_omp_task_taskwait_p (stmt))
2337     {
2338       scan_sharing_clauses (gimple_omp_task_clauses (stmt), ctx);
2339       return;
2340     }
2341 
2342   taskreg_contexts.safe_push (ctx);
2343   if (taskreg_nesting_level > 1)
2344     ctx->is_nested = true;
2345   ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2346   ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2347   name = create_tmp_var_name (".omp_data_s");
2348   name = build_decl (gimple_location (stmt),
2349                          TYPE_DECL, name, ctx->record_type);
2350   DECL_ARTIFICIAL (name) = 1;
2351   DECL_NAMELESS (name) = 1;
2352   TYPE_NAME (ctx->record_type) = name;
2353   TYPE_ARTIFICIAL (ctx->record_type) = 1;
2354   create_omp_child_function (ctx, false);
2355   gimple_omp_task_set_child_fn (stmt, ctx->cb.dst_fn);
2356 
2357   scan_sharing_clauses (gimple_omp_task_clauses (stmt), ctx);
2358 
2359   if (ctx->srecord_type)
2360     {
2361       name = create_tmp_var_name (".omp_data_a");
2362       name = build_decl (gimple_location (stmt),
2363                                TYPE_DECL, name, ctx->srecord_type);
2364       DECL_ARTIFICIAL (name) = 1;
2365       DECL_NAMELESS (name) = 1;
2366       TYPE_NAME (ctx->srecord_type) = name;
2367       TYPE_ARTIFICIAL (ctx->srecord_type) = 1;
2368       create_omp_child_function (ctx, true);
2369     }
2370 
2371   scan_omp (gimple_omp_body_ptr (stmt), ctx);
2372 
2373   if (TYPE_FIELDS (ctx->record_type) == NULL)
2374     {
2375       ctx->record_type = ctx->receiver_decl = NULL;
2376       t = build_int_cst (long_integer_type_node, 0);
2377       gimple_omp_task_set_arg_size (stmt, t);
2378       t = build_int_cst (long_integer_type_node, 1);
2379       gimple_omp_task_set_arg_align (stmt, t);
2380     }
2381 }
2382 
2383 /* Helper function for finish_taskreg_scan, called through walk_tree.
2384    If maybe_lookup_decl_in_outer_context returns non-NULL for some
2385    tree, replace it in the expression.  */
2386 
2387 static tree
finish_taskreg_remap(tree * tp,int * walk_subtrees,void * data)2388 finish_taskreg_remap (tree *tp, int *walk_subtrees, void *data)
2389 {
2390   if (VAR_P (*tp))
2391     {
2392       omp_context *ctx = (omp_context *) data;
2393       tree t = maybe_lookup_decl_in_outer_ctx (*tp, ctx);
2394       if (t != *tp)
2395           {
2396             if (DECL_HAS_VALUE_EXPR_P (t))
2397               t = unshare_expr (DECL_VALUE_EXPR (t));
2398             *tp = t;
2399           }
2400       *walk_subtrees = 0;
2401     }
2402   else if (IS_TYPE_OR_DECL_P (*tp))
2403     *walk_subtrees = 0;
2404   return NULL_TREE;
2405 }
2406 
2407 /* If any decls have been made addressable during scan_omp,
2408    adjust their fields if needed, and layout record types
2409    of parallel/task constructs.  */
2410 
2411 static void
finish_taskreg_scan(omp_context * ctx)2412 finish_taskreg_scan (omp_context *ctx)
2413 {
2414   if (ctx->record_type == NULL_TREE)
2415     return;
2416 
2417   /* If any make_addressable_vars were needed, verify all
2418      OMP_CLAUSE_SHARED clauses on GIMPLE_OMP_{PARALLEL,TASK,TEAMS}
2419      statements if use_pointer_for_field hasn't changed
2420      because of that.  If it did, update field types now.  */
2421   if (make_addressable_vars)
2422     {
2423       tree c;
2424 
2425       for (c = gimple_omp_taskreg_clauses (ctx->stmt);
2426              c; c = OMP_CLAUSE_CHAIN (c))
2427           if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
2428               && !OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
2429             {
2430               tree decl = OMP_CLAUSE_DECL (c);
2431 
2432               /* Global variables don't need to be copied,
2433                  the receiver side will use them directly.  */
2434               if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
2435                 continue;
2436               if (!bitmap_bit_p (make_addressable_vars, DECL_UID (decl))
2437                     || !use_pointer_for_field (decl, ctx))
2438                 continue;
2439               tree field = lookup_field (decl, ctx);
2440               if (TREE_CODE (TREE_TYPE (field)) == POINTER_TYPE
2441                     && TREE_TYPE (TREE_TYPE (field)) == TREE_TYPE (decl))
2442                 continue;
2443               TREE_TYPE (field) = build_pointer_type (TREE_TYPE (decl));
2444               TREE_THIS_VOLATILE (field) = 0;
2445               DECL_USER_ALIGN (field) = 0;
2446               SET_DECL_ALIGN (field, TYPE_ALIGN (TREE_TYPE (field)));
2447               if (TYPE_ALIGN (ctx->record_type) < DECL_ALIGN (field))
2448                 SET_TYPE_ALIGN (ctx->record_type, DECL_ALIGN (field));
2449               if (ctx->srecord_type)
2450                 {
2451                     tree sfield = lookup_sfield (decl, ctx);
2452                     TREE_TYPE (sfield) = TREE_TYPE (field);
2453                     TREE_THIS_VOLATILE (sfield) = 0;
2454                     DECL_USER_ALIGN (sfield) = 0;
2455                     SET_DECL_ALIGN (sfield, DECL_ALIGN (field));
2456                     if (TYPE_ALIGN (ctx->srecord_type) < DECL_ALIGN (sfield))
2457                       SET_TYPE_ALIGN (ctx->srecord_type, DECL_ALIGN (sfield));
2458                 }
2459             }
2460     }
2461 
2462   if (gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL)
2463     {
2464       tree clauses = gimple_omp_parallel_clauses (ctx->stmt);
2465       tree c = omp_find_clause (clauses, OMP_CLAUSE__REDUCTEMP_);
2466       if (c)
2467           {
2468             /* Move the _reductemp_ clause first.  GOMP_parallel_reductions
2469                expects to find it at the start of data.  */
2470             tree f = lookup_field (OMP_CLAUSE_DECL (c), ctx);
2471             tree *p = &TYPE_FIELDS (ctx->record_type);
2472             while (*p)
2473               if (*p == f)
2474                 {
2475                     *p = DECL_CHAIN (*p);
2476                     break;
2477                 }
2478               else
2479                 p = &DECL_CHAIN (*p);
2480             DECL_CHAIN (f) = TYPE_FIELDS (ctx->record_type);
2481             TYPE_FIELDS (ctx->record_type) = f;
2482           }
2483       layout_type (ctx->record_type);
2484       fixup_child_record_type (ctx);
2485     }
2486   else if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
2487     {
2488       layout_type (ctx->record_type);
2489       fixup_child_record_type (ctx);
2490     }
2491   else
2492     {
2493       location_t loc = gimple_location (ctx->stmt);
2494       tree *p, vla_fields = NULL_TREE, *q = &vla_fields;
2495       tree detach_clause
2496           = omp_find_clause (gimple_omp_task_clauses (ctx->stmt),
2497                                  OMP_CLAUSE_DETACH);
2498       /* Move VLA fields to the end.  */
2499       p = &TYPE_FIELDS (ctx->record_type);
2500       while (*p)
2501           if (!TYPE_SIZE_UNIT (TREE_TYPE (*p))
2502               || ! TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (*p))))
2503             {
2504               *q = *p;
2505               *p = TREE_CHAIN (*p);
2506               TREE_CHAIN (*q) = NULL_TREE;
2507               q = &TREE_CHAIN (*q);
2508             }
2509           else
2510             p = &DECL_CHAIN (*p);
2511       *p = vla_fields;
2512       if (gimple_omp_task_taskloop_p (ctx->stmt))
2513           {
2514             /* Move fields corresponding to first and second _looptemp_
2515                clause first.  There are filled by GOMP_taskloop
2516                and thus need to be in specific positions.  */
2517             tree clauses = gimple_omp_task_clauses (ctx->stmt);
2518             tree c1 = omp_find_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
2519             tree c2 = omp_find_clause (OMP_CLAUSE_CHAIN (c1),
2520                                              OMP_CLAUSE__LOOPTEMP_);
2521             tree c3 = omp_find_clause (clauses, OMP_CLAUSE__REDUCTEMP_);
2522             tree f1 = lookup_field (OMP_CLAUSE_DECL (c1), ctx);
2523             tree f2 = lookup_field (OMP_CLAUSE_DECL (c2), ctx);
2524             tree f3 = c3 ? lookup_field (OMP_CLAUSE_DECL (c3), ctx) : NULL_TREE;
2525             p = &TYPE_FIELDS (ctx->record_type);
2526             while (*p)
2527               if (*p == f1 || *p == f2 || *p == f3)
2528                 *p = DECL_CHAIN (*p);
2529               else
2530                 p = &DECL_CHAIN (*p);
2531             DECL_CHAIN (f1) = f2;
2532             if (c3)
2533               {
2534                 DECL_CHAIN (f2) = f3;
2535                 DECL_CHAIN (f3) = TYPE_FIELDS (ctx->record_type);
2536               }
2537             else
2538               DECL_CHAIN (f2) = TYPE_FIELDS (ctx->record_type);
2539             TYPE_FIELDS (ctx->record_type) = f1;
2540             if (ctx->srecord_type)
2541               {
2542                 f1 = lookup_sfield (OMP_CLAUSE_DECL (c1), ctx);
2543                 f2 = lookup_sfield (OMP_CLAUSE_DECL (c2), ctx);
2544                 if (c3)
2545                     f3 = lookup_sfield (OMP_CLAUSE_DECL (c3), ctx);
2546                 p = &TYPE_FIELDS (ctx->srecord_type);
2547                 while (*p)
2548                     if (*p == f1 || *p == f2 || *p == f3)
2549                       *p = DECL_CHAIN (*p);
2550                     else
2551                       p = &DECL_CHAIN (*p);
2552                 DECL_CHAIN (f1) = f2;
2553                 DECL_CHAIN (f2) = TYPE_FIELDS (ctx->srecord_type);
2554                 if (c3)
2555                     {
2556                       DECL_CHAIN (f2) = f3;
2557                       DECL_CHAIN (f3) = TYPE_FIELDS (ctx->srecord_type);
2558                     }
2559                 else
2560                     DECL_CHAIN (f2) = TYPE_FIELDS (ctx->srecord_type);
2561                 TYPE_FIELDS (ctx->srecord_type) = f1;
2562               }
2563           }
2564       if (detach_clause)
2565           {
2566             tree c, field;
2567 
2568             /* Look for a firstprivate clause with the detach event handle.  */
2569             for (c = gimple_omp_taskreg_clauses (ctx->stmt);
2570                  c; c = OMP_CLAUSE_CHAIN (c))
2571               {
2572                 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_FIRSTPRIVATE)
2573                     continue;
2574                 if (maybe_lookup_decl_in_outer_ctx (OMP_CLAUSE_DECL (c), ctx)
2575                       == OMP_CLAUSE_DECL (detach_clause))
2576                     break;
2577               }
2578 
2579             gcc_assert (c);
2580             field = lookup_field (OMP_CLAUSE_DECL (c), ctx);
2581 
2582             /* Move field corresponding to the detach clause first.
2583                This is filled by GOMP_task and needs to be in a
2584                specific position.  */
2585             p = &TYPE_FIELDS (ctx->record_type);
2586             while (*p)
2587               if (*p == field)
2588                 *p = DECL_CHAIN (*p);
2589               else
2590                 p = &DECL_CHAIN (*p);
2591             DECL_CHAIN (field) = TYPE_FIELDS (ctx->record_type);
2592             TYPE_FIELDS (ctx->record_type) = field;
2593             if (ctx->srecord_type)
2594               {
2595                 field = lookup_sfield (OMP_CLAUSE_DECL (c), ctx);
2596                 p = &TYPE_FIELDS (ctx->srecord_type);
2597                 while (*p)
2598                     if (*p == field)
2599                       *p = DECL_CHAIN (*p);
2600                     else
2601                       p = &DECL_CHAIN (*p);
2602                 DECL_CHAIN (field) = TYPE_FIELDS (ctx->srecord_type);
2603                 TYPE_FIELDS (ctx->srecord_type) = field;
2604               }
2605           }
2606       layout_type (ctx->record_type);
2607       fixup_child_record_type (ctx);
2608       if (ctx->srecord_type)
2609           layout_type (ctx->srecord_type);
2610       tree t = fold_convert_loc (loc, long_integer_type_node,
2611                                          TYPE_SIZE_UNIT (ctx->record_type));
2612       if (TREE_CODE (t) != INTEGER_CST)
2613           {
2614             t = unshare_expr (t);
2615             walk_tree (&t, finish_taskreg_remap, ctx, NULL);
2616           }
2617       gimple_omp_task_set_arg_size (ctx->stmt, t);
2618       t = build_int_cst (long_integer_type_node,
2619                                TYPE_ALIGN_UNIT (ctx->record_type));
2620       gimple_omp_task_set_arg_align (ctx->stmt, t);
2621     }
2622 }
2623 
2624 /* Find the enclosing offload context.  */
2625 
2626 static omp_context *
enclosing_target_ctx(omp_context * ctx)2627 enclosing_target_ctx (omp_context *ctx)
2628 {
2629   for (; ctx; ctx = ctx->outer)
2630     if (gimple_code (ctx->stmt) == GIMPLE_OMP_TARGET)
2631       break;
2632 
2633   return ctx;
2634 }
2635 
2636 /* Return whether CTX's parent compute construct is an OpenACC 'kernels'
2637    construct.
2638    (This doesn't include OpenACC 'kernels' decomposed parts.)  */
2639 
2640 static bool
ctx_in_oacc_kernels_region(omp_context * ctx)2641 ctx_in_oacc_kernels_region (omp_context *ctx)
2642 {
2643   for (;ctx != NULL; ctx = ctx->outer)
2644     {
2645       gimple *stmt = ctx->stmt;
2646       if (gimple_code (stmt) == GIMPLE_OMP_TARGET
2647             && gimple_omp_target_kind (stmt) == GF_OMP_TARGET_KIND_OACC_KERNELS)
2648           return true;
2649     }
2650 
2651   return false;
2652 }
2653 
2654 /* Check the parallelism clauses inside a OpenACC 'kernels' region.
2655    (This doesn't include OpenACC 'kernels' decomposed parts.)
2656    Until kernels handling moves to use the same loop indirection
2657    scheme as parallel, we need to do this checking early.  */
2658 
2659 static unsigned
check_oacc_kernel_gwv(gomp_for * stmt,omp_context * ctx)2660 check_oacc_kernel_gwv (gomp_for *stmt, omp_context *ctx)
2661 {
2662   bool checking = true;
2663   unsigned outer_mask = 0;
2664   unsigned this_mask = 0;
2665   bool has_seq = false, has_auto = false;
2666 
2667   if (ctx->outer)
2668     outer_mask = check_oacc_kernel_gwv (NULL,  ctx->outer);
2669   if (!stmt)
2670     {
2671       checking = false;
2672       if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR)
2673           return outer_mask;
2674       stmt = as_a <gomp_for *> (ctx->stmt);
2675     }
2676 
2677   for (tree c = gimple_omp_for_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c))
2678     {
2679       switch (OMP_CLAUSE_CODE (c))
2680           {
2681           case OMP_CLAUSE_GANG:
2682             this_mask |= GOMP_DIM_MASK (GOMP_DIM_GANG);
2683             break;
2684           case OMP_CLAUSE_WORKER:
2685             this_mask |= GOMP_DIM_MASK (GOMP_DIM_WORKER);
2686             break;
2687           case OMP_CLAUSE_VECTOR:
2688             this_mask |= GOMP_DIM_MASK (GOMP_DIM_VECTOR);
2689             break;
2690           case OMP_CLAUSE_SEQ:
2691             has_seq = true;
2692             break;
2693           case OMP_CLAUSE_AUTO:
2694             has_auto = true;
2695             break;
2696           default:
2697             break;
2698           }
2699     }
2700 
2701   if (checking)
2702     {
2703       if (has_seq && (this_mask || has_auto))
2704           error_at (gimple_location (stmt), "%<seq%> overrides other"
2705                       " OpenACC loop specifiers");
2706       else if (has_auto && this_mask)
2707           error_at (gimple_location (stmt), "%<auto%> conflicts with other"
2708                       " OpenACC loop specifiers");
2709 
2710       if (this_mask & outer_mask)
2711           error_at (gimple_location (stmt), "inner loop uses same"
2712                       " OpenACC parallelism as containing loop");
2713     }
2714 
2715   return outer_mask | this_mask;
2716 }
2717 
2718 /* Scan a GIMPLE_OMP_FOR.  */
2719 
2720 static omp_context *
scan_omp_for(gomp_for * stmt,omp_context * outer_ctx)2721 scan_omp_for (gomp_for *stmt, omp_context *outer_ctx)
2722 {
2723   omp_context *ctx;
2724   size_t i;
2725   tree clauses = gimple_omp_for_clauses (stmt);
2726 
2727   ctx = new_omp_context (stmt, outer_ctx);
2728 
2729   if (is_gimple_omp_oacc (stmt))
2730     {
2731       omp_context *tgt = enclosing_target_ctx (outer_ctx);
2732 
2733       if (!(tgt && is_oacc_kernels (tgt)))
2734           for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
2735             {
2736               tree c_op0;
2737               switch (OMP_CLAUSE_CODE (c))
2738                 {
2739                 case OMP_CLAUSE_GANG:
2740                     c_op0 = OMP_CLAUSE_GANG_EXPR (c);
2741                     break;
2742 
2743                 case OMP_CLAUSE_WORKER:
2744                     c_op0 = OMP_CLAUSE_WORKER_EXPR (c);
2745                     break;
2746 
2747                 case OMP_CLAUSE_VECTOR:
2748                     c_op0 = OMP_CLAUSE_VECTOR_EXPR (c);
2749                     break;
2750 
2751                 default:
2752                     continue;
2753                 }
2754 
2755               if (c_op0)
2756                 {
2757                     /* By construction, this is impossible for OpenACC 'kernels'
2758                        decomposed parts.  */
2759                     gcc_assert (!(tgt && is_oacc_kernels_decomposed_part (tgt)));
2760 
2761                     error_at (OMP_CLAUSE_LOCATION (c),
2762                                 "argument not permitted on %qs clause",
2763                                 omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
2764                     if (tgt)
2765                       inform (gimple_location (tgt->stmt),
2766                                 "enclosing parent compute construct");
2767                     else if (oacc_get_fn_attrib (current_function_decl))
2768                       inform (DECL_SOURCE_LOCATION (current_function_decl),
2769                                 "enclosing routine");
2770                     else
2771                       gcc_unreachable ();
2772                 }
2773             }
2774 
2775       if (tgt && is_oacc_kernels (tgt))
2776           check_oacc_kernel_gwv (stmt, ctx);
2777 
2778       /* Collect all variables named in reductions on this loop.  Ensure
2779            that, if this loop has a reduction on some variable v, and there is
2780            a reduction on v somewhere in an outer context, then there is a
2781            reduction on v on all intervening loops as well.  */
2782       tree local_reduction_clauses = NULL;
2783       for (tree c = gimple_omp_for_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c))
2784           {
2785             if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
2786               local_reduction_clauses
2787                 = tree_cons (NULL, c, local_reduction_clauses);
2788           }
2789       if (ctx->outer_reduction_clauses == NULL && ctx->outer != NULL)
2790           ctx->outer_reduction_clauses
2791             = chainon (unshare_expr (ctx->outer->local_reduction_clauses),
2792                          ctx->outer->outer_reduction_clauses);
2793       tree outer_reduction_clauses = ctx->outer_reduction_clauses;
2794       tree local_iter = local_reduction_clauses;
2795       for (; local_iter; local_iter = TREE_CHAIN (local_iter))
2796           {
2797             tree local_clause = TREE_VALUE (local_iter);
2798             tree local_var = OMP_CLAUSE_DECL (local_clause);
2799             tree_code local_op = OMP_CLAUSE_REDUCTION_CODE (local_clause);
2800             bool have_outer_reduction = false;
2801             tree ctx_iter = outer_reduction_clauses;
2802             for (; ctx_iter; ctx_iter = TREE_CHAIN (ctx_iter))
2803               {
2804                 tree outer_clause = TREE_VALUE (ctx_iter);
2805                 tree outer_var = OMP_CLAUSE_DECL (outer_clause);
2806                 tree_code outer_op = OMP_CLAUSE_REDUCTION_CODE (outer_clause);
2807                 if (outer_var == local_var && outer_op != local_op)
2808                     {
2809                       warning_at (OMP_CLAUSE_LOCATION (local_clause), 0,
2810                                     "conflicting reduction operations for %qE",
2811                                     local_var);
2812                       inform (OMP_CLAUSE_LOCATION (outer_clause),
2813                                 "location of the previous reduction for %qE",
2814                                 outer_var);
2815                     }
2816                 if (outer_var == local_var)
2817                     {
2818                       have_outer_reduction = true;
2819                       break;
2820                     }
2821               }
2822             if (have_outer_reduction)
2823               {
2824                 /* There is a reduction on outer_var both on this loop and on
2825                      some enclosing loop.  Walk up the context tree until such a
2826                      loop with a reduction on outer_var is found, and complain
2827                      about all intervening loops that do not have such a
2828                      reduction.  */
2829                 struct omp_context *curr_loop = ctx->outer;
2830                 bool found = false;
2831                 while (curr_loop != NULL)
2832                     {
2833                       tree curr_iter = curr_loop->local_reduction_clauses;
2834                       for (; curr_iter; curr_iter = TREE_CHAIN (curr_iter))
2835                         {
2836                           tree curr_clause = TREE_VALUE (curr_iter);
2837                           tree curr_var = OMP_CLAUSE_DECL (curr_clause);
2838                           if (curr_var == local_var)
2839                               {
2840                                 found = true;
2841                                 break;
2842                               }
2843                         }
2844                       if (!found)
2845                         warning_at (gimple_location (curr_loop->stmt), 0,
2846                                         "nested loop in reduction needs "
2847                                         "reduction clause for %qE",
2848                                         local_var);
2849                       else
2850                         break;
2851                       curr_loop = curr_loop->outer;
2852                     }
2853               }
2854           }
2855       ctx->local_reduction_clauses = local_reduction_clauses;
2856       ctx->outer_reduction_clauses
2857           = chainon (unshare_expr (ctx->local_reduction_clauses),
2858                        ctx->outer_reduction_clauses);
2859 
2860       if (tgt && is_oacc_kernels (tgt))
2861           {
2862             /* Strip out reductions, as they are not handled yet.  */
2863             tree *prev_ptr = &clauses;
2864 
2865             while (tree probe = *prev_ptr)
2866               {
2867                 tree *next_ptr = &OMP_CLAUSE_CHAIN (probe);
2868 
2869                 if (OMP_CLAUSE_CODE (probe) == OMP_CLAUSE_REDUCTION)
2870                     *prev_ptr = *next_ptr;
2871                 else
2872                     prev_ptr = next_ptr;
2873               }
2874 
2875             gimple_omp_for_set_clauses (stmt, clauses);
2876           }
2877     }
2878 
2879   scan_sharing_clauses (clauses, ctx);
2880 
2881   scan_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
2882   for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
2883     {
2884       scan_omp_op (gimple_omp_for_index_ptr (stmt, i), ctx);
2885       scan_omp_op (gimple_omp_for_initial_ptr (stmt, i), ctx);
2886       scan_omp_op (gimple_omp_for_final_ptr (stmt, i), ctx);
2887       scan_omp_op (gimple_omp_for_incr_ptr (stmt, i), ctx);
2888     }
2889   scan_omp (gimple_omp_body_ptr (stmt), ctx);
2890   return ctx;
2891 }
2892 
2893 /* Duplicate #pragma omp simd, one for SIMT, another one for SIMD.  */
2894 
2895 static void
scan_omp_simd(gimple_stmt_iterator * gsi,gomp_for * stmt,omp_context * outer_ctx)2896 scan_omp_simd (gimple_stmt_iterator *gsi, gomp_for *stmt,
2897                  omp_context *outer_ctx)
2898 {
2899   gbind *bind = gimple_build_bind (NULL, NULL, NULL);
2900   gsi_replace (gsi, bind, false);
2901   gimple_seq seq = NULL;
2902   gimple *g = gimple_build_call_internal (IFN_GOMP_USE_SIMT, 0);
2903   tree cond = create_tmp_var_raw (integer_type_node);
2904   DECL_CONTEXT (cond) = current_function_decl;
2905   DECL_SEEN_IN_BIND_EXPR_P (cond) = 1;
2906   gimple_bind_set_vars (bind, cond);
2907   gimple_call_set_lhs (g, cond);
2908   gimple_seq_add_stmt (&seq, g);
2909   tree lab1 = create_artificial_label (UNKNOWN_LOCATION);
2910   tree lab2 = create_artificial_label (UNKNOWN_LOCATION);
2911   tree lab3 = create_artificial_label (UNKNOWN_LOCATION);
2912   g = gimple_build_cond (NE_EXPR, cond, integer_zero_node, lab1, lab2);
2913   gimple_seq_add_stmt (&seq, g);
2914   g = gimple_build_label (lab1);
2915   gimple_seq_add_stmt (&seq, g);
2916   gimple_seq new_seq = copy_gimple_seq_and_replace_locals (stmt);
2917   gomp_for *new_stmt = as_a <gomp_for *> (new_seq);
2918   tree clause = build_omp_clause (gimple_location (stmt), OMP_CLAUSE__SIMT_);
2919   OMP_CLAUSE_CHAIN (clause) = gimple_omp_for_clauses (new_stmt);
2920   gimple_omp_for_set_clauses (new_stmt, clause);
2921   gimple_seq_add_stmt (&seq, new_stmt);
2922   g = gimple_build_goto (lab3);
2923   gimple_seq_add_stmt (&seq, g);
2924   g = gimple_build_label (lab2);
2925   gimple_seq_add_stmt (&seq, g);
2926   gimple_seq_add_stmt (&seq, stmt);
2927   g = gimple_build_label (lab3);
2928   gimple_seq_add_stmt (&seq, g);
2929   gimple_bind_set_body (bind, seq);
2930   update_stmt (bind);
2931   scan_omp_for (new_stmt, outer_ctx);
2932   scan_omp_for (stmt, outer_ctx)->simt_stmt = new_stmt;
2933 }
2934 
2935 static tree omp_find_scan (gimple_stmt_iterator *, bool *,
2936                                  struct walk_stmt_info *);
2937 static omp_context *maybe_lookup_ctx (gimple *);
2938 
2939 /* Duplicate #pragma omp simd, one for the scan input phase loop and one
2940    for scan phase loop.  */
2941 
2942 static void
scan_omp_simd_scan(gimple_stmt_iterator * gsi,gomp_for * stmt,omp_context * outer_ctx)2943 scan_omp_simd_scan (gimple_stmt_iterator *gsi, gomp_for *stmt,
2944                         omp_context *outer_ctx)
2945 {
2946   /* The only change between inclusive and exclusive scan will be
2947      within the first simd loop, so just use inclusive in the
2948      worksharing loop.  */
2949   outer_ctx->scan_inclusive = true;
2950   tree c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_INCLUSIVE);
2951   OMP_CLAUSE_DECL (c) = integer_zero_node;
2952 
2953   gomp_scan *input_stmt = gimple_build_omp_scan (NULL, NULL_TREE);
2954   gomp_scan *scan_stmt = gimple_build_omp_scan (NULL, c);
2955   gsi_replace (gsi, input_stmt, false);
2956   gimple_seq input_body = NULL;
2957   gimple_seq_add_stmt (&input_body, stmt);
2958   gsi_insert_after (gsi, scan_stmt, GSI_NEW_STMT);
2959 
2960   gimple_stmt_iterator input1_gsi = gsi_none ();
2961   struct walk_stmt_info wi;
2962   memset (&wi, 0, sizeof (wi));
2963   wi.val_only = true;
2964   wi.info = (void *) &input1_gsi;
2965   walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), omp_find_scan, NULL, &wi);
2966   gcc_assert (!gsi_end_p (input1_gsi));
2967 
2968   gimple *input_stmt1 = gsi_stmt (input1_gsi);
2969   gsi_next (&input1_gsi);
2970   gimple *scan_stmt1 = gsi_stmt (input1_gsi);
2971   gcc_assert (scan_stmt1 && gimple_code (scan_stmt1) == GIMPLE_OMP_SCAN);
2972   c = gimple_omp_scan_clauses (as_a <gomp_scan *> (scan_stmt1));
2973   if (c && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_EXCLUSIVE)
2974     std::swap (input_stmt1, scan_stmt1);
2975 
2976   gimple_seq input_body1 = gimple_omp_body (input_stmt1);
2977   gimple_omp_set_body (input_stmt1, NULL);
2978 
2979   gimple_seq scan_body = copy_gimple_seq_and_replace_locals (stmt);
2980   gomp_for *new_stmt = as_a <gomp_for *> (scan_body);
2981 
2982   gimple_omp_set_body (input_stmt1, input_body1);
2983   gimple_omp_set_body (scan_stmt1, NULL);
2984 
2985   gimple_stmt_iterator input2_gsi = gsi_none ();
2986   memset (&wi, 0, sizeof (wi));
2987   wi.val_only = true;
2988   wi.info = (void *) &input2_gsi;
2989   walk_gimple_seq_mod (gimple_omp_body_ptr (new_stmt), omp_find_scan,
2990                            NULL, &wi);
2991   gcc_assert (!gsi_end_p (input2_gsi));
2992 
2993   gimple *input_stmt2 = gsi_stmt (input2_gsi);
2994   gsi_next (&input2_gsi);
2995   gimple *scan_stmt2 = gsi_stmt (input2_gsi);
2996   gcc_assert (scan_stmt2 && gimple_code (scan_stmt2) == GIMPLE_OMP_SCAN);
2997   if (c && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_EXCLUSIVE)
2998     std::swap (input_stmt2, scan_stmt2);
2999 
3000   gimple_omp_set_body (input_stmt2, NULL);
3001 
3002   gimple_omp_set_body (input_stmt, input_body);
3003   gimple_omp_set_body (scan_stmt, scan_body);
3004 
3005   omp_context *ctx = new_omp_context (input_stmt, outer_ctx);
3006   scan_omp (gimple_omp_body_ptr (input_stmt), ctx);
3007 
3008   ctx = new_omp_context (scan_stmt, outer_ctx);
3009   scan_omp (gimple_omp_body_ptr (scan_stmt), ctx);
3010 
3011   maybe_lookup_ctx (new_stmt)->for_simd_scan_phase = true;
3012 }
3013 
3014 /* Scan an OpenMP sections directive.  */
3015 
3016 static void
scan_omp_sections(gomp_sections * stmt,omp_context * outer_ctx)3017 scan_omp_sections (gomp_sections *stmt, omp_context *outer_ctx)
3018 {
3019   omp_context *ctx;
3020 
3021   ctx = new_omp_context (stmt, outer_ctx);
3022   scan_sharing_clauses (gimple_omp_sections_clauses (stmt), ctx);
3023   scan_omp (gimple_omp_body_ptr (stmt), ctx);
3024 }
3025 
3026 /* Scan an OpenMP single directive.  */
3027 
3028 static void
scan_omp_single(gomp_single * stmt,omp_context * outer_ctx)3029 scan_omp_single (gomp_single *stmt, omp_context *outer_ctx)
3030 {
3031   omp_context *ctx;
3032   tree name;
3033 
3034   ctx = new_omp_context (stmt, outer_ctx);
3035   ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
3036   ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
3037   name = create_tmp_var_name (".omp_copy_s");
3038   name = build_decl (gimple_location (stmt),
3039                          TYPE_DECL, name, ctx->record_type);
3040   TYPE_NAME (ctx->record_type) = name;
3041 
3042   scan_sharing_clauses (gimple_omp_single_clauses (stmt), ctx);
3043   scan_omp (gimple_omp_body_ptr (stmt), ctx);
3044 
3045   if (TYPE_FIELDS (ctx->record_type) == NULL)
3046     ctx->record_type = NULL;
3047   else
3048     layout_type (ctx->record_type);
3049 }
3050 
3051 /* Scan a GIMPLE_OMP_TARGET.  */
3052 
3053 static void
scan_omp_target(gomp_target * stmt,omp_context * outer_ctx)3054 scan_omp_target (gomp_target *stmt, omp_context *outer_ctx)
3055 {
3056   omp_context *ctx;
3057   tree name;
3058   bool offloaded = is_gimple_omp_offloaded (stmt);
3059   tree clauses = gimple_omp_target_clauses (stmt);
3060 
3061   ctx = new_omp_context (stmt, outer_ctx);
3062   ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
3063   ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
3064   name = create_tmp_var_name (".omp_data_t");
3065   name = build_decl (gimple_location (stmt),
3066                          TYPE_DECL, name, ctx->record_type);
3067   DECL_ARTIFICIAL (name) = 1;
3068   DECL_NAMELESS (name) = 1;
3069   TYPE_NAME (ctx->record_type) = name;
3070   TYPE_ARTIFICIAL (ctx->record_type) = 1;
3071 
3072   if (offloaded)
3073     {
3074       create_omp_child_function (ctx, false);
3075       gimple_omp_target_set_child_fn (stmt, ctx->cb.dst_fn);
3076     }
3077 
3078   scan_sharing_clauses (clauses, ctx);
3079   scan_omp (gimple_omp_body_ptr (stmt), ctx);
3080 
3081   if (TYPE_FIELDS (ctx->record_type) == NULL)
3082     ctx->record_type = ctx->receiver_decl = NULL;
3083   else
3084     {
3085       TYPE_FIELDS (ctx->record_type)
3086           = nreverse (TYPE_FIELDS (ctx->record_type));
3087       if (flag_checking)
3088           {
3089             unsigned int align = DECL_ALIGN (TYPE_FIELDS (ctx->record_type));
3090             for (tree field = TYPE_FIELDS (ctx->record_type);
3091                  field;
3092                  field = DECL_CHAIN (field))
3093               gcc_assert (DECL_ALIGN (field) == align);
3094           }
3095       layout_type (ctx->record_type);
3096       if (offloaded)
3097           fixup_child_record_type (ctx);
3098     }
3099 
3100   if (ctx->teams_nested_p && ctx->nonteams_nested_p)
3101     {
3102       error_at (gimple_location (stmt),
3103                     "%<target%> construct with nested %<teams%> construct "
3104                     "contains directives outside of the %<teams%> construct");
3105       gimple_omp_set_body (stmt, gimple_build_bind (NULL, NULL, NULL));
3106     }
3107 }
3108 
3109 /* Scan an OpenMP teams directive.  */
3110 
3111 static void
scan_omp_teams(gomp_teams * stmt,omp_context * outer_ctx)3112 scan_omp_teams (gomp_teams *stmt, omp_context *outer_ctx)
3113 {
3114   omp_context *ctx = new_omp_context (stmt, outer_ctx);
3115 
3116   if (!gimple_omp_teams_host (stmt))
3117     {
3118       scan_sharing_clauses (gimple_omp_teams_clauses (stmt), ctx);
3119       scan_omp (gimple_omp_body_ptr (stmt), ctx);
3120       return;
3121     }
3122   taskreg_contexts.safe_push (ctx);
3123   gcc_assert (taskreg_nesting_level == 1);
3124   ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
3125   ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
3126   tree name = create_tmp_var_name (".omp_data_s");
3127   name = build_decl (gimple_location (stmt),
3128                          TYPE_DECL, name, ctx->record_type);
3129   DECL_ARTIFICIAL (name) = 1;
3130   DECL_NAMELESS (name) = 1;
3131   TYPE_NAME (ctx->record_type) = name;
3132   TYPE_ARTIFICIAL (ctx->record_type) = 1;
3133   create_omp_child_function (ctx, false);
3134   gimple_omp_teams_set_child_fn (stmt, ctx->cb.dst_fn);
3135 
3136   scan_sharing_clauses (gimple_omp_teams_clauses (stmt), ctx);
3137   scan_omp (gimple_omp_body_ptr (stmt), ctx);
3138 
3139   if (TYPE_FIELDS (ctx->record_type) == NULL)
3140     ctx->record_type = ctx->receiver_decl = NULL;
3141 }
3142 
3143 /* Check nesting restrictions.  */
3144 static bool
check_omp_nesting_restrictions(gimple * stmt,omp_context * ctx)3145 check_omp_nesting_restrictions (gimple *stmt, omp_context *ctx)
3146 {
3147   tree c;
3148 
3149   /* No nesting of non-OpenACC STMT (that is, an OpenMP one, or a GOMP builtin)
3150      inside an OpenACC CTX.  */
3151   if (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD
3152       || gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE)
3153     /* ..., except for the atomic codes that OpenACC shares with OpenMP.  */
3154     ;
3155   else if (!(is_gimple_omp (stmt)
3156                && is_gimple_omp_oacc (stmt)))
3157     {
3158       if (oacc_get_fn_attrib (cfun->decl) != NULL)
3159           {
3160             error_at (gimple_location (stmt),
3161                         "non-OpenACC construct inside of OpenACC routine");
3162             return false;
3163           }
3164       else
3165           for (omp_context *octx = ctx; octx != NULL; octx = octx->outer)
3166             if (is_gimple_omp (octx->stmt)
3167                 && is_gimple_omp_oacc (octx->stmt))
3168               {
3169                 error_at (gimple_location (stmt),
3170                               "non-OpenACC construct inside of OpenACC region");
3171                 return false;
3172               }
3173     }
3174 
3175   if (ctx != NULL)
3176     {
3177       if (gimple_code (ctx->stmt) == GIMPLE_OMP_TARGET
3178             && gimple_omp_target_kind (ctx->stmt) == GF_OMP_TARGET_KIND_REGION)
3179           {
3180             c = omp_find_clause (gimple_omp_target_clauses (ctx->stmt),
3181                                      OMP_CLAUSE_DEVICE);
3182             if (c && OMP_CLAUSE_DEVICE_ANCESTOR (c))
3183               {
3184                 error_at (gimple_location (stmt),
3185                               "OpenMP constructs are not allowed in target region "
3186                               "with %<ancestor%>");
3187                 return false;
3188               }
3189 
3190             if (gimple_code (stmt) == GIMPLE_OMP_TEAMS && !ctx->teams_nested_p)
3191               ctx->teams_nested_p = true;
3192             else
3193               ctx->nonteams_nested_p = true;
3194           }
3195       if (gimple_code (ctx->stmt) == GIMPLE_OMP_SCAN
3196             && ctx->outer
3197             && gimple_code (ctx->outer->stmt) == GIMPLE_OMP_FOR)
3198           ctx = ctx->outer;
3199       if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3200             && gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_SIMD
3201             && !ctx->loop_p)
3202           {
3203             c = NULL_TREE;
3204             if (ctx->order_concurrent
3205                 && (gimple_code (stmt) == GIMPLE_OMP_ORDERED
3206                       || gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD
3207                       || gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE))
3208               {
3209                 error_at (gimple_location (stmt),
3210                               "OpenMP constructs other than %<parallel%>, %<loop%>"
3211                               " or %<simd%> may not be nested inside a region with"
3212                               " the %<order(concurrent)%> clause");
3213                 return false;
3214               }
3215             if (gimple_code (stmt) == GIMPLE_OMP_ORDERED)
3216               {
3217                 c = gimple_omp_ordered_clauses (as_a <gomp_ordered *> (stmt));
3218                 if (omp_find_clause (c, OMP_CLAUSE_SIMD))
3219                     {
3220                       if (omp_find_clause (c, OMP_CLAUSE_THREADS)
3221                           && (ctx->outer == NULL
3222                                 || !gimple_omp_for_combined_into_p (ctx->stmt)
3223                                 || gimple_code (ctx->outer->stmt) != GIMPLE_OMP_FOR
3224                                 || (gimple_omp_for_kind (ctx->outer->stmt)
3225                                     != GF_OMP_FOR_KIND_FOR)
3226                                 || !gimple_omp_for_combined_p (ctx->outer->stmt)))
3227                         {
3228                           error_at (gimple_location (stmt),
3229                                         "%<ordered simd threads%> must be closely "
3230                                         "nested inside of %<%s simd%> region",
3231                                         lang_GNU_Fortran () ? "do" : "for");
3232                           return false;
3233                         }
3234                       return true;
3235                     }
3236               }
3237             else if (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD
3238                        || gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE
3239                        || gimple_code (stmt) == GIMPLE_OMP_SCAN)
3240               return true;
3241             else if (gimple_code (stmt) == GIMPLE_OMP_FOR
3242                        && gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_SIMD)
3243               return true;
3244             error_at (gimple_location (stmt),
3245                         "OpenMP constructs other than "
3246                         "%<ordered simd%>, %<simd%>, %<loop%> or %<atomic%> may "
3247                         "not be nested inside %<simd%> region");
3248             return false;
3249           }
3250       else if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
3251           {
3252             if ((gimple_code (stmt) != GIMPLE_OMP_FOR
3253                  || (gimple_omp_for_kind (stmt) != GF_OMP_FOR_KIND_DISTRIBUTE
3254                        && omp_find_clause (gimple_omp_for_clauses (stmt),
3255                                                OMP_CLAUSE_BIND) == NULL_TREE))
3256                 && gimple_code (stmt) != GIMPLE_OMP_PARALLEL)
3257               {
3258                 error_at (gimple_location (stmt),
3259                               "only %<distribute%>, %<parallel%> or %<loop%> "
3260                               "regions are allowed to be strictly nested inside "
3261                               "%<teams%> region");
3262                 return false;
3263               }
3264           }
3265       else if (ctx->order_concurrent
3266                  && gimple_code (stmt) != GIMPLE_OMP_PARALLEL
3267                  && (gimple_code (stmt) != GIMPLE_OMP_FOR
3268                        || gimple_omp_for_kind (stmt) != GF_OMP_FOR_KIND_SIMD)
3269                  && gimple_code (stmt) != GIMPLE_OMP_SCAN)
3270           {
3271             if (ctx->loop_p)
3272               error_at (gimple_location (stmt),
3273                           "OpenMP constructs other than %<parallel%>, %<loop%> or "
3274                           "%<simd%> may not be nested inside a %<loop%> region");
3275             else
3276               error_at (gimple_location (stmt),
3277                           "OpenMP constructs other than %<parallel%>, %<loop%> or "
3278                           "%<simd%> may not be nested inside a region with "
3279                           "the %<order(concurrent)%> clause");
3280             return false;
3281           }
3282     }
3283   switch (gimple_code (stmt))
3284     {
3285     case GIMPLE_OMP_FOR:
3286       if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_SIMD)
3287           return true;
3288       if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
3289           {
3290             if (ctx != NULL && gimple_code (ctx->stmt) != GIMPLE_OMP_TEAMS)
3291               {
3292                 error_at (gimple_location (stmt),
3293                               "%<distribute%> region must be strictly nested "
3294                               "inside %<teams%> construct");
3295                 return false;
3296               }
3297             return true;
3298           }
3299       /* We split taskloop into task and nested taskloop in it.  */
3300       if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_TASKLOOP)
3301           return true;
3302       /* For now, hope this will change and loop bind(parallel) will not
3303            be allowed in lots of contexts.  */
3304       if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR
3305             && omp_find_clause (gimple_omp_for_clauses (stmt), OMP_CLAUSE_BIND))
3306           return true;
3307       if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_OACC_LOOP)
3308           {
3309             bool ok = false;
3310 
3311             if (ctx)
3312               switch (gimple_code (ctx->stmt))
3313                 {
3314                 case GIMPLE_OMP_FOR:
3315                     ok = (gimple_omp_for_kind (ctx->stmt)
3316                           == GF_OMP_FOR_KIND_OACC_LOOP);
3317                     break;
3318 
3319                 case GIMPLE_OMP_TARGET:
3320                     switch (gimple_omp_target_kind (ctx->stmt))
3321                       {
3322                       case GF_OMP_TARGET_KIND_OACC_PARALLEL:
3323                       case GF_OMP_TARGET_KIND_OACC_KERNELS:
3324                       case GF_OMP_TARGET_KIND_OACC_SERIAL:
3325                       case GF_OMP_TARGET_KIND_OACC_PARALLEL_KERNELS_PARALLELIZED:
3326                       case GF_OMP_TARGET_KIND_OACC_PARALLEL_KERNELS_GANG_SINGLE:
3327                         ok = true;
3328                         break;
3329 
3330                       default:
3331                         break;
3332                       }
3333 
3334                 default:
3335                     break;
3336                 }
3337             else if (oacc_get_fn_attrib (current_function_decl))
3338               ok = true;
3339             if (!ok)
3340               {
3341                 error_at (gimple_location (stmt),
3342                               "OpenACC loop directive must be associated with"
3343                               " an OpenACC compute region");
3344                 return false;
3345               }
3346           }
3347       /* FALLTHRU */
3348     case GIMPLE_CALL:
3349       if (is_gimple_call (stmt)
3350             && (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3351                 == BUILT_IN_GOMP_CANCEL
3352                 || DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3353                      == BUILT_IN_GOMP_CANCELLATION_POINT))
3354           {
3355             const char *bad = NULL;
3356             const char *kind = NULL;
3357             const char *construct
3358               = (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3359                  == BUILT_IN_GOMP_CANCEL)
3360                 ? "cancel"
3361                 : "cancellation point";
3362             if (ctx == NULL)
3363               {
3364                 error_at (gimple_location (stmt), "orphaned %qs construct",
3365                               construct);
3366                 return false;
3367               }
3368             switch (tree_fits_shwi_p (gimple_call_arg (stmt, 0))
3369                       ? tree_to_shwi (gimple_call_arg (stmt, 0))
3370                       : 0)
3371               {
3372               case 1:
3373                 if (gimple_code (ctx->stmt) != GIMPLE_OMP_PARALLEL)
3374                     bad = "parallel";
3375                 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3376                            == BUILT_IN_GOMP_CANCEL
3377                            && !integer_zerop (gimple_call_arg (stmt, 1)))
3378                     ctx->cancellable = true;
3379                 kind = "parallel";
3380                 break;
3381               case 2:
3382                 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
3383                       || gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR)
3384                     bad = "for";
3385                 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3386                            == BUILT_IN_GOMP_CANCEL
3387                            && !integer_zerop (gimple_call_arg (stmt, 1)))
3388                     {
3389                       ctx->cancellable = true;
3390                       if (omp_find_clause (gimple_omp_for_clauses (ctx->stmt),
3391                                                OMP_CLAUSE_NOWAIT))
3392                         warning_at (gimple_location (stmt), 0,
3393                                         "%<cancel for%> inside "
3394                                         "%<nowait%> for construct");
3395                       if (omp_find_clause (gimple_omp_for_clauses (ctx->stmt),
3396                                                OMP_CLAUSE_ORDERED))
3397                         warning_at (gimple_location (stmt), 0,
3398                                         "%<cancel for%> inside "
3399                                         "%<ordered%> for construct");
3400                     }
3401                 kind = "for";
3402                 break;
3403               case 4:
3404                 if (gimple_code (ctx->stmt) != GIMPLE_OMP_SECTIONS
3405                       && gimple_code (ctx->stmt) != GIMPLE_OMP_SECTION)
3406                     bad = "sections";
3407                 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3408                            == BUILT_IN_GOMP_CANCEL
3409                            && !integer_zerop (gimple_call_arg (stmt, 1)))
3410                     {
3411                       if (gimple_code (ctx->stmt) == GIMPLE_OMP_SECTIONS)
3412                         {
3413                           ctx->cancellable = true;
3414                           if (omp_find_clause (gimple_omp_sections_clauses
3415                                                                                 (ctx->stmt),
3416                                                      OMP_CLAUSE_NOWAIT))
3417                               warning_at (gimple_location (stmt), 0,
3418                                             "%<cancel sections%> inside "
3419                                             "%<nowait%> sections construct");
3420                         }
3421                       else
3422                         {
3423                           gcc_assert (ctx->outer
3424                                           && gimple_code (ctx->outer->stmt)
3425                                              == GIMPLE_OMP_SECTIONS);
3426                           ctx->outer->cancellable = true;
3427                           if (omp_find_clause (gimple_omp_sections_clauses
3428                                                                       (ctx->outer->stmt),
3429                                                      OMP_CLAUSE_NOWAIT))
3430                               warning_at (gimple_location (stmt), 0,
3431                                             "%<cancel sections%> inside "
3432                                             "%<nowait%> sections construct");
3433                         }
3434                     }
3435                 kind = "sections";
3436                 break;
3437               case 8:
3438                 if (!is_task_ctx (ctx)
3439                       && (!is_taskloop_ctx (ctx)
3440                           || ctx->outer == NULL
3441                           || !is_task_ctx (ctx->outer)))
3442                     bad = "task";
3443                 else
3444                     {
3445                       for (omp_context *octx = ctx->outer;
3446                            octx; octx = octx->outer)
3447                         {
3448                           switch (gimple_code (octx->stmt))
3449                               {
3450                               case GIMPLE_OMP_TASKGROUP:
3451                                 break;
3452                               case GIMPLE_OMP_TARGET:
3453                                 if (gimple_omp_target_kind (octx->stmt)
3454                                     != GF_OMP_TARGET_KIND_REGION)
3455                                   continue;
3456                                 /* FALLTHRU */
3457                               case GIMPLE_OMP_PARALLEL:
3458                               case GIMPLE_OMP_TEAMS:
3459                                 error_at (gimple_location (stmt),
3460                                             "%<%s taskgroup%> construct not closely "
3461                                             "nested inside of %<taskgroup%> region",
3462                                             construct);
3463                                 return false;
3464                               case GIMPLE_OMP_TASK:
3465                                 if (gimple_omp_task_taskloop_p (octx->stmt)
3466                                     && octx->outer
3467                                     && is_taskloop_ctx (octx->outer))
3468                                   {
3469                                     tree clauses
3470                                         = gimple_omp_for_clauses (octx->outer->stmt);
3471                                     if (!omp_find_clause (clauses, OMP_CLAUSE_NOGROUP))
3472                                         break;
3473                                   }
3474                                 continue;
3475                               default:
3476                                 continue;
3477                               }
3478                           break;
3479                         }
3480                       ctx->cancellable = true;
3481                     }
3482                 kind = "taskgroup";
3483                 break;
3484               default:
3485                 error_at (gimple_location (stmt), "invalid arguments");
3486                 return false;
3487               }
3488             if (bad)
3489               {
3490                 error_at (gimple_location (stmt),
3491                               "%<%s %s%> construct not closely nested inside of %qs",
3492                               construct, kind, bad);
3493                 return false;
3494               }
3495           }
3496       /* FALLTHRU */
3497     case GIMPLE_OMP_SECTIONS:
3498     case GIMPLE_OMP_SINGLE:
3499       for (; ctx != NULL; ctx = ctx->outer)
3500           switch (gimple_code (ctx->stmt))
3501             {
3502             case GIMPLE_OMP_FOR:
3503               if (gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR
3504                     && gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_TASKLOOP)
3505                 break;
3506               /* FALLTHRU */
3507             case GIMPLE_OMP_SECTIONS:
3508             case GIMPLE_OMP_SINGLE:
3509             case GIMPLE_OMP_ORDERED:
3510             case GIMPLE_OMP_MASTER:
3511             case GIMPLE_OMP_MASKED:
3512             case GIMPLE_OMP_TASK:
3513             case GIMPLE_OMP_CRITICAL:
3514               if (is_gimple_call (stmt))
3515                 {
3516                     if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3517                         != BUILT_IN_GOMP_BARRIER)
3518                       return true;
3519                     error_at (gimple_location (stmt),
3520                                 "barrier region may not be closely nested inside "
3521                                 "of work-sharing, %<loop%>, %<critical%>, "
3522                                 "%<ordered%>, %<master%>, %<masked%>, explicit "
3523                                 "%<task%> or %<taskloop%> region");
3524                     return false;
3525                 }
3526               error_at (gimple_location (stmt),
3527                           "work-sharing region may not be closely nested inside "
3528                           "of work-sharing, %<loop%>, %<critical%>, %<ordered%>, "
3529                           "%<master%>, %<masked%>, explicit %<task%> or "
3530                           "%<taskloop%> region");
3531               return false;
3532             case GIMPLE_OMP_PARALLEL:
3533             case GIMPLE_OMP_TEAMS:
3534               return true;
3535             case GIMPLE_OMP_TARGET:
3536               if (gimple_omp_target_kind (ctx->stmt)
3537                     == GF_OMP_TARGET_KIND_REGION)
3538                 return true;
3539               break;
3540             default:
3541               break;
3542             }
3543       break;
3544     case GIMPLE_OMP_MASTER:
3545     case GIMPLE_OMP_MASKED:
3546       for (; ctx != NULL; ctx = ctx->outer)
3547           switch (gimple_code (ctx->stmt))
3548             {
3549             case GIMPLE_OMP_FOR:
3550               if (gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR
3551                     && gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_TASKLOOP)
3552                 break;
3553               /* FALLTHRU */
3554             case GIMPLE_OMP_SECTIONS:
3555             case GIMPLE_OMP_SINGLE:
3556             case GIMPLE_OMP_TASK:
3557               error_at (gimple_location (stmt),
3558                           "%qs region may not be closely nested inside "
3559                           "of work-sharing, %<loop%>, explicit %<task%> or "
3560                           "%<taskloop%> region",
3561                           gimple_code (stmt) == GIMPLE_OMP_MASTER
3562                           ? "master" : "masked");
3563               return false;
3564             case GIMPLE_OMP_PARALLEL:
3565             case GIMPLE_OMP_TEAMS:
3566               return true;
3567             case GIMPLE_OMP_TARGET:
3568               if (gimple_omp_target_kind (ctx->stmt)
3569                     == GF_OMP_TARGET_KIND_REGION)
3570                 return true;
3571               break;
3572             default:
3573               break;
3574             }
3575       break;
3576     case GIMPLE_OMP_SCOPE:
3577       for (; ctx != NULL; ctx = ctx->outer)
3578           switch (gimple_code (ctx->stmt))
3579             {
3580             case GIMPLE_OMP_FOR:
3581               if (gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR
3582                     && gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_TASKLOOP)
3583                 break;
3584               /* FALLTHRU */
3585             case GIMPLE_OMP_SECTIONS:
3586             case GIMPLE_OMP_SINGLE:
3587             case GIMPLE_OMP_TASK:
3588             case GIMPLE_OMP_CRITICAL:
3589             case GIMPLE_OMP_ORDERED:
3590             case GIMPLE_OMP_MASTER:
3591             case GIMPLE_OMP_MASKED:
3592               error_at (gimple_location (stmt),
3593                           "%<scope%> region may not be closely nested inside "
3594                           "of work-sharing, %<loop%>, explicit %<task%>, "
3595                           "%<taskloop%>, %<critical%>, %<ordered%>, %<master%>, "
3596                           "or %<masked%> region");
3597               return false;
3598             case GIMPLE_OMP_PARALLEL:
3599             case GIMPLE_OMP_TEAMS:
3600               return true;
3601             case GIMPLE_OMP_TARGET:
3602               if (gimple_omp_target_kind (ctx->stmt)
3603                     == GF_OMP_TARGET_KIND_REGION)
3604                 return true;
3605               break;
3606             default:
3607               break;
3608             }
3609       break;
3610     case GIMPLE_OMP_TASK:
3611       for (c = gimple_omp_task_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c))
3612           if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
3613               && (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SOURCE
3614                     || OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK))
3615             {
3616               enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_KIND (c);
3617               error_at (OMP_CLAUSE_LOCATION (c),
3618                           "%<depend(%s)%> is only allowed in %<omp ordered%>",
3619                           kind == OMP_CLAUSE_DEPEND_SOURCE ? "source" : "sink");
3620               return false;
3621             }
3622       break;
3623     case GIMPLE_OMP_ORDERED:
3624       for (c = gimple_omp_ordered_clauses (as_a <gomp_ordered *> (stmt));
3625              c; c = OMP_CLAUSE_CHAIN (c))
3626           {
3627             if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND)
3628               {
3629                 gcc_assert (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_THREADS
3630                                 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SIMD);
3631                 continue;
3632               }
3633             enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_KIND (c);
3634             if (kind == OMP_CLAUSE_DEPEND_SOURCE
3635                 || kind == OMP_CLAUSE_DEPEND_SINK)
3636               {
3637                 tree oclause;
3638                 /* Look for containing ordered(N) loop.  */
3639                 if (ctx == NULL
3640                       || gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
3641                       || (oclause
3642                               = omp_find_clause (gimple_omp_for_clauses (ctx->stmt),
3643                                                      OMP_CLAUSE_ORDERED)) == NULL_TREE)
3644                     {
3645                       error_at (OMP_CLAUSE_LOCATION (c),
3646                                   "%<ordered%> construct with %<depend%> clause "
3647                                   "must be closely nested inside an %<ordered%> "
3648                                   "loop");
3649                       return false;
3650                     }
3651                 else if (OMP_CLAUSE_ORDERED_EXPR (oclause) == NULL_TREE)
3652                     {
3653                       error_at (OMP_CLAUSE_LOCATION (c),
3654                                   "%<ordered%> construct with %<depend%> clause "
3655                                   "must be closely nested inside a loop with "
3656                                   "%<ordered%> clause with a parameter");
3657                       return false;
3658                     }
3659               }
3660             else
3661               {
3662                 error_at (OMP_CLAUSE_LOCATION (c),
3663                               "invalid depend kind in omp %<ordered%> %<depend%>");
3664                 return false;
3665               }
3666           }
3667       c = gimple_omp_ordered_clauses (as_a <gomp_ordered *> (stmt));
3668       if (omp_find_clause (c, OMP_CLAUSE_SIMD))
3669           {
3670             /* ordered simd must be closely nested inside of simd region,
3671                and simd region must not encounter constructs other than
3672                ordered simd, therefore ordered simd may be either orphaned,
3673                or ctx->stmt must be simd.  The latter case is handled already
3674                earlier.  */
3675             if (ctx != NULL)
3676               {
3677                 error_at (gimple_location (stmt),
3678                               "%<ordered%> %<simd%> must be closely nested inside "
3679                               "%<simd%> region");
3680                 return false;
3681               }
3682           }
3683       for (; ctx != NULL; ctx = ctx->outer)
3684           switch (gimple_code (ctx->stmt))
3685             {
3686             case GIMPLE_OMP_CRITICAL:
3687             case GIMPLE_OMP_TASK:
3688             case GIMPLE_OMP_ORDERED:
3689             ordered_in_taskloop:
3690               error_at (gimple_location (stmt),
3691                           "%<ordered%> region may not be closely nested inside "
3692                           "of %<critical%>, %<ordered%>, explicit %<task%> or "
3693                           "%<taskloop%> region");
3694               return false;
3695             case GIMPLE_OMP_FOR:
3696               if (gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_TASKLOOP)
3697                 goto ordered_in_taskloop;
3698               tree o;
3699               o = omp_find_clause (gimple_omp_for_clauses (ctx->stmt),
3700                                          OMP_CLAUSE_ORDERED);
3701               if (o == NULL)
3702                 {
3703                     error_at (gimple_location (stmt),
3704                                 "%<ordered%> region must be closely nested inside "
3705                                 "a loop region with an %<ordered%> clause");
3706                     return false;
3707                 }
3708               if (OMP_CLAUSE_ORDERED_EXPR (o) != NULL_TREE
3709                     && omp_find_clause (c, OMP_CLAUSE_DEPEND) == NULL_TREE)
3710                 {
3711                     error_at (gimple_location (stmt),
3712                                 "%<ordered%> region without %<depend%> clause may "
3713                                 "not be closely nested inside a loop region with "
3714                                 "an %<ordered%> clause with a parameter");
3715                     return false;
3716                 }
3717               return true;
3718             case GIMPLE_OMP_TARGET:
3719               if (gimple_omp_target_kind (ctx->stmt)
3720                     != GF_OMP_TARGET_KIND_REGION)
3721                 break;
3722               /* FALLTHRU */
3723             case GIMPLE_OMP_PARALLEL:
3724             case GIMPLE_OMP_TEAMS:
3725               error_at (gimple_location (stmt),
3726                           "%<ordered%> region must be closely nested inside "
3727                           "a loop region with an %<ordered%> clause");
3728               return false;
3729             default:
3730               break;
3731             }
3732       break;
3733     case GIMPLE_OMP_CRITICAL:
3734       {
3735           tree this_stmt_name
3736             = gimple_omp_critical_name (as_a <gomp_critical *> (stmt));
3737           for (; ctx != NULL; ctx = ctx->outer)
3738             if (gomp_critical *other_crit
3739                   = dyn_cast <gomp_critical *> (ctx->stmt))
3740               if (this_stmt_name == gimple_omp_critical_name (other_crit))
3741                 {
3742                     error_at (gimple_location (stmt),
3743                                 "%<critical%> region may not be nested inside "
3744                                  "a %<critical%> region with the same name");
3745                     return false;
3746                 }
3747       }
3748       break;
3749     case GIMPLE_OMP_TEAMS:
3750       if (ctx == NULL)
3751           break;
3752       else if (gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET
3753                  || (gimple_omp_target_kind (ctx->stmt)
3754                        != GF_OMP_TARGET_KIND_REGION))
3755           {
3756             /* Teams construct can appear either strictly nested inside of
3757                target construct with no intervening stmts, or can be encountered
3758                only by initial task (so must not appear inside any OpenMP
3759                construct.  */
3760             error_at (gimple_location (stmt),
3761                         "%<teams%> construct must be closely nested inside of "
3762                         "%<target%> construct or not nested in any OpenMP "
3763                         "construct");
3764             return false;
3765           }
3766       break;
3767     case GIMPLE_OMP_TARGET:
3768       for (c = gimple_omp_target_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c))
3769           if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
3770               && (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SOURCE
3771                     || OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK))
3772             {
3773               enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_KIND (c);
3774               error_at (OMP_CLAUSE_LOCATION (c),
3775                           "%<depend(%s)%> is only allowed in %<omp ordered%>",
3776                           kind == OMP_CLAUSE_DEPEND_SOURCE ? "source" : "sink");
3777               return false;
3778             }
3779       if (is_gimple_omp_offloaded (stmt)
3780             && oacc_get_fn_attrib (cfun->decl) != NULL)
3781           {
3782             error_at (gimple_location (stmt),
3783                         "OpenACC region inside of OpenACC routine, nested "
3784                         "parallelism not supported yet");
3785             return false;
3786           }
3787       for (; ctx != NULL; ctx = ctx->outer)
3788           {
3789             if (gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET)
3790               {
3791                 if (is_gimple_omp (stmt)
3792                       && is_gimple_omp_oacc (stmt)
3793                       && is_gimple_omp (ctx->stmt))
3794                     {
3795                       error_at (gimple_location (stmt),
3796                                   "OpenACC construct inside of non-OpenACC region");
3797                       return false;
3798                     }
3799                 continue;
3800               }
3801 
3802             const char *stmt_name, *ctx_stmt_name;
3803             switch (gimple_omp_target_kind (stmt))
3804               {
3805               case GF_OMP_TARGET_KIND_REGION: stmt_name = "target"; break;
3806               case GF_OMP_TARGET_KIND_DATA: stmt_name = "target data"; break;
3807               case GF_OMP_TARGET_KIND_UPDATE: stmt_name = "target update"; break;
3808               case GF_OMP_TARGET_KIND_ENTER_DATA:
3809                 stmt_name = "target enter data"; break;
3810               case GF_OMP_TARGET_KIND_EXIT_DATA:
3811                 stmt_name = "target exit data"; break;
3812               case GF_OMP_TARGET_KIND_OACC_PARALLEL: stmt_name = "parallel"; break;
3813               case GF_OMP_TARGET_KIND_OACC_KERNELS: stmt_name = "kernels"; break;
3814               case GF_OMP_TARGET_KIND_OACC_SERIAL: stmt_name = "serial"; break;
3815               case GF_OMP_TARGET_KIND_OACC_DATA: stmt_name = "data"; break;
3816               case GF_OMP_TARGET_KIND_OACC_UPDATE: stmt_name = "update"; break;
3817               case GF_OMP_TARGET_KIND_OACC_ENTER_DATA:
3818                 stmt_name = "enter data"; break;
3819               case GF_OMP_TARGET_KIND_OACC_EXIT_DATA:
3820                 stmt_name = "exit data"; break;
3821               case GF_OMP_TARGET_KIND_OACC_DECLARE: stmt_name = "declare"; break;
3822               case GF_OMP_TARGET_KIND_OACC_HOST_DATA: stmt_name = "host_data";
3823                 break;
3824               case GF_OMP_TARGET_KIND_OACC_PARALLEL_KERNELS_PARALLELIZED:
3825               case GF_OMP_TARGET_KIND_OACC_PARALLEL_KERNELS_GANG_SINGLE:
3826               case GF_OMP_TARGET_KIND_OACC_DATA_KERNELS:
3827                 /* OpenACC 'kernels' decomposed parts.  */
3828                 stmt_name = "kernels"; break;
3829               default: gcc_unreachable ();
3830               }
3831             switch (gimple_omp_target_kind (ctx->stmt))
3832               {
3833               case GF_OMP_TARGET_KIND_REGION: ctx_stmt_name = "target"; break;
3834               case GF_OMP_TARGET_KIND_DATA: ctx_stmt_name = "target data"; break;
3835               case GF_OMP_TARGET_KIND_OACC_PARALLEL:
3836                 ctx_stmt_name = "parallel"; break;
3837               case GF_OMP_TARGET_KIND_OACC_KERNELS:
3838                 ctx_stmt_name = "kernels"; break;
3839               case GF_OMP_TARGET_KIND_OACC_SERIAL:
3840                 ctx_stmt_name = "serial"; break;
3841               case GF_OMP_TARGET_KIND_OACC_DATA: ctx_stmt_name = "data"; break;
3842               case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
3843                 ctx_stmt_name = "host_data"; break;
3844               case GF_OMP_TARGET_KIND_OACC_PARALLEL_KERNELS_PARALLELIZED:
3845               case GF_OMP_TARGET_KIND_OACC_PARALLEL_KERNELS_GANG_SINGLE:
3846               case GF_OMP_TARGET_KIND_OACC_DATA_KERNELS:
3847                 /* OpenACC 'kernels' decomposed parts.  */
3848                 ctx_stmt_name = "kernels"; break;
3849               default: gcc_unreachable ();
3850               }
3851 
3852             /* OpenACC/OpenMP mismatch?  */
3853             if (is_gimple_omp_oacc (stmt)
3854                 != is_gimple_omp_oacc (ctx->stmt))
3855               {
3856                 error_at (gimple_location (stmt),
3857                               "%s %qs construct inside of %s %qs region",
3858                               (is_gimple_omp_oacc (stmt)
3859                                ? "OpenACC" : "OpenMP"), stmt_name,
3860                               (is_gimple_omp_oacc (ctx->stmt)
3861                                ? "OpenACC" : "OpenMP"), ctx_stmt_name);
3862                 return false;
3863               }
3864             if (is_gimple_omp_offloaded (ctx->stmt))
3865               {
3866                 /* No GIMPLE_OMP_TARGET inside offloaded OpenACC CTX.  */
3867                 if (is_gimple_omp_oacc (ctx->stmt))
3868                     {
3869                       error_at (gimple_location (stmt),
3870                                   "%qs construct inside of %qs region",
3871                                   stmt_name, ctx_stmt_name);
3872                       return false;
3873                     }
3874                 else
3875                     {
3876                       warning_at (gimple_location (stmt), 0,
3877                                     "%qs construct inside of %qs region",
3878                                     stmt_name, ctx_stmt_name);
3879                     }
3880               }
3881           }
3882       break;
3883     default:
3884       break;
3885     }
3886   return true;
3887 }
3888 
3889 
3890 /* Helper function scan_omp.
3891 
3892    Callback for walk_tree or operators in walk_gimple_stmt used to
3893    scan for OMP directives in TP.  */
3894 
3895 static tree
scan_omp_1_op(tree * tp,int * walk_subtrees,void * data)3896 scan_omp_1_op (tree *tp, int *walk_subtrees, void *data)
3897 {
3898   struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
3899   omp_context *ctx = (omp_context *) wi->info;
3900   tree t = *tp;
3901 
3902   switch (TREE_CODE (t))
3903     {
3904     case VAR_DECL:
3905     case PARM_DECL:
3906     case LABEL_DECL:
3907     case RESULT_DECL:
3908       if (ctx)
3909           {
3910             tree repl = remap_decl (t, &ctx->cb);
3911             gcc_checking_assert (TREE_CODE (repl) != ERROR_MARK);
3912             *tp = repl;
3913           }
3914       break;
3915 
3916     default:
3917       if (ctx && TYPE_P (t))
3918           *tp = remap_type (t, &ctx->cb);
3919       else if (!DECL_P (t))
3920           {
3921             *walk_subtrees = 1;
3922             if (ctx)
3923               {
3924                 tree tem = remap_type (TREE_TYPE (t), &ctx->cb);
3925                 if (tem != TREE_TYPE (t))
3926                     {
3927                       if (TREE_CODE (t) == INTEGER_CST)
3928                         *tp = wide_int_to_tree (tem, wi::to_wide (t));
3929                       else
3930                         TREE_TYPE (t) = tem;
3931                     }
3932               }
3933           }
3934       break;
3935     }
3936 
3937   return NULL_TREE;
3938 }
3939 
3940 /* Return true if FNDECL is a setjmp or a longjmp.  */
3941 
3942 static bool
setjmp_or_longjmp_p(const_tree fndecl)3943 setjmp_or_longjmp_p (const_tree fndecl)
3944 {
3945   if (fndecl_built_in_p (fndecl, BUILT_IN_SETJMP)
3946       || fndecl_built_in_p (fndecl, BUILT_IN_LONGJMP))
3947     return true;
3948 
3949   tree declname = DECL_NAME (fndecl);
3950   if (!declname
3951       || (DECL_CONTEXT (fndecl) != NULL_TREE
3952           && TREE_CODE (DECL_CONTEXT (fndecl)) != TRANSLATION_UNIT_DECL)
3953       || !TREE_PUBLIC (fndecl))
3954     return false;
3955 
3956   const char *name = IDENTIFIER_POINTER (declname);
3957   return !strcmp (name, "setjmp") || !strcmp (name, "longjmp");
3958 }
3959 
3960 /* Return true if FNDECL is an omp_* runtime API call.  */
3961 
3962 static bool
omp_runtime_api_call(const_tree fndecl)3963 omp_runtime_api_call (const_tree fndecl)
3964 {
3965   tree declname = DECL_NAME (fndecl);
3966   if (!declname
3967       || (DECL_CONTEXT (fndecl) != NULL_TREE
3968           && TREE_CODE (DECL_CONTEXT (fndecl)) != TRANSLATION_UNIT_DECL)
3969       || !TREE_PUBLIC (fndecl))
3970     return false;
3971 
3972   const char *name = IDENTIFIER_POINTER (declname);
3973   if (!startswith (name, "omp_"))
3974     return false;
3975 
3976   static const char *omp_runtime_apis[] =
3977     {
3978       /* This array has 3 sections.  First omp_* calls that don't
3979            have any suffixes.  */
3980       "aligned_alloc",
3981       "aligned_calloc",
3982       "alloc",
3983       "calloc",
3984       "free",
3985       "realloc",
3986       "target_alloc",
3987       "target_associate_ptr",
3988       "target_disassociate_ptr",
3989       "target_free",
3990       "target_is_present",
3991       "target_memcpy",
3992       "target_memcpy_rect",
3993       NULL,
3994       /* Now omp_* calls that are available as omp_* and omp_*_; however, the
3995            DECL_NAME is always omp_* without tailing underscore.  */
3996       "capture_affinity",
3997       "destroy_allocator",
3998       "destroy_lock",
3999       "destroy_nest_lock",
4000       "display_affinity",
4001       "fulfill_event",
4002       "get_active_level",
4003       "get_affinity_format",
4004       "get_cancellation",
4005       "get_default_allocator",
4006       "get_default_device",
4007       "get_device_num",
4008       "get_dynamic",
4009       "get_initial_device",
4010       "get_level",
4011       "get_max_active_levels",
4012       "get_max_task_priority",
4013       "get_max_teams",
4014       "get_max_threads",
4015       "get_nested",
4016       "get_num_devices",
4017       "get_num_places",
4018       "get_num_procs",
4019       "get_num_teams",
4020       "get_num_threads",
4021       "get_partition_num_places",
4022       "get_place_num",
4023       "get_proc_bind",
4024       "get_supported_active_levels",
4025       "get_team_num",
4026       "get_teams_thread_limit",
4027       "get_thread_limit",
4028       "get_thread_num",
4029       "get_wtick",
4030       "get_wtime",
4031       "in_final",
4032       "in_parallel",
4033       "init_lock",
4034       "init_nest_lock",
4035       "is_initial_device",
4036       "pause_resource",
4037       "pause_resource_all",
4038       "set_affinity_format",
4039       "set_default_allocator",
4040       "set_lock",
4041       "set_nest_lock",
4042       "test_lock",
4043       "test_nest_lock",
4044       "unset_lock",
4045       "unset_nest_lock",
4046       NULL,
4047       /* And finally calls available as omp_*, omp_*_ and omp_*_8_; however,
4048            as DECL_NAME only omp_* and omp_*_8 appear.  */
4049       "display_env",
4050       "get_ancestor_thread_num",
4051       "init_allocator",
4052       "get_partition_place_nums",
4053       "get_place_num_procs",
4054       "get_place_proc_ids",
4055       "get_schedule",
4056       "get_team_size",
4057       "set_default_device",
4058       "set_dynamic",
4059       "set_max_active_levels",
4060       "set_nested",
4061       "set_num_teams",
4062       "set_num_threads",
4063       "set_schedule",
4064       "set_teams_thread_limit"
4065     };
4066 
4067   int mode = 0;
4068   for (unsigned i = 0; i < ARRAY_SIZE (omp_runtime_apis); i++)
4069     {
4070       if (omp_runtime_apis[i] == NULL)
4071           {
4072             mode++;
4073             continue;
4074           }
4075       size_t len = strlen (omp_runtime_apis[i]);
4076       if (strncmp (name + 4, omp_runtime_apis[i], len) == 0
4077             && (name[4 + len] == '\0'
4078                 || (mode > 1 && strcmp (name + 4 + len, "_8") == 0)))
4079           return true;
4080     }
4081   return false;
4082 }
4083 
4084 /* Helper function for scan_omp.
4085 
4086    Callback for walk_gimple_stmt used to scan for OMP directives in
4087    the current statement in GSI.  */
4088 
4089 static tree
scan_omp_1_stmt(gimple_stmt_iterator * gsi,bool * handled_ops_p,struct walk_stmt_info * wi)4090 scan_omp_1_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
4091                      struct walk_stmt_info *wi)
4092 {
4093   gimple *stmt = gsi_stmt (*gsi);
4094   omp_context *ctx = (omp_context *) wi->info;
4095 
4096   if (gimple_has_location (stmt))
4097     input_location = gimple_location (stmt);
4098 
4099   /* Check the nesting restrictions.  */
4100   bool remove = false;
4101   if (is_gimple_omp (stmt))
4102     remove = !check_omp_nesting_restrictions (stmt, ctx);
4103   else if (is_gimple_call (stmt))
4104     {
4105       tree fndecl = gimple_call_fndecl (stmt);
4106       if (fndecl)
4107           {
4108             if (ctx
4109                 && gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
4110                 && gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_SIMD
4111                 && setjmp_or_longjmp_p (fndecl)
4112                 && !ctx->loop_p)
4113               {
4114                 remove = true;
4115                 error_at (gimple_location (stmt),
4116                               "setjmp/longjmp inside %<simd%> construct");
4117               }
4118             else if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
4119               switch (DECL_FUNCTION_CODE (fndecl))
4120                 {
4121                 case BUILT_IN_GOMP_BARRIER:
4122                 case BUILT_IN_GOMP_CANCEL:
4123                 case BUILT_IN_GOMP_CANCELLATION_POINT:
4124                 case BUILT_IN_GOMP_TASKYIELD:
4125                 case BUILT_IN_GOMP_TASKWAIT:
4126                 case BUILT_IN_GOMP_TASKGROUP_START:
4127                 case BUILT_IN_GOMP_TASKGROUP_END:
4128                     remove = !check_omp_nesting_restrictions (stmt, ctx);
4129                     break;
4130                 default:
4131                     break;
4132                 }
4133             else if (ctx)
4134               {
4135                 omp_context *octx = ctx;
4136                 if (gimple_code (ctx->stmt) == GIMPLE_OMP_SCAN && ctx->outer)
4137                     octx = ctx->outer;
4138                 if (octx->order_concurrent && omp_runtime_api_call (fndecl))
4139                     {
4140                       remove = true;
4141                       error_at (gimple_location (stmt),
4142                                   "OpenMP runtime API call %qD in a region with "
4143                                   "%<order(concurrent)%> clause", fndecl);
4144                     }
4145                 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS
4146                       && omp_runtime_api_call (fndecl)
4147                       && ((IDENTIFIER_LENGTH (DECL_NAME (fndecl))
4148                            != strlen ("omp_get_num_teams"))
4149                           || strcmp (IDENTIFIER_POINTER (DECL_NAME (fndecl)),
4150                                          "omp_get_num_teams") != 0)
4151                       && ((IDENTIFIER_LENGTH (DECL_NAME (fndecl))
4152                            != strlen ("omp_get_team_num"))
4153                           || strcmp (IDENTIFIER_POINTER (DECL_NAME (fndecl)),
4154                                          "omp_get_team_num") != 0))
4155                     {
4156                       remove = true;
4157                       error_at (gimple_location (stmt),
4158                                   "OpenMP runtime API call %qD strictly nested in a "
4159                                   "%<teams%> region", fndecl);
4160                     }
4161                 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TARGET
4162                       && (gimple_omp_target_kind (ctx->stmt)
4163                           == GF_OMP_TARGET_KIND_REGION)
4164                       && omp_runtime_api_call (fndecl))
4165                     {
4166                       tree tgt_clauses = gimple_omp_target_clauses (ctx->stmt);
4167                       tree c = omp_find_clause (tgt_clauses, OMP_CLAUSE_DEVICE);
4168                       if (c && OMP_CLAUSE_DEVICE_ANCESTOR (c))
4169                         error_at (gimple_location (stmt),
4170                                     "OpenMP runtime API call %qD in a region with "
4171                                     "%<device(ancestor)%> clause", fndecl);
4172                     }
4173               }
4174           }
4175     }
4176   if (remove)
4177     {
4178       stmt = gimple_build_nop ();
4179       gsi_replace (gsi, stmt, false);
4180     }
4181 
4182   *handled_ops_p = true;
4183 
4184   switch (gimple_code (stmt))
4185     {
4186     case GIMPLE_OMP_PARALLEL:
4187       taskreg_nesting_level++;
4188       scan_omp_parallel (gsi, ctx);
4189       taskreg_nesting_level--;
4190       break;
4191 
4192     case GIMPLE_OMP_TASK:
4193       taskreg_nesting_level++;
4194       scan_omp_task (gsi, ctx);
4195       taskreg_nesting_level--;
4196       break;
4197 
4198     case GIMPLE_OMP_FOR:
4199       if ((gimple_omp_for_kind (as_a <gomp_for *> (stmt))
4200              == GF_OMP_FOR_KIND_SIMD)
4201             && gimple_omp_for_combined_into_p (stmt)
4202             && gimple_code (ctx->stmt) != GIMPLE_OMP_SCAN)
4203           {
4204             tree clauses = gimple_omp_for_clauses (as_a <gomp_for *> (stmt));
4205             tree c = omp_find_clause (clauses, OMP_CLAUSE_REDUCTION);
4206             if (c && OMP_CLAUSE_REDUCTION_INSCAN (c) && !seen_error ())
4207               {
4208                 scan_omp_simd_scan (gsi, as_a <gomp_for *> (stmt), ctx);
4209                 break;
4210               }
4211           }
4212       if ((gimple_omp_for_kind (as_a <gomp_for *> (stmt))
4213              == GF_OMP_FOR_KIND_SIMD)
4214             && omp_maybe_offloaded_ctx (ctx)
4215             && omp_max_simt_vf ()
4216             && gimple_omp_for_collapse (stmt) == 1)
4217           scan_omp_simd (gsi, as_a <gomp_for *> (stmt), ctx);
4218       else
4219           scan_omp_for (as_a <gomp_for *> (stmt), ctx);
4220       break;
4221 
4222     case GIMPLE_OMP_SCOPE:
4223       ctx = new_omp_context (stmt, ctx);
4224       scan_sharing_clauses (gimple_omp_scope_clauses (stmt), ctx);
4225       scan_omp (gimple_omp_body_ptr (stmt), ctx);
4226       break;
4227 
4228     case GIMPLE_OMP_SECTIONS:
4229       scan_omp_sections (as_a <gomp_sections *> (stmt), ctx);
4230       break;
4231 
4232     case GIMPLE_OMP_SINGLE:
4233       scan_omp_single (as_a <gomp_single *> (stmt), ctx);
4234       break;
4235 
4236     case GIMPLE_OMP_SCAN:
4237       if (tree clauses = gimple_omp_scan_clauses (as_a <gomp_scan *> (stmt)))
4238           {
4239             if (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_INCLUSIVE)
4240               ctx->scan_inclusive = true;
4241             else if (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_EXCLUSIVE)
4242               ctx->scan_exclusive = true;
4243           }
4244       /* FALLTHRU */
4245     case GIMPLE_OMP_SECTION:
4246     case GIMPLE_OMP_MASTER:
4247     case GIMPLE_OMP_ORDERED:
4248     case GIMPLE_OMP_CRITICAL:
4249       ctx = new_omp_context (stmt, ctx);
4250       scan_omp (gimple_omp_body_ptr (stmt), ctx);
4251       break;
4252 
4253     case GIMPLE_OMP_MASKED:
4254       ctx = new_omp_context (stmt, ctx);
4255       scan_sharing_clauses (gimple_omp_masked_clauses (stmt), ctx);
4256       scan_omp (gimple_omp_body_ptr (stmt), ctx);
4257       break;
4258 
4259     case GIMPLE_OMP_TASKGROUP:
4260       ctx = new_omp_context (stmt, ctx);
4261       scan_sharing_clauses (gimple_omp_taskgroup_clauses (stmt), ctx);
4262       scan_omp (gimple_omp_body_ptr (stmt), ctx);
4263       break;
4264 
4265     case GIMPLE_OMP_TARGET:
4266       if (is_gimple_omp_offloaded (stmt))
4267           {
4268             taskreg_nesting_level++;
4269             scan_omp_target (as_a <gomp_target *> (stmt), ctx);
4270             taskreg_nesting_level--;
4271           }
4272       else
4273           scan_omp_target (as_a <gomp_target *> (stmt), ctx);
4274       break;
4275 
4276     case GIMPLE_OMP_TEAMS:
4277       if (gimple_omp_teams_host (as_a <gomp_teams *> (stmt)))
4278           {
4279             taskreg_nesting_level++;
4280             scan_omp_teams (as_a <gomp_teams *> (stmt), ctx);
4281             taskreg_nesting_level--;
4282           }
4283       else
4284           scan_omp_teams (as_a <gomp_teams *> (stmt), ctx);
4285       break;
4286 
4287     case GIMPLE_BIND:
4288       {
4289           tree var;
4290 
4291           *handled_ops_p = false;
4292           if (ctx)
4293             for (var = gimple_bind_vars (as_a <gbind *> (stmt));
4294                  var ;
4295                  var = DECL_CHAIN (var))
4296               insert_decl_map (&ctx->cb, var, var);
4297       }
4298       break;
4299     default:
4300       *handled_ops_p = false;
4301       break;
4302     }
4303 
4304   return NULL_TREE;
4305 }
4306 
4307 
4308 /* Scan all the statements starting at the current statement.  CTX
4309    contains context information about the OMP directives and
4310    clauses found during the scan.  */
4311 
4312 static void
scan_omp(gimple_seq * body_p,omp_context * ctx)4313 scan_omp (gimple_seq *body_p, omp_context *ctx)
4314 {
4315   location_t saved_location;
4316   struct walk_stmt_info wi;
4317 
4318   memset (&wi, 0, sizeof (wi));
4319   wi.info = ctx;
4320   wi.want_locations = true;
4321 
4322   saved_location = input_location;
4323   walk_gimple_seq_mod (body_p, scan_omp_1_stmt, scan_omp_1_op, &wi);
4324   input_location = saved_location;
4325 }
4326 
4327 /* Re-gimplification and code generation routines.  */
4328 
4329 /* Remove omp_member_access_dummy_var variables from gimple_bind_vars
4330    of BIND if in a method.  */
4331 
4332 static void
maybe_remove_omp_member_access_dummy_vars(gbind * bind)4333 maybe_remove_omp_member_access_dummy_vars (gbind *bind)
4334 {
4335   if (DECL_ARGUMENTS (current_function_decl)
4336       && DECL_ARTIFICIAL (DECL_ARGUMENTS (current_function_decl))
4337       && (TREE_CODE (TREE_TYPE (DECL_ARGUMENTS (current_function_decl)))
4338             == POINTER_TYPE))
4339     {
4340       tree vars = gimple_bind_vars (bind);
4341       for (tree *pvar = &vars; *pvar; )
4342           if (omp_member_access_dummy_var (*pvar))
4343             *pvar = DECL_CHAIN (*pvar);
4344           else
4345             pvar = &DECL_CHAIN (*pvar);
4346       gimple_bind_set_vars (bind, vars);
4347     }
4348 }
4349 
4350 /* Remove omp_member_access_dummy_var variables from BLOCK_VARS of
4351    block and its subblocks.  */
4352 
4353 static void
remove_member_access_dummy_vars(tree block)4354 remove_member_access_dummy_vars (tree block)
4355 {
4356   for (tree *pvar = &BLOCK_VARS (block); *pvar; )
4357     if (omp_member_access_dummy_var (*pvar))
4358       *pvar = DECL_CHAIN (*pvar);
4359     else
4360       pvar = &DECL_CHAIN (*pvar);
4361 
4362   for (block = BLOCK_SUBBLOCKS (block); block; block = BLOCK_CHAIN (block))
4363     remove_member_access_dummy_vars (block);
4364 }
4365 
4366 /* If a context was created for STMT when it was scanned, return it.  */
4367 
4368 static omp_context *
maybe_lookup_ctx(gimple * stmt)4369 maybe_lookup_ctx (gimple *stmt)
4370 {
4371   splay_tree_node n;
4372   n = splay_tree_lookup (all_contexts, (splay_tree_key) stmt);
4373   return n ? (omp_context *) n->value : NULL;
4374 }
4375 
4376 
4377 /* Find the mapping for DECL in CTX or the immediately enclosing
4378    context that has a mapping for DECL.
4379 
4380    If CTX is a nested parallel directive, we may have to use the decl
4381    mappings created in CTX's parent context.  Suppose that we have the
4382    following parallel nesting (variable UIDs showed for clarity):
4383 
4384           iD.1562 = 0;
4385           #omp parallel shared(iD.1562)           -> outer parallel
4386             iD.1562 = iD.1562 + 1;
4387 
4388             #omp parallel shared (iD.1562)        -> inner parallel
4389                iD.1562 = iD.1562 - 1;
4390 
4391    Each parallel structure will create a distinct .omp_data_s structure
4392    for copying iD.1562 in/out of the directive:
4393 
4394           outer parallel                .omp_data_s.1.i -> iD.1562
4395           inner parallel                .omp_data_s.2.i -> iD.1562
4396 
4397    A shared variable mapping will produce a copy-out operation before
4398    the parallel directive and a copy-in operation after it.  So, in
4399    this case we would have:
4400 
4401           iD.1562 = 0;
4402           .omp_data_o.1.i = iD.1562;
4403           #omp parallel shared(iD.1562)           -> outer parallel
4404             .omp_data_i.1 = &.omp_data_o.1
4405             .omp_data_i.1->i = .omp_data_i.1->i + 1;
4406 
4407             .omp_data_o.2.i = iD.1562;            -> **
4408             #omp parallel shared(iD.1562)                   -> inner parallel
4409               .omp_data_i.2 = &.omp_data_o.2
4410               .omp_data_i.2->i = .omp_data_i.2->i - 1;
4411 
4412 
4413     ** This is a problem.  The symbol iD.1562 cannot be referenced
4414        inside the body of the outer parallel region.  But since we are
4415        emitting this copy operation while expanding the inner parallel
4416        directive, we need to access the CTX structure of the outer
4417        parallel directive to get the correct mapping:
4418 
4419             .omp_data_o.2.i = .omp_data_i.1->i
4420 
4421     Since there may be other workshare or parallel directives enclosing
4422     the parallel directive, it may be necessary to walk up the context
4423     parent chain.  This is not a problem in general because nested
4424     parallelism happens only rarely.  */
4425 
4426 static tree
lookup_decl_in_outer_ctx(tree decl,omp_context * ctx)4427 lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
4428 {
4429   tree t;
4430   omp_context *up;
4431 
4432   for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
4433     t = maybe_lookup_decl (decl, up);
4434 
4435   gcc_assert (!ctx->is_nested || t || is_global_var (decl));
4436 
4437   return t ? t : decl;
4438 }
4439 
4440 
4441 /* Similar to lookup_decl_in_outer_ctx, but return DECL if not found
4442    in outer contexts.  */
4443 
4444 static tree
maybe_lookup_decl_in_outer_ctx(tree decl,omp_context * ctx)4445 maybe_lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
4446 {
4447   tree t = NULL;
4448   omp_context *up;
4449 
4450   for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
4451     t = maybe_lookup_decl (decl, up);
4452 
4453   return t ? t : decl;
4454 }
4455 
4456 
4457 /* Construct the initialization value for reduction operation OP.  */
4458 
4459 tree
omp_reduction_init_op(location_t loc,enum tree_code op,tree type)4460 omp_reduction_init_op (location_t loc, enum tree_code op, tree type)
4461 {
4462   switch (op)
4463     {
4464     case PLUS_EXPR:
4465     case MINUS_EXPR:
4466     case BIT_IOR_EXPR:
4467     case BIT_XOR_EXPR:
4468     case TRUTH_OR_EXPR:
4469     case TRUTH_ORIF_EXPR:
4470     case TRUTH_XOR_EXPR:
4471     case NE_EXPR:
4472       return build_zero_cst (type);
4473 
4474     case MULT_EXPR:
4475     case TRUTH_AND_EXPR:
4476     case TRUTH_ANDIF_EXPR:
4477     case EQ_EXPR:
4478       return fold_convert_loc (loc, type, integer_one_node);
4479 
4480     case BIT_AND_EXPR:
4481       return fold_convert_loc (loc, type, integer_minus_one_node);
4482 
4483     case MAX_EXPR:
4484       if (SCALAR_FLOAT_TYPE_P (type))
4485           {
4486             REAL_VALUE_TYPE max, min;
4487             if (HONOR_INFINITIES (type))
4488               {
4489                 real_inf (&max);
4490                 real_arithmetic (&min, NEGATE_EXPR, &max, NULL);
4491               }
4492             else
4493               real_maxval (&min, 1, TYPE_MODE (type));
4494             return build_real (type, min);
4495           }
4496       else if (POINTER_TYPE_P (type))
4497           {
4498             wide_int min
4499               = wi::min_value (TYPE_PRECISION (type), TYPE_SIGN (type));
4500             return wide_int_to_tree (type, min);
4501           }
4502       else
4503           {
4504             gcc_assert (INTEGRAL_TYPE_P (type));
4505             return TYPE_MIN_VALUE (type);
4506           }
4507 
4508     case MIN_EXPR:
4509       if (SCALAR_FLOAT_TYPE_P (type))
4510           {
4511             REAL_VALUE_TYPE max;
4512             if (HONOR_INFINITIES (type))
4513               real_inf (&max);
4514             else
4515               real_maxval (&max, 0, TYPE_MODE (type));
4516             return build_real (type, max);
4517           }
4518       else if (POINTER_TYPE_P (type))
4519           {
4520             wide_int max
4521               = wi::max_value (TYPE_PRECISION (type), TYPE_SIGN (type));
4522             return wide_int_to_tree (type, max);
4523           }
4524       else
4525           {
4526             gcc_assert (INTEGRAL_TYPE_P (type));
4527             return TYPE_MAX_VALUE (type);
4528           }
4529 
4530     default:
4531       gcc_unreachable ();
4532     }
4533 }
4534 
4535 /* Construct the initialization value for reduction CLAUSE.  */
4536 
4537 tree
omp_reduction_init(tree clause,tree type)4538 omp_reduction_init (tree clause, tree type)
4539 {
4540   return omp_reduction_init_op (OMP_CLAUSE_LOCATION (clause),
4541                                         OMP_CLAUSE_REDUCTION_CODE (clause), type);
4542 }
4543 
4544 /* Return alignment to be assumed for var in CLAUSE, which should be
4545    OMP_CLAUSE_ALIGNED.  */
4546 
4547 static tree
omp_clause_aligned_alignment(tree clause)4548 omp_clause_aligned_alignment (tree clause)
4549 {
4550   if (OMP_CLAUSE_ALIGNED_ALIGNMENT (clause))
4551     return OMP_CLAUSE_ALIGNED_ALIGNMENT (clause);
4552 
4553   /* Otherwise return implementation defined alignment.  */
4554   unsigned int al = 1;
4555   opt_scalar_mode mode_iter;
4556   auto_vector_modes modes;
4557   targetm.vectorize.autovectorize_vector_modes (&modes, true);
4558   static enum mode_class classes[]
4559     = { MODE_INT, MODE_VECTOR_INT, MODE_FLOAT, MODE_VECTOR_FLOAT };
4560   for (int i = 0; i < 4; i += 2)
4561     /* The for loop above dictates that we only walk through scalar classes.  */
4562     FOR_EACH_MODE_IN_CLASS (mode_iter, classes[i])
4563       {
4564           scalar_mode mode = mode_iter.require ();
4565           machine_mode vmode = targetm.vectorize.preferred_simd_mode (mode);
4566           if (GET_MODE_CLASS (vmode) != classes[i + 1])
4567             continue;
4568           machine_mode alt_vmode;
4569           for (unsigned int j = 0; j < modes.length (); ++j)
4570             if (related_vector_mode (modes[j], mode).exists (&alt_vmode)
4571                 && known_ge (GET_MODE_SIZE (alt_vmode), GET_MODE_SIZE (vmode)))
4572               vmode = alt_vmode;
4573 
4574           tree type = lang_hooks.types.type_for_mode (mode, 1);
4575           if (type == NULL_TREE || TYPE_MODE (type) != mode)
4576             continue;
4577           type = build_vector_type_for_mode (type, vmode);
4578           if (TYPE_MODE (type) != vmode)
4579             continue;
4580           if (TYPE_ALIGN_UNIT (type) > al)
4581             al = TYPE_ALIGN_UNIT (type);
4582       }
4583   return build_int_cst (integer_type_node, al);
4584 }
4585 
4586 
4587 /* This structure is part of the interface between lower_rec_simd_input_clauses
4588    and lower_rec_input_clauses.  */
4589 
4590 class omplow_simd_context {
4591 public:
omplow_simd_context()4592   omplow_simd_context () { memset (this, 0, sizeof (*this)); }
4593   tree idx;
4594   tree lane;
4595   tree lastlane;
4596   vec<tree, va_heap> simt_eargs;
4597   gimple_seq simt_dlist;
4598   poly_uint64_pod max_vf;
4599   bool is_simt;
4600 };
4601 
4602 /* Helper function of lower_rec_input_clauses, used for #pragma omp simd
4603    privatization.  */
4604 
4605 static bool
lower_rec_simd_input_clauses(tree new_var,omp_context * ctx,omplow_simd_context * sctx,tree & ivar,tree & lvar,tree * rvar=NULL,tree * rvar2=NULL)4606 lower_rec_simd_input_clauses (tree new_var, omp_context *ctx,
4607                                     omplow_simd_context *sctx, tree &ivar,
4608                                     tree &lvar, tree *rvar = NULL,
4609                                     tree *rvar2 = NULL)
4610 {
4611   if (known_eq (sctx->max_vf, 0U))
4612     {
4613       sctx->max_vf = sctx->is_simt ? omp_max_simt_vf () : omp_max_vf ();
4614       if (maybe_gt (sctx->max_vf, 1U))
4615           {
4616             tree c = omp_find_clause (gimple_omp_for_clauses (ctx->stmt),
4617                                             OMP_CLAUSE_SAFELEN);
4618             if (c)
4619               {
4620                 poly_uint64 safe_len;
4621                 if (!poly_int_tree_p (OMP_CLAUSE_SAFELEN_EXPR (c), &safe_len)
4622                       || maybe_lt (safe_len, 1U))
4623                     sctx->max_vf = 1;
4624                 else
4625                     sctx->max_vf = lower_bound (sctx->max_vf, safe_len);
4626               }
4627           }
4628       if (sctx->is_simt && !known_eq (sctx->max_vf, 1U))
4629           {
4630             for (tree c = gimple_omp_for_clauses (ctx->stmt); c;
4631                  c = OMP_CLAUSE_CHAIN (c))
4632               {
4633                 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
4634                     continue;
4635 
4636                 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4637                     {
4638                       /* UDR reductions are not supported yet for SIMT, disable
4639                          SIMT.  */
4640                       sctx->max_vf = 1;
4641                       break;
4642                     }
4643 
4644                 if (truth_value_p (OMP_CLAUSE_REDUCTION_CODE (c))
4645                       && !INTEGRAL_TYPE_P (TREE_TYPE (new_var)))
4646                     {
4647                       /* Doing boolean operations on non-integral types is
4648                          for conformance only, it's not worth supporting this
4649                          for SIMT.  */
4650                       sctx->max_vf = 1;
4651                       break;
4652                 }
4653               }
4654           }
4655       if (maybe_gt (sctx->max_vf, 1U))
4656           {
4657             sctx->idx = create_tmp_var (unsigned_type_node);
4658             sctx->lane = create_tmp_var (unsigned_type_node);
4659           }
4660     }
4661   if (known_eq (sctx->max_vf, 1U))
4662     return false;
4663 
4664   if (sctx->is_simt)
4665     {
4666       if (is_gimple_reg (new_var))
4667           {
4668             ivar = lvar = new_var;
4669             return true;
4670           }
4671       tree type = TREE_TYPE (new_var), ptype = build_pointer_type (type);
4672       ivar = lvar = create_tmp_var (type);
4673       TREE_ADDRESSABLE (ivar) = 1;
4674       DECL_ATTRIBUTES (ivar) = tree_cons (get_identifier ("omp simt private"),
4675                                                     NULL, DECL_ATTRIBUTES (ivar));
4676       sctx->simt_eargs.safe_push (build1 (ADDR_EXPR, ptype, ivar));
4677       tree clobber = build_clobber (type);
4678       gimple *g = gimple_build_assign (ivar, clobber);
4679       gimple_seq_add_stmt (&sctx->simt_dlist, g);
4680     }
4681   else
4682     {
4683       tree atype = build_array_type_nelts (TREE_TYPE (new_var), sctx->max_vf);
4684       tree avar = create_tmp_var_raw (atype);
4685       if (TREE_ADDRESSABLE (new_var))
4686           TREE_ADDRESSABLE (avar) = 1;
4687       DECL_ATTRIBUTES (avar)
4688           = tree_cons (get_identifier ("omp simd array"), NULL,
4689                          DECL_ATTRIBUTES (avar));
4690       gimple_add_tmp_var (avar);
4691       tree iavar = avar;
4692       if (rvar && !ctx->for_simd_scan_phase)
4693           {
4694             /* For inscan reductions, create another array temporary,
4695                which will hold the reduced value.  */
4696             iavar = create_tmp_var_raw (atype);
4697             if (TREE_ADDRESSABLE (new_var))
4698               TREE_ADDRESSABLE (iavar) = 1;
4699             DECL_ATTRIBUTES (iavar)
4700               = tree_cons (get_identifier ("omp simd array"), NULL,
4701                                tree_cons (get_identifier ("omp simd inscan"), NULL,
4702                                             DECL_ATTRIBUTES (iavar)));
4703             gimple_add_tmp_var (iavar);
4704             ctx->cb.decl_map->put (avar, iavar);
4705             if (sctx->lastlane == NULL_TREE)
4706               sctx->lastlane = create_tmp_var (unsigned_type_node);
4707             *rvar = build4 (ARRAY_REF, TREE_TYPE (new_var), iavar,
4708                                 sctx->lastlane, NULL_TREE, NULL_TREE);
4709             TREE_THIS_NOTRAP (*rvar) = 1;
4710 
4711             if (ctx->scan_exclusive)
4712               {
4713                 /* And for exclusive scan yet another one, which will
4714                      hold the value during the scan phase.  */
4715                 tree savar = create_tmp_var_raw (atype);
4716                 if (TREE_ADDRESSABLE (new_var))
4717                     TREE_ADDRESSABLE (savar) = 1;
4718                 DECL_ATTRIBUTES (savar)
4719                     = tree_cons (get_identifier ("omp simd array"), NULL,
4720                                    tree_cons (get_identifier ("omp simd inscan "
4721                                                                       "exclusive"), NULL,
4722                                                   DECL_ATTRIBUTES (savar)));
4723                 gimple_add_tmp_var (savar);
4724                 ctx->cb.decl_map->put (iavar, savar);
4725                 *rvar2 = build4 (ARRAY_REF, TREE_TYPE (new_var), savar,
4726                                      sctx->idx, NULL_TREE, NULL_TREE);
4727                 TREE_THIS_NOTRAP (*rvar2) = 1;
4728               }
4729           }
4730       ivar = build4 (ARRAY_REF, TREE_TYPE (new_var), iavar, sctx->idx,
4731                          NULL_TREE, NULL_TREE);
4732       lvar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, sctx->lane,
4733                          NULL_TREE, NULL_TREE);
4734       TREE_THIS_NOTRAP (ivar) = 1;
4735       TREE_THIS_NOTRAP (lvar) = 1;
4736     }
4737   if (DECL_P (new_var))
4738     {
4739       SET_DECL_VALUE_EXPR (new_var, lvar);
4740       DECL_HAS_VALUE_EXPR_P (new_var) = 1;
4741     }
4742   return true;
4743 }
4744 
4745 /* Helper function of lower_rec_input_clauses.  For a reference
4746    in simd reduction, add an underlying variable it will reference.  */
4747 
4748 static void
handle_simd_reference(location_t loc,tree new_vard,gimple_seq * ilist)4749 handle_simd_reference (location_t loc, tree new_vard, gimple_seq *ilist)
4750 {
4751   tree z = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_vard)));
4752   if (TREE_CONSTANT (z))
4753     {
4754       z = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_vard)),
4755                                     get_name (new_vard));
4756       gimple_add_tmp_var (z);
4757       TREE_ADDRESSABLE (z) = 1;
4758       z = build_fold_addr_expr_loc (loc, z);
4759       gimplify_assign (new_vard, z, ilist);
4760     }
4761 }
4762 
4763 /* Helper function for lower_rec_input_clauses.  Emit into ilist sequence
4764    code to emit (type) (tskred_temp[idx]).  */
4765 
4766 static tree
task_reduction_read(gimple_seq * ilist,tree tskred_temp,tree type,unsigned idx)4767 task_reduction_read (gimple_seq *ilist, tree tskred_temp, tree type,
4768                          unsigned idx)
4769 {
4770   unsigned HOST_WIDE_INT sz
4771     = tree_to_uhwi (TYPE_SIZE_UNIT (pointer_sized_int_node));
4772   tree r = build2 (MEM_REF, pointer_sized_int_node,
4773                        tskred_temp, build_int_cst (TREE_TYPE (tskred_temp),
4774                                                          idx * sz));
4775   tree v = create_tmp_var (pointer_sized_int_node);
4776   gimple *g = gimple_build_assign (v, r);
4777   gimple_seq_add_stmt (ilist, g);
4778   if (!useless_type_conversion_p (type, pointer_sized_int_node))
4779     {
4780       v = create_tmp_var (type);
4781       g = gimple_build_assign (v, NOP_EXPR, gimple_assign_lhs (g));
4782       gimple_seq_add_stmt (ilist, g);
4783     }
4784   return v;
4785 }
4786 
4787 /* Lower early initialization of privatized variable NEW_VAR
4788    if it needs an allocator (has allocate clause).  */
4789 
4790 static bool
lower_private_allocate(tree var,tree new_var,tree & allocator,tree & allocate_ptr,gimple_seq * ilist,omp_context * ctx,bool is_ref,tree size)4791 lower_private_allocate (tree var, tree new_var, tree &allocator,
4792                               tree &allocate_ptr, gimple_seq *ilist,
4793                               omp_context *ctx, bool is_ref, tree size)
4794 {
4795   if (allocator)
4796     return false;
4797   gcc_assert (allocate_ptr == NULL_TREE);
4798   if (ctx->allocate_map
4799       && (DECL_P (new_var) || (TYPE_P (new_var) && size)))
4800     if (tree *allocatorp = ctx->allocate_map->get (var))
4801       allocator = *allocatorp;
4802   if (allocator == NULL_TREE)
4803     return false;
4804   if (!is_ref && omp_privatize_by_reference (var))
4805     {
4806       allocator = NULL_TREE;
4807       return false;
4808     }
4809 
4810   unsigned HOST_WIDE_INT ialign = 0;
4811   if (TREE_CODE (allocator) == TREE_LIST)
4812     {
4813       ialign = tree_to_uhwi (TREE_VALUE (allocator));
4814       allocator = TREE_PURPOSE (allocator);
4815     }
4816   if (TREE_CODE (allocator) != INTEGER_CST)
4817     allocator = build_outer_var_ref (allocator, ctx);
4818   allocator = fold_convert (pointer_sized_int_node, allocator);
4819   if (TREE_CODE (allocator) != INTEGER_CST)
4820     {
4821       tree var = create_tmp_var (TREE_TYPE (allocator));
4822       gimplify_assign (var, allocator, ilist);
4823       allocator = var;
4824     }
4825 
4826   tree ptr_type, align, sz = size;
4827   if (TYPE_P (new_var))
4828     {
4829       ptr_type = build_pointer_type (new_var);
4830       ialign = MAX (ialign, TYPE_ALIGN_UNIT (new_var));
4831     }
4832   else if (is_ref)
4833     {
4834       ptr_type = build_pointer_type (TREE_TYPE (TREE_TYPE (new_var)));
4835       ialign = MAX (ialign, TYPE_ALIGN_UNIT (TREE_TYPE (ptr_type)));
4836     }
4837   else
4838     {
4839       ptr_type = build_pointer_type (TREE_TYPE (new_var));
4840       ialign = MAX (ialign, DECL_ALIGN_UNIT (new_var));
4841       if (sz == NULL_TREE)
4842           sz = fold_convert (size_type_node, DECL_SIZE_UNIT (new_var));
4843     }
4844   align = build_int_cst (size_type_node, ialign);
4845   if (TREE_CODE (sz) != INTEGER_CST)
4846     {
4847       tree szvar = create_tmp_var (size_type_node);
4848       gimplify_assign (szvar, sz, ilist);
4849       sz = szvar;
4850     }
4851   allocate_ptr = create_tmp_var (ptr_type);
4852   tree a = builtin_decl_explicit (BUILT_IN_GOMP_ALLOC);
4853   gimple *g = gimple_build_call (a, 3, align, sz, allocator);
4854   gimple_call_set_lhs (g, allocate_ptr);
4855   gimple_seq_add_stmt (ilist, g);
4856   if (!is_ref)
4857     {
4858       tree x = build_simple_mem_ref (allocate_ptr);
4859       TREE_THIS_NOTRAP (x) = 1;
4860       SET_DECL_VALUE_EXPR (new_var, x);
4861       DECL_HAS_VALUE_EXPR_P (new_var) = 1;
4862     }
4863   return true;
4864 }
4865 
4866 /* Generate code to implement the input clauses, FIRSTPRIVATE and COPYIN,
4867    from the receiver (aka child) side and initializers for REFERENCE_TYPE
4868    private variables.  Initialization statements go in ILIST, while calls
4869    to destructors go in DLIST.  */
4870 
4871 static void
lower_rec_input_clauses(tree clauses,gimple_seq * ilist,gimple_seq * dlist,omp_context * ctx,struct omp_for_data * fd)4872 lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
4873                                omp_context *ctx, struct omp_for_data *fd)
4874 {
4875   tree c, copyin_seq, x, ptr;
4876   bool copyin_by_ref = false;
4877   bool lastprivate_firstprivate = false;
4878   bool reduction_omp_orig_ref = false;
4879   int pass;
4880   bool is_simd = (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
4881                       && gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_SIMD);
4882   omplow_simd_context sctx = omplow_simd_context ();
4883   tree simt_lane = NULL_TREE, simtrec = NULL_TREE;
4884   tree ivar = NULL_TREE, lvar = NULL_TREE, uid = NULL_TREE;
4885   gimple_seq llist[4] = { };
4886   tree nonconst_simd_if = NULL_TREE;
4887 
4888   copyin_seq = NULL;
4889   sctx.is_simt = is_simd && omp_find_clause (clauses, OMP_CLAUSE__SIMT_);
4890 
4891   /* Set max_vf=1 (which will later enforce safelen=1) in simd loops
4892      with data sharing clauses referencing variable sized vars.  That
4893      is unnecessarily hard to support and very unlikely to result in
4894      vectorized code anyway.  */
4895   if (is_simd)
4896     for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4897       switch (OMP_CLAUSE_CODE (c))
4898           {
4899           case OMP_CLAUSE_LINEAR:
4900             if (OMP_CLAUSE_LINEAR_ARRAY (c))
4901               sctx.max_vf = 1;
4902             /* FALLTHRU */
4903           case OMP_CLAUSE_PRIVATE:
4904           case OMP_CLAUSE_FIRSTPRIVATE:
4905           case OMP_CLAUSE_LASTPRIVATE:
4906             if (is_variable_sized (OMP_CLAUSE_DECL (c)))
4907               sctx.max_vf = 1;
4908             else if (omp_privatize_by_reference (OMP_CLAUSE_DECL (c)))
4909               {
4910                 tree rtype = TREE_TYPE (TREE_TYPE (OMP_CLAUSE_DECL (c)));
4911                 if (!TREE_CONSTANT (TYPE_SIZE_UNIT (rtype)))
4912                     sctx.max_vf = 1;
4913               }
4914             break;
4915           case OMP_CLAUSE_REDUCTION:
4916           case OMP_CLAUSE_IN_REDUCTION:
4917             if (TREE_CODE (OMP_CLAUSE_DECL (c)) == MEM_REF
4918                 || is_variable_sized (OMP_CLAUSE_DECL (c)))
4919               sctx.max_vf = 1;
4920             else if (omp_privatize_by_reference (OMP_CLAUSE_DECL (c)))
4921               {
4922                 tree rtype = TREE_TYPE (TREE_TYPE (OMP_CLAUSE_DECL (c)));
4923                 if (!TREE_CONSTANT (TYPE_SIZE_UNIT (rtype)))
4924                     sctx.max_vf = 1;
4925               }
4926             break;
4927           case OMP_CLAUSE_IF:
4928             if (integer_zerop (OMP_CLAUSE_IF_EXPR (c)))
4929               sctx.max_vf = 1;
4930             else if (TREE_CODE (OMP_CLAUSE_IF_EXPR (c)) != INTEGER_CST)
4931               nonconst_simd_if = OMP_CLAUSE_IF_EXPR (c);
4932             break;
4933         case OMP_CLAUSE_SIMDLEN:
4934             if (integer_onep (OMP_CLAUSE_SIMDLEN_EXPR (c)))
4935               sctx.max_vf = 1;
4936             break;
4937           case OMP_CLAUSE__CONDTEMP_:
4938             /* FIXME: lastprivate(conditional:) not handled for SIMT yet.  */
4939             if (sctx.is_simt)
4940               sctx.max_vf = 1;
4941             break;
4942           default:
4943             continue;
4944           }
4945 
4946   /* Add a placeholder for simduid.  */
4947   if (sctx.is_simt && maybe_ne (sctx.max_vf, 1U))
4948     sctx.simt_eargs.safe_push (NULL_TREE);
4949 
4950   unsigned task_reduction_cnt = 0;
4951   unsigned task_reduction_cntorig = 0;
4952   unsigned task_reduction_cnt_full = 0;
4953   unsigned task_reduction_cntorig_full = 0;
4954   unsigned task_reduction_other_cnt = 0;
4955   tree tskred_atype = NULL_TREE, tskred_avar = NULL_TREE;
4956   tree tskred_base = NULL_TREE, tskred_temp = NULL_TREE;
4957   /* Do all the fixed sized types in the first pass, and the variable sized
4958      types in the second pass.  This makes sure that the scalar arguments to
4959      the variable sized types are processed before we use them in the
4960      variable sized operations.  For task reductions we use 4 passes, in the
4961      first two we ignore them, in the third one gather arguments for
4962      GOMP_task_reduction_remap call and in the last pass actually handle
4963      the task reductions.  */
4964   for (pass = 0; pass < ((task_reduction_cnt || task_reduction_other_cnt)
4965                                ? 4 : 2); ++pass)
4966     {
4967       if (pass == 2 && task_reduction_cnt)
4968           {
4969             tskred_atype
4970               = build_array_type_nelts (ptr_type_node, task_reduction_cnt
4971                                                                  + task_reduction_cntorig);
4972             tskred_avar = create_tmp_var_raw (tskred_atype);
4973             gimple_add_tmp_var (tskred_avar);
4974             TREE_ADDRESSABLE (tskred_avar) = 1;
4975             task_reduction_cnt_full = task_reduction_cnt;
4976             task_reduction_cntorig_full = task_reduction_cntorig;
4977           }
4978       else if (pass == 3 && task_reduction_cnt)
4979           {
4980             x = builtin_decl_explicit (BUILT_IN_GOMP_TASK_REDUCTION_REMAP);
4981             gimple *g
4982               = gimple_build_call (x, 3, size_int (task_reduction_cnt),
4983                                          size_int (task_reduction_cntorig),
4984                                          build_fold_addr_expr (tskred_avar));
4985             gimple_seq_add_stmt (ilist, g);
4986           }
4987       if (pass == 3 && task_reduction_other_cnt)
4988           {
4989             /* For reduction clauses, build
4990                tskred_base = (void *) tskred_temp[2]
4991                                  + omp_get_thread_num () * tskred_temp[1]
4992                or if tskred_temp[1] is known to be constant, that constant
4993                directly.  This is the start of the private reduction copy block
4994                for the current thread.  */
4995             tree v = create_tmp_var (integer_type_node);
4996             x = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
4997             gimple *g = gimple_build_call (x, 0);
4998             gimple_call_set_lhs (g, v);
4999             gimple_seq_add_stmt (ilist, g);
5000             c = omp_find_clause (clauses, OMP_CLAUSE__REDUCTEMP_);
5001             tskred_temp = OMP_CLAUSE_DECL (c);
5002             if (is_taskreg_ctx (ctx))
5003               tskred_temp = lookup_decl (tskred_temp, ctx);
5004             tree v2 = create_tmp_var (sizetype);
5005             g = gimple_build_assign (v2, NOP_EXPR, v);
5006             gimple_seq_add_stmt (ilist, g);
5007             if (ctx->task_reductions[0])
5008               v = fold_convert (sizetype, ctx->task_reductions[0]);
5009             else
5010               v = task_reduction_read (ilist, tskred_temp, sizetype, 1);
5011             tree v3 = create_tmp_var (sizetype);
5012             g = gimple_build_assign (v3, MULT_EXPR, v2, v);
5013             gimple_seq_add_stmt (ilist, g);
5014             v = task_reduction_read (ilist, tskred_temp, ptr_type_node, 2);
5015             tskred_base = create_tmp_var (ptr_type_node);
5016             g = gimple_build_assign (tskred_base, POINTER_PLUS_EXPR, v, v3);
5017             gimple_seq_add_stmt (ilist, g);
5018           }
5019       task_reduction_cnt = 0;
5020       task_reduction_cntorig = 0;
5021       task_reduction_other_cnt = 0;
5022       for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
5023           {
5024             enum omp_clause_code c_kind = OMP_CLAUSE_CODE (c);
5025             tree var, new_var;
5026             bool by_ref;
5027             location_t clause_loc = OMP_CLAUSE_LOCATION (c);
5028             bool task_reduction_p = false;
5029             bool task_reduction_needs_orig_p = false;
5030             tree cond = NULL_TREE;
5031             tree allocator, allocate_ptr;
5032 
5033             switch (c_kind)
5034               {
5035               case OMP_CLAUSE_PRIVATE:
5036                 if (OMP_CLAUSE_PRIVATE_DEBUG (c))
5037                     continue;
5038                 break;
5039               case OMP_CLAUSE_SHARED:
5040                 /* Ignore shared directives in teams construct inside
5041                      of target construct.  */
5042                 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS
5043                       && !is_host_teams_ctx (ctx))
5044                     continue;
5045                 if (maybe_lookup_decl (OMP_CLAUSE_DECL (c), ctx) == NULL)
5046                     {
5047                       gcc_assert (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c)
5048                                     || is_global_var (OMP_CLAUSE_DECL (c)));
5049                       continue;
5050                     }
5051               case OMP_CLAUSE_FIRSTPRIVATE:
5052               case OMP_CLAUSE_COPYIN:
5053                 break;
5054               case OMP_CLAUSE_LINEAR:
5055                 if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c)
5056                       && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
5057                     lastprivate_firstprivate = true;
5058                 break;
5059               case OMP_CLAUSE_REDUCTION:
5060               case OMP_CLAUSE_IN_REDUCTION:
5061                 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IN_REDUCTION
5062                       || is_task_ctx (ctx)
5063                       || OMP_CLAUSE_REDUCTION_TASK (c))
5064                     {
5065                       task_reduction_p = true;
5066                       if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
5067                         {
5068                           task_reduction_other_cnt++;
5069                           if (pass == 2)
5070                               continue;
5071                         }
5072                       else
5073                         task_reduction_cnt++;
5074                       if (OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c))
5075                         {
5076                           var = OMP_CLAUSE_DECL (c);
5077                           /* If var is a global variable that isn't privatized
5078                                in outer contexts, we don't need to look up the
5079                                original address, it is always the address of the
5080                                global variable itself.  */
5081                           if (!DECL_P (var)
5082                                 || omp_privatize_by_reference (var)
5083                                 || !is_global_var
5084                                         (maybe_lookup_decl_in_outer_ctx (var, ctx)))
5085                               {
5086                                 task_reduction_needs_orig_p = true;
5087                                 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
5088                                   task_reduction_cntorig++;
5089                               }
5090                         }
5091                     }
5092                 else if (OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c))
5093                     reduction_omp_orig_ref = true;
5094                 break;
5095               case OMP_CLAUSE__REDUCTEMP_:
5096                 if (!is_taskreg_ctx (ctx))
5097                     continue;
5098                 /* FALLTHRU */
5099               case OMP_CLAUSE__LOOPTEMP_:
5100                 /* Handle _looptemp_/_reductemp_ clauses only on
5101                      parallel/task.  */
5102                 if (fd)
5103                     continue;
5104                 break;
5105               case OMP_CLAUSE_LASTPRIVATE:
5106                 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
5107                     {
5108                       lastprivate_firstprivate = true;
5109                       if (pass != 0 || is_taskloop_ctx (ctx))
5110                         continue;
5111                     }
5112                 /* Even without corresponding firstprivate, if
5113                      decl is Fortran allocatable, it needs outer var
5114                      reference.  */
5115                 else if (pass == 0
5116                            && lang_hooks.decls.omp_private_outer_ref
5117                                                                       (OMP_CLAUSE_DECL (c)))
5118                     lastprivate_firstprivate = true;
5119                 break;
5120               case OMP_CLAUSE_ALIGNED:
5121                 if (pass != 1)
5122                     continue;
5123                 var = OMP_CLAUSE_DECL (c);
5124                 if (TREE_CODE (TREE_TYPE (var)) == POINTER_TYPE
5125                       && !is_global_var (var))
5126                     {
5127                       new_var = maybe_lookup_decl (var, ctx);
5128                       if (new_var == NULL_TREE)
5129                         new_var = maybe_lookup_decl_in_outer_ctx (var, ctx);
5130                       x = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
5131                       tree alarg = omp_clause_aligned_alignment (c);
5132                       alarg = fold_convert_loc (clause_loc, size_type_node, alarg);
5133                       x = build_call_expr_loc (clause_loc, x, 2, new_var, alarg);
5134                       x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
5135                       x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
5136                       gimplify_and_add (x, ilist);
5137                     }
5138                 else if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE
5139                            && is_global_var (var))
5140                     {
5141                       tree ptype = build_pointer_type (TREE_TYPE (var)), t, t2;
5142                       new_var = lookup_decl (var, ctx);
5143                       t = maybe_lookup_decl_in_outer_ctx (var, ctx);
5144                       t = build_fold_addr_expr_loc (clause_loc, t);
5145                       t2 = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
5146                       tree alarg = omp_clause_aligned_alignment (c);
5147                       alarg = fold_convert_loc (clause_loc, size_type_node, alarg);
5148                       t = build_call_expr_loc (clause_loc, t2, 2, t, alarg);
5149                       t = fold_convert_loc (clause_loc, ptype, t);
5150                       x = create_tmp_var (ptype);
5151                       t = build2 (MODIFY_EXPR, ptype, x, t);
5152                       gimplify_and_add (t, ilist);
5153                       t = build_simple_mem_ref_loc (clause_loc, x);
5154                       SET_DECL_VALUE_EXPR (new_var, t);
5155                       DECL_HAS_VALUE_EXPR_P (new_var) = 1;
5156                     }
5157                 continue;
5158               case OMP_CLAUSE__CONDTEMP_:
5159                 if (is_parallel_ctx (ctx)
5160                       || (is_simd && !OMP_CLAUSE__CONDTEMP__ITER (c)))
5161                     break;
5162                 continue;
5163               default:
5164                 continue;
5165               }
5166 
5167             if (task_reduction_p != (pass >= 2))
5168               continue;
5169 
5170             allocator = NULL_TREE;
5171             allocate_ptr = NULL_TREE;
5172             new_var = var = OMP_CLAUSE_DECL (c);
5173             if ((c_kind == OMP_CLAUSE_REDUCTION
5174                  || c_kind == OMP_CLAUSE_IN_REDUCTION)
5175                 && TREE_CODE (var) == MEM_REF)
5176               {
5177                 var = TREE_OPERAND (var, 0);
5178                 if (TREE_CODE (var) == POINTER_PLUS_EXPR)
5179                     var = TREE_OPERAND (var, 0);
5180                 if (TREE_CODE (var) == INDIRECT_REF
5181                       || TREE_CODE (var) == ADDR_EXPR)
5182                     var = TREE_OPERAND (var, 0);
5183                 if (is_variable_sized (var))
5184                     {
5185                       gcc_assert (DECL_HAS_VALUE_EXPR_P (var));
5186                       var = DECL_VALUE_EXPR (var);
5187                       gcc_assert (TREE_CODE (var) == INDIRECT_REF);
5188                       var = TREE_OPERAND (var, 0);
5189                       gcc_assert (DECL_P (var));
5190                     }
5191                 new_var = var;
5192               }
5193             if (c_kind == OMP_CLAUSE_IN_REDUCTION && is_omp_target (ctx->stmt))
5194               {
5195                 splay_tree_key key = (splay_tree_key) &DECL_CONTEXT (var);
5196                 new_var = (tree) splay_tree_lookup (ctx->field_map, key)->value;
5197               }
5198             else if (c_kind != OMP_CLAUSE_COPYIN)
5199               new_var = lookup_decl (var, ctx);
5200 
5201             if (c_kind == OMP_CLAUSE_SHARED || c_kind == OMP_CLAUSE_COPYIN)
5202               {
5203                 if (pass != 0)
5204                     continue;
5205               }
5206             /* C/C++ array section reductions.  */
5207             else if ((c_kind == OMP_CLAUSE_REDUCTION
5208                         || c_kind == OMP_CLAUSE_IN_REDUCTION)
5209                        && var != OMP_CLAUSE_DECL (c))
5210               {
5211                 if (pass == 0)
5212                     continue;
5213 
5214                 tree bias = TREE_OPERAND (OMP_CLAUSE_DECL (c), 1);
5215                 tree orig_var = TREE_OPERAND (OMP_CLAUSE_DECL (c), 0);
5216 
5217                 if (TREE_CODE (orig_var) == POINTER_PLUS_EXPR)
5218                     {
5219                       tree b = TREE_OPERAND (orig_var, 1);
5220                       if (is_omp_target (ctx->stmt))
5221                         b = NULL_TREE;
5222                       else
5223                         b = maybe_lookup_decl (b, ctx);
5224                       if (b == NULL)
5225                         {
5226                           b = TREE_OPERAND (orig_var, 1);
5227                           b = maybe_lookup_decl_in_outer_ctx (b, ctx);
5228                         }
5229                       if (integer_zerop (bias))
5230                         bias = b;
5231                       else
5232                         {
5233                           bias = fold_convert_loc (clause_loc,
5234                                                          TREE_TYPE (b), bias);
5235                           bias = fold_build2_loc (clause_loc, PLUS_EXPR,
5236                                                         TREE_TYPE (b), b, bias);
5237                         }
5238                       orig_var = TREE_OPERAND (orig_var, 0);
5239                     }
5240                 if (pass == 2)
5241                     {
5242                       tree out = maybe_lookup_decl_in_outer_ctx (var, ctx);
5243                       if (is_global_var (out)
5244                           && TREE_CODE (TREE_TYPE (out)) != POINTER_TYPE
5245                           && (TREE_CODE (TREE_TYPE (out)) != REFERENCE_TYPE
5246                                 || (TREE_CODE (TREE_TYPE (TREE_TYPE (out)))
5247                                     != POINTER_TYPE)))
5248                         x = var;
5249                       else if (is_omp_target (ctx->stmt))
5250                         x = out;
5251                       else
5252                         {
5253                           bool by_ref = use_pointer_for_field (var, NULL);
5254                           x = build_receiver_ref (var, by_ref, ctx);
5255                           if (TREE_CODE (TREE_TYPE (var)) == REFERENCE_TYPE
5256                                 && (TREE_CODE (TREE_TYPE (TREE_TYPE (var)))
5257                                     == POINTER_TYPE))
5258                               x = build_fold_addr_expr (x);
5259                         }
5260                       if (TREE_CODE (orig_var) == INDIRECT_REF)
5261                         x = build_simple_mem_ref (x);
5262                       else if (TREE_CODE (orig_var) == ADDR_EXPR)
5263                         {
5264                           if (var == TREE_OPERAND (orig_var, 0))
5265                               x = build_fold_addr_expr (x);
5266                         }
5267                       bias = fold_convert (sizetype, bias);
5268                       x = fold_convert (ptr_type_node, x);
5269                       x = fold_build2_loc (clause_loc, POINTER_PLUS_EXPR,
5270                                                TREE_TYPE (x), x, bias);
5271                       unsigned cnt = task_reduction_cnt - 1;
5272                       if (!task_reduction_needs_orig_p)
5273                         cnt += (task_reduction_cntorig_full
5274                                   - task_reduction_cntorig);
5275                       else
5276                         cnt = task_reduction_cntorig - 1;
5277                       tree r = build4 (ARRAY_REF, ptr_type_node, tskred_avar,
5278                                            size_int (cnt), NULL_TREE, NULL_TREE);
5279                       gimplify_assign (r, x, ilist);
5280                       continue;
5281                     }
5282 
5283                 if (TREE_CODE (orig_var) == INDIRECT_REF
5284                       || TREE_CODE (orig_var) == ADDR_EXPR)
5285                     orig_var = TREE_OPERAND (orig_var, 0);
5286                 tree d = OMP_CLAUSE_DECL (c);
5287                 tree type = TREE_TYPE (d);
5288                 gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
5289                 tree v = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
5290                 tree sz = v;
5291                 const char *name = get_name (orig_var);
5292                 if (pass != 3 && !TREE_CONSTANT (v))
5293                     {
5294                       tree t;
5295                       if (is_omp_target (ctx->stmt))
5296                         t = NULL_TREE;
5297                       else
5298                         t = maybe_lookup_decl (v, ctx);
5299                       if (t)
5300                         v = t;
5301                       else
5302                         v = maybe_lookup_decl_in_outer_ctx (v, ctx);
5303                       gimplify_expr (&v, ilist, NULL, is_gimple_val, fb_rvalue);
5304                       t = fold_build2_loc (clause_loc, PLUS_EXPR,
5305                                                TREE_TYPE (v), v,
5306                                                build_int_cst (TREE_TYPE (v), 1));
5307                       sz = fold_build2_loc (clause_loc, MULT_EXPR,
5308                                                   TREE_TYPE (v), t,
5309                                                   TYPE_SIZE_UNIT (TREE_TYPE (type)));
5310                     }
5311                 if (pass == 3)
5312                     {
5313                       tree xv = create_tmp_var (ptr_type_node);
5314                       if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
5315                         {
5316                           unsigned cnt = task_reduction_cnt - 1;
5317                           if (!task_reduction_needs_orig_p)
5318                               cnt += (task_reduction_cntorig_full
5319                                         - task_reduction_cntorig);
5320                           else
5321                               cnt = task_reduction_cntorig - 1;
5322                           x = build4 (ARRAY_REF, ptr_type_node, tskred_avar,
5323                                           size_int (cnt), NULL_TREE, NULL_TREE);
5324 
5325                           gimple *g = gimple_build_assign (xv, x);
5326                           gimple_seq_add_stmt (ilist, g);
5327                         }
5328                       else
5329                         {
5330                           unsigned int idx = *ctx->task_reduction_map->get (c);
5331                           tree off;
5332                           if (ctx->task_reductions[1 + idx])
5333                               off = fold_convert (sizetype,
5334                                                       ctx->task_reductions[1 + idx]);
5335                           else
5336                               off = task_reduction_read (ilist, tskred_temp, sizetype,
5337                                                                7 + 3 * idx + 1);
5338                           gimple *g = gimple_build_assign (xv, POINTER_PLUS_EXPR,
5339                                                                    tskred_base, off);
5340                           gimple_seq_add_stmt (ilist, g);
5341                         }
5342                       x = fold_convert (build_pointer_type (boolean_type_node),
5343                                             xv);
5344                       if (TREE_CONSTANT (v))
5345                         x = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (x), x,
5346                                              TYPE_SIZE_UNIT (type));
5347                       else
5348                         {
5349                           tree t;
5350                           if (is_omp_target (ctx->stmt))
5351                               t = NULL_TREE;
5352                           else
5353                               t = maybe_lookup_decl (v, ctx);
5354                           if (t)
5355                               v = t;
5356                           else
5357                               v = maybe_lookup_decl_in_outer_ctx (v, ctx);
5358                           gimplify_expr (&v, ilist, NULL, is_gimple_val,
5359                                              fb_rvalue);
5360                           t = fold_build2_loc (clause_loc, PLUS_EXPR,
5361                                                      TREE_TYPE (v), v,
5362                                                      build_int_cst (TREE_TYPE (v), 1));
5363                           t = fold_build2_loc (clause_loc, MULT_EXPR,
5364                                                      TREE_TYPE (v), t,
5365                                                      TYPE_SIZE_UNIT (TREE_TYPE (type)));
5366                           x = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (x), x, t);
5367                         }
5368                       cond = create_tmp_var (TREE_TYPE (x));
5369                       gimplify_assign (cond, x, ilist);
5370                       x = xv;
5371                     }
5372                 else if (lower_private_allocate (var, type, allocator,
5373                                                          allocate_ptr, ilist, ctx,
5374                                                          true,
5375                                                          TREE_CONSTANT (v)
5376                                                          ? TYPE_SIZE_UNIT (type)
5377                                                          : sz))
5378                     x = allocate_ptr;
5379                 else if (TREE_CONSTANT (v))
5380                     {
5381                       x = create_tmp_var_raw (type, name);
5382                       gimple_add_tmp_var (x);
5383                       TREE_ADDRESSABLE (x) = 1;
5384                       x = build_fold_addr_expr_loc (clause_loc, x);
5385                     }
5386                 else
5387                     {
5388                       tree atmp
5389                         = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
5390                       tree al = size_int (TYPE_ALIGN (TREE_TYPE (type)));
5391                       x = build_call_expr_loc (clause_loc, atmp, 2, sz, al);
5392                     }
5393 
5394                 tree ptype = build_pointer_type (TREE_TYPE (type));
5395                 x = fold_convert_loc (clause_loc, ptype, x);
5396                 tree y = create_tmp_var (ptype, name);
5397                 gimplify_assign (y, x, ilist);
5398                 x = y;
5399                 tree yb = y;
5400 
5401                 if (!integer_zerop (bias))
5402                     {
5403                       bias = fold_convert_loc (clause_loc, pointer_sized_int_node,
5404                                                      bias);
5405                       yb = fold_convert_loc (clause_loc, pointer_sized_int_node,
5406                                                    x);
5407                       yb = fold_build2_loc (clause_loc, MINUS_EXPR,
5408                                                   pointer_sized_int_node, yb, bias);
5409                       x = fold_convert_loc (clause_loc, TREE_TYPE (x), yb);
5410                       yb = create_tmp_var (ptype, name);
5411                       gimplify_assign (yb, x, ilist);
5412                       x = yb;
5413                     }
5414 
5415                 d = TREE_OPERAND (d, 0);
5416                 if (TREE_CODE (d) == POINTER_PLUS_EXPR)
5417                     d = TREE_OPERAND (d, 0);
5418                 if (TREE_CODE (d) == ADDR_EXPR)
5419                     {
5420                       if (orig_var != var)
5421                         {
5422                           gcc_assert (is_variable_sized (orig_var));
5423                           x = fold_convert_loc (clause_loc, TREE_TYPE (new_var),
5424                                                       x);
5425                           gimplify_assign (new_var, x, ilist);
5426                           tree new_orig_var = lookup_decl (orig_var, ctx);
5427                           tree t = build_fold_indirect_ref (new_var);
5428                           DECL_IGNORED_P (new_var) = 0;
5429                           TREE_THIS_NOTRAP (t) = 1;
5430                           SET_DECL_VALUE_EXPR (new_orig_var, t);
5431                           DECL_HAS_VALUE_EXPR_P (new_orig_var) = 1;
5432                         }
5433                       else
5434                         {
5435                           x = build2 (MEM_REF, TREE_TYPE (new_var), x,
5436                                           build_int_cst (ptype, 0));
5437                           SET_DECL_VALUE_EXPR (new_var, x);
5438                           DECL_HAS_VALUE_EXPR_P (new_var) = 1;
5439                         }
5440                     }
5441                 else
5442                     {
5443                       gcc_assert (orig_var == var);
5444                       if (TREE_CODE (d) == INDIRECT_REF)
5445                         {
5446                           x = create_tmp_var (ptype, name);
5447                           TREE_ADDRESSABLE (x) = 1;
5448                           gimplify_assign (x, yb, ilist);
5449                           x = build_fold_addr_expr_loc (clause_loc, x);
5450                         }
5451                       x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
5452                       gimplify_assign (new_var, x, ilist);
5453                     }
5454                 /* GOMP_taskgroup_reduction_register memsets the whole
5455                      array to zero.  If the initializer is zero, we don't
5456                      need to initialize it again, just mark it as ever
5457                      used unconditionally, i.e. cond = true.  */
5458                 if (cond
5459                       && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) == NULL_TREE
5460                       && initializer_zerop (omp_reduction_init (c,
5461                                                                           TREE_TYPE (type))))
5462                     {
5463                       gimple *g = gimple_build_assign (build_simple_mem_ref (cond),
5464                                                                boolean_true_node);
5465                       gimple_seq_add_stmt (ilist, g);
5466                       continue;
5467                     }
5468                 tree end = create_artificial_label (UNKNOWN_LOCATION);
5469                 if (cond)
5470                     {
5471                       gimple *g;
5472                       if (!is_parallel_ctx (ctx))
5473                         {
5474                           tree condv = create_tmp_var (boolean_type_node);
5475                           g = gimple_build_assign (condv,
5476                                                          build_simple_mem_ref (cond));
5477                           gimple_seq_add_stmt (ilist, g);
5478                           tree lab1 = create_artificial_label (UNKNOWN_LOCATION);
5479                           g = gimple_build_cond (NE_EXPR, condv,
5480                                                        boolean_false_node, end, lab1);
5481                           gimple_seq_add_stmt (ilist, g);
5482                           gimple_seq_add_stmt (ilist, gimple_build_label (lab1));
5483                         }
5484                       g = gimple_build_assign (build_simple_mem_ref (cond),
5485                                                      boolean_true_node);
5486                       gimple_seq_add_stmt (ilist, g);
5487                     }
5488 
5489                 tree y1 = create_tmp_var (ptype);
5490                 gimplify_assign (y1, y, ilist);
5491                 tree i2 = NULL_TREE, y2 = NULL_TREE;
5492                 tree body2 = NULL_TREE, end2 = NULL_TREE;
5493                 tree y3 = NULL_TREE, y4 = NULL_TREE;
5494                 if (task_reduction_needs_orig_p)
5495                     {
5496                       y3 = create_tmp_var (ptype);
5497                       tree ref;
5498                       if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
5499                         ref = build4 (ARRAY_REF, ptr_type_node, tskred_avar,
5500                                           size_int (task_reduction_cnt_full
5501                                                       + task_reduction_cntorig - 1),
5502                                           NULL_TREE, NULL_TREE);
5503                       else
5504                         {
5505                           unsigned int idx = *ctx->task_reduction_map->get (c);
5506                           ref = task_reduction_read (ilist, tskred_temp, ptype,
5507                                                              7 + 3 * idx);
5508                         }
5509                       gimplify_assign (y3, ref, ilist);
5510                     }
5511                 else if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) || is_simd)
5512                     {
5513                       if (pass != 3)
5514                         {
5515                           y2 = create_tmp_var (ptype);
5516                           gimplify_assign (y2, y, ilist);
5517                         }
5518                       if (is_simd || OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c))
5519                         {
5520                           tree ref = build_outer_var_ref (var, ctx);
5521                           /* For ref build_outer_var_ref already performs this.  */
5522                           if (TREE_CODE (d) == INDIRECT_REF)
5523                               gcc_assert (omp_privatize_by_reference (var));
5524                           else if (TREE_CODE (d) == ADDR_EXPR)
5525                               ref = build_fold_addr_expr (ref);
5526                           else if (omp_privatize_by_reference (var))
5527                               ref = build_fold_addr_expr (ref);
5528                           ref = fold_convert_loc (clause_loc, ptype, ref);
5529                           if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)
5530                                 && OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c))
5531                               {
5532                                 y3 = create_tmp_var (ptype);
5533                                 gimplify_assign (y3, unshare_expr (ref), ilist);
5534                               }
5535                           if (is_simd)
5536                               {
5537                                 y4 = create_tmp_var (ptype);
5538                                 gimplify_assign (y4, ref, dlist);
5539                               }
5540                         }
5541                     }
5542                 tree i = create_tmp_var (TREE_TYPE (v));
5543                 gimplify_assign (i, build_int_cst (TREE_TYPE (v), 0), ilist);
5544                 tree body = create_artificial_label (UNKNOWN_LOCATION);
5545                 gimple_seq_add_stmt (ilist, gimple_build_label (body));
5546                 if (y2)
5547                     {
5548                       i2 = create_tmp_var (TREE_TYPE (v));
5549                       gimplify_assign (i2, build_int_cst (TREE_TYPE (v), 0), dlist);
5550                       body2 = create_artificial_label (UNKNOWN_LOCATION);
5551                       end2 = create_artificial_label (UNKNOWN_LOCATION);
5552                       gimple_seq_add_stmt (dlist, gimple_build_label (body2));
5553                     }
5554                 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
5555                     {
5556                       tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
5557                       tree decl_placeholder
5558                         = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c);
5559                       SET_DECL_VALUE_EXPR (decl_placeholder,
5560                                                build_simple_mem_ref (y1));
5561                       DECL_HAS_VALUE_EXPR_P (decl_placeholder) = 1;
5562                       SET_DECL_VALUE_EXPR (placeholder,
5563                                                y3 ? build_simple_mem_ref (y3)
5564                                                : error_mark_node);
5565                       DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
5566                       x = lang_hooks.decls.omp_clause_default_ctor
5567                                         (c, build_simple_mem_ref (y1),
5568                                          y3 ? build_simple_mem_ref (y3) : NULL_TREE);
5569                       if (x)
5570                         gimplify_and_add (x, ilist);
5571                       if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
5572                         {
5573                           gimple_seq tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
5574                           lower_omp (&tseq, ctx);
5575                           gimple_seq_add_seq (ilist, tseq);
5576                         }
5577                       OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
5578                       if (is_simd)
5579                         {
5580                           SET_DECL_VALUE_EXPR (decl_placeholder,
5581                                                      build_simple_mem_ref (y2));
5582                           SET_DECL_VALUE_EXPR (placeholder,
5583                                                      build_simple_mem_ref (y4));
5584                           gimple_seq tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
5585                           lower_omp (&tseq, ctx);
5586                           gimple_seq_add_seq (dlist, tseq);
5587                           OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
5588                         }
5589                       DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
5590                       DECL_HAS_VALUE_EXPR_P (decl_placeholder) = 0;
5591                       if (y2)
5592                         {
5593                           x = lang_hooks.decls.omp_clause_dtor
5594                                                             (c, build_simple_mem_ref (y2));
5595                           if (x)
5596                               gimplify_and_add (x, dlist);
5597                         }
5598                     }
5599                 else
5600                     {
5601                       x = omp_reduction_init (c, TREE_TYPE (type));
5602                       enum tree_code code = OMP_CLAUSE_REDUCTION_CODE (c);
5603 
5604                       /* reduction(-:var) sums up the partial results, so it
5605                          acts identically to reduction(+:var).  */
5606                       if (code == MINUS_EXPR)
5607                         code = PLUS_EXPR;
5608 
5609                       gimplify_assign (build_simple_mem_ref (y1), x, ilist);
5610                       if (is_simd)
5611                         {
5612                           x = build2 (code, TREE_TYPE (type),
5613                                           build_simple_mem_ref (y4),
5614                                           build_simple_mem_ref (y2));
5615                           gimplify_assign (build_simple_mem_ref (y4), x, dlist);
5616                         }
5617                     }
5618                 gimple *g
5619                     = gimple_build_assign (y1, POINTER_PLUS_EXPR, y1,
5620                                                TYPE_SIZE_UNIT (TREE_TYPE (type)));
5621                 gimple_seq_add_stmt (ilist, g);
5622                 if (y3)
5623                     {
5624                       g = gimple_build_assign (y3, POINTER_PLUS_EXPR, y3,
5625                                                      TYPE_SIZE_UNIT (TREE_TYPE (type)));
5626                       gimple_seq_add_stmt (ilist, g);
5627                     }
5628                 g = gimple_build_assign (i, PLUS_EXPR, i,
5629                                                build_int_cst (TREE_TYPE (i), 1));
5630                 gimple_seq_add_stmt (ilist, g);
5631                 g = gimple_build_cond (LE_EXPR, i, v, body, end);
5632                 gimple_seq_add_stmt (ilist, g);
5633                 gimple_seq_add_stmt (ilist, gimple_build_label (end));
5634                 if (y2)
5635                     {
5636                       g = gimple_build_assign (y2, POINTER_PLUS_EXPR, y2,
5637                                                      TYPE_SIZE_UNIT (TREE_TYPE (type)));
5638                       gimple_seq_add_stmt (dlist, g);
5639                       if (y4)
5640                         {
5641                           g = gimple_build_assign
5642                                                   (y4, POINTER_PLUS_EXPR, y4,
5643                                                    TYPE_SIZE_UNIT (TREE_TYPE (type)));
5644                           gimple_seq_add_stmt (dlist, g);
5645                         }
5646                       g = gimple_build_assign (i2, PLUS_EXPR, i2,
5647                                                      build_int_cst (TREE_TYPE (i2), 1));
5648                       gimple_seq_add_stmt (dlist, g);
5649                       g = gimple_build_cond (LE_EXPR, i2, v, body2, end2);
5650                       gimple_seq_add_stmt (dlist, g);
5651                       gimple_seq_add_stmt (dlist, gimple_build_label (end2));
5652                     }
5653                 if (allocator)
5654                     {
5655                       tree f = builtin_decl_explicit (BUILT_IN_GOMP_FREE);
5656                       g = gimple_build_call (f, 2, allocate_ptr, allocator);
5657                       gimple_seq_add_stmt (dlist, g);
5658                     }
5659                 continue;
5660               }
5661             else if (pass == 2)
5662               {
5663                 tree out = maybe_lookup_decl_in_outer_ctx (var, ctx);
5664                 if (is_global_var (out))
5665                     x = var;
5666                 else if (is_omp_target (ctx->stmt))
5667                     x = out;
5668                 else
5669                     {
5670                       bool by_ref = use_pointer_for_field (var, ctx);
5671                       x = build_receiver_ref (var, by_ref, ctx);
5672                     }
5673                 if (!omp_privatize_by_reference (var))
5674                     x = build_fold_addr_expr (x);
5675                 x = fold_convert (ptr_type_node, x);
5676                 unsigned cnt = task_reduction_cnt - 1;
5677                 if (!task_reduction_needs_orig_p)
5678                     cnt += task_reduction_cntorig_full - task_reduction_cntorig;
5679                 else
5680                     cnt = task_reduction_cntorig - 1;
5681                 tree r = build4 (ARRAY_REF, ptr_type_node, tskred_avar,
5682                                      size_int (cnt), NULL_TREE, NULL_TREE);
5683                 gimplify_assign (r, x, ilist);
5684                 continue;
5685               }
5686             else if (pass == 3)
5687               {
5688                 tree type = TREE_TYPE (new_var);
5689                 if (!omp_privatize_by_reference (var))
5690                     type = build_pointer_type (type);
5691                 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
5692                     {
5693                       unsigned cnt = task_reduction_cnt - 1;
5694                       if (!task_reduction_needs_orig_p)
5695                         cnt += (task_reduction_cntorig_full
5696                                   - task_reduction_cntorig);
5697                       else
5698                         cnt = task_reduction_cntorig - 1;
5699                       x = build4 (ARRAY_REF, ptr_type_node, tskred_avar,
5700                                     size_int (cnt), NULL_TREE, NULL_TREE);
5701                     }
5702                 else
5703                     {
5704                       unsigned int idx = *ctx->task_reduction_map->get (c);
5705                       tree off;
5706                       if (ctx->task_reductions[1 + idx])
5707                         off = fold_convert (sizetype,
5708                                                   ctx->task_reductions[1 + idx]);
5709                       else
5710                         off = task_reduction_read (ilist, tskred_temp, sizetype,
5711                                                          7 + 3 * idx + 1);
5712                       x = fold_build2 (POINTER_PLUS_EXPR, ptr_type_node,
5713                                            tskred_base, off);
5714                     }
5715                 x = fold_convert (type, x);
5716                 tree t;
5717                 if (omp_privatize_by_reference (var))
5718                     {
5719                       gimplify_assign (new_var, x, ilist);
5720                       t = new_var;
5721                       new_var = build_simple_mem_ref (new_var);
5722                     }
5723                 else
5724                     {
5725                       t = create_tmp_var (type);
5726                       gimplify_assign (t, x, ilist);
5727                       SET_DECL_VALUE_EXPR (new_var, build_simple_mem_ref (t));
5728                       DECL_HAS_VALUE_EXPR_P (new_var) = 1;
5729                     }
5730                 t = fold_convert (build_pointer_type (boolean_type_node), t);
5731                 t = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (t), t,
5732                                      TYPE_SIZE_UNIT (TREE_TYPE (type)));
5733                 cond = create_tmp_var (TREE_TYPE (t));
5734                 gimplify_assign (cond, t, ilist);
5735               }
5736             else if (is_variable_sized (var))
5737               {
5738                 /* For variable sized types, we need to allocate the
5739                      actual storage here.  Call alloca and store the
5740                      result in the pointer decl that we created elsewhere.  */
5741                 if (pass == 0)
5742                     continue;
5743 
5744                 if (c_kind != OMP_CLAUSE_FIRSTPRIVATE || !is_task_ctx (ctx))
5745                     {
5746                       tree tmp;
5747 
5748                       ptr = DECL_VALUE_EXPR (new_var);
5749                       gcc_assert (TREE_CODE (ptr) == INDIRECT_REF);
5750                       ptr = TREE_OPERAND (ptr, 0);
5751                       gcc_assert (DECL_P (ptr));
5752                       x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
5753 
5754                       if (lower_private_allocate (var, new_var, allocator,
5755                                                         allocate_ptr, ilist, ctx,
5756                                                         false, x))
5757                         tmp = allocate_ptr;
5758                       else
5759                         {
5760                           /* void *tmp = __builtin_alloca */
5761                           tree atmp
5762                               = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
5763                           gcall *stmt
5764                               = gimple_build_call (atmp, 2, x,
5765                                                        size_int (DECL_ALIGN (var)));
5766                           cfun->calls_alloca = 1;
5767                           tmp = create_tmp_var_raw (ptr_type_node);
5768                           gimple_add_tmp_var (tmp);
5769                           gimple_call_set_lhs (stmt, tmp);
5770 
5771                           gimple_seq_add_stmt (ilist, stmt);
5772                         }
5773 
5774                       x = fold_convert_loc (clause_loc, TREE_TYPE (ptr), tmp);
5775                       gimplify_assign (ptr, x, ilist);
5776                     }
5777               }
5778             else if (omp_privatize_by_reference (var)
5779                        && (c_kind != OMP_CLAUSE_FIRSTPRIVATE
5780                            || !OMP_CLAUSE_FIRSTPRIVATE_NO_REFERENCE (c)))
5781               {
5782                 /* For references that are being privatized for Fortran,
5783                      allocate new backing storage for the new pointer
5784                      variable.  This allows us to avoid changing all the
5785                      code that expects a pointer to something that expects
5786                      a direct variable.  */
5787                 if (pass == 0)
5788                     continue;
5789 
5790                 x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
5791                 if (c_kind == OMP_CLAUSE_FIRSTPRIVATE && is_task_ctx (ctx))
5792                     {
5793                       x = build_receiver_ref (var, false, ctx);
5794                       if (ctx->allocate_map)
5795                         if (tree *allocatep = ctx->allocate_map->get (var))
5796                           {
5797                               allocator = *allocatep;
5798                               if (TREE_CODE (allocator) == TREE_LIST)
5799                                 allocator = TREE_PURPOSE (allocator);
5800                               if (TREE_CODE (allocator) != INTEGER_CST)
5801                                 allocator = build_outer_var_ref (allocator, ctx);
5802                               allocator = fold_convert (pointer_sized_int_node,
5803                                                               allocator);
5804                               allocate_ptr = unshare_expr (x);
5805                           }
5806                       if (allocator == NULL_TREE)
5807                         x = build_fold_addr_expr_loc (clause_loc, x);
5808                     }
5809                 else if (lower_private_allocate (var, new_var, allocator,
5810                                                          allocate_ptr,
5811                                                          ilist, ctx, true, x))
5812                     x = allocate_ptr;
5813                 else if (TREE_CONSTANT (x))
5814                     {
5815                       /* For reduction in SIMD loop, defer adding the
5816                          initialization of the reference, because if we decide
5817                          to use SIMD array for it, the initilization could cause
5818                          expansion ICE.  Ditto for other privatization clauses.  */
5819                       if (is_simd)
5820                         x = NULL_TREE;
5821                       else
5822                         {
5823                           x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)),
5824                                                         get_name (var));
5825                           gimple_add_tmp_var (x);
5826                           TREE_ADDRESSABLE (x) = 1;
5827                           x = build_fold_addr_expr_loc (clause_loc, x);
5828                         }
5829                     }
5830                 else
5831                     {
5832                       tree atmp
5833                         = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
5834                       tree rtype = TREE_TYPE (TREE_TYPE (new_var));
5835                       tree al = size_int (TYPE_ALIGN (rtype));
5836                       x = build_call_expr_loc (clause_loc, atmp, 2, x, al);
5837                     }
5838 
5839                 if (x)
5840                     {
5841                       x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
5842                       gimplify_assign (new_var, x, ilist);
5843                     }
5844 
5845                 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
5846               }
5847             else if ((c_kind == OMP_CLAUSE_REDUCTION
5848                         || c_kind == OMP_CLAUSE_IN_REDUCTION)
5849                        && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
5850               {
5851                 if (pass == 0)
5852                     continue;
5853               }
5854             else if (pass != 0)
5855               continue;
5856 
5857             switch (OMP_CLAUSE_CODE (c))
5858               {
5859               case OMP_CLAUSE_SHARED:
5860                 /* Ignore shared directives in teams construct inside
5861                      target construct.  */
5862                 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS
5863                       && !is_host_teams_ctx (ctx))
5864                     continue;
5865                 /* Shared global vars are just accessed directly.  */
5866                 if (is_global_var (new_var))
5867                     break;
5868                 /* For taskloop firstprivate/lastprivate, represented
5869                      as firstprivate and shared clause on the task, new_var
5870                      is the firstprivate var.  */
5871                 if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
5872                     break;
5873                 /* Set up the DECL_VALUE_EXPR for shared variables now.  This
5874                      needs to be delayed until after fixup_child_record_type so
5875                      that we get the correct type during the dereference.  */
5876                 by_ref = use_pointer_for_field (var, ctx);
5877                 x = build_receiver_ref (var, by_ref, ctx);
5878                 SET_DECL_VALUE_EXPR (new_var, x);
5879                 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
5880 
5881                 /* ??? If VAR is not passed by reference, and the variable
5882                      hasn't been initialized yet, then we'll get a warning for
5883                      the store into the omp_data_s structure.  Ideally, we'd be
5884                      able to notice this and not store anything at all, but
5885                      we're generating code too early.  Suppress the warning.  */
5886                 if (!by_ref)
5887                     suppress_warning (var, OPT_Wuninitialized);
5888                 break;
5889 
5890               case OMP_CLAUSE__CONDTEMP_:
5891                 if (is_parallel_ctx (ctx))
5892                     {
5893                       x = build_receiver_ref (var, false, ctx);
5894                       SET_DECL_VALUE_EXPR (new_var, x);
5895                       DECL_HAS_VALUE_EXPR_P (new_var) = 1;
5896                     }
5897                 else if (is_simd && !OMP_CLAUSE__CONDTEMP__ITER (c))
5898                     {
5899                       x = build_zero_cst (TREE_TYPE (var));
5900                       goto do_private;
5901                     }
5902                 break;
5903 
5904               case OMP_CLAUSE_LASTPRIVATE:
5905                 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
5906                     break;
5907                 /* FALLTHRU */
5908 
5909               case OMP_CLAUSE_PRIVATE:
5910                 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_PRIVATE)
5911                     x = build_outer_var_ref (var, ctx);
5912                 else if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
5913                     {
5914                       if (is_task_ctx (ctx))
5915                         x = build_receiver_ref (var, false, ctx);
5916                       else
5917                         x = build_outer_var_ref (var, ctx, OMP_CLAUSE_PRIVATE);
5918                     }
5919                 else
5920                     x = NULL;
5921               do_private:
5922                 tree nx;
5923                 bool copy_ctor;
5924                 copy_ctor = false;
5925                 lower_private_allocate (var, new_var, allocator, allocate_ptr,
5926                                               ilist, ctx, false, NULL_TREE);
5927                 nx = unshare_expr (new_var);
5928                 if (is_simd
5929                       && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
5930                       && OMP_CLAUSE_LASTPRIVATE_LOOP_IV (c))
5931                     copy_ctor = true;
5932                 if (copy_ctor)
5933                     nx = lang_hooks.decls.omp_clause_copy_ctor (c, nx, x);
5934                 else
5935                     nx = lang_hooks.decls.omp_clause_default_ctor (c, nx, x);
5936                 if (is_simd)
5937                     {
5938                       tree y = lang_hooks.decls.omp_clause_dtor (c, new_var);
5939                       if ((TREE_ADDRESSABLE (new_var) || nx || y
5940                            || (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
5941                                  && (gimple_omp_for_collapse (ctx->stmt) != 1
5942                                      || (gimple_omp_for_index (ctx->stmt, 0)
5943                                            != new_var)))
5944                            || OMP_CLAUSE_CODE (c) == OMP_CLAUSE__CONDTEMP_
5945                            || omp_privatize_by_reference (var))
5946                           && lower_rec_simd_input_clauses (new_var, ctx, &sctx,
5947                                                                    ivar, lvar))
5948                         {
5949                           if (omp_privatize_by_reference (var))
5950                               {
5951                                 gcc_assert (TREE_CODE (new_var) == MEM_REF);
5952                                 tree new_vard = TREE_OPERAND (new_var, 0);
5953                                 gcc_assert (DECL_P (new_vard));
5954                                 SET_DECL_VALUE_EXPR (new_vard,
5955                                                          build_fold_addr_expr (lvar));
5956                                 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
5957                               }
5958 
5959                           if (nx)
5960                               {
5961                                 tree iv = unshare_expr (ivar);
5962                                 if (copy_ctor)
5963                                   x = lang_hooks.decls.omp_clause_copy_ctor (c, iv,
5964                                                                                        x);
5965                                 else
5966                                   x = lang_hooks.decls.omp_clause_default_ctor (c,
5967                                                                                             iv,
5968                                                                                             x);
5969                               }
5970                           else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE__CONDTEMP_)
5971                               {
5972                                 x = build2 (MODIFY_EXPR, TREE_TYPE (ivar),
5973                                               unshare_expr (ivar), x);
5974                                 nx = x;
5975                               }
5976                           if (nx && x)
5977                               gimplify_and_add (x, &llist[0]);
5978                           if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
5979                                 && OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c))
5980                               {
5981                                 tree v = new_var;
5982                                 if (!DECL_P (v))
5983                                   {
5984                                     gcc_assert (TREE_CODE (v) == MEM_REF);
5985                                     v = TREE_OPERAND (v, 0);
5986                                     gcc_assert (DECL_P (v));
5987                                   }
5988                                 v = *ctx->lastprivate_conditional_map->get (v);
5989                                 tree t = create_tmp_var (TREE_TYPE (v));
5990                                 tree z = build_zero_cst (TREE_TYPE (v));
5991                                 tree orig_v
5992                                   = build_outer_var_ref (var, ctx,
5993                                                                OMP_CLAUSE_LASTPRIVATE);
5994                                 gimple_seq_add_stmt (dlist,
5995                                                          gimple_build_assign (t, z));
5996                                 gcc_assert (DECL_HAS_VALUE_EXPR_P (v));
5997                                 tree civar = DECL_VALUE_EXPR (v);
5998                                 gcc_assert (TREE_CODE (civar) == ARRAY_REF);
5999                                 civar = unshare_expr (civar);
6000                                 TREE_OPERAND (civar, 1) = sctx.idx;
6001                                 x = build2 (MODIFY_EXPR, TREE_TYPE (t), t,
6002                                               unshare_expr (civar));
6003                                 x = build2 (COMPOUND_EXPR, TREE_TYPE (orig_v), x,
6004                                               build2 (MODIFY_EXPR, TREE_TYPE (orig_v),
6005                                                         orig_v, unshare_expr (ivar)));
6006                                 tree cond = build2 (LT_EXPR, boolean_type_node, t,
6007                                                         civar);
6008                                 x = build3 (COND_EXPR, void_type_node, cond, x,
6009                                               void_node);
6010                                 gimple_seq tseq = NULL;
6011                                 gimplify_and_add (x, &tseq);
6012                                 if (ctx->outer)
6013                                   lower_omp (&tseq, ctx->outer);
6014                                 gimple_seq_add_seq (&llist[1], tseq);
6015                               }
6016                           if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
6017                                 && ctx->for_simd_scan_phase)
6018                               {
6019                                 x = unshare_expr (ivar);
6020                                 tree orig_v
6021                                   = build_outer_var_ref (var, ctx,
6022                                                                OMP_CLAUSE_LASTPRIVATE);
6023                                 x = lang_hooks.decls.omp_clause_assign_op (c, x,
6024                                                                                      orig_v);
6025                                 gimplify_and_add (x, &llist[0]);
6026                               }
6027                           if (y)
6028                               {
6029                                 y = lang_hooks.decls.omp_clause_dtor (c, ivar);
6030                                 if (y)
6031                                   gimplify_and_add (y, &llist[1]);
6032                               }
6033                           break;
6034                         }
6035                       if (omp_privatize_by_reference (var))
6036                         {
6037                           gcc_assert (TREE_CODE (new_var) == MEM_REF);
6038                           tree new_vard = TREE_OPERAND (new_var, 0);
6039                           gcc_assert (DECL_P (new_vard));
6040                           tree type = TREE_TYPE (TREE_TYPE (new_vard));
6041                           x = TYPE_SIZE_UNIT (type);
6042                           if (TREE_CONSTANT (x))
6043                               {
6044                                 x = create_tmp_var_raw (type, get_name (var));
6045                                 gimple_add_tmp_var (x);
6046                                 TREE_ADDRESSABLE (x) = 1;
6047                                 x = build_fold_addr_expr_loc (clause_loc, x);
6048                                 x = fold_convert_loc (clause_loc,
6049                                                             TREE_TYPE (new_vard), x);
6050                                 gimplify_assign (new_vard, x, ilist);
6051                               }
6052                         }
6053                     }
6054                 if (nx)
6055                     gimplify_and_add (nx, ilist);
6056                 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
6057                       && is_simd
6058                       && ctx->for_simd_scan_phase)
6059                     {
6060                       tree orig_v = build_outer_var_ref (var, ctx,
6061                                                                  OMP_CLAUSE_LASTPRIVATE);
6062                       x = lang_hooks.decls.omp_clause_assign_op (c, new_var,
6063                                                                            orig_v);
6064                       gimplify_and_add (x, ilist);
6065                     }
6066                 /* FALLTHRU */
6067 
6068               do_dtor:
6069                 x = lang_hooks.decls.omp_clause_dtor (c, new_var);
6070                 if (x)
6071                     gimplify_and_add (x, dlist);
6072                 if (allocator)
6073                     {
6074                       if (!is_gimple_val (allocator))
6075                         {
6076                           tree avar = create_tmp_var (TREE_TYPE (allocator));
6077                           gimplify_assign (avar, allocator, dlist);
6078                           allocator = avar;
6079                         }
6080                       if (!is_gimple_val (allocate_ptr))
6081                         {
6082                           tree apvar = create_tmp_var (TREE_TYPE (allocate_ptr));
6083                           gimplify_assign (apvar, allocate_ptr, dlist);
6084                           allocate_ptr = apvar;
6085                         }
6086                       tree f = builtin_decl_explicit (BUILT_IN_GOMP_FREE);
6087                       gimple *g
6088                         = gimple_build_call (f, 2, allocate_ptr, allocator);
6089                       gimple_seq_add_stmt (dlist, g);
6090                     }
6091                 break;
6092 
6093               case OMP_CLAUSE_LINEAR:
6094                 if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c))
6095                     goto do_firstprivate;
6096                 if (OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
6097                     x = NULL;
6098                 else
6099                     x = build_outer_var_ref (var, ctx);
6100                 goto do_private;
6101 
6102               case OMP_CLAUSE_FIRSTPRIVATE:
6103                 if (is_task_ctx (ctx))
6104                     {
6105                       if ((omp_privatize_by_reference (var)
6106                            && !OMP_CLAUSE_FIRSTPRIVATE_NO_REFERENCE (c))
6107                           || is_variable_sized (var))
6108                         goto do_dtor;
6109                       else if (is_global_var (maybe_lookup_decl_in_outer_ctx (var,
6110                                                                                             ctx))
6111                                  || use_pointer_for_field (var, NULL))
6112                         {
6113                           x = build_receiver_ref (var, false, ctx);
6114                           if (ctx->allocate_map)
6115                               if (tree *allocatep = ctx->allocate_map->get (var))
6116                                 {
6117                                   allocator = *allocatep;
6118                                   if (TREE_CODE (allocator) == TREE_LIST)
6119                                     allocator = TREE_PURPOSE (allocator);
6120                                   if (TREE_CODE (allocator) != INTEGER_CST)
6121                                     allocator = build_outer_var_ref (allocator, ctx);
6122                                   allocator = fold_convert (pointer_sized_int_node,
6123                                                                   allocator);
6124                                   allocate_ptr = unshare_expr (x);
6125                                   x = build_simple_mem_ref (x);
6126                                   TREE_THIS_NOTRAP (x) = 1;
6127                                 }
6128                           SET_DECL_VALUE_EXPR (new_var, x);
6129                           DECL_HAS_VALUE_EXPR_P (new_var) = 1;
6130                           goto do_dtor;
6131                         }
6132                     }
6133                 if (OMP_CLAUSE_FIRSTPRIVATE_NO_REFERENCE (c)
6134                       && omp_privatize_by_reference (var))
6135                     {
6136                       x = build_outer_var_ref (var, ctx);
6137                       gcc_assert (TREE_CODE (x) == MEM_REF
6138                                     && integer_zerop (TREE_OPERAND (x, 1)));
6139                       x = TREE_OPERAND (x, 0);
6140                       x = lang_hooks.decls.omp_clause_copy_ctor
6141                                                             (c, unshare_expr (new_var), x);
6142                       gimplify_and_add (x, ilist);
6143                       goto do_dtor;
6144                     }
6145               do_firstprivate:
6146                 lower_private_allocate (var, new_var, allocator, allocate_ptr,
6147                                               ilist, ctx, false, NULL_TREE);
6148                 x = build_outer_var_ref (var, ctx);
6149                 if (is_simd)
6150                     {
6151                       if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
6152                           && gimple_omp_for_combined_into_p (ctx->stmt))
6153                         {
6154                           tree t = OMP_CLAUSE_LINEAR_STEP (c);
6155                           if (DECL_P (t))
6156                               t = build_outer_var_ref (t, ctx);
6157                           tree stept = TREE_TYPE (t);
6158                           tree ct = omp_find_clause (clauses,
6159                                                              OMP_CLAUSE__LOOPTEMP_);
6160                           gcc_assert (ct);
6161                           tree l = OMP_CLAUSE_DECL (ct);
6162                           tree n1 = fd->loop.n1;
6163                           tree step = fd->loop.step;
6164                           tree itype = TREE_TYPE (l);
6165                           if (POINTER_TYPE_P (itype))
6166                               itype = signed_type_for (itype);
6167                           l = fold_build2 (MINUS_EXPR, itype, l, n1);
6168                           if (TYPE_UNSIGNED (itype)
6169                                 && fd->loop.cond_code == GT_EXPR)
6170                               l = fold_build2 (TRUNC_DIV_EXPR, itype,
6171                                                    fold_build1 (NEGATE_EXPR, itype, l),
6172                                                    fold_build1 (NEGATE_EXPR,
6173                                                                   itype, step));
6174                           else
6175                               l = fold_build2 (TRUNC_DIV_EXPR, itype, l, step);
6176                           t = fold_build2 (MULT_EXPR, stept,
6177                                                fold_convert (stept, l), t);
6178 
6179                           if (OMP_CLAUSE_LINEAR_ARRAY (c))
6180                               {
6181                                 if (omp_privatize_by_reference (var))
6182                                   {
6183                                     gcc_assert (TREE_CODE (new_var) == MEM_REF);
6184                                     tree new_vard = TREE_OPERAND (new_var, 0);
6185                                     gcc_assert (DECL_P (new_vard));
6186                                     tree type = TREE_TYPE (TREE_TYPE (new_vard));
6187                                     nx = TYPE_SIZE_UNIT (type);
6188                                     if (TREE_CONSTANT (nx))
6189                                         {
6190                                           nx = create_tmp_var_raw (type,
6191                                                                          get_name (var));
6192                                           gimple_add_tmp_var (nx);
6193                                           TREE_ADDRESSABLE (nx) = 1;
6194                                           nx = build_fold_addr_expr_loc (clause_loc,
6195                                                                                  nx);
6196                                           nx = fold_convert_loc (clause_loc,
6197                                                                        TREE_TYPE (new_vard),
6198                                                                        nx);
6199                                           gimplify_assign (new_vard, nx, ilist);
6200                                         }
6201                                   }
6202 
6203                                 x = lang_hooks.decls.omp_clause_linear_ctor
6204                                                                       (c, new_var, x, t);
6205                                 gimplify_and_add (x, ilist);
6206                                 goto do_dtor;
6207                               }
6208 
6209                           if (POINTER_TYPE_P (TREE_TYPE (x)))
6210                               x = fold_build_pointer_plus (x, t);
6211                           else
6212                               x = fold_build2 (PLUS_EXPR, TREE_TYPE (x), x,
6213                                                    fold_convert (TREE_TYPE (x), t));
6214                         }
6215 
6216                       if ((OMP_CLAUSE_CODE (c) != OMP_CLAUSE_LINEAR
6217                            || TREE_ADDRESSABLE (new_var)
6218                            || omp_privatize_by_reference (var))
6219                           && lower_rec_simd_input_clauses (new_var, ctx, &sctx,
6220                                                                    ivar, lvar))
6221                         {
6222                           if (omp_privatize_by_reference (var))
6223                               {
6224                                 gcc_assert (TREE_CODE (new_var) == MEM_REF);
6225                                 tree new_vard = TREE_OPERAND (new_var, 0);
6226                                 gcc_assert (DECL_P (new_vard));
6227                                 SET_DECL_VALUE_EXPR (new_vard,
6228                                                          build_fold_addr_expr (lvar));
6229                                 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
6230                               }
6231                           if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR)
6232                               {
6233                                 tree iv = create_tmp_var (TREE_TYPE (new_var));
6234                                 x = lang_hooks.decls.omp_clause_copy_ctor (c, iv, x);
6235                                 gimplify_and_add (x, ilist);
6236                                 gimple_stmt_iterator gsi
6237                                   = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
6238                                 gassign *g
6239                                   = gimple_build_assign (unshare_expr (lvar), iv);
6240                                 gsi_insert_before_without_update (&gsi, g,
6241                                                                           GSI_SAME_STMT);
6242                                 tree t = OMP_CLAUSE_LINEAR_STEP (c);
6243                                 enum tree_code code = PLUS_EXPR;
6244                                 if (POINTER_TYPE_P (TREE_TYPE (new_var)))
6245                                   code = POINTER_PLUS_EXPR;
6246                                 g = gimple_build_assign (iv, code, iv, t);
6247                                 gsi_insert_before_without_update (&gsi, g,
6248                                                                           GSI_SAME_STMT);
6249                                 break;
6250                               }
6251                           x = lang_hooks.decls.omp_clause_copy_ctor
6252                                                             (c, unshare_expr (ivar), x);
6253                           gimplify_and_add (x, &llist[0]);
6254                           x = lang_hooks.decls.omp_clause_dtor (c, ivar);
6255                           if (x)
6256                               gimplify_and_add (x, &llist[1]);
6257                           break;
6258                         }
6259                       if (omp_privatize_by_reference (var))
6260                         {
6261                           gcc_assert (TREE_CODE (new_var) == MEM_REF);
6262                           tree new_vard = TREE_OPERAND (new_var, 0);
6263                           gcc_assert (DECL_P (new_vard));
6264                           tree type = TREE_TYPE (TREE_TYPE (new_vard));
6265                           nx = TYPE_SIZE_UNIT (type);
6266                           if (TREE_CONSTANT (nx))
6267                               {
6268                                 nx = create_tmp_var_raw (type, get_name (var));
6269                                 gimple_add_tmp_var (nx);
6270                                 TREE_ADDRESSABLE (nx) = 1;
6271                                 nx = build_fold_addr_expr_loc (clause_loc, nx);
6272                                 nx = fold_convert_loc (clause_loc,
6273                                                              TREE_TYPE (new_vard), nx);
6274                                 gimplify_assign (new_vard, nx, ilist);
6275                               }
6276                         }
6277                     }
6278                 x = lang_hooks.decls.omp_clause_copy_ctor
6279                                                             (c, unshare_expr (new_var), x);
6280                 gimplify_and_add (x, ilist);
6281                 goto do_dtor;
6282 
6283               case OMP_CLAUSE__LOOPTEMP_:
6284               case OMP_CLAUSE__REDUCTEMP_:
6285                 gcc_assert (is_taskreg_ctx (ctx));
6286                 x = build_outer_var_ref (var, ctx);
6287                 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
6288                 gimplify_and_add (x, ilist);
6289                 break;
6290 
6291               case OMP_CLAUSE_COPYIN:
6292                 by_ref = use_pointer_for_field (var, NULL);
6293                 x = build_receiver_ref (var, by_ref, ctx);
6294                 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, x);
6295                 append_to_statement_list (x, &copyin_seq);
6296                 copyin_by_ref |= by_ref;
6297                 break;
6298 
6299               case OMP_CLAUSE_REDUCTION:
6300               case OMP_CLAUSE_IN_REDUCTION:
6301                 /* OpenACC reductions are initialized using the
6302                      GOACC_REDUCTION internal function.  */
6303                 if (is_gimple_omp_oacc (ctx->stmt))
6304                     break;
6305                 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
6306                     {
6307                       tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
6308                       gimple *tseq;
6309                       tree ptype = TREE_TYPE (placeholder);
6310                       if (cond)
6311                         {
6312                           x = error_mark_node;
6313                           if (OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c)
6314                                 && !task_reduction_needs_orig_p)
6315                               x = var;
6316                           else if (OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c))
6317                               {
6318                                 tree pptype = build_pointer_type (ptype);
6319                                 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
6320                                   x = build4 (ARRAY_REF, ptr_type_node, tskred_avar,
6321                                                   size_int (task_reduction_cnt_full
6322                                                               + task_reduction_cntorig - 1),
6323                                                   NULL_TREE, NULL_TREE);
6324                                 else
6325                                   {
6326                                     unsigned int idx
6327                                         = *ctx->task_reduction_map->get (c);
6328                                     x = task_reduction_read (ilist, tskred_temp,
6329                                                                    pptype, 7 + 3 * idx);
6330                                   }
6331                                 x = fold_convert (pptype, x);
6332                                 x = build_simple_mem_ref (x);
6333                               }
6334                         }
6335                       else
6336                         {
6337                           lower_private_allocate (var, new_var, allocator,
6338                                                         allocate_ptr, ilist, ctx, false,
6339                                                         NULL_TREE);
6340                           x = build_outer_var_ref (var, ctx);
6341 
6342                           if (omp_privatize_by_reference (var)
6343                                 && !useless_type_conversion_p (ptype, TREE_TYPE (x)))
6344                               x = build_fold_addr_expr_loc (clause_loc, x);
6345                         }
6346                       SET_DECL_VALUE_EXPR (placeholder, x);
6347                       DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
6348                       tree new_vard = new_var;
6349                       if (omp_privatize_by_reference (var))
6350                         {
6351                           gcc_assert (TREE_CODE (new_var) == MEM_REF);
6352                           new_vard = TREE_OPERAND (new_var, 0);
6353                           gcc_assert (DECL_P (new_vard));
6354                         }
6355                       tree rvar = NULL_TREE, *rvarp = NULL, rvar2 = NULL_TREE;
6356                       if (is_simd
6357                           && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
6358                           && OMP_CLAUSE_REDUCTION_INSCAN (c))
6359                         rvarp = &rvar;
6360                       if (is_simd
6361                           && lower_rec_simd_input_clauses (new_var, ctx, &sctx,
6362                                                                    ivar, lvar, rvarp,
6363                                                                    &rvar2))
6364                         {
6365                           if (new_vard == new_var)
6366                               {
6367                                 gcc_assert (DECL_VALUE_EXPR (new_var) == lvar);
6368                                 SET_DECL_VALUE_EXPR (new_var, ivar);
6369                               }
6370                           else
6371                               {
6372                                 SET_DECL_VALUE_EXPR (new_vard,
6373                                                          build_fold_addr_expr (ivar));
6374                                 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
6375                               }
6376                           x = lang_hooks.decls.omp_clause_default_ctor
6377                                         (c, unshare_expr (ivar),
6378                                          build_outer_var_ref (var, ctx));
6379                           if (rvarp && ctx->for_simd_scan_phase)
6380                               {
6381                                 if (x)
6382                                   gimplify_and_add (x, &llist[0]);
6383                                 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
6384                                 if (x)
6385                                   gimplify_and_add (x, &llist[1]);
6386                                 break;
6387                               }
6388                           else if (rvarp)
6389                               {
6390                                 if (x)
6391                                   {
6392                                     gimplify_and_add (x, &llist[0]);
6393 
6394                                     tree ivar2 = unshare_expr (lvar);
6395                                     TREE_OPERAND (ivar2, 1) = sctx.idx;
6396                                     x = lang_hooks.decls.omp_clause_default_ctor
6397                                             (c, ivar2, build_outer_var_ref (var, ctx));
6398                                     gimplify_and_add (x, &llist[0]);
6399 
6400                                     if (rvar2)
6401                                         {
6402                                           x = lang_hooks.decls.omp_clause_default_ctor
6403                                                   (c, unshare_expr (rvar2),
6404                                                    build_outer_var_ref (var, ctx));
6405                                           gimplify_and_add (x, &llist[0]);
6406                                         }
6407 
6408                                     /* For types that need construction, add another
6409                                          private var which will be default constructed
6410                                          and optionally initialized with
6411                                          OMP_CLAUSE_REDUCTION_GIMPLE_INIT, as in the
6412                                          loop we want to assign this value instead of
6413                                          constructing and destructing it in each
6414                                          iteration.  */
6415                                     tree nv = create_tmp_var_raw (TREE_TYPE (ivar));
6416                                     gimple_add_tmp_var (nv);
6417                                     ctx->cb.decl_map->put (TREE_OPERAND (rvar2
6418                                                                                    ? rvar2
6419                                                                                    : ivar, 0),
6420                                                                  nv);
6421                                     x = lang_hooks.decls.omp_clause_default_ctor
6422                                             (c, nv, build_outer_var_ref (var, ctx));
6423                                     gimplify_and_add (x, ilist);
6424 
6425                                     if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
6426                                         {
6427                                           tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
6428                                           x = DECL_VALUE_EXPR (new_vard);
6429                                           tree vexpr = nv;
6430                                           if (new_vard != new_var)
6431                                             vexpr = build_fold_addr_expr (nv);
6432                                           SET_DECL_VALUE_EXPR (new_vard, vexpr);
6433                                           lower_omp (&tseq, ctx);
6434                                           SET_DECL_VALUE_EXPR (new_vard, x);
6435                                           gimple_seq_add_seq (ilist, tseq);
6436                                           OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
6437                                         }
6438 
6439                                     x = lang_hooks.decls.omp_clause_dtor (c, nv);
6440                                     if (x)
6441                                         gimplify_and_add (x, dlist);
6442                                   }
6443 
6444                                 tree ref = build_outer_var_ref (var, ctx);
6445                                 x = unshare_expr (ivar);
6446                                 x = lang_hooks.decls.omp_clause_assign_op (c, x,
6447                                                                                      ref);
6448                                 gimplify_and_add (x, &llist[0]);
6449 
6450                                 ref = build_outer_var_ref (var, ctx);
6451                                 x = lang_hooks.decls.omp_clause_assign_op (c, ref,
6452                                                                                      rvar);
6453                                 gimplify_and_add (x, &llist[3]);
6454 
6455                                 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
6456                                 if (new_vard == new_var)
6457                                   SET_DECL_VALUE_EXPR (new_var, lvar);
6458                                 else
6459                                   SET_DECL_VALUE_EXPR (new_vard,
6460                                                              build_fold_addr_expr (lvar));
6461 
6462                                 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
6463                                 if (x)
6464                                   gimplify_and_add (x, &llist[1]);
6465 
6466                                 tree ivar2 = unshare_expr (lvar);
6467                                 TREE_OPERAND (ivar2, 1) = sctx.idx;
6468                                 x = lang_hooks.decls.omp_clause_dtor (c, ivar2);
6469                                 if (x)
6470                                   gimplify_and_add (x, &llist[1]);
6471 
6472                                 if (rvar2)
6473                                   {
6474                                     x = lang_hooks.decls.omp_clause_dtor (c, rvar2);
6475                                     if (x)
6476                                         gimplify_and_add (x, &llist[1]);
6477                                   }
6478                                 break;
6479                               }
6480                           if (x)
6481                               gimplify_and_add (x, &llist[0]);
6482                           if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
6483                               {
6484                                 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
6485                                 lower_omp (&tseq, ctx);
6486                                 gimple_seq_add_seq (&llist[0], tseq);
6487                               }
6488                           OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
6489                           tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
6490                           lower_omp (&tseq, ctx);
6491                           gimple_seq_add_seq (&llist[1], tseq);
6492                           OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
6493                           DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
6494                           if (new_vard == new_var)
6495                               SET_DECL_VALUE_EXPR (new_var, lvar);
6496                           else
6497                               SET_DECL_VALUE_EXPR (new_vard,
6498                                                        build_fold_addr_expr (lvar));
6499                           x = lang_hooks.decls.omp_clause_dtor (c, ivar);
6500                           if (x)
6501                               gimplify_and_add (x, &llist[1]);
6502                           break;
6503                         }
6504                       /* If this is a reference to constant size reduction var
6505                          with placeholder, we haven't emitted the initializer
6506                          for it because it is undesirable if SIMD arrays are used.
6507                          But if they aren't used, we need to emit the deferred
6508                          initialization now.  */
6509                       else if (omp_privatize_by_reference (var) && is_simd)
6510                         handle_simd_reference (clause_loc, new_vard, ilist);
6511 
6512                       tree lab2 = NULL_TREE;
6513                       if (cond)
6514                         {
6515                           gimple *g;
6516                           if (!is_parallel_ctx (ctx))
6517                               {
6518                                 tree condv = create_tmp_var (boolean_type_node);
6519                                 tree m = build_simple_mem_ref (cond);
6520                                 g = gimple_build_assign (condv, m);
6521                                 gimple_seq_add_stmt (ilist, g);
6522                                 tree lab1
6523                                   = create_artificial_label (UNKNOWN_LOCATION);
6524                                 lab2 = create_artificial_label (UNKNOWN_LOCATION);
6525                                 g = gimple_build_cond (NE_EXPR, condv,
6526                                                              boolean_false_node,
6527                                                              lab2, lab1);
6528                                 gimple_seq_add_stmt (ilist, g);
6529                                 gimple_seq_add_stmt (ilist,
6530                                                          gimple_build_label (lab1));
6531                               }
6532                           g = gimple_build_assign (build_simple_mem_ref (cond),
6533                                                          boolean_true_node);
6534                           gimple_seq_add_stmt (ilist, g);
6535                         }
6536                       x = lang_hooks.decls.omp_clause_default_ctor
6537                                         (c, unshare_expr (new_var),
6538                                          cond ? NULL_TREE
6539                                          : build_outer_var_ref (var, ctx));
6540                       if (x)
6541                         gimplify_and_add (x, ilist);
6542 
6543                       if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
6544                           && OMP_CLAUSE_REDUCTION_INSCAN (c))
6545                         {
6546                           if (ctx->for_simd_scan_phase)
6547                               goto do_dtor;
6548                           if (x || (!is_simd
6549                                         && OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c)))
6550                               {
6551                                 tree nv = create_tmp_var_raw (TREE_TYPE (new_var));
6552                                 gimple_add_tmp_var (nv);
6553                                 ctx->cb.decl_map->put (new_vard, nv);
6554                                 x = lang_hooks.decls.omp_clause_default_ctor
6555                                         (c, nv, build_outer_var_ref (var, ctx));
6556                                 if (x)
6557                                   gimplify_and_add (x, ilist);
6558                                 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
6559                                   {
6560                                     tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
6561                                     tree vexpr = nv;
6562                                     if (new_vard != new_var)
6563                                         vexpr = build_fold_addr_expr (nv);
6564                                     SET_DECL_VALUE_EXPR (new_vard, vexpr);
6565                                     DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
6566                                     lower_omp (&tseq, ctx);
6567                                     SET_DECL_VALUE_EXPR (new_vard, NULL_TREE);
6568                                     DECL_HAS_VALUE_EXPR_P (new_vard) = 0;
6569                                     gimple_seq_add_seq (ilist, tseq);
6570                                   }
6571                                 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
6572                                 if (is_simd && ctx->scan_exclusive)
6573                                   {
6574                                     tree nv2
6575                                         = create_tmp_var_raw (TREE_TYPE (new_var));
6576                                     gimple_add_tmp_var (nv2);
6577                                     ctx->cb.decl_map->put (nv, nv2);
6578                                     x = lang_hooks.decls.omp_clause_default_ctor
6579                                             (c, nv2, build_outer_var_ref (var, ctx));
6580                                     gimplify_and_add (x, ilist);
6581                                     x = lang_hooks.decls.omp_clause_dtor (c, nv2);
6582                                     if (x)
6583                                         gimplify_and_add (x, dlist);
6584                                   }
6585                                 x = lang_hooks.decls.omp_clause_dtor (c, nv);
6586                                 if (x)
6587                                   gimplify_and_add (x, dlist);
6588                               }
6589                           else if (is_simd
6590                                      && ctx->scan_exclusive
6591                                      && TREE_ADDRESSABLE (TREE_TYPE (new_var)))
6592                               {
6593                                 tree nv2 = create_tmp_var_raw (TREE_TYPE (new_var));
6594                                 gimple_add_tmp_var (nv2);
6595                                 ctx->cb.decl_map->put (new_vard, nv2);
6596                                 x = lang_hooks.decls.omp_clause_dtor (c, nv2);
6597                                 if (x)
6598                                   gimplify_and_add (x, dlist);
6599                               }
6600                           DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
6601                           goto do_dtor;
6602                         }
6603 
6604                       if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
6605                         {
6606                           tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
6607                           if (c_kind == OMP_CLAUSE_IN_REDUCTION
6608                                 && is_omp_target (ctx->stmt))
6609                               {
6610                                 tree d = maybe_lookup_decl_in_outer_ctx (var, ctx);
6611                                 tree oldv = NULL_TREE;
6612                                 gcc_assert (d);
6613                                 if (DECL_HAS_VALUE_EXPR_P (d))
6614                                   oldv = DECL_VALUE_EXPR (d);
6615                                 SET_DECL_VALUE_EXPR (d, new_vard);
6616                                 DECL_HAS_VALUE_EXPR_P (d) = 1;
6617                                 lower_omp (&tseq, ctx);
6618                                 if (oldv)
6619                                   SET_DECL_VALUE_EXPR (d, oldv);
6620                                 else
6621                                   {
6622                                     SET_DECL_VALUE_EXPR (d, NULL_TREE);
6623                                     DECL_HAS_VALUE_EXPR_P (d) = 0;
6624                                   }
6625                               }
6626                           else
6627                               lower_omp (&tseq, ctx);
6628                           gimple_seq_add_seq (ilist, tseq);
6629                         }
6630                       OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
6631                       if (is_simd)
6632                         {
6633                           tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
6634                           lower_omp (&tseq, ctx);
6635                           gimple_seq_add_seq (dlist, tseq);
6636                           OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
6637                         }
6638                       DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
6639                       if (cond)
6640                         {
6641                           if (lab2)
6642                               gimple_seq_add_stmt (ilist, gimple_build_label (lab2));
6643                           break;
6644                         }
6645                       goto do_dtor;
6646                     }
6647                 else
6648                     {
6649                       x = omp_reduction_init (c, TREE_TYPE (new_var));
6650                       gcc_assert (TREE_CODE (TREE_TYPE (new_var)) != ARRAY_TYPE);
6651                       enum tree_code code = OMP_CLAUSE_REDUCTION_CODE (c);
6652 
6653                       if (cond)
6654                         {
6655                           gimple *g;
6656                           tree lab2 = NULL_TREE;
6657                           /* GOMP_taskgroup_reduction_register memsets the whole
6658                                array to zero.  If the initializer is zero, we don't
6659                                need to initialize it again, just mark it as ever
6660                                used unconditionally, i.e. cond = true.  */
6661                           if (initializer_zerop (x))
6662                               {
6663                                 g = gimple_build_assign (build_simple_mem_ref (cond),
6664                                                                boolean_true_node);
6665                                 gimple_seq_add_stmt (ilist, g);
6666                                 break;
6667                               }
6668 
6669                           /* Otherwise, emit
6670                                if (!cond) { cond = true; new_var = x; }  */
6671                           if (!is_parallel_ctx (ctx))
6672                               {
6673                                 tree condv = create_tmp_var (boolean_type_node);
6674                                 tree m = build_simple_mem_ref (cond);
6675                                 g = gimple_build_assign (condv, m);
6676                                 gimple_seq_add_stmt (ilist, g);
6677                                 tree lab1
6678                                   = create_artificial_label (UNKNOWN_LOCATION);
6679                                 lab2 = create_artificial_label (UNKNOWN_LOCATION);
6680                                 g = gimple_build_cond (NE_EXPR, condv,
6681                                                              boolean_false_node,
6682                                                              lab2, lab1);
6683                                 gimple_seq_add_stmt (ilist, g);
6684                                 gimple_seq_add_stmt (ilist,
6685                                                          gimple_build_label (lab1));
6686                               }
6687                           g = gimple_build_assign (build_simple_mem_ref (cond),
6688                                                          boolean_true_node);
6689                           gimple_seq_add_stmt (ilist, g);
6690                           gimplify_assign (new_var, x, ilist);
6691                           if (lab2)
6692                               gimple_seq_add_stmt (ilist, gimple_build_label (lab2));
6693                           break;
6694                         }
6695 
6696                       /* reduction(-:var) sums up the partial results, so it
6697                          acts identically to reduction(+:var).  */
6698                       if (code == MINUS_EXPR)
6699                         code = PLUS_EXPR;
6700 
6701                       bool is_truth_op
6702                         = (code == TRUTH_ANDIF_EXPR || code == TRUTH_ORIF_EXPR);
6703                       tree new_vard = new_var;
6704                       if (is_simd && omp_privatize_by_reference (var))
6705                         {
6706                           gcc_assert (TREE_CODE (new_var) == MEM_REF);
6707                           new_vard = TREE_OPERAND (new_var, 0);
6708                           gcc_assert (DECL_P (new_vard));
6709                         }
6710                       tree rvar = NULL_TREE, *rvarp = NULL, rvar2 = NULL_TREE;
6711                       if (is_simd
6712                           && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
6713                           && OMP_CLAUSE_REDUCTION_INSCAN (c))
6714                         rvarp = &rvar;
6715                       if (is_simd
6716                           && lower_rec_simd_input_clauses (new_var, ctx, &sctx,
6717                                                                    ivar, lvar, rvarp,
6718                                                                    &rvar2))
6719                         {
6720                           if (new_vard != new_var)
6721                               {
6722                                 SET_DECL_VALUE_EXPR (new_vard,
6723                                                          build_fold_addr_expr (lvar));
6724                                 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
6725                               }
6726 
6727                           tree ref = build_outer_var_ref (var, ctx);
6728 
6729                           if (rvarp)
6730                               {
6731                                 if (ctx->for_simd_scan_phase)
6732                                   break;
6733                                 gimplify_assign (ivar, ref, &llist[0]);
6734                                 ref = build_outer_var_ref (var, ctx);
6735                                 gimplify_assign (ref, rvar, &llist[3]);
6736                                 break;
6737                               }
6738 
6739                           gimplify_assign (unshare_expr (ivar), x, &llist[0]);
6740 
6741                           if (sctx.is_simt)
6742                               {
6743                                 if (!simt_lane)
6744                                   simt_lane = create_tmp_var (unsigned_type_node);
6745                                 x = build_call_expr_internal_loc
6746                                   (UNKNOWN_LOCATION, IFN_GOMP_SIMT_XCHG_BFLY,
6747                                    TREE_TYPE (ivar), 2, ivar, simt_lane);
6748                                 /* Make sure x is evaluated unconditionally.  */
6749                                 tree bfly_var = create_tmp_var (TREE_TYPE (ivar));
6750                                 gimplify_assign (bfly_var, x, &llist[2]);
6751                                 x = build2 (code, TREE_TYPE (ivar), ivar, bfly_var);
6752                                 gimplify_assign (ivar, x, &llist[2]);
6753                               }
6754                           tree ivar2 = ivar;
6755                           tree ref2 = ref;
6756                           if (is_truth_op)
6757                               {
6758                                 tree zero = build_zero_cst (TREE_TYPE (ivar));
6759                                 ivar2 = fold_build2_loc (clause_loc, NE_EXPR,
6760                                                                boolean_type_node, ivar,
6761                                                                zero);
6762                                 ref2 = fold_build2_loc (clause_loc, NE_EXPR,
6763                                                               boolean_type_node, ref,
6764                                                               zero);
6765                               }
6766                           x = build2 (code, TREE_TYPE (ref), ref2, ivar2);
6767                           if (is_truth_op)
6768                               x = fold_convert (TREE_TYPE (ref), x);
6769                           ref = build_outer_var_ref (var, ctx);
6770                           gimplify_assign (ref, x, &llist[1]);
6771 
6772                         }
6773                       else
6774                         {
6775                           lower_private_allocate (var, new_var, allocator,
6776                                                         allocate_ptr, ilist, ctx,
6777                                                         false, NULL_TREE);
6778                           if (omp_privatize_by_reference (var) && is_simd)
6779                               handle_simd_reference (clause_loc, new_vard, ilist);
6780                           if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
6781                                 && OMP_CLAUSE_REDUCTION_INSCAN (c))
6782                               break;
6783                           gimplify_assign (new_var, x, ilist);
6784                           if (is_simd)
6785                               {
6786                                 tree ref = build_outer_var_ref (var, ctx);
6787                                 tree new_var2 = new_var;
6788                                 tree ref2 = ref;
6789                                 if (is_truth_op)
6790                                   {
6791                                     tree zero = build_zero_cst (TREE_TYPE (new_var));
6792                                     new_var2
6793                                         = fold_build2_loc (clause_loc, NE_EXPR,
6794                                                                boolean_type_node, new_var,
6795                                                                zero);
6796                                     ref2 = fold_build2_loc (clause_loc, NE_EXPR,
6797                                                                   boolean_type_node, ref,
6798                                                                   zero);
6799                                   }
6800                                 x = build2 (code, TREE_TYPE (ref2), ref2, new_var2);
6801                                 if (is_truth_op)
6802                                   x = fold_convert (TREE_TYPE (new_var), x);
6803                                 ref = build_outer_var_ref (var, ctx);
6804                                 gimplify_assign (ref, x, dlist);
6805                               }
6806                           if (allocator)
6807                               goto do_dtor;
6808                         }
6809                     }
6810                 break;
6811 
6812               default:
6813                 gcc_unreachable ();
6814               }
6815           }
6816     }
6817   if (tskred_avar)
6818     {
6819       tree clobber = build_clobber (TREE_TYPE (tskred_avar));
6820       gimple_seq_add_stmt (ilist, gimple_build_assign (tskred_avar, clobber));
6821     }
6822 
6823   if (known_eq (sctx.max_vf, 1U))
6824     {
6825       sctx.is_simt = false;
6826       if (ctx->lastprivate_conditional_map)
6827           {
6828             if (gimple_omp_for_combined_into_p (ctx->stmt))
6829               {
6830                 /* Signal to lower_omp_1 that it should use parent context.  */
6831                 ctx->combined_into_simd_safelen1 = true;
6832                 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
6833                     if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
6834                         && OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c))
6835                       {
6836                         tree o = lookup_decl (OMP_CLAUSE_DECL (c), ctx);
6837                         omp_context *outer = ctx->outer;
6838                         if (gimple_code (outer->stmt) == GIMPLE_OMP_SCAN)
6839                           outer = outer->outer;
6840                         tree *v = ctx->lastprivate_conditional_map->get (o);
6841                         tree po = lookup_decl (OMP_CLAUSE_DECL (c), outer);
6842                         tree *pv = outer->lastprivate_conditional_map->get (po);
6843                         *v = *pv;
6844                       }
6845               }
6846             else
6847               {
6848                 /* When not vectorized, treat lastprivate(conditional:) like
6849                      normal lastprivate, as there will be just one simd lane
6850                      writing the privatized variable.  */
6851                 delete ctx->lastprivate_conditional_map;
6852                 ctx->lastprivate_conditional_map = NULL;
6853               }
6854           }
6855     }
6856 
6857   if (nonconst_simd_if)
6858     {
6859       if (sctx.lane == NULL_TREE)
6860           {
6861             sctx.idx = create_tmp_var (unsigned_type_node);
6862             sctx.lane = create_tmp_var (unsigned_type_node);
6863           }
6864       /* FIXME: For now.  */
6865       sctx.is_simt = false;
6866     }
6867 
6868   if (sctx.lane || sctx.is_simt)
6869     {
6870       uid = create_tmp_var (ptr_type_node, "simduid");
6871       /* Don't want uninit warnings on simduid, it is always uninitialized,
6872            but we use it not for the value, but for the DECL_UID only.  */
6873       suppress_warning (uid, OPT_Wuninitialized);
6874       c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__SIMDUID_);
6875       OMP_CLAUSE__SIMDUID__DECL (c) = uid;
6876       OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
6877       gimple_omp_for_set_clauses (ctx->stmt, c);
6878     }
6879   /* Emit calls denoting privatized variables and initializing a pointer to
6880      structure that holds private variables as fields after ompdevlow pass.  */
6881   if (sctx.is_simt)
6882     {
6883       sctx.simt_eargs[0] = uid;
6884       gimple *g
6885           = gimple_build_call_internal_vec (IFN_GOMP_SIMT_ENTER, sctx.simt_eargs);
6886       gimple_call_set_lhs (g, uid);
6887       gimple_seq_add_stmt (ilist, g);
6888       sctx.simt_eargs.release ();
6889 
6890       simtrec = create_tmp_var (ptr_type_node, ".omp_simt");
6891       g = gimple_build_call_internal (IFN_GOMP_SIMT_ENTER_ALLOC, 1, uid);
6892       gimple_call_set_lhs (g, simtrec);
6893       gimple_seq_add_stmt (ilist, g);
6894     }
6895   if (sctx.lane)
6896     {
6897       gimple *g = gimple_build_call_internal (IFN_GOMP_SIMD_LANE,
6898                                                         2 + (nonconst_simd_if != NULL),
6899                                                         uid, integer_zero_node,
6900                                                         nonconst_simd_if);
6901       gimple_call_set_lhs (g, sctx.lane);
6902       gimple_stmt_iterator gsi = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
6903       gsi_insert_before_without_update (&gsi, g, GSI_SAME_STMT);
6904       g = gimple_build_assign (sctx.lane, INTEGER_CST,
6905                                      build_int_cst (unsigned_type_node, 0));
6906       gimple_seq_add_stmt (ilist, g);
6907       if (sctx.lastlane)
6908           {
6909             g = gimple_build_call_internal (IFN_GOMP_SIMD_LAST_LANE,
6910                                                     2, uid, sctx.lane);
6911             gimple_call_set_lhs (g, sctx.lastlane);
6912             gimple_seq_add_stmt (dlist, g);
6913             gimple_seq_add_seq (dlist, llist[3]);
6914           }
6915       /* Emit reductions across SIMT lanes in log_2(simt_vf) steps.  */
6916       if (llist[2])
6917           {
6918             tree simt_vf = create_tmp_var (unsigned_type_node);
6919             g = gimple_build_call_internal (IFN_GOMP_SIMT_VF, 0);
6920             gimple_call_set_lhs (g, simt_vf);
6921             gimple_seq_add_stmt (dlist, g);
6922 
6923             tree t = build_int_cst (unsigned_type_node, 1);
6924             g = gimple_build_assign (simt_lane, INTEGER_CST, t);
6925             gimple_seq_add_stmt (dlist, g);
6926 
6927             t = build_int_cst (unsigned_type_node, 0);
6928             g = gimple_build_assign (sctx.idx, INTEGER_CST, t);
6929             gimple_seq_add_stmt (dlist, g);
6930 
6931             tree body = create_artificial_label (UNKNOWN_LOCATION);
6932             tree header = create_artificial_label (UNKNOWN_LOCATION);
6933             tree end = create_artificial_label (UNKNOWN_LOCATION);
6934             gimple_seq_add_stmt (dlist, gimple_build_goto (header));
6935             gimple_seq_add_stmt (dlist, gimple_build_label (body));
6936 
6937             gimple_seq_add_seq (dlist, llist[2]);
6938 
6939             g = gimple_build_assign (simt_lane, LSHIFT_EXPR, simt_lane, integer_one_node);
6940             gimple_seq_add_stmt (dlist, g);
6941 
6942             gimple_seq_add_stmt (dlist, gimple_build_label (header));
6943             g = gimple_build_cond (LT_EXPR, simt_lane, simt_vf, body, end);
6944             gimple_seq_add_stmt (dlist, g);
6945 
6946             gimple_seq_add_stmt (dlist, gimple_build_label (end));
6947           }
6948       for (int i = 0; i < 2; i++)
6949           if (llist[i])
6950             {
6951               tree vf = create_tmp_var (unsigned_type_node);
6952               g = gimple_build_call_internal (IFN_GOMP_SIMD_VF, 1, uid);
6953               gimple_call_set_lhs (g, vf);
6954               gimple_seq *seq = i == 0 ? ilist : dlist;
6955               gimple_seq_add_stmt (seq, g);
6956               tree t = build_int_cst (unsigned_type_node, 0);
6957               g = gimple_build_assign (sctx.idx, INTEGER_CST, t);
6958               gimple_seq_add_stmt (seq, g);
6959               tree body = create_artificial_label (UNKNOWN_LOCATION);
6960               tree header = create_artificial_label (UNKNOWN_LOCATION);
6961               tree end = create_artificial_label (UNKNOWN_LOCATION);
6962               gimple_seq_add_stmt (seq, gimple_build_goto (header));
6963               gimple_seq_add_stmt (seq, gimple_build_label (body));
6964               gimple_seq_add_seq (seq, llist[i]);
6965               t = build_int_cst (unsigned_type_node, 1);
6966               g = gimple_build_assign (sctx.idx, PLUS_EXPR, sctx.idx, t);
6967               gimple_seq_add_stmt (seq, g);
6968               gimple_seq_add_stmt (seq, gimple_build_label (header));
6969               g = gimple_build_cond (LT_EXPR, sctx.idx, vf, body, end);
6970               gimple_seq_add_stmt (seq, g);
6971               gimple_seq_add_stmt (seq, gimple_build_label (end));
6972             }
6973     }
6974   if (sctx.is_simt)
6975     {
6976       gimple_seq_add_seq (dlist, sctx.simt_dlist);
6977       gimple *g
6978           = gimple_build_call_internal (IFN_GOMP_SIMT_EXIT, 1, simtrec);
6979       gimple_seq_add_stmt (dlist, g);
6980     }
6981 
6982   /* The copyin sequence is not to be executed by the main thread, since
6983      that would result in self-copies.  Perhaps not visible to scalars,
6984      but it certainly is to C++ operator=.  */
6985   if (copyin_seq)
6986     {
6987       x = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM),
6988                                  0);
6989       x = build2 (NE_EXPR, boolean_type_node, x,
6990                       build_int_cst (TREE_TYPE (x), 0));
6991       x = build3 (COND_EXPR, void_type_node, x, copyin_seq, NULL);
6992       gimplify_and_add (x, ilist);
6993     }
6994 
6995   /* If any copyin variable is passed by reference, we must ensure the
6996      master thread doesn't modify it before it is copied over in all
6997      threads.  Similarly for variables in both firstprivate and
6998      lastprivate clauses we need to ensure the lastprivate copying
6999      happens after firstprivate copying in all threads.  And similarly
7000      for UDRs if initializer expression refers to omp_orig.  */
7001   if (copyin_by_ref || lastprivate_firstprivate
7002       || (reduction_omp_orig_ref
7003             && !ctx->scan_inclusive
7004             && !ctx->scan_exclusive))
7005     {
7006       /* Don't add any barrier for #pragma omp simd or
7007            #pragma omp distribute.  */
7008       if (!is_task_ctx (ctx)
7009             && (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
7010                 || gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_FOR))
7011           gimple_seq_add_stmt (ilist, omp_build_barrier (NULL_TREE));
7012     }
7013 
7014   /* If max_vf is non-zero, then we can use only a vectorization factor
7015      up to the max_vf we chose.  So stick it into the safelen clause.  */
7016   if (maybe_ne (sctx.max_vf, 0U))
7017     {
7018       tree c = omp_find_clause (gimple_omp_for_clauses (ctx->stmt),
7019                                         OMP_CLAUSE_SAFELEN);
7020       poly_uint64 safe_len;
7021       if (c == NULL_TREE
7022             || (poly_int_tree_p (OMP_CLAUSE_SAFELEN_EXPR (c), &safe_len)
7023                 && maybe_gt (safe_len, sctx.max_vf)))
7024           {
7025             c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_SAFELEN);
7026             OMP_CLAUSE_SAFELEN_EXPR (c) = build_int_cst (integer_type_node,
7027                                                                    sctx.max_vf);
7028             OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
7029             gimple_omp_for_set_clauses (ctx->stmt, c);
7030           }
7031     }
7032 }
7033 
7034 /* Create temporary variables for lastprivate(conditional:) implementation
7035    in context CTX with CLAUSES.  */
7036 
7037 static void
lower_lastprivate_conditional_clauses(tree * clauses,omp_context * ctx)7038 lower_lastprivate_conditional_clauses (tree *clauses, omp_context *ctx)
7039 {
7040   tree iter_type = NULL_TREE;
7041   tree cond_ptr = NULL_TREE;
7042   tree iter_var = NULL_TREE;
7043   bool is_simd = (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
7044                       && gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_SIMD);
7045   tree next = *clauses;
7046   for (tree c = *clauses; c; c = OMP_CLAUSE_CHAIN (c))
7047     if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
7048           && OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c))
7049       {
7050           if (is_simd)
7051             {
7052               tree cc = omp_find_clause (next, OMP_CLAUSE__CONDTEMP_);
7053               gcc_assert (cc);
7054               if (iter_type == NULL_TREE)
7055                 {
7056                     iter_type = TREE_TYPE (OMP_CLAUSE_DECL (cc));
7057                     iter_var = create_tmp_var_raw (iter_type);
7058                     DECL_CONTEXT (iter_var) = current_function_decl;
7059                     DECL_SEEN_IN_BIND_EXPR_P (iter_var) = 1;
7060                     DECL_CHAIN (iter_var) = ctx->block_vars;
7061                     ctx->block_vars = iter_var;
7062                     tree c3
7063                       = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__CONDTEMP_);
7064                     OMP_CLAUSE__CONDTEMP__ITER (c3) = 1;
7065                     OMP_CLAUSE_DECL (c3) = iter_var;
7066                     OMP_CLAUSE_CHAIN (c3) = *clauses;
7067                     *clauses = c3;
7068                     ctx->lastprivate_conditional_map = new hash_map<tree, tree>;
7069                 }
7070               next = OMP_CLAUSE_CHAIN (cc);
7071               tree o = lookup_decl (OMP_CLAUSE_DECL (c), ctx);
7072               tree v = lookup_decl (OMP_CLAUSE_DECL (cc), ctx);
7073               ctx->lastprivate_conditional_map->put (o, v);
7074               continue;
7075             }
7076           if (iter_type == NULL)
7077             {
7078               if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR)
7079                 {
7080                     struct omp_for_data fd;
7081                     omp_extract_for_data (as_a <gomp_for *> (ctx->stmt), &fd,
7082                                               NULL);
7083                     iter_type = unsigned_type_for (fd.iter_type);
7084                 }
7085               else if (gimple_code (ctx->stmt) == GIMPLE_OMP_SECTIONS)
7086                 iter_type = unsigned_type_node;
7087               tree c2 = omp_find_clause (*clauses, OMP_CLAUSE__CONDTEMP_);
7088               if (c2)
7089                 {
7090                     cond_ptr
7091                       = lookup_decl_in_outer_ctx (OMP_CLAUSE_DECL (c2), ctx);
7092                     OMP_CLAUSE_DECL (c2) = cond_ptr;
7093                 }
7094               else
7095                 {
7096                     cond_ptr = create_tmp_var_raw (build_pointer_type (iter_type));
7097                     DECL_CONTEXT (cond_ptr) = current_function_decl;
7098                     DECL_SEEN_IN_BIND_EXPR_P (cond_ptr) = 1;
7099                     DECL_CHAIN (cond_ptr) = ctx->block_vars;
7100                     ctx->block_vars = cond_ptr;
7101                     c2 = build_omp_clause (UNKNOWN_LOCATION,
7102                                                OMP_CLAUSE__CONDTEMP_);
7103                     OMP_CLAUSE_DECL (c2) = cond_ptr;
7104                     OMP_CLAUSE_CHAIN (c2) = *clauses;
7105                     *clauses = c2;
7106                 }
7107               iter_var = create_tmp_var_raw (iter_type);
7108               DECL_CONTEXT (iter_var) = current_function_decl;
7109               DECL_SEEN_IN_BIND_EXPR_P (iter_var) = 1;
7110               DECL_CHAIN (iter_var) = ctx->block_vars;
7111               ctx->block_vars = iter_var;
7112               tree c3
7113                 = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__CONDTEMP_);
7114               OMP_CLAUSE__CONDTEMP__ITER (c3) = 1;
7115               OMP_CLAUSE_DECL (c3) = iter_var;
7116               OMP_CLAUSE_CHAIN (c3) = OMP_CLAUSE_CHAIN (c2);
7117               OMP_CLAUSE_CHAIN (c2) = c3;
7118               ctx->lastprivate_conditional_map = new hash_map<tree, tree>;
7119             }
7120           tree v = create_tmp_var_raw (iter_type);
7121           DECL_CONTEXT (v) = current_function_decl;
7122           DECL_SEEN_IN_BIND_EXPR_P (v) = 1;
7123           DECL_CHAIN (v) = ctx->block_vars;
7124           ctx->block_vars = v;
7125           tree o = lookup_decl (OMP_CLAUSE_DECL (c), ctx);
7126           ctx->lastprivate_conditional_map->put (o, v);
7127       }
7128 }
7129 
7130 
7131 /* Generate code to implement the LASTPRIVATE clauses.  This is used for
7132    both parallel and workshare constructs.  PREDICATE may be NULL if it's
7133    always true.  BODY_P is the sequence to insert early initialization
7134    if needed, STMT_LIST is where the non-conditional lastprivate handling
7135    goes into and CSTMT_LIST is a sequence that needs to be run in a critical
7136    section.  */
7137 
7138 static void
lower_lastprivate_clauses(tree clauses,tree predicate,gimple_seq * body_p,gimple_seq * stmt_list,gimple_seq * cstmt_list,omp_context * ctx)7139 lower_lastprivate_clauses (tree clauses, tree predicate, gimple_seq *body_p,
7140                                  gimple_seq *stmt_list, gimple_seq *cstmt_list,
7141                                  omp_context *ctx)
7142 {
7143   tree x, c, label = NULL, orig_clauses = clauses;
7144   bool par_clauses = false;
7145   tree simduid = NULL, lastlane = NULL, simtcond = NULL, simtlast = NULL;
7146   unsigned HOST_WIDE_INT conditional_off = 0;
7147   gimple_seq post_stmt_list = NULL;
7148 
7149   /* Early exit if there are no lastprivate or linear clauses.  */
7150   for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
7151     if (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LASTPRIVATE
7152           || (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LINEAR
7153               && !OMP_CLAUSE_LINEAR_NO_COPYOUT (clauses)))
7154       break;
7155   if (clauses == NULL)
7156     {
7157       /* If this was a workshare clause, see if it had been combined
7158            with its parallel.  In that case, look for the clauses on the
7159            parallel statement itself.  */
7160       if (is_parallel_ctx (ctx))
7161           return;
7162 
7163       ctx = ctx->outer;
7164       if (ctx == NULL || !is_parallel_ctx (ctx))
7165           return;
7166 
7167       clauses = omp_find_clause (gimple_omp_parallel_clauses (ctx->stmt),
7168                                          OMP_CLAUSE_LASTPRIVATE);
7169       if (clauses == NULL)
7170           return;
7171       par_clauses = true;
7172     }
7173 
7174   bool maybe_simt = false;
7175   if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
7176       && gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_SIMD)
7177     {
7178       maybe_simt = omp_find_clause (orig_clauses, OMP_CLAUSE__SIMT_);
7179       simduid = omp_find_clause (orig_clauses, OMP_CLAUSE__SIMDUID_);
7180       if (simduid)
7181           simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
7182     }
7183 
7184   if (predicate)
7185     {
7186       gcond *stmt;
7187       tree label_true, arm1, arm2;
7188       enum tree_code pred_code = TREE_CODE (predicate);
7189 
7190       label = create_artificial_label (UNKNOWN_LOCATION);
7191       label_true = create_artificial_label (UNKNOWN_LOCATION);
7192       if (TREE_CODE_CLASS (pred_code) == tcc_comparison)
7193           {
7194             arm1 = TREE_OPERAND (predicate, 0);
7195             arm2 = TREE_OPERAND (predicate, 1);
7196             gimplify_expr (&arm1, stmt_list, NULL, is_gimple_val, fb_rvalue);
7197             gimplify_expr (&arm2, stmt_list, NULL, is_gimple_val, fb_rvalue);
7198           }
7199       else
7200           {
7201             arm1 = predicate;
7202             gimplify_expr (&arm1, stmt_list, NULL, is_gimple_val, fb_rvalue);
7203             arm2 = boolean_false_node;
7204             pred_code = NE_EXPR;
7205           }
7206       if (maybe_simt)
7207           {
7208             c = build2 (pred_code, boolean_type_node, arm1, arm2);
7209             c = fold_convert (integer_type_node, c);
7210             simtcond = create_tmp_var (integer_type_node);
7211             gimplify_assign (simtcond, c, stmt_list);
7212             gcall *g = gimple_build_call_internal (IFN_GOMP_SIMT_VOTE_ANY,
7213                                                              1, simtcond);
7214             c = create_tmp_var (integer_type_node);
7215             gimple_call_set_lhs (g, c);
7216             gimple_seq_add_stmt (stmt_list, g);
7217             stmt = gimple_build_cond (NE_EXPR, c, integer_zero_node,
7218                                             label_true, label);
7219           }
7220       else
7221           stmt = gimple_build_cond (pred_code, arm1, arm2, label_true, label);
7222       gimple_seq_add_stmt (stmt_list, stmt);
7223       gimple_seq_add_stmt (stmt_list, gimple_build_label (label_true));
7224     }
7225 
7226   tree cond_ptr = NULL_TREE;
7227   for (c = clauses; c ;)
7228     {
7229       tree var, new_var;
7230       location_t clause_loc = OMP_CLAUSE_LOCATION (c);
7231       gimple_seq *this_stmt_list = stmt_list;
7232       tree lab2 = NULL_TREE;
7233 
7234       if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
7235             && OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c)
7236             && ctx->lastprivate_conditional_map
7237             && !ctx->combined_into_simd_safelen1)
7238           {
7239             gcc_assert (body_p);
7240             if (simduid)
7241               goto next;
7242             if (cond_ptr == NULL_TREE)
7243               {
7244                 cond_ptr = omp_find_clause (orig_clauses, OMP_CLAUSE__CONDTEMP_);
7245                 cond_ptr = OMP_CLAUSE_DECL (cond_ptr);
7246               }
7247             tree type = TREE_TYPE (TREE_TYPE (cond_ptr));
7248             tree o = lookup_decl (OMP_CLAUSE_DECL (c), ctx);
7249             tree v = *ctx->lastprivate_conditional_map->get (o);
7250             gimplify_assign (v, build_zero_cst (type), body_p);
7251             this_stmt_list = cstmt_list;
7252             tree mem;
7253             if (POINTER_TYPE_P (TREE_TYPE (cond_ptr)))
7254               {
7255                 mem = build2 (MEM_REF, type, cond_ptr,
7256                                   build_int_cst (TREE_TYPE (cond_ptr),
7257                                                      conditional_off));
7258                 conditional_off += tree_to_uhwi (TYPE_SIZE_UNIT (type));
7259               }
7260             else
7261               mem = build4 (ARRAY_REF, type, cond_ptr,
7262                                 size_int (conditional_off++), NULL_TREE, NULL_TREE);
7263             tree mem2 = copy_node (mem);
7264             gimple_seq seq = NULL;
7265             mem = force_gimple_operand (mem, &seq, true, NULL_TREE);
7266             gimple_seq_add_seq (this_stmt_list, seq);
7267             tree lab1 = create_artificial_label (UNKNOWN_LOCATION);
7268             lab2 = create_artificial_label (UNKNOWN_LOCATION);
7269             gimple *g = gimple_build_cond (GT_EXPR, v, mem, lab1, lab2);
7270             gimple_seq_add_stmt (this_stmt_list, g);
7271             gimple_seq_add_stmt (this_stmt_list, gimple_build_label (lab1));
7272             gimplify_assign (mem2, v, this_stmt_list);
7273           }
7274       else if (predicate
7275                  && ctx->combined_into_simd_safelen1
7276                  && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
7277                  && OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c)
7278                  && ctx->lastprivate_conditional_map)
7279           this_stmt_list = &post_stmt_list;
7280 
7281       if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
7282             || (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
7283                 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c)))
7284           {
7285             var = OMP_CLAUSE_DECL (c);
7286             if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
7287                 && OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c)
7288                 && is_taskloop_ctx (ctx))
7289               {
7290                 gcc_checking_assert (ctx->outer && is_task_ctx (ctx->outer));
7291                 new_var = lookup_decl (var, ctx->outer);
7292               }
7293             else
7294               {
7295                 new_var = lookup_decl (var, ctx);
7296                 /* Avoid uninitialized warnings for lastprivate and
7297                      for linear iterators.  */
7298                 if (predicate
7299                       && (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
7300                           || OMP_CLAUSE_LINEAR_NO_COPYIN (c)))
7301                     suppress_warning (new_var, OPT_Wuninitialized);
7302               }
7303 
7304             if (!maybe_simt && simduid && DECL_HAS_VALUE_EXPR_P (new_var))
7305               {
7306                 tree val = DECL_VALUE_EXPR (new_var);
7307                 if (TREE_CODE (val) == ARRAY_REF
7308                       && VAR_P (TREE_OPERAND (val, 0))
7309                       && lookup_attribute ("omp simd array",
7310                                                DECL_ATTRIBUTES (TREE_OPERAND (val,
7311                                                                                       0))))
7312                     {
7313                       if (lastlane == NULL)
7314                         {
7315                           lastlane = create_tmp_var (unsigned_type_node);
7316                           gcall *g
7317                               = gimple_build_call_internal (IFN_GOMP_SIMD_LAST_LANE,
7318                                                                   2, simduid,
7319                                                                   TREE_OPERAND (val, 1));
7320                           gimple_call_set_lhs (g, lastlane);
7321                           gimple_seq_add_stmt (this_stmt_list, g);
7322                         }
7323                       new_var = build4 (ARRAY_REF, TREE_TYPE (val),
7324                                             TREE_OPERAND (val, 0), lastlane,
7325                                             NULL_TREE, NULL_TREE);
7326                       TREE_THIS_NOTRAP (new_var) = 1;
7327                     }
7328               }
7329             else if (maybe_simt)
7330               {
7331                 tree val = (DECL_HAS_VALUE_EXPR_P (new_var)
7332                                 ? DECL_VALUE_EXPR (new_var)
7333                                 : new_var);
7334                 if (simtlast == NULL)
7335                     {
7336                       simtlast = create_tmp_var (unsigned_type_node);
7337                       gcall *g = gimple_build_call_internal
7338                         (IFN_GOMP_SIMT_LAST_LANE, 1, simtcond);
7339                       gimple_call_set_lhs (g, simtlast);
7340                       gimple_seq_add_stmt (this_stmt_list, g);
7341                     }
7342                 x = build_call_expr_internal_loc
7343                     (UNKNOWN_LOCATION, IFN_GOMP_SIMT_XCHG_IDX,
7344                      TREE_TYPE (val), 2, val, simtlast);
7345                 new_var = unshare_expr (new_var);
7346                 gimplify_assign (new_var, x, this_stmt_list);
7347                 new_var = unshare_expr (new_var);
7348               }
7349 
7350             if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
7351                 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
7352               {
7353                 lower_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
7354                 gimple_seq_add_seq (this_stmt_list,
7355                                           OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c));
7356                 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c) = NULL;
7357               }
7358             else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
7359                        && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
7360               {
7361                 lower_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
7362                 gimple_seq_add_seq (this_stmt_list,
7363                                           OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c));
7364                 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c) = NULL;
7365               }
7366 
7367             x = NULL_TREE;
7368             if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
7369                 && OMP_CLAUSE_LASTPRIVATE_LOOP_IV (c)
7370                 && is_taskloop_ctx (ctx))
7371               {
7372                 tree ovar = maybe_lookup_decl_in_outer_ctx (var,
7373                                                                         ctx->outer->outer);
7374                 if (is_global_var (ovar))
7375                     x = ovar;
7376               }
7377             if (!x)
7378               x = build_outer_var_ref (var, ctx, OMP_CLAUSE_LASTPRIVATE);
7379             if (omp_privatize_by_reference (var))
7380               new_var = build_simple_mem_ref_loc (clause_loc, new_var);
7381             x = lang_hooks.decls.omp_clause_assign_op (c, x, new_var);
7382             gimplify_and_add (x, this_stmt_list);
7383 
7384             if (lab2)
7385               gimple_seq_add_stmt (this_stmt_list, gimple_build_label (lab2));
7386           }
7387 
7388      next:
7389       c = OMP_CLAUSE_CHAIN (c);
7390       if (c == NULL && !par_clauses)
7391           {
7392             /* If this was a workshare clause, see if it had been combined
7393                with its parallel.  In that case, continue looking for the
7394                clauses also on the parallel statement itself.  */
7395             if (is_parallel_ctx (ctx))
7396               break;
7397 
7398             ctx = ctx->outer;
7399             if (ctx == NULL || !is_parallel_ctx (ctx))
7400               break;
7401 
7402             c = omp_find_clause (gimple_omp_parallel_clauses (ctx->stmt),
7403                                      OMP_CLAUSE_LASTPRIVATE);
7404             par_clauses = true;
7405           }
7406     }
7407 
7408   if (label)
7409     gimple_seq_add_stmt (stmt_list, gimple_build_label (label));
7410   gimple_seq_add_seq (stmt_list, post_stmt_list);
7411 }
7412 
7413 /* Lower the OpenACC reductions of CLAUSES for compute axis LEVEL
7414    (which might be a placeholder).  INNER is true if this is an inner
7415    axis of a multi-axis loop.  FORK and JOIN are (optional) fork and
7416    join markers.  Generate the before-loop forking sequence in
7417    FORK_SEQ and the after-loop joining sequence to JOIN_SEQ.  The
7418    general form of these sequences is
7419 
7420      GOACC_REDUCTION_SETUP
7421      GOACC_FORK
7422      GOACC_REDUCTION_INIT
7423      ...
7424      GOACC_REDUCTION_FINI
7425      GOACC_JOIN
7426      GOACC_REDUCTION_TEARDOWN.  */
7427 
7428 static void
lower_oacc_reductions(location_t loc,tree clauses,tree level,bool inner,gcall * fork,gcall * private_marker,gcall * join,gimple_seq * fork_seq,gimple_seq * join_seq,omp_context * ctx)7429 lower_oacc_reductions (location_t loc, tree clauses, tree level, bool inner,
7430                            gcall *fork, gcall *private_marker, gcall *join,
7431                            gimple_seq *fork_seq, gimple_seq *join_seq,
7432                            omp_context *ctx)
7433 {
7434   gimple_seq before_fork = NULL;
7435   gimple_seq after_fork = NULL;
7436   gimple_seq before_join = NULL;
7437   gimple_seq after_join = NULL;
7438   tree init_code = NULL_TREE, fini_code = NULL_TREE,
7439     setup_code = NULL_TREE, teardown_code = NULL_TREE;
7440   unsigned offset = 0;
7441 
7442   for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
7443     if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
7444       {
7445           /* No 'reduction' clauses on OpenACC 'kernels'.  */
7446           gcc_checking_assert (!is_oacc_kernels (ctx));
7447           /* Likewise, on OpenACC 'kernels' decomposed parts.  */
7448           gcc_checking_assert (!is_oacc_kernels_decomposed_part (ctx));
7449 
7450           tree orig = OMP_CLAUSE_DECL (c);
7451           tree var = maybe_lookup_decl (orig, ctx);
7452           tree ref_to_res = NULL_TREE;
7453           tree incoming, outgoing, v1, v2, v3;
7454           bool is_private = false;
7455 
7456           enum tree_code rcode = OMP_CLAUSE_REDUCTION_CODE (c);
7457           if (rcode == MINUS_EXPR)
7458             rcode = PLUS_EXPR;
7459           else if (rcode == TRUTH_ANDIF_EXPR)
7460             rcode = BIT_AND_EXPR;
7461           else if (rcode == TRUTH_ORIF_EXPR)
7462             rcode = BIT_IOR_EXPR;
7463           tree op = build_int_cst (unsigned_type_node, rcode);
7464 
7465           if (!var)
7466             var = orig;
7467 
7468           incoming = outgoing = var;
7469 
7470           if (!inner)
7471             {
7472               /* See if an outer construct also reduces this variable.  */
7473               omp_context *outer = ctx;
7474 
7475               while (omp_context *probe = outer->outer)
7476                 {
7477                     enum gimple_code type = gimple_code (probe->stmt);
7478                     tree cls;
7479 
7480                     switch (type)
7481                       {
7482                       case GIMPLE_OMP_FOR:
7483                         cls = gimple_omp_for_clauses (probe->stmt);
7484                         break;
7485 
7486                       case GIMPLE_OMP_TARGET:
7487                         /* No 'reduction' clauses inside OpenACC 'kernels'
7488                            regions.  */
7489                         gcc_checking_assert (!is_oacc_kernels (probe));
7490 
7491                         if (!is_gimple_omp_offloaded (probe->stmt))
7492                           goto do_lookup;
7493 
7494                         cls = gimple_omp_target_clauses (probe->stmt);
7495                         break;
7496 
7497                       default:
7498                         goto do_lookup;
7499                       }
7500 
7501                     outer = probe;
7502                     for (; cls;  cls = OMP_CLAUSE_CHAIN (cls))
7503                       if (OMP_CLAUSE_CODE (cls) == OMP_CLAUSE_REDUCTION
7504                           && orig == OMP_CLAUSE_DECL (cls))
7505                         {
7506                           incoming = outgoing = lookup_decl (orig, probe);
7507                           goto has_outer_reduction;
7508                         }
7509                       else if ((OMP_CLAUSE_CODE (cls) == OMP_CLAUSE_FIRSTPRIVATE
7510                                   || OMP_CLAUSE_CODE (cls) == OMP_CLAUSE_PRIVATE)
7511                                  && orig == OMP_CLAUSE_DECL (cls))
7512                         {
7513                           is_private = true;
7514                           goto do_lookup;
7515                         }
7516                 }
7517 
7518             do_lookup:
7519               /* This is the outermost construct with this reduction,
7520                  see if there's a mapping for it.  */
7521               if (gimple_code (outer->stmt) == GIMPLE_OMP_TARGET
7522                     && maybe_lookup_field (orig, outer) && !is_private)
7523                 {
7524                     ref_to_res = build_receiver_ref (orig, false, outer);
7525                     if (omp_privatize_by_reference (orig))
7526                       ref_to_res = build_simple_mem_ref (ref_to_res);
7527 
7528                     tree type = TREE_TYPE (var);
7529                     if (POINTER_TYPE_P (type))
7530                       type = TREE_TYPE (type);
7531 
7532                     outgoing = var;
7533                     incoming = omp_reduction_init_op (loc, rcode, type);
7534                 }
7535               else
7536                 {
7537                     /* Try to look at enclosing contexts for reduction var,
7538                        use original if no mapping found.  */
7539                     tree t = NULL_TREE;
7540                     omp_context *c = ctx->outer;
7541                     while (c && !t)
7542                       {
7543                         t = maybe_lookup_decl (orig, c);
7544                         c = c->outer;
7545                       }
7546                     incoming = outgoing = (t ? t : orig);
7547                 }
7548 
7549             has_outer_reduction:;
7550             }
7551 
7552           if (!ref_to_res)
7553             ref_to_res = integer_zero_node;
7554 
7555           if (omp_privatize_by_reference (orig))
7556             {
7557               tree type = TREE_TYPE (var);
7558               const char *id = IDENTIFIER_POINTER (DECL_NAME (var));
7559 
7560               if (!inner)
7561                 {
7562                     tree x = create_tmp_var (TREE_TYPE (type), id);
7563                     gimplify_assign (var, build_fold_addr_expr (x), fork_seq);
7564                 }
7565 
7566               v1 = create_tmp_var (type, id);
7567               v2 = create_tmp_var (type, id);
7568               v3 = create_tmp_var (type, id);
7569 
7570               gimplify_assign (v1, var, fork_seq);
7571               gimplify_assign (v2, var, fork_seq);
7572               gimplify_assign (v3, var, fork_seq);
7573 
7574               var = build_simple_mem_ref (var);
7575               v1 = build_simple_mem_ref (v1);
7576               v2 = build_simple_mem_ref (v2);
7577               v3 = build_simple_mem_ref (v3);
7578               outgoing = build_simple_mem_ref (outgoing);
7579 
7580               if (!TREE_CONSTANT (incoming))
7581                 incoming = build_simple_mem_ref (incoming);
7582             }
7583           else
7584             /* Note that 'var' might be a mem ref.  */
7585             v1 = v2 = v3 = var;
7586 
7587           /* Determine position in reduction buffer, which may be used
7588              by target.  The parser has ensured that this is not a
7589              variable-sized type.  */
7590           fixed_size_mode mode
7591             = as_a <fixed_size_mode> (TYPE_MODE (TREE_TYPE (var)));
7592           unsigned align = GET_MODE_ALIGNMENT (mode) /  BITS_PER_UNIT;
7593           offset = (offset + align - 1) & ~(align - 1);
7594           tree off = build_int_cst (sizetype, offset);
7595           offset += GET_MODE_SIZE (mode);
7596 
7597           if (!init_code)
7598             {
7599               init_code = build_int_cst (integer_type_node,
7600                                                IFN_GOACC_REDUCTION_INIT);
7601               fini_code = build_int_cst (integer_type_node,
7602                                                IFN_GOACC_REDUCTION_FINI);
7603               setup_code = build_int_cst (integer_type_node,
7604                                                   IFN_GOACC_REDUCTION_SETUP);
7605               teardown_code = build_int_cst (integer_type_node,
7606                                                      IFN_GOACC_REDUCTION_TEARDOWN);
7607             }
7608 
7609           tree setup_call
7610             = build_call_expr_internal_loc (loc, IFN_GOACC_REDUCTION,
7611                                                     TREE_TYPE (var), 6, setup_code,
7612                                                     unshare_expr (ref_to_res),
7613                                                     unshare_expr (incoming),
7614                                                     level, op, off);
7615           tree init_call
7616             = build_call_expr_internal_loc (loc, IFN_GOACC_REDUCTION,
7617                                                     TREE_TYPE (var), 6, init_code,
7618                                                     unshare_expr (ref_to_res),
7619                                                     unshare_expr (v1), level, op, off);
7620           tree fini_call
7621             = build_call_expr_internal_loc (loc, IFN_GOACC_REDUCTION,
7622                                                     TREE_TYPE (var), 6, fini_code,
7623                                                     unshare_expr (ref_to_res),
7624                                                     unshare_expr (v2), level, op, off);
7625           tree teardown_call
7626             = build_call_expr_internal_loc (loc, IFN_GOACC_REDUCTION,
7627                                                     TREE_TYPE (var), 6, teardown_code,
7628                                                     ref_to_res, unshare_expr (v3),
7629                                                     level, op, off);
7630 
7631           gimplify_assign (unshare_expr (v1), setup_call, &before_fork);
7632           gimplify_assign (unshare_expr (v2), init_call, &after_fork);
7633           gimplify_assign (unshare_expr (v3), fini_call, &before_join);
7634           gimplify_assign (unshare_expr (outgoing), teardown_call, &after_join);
7635       }
7636 
7637   /* Now stitch things together.  */
7638   gimple_seq_add_seq (fork_seq, before_fork);
7639   if (private_marker)
7640     gimple_seq_add_stmt (fork_seq, private_marker);
7641   if (fork)
7642     gimple_seq_add_stmt (fork_seq, fork);
7643   gimple_seq_add_seq (fork_seq, after_fork);
7644 
7645   gimple_seq_add_seq (join_seq, before_join);
7646   if (join)
7647     gimple_seq_add_stmt (join_seq, join);
7648   gimple_seq_add_seq (join_seq, after_join);
7649 }
7650 
7651 /* Generate code to implement the REDUCTION clauses, append it
7652    to STMT_SEQP.  CLIST if non-NULL is a pointer to a sequence
7653    that should be emitted also inside of the critical section,
7654    in that case clear *CLIST afterwards, otherwise leave it as is
7655    and let the caller emit it itself.  */
7656 
7657 static void
lower_reduction_clauses(tree clauses,gimple_seq * stmt_seqp,gimple_seq * clist,omp_context * ctx)7658 lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp,
7659                                gimple_seq *clist, omp_context *ctx)
7660 {
7661   gimple_seq sub_seq = NULL;
7662   gimple *stmt;
7663   tree x, c;
7664   int count = 0;
7665 
7666   /* OpenACC loop reductions are handled elsewhere.  */
7667   if (is_gimple_omp_oacc (ctx->stmt))
7668     return;
7669 
7670   /* SIMD reductions are handled in lower_rec_input_clauses.  */
7671   if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
7672       && gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_SIMD)
7673     return;
7674 
7675   /* inscan reductions are handled elsewhere.  */
7676   if (ctx->scan_inclusive || ctx->scan_exclusive)
7677     return;
7678 
7679   /* First see if there is exactly one reduction clause.  Use OMP_ATOMIC
7680      update in that case, otherwise use a lock.  */
7681   for (c = clauses; c && count < 2; c = OMP_CLAUSE_CHAIN (c))
7682     if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
7683           && !OMP_CLAUSE_REDUCTION_TASK (c))
7684       {
7685           if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)
7686               || TREE_CODE (OMP_CLAUSE_DECL (c)) == MEM_REF)
7687             {
7688               /* Never use OMP_ATOMIC for array reductions or UDRs.  */
7689               count = -1;
7690               break;
7691             }
7692           count++;
7693       }
7694 
7695   if (count == 0)
7696     return;
7697 
7698   for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
7699     {
7700       tree var, ref, new_var, orig_var;
7701       enum tree_code code;
7702       location_t clause_loc = OMP_CLAUSE_LOCATION (c);
7703 
7704       if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION
7705             || OMP_CLAUSE_REDUCTION_TASK (c))
7706           continue;
7707 
7708       enum omp_clause_code ccode = OMP_CLAUSE_REDUCTION;
7709       orig_var = var = OMP_CLAUSE_DECL (c);
7710       if (TREE_CODE (var) == MEM_REF)
7711           {
7712             var = TREE_OPERAND (var, 0);
7713             if (TREE_CODE (var) == POINTER_PLUS_EXPR)
7714               var = TREE_OPERAND (var, 0);
7715             if (TREE_CODE (var) == ADDR_EXPR)
7716               var = TREE_OPERAND (var, 0);
7717             else
7718               {
7719                 /* If this is a pointer or referenced based array
7720                      section, the var could be private in the outer
7721                      context e.g. on orphaned loop construct.  Pretend this
7722                      is private variable's outer reference.  */
7723                 ccode = OMP_CLAUSE_PRIVATE;
7724                 if (TREE_CODE (var) == INDIRECT_REF)
7725                     var = TREE_OPERAND (var, 0);
7726               }
7727             orig_var = var;
7728             if (is_variable_sized (var))
7729               {
7730                 gcc_assert (DECL_HAS_VALUE_EXPR_P (var));
7731                 var = DECL_VALUE_EXPR (var);
7732                 gcc_assert (TREE_CODE (var) == INDIRECT_REF);
7733                 var = TREE_OPERAND (var, 0);
7734                 gcc_assert (DECL_P (var));
7735               }
7736           }
7737       new_var = lookup_decl (var, ctx);
7738       if (var == OMP_CLAUSE_DECL (c)
7739             && omp_privatize_by_reference (var))
7740           new_var = build_simple_mem_ref_loc (clause_loc, new_var);
7741       ref = build_outer_var_ref (var, ctx, ccode);
7742       code = OMP_CLAUSE_REDUCTION_CODE (c);
7743 
7744       /* reduction(-:var) sums up the partial results, so it acts
7745            identically to reduction(+:var).  */
7746       if (code == MINUS_EXPR)
7747         code = PLUS_EXPR;
7748 
7749       bool is_truth_op = (code == TRUTH_ANDIF_EXPR || code == TRUTH_ORIF_EXPR);
7750       if (count == 1)
7751           {
7752             tree addr = build_fold_addr_expr_loc (clause_loc, ref);
7753 
7754             addr = save_expr (addr);
7755             ref = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (addr)), addr);
7756             tree new_var2 = new_var;
7757             tree ref2 = ref;
7758             if (is_truth_op)
7759               {
7760                 tree zero = build_zero_cst (TREE_TYPE (new_var));
7761                 new_var2 = fold_build2_loc (clause_loc, NE_EXPR,
7762                                                     boolean_type_node, new_var, zero);
7763                 ref2 = fold_build2_loc (clause_loc, NE_EXPR, boolean_type_node,
7764                                               ref, zero);
7765               }
7766             x = fold_build2_loc (clause_loc, code, TREE_TYPE (new_var2), ref2,
7767                                      new_var2);
7768             if (is_truth_op)
7769               x = fold_convert (TREE_TYPE (new_var), x);
7770             x = build2 (OMP_ATOMIC, void_type_node, addr, x);
7771             OMP_ATOMIC_MEMORY_ORDER (x) = OMP_MEMORY_ORDER_RELAXED;
7772             gimplify_and_add (x, stmt_seqp);
7773             return;
7774           }
7775       else if (TREE_CODE (OMP_CLAUSE_DECL (c)) == MEM_REF)
7776           {
7777             tree d = OMP_CLAUSE_DECL (c);
7778             tree type = TREE_TYPE (d);
7779             tree v = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
7780             tree i = create_tmp_var (TREE_TYPE (v));
7781             tree ptype = build_pointer_type (TREE_TYPE (type));
7782             tree bias = TREE_OPERAND (d, 1);
7783             d = TREE_OPERAND (d, 0);
7784             if (TREE_CODE (d) == POINTER_PLUS_EXPR)
7785               {
7786                 tree b = TREE_OPERAND (d, 1);
7787                 b = maybe_lookup_decl (b, ctx);
7788                 if (b == NULL)
7789                     {
7790                       b = TREE_OPERAND (d, 1);
7791                       b = maybe_lookup_decl_in_outer_ctx (b, ctx);
7792                     }
7793                 if (integer_zerop (bias))
7794                     bias = b;
7795                 else
7796                     {
7797                       bias = fold_convert_loc (clause_loc, TREE_TYPE (b), bias);
7798                       bias = fold_build2_loc (clause_loc, PLUS_EXPR,
7799                                                     TREE_TYPE (b), b, bias);
7800                     }
7801                 d = TREE_OPERAND (d, 0);
7802               }
7803             /* For ref build_outer_var_ref already performs this, so
7804                only new_var needs a dereference.  */
7805             if (TREE_CODE (d) == INDIRECT_REF)
7806               {
7807                 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
7808                 gcc_assert (omp_privatize_by_reference (var)
7809                                 && var == orig_var);
7810               }
7811             else if (TREE_CODE (d) == ADDR_EXPR)
7812               {
7813                 if (orig_var == var)
7814                     {
7815                       new_var = build_fold_addr_expr (new_var);
7816                       ref = build_fold_addr_expr (ref);
7817                     }
7818               }
7819             else
7820               {
7821                 gcc_assert (orig_var == var);
7822                 if (omp_privatize_by_reference (var))
7823                     ref = build_fold_addr_expr (ref);
7824               }
7825             if (DECL_P (v))
7826               {
7827                 tree t = maybe_lookup_decl (v, ctx);
7828                 if (t)
7829                     v = t;
7830                 else
7831                     v = maybe_lookup_decl_in_outer_ctx (v, ctx);
7832                 gimplify_expr (&v, stmt_seqp, NULL, is_gimple_val, fb_rvalue);
7833               }
7834             if (!integer_zerop (bias))
7835               {
7836                 bias = fold_convert_loc (clause_loc, sizetype, bias);
7837                 new_var = fold_build2_loc (clause_loc, POINTER_PLUS_EXPR,
7838                                                    TREE_TYPE (new_var), new_var,
7839                                                    unshare_expr (bias));
7840                 ref = fold_build2_loc (clause_loc, POINTER_PLUS_EXPR,
7841                                                    TREE_TYPE (ref), ref, bias);
7842               }
7843             new_var = fold_convert_loc (clause_loc, ptype, new_var);
7844             ref = fold_convert_loc (clause_loc, ptype, ref);
7845             tree m = create_tmp_var (ptype);
7846             gimplify_assign (m, new_var, stmt_seqp);
7847             new_var = m;
7848             m = create_tmp_var (ptype);
7849             gimplify_assign (m, ref, stmt_seqp);
7850             ref = m;
7851             gimplify_assign (i, build_int_cst (TREE_TYPE (v), 0), stmt_seqp);
7852             tree body = create_artificial_label (UNKNOWN_LOCATION);
7853             tree end = create_artificial_label (UNKNOWN_LOCATION);
7854             gimple_seq_add_stmt (&sub_seq, gimple_build_label (body));
7855             tree priv = build_simple_mem_ref_loc (clause_loc, new_var);
7856             tree out = build_simple_mem_ref_loc (clause_loc, ref);
7857             if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
7858               {
7859                 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
7860                 tree decl_placeholder
7861                     = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c);
7862                 SET_DECL_VALUE_EXPR (placeholder, out);
7863                 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
7864                 SET_DECL_VALUE_EXPR (decl_placeholder, priv);
7865                 DECL_HAS_VALUE_EXPR_P (decl_placeholder) = 1;
7866                 lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
7867                 gimple_seq_add_seq (&sub_seq,
7868                                           OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
7869                 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
7870                 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
7871                 OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c) = NULL;
7872               }
7873             else
7874               {
7875                 tree out2 = out;
7876                 tree priv2 = priv;
7877                 if (is_truth_op)
7878                     {
7879                       tree zero = build_zero_cst (TREE_TYPE (out));
7880                       out2 = fold_build2_loc (clause_loc, NE_EXPR,
7881                                                     boolean_type_node, out, zero);
7882                       priv2 = fold_build2_loc (clause_loc, NE_EXPR,
7883                                                      boolean_type_node, priv, zero);
7884                     }
7885                 x = build2 (code, TREE_TYPE (out2), out2, priv2);
7886                 if (is_truth_op)
7887                     x = fold_convert (TREE_TYPE (out), x);
7888                 out = unshare_expr (out);
7889                 gimplify_assign (out, x, &sub_seq);
7890               }
7891             gimple *g = gimple_build_assign (new_var, POINTER_PLUS_EXPR, new_var,
7892                                                      TYPE_SIZE_UNIT (TREE_TYPE (type)));
7893             gimple_seq_add_stmt (&sub_seq, g);
7894             g = gimple_build_assign (ref, POINTER_PLUS_EXPR, ref,
7895                                            TYPE_SIZE_UNIT (TREE_TYPE (type)));
7896             gimple_seq_add_stmt (&sub_seq, g);
7897             g = gimple_build_assign (i, PLUS_EXPR, i,
7898                                            build_int_cst (TREE_TYPE (i), 1));
7899             gimple_seq_add_stmt (&sub_seq, g);
7900             g = gimple_build_cond (LE_EXPR, i, v, body, end);
7901             gimple_seq_add_stmt (&sub_seq, g);
7902             gimple_seq_add_stmt (&sub_seq, gimple_build_label (end));
7903           }
7904       else if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
7905           {
7906             tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
7907 
7908             if (omp_privatize_by_reference (var)
7909                 && !useless_type_conversion_p (TREE_TYPE (placeholder),
7910                                                        TREE_TYPE (ref)))
7911               ref = build_fold_addr_expr_loc (clause_loc, ref);
7912             SET_DECL_VALUE_EXPR (placeholder, ref);
7913             DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
7914             lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
7915             gimple_seq_add_seq (&sub_seq, OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
7916             OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
7917             OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
7918           }
7919       else
7920           {
7921             tree new_var2 = new_var;
7922             tree ref2 = ref;
7923             if (is_truth_op)
7924               {
7925                 tree zero = build_zero_cst (TREE_TYPE (new_var));
7926                 new_var2 = fold_build2_loc (clause_loc, NE_EXPR,
7927                                                     boolean_type_node, new_var, zero);
7928                 ref2 = fold_build2_loc (clause_loc, NE_EXPR, boolean_type_node,
7929                                               ref, zero);
7930               }
7931             x = build2 (code, TREE_TYPE (ref), ref2, new_var2);
7932             if (is_truth_op)
7933               x = fold_convert (TREE_TYPE (new_var), x);
7934             ref = build_outer_var_ref (var, ctx);
7935             gimplify_assign (ref, x, &sub_seq);
7936           }
7937     }
7938 
7939   stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START),
7940                                   0);
7941   gimple_seq_add_stmt (stmt_seqp, stmt);
7942 
7943   gimple_seq_add_seq (stmt_seqp, sub_seq);
7944 
7945   if (clist)
7946     {
7947       gimple_seq_add_seq (stmt_seqp, *clist);
7948       *clist = NULL;
7949     }
7950 
7951   stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END),
7952                                   0);
7953   gimple_seq_add_stmt (stmt_seqp, stmt);
7954 }
7955 
7956 
7957 /* Generate code to implement the COPYPRIVATE clauses.  */
7958 
7959 static void
lower_copyprivate_clauses(tree clauses,gimple_seq * slist,gimple_seq * rlist,omp_context * ctx)7960 lower_copyprivate_clauses (tree clauses, gimple_seq *slist, gimple_seq *rlist,
7961                                   omp_context *ctx)
7962 {
7963   tree c;
7964 
7965   for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
7966     {
7967       tree var, new_var, ref, x;
7968       bool by_ref;
7969       location_t clause_loc = OMP_CLAUSE_LOCATION (c);
7970 
7971       if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYPRIVATE)
7972           continue;
7973 
7974       var = OMP_CLAUSE_DECL (c);
7975       by_ref = use_pointer_for_field (var, NULL);
7976 
7977       ref = build_sender_ref (var, ctx);
7978       x = new_var = lookup_decl_in_outer_ctx (var, ctx);
7979       if (by_ref)
7980           {
7981             x = build_fold_addr_expr_loc (clause_loc, new_var);
7982             x = fold_convert_loc (clause_loc, TREE_TYPE (ref), x);
7983           }
7984       gimplify_assign (ref, x, slist);
7985 
7986       ref = build_receiver_ref (var, false, ctx);
7987       if (by_ref)
7988           {
7989             ref = fold_convert_loc (clause_loc,
7990                                           build_pointer_type (TREE_TYPE (new_var)),
7991                                           ref);
7992             ref = build_fold_indirect_ref_loc (clause_loc, ref);
7993           }
7994       if (omp_privatize_by_reference (var))
7995           {
7996             ref = fold_convert_loc (clause_loc, TREE_TYPE (new_var), ref);
7997             ref = build_simple_mem_ref_loc (clause_loc, ref);
7998             new_var = build_simple_mem_ref_loc (clause_loc, new_var);
7999           }
8000       x = lang_hooks.decls.omp_clause_assign_op (c, new_var, ref);
8001       gimplify_and_add (x, rlist);
8002     }
8003 }
8004 
8005 
8006 /* Generate code to implement the clauses, FIRSTPRIVATE, COPYIN, LASTPRIVATE,
8007    and REDUCTION from the sender (aka parent) side.  */
8008 
8009 static void
lower_send_clauses(tree clauses,gimple_seq * ilist,gimple_seq * olist,omp_context * ctx)8010 lower_send_clauses (tree clauses, gimple_seq *ilist, gimple_seq *olist,
8011                         omp_context *ctx)
8012 {
8013   tree c, t;
8014   int ignored_looptemp = 0;
8015   bool is_taskloop = false;
8016 
8017   /* For taskloop, ignore first two _looptemp_ clauses, those are initialized
8018      by GOMP_taskloop.  */
8019   if (is_task_ctx (ctx) && gimple_omp_task_taskloop_p (ctx->stmt))
8020     {
8021       ignored_looptemp = 2;
8022       is_taskloop = true;
8023     }
8024 
8025   for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
8026     {
8027       tree val, ref, x, var;
8028       bool by_ref, do_in = false, do_out = false;
8029       location_t clause_loc = OMP_CLAUSE_LOCATION (c);
8030 
8031       switch (OMP_CLAUSE_CODE (c))
8032           {
8033           case OMP_CLAUSE_PRIVATE:
8034             if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
8035               break;
8036             continue;
8037           case OMP_CLAUSE_FIRSTPRIVATE:
8038           case OMP_CLAUSE_COPYIN:
8039           case OMP_CLAUSE_LASTPRIVATE:
8040           case OMP_CLAUSE_IN_REDUCTION:
8041           case OMP_CLAUSE__REDUCTEMP_:
8042             break;
8043           case OMP_CLAUSE_REDUCTION:
8044             if (is_task_ctx (ctx) || OMP_CLAUSE_REDUCTION_TASK (c))
8045               continue;
8046             break;
8047           case OMP_CLAUSE_SHARED:
8048             if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
8049               break;
8050             continue;
8051           case OMP_CLAUSE__LOOPTEMP_:
8052             if (ignored_looptemp)
8053               {
8054                 ignored_looptemp--;
8055                 continue;
8056               }
8057             break;
8058           default:
8059             continue;
8060           }
8061 
8062       val = OMP_CLAUSE_DECL (c);
8063       if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
8064              || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IN_REDUCTION)
8065             && TREE_CODE (val) == MEM_REF)
8066           {
8067             val = TREE_OPERAND (val, 0);
8068             if (TREE_CODE (val) == POINTER_PLUS_EXPR)
8069               val = TREE_OPERAND (val, 0);
8070             if (TREE_CODE (val) == INDIRECT_REF
8071                 || TREE_CODE (val) == ADDR_EXPR)
8072               val = TREE_OPERAND (val, 0);
8073             if (is_variable_sized (val))
8074               continue;
8075           }
8076 
8077       /* For OMP_CLAUSE_SHARED_FIRSTPRIVATE, look beyond the
8078            outer taskloop region.  */
8079       omp_context *ctx_for_o = ctx;
8080       if (is_taskloop
8081             && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
8082             && OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
8083           ctx_for_o = ctx->outer;
8084 
8085       var = lookup_decl_in_outer_ctx (val, ctx_for_o);
8086 
8087       if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYIN
8088             && is_global_var (var)
8089             && (val == OMP_CLAUSE_DECL (c)
8090                 || !is_task_ctx (ctx)
8091                 || (TREE_CODE (TREE_TYPE (val)) != POINTER_TYPE
8092                       && (TREE_CODE (TREE_TYPE (val)) != REFERENCE_TYPE
8093                           || (TREE_CODE (TREE_TYPE (TREE_TYPE (val)))
8094                                 != POINTER_TYPE)))))
8095           continue;
8096 
8097       t = omp_member_access_dummy_var (var);
8098       if (t)
8099           {
8100             var = DECL_VALUE_EXPR (var);
8101             tree o = maybe_lookup_decl_in_outer_ctx (t, ctx_for_o);
8102             if (o != t)
8103               var = unshare_and_remap (var, t, o);
8104             else
8105               var = unshare_expr (var);
8106           }
8107 
8108       if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED)
8109           {
8110             /* Handle taskloop firstprivate/lastprivate, where the
8111                lastprivate on GIMPLE_OMP_TASK is represented as
8112                OMP_CLAUSE_SHARED_FIRSTPRIVATE.  */
8113             tree f = lookup_sfield ((splay_tree_key) &DECL_UID (val), ctx);
8114             x = omp_build_component_ref (ctx->sender_decl, f);
8115             if (use_pointer_for_field (val, ctx))
8116               var = build_fold_addr_expr (var);
8117             gimplify_assign (x, var, ilist);
8118             DECL_ABSTRACT_ORIGIN (f) = NULL;
8119             continue;
8120           }
8121 
8122       if (((OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION
8123               && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_IN_REDUCTION)
8124              || val == OMP_CLAUSE_DECL (c))
8125             && is_variable_sized (val))
8126           continue;
8127       by_ref = use_pointer_for_field (val, NULL);
8128 
8129       switch (OMP_CLAUSE_CODE (c))
8130           {
8131           case OMP_CLAUSE_FIRSTPRIVATE:
8132             if (OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c)
8133                 && !by_ref
8134                 && is_task_ctx (ctx))
8135               suppress_warning (var);
8136             do_in = true;
8137             break;
8138 
8139           case OMP_CLAUSE_PRIVATE:
8140           case OMP_CLAUSE_COPYIN:
8141           case OMP_CLAUSE__LOOPTEMP_:
8142           case OMP_CLAUSE__REDUCTEMP_:
8143             do_in = true;
8144             break;
8145 
8146           case OMP_CLAUSE_LASTPRIVATE:
8147             if (by_ref || omp_privatize_by_reference (val))
8148               {
8149                 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
8150                     continue;
8151                 do_in = true;
8152               }
8153             else
8154               {
8155                 do_out = true;
8156                 if (lang_hooks.decls.omp_private_outer_ref (val))
8157                     do_in = true;
8158               }
8159             break;
8160 
8161           case OMP_CLAUSE_REDUCTION:
8162           case OMP_CLAUSE_IN_REDUCTION:
8163             do_in = true;
8164             if (val == OMP_CLAUSE_DECL (c))
8165               {
8166                 if (is_task_ctx (ctx))
8167                     by_ref = use_pointer_for_field (val, ctx);
8168                 else
8169                     do_out = !(by_ref || omp_privatize_by_reference (val));
8170               }
8171             else
8172               by_ref = TREE_CODE (TREE_TYPE (val)) == ARRAY_TYPE;
8173             break;
8174 
8175           default:
8176             gcc_unreachable ();
8177           }
8178 
8179       if (do_in)
8180           {
8181             ref = build_sender_ref (val, ctx);
8182             x = by_ref ? build_fold_addr_expr_loc (clause_loc, var) : var;
8183             gimplify_assign (ref, x, ilist);
8184             if (is_task_ctx (ctx))
8185               DECL_ABSTRACT_ORIGIN (TREE_OPERAND (ref, 1)) = NULL;
8186           }
8187 
8188       if (do_out)
8189           {
8190             ref = build_sender_ref (val, ctx);
8191             gimplify_assign (var, ref, olist);
8192           }
8193     }
8194 }
8195 
8196 /* Generate code to implement SHARED from the sender (aka parent)
8197    side.  This is trickier, since GIMPLE_OMP_PARALLEL_CLAUSES doesn't
8198    list things that got automatically shared.  */
8199 
8200 static void
lower_send_shared_vars(gimple_seq * ilist,gimple_seq * olist,omp_context * ctx)8201 lower_send_shared_vars (gimple_seq *ilist, gimple_seq *olist, omp_context *ctx)
8202 {
8203   tree var, ovar, nvar, t, f, x, record_type;
8204 
8205   if (ctx->record_type == NULL)
8206     return;
8207 
8208   record_type = ctx->srecord_type ? ctx->srecord_type : ctx->record_type;
8209   for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
8210     {
8211       ovar = DECL_ABSTRACT_ORIGIN (f);
8212       if (!ovar || TREE_CODE (ovar) == FIELD_DECL)
8213           continue;
8214 
8215       nvar = maybe_lookup_decl (ovar, ctx);
8216       if (!nvar
8217             || !DECL_HAS_VALUE_EXPR_P (nvar)
8218             || (ctx->allocate_map
8219                 && ctx->allocate_map->get (ovar)))
8220           continue;
8221 
8222       /* If CTX is a nested parallel directive.  Find the immediately
8223            enclosing parallel or workshare construct that contains a
8224            mapping for OVAR.  */
8225       var = lookup_decl_in_outer_ctx (ovar, ctx);
8226 
8227       t = omp_member_access_dummy_var (var);
8228       if (t)
8229           {
8230             var = DECL_VALUE_EXPR (var);
8231             tree o = maybe_lookup_decl_in_outer_ctx (t, ctx);
8232             if (o != t)
8233               var = unshare_and_remap (var, t, o);
8234             else
8235               var = unshare_expr (var);
8236           }
8237 
8238       if (use_pointer_for_field (ovar, ctx))
8239           {
8240             x = build_sender_ref (ovar, ctx);
8241             if (TREE_CODE (TREE_TYPE (f)) == ARRAY_TYPE
8242                 && TREE_TYPE (f) == TREE_TYPE (ovar))
8243               {
8244                 gcc_assert (is_parallel_ctx (ctx)
8245                                 && DECL_ARTIFICIAL (ovar));
8246                 /* _condtemp_ clause.  */
8247                 var = build_constructor (TREE_TYPE (x), NULL);
8248               }
8249             else
8250               var = build_fold_addr_expr (var);
8251             gimplify_assign (x, var, ilist);
8252           }
8253       else
8254           {
8255             x = build_sender_ref (ovar, ctx);
8256             gimplify_assign (x, var, ilist);
8257 
8258             if (!TREE_READONLY (var)
8259                 /* We don't need to receive a new reference to a result
8260                    or parm decl.  In fact we may not store to it as we will
8261                      invalidate any pending RSO and generate wrong gimple
8262                      during inlining.  */
8263                 && !((TREE_CODE (var) == RESULT_DECL
8264                         || TREE_CODE (var) == PARM_DECL)
8265                        && DECL_BY_REFERENCE (var)))
8266               {
8267                 x = build_sender_ref (ovar, ctx);
8268                 gimplify_assign (var, x, olist);
8269               }
8270           }
8271     }
8272 }
8273 
8274 /* Emit an OpenACC head marker call, encapulating the partitioning and
8275    other information that must be processed by the target compiler.
8276    Return the maximum number of dimensions the associated loop might
8277    be partitioned over.  */
8278 
8279 static unsigned
lower_oacc_head_mark(location_t loc,tree ddvar,tree clauses,gimple_seq * seq,omp_context * ctx)8280 lower_oacc_head_mark (location_t loc, tree ddvar, tree clauses,
8281                           gimple_seq *seq, omp_context *ctx)
8282 {
8283   unsigned levels = 0;
8284   unsigned tag = 0;
8285   tree gang_static = NULL_TREE;
8286   auto_vec<tree, 5> args;
8287 
8288   args.quick_push (build_int_cst
8289                        (integer_type_node, IFN_UNIQUE_OACC_HEAD_MARK));
8290   args.quick_push (ddvar);
8291   for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
8292     {
8293       switch (OMP_CLAUSE_CODE (c))
8294           {
8295           case OMP_CLAUSE_GANG:
8296             tag |= OLF_DIM_GANG;
8297             gang_static = OMP_CLAUSE_GANG_STATIC_EXPR (c);
8298             /* static:* is represented by -1, and we can ignore it, as
8299                scheduling is always static.  */
8300             if (gang_static && integer_minus_onep (gang_static))
8301               gang_static = NULL_TREE;
8302             levels++;
8303             break;
8304 
8305           case OMP_CLAUSE_WORKER:
8306             tag |= OLF_DIM_WORKER;
8307             levels++;
8308             break;
8309 
8310           case OMP_CLAUSE_VECTOR:
8311             tag |= OLF_DIM_VECTOR;
8312             levels++;
8313             break;
8314 
8315           case OMP_CLAUSE_SEQ:
8316             tag |= OLF_SEQ;
8317             break;
8318 
8319           case OMP_CLAUSE_AUTO:
8320             tag |= OLF_AUTO;
8321             break;
8322 
8323           case OMP_CLAUSE_INDEPENDENT:
8324             tag |= OLF_INDEPENDENT;
8325             break;
8326 
8327           case OMP_CLAUSE_TILE:
8328             tag |= OLF_TILE;
8329             break;
8330 
8331           case OMP_CLAUSE_REDUCTION:
8332             tag |= OLF_REDUCTION;
8333             break;
8334 
8335           default:
8336             continue;
8337           }
8338     }
8339 
8340   if (gang_static)
8341     {
8342       if (DECL_P (gang_static))
8343           gang_static = build_outer_var_ref (gang_static, ctx);
8344       tag |= OLF_GANG_STATIC;
8345     }
8346 
8347   omp_context *tgt = enclosing_target_ctx (ctx);
8348   if (!tgt || is_oacc_parallel_or_serial (tgt))
8349     ;
8350   else if (is_oacc_kernels (tgt))
8351     /* Not using this loops handling inside OpenACC 'kernels' regions.  */
8352     gcc_unreachable ();
8353   else if (is_oacc_kernels_decomposed_part (tgt))
8354     ;
8355   else
8356     gcc_unreachable ();
8357 
8358   /* In a parallel region, loops are implicitly INDEPENDENT.  */
8359   if (!tgt || is_oacc_parallel_or_serial (tgt))
8360     tag |= OLF_INDEPENDENT;
8361 
8362   /* Loops inside OpenACC 'kernels' decomposed parts' regions are expected to
8363      have an explicit 'seq' or 'independent' clause, and no 'auto' clause.  */
8364   if (tgt && is_oacc_kernels_decomposed_part (tgt))
8365     {
8366       gcc_assert (tag & (OLF_SEQ | OLF_INDEPENDENT));
8367       gcc_assert (!(tag & OLF_AUTO));
8368     }
8369 
8370   if (tag & OLF_TILE)
8371     /* Tiling could use all 3 levels.  */
8372     levels = 3;
8373   else
8374     {
8375       /* A loop lacking SEQ, GANG, WORKER and/or VECTOR could be AUTO.
8376            Ensure at least one level, or 2 for possible auto
8377            partitioning */
8378       bool maybe_auto = !(tag & (((GOMP_DIM_MASK (GOMP_DIM_MAX) - 1)
8379                                           << OLF_DIM_BASE) | OLF_SEQ));
8380 
8381       if (levels < 1u + maybe_auto)
8382           levels = 1u + maybe_auto;
8383     }
8384 
8385   args.quick_push (build_int_cst (integer_type_node, levels));
8386   args.quick_push (build_int_cst (integer_type_node, tag));
8387   if (gang_static)
8388     args.quick_push (gang_static);
8389 
8390   gcall *call = gimple_build_call_internal_vec (IFN_UNIQUE, args);
8391   gimple_set_location (call, loc);
8392   gimple_set_lhs (call, ddvar);
8393   gimple_seq_add_stmt (seq, call);
8394 
8395   return levels;
8396 }
8397 
8398 /* Emit an OpenACC lopp head or tail marker to SEQ.  LEVEL is the
8399    partitioning level of the enclosed region.  */
8400 
8401 static void
lower_oacc_loop_marker(location_t loc,tree ddvar,bool head,tree tofollow,gimple_seq * seq)8402 lower_oacc_loop_marker (location_t loc, tree ddvar, bool head,
8403                               tree tofollow, gimple_seq *seq)
8404 {
8405   int marker_kind = (head ? IFN_UNIQUE_OACC_HEAD_MARK
8406                          : IFN_UNIQUE_OACC_TAIL_MARK);
8407   tree marker = build_int_cst (integer_type_node, marker_kind);
8408   int nargs = 2 + (tofollow != NULL_TREE);
8409   gcall *call = gimple_build_call_internal (IFN_UNIQUE, nargs,
8410                                                       marker, ddvar, tofollow);
8411   gimple_set_location (call, loc);
8412   gimple_set_lhs (call, ddvar);
8413   gimple_seq_add_stmt (seq, call);
8414 }
8415 
8416 /* Generate the before and after OpenACC loop sequences.  CLAUSES are
8417    the loop clauses, from which we extract reductions.  Initialize
8418    HEAD and TAIL.  */
8419 
8420 static void
lower_oacc_head_tail(location_t loc,tree clauses,gcall * private_marker,gimple_seq * head,gimple_seq * tail,omp_context * ctx)8421 lower_oacc_head_tail (location_t loc, tree clauses, gcall *private_marker,
8422                           gimple_seq *head, gimple_seq *tail, omp_context *ctx)
8423 {
8424   bool inner = false;
8425   tree ddvar = create_tmp_var (integer_type_node, ".data_dep");
8426   gimple_seq_add_stmt (head, gimple_build_assign (ddvar, integer_zero_node));
8427 
8428   unsigned count = lower_oacc_head_mark (loc, ddvar, clauses, head, ctx);
8429 
8430   if (private_marker)
8431     {
8432       gimple_set_location (private_marker, loc);
8433       gimple_call_set_lhs (private_marker, ddvar);
8434       gimple_call_set_arg (private_marker, 1, ddvar);
8435     }
8436 
8437   tree fork_kind = build_int_cst (unsigned_type_node, IFN_UNIQUE_OACC_FORK);
8438   tree join_kind = build_int_cst (unsigned_type_node, IFN_UNIQUE_OACC_JOIN);
8439 
8440   gcc_assert (count);
8441   for (unsigned done = 1; count; count--, done++)
8442     {
8443       gimple_seq fork_seq = NULL;
8444       gimple_seq join_seq = NULL;
8445 
8446       tree place = build_int_cst (integer_type_node, -1);
8447       gcall *fork = gimple_build_call_internal (IFN_UNIQUE, 3,
8448                                                             fork_kind, ddvar, place);
8449       gimple_set_location (fork, loc);
8450       gimple_set_lhs (fork, ddvar);
8451 
8452       gcall *join = gimple_build_call_internal (IFN_UNIQUE, 3,
8453                                                             join_kind, ddvar, place);
8454       gimple_set_location (join, loc);
8455       gimple_set_lhs (join, ddvar);
8456 
8457       /* Mark the beginning of this level sequence.  */
8458       if (inner)
8459           lower_oacc_loop_marker (loc, ddvar, true,
8460                                         build_int_cst (integer_type_node, count),
8461                                         &fork_seq);
8462       lower_oacc_loop_marker (loc, ddvar, false,
8463                                     build_int_cst (integer_type_node, done),
8464                                     &join_seq);
8465 
8466       lower_oacc_reductions (loc, clauses, place, inner,
8467                                    fork, (count == 1) ? private_marker : NULL,
8468                                    join, &fork_seq, &join_seq,  ctx);
8469 
8470       /* Append this level to head. */
8471       gimple_seq_add_seq (head, fork_seq);
8472       /* Prepend it to tail.  */
8473       gimple_seq_add_seq (&join_seq, *tail);
8474       *tail = join_seq;
8475 
8476       inner = true;
8477     }
8478 
8479   /* Mark the end of the sequence.  */
8480   lower_oacc_loop_marker (loc, ddvar, true, NULL_TREE, head);
8481   lower_oacc_loop_marker (loc, ddvar, false, NULL_TREE, tail);
8482 }
8483 
8484 /* If exceptions are enabled, wrap the statements in BODY in a MUST_NOT_THROW
8485    catch handler and return it.  This prevents programs from violating the
8486    structured block semantics with throws.  */
8487 
8488 static gimple_seq
maybe_catch_exception(gimple_seq body)8489 maybe_catch_exception (gimple_seq body)
8490 {
8491   gimple *g;
8492   tree decl;
8493 
8494   if (!flag_exceptions)
8495     return body;
8496 
8497   if (lang_hooks.eh_protect_cleanup_actions != NULL)
8498     decl = lang_hooks.eh_protect_cleanup_actions ();
8499   else
8500     decl = builtin_decl_explicit (BUILT_IN_TRAP);
8501 
8502   g = gimple_build_eh_must_not_throw (decl);
8503   g = gimple_build_try (body, gimple_seq_alloc_with_stmt (g),
8504                               GIMPLE_TRY_CATCH);
8505 
8506  return gimple_seq_alloc_with_stmt (g);
8507 }
8508 
8509 
8510 /* Routines to lower OMP directives into OMP-GIMPLE.  */
8511 
8512 /* If ctx is a worksharing context inside of a cancellable parallel
8513    region and it isn't nowait, add lhs to its GIMPLE_OMP_RETURN
8514    and conditional branch to parallel's cancel_label to handle
8515    cancellation in the implicit barrier.  */
8516 
8517 static void
maybe_add_implicit_barrier_cancel(omp_context * ctx,gimple * omp_return,gimple_seq * body)8518 maybe_add_implicit_barrier_cancel (omp_context *ctx, gimple *omp_return,
8519                                            gimple_seq *body)
8520 {
8521   gcc_assert (gimple_code (omp_return) == GIMPLE_OMP_RETURN);
8522   if (gimple_omp_return_nowait_p (omp_return))
8523     return;
8524   for (omp_context *outer = ctx->outer; outer; outer = outer->outer)
8525     if (gimple_code (outer->stmt) == GIMPLE_OMP_PARALLEL
8526           && outer->cancellable)
8527       {
8528           tree fndecl = builtin_decl_explicit (BUILT_IN_GOMP_CANCEL);
8529           tree c_bool_type = TREE_TYPE (TREE_TYPE (fndecl));
8530           tree lhs = create_tmp_var (c_bool_type);
8531           gimple_omp_return_set_lhs (omp_return, lhs);
8532           tree fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
8533           gimple *g = gimple_build_cond (NE_EXPR, lhs,
8534                                                fold_convert (c_bool_type,
8535                                                                  boolean_false_node),
8536                                                outer->cancel_label, fallthru_label);
8537           gimple_seq_add_stmt (body, g);
8538           gimple_seq_add_stmt (body, gimple_build_label (fallthru_label));
8539       }
8540     else if (gimple_code (outer->stmt) != GIMPLE_OMP_TASKGROUP
8541                && gimple_code (outer->stmt) != GIMPLE_OMP_SCOPE)
8542       return;
8543 }
8544 
8545 /* Find the first task_reduction or reduction clause or return NULL
8546    if there are none.  */
8547 
8548 static inline tree
omp_task_reductions_find_first(tree clauses,enum tree_code code,enum omp_clause_code ccode)8549 omp_task_reductions_find_first (tree clauses, enum tree_code code,
8550                                         enum omp_clause_code ccode)
8551 {
8552   while (1)
8553     {
8554       clauses = omp_find_clause (clauses, ccode);
8555       if (clauses == NULL_TREE)
8556           return NULL_TREE;
8557       if (ccode != OMP_CLAUSE_REDUCTION
8558             || code == OMP_TASKLOOP
8559             || OMP_CLAUSE_REDUCTION_TASK (clauses))
8560           return clauses;
8561       clauses = OMP_CLAUSE_CHAIN (clauses);
8562     }
8563 }
8564 
8565 static void lower_omp_task_reductions (omp_context *, enum tree_code, tree,
8566                                                gimple_seq *, gimple_seq *);
8567 
8568 /* Lower the OpenMP sections directive in the current statement in GSI_P.
8569    CTX is the enclosing OMP context for the current statement.  */
8570 
8571 static void
lower_omp_sections(gimple_stmt_iterator * gsi_p,omp_context * ctx)8572 lower_omp_sections (gimple_stmt_iterator *gsi_p, omp_context *ctx)
8573 {
8574   tree block, control;
8575   gimple_stmt_iterator tgsi;
8576   gomp_sections *stmt;
8577   gimple *t;
8578   gbind *new_stmt, *bind;
8579   gimple_seq ilist, dlist, olist, tred_dlist = NULL, clist = NULL, new_body;
8580 
8581   stmt = as_a <gomp_sections *> (gsi_stmt (*gsi_p));
8582 
8583   push_gimplify_context ();
8584 
8585   dlist = NULL;
8586   ilist = NULL;
8587 
8588   tree rclauses
8589     = omp_task_reductions_find_first (gimple_omp_sections_clauses (stmt),
8590                                               OMP_SECTIONS, OMP_CLAUSE_REDUCTION);
8591   tree rtmp = NULL_TREE;
8592   if (rclauses)
8593     {
8594       tree type = build_pointer_type (pointer_sized_int_node);
8595       tree temp = create_tmp_var (type);
8596       tree c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__REDUCTEMP_);
8597       OMP_CLAUSE_DECL (c) = temp;
8598       OMP_CLAUSE_CHAIN (c) = gimple_omp_sections_clauses (stmt);
8599       gimple_omp_sections_set_clauses (stmt, c);
8600       lower_omp_task_reductions (ctx, OMP_SECTIONS,
8601                                          gimple_omp_sections_clauses (stmt),
8602                                          &ilist, &tred_dlist);
8603       rclauses = c;
8604       rtmp = make_ssa_name (type);
8605       gimple_seq_add_stmt (&ilist, gimple_build_assign (rtmp, temp));
8606     }
8607 
8608   tree *clauses_ptr = gimple_omp_sections_clauses_ptr (stmt);
8609   lower_lastprivate_conditional_clauses (clauses_ptr, ctx);
8610 
8611   lower_rec_input_clauses (gimple_omp_sections_clauses (stmt),
8612                                  &ilist, &dlist, ctx, NULL);
8613 
8614   control = create_tmp_var (unsigned_type_node, ".section");
8615   gimple_omp_sections_set_control (stmt, control);
8616 
8617   new_body = gimple_omp_body (stmt);
8618   gimple_omp_set_body (stmt, NULL);
8619   tgsi = gsi_start (new_body);
8620   for (; !gsi_end_p (tgsi); gsi_next (&tgsi))
8621     {
8622       omp_context *sctx;
8623       gimple *sec_start;
8624 
8625       sec_start = gsi_stmt (tgsi);
8626       sctx = maybe_lookup_ctx (sec_start);
8627       gcc_assert (sctx);
8628 
8629       lower_omp (gimple_omp_body_ptr (sec_start), sctx);
8630       gsi_insert_seq_after (&tgsi, gimple_omp_body (sec_start),
8631                                   GSI_CONTINUE_LINKING);
8632       gimple_omp_set_body (sec_start, NULL);
8633 
8634       if (gsi_one_before_end_p (tgsi))
8635           {
8636             gimple_seq l = NULL;
8637             lower_lastprivate_clauses (gimple_omp_sections_clauses (stmt), NULL,
8638                                              &ilist, &l, &clist, ctx);
8639             gsi_insert_seq_after (&tgsi, l, GSI_CONTINUE_LINKING);
8640             gimple_omp_section_set_last (sec_start);
8641           }
8642 
8643       gsi_insert_after (&tgsi, gimple_build_omp_return (false),
8644                               GSI_CONTINUE_LINKING);
8645     }
8646 
8647   block = make_node (BLOCK);
8648   bind = gimple_build_bind (NULL, new_body, block);
8649 
8650   olist = NULL;
8651   lower_reduction_clauses (gimple_omp_sections_clauses (stmt), &olist,
8652                                  &clist, ctx);
8653   if (clist)
8654     {
8655       tree fndecl = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START);
8656       gcall *g = gimple_build_call (fndecl, 0);
8657       gimple_seq_add_stmt (&olist, g);
8658       gimple_seq_add_seq (&olist, clist);
8659       fndecl = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END);
8660       g = gimple_build_call (fndecl, 0);
8661       gimple_seq_add_stmt (&olist, g);
8662     }
8663 
8664   block = make_node (BLOCK);
8665   new_stmt = gimple_build_bind (NULL, NULL, block);
8666   gsi_replace (gsi_p, new_stmt, true);
8667 
8668   pop_gimplify_context (new_stmt);
8669   gimple_bind_append_vars (new_stmt, ctx->block_vars);
8670   BLOCK_VARS (block) = gimple_bind_vars (bind);
8671   if (BLOCK_VARS (block))
8672     TREE_USED (block) = 1;
8673 
8674   new_body = NULL;
8675   gimple_seq_add_seq (&new_body, ilist);
8676   gimple_seq_add_stmt (&new_body, stmt);
8677   gimple_seq_add_stmt (&new_body, gimple_build_omp_sections_switch ());
8678   gimple_seq_add_stmt (&new_body, bind);
8679 
8680   t = gimple_build_omp_continue (control, control);
8681   gimple_seq_add_stmt (&new_body, t);
8682 
8683   gimple_seq_add_seq (&new_body, olist);
8684   if (ctx->cancellable)
8685     gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
8686   gimple_seq_add_seq (&new_body, dlist);
8687 
8688   new_body = maybe_catch_exception (new_body);
8689 
8690   bool nowait = omp_find_clause (gimple_omp_sections_clauses (stmt),
8691                                          OMP_CLAUSE_NOWAIT) != NULL_TREE;
8692   t = gimple_build_omp_return (nowait);
8693   gimple_seq_add_stmt (&new_body, t);
8694   gimple_seq_add_seq (&new_body, tred_dlist);
8695   maybe_add_implicit_barrier_cancel (ctx, t, &new_body);
8696 
8697   if (rclauses)
8698     OMP_CLAUSE_DECL (rclauses) = rtmp;
8699 
8700   gimple_bind_set_body (new_stmt, new_body);
8701 }
8702 
8703 
8704 /* A subroutine of lower_omp_single.  Expand the simple form of
8705    a GIMPLE_OMP_SINGLE, without a copyprivate clause:
8706 
8707           if (GOMP_single_start ())
8708             BODY;
8709           [ GOMP_barrier (); ]          -> unless 'nowait' is present.
8710 
8711   FIXME.  It may be better to delay expanding the logic of this until
8712   pass_expand_omp.  The expanded logic may make the job more difficult
8713   to a synchronization analysis pass.  */
8714 
8715 static void
lower_omp_single_simple(gomp_single * single_stmt,gimple_seq * pre_p)8716 lower_omp_single_simple (gomp_single *single_stmt, gimple_seq *pre_p)
8717 {
8718   location_t loc = gimple_location (single_stmt);
8719   tree tlabel = create_artificial_label (loc);
8720   tree flabel = create_artificial_label (loc);
8721   gimple *call, *cond;
8722   tree lhs, decl;
8723 
8724   decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_START);
8725   lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (decl)));
8726   call = gimple_build_call (decl, 0);
8727   gimple_call_set_lhs (call, lhs);
8728   gimple_seq_add_stmt (pre_p, call);
8729 
8730   cond = gimple_build_cond (EQ_EXPR, lhs,
8731                                   fold_convert_loc (loc, TREE_TYPE (lhs),
8732                                                         boolean_true_node),
8733                                   tlabel, flabel);
8734   gimple_seq_add_stmt (pre_p, cond);
8735   gimple_seq_add_stmt (pre_p, gimple_build_label (tlabel));
8736   gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
8737   gimple_seq_add_stmt (pre_p, gimple_build_label (flabel));
8738 }
8739 
8740 
8741 /* A subroutine of lower_omp_single.  Expand the simple form of
8742    a GIMPLE_OMP_SINGLE, with a copyprivate clause:
8743 
8744           #pragma omp single copyprivate (a, b, c)
8745 
8746    Create a new structure to hold copies of 'a', 'b' and 'c' and emit:
8747 
8748       {
8749           if ((copyout_p = GOMP_single_copy_start ()) == NULL)
8750             {
8751               BODY;
8752               copyout.a = a;
8753               copyout.b = b;
8754               copyout.c = c;
8755               GOMP_single_copy_end (&copyout);
8756             }
8757           else
8758             {
8759               a = copyout_p->a;
8760               b = copyout_p->b;
8761               c = copyout_p->c;
8762             }
8763           GOMP_barrier ();
8764       }
8765 
8766   FIXME.  It may be better to delay expanding the logic of this until
8767   pass_expand_omp.  The expanded logic may make the job more difficult
8768   to a synchronization analysis pass.  */
8769 
8770 static void
lower_omp_single_copy(gomp_single * single_stmt,gimple_seq * pre_p,omp_context * ctx)8771 lower_omp_single_copy (gomp_single *single_stmt, gimple_seq *pre_p,
8772                            omp_context *ctx)
8773 {
8774   tree ptr_type, t, l0, l1, l2, bfn_decl;
8775   gimple_seq copyin_seq;
8776   location_t loc = gimple_location (single_stmt);
8777 
8778   ctx->sender_decl = create_tmp_var (ctx->record_type, ".omp_copy_o");
8779 
8780   ptr_type = build_pointer_type (ctx->record_type);
8781   ctx->receiver_decl = create_tmp_var (ptr_type, ".omp_copy_i");
8782 
8783   l0 = create_artificial_label (loc);
8784   l1 = create_artificial_label (loc);
8785   l2 = create_artificial_label (loc);
8786 
8787   bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_START);
8788   t = build_call_expr_loc (loc, bfn_decl, 0);
8789   t = fold_convert_loc (loc, ptr_type, t);
8790   gimplify_assign (ctx->receiver_decl, t, pre_p);
8791 
8792   t = build2 (EQ_EXPR, boolean_type_node, ctx->receiver_decl,
8793                 build_int_cst (ptr_type, 0));
8794   t = build3 (COND_EXPR, void_type_node, t,
8795                 build_and_jump (&l0), build_and_jump (&l1));
8796   gimplify_and_add (t, pre_p);
8797 
8798   gimple_seq_add_stmt (pre_p, gimple_build_label (l0));
8799 
8800   gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
8801 
8802   copyin_seq = NULL;
8803   lower_copyprivate_clauses (gimple_omp_single_clauses (single_stmt), pre_p,
8804                                     &copyin_seq, ctx);
8805 
8806   t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
8807   bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_END);
8808   t = build_call_expr_loc (loc, bfn_decl, 1, t);
8809   gimplify_and_add (t, pre_p);
8810 
8811   t = build_and_jump (&l2);
8812   gimplify_and_add (t, pre_p);
8813 
8814   gimple_seq_add_stmt (pre_p, gimple_build_label (l1));
8815 
8816   gimple_seq_add_seq (pre_p, copyin_seq);
8817 
8818   gimple_seq_add_stmt (pre_p, gimple_build_label (l2));
8819 }
8820 
8821 
8822 /* Expand code for an OpenMP single directive.  */
8823 
8824 static void
lower_omp_single(gimple_stmt_iterator * gsi_p,omp_context * ctx)8825 lower_omp_single (gimple_stmt_iterator *gsi_p, omp_context *ctx)
8826 {
8827   tree block;
8828   gomp_single *single_stmt = as_a <gomp_single *> (gsi_stmt (*gsi_p));
8829   gbind *bind;
8830   gimple_seq bind_body, bind_body_tail = NULL, dlist;
8831 
8832   push_gimplify_context ();
8833 
8834   block = make_node (BLOCK);
8835   bind = gimple_build_bind (NULL, NULL, block);
8836   gsi_replace (gsi_p, bind, true);
8837   bind_body = NULL;
8838   dlist = NULL;
8839   lower_rec_input_clauses (gimple_omp_single_clauses (single_stmt),
8840                                  &bind_body, &dlist, ctx, NULL);
8841   lower_omp (gimple_omp_body_ptr (single_stmt), ctx);
8842 
8843   gimple_seq_add_stmt (&bind_body, single_stmt);
8844 
8845   if (ctx->record_type)
8846     lower_omp_single_copy (single_stmt, &bind_body, ctx);
8847   else
8848     lower_omp_single_simple (single_stmt, &bind_body);
8849 
8850   gimple_omp_set_body (single_stmt, NULL);
8851 
8852   gimple_seq_add_seq (&bind_body, dlist);
8853 
8854   bind_body = maybe_catch_exception (bind_body);
8855 
8856   bool nowait = omp_find_clause (gimple_omp_single_clauses (single_stmt),
8857                                          OMP_CLAUSE_NOWAIT) != NULL_TREE;
8858   gimple *g = gimple_build_omp_return (nowait);
8859   gimple_seq_add_stmt (&bind_body_tail, g);
8860   maybe_add_implicit_barrier_cancel (ctx, g, &bind_body_tail);
8861   if (ctx->record_type)
8862     {
8863       gimple_stmt_iterator gsi = gsi_start (bind_body_tail);
8864       tree clobber = build_clobber (ctx->record_type);
8865       gsi_insert_after (&gsi, gimple_build_assign (ctx->sender_decl,
8866                                                                clobber), GSI_SAME_STMT);
8867     }
8868   gimple_seq_add_seq (&bind_body, bind_body_tail);
8869   gimple_bind_set_body (bind, bind_body);
8870 
8871   pop_gimplify_context (bind);
8872 
8873   gimple_bind_append_vars (bind, ctx->block_vars);
8874   BLOCK_VARS (block) = ctx->block_vars;
8875   if (BLOCK_VARS (block))
8876     TREE_USED (block) = 1;
8877 }
8878 
8879 
8880 /* Lower code for an OMP scope directive.  */
8881 
8882 static void
lower_omp_scope(gimple_stmt_iterator * gsi_p,omp_context * ctx)8883 lower_omp_scope (gimple_stmt_iterator *gsi_p, omp_context *ctx)
8884 {
8885   tree block;
8886   gimple *scope_stmt = gsi_stmt (*gsi_p);
8887   gbind *bind;
8888   gimple_seq bind_body, bind_body_tail = NULL, dlist;
8889   gimple_seq tred_dlist = NULL;
8890 
8891   push_gimplify_context ();
8892 
8893   block = make_node (BLOCK);
8894   bind = gimple_build_bind (NULL, NULL, block);
8895   gsi_replace (gsi_p, bind, true);
8896   bind_body = NULL;
8897   dlist = NULL;
8898 
8899   tree rclauses
8900     = omp_task_reductions_find_first (gimple_omp_scope_clauses (scope_stmt),
8901                                               OMP_SCOPE, OMP_CLAUSE_REDUCTION);
8902   if (rclauses)
8903     {
8904       tree type = build_pointer_type (pointer_sized_int_node);
8905       tree temp = create_tmp_var (type);
8906       tree c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__REDUCTEMP_);
8907       OMP_CLAUSE_DECL (c) = temp;
8908       OMP_CLAUSE_CHAIN (c) = gimple_omp_scope_clauses (scope_stmt);
8909       gimple_omp_scope_set_clauses (scope_stmt, c);
8910       lower_omp_task_reductions (ctx, OMP_SCOPE,
8911                                          gimple_omp_scope_clauses (scope_stmt),
8912                                          &bind_body, &tred_dlist);
8913       rclauses = c;
8914       tree fndecl = builtin_decl_explicit (BUILT_IN_GOMP_SCOPE_START);
8915       gimple *stmt = gimple_build_call (fndecl, 1, temp);
8916       gimple_seq_add_stmt (&bind_body, stmt);
8917     }
8918 
8919   lower_rec_input_clauses (gimple_omp_scope_clauses (scope_stmt),
8920                                  &bind_body, &dlist, ctx, NULL);
8921   lower_omp (gimple_omp_body_ptr (scope_stmt), ctx);
8922 
8923   gimple_seq_add_stmt (&bind_body, scope_stmt);
8924 
8925   gimple_seq_add_seq (&bind_body, gimple_omp_body (scope_stmt));
8926 
8927   gimple_omp_set_body (scope_stmt, NULL);
8928 
8929   gimple_seq clist = NULL;
8930   lower_reduction_clauses (gimple_omp_scope_clauses (scope_stmt),
8931                                  &bind_body, &clist, ctx);
8932   if (clist)
8933     {
8934       tree fndecl = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START);
8935       gcall *g = gimple_build_call (fndecl, 0);
8936       gimple_seq_add_stmt (&bind_body, g);
8937       gimple_seq_add_seq (&bind_body, clist);
8938       fndecl = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END);
8939       g = gimple_build_call (fndecl, 0);
8940       gimple_seq_add_stmt (&bind_body, g);
8941     }
8942 
8943   gimple_seq_add_seq (&bind_body, dlist);
8944 
8945   bind_body = maybe_catch_exception (bind_body);
8946 
8947   bool nowait = omp_find_clause (gimple_omp_scope_clauses (scope_stmt),
8948                                          OMP_CLAUSE_NOWAIT) != NULL_TREE;
8949   gimple *g = gimple_build_omp_return (nowait);
8950   gimple_seq_add_stmt (&bind_body_tail, g);
8951   gimple_seq_add_seq (&bind_body_tail, tred_dlist);
8952   maybe_add_implicit_barrier_cancel (ctx, g, &bind_body_tail);
8953   if (ctx->record_type)
8954     {
8955       gimple_stmt_iterator gsi = gsi_start (bind_body_tail);
8956       tree clobber = build_clobber (ctx->record_type);
8957       gsi_insert_after (&gsi, gimple_build_assign (ctx->sender_decl,
8958                                                                clobber), GSI_SAME_STMT);
8959     }
8960   gimple_seq_add_seq (&bind_body, bind_body_tail);
8961 
8962   gimple_bind_set_body (bind, bind_body);
8963 
8964   pop_gimplify_context (bind);
8965 
8966   gimple_bind_append_vars (bind, ctx->block_vars);
8967   BLOCK_VARS (block) = ctx->block_vars;
8968   if (BLOCK_VARS (block))
8969     TREE_USED (block) = 1;
8970 }
8971 /* Expand code for an OpenMP master or masked directive.  */
8972 
8973 static void
lower_omp_master(gimple_stmt_iterator * gsi_p,omp_context * ctx)8974 lower_omp_master (gimple_stmt_iterator *gsi_p, omp_context *ctx)
8975 {
8976   tree block, lab = NULL, x, bfn_decl;
8977   gimple *stmt = gsi_stmt (*gsi_p);
8978   gbind *bind;
8979   location_t loc = gimple_location (stmt);
8980   gimple_seq tseq;
8981   tree filter = integer_zero_node;
8982 
8983   push_gimplify_context ();
8984 
8985   if (gimple_code (stmt) == GIMPLE_OMP_MASKED)
8986     {
8987       filter = omp_find_clause (gimple_omp_masked_clauses (stmt),
8988                                         OMP_CLAUSE_FILTER);
8989       if (filter)
8990           filter = fold_convert (integer_type_node,
8991                                      OMP_CLAUSE_FILTER_EXPR (filter));
8992       else
8993           filter = integer_zero_node;
8994     }
8995   block = make_node (BLOCK);
8996   bind = gimple_build_bind (NULL, NULL, block);
8997   gsi_replace (gsi_p, bind, true);
8998   gimple_bind_add_stmt (bind, stmt);
8999 
9000   bfn_decl = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
9001   x = build_call_expr_loc (loc, bfn_decl, 0);
9002   x = build2 (EQ_EXPR, boolean_type_node, x, filter);
9003   x = build3 (COND_EXPR, void_type_node, x, NULL, build_and_jump (&lab));
9004   tseq = NULL;
9005   gimplify_and_add (x, &tseq);
9006   gimple_bind_add_seq (bind, tseq);
9007 
9008   lower_omp (gimple_omp_body_ptr (stmt), ctx);
9009   gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
9010   gimple_bind_add_seq (bind, gimple_omp_body (stmt));
9011   gimple_omp_set_body (stmt, NULL);
9012 
9013   gimple_bind_add_stmt (bind, gimple_build_label (lab));
9014 
9015   gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
9016 
9017   pop_gimplify_context (bind);
9018 
9019   gimple_bind_append_vars (bind, ctx->block_vars);
9020   BLOCK_VARS (block) = ctx->block_vars;
9021 }
9022 
9023 /* Helper function for lower_omp_task_reductions.  For a specific PASS
9024    find out the current clause it should be processed, or return false
9025    if all have been processed already.  */
9026 
9027 static inline bool
omp_task_reduction_iterate(int pass,enum tree_code code,enum omp_clause_code ccode,tree * c,tree * decl,tree * type,tree * next)9028 omp_task_reduction_iterate (int pass, enum tree_code code,
9029                                   enum omp_clause_code ccode, tree *c, tree *decl,
9030                                   tree *type, tree *next)
9031 {
9032   for (; *c; *c = omp_find_clause (OMP_CLAUSE_CHAIN (*c), ccode))
9033     {
9034       if (ccode == OMP_CLAUSE_REDUCTION
9035             && code != OMP_TASKLOOP
9036             && !OMP_CLAUSE_REDUCTION_TASK (*c))
9037           continue;
9038       *decl = OMP_CLAUSE_DECL (*c);
9039       *type = TREE_TYPE (*decl);
9040       if (TREE_CODE (*decl) == MEM_REF)
9041           {
9042             if (pass != 1)
9043               continue;
9044           }
9045       else
9046           {
9047             if (omp_privatize_by_reference (*decl))
9048               *type = TREE_TYPE (*type);
9049             if (pass != (!TREE_CONSTANT (TYPE_SIZE_UNIT (*type))))
9050               continue;
9051           }
9052       *next = omp_find_clause (OMP_CLAUSE_CHAIN (*c), ccode);
9053       return true;
9054     }
9055   *decl = NULL_TREE;
9056   *type = NULL_TREE;
9057   *next = NULL_TREE;
9058   return false;
9059 }
9060 
9061 /* Lower task_reduction and reduction clauses (the latter unless CODE is
9062    OMP_TASKGROUP only with task modifier).  Register mapping of those in
9063    START sequence and reducing them and unregister them in the END sequence.  */
9064 
9065 static void
lower_omp_task_reductions(omp_context * ctx,enum tree_code code,tree clauses,gimple_seq * start,gimple_seq * end)9066 lower_omp_task_reductions (omp_context *ctx, enum tree_code code, tree clauses,
9067                                  gimple_seq *start, gimple_seq *end)
9068 {
9069   enum omp_clause_code ccode
9070     = (code == OMP_TASKGROUP
9071        ? OMP_CLAUSE_TASK_REDUCTION : OMP_CLAUSE_REDUCTION);
9072   tree cancellable = NULL_TREE;
9073   clauses = omp_task_reductions_find_first (clauses, code, ccode);
9074   if (clauses == NULL_TREE)
9075     return;
9076   if (code == OMP_FOR || code == OMP_SECTIONS || code == OMP_SCOPE)
9077     {
9078       for (omp_context *outer = ctx->outer; outer; outer = outer->outer)
9079           if (gimple_code (outer->stmt) == GIMPLE_OMP_PARALLEL
9080               && outer->cancellable)
9081             {
9082               cancellable = error_mark_node;
9083               break;
9084             }
9085           else if (gimple_code (outer->stmt) != GIMPLE_OMP_TASKGROUP
9086                      && gimple_code (outer->stmt) != GIMPLE_OMP_SCOPE)
9087             break;
9088     }
9089   tree record_type = lang_hooks.types.make_type (RECORD_TYPE);
9090   tree *last = &TYPE_FIELDS (record_type);
9091   unsigned cnt = 0;
9092   if (cancellable)
9093     {
9094       tree field = build_decl (UNKNOWN_LOCATION, FIELD_DECL, NULL_TREE,
9095                                      ptr_type_node);
9096       tree ifield = build_decl (UNKNOWN_LOCATION, FIELD_DECL, NULL_TREE,
9097                                         integer_type_node);
9098       *last = field;
9099       DECL_CHAIN (field) = ifield;
9100       last = &DECL_CHAIN (ifield);
9101       DECL_CONTEXT (field) = record_type;
9102       if (TYPE_ALIGN (record_type) < DECL_ALIGN (field))
9103           SET_TYPE_ALIGN (record_type, DECL_ALIGN (field));
9104       DECL_CONTEXT (ifield) = record_type;
9105       if (TYPE_ALIGN (record_type) < DECL_ALIGN (ifield))
9106           SET_TYPE_ALIGN (record_type, DECL_ALIGN (ifield));
9107     }
9108   for (int pass = 0; pass < 2; pass++)
9109     {
9110       tree decl, type, next;
9111       for (tree c = clauses;
9112              omp_task_reduction_iterate (pass, code, ccode,
9113                                                &c, &decl, &type, &next); c = next)
9114           {
9115             ++cnt;
9116             tree new_type = type;
9117             if (ctx->outer)
9118               new_type = remap_type (type, &ctx->outer->cb);
9119             tree field
9120               = build_decl (OMP_CLAUSE_LOCATION (c), FIELD_DECL,
9121                                 DECL_P (decl) ? DECL_NAME (decl) : NULL_TREE,
9122                                 new_type);
9123             if (DECL_P (decl) && type == TREE_TYPE (decl))
9124               {
9125                 SET_DECL_ALIGN (field, DECL_ALIGN (decl));
9126                 DECL_USER_ALIGN (field) = DECL_USER_ALIGN (decl);
9127                 TREE_THIS_VOLATILE (field) = TREE_THIS_VOLATILE (decl);
9128               }
9129             else
9130               SET_DECL_ALIGN (field, TYPE_ALIGN (type));
9131             DECL_CONTEXT (field) = record_type;
9132             if (TYPE_ALIGN (record_type) < DECL_ALIGN (field))
9133               SET_TYPE_ALIGN (record_type, DECL_ALIGN (field));
9134             *last = field;
9135             last = &DECL_CHAIN (field);
9136             tree bfield
9137               = build_decl (OMP_CLAUSE_LOCATION (c), FIELD_DECL, NULL_TREE,
9138                                 boolean_type_node);
9139             DECL_CONTEXT (bfield) = record_type;
9140             if (TYPE_ALIGN (record_type) < DECL_ALIGN (bfield))
9141               SET_TYPE_ALIGN (record_type, DECL_ALIGN (bfield));
9142             *last = bfield;
9143             last = &DECL_CHAIN (bfield);
9144           }
9145     }
9146   *last = NULL_TREE;
9147   layout_type (record_type);
9148 
9149   /* Build up an array which registers with the runtime all the reductions
9150      and deregisters them at the end.  Format documented in libgomp/task.c.  */
9151   tree atype = build_array_type_nelts (pointer_sized_int_node, 7 + cnt * 3);
9152   tree avar = create_tmp_var_raw (atype);
9153   gimple_add_tmp_var (avar);
9154   TREE_ADDRESSABLE (avar) = 1;
9155   tree r = build4 (ARRAY_REF, pointer_sized_int_node, avar, size_zero_node,
9156                        NULL_TREE, NULL_TREE);
9157   tree t = build_int_cst (pointer_sized_int_node, cnt);
9158   gimple_seq_add_stmt (start, gimple_build_assign (r, t));
9159   gimple_seq seq = NULL;
9160   tree sz = fold_convert (pointer_sized_int_node,
9161                                 TYPE_SIZE_UNIT (record_type));
9162   int cachesz = 64;
9163   sz = fold_build2 (PLUS_EXPR, pointer_sized_int_node, sz,
9164                         build_int_cst (pointer_sized_int_node, cachesz - 1));
9165   sz = fold_build2 (BIT_AND_EXPR, pointer_sized_int_node, sz,
9166                         build_int_cst (pointer_sized_int_node, ~(cachesz - 1)));
9167   ctx->task_reductions.create (1 + cnt);
9168   ctx->task_reduction_map = new hash_map<tree, unsigned>;
9169   ctx->task_reductions.quick_push (TREE_CODE (sz) == INTEGER_CST
9170                                            ? sz : NULL_TREE);
9171   sz = force_gimple_operand (sz, &seq, true, NULL_TREE);
9172   gimple_seq_add_seq (start, seq);
9173   r = build4 (ARRAY_REF, pointer_sized_int_node, avar, size_one_node,
9174                 NULL_TREE, NULL_TREE);
9175   gimple_seq_add_stmt (start, gimple_build_assign (r, sz));
9176   r = build4 (ARRAY_REF, pointer_sized_int_node, avar, size_int (2),
9177                 NULL_TREE, NULL_TREE);
9178   t = build_int_cst (pointer_sized_int_node,
9179                          MAX (TYPE_ALIGN_UNIT (record_type), (unsigned) cachesz));
9180   gimple_seq_add_stmt (start, gimple_build_assign (r, t));
9181   r = build4 (ARRAY_REF, pointer_sized_int_node, avar, size_int (3),
9182                 NULL_TREE, NULL_TREE);
9183   t = build_int_cst (pointer_sized_int_node, -1);
9184   gimple_seq_add_stmt (start, gimple_build_assign (r, t));
9185   r = build4 (ARRAY_REF, pointer_sized_int_node, avar, size_int (4),
9186                 NULL_TREE, NULL_TREE);
9187   t = build_int_cst (pointer_sized_int_node, 0);
9188   gimple_seq_add_stmt (start, gimple_build_assign (r, t));
9189 
9190   /* In end, build a loop that iterates from 0 to < omp_get_num_threads ()
9191      and for each task reduction checks a bool right after the private variable
9192      within that thread's chunk; if the bool is clear, it hasn't been
9193      initialized and thus isn't going to be reduced nor destructed, otherwise
9194      reduce and destruct it.  */
9195   tree idx = create_tmp_var (size_type_node);
9196   gimple_seq_add_stmt (end, gimple_build_assign (idx, size_zero_node));
9197   tree num_thr_sz = create_tmp_var (size_type_node);
9198   tree lab1 = create_artificial_label (UNKNOWN_LOCATION);
9199   tree lab2 = create_artificial_label (UNKNOWN_LOCATION);
9200   tree lab3 = NULL_TREE, lab7 = NULL_TREE;
9201   gimple *g;
9202   if (code == OMP_FOR || code == OMP_SECTIONS || code == OMP_SCOPE)
9203     {
9204       /* For worksharing constructs or scope, only perform it in the master
9205            thread, with the exception of cancelled implicit barriers - then only
9206            handle the current thread.  */
9207       tree lab4 = create_artificial_label (UNKNOWN_LOCATION);
9208       t = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
9209       tree thr_num = create_tmp_var (integer_type_node);
9210       g = gimple_build_call (t, 0);
9211       gimple_call_set_lhs (g, thr_num);
9212       gimple_seq_add_stmt (end, g);
9213       if (cancellable)
9214           {
9215             tree c;
9216             tree lab5 = create_artificial_label (UNKNOWN_LOCATION);
9217             tree lab6 = create_artificial_label (UNKNOWN_LOCATION);
9218             lab3 = create_artificial_label (UNKNOWN_LOCATION);
9219             if (code == OMP_FOR)
9220               c = gimple_omp_for_clauses (ctx->stmt);
9221             else if (code == OMP_SECTIONS)
9222               c = gimple_omp_sections_clauses (ctx->stmt);
9223             else /* if (code == OMP_SCOPE) */
9224               c = gimple_omp_scope_clauses (ctx->stmt);
9225             c = OMP_CLAUSE_DECL (omp_find_clause (c, OMP_CLAUSE__REDUCTEMP_));
9226             cancellable = c;
9227             g = gimple_build_cond (NE_EXPR, c, build_zero_cst (TREE_TYPE (c)),
9228                                          lab5, lab6);
9229             gimple_seq_add_stmt (end, g);
9230             gimple_seq_add_stmt (end, gimple_build_label (lab5));
9231             g = gimple_build_assign (idx, NOP_EXPR, thr_num);
9232             gimple_seq_add_stmt (end, g);
9233             g = gimple_build_assign (num_thr_sz, PLUS_EXPR, idx,
9234                                            build_one_cst (TREE_TYPE (idx)));
9235             gimple_seq_add_stmt (end, g);
9236             gimple_seq_add_stmt (end, gimple_build_goto (lab3));
9237             gimple_seq_add_stmt (end, gimple_build_label (lab6));
9238           }
9239       g = gimple_build_cond (NE_EXPR, thr_num, integer_zero_node, lab2, lab4);
9240       gimple_seq_add_stmt (end, g);
9241       gimple_seq_add_stmt (end, gimple_build_label (lab4));
9242     }
9243   if (code != OMP_PARALLEL)
9244     {
9245       t = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
9246       tree num_thr = create_tmp_var (integer_type_node);
9247       g = gimple_build_call (t, 0);
9248       gimple_call_set_lhs (g, num_thr);
9249       gimple_seq_add_stmt (end, g);
9250       g = gimple_build_assign (num_thr_sz, NOP_EXPR, num_thr);
9251       gimple_seq_add_stmt (end, g);
9252       if (cancellable)
9253           gimple_seq_add_stmt (end, gimple_build_label (lab3));
9254     }
9255   else
9256     {
9257       tree c = omp_find_clause (gimple_omp_parallel_clauses (ctx->stmt),
9258                                         OMP_CLAUSE__REDUCTEMP_);
9259       t = fold_convert (pointer_sized_int_node, OMP_CLAUSE_DECL (c));
9260       t = fold_convert (size_type_node, t);
9261       gimplify_assign (num_thr_sz, t, end);
9262     }
9263   t = build4 (ARRAY_REF, pointer_sized_int_node, avar, size_int (2),
9264                 NULL_TREE, NULL_TREE);
9265   tree data = create_tmp_var (pointer_sized_int_node);
9266   gimple_seq_add_stmt (end, gimple_build_assign (data, t));
9267   if (code == OMP_TASKLOOP)
9268     {
9269       lab7 = create_artificial_label (UNKNOWN_LOCATION);
9270       g = gimple_build_cond (NE_EXPR, data,
9271                                    build_zero_cst (pointer_sized_int_node),
9272                                    lab1, lab7);
9273       gimple_seq_add_stmt (end, g);
9274     }
9275   gimple_seq_add_stmt (end, gimple_build_label (lab1));
9276   tree ptr;
9277   if (TREE_CODE (TYPE_SIZE_UNIT (record_type)) == INTEGER_CST)
9278     ptr = create_tmp_var (build_pointer_type (record_type));
9279   else
9280     ptr = create_tmp_var (ptr_type_node);
9281   gimple_seq_add_stmt (end, gimple_build_assign (ptr, NOP_EXPR, data));
9282 
9283   tree field = TYPE_FIELDS (record_type);
9284   cnt = 0;
9285   if (cancellable)
9286     field = DECL_CHAIN (DECL_CHAIN (field));
9287   for (int pass = 0; pass < 2; pass++)
9288     {
9289       tree decl, type, next;
9290       for (tree c = clauses;
9291              omp_task_reduction_iterate (pass, code, ccode,
9292                                                &c, &decl, &type, &next); c = next)
9293           {
9294             tree var = decl, ref;
9295             if (TREE_CODE (decl) == MEM_REF)
9296               {
9297                 var = TREE_OPERAND (var, 0);
9298                 if (TREE_CODE (var) == POINTER_PLUS_EXPR)
9299                     var = TREE_OPERAND (var, 0);
9300                 tree v = var;
9301                 if (TREE_CODE (var) == ADDR_EXPR)
9302                     var = TREE_OPERAND (var, 0);
9303                 else if (TREE_CODE (var) == INDIRECT_REF)
9304                     var = TREE_OPERAND (var, 0);
9305                 tree orig_var = var;
9306                 if (is_variable_sized (var))
9307                     {
9308                       gcc_assert (DECL_HAS_VALUE_EXPR_P (var));
9309                       var = DECL_VALUE_EXPR (var);
9310                       gcc_assert (TREE_CODE (var) == INDIRECT_REF);
9311                       var = TREE_OPERAND (var, 0);
9312                       gcc_assert (DECL_P (var));
9313                     }
9314                 t = ref = maybe_lookup_decl_in_outer_ctx (var, ctx);
9315                 if (orig_var != var)
9316                     gcc_assert (TREE_CODE (v) == ADDR_EXPR);
9317                 else if (TREE_CODE (v) == ADDR_EXPR)
9318                     t = build_fold_addr_expr (t);
9319                 else if (TREE_CODE (v) == INDIRECT_REF)
9320                     t = build_fold_indirect_ref (t);
9321                 if (TREE_CODE (TREE_OPERAND (decl, 0)) == POINTER_PLUS_EXPR)
9322                     {
9323                       tree b = TREE_OPERAND (TREE_OPERAND (decl, 0), 1);
9324                       b = maybe_lookup_decl_in_outer_ctx (b, ctx);
9325                       t = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (t), t, b);
9326                     }
9327                 if (!integer_zerop (TREE_OPERAND (decl, 1)))
9328                     t = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (t), t,
9329                                          fold_convert (size_type_node,
9330                                                          TREE_OPERAND (decl, 1)));
9331               }
9332             else
9333               {
9334                 t = ref = maybe_lookup_decl_in_outer_ctx (var, ctx);
9335                 if (!omp_privatize_by_reference (decl))
9336                     t = build_fold_addr_expr (t);
9337               }
9338             t = fold_convert (pointer_sized_int_node, t);
9339             seq = NULL;
9340             t = force_gimple_operand (t, &seq, true, NULL_TREE);
9341             gimple_seq_add_seq (start, seq);
9342             r = build4 (ARRAY_REF, pointer_sized_int_node, avar,
9343                           size_int (7 + cnt * 3), NULL_TREE, NULL_TREE);
9344             gimple_seq_add_stmt (start, gimple_build_assign (r, t));
9345             t = unshare_expr (byte_position (field));
9346             t = fold_convert (pointer_sized_int_node, t);
9347             ctx->task_reduction_map->put (c, cnt);
9348             ctx->task_reductions.quick_push (TREE_CODE (t) == INTEGER_CST
9349                                                      ? t : NULL_TREE);
9350             seq = NULL;
9351             t = force_gimple_operand (t, &seq, true, NULL_TREE);
9352             gimple_seq_add_seq (start, seq);
9353             r = build4 (ARRAY_REF, pointer_sized_int_node, avar,
9354                           size_int (7 + cnt * 3 + 1), NULL_TREE, NULL_TREE);
9355             gimple_seq_add_stmt (start, gimple_build_assign (r, t));
9356 
9357             tree bfield = DECL_CHAIN (field);
9358             tree cond;
9359             if (code == OMP_PARALLEL
9360                 || code == OMP_FOR
9361                 || code == OMP_SECTIONS
9362                 || code == OMP_SCOPE)
9363               /* In parallel, worksharing or scope all threads unconditionally
9364                  initialize all their task reduction private variables.  */
9365               cond = boolean_true_node;
9366             else if (TREE_TYPE (ptr) == ptr_type_node)
9367               {
9368                 cond = build2 (POINTER_PLUS_EXPR, ptr_type_node, ptr,
9369                                    unshare_expr (byte_position (bfield)));
9370                 seq = NULL;
9371                 cond = force_gimple_operand (cond, &seq, true, NULL_TREE);
9372                 gimple_seq_add_seq (end, seq);
9373                 tree pbool = build_pointer_type (TREE_TYPE (bfield));
9374                 cond = build2 (MEM_REF, TREE_TYPE (bfield), cond,
9375                                    build_int_cst (pbool, 0));
9376               }
9377             else
9378               cond = build3 (COMPONENT_REF, TREE_TYPE (bfield),
9379                                  build_simple_mem_ref (ptr), bfield, NULL_TREE);
9380             tree lab3 = create_artificial_label (UNKNOWN_LOCATION);
9381             tree lab4 = create_artificial_label (UNKNOWN_LOCATION);
9382             tree condv = create_tmp_var (boolean_type_node);
9383             gimple_seq_add_stmt (end, gimple_build_assign (condv, cond));
9384             g = gimple_build_cond (NE_EXPR, condv, boolean_false_node,
9385                                          lab3, lab4);
9386             gimple_seq_add_stmt (end, g);
9387             gimple_seq_add_stmt (end, gimple_build_label (lab3));
9388             if (cancellable && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) == NULL_TREE)
9389               {
9390                 /* If this reduction doesn't need destruction and parallel
9391                      has been cancelled, there is nothing to do for this
9392                      reduction, so jump around the merge operation.  */
9393                 tree lab5 = create_artificial_label (UNKNOWN_LOCATION);
9394                 g = gimple_build_cond (NE_EXPR, cancellable,
9395                                              build_zero_cst (TREE_TYPE (cancellable)),
9396                                              lab4, lab5);
9397                 gimple_seq_add_stmt (end, g);
9398                 gimple_seq_add_stmt (end, gimple_build_label (lab5));
9399               }
9400 
9401             tree new_var;
9402             if (TREE_TYPE (ptr) == ptr_type_node)
9403               {
9404                 new_var = build2 (POINTER_PLUS_EXPR, ptr_type_node, ptr,
9405                                         unshare_expr (byte_position (field)));
9406                 seq = NULL;
9407                 new_var = force_gimple_operand (new_var, &seq, true, NULL_TREE);
9408                 gimple_seq_add_seq (end, seq);
9409                 tree pbool = build_pointer_type (TREE_TYPE (field));
9410                 new_var = build2 (MEM_REF, TREE_TYPE (field), new_var,
9411                                         build_int_cst (pbool, 0));
9412               }
9413             else
9414               new_var = build3 (COMPONENT_REF, TREE_TYPE (field),
9415                                     build_simple_mem_ref (ptr), field, NULL_TREE);
9416 
9417             enum tree_code rcode = OMP_CLAUSE_REDUCTION_CODE (c);
9418             if (TREE_CODE (decl) != MEM_REF
9419                 && omp_privatize_by_reference (decl))
9420               ref = build_simple_mem_ref (ref);
9421             /* reduction(-:var) sums up the partial results, so it acts
9422                identically to reduction(+:var).  */
9423             if (rcode == MINUS_EXPR)
9424               rcode = PLUS_EXPR;
9425             if (TREE_CODE (decl) == MEM_REF)
9426               {
9427                 tree type = TREE_TYPE (new_var);
9428                 tree v = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
9429                 tree i = create_tmp_var (TREE_TYPE (v));
9430                 tree ptype = build_pointer_type (TREE_TYPE (type));
9431                 if (DECL_P (v))
9432                     {
9433                       v = maybe_lookup_decl_in_outer_ctx (v, ctx);
9434                       tree vv = create_tmp_var (TREE_TYPE (v));
9435                       gimplify_assign (vv, v, start);
9436                       v = vv;
9437                     }
9438                 ref = build4 (ARRAY_REF, pointer_sized_int_node, avar,
9439                                   size_int (7 + cnt * 3), NULL_TREE, NULL_TREE);
9440                 new_var = build_fold_addr_expr (new_var);
9441                 new_var = fold_convert (ptype, new_var);
9442                 ref = fold_convert (ptype, ref);
9443                 tree m = create_tmp_var (ptype);
9444                 gimplify_assign (m, new_var, end);
9445                 new_var = m;
9446                 m = create_tmp_var (ptype);
9447                 gimplify_assign (m, ref, end);
9448                 ref = m;
9449                 gimplify_assign (i, build_int_cst (TREE_TYPE (v), 0), end);
9450                 tree body = create_artificial_label (UNKNOWN_LOCATION);
9451                 tree endl = create_artificial_label (UNKNOWN_LOCATION);
9452                 gimple_seq_add_stmt (end, gimple_build_label (body));
9453                 tree priv = build_simple_mem_ref (new_var);
9454                 tree out = build_simple_mem_ref (ref);
9455                 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
9456                     {
9457                       tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
9458                       tree decl_placeholder
9459                         = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c);
9460                       tree lab6 = NULL_TREE;
9461                       if (cancellable)
9462                         {
9463                           /* If this reduction needs destruction and parallel
9464                                has been cancelled, jump around the merge operation
9465                                to the destruction.  */
9466                           tree lab5 = create_artificial_label (UNKNOWN_LOCATION);
9467                           lab6 = create_artificial_label (UNKNOWN_LOCATION);
9468                           tree zero = build_zero_cst (TREE_TYPE (cancellable));
9469                           g = gimple_build_cond (NE_EXPR, cancellable, zero,
9470                                                        lab6, lab5);
9471                           gimple_seq_add_stmt (end, g);
9472                           gimple_seq_add_stmt (end, gimple_build_label (lab5));
9473                         }
9474                       SET_DECL_VALUE_EXPR (placeholder, out);
9475                       DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
9476                       SET_DECL_VALUE_EXPR (decl_placeholder, priv);
9477                       DECL_HAS_VALUE_EXPR_P (decl_placeholder) = 1;
9478                       lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
9479                       gimple_seq_add_seq (end,
9480                                               OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
9481                       OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
9482                       if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_TASK_REDUCTION)
9483                         {
9484                           OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
9485                           OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c) = NULL;
9486                         }
9487                       if (cancellable)
9488                         gimple_seq_add_stmt (end, gimple_build_label (lab6));
9489                       tree x = lang_hooks.decls.omp_clause_dtor (c, priv);
9490                       if (x)
9491                         {
9492                           gimple_seq tseq = NULL;
9493                           gimplify_stmt (&x, &tseq);
9494                           gimple_seq_add_seq (end, tseq);
9495                         }
9496                     }
9497                 else
9498                     {
9499                       tree x = build2 (rcode, TREE_TYPE (out), out, priv);
9500                       out = unshare_expr (out);
9501                       gimplify_assign (out, x, end);
9502                     }
9503                 gimple *g
9504                     = gimple_build_assign (new_var, POINTER_PLUS_EXPR, new_var,
9505                                                TYPE_SIZE_UNIT (TREE_TYPE (type)));
9506                 gimple_seq_add_stmt (end, g);
9507                 g = gimple_build_assign (ref, POINTER_PLUS_EXPR, ref,
9508                                                TYPE_SIZE_UNIT (TREE_TYPE (type)));
9509                 gimple_seq_add_stmt (end, g);
9510                 g = gimple_build_assign (i, PLUS_EXPR, i,
9511                                                build_int_cst (TREE_TYPE (i), 1));
9512                 gimple_seq_add_stmt (end, g);
9513                 g = gimple_build_cond (LE_EXPR, i, v, body, endl);
9514                 gimple_seq_add_stmt (end, g);
9515                 gimple_seq_add_stmt (end, gimple_build_label (endl));
9516               }
9517             else if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
9518               {
9519                 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
9520                 tree oldv = NULL_TREE;
9521                 tree lab6 = NULL_TREE;
9522                 if (cancellable)
9523                     {
9524                       /* If this reduction needs destruction and parallel
9525                          has been cancelled, jump around the merge operation
9526                          to the destruction.  */
9527                       tree lab5 = create_artificial_label (UNKNOWN_LOCATION);
9528                       lab6 = create_artificial_label (UNKNOWN_LOCATION);
9529                       tree zero = build_zero_cst (TREE_TYPE (cancellable));
9530                       g = gimple_build_cond (NE_EXPR, cancellable, zero,
9531                                                    lab6, lab5);
9532                       gimple_seq_add_stmt (end, g);
9533                       gimple_seq_add_stmt (end, gimple_build_label (lab5));
9534                     }
9535                 if (omp_privatize_by_reference (decl)
9536                       && !useless_type_conversion_p (TREE_TYPE (placeholder),
9537                                                              TREE_TYPE (ref)))
9538                     ref = build_fold_addr_expr_loc (OMP_CLAUSE_LOCATION (c), ref);
9539                 ref = build_fold_addr_expr_loc (OMP_CLAUSE_LOCATION (c), ref);
9540                 tree refv = create_tmp_var (TREE_TYPE (ref));
9541                 gimplify_assign (refv, ref, end);
9542                 ref = build_simple_mem_ref_loc (OMP_CLAUSE_LOCATION (c), refv);
9543                 SET_DECL_VALUE_EXPR (placeholder, ref);
9544                 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
9545                 tree d = maybe_lookup_decl (decl, ctx);
9546                 gcc_assert (d);
9547                 if (DECL_HAS_VALUE_EXPR_P (d))
9548                     oldv = DECL_VALUE_EXPR (d);
9549                 if (omp_privatize_by_reference (var))
9550                     {
9551                       tree v = fold_convert (TREE_TYPE (d),
9552                                                    build_fold_addr_expr (new_var));
9553                       SET_DECL_VALUE_EXPR (d, v);
9554                     }
9555                 else
9556                     SET_DECL_VALUE_EXPR (d, new_var);
9557                 DECL_HAS_VALUE_EXPR_P (d) = 1;
9558                 lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
9559                 if (oldv)
9560                     SET_DECL_VALUE_EXPR (d, oldv);
9561                 else
9562                     {
9563                       SET_DECL_VALUE_EXPR (d, NULL_TREE);
9564                       DECL_HAS_VALUE_EXPR_P (d) = 0;
9565                     }
9566                 gimple_seq_add_seq (end, OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
9567                 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
9568                 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_TASK_REDUCTION)
9569                     OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
9570                 if (cancellable)
9571                     gimple_seq_add_stmt (end, gimple_build_label (lab6));
9572                 tree x = lang_hooks.decls.omp_clause_dtor (c, new_var);
9573                 if (x)
9574                     {
9575                       gimple_seq tseq = NULL;
9576                       gimplify_stmt (&x, &tseq);
9577                       gimple_seq_add_seq (end, tseq);
9578                     }
9579               }
9580             else
9581               {
9582                 tree x = build2 (rcode, TREE_TYPE (ref), ref, new_var);
9583                 ref = unshare_expr (ref);
9584                 gimplify_assign (ref, x, end);
9585               }
9586             gimple_seq_add_stmt (end, gimple_build_label (lab4));
9587             ++cnt;
9588             field = DECL_CHAIN (bfield);
9589           }
9590     }
9591 
9592   if (code == OMP_TASKGROUP)
9593     {
9594       t = builtin_decl_explicit (BUILT_IN_GOMP_TASKGROUP_REDUCTION_REGISTER);
9595       g = gimple_build_call (t, 1, build_fold_addr_expr (avar));
9596       gimple_seq_add_stmt (start, g);
9597     }
9598   else
9599     {
9600       tree c;
9601       if (code == OMP_FOR)
9602           c = gimple_omp_for_clauses (ctx->stmt);
9603       else if (code == OMP_SECTIONS)
9604           c = gimple_omp_sections_clauses (ctx->stmt);
9605       else if (code == OMP_SCOPE)
9606           c = gimple_omp_scope_clauses (ctx->stmt);
9607       else
9608           c = gimple_omp_taskreg_clauses (ctx->stmt);
9609       c = omp_find_clause (c, OMP_CLAUSE__REDUCTEMP_);
9610       t = fold_convert (TREE_TYPE (OMP_CLAUSE_DECL (c)),
9611                               build_fold_addr_expr (avar));
9612       gimplify_assign (OMP_CLAUSE_DECL (c), t, start);
9613     }
9614 
9615   gimple_seq_add_stmt (end, gimple_build_assign (data, PLUS_EXPR, data, sz));
9616   gimple_seq_add_stmt (end, gimple_build_assign (idx, PLUS_EXPR, idx,
9617                                                              size_one_node));
9618   g = gimple_build_cond (NE_EXPR, idx, num_thr_sz, lab1, lab2);
9619   gimple_seq_add_stmt (end, g);
9620   gimple_seq_add_stmt (end, gimple_build_label (lab2));
9621   if (code == OMP_FOR || code == OMP_SECTIONS || code == OMP_SCOPE)
9622     {
9623       enum built_in_function bfn
9624           = BUILT_IN_GOMP_WORKSHARE_TASK_REDUCTION_UNREGISTER;
9625       t = builtin_decl_explicit (bfn);
9626       tree c_bool_type = TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (t)));
9627       tree arg;
9628       if (cancellable)
9629           {
9630             arg = create_tmp_var (c_bool_type);
9631             gimple_seq_add_stmt (end, gimple_build_assign (arg, NOP_EXPR,
9632                                                                        cancellable));
9633           }
9634       else
9635           arg = build_int_cst (c_bool_type, 0);
9636       g = gimple_build_call (t, 1, arg);
9637     }
9638   else
9639     {
9640       t = builtin_decl_explicit (BUILT_IN_GOMP_TASKGROUP_REDUCTION_UNREGISTER);
9641       g = gimple_build_call (t, 1, build_fold_addr_expr (avar));
9642     }
9643   gimple_seq_add_stmt (end, g);
9644   if (lab7)
9645     gimple_seq_add_stmt (end, gimple_build_label (lab7));
9646   t = build_constructor (atype, NULL);
9647   TREE_THIS_VOLATILE (t) = 1;
9648   gimple_seq_add_stmt (end, gimple_build_assign (avar, t));
9649 }
9650 
9651 /* Expand code for an OpenMP taskgroup directive.  */
9652 
9653 static void
lower_omp_taskgroup(gimple_stmt_iterator * gsi_p,omp_context * ctx)9654 lower_omp_taskgroup (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9655 {
9656   gimple *stmt = gsi_stmt (*gsi_p);
9657   gcall *x;
9658   gbind *bind;
9659   gimple_seq dseq = NULL;
9660   tree block = make_node (BLOCK);
9661 
9662   bind = gimple_build_bind (NULL, NULL, block);
9663   gsi_replace (gsi_p, bind, true);
9664   gimple_bind_add_stmt (bind, stmt);
9665 
9666   push_gimplify_context ();
9667 
9668   x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_TASKGROUP_START),
9669                                0);
9670   gimple_bind_add_stmt (bind, x);
9671 
9672   lower_omp_task_reductions (ctx, OMP_TASKGROUP,
9673                                    gimple_omp_taskgroup_clauses (stmt),
9674                                    gimple_bind_body_ptr (bind), &dseq);
9675 
9676   lower_omp (gimple_omp_body_ptr (stmt), ctx);
9677   gimple_bind_add_seq (bind, gimple_omp_body (stmt));
9678   gimple_omp_set_body (stmt, NULL);
9679 
9680   gimple_bind_add_seq (bind, dseq);
9681 
9682   pop_gimplify_context (bind);
9683 
9684   gimple_bind_append_vars (bind, ctx->block_vars);
9685   BLOCK_VARS (block) = ctx->block_vars;
9686 }
9687 
9688 
9689 /* Fold the OMP_ORDERED_CLAUSES for the OMP_ORDERED in STMT if possible.  */
9690 
9691 static void
lower_omp_ordered_clauses(gimple_stmt_iterator * gsi_p,gomp_ordered * ord_stmt,omp_context * ctx)9692 lower_omp_ordered_clauses (gimple_stmt_iterator *gsi_p, gomp_ordered *ord_stmt,
9693                                  omp_context *ctx)
9694 {
9695   struct omp_for_data fd;
9696   if (!ctx->outer || gimple_code (ctx->outer->stmt) != GIMPLE_OMP_FOR)
9697     return;
9698 
9699   unsigned int len = gimple_omp_for_collapse (ctx->outer->stmt);
9700   struct omp_for_data_loop *loops = XALLOCAVEC (struct omp_for_data_loop, len);
9701   omp_extract_for_data (as_a <gomp_for *> (ctx->outer->stmt), &fd, loops);
9702   if (!fd.ordered)
9703     return;
9704 
9705   tree *list_p = gimple_omp_ordered_clauses_ptr (ord_stmt);
9706   tree c = gimple_omp_ordered_clauses (ord_stmt);
9707   if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
9708       && OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK)
9709     {
9710       /* Merge depend clauses from multiple adjacent
9711            #pragma omp ordered depend(sink:...) constructs
9712            into one #pragma omp ordered depend(sink:...), so that
9713            we can optimize them together.  */
9714       gimple_stmt_iterator gsi = *gsi_p;
9715       gsi_next (&gsi);
9716       while (!gsi_end_p (gsi))
9717           {
9718             gimple *stmt = gsi_stmt (gsi);
9719             if (is_gimple_debug (stmt)
9720                 || gimple_code (stmt) == GIMPLE_NOP)
9721               {
9722                 gsi_next (&gsi);
9723                 continue;
9724               }
9725             if (gimple_code (stmt) != GIMPLE_OMP_ORDERED)
9726               break;
9727             gomp_ordered *ord_stmt2 = as_a <gomp_ordered *> (stmt);
9728             c = gimple_omp_ordered_clauses (ord_stmt2);
9729             if (c == NULL_TREE
9730                 || OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND
9731                 || OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_SINK)
9732               break;
9733             while (*list_p)
9734               list_p = &OMP_CLAUSE_CHAIN (*list_p);
9735             *list_p = c;
9736             gsi_remove (&gsi, true);
9737           }
9738     }
9739 
9740   /* Canonicalize sink dependence clauses into one folded clause if
9741      possible.
9742 
9743      The basic algorithm is to create a sink vector whose first
9744      element is the GCD of all the first elements, and whose remaining
9745      elements are the minimum of the subsequent columns.
9746 
9747      We ignore dependence vectors whose first element is zero because
9748      such dependencies are known to be executed by the same thread.
9749 
9750      We take into account the direction of the loop, so a minimum
9751      becomes a maximum if the loop is iterating forwards.  We also
9752      ignore sink clauses where the loop direction is unknown, or where
9753      the offsets are clearly invalid because they are not a multiple
9754      of the loop increment.
9755 
9756      For example:
9757 
9758           #pragma omp for ordered(2)
9759           for (i=0; i < N; ++i)
9760             for (j=0; j < M; ++j)
9761               {
9762                 #pragma omp ordered \
9763                     depend(sink:i-8,j-2) \
9764                     depend(sink:i,j-1) \          // Completely ignored because i+0.
9765                     depend(sink:i-4,j-3) \
9766                     depend(sink:i-6,j-4)
9767                 #pragma omp ordered depend(source)
9768               }
9769 
9770      Folded clause is:
9771 
9772           depend(sink:-gcd(8,4,6),-min(2,3,4))
9773             -or-
9774           depend(sink:-2,-2)
9775   */
9776 
9777   /* FIXME: Computing GCD's where the first element is zero is
9778      non-trivial in the presence of collapsed loops.  Do this later.  */
9779   if (fd.collapse > 1)
9780     return;
9781 
9782   wide_int *folded_deps = XALLOCAVEC (wide_int, 2 * len - 1);
9783 
9784   /* wide_int is not a POD so it must be default-constructed.  */
9785   for (unsigned i = 0; i != 2 * len - 1; ++i)
9786     new (static_cast<void*>(folded_deps + i)) wide_int ();
9787 
9788   tree folded_dep = NULL_TREE;
9789   /* TRUE if the first dimension's offset is negative.  */
9790   bool neg_offset_p = false;
9791 
9792   list_p = gimple_omp_ordered_clauses_ptr (ord_stmt);
9793   unsigned int i;
9794   while ((c = *list_p) != NULL)
9795     {
9796       bool remove = false;
9797 
9798       gcc_assert (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND);
9799       if (OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_SINK)
9800           goto next_ordered_clause;
9801 
9802       tree vec;
9803       for (vec = OMP_CLAUSE_DECL (c), i = 0;
9804              vec && TREE_CODE (vec) == TREE_LIST;
9805              vec = TREE_CHAIN (vec), ++i)
9806           {
9807             gcc_assert (i < len);
9808 
9809             /* omp_extract_for_data has canonicalized the condition.  */
9810             gcc_assert (fd.loops[i].cond_code == LT_EXPR
9811                           || fd.loops[i].cond_code == GT_EXPR);
9812             bool forward = fd.loops[i].cond_code == LT_EXPR;
9813             bool maybe_lexically_later = true;
9814 
9815             /* While the committee makes up its mind, bail if we have any
9816                non-constant steps.  */
9817             if (TREE_CODE (fd.loops[i].step) != INTEGER_CST)
9818               goto lower_omp_ordered_ret;
9819 
9820             tree itype = TREE_TYPE (TREE_VALUE (vec));
9821             if (POINTER_TYPE_P (itype))
9822               itype = sizetype;
9823             wide_int offset = wide_int::from (wi::to_wide (TREE_PURPOSE (vec)),
9824                                                       TYPE_PRECISION (itype),
9825                                                       TYPE_SIGN (itype));
9826 
9827             /* Ignore invalid offsets that are not multiples of the step.  */
9828             if (!wi::multiple_of_p (wi::abs (offset),
9829                                           wi::abs (wi::to_wide (fd.loops[i].step)),
9830                                           UNSIGNED))
9831               {
9832                 warning_at (OMP_CLAUSE_LOCATION (c), 0,
9833                                 "ignoring sink clause with offset that is not "
9834                                 "a multiple of the loop step");
9835                 remove = true;
9836                 goto next_ordered_clause;
9837               }
9838 
9839             /* Calculate the first dimension.  The first dimension of
9840                the folded dependency vector is the GCD of the first
9841                elements, while ignoring any first elements whose offset
9842                is 0.  */
9843             if (i == 0)
9844               {
9845                 /* Ignore dependence vectors whose first dimension is 0.  */
9846                 if (offset == 0)
9847                     {
9848                       remove = true;
9849                       goto next_ordered_clause;
9850                     }
9851                 else
9852                     {
9853                       if (!TYPE_UNSIGNED (itype) && (forward ^ wi::neg_p (offset)))
9854                         {
9855                           error_at (OMP_CLAUSE_LOCATION (c),
9856                                         "first offset must be in opposite direction "
9857                                         "of loop iterations");
9858                           goto lower_omp_ordered_ret;
9859                         }
9860                       if (forward)
9861                         offset = -offset;
9862                       neg_offset_p = forward;
9863                       /* Initialize the first time around.  */
9864                       if (folded_dep == NULL_TREE)
9865                         {
9866                           folded_dep = c;
9867                           folded_deps[0] = offset;
9868                         }
9869                       else
9870                         folded_deps[0] = wi::gcd (folded_deps[0],
9871                                                         offset, UNSIGNED);
9872                     }
9873               }
9874             /* Calculate minimum for the remaining dimensions.  */
9875             else
9876               {
9877                 folded_deps[len + i - 1] = offset;
9878                 if (folded_dep == c)
9879                     folded_deps[i] = offset;
9880                 else if (maybe_lexically_later
9881                            && !wi::eq_p (folded_deps[i], offset))
9882                     {
9883                       if (forward ^ wi::gts_p (folded_deps[i], offset))
9884                         {
9885                           unsigned int j;
9886                           folded_dep = c;
9887                           for (j = 1; j <= i; j++)
9888                               folded_deps[j] = folded_deps[len + j - 1];
9889                         }
9890                       else
9891                         maybe_lexically_later = false;
9892                     }
9893               }
9894           }
9895       gcc_assert (i == len);
9896 
9897       remove = true;
9898 
9899     next_ordered_clause:
9900       if (remove)
9901           *list_p = OMP_CLAUSE_CHAIN (c);
9902       else
9903           list_p = &OMP_CLAUSE_CHAIN (c);
9904     }
9905 
9906   if (folded_dep)
9907     {
9908       if (neg_offset_p)
9909           folded_deps[0] = -folded_deps[0];
9910 
9911       tree itype = TREE_TYPE (TREE_VALUE (OMP_CLAUSE_DECL (folded_dep)));
9912       if (POINTER_TYPE_P (itype))
9913           itype = sizetype;
9914 
9915       TREE_PURPOSE (OMP_CLAUSE_DECL (folded_dep))
9916           = wide_int_to_tree (itype, folded_deps[0]);
9917       OMP_CLAUSE_CHAIN (folded_dep) = gimple_omp_ordered_clauses (ord_stmt);
9918       *gimple_omp_ordered_clauses_ptr (ord_stmt) = folded_dep;
9919     }
9920 
9921  lower_omp_ordered_ret:
9922 
9923   /* Ordered without clauses is #pragma omp threads, while we want
9924      a nop instead if we remove all clauses.  */
9925   if (gimple_omp_ordered_clauses (ord_stmt) == NULL_TREE)
9926     gsi_replace (gsi_p, gimple_build_nop (), true);
9927 }
9928 
9929 
9930 /* Expand code for an OpenMP ordered directive.  */
9931 
9932 static void
lower_omp_ordered(gimple_stmt_iterator * gsi_p,omp_context * ctx)9933 lower_omp_ordered (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9934 {
9935   tree block;
9936   gimple *stmt = gsi_stmt (*gsi_p), *g;
9937   gomp_ordered *ord_stmt = as_a <gomp_ordered *> (stmt);
9938   gcall *x;
9939   gbind *bind;
9940   bool simd = omp_find_clause (gimple_omp_ordered_clauses (ord_stmt),
9941                                      OMP_CLAUSE_SIMD);
9942   /* FIXME: this should check presence of OMP_CLAUSE__SIMT_ on the enclosing
9943      loop.  */
9944   bool maybe_simt
9945     = simd && omp_maybe_offloaded_ctx (ctx) && omp_max_simt_vf () > 1;
9946   bool threads = omp_find_clause (gimple_omp_ordered_clauses (ord_stmt),
9947                                           OMP_CLAUSE_THREADS);
9948 
9949   if (omp_find_clause (gimple_omp_ordered_clauses (ord_stmt),
9950                            OMP_CLAUSE_DEPEND))
9951     {
9952       /* FIXME: This is needs to be moved to the expansion to verify various
9953            conditions only testable on cfg with dominators computed, and also
9954            all the depend clauses to be merged still might need to be available
9955            for the runtime checks.  */
9956       if (0)
9957           lower_omp_ordered_clauses (gsi_p, ord_stmt, ctx);
9958       return;
9959     }
9960 
9961   push_gimplify_context ();
9962 
9963   block = make_node (BLOCK);
9964   bind = gimple_build_bind (NULL, NULL, block);
9965   gsi_replace (gsi_p, bind, true);
9966   gimple_bind_add_stmt (bind, stmt);
9967 
9968   if (simd)
9969     {
9970       x = gimple_build_call_internal (IFN_GOMP_SIMD_ORDERED_START, 1,
9971                                               build_int_cst (NULL_TREE, threads));
9972       cfun->has_simduid_loops = true;
9973     }
9974   else
9975     x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_START),
9976                                  0);
9977   gimple_bind_add_stmt (bind, x);
9978 
9979   tree counter = NULL_TREE, test = NULL_TREE, body = NULL_TREE;
9980   if (maybe_simt)
9981     {
9982       counter = create_tmp_var (integer_type_node);
9983       g = gimple_build_call_internal (IFN_GOMP_SIMT_LANE, 0);
9984       gimple_call_set_lhs (g, counter);
9985       gimple_bind_add_stmt (bind, g);
9986 
9987       body = create_artificial_label (UNKNOWN_LOCATION);
9988       test = create_artificial_label (UNKNOWN_LOCATION);
9989       gimple_bind_add_stmt (bind, gimple_build_label (body));
9990 
9991       tree simt_pred = create_tmp_var (integer_type_node);
9992       g = gimple_build_call_internal (IFN_GOMP_SIMT_ORDERED_PRED, 1, counter);
9993       gimple_call_set_lhs (g, simt_pred);
9994       gimple_bind_add_stmt (bind, g);
9995 
9996       tree t = create_artificial_label (UNKNOWN_LOCATION);
9997       g = gimple_build_cond (EQ_EXPR, simt_pred, integer_zero_node, t, test);
9998       gimple_bind_add_stmt (bind, g);
9999 
10000       gimple_bind_add_stmt (bind, gimple_build_label (t));
10001     }
10002   lower_omp (gimple_omp_body_ptr (stmt), ctx);
10003   gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
10004   gimple_bind_add_seq (bind, gimple_omp_body (stmt));
10005   gimple_omp_set_body (stmt, NULL);
10006 
10007   if (maybe_simt)
10008     {
10009       gimple_bind_add_stmt (bind, gimple_build_label (test));
10010       g = gimple_build_assign (counter, MINUS_EXPR, counter, integer_one_node);
10011       gimple_bind_add_stmt (bind, g);
10012 
10013       tree c = build2 (GE_EXPR, boolean_type_node, counter, integer_zero_node);
10014       tree nonneg = create_tmp_var (integer_type_node);
10015       gimple_seq tseq = NULL;
10016       gimplify_assign (nonneg, fold_convert (integer_type_node, c), &tseq);
10017       gimple_bind_add_seq (bind, tseq);
10018 
10019       g = gimple_build_call_internal (IFN_GOMP_SIMT_VOTE_ANY, 1, nonneg);
10020       gimple_call_set_lhs (g, nonneg);
10021       gimple_bind_add_stmt (bind, g);
10022 
10023       tree end = create_artificial_label (UNKNOWN_LOCATION);
10024       g = gimple_build_cond (NE_EXPR, nonneg, integer_zero_node, body, end);
10025       gimple_bind_add_stmt (bind, g);
10026 
10027       gimple_bind_add_stmt (bind, gimple_build_label (end));
10028     }
10029   if (simd)
10030     x = gimple_build_call_internal (IFN_GOMP_SIMD_ORDERED_END, 1,
10031                                             build_int_cst (NULL_TREE, threads));
10032   else
10033     x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_END),
10034                                  0);
10035   gimple_bind_add_stmt (bind, x);
10036 
10037   gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
10038 
10039   pop_gimplify_context (bind);
10040 
10041   gimple_bind_append_vars (bind, ctx->block_vars);
10042   BLOCK_VARS (block) = gimple_bind_vars (bind);
10043 }
10044 
10045 
10046 /* Expand code for an OpenMP scan directive and the structured block
10047    before the scan directive.  */
10048 
10049 static void
lower_omp_scan(gimple_stmt_iterator * gsi_p,omp_context * ctx)10050 lower_omp_scan (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10051 {
10052   gimple *stmt = gsi_stmt (*gsi_p);
10053   bool has_clauses
10054     = gimple_omp_scan_clauses (as_a <gomp_scan *> (stmt)) != NULL;
10055   tree lane = NULL_TREE;
10056   gimple_seq before = NULL;
10057   omp_context *octx = ctx->outer;
10058   gcc_assert (octx);
10059   if (octx->scan_exclusive && !has_clauses)
10060     {
10061       gimple_stmt_iterator gsi2 = *gsi_p;
10062       gsi_next (&gsi2);
10063       gimple *stmt2 = gsi_stmt (gsi2);
10064       /* For exclusive scan, swap GIMPLE_OMP_SCAN without clauses
10065            with following GIMPLE_OMP_SCAN with clauses, so that input_phase,
10066            the one with exclusive clause(s), comes first.  */
10067       if (stmt2
10068             && gimple_code (stmt2) == GIMPLE_OMP_SCAN
10069             && gimple_omp_scan_clauses (as_a <gomp_scan *> (stmt2)) != NULL)
10070           {
10071             gsi_remove (gsi_p, false);
10072             gsi_insert_after (gsi_p, stmt, GSI_SAME_STMT);
10073             ctx = maybe_lookup_ctx (stmt2);
10074             gcc_assert (ctx);
10075             lower_omp_scan (gsi_p, ctx);
10076             return;
10077           }
10078     }
10079 
10080   bool input_phase = has_clauses ^ octx->scan_inclusive;
10081   bool is_simd = (gimple_code (octx->stmt) == GIMPLE_OMP_FOR
10082                       && gimple_omp_for_kind (octx->stmt) == GF_OMP_FOR_KIND_SIMD);
10083   bool is_for = (gimple_code (octx->stmt) == GIMPLE_OMP_FOR
10084                      && gimple_omp_for_kind (octx->stmt) == GF_OMP_FOR_KIND_FOR
10085                      && !gimple_omp_for_combined_p (octx->stmt));
10086   bool is_for_simd = is_simd && gimple_omp_for_combined_into_p (octx->stmt);
10087   if (is_for_simd && octx->for_simd_scan_phase)
10088     is_simd = false;
10089   if (is_simd)
10090     if (tree c = omp_find_clause (gimple_omp_for_clauses (octx->stmt),
10091                                           OMP_CLAUSE__SIMDUID_))
10092       {
10093           tree uid = OMP_CLAUSE__SIMDUID__DECL (c);
10094           lane = create_tmp_var (unsigned_type_node);
10095           tree t = build_int_cst (integer_type_node,
10096                                         input_phase ? 1
10097                                         : octx->scan_inclusive ? 2 : 3);
10098           gimple *g
10099             = gimple_build_call_internal (IFN_GOMP_SIMD_LANE, 2, uid, t);
10100           gimple_call_set_lhs (g, lane);
10101           gimple_seq_add_stmt (&before, g);
10102       }
10103 
10104   if (is_simd || is_for)
10105     {
10106       for (tree c = gimple_omp_for_clauses (octx->stmt);
10107              c; c = OMP_CLAUSE_CHAIN (c))
10108           if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
10109               && OMP_CLAUSE_REDUCTION_INSCAN (c))
10110             {
10111               location_t clause_loc = OMP_CLAUSE_LOCATION (c);
10112               tree var = OMP_CLAUSE_DECL (c);
10113               tree new_var = lookup_decl (var, octx);
10114               tree val = new_var;
10115               tree var2 = NULL_TREE;
10116               tree var3 = NULL_TREE;
10117               tree var4 = NULL_TREE;
10118               tree lane0 = NULL_TREE;
10119               tree new_vard = new_var;
10120               if (omp_privatize_by_reference (var))
10121                 {
10122                     new_var = build_simple_mem_ref_loc (clause_loc, new_var);
10123                     val = new_var;
10124                 }
10125               if (DECL_HAS_VALUE_EXPR_P (new_vard))
10126                 {
10127                     val = DECL_VALUE_EXPR (new_vard);
10128                     if (new_vard != new_var)
10129                       {
10130                         gcc_assert (TREE_CODE (val) == ADDR_EXPR);
10131                         val = TREE_OPERAND (val, 0);
10132                       }
10133                     if (TREE_CODE (val) == ARRAY_REF
10134                         && VAR_P (TREE_OPERAND (val, 0)))
10135                       {
10136                         tree v = TREE_OPERAND (val, 0);
10137                         if (lookup_attribute ("omp simd array",
10138                                                     DECL_ATTRIBUTES (v)))
10139                           {
10140                               val = unshare_expr (val);
10141                               lane0 = TREE_OPERAND (val, 1);
10142                               TREE_OPERAND (val, 1) = lane;
10143                               var2 = lookup_decl (v, octx);
10144                               if (octx->scan_exclusive)
10145                                 var4 = lookup_decl (var2, octx);
10146                               if (input_phase
10147                                   && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
10148                                 var3 = maybe_lookup_decl (var4 ? var4 : var2, octx);
10149                               if (!input_phase)
10150                                 {
10151                                   var2 = build4 (ARRAY_REF, TREE_TYPE (val),
10152                                                      var2, lane, NULL_TREE, NULL_TREE);
10153                                   TREE_THIS_NOTRAP (var2) = 1;
10154                                   if (octx->scan_exclusive)
10155                                     {
10156                                         var4 = build4 (ARRAY_REF, TREE_TYPE (val),
10157                                                          var4, lane, NULL_TREE,
10158                                                          NULL_TREE);
10159                                         TREE_THIS_NOTRAP (var4) = 1;
10160                                     }
10161                                 }
10162                               else
10163                                 var2 = val;
10164                           }
10165                       }
10166                     gcc_assert (var2);
10167                 }
10168               else
10169                 {
10170                     var2 = build_outer_var_ref (var, octx);
10171                     if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
10172                       {
10173                         var3 = maybe_lookup_decl (new_vard, octx);
10174                         if (var3 == new_vard || var3 == NULL_TREE)
10175                           var3 = NULL_TREE;
10176                         else if (is_simd && octx->scan_exclusive && !input_phase)
10177                           {
10178                               var4 = maybe_lookup_decl (var3, octx);
10179                               if (var4 == var3 || var4 == NULL_TREE)
10180                                 {
10181                                   if (TREE_ADDRESSABLE (TREE_TYPE (new_var)))
10182                                     {
10183                                         var4 = var3;
10184                                         var3 = NULL_TREE;
10185                                     }
10186                                   else
10187                                     var4 = NULL_TREE;
10188                                 }
10189                           }
10190                       }
10191                     if (is_simd
10192                         && octx->scan_exclusive
10193                         && !input_phase
10194                         && var4 == NULL_TREE)
10195                       var4 = create_tmp_var (TREE_TYPE (val));
10196                 }
10197               if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
10198                 {
10199                     tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
10200                     if (input_phase)
10201                       {
10202                         if (var3)
10203                           {
10204                               /* If we've added a separate identity element
10205                                  variable, copy it over into val.  */
10206                               tree x = lang_hooks.decls.omp_clause_assign_op (c, val,
10207                                                                                           var3);
10208                               gimplify_and_add (x, &before);
10209                           }
10210                         else if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
10211                           {
10212                               /* Otherwise, assign to it the identity element.  */
10213                               gimple_seq tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
10214                               if (is_for)
10215                                 tseq = copy_gimple_seq_and_replace_locals (tseq);
10216                               tree ref = build_outer_var_ref (var, octx);
10217                               tree x = (DECL_HAS_VALUE_EXPR_P (new_vard)
10218                                           ? DECL_VALUE_EXPR (new_vard) : NULL_TREE);
10219                               if (x)
10220                                 {
10221                                   if (new_vard != new_var)
10222                                     val = build_fold_addr_expr_loc (clause_loc, val);
10223                                   SET_DECL_VALUE_EXPR (new_vard, val);
10224                                 }
10225                               SET_DECL_VALUE_EXPR (placeholder, ref);
10226                               DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
10227                               lower_omp (&tseq, octx);
10228                               if (x)
10229                                 SET_DECL_VALUE_EXPR (new_vard, x);
10230                               SET_DECL_VALUE_EXPR (placeholder, NULL_TREE);
10231                               DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
10232                               gimple_seq_add_seq (&before, tseq);
10233                               if (is_simd)
10234                                 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
10235                           }
10236                       }
10237                     else if (is_simd)
10238                       {
10239                         tree x;
10240                         if (octx->scan_exclusive)
10241                           {
10242                               tree v4 = unshare_expr (var4);
10243                               tree v2 = unshare_expr (var2);
10244                               x = lang_hooks.decls.omp_clause_assign_op (c, v4, v2);
10245                               gimplify_and_add (x, &before);
10246                           }
10247                         gimple_seq tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
10248                         x = (DECL_HAS_VALUE_EXPR_P (new_vard)
10249                                ? DECL_VALUE_EXPR (new_vard) : NULL_TREE);
10250                         tree vexpr = val;
10251                         if (x && new_vard != new_var)
10252                           vexpr = build_fold_addr_expr_loc (clause_loc, val);
10253                         if (x)
10254                           SET_DECL_VALUE_EXPR (new_vard, vexpr);
10255                         SET_DECL_VALUE_EXPR (placeholder, var2);
10256                         DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
10257                         lower_omp (&tseq, octx);
10258                         gimple_seq_add_seq (&before, tseq);
10259                         OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
10260                         if (x)
10261                           SET_DECL_VALUE_EXPR (new_vard, x);
10262                         SET_DECL_VALUE_EXPR (placeholder, NULL_TREE);
10263                         DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
10264                         if (octx->scan_inclusive)
10265                           {
10266                               x = lang_hooks.decls.omp_clause_assign_op (c, val,
10267                                                                                    var2);
10268                               gimplify_and_add (x, &before);
10269                           }
10270                         else if (lane0 == NULL_TREE)
10271                           {
10272                               x = lang_hooks.decls.omp_clause_assign_op (c, val,
10273                                                                                    var4);
10274                               gimplify_and_add (x, &before);
10275                           }
10276                       }
10277                 }
10278               else
10279                 {
10280                     if (input_phase)
10281                       {
10282                         /* input phase.  Set val to initializer before
10283                            the body.  */
10284                         tree x = omp_reduction_init (c, TREE_TYPE (new_var));
10285                         gimplify_assign (val, x, &before);
10286                       }
10287                     else if (is_simd)
10288                       {
10289                         /* scan phase.  */
10290                         enum tree_code code = OMP_CLAUSE_REDUCTION_CODE (c);
10291                         if (code == MINUS_EXPR)
10292                           code = PLUS_EXPR;
10293 
10294                         tree x = build2 (code, TREE_TYPE (var2),
10295                                              unshare_expr (var2), unshare_expr (val));
10296                         if (octx->scan_inclusive)
10297                           {
10298                               gimplify_assign (unshare_expr (var2), x, &before);
10299                               gimplify_assign (val, var2, &before);
10300                           }
10301                         else
10302                           {
10303                               gimplify_assign (unshare_expr (var4),
10304                                                    unshare_expr (var2), &before);
10305                               gimplify_assign (var2, x, &before);
10306                               if (lane0 == NULL_TREE)
10307                                 gimplify_assign (val, var4, &before);
10308                           }
10309                       }
10310                 }
10311               if (octx->scan_exclusive && !input_phase && lane0)
10312                 {
10313                     tree vexpr = unshare_expr (var4);
10314                     TREE_OPERAND (vexpr, 1) = lane0;
10315                     if (new_vard != new_var)
10316                       vexpr = build_fold_addr_expr_loc (clause_loc, vexpr);
10317                     SET_DECL_VALUE_EXPR (new_vard, vexpr);
10318                 }
10319             }
10320     }
10321   if (is_simd && !is_for_simd)
10322     {
10323       gsi_insert_seq_after (gsi_p, gimple_omp_body (stmt), GSI_SAME_STMT);
10324       gsi_insert_seq_after (gsi_p, before, GSI_SAME_STMT);
10325       gsi_replace (gsi_p, gimple_build_nop (), true);
10326       return;
10327     }
10328   lower_omp (gimple_omp_body_ptr (stmt), octx);
10329   if (before)
10330     {
10331       gimple_stmt_iterator gsi = gsi_start_1 (gimple_omp_body_ptr (stmt));
10332       gsi_insert_seq_before (&gsi, before, GSI_SAME_STMT);
10333     }
10334 }
10335 
10336 
10337 /* Gimplify a GIMPLE_OMP_CRITICAL statement.  This is a relatively simple
10338    substitution of a couple of function calls.  But in the NAMED case,
10339    requires that languages coordinate a symbol name.  It is therefore
10340    best put here in common code.  */
10341 
10342 static GTY(()) hash_map<tree, tree> *critical_name_mutexes;
10343 
10344 static void
lower_omp_critical(gimple_stmt_iterator * gsi_p,omp_context * ctx)10345 lower_omp_critical (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10346 {
10347   tree block;
10348   tree name, lock, unlock;
10349   gomp_critical *stmt = as_a <gomp_critical *> (gsi_stmt (*gsi_p));
10350   gbind *bind;
10351   location_t loc = gimple_location (stmt);
10352   gimple_seq tbody;
10353 
10354   name = gimple_omp_critical_name (stmt);
10355   if (name)
10356     {
10357       tree decl;
10358 
10359       if (!critical_name_mutexes)
10360           critical_name_mutexes = hash_map<tree, tree>::create_ggc (10);
10361 
10362       tree *n = critical_name_mutexes->get (name);
10363       if (n == NULL)
10364           {
10365             char *new_str;
10366 
10367             decl = create_tmp_var_raw (ptr_type_node);
10368 
10369             new_str = ACONCAT ((".gomp_critical_user_",
10370                                     IDENTIFIER_POINTER (name), NULL));
10371             DECL_NAME (decl) = get_identifier (new_str);
10372             TREE_PUBLIC (decl) = 1;
10373             TREE_STATIC (decl) = 1;
10374             DECL_COMMON (decl) = 1;
10375             DECL_ARTIFICIAL (decl) = 1;
10376             DECL_IGNORED_P (decl) = 1;
10377 
10378             varpool_node::finalize_decl (decl);
10379 
10380             critical_name_mutexes->put (name, decl);
10381           }
10382       else
10383           decl = *n;
10384 
10385       /* If '#pragma omp critical' is inside offloaded region or
10386            inside function marked as offloadable, the symbol must be
10387            marked as offloadable too.  */
10388       omp_context *octx;
10389       if (cgraph_node::get (current_function_decl)->offloadable)
10390           varpool_node::get_create (decl)->offloadable = 1;
10391       else
10392           for (octx = ctx->outer; octx; octx = octx->outer)
10393             if (is_gimple_omp_offloaded (octx->stmt))
10394               {
10395                 varpool_node::get_create (decl)->offloadable = 1;
10396                 break;
10397               }
10398 
10399       lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_START);
10400       lock = build_call_expr_loc (loc, lock, 1,
10401                                           build_fold_addr_expr_loc (loc, decl));
10402 
10403       unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_END);
10404       unlock = build_call_expr_loc (loc, unlock, 1,
10405                                         build_fold_addr_expr_loc (loc, decl));
10406     }
10407   else
10408     {
10409       lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_START);
10410       lock = build_call_expr_loc (loc, lock, 0);
10411 
10412       unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_END);
10413       unlock = build_call_expr_loc (loc, unlock, 0);
10414     }
10415 
10416   push_gimplify_context ();
10417 
10418   block = make_node (BLOCK);
10419   bind = gimple_build_bind (NULL, NULL, block);
10420   gsi_replace (gsi_p, bind, true);
10421   gimple_bind_add_stmt (bind, stmt);
10422 
10423   tbody = gimple_bind_body (bind);
10424   gimplify_and_add (lock, &tbody);
10425   gimple_bind_set_body (bind, tbody);
10426 
10427   lower_omp (gimple_omp_body_ptr (stmt), ctx);
10428   gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
10429   gimple_bind_add_seq (bind, gimple_omp_body (stmt));
10430   gimple_omp_set_body (stmt, NULL);
10431 
10432   tbody = gimple_bind_body (bind);
10433   gimplify_and_add (unlock, &tbody);
10434   gimple_bind_set_body (bind, tbody);
10435 
10436   gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
10437 
10438   pop_gimplify_context (bind);
10439   gimple_bind_append_vars (bind, ctx->block_vars);
10440   BLOCK_VARS (block) = gimple_bind_vars (bind);
10441 }
10442 
10443 /* A subroutine of lower_omp_for.  Generate code to emit the predicate
10444    for a lastprivate clause.  Given a loop control predicate of (V
10445    cond N2), we gate the clause on (!(V cond N2)).  The lowered form
10446    is appended to *DLIST, iterator initialization is appended to
10447    *BODY_P.  *CLIST is for lastprivate(conditional:) code that needs
10448    to be emitted in a critical section.  */
10449 
10450 static void
lower_omp_for_lastprivate(struct omp_for_data * fd,gimple_seq * body_p,gimple_seq * dlist,gimple_seq * clist,struct omp_context * ctx)10451 lower_omp_for_lastprivate (struct omp_for_data *fd, gimple_seq *body_p,
10452                                  gimple_seq *dlist, gimple_seq *clist,
10453                                  struct omp_context *ctx)
10454 {
10455   tree clauses, cond, vinit;
10456   enum tree_code cond_code;
10457   gimple_seq stmts;
10458 
10459   cond_code = fd->loop.cond_code;
10460   cond_code = cond_code == LT_EXPR ? GE_EXPR : LE_EXPR;
10461 
10462   /* When possible, use a strict equality expression.  This can let VRP
10463      type optimizations deduce the value and remove a copy.  */
10464   if (tree_fits_shwi_p (fd->loop.step))
10465     {
10466       HOST_WIDE_INT step = tree_to_shwi (fd->loop.step);
10467       if (step == 1 || step == -1)
10468           cond_code = EQ_EXPR;
10469     }
10470 
10471   tree n2 = fd->loop.n2;
10472   if (fd->collapse > 1
10473       && TREE_CODE (n2) != INTEGER_CST
10474       && gimple_omp_for_combined_into_p (fd->for_stmt))
10475     {
10476       struct omp_context *taskreg_ctx = NULL;
10477       if (gimple_code (ctx->outer->stmt) == GIMPLE_OMP_FOR)
10478           {
10479             gomp_for *gfor = as_a <gomp_for *> (ctx->outer->stmt);
10480             if (gimple_omp_for_kind (gfor) == GF_OMP_FOR_KIND_FOR
10481                 || gimple_omp_for_kind (gfor) == GF_OMP_FOR_KIND_DISTRIBUTE)
10482               {
10483                 if (gimple_omp_for_combined_into_p (gfor))
10484                     {
10485                       gcc_assert (ctx->outer->outer
10486                                     && is_parallel_ctx (ctx->outer->outer));
10487                       taskreg_ctx = ctx->outer->outer;
10488                     }
10489                 else
10490                     {
10491                       struct omp_for_data outer_fd;
10492                       omp_extract_for_data (gfor, &outer_fd, NULL);
10493                       n2 = fold_convert (TREE_TYPE (n2), outer_fd.loop.n2);
10494                     }
10495               }
10496             else if (gimple_omp_for_kind (gfor) == GF_OMP_FOR_KIND_TASKLOOP)
10497               taskreg_ctx = ctx->outer->outer;
10498           }
10499       else if (is_taskreg_ctx (ctx->outer))
10500           taskreg_ctx = ctx->outer;
10501       if (taskreg_ctx)
10502           {
10503             int i;
10504             tree taskreg_clauses
10505               = gimple_omp_taskreg_clauses (taskreg_ctx->stmt);
10506             tree innerc = omp_find_clause (taskreg_clauses,
10507                                                    OMP_CLAUSE__LOOPTEMP_);
10508             gcc_assert (innerc);
10509             int count = fd->collapse;
10510             if (fd->non_rect
10511                 && fd->last_nonrect == fd->first_nonrect + 1)
10512               if (tree v = gimple_omp_for_index (fd->for_stmt, fd->last_nonrect))
10513                 if (!TYPE_UNSIGNED (TREE_TYPE (v)))
10514                     count += 4;
10515             for (i = 0; i < count; i++)
10516               {
10517                 innerc = omp_find_clause (OMP_CLAUSE_CHAIN (innerc),
10518                                                   OMP_CLAUSE__LOOPTEMP_);
10519                 gcc_assert (innerc);
10520               }
10521             innerc = omp_find_clause (OMP_CLAUSE_CHAIN (innerc),
10522                                             OMP_CLAUSE__LOOPTEMP_);
10523             if (innerc)
10524               n2 = fold_convert (TREE_TYPE (n2),
10525                                      lookup_decl (OMP_CLAUSE_DECL (innerc),
10526                                                       taskreg_ctx));
10527           }
10528     }
10529   cond = build2 (cond_code, boolean_type_node, fd->loop.v, n2);
10530 
10531   clauses = gimple_omp_for_clauses (fd->for_stmt);
10532   stmts = NULL;
10533   lower_lastprivate_clauses (clauses, cond, body_p, &stmts, clist, ctx);
10534   if (!gimple_seq_empty_p (stmts))
10535     {
10536       gimple_seq_add_seq (&stmts, *dlist);
10537       *dlist = stmts;
10538 
10539       /* Optimize: v = 0; is usually cheaper than v = some_other_constant.  */
10540       vinit = fd->loop.n1;
10541       if (cond_code == EQ_EXPR
10542             && tree_fits_shwi_p (fd->loop.n2)
10543             && ! integer_zerop (fd->loop.n2))
10544           vinit = build_int_cst (TREE_TYPE (fd->loop.v), 0);
10545       else
10546           vinit = unshare_expr (vinit);
10547 
10548       /* Initialize the iterator variable, so that threads that don't execute
10549            any iterations don't execute the lastprivate clauses by accident.  */
10550       gimplify_assign (fd->loop.v, vinit, body_p);
10551     }
10552 }
10553 
10554 /* OpenACC privatization.
10555 
10556    Or, in other words, *sharing* at the respective OpenACC level of
10557    parallelism.
10558 
10559    From a correctness perspective, a non-addressable variable can't be accessed
10560    outside the current thread, so it can go in a (faster than shared memory)
10561    register -- though that register may need to be broadcast in some
10562    circumstances.  A variable can only meaningfully be "shared" across workers
10563    or vector lanes if its address is taken, e.g. by a call to an atomic
10564    builtin.
10565 
10566    From an optimisation perspective, the answer might be fuzzier: maybe
10567    sometimes, using shared memory directly would be faster than
10568    broadcasting.  */
10569 
10570 static void
oacc_privatization_begin_diagnose_var(const dump_flags_t l_dump_flags,const location_t loc,const tree c,const tree decl)10571 oacc_privatization_begin_diagnose_var (const dump_flags_t l_dump_flags,
10572                                                const location_t loc, const tree c,
10573                                                const tree decl)
10574 {
10575   const dump_user_location_t d_u_loc
10576     = dump_user_location_t::from_location_t (loc);
10577 /* PR100695 "Format decoder, quoting in 'dump_printf' etc." */
10578 #if __GNUC__ >= 10
10579 # pragma GCC diagnostic push
10580 # pragma GCC diagnostic ignored "-Wformat"
10581 #endif
10582   dump_printf_loc (l_dump_flags, d_u_loc,
10583                        "variable %<%T%> ", decl);
10584 #if __GNUC__ >= 10
10585 # pragma GCC diagnostic pop
10586 #endif
10587   if (c)
10588     dump_printf (l_dump_flags,
10589                      "in %qs clause ",
10590                      omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
10591   else
10592     dump_printf (l_dump_flags,
10593                      "declared in block ");
10594 }
10595 
10596 static bool
oacc_privatization_candidate_p(const location_t loc,const tree c,const tree decl)10597 oacc_privatization_candidate_p (const location_t loc, const tree c,
10598                                         const tree decl)
10599 {
10600   dump_flags_t l_dump_flags = get_openacc_privatization_dump_flags ();
10601 
10602   /* There is some differentiation depending on block vs. clause.  */
10603   bool block = !c;
10604 
10605   bool res = true;
10606 
10607   if (res && !VAR_P (decl))
10608     {
10609       /* A PARM_DECL (appearing in a 'private' clause) is expected to have been
10610            privatized into a new VAR_DECL.  */
10611       gcc_checking_assert (TREE_CODE (decl) != PARM_DECL);
10612 
10613       res = false;
10614 
10615       if (dump_enabled_p ())
10616           {
10617             oacc_privatization_begin_diagnose_var (l_dump_flags, loc, c, decl);
10618             dump_printf (l_dump_flags,
10619                            "potentially has improper OpenACC privatization level: %qs\n",
10620                            get_tree_code_name (TREE_CODE (decl)));
10621           }
10622     }
10623 
10624   if (res && block && TREE_STATIC (decl))
10625     {
10626       res = false;
10627 
10628       if (dump_enabled_p ())
10629           {
10630             oacc_privatization_begin_diagnose_var (l_dump_flags, loc, c, decl);
10631             dump_printf (l_dump_flags,
10632                            "isn%'t candidate for adjusting OpenACC privatization level: %s\n",
10633                            "static");
10634           }
10635     }
10636 
10637   if (res && block && DECL_EXTERNAL (decl))
10638     {
10639       res = false;
10640 
10641       if (dump_enabled_p ())
10642           {
10643             oacc_privatization_begin_diagnose_var (l_dump_flags, loc, c, decl);
10644             dump_printf (l_dump_flags,
10645                            "isn%'t candidate for adjusting OpenACC privatization level: %s\n",
10646                            "external");
10647           }
10648     }
10649 
10650   if (res && !TREE_ADDRESSABLE (decl))
10651     {
10652       res = false;
10653 
10654       if (dump_enabled_p ())
10655           {
10656             oacc_privatization_begin_diagnose_var (l_dump_flags, loc, c, decl);
10657             dump_printf (l_dump_flags,
10658                            "isn%'t candidate for adjusting OpenACC privatization level: %s\n",
10659                            "not addressable");
10660           }
10661     }
10662 
10663   /* If an artificial variable has been added to a bind, e.g.
10664      a compiler-generated temporary structure used by the Fortran front-end, do
10665      not consider it as a privatization candidate.  Note that variables on
10666      the stack are private per-thread by default: making them "gang-private"
10667      for OpenACC actually means to share a single instance of a variable
10668      amongst all workers and threads spawned within each gang.
10669      At present, no compiler-generated artificial variables require such
10670      sharing semantics, so this is safe.  */
10671 
10672   if (res && block && DECL_ARTIFICIAL (decl))
10673     {
10674       res = false;
10675 
10676       if (dump_enabled_p ())
10677           {
10678             oacc_privatization_begin_diagnose_var (l_dump_flags, loc, c, decl);
10679             dump_printf (l_dump_flags,
10680                            "isn%'t candidate for adjusting OpenACC privatization "
10681                            "level: %s\n", "artificial");
10682           }
10683     }
10684 
10685   if (res)
10686     {
10687       if (dump_enabled_p ())
10688           {
10689             oacc_privatization_begin_diagnose_var (l_dump_flags, loc, c, decl);
10690             dump_printf (l_dump_flags,
10691                            "is candidate for adjusting OpenACC privatization level\n");
10692           }
10693     }
10694 
10695   if (dump_file && (dump_flags & TDF_DETAILS))
10696     {
10697       print_generic_decl (dump_file, decl, dump_flags);
10698       fprintf (dump_file, "\n");
10699     }
10700 
10701   return res;
10702 }
10703 
10704 /* Scan CLAUSES for candidates for adjusting OpenACC privatization level in
10705    CTX.  */
10706 
10707 static void
oacc_privatization_scan_clause_chain(omp_context * ctx,tree clauses)10708 oacc_privatization_scan_clause_chain (omp_context *ctx, tree clauses)
10709 {
10710   for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
10711     if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE)
10712       {
10713           tree decl = OMP_CLAUSE_DECL (c);
10714 
10715           tree new_decl = lookup_decl (decl, ctx);
10716 
10717           if (!oacc_privatization_candidate_p (OMP_CLAUSE_LOCATION (c), c,
10718                                                        new_decl))
10719             continue;
10720 
10721           gcc_checking_assert
10722             (!ctx->oacc_privatization_candidates.contains (new_decl));
10723           ctx->oacc_privatization_candidates.safe_push (new_decl);
10724       }
10725 }
10726 
10727 /* Scan DECLS for candidates for adjusting OpenACC privatization level in
10728    CTX.  */
10729 
10730 static void
oacc_privatization_scan_decl_chain(omp_context * ctx,tree decls)10731 oacc_privatization_scan_decl_chain (omp_context *ctx, tree decls)
10732 {
10733   for (tree decl = decls; decl; decl = DECL_CHAIN (decl))
10734     {
10735       tree new_decl = lookup_decl (decl, ctx);
10736       gcc_checking_assert (new_decl == decl);
10737 
10738       if (!oacc_privatization_candidate_p (gimple_location (ctx->stmt), NULL,
10739                                                      new_decl))
10740           continue;
10741 
10742       gcc_checking_assert
10743           (!ctx->oacc_privatization_candidates.contains (new_decl));
10744       ctx->oacc_privatization_candidates.safe_push (new_decl);
10745     }
10746 }
10747 
10748 /* Callback for walk_gimple_seq.  Find #pragma omp scan statement.  */
10749 
10750 static tree
omp_find_scan(gimple_stmt_iterator * gsi_p,bool * handled_ops_p,struct walk_stmt_info * wi)10751 omp_find_scan (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
10752                  struct walk_stmt_info *wi)
10753 {
10754   gimple *stmt = gsi_stmt (*gsi_p);
10755 
10756   *handled_ops_p = true;
10757   switch (gimple_code (stmt))
10758     {
10759     WALK_SUBSTMTS;
10760 
10761     case GIMPLE_OMP_FOR:
10762       if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_SIMD
10763             && gimple_omp_for_combined_into_p (stmt))
10764           *handled_ops_p = false;
10765       break;
10766 
10767     case GIMPLE_OMP_SCAN:
10768       *(gimple_stmt_iterator *) (wi->info) = *gsi_p;
10769       return integer_zero_node;
10770     default:
10771       break;
10772     }
10773   return NULL;
10774 }
10775 
10776 /* Helper function for lower_omp_for, add transformations for a worksharing
10777    loop with scan directives inside of it.
10778    For worksharing loop not combined with simd, transform:
10779    #pragma omp for reduction(inscan,+:r) private(i)
10780    for (i = 0; i < n; i = i + 1)
10781      {
10782        {
10783            update (r);
10784        }
10785        #pragma omp scan inclusive(r)
10786        {
10787            use (r);
10788        }
10789      }
10790 
10791    into two worksharing loops + code to merge results:
10792 
10793    num_threads = omp_get_num_threads ();
10794    thread_num = omp_get_thread_num ();
10795    if (thread_num == 0) goto <D.2099>; else goto <D.2100>;
10796    <D.2099>:
10797    var2 = r;
10798    goto <D.2101>;
10799    <D.2100>:
10800    // For UDRs this is UDR init, or if ctors are needed, copy from
10801    // var3 that has been constructed to contain the neutral element.
10802    var2 = 0;
10803    <D.2101>:
10804    ivar = 0;
10805    // The _scantemp_ clauses will arrange for rpriva to be initialized to
10806    // a shared array with num_threads elements and rprivb to a local array
10807    // number of elements equal to the number of (contiguous) iterations the
10808    // current thread will perform.  controlb and controlp variables are
10809    // temporaries to handle deallocation of rprivb at the end of second
10810    // GOMP_FOR.
10811    #pragma omp for _scantemp_(rpriva) _scantemp_(rprivb) _scantemp_(controlb) \
10812      _scantemp_(controlp) reduction(inscan,+:r) private(i) nowait
10813    for (i = 0; i < n; i = i + 1)
10814      {
10815        {
10816            // For UDRs this is UDR init or copy from var3.
10817            r = 0;
10818            // This is the input phase from user code.
10819            update (r);
10820        }
10821        {
10822            // For UDRs this is UDR merge.
10823            var2 = var2 + r;
10824            // Rather than handing it over to the user, save to local thread's
10825            // array.
10826            rprivb[ivar] = var2;
10827            // For exclusive scan, the above two statements are swapped.
10828            ivar = ivar + 1;
10829        }
10830      }
10831    // And remember the final value from this thread's into the shared
10832    // rpriva array.
10833    rpriva[(sizetype) thread_num] = var2;
10834    // If more than one thread, compute using Work-Efficient prefix sum
10835    // the inclusive parallel scan of the rpriva array.
10836    if (num_threads > 1) goto <D.2102>; else goto <D.2103>;
10837    <D.2102>:
10838    GOMP_barrier ();
10839    down = 0;
10840    k = 1;
10841    num_threadsu = (unsigned int) num_threads;
10842    thread_numup1 = (unsigned int) thread_num + 1;
10843    <D.2108>:
10844    twok = k << 1;
10845    if (twok > num_threadsu) goto <D.2110>; else goto <D.2111>;
10846    <D.2110>:
10847    down = 4294967295;
10848    k = k >> 1;
10849    if (k == num_threadsu) goto <D.2112>; else goto <D.2111>;
10850    <D.2112>:
10851    k = k >> 1;
10852    <D.2111>:
10853    twok = k << 1;
10854    cplx = .MUL_OVERFLOW (thread_nump1, twok);
10855    mul = REALPART_EXPR <cplx>;
10856    ovf = IMAGPART_EXPR <cplx>;
10857    if (ovf == 0) goto <D.2116>; else goto <D.2117>;
10858    <D.2116>:
10859    andv = k & down;
10860    andvm1 = andv + 4294967295;
10861    l = mul + andvm1;
10862    if (l < num_threadsu) goto <D.2120>; else goto <D.2117>;
10863    <D.2120>:
10864    // For UDRs this is UDR merge, performed using var2 variable as temporary,
10865    // i.e. var2 = rpriva[l - k]; UDR merge (var2, rpriva[l]); rpriva[l] = var2;
10866    rpriva[l] = rpriva[l - k] + rpriva[l];
10867    <D.2117>:
10868    if (down == 0) goto <D.2121>; else goto <D.2122>;
10869    <D.2121>:
10870    k = k << 1;
10871    goto <D.2123>;
10872    <D.2122>:
10873    k = k >> 1;
10874    <D.2123>:
10875    GOMP_barrier ();
10876    if (k != 0) goto <D.2108>; else goto <D.2103>;
10877    <D.2103>:
10878    if (thread_num == 0) goto <D.2124>; else goto <D.2125>;
10879    <D.2124>:
10880    // For UDRs this is UDR init or copy from var3.
10881    var2 = 0;
10882    goto <D.2126>;
10883    <D.2125>:
10884    var2 = rpriva[thread_num - 1];
10885    <D.2126>:
10886    ivar = 0;
10887    #pragma omp for _scantemp_(controlb) _scantemp_(controlp) \
10888      reduction(inscan,+:r) private(i)
10889    for (i = 0; i < n; i = i + 1)
10890      {
10891        {
10892            // For UDRs, this is r = var2; UDR merge (r, rprivb[ivar]);
10893            r = var2 + rprivb[ivar];
10894        }
10895        {
10896            // This is the scan phase from user code.
10897            use (r);
10898            // Plus a bump of the iterator.
10899            ivar = ivar + 1;
10900        }
10901      }  */
10902 
10903 static void
lower_omp_for_scan(gimple_seq * body_p,gimple_seq * dlist,gomp_for * stmt,struct omp_for_data * fd,omp_context * ctx)10904 lower_omp_for_scan (gimple_seq *body_p, gimple_seq *dlist, gomp_for *stmt,
10905                         struct omp_for_data *fd, omp_context *ctx)
10906 {
10907   bool is_for_simd = gimple_omp_for_combined_p (stmt);
10908   gcc_assert (ctx->scan_inclusive || ctx->scan_exclusive);
10909 
10910   gimple_seq body = gimple_omp_body (stmt);
10911   gimple_stmt_iterator input1_gsi = gsi_none ();
10912   struct walk_stmt_info wi;
10913   memset (&wi, 0, sizeof (wi));
10914   wi.val_only = true;
10915   wi.info = (void *) &input1_gsi;
10916   walk_gimple_seq_mod (&body, omp_find_scan, NULL, &wi);
10917   gcc_assert (!gsi_end_p (input1_gsi));
10918 
10919   gimple *input_stmt1 = gsi_stmt (input1_gsi);
10920   gimple_stmt_iterator gsi = input1_gsi;
10921   gsi_next (&gsi);
10922   gimple_stmt_iterator scan1_gsi = gsi;
10923   gimple *scan_stmt1 = gsi_stmt (gsi);
10924   gcc_assert (scan_stmt1 && gimple_code (scan_stmt1) == GIMPLE_OMP_SCAN);
10925 
10926   gimple_seq input_body = gimple_omp_body (input_stmt1);
10927   gimple_seq scan_body = gimple_omp_body (scan_stmt1);
10928   gimple_omp_set_body (input_stmt1, NULL);
10929   gimple_omp_set_body (scan_stmt1, NULL);
10930   gimple_omp_set_body (stmt, NULL);
10931 
10932   gomp_for *new_stmt = as_a <gomp_for *> (gimple_copy (stmt));
10933   gimple_seq new_body = copy_gimple_seq_and_replace_locals (body);
10934   gimple_omp_set_body (stmt, body);
10935   gimple_omp_set_body (input_stmt1, input_body);
10936 
10937   gimple_stmt_iterator input2_gsi = gsi_none ();
10938   memset (&wi, 0, sizeof (wi));
10939   wi.val_only = true;
10940   wi.info = (void *) &input2_gsi;
10941   walk_gimple_seq_mod (&new_body, omp_find_scan, NULL, &wi);
10942   gcc_assert (!gsi_end_p (input2_gsi));
10943 
10944   gimple *input_stmt2 = gsi_stmt (input2_gsi);
10945   gsi = input2_gsi;
10946   gsi_next (&gsi);
10947   gimple_stmt_iterator scan2_gsi = gsi;
10948   gimple *scan_stmt2 = gsi_stmt (gsi);
10949   gcc_assert (scan_stmt2 && gimple_code (scan_stmt2) == GIMPLE_OMP_SCAN);
10950   gimple_omp_set_body (scan_stmt2, scan_body);
10951 
10952   gimple_stmt_iterator input3_gsi = gsi_none ();
10953   gimple_stmt_iterator scan3_gsi = gsi_none ();
10954   gimple_stmt_iterator input4_gsi = gsi_none ();
10955   gimple_stmt_iterator scan4_gsi = gsi_none ();
10956   gimple *input_stmt3 = NULL, *scan_stmt3 = NULL;
10957   gimple *input_stmt4 = NULL, *scan_stmt4 = NULL;
10958   omp_context *input_simd_ctx = NULL, *scan_simd_ctx = NULL;
10959   if (is_for_simd)
10960     {
10961       memset (&wi, 0, sizeof (wi));
10962       wi.val_only = true;
10963       wi.info = (void *) &input3_gsi;
10964       walk_gimple_seq_mod (&input_body, omp_find_scan, NULL, &wi);
10965       gcc_assert (!gsi_end_p (input3_gsi));
10966 
10967       input_stmt3 = gsi_stmt (input3_gsi);
10968       gsi = input3_gsi;
10969       gsi_next (&gsi);
10970       scan3_gsi = gsi;
10971       scan_stmt3 = gsi_stmt (gsi);
10972       gcc_assert (scan_stmt3 && gimple_code (scan_stmt3) == GIMPLE_OMP_SCAN);
10973 
10974       memset (&wi, 0, sizeof (wi));
10975       wi.val_only = true;
10976       wi.info = (void *) &input4_gsi;
10977       walk_gimple_seq_mod (&scan_body, omp_find_scan, NULL, &wi);
10978       gcc_assert (!gsi_end_p (input4_gsi));
10979 
10980       input_stmt4 = gsi_stmt (input4_gsi);
10981       gsi = input4_gsi;
10982       gsi_next (&gsi);
10983       scan4_gsi = gsi;
10984       scan_stmt4 = gsi_stmt (gsi);
10985       gcc_assert (scan_stmt4 && gimple_code (scan_stmt4) == GIMPLE_OMP_SCAN);
10986 
10987       input_simd_ctx = maybe_lookup_ctx (input_stmt3)->outer;
10988       scan_simd_ctx = maybe_lookup_ctx (input_stmt4)->outer;
10989     }
10990 
10991   tree num_threads = create_tmp_var (integer_type_node);
10992   tree thread_num = create_tmp_var (integer_type_node);
10993   tree nthreads_decl = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
10994   tree threadnum_decl = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
10995   gimple *g = gimple_build_call (nthreads_decl, 0);
10996   gimple_call_set_lhs (g, num_threads);
10997   gimple_seq_add_stmt (body_p, g);
10998   g = gimple_build_call (threadnum_decl, 0);
10999   gimple_call_set_lhs (g, thread_num);
11000   gimple_seq_add_stmt (body_p, g);
11001 
11002   tree ivar = create_tmp_var (sizetype);
11003   tree new_clauses1 = NULL_TREE, new_clauses2 = NULL_TREE;
11004   tree *cp1 = &new_clauses1, *cp2 = &new_clauses2;
11005   tree k = create_tmp_var (unsigned_type_node);
11006   tree l = create_tmp_var (unsigned_type_node);
11007 
11008   gimple_seq clist = NULL, mdlist = NULL;
11009   gimple_seq thr01_list = NULL, thrn1_list = NULL;
11010   gimple_seq thr02_list = NULL, thrn2_list = NULL;
11011   gimple_seq scan1_list = NULL, input2_list = NULL;
11012   gimple_seq last_list = NULL, reduc_list = NULL;
11013   for (tree c = gimple_omp_for_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c))
11014     if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
11015           && OMP_CLAUSE_REDUCTION_INSCAN (c))
11016       {
11017           location_t clause_loc = OMP_CLAUSE_LOCATION (c);
11018           tree var = OMP_CLAUSE_DECL (c);
11019           tree new_var = lookup_decl (var, ctx);
11020           tree var3 = NULL_TREE;
11021           tree new_vard = new_var;
11022           if (omp_privatize_by_reference (var))
11023             new_var = build_simple_mem_ref_loc (clause_loc, new_var);
11024           if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
11025             {
11026               var3 = maybe_lookup_decl (new_vard, ctx);
11027               if (var3 == new_vard)
11028                 var3 = NULL_TREE;
11029             }
11030 
11031           tree ptype = build_pointer_type (TREE_TYPE (new_var));
11032           tree rpriva = create_tmp_var (ptype);
11033           tree nc = build_omp_clause (clause_loc, OMP_CLAUSE__SCANTEMP_);
11034           OMP_CLAUSE_DECL (nc) = rpriva;
11035           *cp1 = nc;
11036           cp1 = &OMP_CLAUSE_CHAIN (nc);
11037 
11038           tree rprivb = create_tmp_var (ptype);
11039           nc = build_omp_clause (clause_loc, OMP_CLAUSE__SCANTEMP_);
11040           OMP_CLAUSE_DECL (nc) = rprivb;
11041           OMP_CLAUSE__SCANTEMP__ALLOC (nc) = 1;
11042           *cp1 = nc;
11043           cp1 = &OMP_CLAUSE_CHAIN (nc);
11044 
11045           tree var2 = create_tmp_var_raw (TREE_TYPE (new_var));
11046           if (new_vard != new_var)
11047             TREE_ADDRESSABLE (var2) = 1;
11048           gimple_add_tmp_var (var2);
11049 
11050           tree x = fold_convert_loc (clause_loc, sizetype, thread_num);
11051           x = fold_build2_loc (clause_loc, MULT_EXPR, sizetype, x,
11052                                    TYPE_SIZE_UNIT (TREE_TYPE (ptype)));
11053           x = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (rpriva), rpriva, x);
11054           tree rpriva_ref = build_simple_mem_ref_loc (clause_loc, x);
11055 
11056           x = fold_build2_loc (clause_loc, PLUS_EXPR, integer_type_node,
11057                                    thread_num, integer_minus_one_node);
11058           x = fold_convert_loc (clause_loc, sizetype, x);
11059           x = fold_build2_loc (clause_loc, MULT_EXPR, sizetype, x,
11060                                    TYPE_SIZE_UNIT (TREE_TYPE (ptype)));
11061           x = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (rpriva), rpriva, x);
11062           tree rprivam1_ref = build_simple_mem_ref_loc (clause_loc, x);
11063 
11064           x = fold_convert_loc (clause_loc, sizetype, l);
11065           x = fold_build2_loc (clause_loc, MULT_EXPR, sizetype, x,
11066                                    TYPE_SIZE_UNIT (TREE_TYPE (ptype)));
11067           x = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (rpriva), rpriva, x);
11068           tree rprival_ref = build_simple_mem_ref_loc (clause_loc, x);
11069 
11070           x = fold_build2_loc (clause_loc, MINUS_EXPR, unsigned_type_node, l, k);
11071           x = fold_convert_loc (clause_loc, sizetype, x);
11072           x = fold_build2_loc (clause_loc, MULT_EXPR, sizetype, x,
11073                                    TYPE_SIZE_UNIT (TREE_TYPE (ptype)));
11074           x = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (rpriva), rpriva, x);
11075           tree rprivalmk_ref = build_simple_mem_ref_loc (clause_loc, x);
11076 
11077           x = fold_build2_loc (clause_loc, MULT_EXPR, sizetype, ivar,
11078                                    TYPE_SIZE_UNIT (TREE_TYPE (ptype)));
11079           x = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (rprivb), rprivb, x);
11080           tree rprivb_ref = build_simple_mem_ref_loc (clause_loc, x);
11081 
11082           tree var4 = is_for_simd ? new_var : var2;
11083           tree var5 = NULL_TREE, var6 = NULL_TREE;
11084           if (is_for_simd)
11085             {
11086               var5 = lookup_decl (var, input_simd_ctx);
11087               var6 = lookup_decl (var, scan_simd_ctx);
11088               if (new_vard != new_var)
11089                 {
11090                     var5 = build_simple_mem_ref_loc (clause_loc, var5);
11091                     var6 = build_simple_mem_ref_loc (clause_loc, var6);
11092                 }
11093             }
11094           if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
11095             {
11096               tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
11097               tree val = var2;
11098 
11099               x = lang_hooks.decls.omp_clause_default_ctor
11100                         (c, var2, build_outer_var_ref (var, ctx));
11101               if (x)
11102                 gimplify_and_add (x, &clist);
11103 
11104               x = build_outer_var_ref (var, ctx);
11105               x = lang_hooks.decls.omp_clause_assign_op (c, unshare_expr (var4),
11106                                                                    x);
11107               gimplify_and_add (x, &thr01_list);
11108 
11109               tree y = (DECL_HAS_VALUE_EXPR_P (new_vard)
11110                           ? DECL_VALUE_EXPR (new_vard) : NULL_TREE);
11111               if (var3)
11112                 {
11113                     x = unshare_expr (var4);
11114                     x = lang_hooks.decls.omp_clause_assign_op (c, x, var3);
11115                     gimplify_and_add (x, &thrn1_list);
11116                     x = unshare_expr (var4);
11117                     x = lang_hooks.decls.omp_clause_assign_op (c, x, var3);
11118                     gimplify_and_add (x, &thr02_list);
11119                 }
11120               else if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
11121                 {
11122                     /* Otherwise, assign to it the identity element.  */
11123                     gimple_seq tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
11124                     tseq = copy_gimple_seq_and_replace_locals (tseq);
11125                     if (!is_for_simd)
11126                       {
11127                         if (new_vard != new_var)
11128                           val = build_fold_addr_expr_loc (clause_loc, val);
11129                         SET_DECL_VALUE_EXPR (new_vard, val);
11130                         DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
11131                       }
11132                     SET_DECL_VALUE_EXPR (placeholder, error_mark_node);
11133                     DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
11134                     lower_omp (&tseq, ctx);
11135                     gimple_seq_add_seq (&thrn1_list, tseq);
11136                     tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
11137                     lower_omp (&tseq, ctx);
11138                     gimple_seq_add_seq (&thr02_list, tseq);
11139                     SET_DECL_VALUE_EXPR (placeholder, NULL_TREE);
11140                     DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
11141                     OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
11142                     if (y)
11143                       SET_DECL_VALUE_EXPR (new_vard, y);
11144                     else
11145                       {
11146                         DECL_HAS_VALUE_EXPR_P (new_vard) = 0;
11147                         SET_DECL_VALUE_EXPR (new_vard, NULL_TREE);
11148                       }
11149                 }
11150 
11151               x = unshare_expr (var4);
11152               x = lang_hooks.decls.omp_clause_assign_op (c, x, rprivam1_ref);
11153               gimplify_and_add (x, &thrn2_list);
11154 
11155               if (is_for_simd)
11156                 {
11157                     x = unshare_expr (rprivb_ref);
11158                     x = lang_hooks.decls.omp_clause_assign_op (c, x, var5);
11159                     gimplify_and_add (x, &scan1_list);
11160                 }
11161               else
11162                 {
11163                     if (ctx->scan_exclusive)
11164                       {
11165                         x = unshare_expr (rprivb_ref);
11166                         x = lang_hooks.decls.omp_clause_assign_op (c, x, var2);
11167                         gimplify_and_add (x, &scan1_list);
11168                       }
11169 
11170                     gimple_seq tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
11171                     tseq = copy_gimple_seq_and_replace_locals (tseq);
11172                     SET_DECL_VALUE_EXPR (placeholder, var2);
11173                     DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
11174                     lower_omp (&tseq, ctx);
11175                     gimple_seq_add_seq (&scan1_list, tseq);
11176 
11177                     if (ctx->scan_inclusive)
11178                       {
11179                         x = unshare_expr (rprivb_ref);
11180                         x = lang_hooks.decls.omp_clause_assign_op (c, x, var2);
11181                         gimplify_and_add (x, &scan1_list);
11182                       }
11183                 }
11184 
11185               x = unshare_expr (rpriva_ref);
11186               x = lang_hooks.decls.omp_clause_assign_op (c, x,
11187                                                                    unshare_expr (var4));
11188               gimplify_and_add (x, &mdlist);
11189 
11190               x = unshare_expr (is_for_simd ? var6 : new_var);
11191               x = lang_hooks.decls.omp_clause_assign_op (c, x, var4);
11192               gimplify_and_add (x, &input2_list);
11193 
11194               val = rprivb_ref;
11195               if (new_vard != new_var)
11196                 val = build_fold_addr_expr_loc (clause_loc, val);
11197 
11198               gimple_seq tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
11199               tseq = copy_gimple_seq_and_replace_locals (tseq);
11200               SET_DECL_VALUE_EXPR (new_vard, val);
11201               DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
11202               if (is_for_simd)
11203                 {
11204                     SET_DECL_VALUE_EXPR (placeholder, var6);
11205                     DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
11206                 }
11207               else
11208                 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
11209               lower_omp (&tseq, ctx);
11210               if (y)
11211                 SET_DECL_VALUE_EXPR (new_vard, y);
11212               else
11213                 {
11214                     DECL_HAS_VALUE_EXPR_P (new_vard) = 0;
11215                     SET_DECL_VALUE_EXPR (new_vard, NULL_TREE);
11216                 }
11217               if (!is_for_simd)
11218                 {
11219                     SET_DECL_VALUE_EXPR (placeholder, new_var);
11220                     DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
11221                     lower_omp (&tseq, ctx);
11222                 }
11223               gimple_seq_add_seq (&input2_list, tseq);
11224 
11225               x = build_outer_var_ref (var, ctx);
11226               x = lang_hooks.decls.omp_clause_assign_op (c, x, rpriva_ref);
11227               gimplify_and_add (x, &last_list);
11228 
11229               x = lang_hooks.decls.omp_clause_assign_op (c, var2, rprivalmk_ref);
11230               gimplify_and_add (x, &reduc_list);
11231               tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
11232               tseq = copy_gimple_seq_and_replace_locals (tseq);
11233               val = rprival_ref;
11234               if (new_vard != new_var)
11235                 val = build_fold_addr_expr_loc (clause_loc, val);
11236               SET_DECL_VALUE_EXPR (new_vard, val);
11237               DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
11238               SET_DECL_VALUE_EXPR (placeholder, var2);
11239               lower_omp (&tseq, ctx);
11240               OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
11241               SET_DECL_VALUE_EXPR (placeholder, NULL_TREE);
11242               DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
11243               if (y)
11244                 SET_DECL_VALUE_EXPR (new_vard, y);
11245               else
11246                 {
11247                     DECL_HAS_VALUE_EXPR_P (new_vard) = 0;
11248                     SET_DECL_VALUE_EXPR (new_vard, NULL_TREE);
11249                 }
11250               gimple_seq_add_seq (&reduc_list, tseq);
11251               x = lang_hooks.decls.omp_clause_assign_op (c, rprival_ref, var2);
11252               gimplify_and_add (x, &reduc_list);
11253 
11254               x = lang_hooks.decls.omp_clause_dtor (c, var2);
11255               if (x)
11256                 gimplify_and_add (x, dlist);
11257             }
11258           else
11259             {
11260               x = build_outer_var_ref (var, ctx);
11261               gimplify_assign (unshare_expr (var4), x, &thr01_list);
11262 
11263               x = omp_reduction_init (c, TREE_TYPE (new_var));
11264               gimplify_assign (unshare_expr (var4), unshare_expr (x),
11265                                    &thrn1_list);
11266               gimplify_assign (unshare_expr (var4), x, &thr02_list);
11267 
11268               gimplify_assign (unshare_expr (var4), rprivam1_ref, &thrn2_list);
11269 
11270               enum tree_code code = OMP_CLAUSE_REDUCTION_CODE (c);
11271               if (code == MINUS_EXPR)
11272                 code = PLUS_EXPR;
11273 
11274               if (is_for_simd)
11275                 gimplify_assign (unshare_expr (rprivb_ref), var5, &scan1_list);
11276               else
11277                 {
11278                     if (ctx->scan_exclusive)
11279                       gimplify_assign (unshare_expr (rprivb_ref), var2,
11280                                            &scan1_list);
11281                     x = build2 (code, TREE_TYPE (new_var), var2, new_var);
11282                     gimplify_assign (var2, x, &scan1_list);
11283                     if (ctx->scan_inclusive)
11284                       gimplify_assign (unshare_expr (rprivb_ref), var2,
11285                                            &scan1_list);
11286                 }
11287 
11288               gimplify_assign (unshare_expr (rpriva_ref), unshare_expr (var4),
11289                                    &mdlist);
11290 
11291               x = build2 (code, TREE_TYPE (new_var), var4, rprivb_ref);
11292               gimplify_assign (is_for_simd ? var6 : new_var, x, &input2_list);
11293 
11294               gimplify_assign (build_outer_var_ref (var, ctx), rpriva_ref,
11295                                    &last_list);
11296 
11297               x = build2 (code, TREE_TYPE (new_var), rprivalmk_ref,
11298                               unshare_expr (rprival_ref));
11299               gimplify_assign (rprival_ref, x, &reduc_list);
11300             }
11301       }
11302 
11303   g = gimple_build_assign (ivar, PLUS_EXPR, ivar, size_one_node);
11304   gimple_seq_add_stmt (&scan1_list, g);
11305   g = gimple_build_assign (ivar, PLUS_EXPR, ivar, size_one_node);
11306   gimple_seq_add_stmt (gimple_omp_body_ptr (is_for_simd
11307                                                       ? scan_stmt4 : scan_stmt2), g);
11308 
11309   tree controlb = create_tmp_var (boolean_type_node);
11310   tree controlp = create_tmp_var (ptr_type_node);
11311   tree nc = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__SCANTEMP_);
11312   OMP_CLAUSE_DECL (nc) = controlb;
11313   OMP_CLAUSE__SCANTEMP__CONTROL (nc) = 1;
11314   *cp1 = nc;
11315   cp1 = &OMP_CLAUSE_CHAIN (nc);
11316   nc = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__SCANTEMP_);
11317   OMP_CLAUSE_DECL (nc) = controlp;
11318   OMP_CLAUSE__SCANTEMP__CONTROL (nc) = 1;
11319   *cp1 = nc;
11320   cp1 = &OMP_CLAUSE_CHAIN (nc);
11321   nc = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__SCANTEMP_);
11322   OMP_CLAUSE_DECL (nc) = controlb;
11323   OMP_CLAUSE__SCANTEMP__CONTROL (nc) = 1;
11324   *cp2 = nc;
11325   cp2 = &OMP_CLAUSE_CHAIN (nc);
11326   nc = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__SCANTEMP_);
11327   OMP_CLAUSE_DECL (nc) = controlp;
11328   OMP_CLAUSE__SCANTEMP__CONTROL (nc) = 1;
11329   *cp2 = nc;
11330   cp2 = &OMP_CLAUSE_CHAIN (nc);
11331 
11332   *cp1 = gimple_omp_for_clauses (stmt);
11333   gimple_omp_for_set_clauses (stmt, new_clauses1);
11334   *cp2 = gimple_omp_for_clauses (new_stmt);
11335   gimple_omp_for_set_clauses (new_stmt, new_clauses2);
11336 
11337   if (is_for_simd)
11338     {
11339       gimple_seq_add_seq (gimple_omp_body_ptr (scan_stmt3), scan1_list);
11340       gimple_seq_add_seq (gimple_omp_body_ptr (input_stmt4), input2_list);
11341 
11342       gsi_insert_seq_after (&input3_gsi, gimple_omp_body (input_stmt3),
11343                                   GSI_SAME_STMT);
11344       gsi_remove (&input3_gsi, true);
11345       gsi_insert_seq_after (&scan3_gsi, gimple_omp_body (scan_stmt3),
11346                                   GSI_SAME_STMT);
11347       gsi_remove (&scan3_gsi, true);
11348       gsi_insert_seq_after (&input4_gsi, gimple_omp_body (input_stmt4),
11349                                   GSI_SAME_STMT);
11350       gsi_remove (&input4_gsi, true);
11351       gsi_insert_seq_after (&scan4_gsi, gimple_omp_body (scan_stmt4),
11352                                   GSI_SAME_STMT);
11353       gsi_remove (&scan4_gsi, true);
11354     }
11355   else
11356     {
11357       gimple_omp_set_body (scan_stmt1, scan1_list);
11358       gimple_omp_set_body (input_stmt2, input2_list);
11359     }
11360 
11361   gsi_insert_seq_after (&input1_gsi, gimple_omp_body (input_stmt1),
11362                               GSI_SAME_STMT);
11363   gsi_remove (&input1_gsi, true);
11364   gsi_insert_seq_after (&scan1_gsi, gimple_omp_body (scan_stmt1),
11365                               GSI_SAME_STMT);
11366   gsi_remove (&scan1_gsi, true);
11367   gsi_insert_seq_after (&input2_gsi, gimple_omp_body (input_stmt2),
11368                               GSI_SAME_STMT);
11369   gsi_remove (&input2_gsi, true);
11370   gsi_insert_seq_after (&scan2_gsi, gimple_omp_body (scan_stmt2),
11371                               GSI_SAME_STMT);
11372   gsi_remove (&scan2_gsi, true);
11373 
11374   gimple_seq_add_seq (body_p, clist);
11375 
11376   tree lab1 = create_artificial_label (UNKNOWN_LOCATION);
11377   tree lab2 = create_artificial_label (UNKNOWN_LOCATION);
11378   tree lab3 = create_artificial_label (UNKNOWN_LOCATION);
11379   g = gimple_build_cond (EQ_EXPR, thread_num, integer_zero_node, lab1, lab2);
11380   gimple_seq_add_stmt (body_p, g);
11381   g = gimple_build_label (lab1);
11382   gimple_seq_add_stmt (body_p, g);
11383   gimple_seq_add_seq (body_p, thr01_list);
11384   g = gimple_build_goto (lab3);
11385   gimple_seq_add_stmt (body_p, g);
11386   g = gimple_build_label (lab2);
11387   gimple_seq_add_stmt (body_p, g);
11388   gimple_seq_add_seq (body_p, thrn1_list);
11389   g = gimple_build_label (lab3);
11390   gimple_seq_add_stmt (body_p, g);
11391 
11392   g = gimple_build_assign (ivar, size_zero_node);
11393   gimple_seq_add_stmt (body_p, g);
11394 
11395   gimple_seq_add_stmt (body_p, stmt);
11396   gimple_seq_add_seq (body_p, body);
11397   gimple_seq_add_stmt (body_p, gimple_build_omp_continue (fd->loop.v,
11398                                                                         fd->loop.v));
11399 
11400   g = gimple_build_omp_return (true);
11401   gimple_seq_add_stmt (body_p, g);
11402   gimple_seq_add_seq (body_p, mdlist);
11403 
11404   lab1 = create_artificial_label (UNKNOWN_LOCATION);
11405   lab2 = create_artificial_label (UNKNOWN_LOCATION);
11406   g = gimple_build_cond (GT_EXPR, num_threads, integer_one_node, lab1, lab2);
11407   gimple_seq_add_stmt (body_p, g);
11408   g = gimple_build_label (lab1);
11409   gimple_seq_add_stmt (body_p, g);
11410 
11411   g = omp_build_barrier (NULL);
11412   gimple_seq_add_stmt (body_p, g);
11413 
11414   tree down = create_tmp_var (unsigned_type_node);
11415   g = gimple_build_assign (down, build_zero_cst (unsigned_type_node));
11416   gimple_seq_add_stmt (body_p, g);
11417 
11418   g = gimple_build_assign (k, build_one_cst (unsigned_type_node));
11419   gimple_seq_add_stmt (body_p, g);
11420 
11421   tree num_threadsu = create_tmp_var (unsigned_type_node);
11422   g = gimple_build_assign (num_threadsu, NOP_EXPR, num_threads);
11423   gimple_seq_add_stmt (body_p, g);
11424 
11425   tree thread_numu = create_tmp_var (unsigned_type_node);
11426   g = gimple_build_assign (thread_numu, NOP_EXPR, thread_num);
11427   gimple_seq_add_stmt (body_p, g);
11428 
11429   tree thread_nump1 = create_tmp_var (unsigned_type_node);
11430   g = gimple_build_assign (thread_nump1, PLUS_EXPR, thread_numu,
11431                                  build_int_cst (unsigned_type_node, 1));
11432   gimple_seq_add_stmt (body_p, g);
11433 
11434   lab3 = create_artificial_label (UNKNOWN_LOCATION);
11435   g = gimple_build_label (lab3);
11436   gimple_seq_add_stmt (body_p, g);
11437 
11438   tree twok = create_tmp_var (unsigned_type_node);
11439   g = gimple_build_assign (twok, LSHIFT_EXPR, k, integer_one_node);
11440   gimple_seq_add_stmt (body_p, g);
11441 
11442   tree lab4 = create_artificial_label (UNKNOWN_LOCATION);
11443   tree lab5 = create_artificial_label (UNKNOWN_LOCATION);
11444   tree lab6 = create_artificial_label (UNKNOWN_LOCATION);
11445   g = gimple_build_cond (GT_EXPR, twok, num_threadsu, lab4, lab5);
11446   gimple_seq_add_stmt (body_p, g);
11447   g = gimple_build_label (lab4);
11448   gimple_seq_add_stmt (body_p, g);
11449   g = gimple_build_assign (down, build_all_ones_cst (unsigned_type_node));
11450   gimple_seq_add_stmt (body_p, g);
11451   g = gimple_build_assign (k, RSHIFT_EXPR, k, integer_one_node);
11452   gimple_seq_add_stmt (body_p, g);
11453 
11454   g = gimple_build_cond (EQ_EXPR, k, num_threadsu, lab6, lab5);
11455   gimple_seq_add_stmt (body_p, g);
11456   g = gimple_build_label (lab6);
11457   gimple_seq_add_stmt (body_p, g);
11458 
11459   g = gimple_build_assign (k, RSHIFT_EXPR, k, integer_one_node);
11460   gimple_seq_add_stmt (body_p, g);
11461 
11462   g = gimple_build_label (lab5);
11463   gimple_seq_add_stmt (body_p, g);
11464 
11465   g = gimple_build_assign (twok, LSHIFT_EXPR, k, integer_one_node);
11466   gimple_seq_add_stmt (body_p, g);
11467 
11468   tree cplx = create_tmp_var (build_complex_type (unsigned_type_node, false));
11469   g = gimple_build_call_internal (IFN_MUL_OVERFLOW, 2, thread_nump1, twok);
11470   gimple_call_set_lhs (g, cplx);
11471   gimple_seq_add_stmt (body_p, g);
11472   tree mul = create_tmp_var (unsigned_type_node);
11473   g = gimple_build_assign (mul, REALPART_EXPR,
11474                                  build1 (REALPART_EXPR, unsigned_type_node, cplx));
11475   gimple_seq_add_stmt (body_p, g);
11476   tree ovf = create_tmp_var (unsigned_type_node);
11477   g = gimple_build_assign (ovf, IMAGPART_EXPR,
11478                                  build1 (IMAGPART_EXPR, unsigned_type_node, cplx));
11479   gimple_seq_add_stmt (body_p, g);
11480 
11481   tree lab7 = create_artificial_label (UNKNOWN_LOCATION);
11482   tree lab8 = create_artificial_label (UNKNOWN_LOCATION);
11483   g = gimple_build_cond (EQ_EXPR, ovf, build_zero_cst (unsigned_type_node),
11484                                lab7, lab8);
11485   gimple_seq_add_stmt (body_p, g);
11486   g = gimple_build_label (lab7);
11487   gimple_seq_add_stmt (body_p, g);
11488 
11489   tree andv = create_tmp_var (unsigned_type_node);
11490   g = gimple_build_assign (andv, BIT_AND_EXPR, k, down);
11491   gimple_seq_add_stmt (body_p, g);
11492   tree andvm1 = create_tmp_var (unsigned_type_node);
11493   g = gimple_build_assign (andvm1, PLUS_EXPR, andv,
11494                                  build_minus_one_cst (unsigned_type_node));
11495   gimple_seq_add_stmt (body_p, g);
11496 
11497   g = gimple_build_assign (l, PLUS_EXPR, mul, andvm1);
11498   gimple_seq_add_stmt (body_p, g);
11499 
11500   tree lab9 = create_artificial_label (UNKNOWN_LOCATION);
11501   g = gimple_build_cond (LT_EXPR, l, num_threadsu, lab9, lab8);
11502   gimple_seq_add_stmt (body_p, g);
11503   g = gimple_build_label (lab9);
11504   gimple_seq_add_stmt (body_p, g);
11505   gimple_seq_add_seq (body_p, reduc_list);
11506   g = gimple_build_label (lab8);
11507   gimple_seq_add_stmt (body_p, g);
11508 
11509   tree lab10 = create_artificial_label (UNKNOWN_LOCATION);
11510   tree lab11 = create_artificial_label (UNKNOWN_LOCATION);
11511   tree lab12 = create_artificial_label (UNKNOWN_LOCATION);
11512   g = gimple_build_cond (EQ_EXPR, down, build_zero_cst (unsigned_type_node),
11513                                lab10, lab11);
11514   gimple_seq_add_stmt (body_p, g);
11515   g = gimple_build_label (lab10);
11516   gimple_seq_add_stmt (body_p, g);
11517   g = gimple_build_assign (k, LSHIFT_EXPR, k, integer_one_node);
11518   gimple_seq_add_stmt (body_p, g);
11519   g = gimple_build_goto (lab12);
11520   gimple_seq_add_stmt (body_p, g);
11521   g = gimple_build_label (lab11);
11522   gimple_seq_add_stmt (body_p, g);
11523   g = gimple_build_assign (k, RSHIFT_EXPR, k, integer_one_node);
11524   gimple_seq_add_stmt (body_p, g);
11525   g = gimple_build_label (lab12);
11526   gimple_seq_add_stmt (body_p, g);
11527 
11528   g = omp_build_barrier (NULL);
11529   gimple_seq_add_stmt (body_p, g);
11530 
11531   g = gimple_build_cond (NE_EXPR, k, build_zero_cst (unsigned_type_node),
11532                                lab3, lab2);
11533   gimple_seq_add_stmt (body_p, g);
11534 
11535   g = gimple_build_label (lab2);
11536   gimple_seq_add_stmt (body_p, g);
11537 
11538   lab1 = create_artificial_label (UNKNOWN_LOCATION);
11539   lab2 = create_artificial_label (UNKNOWN_LOCATION);
11540   lab3 = create_artificial_label (UNKNOWN_LOCATION);
11541   g = gimple_build_cond (EQ_EXPR, thread_num, integer_zero_node, lab1, lab2);
11542   gimple_seq_add_stmt (body_p, g);
11543   g = gimple_build_label (lab1);
11544   gimple_seq_add_stmt (body_p, g);
11545   gimple_seq_add_seq (body_p, thr02_list);
11546   g = gimple_build_goto (lab3);
11547   gimple_seq_add_stmt (body_p, g);
11548   g = gimple_build_label (lab2);
11549   gimple_seq_add_stmt (body_p, g);
11550   gimple_seq_add_seq (body_p, thrn2_list);
11551   g = gimple_build_label (lab3);
11552   gimple_seq_add_stmt (body_p, g);
11553 
11554   g = gimple_build_assign (ivar, size_zero_node);
11555   gimple_seq_add_stmt (body_p, g);
11556   gimple_seq_add_stmt (body_p, new_stmt);
11557   gimple_seq_add_seq (body_p, new_body);
11558 
11559   gimple_seq new_dlist = NULL;
11560   lab1 = create_artificial_label (UNKNOWN_LOCATION);
11561   lab2 = create_artificial_label (UNKNOWN_LOCATION);
11562   tree num_threadsm1 = create_tmp_var (integer_type_node);
11563   g = gimple_build_assign (num_threadsm1, PLUS_EXPR, num_threads,
11564                                  integer_minus_one_node);
11565   gimple_seq_add_stmt (&new_dlist, g);
11566   g = gimple_build_cond (EQ_EXPR, thread_num, num_threadsm1, lab1, lab2);
11567   gimple_seq_add_stmt (&new_dlist, g);
11568   g = gimple_build_label (lab1);
11569   gimple_seq_add_stmt (&new_dlist, g);
11570   gimple_seq_add_seq (&new_dlist, last_list);
11571   g = gimple_build_label (lab2);
11572   gimple_seq_add_stmt (&new_dlist, g);
11573   gimple_seq_add_seq (&new_dlist, *dlist);
11574   *dlist = new_dlist;
11575 }
11576 
11577 /* Build an internal UNIQUE function with type IFN_UNIQUE_OACC_PRIVATE listing
11578    the addresses of variables to be made private at the surrounding
11579    parallelism level.  Such functions appear in the gimple code stream in two
11580    forms, e.g. for a partitioned loop:
11581 
11582       .data_dep.6 = .UNIQUE (OACC_HEAD_MARK, .data_dep.6, 1, 68);
11583       .data_dep.6 = .UNIQUE (OACC_PRIVATE, .data_dep.6, -1, &w);
11584       .data_dep.6 = .UNIQUE (OACC_FORK, .data_dep.6, -1);
11585       .data_dep.6 = .UNIQUE (OACC_HEAD_MARK, .data_dep.6);
11586 
11587    or alternatively, OACC_PRIVATE can appear at the top level of a parallel,
11588    not as part of a HEAD_MARK sequence:
11589 
11590       .UNIQUE (OACC_PRIVATE, 0, 0, &w);
11591 
11592    For such stand-alone appearances, the 3rd argument is always 0, denoting
11593    gang partitioning.  */
11594 
11595 static gcall *
lower_oacc_private_marker(omp_context * ctx)11596 lower_oacc_private_marker (omp_context *ctx)
11597 {
11598   if (ctx->oacc_privatization_candidates.length () == 0)
11599     return NULL;
11600 
11601   auto_vec<tree, 5> args;
11602 
11603   args.quick_push (build_int_cst (integer_type_node, IFN_UNIQUE_OACC_PRIVATE));
11604   args.quick_push (integer_zero_node);
11605   args.quick_push (integer_minus_one_node);
11606 
11607   int i;
11608   tree decl;
11609   FOR_EACH_VEC_ELT (ctx->oacc_privatization_candidates, i, decl)
11610     {
11611       gcc_checking_assert (TREE_ADDRESSABLE (decl));
11612       tree addr = build_fold_addr_expr (decl);
11613       args.safe_push (addr);
11614     }
11615 
11616   return gimple_build_call_internal_vec (IFN_UNIQUE, args);
11617 }
11618 
11619 /* Lower code for an OMP loop directive.  */
11620 
11621 static void
lower_omp_for(gimple_stmt_iterator * gsi_p,omp_context * ctx)11622 lower_omp_for (gimple_stmt_iterator *gsi_p, omp_context *ctx)
11623 {
11624   tree *rhs_p, block;
11625   struct omp_for_data fd, *fdp = NULL;
11626   gomp_for *stmt = as_a <gomp_for *> (gsi_stmt (*gsi_p));
11627   gbind *new_stmt;
11628   gimple_seq omp_for_body, body, dlist, tred_ilist = NULL, tred_dlist = NULL;
11629   gimple_seq cnt_list = NULL, clist = NULL;
11630   gimple_seq oacc_head = NULL, oacc_tail = NULL;
11631   size_t i;
11632 
11633   push_gimplify_context ();
11634 
11635   if (is_gimple_omp_oacc (ctx->stmt))
11636     oacc_privatization_scan_clause_chain (ctx, gimple_omp_for_clauses (stmt));
11637 
11638   lower_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
11639 
11640   block = make_node (BLOCK);
11641   new_stmt = gimple_build_bind (NULL, NULL, block);
11642   /* Replace at gsi right away, so that 'stmt' is no member
11643      of a sequence anymore as we're going to add to a different
11644      one below.  */
11645   gsi_replace (gsi_p, new_stmt, true);
11646 
11647   /* Move declaration of temporaries in the loop body before we make
11648      it go away.  */
11649   omp_for_body = gimple_omp_body (stmt);
11650   if (!gimple_seq_empty_p (omp_for_body)
11651       && gimple_code (gimple_seq_first_stmt (omp_for_body)) == GIMPLE_BIND)
11652     {
11653       gbind *inner_bind
11654           = as_a <gbind *> (gimple_seq_first_stmt (omp_for_body));
11655       tree vars = gimple_bind_vars (inner_bind);
11656       if (is_gimple_omp_oacc (ctx->stmt))
11657           oacc_privatization_scan_decl_chain (ctx, vars);
11658       gimple_bind_append_vars (new_stmt, vars);
11659       /* bind_vars/BLOCK_VARS are being moved to new_stmt/block, don't
11660            keep them on the inner_bind and it's block.  */
11661       gimple_bind_set_vars (inner_bind, NULL_TREE);
11662       if (gimple_bind_block (inner_bind))
11663           BLOCK_VARS (gimple_bind_block (inner_bind)) = NULL_TREE;
11664     }
11665 
11666   if (gimple_omp_for_combined_into_p (stmt))
11667     {
11668       omp_extract_for_data (stmt, &fd, NULL);
11669       fdp = &fd;
11670 
11671       /* We need two temporaries with fd.loop.v type (istart/iend)
11672            and then (fd.collapse - 1) temporaries with the same
11673            type for count2 ... countN-1 vars if not constant.  */
11674       size_t count = 2;
11675       tree type = fd.iter_type;
11676       if (fd.collapse > 1
11677             && TREE_CODE (fd.loop.n2) != INTEGER_CST)
11678           count += fd.collapse - 1;
11679       size_t count2 = 0;
11680       tree type2 = NULL_TREE;
11681       bool taskreg_for
11682           = (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR
11683              || gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_TASKLOOP);
11684       tree outerc = NULL, *pc = gimple_omp_for_clauses_ptr (stmt);
11685       tree simtc = NULL;
11686       tree clauses = *pc;
11687       if (fd.collapse > 1
11688             && fd.non_rect
11689             && fd.last_nonrect == fd.first_nonrect + 1
11690             && TREE_CODE (fd.loop.n2) != INTEGER_CST)
11691           if (tree v = gimple_omp_for_index (stmt, fd.last_nonrect))
11692             if (!TYPE_UNSIGNED (TREE_TYPE (v)))
11693               {
11694                 v = gimple_omp_for_index (stmt, fd.first_nonrect);
11695                 type2 = TREE_TYPE (v);
11696                 count++;
11697                 count2 = 3;
11698               }
11699       if (taskreg_for)
11700           outerc
11701             = omp_find_clause (gimple_omp_taskreg_clauses (ctx->outer->stmt),
11702                                    OMP_CLAUSE__LOOPTEMP_);
11703       if (ctx->simt_stmt)
11704           simtc = omp_find_clause (gimple_omp_for_clauses (ctx->simt_stmt),
11705                                          OMP_CLAUSE__LOOPTEMP_);
11706       for (i = 0; i < count + count2; i++)
11707           {
11708             tree temp;
11709             if (taskreg_for)
11710               {
11711                 gcc_assert (outerc);
11712                 temp = lookup_decl (OMP_CLAUSE_DECL (outerc), ctx->outer);
11713                 outerc = omp_find_clause (OMP_CLAUSE_CHAIN (outerc),
11714                                                   OMP_CLAUSE__LOOPTEMP_);
11715               }
11716             else
11717               {
11718                 /* If there are 2 adjacent SIMD stmts, one with _simt_
11719                      clause, another without, make sure they have the same
11720                      decls in _looptemp_ clauses, because the outer stmt
11721                      they are combined into will look up just one inner_stmt.  */
11722                 if (ctx->simt_stmt)
11723                     temp = OMP_CLAUSE_DECL (simtc);
11724                 else
11725                     temp = create_tmp_var (i >= count ? type2 : type);
11726                 insert_decl_map (&ctx->outer->cb, temp, temp);
11727               }
11728             *pc = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__LOOPTEMP_);
11729             OMP_CLAUSE_DECL (*pc) = temp;
11730             pc = &OMP_CLAUSE_CHAIN (*pc);
11731             if (ctx->simt_stmt)
11732               simtc = omp_find_clause (OMP_CLAUSE_CHAIN (simtc),
11733                                              OMP_CLAUSE__LOOPTEMP_);
11734           }
11735       *pc = clauses;
11736     }
11737 
11738   /* The pre-body and input clauses go before the lowered GIMPLE_OMP_FOR.  */
11739   dlist = NULL;
11740   body = NULL;
11741   tree rclauses
11742     = omp_task_reductions_find_first (gimple_omp_for_clauses (stmt), OMP_FOR,
11743                                               OMP_CLAUSE_REDUCTION);
11744   tree rtmp = NULL_TREE;
11745   if (rclauses)
11746     {
11747       tree type = build_pointer_type (pointer_sized_int_node);
11748       tree temp = create_tmp_var (type);
11749       tree c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__REDUCTEMP_);
11750       OMP_CLAUSE_DECL (c) = temp;
11751       OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (stmt);
11752       gimple_omp_for_set_clauses (stmt, c);
11753       lower_omp_task_reductions (ctx, OMP_FOR,
11754                                          gimple_omp_for_clauses (stmt),
11755                                          &tred_ilist, &tred_dlist);
11756       rclauses = c;
11757       rtmp = make_ssa_name (type);
11758       gimple_seq_add_stmt (&body, gimple_build_assign (rtmp, temp));
11759     }
11760 
11761   lower_lastprivate_conditional_clauses (gimple_omp_for_clauses_ptr (stmt),
11762                                                    ctx);
11763 
11764   lower_rec_input_clauses (gimple_omp_for_clauses (stmt), &body, &dlist, ctx,
11765                                  fdp);
11766   gimple_seq_add_seq (rclauses ? &tred_ilist : &body,
11767                           gimple_omp_for_pre_body (stmt));
11768 
11769   lower_omp (gimple_omp_body_ptr (stmt), ctx);
11770 
11771   gcall *private_marker = NULL;
11772   if (is_gimple_omp_oacc (ctx->stmt)
11773       && !gimple_seq_empty_p (omp_for_body))
11774     private_marker = lower_oacc_private_marker (ctx);
11775 
11776   /* Lower the header expressions.  At this point, we can assume that
11777      the header is of the form:
11778 
11779           #pragma omp for (V = VAL1; V {<|>|<=|>=} VAL2; V = V [+-] VAL3)
11780 
11781      We just need to make sure that VAL1, VAL2 and VAL3 are lowered
11782      using the .omp_data_s mapping, if needed.  */
11783   for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
11784     {
11785       rhs_p = gimple_omp_for_initial_ptr (stmt, i);
11786       if (TREE_CODE (*rhs_p) == TREE_VEC)
11787           {
11788             if (!is_gimple_min_invariant (TREE_VEC_ELT (*rhs_p, 1)))
11789               TREE_VEC_ELT (*rhs_p, 1)
11790                 = get_formal_tmp_var (TREE_VEC_ELT (*rhs_p, 1), &cnt_list);
11791             if (!is_gimple_min_invariant (TREE_VEC_ELT (*rhs_p, 2)))
11792               TREE_VEC_ELT (*rhs_p, 2)
11793                 = get_formal_tmp_var (TREE_VEC_ELT (*rhs_p, 2), &cnt_list);
11794           }
11795       else if (!is_gimple_min_invariant (*rhs_p))
11796           *rhs_p = get_formal_tmp_var (*rhs_p, &cnt_list);
11797       else if (TREE_CODE (*rhs_p) == ADDR_EXPR)
11798           recompute_tree_invariant_for_addr_expr (*rhs_p);
11799 
11800       rhs_p = gimple_omp_for_final_ptr (stmt, i);
11801       if (TREE_CODE (*rhs_p) == TREE_VEC)
11802           {
11803             if (!is_gimple_min_invariant (TREE_VEC_ELT (*rhs_p, 1)))
11804               TREE_VEC_ELT (*rhs_p, 1)
11805                 = get_formal_tmp_var (TREE_VEC_ELT (*rhs_p, 1), &cnt_list);
11806             if (!is_gimple_min_invariant (TREE_VEC_ELT (*rhs_p, 2)))
11807               TREE_VEC_ELT (*rhs_p, 2)
11808                 = get_formal_tmp_var (TREE_VEC_ELT (*rhs_p, 2), &cnt_list);
11809           }
11810       else if (!is_gimple_min_invariant (*rhs_p))
11811           *rhs_p = get_formal_tmp_var (*rhs_p, &cnt_list);
11812       else if (TREE_CODE (*rhs_p) == ADDR_EXPR)
11813           recompute_tree_invariant_for_addr_expr (*rhs_p);
11814 
11815       rhs_p = &TREE_OPERAND (gimple_omp_for_incr (stmt, i), 1);
11816       if (!is_gimple_min_invariant (*rhs_p))
11817           *rhs_p = get_formal_tmp_var (*rhs_p, &cnt_list);
11818     }
11819   if (rclauses)
11820     gimple_seq_add_seq (&tred_ilist, cnt_list);
11821   else
11822     gimple_seq_add_seq (&body, cnt_list);
11823 
11824   /* Once lowered, extract the bounds and clauses.  */
11825   omp_extract_for_data (stmt, &fd, NULL);
11826 
11827   if (is_gimple_omp_oacc (ctx->stmt)
11828       && !ctx_in_oacc_kernels_region (ctx))
11829     lower_oacc_head_tail (gimple_location (stmt),
11830                                 gimple_omp_for_clauses (stmt), private_marker,
11831                                 &oacc_head, &oacc_tail, ctx);
11832 
11833   /* Add OpenACC partitioning and reduction markers just before the loop.  */
11834   if (oacc_head)
11835     gimple_seq_add_seq (&body, oacc_head);
11836 
11837   lower_omp_for_lastprivate (&fd, &body, &dlist, &clist, ctx);
11838 
11839   if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR)
11840     for (tree c = gimple_omp_for_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c))
11841       if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
11842             && !OMP_CLAUSE_LINEAR_NO_COPYIN (c))
11843           {
11844             OMP_CLAUSE_DECL (c) = lookup_decl (OMP_CLAUSE_DECL (c), ctx);
11845             if (DECL_P (OMP_CLAUSE_LINEAR_STEP (c)))
11846               OMP_CLAUSE_LINEAR_STEP (c)
11847                 = maybe_lookup_decl_in_outer_ctx (OMP_CLAUSE_LINEAR_STEP (c),
11848                                                             ctx);
11849           }
11850 
11851   if ((ctx->scan_inclusive || ctx->scan_exclusive)
11852       && gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR)
11853     lower_omp_for_scan (&body, &dlist, stmt, &fd, ctx);
11854   else
11855     {
11856       gimple_seq_add_stmt (&body, stmt);
11857       gimple_seq_add_seq (&body, gimple_omp_body (stmt));
11858     }
11859 
11860   gimple_seq_add_stmt (&body, gimple_build_omp_continue (fd.loop.v,
11861                                                                        fd.loop.v));
11862 
11863   /* After the loop, add exit clauses.  */
11864   lower_reduction_clauses (gimple_omp_for_clauses (stmt), &body, &clist, ctx);
11865 
11866   if (clist)
11867     {
11868       tree fndecl = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START);
11869       gcall *g = gimple_build_call (fndecl, 0);
11870       gimple_seq_add_stmt (&body, g);
11871       gimple_seq_add_seq (&body, clist);
11872       fndecl = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END);
11873       g = gimple_build_call (fndecl, 0);
11874       gimple_seq_add_stmt (&body, g);
11875     }
11876 
11877   if (ctx->cancellable)
11878     gimple_seq_add_stmt (&body, gimple_build_label (ctx->cancel_label));
11879 
11880   gimple_seq_add_seq (&body, dlist);
11881 
11882   if (rclauses)
11883     {
11884       gimple_seq_add_seq (&tred_ilist, body);
11885       body = tred_ilist;
11886     }
11887 
11888   body = maybe_catch_exception (body);
11889 
11890   /* Region exit marker goes at the end of the loop body.  */
11891   gimple *g = gimple_build_omp_return (fd.have_nowait);
11892   gimple_seq_add_stmt (&body, g);
11893 
11894   gimple_seq_add_seq (&body, tred_dlist);
11895 
11896   maybe_add_implicit_barrier_cancel (ctx, g, &body);
11897 
11898   if (rclauses)
11899     OMP_CLAUSE_DECL (rclauses) = rtmp;
11900 
11901   /* Add OpenACC joining and reduction markers just after the loop.  */
11902   if (oacc_tail)
11903     gimple_seq_add_seq (&body, oacc_tail);
11904 
11905   pop_gimplify_context (new_stmt);
11906 
11907   gimple_bind_append_vars (new_stmt, ctx->block_vars);
11908   maybe_remove_omp_member_access_dummy_vars (new_stmt);
11909   BLOCK_VARS (block) = gimple_bind_vars (new_stmt);
11910   if (BLOCK_VARS (block))
11911     TREE_USED (block) = 1;
11912 
11913   gimple_bind_set_body (new_stmt, body);
11914   gimple_omp_set_body (stmt, NULL);
11915   gimple_omp_for_set_pre_body (stmt, NULL);
11916 }
11917 
11918 /* Callback for walk_stmts.  Check if the current statement only contains
11919    GIMPLE_OMP_FOR or GIMPLE_OMP_SECTIONS.  */
11920 
11921 static tree
check_combined_parallel(gimple_stmt_iterator * gsi_p,bool * handled_ops_p,struct walk_stmt_info * wi)11922 check_combined_parallel (gimple_stmt_iterator *gsi_p,
11923                                bool *handled_ops_p,
11924                                struct walk_stmt_info *wi)
11925 {
11926   int *info = (int *) wi->info;
11927   gimple *stmt = gsi_stmt (*gsi_p);
11928 
11929   *handled_ops_p = true;
11930   switch (gimple_code (stmt))
11931     {
11932     WALK_SUBSTMTS;
11933 
11934     case GIMPLE_DEBUG:
11935       break;
11936     case GIMPLE_OMP_FOR:
11937     case GIMPLE_OMP_SECTIONS:
11938       *info = *info == 0 ? 1 : -1;
11939       break;
11940     default:
11941       *info = -1;
11942       break;
11943     }
11944   return NULL;
11945 }
11946 
11947 struct omp_taskcopy_context
11948 {
11949   /* This field must be at the beginning, as we do "inheritance": Some
11950      callback functions for tree-inline.cc (e.g., omp_copy_decl)
11951      receive a copy_body_data pointer that is up-casted to an
11952      omp_context pointer.  */
11953   copy_body_data cb;
11954   omp_context *ctx;
11955 };
11956 
11957 static tree
task_copyfn_copy_decl(tree var,copy_body_data * cb)11958 task_copyfn_copy_decl (tree var, copy_body_data *cb)
11959 {
11960   struct omp_taskcopy_context *tcctx = (struct omp_taskcopy_context *) cb;
11961 
11962   if (splay_tree_lookup (tcctx->ctx->sfield_map, (splay_tree_key) var))
11963     return create_tmp_var (TREE_TYPE (var));
11964 
11965   return var;
11966 }
11967 
11968 static tree
task_copyfn_remap_type(struct omp_taskcopy_context * tcctx,tree orig_type)11969 task_copyfn_remap_type (struct omp_taskcopy_context *tcctx, tree orig_type)
11970 {
11971   tree name, new_fields = NULL, type, f;
11972 
11973   type = lang_hooks.types.make_type (RECORD_TYPE);
11974   name = DECL_NAME (TYPE_NAME (orig_type));
11975   name = build_decl (gimple_location (tcctx->ctx->stmt),
11976                          TYPE_DECL, name, type);
11977   TYPE_NAME (type) = name;
11978 
11979   for (f = TYPE_FIELDS (orig_type); f ; f = TREE_CHAIN (f))
11980     {
11981       tree new_f = copy_node (f);
11982       DECL_CONTEXT (new_f) = type;
11983       TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &tcctx->cb);
11984       TREE_CHAIN (new_f) = new_fields;
11985       walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &tcctx->cb, NULL);
11986       walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r, &tcctx->cb, NULL);
11987       walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
11988                      &tcctx->cb, NULL);
11989       new_fields = new_f;
11990       tcctx->cb.decl_map->put (f, new_f);
11991     }
11992   TYPE_FIELDS (type) = nreverse (new_fields);
11993   layout_type (type);
11994   return type;
11995 }
11996 
11997 /* Create task copyfn.  */
11998 
11999 static void
create_task_copyfn(gomp_task * task_stmt,omp_context * ctx)12000 create_task_copyfn (gomp_task *task_stmt, omp_context *ctx)
12001 {
12002   struct function *child_cfun;
12003   tree child_fn, t, c, src, dst, f, sf, arg, sarg, decl;
12004   tree record_type, srecord_type, bind, list;
12005   bool record_needs_remap = false, srecord_needs_remap = false;
12006   splay_tree_node n;
12007   struct omp_taskcopy_context tcctx;
12008   location_t loc = gimple_location (task_stmt);
12009   size_t looptempno = 0;
12010 
12011   child_fn = gimple_omp_task_copy_fn (task_stmt);
12012   task_cpyfns.safe_push (task_stmt);
12013   child_cfun = DECL_STRUCT_FUNCTION (child_fn);
12014   gcc_assert (child_cfun->cfg == NULL);
12015   DECL_SAVED_TREE (child_fn) = alloc_stmt_list ();
12016 
12017   /* Reset DECL_CONTEXT on function arguments.  */
12018   for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
12019     DECL_CONTEXT (t) = child_fn;
12020 
12021   /* Populate the function.  */
12022   push_gimplify_context ();
12023   push_cfun (child_cfun);
12024 
12025   bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
12026   TREE_SIDE_EFFECTS (bind) = 1;
12027   list = NULL;
12028   DECL_SAVED_TREE (child_fn) = bind;
12029   DECL_SOURCE_LOCATION (child_fn) = gimple_location (task_stmt);
12030 
12031   /* Remap src and dst argument types if needed.  */
12032   record_type = ctx->record_type;
12033   srecord_type = ctx->srecord_type;
12034   for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
12035     if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
12036       {
12037           record_needs_remap = true;
12038           break;
12039       }
12040   for (f = TYPE_FIELDS (srecord_type); f ; f = DECL_CHAIN (f))
12041     if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
12042       {
12043           srecord_needs_remap = true;
12044           break;
12045       }
12046 
12047   if (record_needs_remap || srecord_needs_remap)
12048     {
12049       memset (&tcctx, '\0', sizeof (tcctx));
12050       tcctx.cb.src_fn = ctx->cb.src_fn;
12051       tcctx.cb.dst_fn = child_fn;
12052       tcctx.cb.src_node = cgraph_node::get (tcctx.cb.src_fn);
12053       gcc_checking_assert (tcctx.cb.src_node);
12054       tcctx.cb.dst_node = tcctx.cb.src_node;
12055       tcctx.cb.src_cfun = ctx->cb.src_cfun;
12056       tcctx.cb.copy_decl = task_copyfn_copy_decl;
12057       tcctx.cb.eh_lp_nr = 0;
12058       tcctx.cb.transform_call_graph_edges = CB_CGE_MOVE;
12059       tcctx.cb.decl_map = new hash_map<tree, tree>;
12060       tcctx.ctx = ctx;
12061 
12062       if (record_needs_remap)
12063           record_type = task_copyfn_remap_type (&tcctx, record_type);
12064       if (srecord_needs_remap)
12065           srecord_type = task_copyfn_remap_type (&tcctx, srecord_type);
12066     }
12067   else
12068     tcctx.cb.decl_map = NULL;
12069 
12070   arg = DECL_ARGUMENTS (child_fn);
12071   TREE_TYPE (arg) = build_pointer_type (record_type);
12072   sarg = DECL_CHAIN (arg);
12073   TREE_TYPE (sarg) = build_pointer_type (srecord_type);
12074 
12075   /* First pass: initialize temporaries used in record_type and srecord_type
12076      sizes and field offsets.  */
12077   if (tcctx.cb.decl_map)
12078     for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
12079       if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
12080           {
12081             tree *p;
12082 
12083             decl = OMP_CLAUSE_DECL (c);
12084             p = tcctx.cb.decl_map->get (decl);
12085             if (p == NULL)
12086               continue;
12087             n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
12088             sf = (tree) n->value;
12089             sf = *tcctx.cb.decl_map->get (sf);
12090             src = build_simple_mem_ref_loc (loc, sarg);
12091             src = omp_build_component_ref (src, sf);
12092             t = build2 (MODIFY_EXPR, TREE_TYPE (*p), *p, src);
12093             append_to_statement_list (t, &list);
12094           }
12095 
12096   /* Second pass: copy shared var pointers and copy construct non-VLA
12097      firstprivate vars.  */
12098   for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
12099     switch (OMP_CLAUSE_CODE (c))
12100       {
12101           splay_tree_key key;
12102       case OMP_CLAUSE_SHARED:
12103           decl = OMP_CLAUSE_DECL (c);
12104           key = (splay_tree_key) decl;
12105           if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
12106             key = (splay_tree_key) &DECL_UID (decl);
12107           n = splay_tree_lookup (ctx->field_map, key);
12108           if (n == NULL)
12109             break;
12110           f = (tree) n->value;
12111           if (tcctx.cb.decl_map)
12112             f = *tcctx.cb.decl_map->get (f);
12113           n = splay_tree_lookup (ctx->sfield_map, key);
12114           sf = (tree) n->value;
12115           if (tcctx.cb.decl_map)
12116             sf = *tcctx.cb.decl_map->get (sf);
12117           src = build_simple_mem_ref_loc (loc, sarg);
12118           src = omp_build_component_ref (src, sf);
12119           dst = build_simple_mem_ref_loc (loc, arg);
12120           dst = omp_build_component_ref (dst, f);
12121           t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
12122           append_to_statement_list (t, &list);
12123           break;
12124       case OMP_CLAUSE_REDUCTION:
12125       case OMP_CLAUSE_IN_REDUCTION:
12126           decl = OMP_CLAUSE_DECL (c);
12127           if (TREE_CODE (decl) == MEM_REF)
12128             {
12129               decl = TREE_OPERAND (decl, 0);
12130               if (TREE_CODE (decl) == POINTER_PLUS_EXPR)
12131                 decl = TREE_OPERAND (decl, 0);
12132               if (TREE_CODE (decl) == INDIRECT_REF
12133                     || TREE_CODE (decl) == ADDR_EXPR)
12134                 decl = TREE_OPERAND (decl, 0);
12135             }
12136           key = (splay_tree_key) decl;
12137           n = splay_tree_lookup (ctx->field_map, key);
12138           if (n == NULL)
12139             break;
12140           f = (tree) n->value;
12141           if (tcctx.cb.decl_map)
12142             f = *tcctx.cb.decl_map->get (f);
12143           n = splay_tree_lookup (ctx->sfield_map, key);
12144           sf = (tree) n->value;
12145           if (tcctx.cb.decl_map)
12146             sf = *tcctx.cb.decl_map->get (sf);
12147           src = build_simple_mem_ref_loc (loc, sarg);
12148           src = omp_build_component_ref (src, sf);
12149           if (decl != OMP_CLAUSE_DECL (c)
12150               && TREE_CODE (TREE_TYPE (decl)) == REFERENCE_TYPE
12151               && TREE_CODE (TREE_TYPE (TREE_TYPE (decl))) == POINTER_TYPE)
12152             src = build_simple_mem_ref_loc (loc, src);
12153           dst = build_simple_mem_ref_loc (loc, arg);
12154           dst = omp_build_component_ref (dst, f);
12155           t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
12156           append_to_statement_list (t, &list);
12157           break;
12158       case OMP_CLAUSE__LOOPTEMP_:
12159           /* Fields for first two _looptemp_ clauses are initialized by
12160              GOMP_taskloop*, the rest are handled like firstprivate.  */
12161         if (looptempno < 2)
12162             {
12163               looptempno++;
12164               break;
12165             }
12166           /* FALLTHRU */
12167       case OMP_CLAUSE__REDUCTEMP_:
12168       case OMP_CLAUSE_FIRSTPRIVATE:
12169           decl = OMP_CLAUSE_DECL (c);
12170           if (is_variable_sized (decl))
12171             break;
12172           n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
12173           if (n == NULL)
12174             break;
12175           f = (tree) n->value;
12176           if (tcctx.cb.decl_map)
12177             f = *tcctx.cb.decl_map->get (f);
12178           n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
12179           if (n != NULL)
12180             {
12181               sf = (tree) n->value;
12182               if (tcctx.cb.decl_map)
12183                 sf = *tcctx.cb.decl_map->get (sf);
12184               src = build_simple_mem_ref_loc (loc, sarg);
12185               src = omp_build_component_ref (src, sf);
12186               if (use_pointer_for_field (decl, NULL)
12187                     || omp_privatize_by_reference (decl))
12188                 src = build_simple_mem_ref_loc (loc, src);
12189             }
12190           else
12191             src = decl;
12192           dst = build_simple_mem_ref_loc (loc, arg);
12193           dst = omp_build_component_ref (dst, f);
12194           if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_FIRSTPRIVATE)
12195             t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
12196           else
12197             {
12198               if (ctx->allocate_map)
12199                 if (tree *allocatorp = ctx->allocate_map->get (decl))
12200                     {
12201                       tree allocator = *allocatorp;
12202                       HOST_WIDE_INT ialign = 0;
12203                       if (TREE_CODE (allocator) == TREE_LIST)
12204                         {
12205                           ialign = tree_to_uhwi (TREE_VALUE (allocator));
12206                           allocator = TREE_PURPOSE (allocator);
12207                         }
12208                       if (TREE_CODE (allocator) != INTEGER_CST)
12209                         {
12210                           n = splay_tree_lookup (ctx->sfield_map,
12211                                                        (splay_tree_key) allocator);
12212                           allocator = (tree) n->value;
12213                           if (tcctx.cb.decl_map)
12214                               allocator = *tcctx.cb.decl_map->get (allocator);
12215                           tree a = build_simple_mem_ref_loc (loc, sarg);
12216                           allocator = omp_build_component_ref (a, allocator);
12217                         }
12218                       allocator = fold_convert (pointer_sized_int_node, allocator);
12219                       tree a = builtin_decl_explicit (BUILT_IN_GOMP_ALLOC);
12220                       tree align = build_int_cst (size_type_node,
12221                                                         MAX (ialign,
12222                                                                DECL_ALIGN_UNIT (decl)));
12223                       tree sz = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (dst)));
12224                       tree ptr = build_call_expr_loc (loc, a, 3, align, sz,
12225                                                               allocator);
12226                       ptr = fold_convert (TREE_TYPE (dst), ptr);
12227                       t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, ptr);
12228                       append_to_statement_list (t, &list);
12229                       dst = build_simple_mem_ref_loc (loc, dst);
12230                     }
12231               t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
12232             }
12233           append_to_statement_list (t, &list);
12234           break;
12235       case OMP_CLAUSE_PRIVATE:
12236           if (! OMP_CLAUSE_PRIVATE_OUTER_REF (c))
12237             break;
12238           decl = OMP_CLAUSE_DECL (c);
12239           n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
12240           f = (tree) n->value;
12241           if (tcctx.cb.decl_map)
12242             f = *tcctx.cb.decl_map->get (f);
12243           n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
12244           if (n != NULL)
12245             {
12246               sf = (tree) n->value;
12247               if (tcctx.cb.decl_map)
12248                 sf = *tcctx.cb.decl_map->get (sf);
12249               src = build_simple_mem_ref_loc (loc, sarg);
12250               src = omp_build_component_ref (src, sf);
12251               if (use_pointer_for_field (decl, NULL))
12252                 src = build_simple_mem_ref_loc (loc, src);
12253             }
12254           else
12255             src = decl;
12256           dst = build_simple_mem_ref_loc (loc, arg);
12257           dst = omp_build_component_ref (dst, f);
12258           t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
12259           append_to_statement_list (t, &list);
12260           break;
12261       default:
12262           break;
12263       }
12264 
12265   /* Last pass: handle VLA firstprivates.  */
12266   if (tcctx.cb.decl_map)
12267     for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
12268       if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
12269           {
12270             tree ind, ptr, df;
12271 
12272             decl = OMP_CLAUSE_DECL (c);
12273             if (!is_variable_sized (decl))
12274               continue;
12275             n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
12276             if (n == NULL)
12277               continue;
12278             f = (tree) n->value;
12279             f = *tcctx.cb.decl_map->get (f);
12280             gcc_assert (DECL_HAS_VALUE_EXPR_P (decl));
12281             ind = DECL_VALUE_EXPR (decl);
12282             gcc_assert (TREE_CODE (ind) == INDIRECT_REF);
12283             gcc_assert (DECL_P (TREE_OPERAND (ind, 0)));
12284             n = splay_tree_lookup (ctx->sfield_map,
12285                                          (splay_tree_key) TREE_OPERAND (ind, 0));
12286             sf = (tree) n->value;
12287             sf = *tcctx.cb.decl_map->get (sf);
12288             src = build_simple_mem_ref_loc (loc, sarg);
12289             src = omp_build_component_ref (src, sf);
12290             src = build_simple_mem_ref_loc (loc, src);
12291             dst = build_simple_mem_ref_loc (loc, arg);
12292             dst = omp_build_component_ref (dst, f);
12293             t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
12294             append_to_statement_list (t, &list);
12295             n = splay_tree_lookup (ctx->field_map,
12296                                          (splay_tree_key) TREE_OPERAND (ind, 0));
12297             df = (tree) n->value;
12298             df = *tcctx.cb.decl_map->get (df);
12299             ptr = build_simple_mem_ref_loc (loc, arg);
12300             ptr = omp_build_component_ref (ptr, df);
12301             t = build2 (MODIFY_EXPR, TREE_TYPE (ptr), ptr,
12302                           build_fold_addr_expr_loc (loc, dst));
12303             append_to_statement_list (t, &list);
12304           }
12305 
12306   t = build1 (RETURN_EXPR, void_type_node, NULL);
12307   append_to_statement_list (t, &list);
12308 
12309   if (tcctx.cb.decl_map)
12310     delete tcctx.cb.decl_map;
12311   pop_gimplify_context (NULL);
12312   BIND_EXPR_BODY (bind) = list;
12313   pop_cfun ();
12314 }
12315 
12316 static void
lower_depend_clauses(tree * pclauses,gimple_seq * iseq,gimple_seq * oseq)12317 lower_depend_clauses (tree *pclauses, gimple_seq *iseq, gimple_seq *oseq)
12318 {
12319   tree c, clauses;
12320   gimple *g;
12321   size_t cnt[4] = { 0, 0, 0, 0 }, idx = 2, i;
12322 
12323   clauses = omp_find_clause (*pclauses, OMP_CLAUSE_DEPEND);
12324   gcc_assert (clauses);
12325   for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
12326     if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
12327       switch (OMP_CLAUSE_DEPEND_KIND (c))
12328           {
12329           case OMP_CLAUSE_DEPEND_LAST:
12330             /* Lowering already done at gimplification.  */
12331             return;
12332           case OMP_CLAUSE_DEPEND_IN:
12333             cnt[2]++;
12334             break;
12335           case OMP_CLAUSE_DEPEND_OUT:
12336           case OMP_CLAUSE_DEPEND_INOUT:
12337             cnt[0]++;
12338             break;
12339           case OMP_CLAUSE_DEPEND_MUTEXINOUTSET:
12340             cnt[1]++;
12341             break;
12342           case OMP_CLAUSE_DEPEND_DEPOBJ:
12343             cnt[3]++;
12344             break;
12345           case OMP_CLAUSE_DEPEND_SOURCE:
12346           case OMP_CLAUSE_DEPEND_SINK:
12347             /* FALLTHRU */
12348           default:
12349             gcc_unreachable ();
12350           }
12351   if (cnt[1] || cnt[3])
12352     idx = 5;
12353   size_t total = cnt[0] + cnt[1] + cnt[2] + cnt[3];
12354   tree type = build_array_type_nelts (ptr_type_node, total + idx);
12355   tree array = create_tmp_var (type);
12356   TREE_ADDRESSABLE (array) = 1;
12357   tree r = build4 (ARRAY_REF, ptr_type_node, array, size_int (0), NULL_TREE,
12358                        NULL_TREE);
12359   if (idx == 5)
12360     {
12361       g = gimple_build_assign (r, build_int_cst (ptr_type_node, 0));
12362       gimple_seq_add_stmt (iseq, g);
12363       r = build4 (ARRAY_REF, ptr_type_node, array, size_int (1), NULL_TREE,
12364                       NULL_TREE);
12365     }
12366   g = gimple_build_assign (r, build_int_cst (ptr_type_node, total));
12367   gimple_seq_add_stmt (iseq, g);
12368   for (i = 0; i < (idx == 5 ? 3 : 1); i++)
12369     {
12370       r = build4 (ARRAY_REF, ptr_type_node, array,
12371                       size_int (i + 1 + (idx == 5)), NULL_TREE, NULL_TREE);
12372       g = gimple_build_assign (r, build_int_cst (ptr_type_node, cnt[i]));
12373       gimple_seq_add_stmt (iseq, g);
12374     }
12375   for (i = 0; i < 4; i++)
12376     {
12377       if (cnt[i] == 0)
12378           continue;
12379       for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
12380           if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND)
12381             continue;
12382           else
12383             {
12384               switch (OMP_CLAUSE_DEPEND_KIND (c))
12385                 {
12386                 case OMP_CLAUSE_DEPEND_IN:
12387                     if (i != 2)
12388                       continue;
12389                     break;
12390                 case OMP_CLAUSE_DEPEND_OUT:
12391                 case OMP_CLAUSE_DEPEND_INOUT:
12392                     if (i != 0)
12393                       continue;
12394                     break;
12395                 case OMP_CLAUSE_DEPEND_MUTEXINOUTSET:
12396                     if (i != 1)
12397                       continue;
12398                     break;
12399                 case OMP_CLAUSE_DEPEND_DEPOBJ:
12400                     if (i != 3)
12401                       continue;
12402                     break;
12403                 default:
12404                     gcc_unreachable ();
12405                 }
12406               tree t = OMP_CLAUSE_DECL (c);
12407               t = fold_convert (ptr_type_node, t);
12408               gimplify_expr (&t, iseq, NULL, is_gimple_val, fb_rvalue);
12409               r = build4 (ARRAY_REF, ptr_type_node, array, size_int (idx++),
12410                               NULL_TREE, NULL_TREE);
12411               g = gimple_build_assign (r, t);
12412               gimple_seq_add_stmt (iseq, g);
12413             }
12414     }
12415   c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_DEPEND);
12416   OMP_CLAUSE_DEPEND_KIND (c) = OMP_CLAUSE_DEPEND_LAST;
12417   OMP_CLAUSE_DECL (c) = build_fold_addr_expr (array);
12418   OMP_CLAUSE_CHAIN (c) = *pclauses;
12419   *pclauses = c;
12420   tree clobber = build_clobber (type);
12421   g = gimple_build_assign (array, clobber);
12422   gimple_seq_add_stmt (oseq, g);
12423 }
12424 
12425 /* Lower the OpenMP parallel or task directive in the current statement
12426    in GSI_P.  CTX holds context information for the directive.  */
12427 
12428 static void
lower_omp_taskreg(gimple_stmt_iterator * gsi_p,omp_context * ctx)12429 lower_omp_taskreg (gimple_stmt_iterator *gsi_p, omp_context *ctx)
12430 {
12431   tree clauses;
12432   tree child_fn, t;
12433   gimple *stmt = gsi_stmt (*gsi_p);
12434   gbind *par_bind, *bind, *dep_bind = NULL;
12435   gimple_seq par_body;
12436   location_t loc = gimple_location (stmt);
12437 
12438   clauses = gimple_omp_taskreg_clauses (stmt);
12439   if (gimple_code (stmt) == GIMPLE_OMP_TASK
12440       && gimple_omp_task_taskwait_p (stmt))
12441     {
12442       par_bind = NULL;
12443       par_body = NULL;
12444     }
12445   else
12446     {
12447       par_bind
12448           = as_a <gbind *> (gimple_seq_first_stmt (gimple_omp_body (stmt)));
12449       par_body = gimple_bind_body (par_bind);
12450     }
12451   child_fn = ctx->cb.dst_fn;
12452   if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
12453       && !gimple_omp_parallel_combined_p (stmt))
12454     {
12455       struct walk_stmt_info wi;
12456       int ws_num = 0;
12457 
12458       memset (&wi, 0, sizeof (wi));
12459       wi.info = &ws_num;
12460       wi.val_only = true;
12461       walk_gimple_seq (par_body, check_combined_parallel, NULL, &wi);
12462       if (ws_num == 1)
12463           gimple_omp_parallel_set_combined_p (stmt, true);
12464     }
12465   gimple_seq dep_ilist = NULL;
12466   gimple_seq dep_olist = NULL;
12467   if (gimple_code (stmt) == GIMPLE_OMP_TASK
12468       && omp_find_clause (clauses, OMP_CLAUSE_DEPEND))
12469     {
12470       push_gimplify_context ();
12471       dep_bind = gimple_build_bind (NULL, NULL, make_node (BLOCK));
12472       lower_depend_clauses (gimple_omp_task_clauses_ptr (stmt),
12473                                   &dep_ilist, &dep_olist);
12474     }
12475 
12476   if (gimple_code (stmt) == GIMPLE_OMP_TASK
12477       && gimple_omp_task_taskwait_p (stmt))
12478     {
12479       if (dep_bind)
12480           {
12481             gsi_replace (gsi_p, dep_bind, true);
12482             gimple_bind_add_seq (dep_bind, dep_ilist);
12483             gimple_bind_add_stmt (dep_bind, stmt);
12484             gimple_bind_add_seq (dep_bind, dep_olist);
12485             pop_gimplify_context (dep_bind);
12486           }
12487       return;
12488     }
12489 
12490   if (ctx->srecord_type)
12491     create_task_copyfn (as_a <gomp_task *> (stmt), ctx);
12492 
12493   gimple_seq tskred_ilist = NULL;
12494   gimple_seq tskred_olist = NULL;
12495   if ((is_task_ctx (ctx)
12496        && gimple_omp_task_taskloop_p (ctx->stmt)
12497        && omp_find_clause (gimple_omp_task_clauses (ctx->stmt),
12498                                  OMP_CLAUSE_REDUCTION))
12499       || (is_parallel_ctx (ctx)
12500             && omp_find_clause (gimple_omp_parallel_clauses (stmt),
12501                                     OMP_CLAUSE__REDUCTEMP_)))
12502     {
12503       if (dep_bind == NULL)
12504           {
12505             push_gimplify_context ();
12506             dep_bind = gimple_build_bind (NULL, NULL, make_node (BLOCK));
12507           }
12508       lower_omp_task_reductions (ctx, is_task_ctx (ctx) ? OMP_TASKLOOP
12509                                                                       : OMP_PARALLEL,
12510                                          gimple_omp_taskreg_clauses (ctx->stmt),
12511                                          &tskred_ilist, &tskred_olist);
12512     }
12513 
12514   push_gimplify_context ();
12515 
12516   gimple_seq par_olist = NULL;
12517   gimple_seq par_ilist = NULL;
12518   gimple_seq par_rlist = NULL;
12519   lower_rec_input_clauses (clauses, &par_ilist, &par_olist, ctx, NULL);
12520   lower_omp (&par_body, ctx);
12521   if (gimple_code (stmt) != GIMPLE_OMP_TASK)
12522     lower_reduction_clauses (clauses, &par_rlist, NULL, ctx);
12523 
12524   /* Declare all the variables created by mapping and the variables
12525      declared in the scope of the parallel body.  */
12526   record_vars_into (ctx->block_vars, child_fn);
12527   maybe_remove_omp_member_access_dummy_vars (par_bind);
12528   record_vars_into (gimple_bind_vars (par_bind), child_fn);
12529 
12530   if (ctx->record_type)
12531     {
12532       ctx->sender_decl
12533           = create_tmp_var (ctx->srecord_type ? ctx->srecord_type
12534                                 : ctx->record_type, ".omp_data_o");
12535       DECL_NAMELESS (ctx->sender_decl) = 1;
12536       TREE_ADDRESSABLE (ctx->sender_decl) = 1;
12537       gimple_omp_taskreg_set_data_arg (stmt, ctx->sender_decl);
12538     }
12539 
12540   gimple_seq olist = NULL;
12541   gimple_seq ilist = NULL;
12542   lower_send_clauses (clauses, &ilist, &olist, ctx);
12543   lower_send_shared_vars (&ilist, &olist, ctx);
12544 
12545   if (ctx->record_type)
12546     {
12547       tree clobber = build_clobber (TREE_TYPE (ctx->sender_decl));
12548       gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
12549                                                                       clobber));
12550     }
12551 
12552   /* Once all the expansions are done, sequence all the different
12553      fragments inside gimple_omp_body.  */
12554 
12555   gimple_seq new_body = NULL;
12556 
12557   if (ctx->record_type)
12558     {
12559       t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
12560       /* fixup_child_record_type might have changed receiver_decl's type.  */
12561       t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
12562       gimple_seq_add_stmt (&new_body,
12563                                  gimple_build_assign (ctx->receiver_decl, t));
12564     }
12565 
12566   gimple_seq_add_seq (&new_body, par_ilist);
12567   gimple_seq_add_seq (&new_body, par_body);
12568   gimple_seq_add_seq (&new_body, par_rlist);
12569   if (ctx->cancellable)
12570     gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
12571   gimple_seq_add_seq (&new_body, par_olist);
12572   new_body = maybe_catch_exception (new_body);
12573   if (gimple_code (stmt) == GIMPLE_OMP_TASK)
12574     gimple_seq_add_stmt (&new_body,
12575                                gimple_build_omp_continue (integer_zero_node,
12576                                                                 integer_zero_node));
12577   gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
12578   gimple_omp_set_body (stmt, new_body);
12579 
12580   if (dep_bind && gimple_bind_block (par_bind) == NULL_TREE)
12581     bind = gimple_build_bind (NULL, NULL, make_node (BLOCK));
12582   else
12583     bind = gimple_build_bind (NULL, NULL, gimple_bind_block (par_bind));
12584   gsi_replace (gsi_p, dep_bind ? dep_bind : bind, true);
12585   gimple_bind_add_seq (bind, ilist);
12586   gimple_bind_add_stmt (bind, stmt);
12587   gimple_bind_add_seq (bind, olist);
12588 
12589   pop_gimplify_context (NULL);
12590 
12591   if (dep_bind)
12592     {
12593       gimple_bind_add_seq (dep_bind, dep_ilist);
12594       gimple_bind_add_seq (dep_bind, tskred_ilist);
12595       gimple_bind_add_stmt (dep_bind, bind);
12596       gimple_bind_add_seq (dep_bind, tskred_olist);
12597       gimple_bind_add_seq (dep_bind, dep_olist);
12598       pop_gimplify_context (dep_bind);
12599     }
12600 }
12601 
12602 /* Lower the GIMPLE_OMP_TARGET in the current statement
12603    in GSI_P.  CTX holds context information for the directive.  */
12604 
12605 static void
lower_omp_target(gimple_stmt_iterator * gsi_p,omp_context * ctx)12606 lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
12607 {
12608   tree clauses;
12609   tree child_fn, t, c;
12610   gomp_target *stmt = as_a <gomp_target *> (gsi_stmt (*gsi_p));
12611   gbind *tgt_bind, *bind, *dep_bind = NULL;
12612   gimple_seq tgt_body, olist, ilist, fplist, new_body;
12613   location_t loc = gimple_location (stmt);
12614   bool offloaded, data_region;
12615   unsigned int map_cnt = 0;
12616   tree in_reduction_clauses = NULL_TREE;
12617 
12618   offloaded = is_gimple_omp_offloaded (stmt);
12619   switch (gimple_omp_target_kind (stmt))
12620     {
12621     case GF_OMP_TARGET_KIND_REGION:
12622       tree *p, *q;
12623       q = &in_reduction_clauses;
12624       for (p = gimple_omp_target_clauses_ptr (stmt); *p; )
12625           if (OMP_CLAUSE_CODE (*p) == OMP_CLAUSE_IN_REDUCTION)
12626             {
12627               *q = *p;
12628               q = &OMP_CLAUSE_CHAIN (*q);
12629               *p = OMP_CLAUSE_CHAIN (*p);
12630             }
12631           else
12632             p = &OMP_CLAUSE_CHAIN (*p);
12633       *q = NULL_TREE;
12634       *p = in_reduction_clauses;
12635       /* FALLTHRU */
12636     case GF_OMP_TARGET_KIND_UPDATE:
12637     case GF_OMP_TARGET_KIND_ENTER_DATA:
12638     case GF_OMP_TARGET_KIND_EXIT_DATA:
12639     case GF_OMP_TARGET_KIND_OACC_PARALLEL:
12640     case GF_OMP_TARGET_KIND_OACC_KERNELS:
12641     case GF_OMP_TARGET_KIND_OACC_SERIAL:
12642     case GF_OMP_TARGET_KIND_OACC_UPDATE:
12643     case GF_OMP_TARGET_KIND_OACC_ENTER_DATA:
12644     case GF_OMP_TARGET_KIND_OACC_EXIT_DATA:
12645     case GF_OMP_TARGET_KIND_OACC_DECLARE:
12646     case GF_OMP_TARGET_KIND_OACC_PARALLEL_KERNELS_PARALLELIZED:
12647     case GF_OMP_TARGET_KIND_OACC_PARALLEL_KERNELS_GANG_SINGLE:
12648       data_region = false;
12649       break;
12650     case GF_OMP_TARGET_KIND_DATA:
12651     case GF_OMP_TARGET_KIND_OACC_DATA:
12652     case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
12653     case GF_OMP_TARGET_KIND_OACC_DATA_KERNELS:
12654       data_region = true;
12655       break;
12656     default:
12657       gcc_unreachable ();
12658     }
12659 
12660   clauses = gimple_omp_target_clauses (stmt);
12661 
12662   gimple_seq dep_ilist = NULL;
12663   gimple_seq dep_olist = NULL;
12664   bool has_depend = omp_find_clause (clauses, OMP_CLAUSE_DEPEND) != NULL_TREE;
12665   if (has_depend || in_reduction_clauses)
12666     {
12667       push_gimplify_context ();
12668       dep_bind = gimple_build_bind (NULL, NULL, make_node (BLOCK));
12669       if (has_depend)
12670           lower_depend_clauses (gimple_omp_target_clauses_ptr (stmt),
12671                                     &dep_ilist, &dep_olist);
12672       if (in_reduction_clauses)
12673           lower_rec_input_clauses (in_reduction_clauses, &dep_ilist, &dep_olist,
12674                                          ctx, NULL);
12675     }
12676 
12677   tgt_bind = NULL;
12678   tgt_body = NULL;
12679   if (offloaded)
12680     {
12681       tgt_bind = gimple_seq_first_stmt_as_a_bind (gimple_omp_body (stmt));
12682       tgt_body = gimple_bind_body (tgt_bind);
12683     }
12684   else if (data_region)
12685     tgt_body = gimple_omp_body (stmt);
12686   child_fn = ctx->cb.dst_fn;
12687 
12688   push_gimplify_context ();
12689   fplist = NULL;
12690 
12691   for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
12692     switch (OMP_CLAUSE_CODE (c))
12693       {
12694           tree var, x;
12695 
12696       default:
12697           break;
12698       case OMP_CLAUSE_MAP:
12699 #if CHECKING_P
12700           /* First check what we're prepared to handle in the following.  */
12701           switch (OMP_CLAUSE_MAP_KIND (c))
12702             {
12703             case GOMP_MAP_ALLOC:
12704             case GOMP_MAP_TO:
12705             case GOMP_MAP_FROM:
12706             case GOMP_MAP_TOFROM:
12707             case GOMP_MAP_POINTER:
12708             case GOMP_MAP_TO_PSET:
12709             case GOMP_MAP_DELETE:
12710             case GOMP_MAP_RELEASE:
12711             case GOMP_MAP_ALWAYS_TO:
12712             case GOMP_MAP_ALWAYS_FROM:
12713             case GOMP_MAP_ALWAYS_TOFROM:
12714             case GOMP_MAP_FIRSTPRIVATE_POINTER:
12715             case GOMP_MAP_FIRSTPRIVATE_REFERENCE:
12716             case GOMP_MAP_STRUCT:
12717             case GOMP_MAP_ALWAYS_POINTER:
12718             case GOMP_MAP_ATTACH:
12719             case GOMP_MAP_DETACH:
12720             case GOMP_MAP_ATTACH_ZERO_LENGTH_ARRAY_SECTION:
12721             case GOMP_MAP_POINTER_TO_ZERO_LENGTH_ARRAY_SECTION:
12722               break;
12723             case GOMP_MAP_IF_PRESENT:
12724             case GOMP_MAP_FORCE_ALLOC:
12725             case GOMP_MAP_FORCE_TO:
12726             case GOMP_MAP_FORCE_FROM:
12727             case GOMP_MAP_FORCE_TOFROM:
12728             case GOMP_MAP_FORCE_PRESENT:
12729             case GOMP_MAP_FORCE_DEVICEPTR:
12730             case GOMP_MAP_DEVICE_RESIDENT:
12731             case GOMP_MAP_LINK:
12732             case GOMP_MAP_FORCE_DETACH:
12733               gcc_assert (is_gimple_omp_oacc (stmt));
12734               break;
12735             default:
12736               gcc_unreachable ();
12737             }
12738 #endif
12739             /* FALLTHRU */
12740       case OMP_CLAUSE_TO:
12741       case OMP_CLAUSE_FROM:
12742       oacc_firstprivate:
12743           var = OMP_CLAUSE_DECL (c);
12744           if (!DECL_P (var))
12745             {
12746               if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP
12747                     || (!OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
12748                         && (OMP_CLAUSE_MAP_KIND (c)
12749                               != GOMP_MAP_FIRSTPRIVATE_POINTER)))
12750                 map_cnt++;
12751               continue;
12752             }
12753 
12754           if (DECL_SIZE (var)
12755               && TREE_CODE (DECL_SIZE (var)) != INTEGER_CST)
12756             {
12757               tree var2 = DECL_VALUE_EXPR (var);
12758               gcc_assert (TREE_CODE (var2) == INDIRECT_REF);
12759               var2 = TREE_OPERAND (var2, 0);
12760               gcc_assert (DECL_P (var2));
12761               var = var2;
12762             }
12763 
12764           if (offloaded
12765               && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
12766               && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
12767                     || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_REFERENCE))
12768             {
12769               if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
12770                 {
12771                     if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx))
12772                         && varpool_node::get_create (var)->offloadable)
12773                       continue;
12774 
12775                     tree type = build_pointer_type (TREE_TYPE (var));
12776                     tree new_var = lookup_decl (var, ctx);
12777                     x = create_tmp_var_raw (type, get_name (new_var));
12778                     gimple_add_tmp_var (x);
12779                     x = build_simple_mem_ref (x);
12780                     SET_DECL_VALUE_EXPR (new_var, x);
12781                     DECL_HAS_VALUE_EXPR_P (new_var) = 1;
12782                 }
12783               continue;
12784             }
12785 
12786           if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
12787               && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH
12788                     || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_DETACH)
12789               && is_omp_target (stmt))
12790             {
12791               gcc_assert (maybe_lookup_field (c, ctx));
12792               map_cnt++;
12793               continue;
12794             }
12795 
12796           if (!maybe_lookup_field (var, ctx))
12797             continue;
12798 
12799           /* Don't remap compute constructs' reduction variables, because the
12800              intermediate result must be local to each gang.  */
12801           if (offloaded && !(OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
12802                                  && is_gimple_omp_oacc (ctx->stmt)
12803                                  && OMP_CLAUSE_MAP_IN_REDUCTION (c)))
12804             {
12805               x = build_receiver_ref (var, true, ctx);
12806               tree new_var = lookup_decl (var, ctx);
12807 
12808               if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
12809                     && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
12810                     && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
12811                     && TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
12812                 x = build_simple_mem_ref (x);
12813               if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
12814                 {
12815                     gcc_assert (is_gimple_omp_oacc (ctx->stmt));
12816                     if (omp_privatize_by_reference (new_var)
12817                         && (TREE_CODE (TREE_TYPE (new_var)) != POINTER_TYPE
12818                             || DECL_BY_REFERENCE (var)))
12819                       {
12820                         /* Create a local object to hold the instance
12821                            value.  */
12822                         tree type = TREE_TYPE (TREE_TYPE (new_var));
12823                         const char *id = IDENTIFIER_POINTER (DECL_NAME (new_var));
12824                         tree inst = create_tmp_var (type, id);
12825                         gimplify_assign (inst, fold_indirect_ref (x), &fplist);
12826                         x = build_fold_addr_expr (inst);
12827                       }
12828                     gimplify_assign (new_var, x, &fplist);
12829                 }
12830               else if (DECL_P (new_var))
12831                 {
12832                     SET_DECL_VALUE_EXPR (new_var, x);
12833                     DECL_HAS_VALUE_EXPR_P (new_var) = 1;
12834                 }
12835               else
12836                 gcc_unreachable ();
12837             }
12838           map_cnt++;
12839           break;
12840 
12841       case OMP_CLAUSE_FIRSTPRIVATE:
12842           gcc_checking_assert (offloaded);
12843           if (is_gimple_omp_oacc (ctx->stmt))
12844             {
12845               /* No 'firstprivate' clauses on OpenACC 'kernels'.  */
12846               gcc_checking_assert (!is_oacc_kernels (ctx));
12847               /* Likewise, on OpenACC 'kernels' decomposed parts.  */
12848               gcc_checking_assert (!is_oacc_kernels_decomposed_part (ctx));
12849 
12850               goto oacc_firstprivate;
12851             }
12852           map_cnt++;
12853           var = OMP_CLAUSE_DECL (c);
12854           if (!omp_privatize_by_reference (var)
12855               && !is_gimple_reg_type (TREE_TYPE (var)))
12856             {
12857               tree new_var = lookup_decl (var, ctx);
12858               if (is_variable_sized (var))
12859                 {
12860                     tree pvar = DECL_VALUE_EXPR (var);
12861                     gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
12862                     pvar = TREE_OPERAND (pvar, 0);
12863                     gcc_assert (DECL_P (pvar));
12864                     tree new_pvar = lookup_decl (pvar, ctx);
12865                     x = build_fold_indirect_ref (new_pvar);
12866                     TREE_THIS_NOTRAP (x) = 1;
12867                 }
12868               else
12869                 x = build_receiver_ref (var, true, ctx);
12870               SET_DECL_VALUE_EXPR (new_var, x);
12871               DECL_HAS_VALUE_EXPR_P (new_var) = 1;
12872             }
12873           break;
12874 
12875       case OMP_CLAUSE_PRIVATE:
12876           gcc_checking_assert (offloaded);
12877           if (is_gimple_omp_oacc (ctx->stmt))
12878             {
12879               /* No 'private' clauses on OpenACC 'kernels'.  */
12880               gcc_checking_assert (!is_oacc_kernels (ctx));
12881               /* Likewise, on OpenACC 'kernels' decomposed parts.  */
12882               gcc_checking_assert (!is_oacc_kernels_decomposed_part (ctx));
12883 
12884               break;
12885             }
12886           var = OMP_CLAUSE_DECL (c);
12887           if (is_variable_sized (var))
12888             {
12889               tree new_var = lookup_decl (var, ctx);
12890               tree pvar = DECL_VALUE_EXPR (var);
12891               gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
12892               pvar = TREE_OPERAND (pvar, 0);
12893               gcc_assert (DECL_P (pvar));
12894               tree new_pvar = lookup_decl (pvar, ctx);
12895               x = build_fold_indirect_ref (new_pvar);
12896               TREE_THIS_NOTRAP (x) = 1;
12897               SET_DECL_VALUE_EXPR (new_var, x);
12898               DECL_HAS_VALUE_EXPR_P (new_var) = 1;
12899             }
12900           break;
12901 
12902       case OMP_CLAUSE_USE_DEVICE_PTR:
12903       case OMP_CLAUSE_USE_DEVICE_ADDR:
12904       case OMP_CLAUSE_HAS_DEVICE_ADDR:
12905       case OMP_CLAUSE_IS_DEVICE_PTR:
12906           var = OMP_CLAUSE_DECL (c);
12907           if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_HAS_DEVICE_ADDR)
12908             {
12909               while (TREE_CODE (var) == INDIRECT_REF
12910                        || TREE_CODE (var) == ARRAY_REF)
12911                 var = TREE_OPERAND (var, 0);
12912             }
12913           map_cnt++;
12914           if (is_variable_sized (var))
12915             {
12916               tree new_var = lookup_decl (var, ctx);
12917               tree pvar = DECL_VALUE_EXPR (var);
12918               gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
12919               pvar = TREE_OPERAND (pvar, 0);
12920               gcc_assert (DECL_P (pvar));
12921               tree new_pvar = lookup_decl (pvar, ctx);
12922               x = build_fold_indirect_ref (new_pvar);
12923               TREE_THIS_NOTRAP (x) = 1;
12924               SET_DECL_VALUE_EXPR (new_var, x);
12925               DECL_HAS_VALUE_EXPR_P (new_var) = 1;
12926             }
12927           else if (((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_USE_DEVICE_ADDR
12928                        || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_HAS_DEVICE_ADDR)
12929                       && !omp_privatize_by_reference (var)
12930                       && !omp_is_allocatable_or_ptr (var)
12931                       && !lang_hooks.decls.omp_array_data (var, true))
12932                      || TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
12933             {
12934               tree new_var = lookup_decl (var, ctx);
12935               tree type = build_pointer_type (TREE_TYPE (var));
12936               x = create_tmp_var_raw (type, get_name (new_var));
12937               gimple_add_tmp_var (x);
12938               x = build_simple_mem_ref (x);
12939               SET_DECL_VALUE_EXPR (new_var, x);
12940               DECL_HAS_VALUE_EXPR_P (new_var) = 1;
12941             }
12942           else
12943             {
12944               tree new_var = lookup_decl (var, ctx);
12945               x = create_tmp_var_raw (TREE_TYPE (new_var), get_name (new_var));
12946               gimple_add_tmp_var (x);
12947               SET_DECL_VALUE_EXPR (new_var, x);
12948               DECL_HAS_VALUE_EXPR_P (new_var) = 1;
12949             }
12950           break;
12951       }
12952 
12953   if (offloaded)
12954     {
12955       target_nesting_level++;
12956       lower_omp (&tgt_body, ctx);
12957       target_nesting_level--;
12958     }
12959   else if (data_region)
12960     lower_omp (&tgt_body, ctx);
12961 
12962   if (offloaded)
12963     {
12964       /* Declare all the variables created by mapping and the variables
12965            declared in the scope of the target body.  */
12966       record_vars_into (ctx->block_vars, child_fn);
12967       maybe_remove_omp_member_access_dummy_vars (tgt_bind);
12968       record_vars_into (gimple_bind_vars (tgt_bind), child_fn);
12969     }
12970 
12971   olist = NULL;
12972   ilist = NULL;
12973   if (ctx->record_type)
12974     {
12975       ctx->sender_decl
12976           = create_tmp_var (ctx->record_type, ".omp_data_arr");
12977       DECL_NAMELESS (ctx->sender_decl) = 1;
12978       TREE_ADDRESSABLE (ctx->sender_decl) = 1;
12979       t = make_tree_vec (3);
12980       TREE_VEC_ELT (t, 0) = ctx->sender_decl;
12981       TREE_VEC_ELT (t, 1)
12982           = create_tmp_var (build_array_type_nelts (size_type_node, map_cnt),
12983                                 ".omp_data_sizes");
12984       DECL_NAMELESS (TREE_VEC_ELT (t, 1)) = 1;
12985       TREE_ADDRESSABLE (TREE_VEC_ELT (t, 1)) = 1;
12986       TREE_STATIC (TREE_VEC_ELT (t, 1)) = 1;
12987       tree tkind_type = short_unsigned_type_node;
12988       int talign_shift = 8;
12989       TREE_VEC_ELT (t, 2)
12990           = create_tmp_var (build_array_type_nelts (tkind_type, map_cnt),
12991                                 ".omp_data_kinds");
12992       DECL_NAMELESS (TREE_VEC_ELT (t, 2)) = 1;
12993       TREE_ADDRESSABLE (TREE_VEC_ELT (t, 2)) = 1;
12994       TREE_STATIC (TREE_VEC_ELT (t, 2)) = 1;
12995       gimple_omp_target_set_data_arg (stmt, t);
12996 
12997       vec<constructor_elt, va_gc> *vsize;
12998       vec<constructor_elt, va_gc> *vkind;
12999       vec_alloc (vsize, map_cnt);
13000       vec_alloc (vkind, map_cnt);
13001       unsigned int map_idx = 0;
13002 
13003       for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
13004           switch (OMP_CLAUSE_CODE (c))
13005             {
13006               tree ovar, nc, s, purpose, var, x, type;
13007               unsigned int talign;
13008 
13009             default:
13010               break;
13011 
13012             case OMP_CLAUSE_MAP:
13013             case OMP_CLAUSE_TO:
13014             case OMP_CLAUSE_FROM:
13015             oacc_firstprivate_map:
13016               nc = c;
13017               ovar = OMP_CLAUSE_DECL (c);
13018               if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
13019                     && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
13020                         || (OMP_CLAUSE_MAP_KIND (c)
13021                               == GOMP_MAP_FIRSTPRIVATE_REFERENCE)))
13022                 break;
13023               if (!DECL_P (ovar))
13024                 {
13025                     if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
13026                         && OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
13027                       {
13028                         nc = OMP_CLAUSE_CHAIN (c);
13029                         gcc_checking_assert (OMP_CLAUSE_DECL (nc)
13030                                                    == get_base_address (ovar));
13031                         ovar = OMP_CLAUSE_DECL (nc);
13032                       }
13033                     else
13034                       {
13035                         tree x = build_sender_ref (ovar, ctx);
13036                         tree v = ovar;
13037                         if (in_reduction_clauses
13038                               && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
13039                               && OMP_CLAUSE_MAP_IN_REDUCTION (c))
13040                           {
13041                               v = unshare_expr (v);
13042                               tree *p = &v;
13043                               while (handled_component_p (*p)
13044                                      || TREE_CODE (*p) == INDIRECT_REF
13045                                      || TREE_CODE (*p) == ADDR_EXPR
13046                                      || TREE_CODE (*p) == MEM_REF
13047                                      || TREE_CODE (*p) == NON_LVALUE_EXPR)
13048                                 p = &TREE_OPERAND (*p, 0);
13049                               tree d = *p;
13050                               if (is_variable_sized (d))
13051                                 {
13052                                   gcc_assert (DECL_HAS_VALUE_EXPR_P (d));
13053                                   d = DECL_VALUE_EXPR (d);
13054                                   gcc_assert (TREE_CODE (d) == INDIRECT_REF);
13055                                   d = TREE_OPERAND (d, 0);
13056                                   gcc_assert (DECL_P (d));
13057                                 }
13058                               splay_tree_key key
13059                                 = (splay_tree_key) &DECL_CONTEXT (d);
13060                               tree nd = (tree) splay_tree_lookup (ctx->field_map,
13061                                                                           key)->value;
13062                               if (d == *p)
13063                                 *p = nd;
13064                               else
13065                                 *p = build_fold_indirect_ref (nd);
13066                           }
13067                         v = build_fold_addr_expr_with_type (v, ptr_type_node);
13068                         gimplify_assign (x, v, &ilist);
13069                         nc = NULL_TREE;
13070                       }
13071                 }
13072               else
13073                 {
13074                     if (DECL_SIZE (ovar)
13075                         && TREE_CODE (DECL_SIZE (ovar)) != INTEGER_CST)
13076                       {
13077                         tree ovar2 = DECL_VALUE_EXPR (ovar);
13078                         gcc_assert (TREE_CODE (ovar2) == INDIRECT_REF);
13079                         ovar2 = TREE_OPERAND (ovar2, 0);
13080                         gcc_assert (DECL_P (ovar2));
13081                         ovar = ovar2;
13082                       }
13083                     if (!maybe_lookup_field (ovar, ctx)
13084                         && !(OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
13085                                && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH
13086                                    || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_DETACH)))
13087                       continue;
13088                 }
13089 
13090               talign = TYPE_ALIGN_UNIT (TREE_TYPE (ovar));
13091               if (DECL_P (ovar) && DECL_ALIGN_UNIT (ovar) > talign)
13092                 talign = DECL_ALIGN_UNIT (ovar);
13093 
13094               var = NULL_TREE;
13095               if (nc)
13096                 {
13097                     if (in_reduction_clauses
13098                         && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
13099                         && OMP_CLAUSE_MAP_IN_REDUCTION (c))
13100                       {
13101                         tree d = ovar;
13102                         if (is_variable_sized (d))
13103                           {
13104                               gcc_assert (DECL_HAS_VALUE_EXPR_P (d));
13105                               d = DECL_VALUE_EXPR (d);
13106                               gcc_assert (TREE_CODE (d) == INDIRECT_REF);
13107                               d = TREE_OPERAND (d, 0);
13108                               gcc_assert (DECL_P (d));
13109                           }
13110                         splay_tree_key key
13111                           = (splay_tree_key) &DECL_CONTEXT (d);
13112                         tree nd = (tree) splay_tree_lookup (ctx->field_map,
13113                                                                       key)->value;
13114                         if (d == ovar)
13115                           var = nd;
13116                         else
13117                           var = build_fold_indirect_ref (nd);
13118                       }
13119                     else
13120                       var = lookup_decl_in_outer_ctx (ovar, ctx);
13121                 }
13122               if (nc
13123                     && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
13124                     && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH
13125                         || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_DETACH)
13126                     && is_omp_target (stmt))
13127                 {
13128                     x = build_sender_ref (c, ctx);
13129                     gimplify_assign (x, build_fold_addr_expr (var), &ilist);
13130                 }
13131               else if (nc)
13132                 {
13133                     x = build_sender_ref (ovar, ctx);
13134 
13135                     if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
13136                         && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
13137                         && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
13138                         && TREE_CODE (TREE_TYPE (ovar)) == ARRAY_TYPE)
13139                       {
13140                         gcc_assert (offloaded);
13141                         tree avar
13142                           = create_tmp_var (TREE_TYPE (TREE_TYPE (x)));
13143                         mark_addressable (avar);
13144                         gimplify_assign (avar, build_fold_addr_expr (var), &ilist);
13145                         talign = DECL_ALIGN_UNIT (avar);
13146                         avar = build_fold_addr_expr (avar);
13147                         gimplify_assign (x, avar, &ilist);
13148                       }
13149                     else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
13150                       {
13151                         gcc_assert (is_gimple_omp_oacc (ctx->stmt));
13152                         if (!omp_privatize_by_reference (var))
13153                           {
13154                               if (is_gimple_reg (var)
13155                                   && OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c))
13156                                 suppress_warning (var);
13157                               var = build_fold_addr_expr (var);
13158                           }
13159                         else
13160                           talign = TYPE_ALIGN_UNIT (TREE_TYPE (TREE_TYPE (ovar)));
13161                         gimplify_assign (x, var, &ilist);
13162                       }
13163                     else if (is_gimple_reg (var))
13164                       {
13165                         gcc_assert (offloaded);
13166                         tree avar = create_tmp_var (TREE_TYPE (var));
13167                         mark_addressable (avar);
13168                         enum gomp_map_kind map_kind = OMP_CLAUSE_MAP_KIND (c);
13169                         if (GOMP_MAP_COPY_TO_P (map_kind)
13170                               || map_kind == GOMP_MAP_POINTER
13171                               || map_kind == GOMP_MAP_TO_PSET
13172                               || map_kind == GOMP_MAP_FORCE_DEVICEPTR)
13173                           {
13174                               /* If we need to initialize a temporary
13175                                  with VAR because it is not addressable, and
13176                                  the variable hasn't been initialized yet, then
13177                                  we'll get a warning for the store to avar.
13178                                  Don't warn in that case, the mapping might
13179                                  be implicit.  */
13180                               suppress_warning (var, OPT_Wuninitialized);
13181                               gimplify_assign (avar, var, &ilist);
13182                           }
13183                         avar = build_fold_addr_expr (avar);
13184                         gimplify_assign (x, avar, &ilist);
13185                         if ((GOMP_MAP_COPY_FROM_P (map_kind)
13186                                || map_kind == GOMP_MAP_FORCE_DEVICEPTR)
13187                               && !TYPE_READONLY (TREE_TYPE (var)))
13188                           {
13189                               x = unshare_expr (x);
13190                               x = build_simple_mem_ref (x);
13191                               gimplify_assign (var, x, &olist);
13192                           }
13193                       }
13194                     else
13195                       {
13196                         /* While MAP is handled explicitly by the FE,
13197                            for 'target update', only the identified is passed.  */
13198                         if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FROM
13199                                || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_TO)
13200                               && (omp_is_allocatable_or_ptr (var)
13201                                   && omp_check_optional_argument (var, false)))
13202                           var = build_fold_indirect_ref (var);
13203                         else if ((OMP_CLAUSE_CODE (c) != OMP_CLAUSE_FROM
13204                                     && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_TO)
13205                                    || (!omp_is_allocatable_or_ptr (var)
13206                                          && !omp_check_optional_argument (var, false)))
13207                           var = build_fold_addr_expr (var);
13208                         gimplify_assign (x, var, &ilist);
13209                       }
13210                 }
13211               s = NULL_TREE;
13212               if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
13213                 {
13214                     gcc_checking_assert (is_gimple_omp_oacc (ctx->stmt));
13215                     s = TREE_TYPE (ovar);
13216                     if (TREE_CODE (s) == REFERENCE_TYPE
13217                         || omp_check_optional_argument (ovar, false))
13218                       s = TREE_TYPE (s);
13219                     s = TYPE_SIZE_UNIT (s);
13220                 }
13221               else
13222                 s = OMP_CLAUSE_SIZE (c);
13223               if (s == NULL_TREE)
13224                 s = TYPE_SIZE_UNIT (TREE_TYPE (ovar));
13225               s = fold_convert (size_type_node, s);
13226               purpose = size_int (map_idx++);
13227               CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
13228               if (TREE_CODE (s) != INTEGER_CST)
13229                 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 0;
13230 
13231               unsigned HOST_WIDE_INT tkind, tkind_zero;
13232               switch (OMP_CLAUSE_CODE (c))
13233                 {
13234                 case OMP_CLAUSE_MAP:
13235                     tkind = OMP_CLAUSE_MAP_KIND (c);
13236                     tkind_zero = tkind;
13237                     if (OMP_CLAUSE_MAP_MAYBE_ZERO_LENGTH_ARRAY_SECTION (c))
13238                       switch (tkind)
13239                         {
13240                         case GOMP_MAP_ALLOC:
13241                         case GOMP_MAP_IF_PRESENT:
13242                         case GOMP_MAP_TO:
13243                         case GOMP_MAP_FROM:
13244                         case GOMP_MAP_TOFROM:
13245                         case GOMP_MAP_ALWAYS_TO:
13246                         case GOMP_MAP_ALWAYS_FROM:
13247                         case GOMP_MAP_ALWAYS_TOFROM:
13248                         case GOMP_MAP_RELEASE:
13249                         case GOMP_MAP_FORCE_TO:
13250                         case GOMP_MAP_FORCE_FROM:
13251                         case GOMP_MAP_FORCE_TOFROM:
13252                         case GOMP_MAP_FORCE_PRESENT:
13253                           tkind_zero = GOMP_MAP_ZERO_LEN_ARRAY_SECTION;
13254                           break;
13255                         case GOMP_MAP_DELETE:
13256                           tkind_zero = GOMP_MAP_DELETE_ZERO_LEN_ARRAY_SECTION;
13257                         default:
13258                           break;
13259                         }
13260                     if (tkind_zero != tkind)
13261                       {
13262                         if (integer_zerop (s))
13263                           tkind = tkind_zero;
13264                         else if (integer_nonzerop (s))
13265                           tkind_zero = tkind;
13266                       }
13267                     if (tkind_zero == tkind
13268                         && OMP_CLAUSE_MAP_RUNTIME_IMPLICIT_P (c)
13269                         && (((tkind & GOMP_MAP_FLAG_SPECIAL_BITS)
13270                                & ~GOMP_MAP_IMPLICIT)
13271                               == 0))
13272                       {
13273                         /* If this is an implicit map, and the GOMP_MAP_IMPLICIT
13274                            bits are not interfered by other special bit encodings,
13275                            then turn the GOMP_IMPLICIT_BIT flag on for the runtime
13276                            to see.  */
13277                         tkind |= GOMP_MAP_IMPLICIT;
13278                         tkind_zero = tkind;
13279                       }
13280                     break;
13281                 case OMP_CLAUSE_FIRSTPRIVATE:
13282                     gcc_checking_assert (is_gimple_omp_oacc (ctx->stmt));
13283                     tkind = GOMP_MAP_TO;
13284                     tkind_zero = tkind;
13285                     break;
13286                 case OMP_CLAUSE_TO:
13287                     tkind = GOMP_MAP_TO;
13288                     tkind_zero = tkind;
13289                     break;
13290                 case OMP_CLAUSE_FROM:
13291                     tkind = GOMP_MAP_FROM;
13292                     tkind_zero = tkind;
13293                     break;
13294                 default:
13295                     gcc_unreachable ();
13296                 }
13297               gcc_checking_assert (tkind
13298                                          < (HOST_WIDE_INT_C (1U) << talign_shift));
13299               gcc_checking_assert (tkind_zero
13300                                          < (HOST_WIDE_INT_C (1U) << talign_shift));
13301               talign = ceil_log2 (talign);
13302               tkind |= talign << talign_shift;
13303               tkind_zero |= talign << talign_shift;
13304               gcc_checking_assert (tkind
13305                                          <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
13306               gcc_checking_assert (tkind_zero
13307                                          <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
13308               if (tkind == tkind_zero)
13309                 x = build_int_cstu (tkind_type, tkind);
13310               else
13311                 {
13312                     TREE_STATIC (TREE_VEC_ELT (t, 2)) = 0;
13313                     x = build3 (COND_EXPR, tkind_type,
13314                                   fold_build2 (EQ_EXPR, boolean_type_node,
13315                                                    unshare_expr (s), size_zero_node),
13316                                   build_int_cstu (tkind_type, tkind_zero),
13317                                   build_int_cstu (tkind_type, tkind));
13318                 }
13319               CONSTRUCTOR_APPEND_ELT (vkind, purpose, x);
13320               if (nc && nc != c)
13321                 c = nc;
13322               break;
13323 
13324             case OMP_CLAUSE_FIRSTPRIVATE:
13325               if (is_gimple_omp_oacc (ctx->stmt))
13326                 goto oacc_firstprivate_map;
13327               ovar = OMP_CLAUSE_DECL (c);
13328               if (omp_privatize_by_reference (ovar))
13329                 talign = TYPE_ALIGN_UNIT (TREE_TYPE (TREE_TYPE (ovar)));
13330               else
13331                 talign = DECL_ALIGN_UNIT (ovar);
13332               var = lookup_decl_in_outer_ctx (ovar, ctx);
13333               x = build_sender_ref (ovar, ctx);
13334               tkind = GOMP_MAP_FIRSTPRIVATE;
13335               type = TREE_TYPE (ovar);
13336               if (omp_privatize_by_reference (ovar))
13337                 type = TREE_TYPE (type);
13338               if ((INTEGRAL_TYPE_P (type)
13339                      && TYPE_PRECISION (type) <= POINTER_SIZE)
13340                     || TREE_CODE (type) == POINTER_TYPE)
13341                 {
13342                     tkind = GOMP_MAP_FIRSTPRIVATE_INT;
13343                     tree t = var;
13344                     if (omp_privatize_by_reference (var))
13345                       t = build_simple_mem_ref (var);
13346                     else if (OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c))
13347                       suppress_warning (var);
13348                     if (TREE_CODE (type) != POINTER_TYPE)
13349                       t = fold_convert (pointer_sized_int_node, t);
13350                     t = fold_convert (TREE_TYPE (x), t);
13351                     gimplify_assign (x, t, &ilist);
13352                 }
13353               else if (omp_privatize_by_reference (var))
13354                 gimplify_assign (x, var, &ilist);
13355               else if (is_gimple_reg (var))
13356                 {
13357                     tree avar = create_tmp_var (TREE_TYPE (var));
13358                     mark_addressable (avar);
13359                     if (OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c))
13360                       suppress_warning (var);
13361                     gimplify_assign (avar, var, &ilist);
13362                     avar = build_fold_addr_expr (avar);
13363                     gimplify_assign (x, avar, &ilist);
13364                 }
13365               else
13366                 {
13367                     var = build_fold_addr_expr (var);
13368                     gimplify_assign (x, var, &ilist);
13369                 }
13370               if (tkind == GOMP_MAP_FIRSTPRIVATE_INT)
13371                 s = size_int (0);
13372               else if (omp_privatize_by_reference (ovar))
13373                 s = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (ovar)));
13374               else
13375                 s = TYPE_SIZE_UNIT (TREE_TYPE (ovar));
13376               s = fold_convert (size_type_node, s);
13377               purpose = size_int (map_idx++);
13378               CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
13379               if (TREE_CODE (s) != INTEGER_CST)
13380                 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 0;
13381 
13382               gcc_checking_assert (tkind
13383                                          < (HOST_WIDE_INT_C (1U) << talign_shift));
13384               talign = ceil_log2 (talign);
13385               tkind |= talign << talign_shift;
13386               gcc_checking_assert (tkind
13387                                          <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
13388               CONSTRUCTOR_APPEND_ELT (vkind, purpose,
13389                                             build_int_cstu (tkind_type, tkind));
13390               break;
13391 
13392             case OMP_CLAUSE_USE_DEVICE_PTR:
13393             case OMP_CLAUSE_USE_DEVICE_ADDR:
13394             case OMP_CLAUSE_HAS_DEVICE_ADDR:
13395             case OMP_CLAUSE_IS_DEVICE_PTR:
13396               ovar = OMP_CLAUSE_DECL (c);
13397               if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_HAS_DEVICE_ADDR)
13398                 {
13399                     while (TREE_CODE (ovar) == INDIRECT_REF
13400                            || TREE_CODE (ovar) == ARRAY_REF)
13401                       ovar = TREE_OPERAND (ovar, 0);
13402                 }
13403               var = lookup_decl_in_outer_ctx (ovar, ctx);
13404 
13405               if (lang_hooks.decls.omp_array_data (ovar, true))
13406                 {
13407                     tkind = ((OMP_CLAUSE_CODE (c) != OMP_CLAUSE_IS_DEVICE_PTR
13408                                 && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_HAS_DEVICE_ADDR)
13409                                ? GOMP_MAP_USE_DEVICE_PTR : GOMP_MAP_FIRSTPRIVATE_INT);
13410                     x = build_sender_ref ((splay_tree_key) &DECL_NAME (ovar), ctx);
13411                 }
13412               else if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_IS_DEVICE_PTR
13413                          && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_HAS_DEVICE_ADDR)
13414                 {
13415                     tkind = GOMP_MAP_USE_DEVICE_PTR;
13416                     x = build_sender_ref ((splay_tree_key) &DECL_UID (ovar), ctx);
13417                 }
13418               else
13419                 {
13420                     tkind = GOMP_MAP_FIRSTPRIVATE_INT;
13421                     x = build_sender_ref (ovar, ctx);
13422                 }
13423 
13424               if (is_gimple_omp_oacc (ctx->stmt))
13425                 {
13426                     gcc_assert (tkind == GOMP_MAP_USE_DEVICE_PTR);
13427 
13428                     if (OMP_CLAUSE_USE_DEVICE_PTR_IF_PRESENT (c))
13429                       tkind = GOMP_MAP_USE_DEVICE_PTR_IF_PRESENT;
13430                 }
13431 
13432               type = TREE_TYPE (ovar);
13433               if (lang_hooks.decls.omp_array_data (ovar, true))
13434                 var = lang_hooks.decls.omp_array_data (var, false);
13435               else if (((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_USE_DEVICE_ADDR
13436                           || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_HAS_DEVICE_ADDR)
13437                           && !omp_privatize_by_reference (ovar)
13438                           && !omp_is_allocatable_or_ptr (ovar))
13439                          || TREE_CODE (type) == ARRAY_TYPE)
13440                 var = build_fold_addr_expr (var);
13441               else
13442                 {
13443                     if (omp_privatize_by_reference (ovar)
13444                         || omp_check_optional_argument (ovar, false)
13445                         || omp_is_allocatable_or_ptr (ovar))
13446                       {
13447                         type = TREE_TYPE (type);
13448                         if (POINTER_TYPE_P (type)
13449                               && TREE_CODE (type) != ARRAY_TYPE
13450                               && ((OMP_CLAUSE_CODE (c) != OMP_CLAUSE_USE_DEVICE_ADDR
13451                                   && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_HAS_DEVICE_ADDR
13452                                   && !omp_is_allocatable_or_ptr (ovar))
13453                                  || (omp_privatize_by_reference (ovar)
13454                                      && omp_is_allocatable_or_ptr (ovar))))
13455                           var = build_simple_mem_ref (var);
13456                         var = fold_convert (TREE_TYPE (x), var);
13457                       }
13458                 }
13459               tree present;
13460               present = omp_check_optional_argument (ovar, true);
13461               if (present)
13462                 {
13463                     tree null_label = create_artificial_label (UNKNOWN_LOCATION);
13464                     tree notnull_label = create_artificial_label (UNKNOWN_LOCATION);
13465                     tree opt_arg_label = create_artificial_label (UNKNOWN_LOCATION);
13466                     tree new_x = unshare_expr (x);
13467                     gimplify_expr (&present, &ilist, NULL, is_gimple_val,
13468                                      fb_rvalue);
13469                     gcond *cond = gimple_build_cond_from_tree (present,
13470                                                                          notnull_label,
13471                                                                          null_label);
13472                     gimple_seq_add_stmt (&ilist, cond);
13473                     gimple_seq_add_stmt (&ilist, gimple_build_label (null_label));
13474                     gimplify_assign (new_x, null_pointer_node, &ilist);
13475                     gimple_seq_add_stmt (&ilist, gimple_build_goto (opt_arg_label));
13476                     gimple_seq_add_stmt (&ilist,
13477                                              gimple_build_label (notnull_label));
13478                     gimplify_assign (x, var, &ilist);
13479                     gimple_seq_add_stmt (&ilist,
13480                                              gimple_build_label (opt_arg_label));
13481                 }
13482               else
13483                 gimplify_assign (x, var, &ilist);
13484               s = size_int (0);
13485               purpose = size_int (map_idx++);
13486               CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
13487               gcc_checking_assert (tkind
13488                                          < (HOST_WIDE_INT_C (1U) << talign_shift));
13489               gcc_checking_assert (tkind
13490                                          <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
13491               CONSTRUCTOR_APPEND_ELT (vkind, purpose,
13492                                             build_int_cstu (tkind_type, tkind));
13493               break;
13494             }
13495 
13496       gcc_assert (map_idx == map_cnt);
13497 
13498       DECL_INITIAL (TREE_VEC_ELT (t, 1))
13499           = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)), vsize);
13500       DECL_INITIAL (TREE_VEC_ELT (t, 2))
13501           = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 2)), vkind);
13502       for (int i = 1; i <= 2; i++)
13503           if (!TREE_STATIC (TREE_VEC_ELT (t, i)))
13504             {
13505               gimple_seq initlist = NULL;
13506               force_gimple_operand (build1 (DECL_EXPR, void_type_node,
13507                                                     TREE_VEC_ELT (t, i)),
13508                                           &initlist, true, NULL_TREE);
13509               gimple_seq_add_seq (&ilist, initlist);
13510 
13511               tree clobber = build_clobber (TREE_TYPE (TREE_VEC_ELT (t, i)));
13512               gimple_seq_add_stmt (&olist,
13513                                          gimple_build_assign (TREE_VEC_ELT (t, i),
13514                                                                   clobber));
13515             }
13516           else if (omp_maybe_offloaded_ctx (ctx->outer))
13517             {
13518               tree id = get_identifier ("omp declare target");
13519               tree decl = TREE_VEC_ELT (t, i);
13520               DECL_ATTRIBUTES (decl)
13521                 = tree_cons (id, NULL_TREE, DECL_ATTRIBUTES (decl));
13522               varpool_node *node = varpool_node::get (decl);
13523               if (node)
13524                 {
13525                     node->offloadable = 1;
13526                     if (ENABLE_OFFLOADING)
13527                       {
13528                         g->have_offload = true;
13529                         vec_safe_push (offload_vars, t);
13530                       }
13531                 }
13532             }
13533 
13534       tree clobber = build_clobber (ctx->record_type);
13535       gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
13536                                                                       clobber));
13537     }
13538 
13539   /* Once all the expansions are done, sequence all the different
13540      fragments inside gimple_omp_body.  */
13541 
13542   new_body = NULL;
13543 
13544   if (offloaded
13545       && ctx->record_type)
13546     {
13547       t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
13548       /* fixup_child_record_type might have changed receiver_decl's type.  */
13549       t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
13550       gimple_seq_add_stmt (&new_body,
13551                                  gimple_build_assign (ctx->receiver_decl, t));
13552     }
13553   gimple_seq_add_seq (&new_body, fplist);
13554 
13555   if (offloaded || data_region)
13556     {
13557       tree prev = NULL_TREE;
13558       for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
13559           switch (OMP_CLAUSE_CODE (c))
13560             {
13561               tree var, x;
13562             default:
13563               break;
13564             case OMP_CLAUSE_FIRSTPRIVATE:
13565               if (is_gimple_omp_oacc (ctx->stmt))
13566                 break;
13567               var = OMP_CLAUSE_DECL (c);
13568               if (omp_privatize_by_reference (var)
13569                     || is_gimple_reg_type (TREE_TYPE (var)))
13570                 {
13571                     tree new_var = lookup_decl (var, ctx);
13572                     tree type;
13573                     type = TREE_TYPE (var);
13574                     if (omp_privatize_by_reference (var))
13575                       type = TREE_TYPE (type);
13576                     if ((INTEGRAL_TYPE_P (type)
13577                          && TYPE_PRECISION (type) <= POINTER_SIZE)
13578                         || TREE_CODE (type) == POINTER_TYPE)
13579                       {
13580                         x = build_receiver_ref (var, false, ctx);
13581                         if (TREE_CODE (type) != POINTER_TYPE)
13582                           x = fold_convert (pointer_sized_int_node, x);
13583                         x = fold_convert (type, x);
13584                         gimplify_expr (&x, &new_body, NULL, is_gimple_val,
13585                                            fb_rvalue);
13586                         if (omp_privatize_by_reference (var))
13587                           {
13588                               tree v = create_tmp_var_raw (type, get_name (var));
13589                               gimple_add_tmp_var (v);
13590                               TREE_ADDRESSABLE (v) = 1;
13591                               gimple_seq_add_stmt (&new_body,
13592                                                        gimple_build_assign (v, x));
13593                               x = build_fold_addr_expr (v);
13594                           }
13595                         gimple_seq_add_stmt (&new_body,
13596                                                    gimple_build_assign (new_var, x));
13597                       }
13598                     else
13599                       {
13600                         bool by_ref = !omp_privatize_by_reference (var);
13601                         x = build_receiver_ref (var, by_ref, ctx);
13602                         gimplify_expr (&x, &new_body, NULL, is_gimple_val,
13603                                            fb_rvalue);
13604                         gimple_seq_add_stmt (&new_body,
13605                                                    gimple_build_assign (new_var, x));
13606                       }
13607                 }
13608               else if (is_variable_sized (var))
13609                 {
13610                     tree pvar = DECL_VALUE_EXPR (var);
13611                     gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
13612                     pvar = TREE_OPERAND (pvar, 0);
13613                     gcc_assert (DECL_P (pvar));
13614                     tree new_var = lookup_decl (pvar, ctx);
13615                     x = build_receiver_ref (var, false, ctx);
13616                     gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
13617                     gimple_seq_add_stmt (&new_body,
13618                                              gimple_build_assign (new_var, x));
13619                 }
13620               break;
13621             case OMP_CLAUSE_PRIVATE:
13622               if (is_gimple_omp_oacc (ctx->stmt))
13623                 break;
13624               var = OMP_CLAUSE_DECL (c);
13625               if (omp_privatize_by_reference (var))
13626                 {
13627                     location_t clause_loc = OMP_CLAUSE_LOCATION (c);
13628                     tree new_var = lookup_decl (var, ctx);
13629                     x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
13630                     if (TREE_CONSTANT (x))
13631                       {
13632                         x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)),
13633                                                       get_name (var));
13634                         gimple_add_tmp_var (x);
13635                         TREE_ADDRESSABLE (x) = 1;
13636                         x = build_fold_addr_expr_loc (clause_loc, x);
13637                       }
13638                     else
13639                       break;
13640 
13641                     x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
13642                     gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
13643                     gimple_seq_add_stmt (&new_body,
13644                                              gimple_build_assign (new_var, x));
13645                 }
13646               break;
13647             case OMP_CLAUSE_USE_DEVICE_PTR:
13648             case OMP_CLAUSE_USE_DEVICE_ADDR:
13649             case OMP_CLAUSE_HAS_DEVICE_ADDR:
13650             case OMP_CLAUSE_IS_DEVICE_PTR:
13651               tree new_var;
13652               gimple_seq assign_body;
13653               bool is_array_data;
13654               bool do_optional_check;
13655               assign_body = NULL;
13656               do_optional_check = false;
13657               var = OMP_CLAUSE_DECL (c);
13658               is_array_data = lang_hooks.decls.omp_array_data (var, true) != NULL;
13659 
13660               if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_IS_DEVICE_PTR
13661                     && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_HAS_DEVICE_ADDR)
13662                 x = build_sender_ref (is_array_data
13663                                             ? (splay_tree_key) &DECL_NAME (var)
13664                                             : (splay_tree_key) &DECL_UID (var), ctx);
13665               else
13666                 {
13667                     if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_HAS_DEVICE_ADDR)
13668                       {
13669                         while (TREE_CODE (var) == INDIRECT_REF
13670                                  || TREE_CODE (var) == ARRAY_REF)
13671                           var = TREE_OPERAND (var, 0);
13672                       }
13673                     x = build_receiver_ref (var, false, ctx);
13674                 }
13675 
13676               if (is_array_data)
13677                 {
13678                     bool is_ref = omp_privatize_by_reference (var);
13679                     do_optional_check = true;
13680                     /* First, we copy the descriptor data from the host; then
13681                        we update its data to point to the target address.  */
13682                     new_var = lookup_decl (var, ctx);
13683                     new_var = DECL_VALUE_EXPR (new_var);
13684                     tree v = new_var;
13685 
13686                     if (is_ref)
13687                       {
13688                         var = build_fold_indirect_ref (var);
13689                         gimplify_expr (&var, &assign_body, NULL, is_gimple_val,
13690                                            fb_rvalue);
13691                         v = create_tmp_var_raw (TREE_TYPE (var), get_name (var));
13692                         gimple_add_tmp_var (v);
13693                         TREE_ADDRESSABLE (v) = 1;
13694                         gimple_seq_add_stmt (&assign_body,
13695                                                    gimple_build_assign (v, var));
13696                         tree rhs = build_fold_addr_expr (v);
13697                         gimple_seq_add_stmt (&assign_body,
13698                                                    gimple_build_assign (new_var, rhs));
13699                       }
13700                     else
13701                       gimple_seq_add_stmt (&assign_body,
13702                                                gimple_build_assign (new_var, var));
13703 
13704                     tree v2 = lang_hooks.decls.omp_array_data (unshare_expr (v), false);
13705                     gcc_assert (v2);
13706                     gimplify_expr (&x, &assign_body, NULL, is_gimple_val, fb_rvalue);
13707                     gimple_seq_add_stmt (&assign_body,
13708                                              gimple_build_assign (v2, x));
13709                 }
13710               else if (is_variable_sized (var))
13711                 {
13712                     tree pvar = DECL_VALUE_EXPR (var);
13713                     gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
13714                     pvar = TREE_OPERAND (pvar, 0);
13715                     gcc_assert (DECL_P (pvar));
13716                     new_var = lookup_decl (pvar, ctx);
13717                     gimplify_expr (&x, &assign_body, NULL, is_gimple_val, fb_rvalue);
13718                     gimple_seq_add_stmt (&assign_body,
13719                                              gimple_build_assign (new_var, x));
13720                 }
13721               else if (((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_USE_DEVICE_ADDR
13722                           || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_HAS_DEVICE_ADDR)
13723                           && !omp_privatize_by_reference (var)
13724                           && !omp_is_allocatable_or_ptr (var))
13725                          || TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
13726                 {
13727                     new_var = lookup_decl (var, ctx);
13728                     new_var = DECL_VALUE_EXPR (new_var);
13729                     gcc_assert (TREE_CODE (new_var) == MEM_REF);
13730                     new_var = TREE_OPERAND (new_var, 0);
13731                     gcc_assert (DECL_P (new_var));
13732                     gimplify_expr (&x, &assign_body, NULL, is_gimple_val, fb_rvalue);
13733                     gimple_seq_add_stmt (&assign_body,
13734                                              gimple_build_assign (new_var, x));
13735                 }
13736               else
13737                 {
13738                     tree type = TREE_TYPE (var);
13739                     new_var = lookup_decl (var, ctx);
13740                     if (omp_privatize_by_reference (var))
13741                       {
13742                         type = TREE_TYPE (type);
13743                         if (POINTER_TYPE_P (type)
13744                               && TREE_CODE (type) != ARRAY_TYPE
13745                               && ((OMP_CLAUSE_CODE (c) != OMP_CLAUSE_USE_DEVICE_ADDR
13746                                   && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_HAS_DEVICE_ADDR)
13747                                   || (omp_privatize_by_reference (var)
13748                                         && omp_is_allocatable_or_ptr (var))))
13749                           {
13750                               tree v = create_tmp_var_raw (type, get_name (var));
13751                               gimple_add_tmp_var (v);
13752                               TREE_ADDRESSABLE (v) = 1;
13753                               x = fold_convert (type, x);
13754                               gimplify_expr (&x, &assign_body, NULL, is_gimple_val,
13755                                                fb_rvalue);
13756                               gimple_seq_add_stmt (&assign_body,
13757                                                        gimple_build_assign (v, x));
13758                               x = build_fold_addr_expr (v);
13759                               do_optional_check = true;
13760                           }
13761                       }
13762                     new_var = DECL_VALUE_EXPR (new_var);
13763                     x = fold_convert (TREE_TYPE (new_var), x);
13764                     gimplify_expr (&x, &assign_body, NULL, is_gimple_val, fb_rvalue);
13765                     gimple_seq_add_stmt (&assign_body,
13766                                              gimple_build_assign (new_var, x));
13767                 }
13768               tree present;
13769               present = ((do_optional_check
13770                               && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_HAS_DEVICE_ADDR
13771                               && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_IS_DEVICE_PTR)
13772                            ? omp_check_optional_argument (OMP_CLAUSE_DECL (c), true)
13773                            : NULL_TREE);
13774               if (present)
13775                 {
13776                     tree null_label = create_artificial_label (UNKNOWN_LOCATION);
13777                     tree notnull_label = create_artificial_label (UNKNOWN_LOCATION);
13778                     tree opt_arg_label = create_artificial_label (UNKNOWN_LOCATION);
13779                     glabel *null_glabel = gimple_build_label (null_label);
13780                     glabel *notnull_glabel = gimple_build_label (notnull_label);
13781                     ggoto *opt_arg_ggoto = gimple_build_goto (opt_arg_label);
13782                     gimplify_expr (&x, &new_body, NULL, is_gimple_val,
13783                                                      fb_rvalue);
13784                     gimplify_expr (&present, &new_body, NULL, is_gimple_val,
13785                                      fb_rvalue);
13786                     gcond *cond = gimple_build_cond_from_tree (present,
13787                                                                          notnull_label,
13788                                                                          null_label);
13789                     gimple_seq_add_stmt (&new_body, cond);
13790                     gimple_seq_add_stmt (&new_body, null_glabel);
13791                     gimplify_assign (new_var, null_pointer_node, &new_body);
13792                     gimple_seq_add_stmt (&new_body, opt_arg_ggoto);
13793                     gimple_seq_add_stmt (&new_body, notnull_glabel);
13794                     gimple_seq_add_seq (&new_body, assign_body);
13795                     gimple_seq_add_stmt (&new_body,
13796                                              gimple_build_label (opt_arg_label));
13797                 }
13798               else
13799                 gimple_seq_add_seq (&new_body, assign_body);
13800               break;
13801             }
13802       /* Handle GOMP_MAP_FIRSTPRIVATE_{POINTER,REFERENCE} in second pass,
13803            so that firstprivate vars holding OMP_CLAUSE_SIZE if needed
13804            are already handled.  Similarly OMP_CLAUSE_PRIVATE for VLAs
13805            or references to VLAs.  */
13806       for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
13807           switch (OMP_CLAUSE_CODE (c))
13808             {
13809               tree var;
13810             default:
13811               break;
13812             case OMP_CLAUSE_MAP:
13813               if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
13814                     || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_REFERENCE)
13815                 {
13816                     location_t clause_loc = OMP_CLAUSE_LOCATION (c);
13817                     poly_int64 offset = 0;
13818                     gcc_assert (prev);
13819                     var = OMP_CLAUSE_DECL (c);
13820                     if (DECL_P (var)
13821                         && TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE
13822                         && is_global_var (maybe_lookup_decl_in_outer_ctx (var,
13823                                                                                       ctx))
13824                         && varpool_node::get_create (var)->offloadable)
13825                       break;
13826                     if (TREE_CODE (var) == INDIRECT_REF
13827                         && TREE_CODE (TREE_OPERAND (var, 0)) == COMPONENT_REF)
13828                       var = TREE_OPERAND (var, 0);
13829                     if (TREE_CODE (var) == COMPONENT_REF)
13830                       {
13831                         var = get_addr_base_and_unit_offset (var, &offset);
13832                         gcc_assert (var != NULL_TREE && DECL_P (var));
13833                       }
13834                     else if (DECL_SIZE (var)
13835                                && TREE_CODE (DECL_SIZE (var)) != INTEGER_CST)
13836                       {
13837                         tree var2 = DECL_VALUE_EXPR (var);
13838                         gcc_assert (TREE_CODE (var2) == INDIRECT_REF);
13839                         var2 = TREE_OPERAND (var2, 0);
13840                         gcc_assert (DECL_P (var2));
13841                         var = var2;
13842                       }
13843                     tree new_var = lookup_decl (var, ctx), x;
13844                     tree type = TREE_TYPE (new_var);
13845                     bool is_ref;
13846                     if (TREE_CODE (OMP_CLAUSE_DECL (c)) == INDIRECT_REF
13847                         && (TREE_CODE (TREE_OPERAND (OMP_CLAUSE_DECL (c), 0))
13848                               == COMPONENT_REF))
13849                       {
13850                         type = TREE_TYPE (TREE_OPERAND (OMP_CLAUSE_DECL (c), 0));
13851                         is_ref = true;
13852                         new_var = build2 (MEM_REF, type,
13853                                               build_fold_addr_expr (new_var),
13854                                               build_int_cst (build_pointer_type (type),
13855                                                                  offset));
13856                       }
13857                     else if (TREE_CODE (OMP_CLAUSE_DECL (c)) == COMPONENT_REF)
13858                       {
13859                         type = TREE_TYPE (OMP_CLAUSE_DECL (c));
13860                         is_ref = TREE_CODE (type) == REFERENCE_TYPE;
13861                         new_var = build2 (MEM_REF, type,
13862                                               build_fold_addr_expr (new_var),
13863                                               build_int_cst (build_pointer_type (type),
13864                                                                  offset));
13865                       }
13866                     else
13867                       is_ref = omp_privatize_by_reference (var);
13868                     if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_REFERENCE)
13869                       is_ref = false;
13870                     bool ref_to_array = false;
13871                     if (is_ref)
13872                       {
13873                         type = TREE_TYPE (type);
13874                         if (TREE_CODE (type) == ARRAY_TYPE)
13875                           {
13876                               type = build_pointer_type (type);
13877                               ref_to_array = true;
13878                           }
13879                       }
13880                     else if (TREE_CODE (type) == ARRAY_TYPE)
13881                       {
13882                         tree decl2 = DECL_VALUE_EXPR (new_var);
13883                         gcc_assert (TREE_CODE (decl2) == MEM_REF);
13884                         decl2 = TREE_OPERAND (decl2, 0);
13885                         gcc_assert (DECL_P (decl2));
13886                         new_var = decl2;
13887                         type = TREE_TYPE (new_var);
13888                       }
13889                     x = build_receiver_ref (OMP_CLAUSE_DECL (prev), false, ctx);
13890                     x = fold_convert_loc (clause_loc, type, x);
13891                     if (!integer_zerop (OMP_CLAUSE_SIZE (c)))
13892                       {
13893                         tree bias = OMP_CLAUSE_SIZE (c);
13894                         if (DECL_P (bias))
13895                           bias = lookup_decl (bias, ctx);
13896                         bias = fold_convert_loc (clause_loc, sizetype, bias);
13897                         bias = fold_build1_loc (clause_loc, NEGATE_EXPR, sizetype,
13898                                                       bias);
13899                         x = fold_build2_loc (clause_loc, POINTER_PLUS_EXPR,
13900                                                    TREE_TYPE (x), x, bias);
13901                       }
13902                     if (ref_to_array)
13903                       x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
13904                     gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
13905                     if (is_ref && !ref_to_array)
13906                       {
13907                         tree t = create_tmp_var_raw (type, get_name (var));
13908                         gimple_add_tmp_var (t);
13909                         TREE_ADDRESSABLE (t) = 1;
13910                         gimple_seq_add_stmt (&new_body,
13911                                                    gimple_build_assign (t, x));
13912                         x = build_fold_addr_expr_loc (clause_loc, t);
13913                       }
13914                     gimple_seq_add_stmt (&new_body,
13915                                              gimple_build_assign (new_var, x));
13916                     prev = NULL_TREE;
13917                 }
13918               else if (OMP_CLAUSE_CHAIN (c)
13919                          && OMP_CLAUSE_CODE (OMP_CLAUSE_CHAIN (c))
13920                               == OMP_CLAUSE_MAP
13921                          && (OMP_CLAUSE_MAP_KIND (OMP_CLAUSE_CHAIN (c))
13922                                == GOMP_MAP_FIRSTPRIVATE_POINTER
13923                                || (OMP_CLAUSE_MAP_KIND (OMP_CLAUSE_CHAIN (c))
13924                                    == GOMP_MAP_FIRSTPRIVATE_REFERENCE)))
13925                 prev = c;
13926               break;
13927             case OMP_CLAUSE_PRIVATE:
13928               var = OMP_CLAUSE_DECL (c);
13929               if (is_variable_sized (var))
13930                 {
13931                     location_t clause_loc = OMP_CLAUSE_LOCATION (c);
13932                     tree new_var = lookup_decl (var, ctx);
13933                     tree pvar = DECL_VALUE_EXPR (var);
13934                     gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
13935                     pvar = TREE_OPERAND (pvar, 0);
13936                     gcc_assert (DECL_P (pvar));
13937                     tree new_pvar = lookup_decl (pvar, ctx);
13938                     tree atmp = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
13939                     tree al = size_int (DECL_ALIGN (var));
13940                     tree x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
13941                     x = build_call_expr_loc (clause_loc, atmp, 2, x, al);
13942                     x = fold_convert_loc (clause_loc, TREE_TYPE (new_pvar), x);
13943                     gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
13944                     gimple_seq_add_stmt (&new_body,
13945                                              gimple_build_assign (new_pvar, x));
13946                 }
13947               else if (omp_privatize_by_reference (var)
13948                          && !is_gimple_omp_oacc (ctx->stmt))
13949                 {
13950                     location_t clause_loc = OMP_CLAUSE_LOCATION (c);
13951                     tree new_var = lookup_decl (var, ctx);
13952                     tree x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
13953                     if (TREE_CONSTANT (x))
13954                       break;
13955                     else
13956                       {
13957                         tree atmp
13958                           = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
13959                         tree rtype = TREE_TYPE (TREE_TYPE (new_var));
13960                         tree al = size_int (TYPE_ALIGN (rtype));
13961                         x = build_call_expr_loc (clause_loc, atmp, 2, x, al);
13962                       }
13963 
13964                     x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
13965                     gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
13966                     gimple_seq_add_stmt (&new_body,
13967                                              gimple_build_assign (new_var, x));
13968                 }
13969               break;
13970             }
13971 
13972       gimple_seq fork_seq = NULL;
13973       gimple_seq join_seq = NULL;
13974 
13975       if (offloaded && is_gimple_omp_oacc (ctx->stmt))
13976           {
13977             /* If there are reductions on the offloaded region itself, treat
13978                them as a dummy GANG loop.  */
13979             tree level = build_int_cst (integer_type_node, GOMP_DIM_GANG);
13980 
13981             gcall *private_marker = lower_oacc_private_marker (ctx);
13982 
13983             if (private_marker)
13984               gimple_call_set_arg (private_marker, 2, level);
13985 
13986             lower_oacc_reductions (gimple_location (ctx->stmt), clauses, level,
13987                                          false, NULL, private_marker, NULL, &fork_seq,
13988                                          &join_seq, ctx);
13989           }
13990 
13991       gimple_seq_add_seq (&new_body, fork_seq);
13992       gimple_seq_add_seq (&new_body, tgt_body);
13993       gimple_seq_add_seq (&new_body, join_seq);
13994 
13995       if (offloaded)
13996           {
13997             new_body = maybe_catch_exception (new_body);
13998             gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
13999           }
14000       gimple_omp_set_body (stmt, new_body);
14001     }
14002 
14003   bind = gimple_build_bind (NULL, NULL,
14004                                   tgt_bind ? gimple_bind_block (tgt_bind)
14005                                              : NULL_TREE);
14006   gsi_replace (gsi_p, dep_bind ? dep_bind : bind, true);
14007   gimple_bind_add_seq (bind, ilist);
14008   gimple_bind_add_stmt (bind, stmt);
14009   gimple_bind_add_seq (bind, olist);
14010 
14011   pop_gimplify_context (NULL);
14012 
14013   if (dep_bind)
14014     {
14015       gimple_bind_add_seq (dep_bind, dep_ilist);
14016       gimple_bind_add_stmt (dep_bind, bind);
14017       gimple_bind_add_seq (dep_bind, dep_olist);
14018       pop_gimplify_context (dep_bind);
14019     }
14020 }
14021 
14022 /* Expand code for an OpenMP teams directive.  */
14023 
14024 static void
lower_omp_teams(gimple_stmt_iterator * gsi_p,omp_context * ctx)14025 lower_omp_teams (gimple_stmt_iterator *gsi_p, omp_context *ctx)
14026 {
14027   gomp_teams *teams_stmt = as_a <gomp_teams *> (gsi_stmt (*gsi_p));
14028   push_gimplify_context ();
14029 
14030   tree block = make_node (BLOCK);
14031   gbind *bind = gimple_build_bind (NULL, NULL, block);
14032   gsi_replace (gsi_p, bind, true);
14033   gimple_seq bind_body = NULL;
14034   gimple_seq dlist = NULL;
14035   gimple_seq olist = NULL;
14036 
14037   tree num_teams = omp_find_clause (gimple_omp_teams_clauses (teams_stmt),
14038                                             OMP_CLAUSE_NUM_TEAMS);
14039   tree num_teams_lower = NULL_TREE;
14040   if (num_teams == NULL_TREE)
14041     num_teams = build_int_cst (unsigned_type_node, 0);
14042   else
14043     {
14044       num_teams_lower = OMP_CLAUSE_NUM_TEAMS_LOWER_EXPR (num_teams);
14045       if (num_teams_lower)
14046           {
14047             num_teams_lower = fold_convert (unsigned_type_node, num_teams_lower);
14048             gimplify_expr (&num_teams_lower, &bind_body, NULL, is_gimple_val,
14049                                fb_rvalue);
14050           }
14051       num_teams = OMP_CLAUSE_NUM_TEAMS_UPPER_EXPR (num_teams);
14052       num_teams = fold_convert (unsigned_type_node, num_teams);
14053       gimplify_expr (&num_teams, &bind_body, NULL, is_gimple_val, fb_rvalue);
14054     }
14055   if (num_teams_lower == NULL_TREE)
14056     num_teams_lower = num_teams;
14057   tree thread_limit = omp_find_clause (gimple_omp_teams_clauses (teams_stmt),
14058                                                OMP_CLAUSE_THREAD_LIMIT);
14059   if (thread_limit == NULL_TREE)
14060     thread_limit = build_int_cst (unsigned_type_node, 0);
14061   else
14062     {
14063       thread_limit = OMP_CLAUSE_THREAD_LIMIT_EXPR (thread_limit);
14064       thread_limit = fold_convert (unsigned_type_node, thread_limit);
14065       gimplify_expr (&thread_limit, &bind_body, NULL, is_gimple_val,
14066                          fb_rvalue);
14067     }
14068   location_t loc = gimple_location (teams_stmt);
14069   tree decl = builtin_decl_explicit (BUILT_IN_GOMP_TEAMS4);
14070   tree rettype = TREE_TYPE (TREE_TYPE (decl));
14071   tree first = create_tmp_var (rettype);
14072   gimple_seq_add_stmt (&bind_body,
14073                            gimple_build_assign (first, build_one_cst (rettype)));
14074   tree llabel = create_artificial_label (loc);
14075   gimple_seq_add_stmt (&bind_body, gimple_build_label (llabel));
14076   gimple *call
14077     = gimple_build_call (decl, 4, num_teams_lower, num_teams, thread_limit,
14078                                first);
14079   gimple_set_location (call, loc);
14080   tree temp = create_tmp_var (rettype);
14081   gimple_call_set_lhs (call, temp);
14082   gimple_seq_add_stmt (&bind_body, call);
14083 
14084   tree tlabel = create_artificial_label (loc);
14085   tree flabel = create_artificial_label (loc);
14086   gimple *cond = gimple_build_cond (NE_EXPR, temp, build_zero_cst (rettype),
14087                                             tlabel, flabel);
14088   gimple_seq_add_stmt (&bind_body, cond);
14089   gimple_seq_add_stmt (&bind_body, gimple_build_label (tlabel));
14090   gimple_seq_add_stmt (&bind_body,
14091                            gimple_build_assign (first, build_zero_cst (rettype)));
14092 
14093   lower_rec_input_clauses (gimple_omp_teams_clauses (teams_stmt),
14094                                  &bind_body, &dlist, ctx, NULL);
14095   lower_omp (gimple_omp_body_ptr (teams_stmt), ctx);
14096   lower_reduction_clauses (gimple_omp_teams_clauses (teams_stmt), &olist,
14097                                  NULL, ctx);
14098   gimple_seq_add_stmt (&bind_body, teams_stmt);
14099 
14100   gimple_seq_add_seq (&bind_body, gimple_omp_body (teams_stmt));
14101   gimple_omp_set_body (teams_stmt, NULL);
14102   gimple_seq_add_seq (&bind_body, olist);
14103   gimple_seq_add_seq (&bind_body, dlist);
14104   gimple_seq_add_stmt (&bind_body, gimple_build_omp_return (true));
14105   gimple_seq_add_stmt (&bind_body, gimple_build_goto (llabel));
14106   gimple_seq_add_stmt (&bind_body, gimple_build_label (flabel));
14107   gimple_bind_set_body (bind, bind_body);
14108 
14109   pop_gimplify_context (bind);
14110 
14111   gimple_bind_append_vars (bind, ctx->block_vars);
14112   BLOCK_VARS (block) = ctx->block_vars;
14113   if (BLOCK_VARS (block))
14114     TREE_USED (block) = 1;
14115 }
14116 
14117 /* Callback for lower_omp_1.  Return non-NULL if *tp needs to be
14118    regimplified.  If DATA is non-NULL, lower_omp_1 is outside
14119    of OMP context, but with make_addressable_vars set.  */
14120 
14121 static tree
lower_omp_regimplify_p(tree * tp,int * walk_subtrees,void * data)14122 lower_omp_regimplify_p (tree *tp, int *walk_subtrees,
14123                               void *data)
14124 {
14125   tree t = *tp;
14126 
14127   /* Any variable with DECL_VALUE_EXPR needs to be regimplified.  */
14128   if ((VAR_P (t) || TREE_CODE (t) == PARM_DECL || TREE_CODE (t) == RESULT_DECL)
14129       && data == NULL
14130       && DECL_HAS_VALUE_EXPR_P (t))
14131     return t;
14132 
14133   if (make_addressable_vars
14134       && DECL_P (t)
14135       && bitmap_bit_p (make_addressable_vars, DECL_UID (t)))
14136     return t;
14137 
14138   /* If a global variable has been privatized, TREE_CONSTANT on
14139      ADDR_EXPR might be wrong.  */
14140   if (data == NULL && TREE_CODE (t) == ADDR_EXPR)
14141     recompute_tree_invariant_for_addr_expr (t);
14142 
14143   *walk_subtrees = !IS_TYPE_OR_DECL_P (t);
14144   return NULL_TREE;
14145 }
14146 
14147 /* Data to be communicated between lower_omp_regimplify_operands and
14148    lower_omp_regimplify_operands_p.  */
14149 
14150 struct lower_omp_regimplify_operands_data
14151 {
14152   omp_context *ctx;
14153   vec<tree> *decls;
14154 };
14155 
14156 /* Helper function for lower_omp_regimplify_operands.  Find
14157    omp_member_access_dummy_var vars and adjust temporarily their
14158    DECL_VALUE_EXPRs if needed.  */
14159 
14160 static tree
lower_omp_regimplify_operands_p(tree * tp,int * walk_subtrees,void * data)14161 lower_omp_regimplify_operands_p (tree *tp, int *walk_subtrees,
14162                                          void *data)
14163 {
14164   tree t = omp_member_access_dummy_var (*tp);
14165   if (t)
14166     {
14167       struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
14168       lower_omp_regimplify_operands_data *ldata
14169           = (lower_omp_regimplify_operands_data *) wi->info;
14170       tree o = maybe_lookup_decl (t, ldata->ctx);
14171       if (o != t)
14172           {
14173             ldata->decls->safe_push (DECL_VALUE_EXPR (*tp));
14174             ldata->decls->safe_push (*tp);
14175             tree v = unshare_and_remap (DECL_VALUE_EXPR (*tp), t, o);
14176             SET_DECL_VALUE_EXPR (*tp, v);
14177           }
14178     }
14179   *walk_subtrees = !IS_TYPE_OR_DECL_P (*tp);
14180   return NULL_TREE;
14181 }
14182 
14183 /* Wrapper around gimple_regimplify_operands that adjusts DECL_VALUE_EXPRs
14184    of omp_member_access_dummy_var vars during regimplification.  */
14185 
14186 static void
lower_omp_regimplify_operands(omp_context * ctx,gimple * stmt,gimple_stmt_iterator * gsi_p)14187 lower_omp_regimplify_operands (omp_context *ctx, gimple *stmt,
14188                                      gimple_stmt_iterator *gsi_p)
14189 {
14190   auto_vec<tree, 10> decls;
14191   if (ctx)
14192     {
14193       struct walk_stmt_info wi;
14194       memset (&wi, '\0', sizeof (wi));
14195       struct lower_omp_regimplify_operands_data data;
14196       data.ctx = ctx;
14197       data.decls = &decls;
14198       wi.info = &data;
14199       walk_gimple_op (stmt, lower_omp_regimplify_operands_p, &wi);
14200     }
14201   gimple_regimplify_operands (stmt, gsi_p);
14202   while (!decls.is_empty ())
14203     {
14204       tree t = decls.pop ();
14205       tree v = decls.pop ();
14206       SET_DECL_VALUE_EXPR (t, v);
14207     }
14208 }
14209 
14210 static void
lower_omp_1(gimple_stmt_iterator * gsi_p,omp_context * ctx)14211 lower_omp_1 (gimple_stmt_iterator *gsi_p, omp_context *ctx)
14212 {
14213   gimple *stmt = gsi_stmt (*gsi_p);
14214   struct walk_stmt_info wi;
14215   gcall *call_stmt;
14216 
14217   if (gimple_has_location (stmt))
14218     input_location = gimple_location (stmt);
14219 
14220   if (make_addressable_vars)
14221     memset (&wi, '\0', sizeof (wi));
14222 
14223   /* If we have issued syntax errors, avoid doing any heavy lifting.
14224      Just replace the OMP directives with a NOP to avoid
14225      confusing RTL expansion.  */
14226   if (seen_error () && is_gimple_omp (stmt))
14227     {
14228       gsi_replace (gsi_p, gimple_build_nop (), true);
14229       return;
14230     }
14231 
14232   switch (gimple_code (stmt))
14233     {
14234     case GIMPLE_COND:
14235       {
14236           gcond *cond_stmt = as_a <gcond *> (stmt);
14237           if ((ctx || make_addressable_vars)
14238               && (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
14239                                  lower_omp_regimplify_p,
14240                                  ctx ? NULL : &wi, NULL)
14241                     || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
14242                                     lower_omp_regimplify_p,
14243                                     ctx ? NULL : &wi, NULL)))
14244             lower_omp_regimplify_operands (ctx, cond_stmt, gsi_p);
14245       }
14246       break;
14247     case GIMPLE_CATCH:
14248       lower_omp (gimple_catch_handler_ptr (as_a <gcatch *> (stmt)), ctx);
14249       break;
14250     case GIMPLE_EH_FILTER:
14251       lower_omp (gimple_eh_filter_failure_ptr (stmt), ctx);
14252       break;
14253     case GIMPLE_TRY:
14254       lower_omp (gimple_try_eval_ptr (stmt), ctx);
14255       lower_omp (gimple_try_cleanup_ptr (stmt), ctx);
14256       break;
14257     case GIMPLE_TRANSACTION:
14258       lower_omp (gimple_transaction_body_ptr (as_a <gtransaction *> (stmt)),
14259                      ctx);
14260       break;
14261     case GIMPLE_BIND:
14262       if (ctx && is_gimple_omp_oacc (ctx->stmt))
14263           {
14264             tree vars = gimple_bind_vars (as_a <gbind *> (stmt));
14265             oacc_privatization_scan_decl_chain (ctx, vars);
14266           }
14267       lower_omp (gimple_bind_body_ptr (as_a <gbind *> (stmt)), ctx);
14268       maybe_remove_omp_member_access_dummy_vars (as_a <gbind *> (stmt));
14269       break;
14270     case GIMPLE_OMP_PARALLEL:
14271     case GIMPLE_OMP_TASK:
14272       ctx = maybe_lookup_ctx (stmt);
14273       gcc_assert (ctx);
14274       if (ctx->cancellable)
14275           ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
14276       lower_omp_taskreg (gsi_p, ctx);
14277       break;
14278     case GIMPLE_OMP_FOR:
14279       ctx = maybe_lookup_ctx (stmt);
14280       gcc_assert (ctx);
14281       if (ctx->cancellable)
14282           ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
14283       lower_omp_for (gsi_p, ctx);
14284       break;
14285     case GIMPLE_OMP_SECTIONS:
14286       ctx = maybe_lookup_ctx (stmt);
14287       gcc_assert (ctx);
14288       if (ctx->cancellable)
14289           ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
14290       lower_omp_sections (gsi_p, ctx);
14291       break;
14292     case GIMPLE_OMP_SCOPE:
14293       ctx = maybe_lookup_ctx (stmt);
14294       gcc_assert (ctx);
14295       lower_omp_scope (gsi_p, ctx);
14296       break;
14297     case GIMPLE_OMP_SINGLE:
14298       ctx = maybe_lookup_ctx (stmt);
14299       gcc_assert (ctx);
14300       lower_omp_single (gsi_p, ctx);
14301       break;
14302     case GIMPLE_OMP_MASTER:
14303     case GIMPLE_OMP_MASKED:
14304       ctx = maybe_lookup_ctx (stmt);
14305       gcc_assert (ctx);
14306       lower_omp_master (gsi_p, ctx);
14307       break;
14308     case GIMPLE_OMP_TASKGROUP:
14309       ctx = maybe_lookup_ctx (stmt);
14310       gcc_assert (ctx);
14311       lower_omp_taskgroup (gsi_p, ctx);
14312       break;
14313     case GIMPLE_OMP_ORDERED:
14314       ctx = maybe_lookup_ctx (stmt);
14315       gcc_assert (ctx);
14316       lower_omp_ordered (gsi_p, ctx);
14317       break;
14318     case GIMPLE_OMP_SCAN:
14319       ctx = maybe_lookup_ctx (stmt);
14320       gcc_assert (ctx);
14321       lower_omp_scan (gsi_p, ctx);
14322       break;
14323     case GIMPLE_OMP_CRITICAL:
14324       ctx = maybe_lookup_ctx (stmt);
14325       gcc_assert (ctx);
14326       lower_omp_critical (gsi_p, ctx);
14327       break;
14328     case GIMPLE_OMP_ATOMIC_LOAD:
14329       if ((ctx || make_addressable_vars)
14330             && walk_tree (gimple_omp_atomic_load_rhs_ptr (
14331                                 as_a <gomp_atomic_load *> (stmt)),
14332                               lower_omp_regimplify_p, ctx ? NULL : &wi, NULL))
14333           lower_omp_regimplify_operands (ctx, stmt, gsi_p);
14334       break;
14335     case GIMPLE_OMP_TARGET:
14336       ctx = maybe_lookup_ctx (stmt);
14337       gcc_assert (ctx);
14338       lower_omp_target (gsi_p, ctx);
14339       break;
14340     case GIMPLE_OMP_TEAMS:
14341       ctx = maybe_lookup_ctx (stmt);
14342       gcc_assert (ctx);
14343       if (gimple_omp_teams_host (as_a <gomp_teams *> (stmt)))
14344           lower_omp_taskreg (gsi_p, ctx);
14345       else
14346           lower_omp_teams (gsi_p, ctx);
14347       break;
14348     case GIMPLE_CALL:
14349       tree fndecl;
14350       call_stmt = as_a <gcall *> (stmt);
14351       fndecl = gimple_call_fndecl (call_stmt);
14352       if (fndecl
14353             && fndecl_built_in_p (fndecl, BUILT_IN_NORMAL))
14354           switch (DECL_FUNCTION_CODE (fndecl))
14355             {
14356             case BUILT_IN_GOMP_BARRIER:
14357               if (ctx == NULL)
14358                 break;
14359               /* FALLTHRU */
14360             case BUILT_IN_GOMP_CANCEL:
14361             case BUILT_IN_GOMP_CANCELLATION_POINT:
14362               omp_context *cctx;
14363               cctx = ctx;
14364               if (gimple_code (cctx->stmt) == GIMPLE_OMP_SECTION)
14365                 cctx = cctx->outer;
14366               gcc_assert (gimple_call_lhs (call_stmt) == NULL_TREE);
14367               if (!cctx->cancellable)
14368                 {
14369                     if (DECL_FUNCTION_CODE (fndecl)
14370                         == BUILT_IN_GOMP_CANCELLATION_POINT)
14371                       {
14372                         stmt = gimple_build_nop ();
14373                         gsi_replace (gsi_p, stmt, false);
14374                       }
14375                     break;
14376                 }
14377               if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_GOMP_BARRIER)
14378                 {
14379                     fndecl = builtin_decl_explicit (BUILT_IN_GOMP_BARRIER_CANCEL);
14380                     gimple_call_set_fndecl (call_stmt, fndecl);
14381                     gimple_call_set_fntype (call_stmt, TREE_TYPE (fndecl));
14382                 }
14383               tree lhs;
14384               lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (fndecl)));
14385               gimple_call_set_lhs (call_stmt, lhs);
14386               tree fallthru_label;
14387               fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
14388               gimple *g;
14389               g = gimple_build_label (fallthru_label);
14390               gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
14391               g = gimple_build_cond (NE_EXPR, lhs,
14392                                            fold_convert (TREE_TYPE (lhs),
14393                                                              boolean_false_node),
14394                                            cctx->cancel_label, fallthru_label);
14395               gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
14396               break;
14397             default:
14398               break;
14399             }
14400       goto regimplify;
14401 
14402     case GIMPLE_ASSIGN:
14403       for (omp_context *up = ctx; up; up = up->outer)
14404           {
14405             if (gimple_code (up->stmt) == GIMPLE_OMP_ORDERED
14406                 || gimple_code (up->stmt) == GIMPLE_OMP_CRITICAL
14407                 || gimple_code (up->stmt) == GIMPLE_OMP_TASKGROUP
14408                 || gimple_code (up->stmt) == GIMPLE_OMP_SCOPE
14409                 || gimple_code (up->stmt) == GIMPLE_OMP_SECTION
14410                 || gimple_code (up->stmt) == GIMPLE_OMP_SCAN
14411                 || (gimple_code (up->stmt) == GIMPLE_OMP_TARGET
14412                       && (gimple_omp_target_kind (up->stmt)
14413                           == GF_OMP_TARGET_KIND_DATA)))
14414               continue;
14415             else if (!up->lastprivate_conditional_map)
14416               break;
14417             tree lhs = get_base_address (gimple_assign_lhs (stmt));
14418             if (TREE_CODE (lhs) == MEM_REF
14419                 && DECL_P (TREE_OPERAND (lhs, 0))
14420                 && TREE_CODE (TREE_TYPE (TREE_OPERAND (lhs,
14421                                                                  0))) == REFERENCE_TYPE)
14422               lhs = TREE_OPERAND (lhs, 0);
14423             if (DECL_P (lhs))
14424               if (tree *v = up->lastprivate_conditional_map->get (lhs))
14425                 {
14426                     tree clauses;
14427                     if (up->combined_into_simd_safelen1)
14428                       {
14429                         up = up->outer;
14430                         if (gimple_code (up->stmt) == GIMPLE_OMP_SCAN)
14431                           up = up->outer;
14432                       }
14433                     if (gimple_code (up->stmt) == GIMPLE_OMP_FOR)
14434                       clauses = gimple_omp_for_clauses (up->stmt);
14435                     else
14436                       clauses = gimple_omp_sections_clauses (up->stmt);
14437                     tree c = omp_find_clause (clauses, OMP_CLAUSE__CONDTEMP_);
14438                     if (!OMP_CLAUSE__CONDTEMP__ITER (c))
14439                       c = omp_find_clause (OMP_CLAUSE_CHAIN (c),
14440                                                OMP_CLAUSE__CONDTEMP_);
14441                     gcc_assert (OMP_CLAUSE__CONDTEMP__ITER (c));
14442                     gimple *g = gimple_build_assign (*v, OMP_CLAUSE_DECL (c));
14443                     gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
14444                 }
14445           }
14446       /* FALLTHRU */
14447 
14448     default:
14449     regimplify:
14450       if ((ctx || make_addressable_vars)
14451             && walk_gimple_op (stmt, lower_omp_regimplify_p,
14452                                    ctx ? NULL : &wi))
14453           {
14454             /* Just remove clobbers, this should happen only if we have
14455                "privatized" local addressable variables in SIMD regions,
14456                the clobber isn't needed in that case and gimplifying address
14457                of the ARRAY_REF into a pointer and creating MEM_REF based
14458                clobber would create worse code than we get with the clobber
14459                dropped.  */
14460             if (gimple_clobber_p (stmt))
14461               {
14462                 gsi_replace (gsi_p, gimple_build_nop (), true);
14463                 break;
14464               }
14465             lower_omp_regimplify_operands (ctx, stmt, gsi_p);
14466           }
14467       break;
14468     }
14469 }
14470 
14471 static void
lower_omp(gimple_seq * body,omp_context * ctx)14472 lower_omp (gimple_seq *body, omp_context *ctx)
14473 {
14474   location_t saved_location = input_location;
14475   gimple_stmt_iterator gsi;
14476   for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
14477     lower_omp_1 (&gsi, ctx);
14478   /* During gimplification, we haven't folded statments inside offloading
14479      or taskreg regions (gimplify.cc:maybe_fold_stmt); do that now.  */
14480   if (target_nesting_level || taskreg_nesting_level)
14481     for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
14482       fold_stmt (&gsi);
14483   input_location = saved_location;
14484 }
14485 
14486 /* Main entry point.  */
14487 
14488 static unsigned int
execute_lower_omp(void)14489 execute_lower_omp (void)
14490 {
14491   gimple_seq body;
14492   int i;
14493   omp_context *ctx;
14494 
14495   /* This pass always runs, to provide PROP_gimple_lomp.
14496      But often, there is nothing to do.  */
14497   if (flag_openacc == 0 && flag_openmp == 0
14498       && flag_openmp_simd == 0)
14499     return 0;
14500 
14501   all_contexts = splay_tree_new (splay_tree_compare_pointers, 0,
14502                                          delete_omp_context);
14503 
14504   body = gimple_body (current_function_decl);
14505 
14506   scan_omp (&body, NULL);
14507   gcc_assert (taskreg_nesting_level == 0);
14508   FOR_EACH_VEC_ELT (taskreg_contexts, i, ctx)
14509     finish_taskreg_scan (ctx);
14510   taskreg_contexts.release ();
14511 
14512   if (all_contexts->root)
14513     {
14514       if (make_addressable_vars)
14515           push_gimplify_context ();
14516       lower_omp (&body, NULL);
14517       if (make_addressable_vars)
14518           pop_gimplify_context (NULL);
14519     }
14520 
14521   if (all_contexts)
14522     {
14523       splay_tree_delete (all_contexts);
14524       all_contexts = NULL;
14525     }
14526   BITMAP_FREE (make_addressable_vars);
14527   BITMAP_FREE (global_nonaddressable_vars);
14528 
14529   /* If current function is a method, remove artificial dummy VAR_DECL created
14530      for non-static data member privatization, they aren't needed for
14531      debuginfo nor anything else, have been already replaced everywhere in the
14532      IL and cause problems with LTO.  */
14533   if (DECL_ARGUMENTS (current_function_decl)
14534       && DECL_ARTIFICIAL (DECL_ARGUMENTS (current_function_decl))
14535       && (TREE_CODE (TREE_TYPE (DECL_ARGUMENTS (current_function_decl)))
14536             == POINTER_TYPE))
14537     remove_member_access_dummy_vars (DECL_INITIAL (current_function_decl));
14538 
14539   for (auto task_stmt : task_cpyfns)
14540     finalize_task_copyfn (task_stmt);
14541   task_cpyfns.release ();
14542   return 0;
14543 }
14544 
14545 namespace {
14546 
14547 const pass_data pass_data_lower_omp =
14548 {
14549   GIMPLE_PASS, /* type */
14550   "omplower", /* name */
14551   OPTGROUP_OMP, /* optinfo_flags */
14552   TV_NONE, /* tv_id */
14553   PROP_gimple_any, /* properties_required */
14554   PROP_gimple_lomp | PROP_gimple_lomp_dev, /* properties_provided */
14555   0, /* properties_destroyed */
14556   0, /* todo_flags_start */
14557   0, /* todo_flags_finish */
14558 };
14559 
14560 class pass_lower_omp : public gimple_opt_pass
14561 {
14562 public:
pass_lower_omp(gcc::context * ctxt)14563   pass_lower_omp (gcc::context *ctxt)
14564     : gimple_opt_pass (pass_data_lower_omp, ctxt)
14565   {}
14566 
14567   /* opt_pass methods: */
execute(function *)14568   virtual unsigned int execute (function *) { return execute_lower_omp (); }
14569 
14570 }; // class pass_lower_omp
14571 
14572 } // anon namespace
14573 
14574 gimple_opt_pass *
make_pass_lower_omp(gcc::context * ctxt)14575 make_pass_lower_omp (gcc::context *ctxt)
14576 {
14577   return new pass_lower_omp (ctxt);
14578 }
14579 
14580 /* The following is a utility to diagnose structured block violations.
14581    It is not part of the "omplower" pass, as that's invoked too late.  It
14582    should be invoked by the respective front ends after gimplification.  */
14583 
14584 static splay_tree all_labels;
14585 
14586 /* Check for mismatched contexts and generate an error if needed.  Return
14587    true if an error is detected.  */
14588 
14589 static bool
diagnose_sb_0(gimple_stmt_iterator * gsi_p,gimple * branch_ctx,gimple * label_ctx)14590 diagnose_sb_0 (gimple_stmt_iterator *gsi_p,
14591                  gimple *branch_ctx, gimple *label_ctx)
14592 {
14593   gcc_checking_assert (!branch_ctx || is_gimple_omp (branch_ctx));
14594   gcc_checking_assert (!label_ctx || is_gimple_omp (label_ctx));
14595 
14596   if (label_ctx == branch_ctx)
14597     return false;
14598 
14599   const char* kind = NULL;
14600 
14601   if (flag_openacc)
14602     {
14603       if ((branch_ctx && is_gimple_omp_oacc (branch_ctx))
14604             || (label_ctx && is_gimple_omp_oacc (label_ctx)))
14605           {
14606             gcc_checking_assert (kind == NULL);
14607             kind = "OpenACC";
14608           }
14609     }
14610   if (kind == NULL)
14611     {
14612       gcc_checking_assert (flag_openmp || flag_openmp_simd);
14613       kind = "OpenMP";
14614     }
14615 
14616   /* Previously we kept track of the label's entire context in diagnose_sb_[12]
14617      so we could traverse it and issue a correct "exit" or "enter" error
14618      message upon a structured block violation.
14619 
14620      We built the context by building a list with tree_cons'ing, but there is
14621      no easy counterpart in gimple tuples.  It seems like far too much work
14622      for issuing exit/enter error messages.  If someone really misses the
14623      distinct error message... patches welcome.  */
14624 
14625 #if 0
14626   /* Try to avoid confusing the user by producing and error message
14627      with correct "exit" or "enter" verbiage.  We prefer "exit"
14628      unless we can show that LABEL_CTX is nested within BRANCH_CTX.  */
14629   if (branch_ctx == NULL)
14630     exit_p = false;
14631   else
14632     {
14633       while (label_ctx)
14634           {
14635             if (TREE_VALUE (label_ctx) == branch_ctx)
14636               {
14637                 exit_p = false;
14638                 break;
14639               }
14640             label_ctx = TREE_CHAIN (label_ctx);
14641           }
14642     }
14643 
14644   if (exit_p)
14645     error ("invalid exit from %s structured block", kind);
14646   else
14647     error ("invalid entry to %s structured block", kind);
14648 #endif
14649 
14650   /* If it's obvious we have an invalid entry, be specific about the error.  */
14651   if (branch_ctx == NULL)
14652     error ("invalid entry to %s structured block", kind);
14653   else
14654     {
14655       /* Otherwise, be vague and lazy, but efficient.  */
14656       error ("invalid branch to/from %s structured block", kind);
14657     }
14658 
14659   gsi_replace (gsi_p, gimple_build_nop (), false);
14660   return true;
14661 }
14662 
14663 /* Pass 1: Create a minimal tree of structured blocks, and record
14664    where each label is found.  */
14665 
14666 static tree
diagnose_sb_1(gimple_stmt_iterator * gsi_p,bool * handled_ops_p,struct walk_stmt_info * wi)14667 diagnose_sb_1 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
14668                  struct walk_stmt_info *wi)
14669 {
14670   gimple *context = (gimple *) wi->info;
14671   gimple *inner_context;
14672   gimple *stmt = gsi_stmt (*gsi_p);
14673 
14674   *handled_ops_p = true;
14675 
14676   switch (gimple_code (stmt))
14677     {
14678     WALK_SUBSTMTS;
14679 
14680     case GIMPLE_OMP_PARALLEL:
14681     case GIMPLE_OMP_TASK:
14682     case GIMPLE_OMP_SCOPE:
14683     case GIMPLE_OMP_SECTIONS:
14684     case GIMPLE_OMP_SINGLE:
14685     case GIMPLE_OMP_SECTION:
14686     case GIMPLE_OMP_MASTER:
14687     case GIMPLE_OMP_MASKED:
14688     case GIMPLE_OMP_ORDERED:
14689     case GIMPLE_OMP_SCAN:
14690     case GIMPLE_OMP_CRITICAL:
14691     case GIMPLE_OMP_TARGET:
14692     case GIMPLE_OMP_TEAMS:
14693     case GIMPLE_OMP_TASKGROUP:
14694       /* The minimal context here is just the current OMP construct.  */
14695       inner_context = stmt;
14696       wi->info = inner_context;
14697       walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
14698       wi->info = context;
14699       break;
14700 
14701     case GIMPLE_OMP_FOR:
14702       inner_context = stmt;
14703       wi->info = inner_context;
14704       /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
14705            walk them.  */
14706       walk_gimple_seq (gimple_omp_for_pre_body (stmt),
14707                            diagnose_sb_1, NULL, wi);
14708       walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
14709       wi->info = context;
14710       break;
14711 
14712     case GIMPLE_LABEL:
14713       splay_tree_insert (all_labels,
14714                                (splay_tree_key) gimple_label_label (
14715                                                       as_a <glabel *> (stmt)),
14716                                (splay_tree_value) context);
14717       break;
14718 
14719     default:
14720       break;
14721     }
14722 
14723   return NULL_TREE;
14724 }
14725 
14726 /* Pass 2: Check each branch and see if its context differs from that of
14727    the destination label's context.  */
14728 
14729 static tree
diagnose_sb_2(gimple_stmt_iterator * gsi_p,bool * handled_ops_p,struct walk_stmt_info * wi)14730 diagnose_sb_2 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
14731                  struct walk_stmt_info *wi)
14732 {
14733   gimple *context = (gimple *) wi->info;
14734   splay_tree_node n;
14735   gimple *stmt = gsi_stmt (*gsi_p);
14736 
14737   *handled_ops_p = true;
14738 
14739   switch (gimple_code (stmt))
14740     {
14741     WALK_SUBSTMTS;
14742 
14743     case GIMPLE_OMP_PARALLEL:
14744     case GIMPLE_OMP_TASK:
14745     case GIMPLE_OMP_SCOPE:
14746     case GIMPLE_OMP_SECTIONS:
14747     case GIMPLE_OMP_SINGLE:
14748     case GIMPLE_OMP_SECTION:
14749     case GIMPLE_OMP_MASTER:
14750     case GIMPLE_OMP_MASKED:
14751     case GIMPLE_OMP_ORDERED:
14752     case GIMPLE_OMP_SCAN:
14753     case GIMPLE_OMP_CRITICAL:
14754     case GIMPLE_OMP_TARGET:
14755     case GIMPLE_OMP_TEAMS:
14756     case GIMPLE_OMP_TASKGROUP:
14757       wi->info = stmt;
14758       walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
14759       wi->info = context;
14760       break;
14761 
14762     case GIMPLE_OMP_FOR:
14763       wi->info = stmt;
14764       /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
14765            walk them.  */
14766       walk_gimple_seq_mod (gimple_omp_for_pre_body_ptr (stmt),
14767                                  diagnose_sb_2, NULL, wi);
14768       walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
14769       wi->info = context;
14770       break;
14771 
14772     case GIMPLE_COND:
14773           {
14774             gcond *cond_stmt = as_a <gcond *> (stmt);
14775             tree lab = gimple_cond_true_label (cond_stmt);
14776             if (lab)
14777               {
14778                 n = splay_tree_lookup (all_labels,
14779                                              (splay_tree_key) lab);
14780                 diagnose_sb_0 (gsi_p, context,
14781                                    n ? (gimple *) n->value : NULL);
14782               }
14783             lab = gimple_cond_false_label (cond_stmt);
14784             if (lab)
14785               {
14786                 n = splay_tree_lookup (all_labels,
14787                                              (splay_tree_key) lab);
14788                 diagnose_sb_0 (gsi_p, context,
14789                                    n ? (gimple *) n->value : NULL);
14790               }
14791           }
14792       break;
14793 
14794     case GIMPLE_GOTO:
14795       {
14796           tree lab = gimple_goto_dest (stmt);
14797           if (TREE_CODE (lab) != LABEL_DECL)
14798             break;
14799 
14800           n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
14801           diagnose_sb_0 (gsi_p, context, n ? (gimple *) n->value : NULL);
14802       }
14803       break;
14804 
14805     case GIMPLE_SWITCH:
14806       {
14807           gswitch *switch_stmt = as_a <gswitch *> (stmt);
14808           unsigned int i;
14809           for (i = 0; i < gimple_switch_num_labels (switch_stmt); ++i)
14810             {
14811               tree lab = CASE_LABEL (gimple_switch_label (switch_stmt, i));
14812               n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
14813               if (n && diagnose_sb_0 (gsi_p, context, (gimple *) n->value))
14814                 break;
14815             }
14816       }
14817       break;
14818 
14819     case GIMPLE_RETURN:
14820       diagnose_sb_0 (gsi_p, context, NULL);
14821       break;
14822 
14823     default:
14824       break;
14825     }
14826 
14827   return NULL_TREE;
14828 }
14829 
14830 static unsigned int
diagnose_omp_structured_block_errors(void)14831 diagnose_omp_structured_block_errors (void)
14832 {
14833   struct walk_stmt_info wi;
14834   gimple_seq body = gimple_body (current_function_decl);
14835 
14836   all_labels = splay_tree_new (splay_tree_compare_pointers, 0, 0);
14837 
14838   memset (&wi, 0, sizeof (wi));
14839   walk_gimple_seq (body, diagnose_sb_1, NULL, &wi);
14840 
14841   memset (&wi, 0, sizeof (wi));
14842   wi.want_locations = true;
14843   walk_gimple_seq_mod (&body, diagnose_sb_2, NULL, &wi);
14844 
14845   gimple_set_body (current_function_decl, body);
14846 
14847   splay_tree_delete (all_labels);
14848   all_labels = NULL;
14849 
14850   return 0;
14851 }
14852 
14853 namespace {
14854 
14855 const pass_data pass_data_diagnose_omp_blocks =
14856 {
14857   GIMPLE_PASS, /* type */
14858   "*diagnose_omp_blocks", /* name */
14859   OPTGROUP_OMP, /* optinfo_flags */
14860   TV_NONE, /* tv_id */
14861   PROP_gimple_any, /* properties_required */
14862   0, /* properties_provided */
14863   0, /* properties_destroyed */
14864   0, /* todo_flags_start */
14865   0, /* todo_flags_finish */
14866 };
14867 
14868 class pass_diagnose_omp_blocks : public gimple_opt_pass
14869 {
14870 public:
pass_diagnose_omp_blocks(gcc::context * ctxt)14871   pass_diagnose_omp_blocks (gcc::context *ctxt)
14872     : gimple_opt_pass (pass_data_diagnose_omp_blocks, ctxt)
14873   {}
14874 
14875   /* opt_pass methods: */
gate(function *)14876   virtual bool gate (function *)
14877   {
14878     return flag_openacc || flag_openmp || flag_openmp_simd;
14879   }
execute(function *)14880   virtual unsigned int execute (function *)
14881     {
14882       return diagnose_omp_structured_block_errors ();
14883     }
14884 
14885 }; // class pass_diagnose_omp_blocks
14886 
14887 } // anon namespace
14888 
14889 gimple_opt_pass *
make_pass_diagnose_omp_blocks(gcc::context * ctxt)14890 make_pass_diagnose_omp_blocks (gcc::context *ctxt)
14891 {
14892   return new pass_diagnose_omp_blocks (ctxt);
14893 }
14894 
14895 
14896 #include "gt-omp-low.h"
14897