OSDN Git Service

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