OSDN Git Service

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