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