OSDN Git Service

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