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