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