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