OSDN Git Service

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