OSDN Git Service

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