OSDN Git Service

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