1/* Lowering pass for OpenMP directives.  Converts OpenMP directives
2   into explicit calls to the runtime library (libgomp) and data
3   marshalling to implement data sharing and copying clauses.
4   Contributed by Diego Novillo <dnovillo@redhat.com>
5
6   Copyright (C) 2005, 2006 Free Software Foundation, Inc.
7
8This file is part of GCC.
9
10GCC is free software; you can redistribute it and/or modify it under
11the terms of the GNU General Public License as published by the Free
12Software Foundation; either version 2, or (at your option) any later
13version.
14
15GCC is distributed in the hope that it will be useful, but WITHOUT ANY
16WARRANTY; without even the implied warranty of MERCHANTABILITY or
17FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
18for more details.
19
20You should have received a copy of the GNU General Public License
21along with GCC; see the file COPYING.  If not, write to the Free
22Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
2302110-1301, USA.  */
24
25#include "config.h"
26#include "system.h"
27#include "coretypes.h"
28#include "tm.h"
29#include "tree.h"
30#include "rtl.h"
31#include "tree-gimple.h"
32#include "tree-inline.h"
33#include "langhooks.h"
34#include "diagnostic.h"
35#include "tree-flow.h"
36#include "timevar.h"
37#include "flags.h"
38#include "function.h"
39#include "expr.h"
40#include "toplev.h"
41#include "tree-pass.h"
42#include "ggc.h"
43#include "except.h"
44
45
46/* Lowering of OpenMP parallel and workshare constructs proceeds in two
47   phases.  The first phase scans the function looking for OMP statements
48   and then for variables that must be replaced to satisfy data sharing
49   clauses.  The second phase expands code for the constructs, as well as
50   re-gimplifying things when variables have been replaced with complex
51   expressions.
52
53   Final code generation is done by pass_expand_omp.  The flowgraph is
54   scanned for parallel regions which are then moved to a new
55   function, to be invoked by the thread library.  */
56
57/* Context structure.  Used to store information about each parallel
58   directive in the code.  */
59
60typedef struct omp_context
61{
62  /* This field must be at the beginning, as we do "inheritance": Some
63     callback functions for tree-inline.c (e.g., omp_copy_decl)
64     receive a copy_body_data pointer that is up-casted to an
65     omp_context pointer.  */
66  copy_body_data cb;
67
68  /* The tree of contexts corresponding to the encountered constructs.  */
69  struct omp_context *outer;
70  tree stmt;
71
72  /* Map variables to fields in a structure that allows communication
73     between sending and receiving threads.  */
74  splay_tree field_map;
75  tree record_type;
76  tree sender_decl;
77  tree receiver_decl;
78
79  /* A chain of variables to add to the top-level block surrounding the
80     construct.  In the case of a parallel, this is in the child function.  */
81  tree block_vars;
82
83  /* What to do with variables with implicitly determined sharing
84     attributes.  */
85  enum omp_clause_default_kind default_kind;
86
87  /* Nesting depth of this context.  Used to beautify error messages re
88     invalid gotos.  The outermost ctx is depth 1, with depth 0 being
89     reserved for the main body of the function.  */
90  int depth;
91
92  /* True if this parallel directive is nested within another.  */
93  bool is_nested;
94} omp_context;
95
96
97/* A structure describing the main elements of a parallel loop.  */
98
99struct omp_for_data
100{
101  tree v, n1, n2, step, chunk_size, for_stmt;
102  enum tree_code cond_code;
103  tree pre;
104  bool have_nowait, have_ordered;
105  enum omp_clause_schedule_kind sched_kind;
106};
107
108
109static splay_tree all_contexts;
110static int parallel_nesting_level;
111struct omp_region *root_omp_region;
112
113static void scan_omp (tree *, omp_context *);
114static void lower_omp (tree *, omp_context *);
115static tree lookup_decl_in_outer_ctx (tree, omp_context *);
116static tree maybe_lookup_decl_in_outer_ctx (tree, omp_context *);
117
118/* Find an OpenMP clause of type KIND within CLAUSES.  */
119
120static tree
121find_omp_clause (tree clauses, enum omp_clause_code kind)
122{
123  for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
124    if (OMP_CLAUSE_CODE (clauses) == kind)
125      return clauses;
126
127  return NULL_TREE;
128}
129
130/* Return true if CTX is for an omp parallel.  */
131
132static inline bool
133is_parallel_ctx (omp_context *ctx)
134{
135  return TREE_CODE (ctx->stmt) == OMP_PARALLEL;
136}
137
138
139/* Return true if REGION is a combined parallel+workshare region.  */
140
141static inline bool
142is_combined_parallel (struct omp_region *region)
143{
144  return region->is_combined_parallel;
145}
146
147
148/* Extract the header elements of parallel loop FOR_STMT and store
149   them into *FD.  */
150
151static void
152extract_omp_for_data (tree for_stmt, struct omp_for_data *fd)
153{
154  tree t;
155
156  fd->for_stmt = for_stmt;
157  fd->pre = NULL;
158
159  t = OMP_FOR_INIT (for_stmt);
160  gcc_assert (TREE_CODE (t) == MODIFY_EXPR);
161  fd->v = TREE_OPERAND (t, 0);
162  gcc_assert (DECL_P (fd->v));
163  gcc_assert (TREE_CODE (TREE_TYPE (fd->v)) == INTEGER_TYPE);
164  fd->n1 = TREE_OPERAND (t, 1);
165
166  t = OMP_FOR_COND (for_stmt);
167  fd->cond_code = TREE_CODE (t);
168  gcc_assert (TREE_OPERAND (t, 0) == fd->v);
169  fd->n2 = TREE_OPERAND (t, 1);
170  switch (fd->cond_code)
171    {
172    case LT_EXPR:
173    case GT_EXPR:
174      break;
175    case LE_EXPR:
176      fd->n2 = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->n2), fd->n2,
177			   build_int_cst (TREE_TYPE (fd->n2), 1));
178      fd->cond_code = LT_EXPR;
179      break;
180    case GE_EXPR:
181      fd->n2 = fold_build2 (MINUS_EXPR, TREE_TYPE (fd->n2), fd->n2,
182			   build_int_cst (TREE_TYPE (fd->n2), 1));
183      fd->cond_code = GT_EXPR;
184      break;
185    default:
186      gcc_unreachable ();
187    }
188
189  t = OMP_FOR_INCR (fd->for_stmt);
190  gcc_assert (TREE_CODE (t) == MODIFY_EXPR);
191  gcc_assert (TREE_OPERAND (t, 0) == fd->v);
192  t = TREE_OPERAND (t, 1);
193  gcc_assert (TREE_OPERAND (t, 0) == fd->v);
194  switch (TREE_CODE (t))
195    {
196    case PLUS_EXPR:
197      fd->step = TREE_OPERAND (t, 1);
198      break;
199    case MINUS_EXPR:
200      fd->step = TREE_OPERAND (t, 1);
201      fd->step = fold_build1 (NEGATE_EXPR, TREE_TYPE (fd->step), fd->step);
202      break;
203    default:
204      gcc_unreachable ();
205    }
206
207  fd->have_nowait = fd->have_ordered = false;
208  fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
209  fd->chunk_size = NULL_TREE;
210
211  for (t = OMP_FOR_CLAUSES (for_stmt); t ; t = OMP_CLAUSE_CHAIN (t))
212    switch (OMP_CLAUSE_CODE (t))
213      {
214      case OMP_CLAUSE_NOWAIT:
215	fd->have_nowait = true;
216	break;
217      case OMP_CLAUSE_ORDERED:
218	fd->have_ordered = true;
219	break;
220      case OMP_CLAUSE_SCHEDULE:
221	fd->sched_kind = OMP_CLAUSE_SCHEDULE_KIND (t);
222	fd->chunk_size = OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (t);
223	break;
224      default:
225	break;
226      }
227
228  if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
229    gcc_assert (fd->chunk_size == NULL);
230  else if (fd->chunk_size == NULL)
231    {
232      /* We only need to compute a default chunk size for ordered
233	 static loops and dynamic loops.  */
234      if (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC || fd->have_ordered)
235	fd->chunk_size = (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
236			 ? integer_zero_node : integer_one_node;
237    }
238}
239
240
241/* Given two blocks PAR_ENTRY_BB and WS_ENTRY_BB such that WS_ENTRY_BB
242   is the immediate dominator of PAR_ENTRY_BB, return true if there
243   are no data dependencies that would prevent expanding the parallel
244   directive at PAR_ENTRY_BB as a combined parallel+workshare region.
245
246   When expanding a combined parallel+workshare region, the call to
247   the child function may need additional arguments in the case of
248   OMP_FOR regions.  In some cases, these arguments are computed out
249   of variables passed in from the parent to the child via 'struct
250   .omp_data_s'.  For instance:
251
252	#pragma omp parallel for schedule (guided, i * 4)
253	for (j ...)
254
255   Is lowered into:
256
257   	# BLOCK 2 (PAR_ENTRY_BB)
258	.omp_data_o.i = i;
259	#pragma omp parallel [child fn: bar.omp_fn.0 ( ..., D.1598)
260
261	# BLOCK 3 (WS_ENTRY_BB)
262	.omp_data_i = &.omp_data_o;
263	D.1667 = .omp_data_i->i;
264	D.1598 = D.1667 * 4;
265	#pragma omp for schedule (guided, D.1598)
266
267   When we outline the parallel region, the call to the child function
268   'bar.omp_fn.0' will need the value D.1598 in its argument list, but
269   that value is computed *after* the call site.  So, in principle we
270   cannot do the transformation.
271
272   To see whether the code in WS_ENTRY_BB blocks the combined
273   parallel+workshare call, we collect all the variables used in the
274   OMP_FOR header check whether they appear on the LHS of any
275   statement in WS_ENTRY_BB.  If so, then we cannot emit the combined
276   call.
277
278   FIXME.  If we had the SSA form built at this point, we could merely
279   hoist the code in block 3 into block 2 and be done with it.  But at
280   this point we don't have dataflow information and though we could
281   hack something up here, it is really not worth the aggravation.  */
282
283static bool
284workshare_safe_to_combine_p (basic_block par_entry_bb, basic_block ws_entry_bb)
285{
286  struct omp_for_data fd;
287  tree par_stmt, ws_stmt;
288
289  par_stmt = last_stmt (par_entry_bb);
290  ws_stmt = last_stmt (ws_entry_bb);
291
292  if (TREE_CODE (ws_stmt) == OMP_SECTIONS)
293    return true;
294
295  gcc_assert (TREE_CODE (ws_stmt) == OMP_FOR);
296
297  extract_omp_for_data (ws_stmt, &fd);
298
299  /* FIXME.  We give up too easily here.  If any of these arguments
300     are not constants, they will likely involve variables that have
301     been mapped into fields of .omp_data_s for sharing with the child
302     function.  With appropriate data flow, it would be possible to
303     see through this.  */
304  if (!is_gimple_min_invariant (fd.n1)
305      || !is_gimple_min_invariant (fd.n2)
306      || !is_gimple_min_invariant (fd.step)
307      || (fd.chunk_size && !is_gimple_min_invariant (fd.chunk_size)))
308    return false;
309
310  return true;
311}
312
313
314/* Collect additional arguments needed to emit a combined
315   parallel+workshare call.  WS_STMT is the workshare directive being
316   expanded.  */
317
318static tree
319get_ws_args_for (tree ws_stmt)
320{
321  tree t;
322
323  if (TREE_CODE (ws_stmt) == OMP_FOR)
324    {
325      struct omp_for_data fd;
326      tree ws_args;
327
328      extract_omp_for_data (ws_stmt, &fd);
329
330      ws_args = NULL_TREE;
331      if (fd.chunk_size)
332	{
333	  t = fold_convert (long_integer_type_node, fd.chunk_size);
334	  ws_args = tree_cons (NULL, t, ws_args);
335	}
336
337      t = fold_convert (long_integer_type_node, fd.step);
338      ws_args = tree_cons (NULL, t, ws_args);
339
340      t = fold_convert (long_integer_type_node, fd.n2);
341      ws_args = tree_cons (NULL, t, ws_args);
342
343      t = fold_convert (long_integer_type_node, fd.n1);
344      ws_args = tree_cons (NULL, t, ws_args);
345
346      return ws_args;
347    }
348  else if (TREE_CODE (ws_stmt) == OMP_SECTIONS)
349    {
350      basic_block bb = bb_for_stmt (ws_stmt);
351      t = build_int_cst (unsigned_type_node, EDGE_COUNT (bb->succs));
352      t = tree_cons (NULL, t, NULL);
353      return t;
354    }
355
356  gcc_unreachable ();
357}
358
359
360/* Discover whether REGION is a combined parallel+workshare region.  */
361
362static void
363determine_parallel_type (struct omp_region *region)
364{
365  basic_block par_entry_bb, par_exit_bb;
366  basic_block ws_entry_bb, ws_exit_bb;
367
368  if (region == NULL || region->inner == NULL
369      || region->exit == NULL || region->inner->exit == NULL)
370    return;
371
372  /* We only support parallel+for and parallel+sections.  */
373  if (region->type != OMP_PARALLEL
374      || (region->inner->type != OMP_FOR
375	  && region->inner->type != OMP_SECTIONS))
376    return;
377
378  /* Check for perfect nesting PAR_ENTRY_BB -> WS_ENTRY_BB and
379     WS_EXIT_BB -> PAR_EXIT_BB.  */
380  par_entry_bb = region->entry;
381  par_exit_bb = region->exit;
382  ws_entry_bb = region->inner->entry;
383  ws_exit_bb = region->inner->exit;
384
385  if (single_succ (par_entry_bb) == ws_entry_bb
386      && single_succ (ws_exit_bb) == par_exit_bb
387      && workshare_safe_to_combine_p (par_entry_bb, ws_entry_bb)
388      && (OMP_PARALLEL_COMBINED (last_stmt (par_entry_bb))
389	  || (last_and_only_stmt (ws_entry_bb)
390	      && last_and_only_stmt (par_exit_bb))))
391    {
392      tree ws_stmt = last_stmt (ws_entry_bb);
393
394      if (region->inner->type == OMP_FOR)
395	{
396	  /* If this is a combined parallel loop, we need to determine
397	     whether or not to use the combined library calls.  There
398	     are two cases where we do not apply the transformation:
399	     static loops and any kind of ordered loop.  In the first
400	     case, we already open code the loop so there is no need
401	     to do anything else.  In the latter case, the combined
402	     parallel loop call would still need extra synchronization
403	     to implement ordered semantics, so there would not be any
404	     gain in using the combined call.  */
405	  tree clauses = OMP_FOR_CLAUSES (ws_stmt);
406	  tree c = find_omp_clause (clauses, OMP_CLAUSE_SCHEDULE);
407	  if (c == NULL
408	      || OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_STATIC
409	      || find_omp_clause (clauses, OMP_CLAUSE_ORDERED))
410	    {
411	      region->is_combined_parallel = false;
412	      region->inner->is_combined_parallel = false;
413	      return;
414	    }
415	}
416
417      region->is_combined_parallel = true;
418      region->inner->is_combined_parallel = true;
419      region->ws_args = get_ws_args_for (ws_stmt);
420    }
421}
422
423
424/* Return true if EXPR is variable sized.  */
425
426static inline bool
427is_variable_sized (tree expr)
428{
429  return !TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (expr)));
430}
431
432/* Return true if DECL is a reference type.  */
433
434static inline bool
435is_reference (tree decl)
436{
437  return lang_hooks.decls.omp_privatize_by_reference (decl);
438}
439
440/* Lookup variables in the decl or field splay trees.  The "maybe" form
441   allows for the variable form to not have been entered, otherwise we
442   assert that the variable must have been entered.  */
443
444static inline tree
445lookup_decl (tree var, omp_context *ctx)
446{
447  splay_tree_node n;
448  n = splay_tree_lookup (ctx->cb.decl_map, (splay_tree_key) var);
449  return (tree) n->value;
450}
451
452static inline tree
453maybe_lookup_decl (tree var, omp_context *ctx)
454{
455  splay_tree_node n;
456  n = splay_tree_lookup (ctx->cb.decl_map, (splay_tree_key) var);
457  return n ? (tree) n->value : NULL_TREE;
458}
459
460static inline tree
461lookup_field (tree var, omp_context *ctx)
462{
463  splay_tree_node n;
464  n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
465  return (tree) n->value;
466}
467
468static inline tree
469maybe_lookup_field (tree var, omp_context *ctx)
470{
471  splay_tree_node n;
472  n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
473  return n ? (tree) n->value : NULL_TREE;
474}
475
476/* Return true if DECL should be copied by pointer.  SHARED_P is true
477   if DECL is to be shared.  */
478
479static bool
480use_pointer_for_field (tree decl, bool shared_p)
481{
482  if (AGGREGATE_TYPE_P (TREE_TYPE (decl)))
483    return true;
484
485  /* We can only use copy-in/copy-out semantics for shared variables
486     when we know the value is not accessible from an outer scope.  */
487  if (shared_p)
488    {
489      /* ??? Trivially accessible from anywhere.  But why would we even
490	 be passing an address in this case?  Should we simply assert
491	 this to be false, or should we have a cleanup pass that removes
492	 these from the list of mappings?  */
493      if (TREE_STATIC (decl) || DECL_EXTERNAL (decl))
494	return true;
495
496      /* For variables with DECL_HAS_VALUE_EXPR_P set, we cannot tell
497	 without analyzing the expression whether or not its location
498	 is accessible to anyone else.  In the case of nested parallel
499	 regions it certainly may be.  */
500      if (TREE_CODE (decl) != RESULT_DECL && DECL_HAS_VALUE_EXPR_P (decl))
501	return true;
502
503      /* Do not use copy-in/copy-out for variables that have their
504	 address taken.  */
505      if (TREE_ADDRESSABLE (decl))
506	return true;
507    }
508
509  return false;
510}
511
512/* Construct a new automatic decl similar to VAR.  */
513
514static tree
515omp_copy_decl_2 (tree var, tree name, tree type, omp_context *ctx)
516{
517  tree copy = build_decl (VAR_DECL, name, type);
518
519  TREE_ADDRESSABLE (copy) = TREE_ADDRESSABLE (var);
520  DECL_COMPLEX_GIMPLE_REG_P (copy) = DECL_COMPLEX_GIMPLE_REG_P (var);
521  DECL_ARTIFICIAL (copy) = DECL_ARTIFICIAL (var);
522  DECL_IGNORED_P (copy) = DECL_IGNORED_P (var);
523  TREE_USED (copy) = 1;
524  DECL_CONTEXT (copy) = current_function_decl;
525  DECL_SEEN_IN_BIND_EXPR_P (copy) = 1;
526
527  TREE_CHAIN (copy) = ctx->block_vars;
528  ctx->block_vars = copy;
529
530  return copy;
531}
532
533static tree
534omp_copy_decl_1 (tree var, omp_context *ctx)
535{
536  return omp_copy_decl_2 (var, DECL_NAME (var), TREE_TYPE (var), ctx);
537}
538
539/* Build tree nodes to access the field for VAR on the receiver side.  */
540
541static tree
542build_receiver_ref (tree var, bool by_ref, omp_context *ctx)
543{
544  tree x, field = lookup_field (var, ctx);
545
546  /* If the receiver record type was remapped in the child function,
547     remap the field into the new record type.  */
548  x = maybe_lookup_field (field, ctx);
549  if (x != NULL)
550    field = x;
551
552  x = build_fold_indirect_ref (ctx->receiver_decl);
553  x = build3 (COMPONENT_REF, TREE_TYPE (field), x, field, NULL);
554  if (by_ref)
555    x = build_fold_indirect_ref (x);
556
557  return x;
558}
559
560/* Build tree nodes to access VAR in the scope outer to CTX.  In the case
561   of a parallel, this is a component reference; for workshare constructs
562   this is some variable.  */
563
564static tree
565build_outer_var_ref (tree var, omp_context *ctx)
566{
567  tree x;
568
569  if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx)))
570    x = var;
571  else if (is_variable_sized (var))
572    {
573      x = TREE_OPERAND (DECL_VALUE_EXPR (var), 0);
574      x = build_outer_var_ref (x, ctx);
575      x = build_fold_indirect_ref (x);
576    }
577  else if (is_parallel_ctx (ctx))
578    {
579      bool by_ref = use_pointer_for_field (var, false);
580      x = build_receiver_ref (var, by_ref, ctx);
581    }
582  else if (ctx->outer)
583    x = lookup_decl (var, ctx->outer);
584  else if (is_reference (var))
585    /* This can happen with orphaned constructs.  If var is reference, it is
586       possible it is shared and as such valid.  */
587    x = var;
588  else
589    gcc_unreachable ();
590
591  if (is_reference (var))
592    x = build_fold_indirect_ref (x);
593
594  return x;
595}
596
597/* Build tree nodes to access the field for VAR on the sender side.  */
598
599static tree
600build_sender_ref (tree var, omp_context *ctx)
601{
602  tree field = lookup_field (var, ctx);
603  return build3 (COMPONENT_REF, TREE_TYPE (field),
604		 ctx->sender_decl, field, NULL);
605}
606
607/* Add a new field for VAR inside the structure CTX->SENDER_DECL.  */
608
609static void
610install_var_field (tree var, bool by_ref, omp_context *ctx)
611{
612  tree field, type;
613
614  gcc_assert (!splay_tree_lookup (ctx->field_map, (splay_tree_key) var));
615
616  type = TREE_TYPE (var);
617  if (by_ref)
618    type = build_pointer_type (type);
619
620  field = build_decl (FIELD_DECL, DECL_NAME (var), type);
621
622  /* Remember what variable this field was created for.  This does have a
623     side effect of making dwarf2out ignore this member, so for helpful
624     debugging we clear it later in delete_omp_context.  */
625  DECL_ABSTRACT_ORIGIN (field) = var;
626
627  insert_field_into_struct (ctx->record_type, field);
628
629  splay_tree_insert (ctx->field_map, (splay_tree_key) var,
630		     (splay_tree_value) field);
631}
632
633static tree
634install_var_local (tree var, omp_context *ctx)
635{
636  tree new_var = omp_copy_decl_1 (var, ctx);
637  insert_decl_map (&ctx->cb, var, new_var);
638  return new_var;
639}
640
641/* Adjust the replacement for DECL in CTX for the new context.  This means
642   copying the DECL_VALUE_EXPR, and fixing up the type.  */
643
644static void
645fixup_remapped_decl (tree decl, omp_context *ctx, bool private_debug)
646{
647  tree new_decl, size;
648
649  new_decl = lookup_decl (decl, ctx);
650
651  TREE_TYPE (new_decl) = remap_type (TREE_TYPE (decl), &ctx->cb);
652
653  if ((!TREE_CONSTANT (DECL_SIZE (new_decl)) || private_debug)
654      && DECL_HAS_VALUE_EXPR_P (decl))
655    {
656      tree ve = DECL_VALUE_EXPR (decl);
657      walk_tree (&ve, copy_body_r, &ctx->cb, NULL);
658      SET_DECL_VALUE_EXPR (new_decl, ve);
659      DECL_HAS_VALUE_EXPR_P (new_decl) = 1;
660    }
661
662  if (!TREE_CONSTANT (DECL_SIZE (new_decl)))
663    {
664      size = remap_decl (DECL_SIZE (decl), &ctx->cb);
665      if (size == error_mark_node)
666	size = TYPE_SIZE (TREE_TYPE (new_decl));
667      DECL_SIZE (new_decl) = size;
668
669      size = remap_decl (DECL_SIZE_UNIT (decl), &ctx->cb);
670      if (size == error_mark_node)
671	size = TYPE_SIZE_UNIT (TREE_TYPE (new_decl));
672      DECL_SIZE_UNIT (new_decl) = size;
673    }
674}
675
676/* The callback for remap_decl.  Search all containing contexts for a
677   mapping of the variable; this avoids having to duplicate the splay
678   tree ahead of time.  We know a mapping doesn't already exist in the
679   given context.  Create new mappings to implement default semantics.  */
680
681static tree
682omp_copy_decl (tree var, copy_body_data *cb)
683{
684  omp_context *ctx = (omp_context *) cb;
685  tree new_var;
686
687  if (TREE_CODE (var) == LABEL_DECL)
688    {
689      new_var = create_artificial_label ();
690      DECL_CONTEXT (new_var) = current_function_decl;
691      insert_decl_map (&ctx->cb, var, new_var);
692      return new_var;
693    }
694
695  while (!is_parallel_ctx (ctx))
696    {
697      ctx = ctx->outer;
698      if (ctx == NULL)
699	return var;
700      new_var = maybe_lookup_decl (var, ctx);
701      if (new_var)
702	return new_var;
703    }
704
705  if (is_global_var (var) || decl_function_context (var) != ctx->cb.src_fn)
706    return var;
707
708  return error_mark_node;
709}
710
711
712/* Return the parallel region associated with STMT.  */
713
714/* Debugging dumps for parallel regions.  */
715void dump_omp_region (FILE *, struct omp_region *, int);
716void debug_omp_region (struct omp_region *);
717void debug_all_omp_regions (void);
718
719/* Dump the parallel region tree rooted at REGION.  */
720
721void
722dump_omp_region (FILE *file, struct omp_region *region, int indent)
723{
724  fprintf (file, "%*sbb %d: %s\n", indent, "", region->entry->index,
725	   tree_code_name[region->type]);
726
727  if (region->inner)
728    dump_omp_region (file, region->inner, indent + 4);
729
730  if (region->cont)
731    {
732      fprintf (file, "%*sbb %d: OMP_CONTINUE\n", indent, "",
733	       region->cont->index);
734    }
735
736  if (region->exit)
737    fprintf (file, "%*sbb %d: OMP_RETURN\n", indent, "",
738	     region->exit->index);
739  else
740    fprintf (file, "%*s[no exit marker]\n", indent, "");
741
742  if (region->next)
743    dump_omp_region (file, region->next, indent);
744}
745
746void
747debug_omp_region (struct omp_region *region)
748{
749  dump_omp_region (stderr, region, 0);
750}
751
752void
753debug_all_omp_regions (void)
754{
755  dump_omp_region (stderr, root_omp_region, 0);
756}
757
758
759/* Create a new parallel region starting at STMT inside region PARENT.  */
760
761struct omp_region *
762new_omp_region (basic_block bb, enum tree_code type, struct omp_region *parent)
763{
764  struct omp_region *region = xcalloc (1, sizeof (*region));
765
766  region->outer = parent;
767  region->entry = bb;
768  region->type = type;
769
770  if (parent)
771    {
772      /* This is a nested region.  Add it to the list of inner
773	 regions in PARENT.  */
774      region->next = parent->inner;
775      parent->inner = region;
776    }
777  else
778    {
779      /* This is a toplevel region.  Add it to the list of toplevel
780	 regions in ROOT_OMP_REGION.  */
781      region->next = root_omp_region;
782      root_omp_region = region;
783    }
784
785  return region;
786}
787
788/* Release the memory associated with the region tree rooted at REGION.  */
789
790static void
791free_omp_region_1 (struct omp_region *region)
792{
793  struct omp_region *i, *n;
794
795  for (i = region->inner; i ; i = n)
796    {
797      n = i->next;
798      free_omp_region_1 (i);
799    }
800
801  free (region);
802}
803
804/* Release the memory for the entire omp region tree.  */
805
806void
807free_omp_regions (void)
808{
809  struct omp_region *r, *n;
810  for (r = root_omp_region; r ; r = n)
811    {
812      n = r->next;
813      free_omp_region_1 (r);
814    }
815  root_omp_region = NULL;
816}
817
818
819/* Create a new context, with OUTER_CTX being the surrounding context.  */
820
821static omp_context *
822new_omp_context (tree stmt, omp_context *outer_ctx)
823{
824  omp_context *ctx = XCNEW (omp_context);
825
826  splay_tree_insert (all_contexts, (splay_tree_key) stmt,
827		     (splay_tree_value) ctx);
828  ctx->stmt = stmt;
829
830  if (outer_ctx)
831    {
832      ctx->outer = outer_ctx;
833      ctx->cb = outer_ctx->cb;
834      ctx->cb.block = NULL;
835      ctx->depth = outer_ctx->depth + 1;
836    }
837  else
838    {
839      ctx->cb.src_fn = current_function_decl;
840      ctx->cb.dst_fn = current_function_decl;
841      ctx->cb.src_node = cgraph_node (current_function_decl);
842      ctx->cb.dst_node = ctx->cb.src_node;
843      ctx->cb.src_cfun = cfun;
844      ctx->cb.copy_decl = omp_copy_decl;
845      ctx->cb.eh_region = -1;
846      ctx->cb.transform_call_graph_edges = CB_CGE_MOVE;
847      ctx->depth = 1;
848    }
849
850  ctx->cb.decl_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
851
852  return ctx;
853}
854
855/* Destroy a omp_context data structures.  Called through the splay tree
856   value delete callback.  */
857
858static void
859delete_omp_context (splay_tree_value value)
860{
861  omp_context *ctx = (omp_context *) value;
862
863  splay_tree_delete (ctx->cb.decl_map);
864
865  if (ctx->field_map)
866    splay_tree_delete (ctx->field_map);
867
868  /* We hijacked DECL_ABSTRACT_ORIGIN earlier.  We need to clear it before
869     it produces corrupt debug information.  */
870  if (ctx->record_type)
871    {
872      tree t;
873      for (t = TYPE_FIELDS (ctx->record_type); t ; t = TREE_CHAIN (t))
874	DECL_ABSTRACT_ORIGIN (t) = NULL;
875    }
876
877  XDELETE (ctx);
878}
879
880/* Fix up RECEIVER_DECL with a type that has been remapped to the child
881   context.  */
882
883static void
884fixup_child_record_type (omp_context *ctx)
885{
886  tree f, type = ctx->record_type;
887
888  /* ??? It isn't sufficient to just call remap_type here, because
889     variably_modified_type_p doesn't work the way we expect for
890     record types.  Testing each field for whether it needs remapping
891     and creating a new record by hand works, however.  */
892  for (f = TYPE_FIELDS (type); f ; f = TREE_CHAIN (f))
893    if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
894      break;
895  if (f)
896    {
897      tree name, new_fields = NULL;
898
899      type = lang_hooks.types.make_type (RECORD_TYPE);
900      name = DECL_NAME (TYPE_NAME (ctx->record_type));
901      name = build_decl (TYPE_DECL, name, type);
902      TYPE_NAME (type) = name;
903
904      for (f = TYPE_FIELDS (ctx->record_type); f ; f = TREE_CHAIN (f))
905	{
906	  tree new_f = copy_node (f);
907	  DECL_CONTEXT (new_f) = type;
908	  TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &ctx->cb);
909	  TREE_CHAIN (new_f) = new_fields;
910	  new_fields = new_f;
911
912	  /* Arrange to be able to look up the receiver field
913	     given the sender field.  */
914	  splay_tree_insert (ctx->field_map, (splay_tree_key) f,
915			     (splay_tree_value) new_f);
916	}
917      TYPE_FIELDS (type) = nreverse (new_fields);
918      layout_type (type);
919    }
920
921  TREE_TYPE (ctx->receiver_decl) = build_pointer_type (type);
922}
923
924/* Instantiate decls as necessary in CTX to satisfy the data sharing
925   specified by CLAUSES.  */
926
927static void
928scan_sharing_clauses (tree clauses, omp_context *ctx)
929{
930  tree c, decl;
931  bool scan_array_reductions = false;
932
933  for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
934    {
935      bool by_ref;
936
937      switch (OMP_CLAUSE_CODE (c))
938	{
939	case OMP_CLAUSE_PRIVATE:
940	  decl = OMP_CLAUSE_DECL (c);
941	  if (!is_variable_sized (decl))
942	    install_var_local (decl, ctx);
943	  break;
944
945	case OMP_CLAUSE_SHARED:
946	  gcc_assert (is_parallel_ctx (ctx));
947	  decl = OMP_CLAUSE_DECL (c);
948	  gcc_assert (!is_variable_sized (decl));
949	  by_ref = use_pointer_for_field (decl, true);
950	  /* Global variables don't need to be copied,
951	     the receiver side will use them directly.  */
952	  if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
953	    break;
954	  if (! TREE_READONLY (decl)
955	      || TREE_ADDRESSABLE (decl)
956	      || by_ref
957	      || is_reference (decl))
958	    {
959	      install_var_field (decl, by_ref, ctx);
960	      install_var_local (decl, ctx);
961	      break;
962	    }
963	  /* We don't need to copy const scalar vars back.  */
964	  OMP_CLAUSE_SET_CODE (c, OMP_CLAUSE_FIRSTPRIVATE);
965	  goto do_private;
966
967	case OMP_CLAUSE_LASTPRIVATE:
968	  /* Let the corresponding firstprivate clause create
969	     the variable.  */
970	  if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
971	    break;
972	  /* FALLTHRU */
973
974	case OMP_CLAUSE_FIRSTPRIVATE:
975	case OMP_CLAUSE_REDUCTION:
976	  decl = OMP_CLAUSE_DECL (c);
977	do_private:
978	  if (is_variable_sized (decl))
979	    break;
980	  else if (is_parallel_ctx (ctx)
981		   && ! is_global_var (maybe_lookup_decl_in_outer_ctx (decl,
982								       ctx)))
983	    {
984	      by_ref = use_pointer_for_field (decl, false);
985	      install_var_field (decl, by_ref, ctx);
986	    }
987	  install_var_local (decl, ctx);
988	  break;
989
990	case OMP_CLAUSE_COPYPRIVATE:
991	  if (ctx->outer)
992	    scan_omp (&OMP_CLAUSE_DECL (c), ctx->outer);
993	  /* FALLTHRU */
994
995	case OMP_CLAUSE_COPYIN:
996	  decl = OMP_CLAUSE_DECL (c);
997	  by_ref = use_pointer_for_field (decl, false);
998	  install_var_field (decl, by_ref, ctx);
999	  break;
1000
1001	case OMP_CLAUSE_DEFAULT:
1002	  ctx->default_kind = OMP_CLAUSE_DEFAULT_KIND (c);
1003	  break;
1004
1005	case OMP_CLAUSE_IF:
1006	case OMP_CLAUSE_NUM_THREADS:
1007	case OMP_CLAUSE_SCHEDULE:
1008	  if (ctx->outer)
1009	    scan_omp (&OMP_CLAUSE_OPERAND (c, 0), ctx->outer);
1010	  break;
1011
1012	case OMP_CLAUSE_NOWAIT:
1013	case OMP_CLAUSE_ORDERED:
1014	  break;
1015
1016	default:
1017	  gcc_unreachable ();
1018	}
1019    }
1020
1021  for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1022    {
1023      switch (OMP_CLAUSE_CODE (c))
1024	{
1025	case OMP_CLAUSE_LASTPRIVATE:
1026	  /* Let the corresponding firstprivate clause create
1027	     the variable.  */
1028	  if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1029	    break;
1030	  /* FALLTHRU */
1031
1032	case OMP_CLAUSE_PRIVATE:
1033	case OMP_CLAUSE_FIRSTPRIVATE:
1034	case OMP_CLAUSE_REDUCTION:
1035	  decl = OMP_CLAUSE_DECL (c);
1036	  if (is_variable_sized (decl))
1037	    install_var_local (decl, ctx);
1038	  fixup_remapped_decl (decl, ctx,
1039			       OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE
1040			       && OMP_CLAUSE_PRIVATE_DEBUG (c));
1041	  if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1042	      && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1043	    scan_array_reductions = true;
1044	  break;
1045
1046	case OMP_CLAUSE_SHARED:
1047	  decl = OMP_CLAUSE_DECL (c);
1048	  if (! is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1049	    fixup_remapped_decl (decl, ctx, false);
1050	  break;
1051
1052	case OMP_CLAUSE_COPYPRIVATE:
1053	case OMP_CLAUSE_COPYIN:
1054	case OMP_CLAUSE_DEFAULT:
1055	case OMP_CLAUSE_IF:
1056	case OMP_CLAUSE_NUM_THREADS:
1057	case OMP_CLAUSE_SCHEDULE:
1058	case OMP_CLAUSE_NOWAIT:
1059	case OMP_CLAUSE_ORDERED:
1060	  break;
1061
1062	default:
1063	  gcc_unreachable ();
1064	}
1065    }
1066
1067  if (scan_array_reductions)
1068    for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1069      if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1070	  && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1071	{
1072	  scan_omp (&OMP_CLAUSE_REDUCTION_INIT (c), ctx);
1073	  scan_omp (&OMP_CLAUSE_REDUCTION_MERGE (c), ctx);
1074	}
1075}
1076
1077/* Create a new name for omp child function.  Returns an identifier.  */
1078
1079static GTY(()) unsigned int tmp_ompfn_id_num;
1080
1081static tree
1082create_omp_child_function_name (void)
1083{
1084  tree name = DECL_ASSEMBLER_NAME (current_function_decl);
1085  size_t len = IDENTIFIER_LENGTH (name);
1086  char *tmp_name, *prefix;
1087
1088  prefix = alloca (len + sizeof ("_omp_fn"));
1089  memcpy (prefix, IDENTIFIER_POINTER (name), len);
1090  strcpy (prefix + len, "_omp_fn");
1091#ifndef NO_DOT_IN_LABEL
1092  prefix[len] = '.';
1093#elif !defined NO_DOLLAR_IN_LABEL
1094  prefix[len] = '$';
1095#endif
1096  ASM_FORMAT_PRIVATE_NAME (tmp_name, prefix, tmp_ompfn_id_num++);
1097  return get_identifier (tmp_name);
1098}
1099
1100/* Build a decl for the omp child function.  It'll not contain a body
1101   yet, just the bare decl.  */
1102
1103static void
1104create_omp_child_function (omp_context *ctx)
1105{
1106  tree decl, type, name, t;
1107
1108  name = create_omp_child_function_name ();
1109  type = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
1110
1111  decl = build_decl (FUNCTION_DECL, name, type);
1112  decl = lang_hooks.decls.pushdecl (decl);
1113
1114  ctx->cb.dst_fn = decl;
1115
1116  TREE_STATIC (decl) = 1;
1117  TREE_USED (decl) = 1;
1118  DECL_ARTIFICIAL (decl) = 1;
1119  DECL_IGNORED_P (decl) = 0;
1120  TREE_PUBLIC (decl) = 0;
1121  DECL_UNINLINABLE (decl) = 1;
1122  DECL_EXTERNAL (decl) = 0;
1123  DECL_CONTEXT (decl) = NULL_TREE;
1124  DECL_INITIAL (decl) = make_node (BLOCK);
1125
1126  t = build_decl (RESULT_DECL, NULL_TREE, void_type_node);
1127  DECL_ARTIFICIAL (t) = 1;
1128  DECL_IGNORED_P (t) = 1;
1129  DECL_RESULT (decl) = t;
1130
1131  t = build_decl (PARM_DECL, get_identifier (".omp_data_i"), ptr_type_node);
1132  DECL_ARTIFICIAL (t) = 1;
1133  DECL_ARG_TYPE (t) = ptr_type_node;
1134  DECL_CONTEXT (t) = current_function_decl;
1135  TREE_USED (t) = 1;
1136  DECL_ARGUMENTS (decl) = t;
1137  ctx->receiver_decl = t;
1138
1139  /* Allocate memory for the function structure.  The call to
1140     allocate_struct_function clobbers CFUN, so we need to restore
1141     it afterward.  */
1142  allocate_struct_function (decl);
1143  DECL_SOURCE_LOCATION (decl) = EXPR_LOCATION (ctx->stmt);
1144  cfun->function_end_locus = EXPR_LOCATION (ctx->stmt);
1145  cfun = ctx->cb.src_cfun;
1146}
1147
1148
1149/* Scan an OpenMP parallel directive.  */
1150
1151static void
1152scan_omp_parallel (tree *stmt_p, omp_context *outer_ctx)
1153{
1154  omp_context *ctx;
1155  tree name;
1156
1157  /* Ignore parallel directives with empty bodies, unless there
1158     are copyin clauses.  */
1159  if (optimize > 0
1160      && empty_body_p (OMP_PARALLEL_BODY (*stmt_p))
1161      && find_omp_clause (OMP_CLAUSES (*stmt_p), OMP_CLAUSE_COPYIN) == NULL)
1162    {
1163      *stmt_p = build_empty_stmt ();
1164      return;
1165    }
1166
1167  ctx = new_omp_context (*stmt_p, outer_ctx);
1168  if (parallel_nesting_level > 1)
1169    ctx->is_nested = true;
1170  ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
1171  ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
1172  ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
1173  name = create_tmp_var_name (".omp_data_s");
1174  name = build_decl (TYPE_DECL, name, ctx->record_type);
1175  TYPE_NAME (ctx->record_type) = name;
1176  create_omp_child_function (ctx);
1177  OMP_PARALLEL_FN (*stmt_p) = ctx->cb.dst_fn;
1178
1179  scan_sharing_clauses (OMP_PARALLEL_CLAUSES (*stmt_p), ctx);
1180  scan_omp (&OMP_PARALLEL_BODY (*stmt_p), ctx);
1181
1182  if (TYPE_FIELDS (ctx->record_type) == NULL)
1183    ctx->record_type = ctx->receiver_decl = NULL;
1184  else
1185    {
1186      layout_type (ctx->record_type);
1187      fixup_child_record_type (ctx);
1188    }
1189}
1190
1191
1192/* Scan an OpenMP loop directive.  */
1193
1194static void
1195scan_omp_for (tree *stmt_p, omp_context *outer_ctx)
1196{
1197  omp_context *ctx;
1198  tree stmt;
1199
1200  stmt = *stmt_p;
1201  ctx = new_omp_context (stmt, outer_ctx);
1202
1203  scan_sharing_clauses (OMP_FOR_CLAUSES (stmt), ctx);
1204
1205  scan_omp (&OMP_FOR_PRE_BODY (stmt), ctx);
1206  scan_omp (&OMP_FOR_INIT (stmt), ctx);
1207  scan_omp (&OMP_FOR_COND (stmt), ctx);
1208  scan_omp (&OMP_FOR_INCR (stmt), ctx);
1209  scan_omp (&OMP_FOR_BODY (stmt), ctx);
1210}
1211
1212/* Scan an OpenMP sections directive.  */
1213
1214static void
1215scan_omp_sections (tree *stmt_p, omp_context *outer_ctx)
1216{
1217  tree stmt;
1218  omp_context *ctx;
1219
1220  stmt = *stmt_p;
1221  ctx = new_omp_context (stmt, outer_ctx);
1222  scan_sharing_clauses (OMP_SECTIONS_CLAUSES (stmt), ctx);
1223  scan_omp (&OMP_SECTIONS_BODY (stmt), ctx);
1224}
1225
1226/* Scan an OpenMP single directive.  */
1227
1228static void
1229scan_omp_single (tree *stmt_p, omp_context *outer_ctx)
1230{
1231  tree stmt = *stmt_p;
1232  omp_context *ctx;
1233  tree name;
1234
1235  ctx = new_omp_context (stmt, outer_ctx);
1236  ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
1237  ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
1238  name = create_tmp_var_name (".omp_copy_s");
1239  name = build_decl (TYPE_DECL, name, ctx->record_type);
1240  TYPE_NAME (ctx->record_type) = name;
1241
1242  scan_sharing_clauses (OMP_SINGLE_CLAUSES (stmt), ctx);
1243  scan_omp (&OMP_SINGLE_BODY (stmt), ctx);
1244
1245  if (TYPE_FIELDS (ctx->record_type) == NULL)
1246    ctx->record_type = NULL;
1247  else
1248    layout_type (ctx->record_type);
1249}
1250
1251
1252/* Check OpenMP nesting restrictions.  */
1253static void
1254check_omp_nesting_restrictions (tree t, omp_context *ctx)
1255{
1256  switch (TREE_CODE (t))
1257    {
1258    case OMP_FOR:
1259    case OMP_SECTIONS:
1260    case OMP_SINGLE:
1261      for (; ctx != NULL; ctx = ctx->outer)
1262	switch (TREE_CODE (ctx->stmt))
1263	  {
1264	  case OMP_FOR:
1265	  case OMP_SECTIONS:
1266	  case OMP_SINGLE:
1267	  case OMP_ORDERED:
1268	  case OMP_MASTER:
1269	    warning (0, "work-sharing region may not be closely nested inside "
1270			"of work-sharing, critical, ordered or master region");
1271	    return;
1272	  case OMP_PARALLEL:
1273	    return;
1274	  default:
1275	    break;
1276	  }
1277      break;
1278    case OMP_MASTER:
1279      for (; ctx != NULL; ctx = ctx->outer)
1280	switch (TREE_CODE (ctx->stmt))
1281	  {
1282	  case OMP_FOR:
1283	  case OMP_SECTIONS:
1284	  case OMP_SINGLE:
1285	    warning (0, "master region may not be closely nested inside "
1286			"of work-sharing region");
1287	    return;
1288	  case OMP_PARALLEL:
1289	    return;
1290	  default:
1291	    break;
1292	  }
1293      break;
1294    case OMP_ORDERED:
1295      for (; ctx != NULL; ctx = ctx->outer)
1296	switch (TREE_CODE (ctx->stmt))
1297	  {
1298	  case OMP_CRITICAL:
1299	    warning (0, "ordered region may not be closely nested inside "
1300			"of critical region");
1301	    return;
1302	  case OMP_FOR:
1303	    if (find_omp_clause (OMP_CLAUSES (ctx->stmt),
1304				 OMP_CLAUSE_ORDERED) == NULL)
1305	      warning (0, "ordered region must be closely nested inside "
1306			  "a loop region with an ordered clause");
1307	    return;
1308	  case OMP_PARALLEL:
1309	    return;
1310	  default:
1311	    break;
1312	  }
1313      break;
1314    case OMP_CRITICAL:
1315      for (; ctx != NULL; ctx = ctx->outer)
1316	if (TREE_CODE (ctx->stmt) == OMP_CRITICAL
1317	    && OMP_CRITICAL_NAME (t) == OMP_CRITICAL_NAME (ctx->stmt))
1318	  {
1319	    warning (0, "critical region may not be nested inside a critical "
1320			"region with the same name");
1321	    return;
1322	  }
1323      break;
1324    default:
1325      break;
1326    }
1327}
1328
1329
1330/* Callback for walk_stmts used to scan for OpenMP directives at TP.  */
1331
1332static tree
1333scan_omp_1 (tree *tp, int *walk_subtrees, void *data)
1334{
1335  struct walk_stmt_info *wi = data;
1336  omp_context *ctx = wi->info;
1337  tree t = *tp;
1338
1339  if (EXPR_HAS_LOCATION (t))
1340    input_location = EXPR_LOCATION (t);
1341
1342  /* Check the OpenMP nesting restrictions.  */
1343  if (OMP_DIRECTIVE_P (t) && ctx != NULL)
1344    check_omp_nesting_restrictions (t, ctx);
1345
1346  *walk_subtrees = 0;
1347  switch (TREE_CODE (t))
1348    {
1349    case OMP_PARALLEL:
1350      parallel_nesting_level++;
1351      scan_omp_parallel (tp, ctx);
1352      parallel_nesting_level--;
1353      break;
1354
1355    case OMP_FOR:
1356      scan_omp_for (tp, ctx);
1357      break;
1358
1359    case OMP_SECTIONS:
1360      scan_omp_sections (tp, ctx);
1361      break;
1362
1363    case OMP_SINGLE:
1364      scan_omp_single (tp, ctx);
1365      break;
1366
1367    case OMP_SECTION:
1368    case OMP_MASTER:
1369    case OMP_ORDERED:
1370    case OMP_CRITICAL:
1371      ctx = new_omp_context (*tp, ctx);
1372      scan_omp (&OMP_BODY (*tp), ctx);
1373      break;
1374
1375    case BIND_EXPR:
1376      {
1377	tree var;
1378	*walk_subtrees = 1;
1379
1380	for (var = BIND_EXPR_VARS (t); var ; var = TREE_CHAIN (var))
1381	  insert_decl_map (&ctx->cb, var, var);
1382      }
1383      break;
1384
1385    case VAR_DECL:
1386    case PARM_DECL:
1387    case LABEL_DECL:
1388    case RESULT_DECL:
1389      if (ctx)
1390	*tp = remap_decl (t, &ctx->cb);
1391      break;
1392
1393    default:
1394      if (ctx && TYPE_P (t))
1395	*tp = remap_type (t, &ctx->cb);
1396      else if (!DECL_P (t))
1397	*walk_subtrees = 1;
1398      break;
1399    }
1400
1401  return NULL_TREE;
1402}
1403
1404
1405/* Scan all the statements starting at STMT_P.  CTX contains context
1406   information about the OpenMP directives and clauses found during
1407   the scan.  */
1408
1409static void
1410scan_omp (tree *stmt_p, omp_context *ctx)
1411{
1412  location_t saved_location;
1413  struct walk_stmt_info wi;
1414
1415  memset (&wi, 0, sizeof (wi));
1416  wi.callback = scan_omp_1;
1417  wi.info = ctx;
1418  wi.want_bind_expr = (ctx != NULL);
1419  wi.want_locations = true;
1420
1421  saved_location = input_location;
1422  walk_stmts (&wi, stmt_p);
1423  input_location = saved_location;
1424}
1425
1426/* Re-gimplification and code generation routines.  */
1427
1428/* Build a call to GOMP_barrier.  */
1429
1430static void
1431build_omp_barrier (tree *stmt_list)
1432{
1433  tree t;
1434
1435  t = built_in_decls[BUILT_IN_GOMP_BARRIER];
1436  t = build_function_call_expr (t, NULL);
1437  gimplify_and_add (t, stmt_list);
1438}
1439
1440/* If a context was created for STMT when it was scanned, return it.  */
1441
1442static omp_context *
1443maybe_lookup_ctx (tree stmt)
1444{
1445  splay_tree_node n;
1446  n = splay_tree_lookup (all_contexts, (splay_tree_key) stmt);
1447  return n ? (omp_context *) n->value : NULL;
1448}
1449
1450
1451/* Find the mapping for DECL in CTX or the immediately enclosing
1452   context that has a mapping for DECL.
1453
1454   If CTX is a nested parallel directive, we may have to use the decl
1455   mappings created in CTX's parent context.  Suppose that we have the
1456   following parallel nesting (variable UIDs showed for clarity):
1457
1458	iD.1562 = 0;
1459     	#omp parallel shared(iD.1562)		-> outer parallel
1460	  iD.1562 = iD.1562 + 1;
1461
1462	  #omp parallel shared (iD.1562)	-> inner parallel
1463	     iD.1562 = iD.1562 - 1;
1464
1465   Each parallel structure will create a distinct .omp_data_s structure
1466   for copying iD.1562 in/out of the directive:
1467
1468  	outer parallel		.omp_data_s.1.i -> iD.1562
1469	inner parallel		.omp_data_s.2.i -> iD.1562
1470
1471   A shared variable mapping will produce a copy-out operation before
1472   the parallel directive and a copy-in operation after it.  So, in
1473   this case we would have:
1474
1475  	iD.1562 = 0;
1476	.omp_data_o.1.i = iD.1562;
1477	#omp parallel shared(iD.1562)		-> outer parallel
1478	  .omp_data_i.1 = &.omp_data_o.1
1479	  .omp_data_i.1->i = .omp_data_i.1->i + 1;
1480
1481	  .omp_data_o.2.i = iD.1562;		-> **
1482	  #omp parallel shared(iD.1562)		-> inner parallel
1483	    .omp_data_i.2 = &.omp_data_o.2
1484	    .omp_data_i.2->i = .omp_data_i.2->i - 1;
1485
1486
1487    ** This is a problem.  The symbol iD.1562 cannot be referenced
1488       inside the body of the outer parallel region.  But since we are
1489       emitting this copy operation while expanding the inner parallel
1490       directive, we need to access the CTX structure of the outer
1491       parallel directive to get the correct mapping:
1492
1493	  .omp_data_o.2.i = .omp_data_i.1->i
1494
1495    Since there may be other workshare or parallel directives enclosing
1496    the parallel directive, it may be necessary to walk up the context
1497    parent chain.  This is not a problem in general because nested
1498    parallelism happens only rarely.  */
1499
1500static tree
1501lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
1502{
1503  tree t;
1504  omp_context *up;
1505
1506  gcc_assert (ctx->is_nested);
1507
1508  for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
1509    t = maybe_lookup_decl (decl, up);
1510
1511  gcc_assert (t || is_global_var (decl));
1512
1513  return t ? t : decl;
1514}
1515
1516
1517/* Similar to lookup_decl_in_outer_ctx, but return DECL if not found
1518   in outer contexts.  */
1519
1520static tree
1521maybe_lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
1522{
1523  tree t = NULL;
1524  omp_context *up;
1525
1526  if (ctx->is_nested)
1527    for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
1528      t = maybe_lookup_decl (decl, up);
1529
1530  return t ? t : decl;
1531}
1532
1533
1534/* Construct the initialization value for reduction CLAUSE.  */
1535
1536tree
1537omp_reduction_init (tree clause, tree type)
1538{
1539  switch (OMP_CLAUSE_REDUCTION_CODE (clause))
1540    {
1541    case PLUS_EXPR:
1542    case MINUS_EXPR:
1543    case BIT_IOR_EXPR:
1544    case BIT_XOR_EXPR:
1545    case TRUTH_OR_EXPR:
1546    case TRUTH_ORIF_EXPR:
1547    case TRUTH_XOR_EXPR:
1548    case NE_EXPR:
1549      return fold_convert (type, integer_zero_node);
1550
1551    case MULT_EXPR:
1552    case TRUTH_AND_EXPR:
1553    case TRUTH_ANDIF_EXPR:
1554    case EQ_EXPR:
1555      return fold_convert (type, integer_one_node);
1556
1557    case BIT_AND_EXPR:
1558      return fold_convert (type, integer_minus_one_node);
1559
1560    case MAX_EXPR:
1561      if (SCALAR_FLOAT_TYPE_P (type))
1562	{
1563	  REAL_VALUE_TYPE max, min;
1564	  if (HONOR_INFINITIES (TYPE_MODE (type)))
1565	    {
1566	      real_inf (&max);
1567	      real_arithmetic (&min, NEGATE_EXPR, &max, NULL);
1568	    }
1569	  else
1570	    real_maxval (&min, 1, TYPE_MODE (type));
1571	  return build_real (type, min);
1572	}
1573      else
1574	{
1575	  gcc_assert (INTEGRAL_TYPE_P (type));
1576	  return TYPE_MIN_VALUE (type);
1577	}
1578
1579    case MIN_EXPR:
1580      if (SCALAR_FLOAT_TYPE_P (type))
1581	{
1582	  REAL_VALUE_TYPE max;
1583	  if (HONOR_INFINITIES (TYPE_MODE (type)))
1584	    real_inf (&max);
1585	  else
1586	    real_maxval (&max, 0, TYPE_MODE (type));
1587	  return build_real (type, max);
1588	}
1589      else
1590	{
1591	  gcc_assert (INTEGRAL_TYPE_P (type));
1592	  return TYPE_MAX_VALUE (type);
1593	}
1594
1595    default:
1596      gcc_unreachable ();
1597    }
1598}
1599
1600/* Generate code to implement the input clauses, FIRSTPRIVATE and COPYIN,
1601   from the receiver (aka child) side and initializers for REFERENCE_TYPE
1602   private variables.  Initialization statements go in ILIST, while calls
1603   to destructors go in DLIST.  */
1604
1605static void
1606lower_rec_input_clauses (tree clauses, tree *ilist, tree *dlist,
1607			 omp_context *ctx)
1608{
1609  tree_stmt_iterator diter;
1610  tree c, dtor, copyin_seq, x, args, ptr;
1611  bool copyin_by_ref = false;
1612  bool lastprivate_firstprivate = false;
1613  int pass;
1614
1615  *dlist = alloc_stmt_list ();
1616  diter = tsi_start (*dlist);
1617  copyin_seq = NULL;
1618
1619  /* Do all the fixed sized types in the first pass, and the variable sized
1620     types in the second pass.  This makes sure that the scalar arguments to
1621     the variable sized types are processed before we use them in the
1622     variable sized operations.  */
1623  for (pass = 0; pass < 2; ++pass)
1624    {
1625      for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
1626	{
1627	  enum omp_clause_code c_kind = OMP_CLAUSE_CODE (c);
1628	  tree var, new_var;
1629	  bool by_ref;
1630
1631	  switch (c_kind)
1632	    {
1633	    case OMP_CLAUSE_PRIVATE:
1634	      if (OMP_CLAUSE_PRIVATE_DEBUG (c))
1635		continue;
1636	      break;
1637	    case OMP_CLAUSE_SHARED:
1638	      if (maybe_lookup_decl (OMP_CLAUSE_DECL (c), ctx) == NULL)
1639		{
1640		  gcc_assert (is_global_var (OMP_CLAUSE_DECL (c)));
1641		  continue;
1642		}
1643	    case OMP_CLAUSE_FIRSTPRIVATE:
1644	    case OMP_CLAUSE_COPYIN:
1645	    case OMP_CLAUSE_REDUCTION:
1646	      break;
1647	    case OMP_CLAUSE_LASTPRIVATE:
1648	      if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1649		{
1650		  lastprivate_firstprivate = true;
1651		  if (pass != 0)
1652		    continue;
1653		}
1654	      break;
1655	    default:
1656	      continue;
1657	    }
1658
1659	  new_var = var = OMP_CLAUSE_DECL (c);
1660	  if (c_kind != OMP_CLAUSE_COPYIN)
1661	    new_var = lookup_decl (var, ctx);
1662
1663	  if (c_kind == OMP_CLAUSE_SHARED || c_kind == OMP_CLAUSE_COPYIN)
1664	    {
1665	      if (pass != 0)
1666		continue;
1667	    }
1668	  else if (is_variable_sized (var))
1669	    {
1670	      /* For variable sized types, we need to allocate the
1671		 actual storage here.  Call alloca and store the
1672		 result in the pointer decl that we created elsewhere.  */
1673	      if (pass == 0)
1674		continue;
1675
1676	      ptr = DECL_VALUE_EXPR (new_var);
1677	      gcc_assert (TREE_CODE (ptr) == INDIRECT_REF);
1678	      ptr = TREE_OPERAND (ptr, 0);
1679	      gcc_assert (DECL_P (ptr));
1680
1681	      x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
1682	      args = tree_cons (NULL, x, NULL);
1683	      x = built_in_decls[BUILT_IN_ALLOCA];
1684	      x = build_function_call_expr (x, args);
1685	      x = fold_convert (TREE_TYPE (ptr), x);
1686	      x = build2 (MODIFY_EXPR, void_type_node, ptr, x);
1687	      gimplify_and_add (x, ilist);
1688	    }
1689	  else if (is_reference (var))
1690	    {
1691	      /* For references that are being privatized for Fortran,
1692		 allocate new backing storage for the new pointer
1693		 variable.  This allows us to avoid changing all the
1694		 code that expects a pointer to something that expects
1695		 a direct variable.  Note that this doesn't apply to
1696		 C++, since reference types are disallowed in data
1697		 sharing clauses there, except for NRV optimized
1698		 return values.  */
1699	      if (pass == 0)
1700		continue;
1701
1702	      x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
1703	      if (TREE_CONSTANT (x))
1704		{
1705		  const char *name = NULL;
1706		  if (DECL_NAME (var))
1707		    name = IDENTIFIER_POINTER (DECL_NAME (new_var));
1708
1709		  x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)),
1710					  name);
1711		  gimple_add_tmp_var (x);
1712		  x = build_fold_addr_expr_with_type (x, TREE_TYPE (new_var));
1713		}
1714	      else
1715		{
1716		  args = tree_cons (NULL, x, NULL);
1717		  x = built_in_decls[BUILT_IN_ALLOCA];
1718		  x = build_function_call_expr (x, args);
1719		  x = fold_convert (TREE_TYPE (new_var), x);
1720		}
1721
1722	      x = build2 (MODIFY_EXPR, void_type_node, new_var, x);
1723	      gimplify_and_add (x, ilist);
1724
1725	      new_var = build_fold_indirect_ref (new_var);
1726	    }
1727	  else if (c_kind == OMP_CLAUSE_REDUCTION
1728		   && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1729	    {
1730	      if (pass == 0)
1731		continue;
1732	    }
1733	  else if (pass != 0)
1734	    continue;
1735
1736	  switch (OMP_CLAUSE_CODE (c))
1737	    {
1738	    case OMP_CLAUSE_SHARED:
1739	      /* Shared global vars are just accessed directly.  */
1740	      if (is_global_var (new_var))
1741		break;
1742	      /* Set up the DECL_VALUE_EXPR for shared variables now.  This
1743		 needs to be delayed until after fixup_child_record_type so
1744		 that we get the correct type during the dereference.  */
1745	      by_ref = use_pointer_for_field (var, true);
1746	      x = build_receiver_ref (var, by_ref, ctx);
1747	      SET_DECL_VALUE_EXPR (new_var, x);
1748	      DECL_HAS_VALUE_EXPR_P (new_var) = 1;
1749
1750	      /* ??? If VAR is not passed by reference, and the variable
1751		 hasn't been initialized yet, then we'll get a warning for
1752		 the store into the omp_data_s structure.  Ideally, we'd be
1753		 able to notice this and not store anything at all, but
1754		 we're generating code too early.  Suppress the warning.  */
1755	      if (!by_ref)
1756		TREE_NO_WARNING (var) = 1;
1757	      break;
1758
1759	    case OMP_CLAUSE_LASTPRIVATE:
1760	      if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1761		break;
1762	      /* FALLTHRU */
1763
1764	    case OMP_CLAUSE_PRIVATE:
1765	      x = lang_hooks.decls.omp_clause_default_ctor (c, new_var);
1766	      if (x)
1767		gimplify_and_add (x, ilist);
1768	      /* FALLTHRU */
1769
1770	    do_dtor:
1771	      x = lang_hooks.decls.omp_clause_dtor (c, new_var);
1772	      if (x)
1773		{
1774		  dtor = x;
1775		  gimplify_stmt (&dtor);
1776		  tsi_link_before (&diter, dtor, TSI_SAME_STMT);
1777		}
1778	      break;
1779
1780	    case OMP_CLAUSE_FIRSTPRIVATE:
1781	      x = build_outer_var_ref (var, ctx);
1782	      x = lang_hooks.decls.omp_clause_copy_ctor (c, new_var, x);
1783	      gimplify_and_add (x, ilist);
1784	      goto do_dtor;
1785	      break;
1786
1787	    case OMP_CLAUSE_COPYIN:
1788	      by_ref = use_pointer_for_field (var, false);
1789	      x = build_receiver_ref (var, by_ref, ctx);
1790	      x = lang_hooks.decls.omp_clause_assign_op (c, new_var, x);
1791	      append_to_statement_list (x, &copyin_seq);
1792	      copyin_by_ref |= by_ref;
1793	      break;
1794
1795	    case OMP_CLAUSE_REDUCTION:
1796	      if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1797		{
1798		  gimplify_and_add (OMP_CLAUSE_REDUCTION_INIT (c), ilist);
1799		  OMP_CLAUSE_REDUCTION_INIT (c) = NULL;
1800		}
1801	      else
1802		{
1803		  x = omp_reduction_init (c, TREE_TYPE (new_var));
1804		  gcc_assert (TREE_CODE (TREE_TYPE (new_var)) != ARRAY_TYPE);
1805		  x = build2 (MODIFY_EXPR, void_type_node, new_var, x);
1806		  gimplify_and_add (x, ilist);
1807		}
1808	      break;
1809
1810	    default:
1811	      gcc_unreachable ();
1812	    }
1813	}
1814    }
1815
1816  /* The copyin sequence is not to be executed by the main thread, since
1817     that would result in self-copies.  Perhaps not visible to scalars,
1818     but it certainly is to C++ operator=.  */
1819  if (copyin_seq)
1820    {
1821      x = built_in_decls[BUILT_IN_OMP_GET_THREAD_NUM];
1822      x = build_function_call_expr (x, NULL);
1823      x = build2 (NE_EXPR, boolean_type_node, x,
1824		  build_int_cst (TREE_TYPE (x), 0));
1825      x = build3 (COND_EXPR, void_type_node, x, copyin_seq, NULL);
1826      gimplify_and_add (x, ilist);
1827    }
1828
1829  /* If any copyin variable is passed by reference, we must ensure the
1830     master thread doesn't modify it before it is copied over in all
1831     threads.  Similarly for variables in both firstprivate and
1832     lastprivate clauses we need to ensure the lastprivate copying
1833     happens after firstprivate copying in all threads.  */
1834  if (copyin_by_ref || lastprivate_firstprivate)
1835    build_omp_barrier (ilist);
1836}
1837
1838
1839/* Generate code to implement the LASTPRIVATE clauses.  This is used for
1840   both parallel and workshare constructs.  PREDICATE may be NULL if it's
1841   always true.   */
1842
1843static void
1844lower_lastprivate_clauses (tree clauses, tree predicate, tree *stmt_list,
1845			    omp_context *ctx)
1846{
1847  tree sub_list, x, c;
1848
1849  /* Early exit if there are no lastprivate clauses.  */
1850  clauses = find_omp_clause (clauses, OMP_CLAUSE_LASTPRIVATE);
1851  if (clauses == NULL)
1852    {
1853      /* If this was a workshare clause, see if it had been combined
1854	 with its parallel.  In that case, look for the clauses on the
1855	 parallel statement itself.  */
1856      if (is_parallel_ctx (ctx))
1857	return;
1858
1859      ctx = ctx->outer;
1860      if (ctx == NULL || !is_parallel_ctx (ctx))
1861	return;
1862
1863      clauses = find_omp_clause (OMP_PARALLEL_CLAUSES (ctx->stmt),
1864				 OMP_CLAUSE_LASTPRIVATE);
1865      if (clauses == NULL)
1866	return;
1867    }
1868
1869  sub_list = alloc_stmt_list ();
1870
1871  for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
1872    {
1873      tree var, new_var;
1874
1875      if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_LASTPRIVATE)
1876	continue;
1877
1878      var = OMP_CLAUSE_DECL (c);
1879      new_var = lookup_decl (var, ctx);
1880
1881      x = build_outer_var_ref (var, ctx);
1882      if (is_reference (var))
1883	new_var = build_fold_indirect_ref (new_var);
1884      x = lang_hooks.decls.omp_clause_assign_op (c, x, new_var);
1885      append_to_statement_list (x, &sub_list);
1886    }
1887
1888  if (predicate)
1889    x = build3 (COND_EXPR, void_type_node, predicate, sub_list, NULL);
1890  else
1891    x = sub_list;
1892
1893  gimplify_and_add (x, stmt_list);
1894}
1895
1896
1897/* Generate code to implement the REDUCTION clauses.  */
1898
1899static void
1900lower_reduction_clauses (tree clauses, tree *stmt_list, omp_context *ctx)
1901{
1902  tree sub_list = NULL, x, c;
1903  int count = 0;
1904
1905  /* First see if there is exactly one reduction clause.  Use OMP_ATOMIC
1906     update in that case, otherwise use a lock.  */
1907  for (c = clauses; c && count < 2; c = OMP_CLAUSE_CHAIN (c))
1908    if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
1909      {
1910	if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1911	  {
1912	    /* Never use OMP_ATOMIC for array reductions.  */
1913	    count = -1;
1914	    break;
1915	  }
1916	count++;
1917      }
1918
1919  if (count == 0)
1920    return;
1921
1922  for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
1923    {
1924      tree var, ref, new_var;
1925      enum tree_code code;
1926
1927      if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
1928	continue;
1929
1930      var = OMP_CLAUSE_DECL (c);
1931      new_var = lookup_decl (var, ctx);
1932      if (is_reference (var))
1933	new_var = build_fold_indirect_ref (new_var);
1934      ref = build_outer_var_ref (var, ctx);
1935      code = OMP_CLAUSE_REDUCTION_CODE (c);
1936
1937      /* reduction(-:var) sums up the partial results, so it acts
1938	 identically to reduction(+:var).  */
1939      if (code == MINUS_EXPR)
1940        code = PLUS_EXPR;
1941
1942      if (count == 1)
1943	{
1944	  tree addr = build_fold_addr_expr (ref);
1945
1946	  addr = save_expr (addr);
1947	  ref = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (addr)), addr);
1948	  x = fold_build2 (code, TREE_TYPE (ref), ref, new_var);
1949	  x = build2 (OMP_ATOMIC, void_type_node, addr, x);
1950	  gimplify_and_add (x, stmt_list);
1951	  return;
1952	}
1953
1954      if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1955	{
1956	  tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
1957
1958	  if (is_reference (var))
1959	    ref = build_fold_addr_expr (ref);
1960	  SET_DECL_VALUE_EXPR (placeholder, ref);
1961	  DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
1962	  gimplify_and_add (OMP_CLAUSE_REDUCTION_MERGE (c), &sub_list);
1963	  OMP_CLAUSE_REDUCTION_MERGE (c) = NULL;
1964	  OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
1965	}
1966      else
1967	{
1968	  x = build2 (code, TREE_TYPE (ref), ref, new_var);
1969	  ref = build_outer_var_ref (var, ctx);
1970	  x = build2 (MODIFY_EXPR, void_type_node, ref, x);
1971	  append_to_statement_list (x, &sub_list);
1972	}
1973    }
1974
1975  x = built_in_decls[BUILT_IN_GOMP_ATOMIC_START];
1976  x = build_function_call_expr (x, NULL);
1977  gimplify_and_add (x, stmt_list);
1978
1979  gimplify_and_add (sub_list, stmt_list);
1980
1981  x = built_in_decls[BUILT_IN_GOMP_ATOMIC_END];
1982  x = build_function_call_expr (x, NULL);
1983  gimplify_and_add (x, stmt_list);
1984}
1985
1986
1987/* Generate code to implement the COPYPRIVATE clauses.  */
1988
1989static void
1990lower_copyprivate_clauses (tree clauses, tree *slist, tree *rlist,
1991			    omp_context *ctx)
1992{
1993  tree c;
1994
1995  for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
1996    {
1997      tree var, ref, x;
1998      bool by_ref;
1999
2000      if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYPRIVATE)
2001	continue;
2002
2003      var = OMP_CLAUSE_DECL (c);
2004      by_ref = use_pointer_for_field (var, false);
2005
2006      ref = build_sender_ref (var, ctx);
2007      x = (ctx->is_nested) ? lookup_decl_in_outer_ctx (var, ctx) : var;
2008      x = by_ref ? build_fold_addr_expr (x) : x;
2009      x = build2 (MODIFY_EXPR, void_type_node, ref, x);
2010      gimplify_and_add (x, slist);
2011
2012      ref = build_receiver_ref (var, by_ref, ctx);
2013      if (is_reference (var))
2014	{
2015	  ref = build_fold_indirect_ref (ref);
2016	  var = build_fold_indirect_ref (var);
2017	}
2018      x = lang_hooks.decls.omp_clause_assign_op (c, var, ref);
2019      gimplify_and_add (x, rlist);
2020    }
2021}
2022
2023
2024/* Generate code to implement the clauses, FIRSTPRIVATE, COPYIN, LASTPRIVATE,
2025   and REDUCTION from the sender (aka parent) side.  */
2026
2027static void
2028lower_send_clauses (tree clauses, tree *ilist, tree *olist, omp_context *ctx)
2029{
2030  tree c;
2031
2032  for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
2033    {
2034      tree val, ref, x, var;
2035      bool by_ref, do_in = false, do_out = false;
2036
2037      switch (OMP_CLAUSE_CODE (c))
2038	{
2039	case OMP_CLAUSE_FIRSTPRIVATE:
2040	case OMP_CLAUSE_COPYIN:
2041	case OMP_CLAUSE_LASTPRIVATE:
2042	case OMP_CLAUSE_REDUCTION:
2043	  break;
2044	default:
2045	  continue;
2046	}
2047
2048      var = val = OMP_CLAUSE_DECL (c);
2049      if (ctx->is_nested)
2050	var = lookup_decl_in_outer_ctx (val, ctx);
2051
2052      if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYIN
2053	  && is_global_var (var))
2054	continue;
2055      if (is_variable_sized (val))
2056	continue;
2057      by_ref = use_pointer_for_field (val, false);
2058
2059      switch (OMP_CLAUSE_CODE (c))
2060	{
2061	case OMP_CLAUSE_FIRSTPRIVATE:
2062	case OMP_CLAUSE_COPYIN:
2063	  do_in = true;
2064	  break;
2065
2066	case OMP_CLAUSE_LASTPRIVATE:
2067	  if (by_ref || is_reference (val))
2068	    {
2069	      if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
2070		continue;
2071	      do_in = true;
2072	    }
2073	  else
2074	    do_out = true;
2075	  break;
2076
2077	case OMP_CLAUSE_REDUCTION:
2078	  do_in = true;
2079	  do_out = !(by_ref || is_reference (val));
2080	  break;
2081
2082	default:
2083	  gcc_unreachable ();
2084	}
2085
2086      if (do_in)
2087	{
2088	  ref = build_sender_ref (val, ctx);
2089	  x = by_ref ? build_fold_addr_expr (var) : var;
2090	  x = build2 (MODIFY_EXPR, void_type_node, ref, x);
2091	  gimplify_and_add (x, ilist);
2092	}
2093
2094      if (do_out)
2095	{
2096	  ref = build_sender_ref (val, ctx);
2097	  x = build2 (MODIFY_EXPR, void_type_node, var, ref);
2098	  gimplify_and_add (x, olist);
2099	}
2100    }
2101}
2102
2103/* Generate code to implement SHARED from the sender (aka parent) side.
2104   This is trickier, since OMP_PARALLEL_CLAUSES doesn't list things that
2105   got automatically shared.  */
2106
2107static void
2108lower_send_shared_vars (tree *ilist, tree *olist, omp_context *ctx)
2109{
2110  tree var, ovar, nvar, f, x;
2111
2112  if (ctx->record_type == NULL)
2113    return;
2114
2115  for (f = TYPE_FIELDS (ctx->record_type); f ; f = TREE_CHAIN (f))
2116    {
2117      ovar = DECL_ABSTRACT_ORIGIN (f);
2118      nvar = maybe_lookup_decl (ovar, ctx);
2119      if (!nvar || !DECL_HAS_VALUE_EXPR_P (nvar))
2120	continue;
2121
2122      var = ovar;
2123
2124      /* If CTX is a nested parallel directive.  Find the immediately
2125	 enclosing parallel or workshare construct that contains a
2126	 mapping for OVAR.  */
2127      if (ctx->is_nested)
2128	var = lookup_decl_in_outer_ctx (ovar, ctx);
2129
2130      if (use_pointer_for_field (ovar, true))
2131	{
2132	  x = build_sender_ref (ovar, ctx);
2133	  var = build_fold_addr_expr (var);
2134	  x = build2 (MODIFY_EXPR, void_type_node, x, var);
2135	  gimplify_and_add (x, ilist);
2136	}
2137      else
2138	{
2139	  x = build_sender_ref (ovar, ctx);
2140	  x = build2 (MODIFY_EXPR, void_type_node, x, var);
2141	  gimplify_and_add (x, ilist);
2142
2143	  x = build_sender_ref (ovar, ctx);
2144	  x = build2 (MODIFY_EXPR, void_type_node, var, x);
2145	  gimplify_and_add (x, olist);
2146	}
2147    }
2148}
2149
2150/* Build the function calls to GOMP_parallel_start etc to actually
2151   generate the parallel operation.  REGION is the parallel region
2152   being expanded.  BB is the block where to insert the code.  WS_ARGS
2153   will be set if this is a call to a combined parallel+workshare
2154   construct, it contains the list of additional arguments needed by
2155   the workshare construct.  */
2156
2157static void
2158expand_parallel_call (struct omp_region *region, basic_block bb,
2159		      tree entry_stmt, tree ws_args)
2160{
2161  tree t, args, val, cond, c, list, clauses;
2162  block_stmt_iterator si;
2163  int start_ix;
2164
2165  clauses = OMP_PARALLEL_CLAUSES (entry_stmt);
2166  push_gimplify_context ();
2167
2168  /* Determine what flavor of GOMP_parallel_start we will be
2169     emitting.  */
2170  start_ix = BUILT_IN_GOMP_PARALLEL_START;
2171  if (is_combined_parallel (region))
2172    {
2173      switch (region->inner->type)
2174	{
2175	case OMP_FOR:
2176	  start_ix = BUILT_IN_GOMP_PARALLEL_LOOP_STATIC_START
2177		     + region->inner->sched_kind;
2178	  break;
2179	case OMP_SECTIONS:
2180	  start_ix = BUILT_IN_GOMP_PARALLEL_SECTIONS_START;
2181	  break;
2182	default:
2183	  gcc_unreachable ();
2184	}
2185    }
2186
2187  /* By default, the value of NUM_THREADS is zero (selected at run time)
2188     and there is no conditional.  */
2189  cond = NULL_TREE;
2190  val = build_int_cst (unsigned_type_node, 0);
2191
2192  c = find_omp_clause (clauses, OMP_CLAUSE_IF);
2193  if (c)
2194    cond = OMP_CLAUSE_IF_EXPR (c);
2195
2196  c = find_omp_clause (clauses, OMP_CLAUSE_NUM_THREADS);
2197  if (c)
2198    val = OMP_CLAUSE_NUM_THREADS_EXPR (c);
2199
2200  /* Ensure 'val' is of the correct type.  */
2201  val = fold_convert (unsigned_type_node, val);
2202
2203  /* If we found the clause 'if (cond)', build either
2204     (cond != 0) or (cond ? val : 1u).  */
2205  if (cond)
2206    {
2207      block_stmt_iterator si;
2208
2209      cond = gimple_boolify (cond);
2210
2211      if (integer_zerop (val))
2212	val = build2 (EQ_EXPR, unsigned_type_node, cond,
2213		      build_int_cst (TREE_TYPE (cond), 0));
2214      else
2215	{
2216	  basic_block cond_bb, then_bb, else_bb;
2217	  edge e;
2218	  tree t, then_lab, else_lab, tmp;
2219
2220	  tmp = create_tmp_var (TREE_TYPE (val), NULL);
2221	  e = split_block (bb, NULL);
2222	  cond_bb = e->src;
2223	  bb = e->dest;
2224	  remove_edge (e);
2225
2226	  then_bb = create_empty_bb (cond_bb);
2227	  else_bb = create_empty_bb (then_bb);
2228	  then_lab = create_artificial_label ();
2229	  else_lab = create_artificial_label ();
2230
2231	  t = build3 (COND_EXPR, void_type_node,
2232		      cond,
2233		      build_and_jump (&then_lab),
2234		      build_and_jump (&else_lab));
2235
2236	  si = bsi_start (cond_bb);
2237	  bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
2238
2239	  si = bsi_start (then_bb);
2240	  t = build1 (LABEL_EXPR, void_type_node, then_lab);
2241	  bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
2242	  t = build2 (MODIFY_EXPR, void_type_node, tmp, val);
2243	  bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
2244
2245	  si = bsi_start (else_bb);
2246	  t = build1 (LABEL_EXPR, void_type_node, else_lab);
2247	  bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
2248	  t = build2 (MODIFY_EXPR, void_type_node, tmp,
2249	              build_int_cst (unsigned_type_node, 1));
2250	  bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
2251
2252	  make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
2253	  make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
2254	  make_edge (then_bb, bb, EDGE_FALLTHRU);
2255	  make_edge (else_bb, bb, EDGE_FALLTHRU);
2256
2257	  val = tmp;
2258	}
2259
2260      list = NULL_TREE;
2261      val = get_formal_tmp_var (val, &list);
2262      si = bsi_start (bb);
2263      bsi_insert_after (&si, list, BSI_CONTINUE_LINKING);
2264    }
2265
2266  list = NULL_TREE;
2267  args = tree_cons (NULL, val, NULL);
2268  t = OMP_PARALLEL_DATA_ARG (entry_stmt);
2269  if (t == NULL)
2270    t = null_pointer_node;
2271  else
2272    t = build_fold_addr_expr (t);
2273  args = tree_cons (NULL, t, args);
2274  t = build_fold_addr_expr (OMP_PARALLEL_FN (entry_stmt));
2275  args = tree_cons (NULL, t, args);
2276
2277  if (ws_args)
2278    args = chainon (args, ws_args);
2279
2280  t = built_in_decls[start_ix];
2281  t = build_function_call_expr (t, args);
2282  gimplify_and_add (t, &list);
2283
2284  t = OMP_PARALLEL_DATA_ARG (entry_stmt);
2285  if (t == NULL)
2286    t = null_pointer_node;
2287  else
2288    t = build_fold_addr_expr (t);
2289  args = tree_cons (NULL, t, NULL);
2290  t = build_function_call_expr (OMP_PARALLEL_FN (entry_stmt), args);
2291  gimplify_and_add (t, &list);
2292
2293  t = built_in_decls[BUILT_IN_GOMP_PARALLEL_END];
2294  t = build_function_call_expr (t, NULL);
2295  gimplify_and_add (t, &list);
2296
2297  si = bsi_last (bb);
2298  bsi_insert_after (&si, list, BSI_CONTINUE_LINKING);
2299
2300  pop_gimplify_context (NULL_TREE);
2301}
2302
2303
2304/* If exceptions are enabled, wrap *STMT_P in a MUST_NOT_THROW catch
2305   handler.  This prevents programs from violating the structured
2306   block semantics with throws.  */
2307
2308static void
2309maybe_catch_exception (tree *stmt_p)
2310{
2311  tree f, t;
2312
2313  if (!flag_exceptions)
2314    return;
2315
2316  if (lang_protect_cleanup_actions)
2317    t = lang_protect_cleanup_actions ();
2318  else
2319    {
2320      t = built_in_decls[BUILT_IN_TRAP];
2321      t = build_function_call_expr (t, NULL);
2322    }
2323  f = build2 (EH_FILTER_EXPR, void_type_node, NULL, NULL);
2324  EH_FILTER_MUST_NOT_THROW (f) = 1;
2325  gimplify_and_add (t, &EH_FILTER_FAILURE (f));
2326
2327  t = build2 (TRY_CATCH_EXPR, void_type_node, *stmt_p, NULL);
2328  append_to_statement_list (f, &TREE_OPERAND (t, 1));
2329
2330  *stmt_p = NULL;
2331  append_to_statement_list (t, stmt_p);
2332}
2333
2334/* Chain all the DECLs in LIST by their TREE_CHAIN fields.  */
2335
2336static tree
2337list2chain (tree list)
2338{
2339  tree t;
2340
2341  for (t = list; t; t = TREE_CHAIN (t))
2342    {
2343      tree var = TREE_VALUE (t);
2344      if (TREE_CHAIN (t))
2345	TREE_CHAIN (var) = TREE_VALUE (TREE_CHAIN (t));
2346      else
2347	TREE_CHAIN (var) = NULL_TREE;
2348    }
2349
2350  return list ? TREE_VALUE (list) : NULL_TREE;
2351}
2352
2353
2354/* Remove barriers in REGION->EXIT's block.  Note that this is only
2355   valid for OMP_PARALLEL regions.  Since the end of a parallel region
2356   is an implicit barrier, any workshare inside the OMP_PARALLEL that
2357   left a barrier at the end of the OMP_PARALLEL region can now be
2358   removed.  */
2359
2360static void
2361remove_exit_barrier (struct omp_region *region)
2362{
2363  block_stmt_iterator si;
2364  basic_block exit_bb;
2365  edge_iterator ei;
2366  edge e;
2367  tree t;
2368
2369  exit_bb = region->exit;
2370
2371  /* If the parallel region doesn't return, we don't have REGION->EXIT
2372     block at all.  */
2373  if (! exit_bb)
2374    return;
2375
2376  /* The last insn in the block will be the parallel's OMP_RETURN.  The
2377     workshare's OMP_RETURN will be in a preceding block.  The kinds of
2378     statements that can appear in between are extremely limited -- no
2379     memory operations at all.  Here, we allow nothing at all, so the
2380     only thing we allow to precede this OMP_RETURN is a label.  */
2381  si = bsi_last (exit_bb);
2382  gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_RETURN);
2383  bsi_prev (&si);
2384  if (!bsi_end_p (si) && TREE_CODE (bsi_stmt (si)) != LABEL_EXPR)
2385    return;
2386
2387  FOR_EACH_EDGE (e, ei, exit_bb->preds)
2388    {
2389      si = bsi_last (e->src);
2390      if (bsi_end_p (si))
2391	continue;
2392      t = bsi_stmt (si);
2393      if (TREE_CODE (t) == OMP_RETURN)
2394	OMP_RETURN_NOWAIT (t) = 1;
2395    }
2396}
2397
2398static void
2399remove_exit_barriers (struct omp_region *region)
2400{
2401  if (region->type == OMP_PARALLEL)
2402    remove_exit_barrier (region);
2403
2404  if (region->inner)
2405    {
2406      region = region->inner;
2407      remove_exit_barriers (region);
2408      while (region->next)
2409	{
2410	  region = region->next;
2411	  remove_exit_barriers (region);
2412	}
2413    }
2414}
2415
2416/* Expand the OpenMP parallel directive starting at REGION.  */
2417
2418static void
2419expand_omp_parallel (struct omp_region *region)
2420{
2421  basic_block entry_bb, exit_bb, new_bb;
2422  struct function *child_cfun, *saved_cfun;
2423  tree child_fn, block, t, ws_args;
2424  block_stmt_iterator si;
2425  tree entry_stmt;
2426  edge e;
2427  bool do_cleanup_cfg = false;
2428
2429  entry_stmt = last_stmt (region->entry);
2430  child_fn = OMP_PARALLEL_FN (entry_stmt);
2431  child_cfun = DECL_STRUCT_FUNCTION (child_fn);
2432  saved_cfun = cfun;
2433
2434  entry_bb = region->entry;
2435  exit_bb = region->exit;
2436
2437  if (is_combined_parallel (region))
2438    ws_args = region->ws_args;
2439  else
2440    ws_args = NULL_TREE;
2441
2442  if (child_cfun->cfg)
2443    {
2444      /* Due to inlining, it may happen that we have already outlined
2445	 the region, in which case all we need to do is make the
2446	 sub-graph unreachable and emit the parallel call.  */
2447      edge entry_succ_e, exit_succ_e;
2448      block_stmt_iterator si;
2449
2450      entry_succ_e = single_succ_edge (entry_bb);
2451
2452      si = bsi_last (entry_bb);
2453      gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_PARALLEL);
2454      bsi_remove (&si, true);
2455
2456      new_bb = entry_bb;
2457      remove_edge (entry_succ_e);
2458      if (exit_bb)
2459	{
2460	  exit_succ_e = single_succ_edge (exit_bb);
2461	  make_edge (new_bb, exit_succ_e->dest, EDGE_FALLTHRU);
2462	}
2463      do_cleanup_cfg = true;
2464    }
2465  else
2466    {
2467      /* If the parallel region needs data sent from the parent
2468	 function, then the very first statement (except possible
2469	 tree profile counter updates) of the parallel body
2470	 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O.  Since
2471	 &.OMP_DATA_O is passed as an argument to the child function,
2472	 we need to replace it with the argument as seen by the child
2473	 function.
2474
2475	 In most cases, this will end up being the identity assignment
2476	 .OMP_DATA_I = .OMP_DATA_I.  However, if the parallel body had
2477	 a function call that has been inlined, the original PARM_DECL
2478	 .OMP_DATA_I may have been converted into a different local
2479	 variable.  In which case, we need to keep the assignment.  */
2480      if (OMP_PARALLEL_DATA_ARG (entry_stmt))
2481	{
2482	  basic_block entry_succ_bb = single_succ (entry_bb);
2483	  block_stmt_iterator si;
2484
2485	  for (si = bsi_start (entry_succ_bb); ; bsi_next (&si))
2486	    {
2487	      tree stmt, arg;
2488
2489	      gcc_assert (!bsi_end_p (si));
2490	      stmt = bsi_stmt (si);
2491	      if (TREE_CODE (stmt) != MODIFY_EXPR)
2492		continue;
2493
2494	      arg = TREE_OPERAND (stmt, 1);
2495	      STRIP_NOPS (arg);
2496	      if (TREE_CODE (arg) == ADDR_EXPR
2497		  && TREE_OPERAND (arg, 0)
2498		     == OMP_PARALLEL_DATA_ARG (entry_stmt))
2499		{
2500		  if (TREE_OPERAND (stmt, 0) == DECL_ARGUMENTS (child_fn))
2501		    bsi_remove (&si, true);
2502		  else
2503		    TREE_OPERAND (stmt, 1) = DECL_ARGUMENTS (child_fn);
2504		  break;
2505		}
2506	    }
2507	}
2508
2509      /* Declare local variables needed in CHILD_CFUN.  */
2510      block = DECL_INITIAL (child_fn);
2511      BLOCK_VARS (block) = list2chain (child_cfun->unexpanded_var_list);
2512      DECL_SAVED_TREE (child_fn) = single_succ (entry_bb)->stmt_list;
2513
2514      /* Reset DECL_CONTEXT on locals and function arguments.  */
2515      for (t = BLOCK_VARS (block); t; t = TREE_CHAIN (t))
2516	DECL_CONTEXT (t) = child_fn;
2517
2518      for (t = DECL_ARGUMENTS (child_fn); t; t = TREE_CHAIN (t))
2519	DECL_CONTEXT (t) = child_fn;
2520
2521      /* Split ENTRY_BB at OMP_PARALLEL so that it can be moved to the
2522	 child function.  */
2523      si = bsi_last (entry_bb);
2524      t = bsi_stmt (si);
2525      gcc_assert (t && TREE_CODE (t) == OMP_PARALLEL);
2526      bsi_remove (&si, true);
2527      e = split_block (entry_bb, t);
2528      entry_bb = e->dest;
2529      single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
2530
2531      /* Move the parallel region into CHILD_CFUN.  We need to reset
2532	 dominance information because the expansion of the inner
2533	 regions has invalidated it.  */
2534      free_dominance_info (CDI_DOMINATORS);
2535      new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb);
2536      if (exit_bb)
2537	single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
2538      cgraph_add_new_function (child_fn);
2539
2540      /* Convert OMP_RETURN into a RETURN_EXPR.  */
2541      if (exit_bb)
2542	{
2543	  si = bsi_last (exit_bb);
2544	  gcc_assert (!bsi_end_p (si)
2545		      && TREE_CODE (bsi_stmt (si)) == OMP_RETURN);
2546	  t = build1 (RETURN_EXPR, void_type_node, NULL);
2547	  bsi_insert_after (&si, t, BSI_SAME_STMT);
2548	  bsi_remove (&si, true);
2549	}
2550    }
2551
2552  /* Emit a library call to launch the children threads.  */
2553  expand_parallel_call (region, new_bb, entry_stmt, ws_args);
2554
2555  if (do_cleanup_cfg)
2556    {
2557      /* Clean up the unreachable sub-graph we created above.  */
2558      free_dominance_info (CDI_DOMINATORS);
2559      free_dominance_info (CDI_POST_DOMINATORS);
2560      cleanup_tree_cfg ();
2561    }
2562}
2563
2564
2565/* A subroutine of expand_omp_for.  Generate code for a parallel
2566   loop with any schedule.  Given parameters:
2567
2568	for (V = N1; V cond N2; V += STEP) BODY;
2569
2570   where COND is "<" or ">", we generate pseudocode
2571
2572	more = GOMP_loop_foo_start (N1, N2, STEP, CHUNK, &istart0, &iend0);
2573	if (more) goto L0; else goto L3;
2574    L0:
2575	V = istart0;
2576	iend = iend0;
2577    L1:
2578	BODY;
2579	V += STEP;
2580	if (V cond iend) goto L1; else goto L2;
2581    L2:
2582	if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
2583    L3:
2584
2585    If this is a combined omp parallel loop, instead of the call to
2586    GOMP_loop_foo_start, we emit 'goto L3'.  */
2587
2588static void
2589expand_omp_for_generic (struct omp_region *region,
2590			struct omp_for_data *fd,
2591			enum built_in_function start_fn,
2592			enum built_in_function next_fn)
2593{
2594  tree l0, l1, l2 = NULL, l3 = NULL;
2595  tree type, istart0, iend0, iend;
2596  tree t, args, list;
2597  basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb;
2598  basic_block l2_bb = NULL, l3_bb = NULL;
2599  block_stmt_iterator si;
2600  bool in_combined_parallel = is_combined_parallel (region);
2601
2602  type = TREE_TYPE (fd->v);
2603
2604  istart0 = create_tmp_var (long_integer_type_node, ".istart0");
2605  iend0 = create_tmp_var (long_integer_type_node, ".iend0");
2606  iend = create_tmp_var (type, NULL);
2607  TREE_ADDRESSABLE (istart0) = 1;
2608  TREE_ADDRESSABLE (iend0) = 1;
2609
2610  gcc_assert ((region->cont != NULL) ^ (region->exit == NULL));
2611
2612  entry_bb = region->entry;
2613  l0_bb = create_empty_bb (entry_bb);
2614  l1_bb = single_succ (entry_bb);
2615
2616  l0 = tree_block_label (l0_bb);
2617  l1 = tree_block_label (l1_bb);
2618
2619  cont_bb = region->cont;
2620  exit_bb = region->exit;
2621  if (cont_bb)
2622    {
2623      l2_bb = create_empty_bb (cont_bb);
2624      l3_bb = single_succ (cont_bb);
2625
2626      l2 = tree_block_label (l2_bb);
2627      l3 = tree_block_label (l3_bb);
2628    }
2629
2630  si = bsi_last (entry_bb);
2631  gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_FOR);
2632  if (!in_combined_parallel)
2633    {
2634      /* If this is not a combined parallel loop, emit a call to
2635	 GOMP_loop_foo_start in ENTRY_BB.  */
2636      list = alloc_stmt_list ();
2637      t = build_fold_addr_expr (iend0);
2638      args = tree_cons (NULL, t, NULL);
2639      t = build_fold_addr_expr (istart0);
2640      args = tree_cons (NULL, t, args);
2641      if (fd->chunk_size)
2642	{
2643	  t = fold_convert (long_integer_type_node, fd->chunk_size);
2644	  args = tree_cons (NULL, t, args);
2645	}
2646      t = fold_convert (long_integer_type_node, fd->step);
2647      args = tree_cons (NULL, t, args);
2648      t = fold_convert (long_integer_type_node, fd->n2);
2649      args = tree_cons (NULL, t, args);
2650      t = fold_convert (long_integer_type_node, fd->n1);
2651      args = tree_cons (NULL, t, args);
2652      t = build_function_call_expr (built_in_decls[start_fn], args);
2653      t = get_formal_tmp_var (t, &list);
2654      if (cont_bb)
2655	{
2656	  t = build3 (COND_EXPR, void_type_node, t, build_and_jump (&l0),
2657		      build_and_jump (&l3));
2658	  append_to_statement_list (t, &list);
2659	}
2660      bsi_insert_after (&si, list, BSI_SAME_STMT);
2661    }
2662  bsi_remove (&si, true);
2663
2664  /* Iteration setup for sequential loop goes in L0_BB.  */
2665  list = alloc_stmt_list ();
2666  t = fold_convert (type, istart0);
2667  t = build2 (MODIFY_EXPR, void_type_node, fd->v, t);
2668  gimplify_and_add (t, &list);
2669
2670  t = fold_convert (type, iend0);
2671  t = build2 (MODIFY_EXPR, void_type_node, iend, t);
2672  gimplify_and_add (t, &list);
2673
2674  si = bsi_start (l0_bb);
2675  bsi_insert_after (&si, list, BSI_CONTINUE_LINKING);
2676
2677  /* Handle the rare case where BODY doesn't ever return.  */
2678  if (cont_bb == NULL)
2679    {
2680      remove_edge (single_succ_edge (entry_bb));
2681      make_edge (entry_bb, l0_bb, EDGE_FALLTHRU);
2682      make_edge (l0_bb, l1_bb, EDGE_FALLTHRU);
2683      return;
2684    }
2685
2686  /* Code to control the increment and predicate for the sequential
2687     loop goes in the first half of EXIT_BB (we split EXIT_BB so
2688     that we can inherit all the edges going out of the loop
2689     body).  */
2690  list = alloc_stmt_list ();
2691
2692  t = build2 (PLUS_EXPR, type, fd->v, fd->step);
2693  t = build2 (MODIFY_EXPR, void_type_node, fd->v, t);
2694  gimplify_and_add (t, &list);
2695
2696  t = build2 (fd->cond_code, boolean_type_node, fd->v, iend);
2697  t = get_formal_tmp_var (t, &list);
2698  t = build3 (COND_EXPR, void_type_node, t, build_and_jump (&l1),
2699	      build_and_jump (&l2));
2700  append_to_statement_list (t, &list);
2701
2702  si = bsi_last (cont_bb);
2703  bsi_insert_after (&si, list, BSI_SAME_STMT);
2704  gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_CONTINUE);
2705  bsi_remove (&si, true);
2706
2707  /* Emit code to get the next parallel iteration in L2_BB.  */
2708  list = alloc_stmt_list ();
2709
2710  t = build_fold_addr_expr (iend0);
2711  args = tree_cons (NULL, t, NULL);
2712  t = build_fold_addr_expr (istart0);
2713  args = tree_cons (NULL, t, args);
2714  t = build_function_call_expr (built_in_decls[next_fn], args);
2715  t = get_formal_tmp_var (t, &list);
2716  t = build3 (COND_EXPR, void_type_node, t, build_and_jump (&l0),
2717	      build_and_jump (&l3));
2718  append_to_statement_list (t, &list);
2719
2720  si = bsi_start (l2_bb);
2721  bsi_insert_after (&si, list, BSI_CONTINUE_LINKING);
2722
2723  /* Add the loop cleanup function.  */
2724  si = bsi_last (exit_bb);
2725  if (OMP_RETURN_NOWAIT (bsi_stmt (si)))
2726    t = built_in_decls[BUILT_IN_GOMP_LOOP_END_NOWAIT];
2727  else
2728    t = built_in_decls[BUILT_IN_GOMP_LOOP_END];
2729  t = build_function_call_expr (t, NULL);
2730  bsi_insert_after (&si, t, BSI_SAME_STMT);
2731  bsi_remove (&si, true);
2732
2733  /* Connect the new blocks.  */
2734  remove_edge (single_succ_edge (entry_bb));
2735  if (in_combined_parallel)
2736    make_edge (entry_bb, l2_bb, EDGE_FALLTHRU);
2737  else
2738    {
2739      make_edge (entry_bb, l0_bb, EDGE_TRUE_VALUE);
2740      make_edge (entry_bb, l3_bb, EDGE_FALSE_VALUE);
2741    }
2742
2743  make_edge (l0_bb, l1_bb, EDGE_FALLTHRU);
2744
2745  remove_edge (single_succ_edge (cont_bb));
2746  make_edge (cont_bb, l1_bb, EDGE_TRUE_VALUE);
2747  make_edge (cont_bb, l2_bb, EDGE_FALSE_VALUE);
2748
2749  make_edge (l2_bb, l0_bb, EDGE_TRUE_VALUE);
2750  make_edge (l2_bb, l3_bb, EDGE_FALSE_VALUE);
2751}
2752
2753
2754/* A subroutine of expand_omp_for.  Generate code for a parallel
2755   loop with static schedule and no specified chunk size.  Given
2756   parameters:
2757
2758	for (V = N1; V cond N2; V += STEP) BODY;
2759
2760   where COND is "<" or ">", we generate pseudocode
2761
2762	if (cond is <)
2763	  adj = STEP - 1;
2764	else
2765	  adj = STEP + 1;
2766	n = (adj + N2 - N1) / STEP;
2767	q = n / nthreads;
2768	q += (q * nthreads != n);
2769	s0 = q * threadid;
2770	e0 = min(s0 + q, n);
2771	if (s0 >= e0) goto L2; else goto L0;
2772    L0:
2773	V = s0 * STEP + N1;
2774	e = e0 * STEP + N1;
2775    L1:
2776	BODY;
2777	V += STEP;
2778	if (V cond e) goto L1;
2779    L2:
2780*/
2781
2782static void
2783expand_omp_for_static_nochunk (struct omp_region *region,
2784			       struct omp_for_data *fd)
2785{
2786  tree l0, l1, l2, n, q, s0, e0, e, t, nthreads, threadid;
2787  tree type, list;
2788  basic_block entry_bb, exit_bb, seq_start_bb, body_bb, cont_bb;
2789  basic_block fin_bb;
2790  block_stmt_iterator si;
2791
2792  type = TREE_TYPE (fd->v);
2793
2794  entry_bb = region->entry;
2795  seq_start_bb = create_empty_bb (entry_bb);
2796  body_bb = single_succ (entry_bb);
2797  cont_bb = region->cont;
2798  fin_bb = single_succ (cont_bb);
2799  exit_bb = region->exit;
2800
2801  l0 = tree_block_label (seq_start_bb);
2802  l1 = tree_block_label (body_bb);
2803  l2 = tree_block_label (fin_bb);
2804
2805  /* Iteration space partitioning goes in ENTRY_BB.  */
2806  list = alloc_stmt_list ();
2807
2808  t = built_in_decls[BUILT_IN_OMP_GET_NUM_THREADS];
2809  t = build_function_call_expr (t, NULL);
2810  t = fold_convert (type, t);
2811  nthreads = get_formal_tmp_var (t, &list);
2812
2813  t = built_in_decls[BUILT_IN_OMP_GET_THREAD_NUM];
2814  t = build_function_call_expr (t, NULL);
2815  t = fold_convert (type, t);
2816  threadid = get_formal_tmp_var (t, &list);
2817
2818  fd->n1 = fold_convert (type, fd->n1);
2819  if (!is_gimple_val (fd->n1))
2820    fd->n1 = get_formal_tmp_var (fd->n1, &list);
2821
2822  fd->n2 = fold_convert (type, fd->n2);
2823  if (!is_gimple_val (fd->n2))
2824    fd->n2 = get_formal_tmp_var (fd->n2, &list);
2825
2826  fd->step = fold_convert (type, fd->step);
2827  if (!is_gimple_val (fd->step))
2828    fd->step = get_formal_tmp_var (fd->step, &list);
2829
2830  t = build_int_cst (type, (fd->cond_code == LT_EXPR ? -1 : 1));
2831  t = fold_build2 (PLUS_EXPR, type, fd->step, t);
2832  t = fold_build2 (PLUS_EXPR, type, t, fd->n2);
2833  t = fold_build2 (MINUS_EXPR, type, t, fd->n1);
2834  t = fold_build2 (TRUNC_DIV_EXPR, type, t, fd->step);
2835  t = fold_convert (type, t);
2836  if (is_gimple_val (t))
2837    n = t;
2838  else
2839    n = get_formal_tmp_var (t, &list);
2840
2841  t = build2 (TRUNC_DIV_EXPR, type, n, nthreads);
2842  q = get_formal_tmp_var (t, &list);
2843
2844  t = build2 (MULT_EXPR, type, q, nthreads);
2845  t = build2 (NE_EXPR, type, t, n);
2846  t = build2 (PLUS_EXPR, type, q, t);
2847  q = get_formal_tmp_var (t, &list);
2848
2849  t = build2 (MULT_EXPR, type, q, threadid);
2850  s0 = get_formal_tmp_var (t, &list);
2851
2852  t = build2 (PLUS_EXPR, type, s0, q);
2853  t = build2 (MIN_EXPR, type, t, n);
2854  e0 = get_formal_tmp_var (t, &list);
2855
2856  t = build2 (GE_EXPR, boolean_type_node, s0, e0);
2857  t = build3 (COND_EXPR, void_type_node, t, build_and_jump (&l2),
2858	      build_and_jump (&l0));
2859  append_to_statement_list (t, &list);
2860
2861  si = bsi_last (entry_bb);
2862  gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_FOR);
2863  bsi_insert_after (&si, list, BSI_SAME_STMT);
2864  bsi_remove (&si, true);
2865
2866  /* Setup code for sequential iteration goes in SEQ_START_BB.  */
2867  list = alloc_stmt_list ();
2868
2869  t = fold_convert (type, s0);
2870  t = build2 (MULT_EXPR, type, t, fd->step);
2871  t = build2 (PLUS_EXPR, type, t, fd->n1);
2872  t = build2 (MODIFY_EXPR, void_type_node, fd->v, t);
2873  gimplify_and_add (t, &list);
2874
2875  t = fold_convert (type, e0);
2876  t = build2 (MULT_EXPR, type, t, fd->step);
2877  t = build2 (PLUS_EXPR, type, t, fd->n1);
2878  e = get_formal_tmp_var (t, &list);
2879
2880  si = bsi_start (seq_start_bb);
2881  bsi_insert_after (&si, list, BSI_CONTINUE_LINKING);
2882
2883  /* The code controlling the sequential loop replaces the OMP_CONTINUE.  */
2884  list = alloc_stmt_list ();
2885
2886  t = build2 (PLUS_EXPR, type, fd->v, fd->step);
2887  t = build2 (MODIFY_EXPR, void_type_node, fd->v, t);
2888  gimplify_and_add (t, &list);
2889
2890  t = build2 (fd->cond_code, boolean_type_node, fd->v, e);
2891  t = get_formal_tmp_var (t, &list);
2892  t = build3 (COND_EXPR, void_type_node, t, build_and_jump (&l1),
2893	      build_and_jump (&l2));
2894  append_to_statement_list (t, &list);
2895
2896  si = bsi_last (cont_bb);
2897  gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_CONTINUE);
2898  bsi_insert_after (&si, list, BSI_SAME_STMT);
2899  bsi_remove (&si, true);
2900
2901  /* Replace the OMP_RETURN with a barrier, or nothing.  */
2902  si = bsi_last (exit_bb);
2903  if (!OMP_RETURN_NOWAIT (bsi_stmt (si)))
2904    {
2905      list = alloc_stmt_list ();
2906      build_omp_barrier (&list);
2907      bsi_insert_after (&si, list, BSI_SAME_STMT);
2908    }
2909  bsi_remove (&si, true);
2910
2911  /* Connect all the blocks.  */
2912  make_edge (seq_start_bb, body_bb, EDGE_FALLTHRU);
2913
2914  remove_edge (single_succ_edge (entry_bb));
2915  make_edge (entry_bb, fin_bb, EDGE_TRUE_VALUE);
2916  make_edge (entry_bb, seq_start_bb, EDGE_FALSE_VALUE);
2917
2918  make_edge (cont_bb, body_bb, EDGE_TRUE_VALUE);
2919  find_edge (cont_bb, fin_bb)->flags = EDGE_FALSE_VALUE;
2920}
2921
2922
2923/* A subroutine of expand_omp_for.  Generate code for a parallel
2924   loop with static schedule and a specified chunk size.  Given
2925   parameters:
2926
2927	for (V = N1; V cond N2; V += STEP) BODY;
2928
2929   where COND is "<" or ">", we generate pseudocode
2930
2931	if (cond is <)
2932	  adj = STEP - 1;
2933	else
2934	  adj = STEP + 1;
2935	n = (adj + N2 - N1) / STEP;
2936	trip = 0;
2937    L0:
2938	s0 = (trip * nthreads + threadid) * CHUNK;
2939	e0 = min(s0 + CHUNK, n);
2940	if (s0 < n) goto L1; else goto L4;
2941    L1:
2942	V = s0 * STEP + N1;
2943	e = e0 * STEP + N1;
2944    L2:
2945	BODY;
2946	V += STEP;
2947	if (V cond e) goto L2; else goto L3;
2948    L3:
2949	trip += 1;
2950	goto L0;
2951    L4:
2952*/
2953
2954static void
2955expand_omp_for_static_chunk (struct omp_region *region, struct omp_for_data *fd)
2956{
2957  tree l0, l1, l2, l3, l4, n, s0, e0, e, t;
2958  tree trip, nthreads, threadid;
2959  tree type;
2960  basic_block entry_bb, exit_bb, body_bb, seq_start_bb, iter_part_bb;
2961  basic_block trip_update_bb, cont_bb, fin_bb;
2962  tree list;
2963  block_stmt_iterator si;
2964
2965  type = TREE_TYPE (fd->v);
2966
2967  entry_bb = region->entry;
2968  iter_part_bb = create_empty_bb (entry_bb);
2969  seq_start_bb = create_empty_bb (iter_part_bb);
2970  body_bb = single_succ (entry_bb);
2971  cont_bb = region->cont;
2972  trip_update_bb = create_empty_bb (cont_bb);
2973  fin_bb = single_succ (cont_bb);
2974  exit_bb = region->exit;
2975
2976  l0 = tree_block_label (iter_part_bb);
2977  l1 = tree_block_label (seq_start_bb);
2978  l2 = tree_block_label (body_bb);
2979  l3 = tree_block_label (trip_update_bb);
2980  l4 = tree_block_label (fin_bb);
2981
2982  /* Trip and adjustment setup goes in ENTRY_BB.  */
2983  list = alloc_stmt_list ();
2984
2985  t = built_in_decls[BUILT_IN_OMP_GET_NUM_THREADS];
2986  t = build_function_call_expr (t, NULL);
2987  t = fold_convert (type, t);
2988  nthreads = get_formal_tmp_var (t, &list);
2989
2990  t = built_in_decls[BUILT_IN_OMP_GET_THREAD_NUM];
2991  t = build_function_call_expr (t, NULL);
2992  t = fold_convert (type, t);
2993  threadid = get_formal_tmp_var (t, &list);
2994
2995  fd->n1 = fold_convert (type, fd->n1);
2996  if (!is_gimple_val (fd->n1))
2997    fd->n1 = get_formal_tmp_var (fd->n1, &list);
2998
2999  fd->n2 = fold_convert (type, fd->n2);
3000  if (!is_gimple_val (fd->n2))
3001    fd->n2 = get_formal_tmp_var (fd->n2, &list);
3002
3003  fd->step = fold_convert (type, fd->step);
3004  if (!is_gimple_val (fd->step))
3005    fd->step = get_formal_tmp_var (fd->step, &list);
3006
3007  fd->chunk_size = fold_convert (type, fd->chunk_size);
3008  if (!is_gimple_val (fd->chunk_size))
3009    fd->chunk_size = get_formal_tmp_var (fd->chunk_size, &list);
3010
3011  t = build_int_cst (type, (fd->cond_code == LT_EXPR ? -1 : 1));
3012  t = fold_build2 (PLUS_EXPR, type, fd->step, t);
3013  t = fold_build2 (PLUS_EXPR, type, t, fd->n2);
3014  t = fold_build2 (MINUS_EXPR, type, t, fd->n1);
3015  t = fold_build2 (TRUNC_DIV_EXPR, type, t, fd->step);
3016  t = fold_convert (type, t);
3017  if (is_gimple_val (t))
3018    n = t;
3019  else
3020    n = get_formal_tmp_var (t, &list);
3021
3022  t = build_int_cst (type, 0);
3023  trip = get_initialized_tmp_var (t, &list, NULL);
3024
3025  si = bsi_last (entry_bb);
3026  gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_FOR);
3027  bsi_insert_after (&si, list, BSI_SAME_STMT);
3028  bsi_remove (&si, true);
3029
3030  /* Iteration space partitioning goes in ITER_PART_BB.  */
3031  list = alloc_stmt_list ();
3032
3033  t = build2 (MULT_EXPR, type, trip, nthreads);
3034  t = build2 (PLUS_EXPR, type, t, threadid);
3035  t = build2 (MULT_EXPR, type, t, fd->chunk_size);
3036  s0 = get_formal_tmp_var (t, &list);
3037
3038  t = build2 (PLUS_EXPR, type, s0, fd->chunk_size);
3039  t = build2 (MIN_EXPR, type, t, n);
3040  e0 = get_formal_tmp_var (t, &list);
3041
3042  t = build2 (LT_EXPR, boolean_type_node, s0, n);
3043  t = build3 (COND_EXPR, void_type_node, t,
3044	      build_and_jump (&l1), build_and_jump (&l4));
3045  append_to_statement_list (t, &list);
3046
3047  si = bsi_start (iter_part_bb);
3048  bsi_insert_after (&si, list, BSI_CONTINUE_LINKING);
3049
3050  /* Setup code for sequential iteration goes in SEQ_START_BB.  */
3051  list = alloc_stmt_list ();
3052
3053  t = fold_convert (type, s0);
3054  t = build2 (MULT_EXPR, type, t, fd->step);
3055  t = build2 (PLUS_EXPR, type, t, fd->n1);
3056  t = build2 (MODIFY_EXPR, void_type_node, fd->v, t);
3057  gimplify_and_add (t, &list);
3058
3059  t = fold_convert (type, e0);
3060  t = build2 (MULT_EXPR, type, t, fd->step);
3061  t = build2 (PLUS_EXPR, type, t, fd->n1);
3062  e = get_formal_tmp_var (t, &list);
3063
3064  si = bsi_start (seq_start_bb);
3065  bsi_insert_after (&si, list, BSI_CONTINUE_LINKING);
3066
3067  /* The code controlling the sequential loop goes in CONT_BB,
3068     replacing the OMP_CONTINUE.  */
3069  list = alloc_stmt_list ();
3070
3071  t = build2 (PLUS_EXPR, type, fd->v, fd->step);
3072  t = build2 (MODIFY_EXPR, void_type_node, fd->v, t);
3073  gimplify_and_add (t, &list);
3074
3075  t = build2 (fd->cond_code, boolean_type_node, fd->v, e);
3076  t = get_formal_tmp_var (t, &list);
3077  t = build3 (COND_EXPR, void_type_node, t,
3078	      build_and_jump (&l2), build_and_jump (&l3));
3079  append_to_statement_list (t, &list);
3080
3081  si = bsi_last (cont_bb);
3082  gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_CONTINUE);
3083  bsi_insert_after (&si, list, BSI_SAME_STMT);
3084  bsi_remove (&si, true);
3085
3086  /* Trip update code goes into TRIP_UPDATE_BB.  */
3087  list = alloc_stmt_list ();
3088
3089  t = build_int_cst (type, 1);
3090  t = build2 (PLUS_EXPR, type, trip, t);
3091  t = build2 (MODIFY_EXPR, void_type_node, trip, t);
3092  gimplify_and_add (t, &list);
3093
3094  si = bsi_start (trip_update_bb);
3095  bsi_insert_after (&si, list, BSI_CONTINUE_LINKING);
3096
3097  /* Replace the OMP_RETURN with a barrier, or nothing.  */
3098  si = bsi_last (exit_bb);
3099  if (!OMP_RETURN_NOWAIT (bsi_stmt (si)))
3100    {
3101      list = alloc_stmt_list ();
3102      build_omp_barrier (&list);
3103      bsi_insert_after (&si, list, BSI_SAME_STMT);
3104    }
3105  bsi_remove (&si, true);
3106
3107  /* Connect the new blocks.  */
3108  remove_edge (single_succ_edge (entry_bb));
3109  make_edge (entry_bb, iter_part_bb, EDGE_FALLTHRU);
3110
3111  make_edge (iter_part_bb, seq_start_bb, EDGE_TRUE_VALUE);
3112  make_edge (iter_part_bb, fin_bb, EDGE_FALSE_VALUE);
3113
3114  make_edge (seq_start_bb, body_bb, EDGE_FALLTHRU);
3115
3116  remove_edge (single_succ_edge (cont_bb));
3117  make_edge (cont_bb, body_bb, EDGE_TRUE_VALUE);
3118  make_edge (cont_bb, trip_update_bb, EDGE_FALSE_VALUE);
3119
3120  make_edge (trip_update_bb, iter_part_bb, EDGE_FALLTHRU);
3121}
3122
3123
3124/* Expand the OpenMP loop defined by REGION.  */
3125
3126static void
3127expand_omp_for (struct omp_region *region)
3128{
3129  struct omp_for_data fd;
3130
3131  push_gimplify_context ();
3132
3133  extract_omp_for_data (last_stmt (region->entry), &fd);
3134  region->sched_kind = fd.sched_kind;
3135
3136  if (fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
3137      && !fd.have_ordered
3138      && region->cont
3139      && region->exit)
3140    {
3141      if (fd.chunk_size == NULL)
3142	expand_omp_for_static_nochunk (region, &fd);
3143      else
3144	expand_omp_for_static_chunk (region, &fd);
3145    }
3146  else
3147    {
3148      int fn_index = fd.sched_kind + fd.have_ordered * 4;
3149      int start_ix = BUILT_IN_GOMP_LOOP_STATIC_START + fn_index;
3150      int next_ix = BUILT_IN_GOMP_LOOP_STATIC_NEXT + fn_index;
3151      expand_omp_for_generic (region, &fd, start_ix, next_ix);
3152    }
3153
3154  pop_gimplify_context (NULL);
3155}
3156
3157
3158/* Expand code for an OpenMP sections directive.  In pseudo code, we generate
3159
3160	v = GOMP_sections_start (n);
3161    L0:
3162	switch (v)
3163	  {
3164	  case 0:
3165	    goto L2;
3166	  case 1:
3167	    section 1;
3168	    goto L1;
3169	  case 2:
3170	    ...
3171	  case n:
3172	    ...
3173	  default:
3174	    abort ();
3175	  }
3176    L1:
3177	v = GOMP_sections_next ();
3178	goto L0;
3179    L2:
3180	reduction;
3181
3182    If this is a combined parallel sections, replace the call to
3183    GOMP_sections_start with 'goto L1'.  */
3184
3185static void
3186expand_omp_sections (struct omp_region *region)
3187{
3188  tree label_vec, l0, l1, l2, t, u, v, sections_stmt;
3189  unsigned i, len;
3190  basic_block entry_bb, exit_bb, l0_bb, l1_bb, l2_bb, default_bb;
3191  block_stmt_iterator si;
3192  struct omp_region *inner;
3193  edge e;
3194
3195  entry_bb = region->entry;
3196  l0_bb = create_empty_bb (entry_bb);
3197  l0 = tree_block_label (l0_bb);
3198
3199  gcc_assert ((region->cont != NULL) ^ (region->exit == NULL));
3200  l1_bb = region->cont;
3201  if (l1_bb)
3202    {
3203      l2_bb = single_succ (l1_bb);
3204      default_bb = create_empty_bb (l1_bb->prev_bb);
3205
3206      l1 = tree_block_label (l1_bb);
3207    }
3208  else
3209    {
3210      l2_bb = create_empty_bb (l0_bb);
3211      default_bb = l2_bb;
3212
3213      l1 = NULL;
3214    }
3215  l2 = tree_block_label (l2_bb);
3216
3217  exit_bb = region->exit;
3218
3219  v = create_tmp_var (unsigned_type_node, ".section");
3220
3221  /* We will build a switch() with enough cases for all the
3222     OMP_SECTION regions, a '0' case to handle the end of more work
3223     and a default case to abort if something goes wrong.  */
3224  len = EDGE_COUNT (entry_bb->succs);
3225  label_vec = make_tree_vec (len + 2);
3226
3227  /* The call to GOMP_sections_start goes in ENTRY_BB, replacing the
3228     OMP_SECTIONS statement.  */
3229  si = bsi_last (entry_bb);
3230  sections_stmt = bsi_stmt (si);
3231  gcc_assert (TREE_CODE (sections_stmt) == OMP_SECTIONS);
3232  if (!is_combined_parallel (region))
3233    {
3234      /* If we are not inside a combined parallel+sections region,
3235	 call GOMP_sections_start.  */
3236      t = build_int_cst (unsigned_type_node, len);
3237      t = tree_cons (NULL, t, NULL);
3238      u = built_in_decls[BUILT_IN_GOMP_SECTIONS_START];
3239      t = build_function_call_expr (u, t);
3240      t = build2 (MODIFY_EXPR, void_type_node, v, t);
3241      bsi_insert_after (&si, t, BSI_SAME_STMT);
3242    }
3243  bsi_remove (&si, true);
3244
3245  /* The switch() statement replacing OMP_SECTIONS goes in L0_BB.  */
3246  si = bsi_start (l0_bb);
3247
3248  t = build3 (SWITCH_EXPR, void_type_node, v, NULL, label_vec);
3249  bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
3250
3251  t = build3 (CASE_LABEL_EXPR, void_type_node,
3252	      build_int_cst (unsigned_type_node, 0), NULL, l2);
3253  TREE_VEC_ELT (label_vec, 0) = t;
3254  make_edge (l0_bb, l2_bb, 0);
3255
3256  /* Convert each OMP_SECTION into a CASE_LABEL_EXPR.  */
3257  for (inner = region->inner, i = 1; inner; inner = inner->next, ++i)
3258    {
3259      basic_block s_entry_bb, s_exit_bb;
3260
3261      s_entry_bb = inner->entry;
3262      s_exit_bb = inner->exit;
3263
3264      t = tree_block_label (s_entry_bb);
3265      u = build_int_cst (unsigned_type_node, i);
3266      u = build3 (CASE_LABEL_EXPR, void_type_node, u, NULL, t);
3267      TREE_VEC_ELT (label_vec, i) = u;
3268
3269      si = bsi_last (s_entry_bb);
3270      gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_SECTION);
3271      gcc_assert (i < len || OMP_SECTION_LAST (bsi_stmt (si)));
3272      bsi_remove (&si, true);
3273
3274      e = single_pred_edge (s_entry_bb);
3275      e->flags = 0;
3276      redirect_edge_pred (e, l0_bb);
3277
3278      single_succ_edge (s_entry_bb)->flags = EDGE_FALLTHRU;
3279
3280      if (s_exit_bb == NULL)
3281	continue;
3282
3283      si = bsi_last (s_exit_bb);
3284      gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_RETURN);
3285      bsi_remove (&si, true);
3286
3287      single_succ_edge (s_exit_bb)->flags = EDGE_FALLTHRU;
3288    }
3289
3290  /* Error handling code goes in DEFAULT_BB.  */
3291  t = tree_block_label (default_bb);
3292  u = build3 (CASE_LABEL_EXPR, void_type_node, NULL, NULL, t);
3293  TREE_VEC_ELT (label_vec, len + 1) = u;
3294  make_edge (l0_bb, default_bb, 0);
3295
3296  si = bsi_start (default_bb);
3297  t = built_in_decls[BUILT_IN_TRAP];
3298  t = build_function_call_expr (t, NULL);
3299  bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
3300
3301  /* Code to get the next section goes in L1_BB.  */
3302  if (l1_bb)
3303    {
3304      si = bsi_last (l1_bb);
3305      gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_CONTINUE);
3306
3307      t = built_in_decls[BUILT_IN_GOMP_SECTIONS_NEXT];
3308      t = build_function_call_expr (t, NULL);
3309      t = build2 (MODIFY_EXPR, void_type_node, v, t);
3310      bsi_insert_after (&si, t, BSI_SAME_STMT);
3311      bsi_remove (&si, true);
3312    }
3313
3314  /* Cleanup function replaces OMP_RETURN in EXIT_BB.  */
3315  if (exit_bb)
3316    {
3317      si = bsi_last (exit_bb);
3318      if (OMP_RETURN_NOWAIT (bsi_stmt (si)))
3319	t = built_in_decls[BUILT_IN_GOMP_SECTIONS_END_NOWAIT];
3320      else
3321	t = built_in_decls[BUILT_IN_GOMP_SECTIONS_END];
3322      t = build_function_call_expr (t, NULL);
3323      bsi_insert_after (&si, t, BSI_SAME_STMT);
3324      bsi_remove (&si, true);
3325    }
3326
3327  /* Connect the new blocks.  */
3328  if (is_combined_parallel (region))
3329    {
3330      /* If this was a combined parallel+sections region, we did not
3331	 emit a GOMP_sections_start in the entry block, so we just
3332	 need to jump to L1_BB to get the next section.  */
3333      make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
3334    }
3335  else
3336    make_edge (entry_bb, l0_bb, EDGE_FALLTHRU);
3337
3338  if (l1_bb)
3339    {
3340      e = single_succ_edge (l1_bb);
3341      redirect_edge_succ (e, l0_bb);
3342      e->flags = EDGE_FALLTHRU;
3343    }
3344}
3345
3346
3347/* Expand code for an OpenMP single directive.  We've already expanded
3348   much of the code, here we simply place the GOMP_barrier call.  */
3349
3350static void
3351expand_omp_single (struct omp_region *region)
3352{
3353  basic_block entry_bb, exit_bb;
3354  block_stmt_iterator si;
3355  bool need_barrier = false;
3356
3357  entry_bb = region->entry;
3358  exit_bb = region->exit;
3359
3360  si = bsi_last (entry_bb);
3361  /* The terminal barrier at the end of a GOMP_single_copy sequence cannot
3362     be removed.  We need to ensure that the thread that entered the single
3363     does not exit before the data is copied out by the other threads.  */
3364  if (find_omp_clause (OMP_SINGLE_CLAUSES (bsi_stmt (si)),
3365		       OMP_CLAUSE_COPYPRIVATE))
3366    need_barrier = true;
3367  gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_SINGLE);
3368  bsi_remove (&si, true);
3369  single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
3370
3371  si = bsi_last (exit_bb);
3372  if (!OMP_RETURN_NOWAIT (bsi_stmt (si)) || need_barrier)
3373    {
3374      tree t = alloc_stmt_list ();
3375      build_omp_barrier (&t);
3376      bsi_insert_after (&si, t, BSI_SAME_STMT);
3377    }
3378  bsi_remove (&si, true);
3379  single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
3380}
3381
3382
3383/* Generic expansion for OpenMP synchronization directives: master,
3384   ordered and critical.  All we need to do here is remove the entry
3385   and exit markers for REGION.  */
3386
3387static void
3388expand_omp_synch (struct omp_region *region)
3389{
3390  basic_block entry_bb, exit_bb;
3391  block_stmt_iterator si;
3392
3393  entry_bb = region->entry;
3394  exit_bb = region->exit;
3395
3396  si = bsi_last (entry_bb);
3397  gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_SINGLE
3398	      || TREE_CODE (bsi_stmt (si)) == OMP_MASTER
3399	      || TREE_CODE (bsi_stmt (si)) == OMP_ORDERED
3400	      || TREE_CODE (bsi_stmt (si)) == OMP_CRITICAL);
3401  bsi_remove (&si, true);
3402  single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
3403
3404  if (exit_bb)
3405    {
3406      si = bsi_last (exit_bb);
3407      gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_RETURN);
3408      bsi_remove (&si, true);
3409      single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
3410    }
3411}
3412
3413
3414/* Expand the parallel region tree rooted at REGION.  Expansion
3415   proceeds in depth-first order.  Innermost regions are expanded
3416   first.  This way, parallel regions that require a new function to
3417   be created (e.g., OMP_PARALLEL) can be expanded without having any
3418   internal dependencies in their body.  */
3419
3420static void
3421expand_omp (struct omp_region *region)
3422{
3423  while (region)
3424    {
3425      if (region->inner)
3426	expand_omp (region->inner);
3427
3428      switch (region->type)
3429	{
3430	case OMP_PARALLEL:
3431	  expand_omp_parallel (region);
3432	  break;
3433
3434	case OMP_FOR:
3435	  expand_omp_for (region);
3436	  break;
3437
3438	case OMP_SECTIONS:
3439	  expand_omp_sections (region);
3440	  break;
3441
3442	case OMP_SECTION:
3443	  /* Individual omp sections are handled together with their
3444	     parent OMP_SECTIONS region.  */
3445	  break;
3446
3447	case OMP_SINGLE:
3448	  expand_omp_single (region);
3449	  break;
3450
3451	case OMP_MASTER:
3452	case OMP_ORDERED:
3453	case OMP_CRITICAL:
3454	  expand_omp_synch (region);
3455	  break;
3456
3457	default:
3458	  gcc_unreachable ();
3459	}
3460
3461      region = region->next;
3462    }
3463}
3464
3465
3466/* Helper for build_omp_regions.  Scan the dominator tree starting at
3467   block BB.  PARENT is the region that contains BB.  */
3468
3469static void
3470build_omp_regions_1 (basic_block bb, struct omp_region *parent)
3471{
3472  block_stmt_iterator si;
3473  tree stmt;
3474  basic_block son;
3475
3476  si = bsi_last (bb);
3477  if (!bsi_end_p (si) && OMP_DIRECTIVE_P (bsi_stmt (si)))
3478    {
3479      struct omp_region *region;
3480      enum tree_code code;
3481
3482      stmt = bsi_stmt (si);
3483      code = TREE_CODE (stmt);
3484
3485      if (code == OMP_RETURN)
3486	{
3487	  /* STMT is the return point out of region PARENT.  Mark it
3488	     as the exit point and make PARENT the immediately
3489	     enclosing region.  */
3490	  gcc_assert (parent);
3491	  region = parent;
3492	  region->exit = bb;
3493	  parent = parent->outer;
3494
3495	  /* If REGION is a parallel region, determine whether it is
3496	     a combined parallel+workshare region.  */
3497	  if (region->type == OMP_PARALLEL)
3498	    determine_parallel_type (region);
3499	}
3500      else if (code == OMP_CONTINUE)
3501	{
3502	  gcc_assert (parent);
3503	  parent->cont = bb;
3504	}
3505      else
3506	{
3507	  /* Otherwise, this directive becomes the parent for a new
3508	     region.  */
3509	  region = new_omp_region (bb, code, parent);
3510	  parent = region;
3511	}
3512    }
3513
3514  for (son = first_dom_son (CDI_DOMINATORS, bb);
3515       son;
3516       son = next_dom_son (CDI_DOMINATORS, son))
3517    build_omp_regions_1 (son, parent);
3518}
3519
3520
3521/* Scan the CFG and build a tree of OMP regions.  Return the root of
3522   the OMP region tree.  */
3523
3524static void
3525build_omp_regions (void)
3526{
3527  gcc_assert (root_omp_region == NULL);
3528  calculate_dominance_info (CDI_DOMINATORS);
3529  build_omp_regions_1 (ENTRY_BLOCK_PTR, NULL);
3530}
3531
3532
3533/* Main entry point for expanding OMP-GIMPLE into runtime calls.  */
3534
3535static unsigned int
3536execute_expand_omp (void)
3537{
3538  build_omp_regions ();
3539
3540  if (!root_omp_region)
3541    return 0;
3542
3543  if (dump_file)
3544    {
3545      fprintf (dump_file, "\nOMP region tree\n\n");
3546      dump_omp_region (dump_file, root_omp_region, 0);
3547      fprintf (dump_file, "\n");
3548    }
3549
3550  remove_exit_barriers (root_omp_region);
3551
3552  expand_omp (root_omp_region);
3553
3554  free_dominance_info (CDI_DOMINATORS);
3555  free_dominance_info (CDI_POST_DOMINATORS);
3556  cleanup_tree_cfg ();
3557
3558  free_omp_regions ();
3559
3560  return 0;
3561}
3562
3563static bool
3564gate_expand_omp (void)
3565{
3566  return flag_openmp != 0 && errorcount == 0;
3567}
3568
3569struct tree_opt_pass pass_expand_omp =
3570{
3571  "ompexp",				/* name */
3572  gate_expand_omp,			/* gate */
3573  execute_expand_omp,			/* execute */
3574  NULL,					/* sub */
3575  NULL,					/* next */
3576  0,					/* static_pass_number */
3577  0,					/* tv_id */
3578  PROP_gimple_any,			/* properties_required */
3579  PROP_gimple_lomp,			/* properties_provided */
3580  0,					/* properties_destroyed */
3581  0,					/* todo_flags_start */
3582  TODO_dump_func,			/* todo_flags_finish */
3583  0					/* letter */
3584};
3585
3586/* Routines to lower OpenMP directives into OMP-GIMPLE.  */
3587
3588/* Lower the OpenMP sections directive in *STMT_P.  */
3589
3590static void
3591lower_omp_sections (tree *stmt_p, omp_context *ctx)
3592{
3593  tree new_stmt, stmt, body, bind, block, ilist, olist, new_body;
3594  tree t, dlist;
3595  tree_stmt_iterator tsi;
3596  unsigned i, len;
3597
3598  stmt = *stmt_p;
3599
3600  push_gimplify_context ();
3601
3602  dlist = NULL;
3603  ilist = NULL;
3604  lower_rec_input_clauses (OMP_SECTIONS_CLAUSES (stmt), &ilist, &dlist, ctx);
3605
3606  tsi = tsi_start (OMP_SECTIONS_BODY (stmt));
3607  for (len = 0; !tsi_end_p (tsi); len++, tsi_next (&tsi))
3608    continue;
3609
3610  tsi = tsi_start (OMP_SECTIONS_BODY (stmt));
3611  body = alloc_stmt_list ();
3612  for (i = 0; i < len; i++, tsi_next (&tsi))
3613    {
3614      omp_context *sctx;
3615      tree sec_start, sec_end;
3616
3617      sec_start = tsi_stmt (tsi);
3618      sctx = maybe_lookup_ctx (sec_start);
3619      gcc_assert (sctx);
3620
3621      append_to_statement_list (sec_start, &body);
3622
3623      lower_omp (&OMP_SECTION_BODY (sec_start), sctx);
3624      append_to_statement_list (OMP_SECTION_BODY (sec_start), &body);
3625      OMP_SECTION_BODY (sec_start) = NULL;
3626
3627      if (i == len - 1)
3628	{
3629	  tree l = alloc_stmt_list ();
3630	  lower_lastprivate_clauses (OMP_SECTIONS_CLAUSES (stmt), NULL,
3631				     &l, ctx);
3632	  append_to_statement_list (l, &body);
3633	  OMP_SECTION_LAST (sec_start) = 1;
3634	}
3635
3636      sec_end = make_node (OMP_RETURN);
3637      append_to_statement_list (sec_end, &body);
3638    }
3639
3640  block = make_node (BLOCK);
3641  bind = build3 (BIND_EXPR, void_type_node, NULL, body, block);
3642
3643  olist = NULL_TREE;
3644  lower_reduction_clauses (OMP_SECTIONS_CLAUSES (stmt), &olist, ctx);
3645
3646  pop_gimplify_context (NULL_TREE);
3647  record_vars_into (ctx->block_vars, ctx->cb.dst_fn);
3648
3649  new_stmt = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
3650  TREE_SIDE_EFFECTS (new_stmt) = 1;
3651
3652  new_body = alloc_stmt_list ();
3653  append_to_statement_list (ilist, &new_body);
3654  append_to_statement_list (stmt, &new_body);
3655  append_to_statement_list (bind, &new_body);
3656
3657  t = make_node (OMP_CONTINUE);
3658  append_to_statement_list (t, &new_body);
3659
3660  append_to_statement_list (olist, &new_body);
3661  append_to_statement_list (dlist, &new_body);
3662
3663  maybe_catch_exception (&new_body);
3664
3665  t = make_node (OMP_RETURN);
3666  OMP_RETURN_NOWAIT (t) = !!find_omp_clause (OMP_SECTIONS_CLAUSES (stmt),
3667					     OMP_CLAUSE_NOWAIT);
3668  append_to_statement_list (t, &new_body);
3669
3670  BIND_EXPR_BODY (new_stmt) = new_body;
3671  OMP_SECTIONS_BODY (stmt) = NULL;
3672
3673  *stmt_p = new_stmt;
3674}
3675
3676
3677/* A subroutine of lower_omp_single.  Expand the simple form of
3678   an OMP_SINGLE, without a copyprivate clause:
3679
3680     	if (GOMP_single_start ())
3681	  BODY;
3682	[ GOMP_barrier (); ]	-> unless 'nowait' is present.
3683
3684  FIXME.  It may be better to delay expanding the logic of this until
3685  pass_expand_omp.  The expanded logic may make the job more difficult
3686  to a synchronization analysis pass.  */
3687
3688static void
3689lower_omp_single_simple (tree single_stmt, tree *pre_p)
3690{
3691  tree t;
3692
3693  t = built_in_decls[BUILT_IN_GOMP_SINGLE_START];
3694  t = build_function_call_expr (t, NULL);
3695  t = build3 (COND_EXPR, void_type_node, t,
3696	      OMP_SINGLE_BODY (single_stmt), NULL);
3697  gimplify_and_add (t, pre_p);
3698}
3699
3700
3701/* A subroutine of lower_omp_single.  Expand the simple form of
3702   an OMP_SINGLE, with a copyprivate clause:
3703
3704	#pragma omp single copyprivate (a, b, c)
3705
3706   Create a new structure to hold copies of 'a', 'b' and 'c' and emit:
3707
3708      {
3709	if ((copyout_p = GOMP_single_copy_start ()) == NULL)
3710	  {
3711	    BODY;
3712	    copyout.a = a;
3713	    copyout.b = b;
3714	    copyout.c = c;
3715	    GOMP_single_copy_end (&copyout);
3716	  }
3717	else
3718	  {
3719	    a = copyout_p->a;
3720	    b = copyout_p->b;
3721	    c = copyout_p->c;
3722	  }
3723	GOMP_barrier ();
3724      }
3725
3726  FIXME.  It may be better to delay expanding the logic of this until
3727  pass_expand_omp.  The expanded logic may make the job more difficult
3728  to a synchronization analysis pass.  */
3729
3730static void
3731lower_omp_single_copy (tree single_stmt, tree *pre_p, omp_context *ctx)
3732{
3733  tree ptr_type, t, args, l0, l1, l2, copyin_seq;
3734
3735  ctx->sender_decl = create_tmp_var (ctx->record_type, ".omp_copy_o");
3736
3737  ptr_type = build_pointer_type (ctx->record_type);
3738  ctx->receiver_decl = create_tmp_var (ptr_type, ".omp_copy_i");
3739
3740  l0 = create_artificial_label ();
3741  l1 = create_artificial_label ();
3742  l2 = create_artificial_label ();
3743
3744  t = built_in_decls[BUILT_IN_GOMP_SINGLE_COPY_START];
3745  t = build_function_call_expr (t, NULL);
3746  t = fold_convert (ptr_type, t);
3747  t = build2 (MODIFY_EXPR, void_type_node, ctx->receiver_decl, t);
3748  gimplify_and_add (t, pre_p);
3749
3750  t = build2 (EQ_EXPR, boolean_type_node, ctx->receiver_decl,
3751	      build_int_cst (ptr_type, 0));
3752  t = build3 (COND_EXPR, void_type_node, t,
3753	      build_and_jump (&l0), build_and_jump (&l1));
3754  gimplify_and_add (t, pre_p);
3755
3756  t = build1 (LABEL_EXPR, void_type_node, l0);
3757  gimplify_and_add (t, pre_p);
3758
3759  append_to_statement_list (OMP_SINGLE_BODY (single_stmt), pre_p);
3760
3761  copyin_seq = NULL;
3762  lower_copyprivate_clauses (OMP_SINGLE_CLAUSES (single_stmt), pre_p,
3763			      &copyin_seq, ctx);
3764
3765  t = build_fold_addr_expr (ctx->sender_decl);
3766  args = tree_cons (NULL, t, NULL);
3767  t = built_in_decls[BUILT_IN_GOMP_SINGLE_COPY_END];
3768  t = build_function_call_expr (t, args);
3769  gimplify_and_add (t, pre_p);
3770
3771  t = build_and_jump (&l2);
3772  gimplify_and_add (t, pre_p);
3773
3774  t = build1 (LABEL_EXPR, void_type_node, l1);
3775  gimplify_and_add (t, pre_p);
3776
3777  append_to_statement_list (copyin_seq, pre_p);
3778
3779  t = build1 (LABEL_EXPR, void_type_node, l2);
3780  gimplify_and_add (t, pre_p);
3781}
3782
3783
3784/* Expand code for an OpenMP single directive.  */
3785
3786static void
3787lower_omp_single (tree *stmt_p, omp_context *ctx)
3788{
3789  tree t, bind, block, single_stmt = *stmt_p, dlist;
3790
3791  push_gimplify_context ();
3792
3793  block = make_node (BLOCK);
3794  *stmt_p = bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, block);
3795  TREE_SIDE_EFFECTS (bind) = 1;
3796
3797  lower_rec_input_clauses (OMP_SINGLE_CLAUSES (single_stmt),
3798			   &BIND_EXPR_BODY (bind), &dlist, ctx);
3799  lower_omp (&OMP_SINGLE_BODY (single_stmt), ctx);
3800
3801  append_to_statement_list (single_stmt, &BIND_EXPR_BODY (bind));
3802
3803  if (ctx->record_type)
3804    lower_omp_single_copy (single_stmt, &BIND_EXPR_BODY (bind), ctx);
3805  else
3806    lower_omp_single_simple (single_stmt, &BIND_EXPR_BODY (bind));
3807
3808  OMP_SINGLE_BODY (single_stmt) = NULL;
3809
3810  append_to_statement_list (dlist, &BIND_EXPR_BODY (bind));
3811
3812  maybe_catch_exception (&BIND_EXPR_BODY (bind));
3813
3814  t = make_node (OMP_RETURN);
3815  OMP_RETURN_NOWAIT (t) = !!find_omp_clause (OMP_SINGLE_CLAUSES (single_stmt),
3816					     OMP_CLAUSE_NOWAIT);
3817  append_to_statement_list (t, &BIND_EXPR_BODY (bind));
3818
3819  pop_gimplify_context (bind);
3820
3821  BIND_EXPR_VARS (bind) = chainon (BIND_EXPR_VARS (bind), ctx->block_vars);
3822  BLOCK_VARS (block) = BIND_EXPR_VARS (bind);
3823}
3824
3825
3826/* Expand code for an OpenMP master directive.  */
3827
3828static void
3829lower_omp_master (tree *stmt_p, omp_context *ctx)
3830{
3831  tree bind, block, stmt = *stmt_p, lab = NULL, x;
3832
3833  push_gimplify_context ();
3834
3835  block = make_node (BLOCK);
3836  *stmt_p = bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, block);
3837  TREE_SIDE_EFFECTS (bind) = 1;
3838
3839  append_to_statement_list (stmt, &BIND_EXPR_BODY (bind));
3840
3841  x = built_in_decls[BUILT_IN_OMP_GET_THREAD_NUM];
3842  x = build_function_call_expr (x, NULL);
3843  x = build2 (EQ_EXPR, boolean_type_node, x, integer_zero_node);
3844  x = build3 (COND_EXPR, void_type_node, x, NULL, build_and_jump (&lab));
3845  gimplify_and_add (x, &BIND_EXPR_BODY (bind));
3846
3847  lower_omp (&OMP_MASTER_BODY (stmt), ctx);
3848  maybe_catch_exception (&OMP_MASTER_BODY (stmt));
3849  append_to_statement_list (OMP_MASTER_BODY (stmt), &BIND_EXPR_BODY (bind));
3850  OMP_MASTER_BODY (stmt) = NULL;
3851
3852  x = build1 (LABEL_EXPR, void_type_node, lab);
3853  gimplify_and_add (x, &BIND_EXPR_BODY (bind));
3854
3855  x = make_node (OMP_RETURN);
3856  OMP_RETURN_NOWAIT (x) = 1;
3857  append_to_statement_list (x, &BIND_EXPR_BODY (bind));
3858
3859  pop_gimplify_context (bind);
3860
3861  BIND_EXPR_VARS (bind) = chainon (BIND_EXPR_VARS (bind), ctx->block_vars);
3862  BLOCK_VARS (block) = BIND_EXPR_VARS (bind);
3863}
3864
3865
3866/* Expand code for an OpenMP ordered directive.  */
3867
3868static void
3869lower_omp_ordered (tree *stmt_p, omp_context *ctx)
3870{
3871  tree bind, block, stmt = *stmt_p, x;
3872
3873  push_gimplify_context ();
3874
3875  block = make_node (BLOCK);
3876  *stmt_p = bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, block);
3877  TREE_SIDE_EFFECTS (bind) = 1;
3878
3879  append_to_statement_list (stmt, &BIND_EXPR_BODY (bind));
3880
3881  x = built_in_decls[BUILT_IN_GOMP_ORDERED_START];
3882  x = build_function_call_expr (x, NULL);
3883  gimplify_and_add (x, &BIND_EXPR_BODY (bind));
3884
3885  lower_omp (&OMP_ORDERED_BODY (stmt), ctx);
3886  maybe_catch_exception (&OMP_ORDERED_BODY (stmt));
3887  append_to_statement_list (OMP_ORDERED_BODY (stmt), &BIND_EXPR_BODY (bind));
3888  OMP_ORDERED_BODY (stmt) = NULL;
3889
3890  x = built_in_decls[BUILT_IN_GOMP_ORDERED_END];
3891  x = build_function_call_expr (x, NULL);
3892  gimplify_and_add (x, &BIND_EXPR_BODY (bind));
3893
3894  x = make_node (OMP_RETURN);
3895  OMP_RETURN_NOWAIT (x) = 1;
3896  append_to_statement_list (x, &BIND_EXPR_BODY (bind));
3897
3898  pop_gimplify_context (bind);
3899
3900  BIND_EXPR_VARS (bind) = chainon (BIND_EXPR_VARS (bind), ctx->block_vars);
3901  BLOCK_VARS (block) = BIND_EXPR_VARS (bind);
3902}
3903
3904
3905/* Gimplify an OMP_CRITICAL statement.  This is a relatively simple
3906   substitution of a couple of function calls.  But in the NAMED case,
3907   requires that languages coordinate a symbol name.  It is therefore
3908   best put here in common code.  */
3909
3910static GTY((param1_is (tree), param2_is (tree)))
3911  splay_tree critical_name_mutexes;
3912
3913static void
3914lower_omp_critical (tree *stmt_p, omp_context *ctx)
3915{
3916  tree bind, block, stmt = *stmt_p;
3917  tree t, lock, unlock, name;
3918
3919  name = OMP_CRITICAL_NAME (stmt);
3920  if (name)
3921    {
3922      tree decl, args;
3923      splay_tree_node n;
3924
3925      if (!critical_name_mutexes)
3926	critical_name_mutexes
3927	  = splay_tree_new_ggc (splay_tree_compare_pointers);
3928
3929      n = splay_tree_lookup (critical_name_mutexes, (splay_tree_key) name);
3930      if (n == NULL)
3931	{
3932	  char *new_str;
3933
3934	  decl = create_tmp_var_raw (ptr_type_node, NULL);
3935
3936	  new_str = ACONCAT ((".gomp_critical_user_",
3937			      IDENTIFIER_POINTER (name), NULL));
3938	  DECL_NAME (decl) = get_identifier (new_str);
3939	  TREE_PUBLIC (decl) = 1;
3940	  TREE_STATIC (decl) = 1;
3941	  DECL_COMMON (decl) = 1;
3942	  DECL_ARTIFICIAL (decl) = 1;
3943	  DECL_IGNORED_P (decl) = 1;
3944	  cgraph_varpool_finalize_decl (decl);
3945
3946	  splay_tree_insert (critical_name_mutexes, (splay_tree_key) name,
3947			     (splay_tree_value) decl);
3948	}
3949      else
3950	decl = (tree) n->value;
3951
3952      args = tree_cons (NULL, build_fold_addr_expr (decl), NULL);
3953      lock = built_in_decls[BUILT_IN_GOMP_CRITICAL_NAME_START];
3954      lock = build_function_call_expr (lock, args);
3955
3956      args = tree_cons (NULL, build_fold_addr_expr (decl), NULL);
3957      unlock = built_in_decls[BUILT_IN_GOMP_CRITICAL_NAME_END];
3958      unlock = build_function_call_expr (unlock, args);
3959    }
3960  else
3961    {
3962      lock = built_in_decls[BUILT_IN_GOMP_CRITICAL_START];
3963      lock = build_function_call_expr (lock, NULL);
3964
3965      unlock = built_in_decls[BUILT_IN_GOMP_CRITICAL_END];
3966      unlock = build_function_call_expr (unlock, NULL);
3967    }
3968
3969  push_gimplify_context ();
3970
3971  block = make_node (BLOCK);
3972  *stmt_p = bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, block);
3973  TREE_SIDE_EFFECTS (bind) = 1;
3974
3975  append_to_statement_list (stmt, &BIND_EXPR_BODY (bind));
3976
3977  gimplify_and_add (lock, &BIND_EXPR_BODY (bind));
3978
3979  lower_omp (&OMP_CRITICAL_BODY (stmt), ctx);
3980  maybe_catch_exception (&OMP_CRITICAL_BODY (stmt));
3981  append_to_statement_list (OMP_CRITICAL_BODY (stmt), &BIND_EXPR_BODY (bind));
3982  OMP_CRITICAL_BODY (stmt) = NULL;
3983
3984  gimplify_and_add (unlock, &BIND_EXPR_BODY (bind));
3985
3986  t = make_node (OMP_RETURN);
3987  OMP_RETURN_NOWAIT (t) = 1;
3988  append_to_statement_list (t, &BIND_EXPR_BODY (bind));
3989
3990  pop_gimplify_context (bind);
3991  BIND_EXPR_VARS (bind) = chainon (BIND_EXPR_VARS (bind), ctx->block_vars);
3992  BLOCK_VARS (block) = BIND_EXPR_VARS (bind);
3993}
3994
3995
3996/* A subroutine of lower_omp_for.  Generate code to emit the predicate
3997   for a lastprivate clause.  Given a loop control predicate of (V
3998   cond N2), we gate the clause on (!(V cond N2)).  The lowered form
3999   is appended to *DLIST, iterator initialization is appended to
4000   *BODY_P.  */
4001
4002static void
4003lower_omp_for_lastprivate (struct omp_for_data *fd, tree *body_p,
4004			   tree *dlist, struct omp_context *ctx)
4005{
4006  tree clauses, cond, stmts, vinit, t;
4007  enum tree_code cond_code;
4008
4009  cond_code = fd->cond_code;
4010  cond_code = cond_code == LT_EXPR ? GE_EXPR : LE_EXPR;
4011
4012  /* When possible, use a strict equality expression.  This can let VRP
4013     type optimizations deduce the value and remove a copy.  */
4014  if (host_integerp (fd->step, 0))
4015    {
4016      HOST_WIDE_INT step = TREE_INT_CST_LOW (fd->step);
4017      if (step == 1 || step == -1)
4018	cond_code = EQ_EXPR;
4019    }
4020
4021  cond = build2 (cond_code, boolean_type_node, fd->v, fd->n2);
4022
4023  clauses = OMP_FOR_CLAUSES (fd->for_stmt);
4024  stmts = NULL;
4025  lower_lastprivate_clauses (clauses, cond, &stmts, ctx);
4026  if (stmts != NULL)
4027    {
4028      append_to_statement_list (stmts, dlist);
4029
4030      /* Optimize: v = 0; is usually cheaper than v = some_other_constant.  */
4031      vinit = fd->n1;
4032      if (cond_code == EQ_EXPR
4033	  && host_integerp (fd->n2, 0)
4034	  && ! integer_zerop (fd->n2))
4035	vinit = build_int_cst (TREE_TYPE (fd->v), 0);
4036
4037      /* Initialize the iterator variable, so that threads that don't execute
4038	 any iterations don't execute the lastprivate clauses by accident.  */
4039      t = build2 (MODIFY_EXPR, void_type_node, fd->v, vinit);
4040      gimplify_and_add (t, body_p);
4041    }
4042}
4043
4044
4045/* Lower code for an OpenMP loop directive.  */
4046
4047static void
4048lower_omp_for (tree *stmt_p, omp_context *ctx)
4049{
4050  tree t, stmt, ilist, dlist, new_stmt, *body_p, *rhs_p;
4051  struct omp_for_data fd;
4052
4053  stmt = *stmt_p;
4054
4055  push_gimplify_context ();
4056
4057  lower_omp (&OMP_FOR_PRE_BODY (stmt), ctx);
4058  lower_omp (&OMP_FOR_BODY (stmt), ctx);
4059
4060  /* Move declaration of temporaries in the loop body before we make
4061     it go away.  */
4062  if (TREE_CODE (OMP_FOR_BODY (stmt)) == BIND_EXPR)
4063    record_vars_into (BIND_EXPR_VARS (OMP_FOR_BODY (stmt)), ctx->cb.dst_fn);
4064
4065  new_stmt = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
4066  TREE_SIDE_EFFECTS (new_stmt) = 1;
4067  body_p = &BIND_EXPR_BODY (new_stmt);
4068
4069  /* The pre-body and input clauses go before the lowered OMP_FOR.  */
4070  ilist = NULL;
4071  dlist = NULL;
4072  append_to_statement_list (OMP_FOR_PRE_BODY (stmt), body_p);
4073  lower_rec_input_clauses (OMP_FOR_CLAUSES (stmt), body_p, &dlist, ctx);
4074
4075  /* Lower the header expressions.  At this point, we can assume that
4076     the header is of the form:
4077
4078     	#pragma omp for (V = VAL1; V {<|>|<=|>=} VAL2; V = V [+-] VAL3)
4079
4080     We just need to make sure that VAL1, VAL2 and VAL3 are lowered
4081     using the .omp_data_s mapping, if needed.  */
4082  rhs_p = &TREE_OPERAND (OMP_FOR_INIT (stmt), 1);
4083  if (!is_gimple_min_invariant (*rhs_p))
4084    *rhs_p = get_formal_tmp_var (*rhs_p, body_p);
4085
4086  rhs_p = &TREE_OPERAND (OMP_FOR_COND (stmt), 1);
4087  if (!is_gimple_min_invariant (*rhs_p))
4088    *rhs_p = get_formal_tmp_var (*rhs_p, body_p);
4089
4090  rhs_p = &TREE_OPERAND (TREE_OPERAND (OMP_FOR_INCR (stmt), 1), 1);
4091  if (!is_gimple_min_invariant (*rhs_p))
4092    *rhs_p = get_formal_tmp_var (*rhs_p, body_p);
4093
4094  /* Once lowered, extract the bounds and clauses.  */
4095  extract_omp_for_data (stmt, &fd);
4096
4097  lower_omp_for_lastprivate (&fd, body_p, &dlist, ctx);
4098
4099  append_to_statement_list (stmt, body_p);
4100
4101  append_to_statement_list (OMP_FOR_BODY (stmt), body_p);
4102
4103  t = make_node (OMP_CONTINUE);
4104  append_to_statement_list (t, body_p);
4105
4106  /* After the loop, add exit clauses.  */
4107  lower_reduction_clauses (OMP_FOR_CLAUSES (stmt), body_p, ctx);
4108  append_to_statement_list (dlist, body_p);
4109
4110  maybe_catch_exception (body_p);
4111
4112  /* Region exit marker goes at the end of the loop body.  */
4113  t = make_node (OMP_RETURN);
4114  OMP_RETURN_NOWAIT (t) = fd.have_nowait;
4115  append_to_statement_list (t, body_p);
4116
4117  pop_gimplify_context (NULL_TREE);
4118  record_vars_into (ctx->block_vars, ctx->cb.dst_fn);
4119
4120  OMP_FOR_BODY (stmt) = NULL_TREE;
4121  OMP_FOR_PRE_BODY (stmt) = NULL_TREE;
4122  *stmt_p = new_stmt;
4123}
4124
4125/* Callback for walk_stmts.  Check if *TP only contains OMP_FOR
4126   or OMP_PARALLEL.  */
4127
4128static tree
4129check_combined_parallel (tree *tp, int *walk_subtrees, void *data)
4130{
4131  struct walk_stmt_info *wi = data;
4132  int *info = wi->info;
4133
4134  *walk_subtrees = 0;
4135  switch (TREE_CODE (*tp))
4136    {
4137    case OMP_FOR:
4138    case OMP_SECTIONS:
4139      *info = *info == 0 ? 1 : -1;
4140      break;
4141    default:
4142      *info = -1;
4143      break;
4144    }
4145  return NULL;
4146}
4147
4148/* Lower the OpenMP parallel directive in *STMT_P.  CTX holds context
4149   information for the directive.  */
4150
4151static void
4152lower_omp_parallel (tree *stmt_p, omp_context *ctx)
4153{
4154  tree clauses, par_bind, par_body, new_body, bind;
4155  tree olist, ilist, par_olist, par_ilist;
4156  tree stmt, child_fn, t;
4157
4158  stmt = *stmt_p;
4159
4160  clauses = OMP_PARALLEL_CLAUSES (stmt);
4161  par_bind = OMP_PARALLEL_BODY (stmt);
4162  par_body = BIND_EXPR_BODY (par_bind);
4163  child_fn = ctx->cb.dst_fn;
4164  if (!OMP_PARALLEL_COMBINED (stmt))
4165    {
4166      struct walk_stmt_info wi;
4167      int ws_num = 0;
4168
4169      memset (&wi, 0, sizeof (wi));
4170      wi.callback = check_combined_parallel;
4171      wi.info = &ws_num;
4172      wi.val_only = true;
4173      walk_stmts (&wi, &par_bind);
4174      if (ws_num == 1)
4175	OMP_PARALLEL_COMBINED (stmt) = 1;
4176    }
4177
4178  push_gimplify_context ();
4179
4180  par_olist = NULL_TREE;
4181  par_ilist = NULL_TREE;
4182  lower_rec_input_clauses (clauses, &par_ilist, &par_olist, ctx);
4183  lower_omp (&par_body, ctx);
4184  lower_reduction_clauses (clauses, &par_olist, ctx);
4185
4186  /* Declare all the variables created by mapping and the variables
4187     declared in the scope of the parallel body.  */
4188  record_vars_into (ctx->block_vars, child_fn);
4189  record_vars_into (BIND_EXPR_VARS (par_bind), child_fn);
4190
4191  if (ctx->record_type)
4192    {
4193      ctx->sender_decl = create_tmp_var (ctx->record_type, ".omp_data_o");
4194      OMP_PARALLEL_DATA_ARG (stmt) = ctx->sender_decl;
4195    }
4196
4197  olist = NULL_TREE;
4198  ilist = NULL_TREE;
4199  lower_send_clauses (clauses, &ilist, &olist, ctx);
4200  lower_send_shared_vars (&ilist, &olist, ctx);
4201
4202  /* Once all the expansions are done, sequence all the different
4203     fragments inside OMP_PARALLEL_BODY.  */
4204  bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
4205  append_to_statement_list (ilist, &BIND_EXPR_BODY (bind));
4206
4207  new_body = alloc_stmt_list ();
4208
4209  if (ctx->record_type)
4210    {
4211      t = build_fold_addr_expr (ctx->sender_decl);
4212      /* fixup_child_record_type might have changed receiver_decl's type.  */
4213      t = fold_convert (TREE_TYPE (ctx->receiver_decl), t);
4214      t = build2 (MODIFY_EXPR, void_type_node, ctx->receiver_decl, t);
4215      append_to_statement_list (t, &new_body);
4216    }
4217
4218  append_to_statement_list (par_ilist, &new_body);
4219  append_to_statement_list (par_body, &new_body);
4220  append_to_statement_list (par_olist, &new_body);
4221  maybe_catch_exception (&new_body);
4222  t = make_node (OMP_RETURN);
4223  append_to_statement_list (t, &new_body);
4224  OMP_PARALLEL_BODY (stmt) = new_body;
4225
4226  append_to_statement_list (stmt, &BIND_EXPR_BODY (bind));
4227  append_to_statement_list (olist, &BIND_EXPR_BODY (bind));
4228
4229  *stmt_p = bind;
4230
4231  pop_gimplify_context (NULL_TREE);
4232}
4233
4234
4235/* Pass *TP back through the gimplifier within the context determined by WI.
4236   This handles replacement of DECL_VALUE_EXPR, as well as adjusting the
4237   flags on ADDR_EXPR.  */
4238
4239static void
4240lower_regimplify (tree *tp, struct walk_stmt_info *wi)
4241{
4242  enum gimplify_status gs;
4243  tree pre = NULL;
4244
4245  if (wi->is_lhs)
4246    gs = gimplify_expr (tp, &pre, NULL, is_gimple_lvalue, fb_lvalue);
4247  else if (wi->val_only)
4248    gs = gimplify_expr (tp, &pre, NULL, is_gimple_val, fb_rvalue);
4249  else
4250    gs = gimplify_expr (tp, &pre, NULL, is_gimple_formal_tmp_var, fb_rvalue);
4251  gcc_assert (gs == GS_ALL_DONE);
4252
4253  if (pre)
4254    tsi_link_before (&wi->tsi, pre, TSI_SAME_STMT);
4255}
4256
4257/* Copy EXP into a temporary.  Insert the initialization statement before TSI.  */
4258
4259static tree
4260init_tmp_var (tree exp, tree_stmt_iterator *tsi)
4261{
4262  tree t, stmt;
4263
4264  t = create_tmp_var (TREE_TYPE (exp), NULL);
4265  if (TREE_CODE (TREE_TYPE (t)) == COMPLEX_TYPE)
4266    DECL_COMPLEX_GIMPLE_REG_P (t) = 1;
4267  stmt = build2 (MODIFY_EXPR, TREE_TYPE (t), t, exp);
4268  SET_EXPR_LOCUS (stmt, EXPR_LOCUS (tsi_stmt (*tsi)));
4269  tsi_link_before (tsi, stmt, TSI_SAME_STMT);
4270
4271  return t;
4272}
4273
4274/* Similarly, but copy from the temporary and insert the statement
4275   after the iterator.  */
4276
4277static tree
4278save_tmp_var (tree exp, tree_stmt_iterator *tsi)
4279{
4280  tree t, stmt;
4281
4282  t = create_tmp_var (TREE_TYPE (exp), NULL);
4283  if (TREE_CODE (TREE_TYPE (t)) == COMPLEX_TYPE)
4284    DECL_COMPLEX_GIMPLE_REG_P (t) = 1;
4285  stmt = build2 (MODIFY_EXPR, TREE_TYPE (t), exp, t);
4286  SET_EXPR_LOCUS (stmt, EXPR_LOCUS (tsi_stmt (*tsi)));
4287  tsi_link_after (tsi, stmt, TSI_SAME_STMT);
4288
4289  return t;
4290}
4291
4292/* Callback for walk_stmts.  Lower the OpenMP directive pointed by TP.  */
4293
4294static tree
4295lower_omp_1 (tree *tp, int *walk_subtrees, void *data)
4296{
4297  struct walk_stmt_info *wi = data;
4298  omp_context *ctx = wi->info;
4299  tree t = *tp;
4300
4301  /* If we have issued syntax errors, avoid doing any heavy lifting.
4302     Just replace the OpenMP directives with a NOP to avoid
4303     confusing RTL expansion.  */
4304  if (errorcount && OMP_DIRECTIVE_P (*tp))
4305    {
4306      *tp = build_empty_stmt ();
4307      return NULL_TREE;
4308    }
4309
4310  *walk_subtrees = 0;
4311  switch (TREE_CODE (*tp))
4312    {
4313    case OMP_PARALLEL:
4314      ctx = maybe_lookup_ctx (t);
4315      lower_omp_parallel (tp, ctx);
4316      break;
4317
4318    case OMP_FOR:
4319      ctx = maybe_lookup_ctx (t);
4320      gcc_assert (ctx);
4321      lower_omp_for (tp, ctx);
4322      break;
4323
4324    case OMP_SECTIONS:
4325      ctx = maybe_lookup_ctx (t);
4326      gcc_assert (ctx);
4327      lower_omp_sections (tp, ctx);
4328      break;
4329
4330    case OMP_SINGLE:
4331      ctx = maybe_lookup_ctx (t);
4332      gcc_assert (ctx);
4333      lower_omp_single (tp, ctx);
4334      break;
4335
4336    case OMP_MASTER:
4337      ctx = maybe_lookup_ctx (t);
4338      gcc_assert (ctx);
4339      lower_omp_master (tp, ctx);
4340      break;
4341
4342    case OMP_ORDERED:
4343      ctx = maybe_lookup_ctx (t);
4344      gcc_assert (ctx);
4345      lower_omp_ordered (tp, ctx);
4346      break;
4347
4348    case OMP_CRITICAL:
4349      ctx = maybe_lookup_ctx (t);
4350      gcc_assert (ctx);
4351      lower_omp_critical (tp, ctx);
4352      break;
4353
4354    case VAR_DECL:
4355      if (ctx && DECL_HAS_VALUE_EXPR_P (t))
4356	{
4357	  lower_regimplify (&t, wi);
4358	  if (wi->val_only)
4359	    {
4360	      if (wi->is_lhs)
4361		t = save_tmp_var (t, &wi->tsi);
4362	      else
4363		t = init_tmp_var (t, &wi->tsi);
4364	    }
4365	  *tp = t;
4366	}
4367      break;
4368
4369    case ADDR_EXPR:
4370      if (ctx)
4371	lower_regimplify (tp, wi);
4372      break;
4373
4374    case ARRAY_REF:
4375    case ARRAY_RANGE_REF:
4376    case REALPART_EXPR:
4377    case IMAGPART_EXPR:
4378    case COMPONENT_REF:
4379    case VIEW_CONVERT_EXPR:
4380      if (ctx)
4381	lower_regimplify (tp, wi);
4382      break;
4383
4384    case INDIRECT_REF:
4385      if (ctx)
4386	{
4387	  wi->is_lhs = false;
4388	  wi->val_only = true;
4389	  lower_regimplify (&TREE_OPERAND (t, 0), wi);
4390	}
4391      break;
4392
4393    default:
4394      if (!TYPE_P (t) && !DECL_P (t))
4395	*walk_subtrees = 1;
4396      break;
4397    }
4398
4399  return NULL_TREE;
4400}
4401
4402static void
4403lower_omp (tree *stmt_p, omp_context *ctx)
4404{
4405  struct walk_stmt_info wi;
4406
4407  memset (&wi, 0, sizeof (wi));
4408  wi.callback = lower_omp_1;
4409  wi.info = ctx;
4410  wi.val_only = true;
4411  wi.want_locations = true;
4412
4413  walk_stmts (&wi, stmt_p);
4414}
4415
4416/* Main entry point.  */
4417
4418static unsigned int
4419execute_lower_omp (void)
4420{
4421  all_contexts = splay_tree_new (splay_tree_compare_pointers, 0,
4422				 delete_omp_context);
4423
4424  scan_omp (&DECL_SAVED_TREE (current_function_decl), NULL);
4425  gcc_assert (parallel_nesting_level == 0);
4426
4427  if (all_contexts->root)
4428    lower_omp (&DECL_SAVED_TREE (current_function_decl), NULL);
4429
4430  if (all_contexts)
4431    {
4432      splay_tree_delete (all_contexts);
4433      all_contexts = NULL;
4434    }
4435  return 0;
4436}
4437
4438static bool
4439gate_lower_omp (void)
4440{
4441  return flag_openmp != 0;
4442}
4443
4444struct tree_opt_pass pass_lower_omp =
4445{
4446  "omplower",				/* name */
4447  gate_lower_omp,			/* gate */
4448  execute_lower_omp,			/* execute */
4449  NULL,					/* sub */
4450  NULL,					/* next */
4451  0,					/* static_pass_number */
4452  0,					/* tv_id */
4453  PROP_gimple_any,			/* properties_required */
4454  PROP_gimple_lomp,			/* properties_provided */
4455  0,					/* properties_destroyed */
4456  0,					/* todo_flags_start */
4457  TODO_dump_func,			/* todo_flags_finish */
4458  0					/* letter */
4459};
4460
4461/* The following is a utility to diagnose OpenMP structured block violations.
4462   It is not part of the "omplower" pass, as that's invoked too late.  It
4463   should be invoked by the respective front ends after gimplification.  */
4464
4465static splay_tree all_labels;
4466
4467/* Check for mismatched contexts and generate an error if needed.  Return
4468   true if an error is detected.  */
4469
4470static bool
4471diagnose_sb_0 (tree *stmt_p, tree branch_ctx, tree label_ctx)
4472{
4473  bool exit_p = true;
4474
4475  if ((label_ctx ? TREE_VALUE (label_ctx) : NULL) == branch_ctx)
4476    return false;
4477
4478  /* Try to avoid confusing the user by producing and error message
4479     with correct "exit" or "enter" verbage.  We prefer "exit"
4480     unless we can show that LABEL_CTX is nested within BRANCH_CTX.  */
4481  if (branch_ctx == NULL)
4482    exit_p = false;
4483  else
4484    {
4485      while (label_ctx)
4486	{
4487	  if (TREE_VALUE (label_ctx) == branch_ctx)
4488	    {
4489	      exit_p = false;
4490	      break;
4491	    }
4492	  label_ctx = TREE_CHAIN (label_ctx);
4493	}
4494    }
4495
4496  if (exit_p)
4497    error ("invalid exit from OpenMP structured block");
4498  else
4499    error ("invalid entry to OpenMP structured block");
4500
4501  *stmt_p = build_empty_stmt ();
4502  return true;
4503}
4504
4505/* Pass 1: Create a minimal tree of OpenMP structured blocks, and record
4506   where in the tree each label is found.  */
4507
4508static tree
4509diagnose_sb_1 (tree *tp, int *walk_subtrees, void *data)
4510{
4511  struct walk_stmt_info *wi = data;
4512  tree context = (tree) wi->info;
4513  tree inner_context;
4514  tree t = *tp;
4515
4516  *walk_subtrees = 0;
4517  switch (TREE_CODE (t))
4518    {
4519    case OMP_PARALLEL:
4520    case OMP_SECTIONS:
4521    case OMP_SINGLE:
4522      walk_tree (&OMP_CLAUSES (t), diagnose_sb_1, wi, NULL);
4523      /* FALLTHRU */
4524    case OMP_SECTION:
4525    case OMP_MASTER:
4526    case OMP_ORDERED:
4527    case OMP_CRITICAL:
4528      /* The minimal context here is just a tree of statements.  */
4529      inner_context = tree_cons (NULL, t, context);
4530      wi->info = inner_context;
4531      walk_stmts (wi, &OMP_BODY (t));
4532      wi->info = context;
4533      break;
4534
4535    case OMP_FOR:
4536      walk_tree (&OMP_FOR_CLAUSES (t), diagnose_sb_1, wi, NULL);
4537      inner_context = tree_cons (NULL, t, context);
4538      wi->info = inner_context;
4539      walk_tree (&OMP_FOR_INIT (t), diagnose_sb_1, wi, NULL);
4540      walk_tree (&OMP_FOR_COND (t), diagnose_sb_1, wi, NULL);
4541      walk_tree (&OMP_FOR_INCR (t), diagnose_sb_1, wi, NULL);
4542      walk_stmts (wi, &OMP_FOR_PRE_BODY (t));
4543      walk_stmts (wi, &OMP_FOR_BODY (t));
4544      wi->info = context;
4545      break;
4546
4547    case LABEL_EXPR:
4548      splay_tree_insert (all_labels, (splay_tree_key) LABEL_EXPR_LABEL (t),
4549			 (splay_tree_value) context);
4550      break;
4551
4552    default:
4553      break;
4554    }
4555
4556  return NULL_TREE;
4557}
4558
4559/* Pass 2: Check each branch and see if its context differs from that of
4560   the destination label's context.  */
4561
4562static tree
4563diagnose_sb_2 (tree *tp, int *walk_subtrees, void *data)
4564{
4565  struct walk_stmt_info *wi = data;
4566  tree context = (tree) wi->info;
4567  splay_tree_node n;
4568  tree t = *tp;
4569
4570  *walk_subtrees = 0;
4571  switch (TREE_CODE (t))
4572    {
4573    case OMP_PARALLEL:
4574    case OMP_SECTIONS:
4575    case OMP_SINGLE:
4576      walk_tree (&OMP_CLAUSES (t), diagnose_sb_2, wi, NULL);
4577      /* FALLTHRU */
4578    case OMP_SECTION:
4579    case OMP_MASTER:
4580    case OMP_ORDERED:
4581    case OMP_CRITICAL:
4582      wi->info = t;
4583      walk_stmts (wi, &OMP_BODY (t));
4584      wi->info = context;
4585      break;
4586
4587    case OMP_FOR:
4588      walk_tree (&OMP_FOR_CLAUSES (t), diagnose_sb_2, wi, NULL);
4589      wi->info = t;
4590      walk_tree (&OMP_FOR_INIT (t), diagnose_sb_2, wi, NULL);
4591      walk_tree (&OMP_FOR_COND (t), diagnose_sb_2, wi, NULL);
4592      walk_tree (&OMP_FOR_INCR (t), diagnose_sb_2, wi, NULL);
4593      walk_stmts (wi, &OMP_FOR_PRE_BODY (t));
4594      walk_stmts (wi, &OMP_FOR_BODY (t));
4595      wi->info = context;
4596      break;
4597
4598    case GOTO_EXPR:
4599      {
4600	tree lab = GOTO_DESTINATION (t);
4601	if (TREE_CODE (lab) != LABEL_DECL)
4602	  break;
4603
4604	n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
4605	diagnose_sb_0 (tp, context, n ? (tree) n->value : NULL_TREE);
4606      }
4607      break;
4608
4609    case SWITCH_EXPR:
4610      {
4611	tree vec = SWITCH_LABELS (t);
4612	int i, len = TREE_VEC_LENGTH (vec);
4613	for (i = 0; i < len; ++i)
4614	  {
4615	    tree lab = CASE_LABEL (TREE_VEC_ELT (vec, i));
4616	    n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
4617	    if (diagnose_sb_0 (tp, context, (tree) n->value))
4618	      break;
4619	  }
4620      }
4621      break;
4622
4623    case RETURN_EXPR:
4624      diagnose_sb_0 (tp, context, NULL_TREE);
4625      break;
4626
4627    default:
4628      break;
4629    }
4630
4631  return NULL_TREE;
4632}
4633
4634void
4635diagnose_omp_structured_block_errors (tree fndecl)
4636{
4637  tree save_current = current_function_decl;
4638  struct walk_stmt_info wi;
4639
4640  current_function_decl = fndecl;
4641
4642  all_labels = splay_tree_new (splay_tree_compare_pointers, 0, 0);
4643
4644  memset (&wi, 0, sizeof (wi));
4645  wi.callback = diagnose_sb_1;
4646  walk_stmts (&wi, &DECL_SAVED_TREE (fndecl));
4647
4648  memset (&wi, 0, sizeof (wi));
4649  wi.callback = diagnose_sb_2;
4650  wi.want_locations = true;
4651  wi.want_return_expr = true;
4652  walk_stmts (&wi, &DECL_SAVED_TREE (fndecl));
4653
4654  splay_tree_delete (all_labels);
4655  all_labels = NULL;
4656
4657  current_function_decl = save_current;
4658}
4659
4660#include "gt-omp-low.h"
4661