OSDN Git Service

2007-05-02 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, 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
2217           t = build3 (COND_EXPR, void_type_node,
2218                       cond, NULL_TREE, NULL_TREE);
2219
2220           si = bsi_start (cond_bb);
2221           bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
2222
2223           si = bsi_start (then_bb);
2224           t = build_gimple_modify_stmt (tmp, val);
2225           bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
2226
2227           si = bsi_start (else_bb);
2228           t = build_gimple_modify_stmt (tmp, 
2229                                         build_int_cst (unsigned_type_node, 1));
2230           bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
2231
2232           make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
2233           make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
2234           make_edge (then_bb, bb, EDGE_FALLTHRU);
2235           make_edge (else_bb, bb, EDGE_FALLTHRU);
2236
2237           val = tmp;
2238         }
2239
2240       list = NULL_TREE;
2241       val = get_formal_tmp_var (val, &list);
2242       si = bsi_start (bb);
2243       bsi_insert_after (&si, list, BSI_CONTINUE_LINKING);
2244     }
2245
2246   list = NULL_TREE;
2247   t = OMP_PARALLEL_DATA_ARG (entry_stmt);
2248   if (t == NULL)
2249     t1 = null_pointer_node;
2250   else
2251     t1 = build_fold_addr_expr (t);
2252   t2 = build_fold_addr_expr (OMP_PARALLEL_FN (entry_stmt));
2253
2254   if (ws_args)
2255     {
2256       tree args = tree_cons (NULL, t2,
2257                              tree_cons (NULL, t1,
2258                                         tree_cons (NULL, val, ws_args)));
2259       t = build_function_call_expr (built_in_decls[start_ix], args);
2260     }
2261   else
2262     t = build_call_expr (built_in_decls[start_ix], 3, t2, t1, val);
2263
2264   gimplify_and_add (t, &list);
2265
2266   t = OMP_PARALLEL_DATA_ARG (entry_stmt);
2267   if (t == NULL)
2268     t = null_pointer_node;
2269   else
2270     t = build_fold_addr_expr (t);
2271   t = build_call_expr (OMP_PARALLEL_FN (entry_stmt), 1, t);
2272   gimplify_and_add (t, &list);
2273
2274   t = build_call_expr (built_in_decls[BUILT_IN_GOMP_PARALLEL_END], 0);
2275   gimplify_and_add (t, &list);
2276
2277   si = bsi_last (bb);
2278   bsi_insert_after (&si, list, BSI_CONTINUE_LINKING);
2279
2280   pop_gimplify_context (NULL_TREE);
2281 }
2282
2283
2284 /* If exceptions are enabled, wrap *STMT_P in a MUST_NOT_THROW catch
2285    handler.  This prevents programs from violating the structured
2286    block semantics with throws.  */
2287
2288 static void
2289 maybe_catch_exception (tree *stmt_p)
2290 {
2291   tree f, t;
2292
2293   if (!flag_exceptions)
2294     return;
2295
2296   if (lang_protect_cleanup_actions)
2297     t = lang_protect_cleanup_actions ();
2298   else
2299     t = build_call_expr (built_in_decls[BUILT_IN_TRAP], 0);
2300   f = build2 (EH_FILTER_EXPR, void_type_node, NULL, NULL);
2301   EH_FILTER_MUST_NOT_THROW (f) = 1;
2302   gimplify_and_add (t, &EH_FILTER_FAILURE (f));
2303   
2304   t = build2 (TRY_CATCH_EXPR, void_type_node, *stmt_p, NULL);
2305   append_to_statement_list (f, &TREE_OPERAND (t, 1));
2306
2307   *stmt_p = NULL;
2308   append_to_statement_list (t, stmt_p);
2309 }
2310
2311 /* Chain all the DECLs in LIST by their TREE_CHAIN fields.  */
2312
2313 static tree
2314 list2chain (tree list)
2315 {
2316   tree t;
2317
2318   for (t = list; t; t = TREE_CHAIN (t))
2319     {
2320       tree var = TREE_VALUE (t);
2321       if (TREE_CHAIN (t))
2322         TREE_CHAIN (var) = TREE_VALUE (TREE_CHAIN (t));
2323       else
2324         TREE_CHAIN (var) = NULL_TREE;
2325     }
2326
2327   return list ? TREE_VALUE (list) : NULL_TREE;
2328 }
2329
2330
2331 /* Remove barriers in REGION->EXIT's block.  Note that this is only
2332    valid for OMP_PARALLEL regions.  Since the end of a parallel region
2333    is an implicit barrier, any workshare inside the OMP_PARALLEL that
2334    left a barrier at the end of the OMP_PARALLEL region can now be
2335    removed.  */
2336
2337 static void
2338 remove_exit_barrier (struct omp_region *region)
2339 {
2340   block_stmt_iterator si;
2341   basic_block exit_bb;
2342   edge_iterator ei;
2343   edge e;
2344   tree t;
2345
2346   exit_bb = region->exit;
2347
2348   /* If the parallel region doesn't return, we don't have REGION->EXIT
2349      block at all.  */
2350   if (! exit_bb)
2351     return;
2352
2353   /* The last insn in the block will be the parallel's OMP_RETURN.  The
2354      workshare's OMP_RETURN will be in a preceding block.  The kinds of
2355      statements that can appear in between are extremely limited -- no
2356      memory operations at all.  Here, we allow nothing at all, so the
2357      only thing we allow to precede this OMP_RETURN is a label.  */
2358   si = bsi_last (exit_bb);
2359   gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_RETURN);
2360   bsi_prev (&si);
2361   if (!bsi_end_p (si) && TREE_CODE (bsi_stmt (si)) != LABEL_EXPR)
2362     return;
2363
2364   FOR_EACH_EDGE (e, ei, exit_bb->preds)
2365     {
2366       si = bsi_last (e->src);
2367       if (bsi_end_p (si))
2368         continue;
2369       t = bsi_stmt (si);
2370       if (TREE_CODE (t) == OMP_RETURN)
2371         OMP_RETURN_NOWAIT (t) = 1;
2372     }
2373 }
2374
2375 static void
2376 remove_exit_barriers (struct omp_region *region)
2377 {
2378   if (region->type == OMP_PARALLEL)
2379     remove_exit_barrier (region);
2380
2381   if (region->inner)
2382     {
2383       region = region->inner;
2384       remove_exit_barriers (region);
2385       while (region->next)
2386         {
2387           region = region->next;
2388           remove_exit_barriers (region);
2389         }
2390     }
2391 }
2392
2393 /* Expand the OpenMP parallel directive starting at REGION.  */
2394
2395 static void
2396 expand_omp_parallel (struct omp_region *region)
2397 {
2398   basic_block entry_bb, exit_bb, new_bb;
2399   struct function *child_cfun, *saved_cfun;
2400   tree child_fn, block, t, ws_args;
2401   block_stmt_iterator si;
2402   tree entry_stmt;
2403   edge e;
2404   bool do_cleanup_cfg = false;
2405
2406   entry_stmt = last_stmt (region->entry);
2407   child_fn = OMP_PARALLEL_FN (entry_stmt);
2408   child_cfun = DECL_STRUCT_FUNCTION (child_fn);
2409   saved_cfun = cfun;
2410
2411   entry_bb = region->entry;
2412   exit_bb = region->exit;
2413
2414   if (is_combined_parallel (region))
2415     ws_args = region->ws_args;
2416   else
2417     ws_args = NULL_TREE;
2418
2419   if (child_cfun->cfg)
2420     {
2421       /* Due to inlining, it may happen that we have already outlined
2422          the region, in which case all we need to do is make the
2423          sub-graph unreachable and emit the parallel call.  */
2424       edge entry_succ_e, exit_succ_e;
2425       block_stmt_iterator si;
2426
2427       entry_succ_e = single_succ_edge (entry_bb);
2428
2429       si = bsi_last (entry_bb);
2430       gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_PARALLEL);
2431       bsi_remove (&si, true);
2432
2433       new_bb = entry_bb;
2434       remove_edge (entry_succ_e);
2435       if (exit_bb)
2436         {
2437           exit_succ_e = single_succ_edge (exit_bb);
2438           make_edge (new_bb, exit_succ_e->dest, EDGE_FALLTHRU);
2439         }
2440       do_cleanup_cfg = true;
2441     }
2442   else
2443     {
2444       /* If the parallel region needs data sent from the parent
2445          function, then the very first statement (except possible
2446          tree profile counter updates) of the parallel body
2447          is a copy assignment .OMP_DATA_I = &.OMP_DATA_O.  Since
2448          &.OMP_DATA_O is passed as an argument to the child function,
2449          we need to replace it with the argument as seen by the child
2450          function.
2451
2452          In most cases, this will end up being the identity assignment
2453          .OMP_DATA_I = .OMP_DATA_I.  However, if the parallel body had
2454          a function call that has been inlined, the original PARM_DECL
2455          .OMP_DATA_I may have been converted into a different local
2456          variable.  In which case, we need to keep the assignment.  */
2457       if (OMP_PARALLEL_DATA_ARG (entry_stmt))
2458         {
2459           basic_block entry_succ_bb = single_succ (entry_bb);
2460           block_stmt_iterator si;
2461
2462           for (si = bsi_start (entry_succ_bb); ; bsi_next (&si))
2463             {
2464               tree stmt, arg;
2465
2466               gcc_assert (!bsi_end_p (si));
2467               stmt = bsi_stmt (si);
2468               if (TREE_CODE (stmt) != GIMPLE_MODIFY_STMT)
2469                 continue;
2470
2471               arg = GIMPLE_STMT_OPERAND (stmt, 1);
2472               STRIP_NOPS (arg);
2473               if (TREE_CODE (arg) == ADDR_EXPR
2474                   && TREE_OPERAND (arg, 0)
2475                      == OMP_PARALLEL_DATA_ARG (entry_stmt))
2476                 {
2477                   if (GIMPLE_STMT_OPERAND (stmt, 0)
2478                       == DECL_ARGUMENTS (child_fn))
2479                     bsi_remove (&si, true);
2480                   else
2481                     GIMPLE_STMT_OPERAND (stmt, 1) = DECL_ARGUMENTS (child_fn);
2482                   break;
2483                 }
2484             }
2485         }
2486
2487       /* Declare local variables needed in CHILD_CFUN.  */
2488       block = DECL_INITIAL (child_fn);
2489       BLOCK_VARS (block) = list2chain (child_cfun->unexpanded_var_list);
2490       DECL_SAVED_TREE (child_fn) = bb_stmt_list (single_succ (entry_bb));
2491
2492       /* Reset DECL_CONTEXT on locals and function arguments.  */
2493       for (t = BLOCK_VARS (block); t; t = TREE_CHAIN (t))
2494         DECL_CONTEXT (t) = child_fn;
2495
2496       for (t = DECL_ARGUMENTS (child_fn); t; t = TREE_CHAIN (t))
2497         DECL_CONTEXT (t) = child_fn;
2498
2499       /* Split ENTRY_BB at OMP_PARALLEL so that it can be moved to the
2500          child function.  */
2501       si = bsi_last (entry_bb);
2502       t = bsi_stmt (si);
2503       gcc_assert (t && TREE_CODE (t) == OMP_PARALLEL);
2504       bsi_remove (&si, true);
2505       e = split_block (entry_bb, t);
2506       entry_bb = e->dest;
2507       single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
2508
2509       /* Move the parallel region into CHILD_CFUN.  We need to reset
2510          dominance information because the expansion of the inner
2511          regions has invalidated it.  */
2512       free_dominance_info (CDI_DOMINATORS);
2513       new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb);
2514       if (exit_bb)
2515         single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
2516       DECL_STRUCT_FUNCTION (child_fn)->curr_properties
2517         = cfun->curr_properties;
2518       cgraph_add_new_function (child_fn, true);
2519
2520       /* Convert OMP_RETURN into a RETURN_EXPR.  */
2521       if (exit_bb)
2522         {
2523           si = bsi_last (exit_bb);
2524           gcc_assert (!bsi_end_p (si)
2525                       && TREE_CODE (bsi_stmt (si)) == OMP_RETURN);
2526           t = build1 (RETURN_EXPR, void_type_node, NULL);
2527           bsi_insert_after (&si, t, BSI_SAME_STMT);
2528           bsi_remove (&si, true);
2529         }
2530     }
2531
2532   /* Emit a library call to launch the children threads.  */
2533   expand_parallel_call (region, new_bb, entry_stmt, ws_args);
2534
2535   if (do_cleanup_cfg)
2536     {
2537       /* Clean up the unreachable sub-graph we created above.  */
2538       free_dominance_info (CDI_DOMINATORS);
2539       free_dominance_info (CDI_POST_DOMINATORS);
2540       cleanup_tree_cfg ();
2541     }
2542 }
2543
2544
2545 /* A subroutine of expand_omp_for.  Generate code for a parallel
2546    loop with any schedule.  Given parameters:
2547
2548         for (V = N1; V cond N2; V += STEP) BODY;
2549
2550    where COND is "<" or ">", we generate pseudocode
2551
2552         more = GOMP_loop_foo_start (N1, N2, STEP, CHUNK, &istart0, &iend0);
2553         if (more) goto L0; else goto L3;
2554     L0:
2555         V = istart0;
2556         iend = iend0;
2557     L1:
2558         BODY;
2559         V += STEP;
2560         if (V cond iend) goto L1; else goto L2;
2561     L2:
2562         if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
2563     L3:
2564
2565     If this is a combined omp parallel loop, instead of the call to
2566     GOMP_loop_foo_start, we emit 'goto L3'.  */
2567
2568 static void
2569 expand_omp_for_generic (struct omp_region *region,
2570                         struct omp_for_data *fd,
2571                         enum built_in_function start_fn,
2572                         enum built_in_function next_fn)
2573 {
2574   tree type, istart0, iend0, iend;
2575   tree t, list;
2576   basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb;
2577   basic_block l2_bb = NULL, l3_bb = NULL;
2578   block_stmt_iterator si;
2579   bool in_combined_parallel = is_combined_parallel (region);
2580
2581   type = TREE_TYPE (fd->v);
2582
2583   istart0 = create_tmp_var (long_integer_type_node, ".istart0");
2584   iend0 = create_tmp_var (long_integer_type_node, ".iend0");
2585   iend = create_tmp_var (type, NULL);
2586   TREE_ADDRESSABLE (istart0) = 1;
2587   TREE_ADDRESSABLE (iend0) = 1;
2588
2589   gcc_assert ((region->cont != NULL) ^ (region->exit == NULL));
2590
2591   entry_bb = region->entry;
2592   l0_bb = create_empty_bb (entry_bb);
2593   l1_bb = single_succ (entry_bb);
2594
2595   cont_bb = region->cont;
2596   exit_bb = region->exit;
2597   if (cont_bb)
2598     {
2599       l2_bb = create_empty_bb (cont_bb);
2600       l3_bb = single_succ (cont_bb);
2601     }
2602
2603   si = bsi_last (entry_bb);
2604   gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_FOR);
2605   if (!in_combined_parallel)
2606     {
2607       tree t0, t1, t2, t3, t4;
2608       /* If this is not a combined parallel loop, emit a call to
2609          GOMP_loop_foo_start in ENTRY_BB.  */
2610       list = alloc_stmt_list ();
2611       t4 = build_fold_addr_expr (iend0);
2612       t3 = build_fold_addr_expr (istart0);
2613       t2 = fold_convert (long_integer_type_node, fd->step);
2614       t1 = fold_convert (long_integer_type_node, fd->n2);
2615       t0 = fold_convert (long_integer_type_node, fd->n1);
2616       if (fd->chunk_size)
2617         {
2618           t = fold_convert (long_integer_type_node, fd->chunk_size);
2619           t = build_call_expr (built_in_decls[start_fn], 6,
2620                                t0, t1, t2, t, t3, t4);
2621         }
2622       else
2623         t = build_call_expr (built_in_decls[start_fn], 5,
2624                              t0, t1, t2, t3, t4);
2625       t = get_formal_tmp_var (t, &list);
2626       if (cont_bb)
2627         {
2628           t = build3 (COND_EXPR, void_type_node, t, NULL_TREE, NULL_TREE);
2629           append_to_statement_list (t, &list);
2630         }
2631       bsi_insert_after (&si, list, BSI_SAME_STMT);
2632     }
2633   bsi_remove (&si, true);
2634
2635   /* Iteration setup for sequential loop goes in L0_BB.  */
2636   list = alloc_stmt_list ();
2637   t = fold_convert (type, istart0);
2638   t = build_gimple_modify_stmt (fd->v, t);
2639   gimplify_and_add (t, &list);
2640
2641   t = fold_convert (type, iend0);
2642   t = build_gimple_modify_stmt (iend, t);
2643   gimplify_and_add (t, &list);
2644
2645   si = bsi_start (l0_bb);
2646   bsi_insert_after (&si, list, BSI_CONTINUE_LINKING);
2647
2648   /* Handle the rare case where BODY doesn't ever return.  */
2649   if (cont_bb == NULL)
2650     {
2651       remove_edge (single_succ_edge (entry_bb));
2652       make_edge (entry_bb, l0_bb, EDGE_FALLTHRU);
2653       make_edge (l0_bb, l1_bb, EDGE_FALLTHRU);
2654       return;
2655     }
2656
2657   /* Code to control the increment and predicate for the sequential
2658      loop goes in the first half of EXIT_BB (we split EXIT_BB so
2659      that we can inherit all the edges going out of the loop
2660      body).  */
2661   list = alloc_stmt_list ();
2662
2663   t = build2 (PLUS_EXPR, type, fd->v, fd->step);
2664   t = build_gimple_modify_stmt (fd->v, t);
2665   gimplify_and_add (t, &list);
2666   
2667   t = build2 (fd->cond_code, boolean_type_node, fd->v, iend);
2668   t = get_formal_tmp_var (t, &list);
2669   t = build3 (COND_EXPR, void_type_node, t, NULL_TREE, NULL_TREE);
2670   append_to_statement_list (t, &list);
2671
2672   si = bsi_last (cont_bb);
2673   bsi_insert_after (&si, list, BSI_SAME_STMT);
2674   gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_CONTINUE);
2675   bsi_remove (&si, true);
2676
2677   /* Emit code to get the next parallel iteration in L2_BB.  */
2678   list = alloc_stmt_list ();
2679
2680   t = build_call_expr (built_in_decls[next_fn], 2,
2681                        build_fold_addr_expr (istart0),
2682                        build_fold_addr_expr (iend0));
2683   t = get_formal_tmp_var (t, &list);
2684   t = build3 (COND_EXPR, void_type_node, t, NULL_TREE, NULL_TREE);
2685   append_to_statement_list (t, &list);
2686   
2687   si = bsi_start (l2_bb);
2688   bsi_insert_after (&si, list, BSI_CONTINUE_LINKING);
2689
2690   /* Add the loop cleanup function.  */
2691   si = bsi_last (exit_bb);
2692   if (OMP_RETURN_NOWAIT (bsi_stmt (si)))
2693     t = built_in_decls[BUILT_IN_GOMP_LOOP_END_NOWAIT];
2694   else
2695     t = built_in_decls[BUILT_IN_GOMP_LOOP_END];
2696   t = build_call_expr (t, 0);
2697   bsi_insert_after (&si, t, BSI_SAME_STMT);
2698   bsi_remove (&si, true);
2699
2700   /* Connect the new blocks.  */
2701   remove_edge (single_succ_edge (entry_bb));
2702   if (in_combined_parallel)
2703     make_edge (entry_bb, l2_bb, EDGE_FALLTHRU);
2704   else
2705     {
2706       make_edge (entry_bb, l0_bb, EDGE_TRUE_VALUE);
2707       make_edge (entry_bb, l3_bb, EDGE_FALSE_VALUE);
2708     }
2709
2710   make_edge (l0_bb, l1_bb, EDGE_FALLTHRU);
2711
2712   remove_edge (single_succ_edge (cont_bb));
2713   make_edge (cont_bb, l1_bb, EDGE_TRUE_VALUE);
2714   make_edge (cont_bb, l2_bb, EDGE_FALSE_VALUE);
2715
2716   make_edge (l2_bb, l0_bb, EDGE_TRUE_VALUE);
2717   make_edge (l2_bb, l3_bb, EDGE_FALSE_VALUE);
2718 }
2719
2720
2721 /* A subroutine of expand_omp_for.  Generate code for a parallel
2722    loop with static schedule and no specified chunk size.  Given
2723    parameters:
2724
2725         for (V = N1; V cond N2; V += STEP) BODY;
2726
2727    where COND is "<" or ">", we generate pseudocode
2728
2729         if (cond is <)
2730           adj = STEP - 1;
2731         else
2732           adj = STEP + 1;
2733         n = (adj + N2 - N1) / STEP;
2734         q = n / nthreads;
2735         q += (q * nthreads != n);
2736         s0 = q * threadid;
2737         e0 = min(s0 + q, n);
2738         if (s0 >= e0) goto L2; else goto L0;
2739     L0:
2740         V = s0 * STEP + N1;
2741         e = e0 * STEP + N1;
2742     L1:
2743         BODY;
2744         V += STEP;
2745         if (V cond e) goto L1;
2746     L2:
2747 */
2748
2749 static void
2750 expand_omp_for_static_nochunk (struct omp_region *region,
2751                                struct omp_for_data *fd)
2752 {
2753   tree n, q, s0, e0, e, t, nthreads, threadid;
2754   tree type, list;
2755   basic_block entry_bb, exit_bb, seq_start_bb, body_bb, cont_bb;
2756   basic_block fin_bb;
2757   block_stmt_iterator si;
2758
2759   type = TREE_TYPE (fd->v);
2760
2761   entry_bb = region->entry;
2762   seq_start_bb = create_empty_bb (entry_bb);
2763   body_bb = single_succ (entry_bb);
2764   cont_bb = region->cont;
2765   fin_bb = single_succ (cont_bb);
2766   exit_bb = region->exit;
2767
2768   /* Iteration space partitioning goes in ENTRY_BB.  */
2769   list = alloc_stmt_list ();
2770
2771   t = build_call_expr (built_in_decls[BUILT_IN_OMP_GET_NUM_THREADS], 0);
2772   t = fold_convert (type, t);
2773   nthreads = get_formal_tmp_var (t, &list);
2774   
2775   t = build_call_expr (built_in_decls[BUILT_IN_OMP_GET_THREAD_NUM], 0);
2776   t = fold_convert (type, t);
2777   threadid = get_formal_tmp_var (t, &list);
2778
2779   fd->n1 = fold_convert (type, fd->n1);
2780   if (!is_gimple_val (fd->n1))
2781     fd->n1 = get_formal_tmp_var (fd->n1, &list);
2782
2783   fd->n2 = fold_convert (type, fd->n2);
2784   if (!is_gimple_val (fd->n2))
2785     fd->n2 = get_formal_tmp_var (fd->n2, &list);
2786
2787   fd->step = fold_convert (type, fd->step);
2788   if (!is_gimple_val (fd->step))
2789     fd->step = get_formal_tmp_var (fd->step, &list);
2790
2791   t = build_int_cst (type, (fd->cond_code == LT_EXPR ? -1 : 1));
2792   t = fold_build2 (PLUS_EXPR, type, fd->step, t);
2793   t = fold_build2 (PLUS_EXPR, type, t, fd->n2);
2794   t = fold_build2 (MINUS_EXPR, type, t, fd->n1);
2795   t = fold_build2 (TRUNC_DIV_EXPR, type, t, fd->step);
2796   t = fold_convert (type, t);
2797   if (is_gimple_val (t))
2798     n = t;
2799   else
2800     n = get_formal_tmp_var (t, &list);
2801
2802   t = build2 (TRUNC_DIV_EXPR, type, n, nthreads);
2803   q = get_formal_tmp_var (t, &list);
2804
2805   t = build2 (MULT_EXPR, type, q, nthreads);
2806   t = build2 (NE_EXPR, type, t, n);
2807   t = build2 (PLUS_EXPR, type, q, t);
2808   q = get_formal_tmp_var (t, &list);
2809
2810   t = build2 (MULT_EXPR, type, q, threadid);
2811   s0 = get_formal_tmp_var (t, &list);
2812
2813   t = build2 (PLUS_EXPR, type, s0, q);
2814   t = build2 (MIN_EXPR, type, t, n);
2815   e0 = get_formal_tmp_var (t, &list);
2816
2817   t = build2 (GE_EXPR, boolean_type_node, s0, e0);
2818   t = build3 (COND_EXPR, void_type_node, t, NULL_TREE, NULL_TREE);
2819   append_to_statement_list (t, &list);
2820
2821   si = bsi_last (entry_bb);
2822   gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_FOR);
2823   bsi_insert_after (&si, list, BSI_SAME_STMT);
2824   bsi_remove (&si, true);
2825
2826   /* Setup code for sequential iteration goes in SEQ_START_BB.  */
2827   list = alloc_stmt_list ();
2828
2829   t = fold_convert (type, s0);
2830   t = build2 (MULT_EXPR, type, t, fd->step);
2831   t = build2 (PLUS_EXPR, type, t, fd->n1);
2832   t = build_gimple_modify_stmt (fd->v, t);
2833   gimplify_and_add (t, &list);
2834
2835   t = fold_convert (type, e0);
2836   t = build2 (MULT_EXPR, type, t, fd->step);
2837   t = build2 (PLUS_EXPR, type, t, fd->n1);
2838   e = get_formal_tmp_var (t, &list);
2839
2840   si = bsi_start (seq_start_bb);
2841   bsi_insert_after (&si, list, BSI_CONTINUE_LINKING);
2842
2843   /* The code controlling the sequential loop replaces the OMP_CONTINUE.  */
2844   list = alloc_stmt_list ();
2845
2846   t = build2 (PLUS_EXPR, type, fd->v, fd->step);
2847   t = build_gimple_modify_stmt (fd->v, t);
2848   gimplify_and_add (t, &list);
2849
2850   t = build2 (fd->cond_code, boolean_type_node, fd->v, e);
2851   t = get_formal_tmp_var (t, &list);
2852   t = build3 (COND_EXPR, void_type_node, t, NULL_TREE, NULL_TREE);
2853   append_to_statement_list (t, &list);
2854
2855   si = bsi_last (cont_bb);
2856   gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_CONTINUE);
2857   bsi_insert_after (&si, list, BSI_SAME_STMT);
2858   bsi_remove (&si, true);
2859
2860   /* Replace the OMP_RETURN with a barrier, or nothing.  */
2861   si = bsi_last (exit_bb);
2862   if (!OMP_RETURN_NOWAIT (bsi_stmt (si)))
2863     {
2864       list = alloc_stmt_list ();
2865       build_omp_barrier (&list);
2866       bsi_insert_after (&si, list, BSI_SAME_STMT);
2867     }
2868   bsi_remove (&si, true);
2869
2870   /* Connect all the blocks.  */
2871   make_edge (seq_start_bb, body_bb, EDGE_FALLTHRU);
2872
2873   remove_edge (single_succ_edge (entry_bb));
2874   make_edge (entry_bb, fin_bb, EDGE_TRUE_VALUE);
2875   make_edge (entry_bb, seq_start_bb, EDGE_FALSE_VALUE);
2876
2877   make_edge (cont_bb, body_bb, EDGE_TRUE_VALUE);
2878   find_edge (cont_bb, fin_bb)->flags = EDGE_FALSE_VALUE;
2879 }
2880
2881
2882 /* A subroutine of expand_omp_for.  Generate code for a parallel
2883    loop with static schedule and a specified chunk size.  Given
2884    parameters:
2885
2886         for (V = N1; V cond N2; V += STEP) BODY;
2887
2888    where COND is "<" or ">", we generate pseudocode
2889
2890         if (cond is <)
2891           adj = STEP - 1;
2892         else
2893           adj = STEP + 1;
2894         n = (adj + N2 - N1) / STEP;
2895         trip = 0;
2896     L0:
2897         s0 = (trip * nthreads + threadid) * CHUNK;
2898         e0 = min(s0 + CHUNK, n);
2899         if (s0 < n) goto L1; else goto L4;
2900     L1:
2901         V = s0 * STEP + N1;
2902         e = e0 * STEP + N1;
2903     L2:
2904         BODY;
2905         V += STEP;
2906         if (V cond e) goto L2; else goto L3;
2907     L3:
2908         trip += 1;
2909         goto L0;
2910     L4:
2911 */
2912
2913 static void
2914 expand_omp_for_static_chunk (struct omp_region *region, struct omp_for_data *fd)
2915 {
2916   tree n, s0, e0, e, t;
2917   tree trip, nthreads, threadid;
2918   tree type;
2919   basic_block entry_bb, exit_bb, body_bb, seq_start_bb, iter_part_bb;
2920   basic_block trip_update_bb, cont_bb, fin_bb;
2921   tree list;
2922   block_stmt_iterator si;
2923
2924   type = TREE_TYPE (fd->v);
2925
2926   entry_bb = region->entry;
2927   iter_part_bb = create_empty_bb (entry_bb);
2928   seq_start_bb = create_empty_bb (iter_part_bb);
2929   body_bb = single_succ (entry_bb);
2930   cont_bb = region->cont;
2931   trip_update_bb = create_empty_bb (cont_bb);
2932   fin_bb = single_succ (cont_bb);
2933   exit_bb = region->exit;
2934
2935   /* Trip and adjustment setup goes in ENTRY_BB.  */
2936   list = alloc_stmt_list ();
2937
2938   t = build_call_expr (built_in_decls[BUILT_IN_OMP_GET_NUM_THREADS], 0);
2939   t = fold_convert (type, t);
2940   nthreads = get_formal_tmp_var (t, &list);
2941   
2942   t = build_call_expr (built_in_decls[BUILT_IN_OMP_GET_THREAD_NUM], 0);
2943   t = fold_convert (type, t);
2944   threadid = get_formal_tmp_var (t, &list);
2945
2946   fd->n1 = fold_convert (type, fd->n1);
2947   if (!is_gimple_val (fd->n1))
2948     fd->n1 = get_formal_tmp_var (fd->n1, &list);
2949
2950   fd->n2 = fold_convert (type, fd->n2);
2951   if (!is_gimple_val (fd->n2))
2952     fd->n2 = get_formal_tmp_var (fd->n2, &list);
2953
2954   fd->step = fold_convert (type, fd->step);
2955   if (!is_gimple_val (fd->step))
2956     fd->step = get_formal_tmp_var (fd->step, &list);
2957
2958   fd->chunk_size = fold_convert (type, fd->chunk_size);
2959   if (!is_gimple_val (fd->chunk_size))
2960     fd->chunk_size = get_formal_tmp_var (fd->chunk_size, &list);
2961
2962   t = build_int_cst (type, (fd->cond_code == LT_EXPR ? -1 : 1));
2963   t = fold_build2 (PLUS_EXPR, type, fd->step, t);
2964   t = fold_build2 (PLUS_EXPR, type, t, fd->n2);
2965   t = fold_build2 (MINUS_EXPR, type, t, fd->n1);
2966   t = fold_build2 (TRUNC_DIV_EXPR, type, t, fd->step);
2967   t = fold_convert (type, t);
2968   if (is_gimple_val (t))
2969     n = t;
2970   else
2971     n = get_formal_tmp_var (t, &list);
2972
2973   t = build_int_cst (type, 0);
2974   trip = get_initialized_tmp_var (t, &list, NULL);
2975
2976   si = bsi_last (entry_bb);
2977   gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_FOR);
2978   bsi_insert_after (&si, list, BSI_SAME_STMT);
2979   bsi_remove (&si, true);
2980
2981   /* Iteration space partitioning goes in ITER_PART_BB.  */
2982   list = alloc_stmt_list ();
2983
2984   t = build2 (MULT_EXPR, type, trip, nthreads);
2985   t = build2 (PLUS_EXPR, type, t, threadid);
2986   t = build2 (MULT_EXPR, type, t, fd->chunk_size);
2987   s0 = get_formal_tmp_var (t, &list);
2988
2989   t = build2 (PLUS_EXPR, type, s0, fd->chunk_size);
2990   t = build2 (MIN_EXPR, type, t, n);
2991   e0 = get_formal_tmp_var (t, &list);
2992
2993   t = build2 (LT_EXPR, boolean_type_node, s0, n);
2994   t = build3 (COND_EXPR, void_type_node, t, NULL_TREE, NULL_TREE);
2995   append_to_statement_list (t, &list);
2996
2997   si = bsi_start (iter_part_bb);
2998   bsi_insert_after (&si, list, BSI_CONTINUE_LINKING);
2999
3000   /* Setup code for sequential iteration goes in SEQ_START_BB.  */
3001   list = alloc_stmt_list ();
3002
3003   t = fold_convert (type, s0);
3004   t = build2 (MULT_EXPR, type, t, fd->step);
3005   t = build2 (PLUS_EXPR, type, t, fd->n1);
3006   t = build_gimple_modify_stmt (fd->v, t);
3007   gimplify_and_add (t, &list);
3008
3009   t = fold_convert (type, e0);
3010   t = build2 (MULT_EXPR, type, t, fd->step);
3011   t = build2 (PLUS_EXPR, type, t, fd->n1);
3012   e = get_formal_tmp_var (t, &list);
3013
3014   si = bsi_start (seq_start_bb);
3015   bsi_insert_after (&si, list, BSI_CONTINUE_LINKING);
3016
3017   /* The code controlling the sequential loop goes in CONT_BB,
3018      replacing the OMP_CONTINUE.  */
3019   list = alloc_stmt_list ();
3020
3021   t = build2 (PLUS_EXPR, type, fd->v, fd->step);
3022   t = build_gimple_modify_stmt (fd->v, t);
3023   gimplify_and_add (t, &list);
3024
3025   t = build2 (fd->cond_code, boolean_type_node, fd->v, e);
3026   t = get_formal_tmp_var (t, &list);
3027   t = build3 (COND_EXPR, void_type_node, t, NULL_TREE, NULL_TREE);
3028   append_to_statement_list (t, &list);
3029   
3030   si = bsi_last (cont_bb);
3031   gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_CONTINUE);
3032   bsi_insert_after (&si, list, BSI_SAME_STMT);
3033   bsi_remove (&si, true);
3034
3035   /* Trip update code goes into TRIP_UPDATE_BB.  */
3036   list = alloc_stmt_list ();
3037
3038   t = build_int_cst (type, 1);
3039   t = build2 (PLUS_EXPR, type, trip, t);
3040   t = build_gimple_modify_stmt (trip, t);
3041   gimplify_and_add (t, &list);
3042
3043   si = bsi_start (trip_update_bb);
3044   bsi_insert_after (&si, list, BSI_CONTINUE_LINKING);
3045
3046   /* Replace the OMP_RETURN with a barrier, or nothing.  */
3047   si = bsi_last (exit_bb);
3048   if (!OMP_RETURN_NOWAIT (bsi_stmt (si)))
3049     {
3050       list = alloc_stmt_list ();
3051       build_omp_barrier (&list);
3052       bsi_insert_after (&si, list, BSI_SAME_STMT);
3053     }
3054   bsi_remove (&si, true);
3055
3056   /* Connect the new blocks.  */
3057   remove_edge (single_succ_edge (entry_bb));
3058   make_edge (entry_bb, iter_part_bb, EDGE_FALLTHRU);
3059
3060   make_edge (iter_part_bb, seq_start_bb, EDGE_TRUE_VALUE);
3061   make_edge (iter_part_bb, fin_bb, EDGE_FALSE_VALUE);
3062
3063   make_edge (seq_start_bb, body_bb, EDGE_FALLTHRU);
3064
3065   remove_edge (single_succ_edge (cont_bb));
3066   make_edge (cont_bb, body_bb, EDGE_TRUE_VALUE);
3067   make_edge (cont_bb, trip_update_bb, EDGE_FALSE_VALUE);
3068
3069   make_edge (trip_update_bb, iter_part_bb, EDGE_FALLTHRU);
3070 }
3071
3072
3073 /* Expand the OpenMP loop defined by REGION.  */
3074
3075 static void
3076 expand_omp_for (struct omp_region *region)
3077 {
3078   struct omp_for_data fd;
3079
3080   push_gimplify_context ();
3081
3082   extract_omp_for_data (last_stmt (region->entry), &fd);
3083   region->sched_kind = fd.sched_kind;
3084
3085   if (fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
3086       && !fd.have_ordered
3087       && region->cont
3088       && region->exit)
3089     {
3090       if (fd.chunk_size == NULL)
3091         expand_omp_for_static_nochunk (region, &fd);
3092       else
3093         expand_omp_for_static_chunk (region, &fd);
3094     }
3095   else
3096     {
3097       int fn_index = fd.sched_kind + fd.have_ordered * 4;
3098       int start_ix = BUILT_IN_GOMP_LOOP_STATIC_START + fn_index;
3099       int next_ix = BUILT_IN_GOMP_LOOP_STATIC_NEXT + fn_index;
3100       expand_omp_for_generic (region, &fd, start_ix, next_ix);
3101     }
3102
3103   pop_gimplify_context (NULL);
3104 }
3105
3106
3107 /* Expand code for an OpenMP sections directive.  In pseudo code, we generate
3108
3109         v = GOMP_sections_start (n);
3110     L0:
3111         switch (v)
3112           {
3113           case 0:
3114             goto L2;
3115           case 1:
3116             section 1;
3117             goto L1;
3118           case 2:
3119             ...
3120           case n:
3121             ...
3122           default:
3123             abort ();
3124           }
3125     L1:
3126         v = GOMP_sections_next ();
3127         goto L0;
3128     L2:
3129         reduction;
3130
3131     If this is a combined parallel sections, replace the call to
3132     GOMP_sections_start with 'goto L1'.  */
3133
3134 static void
3135 expand_omp_sections (struct omp_region *region)
3136 {
3137   tree label_vec, l0, l1, l2, t, u, v, sections_stmt;
3138   unsigned i, len;
3139   basic_block entry_bb, exit_bb, l0_bb, l1_bb, l2_bb, default_bb;
3140   block_stmt_iterator si;
3141   struct omp_region *inner;
3142   edge e;
3143
3144   entry_bb = region->entry;
3145   l0_bb = create_empty_bb (entry_bb);
3146   l0 = tree_block_label (l0_bb);
3147
3148   gcc_assert ((region->cont != NULL) ^ (region->exit == NULL));
3149   l1_bb = region->cont;
3150   if (l1_bb)
3151     {
3152       l2_bb = single_succ (l1_bb);
3153       default_bb = create_empty_bb (l1_bb->prev_bb);
3154
3155       l1 = tree_block_label (l1_bb);
3156     }
3157   else
3158     {
3159       l2_bb = create_empty_bb (l0_bb);
3160       default_bb = l2_bb;
3161
3162       l1 = NULL;
3163     }
3164   l2 = tree_block_label (l2_bb);
3165
3166   exit_bb = region->exit;
3167
3168   v = create_tmp_var (unsigned_type_node, ".section");
3169
3170   /* We will build a switch() with enough cases for all the
3171      OMP_SECTION regions, a '0' case to handle the end of more work
3172      and a default case to abort if something goes wrong.  */
3173   len = EDGE_COUNT (entry_bb->succs);
3174   label_vec = make_tree_vec (len + 2);
3175
3176   /* The call to GOMP_sections_start goes in ENTRY_BB, replacing the
3177      OMP_SECTIONS statement.  */
3178   si = bsi_last (entry_bb);
3179   sections_stmt = bsi_stmt (si);
3180   gcc_assert (TREE_CODE (sections_stmt) == OMP_SECTIONS);
3181   if (!is_combined_parallel (region))
3182     {
3183       /* If we are not inside a combined parallel+sections region,
3184          call GOMP_sections_start.  */
3185       t = build_int_cst (unsigned_type_node, len);
3186       u = built_in_decls[BUILT_IN_GOMP_SECTIONS_START];
3187       t = build_call_expr (u, 1, t);
3188       t = build_gimple_modify_stmt (v, t);
3189       bsi_insert_after (&si, t, BSI_SAME_STMT);
3190     }
3191   bsi_remove (&si, true);
3192
3193   /* The switch() statement replacing OMP_SECTIONS goes in L0_BB.  */
3194   si = bsi_start (l0_bb);
3195
3196   t = build3 (SWITCH_EXPR, void_type_node, v, NULL, label_vec);
3197   bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
3198
3199   t = build3 (CASE_LABEL_EXPR, void_type_node,
3200               build_int_cst (unsigned_type_node, 0), NULL, l2);
3201   TREE_VEC_ELT (label_vec, 0) = t;
3202   make_edge (l0_bb, l2_bb, 0);
3203
3204   /* Convert each OMP_SECTION into a CASE_LABEL_EXPR.  */
3205   for (inner = region->inner, i = 1; inner; inner = inner->next, ++i)
3206     {
3207       basic_block s_entry_bb, s_exit_bb;
3208
3209       s_entry_bb = inner->entry;
3210       s_exit_bb = inner->exit;
3211
3212       t = tree_block_label (s_entry_bb);
3213       u = build_int_cst (unsigned_type_node, i);
3214       u = build3 (CASE_LABEL_EXPR, void_type_node, u, NULL, t);
3215       TREE_VEC_ELT (label_vec, i) = u;
3216
3217       si = bsi_last (s_entry_bb);
3218       gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_SECTION);
3219       gcc_assert (i < len || OMP_SECTION_LAST (bsi_stmt (si)));
3220       bsi_remove (&si, true);
3221
3222       e = single_pred_edge (s_entry_bb);
3223       e->flags = 0;
3224       redirect_edge_pred (e, l0_bb);
3225
3226       single_succ_edge (s_entry_bb)->flags = EDGE_FALLTHRU;
3227
3228       if (s_exit_bb == NULL)
3229         continue;
3230
3231       si = bsi_last (s_exit_bb);
3232       gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_RETURN);
3233       bsi_remove (&si, true);
3234
3235       single_succ_edge (s_exit_bb)->flags = EDGE_FALLTHRU;
3236     }
3237
3238   /* Error handling code goes in DEFAULT_BB.  */
3239   t = tree_block_label (default_bb);
3240   u = build3 (CASE_LABEL_EXPR, void_type_node, NULL, NULL, t);
3241   TREE_VEC_ELT (label_vec, len + 1) = u;
3242   make_edge (l0_bb, default_bb, 0);
3243
3244   si = bsi_start (default_bb);
3245   t = build_call_expr (built_in_decls[BUILT_IN_TRAP], 0);
3246   bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
3247
3248   /* Code to get the next section goes in L1_BB.  */
3249   if (l1_bb)
3250     {
3251       si = bsi_last (l1_bb);
3252       gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_CONTINUE);
3253
3254       t = build_call_expr (built_in_decls[BUILT_IN_GOMP_SECTIONS_NEXT], 0);
3255       t = build_gimple_modify_stmt (v, t);
3256       bsi_insert_after (&si, t, BSI_SAME_STMT);
3257       bsi_remove (&si, true);
3258     }
3259
3260   /* Cleanup function replaces OMP_RETURN in EXIT_BB.  */
3261   if (exit_bb)
3262     {
3263       si = bsi_last (exit_bb);
3264       if (OMP_RETURN_NOWAIT (bsi_stmt (si)))
3265         t = built_in_decls[BUILT_IN_GOMP_SECTIONS_END_NOWAIT];
3266       else
3267         t = built_in_decls[BUILT_IN_GOMP_SECTIONS_END];
3268       t = build_call_expr (t, 0);
3269       bsi_insert_after (&si, t, BSI_SAME_STMT);
3270       bsi_remove (&si, true);
3271     }
3272
3273   /* Connect the new blocks.  */
3274   if (is_combined_parallel (region))
3275     {
3276       /* If this was a combined parallel+sections region, we did not
3277          emit a GOMP_sections_start in the entry block, so we just
3278          need to jump to L1_BB to get the next section.  */
3279       make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
3280     }
3281   else
3282     make_edge (entry_bb, l0_bb, EDGE_FALLTHRU);
3283
3284   if (l1_bb)
3285     {
3286       e = single_succ_edge (l1_bb);
3287       redirect_edge_succ (e, l0_bb);
3288       e->flags = EDGE_FALLTHRU;
3289     }
3290 }
3291
3292
3293 /* Expand code for an OpenMP single directive.  We've already expanded
3294    much of the code, here we simply place the GOMP_barrier call.  */
3295
3296 static void
3297 expand_omp_single (struct omp_region *region)
3298 {
3299   basic_block entry_bb, exit_bb;
3300   block_stmt_iterator si;
3301   bool need_barrier = false;
3302
3303   entry_bb = region->entry;
3304   exit_bb = region->exit;
3305
3306   si = bsi_last (entry_bb);
3307   /* The terminal barrier at the end of a GOMP_single_copy sequence cannot
3308      be removed.  We need to ensure that the thread that entered the single
3309      does not exit before the data is copied out by the other threads.  */
3310   if (find_omp_clause (OMP_SINGLE_CLAUSES (bsi_stmt (si)),
3311                        OMP_CLAUSE_COPYPRIVATE))
3312     need_barrier = true;
3313   gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_SINGLE);
3314   bsi_remove (&si, true);
3315   single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
3316
3317   si = bsi_last (exit_bb);
3318   if (!OMP_RETURN_NOWAIT (bsi_stmt (si)) || need_barrier)
3319     {
3320       tree t = alloc_stmt_list ();
3321       build_omp_barrier (&t);
3322       bsi_insert_after (&si, t, BSI_SAME_STMT);
3323     }
3324   bsi_remove (&si, true);
3325   single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
3326 }
3327
3328
3329 /* Generic expansion for OpenMP synchronization directives: master,
3330    ordered and critical.  All we need to do here is remove the entry
3331    and exit markers for REGION.  */
3332
3333 static void
3334 expand_omp_synch (struct omp_region *region)
3335 {
3336   basic_block entry_bb, exit_bb;
3337   block_stmt_iterator si;
3338
3339   entry_bb = region->entry;
3340   exit_bb = region->exit;
3341
3342   si = bsi_last (entry_bb);
3343   gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_SINGLE
3344               || TREE_CODE (bsi_stmt (si)) == OMP_MASTER
3345               || TREE_CODE (bsi_stmt (si)) == OMP_ORDERED
3346               || TREE_CODE (bsi_stmt (si)) == OMP_CRITICAL);
3347   bsi_remove (&si, true);
3348   single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
3349
3350   if (exit_bb)
3351     {
3352       si = bsi_last (exit_bb);
3353       gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_RETURN);
3354       bsi_remove (&si, true);
3355       single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
3356     }
3357 }
3358
3359
3360 /* Expand the parallel region tree rooted at REGION.  Expansion
3361    proceeds in depth-first order.  Innermost regions are expanded
3362    first.  This way, parallel regions that require a new function to
3363    be created (e.g., OMP_PARALLEL) can be expanded without having any
3364    internal dependencies in their body.  */
3365
3366 static void
3367 expand_omp (struct omp_region *region)
3368 {
3369   while (region)
3370     {
3371       if (region->inner)
3372         expand_omp (region->inner);
3373
3374       switch (region->type)
3375         {
3376         case OMP_PARALLEL:
3377           expand_omp_parallel (region);
3378           break;
3379
3380         case OMP_FOR:
3381           expand_omp_for (region);
3382           break;
3383
3384         case OMP_SECTIONS:
3385           expand_omp_sections (region);
3386           break;
3387
3388         case OMP_SECTION:
3389           /* Individual omp sections are handled together with their
3390              parent OMP_SECTIONS region.  */
3391           break;
3392
3393         case OMP_SINGLE:
3394           expand_omp_single (region);
3395           break;
3396
3397         case OMP_MASTER:
3398         case OMP_ORDERED:
3399         case OMP_CRITICAL:
3400           expand_omp_synch (region);
3401           break;
3402
3403         default:
3404           gcc_unreachable ();
3405         }
3406
3407       region = region->next;
3408     }
3409 }
3410
3411
3412 /* Helper for build_omp_regions.  Scan the dominator tree starting at
3413    block BB.  PARENT is the region that contains BB.  */
3414
3415 static void
3416 build_omp_regions_1 (basic_block bb, struct omp_region *parent)
3417 {
3418   block_stmt_iterator si;
3419   tree stmt;
3420   basic_block son;
3421
3422   si = bsi_last (bb);
3423   if (!bsi_end_p (si) && OMP_DIRECTIVE_P (bsi_stmt (si)))
3424     {
3425       struct omp_region *region;
3426       enum tree_code code;
3427
3428       stmt = bsi_stmt (si);
3429       code = TREE_CODE (stmt);
3430
3431       if (code == OMP_RETURN)
3432         {
3433           /* STMT is the return point out of region PARENT.  Mark it
3434              as the exit point and make PARENT the immediately
3435              enclosing region.  */
3436           gcc_assert (parent);
3437           region = parent;
3438           region->exit = bb;
3439           parent = parent->outer;
3440
3441           /* If REGION is a parallel region, determine whether it is
3442              a combined parallel+workshare region.  */
3443           if (region->type == OMP_PARALLEL)
3444             determine_parallel_type (region);
3445         }
3446       else if (code == OMP_CONTINUE)
3447         {
3448           gcc_assert (parent);
3449           parent->cont = bb;
3450         }
3451       else
3452         {
3453           /* Otherwise, this directive becomes the parent for a new
3454              region.  */
3455           region = new_omp_region (bb, code, parent);
3456           parent = region;
3457         }
3458     }
3459
3460   for (son = first_dom_son (CDI_DOMINATORS, bb);
3461        son;
3462        son = next_dom_son (CDI_DOMINATORS, son))
3463     build_omp_regions_1 (son, parent);
3464 }
3465
3466
3467 /* Scan the CFG and build a tree of OMP regions.  Return the root of
3468    the OMP region tree.  */
3469
3470 static void
3471 build_omp_regions (void)
3472 {
3473   gcc_assert (root_omp_region == NULL);
3474   calculate_dominance_info (CDI_DOMINATORS);
3475   build_omp_regions_1 (ENTRY_BLOCK_PTR, NULL);
3476 }
3477
3478
3479 /* Main entry point for expanding OMP-GIMPLE into runtime calls.  */
3480
3481 static unsigned int
3482 execute_expand_omp (void)
3483 {
3484   build_omp_regions ();
3485
3486   if (!root_omp_region)
3487     return 0;
3488
3489   if (dump_file)
3490     {
3491       fprintf (dump_file, "\nOMP region tree\n\n");
3492       dump_omp_region (dump_file, root_omp_region, 0);
3493       fprintf (dump_file, "\n");
3494     }
3495
3496   remove_exit_barriers (root_omp_region);
3497
3498   expand_omp (root_omp_region);
3499
3500   free_dominance_info (CDI_DOMINATORS);
3501   free_dominance_info (CDI_POST_DOMINATORS);
3502   cleanup_tree_cfg ();
3503
3504   free_omp_regions ();
3505
3506   return 0;
3507 }
3508
3509 static bool
3510 gate_expand_omp (void)
3511 {
3512   return flag_openmp != 0 && errorcount == 0;
3513 }
3514
3515 struct tree_opt_pass pass_expand_omp = 
3516 {
3517   "ompexp",                             /* name */
3518   gate_expand_omp,                      /* gate */
3519   execute_expand_omp,                   /* execute */
3520   NULL,                                 /* sub */
3521   NULL,                                 /* next */
3522   0,                                    /* static_pass_number */
3523   0,                                    /* tv_id */
3524   PROP_gimple_any,                      /* properties_required */
3525   PROP_gimple_lomp,                     /* properties_provided */
3526   0,                                    /* properties_destroyed */
3527   0,                                    /* todo_flags_start */
3528   TODO_dump_func,                       /* todo_flags_finish */
3529   0                                     /* letter */
3530 };
3531 \f
3532 /* Routines to lower OpenMP directives into OMP-GIMPLE.  */
3533
3534 /* Lower the OpenMP sections directive in *STMT_P.  */
3535
3536 static void
3537 lower_omp_sections (tree *stmt_p, omp_context *ctx)
3538 {
3539   tree new_stmt, stmt, body, bind, block, ilist, olist, new_body;
3540   tree t, dlist;
3541   tree_stmt_iterator tsi;
3542   unsigned i, len;
3543
3544   stmt = *stmt_p;
3545
3546   push_gimplify_context ();
3547
3548   dlist = NULL;
3549   ilist = NULL;
3550   lower_rec_input_clauses (OMP_SECTIONS_CLAUSES (stmt), &ilist, &dlist, ctx);
3551
3552   tsi = tsi_start (OMP_SECTIONS_BODY (stmt));
3553   for (len = 0; !tsi_end_p (tsi); len++, tsi_next (&tsi))
3554     continue;
3555
3556   tsi = tsi_start (OMP_SECTIONS_BODY (stmt));
3557   body = alloc_stmt_list ();
3558   for (i = 0; i < len; i++, tsi_next (&tsi))
3559     {
3560       omp_context *sctx;
3561       tree sec_start, sec_end;
3562
3563       sec_start = tsi_stmt (tsi);
3564       sctx = maybe_lookup_ctx (sec_start);
3565       gcc_assert (sctx);
3566
3567       append_to_statement_list (sec_start, &body);
3568
3569       lower_omp (&OMP_SECTION_BODY (sec_start), sctx);
3570       append_to_statement_list (OMP_SECTION_BODY (sec_start), &body);
3571       OMP_SECTION_BODY (sec_start) = NULL;
3572
3573       if (i == len - 1)
3574         {
3575           tree l = alloc_stmt_list ();
3576           lower_lastprivate_clauses (OMP_SECTIONS_CLAUSES (stmt), NULL,
3577                                      &l, ctx);
3578           append_to_statement_list (l, &body);
3579           OMP_SECTION_LAST (sec_start) = 1;
3580         }
3581       
3582       sec_end = make_node (OMP_RETURN);
3583       append_to_statement_list (sec_end, &body);
3584     }
3585
3586   block = make_node (BLOCK);
3587   bind = build3 (BIND_EXPR, void_type_node, NULL, body, block);
3588
3589   olist = NULL_TREE;
3590   lower_reduction_clauses (OMP_SECTIONS_CLAUSES (stmt), &olist, ctx);
3591
3592   pop_gimplify_context (NULL_TREE);
3593   record_vars_into (ctx->block_vars, ctx->cb.dst_fn);
3594
3595   new_stmt = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
3596   TREE_SIDE_EFFECTS (new_stmt) = 1;
3597
3598   new_body = alloc_stmt_list ();
3599   append_to_statement_list (ilist, &new_body);
3600   append_to_statement_list (stmt, &new_body);
3601   append_to_statement_list (bind, &new_body);
3602
3603   t = make_node (OMP_CONTINUE);
3604   append_to_statement_list (t, &new_body);
3605
3606   append_to_statement_list (olist, &new_body);
3607   append_to_statement_list (dlist, &new_body);
3608
3609   maybe_catch_exception (&new_body);
3610
3611   t = make_node (OMP_RETURN);
3612   OMP_RETURN_NOWAIT (t) = !!find_omp_clause (OMP_SECTIONS_CLAUSES (stmt),
3613                                              OMP_CLAUSE_NOWAIT);
3614   append_to_statement_list (t, &new_body);
3615
3616   BIND_EXPR_BODY (new_stmt) = new_body;
3617   OMP_SECTIONS_BODY (stmt) = NULL;
3618
3619   *stmt_p = new_stmt;
3620 }
3621
3622
3623 /* A subroutine of lower_omp_single.  Expand the simple form of
3624    an OMP_SINGLE, without a copyprivate clause:
3625
3626         if (GOMP_single_start ())
3627           BODY;
3628         [ GOMP_barrier (); ]    -> unless 'nowait' is present.
3629
3630   FIXME.  It may be better to delay expanding the logic of this until
3631   pass_expand_omp.  The expanded logic may make the job more difficult
3632   to a synchronization analysis pass.  */
3633
3634 static void
3635 lower_omp_single_simple (tree single_stmt, tree *pre_p)
3636 {
3637   tree t;
3638
3639   t = build_call_expr (built_in_decls[BUILT_IN_GOMP_SINGLE_START], 0);
3640   t = build3 (COND_EXPR, void_type_node, t,
3641               OMP_SINGLE_BODY (single_stmt), NULL);
3642   gimplify_and_add (t, pre_p);
3643 }
3644
3645
3646 /* A subroutine of lower_omp_single.  Expand the simple form of
3647    an OMP_SINGLE, with a copyprivate clause:
3648
3649         #pragma omp single copyprivate (a, b, c)
3650
3651    Create a new structure to hold copies of 'a', 'b' and 'c' and emit:
3652
3653       {
3654         if ((copyout_p = GOMP_single_copy_start ()) == NULL)
3655           {
3656             BODY;
3657             copyout.a = a;
3658             copyout.b = b;
3659             copyout.c = c;
3660             GOMP_single_copy_end (&copyout);
3661           }
3662         else
3663           {
3664             a = copyout_p->a;
3665             b = copyout_p->b;
3666             c = copyout_p->c;
3667           }
3668         GOMP_barrier ();
3669       }
3670
3671   FIXME.  It may be better to delay expanding the logic of this until
3672   pass_expand_omp.  The expanded logic may make the job more difficult
3673   to a synchronization analysis pass.  */
3674
3675 static void
3676 lower_omp_single_copy (tree single_stmt, tree *pre_p, omp_context *ctx)
3677 {
3678   tree ptr_type, t, l0, l1, l2, copyin_seq;
3679
3680   ctx->sender_decl = create_tmp_var (ctx->record_type, ".omp_copy_o");
3681
3682   ptr_type = build_pointer_type (ctx->record_type);
3683   ctx->receiver_decl = create_tmp_var (ptr_type, ".omp_copy_i");
3684
3685   l0 = create_artificial_label ();
3686   l1 = create_artificial_label ();
3687   l2 = create_artificial_label ();
3688
3689   t = build_call_expr (built_in_decls[BUILT_IN_GOMP_SINGLE_COPY_START], 0);
3690   t = fold_convert (ptr_type, t);
3691   t = build_gimple_modify_stmt (ctx->receiver_decl, t);
3692   gimplify_and_add (t, pre_p);
3693
3694   t = build2 (EQ_EXPR, boolean_type_node, ctx->receiver_decl,
3695               build_int_cst (ptr_type, 0));
3696   t = build3 (COND_EXPR, void_type_node, t,
3697               build_and_jump (&l0), build_and_jump (&l1));
3698   gimplify_and_add (t, pre_p);
3699
3700   t = build1 (LABEL_EXPR, void_type_node, l0);
3701   gimplify_and_add (t, pre_p);
3702
3703   append_to_statement_list (OMP_SINGLE_BODY (single_stmt), pre_p);
3704
3705   copyin_seq = NULL;
3706   lower_copyprivate_clauses (OMP_SINGLE_CLAUSES (single_stmt), pre_p,
3707                               &copyin_seq, ctx);
3708
3709   t = build_fold_addr_expr (ctx->sender_decl);
3710   t = build_call_expr (built_in_decls[BUILT_IN_GOMP_SINGLE_COPY_END], 1, t);
3711   gimplify_and_add (t, pre_p);
3712
3713   t = build_and_jump (&l2);
3714   gimplify_and_add (t, pre_p);
3715
3716   t = build1 (LABEL_EXPR, void_type_node, l1);
3717   gimplify_and_add (t, pre_p);
3718
3719   append_to_statement_list (copyin_seq, pre_p);
3720
3721   t = build1 (LABEL_EXPR, void_type_node, l2);
3722   gimplify_and_add (t, pre_p);
3723 }
3724
3725
3726 /* Expand code for an OpenMP single directive.  */
3727
3728 static void
3729 lower_omp_single (tree *stmt_p, omp_context *ctx)
3730 {
3731   tree t, bind, block, single_stmt = *stmt_p, dlist;
3732
3733   push_gimplify_context ();
3734
3735   block = make_node (BLOCK);
3736   *stmt_p = bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, block);
3737   TREE_SIDE_EFFECTS (bind) = 1;
3738
3739   lower_rec_input_clauses (OMP_SINGLE_CLAUSES (single_stmt),
3740                            &BIND_EXPR_BODY (bind), &dlist, ctx);
3741   lower_omp (&OMP_SINGLE_BODY (single_stmt), ctx);
3742
3743   append_to_statement_list (single_stmt, &BIND_EXPR_BODY (bind));
3744
3745   if (ctx->record_type)
3746     lower_omp_single_copy (single_stmt, &BIND_EXPR_BODY (bind), ctx);
3747   else
3748     lower_omp_single_simple (single_stmt, &BIND_EXPR_BODY (bind));
3749
3750   OMP_SINGLE_BODY (single_stmt) = NULL;
3751
3752   append_to_statement_list (dlist, &BIND_EXPR_BODY (bind));
3753
3754   maybe_catch_exception (&BIND_EXPR_BODY (bind));
3755
3756   t = make_node (OMP_RETURN);
3757   OMP_RETURN_NOWAIT (t) = !!find_omp_clause (OMP_SINGLE_CLAUSES (single_stmt),
3758                                              OMP_CLAUSE_NOWAIT);
3759   append_to_statement_list (t, &BIND_EXPR_BODY (bind));
3760
3761   pop_gimplify_context (bind);
3762
3763   BIND_EXPR_VARS (bind) = chainon (BIND_EXPR_VARS (bind), ctx->block_vars);
3764   BLOCK_VARS (block) = BIND_EXPR_VARS (bind);
3765 }
3766
3767
3768 /* Expand code for an OpenMP master directive.  */
3769
3770 static void
3771 lower_omp_master (tree *stmt_p, omp_context *ctx)
3772 {
3773   tree bind, block, stmt = *stmt_p, lab = NULL, x;
3774
3775   push_gimplify_context ();
3776
3777   block = make_node (BLOCK);
3778   *stmt_p = bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, block);
3779   TREE_SIDE_EFFECTS (bind) = 1;
3780
3781   append_to_statement_list (stmt, &BIND_EXPR_BODY (bind));
3782
3783   x = build_call_expr (built_in_decls[BUILT_IN_OMP_GET_THREAD_NUM], 0);
3784   x = build2 (EQ_EXPR, boolean_type_node, x, integer_zero_node);
3785   x = build3 (COND_EXPR, void_type_node, x, NULL, build_and_jump (&lab));
3786   gimplify_and_add (x, &BIND_EXPR_BODY (bind));
3787
3788   lower_omp (&OMP_MASTER_BODY (stmt), ctx);
3789   maybe_catch_exception (&OMP_MASTER_BODY (stmt));
3790   append_to_statement_list (OMP_MASTER_BODY (stmt), &BIND_EXPR_BODY (bind));
3791   OMP_MASTER_BODY (stmt) = NULL;
3792
3793   x = build1 (LABEL_EXPR, void_type_node, lab);
3794   gimplify_and_add (x, &BIND_EXPR_BODY (bind));
3795
3796   x = make_node (OMP_RETURN);
3797   OMP_RETURN_NOWAIT (x) = 1;
3798   append_to_statement_list (x, &BIND_EXPR_BODY (bind));
3799
3800   pop_gimplify_context (bind);
3801
3802   BIND_EXPR_VARS (bind) = chainon (BIND_EXPR_VARS (bind), ctx->block_vars);
3803   BLOCK_VARS (block) = BIND_EXPR_VARS (bind);
3804 }
3805
3806
3807 /* Expand code for an OpenMP ordered directive.  */
3808
3809 static void
3810 lower_omp_ordered (tree *stmt_p, omp_context *ctx)
3811 {
3812   tree bind, block, stmt = *stmt_p, x;
3813
3814   push_gimplify_context ();
3815
3816   block = make_node (BLOCK);
3817   *stmt_p = bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, block);
3818   TREE_SIDE_EFFECTS (bind) = 1;
3819
3820   append_to_statement_list (stmt, &BIND_EXPR_BODY (bind));
3821
3822   x = build_call_expr (built_in_decls[BUILT_IN_GOMP_ORDERED_START], 0);
3823   gimplify_and_add (x, &BIND_EXPR_BODY (bind));
3824
3825   lower_omp (&OMP_ORDERED_BODY (stmt), ctx);
3826   maybe_catch_exception (&OMP_ORDERED_BODY (stmt));
3827   append_to_statement_list (OMP_ORDERED_BODY (stmt), &BIND_EXPR_BODY (bind));
3828   OMP_ORDERED_BODY (stmt) = NULL;
3829
3830   x = build_call_expr (built_in_decls[BUILT_IN_GOMP_ORDERED_END], 0);
3831   gimplify_and_add (x, &BIND_EXPR_BODY (bind));
3832
3833   x = make_node (OMP_RETURN);
3834   OMP_RETURN_NOWAIT (x) = 1;
3835   append_to_statement_list (x, &BIND_EXPR_BODY (bind));
3836
3837   pop_gimplify_context (bind);
3838
3839   BIND_EXPR_VARS (bind) = chainon (BIND_EXPR_VARS (bind), ctx->block_vars);
3840   BLOCK_VARS (block) = BIND_EXPR_VARS (bind);
3841 }
3842
3843
3844 /* Gimplify an OMP_CRITICAL statement.  This is a relatively simple
3845    substitution of a couple of function calls.  But in the NAMED case,
3846    requires that languages coordinate a symbol name.  It is therefore
3847    best put here in common code.  */
3848
3849 static GTY((param1_is (tree), param2_is (tree)))
3850   splay_tree critical_name_mutexes;
3851
3852 static void
3853 lower_omp_critical (tree *stmt_p, omp_context *ctx)
3854 {
3855   tree bind, block, stmt = *stmt_p;
3856   tree t, lock, unlock, name;
3857
3858   name = OMP_CRITICAL_NAME (stmt);
3859   if (name)
3860     {
3861       tree decl;
3862       splay_tree_node n;
3863
3864       if (!critical_name_mutexes)
3865         critical_name_mutexes
3866           = splay_tree_new_ggc (splay_tree_compare_pointers);
3867
3868       n = splay_tree_lookup (critical_name_mutexes, (splay_tree_key) name);
3869       if (n == NULL)
3870         {
3871           char *new_str;
3872
3873           decl = create_tmp_var_raw (ptr_type_node, NULL);
3874
3875           new_str = ACONCAT ((".gomp_critical_user_",
3876                               IDENTIFIER_POINTER (name), NULL));
3877           DECL_NAME (decl) = get_identifier (new_str);
3878           TREE_PUBLIC (decl) = 1;
3879           TREE_STATIC (decl) = 1;
3880           DECL_COMMON (decl) = 1;
3881           DECL_ARTIFICIAL (decl) = 1;
3882           DECL_IGNORED_P (decl) = 1;
3883           varpool_finalize_decl (decl);
3884
3885           splay_tree_insert (critical_name_mutexes, (splay_tree_key) name,
3886                              (splay_tree_value) decl);
3887         }
3888       else
3889         decl = (tree) n->value;
3890
3891       lock = built_in_decls[BUILT_IN_GOMP_CRITICAL_NAME_START];
3892       lock = build_call_expr (lock, 1, build_fold_addr_expr (decl));
3893
3894       unlock = built_in_decls[BUILT_IN_GOMP_CRITICAL_NAME_END];
3895       unlock = build_call_expr (unlock, 1, build_fold_addr_expr (decl));
3896     }
3897   else
3898     {
3899       lock = built_in_decls[BUILT_IN_GOMP_CRITICAL_START];
3900       lock = build_call_expr (lock, 0);
3901
3902       unlock = built_in_decls[BUILT_IN_GOMP_CRITICAL_END];
3903       unlock = build_call_expr (unlock, 0);
3904     }
3905
3906   push_gimplify_context ();
3907
3908   block = make_node (BLOCK);
3909   *stmt_p = bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, block);
3910   TREE_SIDE_EFFECTS (bind) = 1;
3911
3912   append_to_statement_list (stmt, &BIND_EXPR_BODY (bind));
3913
3914   gimplify_and_add (lock, &BIND_EXPR_BODY (bind));
3915
3916   lower_omp (&OMP_CRITICAL_BODY (stmt), ctx);
3917   maybe_catch_exception (&OMP_CRITICAL_BODY (stmt));
3918   append_to_statement_list (OMP_CRITICAL_BODY (stmt), &BIND_EXPR_BODY (bind));
3919   OMP_CRITICAL_BODY (stmt) = NULL;
3920
3921   gimplify_and_add (unlock, &BIND_EXPR_BODY (bind));
3922
3923   t = make_node (OMP_RETURN);
3924   OMP_RETURN_NOWAIT (t) = 1;
3925   append_to_statement_list (t, &BIND_EXPR_BODY (bind));
3926
3927   pop_gimplify_context (bind);
3928   BIND_EXPR_VARS (bind) = chainon (BIND_EXPR_VARS (bind), ctx->block_vars);
3929   BLOCK_VARS (block) = BIND_EXPR_VARS (bind);
3930 }
3931
3932
3933 /* A subroutine of lower_omp_for.  Generate code to emit the predicate
3934    for a lastprivate clause.  Given a loop control predicate of (V
3935    cond N2), we gate the clause on (!(V cond N2)).  The lowered form
3936    is appended to *DLIST, iterator initialization is appended to
3937    *BODY_P.  */
3938
3939 static void
3940 lower_omp_for_lastprivate (struct omp_for_data *fd, tree *body_p,
3941                            tree *dlist, struct omp_context *ctx)
3942 {
3943   tree clauses, cond, stmts, vinit, t;
3944   enum tree_code cond_code;
3945   
3946   cond_code = fd->cond_code;
3947   cond_code = cond_code == LT_EXPR ? GE_EXPR : LE_EXPR;
3948
3949   /* When possible, use a strict equality expression.  This can let VRP
3950      type optimizations deduce the value and remove a copy.  */
3951   if (host_integerp (fd->step, 0))
3952     {
3953       HOST_WIDE_INT step = TREE_INT_CST_LOW (fd->step);
3954       if (step == 1 || step == -1)
3955         cond_code = EQ_EXPR;
3956     }
3957
3958   cond = build2 (cond_code, boolean_type_node, fd->v, fd->n2);
3959
3960   clauses = OMP_FOR_CLAUSES (fd->for_stmt);
3961   stmts = NULL;
3962   lower_lastprivate_clauses (clauses, cond, &stmts, ctx);
3963   if (stmts != NULL)
3964     {
3965       append_to_statement_list (stmts, dlist);
3966
3967       /* Optimize: v = 0; is usually cheaper than v = some_other_constant.  */
3968       vinit = fd->n1;
3969       if (cond_code == EQ_EXPR
3970           && host_integerp (fd->n2, 0)
3971           && ! integer_zerop (fd->n2))
3972         vinit = build_int_cst (TREE_TYPE (fd->v), 0);
3973
3974       /* Initialize the iterator variable, so that threads that don't execute
3975          any iterations don't execute the lastprivate clauses by accident.  */
3976       t = build_gimple_modify_stmt (fd->v, vinit);
3977       gimplify_and_add (t, body_p);
3978     }
3979 }
3980
3981
3982 /* Lower code for an OpenMP loop directive.  */
3983
3984 static void
3985 lower_omp_for (tree *stmt_p, omp_context *ctx)
3986 {
3987   tree t, stmt, ilist, dlist, new_stmt, *body_p, *rhs_p;
3988   struct omp_for_data fd;
3989
3990   stmt = *stmt_p;
3991
3992   push_gimplify_context ();
3993
3994   lower_omp (&OMP_FOR_PRE_BODY (stmt), ctx);
3995   lower_omp (&OMP_FOR_BODY (stmt), ctx);
3996
3997   /* Move declaration of temporaries in the loop body before we make
3998      it go away.  */
3999   if (TREE_CODE (OMP_FOR_BODY (stmt)) == BIND_EXPR)
4000     record_vars_into (BIND_EXPR_VARS (OMP_FOR_BODY (stmt)), ctx->cb.dst_fn);
4001
4002   new_stmt = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
4003   TREE_SIDE_EFFECTS (new_stmt) = 1;
4004   body_p = &BIND_EXPR_BODY (new_stmt);
4005
4006   /* The pre-body and input clauses go before the lowered OMP_FOR.  */
4007   ilist = NULL;
4008   dlist = NULL;
4009   append_to_statement_list (OMP_FOR_PRE_BODY (stmt), body_p);
4010   lower_rec_input_clauses (OMP_FOR_CLAUSES (stmt), body_p, &dlist, ctx);
4011
4012   /* Lower the header expressions.  At this point, we can assume that
4013      the header is of the form:
4014
4015         #pragma omp for (V = VAL1; V {<|>|<=|>=} VAL2; V = V [+-] VAL3)
4016
4017      We just need to make sure that VAL1, VAL2 and VAL3 are lowered
4018      using the .omp_data_s mapping, if needed.  */
4019   rhs_p = &GIMPLE_STMT_OPERAND (OMP_FOR_INIT (stmt), 1);
4020   if (!is_gimple_min_invariant (*rhs_p))
4021     *rhs_p = get_formal_tmp_var (*rhs_p, body_p);
4022
4023   rhs_p = &TREE_OPERAND (OMP_FOR_COND (stmt), 1);
4024   if (!is_gimple_min_invariant (*rhs_p))
4025     *rhs_p = get_formal_tmp_var (*rhs_p, body_p);
4026
4027   rhs_p = &TREE_OPERAND (GIMPLE_STMT_OPERAND (OMP_FOR_INCR (stmt), 1), 1);
4028   if (!is_gimple_min_invariant (*rhs_p))
4029     *rhs_p = get_formal_tmp_var (*rhs_p, body_p);
4030
4031   /* Once lowered, extract the bounds and clauses.  */
4032   extract_omp_for_data (stmt, &fd);
4033
4034   lower_omp_for_lastprivate (&fd, body_p, &dlist, ctx);
4035
4036   append_to_statement_list (stmt, body_p);
4037
4038   append_to_statement_list (OMP_FOR_BODY (stmt), body_p);
4039
4040   t = make_node (OMP_CONTINUE);
4041   append_to_statement_list (t, body_p);
4042
4043   /* After the loop, add exit clauses.  */
4044   lower_reduction_clauses (OMP_FOR_CLAUSES (stmt), body_p, ctx);
4045   append_to_statement_list (dlist, body_p);
4046
4047   maybe_catch_exception (body_p);
4048
4049   /* Region exit marker goes at the end of the loop body.  */
4050   t = make_node (OMP_RETURN);
4051   OMP_RETURN_NOWAIT (t) = fd.have_nowait;
4052   append_to_statement_list (t, body_p);
4053
4054   pop_gimplify_context (NULL_TREE);
4055   record_vars_into (ctx->block_vars, ctx->cb.dst_fn);
4056
4057   OMP_FOR_BODY (stmt) = NULL_TREE;
4058   OMP_FOR_PRE_BODY (stmt) = NULL_TREE;
4059   *stmt_p = new_stmt;
4060 }
4061
4062
4063 /* Lower the OpenMP parallel directive in *STMT_P.  CTX holds context
4064    information for the directive.  */
4065
4066 static void
4067 lower_omp_parallel (tree *stmt_p, omp_context *ctx)
4068 {
4069   tree clauses, par_bind, par_body, new_body, bind;
4070   tree olist, ilist, par_olist, par_ilist;
4071   tree stmt, child_fn, t;
4072
4073   stmt = *stmt_p;
4074
4075   clauses = OMP_PARALLEL_CLAUSES (stmt);
4076   par_bind = OMP_PARALLEL_BODY (stmt);
4077   par_body = BIND_EXPR_BODY (par_bind);
4078   child_fn = ctx->cb.dst_fn;
4079
4080   push_gimplify_context ();
4081
4082   par_olist = NULL_TREE;
4083   par_ilist = NULL_TREE;
4084   lower_rec_input_clauses (clauses, &par_ilist, &par_olist, ctx);
4085   lower_omp (&par_body, ctx);
4086   lower_reduction_clauses (clauses, &par_olist, ctx);
4087
4088   /* Declare all the variables created by mapping and the variables
4089      declared in the scope of the parallel body.  */
4090   record_vars_into (ctx->block_vars, child_fn);
4091   record_vars_into (BIND_EXPR_VARS (par_bind), child_fn);
4092
4093   if (ctx->record_type)
4094     {
4095       ctx->sender_decl = create_tmp_var (ctx->record_type, ".omp_data_o");
4096       OMP_PARALLEL_DATA_ARG (stmt) = ctx->sender_decl;
4097     }
4098
4099   olist = NULL_TREE;
4100   ilist = NULL_TREE;
4101   lower_send_clauses (clauses, &ilist, &olist, ctx);
4102   lower_send_shared_vars (&ilist, &olist, ctx);
4103
4104   /* Once all the expansions are done, sequence all the different
4105      fragments inside OMP_PARALLEL_BODY.  */
4106   bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
4107   append_to_statement_list (ilist, &BIND_EXPR_BODY (bind));
4108
4109   new_body = alloc_stmt_list ();
4110
4111   if (ctx->record_type)
4112     {
4113       t = build_fold_addr_expr (ctx->sender_decl);
4114       /* fixup_child_record_type might have changed receiver_decl's type.  */
4115       t = fold_convert (TREE_TYPE (ctx->receiver_decl), t);
4116       t = build_gimple_modify_stmt (ctx->receiver_decl, t);
4117       append_to_statement_list (t, &new_body);
4118     }
4119
4120   append_to_statement_list (par_ilist, &new_body);
4121   append_to_statement_list (par_body, &new_body);
4122   append_to_statement_list (par_olist, &new_body);
4123   maybe_catch_exception (&new_body);
4124   t = make_node (OMP_RETURN);
4125   append_to_statement_list (t, &new_body);
4126   OMP_PARALLEL_BODY (stmt) = new_body;
4127
4128   append_to_statement_list (stmt, &BIND_EXPR_BODY (bind));
4129   append_to_statement_list (olist, &BIND_EXPR_BODY (bind));
4130
4131   *stmt_p = bind;
4132
4133   pop_gimplify_context (NULL_TREE);
4134 }
4135
4136
4137 /* Pass *TP back through the gimplifier within the context determined by WI.
4138    This handles replacement of DECL_VALUE_EXPR, as well as adjusting the 
4139    flags on ADDR_EXPR.  */
4140
4141 static void
4142 lower_regimplify (tree *tp, struct walk_stmt_info *wi)
4143 {
4144   enum gimplify_status gs;
4145   tree pre = NULL;
4146
4147   if (wi->is_lhs)
4148     gs = gimplify_expr (tp, &pre, NULL, is_gimple_lvalue, fb_lvalue);
4149   else if (wi->val_only)
4150     gs = gimplify_expr (tp, &pre, NULL, is_gimple_val, fb_rvalue);
4151   else
4152     gs = gimplify_expr (tp, &pre, NULL, is_gimple_formal_tmp_var, fb_rvalue);
4153   gcc_assert (gs == GS_ALL_DONE);
4154
4155   if (pre)
4156     tsi_link_before (&wi->tsi, pre, TSI_SAME_STMT);
4157 }
4158
4159 /* Copy EXP into a temporary.  Insert the initialization statement before TSI.  */
4160
4161 static tree
4162 init_tmp_var (tree exp, tree_stmt_iterator *tsi)
4163 {
4164   tree t, stmt;
4165
4166   t = create_tmp_var (TREE_TYPE (exp), NULL);
4167   DECL_GIMPLE_REG_P (t) = 1;
4168   stmt = build_gimple_modify_stmt (t, exp);
4169   SET_EXPR_LOCUS (stmt, EXPR_LOCUS (tsi_stmt (*tsi)));
4170   tsi_link_before (tsi, stmt, TSI_SAME_STMT);
4171
4172   return t;
4173 }
4174
4175 /* Similarly, but copy from the temporary and insert the statement
4176    after the iterator.  */
4177
4178 static tree
4179 save_tmp_var (tree exp, tree_stmt_iterator *tsi)
4180 {
4181   tree t, stmt;
4182
4183   t = create_tmp_var (TREE_TYPE (exp), NULL);
4184   DECL_GIMPLE_REG_P (t) = 1;
4185   stmt = build_gimple_modify_stmt (exp, t);
4186   SET_EXPR_LOCUS (stmt, EXPR_LOCUS (tsi_stmt (*tsi)));
4187   tsi_link_after (tsi, stmt, TSI_SAME_STMT);
4188
4189   return t;
4190 }
4191
4192 /* Callback for walk_stmts.  Lower the OpenMP directive pointed by TP.  */
4193
4194 static tree
4195 lower_omp_1 (tree *tp, int *walk_subtrees, void *data)
4196 {
4197   struct walk_stmt_info *wi = data;
4198   omp_context *ctx = wi->info;
4199   tree t = *tp;
4200
4201   /* If we have issued syntax errors, avoid doing any heavy lifting.
4202      Just replace the OpenMP directives with a NOP to avoid
4203      confusing RTL expansion.  */
4204   if (errorcount && OMP_DIRECTIVE_P (*tp))
4205     {
4206       *tp = build_empty_stmt ();
4207       return NULL_TREE;
4208     }
4209
4210   *walk_subtrees = 0;
4211   switch (TREE_CODE (*tp))
4212     {
4213     case OMP_PARALLEL:
4214       ctx = maybe_lookup_ctx (t);
4215       lower_omp_parallel (tp, ctx);
4216       break;
4217
4218     case OMP_FOR:
4219       ctx = maybe_lookup_ctx (t);
4220       gcc_assert (ctx);
4221       lower_omp_for (tp, ctx);
4222       break;
4223
4224     case OMP_SECTIONS:
4225       ctx = maybe_lookup_ctx (t);
4226       gcc_assert (ctx);
4227       lower_omp_sections (tp, ctx);
4228       break;
4229
4230     case OMP_SINGLE:
4231       ctx = maybe_lookup_ctx (t);
4232       gcc_assert (ctx);
4233       lower_omp_single (tp, ctx);
4234       break;
4235
4236     case OMP_MASTER:
4237       ctx = maybe_lookup_ctx (t);
4238       gcc_assert (ctx);
4239       lower_omp_master (tp, ctx);
4240       break;
4241
4242     case OMP_ORDERED:
4243       ctx = maybe_lookup_ctx (t);
4244       gcc_assert (ctx);
4245       lower_omp_ordered (tp, ctx);
4246       break;
4247
4248     case OMP_CRITICAL:
4249       ctx = maybe_lookup_ctx (t);
4250       gcc_assert (ctx);
4251       lower_omp_critical (tp, ctx);
4252       break;
4253
4254     case VAR_DECL:
4255       if (ctx && DECL_HAS_VALUE_EXPR_P (t))
4256         {
4257           lower_regimplify (&t, wi);
4258           if (wi->val_only)
4259             {
4260               if (wi->is_lhs)
4261                 t = save_tmp_var (t, &wi->tsi);
4262               else
4263                 t = init_tmp_var (t, &wi->tsi);
4264             }
4265           *tp = t;
4266         }
4267       break;
4268
4269     case ADDR_EXPR:
4270       if (ctx)
4271         lower_regimplify (tp, wi);
4272       break;
4273
4274     case ARRAY_REF:
4275     case ARRAY_RANGE_REF:
4276     case REALPART_EXPR:
4277     case IMAGPART_EXPR:
4278     case COMPONENT_REF:
4279     case VIEW_CONVERT_EXPR:
4280       if (ctx)
4281         lower_regimplify (tp, wi);
4282       break;
4283
4284     case INDIRECT_REF:
4285       if (ctx)
4286         {
4287           wi->is_lhs = false;
4288           wi->val_only = true;
4289           lower_regimplify (&TREE_OPERAND (t, 0), wi);
4290         }
4291       break;
4292
4293     default:
4294       if (!TYPE_P (t) && !DECL_P (t))
4295         *walk_subtrees = 1;
4296       break;
4297     }
4298
4299   return NULL_TREE;
4300 }
4301
4302 static void
4303 lower_omp (tree *stmt_p, omp_context *ctx)
4304 {
4305   struct walk_stmt_info wi;
4306
4307   memset (&wi, 0, sizeof (wi));
4308   wi.callback = lower_omp_1;
4309   wi.info = ctx;
4310   wi.val_only = true;
4311   wi.want_locations = true;
4312
4313   walk_stmts (&wi, stmt_p);
4314 }
4315 \f
4316 /* Main entry point.  */
4317
4318 static unsigned int
4319 execute_lower_omp (void)
4320 {
4321   all_contexts = splay_tree_new (splay_tree_compare_pointers, 0,
4322                                  delete_omp_context);
4323
4324   scan_omp (&DECL_SAVED_TREE (current_function_decl), NULL);
4325   gcc_assert (parallel_nesting_level == 0);
4326
4327   if (all_contexts->root)
4328     lower_omp (&DECL_SAVED_TREE (current_function_decl), NULL);
4329
4330   if (all_contexts)
4331     {
4332       splay_tree_delete (all_contexts);
4333       all_contexts = NULL;
4334     }
4335   return 0;
4336 }
4337
4338 static bool
4339 gate_lower_omp (void)
4340 {
4341   return flag_openmp != 0;
4342 }
4343
4344 struct tree_opt_pass pass_lower_omp = 
4345 {
4346   "omplower",                           /* name */
4347   gate_lower_omp,                       /* gate */
4348   execute_lower_omp,                    /* execute */
4349   NULL,                                 /* sub */
4350   NULL,                                 /* next */
4351   0,                                    /* static_pass_number */
4352   0,                                    /* tv_id */
4353   PROP_gimple_any,                      /* properties_required */
4354   PROP_gimple_lomp,                     /* properties_provided */
4355   0,                                    /* properties_destroyed */
4356   0,                                    /* todo_flags_start */
4357   TODO_dump_func,                       /* todo_flags_finish */
4358   0                                     /* letter */
4359 };
4360 \f
4361 /* The following is a utility to diagnose OpenMP structured block violations.
4362    It is not part of the "omplower" pass, as that's invoked too late.  It
4363    should be invoked by the respective front ends after gimplification.  */
4364
4365 static splay_tree all_labels;
4366
4367 /* Check for mismatched contexts and generate an error if needed.  Return
4368    true if an error is detected.  */
4369
4370 static bool
4371 diagnose_sb_0 (tree *stmt_p, tree branch_ctx, tree label_ctx)
4372 {
4373   bool exit_p = true;
4374
4375   if ((label_ctx ? TREE_VALUE (label_ctx) : NULL) == branch_ctx)
4376     return false;
4377
4378   /* Try to avoid confusing the user by producing and error message
4379      with correct "exit" or "enter" verbage.  We prefer "exit"
4380      unless we can show that LABEL_CTX is nested within BRANCH_CTX.  */
4381   if (branch_ctx == NULL)
4382     exit_p = false;
4383   else
4384     {
4385       while (label_ctx)
4386         {
4387           if (TREE_VALUE (label_ctx) == branch_ctx)
4388             {
4389               exit_p = false;
4390               break;
4391             }
4392           label_ctx = TREE_CHAIN (label_ctx);
4393         }
4394     }
4395
4396   if (exit_p)
4397     error ("invalid exit from OpenMP structured block");
4398   else
4399     error ("invalid entry to OpenMP structured block");
4400
4401   *stmt_p = build_empty_stmt ();
4402   return true;
4403 }
4404
4405 /* Pass 1: Create a minimal tree of OpenMP structured blocks, and record
4406    where in the tree each label is found.  */
4407
4408 static tree
4409 diagnose_sb_1 (tree *tp, int *walk_subtrees, void *data)
4410 {
4411   struct walk_stmt_info *wi = data;
4412   tree context = (tree) wi->info;
4413   tree inner_context;
4414   tree t = *tp;
4415
4416   *walk_subtrees = 0;
4417   switch (TREE_CODE (t))
4418     {
4419     case OMP_PARALLEL:
4420     case OMP_SECTIONS:
4421     case OMP_SINGLE:
4422       walk_tree (&OMP_CLAUSES (t), diagnose_sb_1, wi, NULL);
4423       /* FALLTHRU */
4424     case OMP_SECTION:
4425     case OMP_MASTER:
4426     case OMP_ORDERED:
4427     case OMP_CRITICAL:
4428       /* The minimal context here is just a tree of statements.  */
4429       inner_context = tree_cons (NULL, t, context);
4430       wi->info = inner_context;
4431       walk_stmts (wi, &OMP_BODY (t));
4432       wi->info = context;
4433       break;
4434
4435     case OMP_FOR:
4436       walk_tree (&OMP_FOR_CLAUSES (t), diagnose_sb_1, wi, NULL);
4437       inner_context = tree_cons (NULL, t, context);
4438       wi->info = inner_context;
4439       walk_tree (&OMP_FOR_INIT (t), diagnose_sb_1, wi, NULL);
4440       walk_tree (&OMP_FOR_COND (t), diagnose_sb_1, wi, NULL);
4441       walk_tree (&OMP_FOR_INCR (t), diagnose_sb_1, wi, NULL);
4442       walk_stmts (wi, &OMP_FOR_PRE_BODY (t));
4443       walk_stmts (wi, &OMP_FOR_BODY (t));
4444       wi->info = context;
4445       break;
4446
4447     case LABEL_EXPR:
4448       splay_tree_insert (all_labels, (splay_tree_key) LABEL_EXPR_LABEL (t),
4449                          (splay_tree_value) context);
4450       break;
4451
4452     default:
4453       break;
4454     }
4455
4456   return NULL_TREE;
4457 }
4458
4459 /* Pass 2: Check each branch and see if its context differs from that of
4460    the destination label's context.  */
4461
4462 static tree
4463 diagnose_sb_2 (tree *tp, int *walk_subtrees, void *data)
4464 {
4465   struct walk_stmt_info *wi = data;
4466   tree context = (tree) wi->info;
4467   splay_tree_node n;
4468   tree t = *tp;
4469
4470   *walk_subtrees = 0;
4471   switch (TREE_CODE (t))
4472     {
4473     case OMP_PARALLEL:
4474     case OMP_SECTIONS:
4475     case OMP_SINGLE:
4476       walk_tree (&OMP_CLAUSES (t), diagnose_sb_2, wi, NULL);
4477       /* FALLTHRU */
4478     case OMP_SECTION:
4479     case OMP_MASTER:
4480     case OMP_ORDERED:
4481     case OMP_CRITICAL:
4482       wi->info = t;
4483       walk_stmts (wi, &OMP_BODY (t));
4484       wi->info = context;
4485       break;
4486
4487     case OMP_FOR:
4488       walk_tree (&OMP_FOR_CLAUSES (t), diagnose_sb_2, wi, NULL);
4489       wi->info = t;
4490       walk_tree (&OMP_FOR_INIT (t), diagnose_sb_2, wi, NULL);
4491       walk_tree (&OMP_FOR_COND (t), diagnose_sb_2, wi, NULL);
4492       walk_tree (&OMP_FOR_INCR (t), diagnose_sb_2, wi, NULL);
4493       walk_stmts (wi, &OMP_FOR_PRE_BODY (t));
4494       walk_stmts (wi, &OMP_FOR_BODY (t));
4495       wi->info = context;
4496       break;
4497
4498     case GOTO_EXPR:
4499       {
4500         tree lab = GOTO_DESTINATION (t);
4501         if (TREE_CODE (lab) != LABEL_DECL)
4502           break;
4503
4504         n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
4505         diagnose_sb_0 (tp, context, n ? (tree) n->value : NULL_TREE);
4506       }
4507       break;
4508
4509     case SWITCH_EXPR:
4510       {
4511         tree vec = SWITCH_LABELS (t);
4512         int i, len = TREE_VEC_LENGTH (vec);
4513         for (i = 0; i < len; ++i)
4514           {
4515             tree lab = CASE_LABEL (TREE_VEC_ELT (vec, i));
4516             n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
4517             if (diagnose_sb_0 (tp, context, (tree) n->value))
4518               break;
4519           }
4520       }
4521       break;
4522
4523     case RETURN_EXPR:
4524       diagnose_sb_0 (tp, context, NULL_TREE);
4525       break;
4526
4527     default:
4528       break;
4529     }
4530
4531   return NULL_TREE;
4532 }
4533
4534 void
4535 diagnose_omp_structured_block_errors (tree fndecl)
4536 {
4537   tree save_current = current_function_decl;
4538   struct walk_stmt_info wi;
4539
4540   current_function_decl = fndecl;
4541
4542   all_labels = splay_tree_new (splay_tree_compare_pointers, 0, 0);
4543
4544   memset (&wi, 0, sizeof (wi));
4545   wi.callback = diagnose_sb_1;
4546   walk_stmts (&wi, &DECL_SAVED_TREE (fndecl));
4547
4548   memset (&wi, 0, sizeof (wi));
4549   wi.callback = diagnose_sb_2;
4550   wi.want_locations = true;
4551   wi.want_return_expr = true;
4552   walk_stmts (&wi, &DECL_SAVED_TREE (fndecl));
4553
4554   splay_tree_delete (all_labels);
4555   all_labels = NULL;
4556
4557   current_function_decl = save_current;
4558 }
4559
4560 #include "gt-omp-low.h"