OSDN Git Service

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