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