OSDN Git Service

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