re PR middle-end/54017 (Incorrect implementation of infinite loops in OpenMP sections...
[gcc.git] / gcc / omp-low.c
1 /* Lowering pass for OpenMP directives. Converts OpenMP directives
2 into explicit calls to the runtime library (libgomp) and data
3 marshalling to implement data sharing and copying clauses.
4 Contributed by Diego Novillo <dnovillo@redhat.com>
5
6 Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
7 Free Software Foundation, Inc.
8
9 This file is part of GCC.
10
11 GCC is free software; you can redistribute it and/or modify it under
12 the terms of the GNU General Public License as published by the Free
13 Software Foundation; either version 3, or (at your option) any later
14 version.
15
16 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
17 WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19 for more details.
20
21 You should have received a copy of the GNU General Public License
22 along with GCC; see the file COPYING3. If not see
23 <http://www.gnu.org/licenses/>. */
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 "gimple.h"
32 #include "tree-iterator.h"
33 #include "tree-inline.h"
34 #include "langhooks.h"
35 #include "diagnostic-core.h"
36 #include "tree-flow.h"
37 #include "flags.h"
38 #include "function.h"
39 #include "expr.h"
40 #include "tree-pass.h"
41 #include "ggc.h"
42 #include "except.h"
43 #include "splay-tree.h"
44 #include "optabs.h"
45 #include "cfgloop.h"
46
47
48 /* Lowering of OpenMP parallel and workshare constructs proceeds in two
49 phases. The first phase scans the function looking for OMP statements
50 and then for variables that must be replaced to satisfy data sharing
51 clauses. The second phase expands code for the constructs, as well as
52 re-gimplifying things when variables have been replaced with complex
53 expressions.
54
55 Final code generation is done by pass_expand_omp. The flowgraph is
56 scanned for parallel regions which are then moved to a new
57 function, to be invoked by the thread library. */
58
59 /* Context structure. Used to store information about each parallel
60 directive in the code. */
61
62 typedef struct omp_context
63 {
64 /* This field must be at the beginning, as we do "inheritance": Some
65 callback functions for tree-inline.c (e.g., omp_copy_decl)
66 receive a copy_body_data pointer that is up-casted to an
67 omp_context pointer. */
68 copy_body_data cb;
69
70 /* The tree of contexts corresponding to the encountered constructs. */
71 struct omp_context *outer;
72 gimple stmt;
73
74 /* Map variables to fields in a structure that allows communication
75 between sending and receiving threads. */
76 splay_tree field_map;
77 tree record_type;
78 tree sender_decl;
79 tree receiver_decl;
80
81 /* These are used just by task contexts, if task firstprivate fn is
82 needed. srecord_type is used to communicate from the thread
83 that encountered the task construct to task firstprivate fn,
84 record_type is allocated by GOMP_task, initialized by task firstprivate
85 fn and passed to the task body fn. */
86 splay_tree sfield_map;
87 tree srecord_type;
88
89 /* A chain of variables to add to the top-level block surrounding the
90 construct. In the case of a parallel, this is in the child function. */
91 tree block_vars;
92
93 /* What to do with variables with implicitly determined sharing
94 attributes. */
95 enum omp_clause_default_kind default_kind;
96
97 /* Nesting depth of this context. Used to beautify error messages re
98 invalid gotos. The outermost ctx is depth 1, with depth 0 being
99 reserved for the main body of the function. */
100 int depth;
101
102 /* True if this parallel directive is nested within another. */
103 bool is_nested;
104 } omp_context;
105
106
107 struct omp_for_data_loop
108 {
109 tree v, n1, n2, step;
110 enum tree_code cond_code;
111 };
112
113 /* A structure describing the main elements of a parallel loop. */
114
115 struct omp_for_data
116 {
117 struct omp_for_data_loop loop;
118 tree chunk_size;
119 gimple for_stmt;
120 tree pre, iter_type;
121 int collapse;
122 bool have_nowait, have_ordered;
123 enum omp_clause_schedule_kind sched_kind;
124 struct omp_for_data_loop *loops;
125 };
126
127
128 static splay_tree all_contexts;
129 static int taskreg_nesting_level;
130 struct omp_region *root_omp_region;
131 static bitmap task_shared_vars;
132
133 static void scan_omp (gimple_seq *, omp_context *);
134 static tree scan_omp_1_op (tree *, int *, void *);
135
136 #define WALK_SUBSTMTS \
137 case GIMPLE_BIND: \
138 case GIMPLE_TRY: \
139 case GIMPLE_CATCH: \
140 case GIMPLE_EH_FILTER: \
141 case GIMPLE_TRANSACTION: \
142 /* The sub-statements for these should be walked. */ \
143 *handled_ops_p = false; \
144 break;
145
146 /* Convenience function for calling scan_omp_1_op on tree operands. */
147
148 static inline tree
149 scan_omp_op (tree *tp, omp_context *ctx)
150 {
151 struct walk_stmt_info wi;
152
153 memset (&wi, 0, sizeof (wi));
154 wi.info = ctx;
155 wi.want_locations = true;
156
157 return walk_tree (tp, scan_omp_1_op, &wi, NULL);
158 }
159
160 static void lower_omp (gimple_seq *, omp_context *);
161 static tree lookup_decl_in_outer_ctx (tree, omp_context *);
162 static tree maybe_lookup_decl_in_outer_ctx (tree, omp_context *);
163
164 /* Find an OpenMP clause of type KIND within CLAUSES. */
165
166 tree
167 find_omp_clause (tree clauses, enum omp_clause_code kind)
168 {
169 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
170 if (OMP_CLAUSE_CODE (clauses) == kind)
171 return clauses;
172
173 return NULL_TREE;
174 }
175
176 /* Return true if CTX is for an omp parallel. */
177
178 static inline bool
179 is_parallel_ctx (omp_context *ctx)
180 {
181 return gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL;
182 }
183
184
185 /* Return true if CTX is for an omp task. */
186
187 static inline bool
188 is_task_ctx (omp_context *ctx)
189 {
190 return gimple_code (ctx->stmt) == GIMPLE_OMP_TASK;
191 }
192
193
194 /* Return true if CTX is for an omp parallel or omp task. */
195
196 static inline bool
197 is_taskreg_ctx (omp_context *ctx)
198 {
199 return gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL
200 || gimple_code (ctx->stmt) == GIMPLE_OMP_TASK;
201 }
202
203
204 /* Return true if REGION is a combined parallel+workshare region. */
205
206 static inline bool
207 is_combined_parallel (struct omp_region *region)
208 {
209 return region->is_combined_parallel;
210 }
211
212
213 /* Extract the header elements of parallel loop FOR_STMT and store
214 them into *FD. */
215
216 static void
217 extract_omp_for_data (gimple for_stmt, struct omp_for_data *fd,
218 struct omp_for_data_loop *loops)
219 {
220 tree t, var, *collapse_iter, *collapse_count;
221 tree count = NULL_TREE, iter_type = long_integer_type_node;
222 struct omp_for_data_loop *loop;
223 int i;
224 struct omp_for_data_loop dummy_loop;
225 location_t loc = gimple_location (for_stmt);
226
227 fd->for_stmt = for_stmt;
228 fd->pre = NULL;
229 fd->collapse = gimple_omp_for_collapse (for_stmt);
230 if (fd->collapse > 1)
231 fd->loops = loops;
232 else
233 fd->loops = &fd->loop;
234
235 fd->have_nowait = fd->have_ordered = false;
236 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
237 fd->chunk_size = NULL_TREE;
238 collapse_iter = NULL;
239 collapse_count = NULL;
240
241 for (t = gimple_omp_for_clauses (for_stmt); t ; t = OMP_CLAUSE_CHAIN (t))
242 switch (OMP_CLAUSE_CODE (t))
243 {
244 case OMP_CLAUSE_NOWAIT:
245 fd->have_nowait = true;
246 break;
247 case OMP_CLAUSE_ORDERED:
248 fd->have_ordered = true;
249 break;
250 case OMP_CLAUSE_SCHEDULE:
251 fd->sched_kind = OMP_CLAUSE_SCHEDULE_KIND (t);
252 fd->chunk_size = OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (t);
253 break;
254 case OMP_CLAUSE_COLLAPSE:
255 if (fd->collapse > 1)
256 {
257 collapse_iter = &OMP_CLAUSE_COLLAPSE_ITERVAR (t);
258 collapse_count = &OMP_CLAUSE_COLLAPSE_COUNT (t);
259 }
260 default:
261 break;
262 }
263
264 /* FIXME: for now map schedule(auto) to schedule(static).
265 There should be analysis to determine whether all iterations
266 are approximately the same amount of work (then schedule(static)
267 is best) or if it varies (then schedule(dynamic,N) is better). */
268 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_AUTO)
269 {
270 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
271 gcc_assert (fd->chunk_size == NULL);
272 }
273 gcc_assert (fd->collapse == 1 || collapse_iter != NULL);
274 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
275 gcc_assert (fd->chunk_size == NULL);
276 else if (fd->chunk_size == NULL)
277 {
278 /* We only need to compute a default chunk size for ordered
279 static loops and dynamic loops. */
280 if (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
281 || fd->have_ordered
282 || fd->collapse > 1)
283 fd->chunk_size = (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
284 ? integer_zero_node : integer_one_node;
285 }
286
287 for (i = 0; i < fd->collapse; i++)
288 {
289 if (fd->collapse == 1)
290 loop = &fd->loop;
291 else if (loops != NULL)
292 loop = loops + i;
293 else
294 loop = &dummy_loop;
295
296
297 loop->v = gimple_omp_for_index (for_stmt, i);
298 gcc_assert (SSA_VAR_P (loop->v));
299 gcc_assert (TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
300 || TREE_CODE (TREE_TYPE (loop->v)) == POINTER_TYPE);
301 var = TREE_CODE (loop->v) == SSA_NAME ? SSA_NAME_VAR (loop->v) : loop->v;
302 loop->n1 = gimple_omp_for_initial (for_stmt, i);
303
304 loop->cond_code = gimple_omp_for_cond (for_stmt, i);
305 loop->n2 = gimple_omp_for_final (for_stmt, i);
306 switch (loop->cond_code)
307 {
308 case LT_EXPR:
309 case GT_EXPR:
310 break;
311 case LE_EXPR:
312 if (POINTER_TYPE_P (TREE_TYPE (loop->n2)))
313 loop->n2 = fold_build_pointer_plus_hwi_loc (loc, loop->n2, 1);
314 else
315 loop->n2 = fold_build2_loc (loc,
316 PLUS_EXPR, TREE_TYPE (loop->n2), loop->n2,
317 build_int_cst (TREE_TYPE (loop->n2), 1));
318 loop->cond_code = LT_EXPR;
319 break;
320 case GE_EXPR:
321 if (POINTER_TYPE_P (TREE_TYPE (loop->n2)))
322 loop->n2 = fold_build_pointer_plus_hwi_loc (loc, loop->n2, -1);
323 else
324 loop->n2 = fold_build2_loc (loc,
325 MINUS_EXPR, TREE_TYPE (loop->n2), loop->n2,
326 build_int_cst (TREE_TYPE (loop->n2), 1));
327 loop->cond_code = GT_EXPR;
328 break;
329 default:
330 gcc_unreachable ();
331 }
332
333 t = gimple_omp_for_incr (for_stmt, i);
334 gcc_assert (TREE_OPERAND (t, 0) == var);
335 switch (TREE_CODE (t))
336 {
337 case PLUS_EXPR:
338 loop->step = TREE_OPERAND (t, 1);
339 break;
340 case POINTER_PLUS_EXPR:
341 loop->step = fold_convert (ssizetype, TREE_OPERAND (t, 1));
342 break;
343 case MINUS_EXPR:
344 loop->step = TREE_OPERAND (t, 1);
345 loop->step = fold_build1_loc (loc,
346 NEGATE_EXPR, TREE_TYPE (loop->step),
347 loop->step);
348 break;
349 default:
350 gcc_unreachable ();
351 }
352
353 if (iter_type != long_long_unsigned_type_node)
354 {
355 if (POINTER_TYPE_P (TREE_TYPE (loop->v)))
356 iter_type = long_long_unsigned_type_node;
357 else if (TYPE_UNSIGNED (TREE_TYPE (loop->v))
358 && TYPE_PRECISION (TREE_TYPE (loop->v))
359 >= TYPE_PRECISION (iter_type))
360 {
361 tree n;
362
363 if (loop->cond_code == LT_EXPR)
364 n = fold_build2_loc (loc,
365 PLUS_EXPR, TREE_TYPE (loop->v),
366 loop->n2, loop->step);
367 else
368 n = loop->n1;
369 if (TREE_CODE (n) != INTEGER_CST
370 || tree_int_cst_lt (TYPE_MAX_VALUE (iter_type), n))
371 iter_type = long_long_unsigned_type_node;
372 }
373 else if (TYPE_PRECISION (TREE_TYPE (loop->v))
374 > TYPE_PRECISION (iter_type))
375 {
376 tree n1, n2;
377
378 if (loop->cond_code == LT_EXPR)
379 {
380 n1 = loop->n1;
381 n2 = fold_build2_loc (loc,
382 PLUS_EXPR, TREE_TYPE (loop->v),
383 loop->n2, loop->step);
384 }
385 else
386 {
387 n1 = fold_build2_loc (loc,
388 MINUS_EXPR, TREE_TYPE (loop->v),
389 loop->n2, loop->step);
390 n2 = loop->n1;
391 }
392 if (TREE_CODE (n1) != INTEGER_CST
393 || TREE_CODE (n2) != INTEGER_CST
394 || !tree_int_cst_lt (TYPE_MIN_VALUE (iter_type), n1)
395 || !tree_int_cst_lt (n2, TYPE_MAX_VALUE (iter_type)))
396 iter_type = long_long_unsigned_type_node;
397 }
398 }
399
400 if (collapse_count && *collapse_count == NULL)
401 {
402 if ((i == 0 || count != NULL_TREE)
403 && TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
404 && TREE_CONSTANT (loop->n1)
405 && TREE_CONSTANT (loop->n2)
406 && TREE_CODE (loop->step) == INTEGER_CST)
407 {
408 tree itype = TREE_TYPE (loop->v);
409
410 if (POINTER_TYPE_P (itype))
411 itype = signed_type_for (itype);
412 t = build_int_cst (itype, (loop->cond_code == LT_EXPR ? -1 : 1));
413 t = fold_build2_loc (loc,
414 PLUS_EXPR, itype,
415 fold_convert_loc (loc, itype, loop->step), t);
416 t = fold_build2_loc (loc, PLUS_EXPR, itype, t,
417 fold_convert_loc (loc, itype, loop->n2));
418 t = fold_build2_loc (loc, MINUS_EXPR, itype, t,
419 fold_convert_loc (loc, itype, loop->n1));
420 if (TYPE_UNSIGNED (itype) && loop->cond_code == GT_EXPR)
421 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype,
422 fold_build1_loc (loc, NEGATE_EXPR, itype, t),
423 fold_build1_loc (loc, NEGATE_EXPR, itype,
424 fold_convert_loc (loc, itype,
425 loop->step)));
426 else
427 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, t,
428 fold_convert_loc (loc, itype, loop->step));
429 t = fold_convert_loc (loc, long_long_unsigned_type_node, t);
430 if (count != NULL_TREE)
431 count = fold_build2_loc (loc,
432 MULT_EXPR, long_long_unsigned_type_node,
433 count, t);
434 else
435 count = t;
436 if (TREE_CODE (count) != INTEGER_CST)
437 count = NULL_TREE;
438 }
439 else
440 count = NULL_TREE;
441 }
442 }
443
444 if (count)
445 {
446 if (!tree_int_cst_lt (count, TYPE_MAX_VALUE (long_integer_type_node)))
447 iter_type = long_long_unsigned_type_node;
448 else
449 iter_type = long_integer_type_node;
450 }
451 else if (collapse_iter && *collapse_iter != NULL)
452 iter_type = TREE_TYPE (*collapse_iter);
453 fd->iter_type = iter_type;
454 if (collapse_iter && *collapse_iter == NULL)
455 *collapse_iter = create_tmp_var (iter_type, ".iter");
456 if (collapse_count && *collapse_count == NULL)
457 {
458 if (count)
459 *collapse_count = fold_convert_loc (loc, iter_type, count);
460 else
461 *collapse_count = create_tmp_var (iter_type, ".count");
462 }
463
464 if (fd->collapse > 1)
465 {
466 fd->loop.v = *collapse_iter;
467 fd->loop.n1 = build_int_cst (TREE_TYPE (fd->loop.v), 0);
468 fd->loop.n2 = *collapse_count;
469 fd->loop.step = build_int_cst (TREE_TYPE (fd->loop.v), 1);
470 fd->loop.cond_code = LT_EXPR;
471 }
472 }
473
474
475 /* Given two blocks PAR_ENTRY_BB and WS_ENTRY_BB such that WS_ENTRY_BB
476 is the immediate dominator of PAR_ENTRY_BB, return true if there
477 are no data dependencies that would prevent expanding the parallel
478 directive at PAR_ENTRY_BB as a combined parallel+workshare region.
479
480 When expanding a combined parallel+workshare region, the call to
481 the child function may need additional arguments in the case of
482 GIMPLE_OMP_FOR regions. In some cases, these arguments are
483 computed out of variables passed in from the parent to the child
484 via 'struct .omp_data_s'. For instance:
485
486 #pragma omp parallel for schedule (guided, i * 4)
487 for (j ...)
488
489 Is lowered into:
490
491 # BLOCK 2 (PAR_ENTRY_BB)
492 .omp_data_o.i = i;
493 #pragma omp parallel [child fn: bar.omp_fn.0 ( ..., D.1598)
494
495 # BLOCK 3 (WS_ENTRY_BB)
496 .omp_data_i = &.omp_data_o;
497 D.1667 = .omp_data_i->i;
498 D.1598 = D.1667 * 4;
499 #pragma omp for schedule (guided, D.1598)
500
501 When we outline the parallel region, the call to the child function
502 'bar.omp_fn.0' will need the value D.1598 in its argument list, but
503 that value is computed *after* the call site. So, in principle we
504 cannot do the transformation.
505
506 To see whether the code in WS_ENTRY_BB blocks the combined
507 parallel+workshare call, we collect all the variables used in the
508 GIMPLE_OMP_FOR header check whether they appear on the LHS of any
509 statement in WS_ENTRY_BB. If so, then we cannot emit the combined
510 call.
511
512 FIXME. If we had the SSA form built at this point, we could merely
513 hoist the code in block 3 into block 2 and be done with it. But at
514 this point we don't have dataflow information and though we could
515 hack something up here, it is really not worth the aggravation. */
516
517 static bool
518 workshare_safe_to_combine_p (basic_block ws_entry_bb)
519 {
520 struct omp_for_data fd;
521 gimple ws_stmt = last_stmt (ws_entry_bb);
522
523 if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
524 return true;
525
526 gcc_assert (gimple_code (ws_stmt) == GIMPLE_OMP_FOR);
527
528 extract_omp_for_data (ws_stmt, &fd, NULL);
529
530 if (fd.collapse > 1 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
531 return false;
532 if (fd.iter_type != long_integer_type_node)
533 return false;
534
535 /* FIXME. We give up too easily here. If any of these arguments
536 are not constants, they will likely involve variables that have
537 been mapped into fields of .omp_data_s for sharing with the child
538 function. With appropriate data flow, it would be possible to
539 see through this. */
540 if (!is_gimple_min_invariant (fd.loop.n1)
541 || !is_gimple_min_invariant (fd.loop.n2)
542 || !is_gimple_min_invariant (fd.loop.step)
543 || (fd.chunk_size && !is_gimple_min_invariant (fd.chunk_size)))
544 return false;
545
546 return true;
547 }
548
549
550 /* Collect additional arguments needed to emit a combined
551 parallel+workshare call. WS_STMT is the workshare directive being
552 expanded. */
553
554 static VEC(tree,gc) *
555 get_ws_args_for (gimple ws_stmt)
556 {
557 tree t;
558 location_t loc = gimple_location (ws_stmt);
559 VEC(tree,gc) *ws_args;
560
561 if (gimple_code (ws_stmt) == GIMPLE_OMP_FOR)
562 {
563 struct omp_for_data fd;
564
565 extract_omp_for_data (ws_stmt, &fd, NULL);
566
567 ws_args = VEC_alloc (tree, gc, 3 + (fd.chunk_size != 0));
568
569 t = fold_convert_loc (loc, long_integer_type_node, fd.loop.n1);
570 VEC_quick_push (tree, ws_args, t);
571
572 t = fold_convert_loc (loc, long_integer_type_node, fd.loop.n2);
573 VEC_quick_push (tree, ws_args, t);
574
575 t = fold_convert_loc (loc, long_integer_type_node, fd.loop.step);
576 VEC_quick_push (tree, ws_args, t);
577
578 if (fd.chunk_size)
579 {
580 t = fold_convert_loc (loc, long_integer_type_node, fd.chunk_size);
581 VEC_quick_push (tree, ws_args, t);
582 }
583
584 return ws_args;
585 }
586 else if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
587 {
588 /* Number of sections is equal to the number of edges from the
589 GIMPLE_OMP_SECTIONS_SWITCH statement, except for the one to
590 the exit of the sections region. */
591 basic_block bb = single_succ (gimple_bb (ws_stmt));
592 t = build_int_cst (unsigned_type_node, EDGE_COUNT (bb->succs) - 1);
593 ws_args = VEC_alloc (tree, gc, 1);
594 VEC_quick_push (tree, ws_args, t);
595 return ws_args;
596 }
597
598 gcc_unreachable ();
599 }
600
601
602 /* Discover whether REGION is a combined parallel+workshare region. */
603
604 static void
605 determine_parallel_type (struct omp_region *region)
606 {
607 basic_block par_entry_bb, par_exit_bb;
608 basic_block ws_entry_bb, ws_exit_bb;
609
610 if (region == NULL || region->inner == NULL
611 || region->exit == NULL || region->inner->exit == NULL
612 || region->inner->cont == NULL)
613 return;
614
615 /* We only support parallel+for and parallel+sections. */
616 if (region->type != GIMPLE_OMP_PARALLEL
617 || (region->inner->type != GIMPLE_OMP_FOR
618 && region->inner->type != GIMPLE_OMP_SECTIONS))
619 return;
620
621 /* Check for perfect nesting PAR_ENTRY_BB -> WS_ENTRY_BB and
622 WS_EXIT_BB -> PAR_EXIT_BB. */
623 par_entry_bb = region->entry;
624 par_exit_bb = region->exit;
625 ws_entry_bb = region->inner->entry;
626 ws_exit_bb = region->inner->exit;
627
628 if (single_succ (par_entry_bb) == ws_entry_bb
629 && single_succ (ws_exit_bb) == par_exit_bb
630 && workshare_safe_to_combine_p (ws_entry_bb)
631 && (gimple_omp_parallel_combined_p (last_stmt (par_entry_bb))
632 || (last_and_only_stmt (ws_entry_bb)
633 && last_and_only_stmt (par_exit_bb))))
634 {
635 gimple ws_stmt = last_stmt (ws_entry_bb);
636
637 if (region->inner->type == GIMPLE_OMP_FOR)
638 {
639 /* If this is a combined parallel loop, we need to determine
640 whether or not to use the combined library calls. There
641 are two cases where we do not apply the transformation:
642 static loops and any kind of ordered loop. In the first
643 case, we already open code the loop so there is no need
644 to do anything else. In the latter case, the combined
645 parallel loop call would still need extra synchronization
646 to implement ordered semantics, so there would not be any
647 gain in using the combined call. */
648 tree clauses = gimple_omp_for_clauses (ws_stmt);
649 tree c = find_omp_clause (clauses, OMP_CLAUSE_SCHEDULE);
650 if (c == NULL
651 || OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_STATIC
652 || find_omp_clause (clauses, OMP_CLAUSE_ORDERED))
653 {
654 region->is_combined_parallel = false;
655 region->inner->is_combined_parallel = false;
656 return;
657 }
658 }
659
660 region->is_combined_parallel = true;
661 region->inner->is_combined_parallel = true;
662 region->ws_args = get_ws_args_for (ws_stmt);
663 }
664 }
665
666
667 /* Return true if EXPR is variable sized. */
668
669 static inline bool
670 is_variable_sized (const_tree expr)
671 {
672 return !TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (expr)));
673 }
674
675 /* Return true if DECL is a reference type. */
676
677 static inline bool
678 is_reference (tree decl)
679 {
680 return lang_hooks.decls.omp_privatize_by_reference (decl);
681 }
682
683 /* Lookup variables in the decl or field splay trees. The "maybe" form
684 allows for the variable form to not have been entered, otherwise we
685 assert that the variable must have been entered. */
686
687 static inline tree
688 lookup_decl (tree var, omp_context *ctx)
689 {
690 tree *n;
691 n = (tree *) pointer_map_contains (ctx->cb.decl_map, var);
692 return *n;
693 }
694
695 static inline tree
696 maybe_lookup_decl (const_tree var, omp_context *ctx)
697 {
698 tree *n;
699 n = (tree *) pointer_map_contains (ctx->cb.decl_map, var);
700 return n ? *n : NULL_TREE;
701 }
702
703 static inline tree
704 lookup_field (tree var, omp_context *ctx)
705 {
706 splay_tree_node n;
707 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
708 return (tree) n->value;
709 }
710
711 static inline tree
712 lookup_sfield (tree var, omp_context *ctx)
713 {
714 splay_tree_node n;
715 n = splay_tree_lookup (ctx->sfield_map
716 ? ctx->sfield_map : ctx->field_map,
717 (splay_tree_key) var);
718 return (tree) n->value;
719 }
720
721 static inline tree
722 maybe_lookup_field (tree var, omp_context *ctx)
723 {
724 splay_tree_node n;
725 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
726 return n ? (tree) n->value : NULL_TREE;
727 }
728
729 /* Return true if DECL should be copied by pointer. SHARED_CTX is
730 the parallel context if DECL is to be shared. */
731
732 static bool
733 use_pointer_for_field (tree decl, omp_context *shared_ctx)
734 {
735 if (AGGREGATE_TYPE_P (TREE_TYPE (decl)))
736 return true;
737
738 /* We can only use copy-in/copy-out semantics for shared variables
739 when we know the value is not accessible from an outer scope. */
740 if (shared_ctx)
741 {
742 /* ??? Trivially accessible from anywhere. But why would we even
743 be passing an address in this case? Should we simply assert
744 this to be false, or should we have a cleanup pass that removes
745 these from the list of mappings? */
746 if (TREE_STATIC (decl) || DECL_EXTERNAL (decl))
747 return true;
748
749 /* For variables with DECL_HAS_VALUE_EXPR_P set, we cannot tell
750 without analyzing the expression whether or not its location
751 is accessible to anyone else. In the case of nested parallel
752 regions it certainly may be. */
753 if (TREE_CODE (decl) != RESULT_DECL && DECL_HAS_VALUE_EXPR_P (decl))
754 return true;
755
756 /* Do not use copy-in/copy-out for variables that have their
757 address taken. */
758 if (TREE_ADDRESSABLE (decl))
759 return true;
760
761 /* Disallow copy-in/out in nested parallel if
762 decl is shared in outer parallel, otherwise
763 each thread could store the shared variable
764 in its own copy-in location, making the
765 variable no longer really shared. */
766 if (!TREE_READONLY (decl) && shared_ctx->is_nested)
767 {
768 omp_context *up;
769
770 for (up = shared_ctx->outer; up; up = up->outer)
771 if (is_taskreg_ctx (up) && maybe_lookup_decl (decl, up))
772 break;
773
774 if (up)
775 {
776 tree c;
777
778 for (c = gimple_omp_taskreg_clauses (up->stmt);
779 c; c = OMP_CLAUSE_CHAIN (c))
780 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
781 && OMP_CLAUSE_DECL (c) == decl)
782 break;
783
784 if (c)
785 goto maybe_mark_addressable_and_ret;
786 }
787 }
788
789 /* For tasks avoid using copy-in/out, unless they are readonly
790 (in which case just copy-in is used). As tasks can be
791 deferred or executed in different thread, when GOMP_task
792 returns, the task hasn't necessarily terminated. */
793 if (!TREE_READONLY (decl) && is_task_ctx (shared_ctx))
794 {
795 tree outer;
796 maybe_mark_addressable_and_ret:
797 outer = maybe_lookup_decl_in_outer_ctx (decl, shared_ctx);
798 if (is_gimple_reg (outer))
799 {
800 /* Taking address of OUTER in lower_send_shared_vars
801 might need regimplification of everything that uses the
802 variable. */
803 if (!task_shared_vars)
804 task_shared_vars = BITMAP_ALLOC (NULL);
805 bitmap_set_bit (task_shared_vars, DECL_UID (outer));
806 TREE_ADDRESSABLE (outer) = 1;
807 }
808 return true;
809 }
810 }
811
812 return false;
813 }
814
815 /* Create a new VAR_DECL and copy information from VAR to it. */
816
817 tree
818 copy_var_decl (tree var, tree name, tree type)
819 {
820 tree copy = build_decl (DECL_SOURCE_LOCATION (var), VAR_DECL, name, type);
821
822 TREE_ADDRESSABLE (copy) = TREE_ADDRESSABLE (var);
823 TREE_THIS_VOLATILE (copy) = TREE_THIS_VOLATILE (var);
824 DECL_GIMPLE_REG_P (copy) = DECL_GIMPLE_REG_P (var);
825 DECL_ARTIFICIAL (copy) = DECL_ARTIFICIAL (var);
826 DECL_IGNORED_P (copy) = DECL_IGNORED_P (var);
827 DECL_CONTEXT (copy) = DECL_CONTEXT (var);
828 TREE_USED (copy) = 1;
829 DECL_SEEN_IN_BIND_EXPR_P (copy) = 1;
830
831 return copy;
832 }
833
834 /* Construct a new automatic decl similar to VAR. */
835
836 static tree
837 omp_copy_decl_2 (tree var, tree name, tree type, omp_context *ctx)
838 {
839 tree copy = copy_var_decl (var, name, type);
840
841 DECL_CONTEXT (copy) = current_function_decl;
842 DECL_CHAIN (copy) = ctx->block_vars;
843 ctx->block_vars = copy;
844
845 return copy;
846 }
847
848 static tree
849 omp_copy_decl_1 (tree var, omp_context *ctx)
850 {
851 return omp_copy_decl_2 (var, DECL_NAME (var), TREE_TYPE (var), ctx);
852 }
853
854 /* Build COMPONENT_REF and set TREE_THIS_VOLATILE and TREE_READONLY on it
855 as appropriate. */
856 static tree
857 omp_build_component_ref (tree obj, tree field)
858 {
859 tree ret = build3 (COMPONENT_REF, TREE_TYPE (field), obj, field, NULL);
860 if (TREE_THIS_VOLATILE (field))
861 TREE_THIS_VOLATILE (ret) |= 1;
862 if (TREE_READONLY (field))
863 TREE_READONLY (ret) |= 1;
864 return ret;
865 }
866
867 /* Build tree nodes to access the field for VAR on the receiver side. */
868
869 static tree
870 build_receiver_ref (tree var, bool by_ref, omp_context *ctx)
871 {
872 tree x, field = lookup_field (var, ctx);
873
874 /* If the receiver record type was remapped in the child function,
875 remap the field into the new record type. */
876 x = maybe_lookup_field (field, ctx);
877 if (x != NULL)
878 field = x;
879
880 x = build_simple_mem_ref (ctx->receiver_decl);
881 x = omp_build_component_ref (x, field);
882 if (by_ref)
883 x = build_simple_mem_ref (x);
884
885 return x;
886 }
887
888 /* Build tree nodes to access VAR in the scope outer to CTX. In the case
889 of a parallel, this is a component reference; for workshare constructs
890 this is some variable. */
891
892 static tree
893 build_outer_var_ref (tree var, omp_context *ctx)
894 {
895 tree x;
896
897 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx)))
898 x = var;
899 else if (is_variable_sized (var))
900 {
901 x = TREE_OPERAND (DECL_VALUE_EXPR (var), 0);
902 x = build_outer_var_ref (x, ctx);
903 x = build_simple_mem_ref (x);
904 }
905 else if (is_taskreg_ctx (ctx))
906 {
907 bool by_ref = use_pointer_for_field (var, NULL);
908 x = build_receiver_ref (var, by_ref, ctx);
909 }
910 else if (ctx->outer)
911 x = lookup_decl (var, ctx->outer);
912 else if (is_reference (var))
913 /* This can happen with orphaned constructs. If var is reference, it is
914 possible it is shared and as such valid. */
915 x = var;
916 else
917 gcc_unreachable ();
918
919 if (is_reference (var))
920 x = build_simple_mem_ref (x);
921
922 return x;
923 }
924
925 /* Build tree nodes to access the field for VAR on the sender side. */
926
927 static tree
928 build_sender_ref (tree var, omp_context *ctx)
929 {
930 tree field = lookup_sfield (var, ctx);
931 return omp_build_component_ref (ctx->sender_decl, field);
932 }
933
934 /* Add a new field for VAR inside the structure CTX->SENDER_DECL. */
935
936 static void
937 install_var_field (tree var, bool by_ref, int mask, omp_context *ctx)
938 {
939 tree field, type, sfield = NULL_TREE;
940
941 gcc_assert ((mask & 1) == 0
942 || !splay_tree_lookup (ctx->field_map, (splay_tree_key) var));
943 gcc_assert ((mask & 2) == 0 || !ctx->sfield_map
944 || !splay_tree_lookup (ctx->sfield_map, (splay_tree_key) var));
945
946 type = TREE_TYPE (var);
947 if (by_ref)
948 type = build_pointer_type (type);
949 else if ((mask & 3) == 1 && is_reference (var))
950 type = TREE_TYPE (type);
951
952 field = build_decl (DECL_SOURCE_LOCATION (var),
953 FIELD_DECL, DECL_NAME (var), type);
954
955 /* Remember what variable this field was created for. This does have a
956 side effect of making dwarf2out ignore this member, so for helpful
957 debugging we clear it later in delete_omp_context. */
958 DECL_ABSTRACT_ORIGIN (field) = var;
959 if (type == TREE_TYPE (var))
960 {
961 DECL_ALIGN (field) = DECL_ALIGN (var);
962 DECL_USER_ALIGN (field) = DECL_USER_ALIGN (var);
963 TREE_THIS_VOLATILE (field) = TREE_THIS_VOLATILE (var);
964 }
965 else
966 DECL_ALIGN (field) = TYPE_ALIGN (type);
967
968 if ((mask & 3) == 3)
969 {
970 insert_field_into_struct (ctx->record_type, field);
971 if (ctx->srecord_type)
972 {
973 sfield = build_decl (DECL_SOURCE_LOCATION (var),
974 FIELD_DECL, DECL_NAME (var), type);
975 DECL_ABSTRACT_ORIGIN (sfield) = var;
976 DECL_ALIGN (sfield) = DECL_ALIGN (field);
977 DECL_USER_ALIGN (sfield) = DECL_USER_ALIGN (field);
978 TREE_THIS_VOLATILE (sfield) = TREE_THIS_VOLATILE (field);
979 insert_field_into_struct (ctx->srecord_type, sfield);
980 }
981 }
982 else
983 {
984 if (ctx->srecord_type == NULL_TREE)
985 {
986 tree t;
987
988 ctx->srecord_type = lang_hooks.types.make_type (RECORD_TYPE);
989 ctx->sfield_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
990 for (t = TYPE_FIELDS (ctx->record_type); t ; t = TREE_CHAIN (t))
991 {
992 sfield = build_decl (DECL_SOURCE_LOCATION (var),
993 FIELD_DECL, DECL_NAME (t), TREE_TYPE (t));
994 DECL_ABSTRACT_ORIGIN (sfield) = DECL_ABSTRACT_ORIGIN (t);
995 insert_field_into_struct (ctx->srecord_type, sfield);
996 splay_tree_insert (ctx->sfield_map,
997 (splay_tree_key) DECL_ABSTRACT_ORIGIN (t),
998 (splay_tree_value) sfield);
999 }
1000 }
1001 sfield = field;
1002 insert_field_into_struct ((mask & 1) ? ctx->record_type
1003 : ctx->srecord_type, field);
1004 }
1005
1006 if (mask & 1)
1007 splay_tree_insert (ctx->field_map, (splay_tree_key) var,
1008 (splay_tree_value) field);
1009 if ((mask & 2) && ctx->sfield_map)
1010 splay_tree_insert (ctx->sfield_map, (splay_tree_key) var,
1011 (splay_tree_value) sfield);
1012 }
1013
1014 static tree
1015 install_var_local (tree var, omp_context *ctx)
1016 {
1017 tree new_var = omp_copy_decl_1 (var, ctx);
1018 insert_decl_map (&ctx->cb, var, new_var);
1019 return new_var;
1020 }
1021
1022 /* Adjust the replacement for DECL in CTX for the new context. This means
1023 copying the DECL_VALUE_EXPR, and fixing up the type. */
1024
1025 static void
1026 fixup_remapped_decl (tree decl, omp_context *ctx, bool private_debug)
1027 {
1028 tree new_decl, size;
1029
1030 new_decl = lookup_decl (decl, ctx);
1031
1032 TREE_TYPE (new_decl) = remap_type (TREE_TYPE (decl), &ctx->cb);
1033
1034 if ((!TREE_CONSTANT (DECL_SIZE (new_decl)) || private_debug)
1035 && DECL_HAS_VALUE_EXPR_P (decl))
1036 {
1037 tree ve = DECL_VALUE_EXPR (decl);
1038 walk_tree (&ve, copy_tree_body_r, &ctx->cb, NULL);
1039 SET_DECL_VALUE_EXPR (new_decl, ve);
1040 DECL_HAS_VALUE_EXPR_P (new_decl) = 1;
1041 }
1042
1043 if (!TREE_CONSTANT (DECL_SIZE (new_decl)))
1044 {
1045 size = remap_decl (DECL_SIZE (decl), &ctx->cb);
1046 if (size == error_mark_node)
1047 size = TYPE_SIZE (TREE_TYPE (new_decl));
1048 DECL_SIZE (new_decl) = size;
1049
1050 size = remap_decl (DECL_SIZE_UNIT (decl), &ctx->cb);
1051 if (size == error_mark_node)
1052 size = TYPE_SIZE_UNIT (TREE_TYPE (new_decl));
1053 DECL_SIZE_UNIT (new_decl) = size;
1054 }
1055 }
1056
1057 /* The callback for remap_decl. Search all containing contexts for a
1058 mapping of the variable; this avoids having to duplicate the splay
1059 tree ahead of time. We know a mapping doesn't already exist in the
1060 given context. Create new mappings to implement default semantics. */
1061
1062 static tree
1063 omp_copy_decl (tree var, copy_body_data *cb)
1064 {
1065 omp_context *ctx = (omp_context *) cb;
1066 tree new_var;
1067
1068 if (TREE_CODE (var) == LABEL_DECL)
1069 {
1070 new_var = create_artificial_label (DECL_SOURCE_LOCATION (var));
1071 DECL_CONTEXT (new_var) = current_function_decl;
1072 insert_decl_map (&ctx->cb, var, new_var);
1073 return new_var;
1074 }
1075
1076 while (!is_taskreg_ctx (ctx))
1077 {
1078 ctx = ctx->outer;
1079 if (ctx == NULL)
1080 return var;
1081 new_var = maybe_lookup_decl (var, ctx);
1082 if (new_var)
1083 return new_var;
1084 }
1085
1086 if (is_global_var (var) || decl_function_context (var) != ctx->cb.src_fn)
1087 return var;
1088
1089 return error_mark_node;
1090 }
1091
1092
1093 /* Return the parallel region associated with STMT. */
1094
1095 /* Debugging dumps for parallel regions. */
1096 void dump_omp_region (FILE *, struct omp_region *, int);
1097 void debug_omp_region (struct omp_region *);
1098 void debug_all_omp_regions (void);
1099
1100 /* Dump the parallel region tree rooted at REGION. */
1101
1102 void
1103 dump_omp_region (FILE *file, struct omp_region *region, int indent)
1104 {
1105 fprintf (file, "%*sbb %d: %s\n", indent, "", region->entry->index,
1106 gimple_code_name[region->type]);
1107
1108 if (region->inner)
1109 dump_omp_region (file, region->inner, indent + 4);
1110
1111 if (region->cont)
1112 {
1113 fprintf (file, "%*sbb %d: GIMPLE_OMP_CONTINUE\n", indent, "",
1114 region->cont->index);
1115 }
1116
1117 if (region->exit)
1118 fprintf (file, "%*sbb %d: GIMPLE_OMP_RETURN\n", indent, "",
1119 region->exit->index);
1120 else
1121 fprintf (file, "%*s[no exit marker]\n", indent, "");
1122
1123 if (region->next)
1124 dump_omp_region (file, region->next, indent);
1125 }
1126
1127 DEBUG_FUNCTION void
1128 debug_omp_region (struct omp_region *region)
1129 {
1130 dump_omp_region (stderr, region, 0);
1131 }
1132
1133 DEBUG_FUNCTION void
1134 debug_all_omp_regions (void)
1135 {
1136 dump_omp_region (stderr, root_omp_region, 0);
1137 }
1138
1139
1140 /* Create a new parallel region starting at STMT inside region PARENT. */
1141
1142 struct omp_region *
1143 new_omp_region (basic_block bb, enum gimple_code type,
1144 struct omp_region *parent)
1145 {
1146 struct omp_region *region = XCNEW (struct omp_region);
1147
1148 region->outer = parent;
1149 region->entry = bb;
1150 region->type = type;
1151
1152 if (parent)
1153 {
1154 /* This is a nested region. Add it to the list of inner
1155 regions in PARENT. */
1156 region->next = parent->inner;
1157 parent->inner = region;
1158 }
1159 else
1160 {
1161 /* This is a toplevel region. Add it to the list of toplevel
1162 regions in ROOT_OMP_REGION. */
1163 region->next = root_omp_region;
1164 root_omp_region = region;
1165 }
1166
1167 return region;
1168 }
1169
1170 /* Release the memory associated with the region tree rooted at REGION. */
1171
1172 static void
1173 free_omp_region_1 (struct omp_region *region)
1174 {
1175 struct omp_region *i, *n;
1176
1177 for (i = region->inner; i ; i = n)
1178 {
1179 n = i->next;
1180 free_omp_region_1 (i);
1181 }
1182
1183 free (region);
1184 }
1185
1186 /* Release the memory for the entire omp region tree. */
1187
1188 void
1189 free_omp_regions (void)
1190 {
1191 struct omp_region *r, *n;
1192 for (r = root_omp_region; r ; r = n)
1193 {
1194 n = r->next;
1195 free_omp_region_1 (r);
1196 }
1197 root_omp_region = NULL;
1198 }
1199
1200
1201 /* Create a new context, with OUTER_CTX being the surrounding context. */
1202
1203 static omp_context *
1204 new_omp_context (gimple stmt, omp_context *outer_ctx)
1205 {
1206 omp_context *ctx = XCNEW (omp_context);
1207
1208 splay_tree_insert (all_contexts, (splay_tree_key) stmt,
1209 (splay_tree_value) ctx);
1210 ctx->stmt = stmt;
1211
1212 if (outer_ctx)
1213 {
1214 ctx->outer = outer_ctx;
1215 ctx->cb = outer_ctx->cb;
1216 ctx->cb.block = NULL;
1217 ctx->depth = outer_ctx->depth + 1;
1218 }
1219 else
1220 {
1221 ctx->cb.src_fn = current_function_decl;
1222 ctx->cb.dst_fn = current_function_decl;
1223 ctx->cb.src_node = cgraph_get_node (current_function_decl);
1224 gcc_checking_assert (ctx->cb.src_node);
1225 ctx->cb.dst_node = ctx->cb.src_node;
1226 ctx->cb.src_cfun = cfun;
1227 ctx->cb.copy_decl = omp_copy_decl;
1228 ctx->cb.eh_lp_nr = 0;
1229 ctx->cb.transform_call_graph_edges = CB_CGE_MOVE;
1230 ctx->depth = 1;
1231 }
1232
1233 ctx->cb.decl_map = pointer_map_create ();
1234
1235 return ctx;
1236 }
1237
1238 static gimple_seq maybe_catch_exception (gimple_seq);
1239
1240 /* Finalize task copyfn. */
1241
1242 static void
1243 finalize_task_copyfn (gimple task_stmt)
1244 {
1245 struct function *child_cfun;
1246 tree child_fn, old_fn;
1247 gimple_seq seq = NULL, new_seq;
1248 gimple bind;
1249
1250 child_fn = gimple_omp_task_copy_fn (task_stmt);
1251 if (child_fn == NULL_TREE)
1252 return;
1253
1254 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
1255
1256 /* Inform the callgraph about the new function. */
1257 DECL_STRUCT_FUNCTION (child_fn)->curr_properties
1258 = cfun->curr_properties & ~PROP_loops;
1259
1260 old_fn = current_function_decl;
1261 push_cfun (child_cfun);
1262 current_function_decl = child_fn;
1263 bind = gimplify_body (child_fn, false);
1264 gimple_seq_add_stmt (&seq, bind);
1265 new_seq = maybe_catch_exception (seq);
1266 if (new_seq != seq)
1267 {
1268 bind = gimple_build_bind (NULL, new_seq, NULL);
1269 seq = NULL;
1270 gimple_seq_add_stmt (&seq, bind);
1271 }
1272 gimple_set_body (child_fn, seq);
1273 pop_cfun ();
1274 current_function_decl = old_fn;
1275
1276 cgraph_add_new_function (child_fn, false);
1277 }
1278
1279 /* Destroy a omp_context data structures. Called through the splay tree
1280 value delete callback. */
1281
1282 static void
1283 delete_omp_context (splay_tree_value value)
1284 {
1285 omp_context *ctx = (omp_context *) value;
1286
1287 pointer_map_destroy (ctx->cb.decl_map);
1288
1289 if (ctx->field_map)
1290 splay_tree_delete (ctx->field_map);
1291 if (ctx->sfield_map)
1292 splay_tree_delete (ctx->sfield_map);
1293
1294 /* We hijacked DECL_ABSTRACT_ORIGIN earlier. We need to clear it before
1295 it produces corrupt debug information. */
1296 if (ctx->record_type)
1297 {
1298 tree t;
1299 for (t = TYPE_FIELDS (ctx->record_type); t ; t = DECL_CHAIN (t))
1300 DECL_ABSTRACT_ORIGIN (t) = NULL;
1301 }
1302 if (ctx->srecord_type)
1303 {
1304 tree t;
1305 for (t = TYPE_FIELDS (ctx->srecord_type); t ; t = DECL_CHAIN (t))
1306 DECL_ABSTRACT_ORIGIN (t) = NULL;
1307 }
1308
1309 if (is_task_ctx (ctx))
1310 finalize_task_copyfn (ctx->stmt);
1311
1312 XDELETE (ctx);
1313 }
1314
1315 /* Fix up RECEIVER_DECL with a type that has been remapped to the child
1316 context. */
1317
1318 static void
1319 fixup_child_record_type (omp_context *ctx)
1320 {
1321 tree f, type = ctx->record_type;
1322
1323 /* ??? It isn't sufficient to just call remap_type here, because
1324 variably_modified_type_p doesn't work the way we expect for
1325 record types. Testing each field for whether it needs remapping
1326 and creating a new record by hand works, however. */
1327 for (f = TYPE_FIELDS (type); f ; f = DECL_CHAIN (f))
1328 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
1329 break;
1330 if (f)
1331 {
1332 tree name, new_fields = NULL;
1333
1334 type = lang_hooks.types.make_type (RECORD_TYPE);
1335 name = DECL_NAME (TYPE_NAME (ctx->record_type));
1336 name = build_decl (DECL_SOURCE_LOCATION (ctx->receiver_decl),
1337 TYPE_DECL, name, type);
1338 TYPE_NAME (type) = name;
1339
1340 for (f = TYPE_FIELDS (ctx->record_type); f ; f = DECL_CHAIN (f))
1341 {
1342 tree new_f = copy_node (f);
1343 DECL_CONTEXT (new_f) = type;
1344 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &ctx->cb);
1345 DECL_CHAIN (new_f) = new_fields;
1346 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &ctx->cb, NULL);
1347 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r,
1348 &ctx->cb, NULL);
1349 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
1350 &ctx->cb, NULL);
1351 new_fields = new_f;
1352
1353 /* Arrange to be able to look up the receiver field
1354 given the sender field. */
1355 splay_tree_insert (ctx->field_map, (splay_tree_key) f,
1356 (splay_tree_value) new_f);
1357 }
1358 TYPE_FIELDS (type) = nreverse (new_fields);
1359 layout_type (type);
1360 }
1361
1362 TREE_TYPE (ctx->receiver_decl) = build_pointer_type (type);
1363 }
1364
1365 /* Instantiate decls as necessary in CTX to satisfy the data sharing
1366 specified by CLAUSES. */
1367
1368 static void
1369 scan_sharing_clauses (tree clauses, omp_context *ctx)
1370 {
1371 tree c, decl;
1372 bool scan_array_reductions = false;
1373
1374 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1375 {
1376 bool by_ref;
1377
1378 switch (OMP_CLAUSE_CODE (c))
1379 {
1380 case OMP_CLAUSE_PRIVATE:
1381 decl = OMP_CLAUSE_DECL (c);
1382 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
1383 goto do_private;
1384 else if (!is_variable_sized (decl))
1385 install_var_local (decl, ctx);
1386 break;
1387
1388 case OMP_CLAUSE_SHARED:
1389 gcc_assert (is_taskreg_ctx (ctx));
1390 decl = OMP_CLAUSE_DECL (c);
1391 gcc_assert (!COMPLETE_TYPE_P (TREE_TYPE (decl))
1392 || !is_variable_sized (decl));
1393 /* Global variables don't need to be copied,
1394 the receiver side will use them directly. */
1395 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1396 break;
1397 by_ref = use_pointer_for_field (decl, ctx);
1398 if (! TREE_READONLY (decl)
1399 || TREE_ADDRESSABLE (decl)
1400 || by_ref
1401 || is_reference (decl))
1402 {
1403 install_var_field (decl, by_ref, 3, ctx);
1404 install_var_local (decl, ctx);
1405 break;
1406 }
1407 /* We don't need to copy const scalar vars back. */
1408 OMP_CLAUSE_SET_CODE (c, OMP_CLAUSE_FIRSTPRIVATE);
1409 goto do_private;
1410
1411 case OMP_CLAUSE_LASTPRIVATE:
1412 /* Let the corresponding firstprivate clause create
1413 the variable. */
1414 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1415 break;
1416 /* FALLTHRU */
1417
1418 case OMP_CLAUSE_FIRSTPRIVATE:
1419 case OMP_CLAUSE_REDUCTION:
1420 decl = OMP_CLAUSE_DECL (c);
1421 do_private:
1422 if (is_variable_sized (decl))
1423 {
1424 if (is_task_ctx (ctx))
1425 install_var_field (decl, false, 1, ctx);
1426 break;
1427 }
1428 else if (is_taskreg_ctx (ctx))
1429 {
1430 bool global
1431 = is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx));
1432 by_ref = use_pointer_for_field (decl, NULL);
1433
1434 if (is_task_ctx (ctx)
1435 && (global || by_ref || is_reference (decl)))
1436 {
1437 install_var_field (decl, false, 1, ctx);
1438 if (!global)
1439 install_var_field (decl, by_ref, 2, ctx);
1440 }
1441 else if (!global)
1442 install_var_field (decl, by_ref, 3, ctx);
1443 }
1444 install_var_local (decl, ctx);
1445 break;
1446
1447 case OMP_CLAUSE_COPYPRIVATE:
1448 case OMP_CLAUSE_COPYIN:
1449 decl = OMP_CLAUSE_DECL (c);
1450 by_ref = use_pointer_for_field (decl, NULL);
1451 install_var_field (decl, by_ref, 3, ctx);
1452 break;
1453
1454 case OMP_CLAUSE_DEFAULT:
1455 ctx->default_kind = OMP_CLAUSE_DEFAULT_KIND (c);
1456 break;
1457
1458 case OMP_CLAUSE_FINAL:
1459 case OMP_CLAUSE_IF:
1460 case OMP_CLAUSE_NUM_THREADS:
1461 case OMP_CLAUSE_SCHEDULE:
1462 if (ctx->outer)
1463 scan_omp_op (&OMP_CLAUSE_OPERAND (c, 0), ctx->outer);
1464 break;
1465
1466 case OMP_CLAUSE_NOWAIT:
1467 case OMP_CLAUSE_ORDERED:
1468 case OMP_CLAUSE_COLLAPSE:
1469 case OMP_CLAUSE_UNTIED:
1470 case OMP_CLAUSE_MERGEABLE:
1471 break;
1472
1473 default:
1474 gcc_unreachable ();
1475 }
1476 }
1477
1478 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1479 {
1480 switch (OMP_CLAUSE_CODE (c))
1481 {
1482 case OMP_CLAUSE_LASTPRIVATE:
1483 /* Let the corresponding firstprivate clause create
1484 the variable. */
1485 if (OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
1486 scan_array_reductions = true;
1487 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1488 break;
1489 /* FALLTHRU */
1490
1491 case OMP_CLAUSE_PRIVATE:
1492 case OMP_CLAUSE_FIRSTPRIVATE:
1493 case OMP_CLAUSE_REDUCTION:
1494 decl = OMP_CLAUSE_DECL (c);
1495 if (is_variable_sized (decl))
1496 install_var_local (decl, ctx);
1497 fixup_remapped_decl (decl, ctx,
1498 OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE
1499 && OMP_CLAUSE_PRIVATE_DEBUG (c));
1500 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1501 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1502 scan_array_reductions = true;
1503 break;
1504
1505 case OMP_CLAUSE_SHARED:
1506 decl = OMP_CLAUSE_DECL (c);
1507 if (! is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1508 fixup_remapped_decl (decl, ctx, false);
1509 break;
1510
1511 case OMP_CLAUSE_COPYPRIVATE:
1512 case OMP_CLAUSE_COPYIN:
1513 case OMP_CLAUSE_DEFAULT:
1514 case OMP_CLAUSE_IF:
1515 case OMP_CLAUSE_NUM_THREADS:
1516 case OMP_CLAUSE_SCHEDULE:
1517 case OMP_CLAUSE_NOWAIT:
1518 case OMP_CLAUSE_ORDERED:
1519 case OMP_CLAUSE_COLLAPSE:
1520 case OMP_CLAUSE_UNTIED:
1521 case OMP_CLAUSE_FINAL:
1522 case OMP_CLAUSE_MERGEABLE:
1523 break;
1524
1525 default:
1526 gcc_unreachable ();
1527 }
1528 }
1529
1530 if (scan_array_reductions)
1531 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1532 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1533 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1534 {
1535 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c), ctx);
1536 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
1537 }
1538 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
1539 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
1540 scan_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
1541 }
1542
1543 /* Create a new name for omp child function. Returns an identifier. */
1544
1545 static GTY(()) unsigned int tmp_ompfn_id_num;
1546
1547 static tree
1548 create_omp_child_function_name (bool task_copy)
1549 {
1550 return (clone_function_name (current_function_decl,
1551 task_copy ? "_omp_cpyfn" : "_omp_fn"));
1552 }
1553
1554 /* Build a decl for the omp child function. It'll not contain a body
1555 yet, just the bare decl. */
1556
1557 static void
1558 create_omp_child_function (omp_context *ctx, bool task_copy)
1559 {
1560 tree decl, type, name, t;
1561
1562 name = create_omp_child_function_name (task_copy);
1563 if (task_copy)
1564 type = build_function_type_list (void_type_node, ptr_type_node,
1565 ptr_type_node, NULL_TREE);
1566 else
1567 type = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
1568
1569 decl = build_decl (gimple_location (ctx->stmt),
1570 FUNCTION_DECL, name, type);
1571
1572 if (!task_copy)
1573 ctx->cb.dst_fn = decl;
1574 else
1575 gimple_omp_task_set_copy_fn (ctx->stmt, decl);
1576
1577 TREE_STATIC (decl) = 1;
1578 TREE_USED (decl) = 1;
1579 DECL_ARTIFICIAL (decl) = 1;
1580 DECL_NAMELESS (decl) = 1;
1581 DECL_IGNORED_P (decl) = 0;
1582 TREE_PUBLIC (decl) = 0;
1583 DECL_UNINLINABLE (decl) = 1;
1584 DECL_EXTERNAL (decl) = 0;
1585 DECL_CONTEXT (decl) = NULL_TREE;
1586 DECL_INITIAL (decl) = make_node (BLOCK);
1587
1588 t = build_decl (DECL_SOURCE_LOCATION (decl),
1589 RESULT_DECL, NULL_TREE, void_type_node);
1590 DECL_ARTIFICIAL (t) = 1;
1591 DECL_IGNORED_P (t) = 1;
1592 DECL_CONTEXT (t) = decl;
1593 DECL_RESULT (decl) = t;
1594
1595 t = build_decl (DECL_SOURCE_LOCATION (decl),
1596 PARM_DECL, get_identifier (".omp_data_i"), ptr_type_node);
1597 DECL_ARTIFICIAL (t) = 1;
1598 DECL_NAMELESS (t) = 1;
1599 DECL_ARG_TYPE (t) = ptr_type_node;
1600 DECL_CONTEXT (t) = current_function_decl;
1601 TREE_USED (t) = 1;
1602 DECL_ARGUMENTS (decl) = t;
1603 if (!task_copy)
1604 ctx->receiver_decl = t;
1605 else
1606 {
1607 t = build_decl (DECL_SOURCE_LOCATION (decl),
1608 PARM_DECL, get_identifier (".omp_data_o"),
1609 ptr_type_node);
1610 DECL_ARTIFICIAL (t) = 1;
1611 DECL_NAMELESS (t) = 1;
1612 DECL_ARG_TYPE (t) = ptr_type_node;
1613 DECL_CONTEXT (t) = current_function_decl;
1614 TREE_USED (t) = 1;
1615 TREE_ADDRESSABLE (t) = 1;
1616 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
1617 DECL_ARGUMENTS (decl) = t;
1618 }
1619
1620 /* Allocate memory for the function structure. The call to
1621 allocate_struct_function clobbers CFUN, so we need to restore
1622 it afterward. */
1623 push_struct_function (decl);
1624 cfun->function_end_locus = gimple_location (ctx->stmt);
1625 pop_cfun ();
1626 }
1627
1628
1629 /* Scan an OpenMP parallel directive. */
1630
1631 static void
1632 scan_omp_parallel (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
1633 {
1634 omp_context *ctx;
1635 tree name;
1636 gimple stmt = gsi_stmt (*gsi);
1637
1638 /* Ignore parallel directives with empty bodies, unless there
1639 are copyin clauses. */
1640 if (optimize > 0
1641 && empty_body_p (gimple_omp_body (stmt))
1642 && find_omp_clause (gimple_omp_parallel_clauses (stmt),
1643 OMP_CLAUSE_COPYIN) == NULL)
1644 {
1645 gsi_replace (gsi, gimple_build_nop (), false);
1646 return;
1647 }
1648
1649 ctx = new_omp_context (stmt, outer_ctx);
1650 if (taskreg_nesting_level > 1)
1651 ctx->is_nested = true;
1652 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
1653 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
1654 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
1655 name = create_tmp_var_name (".omp_data_s");
1656 name = build_decl (gimple_location (stmt),
1657 TYPE_DECL, name, ctx->record_type);
1658 DECL_ARTIFICIAL (name) = 1;
1659 DECL_NAMELESS (name) = 1;
1660 TYPE_NAME (ctx->record_type) = name;
1661 create_omp_child_function (ctx, false);
1662 gimple_omp_parallel_set_child_fn (stmt, ctx->cb.dst_fn);
1663
1664 scan_sharing_clauses (gimple_omp_parallel_clauses (stmt), ctx);
1665 scan_omp (gimple_omp_body_ptr (stmt), ctx);
1666
1667 if (TYPE_FIELDS (ctx->record_type) == NULL)
1668 ctx->record_type = ctx->receiver_decl = NULL;
1669 else
1670 {
1671 layout_type (ctx->record_type);
1672 fixup_child_record_type (ctx);
1673 }
1674 }
1675
1676 /* Scan an OpenMP task directive. */
1677
1678 static void
1679 scan_omp_task (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
1680 {
1681 omp_context *ctx;
1682 tree name, t;
1683 gimple stmt = gsi_stmt (*gsi);
1684 location_t loc = gimple_location (stmt);
1685
1686 /* Ignore task directives with empty bodies. */
1687 if (optimize > 0
1688 && empty_body_p (gimple_omp_body (stmt)))
1689 {
1690 gsi_replace (gsi, gimple_build_nop (), false);
1691 return;
1692 }
1693
1694 ctx = new_omp_context (stmt, outer_ctx);
1695 if (taskreg_nesting_level > 1)
1696 ctx->is_nested = true;
1697 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
1698 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
1699 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
1700 name = create_tmp_var_name (".omp_data_s");
1701 name = build_decl (gimple_location (stmt),
1702 TYPE_DECL, name, ctx->record_type);
1703 DECL_ARTIFICIAL (name) = 1;
1704 DECL_NAMELESS (name) = 1;
1705 TYPE_NAME (ctx->record_type) = name;
1706 create_omp_child_function (ctx, false);
1707 gimple_omp_task_set_child_fn (stmt, ctx->cb.dst_fn);
1708
1709 scan_sharing_clauses (gimple_omp_task_clauses (stmt), ctx);
1710
1711 if (ctx->srecord_type)
1712 {
1713 name = create_tmp_var_name (".omp_data_a");
1714 name = build_decl (gimple_location (stmt),
1715 TYPE_DECL, name, ctx->srecord_type);
1716 DECL_ARTIFICIAL (name) = 1;
1717 DECL_NAMELESS (name) = 1;
1718 TYPE_NAME (ctx->srecord_type) = name;
1719 create_omp_child_function (ctx, true);
1720 }
1721
1722 scan_omp (gimple_omp_body_ptr (stmt), ctx);
1723
1724 if (TYPE_FIELDS (ctx->record_type) == NULL)
1725 {
1726 ctx->record_type = ctx->receiver_decl = NULL;
1727 t = build_int_cst (long_integer_type_node, 0);
1728 gimple_omp_task_set_arg_size (stmt, t);
1729 t = build_int_cst (long_integer_type_node, 1);
1730 gimple_omp_task_set_arg_align (stmt, t);
1731 }
1732 else
1733 {
1734 tree *p, vla_fields = NULL_TREE, *q = &vla_fields;
1735 /* Move VLA fields to the end. */
1736 p = &TYPE_FIELDS (ctx->record_type);
1737 while (*p)
1738 if (!TYPE_SIZE_UNIT (TREE_TYPE (*p))
1739 || ! TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (*p))))
1740 {
1741 *q = *p;
1742 *p = TREE_CHAIN (*p);
1743 TREE_CHAIN (*q) = NULL_TREE;
1744 q = &TREE_CHAIN (*q);
1745 }
1746 else
1747 p = &DECL_CHAIN (*p);
1748 *p = vla_fields;
1749 layout_type (ctx->record_type);
1750 fixup_child_record_type (ctx);
1751 if (ctx->srecord_type)
1752 layout_type (ctx->srecord_type);
1753 t = fold_convert_loc (loc, long_integer_type_node,
1754 TYPE_SIZE_UNIT (ctx->record_type));
1755 gimple_omp_task_set_arg_size (stmt, t);
1756 t = build_int_cst (long_integer_type_node,
1757 TYPE_ALIGN_UNIT (ctx->record_type));
1758 gimple_omp_task_set_arg_align (stmt, t);
1759 }
1760 }
1761
1762
1763 /* Scan an OpenMP loop directive. */
1764
1765 static void
1766 scan_omp_for (gimple stmt, omp_context *outer_ctx)
1767 {
1768 omp_context *ctx;
1769 size_t i;
1770
1771 ctx = new_omp_context (stmt, outer_ctx);
1772
1773 scan_sharing_clauses (gimple_omp_for_clauses (stmt), ctx);
1774
1775 scan_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
1776 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
1777 {
1778 scan_omp_op (gimple_omp_for_index_ptr (stmt, i), ctx);
1779 scan_omp_op (gimple_omp_for_initial_ptr (stmt, i), ctx);
1780 scan_omp_op (gimple_omp_for_final_ptr (stmt, i), ctx);
1781 scan_omp_op (gimple_omp_for_incr_ptr (stmt, i), ctx);
1782 }
1783 scan_omp (gimple_omp_body_ptr (stmt), ctx);
1784 }
1785
1786 /* Scan an OpenMP sections directive. */
1787
1788 static void
1789 scan_omp_sections (gimple stmt, omp_context *outer_ctx)
1790 {
1791 omp_context *ctx;
1792
1793 ctx = new_omp_context (stmt, outer_ctx);
1794 scan_sharing_clauses (gimple_omp_sections_clauses (stmt), ctx);
1795 scan_omp (gimple_omp_body_ptr (stmt), ctx);
1796 }
1797
1798 /* Scan an OpenMP single directive. */
1799
1800 static void
1801 scan_omp_single (gimple stmt, omp_context *outer_ctx)
1802 {
1803 omp_context *ctx;
1804 tree name;
1805
1806 ctx = new_omp_context (stmt, outer_ctx);
1807 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
1808 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
1809 name = create_tmp_var_name (".omp_copy_s");
1810 name = build_decl (gimple_location (stmt),
1811 TYPE_DECL, name, ctx->record_type);
1812 TYPE_NAME (ctx->record_type) = name;
1813
1814 scan_sharing_clauses (gimple_omp_single_clauses (stmt), ctx);
1815 scan_omp (gimple_omp_body_ptr (stmt), ctx);
1816
1817 if (TYPE_FIELDS (ctx->record_type) == NULL)
1818 ctx->record_type = NULL;
1819 else
1820 layout_type (ctx->record_type);
1821 }
1822
1823
1824 /* Check OpenMP nesting restrictions. */
1825 static bool
1826 check_omp_nesting_restrictions (gimple stmt, omp_context *ctx)
1827 {
1828 switch (gimple_code (stmt))
1829 {
1830 case GIMPLE_OMP_FOR:
1831 case GIMPLE_OMP_SECTIONS:
1832 case GIMPLE_OMP_SINGLE:
1833 case GIMPLE_CALL:
1834 for (; ctx != NULL; ctx = ctx->outer)
1835 switch (gimple_code (ctx->stmt))
1836 {
1837 case GIMPLE_OMP_FOR:
1838 case GIMPLE_OMP_SECTIONS:
1839 case GIMPLE_OMP_SINGLE:
1840 case GIMPLE_OMP_ORDERED:
1841 case GIMPLE_OMP_MASTER:
1842 case GIMPLE_OMP_TASK:
1843 if (is_gimple_call (stmt))
1844 {
1845 error_at (gimple_location (stmt),
1846 "barrier region may not be closely nested inside "
1847 "of work-sharing, critical, ordered, master or "
1848 "explicit task region");
1849 return false;
1850 }
1851 error_at (gimple_location (stmt),
1852 "work-sharing region may not be closely nested inside "
1853 "of work-sharing, critical, ordered, master or explicit "
1854 "task region");
1855 return false;
1856 case GIMPLE_OMP_PARALLEL:
1857 return true;
1858 default:
1859 break;
1860 }
1861 break;
1862 case GIMPLE_OMP_MASTER:
1863 for (; ctx != NULL; ctx = ctx->outer)
1864 switch (gimple_code (ctx->stmt))
1865 {
1866 case GIMPLE_OMP_FOR:
1867 case GIMPLE_OMP_SECTIONS:
1868 case GIMPLE_OMP_SINGLE:
1869 case GIMPLE_OMP_TASK:
1870 error_at (gimple_location (stmt),
1871 "master region may not be closely nested inside "
1872 "of work-sharing or explicit task region");
1873 return false;
1874 case GIMPLE_OMP_PARALLEL:
1875 return true;
1876 default:
1877 break;
1878 }
1879 break;
1880 case GIMPLE_OMP_ORDERED:
1881 for (; ctx != NULL; ctx = ctx->outer)
1882 switch (gimple_code (ctx->stmt))
1883 {
1884 case GIMPLE_OMP_CRITICAL:
1885 case GIMPLE_OMP_TASK:
1886 error_at (gimple_location (stmt),
1887 "ordered region may not be closely nested inside "
1888 "of critical or explicit task region");
1889 return false;
1890 case GIMPLE_OMP_FOR:
1891 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
1892 OMP_CLAUSE_ORDERED) == NULL)
1893 {
1894 error_at (gimple_location (stmt),
1895 "ordered region must be closely nested inside "
1896 "a loop region with an ordered clause");
1897 return false;
1898 }
1899 return true;
1900 case GIMPLE_OMP_PARALLEL:
1901 return true;
1902 default:
1903 break;
1904 }
1905 break;
1906 case GIMPLE_OMP_CRITICAL:
1907 for (; ctx != NULL; ctx = ctx->outer)
1908 if (gimple_code (ctx->stmt) == GIMPLE_OMP_CRITICAL
1909 && (gimple_omp_critical_name (stmt)
1910 == gimple_omp_critical_name (ctx->stmt)))
1911 {
1912 error_at (gimple_location (stmt),
1913 "critical region may not be nested inside a critical "
1914 "region with the same name");
1915 return false;
1916 }
1917 break;
1918 default:
1919 break;
1920 }
1921 return true;
1922 }
1923
1924
1925 /* Helper function scan_omp.
1926
1927 Callback for walk_tree or operators in walk_gimple_stmt used to
1928 scan for OpenMP directives in TP. */
1929
1930 static tree
1931 scan_omp_1_op (tree *tp, int *walk_subtrees, void *data)
1932 {
1933 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
1934 omp_context *ctx = (omp_context *) wi->info;
1935 tree t = *tp;
1936
1937 switch (TREE_CODE (t))
1938 {
1939 case VAR_DECL:
1940 case PARM_DECL:
1941 case LABEL_DECL:
1942 case RESULT_DECL:
1943 if (ctx)
1944 *tp = remap_decl (t, &ctx->cb);
1945 break;
1946
1947 default:
1948 if (ctx && TYPE_P (t))
1949 *tp = remap_type (t, &ctx->cb);
1950 else if (!DECL_P (t))
1951 {
1952 *walk_subtrees = 1;
1953 if (ctx)
1954 {
1955 tree tem = remap_type (TREE_TYPE (t), &ctx->cb);
1956 if (tem != TREE_TYPE (t))
1957 {
1958 if (TREE_CODE (t) == INTEGER_CST)
1959 *tp = build_int_cst_wide (tem,
1960 TREE_INT_CST_LOW (t),
1961 TREE_INT_CST_HIGH (t));
1962 else
1963 TREE_TYPE (t) = tem;
1964 }
1965 }
1966 }
1967 break;
1968 }
1969
1970 return NULL_TREE;
1971 }
1972
1973
1974 /* Helper function for scan_omp.
1975
1976 Callback for walk_gimple_stmt used to scan for OpenMP directives in
1977 the current statement in GSI. */
1978
1979 static tree
1980 scan_omp_1_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
1981 struct walk_stmt_info *wi)
1982 {
1983 gimple stmt = gsi_stmt (*gsi);
1984 omp_context *ctx = (omp_context *) wi->info;
1985
1986 if (gimple_has_location (stmt))
1987 input_location = gimple_location (stmt);
1988
1989 /* Check the OpenMP nesting restrictions. */
1990 if (ctx != NULL)
1991 {
1992 bool remove = false;
1993 if (is_gimple_omp (stmt))
1994 remove = !check_omp_nesting_restrictions (stmt, ctx);
1995 else if (is_gimple_call (stmt))
1996 {
1997 tree fndecl = gimple_call_fndecl (stmt);
1998 if (fndecl && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
1999 && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_GOMP_BARRIER)
2000 remove = !check_omp_nesting_restrictions (stmt, ctx);
2001 }
2002 if (remove)
2003 {
2004 stmt = gimple_build_nop ();
2005 gsi_replace (gsi, stmt, false);
2006 }
2007 }
2008
2009 *handled_ops_p = true;
2010
2011 switch (gimple_code (stmt))
2012 {
2013 case GIMPLE_OMP_PARALLEL:
2014 taskreg_nesting_level++;
2015 scan_omp_parallel (gsi, ctx);
2016 taskreg_nesting_level--;
2017 break;
2018
2019 case GIMPLE_OMP_TASK:
2020 taskreg_nesting_level++;
2021 scan_omp_task (gsi, ctx);
2022 taskreg_nesting_level--;
2023 break;
2024
2025 case GIMPLE_OMP_FOR:
2026 scan_omp_for (stmt, ctx);
2027 break;
2028
2029 case GIMPLE_OMP_SECTIONS:
2030 scan_omp_sections (stmt, ctx);
2031 break;
2032
2033 case GIMPLE_OMP_SINGLE:
2034 scan_omp_single (stmt, ctx);
2035 break;
2036
2037 case GIMPLE_OMP_SECTION:
2038 case GIMPLE_OMP_MASTER:
2039 case GIMPLE_OMP_ORDERED:
2040 case GIMPLE_OMP_CRITICAL:
2041 ctx = new_omp_context (stmt, ctx);
2042 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2043 break;
2044
2045 case GIMPLE_BIND:
2046 {
2047 tree var;
2048
2049 *handled_ops_p = false;
2050 if (ctx)
2051 for (var = gimple_bind_vars (stmt); var ; var = DECL_CHAIN (var))
2052 insert_decl_map (&ctx->cb, var, var);
2053 }
2054 break;
2055 default:
2056 *handled_ops_p = false;
2057 break;
2058 }
2059
2060 return NULL_TREE;
2061 }
2062
2063
2064 /* Scan all the statements starting at the current statement. CTX
2065 contains context information about the OpenMP directives and
2066 clauses found during the scan. */
2067
2068 static void
2069 scan_omp (gimple_seq *body_p, omp_context *ctx)
2070 {
2071 location_t saved_location;
2072 struct walk_stmt_info wi;
2073
2074 memset (&wi, 0, sizeof (wi));
2075 wi.info = ctx;
2076 wi.want_locations = true;
2077
2078 saved_location = input_location;
2079 walk_gimple_seq_mod (body_p, scan_omp_1_stmt, scan_omp_1_op, &wi);
2080 input_location = saved_location;
2081 }
2082 \f
2083 /* Re-gimplification and code generation routines. */
2084
2085 /* Build a call to GOMP_barrier. */
2086
2087 static tree
2088 build_omp_barrier (void)
2089 {
2090 return build_call_expr (builtin_decl_explicit (BUILT_IN_GOMP_BARRIER), 0);
2091 }
2092
2093 /* If a context was created for STMT when it was scanned, return it. */
2094
2095 static omp_context *
2096 maybe_lookup_ctx (gimple stmt)
2097 {
2098 splay_tree_node n;
2099 n = splay_tree_lookup (all_contexts, (splay_tree_key) stmt);
2100 return n ? (omp_context *) n->value : NULL;
2101 }
2102
2103
2104 /* Find the mapping for DECL in CTX or the immediately enclosing
2105 context that has a mapping for DECL.
2106
2107 If CTX is a nested parallel directive, we may have to use the decl
2108 mappings created in CTX's parent context. Suppose that we have the
2109 following parallel nesting (variable UIDs showed for clarity):
2110
2111 iD.1562 = 0;
2112 #omp parallel shared(iD.1562) -> outer parallel
2113 iD.1562 = iD.1562 + 1;
2114
2115 #omp parallel shared (iD.1562) -> inner parallel
2116 iD.1562 = iD.1562 - 1;
2117
2118 Each parallel structure will create a distinct .omp_data_s structure
2119 for copying iD.1562 in/out of the directive:
2120
2121 outer parallel .omp_data_s.1.i -> iD.1562
2122 inner parallel .omp_data_s.2.i -> iD.1562
2123
2124 A shared variable mapping will produce a copy-out operation before
2125 the parallel directive and a copy-in operation after it. So, in
2126 this case we would have:
2127
2128 iD.1562 = 0;
2129 .omp_data_o.1.i = iD.1562;
2130 #omp parallel shared(iD.1562) -> outer parallel
2131 .omp_data_i.1 = &.omp_data_o.1
2132 .omp_data_i.1->i = .omp_data_i.1->i + 1;
2133
2134 .omp_data_o.2.i = iD.1562; -> **
2135 #omp parallel shared(iD.1562) -> inner parallel
2136 .omp_data_i.2 = &.omp_data_o.2
2137 .omp_data_i.2->i = .omp_data_i.2->i - 1;
2138
2139
2140 ** This is a problem. The symbol iD.1562 cannot be referenced
2141 inside the body of the outer parallel region. But since we are
2142 emitting this copy operation while expanding the inner parallel
2143 directive, we need to access the CTX structure of the outer
2144 parallel directive to get the correct mapping:
2145
2146 .omp_data_o.2.i = .omp_data_i.1->i
2147
2148 Since there may be other workshare or parallel directives enclosing
2149 the parallel directive, it may be necessary to walk up the context
2150 parent chain. This is not a problem in general because nested
2151 parallelism happens only rarely. */
2152
2153 static tree
2154 lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
2155 {
2156 tree t;
2157 omp_context *up;
2158
2159 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
2160 t = maybe_lookup_decl (decl, up);
2161
2162 gcc_assert (!ctx->is_nested || t || is_global_var (decl));
2163
2164 return t ? t : decl;
2165 }
2166
2167
2168 /* Similar to lookup_decl_in_outer_ctx, but return DECL if not found
2169 in outer contexts. */
2170
2171 static tree
2172 maybe_lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
2173 {
2174 tree t = NULL;
2175 omp_context *up;
2176
2177 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
2178 t = maybe_lookup_decl (decl, up);
2179
2180 return t ? t : decl;
2181 }
2182
2183
2184 /* Construct the initialization value for reduction CLAUSE. */
2185
2186 tree
2187 omp_reduction_init (tree clause, tree type)
2188 {
2189 location_t loc = OMP_CLAUSE_LOCATION (clause);
2190 switch (OMP_CLAUSE_REDUCTION_CODE (clause))
2191 {
2192 case PLUS_EXPR:
2193 case MINUS_EXPR:
2194 case BIT_IOR_EXPR:
2195 case BIT_XOR_EXPR:
2196 case TRUTH_OR_EXPR:
2197 case TRUTH_ORIF_EXPR:
2198 case TRUTH_XOR_EXPR:
2199 case NE_EXPR:
2200 return build_zero_cst (type);
2201
2202 case MULT_EXPR:
2203 case TRUTH_AND_EXPR:
2204 case TRUTH_ANDIF_EXPR:
2205 case EQ_EXPR:
2206 return fold_convert_loc (loc, type, integer_one_node);
2207
2208 case BIT_AND_EXPR:
2209 return fold_convert_loc (loc, type, integer_minus_one_node);
2210
2211 case MAX_EXPR:
2212 if (SCALAR_FLOAT_TYPE_P (type))
2213 {
2214 REAL_VALUE_TYPE max, min;
2215 if (HONOR_INFINITIES (TYPE_MODE (type)))
2216 {
2217 real_inf (&max);
2218 real_arithmetic (&min, NEGATE_EXPR, &max, NULL);
2219 }
2220 else
2221 real_maxval (&min, 1, TYPE_MODE (type));
2222 return build_real (type, min);
2223 }
2224 else
2225 {
2226 gcc_assert (INTEGRAL_TYPE_P (type));
2227 return TYPE_MIN_VALUE (type);
2228 }
2229
2230 case MIN_EXPR:
2231 if (SCALAR_FLOAT_TYPE_P (type))
2232 {
2233 REAL_VALUE_TYPE max;
2234 if (HONOR_INFINITIES (TYPE_MODE (type)))
2235 real_inf (&max);
2236 else
2237 real_maxval (&max, 0, TYPE_MODE (type));
2238 return build_real (type, max);
2239 }
2240 else
2241 {
2242 gcc_assert (INTEGRAL_TYPE_P (type));
2243 return TYPE_MAX_VALUE (type);
2244 }
2245
2246 default:
2247 gcc_unreachable ();
2248 }
2249 }
2250
2251 /* Generate code to implement the input clauses, FIRSTPRIVATE and COPYIN,
2252 from the receiver (aka child) side and initializers for REFERENCE_TYPE
2253 private variables. Initialization statements go in ILIST, while calls
2254 to destructors go in DLIST. */
2255
2256 static void
2257 lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
2258 omp_context *ctx)
2259 {
2260 tree c, dtor, copyin_seq, x, ptr;
2261 bool copyin_by_ref = false;
2262 bool lastprivate_firstprivate = false;
2263 int pass;
2264
2265 copyin_seq = NULL;
2266
2267 /* Do all the fixed sized types in the first pass, and the variable sized
2268 types in the second pass. This makes sure that the scalar arguments to
2269 the variable sized types are processed before we use them in the
2270 variable sized operations. */
2271 for (pass = 0; pass < 2; ++pass)
2272 {
2273 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
2274 {
2275 enum omp_clause_code c_kind = OMP_CLAUSE_CODE (c);
2276 tree var, new_var;
2277 bool by_ref;
2278 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
2279
2280 switch (c_kind)
2281 {
2282 case OMP_CLAUSE_PRIVATE:
2283 if (OMP_CLAUSE_PRIVATE_DEBUG (c))
2284 continue;
2285 break;
2286 case OMP_CLAUSE_SHARED:
2287 if (maybe_lookup_decl (OMP_CLAUSE_DECL (c), ctx) == NULL)
2288 {
2289 gcc_assert (is_global_var (OMP_CLAUSE_DECL (c)));
2290 continue;
2291 }
2292 case OMP_CLAUSE_FIRSTPRIVATE:
2293 case OMP_CLAUSE_COPYIN:
2294 case OMP_CLAUSE_REDUCTION:
2295 break;
2296 case OMP_CLAUSE_LASTPRIVATE:
2297 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
2298 {
2299 lastprivate_firstprivate = true;
2300 if (pass != 0)
2301 continue;
2302 }
2303 break;
2304 default:
2305 continue;
2306 }
2307
2308 new_var = var = OMP_CLAUSE_DECL (c);
2309 if (c_kind != OMP_CLAUSE_COPYIN)
2310 new_var = lookup_decl (var, ctx);
2311
2312 if (c_kind == OMP_CLAUSE_SHARED || c_kind == OMP_CLAUSE_COPYIN)
2313 {
2314 if (pass != 0)
2315 continue;
2316 }
2317 else if (is_variable_sized (var))
2318 {
2319 /* For variable sized types, we need to allocate the
2320 actual storage here. Call alloca and store the
2321 result in the pointer decl that we created elsewhere. */
2322 if (pass == 0)
2323 continue;
2324
2325 if (c_kind != OMP_CLAUSE_FIRSTPRIVATE || !is_task_ctx (ctx))
2326 {
2327 gimple stmt;
2328 tree tmp, atmp;
2329
2330 ptr = DECL_VALUE_EXPR (new_var);
2331 gcc_assert (TREE_CODE (ptr) == INDIRECT_REF);
2332 ptr = TREE_OPERAND (ptr, 0);
2333 gcc_assert (DECL_P (ptr));
2334 x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
2335
2336 /* void *tmp = __builtin_alloca */
2337 atmp = builtin_decl_explicit (BUILT_IN_ALLOCA);
2338 stmt = gimple_build_call (atmp, 1, x);
2339 tmp = create_tmp_var_raw (ptr_type_node, NULL);
2340 gimple_add_tmp_var (tmp);
2341 gimple_call_set_lhs (stmt, tmp);
2342
2343 gimple_seq_add_stmt (ilist, stmt);
2344
2345 x = fold_convert_loc (clause_loc, TREE_TYPE (ptr), tmp);
2346 gimplify_assign (ptr, x, ilist);
2347 }
2348 }
2349 else if (is_reference (var))
2350 {
2351 /* For references that are being privatized for Fortran,
2352 allocate new backing storage for the new pointer
2353 variable. This allows us to avoid changing all the
2354 code that expects a pointer to something that expects
2355 a direct variable. Note that this doesn't apply to
2356 C++, since reference types are disallowed in data
2357 sharing clauses there, except for NRV optimized
2358 return values. */
2359 if (pass == 0)
2360 continue;
2361
2362 x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
2363 if (c_kind == OMP_CLAUSE_FIRSTPRIVATE && is_task_ctx (ctx))
2364 {
2365 x = build_receiver_ref (var, false, ctx);
2366 x = build_fold_addr_expr_loc (clause_loc, x);
2367 }
2368 else if (TREE_CONSTANT (x))
2369 {
2370 const char *name = NULL;
2371 if (DECL_NAME (var))
2372 name = IDENTIFIER_POINTER (DECL_NAME (new_var));
2373
2374 x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)),
2375 name);
2376 gimple_add_tmp_var (x);
2377 TREE_ADDRESSABLE (x) = 1;
2378 x = build_fold_addr_expr_loc (clause_loc, x);
2379 }
2380 else
2381 {
2382 tree atmp = builtin_decl_explicit (BUILT_IN_ALLOCA);
2383 x = build_call_expr_loc (clause_loc, atmp, 1, x);
2384 }
2385
2386 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
2387 gimplify_assign (new_var, x, ilist);
2388
2389 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
2390 }
2391 else if (c_kind == OMP_CLAUSE_REDUCTION
2392 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
2393 {
2394 if (pass == 0)
2395 continue;
2396 }
2397 else if (pass != 0)
2398 continue;
2399
2400 switch (OMP_CLAUSE_CODE (c))
2401 {
2402 case OMP_CLAUSE_SHARED:
2403 /* Shared global vars are just accessed directly. */
2404 if (is_global_var (new_var))
2405 break;
2406 /* Set up the DECL_VALUE_EXPR for shared variables now. This
2407 needs to be delayed until after fixup_child_record_type so
2408 that we get the correct type during the dereference. */
2409 by_ref = use_pointer_for_field (var, ctx);
2410 x = build_receiver_ref (var, by_ref, ctx);
2411 SET_DECL_VALUE_EXPR (new_var, x);
2412 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
2413
2414 /* ??? If VAR is not passed by reference, and the variable
2415 hasn't been initialized yet, then we'll get a warning for
2416 the store into the omp_data_s structure. Ideally, we'd be
2417 able to notice this and not store anything at all, but
2418 we're generating code too early. Suppress the warning. */
2419 if (!by_ref)
2420 TREE_NO_WARNING (var) = 1;
2421 break;
2422
2423 case OMP_CLAUSE_LASTPRIVATE:
2424 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
2425 break;
2426 /* FALLTHRU */
2427
2428 case OMP_CLAUSE_PRIVATE:
2429 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_PRIVATE)
2430 x = build_outer_var_ref (var, ctx);
2431 else if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
2432 {
2433 if (is_task_ctx (ctx))
2434 x = build_receiver_ref (var, false, ctx);
2435 else
2436 x = build_outer_var_ref (var, ctx);
2437 }
2438 else
2439 x = NULL;
2440 x = lang_hooks.decls.omp_clause_default_ctor (c, new_var, x);
2441 if (x)
2442 gimplify_and_add (x, ilist);
2443 /* FALLTHRU */
2444
2445 do_dtor:
2446 x = lang_hooks.decls.omp_clause_dtor (c, new_var);
2447 if (x)
2448 {
2449 gimple_seq tseq = NULL;
2450
2451 dtor = x;
2452 gimplify_stmt (&dtor, &tseq);
2453 gimple_seq_add_seq (dlist, tseq);
2454 }
2455 break;
2456
2457 case OMP_CLAUSE_FIRSTPRIVATE:
2458 if (is_task_ctx (ctx))
2459 {
2460 if (is_reference (var) || is_variable_sized (var))
2461 goto do_dtor;
2462 else if (is_global_var (maybe_lookup_decl_in_outer_ctx (var,
2463 ctx))
2464 || use_pointer_for_field (var, NULL))
2465 {
2466 x = build_receiver_ref (var, false, ctx);
2467 SET_DECL_VALUE_EXPR (new_var, x);
2468 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
2469 goto do_dtor;
2470 }
2471 }
2472 x = build_outer_var_ref (var, ctx);
2473 x = lang_hooks.decls.omp_clause_copy_ctor (c, new_var, x);
2474 gimplify_and_add (x, ilist);
2475 goto do_dtor;
2476 break;
2477
2478 case OMP_CLAUSE_COPYIN:
2479 by_ref = use_pointer_for_field (var, NULL);
2480 x = build_receiver_ref (var, by_ref, ctx);
2481 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, x);
2482 append_to_statement_list (x, &copyin_seq);
2483 copyin_by_ref |= by_ref;
2484 break;
2485
2486 case OMP_CLAUSE_REDUCTION:
2487 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
2488 {
2489 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
2490 x = build_outer_var_ref (var, ctx);
2491
2492 if (is_reference (var))
2493 x = build_fold_addr_expr_loc (clause_loc, x);
2494 SET_DECL_VALUE_EXPR (placeholder, x);
2495 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
2496 lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c), ctx);
2497 gimple_seq_add_seq (ilist,
2498 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c));
2499 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
2500 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
2501 }
2502 else
2503 {
2504 x = omp_reduction_init (c, TREE_TYPE (new_var));
2505 gcc_assert (TREE_CODE (TREE_TYPE (new_var)) != ARRAY_TYPE);
2506 gimplify_assign (new_var, x, ilist);
2507 }
2508 break;
2509
2510 default:
2511 gcc_unreachable ();
2512 }
2513 }
2514 }
2515
2516 /* The copyin sequence is not to be executed by the main thread, since
2517 that would result in self-copies. Perhaps not visible to scalars,
2518 but it certainly is to C++ operator=. */
2519 if (copyin_seq)
2520 {
2521 x = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM),
2522 0);
2523 x = build2 (NE_EXPR, boolean_type_node, x,
2524 build_int_cst (TREE_TYPE (x), 0));
2525 x = build3 (COND_EXPR, void_type_node, x, copyin_seq, NULL);
2526 gimplify_and_add (x, ilist);
2527 }
2528
2529 /* If any copyin variable is passed by reference, we must ensure the
2530 master thread doesn't modify it before it is copied over in all
2531 threads. Similarly for variables in both firstprivate and
2532 lastprivate clauses we need to ensure the lastprivate copying
2533 happens after firstprivate copying in all threads. */
2534 if (copyin_by_ref || lastprivate_firstprivate)
2535 gimplify_and_add (build_omp_barrier (), ilist);
2536 }
2537
2538
2539 /* Generate code to implement the LASTPRIVATE clauses. This is used for
2540 both parallel and workshare constructs. PREDICATE may be NULL if it's
2541 always true. */
2542
2543 static void
2544 lower_lastprivate_clauses (tree clauses, tree predicate, gimple_seq *stmt_list,
2545 omp_context *ctx)
2546 {
2547 tree x, c, label = NULL;
2548 bool par_clauses = false;
2549
2550 /* Early exit if there are no lastprivate clauses. */
2551 clauses = find_omp_clause (clauses, OMP_CLAUSE_LASTPRIVATE);
2552 if (clauses == NULL)
2553 {
2554 /* If this was a workshare clause, see if it had been combined
2555 with its parallel. In that case, look for the clauses on the
2556 parallel statement itself. */
2557 if (is_parallel_ctx (ctx))
2558 return;
2559
2560 ctx = ctx->outer;
2561 if (ctx == NULL || !is_parallel_ctx (ctx))
2562 return;
2563
2564 clauses = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
2565 OMP_CLAUSE_LASTPRIVATE);
2566 if (clauses == NULL)
2567 return;
2568 par_clauses = true;
2569 }
2570
2571 if (predicate)
2572 {
2573 gimple stmt;
2574 tree label_true, arm1, arm2;
2575
2576 label = create_artificial_label (UNKNOWN_LOCATION);
2577 label_true = create_artificial_label (UNKNOWN_LOCATION);
2578 arm1 = TREE_OPERAND (predicate, 0);
2579 arm2 = TREE_OPERAND (predicate, 1);
2580 gimplify_expr (&arm1, stmt_list, NULL, is_gimple_val, fb_rvalue);
2581 gimplify_expr (&arm2, stmt_list, NULL, is_gimple_val, fb_rvalue);
2582 stmt = gimple_build_cond (TREE_CODE (predicate), arm1, arm2,
2583 label_true, label);
2584 gimple_seq_add_stmt (stmt_list, stmt);
2585 gimple_seq_add_stmt (stmt_list, gimple_build_label (label_true));
2586 }
2587
2588 for (c = clauses; c ;)
2589 {
2590 tree var, new_var;
2591 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
2592
2593 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE)
2594 {
2595 var = OMP_CLAUSE_DECL (c);
2596 new_var = lookup_decl (var, ctx);
2597
2598 if (OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
2599 {
2600 lower_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
2601 gimple_seq_add_seq (stmt_list,
2602 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c));
2603 }
2604 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c) = NULL;
2605
2606 x = build_outer_var_ref (var, ctx);
2607 if (is_reference (var))
2608 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
2609 x = lang_hooks.decls.omp_clause_assign_op (c, x, new_var);
2610 gimplify_and_add (x, stmt_list);
2611 }
2612 c = OMP_CLAUSE_CHAIN (c);
2613 if (c == NULL && !par_clauses)
2614 {
2615 /* If this was a workshare clause, see if it had been combined
2616 with its parallel. In that case, continue looking for the
2617 clauses also on the parallel statement itself. */
2618 if (is_parallel_ctx (ctx))
2619 break;
2620
2621 ctx = ctx->outer;
2622 if (ctx == NULL || !is_parallel_ctx (ctx))
2623 break;
2624
2625 c = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
2626 OMP_CLAUSE_LASTPRIVATE);
2627 par_clauses = true;
2628 }
2629 }
2630
2631 if (label)
2632 gimple_seq_add_stmt (stmt_list, gimple_build_label (label));
2633 }
2634
2635
2636 /* Generate code to implement the REDUCTION clauses. */
2637
2638 static void
2639 lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp, omp_context *ctx)
2640 {
2641 gimple_seq sub_seq = NULL;
2642 gimple stmt;
2643 tree x, c;
2644 int count = 0;
2645
2646 /* First see if there is exactly one reduction clause. Use OMP_ATOMIC
2647 update in that case, otherwise use a lock. */
2648 for (c = clauses; c && count < 2; c = OMP_CLAUSE_CHAIN (c))
2649 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
2650 {
2651 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
2652 {
2653 /* Never use OMP_ATOMIC for array reductions. */
2654 count = -1;
2655 break;
2656 }
2657 count++;
2658 }
2659
2660 if (count == 0)
2661 return;
2662
2663 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
2664 {
2665 tree var, ref, new_var;
2666 enum tree_code code;
2667 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
2668
2669 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
2670 continue;
2671
2672 var = OMP_CLAUSE_DECL (c);
2673 new_var = lookup_decl (var, ctx);
2674 if (is_reference (var))
2675 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
2676 ref = build_outer_var_ref (var, ctx);
2677 code = OMP_CLAUSE_REDUCTION_CODE (c);
2678
2679 /* reduction(-:var) sums up the partial results, so it acts
2680 identically to reduction(+:var). */
2681 if (code == MINUS_EXPR)
2682 code = PLUS_EXPR;
2683
2684 if (count == 1)
2685 {
2686 tree addr = build_fold_addr_expr_loc (clause_loc, ref);
2687
2688 addr = save_expr (addr);
2689 ref = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (addr)), addr);
2690 x = fold_build2_loc (clause_loc, code, TREE_TYPE (ref), ref, new_var);
2691 x = build2 (OMP_ATOMIC, void_type_node, addr, x);
2692 gimplify_and_add (x, stmt_seqp);
2693 return;
2694 }
2695
2696 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
2697 {
2698 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
2699
2700 if (is_reference (var))
2701 ref = build_fold_addr_expr_loc (clause_loc, ref);
2702 SET_DECL_VALUE_EXPR (placeholder, ref);
2703 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
2704 lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
2705 gimple_seq_add_seq (&sub_seq, OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
2706 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
2707 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
2708 }
2709 else
2710 {
2711 x = build2 (code, TREE_TYPE (ref), ref, new_var);
2712 ref = build_outer_var_ref (var, ctx);
2713 gimplify_assign (ref, x, &sub_seq);
2714 }
2715 }
2716
2717 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START),
2718 0);
2719 gimple_seq_add_stmt (stmt_seqp, stmt);
2720
2721 gimple_seq_add_seq (stmt_seqp, sub_seq);
2722
2723 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END),
2724 0);
2725 gimple_seq_add_stmt (stmt_seqp, stmt);
2726 }
2727
2728
2729 /* Generate code to implement the COPYPRIVATE clauses. */
2730
2731 static void
2732 lower_copyprivate_clauses (tree clauses, gimple_seq *slist, gimple_seq *rlist,
2733 omp_context *ctx)
2734 {
2735 tree c;
2736
2737 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
2738 {
2739 tree var, new_var, ref, x;
2740 bool by_ref;
2741 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
2742
2743 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYPRIVATE)
2744 continue;
2745
2746 var = OMP_CLAUSE_DECL (c);
2747 by_ref = use_pointer_for_field (var, NULL);
2748
2749 ref = build_sender_ref (var, ctx);
2750 x = new_var = lookup_decl_in_outer_ctx (var, ctx);
2751 if (by_ref)
2752 {
2753 x = build_fold_addr_expr_loc (clause_loc, new_var);
2754 x = fold_convert_loc (clause_loc, TREE_TYPE (ref), x);
2755 }
2756 gimplify_assign (ref, x, slist);
2757
2758 ref = build_receiver_ref (var, false, ctx);
2759 if (by_ref)
2760 {
2761 ref = fold_convert_loc (clause_loc,
2762 build_pointer_type (TREE_TYPE (new_var)),
2763 ref);
2764 ref = build_fold_indirect_ref_loc (clause_loc, ref);
2765 }
2766 if (is_reference (var))
2767 {
2768 ref = fold_convert_loc (clause_loc, TREE_TYPE (new_var), ref);
2769 ref = build_simple_mem_ref_loc (clause_loc, ref);
2770 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
2771 }
2772 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, ref);
2773 gimplify_and_add (x, rlist);
2774 }
2775 }
2776
2777
2778 /* Generate code to implement the clauses, FIRSTPRIVATE, COPYIN, LASTPRIVATE,
2779 and REDUCTION from the sender (aka parent) side. */
2780
2781 static void
2782 lower_send_clauses (tree clauses, gimple_seq *ilist, gimple_seq *olist,
2783 omp_context *ctx)
2784 {
2785 tree c;
2786
2787 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
2788 {
2789 tree val, ref, x, var;
2790 bool by_ref, do_in = false, do_out = false;
2791 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
2792
2793 switch (OMP_CLAUSE_CODE (c))
2794 {
2795 case OMP_CLAUSE_PRIVATE:
2796 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
2797 break;
2798 continue;
2799 case OMP_CLAUSE_FIRSTPRIVATE:
2800 case OMP_CLAUSE_COPYIN:
2801 case OMP_CLAUSE_LASTPRIVATE:
2802 case OMP_CLAUSE_REDUCTION:
2803 break;
2804 default:
2805 continue;
2806 }
2807
2808 val = OMP_CLAUSE_DECL (c);
2809 var = lookup_decl_in_outer_ctx (val, ctx);
2810
2811 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYIN
2812 && is_global_var (var))
2813 continue;
2814 if (is_variable_sized (val))
2815 continue;
2816 by_ref = use_pointer_for_field (val, NULL);
2817
2818 switch (OMP_CLAUSE_CODE (c))
2819 {
2820 case OMP_CLAUSE_PRIVATE:
2821 case OMP_CLAUSE_FIRSTPRIVATE:
2822 case OMP_CLAUSE_COPYIN:
2823 do_in = true;
2824 break;
2825
2826 case OMP_CLAUSE_LASTPRIVATE:
2827 if (by_ref || is_reference (val))
2828 {
2829 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
2830 continue;
2831 do_in = true;
2832 }
2833 else
2834 {
2835 do_out = true;
2836 if (lang_hooks.decls.omp_private_outer_ref (val))
2837 do_in = true;
2838 }
2839 break;
2840
2841 case OMP_CLAUSE_REDUCTION:
2842 do_in = true;
2843 do_out = !(by_ref || is_reference (val));
2844 break;
2845
2846 default:
2847 gcc_unreachable ();
2848 }
2849
2850 if (do_in)
2851 {
2852 ref = build_sender_ref (val, ctx);
2853 x = by_ref ? build_fold_addr_expr_loc (clause_loc, var) : var;
2854 gimplify_assign (ref, x, ilist);
2855 if (is_task_ctx (ctx))
2856 DECL_ABSTRACT_ORIGIN (TREE_OPERAND (ref, 1)) = NULL;
2857 }
2858
2859 if (do_out)
2860 {
2861 ref = build_sender_ref (val, ctx);
2862 gimplify_assign (var, ref, olist);
2863 }
2864 }
2865 }
2866
2867 /* Generate code to implement SHARED from the sender (aka parent)
2868 side. This is trickier, since GIMPLE_OMP_PARALLEL_CLAUSES doesn't
2869 list things that got automatically shared. */
2870
2871 static void
2872 lower_send_shared_vars (gimple_seq *ilist, gimple_seq *olist, omp_context *ctx)
2873 {
2874 tree var, ovar, nvar, f, x, record_type;
2875
2876 if (ctx->record_type == NULL)
2877 return;
2878
2879 record_type = ctx->srecord_type ? ctx->srecord_type : ctx->record_type;
2880 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
2881 {
2882 ovar = DECL_ABSTRACT_ORIGIN (f);
2883 nvar = maybe_lookup_decl (ovar, ctx);
2884 if (!nvar || !DECL_HAS_VALUE_EXPR_P (nvar))
2885 continue;
2886
2887 /* If CTX is a nested parallel directive. Find the immediately
2888 enclosing parallel or workshare construct that contains a
2889 mapping for OVAR. */
2890 var = lookup_decl_in_outer_ctx (ovar, ctx);
2891
2892 if (use_pointer_for_field (ovar, ctx))
2893 {
2894 x = build_sender_ref (ovar, ctx);
2895 var = build_fold_addr_expr (var);
2896 gimplify_assign (x, var, ilist);
2897 }
2898 else
2899 {
2900 x = build_sender_ref (ovar, ctx);
2901 gimplify_assign (x, var, ilist);
2902
2903 if (!TREE_READONLY (var)
2904 /* We don't need to receive a new reference to a result
2905 or parm decl. In fact we may not store to it as we will
2906 invalidate any pending RSO and generate wrong gimple
2907 during inlining. */
2908 && !((TREE_CODE (var) == RESULT_DECL
2909 || TREE_CODE (var) == PARM_DECL)
2910 && DECL_BY_REFERENCE (var)))
2911 {
2912 x = build_sender_ref (ovar, ctx);
2913 gimplify_assign (var, x, olist);
2914 }
2915 }
2916 }
2917 }
2918
2919
2920 /* A convenience function to build an empty GIMPLE_COND with just the
2921 condition. */
2922
2923 static gimple
2924 gimple_build_cond_empty (tree cond)
2925 {
2926 enum tree_code pred_code;
2927 tree lhs, rhs;
2928
2929 gimple_cond_get_ops_from_tree (cond, &pred_code, &lhs, &rhs);
2930 return gimple_build_cond (pred_code, lhs, rhs, NULL_TREE, NULL_TREE);
2931 }
2932
2933
2934 /* Build the function calls to GOMP_parallel_start etc to actually
2935 generate the parallel operation. REGION is the parallel region
2936 being expanded. BB is the block where to insert the code. WS_ARGS
2937 will be set if this is a call to a combined parallel+workshare
2938 construct, it contains the list of additional arguments needed by
2939 the workshare construct. */
2940
2941 static void
2942 expand_parallel_call (struct omp_region *region, basic_block bb,
2943 gimple entry_stmt, VEC(tree,gc) *ws_args)
2944 {
2945 tree t, t1, t2, val, cond, c, clauses;
2946 gimple_stmt_iterator gsi;
2947 gimple stmt;
2948 enum built_in_function start_ix;
2949 int start_ix2;
2950 location_t clause_loc;
2951 VEC(tree,gc) *args;
2952
2953 clauses = gimple_omp_parallel_clauses (entry_stmt);
2954
2955 /* Determine what flavor of GOMP_parallel_start we will be
2956 emitting. */
2957 start_ix = BUILT_IN_GOMP_PARALLEL_START;
2958 if (is_combined_parallel (region))
2959 {
2960 switch (region->inner->type)
2961 {
2962 case GIMPLE_OMP_FOR:
2963 gcc_assert (region->inner->sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
2964 start_ix2 = ((int)BUILT_IN_GOMP_PARALLEL_LOOP_STATIC_START
2965 + (region->inner->sched_kind
2966 == OMP_CLAUSE_SCHEDULE_RUNTIME
2967 ? 3 : region->inner->sched_kind));
2968 start_ix = (enum built_in_function)start_ix2;
2969 break;
2970 case GIMPLE_OMP_SECTIONS:
2971 start_ix = BUILT_IN_GOMP_PARALLEL_SECTIONS_START;
2972 break;
2973 default:
2974 gcc_unreachable ();
2975 }
2976 }
2977
2978 /* By default, the value of NUM_THREADS is zero (selected at run time)
2979 and there is no conditional. */
2980 cond = NULL_TREE;
2981 val = build_int_cst (unsigned_type_node, 0);
2982
2983 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
2984 if (c)
2985 cond = OMP_CLAUSE_IF_EXPR (c);
2986
2987 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_THREADS);
2988 if (c)
2989 {
2990 val = OMP_CLAUSE_NUM_THREADS_EXPR (c);
2991 clause_loc = OMP_CLAUSE_LOCATION (c);
2992 }
2993 else
2994 clause_loc = gimple_location (entry_stmt);
2995
2996 /* Ensure 'val' is of the correct type. */
2997 val = fold_convert_loc (clause_loc, unsigned_type_node, val);
2998
2999 /* If we found the clause 'if (cond)', build either
3000 (cond != 0) or (cond ? val : 1u). */
3001 if (cond)
3002 {
3003 gimple_stmt_iterator gsi;
3004
3005 cond = gimple_boolify (cond);
3006
3007 if (integer_zerop (val))
3008 val = fold_build2_loc (clause_loc,
3009 EQ_EXPR, unsigned_type_node, cond,
3010 build_int_cst (TREE_TYPE (cond), 0));
3011 else
3012 {
3013 basic_block cond_bb, then_bb, else_bb;
3014 edge e, e_then, e_else;
3015 tree tmp_then, tmp_else, tmp_join, tmp_var;
3016
3017 tmp_var = create_tmp_var (TREE_TYPE (val), NULL);
3018 if (gimple_in_ssa_p (cfun))
3019 {
3020 tmp_then = make_ssa_name (tmp_var, NULL);
3021 tmp_else = make_ssa_name (tmp_var, NULL);
3022 tmp_join = make_ssa_name (tmp_var, NULL);
3023 }
3024 else
3025 {
3026 tmp_then = tmp_var;
3027 tmp_else = tmp_var;
3028 tmp_join = tmp_var;
3029 }
3030
3031 e = split_block (bb, NULL);
3032 cond_bb = e->src;
3033 bb = e->dest;
3034 remove_edge (e);
3035
3036 then_bb = create_empty_bb (cond_bb);
3037 else_bb = create_empty_bb (then_bb);
3038 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
3039 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
3040
3041 stmt = gimple_build_cond_empty (cond);
3042 gsi = gsi_start_bb (cond_bb);
3043 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
3044
3045 gsi = gsi_start_bb (then_bb);
3046 stmt = gimple_build_assign (tmp_then, val);
3047 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
3048
3049 gsi = gsi_start_bb (else_bb);
3050 stmt = gimple_build_assign
3051 (tmp_else, build_int_cst (unsigned_type_node, 1));
3052 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
3053
3054 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
3055 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
3056 e_then = make_edge (then_bb, bb, EDGE_FALLTHRU);
3057 e_else = make_edge (else_bb, bb, EDGE_FALLTHRU);
3058
3059 if (gimple_in_ssa_p (cfun))
3060 {
3061 gimple phi = create_phi_node (tmp_join, bb);
3062 SSA_NAME_DEF_STMT (tmp_join) = phi;
3063 add_phi_arg (phi, tmp_then, e_then, UNKNOWN_LOCATION);
3064 add_phi_arg (phi, tmp_else, e_else, UNKNOWN_LOCATION);
3065 }
3066
3067 val = tmp_join;
3068 }
3069
3070 gsi = gsi_start_bb (bb);
3071 val = force_gimple_operand_gsi (&gsi, val, true, NULL_TREE,
3072 false, GSI_CONTINUE_LINKING);
3073 }
3074
3075 gsi = gsi_last_bb (bb);
3076 t = gimple_omp_parallel_data_arg (entry_stmt);
3077 if (t == NULL)
3078 t1 = null_pointer_node;
3079 else
3080 t1 = build_fold_addr_expr (t);
3081 t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
3082
3083 args = VEC_alloc (tree, gc, 3 + VEC_length (tree, ws_args));
3084 VEC_quick_push (tree, args, t2);
3085 VEC_quick_push (tree, args, t1);
3086 VEC_quick_push (tree, args, val);
3087 VEC_splice (tree, args, ws_args);
3088
3089 t = build_call_expr_loc_vec (UNKNOWN_LOCATION,
3090 builtin_decl_explicit (start_ix), args);
3091
3092 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
3093 false, GSI_CONTINUE_LINKING);
3094
3095 t = gimple_omp_parallel_data_arg (entry_stmt);
3096 if (t == NULL)
3097 t = null_pointer_node;
3098 else
3099 t = build_fold_addr_expr (t);
3100 t = build_call_expr_loc (gimple_location (entry_stmt),
3101 gimple_omp_parallel_child_fn (entry_stmt), 1, t);
3102 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
3103 false, GSI_CONTINUE_LINKING);
3104
3105 t = build_call_expr_loc (gimple_location (entry_stmt),
3106 builtin_decl_explicit (BUILT_IN_GOMP_PARALLEL_END),
3107 0);
3108 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
3109 false, GSI_CONTINUE_LINKING);
3110 }
3111
3112
3113 /* Build the function call to GOMP_task to actually
3114 generate the task operation. BB is the block where to insert the code. */
3115
3116 static void
3117 expand_task_call (basic_block bb, gimple entry_stmt)
3118 {
3119 tree t, t1, t2, t3, flags, cond, c, c2, clauses;
3120 gimple_stmt_iterator gsi;
3121 location_t loc = gimple_location (entry_stmt);
3122
3123 clauses = gimple_omp_task_clauses (entry_stmt);
3124
3125 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
3126 if (c)
3127 cond = gimple_boolify (OMP_CLAUSE_IF_EXPR (c));
3128 else
3129 cond = boolean_true_node;
3130
3131 c = find_omp_clause (clauses, OMP_CLAUSE_UNTIED);
3132 c2 = find_omp_clause (clauses, OMP_CLAUSE_MERGEABLE);
3133 flags = build_int_cst (unsigned_type_node,
3134 (c ? 1 : 0) + (c2 ? 4 : 0));
3135
3136 c = find_omp_clause (clauses, OMP_CLAUSE_FINAL);
3137 if (c)
3138 {
3139 c = gimple_boolify (OMP_CLAUSE_FINAL_EXPR (c));
3140 c = fold_build3_loc (loc, COND_EXPR, unsigned_type_node, c,
3141 build_int_cst (unsigned_type_node, 2),
3142 build_int_cst (unsigned_type_node, 0));
3143 flags = fold_build2_loc (loc, PLUS_EXPR, unsigned_type_node, flags, c);
3144 }
3145
3146 gsi = gsi_last_bb (bb);
3147 t = gimple_omp_task_data_arg (entry_stmt);
3148 if (t == NULL)
3149 t2 = null_pointer_node;
3150 else
3151 t2 = build_fold_addr_expr_loc (loc, t);
3152 t1 = build_fold_addr_expr_loc (loc, gimple_omp_task_child_fn (entry_stmt));
3153 t = gimple_omp_task_copy_fn (entry_stmt);
3154 if (t == NULL)
3155 t3 = null_pointer_node;
3156 else
3157 t3 = build_fold_addr_expr_loc (loc, t);
3158
3159 t = build_call_expr (builtin_decl_explicit (BUILT_IN_GOMP_TASK),
3160 7, t1, t2, t3,
3161 gimple_omp_task_arg_size (entry_stmt),
3162 gimple_omp_task_arg_align (entry_stmt), cond, flags);
3163
3164 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
3165 false, GSI_CONTINUE_LINKING);
3166 }
3167
3168
3169 /* If exceptions are enabled, wrap the statements in BODY in a MUST_NOT_THROW
3170 catch handler and return it. This prevents programs from violating the
3171 structured block semantics with throws. */
3172
3173 static gimple_seq
3174 maybe_catch_exception (gimple_seq body)
3175 {
3176 gimple g;
3177 tree decl;
3178
3179 if (!flag_exceptions)
3180 return body;
3181
3182 if (lang_hooks.eh_protect_cleanup_actions != NULL)
3183 decl = lang_hooks.eh_protect_cleanup_actions ();
3184 else
3185 decl = builtin_decl_explicit (BUILT_IN_TRAP);
3186
3187 g = gimple_build_eh_must_not_throw (decl);
3188 g = gimple_build_try (body, gimple_seq_alloc_with_stmt (g),
3189 GIMPLE_TRY_CATCH);
3190
3191 return gimple_seq_alloc_with_stmt (g);
3192 }
3193
3194 /* Chain all the DECLs in LIST by their TREE_CHAIN fields. */
3195
3196 static tree
3197 vec2chain (VEC(tree,gc) *v)
3198 {
3199 tree chain = NULL_TREE, t;
3200 unsigned ix;
3201
3202 FOR_EACH_VEC_ELT_REVERSE (tree, v, ix, t)
3203 {
3204 DECL_CHAIN (t) = chain;
3205 chain = t;
3206 }
3207
3208 return chain;
3209 }
3210
3211
3212 /* Remove barriers in REGION->EXIT's block. Note that this is only
3213 valid for GIMPLE_OMP_PARALLEL regions. Since the end of a parallel region
3214 is an implicit barrier, any workshare inside the GIMPLE_OMP_PARALLEL that
3215 left a barrier at the end of the GIMPLE_OMP_PARALLEL region can now be
3216 removed. */
3217
3218 static void
3219 remove_exit_barrier (struct omp_region *region)
3220 {
3221 gimple_stmt_iterator gsi;
3222 basic_block exit_bb;
3223 edge_iterator ei;
3224 edge e;
3225 gimple stmt;
3226 int any_addressable_vars = -1;
3227
3228 exit_bb = region->exit;
3229
3230 /* If the parallel region doesn't return, we don't have REGION->EXIT
3231 block at all. */
3232 if (! exit_bb)
3233 return;
3234
3235 /* The last insn in the block will be the parallel's GIMPLE_OMP_RETURN. The
3236 workshare's GIMPLE_OMP_RETURN will be in a preceding block. The kinds of
3237 statements that can appear in between are extremely limited -- no
3238 memory operations at all. Here, we allow nothing at all, so the
3239 only thing we allow to precede this GIMPLE_OMP_RETURN is a label. */
3240 gsi = gsi_last_bb (exit_bb);
3241 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
3242 gsi_prev (&gsi);
3243 if (!gsi_end_p (gsi) && gimple_code (gsi_stmt (gsi)) != GIMPLE_LABEL)
3244 return;
3245
3246 FOR_EACH_EDGE (e, ei, exit_bb->preds)
3247 {
3248 gsi = gsi_last_bb (e->src);
3249 if (gsi_end_p (gsi))
3250 continue;
3251 stmt = gsi_stmt (gsi);
3252 if (gimple_code (stmt) == GIMPLE_OMP_RETURN
3253 && !gimple_omp_return_nowait_p (stmt))
3254 {
3255 /* OpenMP 3.0 tasks unfortunately prevent this optimization
3256 in many cases. If there could be tasks queued, the barrier
3257 might be needed to let the tasks run before some local
3258 variable of the parallel that the task uses as shared
3259 runs out of scope. The task can be spawned either
3260 from within current function (this would be easy to check)
3261 or from some function it calls and gets passed an address
3262 of such a variable. */
3263 if (any_addressable_vars < 0)
3264 {
3265 gimple parallel_stmt = last_stmt (region->entry);
3266 tree child_fun = gimple_omp_parallel_child_fn (parallel_stmt);
3267 tree local_decls, block, decl;
3268 unsigned ix;
3269
3270 any_addressable_vars = 0;
3271 FOR_EACH_LOCAL_DECL (DECL_STRUCT_FUNCTION (child_fun), ix, decl)
3272 if (TREE_ADDRESSABLE (decl))
3273 {
3274 any_addressable_vars = 1;
3275 break;
3276 }
3277 for (block = gimple_block (stmt);
3278 !any_addressable_vars
3279 && block
3280 && TREE_CODE (block) == BLOCK;
3281 block = BLOCK_SUPERCONTEXT (block))
3282 {
3283 for (local_decls = BLOCK_VARS (block);
3284 local_decls;
3285 local_decls = DECL_CHAIN (local_decls))
3286 if (TREE_ADDRESSABLE (local_decls))
3287 {
3288 any_addressable_vars = 1;
3289 break;
3290 }
3291 if (block == gimple_block (parallel_stmt))
3292 break;
3293 }
3294 }
3295 if (!any_addressable_vars)
3296 gimple_omp_return_set_nowait (stmt);
3297 }
3298 }
3299 }
3300
3301 static void
3302 remove_exit_barriers (struct omp_region *region)
3303 {
3304 if (region->type == GIMPLE_OMP_PARALLEL)
3305 remove_exit_barrier (region);
3306
3307 if (region->inner)
3308 {
3309 region = region->inner;
3310 remove_exit_barriers (region);
3311 while (region->next)
3312 {
3313 region = region->next;
3314 remove_exit_barriers (region);
3315 }
3316 }
3317 }
3318
3319 /* Optimize omp_get_thread_num () and omp_get_num_threads ()
3320 calls. These can't be declared as const functions, but
3321 within one parallel body they are constant, so they can be
3322 transformed there into __builtin_omp_get_{thread_num,num_threads} ()
3323 which are declared const. Similarly for task body, except
3324 that in untied task omp_get_thread_num () can change at any task
3325 scheduling point. */
3326
3327 static void
3328 optimize_omp_library_calls (gimple entry_stmt)
3329 {
3330 basic_block bb;
3331 gimple_stmt_iterator gsi;
3332 tree thr_num_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
3333 tree thr_num_id = DECL_ASSEMBLER_NAME (thr_num_tree);
3334 tree num_thr_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
3335 tree num_thr_id = DECL_ASSEMBLER_NAME (num_thr_tree);
3336 bool untied_task = (gimple_code (entry_stmt) == GIMPLE_OMP_TASK
3337 && find_omp_clause (gimple_omp_task_clauses (entry_stmt),
3338 OMP_CLAUSE_UNTIED) != NULL);
3339
3340 FOR_EACH_BB (bb)
3341 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
3342 {
3343 gimple call = gsi_stmt (gsi);
3344 tree decl;
3345
3346 if (is_gimple_call (call)
3347 && (decl = gimple_call_fndecl (call))
3348 && DECL_EXTERNAL (decl)
3349 && TREE_PUBLIC (decl)
3350 && DECL_INITIAL (decl) == NULL)
3351 {
3352 tree built_in;
3353
3354 if (DECL_NAME (decl) == thr_num_id)
3355 {
3356 /* In #pragma omp task untied omp_get_thread_num () can change
3357 during the execution of the task region. */
3358 if (untied_task)
3359 continue;
3360 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
3361 }
3362 else if (DECL_NAME (decl) == num_thr_id)
3363 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
3364 else
3365 continue;
3366
3367 if (DECL_ASSEMBLER_NAME (decl) != DECL_ASSEMBLER_NAME (built_in)
3368 || gimple_call_num_args (call) != 0)
3369 continue;
3370
3371 if (flag_exceptions && !TREE_NOTHROW (decl))
3372 continue;
3373
3374 if (TREE_CODE (TREE_TYPE (decl)) != FUNCTION_TYPE
3375 || !types_compatible_p (TREE_TYPE (TREE_TYPE (decl)),
3376 TREE_TYPE (TREE_TYPE (built_in))))
3377 continue;
3378
3379 gimple_call_set_fndecl (call, built_in);
3380 }
3381 }
3382 }
3383
3384 /* Expand the OpenMP parallel or task directive starting at REGION. */
3385
3386 static void
3387 expand_omp_taskreg (struct omp_region *region)
3388 {
3389 basic_block entry_bb, exit_bb, new_bb;
3390 struct function *child_cfun;
3391 tree child_fn, block, t;
3392 tree save_current;
3393 gimple_stmt_iterator gsi;
3394 gimple entry_stmt, stmt;
3395 edge e;
3396 VEC(tree,gc) *ws_args;
3397
3398 entry_stmt = last_stmt (region->entry);
3399 child_fn = gimple_omp_taskreg_child_fn (entry_stmt);
3400 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
3401 /* If this function has been already instrumented, make sure
3402 the child function isn't instrumented again. */
3403 child_cfun->after_tree_profile = cfun->after_tree_profile;
3404
3405 entry_bb = region->entry;
3406 exit_bb = region->exit;
3407
3408 if (is_combined_parallel (region))
3409 ws_args = region->ws_args;
3410 else
3411 ws_args = NULL;
3412
3413 if (child_cfun->cfg)
3414 {
3415 /* Due to inlining, it may happen that we have already outlined
3416 the region, in which case all we need to do is make the
3417 sub-graph unreachable and emit the parallel call. */
3418 edge entry_succ_e, exit_succ_e;
3419 gimple_stmt_iterator gsi;
3420
3421 entry_succ_e = single_succ_edge (entry_bb);
3422
3423 gsi = gsi_last_bb (entry_bb);
3424 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_PARALLEL
3425 || gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_TASK);
3426 gsi_remove (&gsi, true);
3427
3428 new_bb = entry_bb;
3429 if (exit_bb)
3430 {
3431 exit_succ_e = single_succ_edge (exit_bb);
3432 make_edge (new_bb, exit_succ_e->dest, EDGE_FALLTHRU);
3433 }
3434 remove_edge_and_dominated_blocks (entry_succ_e);
3435 }
3436 else
3437 {
3438 unsigned srcidx, dstidx, num;
3439
3440 /* If the parallel region needs data sent from the parent
3441 function, then the very first statement (except possible
3442 tree profile counter updates) of the parallel body
3443 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
3444 &.OMP_DATA_O is passed as an argument to the child function,
3445 we need to replace it with the argument as seen by the child
3446 function.
3447
3448 In most cases, this will end up being the identity assignment
3449 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
3450 a function call that has been inlined, the original PARM_DECL
3451 .OMP_DATA_I may have been converted into a different local
3452 variable. In which case, we need to keep the assignment. */
3453 if (gimple_omp_taskreg_data_arg (entry_stmt))
3454 {
3455 basic_block entry_succ_bb = single_succ (entry_bb);
3456 gimple_stmt_iterator gsi;
3457 tree arg, narg;
3458 gimple parcopy_stmt = NULL;
3459
3460 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
3461 {
3462 gimple stmt;
3463
3464 gcc_assert (!gsi_end_p (gsi));
3465 stmt = gsi_stmt (gsi);
3466 if (gimple_code (stmt) != GIMPLE_ASSIGN)
3467 continue;
3468
3469 if (gimple_num_ops (stmt) == 2)
3470 {
3471 tree arg = gimple_assign_rhs1 (stmt);
3472
3473 /* We're ignore the subcode because we're
3474 effectively doing a STRIP_NOPS. */
3475
3476 if (TREE_CODE (arg) == ADDR_EXPR
3477 && TREE_OPERAND (arg, 0)
3478 == gimple_omp_taskreg_data_arg (entry_stmt))
3479 {
3480 parcopy_stmt = stmt;
3481 break;
3482 }
3483 }
3484 }
3485
3486 gcc_assert (parcopy_stmt != NULL);
3487 arg = DECL_ARGUMENTS (child_fn);
3488
3489 if (!gimple_in_ssa_p (cfun))
3490 {
3491 if (gimple_assign_lhs (parcopy_stmt) == arg)
3492 gsi_remove (&gsi, true);
3493 else
3494 {
3495 /* ?? Is setting the subcode really necessary ?? */
3496 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (arg));
3497 gimple_assign_set_rhs1 (parcopy_stmt, arg);
3498 }
3499 }
3500 else
3501 {
3502 /* If we are in ssa form, we must load the value from the default
3503 definition of the argument. That should not be defined now,
3504 since the argument is not used uninitialized. */
3505 gcc_assert (gimple_default_def (cfun, arg) == NULL);
3506 narg = make_ssa_name (arg, gimple_build_nop ());
3507 set_default_def (arg, narg);
3508 /* ?? Is setting the subcode really necessary ?? */
3509 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (narg));
3510 gimple_assign_set_rhs1 (parcopy_stmt, narg);
3511 update_stmt (parcopy_stmt);
3512 }
3513 }
3514
3515 /* Declare local variables needed in CHILD_CFUN. */
3516 block = DECL_INITIAL (child_fn);
3517 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
3518 /* The gimplifier could record temporaries in parallel/task block
3519 rather than in containing function's local_decls chain,
3520 which would mean cgraph missed finalizing them. Do it now. */
3521 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
3522 if (TREE_CODE (t) == VAR_DECL
3523 && TREE_STATIC (t)
3524 && !DECL_EXTERNAL (t))
3525 varpool_finalize_decl (t);
3526 DECL_SAVED_TREE (child_fn) = NULL;
3527 /* We'll create a CFG for child_fn, so no gimple body is needed. */
3528 gimple_set_body (child_fn, NULL);
3529 TREE_USED (block) = 1;
3530
3531 /* Reset DECL_CONTEXT on function arguments. */
3532 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
3533 DECL_CONTEXT (t) = child_fn;
3534
3535 /* Split ENTRY_BB at GIMPLE_OMP_PARALLEL or GIMPLE_OMP_TASK,
3536 so that it can be moved to the child function. */
3537 gsi = gsi_last_bb (entry_bb);
3538 stmt = gsi_stmt (gsi);
3539 gcc_assert (stmt && (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
3540 || gimple_code (stmt) == GIMPLE_OMP_TASK));
3541 gsi_remove (&gsi, true);
3542 e = split_block (entry_bb, stmt);
3543 entry_bb = e->dest;
3544 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
3545
3546 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
3547 if (exit_bb)
3548 {
3549 gsi = gsi_last_bb (exit_bb);
3550 gcc_assert (!gsi_end_p (gsi)
3551 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
3552 stmt = gimple_build_return (NULL);
3553 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
3554 gsi_remove (&gsi, true);
3555 }
3556
3557 /* Move the parallel region into CHILD_CFUN. */
3558
3559 if (gimple_in_ssa_p (cfun))
3560 {
3561 init_tree_ssa (child_cfun);
3562 init_ssa_operands (child_cfun);
3563 child_cfun->gimple_df->in_ssa_p = true;
3564 block = NULL_TREE;
3565 }
3566 else
3567 block = gimple_block (entry_stmt);
3568
3569 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
3570 if (exit_bb)
3571 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
3572
3573 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
3574 num = VEC_length (tree, child_cfun->local_decls);
3575 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
3576 {
3577 t = VEC_index (tree, child_cfun->local_decls, srcidx);
3578 if (DECL_CONTEXT (t) == cfun->decl)
3579 continue;
3580 if (srcidx != dstidx)
3581 VEC_replace (tree, child_cfun->local_decls, dstidx, t);
3582 dstidx++;
3583 }
3584 if (dstidx != num)
3585 VEC_truncate (tree, child_cfun->local_decls, dstidx);
3586
3587 /* Inform the callgraph about the new function. */
3588 DECL_STRUCT_FUNCTION (child_fn)->curr_properties
3589 = cfun->curr_properties & ~PROP_loops;
3590 cgraph_add_new_function (child_fn, true);
3591
3592 /* Fix the callgraph edges for child_cfun. Those for cfun will be
3593 fixed in a following pass. */
3594 push_cfun (child_cfun);
3595 save_current = current_function_decl;
3596 current_function_decl = child_fn;
3597 if (optimize)
3598 optimize_omp_library_calls (entry_stmt);
3599 rebuild_cgraph_edges ();
3600
3601 /* Some EH regions might become dead, see PR34608. If
3602 pass_cleanup_cfg isn't the first pass to happen with the
3603 new child, these dead EH edges might cause problems.
3604 Clean them up now. */
3605 if (flag_exceptions)
3606 {
3607 basic_block bb;
3608 bool changed = false;
3609
3610 FOR_EACH_BB (bb)
3611 changed |= gimple_purge_dead_eh_edges (bb);
3612 if (changed)
3613 cleanup_tree_cfg ();
3614 }
3615 if (gimple_in_ssa_p (cfun))
3616 update_ssa (TODO_update_ssa);
3617 current_function_decl = save_current;
3618 pop_cfun ();
3619 }
3620
3621 /* Emit a library call to launch the children threads. */
3622 if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
3623 expand_parallel_call (region, new_bb, entry_stmt, ws_args);
3624 else
3625 expand_task_call (new_bb, entry_stmt);
3626 if (gimple_in_ssa_p (cfun))
3627 update_ssa (TODO_update_ssa_only_virtuals);
3628 }
3629
3630
3631 /* A subroutine of expand_omp_for. Generate code for a parallel
3632 loop with any schedule. Given parameters:
3633
3634 for (V = N1; V cond N2; V += STEP) BODY;
3635
3636 where COND is "<" or ">", we generate pseudocode
3637
3638 more = GOMP_loop_foo_start (N1, N2, STEP, CHUNK, &istart0, &iend0);
3639 if (more) goto L0; else goto L3;
3640 L0:
3641 V = istart0;
3642 iend = iend0;
3643 L1:
3644 BODY;
3645 V += STEP;
3646 if (V cond iend) goto L1; else goto L2;
3647 L2:
3648 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
3649 L3:
3650
3651 If this is a combined omp parallel loop, instead of the call to
3652 GOMP_loop_foo_start, we call GOMP_loop_foo_next.
3653
3654 For collapsed loops, given parameters:
3655 collapse(3)
3656 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
3657 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
3658 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
3659 BODY;
3660
3661 we generate pseudocode
3662
3663 if (cond3 is <)
3664 adj = STEP3 - 1;
3665 else
3666 adj = STEP3 + 1;
3667 count3 = (adj + N32 - N31) / STEP3;
3668 if (cond2 is <)
3669 adj = STEP2 - 1;
3670 else
3671 adj = STEP2 + 1;
3672 count2 = (adj + N22 - N21) / STEP2;
3673 if (cond1 is <)
3674 adj = STEP1 - 1;
3675 else
3676 adj = STEP1 + 1;
3677 count1 = (adj + N12 - N11) / STEP1;
3678 count = count1 * count2 * count3;
3679 more = GOMP_loop_foo_start (0, count, 1, CHUNK, &istart0, &iend0);
3680 if (more) goto L0; else goto L3;
3681 L0:
3682 V = istart0;
3683 T = V;
3684 V3 = N31 + (T % count3) * STEP3;
3685 T = T / count3;
3686 V2 = N21 + (T % count2) * STEP2;
3687 T = T / count2;
3688 V1 = N11 + T * STEP1;
3689 iend = iend0;
3690 L1:
3691 BODY;
3692 V += 1;
3693 if (V < iend) goto L10; else goto L2;
3694 L10:
3695 V3 += STEP3;
3696 if (V3 cond3 N32) goto L1; else goto L11;
3697 L11:
3698 V3 = N31;
3699 V2 += STEP2;
3700 if (V2 cond2 N22) goto L1; else goto L12;
3701 L12:
3702 V2 = N21;
3703 V1 += STEP1;
3704 goto L1;
3705 L2:
3706 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
3707 L3:
3708
3709 */
3710
3711 static void
3712 expand_omp_for_generic (struct omp_region *region,
3713 struct omp_for_data *fd,
3714 enum built_in_function start_fn,
3715 enum built_in_function next_fn)
3716 {
3717 tree type, istart0, iend0, iend;
3718 tree t, vmain, vback, bias = NULL_TREE;
3719 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, collapse_bb;
3720 basic_block l2_bb = NULL, l3_bb = NULL;
3721 gimple_stmt_iterator gsi;
3722 gimple stmt;
3723 bool in_combined_parallel = is_combined_parallel (region);
3724 bool broken_loop = region->cont == NULL;
3725 edge e, ne;
3726 tree *counts = NULL;
3727 int i;
3728
3729 gcc_assert (!broken_loop || !in_combined_parallel);
3730 gcc_assert (fd->iter_type == long_integer_type_node
3731 || !in_combined_parallel);
3732
3733 type = TREE_TYPE (fd->loop.v);
3734 istart0 = create_tmp_var (fd->iter_type, ".istart0");
3735 iend0 = create_tmp_var (fd->iter_type, ".iend0");
3736 TREE_ADDRESSABLE (istart0) = 1;
3737 TREE_ADDRESSABLE (iend0) = 1;
3738 if (gimple_referenced_vars (cfun))
3739 {
3740 add_referenced_var (istart0);
3741 add_referenced_var (iend0);
3742 }
3743
3744 /* See if we need to bias by LLONG_MIN. */
3745 if (fd->iter_type == long_long_unsigned_type_node
3746 && TREE_CODE (type) == INTEGER_TYPE
3747 && !TYPE_UNSIGNED (type))
3748 {
3749 tree n1, n2;
3750
3751 if (fd->loop.cond_code == LT_EXPR)
3752 {
3753 n1 = fd->loop.n1;
3754 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
3755 }
3756 else
3757 {
3758 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
3759 n2 = fd->loop.n1;
3760 }
3761 if (TREE_CODE (n1) != INTEGER_CST
3762 || TREE_CODE (n2) != INTEGER_CST
3763 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
3764 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
3765 }
3766
3767 entry_bb = region->entry;
3768 cont_bb = region->cont;
3769 collapse_bb = NULL;
3770 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
3771 gcc_assert (broken_loop
3772 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
3773 l0_bb = split_edge (FALLTHRU_EDGE (entry_bb));
3774 l1_bb = single_succ (l0_bb);
3775 if (!broken_loop)
3776 {
3777 l2_bb = create_empty_bb (cont_bb);
3778 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l1_bb);
3779 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
3780 }
3781 else
3782 l2_bb = NULL;
3783 l3_bb = BRANCH_EDGE (entry_bb)->dest;
3784 exit_bb = region->exit;
3785
3786 gsi = gsi_last_bb (entry_bb);
3787
3788 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
3789 if (fd->collapse > 1)
3790 {
3791 /* collapsed loops need work for expansion in SSA form. */
3792 gcc_assert (!gimple_in_ssa_p (cfun));
3793 counts = (tree *) alloca (fd->collapse * sizeof (tree));
3794 for (i = 0; i < fd->collapse; i++)
3795 {
3796 tree itype = TREE_TYPE (fd->loops[i].v);
3797
3798 if (POINTER_TYPE_P (itype))
3799 itype = signed_type_for (itype);
3800 t = build_int_cst (itype, (fd->loops[i].cond_code == LT_EXPR
3801 ? -1 : 1));
3802 t = fold_build2 (PLUS_EXPR, itype,
3803 fold_convert (itype, fd->loops[i].step), t);
3804 t = fold_build2 (PLUS_EXPR, itype, t,
3805 fold_convert (itype, fd->loops[i].n2));
3806 t = fold_build2 (MINUS_EXPR, itype, t,
3807 fold_convert (itype, fd->loops[i].n1));
3808 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
3809 t = fold_build2 (TRUNC_DIV_EXPR, itype,
3810 fold_build1 (NEGATE_EXPR, itype, t),
3811 fold_build1 (NEGATE_EXPR, itype,
3812 fold_convert (itype,
3813 fd->loops[i].step)));
3814 else
3815 t = fold_build2 (TRUNC_DIV_EXPR, itype, t,
3816 fold_convert (itype, fd->loops[i].step));
3817 t = fold_convert (type, t);
3818 if (TREE_CODE (t) == INTEGER_CST)
3819 counts[i] = t;
3820 else
3821 {
3822 counts[i] = make_rename_temp (type, ".count");
3823 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE,
3824 true, GSI_SAME_STMT);
3825 stmt = gimple_build_assign (counts[i], t);
3826 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
3827 }
3828 if (SSA_VAR_P (fd->loop.n2))
3829 {
3830 if (i == 0)
3831 t = counts[0];
3832 else
3833 {
3834 t = fold_build2 (MULT_EXPR, type, fd->loop.n2, counts[i]);
3835 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE,
3836 true, GSI_SAME_STMT);
3837 }
3838 stmt = gimple_build_assign (fd->loop.n2, t);
3839 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
3840 }
3841 }
3842 }
3843 if (in_combined_parallel)
3844 {
3845 /* In a combined parallel loop, emit a call to
3846 GOMP_loop_foo_next. */
3847 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
3848 build_fold_addr_expr (istart0),
3849 build_fold_addr_expr (iend0));
3850 }
3851 else
3852 {
3853 tree t0, t1, t2, t3, t4;
3854 /* If this is not a combined parallel loop, emit a call to
3855 GOMP_loop_foo_start in ENTRY_BB. */
3856 t4 = build_fold_addr_expr (iend0);
3857 t3 = build_fold_addr_expr (istart0);
3858 t2 = fold_convert (fd->iter_type, fd->loop.step);
3859 if (POINTER_TYPE_P (type)
3860 && TYPE_PRECISION (type) != TYPE_PRECISION (fd->iter_type))
3861 {
3862 /* Avoid casting pointers to integer of a different size. */
3863 tree itype = signed_type_for (type);
3864 t1 = fold_convert (fd->iter_type, fold_convert (itype, fd->loop.n2));
3865 t0 = fold_convert (fd->iter_type, fold_convert (itype, fd->loop.n1));
3866 }
3867 else
3868 {
3869 t1 = fold_convert (fd->iter_type, fd->loop.n2);
3870 t0 = fold_convert (fd->iter_type, fd->loop.n1);
3871 }
3872 if (bias)
3873 {
3874 t1 = fold_build2 (PLUS_EXPR, fd->iter_type, t1, bias);
3875 t0 = fold_build2 (PLUS_EXPR, fd->iter_type, t0, bias);
3876 }
3877 if (fd->iter_type == long_integer_type_node)
3878 {
3879 if (fd->chunk_size)
3880 {
3881 t = fold_convert (fd->iter_type, fd->chunk_size);
3882 t = build_call_expr (builtin_decl_explicit (start_fn),
3883 6, t0, t1, t2, t, t3, t4);
3884 }
3885 else
3886 t = build_call_expr (builtin_decl_explicit (start_fn),
3887 5, t0, t1, t2, t3, t4);
3888 }
3889 else
3890 {
3891 tree t5;
3892 tree c_bool_type;
3893 tree bfn_decl;
3894
3895 /* The GOMP_loop_ull_*start functions have additional boolean
3896 argument, true for < loops and false for > loops.
3897 In Fortran, the C bool type can be different from
3898 boolean_type_node. */
3899 bfn_decl = builtin_decl_explicit (start_fn);
3900 c_bool_type = TREE_TYPE (TREE_TYPE (bfn_decl));
3901 t5 = build_int_cst (c_bool_type,
3902 fd->loop.cond_code == LT_EXPR ? 1 : 0);
3903 if (fd->chunk_size)
3904 {
3905 tree bfn_decl = builtin_decl_explicit (start_fn);
3906 t = fold_convert (fd->iter_type, fd->chunk_size);
3907 t = build_call_expr (bfn_decl, 7, t5, t0, t1, t2, t, t3, t4);
3908 }
3909 else
3910 t = build_call_expr (builtin_decl_explicit (start_fn),
3911 6, t5, t0, t1, t2, t3, t4);
3912 }
3913 }
3914 if (TREE_TYPE (t) != boolean_type_node)
3915 t = fold_build2 (NE_EXPR, boolean_type_node,
3916 t, build_int_cst (TREE_TYPE (t), 0));
3917 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
3918 true, GSI_SAME_STMT);
3919 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
3920
3921 /* Remove the GIMPLE_OMP_FOR statement. */
3922 gsi_remove (&gsi, true);
3923
3924 /* Iteration setup for sequential loop goes in L0_BB. */
3925 gsi = gsi_start_bb (l0_bb);
3926 t = istart0;
3927 if (bias)
3928 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
3929 if (POINTER_TYPE_P (type))
3930 t = fold_convert (signed_type_for (type), t);
3931 t = fold_convert (type, t);
3932 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE,
3933 false, GSI_CONTINUE_LINKING);
3934 stmt = gimple_build_assign (fd->loop.v, t);
3935 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
3936
3937 t = iend0;
3938 if (bias)
3939 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
3940 if (POINTER_TYPE_P (type))
3941 t = fold_convert (signed_type_for (type), t);
3942 t = fold_convert (type, t);
3943 iend = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
3944 false, GSI_CONTINUE_LINKING);
3945 if (fd->collapse > 1)
3946 {
3947 tree tem = make_rename_temp (type, ".tem");
3948 stmt = gimple_build_assign (tem, fd->loop.v);
3949 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
3950 for (i = fd->collapse - 1; i >= 0; i--)
3951 {
3952 tree vtype = TREE_TYPE (fd->loops[i].v), itype;
3953 itype = vtype;
3954 if (POINTER_TYPE_P (vtype))
3955 itype = signed_type_for (vtype);
3956 t = fold_build2 (TRUNC_MOD_EXPR, type, tem, counts[i]);
3957 t = fold_convert (itype, t);
3958 t = fold_build2 (MULT_EXPR, itype, t,
3959 fold_convert (itype, fd->loops[i].step));
3960 if (POINTER_TYPE_P (vtype))
3961 t = fold_build_pointer_plus (fd->loops[i].n1, t);
3962 else
3963 t = fold_build2 (PLUS_EXPR, itype, fd->loops[i].n1, t);
3964 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE,
3965 false, GSI_CONTINUE_LINKING);
3966 stmt = gimple_build_assign (fd->loops[i].v, t);
3967 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
3968 if (i != 0)
3969 {
3970 t = fold_build2 (TRUNC_DIV_EXPR, type, tem, counts[i]);
3971 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE,
3972 false, GSI_CONTINUE_LINKING);
3973 stmt = gimple_build_assign (tem, t);
3974 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
3975 }
3976 }
3977 }
3978
3979 if (!broken_loop)
3980 {
3981 /* Code to control the increment and predicate for the sequential
3982 loop goes in the CONT_BB. */
3983 gsi = gsi_last_bb (cont_bb);
3984 stmt = gsi_stmt (gsi);
3985 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
3986 vmain = gimple_omp_continue_control_use (stmt);
3987 vback = gimple_omp_continue_control_def (stmt);
3988
3989 if (POINTER_TYPE_P (type))
3990 t = fold_build_pointer_plus (vmain, fd->loop.step);
3991 else
3992 t = fold_build2 (PLUS_EXPR, type, vmain, fd->loop.step);
3993 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE,
3994 true, GSI_SAME_STMT);
3995 stmt = gimple_build_assign (vback, t);
3996 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
3997
3998 t = build2 (fd->loop.cond_code, boolean_type_node, vback, iend);
3999 stmt = gimple_build_cond_empty (t);
4000 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
4001
4002 /* Remove GIMPLE_OMP_CONTINUE. */
4003 gsi_remove (&gsi, true);
4004
4005 if (fd->collapse > 1)
4006 {
4007 basic_block last_bb, bb;
4008
4009 last_bb = cont_bb;
4010 for (i = fd->collapse - 1; i >= 0; i--)
4011 {
4012 tree vtype = TREE_TYPE (fd->loops[i].v);
4013
4014 bb = create_empty_bb (last_bb);
4015 gsi = gsi_start_bb (bb);
4016
4017 if (i < fd->collapse - 1)
4018 {
4019 e = make_edge (last_bb, bb, EDGE_FALSE_VALUE);
4020 e->probability = REG_BR_PROB_BASE / 8;
4021
4022 t = fd->loops[i + 1].n1;
4023 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE,
4024 false, GSI_CONTINUE_LINKING);
4025 stmt = gimple_build_assign (fd->loops[i + 1].v, t);
4026 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4027 }
4028 else
4029 collapse_bb = bb;
4030
4031 set_immediate_dominator (CDI_DOMINATORS, bb, last_bb);
4032
4033 if (POINTER_TYPE_P (vtype))
4034 t = fold_build_pointer_plus (fd->loops[i].v, fd->loops[i].step);
4035 else
4036 t = fold_build2 (PLUS_EXPR, vtype, fd->loops[i].v,
4037 fd->loops[i].step);
4038 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE,
4039 false, GSI_CONTINUE_LINKING);
4040 stmt = gimple_build_assign (fd->loops[i].v, t);
4041 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4042
4043 if (i > 0)
4044 {
4045 t = fd->loops[i].n2;
4046 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
4047 false, GSI_CONTINUE_LINKING);
4048 t = fold_build2 (fd->loops[i].cond_code, boolean_type_node,
4049 fd->loops[i].v, t);
4050 stmt = gimple_build_cond_empty (t);
4051 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4052 e = make_edge (bb, l1_bb, EDGE_TRUE_VALUE);
4053 e->probability = REG_BR_PROB_BASE * 7 / 8;
4054 }
4055 else
4056 make_edge (bb, l1_bb, EDGE_FALLTHRU);
4057 last_bb = bb;
4058 }
4059 }
4060
4061 /* Emit code to get the next parallel iteration in L2_BB. */
4062 gsi = gsi_start_bb (l2_bb);
4063
4064 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
4065 build_fold_addr_expr (istart0),
4066 build_fold_addr_expr (iend0));
4067 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
4068 false, GSI_CONTINUE_LINKING);
4069 if (TREE_TYPE (t) != boolean_type_node)
4070 t = fold_build2 (NE_EXPR, boolean_type_node,
4071 t, build_int_cst (TREE_TYPE (t), 0));
4072 stmt = gimple_build_cond_empty (t);
4073 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4074 }
4075
4076 /* Add the loop cleanup function. */
4077 gsi = gsi_last_bb (exit_bb);
4078 if (gimple_omp_return_nowait_p (gsi_stmt (gsi)))
4079 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_NOWAIT);
4080 else
4081 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END);
4082 stmt = gimple_build_call (t, 0);
4083 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
4084 gsi_remove (&gsi, true);
4085
4086 /* Connect the new blocks. */
4087 find_edge (entry_bb, l0_bb)->flags = EDGE_TRUE_VALUE;
4088 find_edge (entry_bb, l3_bb)->flags = EDGE_FALSE_VALUE;
4089
4090 if (!broken_loop)
4091 {
4092 gimple_seq phis;
4093
4094 e = find_edge (cont_bb, l3_bb);
4095 ne = make_edge (l2_bb, l3_bb, EDGE_FALSE_VALUE);
4096
4097 phis = phi_nodes (l3_bb);
4098 for (gsi = gsi_start (phis); !gsi_end_p (gsi); gsi_next (&gsi))
4099 {
4100 gimple phi = gsi_stmt (gsi);
4101 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, ne),
4102 PHI_ARG_DEF_FROM_EDGE (phi, e));
4103 }
4104 remove_edge (e);
4105
4106 make_edge (cont_bb, l2_bb, EDGE_FALSE_VALUE);
4107 if (fd->collapse > 1)
4108 {
4109 e = find_edge (cont_bb, l1_bb);
4110 remove_edge (e);
4111 e = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
4112 }
4113 else
4114 {
4115 e = find_edge (cont_bb, l1_bb);
4116 e->flags = EDGE_TRUE_VALUE;
4117 }
4118 e->probability = REG_BR_PROB_BASE * 7 / 8;
4119 find_edge (cont_bb, l2_bb)->probability = REG_BR_PROB_BASE / 8;
4120 make_edge (l2_bb, l0_bb, EDGE_TRUE_VALUE);
4121
4122 set_immediate_dominator (CDI_DOMINATORS, l2_bb,
4123 recompute_dominator (CDI_DOMINATORS, l2_bb));
4124 set_immediate_dominator (CDI_DOMINATORS, l3_bb,
4125 recompute_dominator (CDI_DOMINATORS, l3_bb));
4126 set_immediate_dominator (CDI_DOMINATORS, l0_bb,
4127 recompute_dominator (CDI_DOMINATORS, l0_bb));
4128 set_immediate_dominator (CDI_DOMINATORS, l1_bb,
4129 recompute_dominator (CDI_DOMINATORS, l1_bb));
4130 }
4131 }
4132
4133
4134 /* A subroutine of expand_omp_for. Generate code for a parallel
4135 loop with static schedule and no specified chunk size. Given
4136 parameters:
4137
4138 for (V = N1; V cond N2; V += STEP) BODY;
4139
4140 where COND is "<" or ">", we generate pseudocode
4141
4142 if (cond is <)
4143 adj = STEP - 1;
4144 else
4145 adj = STEP + 1;
4146 if ((__typeof (V)) -1 > 0 && cond is >)
4147 n = -(adj + N2 - N1) / -STEP;
4148 else
4149 n = (adj + N2 - N1) / STEP;
4150 q = n / nthreads;
4151 tt = n % nthreads;
4152 if (threadid < tt) goto L3; else goto L4;
4153 L3:
4154 tt = 0;
4155 q = q + 1;
4156 L4:
4157 s0 = q * threadid + tt;
4158 e0 = s0 + q;
4159 V = s0 * STEP + N1;
4160 if (s0 >= e0) goto L2; else goto L0;
4161 L0:
4162 e = e0 * STEP + N1;
4163 L1:
4164 BODY;
4165 V += STEP;
4166 if (V cond e) goto L1;
4167 L2:
4168 */
4169
4170 static void
4171 expand_omp_for_static_nochunk (struct omp_region *region,
4172 struct omp_for_data *fd)
4173 {
4174 tree n, q, s0, e0, e, t, tt, nthreads, threadid;
4175 tree type, itype, vmain, vback;
4176 basic_block entry_bb, second_bb, third_bb, exit_bb, seq_start_bb;
4177 basic_block body_bb, cont_bb;
4178 basic_block fin_bb;
4179 gimple_stmt_iterator gsi;
4180 gimple stmt;
4181 edge ep;
4182
4183 itype = type = TREE_TYPE (fd->loop.v);
4184 if (POINTER_TYPE_P (type))
4185 itype = signed_type_for (type);
4186
4187 entry_bb = region->entry;
4188 cont_bb = region->cont;
4189 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
4190 gcc_assert (BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
4191 seq_start_bb = split_edge (FALLTHRU_EDGE (entry_bb));
4192 body_bb = single_succ (seq_start_bb);
4193 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
4194 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
4195 fin_bb = FALLTHRU_EDGE (cont_bb)->dest;
4196 exit_bb = region->exit;
4197
4198 /* Iteration space partitioning goes in ENTRY_BB. */
4199 gsi = gsi_last_bb (entry_bb);
4200 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
4201
4202 t = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS), 0);
4203 t = fold_convert (itype, t);
4204 nthreads = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
4205 true, GSI_SAME_STMT);
4206
4207 t = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM), 0);
4208 t = fold_convert (itype, t);
4209 threadid = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
4210 true, GSI_SAME_STMT);
4211
4212 fd->loop.n1
4213 = force_gimple_operand_gsi (&gsi, fold_convert (type, fd->loop.n1),
4214 true, NULL_TREE, true, GSI_SAME_STMT);
4215 fd->loop.n2
4216 = force_gimple_operand_gsi (&gsi, fold_convert (itype, fd->loop.n2),
4217 true, NULL_TREE, true, GSI_SAME_STMT);
4218 fd->loop.step
4219 = force_gimple_operand_gsi (&gsi, fold_convert (itype, fd->loop.step),
4220 true, NULL_TREE, true, GSI_SAME_STMT);
4221
4222 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
4223 t = fold_build2 (PLUS_EXPR, itype, fd->loop.step, t);
4224 t = fold_build2 (PLUS_EXPR, itype, t, fd->loop.n2);
4225 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, fd->loop.n1));
4226 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
4227 t = fold_build2 (TRUNC_DIV_EXPR, itype,
4228 fold_build1 (NEGATE_EXPR, itype, t),
4229 fold_build1 (NEGATE_EXPR, itype, fd->loop.step));
4230 else
4231 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, fd->loop.step);
4232 t = fold_convert (itype, t);
4233 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
4234
4235 q = make_rename_temp (itype, "q");
4236 t = fold_build2 (TRUNC_DIV_EXPR, itype, n, nthreads);
4237 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
4238 gsi_insert_before (&gsi, gimple_build_assign (q, t), GSI_SAME_STMT);
4239
4240 tt = make_rename_temp (itype, "tt");
4241 t = fold_build2 (TRUNC_MOD_EXPR, itype, n, nthreads);
4242 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
4243 gsi_insert_before (&gsi, gimple_build_assign (tt, t), GSI_SAME_STMT);
4244
4245 t = build2 (LT_EXPR, boolean_type_node, threadid, tt);
4246 stmt = gimple_build_cond_empty (t);
4247 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
4248
4249 second_bb = split_block (entry_bb, stmt)->dest;
4250 gsi = gsi_last_bb (second_bb);
4251 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
4252
4253 gsi_insert_before (&gsi, gimple_build_assign (tt, build_int_cst (itype, 0)),
4254 GSI_SAME_STMT);
4255 stmt = gimple_build_assign_with_ops (PLUS_EXPR, q, q,
4256 build_int_cst (itype, 1));
4257 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
4258
4259 third_bb = split_block (second_bb, stmt)->dest;
4260 gsi = gsi_last_bb (third_bb);
4261 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
4262
4263 t = build2 (MULT_EXPR, itype, q, threadid);
4264 t = build2 (PLUS_EXPR, itype, t, tt);
4265 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
4266
4267 t = fold_build2 (PLUS_EXPR, itype, s0, q);
4268 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
4269
4270 t = build2 (GE_EXPR, boolean_type_node, s0, e0);
4271 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
4272
4273 /* Remove the GIMPLE_OMP_FOR statement. */
4274 gsi_remove (&gsi, true);
4275
4276 /* Setup code for sequential iteration goes in SEQ_START_BB. */
4277 gsi = gsi_start_bb (seq_start_bb);
4278
4279 t = fold_convert (itype, s0);
4280 t = fold_build2 (MULT_EXPR, itype, t, fd->loop.step);
4281 if (POINTER_TYPE_P (type))
4282 t = fold_build_pointer_plus (fd->loop.n1, t);
4283 else
4284 t = fold_build2 (PLUS_EXPR, type, t, fd->loop.n1);
4285 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE,
4286 false, GSI_CONTINUE_LINKING);
4287 stmt = gimple_build_assign (fd->loop.v, t);
4288 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4289
4290 t = fold_convert (itype, e0);
4291 t = fold_build2 (MULT_EXPR, itype, t, fd->loop.step);
4292 if (POINTER_TYPE_P (type))
4293 t = fold_build_pointer_plus (fd->loop.n1, t);
4294 else
4295 t = fold_build2 (PLUS_EXPR, type, t, fd->loop.n1);
4296 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
4297 false, GSI_CONTINUE_LINKING);
4298
4299 /* The code controlling the sequential loop replaces the
4300 GIMPLE_OMP_CONTINUE. */
4301 gsi = gsi_last_bb (cont_bb);
4302 stmt = gsi_stmt (gsi);
4303 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
4304 vmain = gimple_omp_continue_control_use (stmt);
4305 vback = gimple_omp_continue_control_def (stmt);
4306
4307 if (POINTER_TYPE_P (type))
4308 t = fold_build_pointer_plus (vmain, fd->loop.step);
4309 else
4310 t = fold_build2 (PLUS_EXPR, type, vmain, fd->loop.step);
4311 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE,
4312 true, GSI_SAME_STMT);
4313 stmt = gimple_build_assign (vback, t);
4314 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
4315
4316 t = build2 (fd->loop.cond_code, boolean_type_node, vback, e);
4317 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
4318
4319 /* Remove the GIMPLE_OMP_CONTINUE statement. */
4320 gsi_remove (&gsi, true);
4321
4322 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
4323 gsi = gsi_last_bb (exit_bb);
4324 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
4325 force_gimple_operand_gsi (&gsi, build_omp_barrier (), false, NULL_TREE,
4326 false, GSI_SAME_STMT);
4327 gsi_remove (&gsi, true);
4328
4329 /* Connect all the blocks. */
4330 ep = make_edge (entry_bb, third_bb, EDGE_FALSE_VALUE);
4331 ep->probability = REG_BR_PROB_BASE / 4 * 3;
4332 ep = find_edge (entry_bb, second_bb);
4333 ep->flags = EDGE_TRUE_VALUE;
4334 ep->probability = REG_BR_PROB_BASE / 4;
4335 find_edge (third_bb, seq_start_bb)->flags = EDGE_FALSE_VALUE;
4336 find_edge (third_bb, fin_bb)->flags = EDGE_TRUE_VALUE;
4337
4338 find_edge (cont_bb, body_bb)->flags = EDGE_TRUE_VALUE;
4339 find_edge (cont_bb, fin_bb)->flags = EDGE_FALSE_VALUE;
4340
4341 set_immediate_dominator (CDI_DOMINATORS, second_bb, entry_bb);
4342 set_immediate_dominator (CDI_DOMINATORS, third_bb, entry_bb);
4343 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb, third_bb);
4344 set_immediate_dominator (CDI_DOMINATORS, body_bb,
4345 recompute_dominator (CDI_DOMINATORS, body_bb));
4346 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
4347 recompute_dominator (CDI_DOMINATORS, fin_bb));
4348 }
4349
4350
4351 /* A subroutine of expand_omp_for. Generate code for a parallel
4352 loop with static schedule and a specified chunk size. Given
4353 parameters:
4354
4355 for (V = N1; V cond N2; V += STEP) BODY;
4356
4357 where COND is "<" or ">", we generate pseudocode
4358
4359 if (cond is <)
4360 adj = STEP - 1;
4361 else
4362 adj = STEP + 1;
4363 if ((__typeof (V)) -1 > 0 && cond is >)
4364 n = -(adj + N2 - N1) / -STEP;
4365 else
4366 n = (adj + N2 - N1) / STEP;
4367 trip = 0;
4368 V = threadid * CHUNK * STEP + N1; -- this extra definition of V is
4369 here so that V is defined
4370 if the loop is not entered
4371 L0:
4372 s0 = (trip * nthreads + threadid) * CHUNK;
4373 e0 = min(s0 + CHUNK, n);
4374 if (s0 < n) goto L1; else goto L4;
4375 L1:
4376 V = s0 * STEP + N1;
4377 e = e0 * STEP + N1;
4378 L2:
4379 BODY;
4380 V += STEP;
4381 if (V cond e) goto L2; else goto L3;
4382 L3:
4383 trip += 1;
4384 goto L0;
4385 L4:
4386 */
4387
4388 static void
4389 expand_omp_for_static_chunk (struct omp_region *region, struct omp_for_data *fd)
4390 {
4391 tree n, s0, e0, e, t;
4392 tree trip_var, trip_init, trip_main, trip_back, nthreads, threadid;
4393 tree type, itype, v_main, v_back, v_extra;
4394 basic_block entry_bb, exit_bb, body_bb, seq_start_bb, iter_part_bb;
4395 basic_block trip_update_bb, cont_bb, fin_bb;
4396 gimple_stmt_iterator si;
4397 gimple stmt;
4398 edge se;
4399
4400 itype = type = TREE_TYPE (fd->loop.v);
4401 if (POINTER_TYPE_P (type))
4402 itype = signed_type_for (type);
4403
4404 entry_bb = region->entry;
4405 se = split_block (entry_bb, last_stmt (entry_bb));
4406 entry_bb = se->src;
4407 iter_part_bb = se->dest;
4408 cont_bb = region->cont;
4409 gcc_assert (EDGE_COUNT (iter_part_bb->succs) == 2);
4410 gcc_assert (BRANCH_EDGE (iter_part_bb)->dest
4411 == FALLTHRU_EDGE (cont_bb)->dest);
4412 seq_start_bb = split_edge (FALLTHRU_EDGE (iter_part_bb));
4413 body_bb = single_succ (seq_start_bb);
4414 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
4415 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
4416 fin_bb = FALLTHRU_EDGE (cont_bb)->dest;
4417 trip_update_bb = split_edge (FALLTHRU_EDGE (cont_bb));
4418 exit_bb = region->exit;
4419
4420 /* Trip and adjustment setup goes in ENTRY_BB. */
4421 si = gsi_last_bb (entry_bb);
4422 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_FOR);
4423
4424 t = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS), 0);
4425 t = fold_convert (itype, t);
4426 nthreads = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
4427 true, GSI_SAME_STMT);
4428
4429 t = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM), 0);
4430 t = fold_convert (itype, t);
4431 threadid = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
4432 true, GSI_SAME_STMT);
4433
4434 fd->loop.n1
4435 = force_gimple_operand_gsi (&si, fold_convert (type, fd->loop.n1),
4436 true, NULL_TREE, true, GSI_SAME_STMT);
4437 fd->loop.n2
4438 = force_gimple_operand_gsi (&si, fold_convert (itype, fd->loop.n2),
4439 true, NULL_TREE, true, GSI_SAME_STMT);
4440 fd->loop.step
4441 = force_gimple_operand_gsi (&si, fold_convert (itype, fd->loop.step),
4442 true, NULL_TREE, true, GSI_SAME_STMT);
4443 fd->chunk_size
4444 = force_gimple_operand_gsi (&si, fold_convert (itype, fd->chunk_size),
4445 true, NULL_TREE, true, GSI_SAME_STMT);
4446
4447 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
4448 t = fold_build2 (PLUS_EXPR, itype, fd->loop.step, t);
4449 t = fold_build2 (PLUS_EXPR, itype, t, fd->loop.n2);
4450 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, fd->loop.n1));
4451 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
4452 t = fold_build2 (TRUNC_DIV_EXPR, itype,
4453 fold_build1 (NEGATE_EXPR, itype, t),
4454 fold_build1 (NEGATE_EXPR, itype, fd->loop.step));
4455 else
4456 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, fd->loop.step);
4457 t = fold_convert (itype, t);
4458 n = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
4459 true, GSI_SAME_STMT);
4460
4461 trip_var = create_tmp_reg (itype, ".trip");
4462 if (gimple_in_ssa_p (cfun))
4463 {
4464 add_referenced_var (trip_var);
4465 trip_init = make_ssa_name (trip_var, NULL);
4466 trip_main = make_ssa_name (trip_var, NULL);
4467 trip_back = make_ssa_name (trip_var, NULL);
4468 }
4469 else
4470 {
4471 trip_init = trip_var;
4472 trip_main = trip_var;
4473 trip_back = trip_var;
4474 }
4475
4476 stmt = gimple_build_assign (trip_init, build_int_cst (itype, 0));
4477 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
4478
4479 t = fold_build2 (MULT_EXPR, itype, threadid, fd->chunk_size);
4480 t = fold_build2 (MULT_EXPR, itype, t, fd->loop.step);
4481 if (POINTER_TYPE_P (type))
4482 t = fold_build_pointer_plus (fd->loop.n1, t);
4483 else
4484 t = fold_build2 (PLUS_EXPR, type, t, fd->loop.n1);
4485 v_extra = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
4486 true, GSI_SAME_STMT);
4487
4488 /* Remove the GIMPLE_OMP_FOR. */
4489 gsi_remove (&si, true);
4490
4491 /* Iteration space partitioning goes in ITER_PART_BB. */
4492 si = gsi_last_bb (iter_part_bb);
4493
4494 t = fold_build2 (MULT_EXPR, itype, trip_main, nthreads);
4495 t = fold_build2 (PLUS_EXPR, itype, t, threadid);
4496 t = fold_build2 (MULT_EXPR, itype, t, fd->chunk_size);
4497 s0 = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
4498 false, GSI_CONTINUE_LINKING);
4499
4500 t = fold_build2 (PLUS_EXPR, itype, s0, fd->chunk_size);
4501 t = fold_build2 (MIN_EXPR, itype, t, n);
4502 e0 = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
4503 false, GSI_CONTINUE_LINKING);
4504
4505 t = build2 (LT_EXPR, boolean_type_node, s0, n);
4506 gsi_insert_after (&si, gimple_build_cond_empty (t), GSI_CONTINUE_LINKING);
4507
4508 /* Setup code for sequential iteration goes in SEQ_START_BB. */
4509 si = gsi_start_bb (seq_start_bb);
4510
4511 t = fold_convert (itype, s0);
4512 t = fold_build2 (MULT_EXPR, itype, t, fd->loop.step);
4513 if (POINTER_TYPE_P (type))
4514 t = fold_build_pointer_plus (fd->loop.n1, t);
4515 else
4516 t = fold_build2 (PLUS_EXPR, type, t, fd->loop.n1);
4517 t = force_gimple_operand_gsi (&si, t, false, NULL_TREE,
4518 false, GSI_CONTINUE_LINKING);
4519 stmt = gimple_build_assign (fd->loop.v, t);
4520 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
4521
4522 t = fold_convert (itype, e0);
4523 t = fold_build2 (MULT_EXPR, itype, t, fd->loop.step);
4524 if (POINTER_TYPE_P (type))
4525 t = fold_build_pointer_plus (fd->loop.n1, t);
4526 else
4527 t = fold_build2 (PLUS_EXPR, type, t, fd->loop.n1);
4528 e = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
4529 false, GSI_CONTINUE_LINKING);
4530
4531 /* The code controlling the sequential loop goes in CONT_BB,
4532 replacing the GIMPLE_OMP_CONTINUE. */
4533 si = gsi_last_bb (cont_bb);
4534 stmt = gsi_stmt (si);
4535 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
4536 v_main = gimple_omp_continue_control_use (stmt);
4537 v_back = gimple_omp_continue_control_def (stmt);
4538
4539 if (POINTER_TYPE_P (type))
4540 t = fold_build_pointer_plus (v_main, fd->loop.step);
4541 else
4542 t = fold_build2 (PLUS_EXPR, type, v_main, fd->loop.step);
4543 stmt = gimple_build_assign (v_back, t);
4544 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
4545
4546 t = build2 (fd->loop.cond_code, boolean_type_node, v_back, e);
4547 gsi_insert_before (&si, gimple_build_cond_empty (t), GSI_SAME_STMT);
4548
4549 /* Remove GIMPLE_OMP_CONTINUE. */
4550 gsi_remove (&si, true);
4551
4552 /* Trip update code goes into TRIP_UPDATE_BB. */
4553 si = gsi_start_bb (trip_update_bb);
4554
4555 t = build_int_cst (itype, 1);
4556 t = build2 (PLUS_EXPR, itype, trip_main, t);
4557 stmt = gimple_build_assign (trip_back, t);
4558 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
4559
4560 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
4561 si = gsi_last_bb (exit_bb);
4562 if (!gimple_omp_return_nowait_p (gsi_stmt (si)))
4563 force_gimple_operand_gsi (&si, build_omp_barrier (), false, NULL_TREE,
4564 false, GSI_SAME_STMT);
4565 gsi_remove (&si, true);
4566
4567 /* Connect the new blocks. */
4568 find_edge (iter_part_bb, seq_start_bb)->flags = EDGE_TRUE_VALUE;
4569 find_edge (iter_part_bb, fin_bb)->flags = EDGE_FALSE_VALUE;
4570
4571 find_edge (cont_bb, body_bb)->flags = EDGE_TRUE_VALUE;
4572 find_edge (cont_bb, trip_update_bb)->flags = EDGE_FALSE_VALUE;
4573
4574 redirect_edge_and_branch (single_succ_edge (trip_update_bb), iter_part_bb);
4575
4576 if (gimple_in_ssa_p (cfun))
4577 {
4578 gimple_stmt_iterator psi;
4579 gimple phi;
4580 edge re, ene;
4581 edge_var_map_vector head;
4582 edge_var_map *vm;
4583 size_t i;
4584
4585 /* When we redirect the edge from trip_update_bb to iter_part_bb, we
4586 remove arguments of the phi nodes in fin_bb. We need to create
4587 appropriate phi nodes in iter_part_bb instead. */
4588 se = single_pred_edge (fin_bb);
4589 re = single_succ_edge (trip_update_bb);
4590 head = redirect_edge_var_map_vector (re);
4591 ene = single_succ_edge (entry_bb);
4592
4593 psi = gsi_start_phis (fin_bb);
4594 for (i = 0; !gsi_end_p (psi) && VEC_iterate (edge_var_map, head, i, vm);
4595 gsi_next (&psi), ++i)
4596 {
4597 gimple nphi;
4598 source_location locus;
4599
4600 phi = gsi_stmt (psi);
4601 t = gimple_phi_result (phi);
4602 gcc_assert (t == redirect_edge_var_map_result (vm));
4603 nphi = create_phi_node (t, iter_part_bb);
4604 SSA_NAME_DEF_STMT (t) = nphi;
4605
4606 t = PHI_ARG_DEF_FROM_EDGE (phi, se);
4607 locus = gimple_phi_arg_location_from_edge (phi, se);
4608
4609 /* A special case -- fd->loop.v is not yet computed in
4610 iter_part_bb, we need to use v_extra instead. */
4611 if (t == fd->loop.v)
4612 t = v_extra;
4613 add_phi_arg (nphi, t, ene, locus);
4614 locus = redirect_edge_var_map_location (vm);
4615 add_phi_arg (nphi, redirect_edge_var_map_def (vm), re, locus);
4616 }
4617 gcc_assert (!gsi_end_p (psi) && i == VEC_length (edge_var_map, head));
4618 redirect_edge_var_map_clear (re);
4619 while (1)
4620 {
4621 psi = gsi_start_phis (fin_bb);
4622 if (gsi_end_p (psi))
4623 break;
4624 remove_phi_node (&psi, false);
4625 }
4626
4627 /* Make phi node for trip. */
4628 phi = create_phi_node (trip_main, iter_part_bb);
4629 SSA_NAME_DEF_STMT (trip_main) = phi;
4630 add_phi_arg (phi, trip_back, single_succ_edge (trip_update_bb),
4631 UNKNOWN_LOCATION);
4632 add_phi_arg (phi, trip_init, single_succ_edge (entry_bb),
4633 UNKNOWN_LOCATION);
4634 }
4635
4636 set_immediate_dominator (CDI_DOMINATORS, trip_update_bb, cont_bb);
4637 set_immediate_dominator (CDI_DOMINATORS, iter_part_bb,
4638 recompute_dominator (CDI_DOMINATORS, iter_part_bb));
4639 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
4640 recompute_dominator (CDI_DOMINATORS, fin_bb));
4641 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb,
4642 recompute_dominator (CDI_DOMINATORS, seq_start_bb));
4643 set_immediate_dominator (CDI_DOMINATORS, body_bb,
4644 recompute_dominator (CDI_DOMINATORS, body_bb));
4645 }
4646
4647
4648 /* Expand the OpenMP loop defined by REGION. */
4649
4650 static void
4651 expand_omp_for (struct omp_region *region)
4652 {
4653 struct omp_for_data fd;
4654 struct omp_for_data_loop *loops;
4655
4656 loops
4657 = (struct omp_for_data_loop *)
4658 alloca (gimple_omp_for_collapse (last_stmt (region->entry))
4659 * sizeof (struct omp_for_data_loop));
4660 extract_omp_for_data (last_stmt (region->entry), &fd, loops);
4661 region->sched_kind = fd.sched_kind;
4662
4663 gcc_assert (EDGE_COUNT (region->entry->succs) == 2);
4664 BRANCH_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
4665 FALLTHRU_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
4666 if (region->cont)
4667 {
4668 gcc_assert (EDGE_COUNT (region->cont->succs) == 2);
4669 BRANCH_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
4670 FALLTHRU_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
4671 }
4672
4673 if (fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
4674 && !fd.have_ordered
4675 && fd.collapse == 1
4676 && region->cont != NULL)
4677 {
4678 if (fd.chunk_size == NULL)
4679 expand_omp_for_static_nochunk (region, &fd);
4680 else
4681 expand_omp_for_static_chunk (region, &fd);
4682 }
4683 else
4684 {
4685 int fn_index, start_ix, next_ix;
4686
4687 if (fd.chunk_size == NULL
4688 && fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
4689 fd.chunk_size = integer_zero_node;
4690 gcc_assert (fd.sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
4691 fn_index = (fd.sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
4692 ? 3 : fd.sched_kind;
4693 fn_index += fd.have_ordered * 4;
4694 start_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_START) + fn_index;
4695 next_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_NEXT) + fn_index;
4696 if (fd.iter_type == long_long_unsigned_type_node)
4697 {
4698 start_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_START
4699 - (int)BUILT_IN_GOMP_LOOP_STATIC_START);
4700 next_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_NEXT
4701 - (int)BUILT_IN_GOMP_LOOP_STATIC_NEXT);
4702 }
4703 expand_omp_for_generic (region, &fd, (enum built_in_function) start_ix,
4704 (enum built_in_function) next_ix);
4705 }
4706
4707 if (gimple_in_ssa_p (cfun))
4708 update_ssa (TODO_update_ssa_only_virtuals);
4709 }
4710
4711
4712 /* Expand code for an OpenMP sections directive. In pseudo code, we generate
4713
4714 v = GOMP_sections_start (n);
4715 L0:
4716 switch (v)
4717 {
4718 case 0:
4719 goto L2;
4720 case 1:
4721 section 1;
4722 goto L1;
4723 case 2:
4724 ...
4725 case n:
4726 ...
4727 default:
4728 abort ();
4729 }
4730 L1:
4731 v = GOMP_sections_next ();
4732 goto L0;
4733 L2:
4734 reduction;
4735
4736 If this is a combined parallel sections, replace the call to
4737 GOMP_sections_start with call to GOMP_sections_next. */
4738
4739 static void
4740 expand_omp_sections (struct omp_region *region)
4741 {
4742 tree t, u, vin = NULL, vmain, vnext, l2;
4743 VEC (tree,heap) *label_vec;
4744 unsigned len;
4745 basic_block entry_bb, l0_bb, l1_bb, l2_bb, default_bb;
4746 gimple_stmt_iterator si, switch_si;
4747 gimple sections_stmt, stmt, cont;
4748 edge_iterator ei;
4749 edge e;
4750 struct omp_region *inner;
4751 unsigned i, casei;
4752 bool exit_reachable = region->cont != NULL;
4753
4754 gcc_assert (region->exit != NULL);
4755 entry_bb = region->entry;
4756 l0_bb = single_succ (entry_bb);
4757 l1_bb = region->cont;
4758 l2_bb = region->exit;
4759 if (single_pred_p (l2_bb) && single_pred (l2_bb) == l0_bb)
4760 l2 = gimple_block_label (l2_bb);
4761 else
4762 {
4763 /* This can happen if there are reductions. */
4764 len = EDGE_COUNT (l0_bb->succs);
4765 gcc_assert (len > 0);
4766 e = EDGE_SUCC (l0_bb, len - 1);
4767 si = gsi_last_bb (e->dest);
4768 l2 = NULL_TREE;
4769 if (gsi_end_p (si)
4770 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
4771 l2 = gimple_block_label (e->dest);
4772 else
4773 FOR_EACH_EDGE (e, ei, l0_bb->succs)
4774 {
4775 si = gsi_last_bb (e->dest);
4776 if (gsi_end_p (si)
4777 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
4778 {
4779 l2 = gimple_block_label (e->dest);
4780 break;
4781 }
4782 }
4783 }
4784 if (exit_reachable)
4785 default_bb = create_empty_bb (l1_bb->prev_bb);
4786 else
4787 default_bb = create_empty_bb (l0_bb);
4788
4789 /* We will build a switch() with enough cases for all the
4790 GIMPLE_OMP_SECTION regions, a '0' case to handle the end of more work
4791 and a default case to abort if something goes wrong. */
4792 len = EDGE_COUNT (l0_bb->succs);
4793
4794 /* Use VEC_quick_push on label_vec throughout, since we know the size
4795 in advance. */
4796 label_vec = VEC_alloc (tree, heap, len);
4797
4798 /* The call to GOMP_sections_start goes in ENTRY_BB, replacing the
4799 GIMPLE_OMP_SECTIONS statement. */
4800 si = gsi_last_bb (entry_bb);
4801 sections_stmt = gsi_stmt (si);
4802 gcc_assert (gimple_code (sections_stmt) == GIMPLE_OMP_SECTIONS);
4803 vin = gimple_omp_sections_control (sections_stmt);
4804 if (!is_combined_parallel (region))
4805 {
4806 /* If we are not inside a combined parallel+sections region,
4807 call GOMP_sections_start. */
4808 t = build_int_cst (unsigned_type_node,
4809 exit_reachable ? len - 1 : len);
4810 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_START);
4811 stmt = gimple_build_call (u, 1, t);
4812 }
4813 else
4814 {
4815 /* Otherwise, call GOMP_sections_next. */
4816 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
4817 stmt = gimple_build_call (u, 0);
4818 }
4819 gimple_call_set_lhs (stmt, vin);
4820 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
4821 gsi_remove (&si, true);
4822
4823 /* The switch() statement replacing GIMPLE_OMP_SECTIONS_SWITCH goes in
4824 L0_BB. */
4825 switch_si = gsi_last_bb (l0_bb);
4826 gcc_assert (gimple_code (gsi_stmt (switch_si)) == GIMPLE_OMP_SECTIONS_SWITCH);
4827 if (exit_reachable)
4828 {
4829 cont = last_stmt (l1_bb);
4830 gcc_assert (gimple_code (cont) == GIMPLE_OMP_CONTINUE);
4831 vmain = gimple_omp_continue_control_use (cont);
4832 vnext = gimple_omp_continue_control_def (cont);
4833 }
4834 else
4835 {
4836 vmain = vin;
4837 vnext = NULL_TREE;
4838 }
4839
4840 t = build_case_label (build_int_cst (unsigned_type_node, 0), NULL, l2);
4841 VEC_quick_push (tree, label_vec, t);
4842 i = 1;
4843
4844 /* Convert each GIMPLE_OMP_SECTION into a CASE_LABEL_EXPR. */
4845 for (inner = region->inner, casei = 1;
4846 inner;
4847 inner = inner->next, i++, casei++)
4848 {
4849 basic_block s_entry_bb, s_exit_bb;
4850
4851 /* Skip optional reduction region. */
4852 if (inner->type == GIMPLE_OMP_ATOMIC_LOAD)
4853 {
4854 --i;
4855 --casei;
4856 continue;
4857 }
4858
4859 s_entry_bb = inner->entry;
4860 s_exit_bb = inner->exit;
4861
4862 t = gimple_block_label (s_entry_bb);
4863 u = build_int_cst (unsigned_type_node, casei);
4864 u = build_case_label (u, NULL, t);
4865 VEC_quick_push (tree, label_vec, u);
4866
4867 si = gsi_last_bb (s_entry_bb);
4868 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SECTION);
4869 gcc_assert (i < len || gimple_omp_section_last_p (gsi_stmt (si)));
4870 gsi_remove (&si, true);
4871 single_succ_edge (s_entry_bb)->flags = EDGE_FALLTHRU;
4872
4873 if (s_exit_bb == NULL)
4874 continue;
4875
4876 si = gsi_last_bb (s_exit_bb);
4877 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
4878 gsi_remove (&si, true);
4879
4880 single_succ_edge (s_exit_bb)->flags = EDGE_FALLTHRU;
4881 }
4882
4883 /* Error handling code goes in DEFAULT_BB. */
4884 t = gimple_block_label (default_bb);
4885 u = build_case_label (NULL, NULL, t);
4886 make_edge (l0_bb, default_bb, 0);
4887
4888 stmt = gimple_build_switch_vec (vmain, u, label_vec);
4889 gsi_insert_after (&switch_si, stmt, GSI_SAME_STMT);
4890 gsi_remove (&switch_si, true);
4891 VEC_free (tree, heap, label_vec);
4892
4893 si = gsi_start_bb (default_bb);
4894 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
4895 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
4896
4897 if (exit_reachable)
4898 {
4899 tree bfn_decl;
4900
4901 /* Code to get the next section goes in L1_BB. */
4902 si = gsi_last_bb (l1_bb);
4903 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CONTINUE);
4904
4905 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
4906 stmt = gimple_build_call (bfn_decl, 0);
4907 gimple_call_set_lhs (stmt, vnext);
4908 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
4909 gsi_remove (&si, true);
4910
4911 single_succ_edge (l1_bb)->flags = EDGE_FALLTHRU;
4912 }
4913
4914 /* Cleanup function replaces GIMPLE_OMP_RETURN in EXIT_BB. */
4915 si = gsi_last_bb (l2_bb);
4916 if (gimple_omp_return_nowait_p (gsi_stmt (si)))
4917 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_NOWAIT);
4918 else
4919 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END);
4920 stmt = gimple_build_call (t, 0);
4921 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
4922 gsi_remove (&si, true);
4923
4924 set_immediate_dominator (CDI_DOMINATORS, default_bb, l0_bb);
4925 }
4926
4927
4928 /* Expand code for an OpenMP single directive. We've already expanded
4929 much of the code, here we simply place the GOMP_barrier call. */
4930
4931 static void
4932 expand_omp_single (struct omp_region *region)
4933 {
4934 basic_block entry_bb, exit_bb;
4935 gimple_stmt_iterator si;
4936 bool need_barrier = false;
4937
4938 entry_bb = region->entry;
4939 exit_bb = region->exit;
4940
4941 si = gsi_last_bb (entry_bb);
4942 /* The terminal barrier at the end of a GOMP_single_copy sequence cannot
4943 be removed. We need to ensure that the thread that entered the single
4944 does not exit before the data is copied out by the other threads. */
4945 if (find_omp_clause (gimple_omp_single_clauses (gsi_stmt (si)),
4946 OMP_CLAUSE_COPYPRIVATE))
4947 need_barrier = true;
4948 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE);
4949 gsi_remove (&si, true);
4950 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
4951
4952 si = gsi_last_bb (exit_bb);
4953 if (!gimple_omp_return_nowait_p (gsi_stmt (si)) || need_barrier)
4954 force_gimple_operand_gsi (&si, build_omp_barrier (), false, NULL_TREE,
4955 false, GSI_SAME_STMT);
4956 gsi_remove (&si, true);
4957 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
4958 }
4959
4960
4961 /* Generic expansion for OpenMP synchronization directives: master,
4962 ordered and critical. All we need to do here is remove the entry
4963 and exit markers for REGION. */
4964
4965 static void
4966 expand_omp_synch (struct omp_region *region)
4967 {
4968 basic_block entry_bb, exit_bb;
4969 gimple_stmt_iterator si;
4970
4971 entry_bb = region->entry;
4972 exit_bb = region->exit;
4973
4974 si = gsi_last_bb (entry_bb);
4975 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE
4976 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_MASTER
4977 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ORDERED
4978 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CRITICAL);
4979 gsi_remove (&si, true);
4980 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
4981
4982 if (exit_bb)
4983 {
4984 si = gsi_last_bb (exit_bb);
4985 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
4986 gsi_remove (&si, true);
4987 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
4988 }
4989 }
4990
4991 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
4992 operation as a normal volatile load. */
4993
4994 static bool
4995 expand_omp_atomic_load (basic_block load_bb, tree addr,
4996 tree loaded_val, int index)
4997 {
4998 enum built_in_function tmpbase;
4999 gimple_stmt_iterator gsi;
5000 basic_block store_bb;
5001 location_t loc;
5002 gimple stmt;
5003 tree decl, call, type, itype;
5004
5005 gsi = gsi_last_bb (load_bb);
5006 stmt = gsi_stmt (gsi);
5007 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
5008 loc = gimple_location (stmt);
5009
5010 /* ??? If the target does not implement atomic_load_optab[mode], and mode
5011 is smaller than word size, then expand_atomic_load assumes that the load
5012 is atomic. We could avoid the builtin entirely in this case. */
5013
5014 tmpbase = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
5015 decl = builtin_decl_explicit (tmpbase);
5016 if (decl == NULL_TREE)
5017 return false;
5018
5019 type = TREE_TYPE (loaded_val);
5020 itype = TREE_TYPE (TREE_TYPE (decl));
5021
5022 call = build_call_expr_loc (loc, decl, 2, addr,
5023 build_int_cst (NULL, MEMMODEL_RELAXED));
5024 if (!useless_type_conversion_p (type, itype))
5025 call = fold_build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
5026 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
5027
5028 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
5029 gsi_remove (&gsi, true);
5030
5031 store_bb = single_succ (load_bb);
5032 gsi = gsi_last_bb (store_bb);
5033 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
5034 gsi_remove (&gsi, true);
5035
5036 if (gimple_in_ssa_p (cfun))
5037 update_ssa (TODO_update_ssa_no_phi);
5038
5039 return true;
5040 }
5041
5042 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
5043 operation as a normal volatile store. */
5044
5045 static bool
5046 expand_omp_atomic_store (basic_block load_bb, tree addr,
5047 tree loaded_val, tree stored_val, int index)
5048 {
5049 enum built_in_function tmpbase;
5050 gimple_stmt_iterator gsi;
5051 basic_block store_bb = single_succ (load_bb);
5052 location_t loc;
5053 gimple stmt;
5054 tree decl, call, type, itype;
5055 enum machine_mode imode;
5056 bool exchange;
5057
5058 gsi = gsi_last_bb (load_bb);
5059 stmt = gsi_stmt (gsi);
5060 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
5061
5062 /* If the load value is needed, then this isn't a store but an exchange. */
5063 exchange = gimple_omp_atomic_need_value_p (stmt);
5064
5065 gsi = gsi_last_bb (store_bb);
5066 stmt = gsi_stmt (gsi);
5067 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE);
5068 loc = gimple_location (stmt);
5069
5070 /* ??? If the target does not implement atomic_store_optab[mode], and mode
5071 is smaller than word size, then expand_atomic_store assumes that the store
5072 is atomic. We could avoid the builtin entirely in this case. */
5073
5074 tmpbase = (exchange ? BUILT_IN_ATOMIC_EXCHANGE_N : BUILT_IN_ATOMIC_STORE_N);
5075 tmpbase = (enum built_in_function) ((int) tmpbase + index + 1);
5076 decl = builtin_decl_explicit (tmpbase);
5077 if (decl == NULL_TREE)
5078 return false;
5079
5080 type = TREE_TYPE (stored_val);
5081
5082 /* Dig out the type of the function's second argument. */
5083 itype = TREE_TYPE (decl);
5084 itype = TYPE_ARG_TYPES (itype);
5085 itype = TREE_CHAIN (itype);
5086 itype = TREE_VALUE (itype);
5087 imode = TYPE_MODE (itype);
5088
5089 if (exchange && !can_atomic_exchange_p (imode, true))
5090 return false;
5091
5092 if (!useless_type_conversion_p (itype, type))
5093 stored_val = fold_build1_loc (loc, VIEW_CONVERT_EXPR, itype, stored_val);
5094 call = build_call_expr_loc (loc, decl, 3, addr, stored_val,
5095 build_int_cst (NULL, MEMMODEL_RELAXED));
5096 if (exchange)
5097 {
5098 if (!useless_type_conversion_p (type, itype))
5099 call = build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
5100 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
5101 }
5102
5103 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
5104 gsi_remove (&gsi, true);
5105
5106 /* Remove the GIMPLE_OMP_ATOMIC_LOAD that we verified above. */
5107 gsi = gsi_last_bb (load_bb);
5108 gsi_remove (&gsi, true);
5109
5110 if (gimple_in_ssa_p (cfun))
5111 update_ssa (TODO_update_ssa_no_phi);
5112
5113 return true;
5114 }
5115
5116 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
5117 operation as a __atomic_fetch_op builtin. INDEX is log2 of the
5118 size of the data type, and thus usable to find the index of the builtin
5119 decl. Returns false if the expression is not of the proper form. */
5120
5121 static bool
5122 expand_omp_atomic_fetch_op (basic_block load_bb,
5123 tree addr, tree loaded_val,
5124 tree stored_val, int index)
5125 {
5126 enum built_in_function oldbase, newbase, tmpbase;
5127 tree decl, itype, call;
5128 tree lhs, rhs;
5129 basic_block store_bb = single_succ (load_bb);
5130 gimple_stmt_iterator gsi;
5131 gimple stmt;
5132 location_t loc;
5133 enum tree_code code;
5134 bool need_old, need_new;
5135 enum machine_mode imode;
5136
5137 /* We expect to find the following sequences:
5138
5139 load_bb:
5140 GIMPLE_OMP_ATOMIC_LOAD (tmp, mem)
5141
5142 store_bb:
5143 val = tmp OP something; (or: something OP tmp)
5144 GIMPLE_OMP_STORE (val)
5145
5146 ???FIXME: Allow a more flexible sequence.
5147 Perhaps use data flow to pick the statements.
5148
5149 */
5150
5151 gsi = gsi_after_labels (store_bb);
5152 stmt = gsi_stmt (gsi);
5153 loc = gimple_location (stmt);
5154 if (!is_gimple_assign (stmt))
5155 return false;
5156 gsi_next (&gsi);
5157 if (gimple_code (gsi_stmt (gsi)) != GIMPLE_OMP_ATOMIC_STORE)
5158 return false;
5159 need_new = gimple_omp_atomic_need_value_p (gsi_stmt (gsi));
5160 need_old = gimple_omp_atomic_need_value_p (last_stmt (load_bb));
5161 gcc_checking_assert (!need_old || !need_new);
5162
5163 if (!operand_equal_p (gimple_assign_lhs (stmt), stored_val, 0))
5164 return false;
5165
5166 /* Check for one of the supported fetch-op operations. */
5167 code = gimple_assign_rhs_code (stmt);
5168 switch (code)
5169 {
5170 case PLUS_EXPR:
5171 case POINTER_PLUS_EXPR:
5172 oldbase = BUILT_IN_ATOMIC_FETCH_ADD_N;
5173 newbase = BUILT_IN_ATOMIC_ADD_FETCH_N;
5174 break;
5175 case MINUS_EXPR:
5176 oldbase = BUILT_IN_ATOMIC_FETCH_SUB_N;
5177 newbase = BUILT_IN_ATOMIC_SUB_FETCH_N;
5178 break;
5179 case BIT_AND_EXPR:
5180 oldbase = BUILT_IN_ATOMIC_FETCH_AND_N;
5181 newbase = BUILT_IN_ATOMIC_AND_FETCH_N;
5182 break;
5183 case BIT_IOR_EXPR:
5184 oldbase = BUILT_IN_ATOMIC_FETCH_OR_N;
5185 newbase = BUILT_IN_ATOMIC_OR_FETCH_N;
5186 break;
5187 case BIT_XOR_EXPR:
5188 oldbase = BUILT_IN_ATOMIC_FETCH_XOR_N;
5189 newbase = BUILT_IN_ATOMIC_XOR_FETCH_N;
5190 break;
5191 default:
5192 return false;
5193 }
5194
5195 /* Make sure the expression is of the proper form. */
5196 if (operand_equal_p (gimple_assign_rhs1 (stmt), loaded_val, 0))
5197 rhs = gimple_assign_rhs2 (stmt);
5198 else if (commutative_tree_code (gimple_assign_rhs_code (stmt))
5199 && operand_equal_p (gimple_assign_rhs2 (stmt), loaded_val, 0))
5200 rhs = gimple_assign_rhs1 (stmt);
5201 else
5202 return false;
5203
5204 tmpbase = ((enum built_in_function)
5205 ((need_new ? newbase : oldbase) + index + 1));
5206 decl = builtin_decl_explicit (tmpbase);
5207 if (decl == NULL_TREE)
5208 return false;
5209 itype = TREE_TYPE (TREE_TYPE (decl));
5210 imode = TYPE_MODE (itype);
5211
5212 /* We could test all of the various optabs involved, but the fact of the
5213 matter is that (with the exception of i486 vs i586 and xadd) all targets
5214 that support any atomic operaton optab also implements compare-and-swap.
5215 Let optabs.c take care of expanding any compare-and-swap loop. */
5216 if (!can_compare_and_swap_p (imode, true))
5217 return false;
5218
5219 gsi = gsi_last_bb (load_bb);
5220 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_LOAD);
5221
5222 /* OpenMP does not imply any barrier-like semantics on its atomic ops.
5223 It only requires that the operation happen atomically. Thus we can
5224 use the RELAXED memory model. */
5225 call = build_call_expr_loc (loc, decl, 3, addr,
5226 fold_convert_loc (loc, itype, rhs),
5227 build_int_cst (NULL, MEMMODEL_RELAXED));
5228
5229 if (need_old || need_new)
5230 {
5231 lhs = need_old ? loaded_val : stored_val;
5232 call = fold_convert_loc (loc, TREE_TYPE (lhs), call);
5233 call = build2_loc (loc, MODIFY_EXPR, void_type_node, lhs, call);
5234 }
5235 else
5236 call = fold_convert_loc (loc, void_type_node, call);
5237 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
5238 gsi_remove (&gsi, true);
5239
5240 gsi = gsi_last_bb (store_bb);
5241 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
5242 gsi_remove (&gsi, true);
5243 gsi = gsi_last_bb (store_bb);
5244 gsi_remove (&gsi, true);
5245
5246 if (gimple_in_ssa_p (cfun))
5247 update_ssa (TODO_update_ssa_no_phi);
5248
5249 return true;
5250 }
5251
5252 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
5253
5254 oldval = *addr;
5255 repeat:
5256 newval = rhs; // with oldval replacing *addr in rhs
5257 oldval = __sync_val_compare_and_swap (addr, oldval, newval);
5258 if (oldval != newval)
5259 goto repeat;
5260
5261 INDEX is log2 of the size of the data type, and thus usable to find the
5262 index of the builtin decl. */
5263
5264 static bool
5265 expand_omp_atomic_pipeline (basic_block load_bb, basic_block store_bb,
5266 tree addr, tree loaded_val, tree stored_val,
5267 int index)
5268 {
5269 tree loadedi, storedi, initial, new_storedi, old_vali;
5270 tree type, itype, cmpxchg, iaddr;
5271 gimple_stmt_iterator si;
5272 basic_block loop_header = single_succ (load_bb);
5273 gimple phi, stmt;
5274 edge e;
5275 enum built_in_function fncode;
5276
5277 /* ??? We need a non-pointer interface to __atomic_compare_exchange in
5278 order to use the RELAXED memory model effectively. */
5279 fncode = (enum built_in_function)((int)BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_N
5280 + index + 1);
5281 cmpxchg = builtin_decl_explicit (fncode);
5282 if (cmpxchg == NULL_TREE)
5283 return false;
5284 type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
5285 itype = TREE_TYPE (TREE_TYPE (cmpxchg));
5286
5287 if (!can_compare_and_swap_p (TYPE_MODE (itype), true))
5288 return false;
5289
5290 /* Load the initial value, replacing the GIMPLE_OMP_ATOMIC_LOAD. */
5291 si = gsi_last_bb (load_bb);
5292 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
5293
5294 /* For floating-point values, we'll need to view-convert them to integers
5295 so that we can perform the atomic compare and swap. Simplify the
5296 following code by always setting up the "i"ntegral variables. */
5297 if (!INTEGRAL_TYPE_P (type) && !POINTER_TYPE_P (type))
5298 {
5299 tree iaddr_val;
5300
5301 iaddr = make_rename_temp (build_pointer_type_for_mode (itype, ptr_mode,
5302 true), NULL);
5303 iaddr_val
5304 = force_gimple_operand_gsi (&si,
5305 fold_convert (TREE_TYPE (iaddr), addr),
5306 false, NULL_TREE, true, GSI_SAME_STMT);
5307 stmt = gimple_build_assign (iaddr, iaddr_val);
5308 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
5309 loadedi = create_tmp_var (itype, NULL);
5310 if (gimple_in_ssa_p (cfun))
5311 {
5312 add_referenced_var (iaddr);
5313 add_referenced_var (loadedi);
5314 loadedi = make_ssa_name (loadedi, NULL);
5315 }
5316 }
5317 else
5318 {
5319 iaddr = addr;
5320 loadedi = loaded_val;
5321 }
5322
5323 initial
5324 = force_gimple_operand_gsi (&si,
5325 build2 (MEM_REF, TREE_TYPE (TREE_TYPE (iaddr)),
5326 iaddr,
5327 build_int_cst (TREE_TYPE (iaddr), 0)),
5328 true, NULL_TREE, true, GSI_SAME_STMT);
5329
5330 /* Move the value to the LOADEDI temporary. */
5331 if (gimple_in_ssa_p (cfun))
5332 {
5333 gcc_assert (gimple_seq_empty_p (phi_nodes (loop_header)));
5334 phi = create_phi_node (loadedi, loop_header);
5335 SSA_NAME_DEF_STMT (loadedi) = phi;
5336 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, single_succ_edge (load_bb)),
5337 initial);
5338 }
5339 else
5340 gsi_insert_before (&si,
5341 gimple_build_assign (loadedi, initial),
5342 GSI_SAME_STMT);
5343 if (loadedi != loaded_val)
5344 {
5345 gimple_stmt_iterator gsi2;
5346 tree x;
5347
5348 x = build1 (VIEW_CONVERT_EXPR, type, loadedi);
5349 gsi2 = gsi_start_bb (loop_header);
5350 if (gimple_in_ssa_p (cfun))
5351 {
5352 gimple stmt;
5353 x = force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
5354 true, GSI_SAME_STMT);
5355 stmt = gimple_build_assign (loaded_val, x);
5356 gsi_insert_before (&gsi2, stmt, GSI_SAME_STMT);
5357 }
5358 else
5359 {
5360 x = build2 (MODIFY_EXPR, TREE_TYPE (loaded_val), loaded_val, x);
5361 force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
5362 true, GSI_SAME_STMT);
5363 }
5364 }
5365 gsi_remove (&si, true);
5366
5367 si = gsi_last_bb (store_bb);
5368 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
5369
5370 if (iaddr == addr)
5371 storedi = stored_val;
5372 else
5373 storedi =
5374 force_gimple_operand_gsi (&si,
5375 build1 (VIEW_CONVERT_EXPR, itype,
5376 stored_val), true, NULL_TREE, true,
5377 GSI_SAME_STMT);
5378
5379 /* Build the compare&swap statement. */
5380 new_storedi = build_call_expr (cmpxchg, 3, iaddr, loadedi, storedi);
5381 new_storedi = force_gimple_operand_gsi (&si,
5382 fold_convert (TREE_TYPE (loadedi),
5383 new_storedi),
5384 true, NULL_TREE,
5385 true, GSI_SAME_STMT);
5386
5387 if (gimple_in_ssa_p (cfun))
5388 old_vali = loadedi;
5389 else
5390 {
5391 old_vali = create_tmp_var (TREE_TYPE (loadedi), NULL);
5392 if (gimple_in_ssa_p (cfun))
5393 add_referenced_var (old_vali);
5394 stmt = gimple_build_assign (old_vali, loadedi);
5395 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
5396
5397 stmt = gimple_build_assign (loadedi, new_storedi);
5398 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
5399 }
5400
5401 /* Note that we always perform the comparison as an integer, even for
5402 floating point. This allows the atomic operation to properly
5403 succeed even with NaNs and -0.0. */
5404 stmt = gimple_build_cond_empty
5405 (build2 (NE_EXPR, boolean_type_node,
5406 new_storedi, old_vali));
5407 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
5408
5409 /* Update cfg. */
5410 e = single_succ_edge (store_bb);
5411 e->flags &= ~EDGE_FALLTHRU;
5412 e->flags |= EDGE_FALSE_VALUE;
5413
5414 e = make_edge (store_bb, loop_header, EDGE_TRUE_VALUE);
5415
5416 /* Copy the new value to loadedi (we already did that before the condition
5417 if we are not in SSA). */
5418 if (gimple_in_ssa_p (cfun))
5419 {
5420 phi = gimple_seq_first_stmt (phi_nodes (loop_header));
5421 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, e), new_storedi);
5422 }
5423
5424 /* Remove GIMPLE_OMP_ATOMIC_STORE. */
5425 gsi_remove (&si, true);
5426
5427 if (gimple_in_ssa_p (cfun))
5428 update_ssa (TODO_update_ssa_no_phi);
5429
5430 return true;
5431 }
5432
5433 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
5434
5435 GOMP_atomic_start ();
5436 *addr = rhs;
5437 GOMP_atomic_end ();
5438
5439 The result is not globally atomic, but works so long as all parallel
5440 references are within #pragma omp atomic directives. According to
5441 responses received from omp@openmp.org, appears to be within spec.
5442 Which makes sense, since that's how several other compilers handle
5443 this situation as well.
5444 LOADED_VAL and ADDR are the operands of GIMPLE_OMP_ATOMIC_LOAD we're
5445 expanding. STORED_VAL is the operand of the matching
5446 GIMPLE_OMP_ATOMIC_STORE.
5447
5448 We replace
5449 GIMPLE_OMP_ATOMIC_LOAD (loaded_val, addr) with
5450 loaded_val = *addr;
5451
5452 and replace
5453 GIMPLE_OMP_ATOMIC_STORE (stored_val) with
5454 *addr = stored_val;
5455 */
5456
5457 static bool
5458 expand_omp_atomic_mutex (basic_block load_bb, basic_block store_bb,
5459 tree addr, tree loaded_val, tree stored_val)
5460 {
5461 gimple_stmt_iterator si;
5462 gimple stmt;
5463 tree t;
5464
5465 si = gsi_last_bb (load_bb);
5466 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
5467
5468 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START);
5469 t = build_call_expr (t, 0);
5470 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
5471
5472 stmt = gimple_build_assign (loaded_val, build_simple_mem_ref (addr));
5473 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
5474 gsi_remove (&si, true);
5475
5476 si = gsi_last_bb (store_bb);
5477 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
5478
5479 stmt = gimple_build_assign (build_simple_mem_ref (unshare_expr (addr)),
5480 stored_val);
5481 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
5482
5483 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END);
5484 t = build_call_expr (t, 0);
5485 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
5486 gsi_remove (&si, true);
5487
5488 if (gimple_in_ssa_p (cfun))
5489 update_ssa (TODO_update_ssa_no_phi);
5490 return true;
5491 }
5492
5493 /* Expand an GIMPLE_OMP_ATOMIC statement. We try to expand
5494 using expand_omp_atomic_fetch_op. If it failed, we try to
5495 call expand_omp_atomic_pipeline, and if it fails too, the
5496 ultimate fallback is wrapping the operation in a mutex
5497 (expand_omp_atomic_mutex). REGION is the atomic region built
5498 by build_omp_regions_1(). */
5499
5500 static void
5501 expand_omp_atomic (struct omp_region *region)
5502 {
5503 basic_block load_bb = region->entry, store_bb = region->exit;
5504 gimple load = last_stmt (load_bb), store = last_stmt (store_bb);
5505 tree loaded_val = gimple_omp_atomic_load_lhs (load);
5506 tree addr = gimple_omp_atomic_load_rhs (load);
5507 tree stored_val = gimple_omp_atomic_store_val (store);
5508 tree type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
5509 HOST_WIDE_INT index;
5510
5511 /* Make sure the type is one of the supported sizes. */
5512 index = tree_low_cst (TYPE_SIZE_UNIT (type), 1);
5513 index = exact_log2 (index);
5514 if (index >= 0 && index <= 4)
5515 {
5516 unsigned int align = TYPE_ALIGN_UNIT (type);
5517
5518 /* __sync builtins require strict data alignment. */
5519 if (exact_log2 (align) >= index)
5520 {
5521 /* Atomic load. */
5522 if (loaded_val == stored_val
5523 && (GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
5524 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
5525 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
5526 && expand_omp_atomic_load (load_bb, addr, loaded_val, index))
5527 return;
5528
5529 /* Atomic store. */
5530 if ((GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
5531 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
5532 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
5533 && store_bb == single_succ (load_bb)
5534 && first_stmt (store_bb) == store
5535 && expand_omp_atomic_store (load_bb, addr, loaded_val,
5536 stored_val, index))
5537 return;
5538
5539 /* When possible, use specialized atomic update functions. */
5540 if ((INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type))
5541 && store_bb == single_succ (load_bb)
5542 && expand_omp_atomic_fetch_op (load_bb, addr,
5543 loaded_val, stored_val, index))
5544 return;
5545
5546 /* If we don't have specialized __sync builtins, try and implement
5547 as a compare and swap loop. */
5548 if (expand_omp_atomic_pipeline (load_bb, store_bb, addr,
5549 loaded_val, stored_val, index))
5550 return;
5551 }
5552 }
5553
5554 /* The ultimate fallback is wrapping the operation in a mutex. */
5555 expand_omp_atomic_mutex (load_bb, store_bb, addr, loaded_val, stored_val);
5556 }
5557
5558
5559 /* Expand the parallel region tree rooted at REGION. Expansion
5560 proceeds in depth-first order. Innermost regions are expanded
5561 first. This way, parallel regions that require a new function to
5562 be created (e.g., GIMPLE_OMP_PARALLEL) can be expanded without having any
5563 internal dependencies in their body. */
5564
5565 static void
5566 expand_omp (struct omp_region *region)
5567 {
5568 while (region)
5569 {
5570 location_t saved_location;
5571
5572 /* First, determine whether this is a combined parallel+workshare
5573 region. */
5574 if (region->type == GIMPLE_OMP_PARALLEL)
5575 determine_parallel_type (region);
5576
5577 if (region->inner)
5578 expand_omp (region->inner);
5579
5580 saved_location = input_location;
5581 if (gimple_has_location (last_stmt (region->entry)))
5582 input_location = gimple_location (last_stmt (region->entry));
5583
5584 switch (region->type)
5585 {
5586 case GIMPLE_OMP_PARALLEL:
5587 case GIMPLE_OMP_TASK:
5588 expand_omp_taskreg (region);
5589 break;
5590
5591 case GIMPLE_OMP_FOR:
5592 expand_omp_for (region);
5593 break;
5594
5595 case GIMPLE_OMP_SECTIONS:
5596 expand_omp_sections (region);
5597 break;
5598
5599 case GIMPLE_OMP_SECTION:
5600 /* Individual omp sections are handled together with their
5601 parent GIMPLE_OMP_SECTIONS region. */
5602 break;
5603
5604 case GIMPLE_OMP_SINGLE:
5605 expand_omp_single (region);
5606 break;
5607
5608 case GIMPLE_OMP_MASTER:
5609 case GIMPLE_OMP_ORDERED:
5610 case GIMPLE_OMP_CRITICAL:
5611 expand_omp_synch (region);
5612 break;
5613
5614 case GIMPLE_OMP_ATOMIC_LOAD:
5615 expand_omp_atomic (region);
5616 break;
5617
5618 default:
5619 gcc_unreachable ();
5620 }
5621
5622 input_location = saved_location;
5623 region = region->next;
5624 }
5625 }
5626
5627
5628 /* Helper for build_omp_regions. Scan the dominator tree starting at
5629 block BB. PARENT is the region that contains BB. If SINGLE_TREE is
5630 true, the function ends once a single tree is built (otherwise, whole
5631 forest of OMP constructs may be built). */
5632
5633 static void
5634 build_omp_regions_1 (basic_block bb, struct omp_region *parent,
5635 bool single_tree)
5636 {
5637 gimple_stmt_iterator gsi;
5638 gimple stmt;
5639 basic_block son;
5640
5641 gsi = gsi_last_bb (bb);
5642 if (!gsi_end_p (gsi) && is_gimple_omp (gsi_stmt (gsi)))
5643 {
5644 struct omp_region *region;
5645 enum gimple_code code;
5646
5647 stmt = gsi_stmt (gsi);
5648 code = gimple_code (stmt);
5649 if (code == GIMPLE_OMP_RETURN)
5650 {
5651 /* STMT is the return point out of region PARENT. Mark it
5652 as the exit point and make PARENT the immediately
5653 enclosing region. */
5654 gcc_assert (parent);
5655 region = parent;
5656 region->exit = bb;
5657 parent = parent->outer;
5658 }
5659 else if (code == GIMPLE_OMP_ATOMIC_STORE)
5660 {
5661 /* GIMPLE_OMP_ATOMIC_STORE is analoguous to
5662 GIMPLE_OMP_RETURN, but matches with
5663 GIMPLE_OMP_ATOMIC_LOAD. */
5664 gcc_assert (parent);
5665 gcc_assert (parent->type == GIMPLE_OMP_ATOMIC_LOAD);
5666 region = parent;
5667 region->exit = bb;
5668 parent = parent->outer;
5669 }
5670
5671 else if (code == GIMPLE_OMP_CONTINUE)
5672 {
5673 gcc_assert (parent);
5674 parent->cont = bb;
5675 }
5676 else if (code == GIMPLE_OMP_SECTIONS_SWITCH)
5677 {
5678 /* GIMPLE_OMP_SECTIONS_SWITCH is part of
5679 GIMPLE_OMP_SECTIONS, and we do nothing for it. */
5680 ;
5681 }
5682 else
5683 {
5684 /* Otherwise, this directive becomes the parent for a new
5685 region. */
5686 region = new_omp_region (bb, code, parent);
5687 parent = region;
5688 }
5689 }
5690
5691 if (single_tree && !parent)
5692 return;
5693
5694 for (son = first_dom_son (CDI_DOMINATORS, bb);
5695 son;
5696 son = next_dom_son (CDI_DOMINATORS, son))
5697 build_omp_regions_1 (son, parent, single_tree);
5698 }
5699
5700 /* Builds the tree of OMP regions rooted at ROOT, storing it to
5701 root_omp_region. */
5702
5703 static void
5704 build_omp_regions_root (basic_block root)
5705 {
5706 gcc_assert (root_omp_region == NULL);
5707 build_omp_regions_1 (root, NULL, true);
5708 gcc_assert (root_omp_region != NULL);
5709 }
5710
5711 /* Expands omp construct (and its subconstructs) starting in HEAD. */
5712
5713 void
5714 omp_expand_local (basic_block head)
5715 {
5716 build_omp_regions_root (head);
5717 if (dump_file && (dump_flags & TDF_DETAILS))
5718 {
5719 fprintf (dump_file, "\nOMP region tree\n\n");
5720 dump_omp_region (dump_file, root_omp_region, 0);
5721 fprintf (dump_file, "\n");
5722 }
5723
5724 remove_exit_barriers (root_omp_region);
5725 expand_omp (root_omp_region);
5726
5727 free_omp_regions ();
5728 }
5729
5730 /* Scan the CFG and build a tree of OMP regions. Return the root of
5731 the OMP region tree. */
5732
5733 static void
5734 build_omp_regions (void)
5735 {
5736 gcc_assert (root_omp_region == NULL);
5737 calculate_dominance_info (CDI_DOMINATORS);
5738 build_omp_regions_1 (ENTRY_BLOCK_PTR, NULL, false);
5739 }
5740
5741 /* Main entry point for expanding OMP-GIMPLE into runtime calls. */
5742
5743 static unsigned int
5744 execute_expand_omp (void)
5745 {
5746 build_omp_regions ();
5747
5748 if (!root_omp_region)
5749 return 0;
5750
5751 if (dump_file)
5752 {
5753 fprintf (dump_file, "\nOMP region tree\n\n");
5754 dump_omp_region (dump_file, root_omp_region, 0);
5755 fprintf (dump_file, "\n");
5756 }
5757
5758 remove_exit_barriers (root_omp_region);
5759
5760 expand_omp (root_omp_region);
5761
5762 cleanup_tree_cfg ();
5763
5764 free_omp_regions ();
5765
5766 return 0;
5767 }
5768
5769 /* OMP expansion -- the default pass, run before creation of SSA form. */
5770
5771 static bool
5772 gate_expand_omp (void)
5773 {
5774 return (flag_openmp != 0 && !seen_error ());
5775 }
5776
5777 struct gimple_opt_pass pass_expand_omp =
5778 {
5779 {
5780 GIMPLE_PASS,
5781 "ompexp", /* name */
5782 gate_expand_omp, /* gate */
5783 execute_expand_omp, /* execute */
5784 NULL, /* sub */
5785 NULL, /* next */
5786 0, /* static_pass_number */
5787 TV_NONE, /* tv_id */
5788 PROP_gimple_any, /* properties_required */
5789 0, /* properties_provided */
5790 0, /* properties_destroyed */
5791 0, /* todo_flags_start */
5792 0 /* todo_flags_finish */
5793 }
5794 };
5795 \f
5796 /* Routines to lower OpenMP directives into OMP-GIMPLE. */
5797
5798 /* Lower the OpenMP sections directive in the current statement in GSI_P.
5799 CTX is the enclosing OMP context for the current statement. */
5800
5801 static void
5802 lower_omp_sections (gimple_stmt_iterator *gsi_p, omp_context *ctx)
5803 {
5804 tree block, control;
5805 gimple_stmt_iterator tgsi;
5806 gimple stmt, new_stmt, bind, t;
5807 gimple_seq ilist, dlist, olist, new_body;
5808 struct gimplify_ctx gctx;
5809
5810 stmt = gsi_stmt (*gsi_p);
5811
5812 push_gimplify_context (&gctx);
5813
5814 dlist = NULL;
5815 ilist = NULL;
5816 lower_rec_input_clauses (gimple_omp_sections_clauses (stmt),
5817 &ilist, &dlist, ctx);
5818
5819 new_body = gimple_omp_body (stmt);
5820 gimple_omp_set_body (stmt, NULL);
5821 tgsi = gsi_start (new_body);
5822 for (; !gsi_end_p (tgsi); gsi_next (&tgsi))
5823 {
5824 omp_context *sctx;
5825 gimple sec_start;
5826
5827 sec_start = gsi_stmt (tgsi);
5828 sctx = maybe_lookup_ctx (sec_start);
5829 gcc_assert (sctx);
5830
5831 lower_omp (gimple_omp_body_ptr (sec_start), sctx);
5832 gsi_insert_seq_after (&tgsi, gimple_omp_body (sec_start),
5833 GSI_CONTINUE_LINKING);
5834 gimple_omp_set_body (sec_start, NULL);
5835
5836 if (gsi_one_before_end_p (tgsi))
5837 {
5838 gimple_seq l = NULL;
5839 lower_lastprivate_clauses (gimple_omp_sections_clauses (stmt), NULL,
5840 &l, ctx);
5841 gsi_insert_seq_after (&tgsi, l, GSI_CONTINUE_LINKING);
5842 gimple_omp_section_set_last (sec_start);
5843 }
5844
5845 gsi_insert_after (&tgsi, gimple_build_omp_return (false),
5846 GSI_CONTINUE_LINKING);
5847 }
5848
5849 block = make_node (BLOCK);
5850 bind = gimple_build_bind (NULL, new_body, block);
5851
5852 olist = NULL;
5853 lower_reduction_clauses (gimple_omp_sections_clauses (stmt), &olist, ctx);
5854
5855 block = make_node (BLOCK);
5856 new_stmt = gimple_build_bind (NULL, NULL, block);
5857 gsi_replace (gsi_p, new_stmt, true);
5858
5859 pop_gimplify_context (new_stmt);
5860 gimple_bind_append_vars (new_stmt, ctx->block_vars);
5861 BLOCK_VARS (block) = gimple_bind_vars (bind);
5862 if (BLOCK_VARS (block))
5863 TREE_USED (block) = 1;
5864
5865 new_body = NULL;
5866 gimple_seq_add_seq (&new_body, ilist);
5867 gimple_seq_add_stmt (&new_body, stmt);
5868 gimple_seq_add_stmt (&new_body, gimple_build_omp_sections_switch ());
5869 gimple_seq_add_stmt (&new_body, bind);
5870
5871 control = create_tmp_var (unsigned_type_node, ".section");
5872 t = gimple_build_omp_continue (control, control);
5873 gimple_omp_sections_set_control (stmt, control);
5874 gimple_seq_add_stmt (&new_body, t);
5875
5876 gimple_seq_add_seq (&new_body, olist);
5877 gimple_seq_add_seq (&new_body, dlist);
5878
5879 new_body = maybe_catch_exception (new_body);
5880
5881 t = gimple_build_omp_return
5882 (!!find_omp_clause (gimple_omp_sections_clauses (stmt),
5883 OMP_CLAUSE_NOWAIT));
5884 gimple_seq_add_stmt (&new_body, t);
5885
5886 gimple_bind_set_body (new_stmt, new_body);
5887 }
5888
5889
5890 /* A subroutine of lower_omp_single. Expand the simple form of
5891 a GIMPLE_OMP_SINGLE, without a copyprivate clause:
5892
5893 if (GOMP_single_start ())
5894 BODY;
5895 [ GOMP_barrier (); ] -> unless 'nowait' is present.
5896
5897 FIXME. It may be better to delay expanding the logic of this until
5898 pass_expand_omp. The expanded logic may make the job more difficult
5899 to a synchronization analysis pass. */
5900
5901 static void
5902 lower_omp_single_simple (gimple single_stmt, gimple_seq *pre_p)
5903 {
5904 location_t loc = gimple_location (single_stmt);
5905 tree tlabel = create_artificial_label (loc);
5906 tree flabel = create_artificial_label (loc);
5907 gimple call, cond;
5908 tree lhs, decl;
5909
5910 decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_START);
5911 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (decl)), NULL);
5912 call = gimple_build_call (decl, 0);
5913 gimple_call_set_lhs (call, lhs);
5914 gimple_seq_add_stmt (pre_p, call);
5915
5916 cond = gimple_build_cond (EQ_EXPR, lhs,
5917 fold_convert_loc (loc, TREE_TYPE (lhs),
5918 boolean_true_node),
5919 tlabel, flabel);
5920 gimple_seq_add_stmt (pre_p, cond);
5921 gimple_seq_add_stmt (pre_p, gimple_build_label (tlabel));
5922 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
5923 gimple_seq_add_stmt (pre_p, gimple_build_label (flabel));
5924 }
5925
5926
5927 /* A subroutine of lower_omp_single. Expand the simple form of
5928 a GIMPLE_OMP_SINGLE, with a copyprivate clause:
5929
5930 #pragma omp single copyprivate (a, b, c)
5931
5932 Create a new structure to hold copies of 'a', 'b' and 'c' and emit:
5933
5934 {
5935 if ((copyout_p = GOMP_single_copy_start ()) == NULL)
5936 {
5937 BODY;
5938 copyout.a = a;
5939 copyout.b = b;
5940 copyout.c = c;
5941 GOMP_single_copy_end (&copyout);
5942 }
5943 else
5944 {
5945 a = copyout_p->a;
5946 b = copyout_p->b;
5947 c = copyout_p->c;
5948 }
5949 GOMP_barrier ();
5950 }
5951
5952 FIXME. It may be better to delay expanding the logic of this until
5953 pass_expand_omp. The expanded logic may make the job more difficult
5954 to a synchronization analysis pass. */
5955
5956 static void
5957 lower_omp_single_copy (gimple single_stmt, gimple_seq *pre_p, omp_context *ctx)
5958 {
5959 tree ptr_type, t, l0, l1, l2, bfn_decl;
5960 gimple_seq copyin_seq;
5961 location_t loc = gimple_location (single_stmt);
5962
5963 ctx->sender_decl = create_tmp_var (ctx->record_type, ".omp_copy_o");
5964
5965 ptr_type = build_pointer_type (ctx->record_type);
5966 ctx->receiver_decl = create_tmp_var (ptr_type, ".omp_copy_i");
5967
5968 l0 = create_artificial_label (loc);
5969 l1 = create_artificial_label (loc);
5970 l2 = create_artificial_label (loc);
5971
5972 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_START);
5973 t = build_call_expr_loc (loc, bfn_decl, 0);
5974 t = fold_convert_loc (loc, ptr_type, t);
5975 gimplify_assign (ctx->receiver_decl, t, pre_p);
5976
5977 t = build2 (EQ_EXPR, boolean_type_node, ctx->receiver_decl,
5978 build_int_cst (ptr_type, 0));
5979 t = build3 (COND_EXPR, void_type_node, t,
5980 build_and_jump (&l0), build_and_jump (&l1));
5981 gimplify_and_add (t, pre_p);
5982
5983 gimple_seq_add_stmt (pre_p, gimple_build_label (l0));
5984
5985 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
5986
5987 copyin_seq = NULL;
5988 lower_copyprivate_clauses (gimple_omp_single_clauses (single_stmt), pre_p,
5989 &copyin_seq, ctx);
5990
5991 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
5992 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_END);
5993 t = build_call_expr_loc (loc, bfn_decl, 1, t);
5994 gimplify_and_add (t, pre_p);
5995
5996 t = build_and_jump (&l2);
5997 gimplify_and_add (t, pre_p);
5998
5999 gimple_seq_add_stmt (pre_p, gimple_build_label (l1));
6000
6001 gimple_seq_add_seq (pre_p, copyin_seq);
6002
6003 gimple_seq_add_stmt (pre_p, gimple_build_label (l2));
6004 }
6005
6006
6007 /* Expand code for an OpenMP single directive. */
6008
6009 static void
6010 lower_omp_single (gimple_stmt_iterator *gsi_p, omp_context *ctx)
6011 {
6012 tree block;
6013 gimple t, bind, single_stmt = gsi_stmt (*gsi_p);
6014 gimple_seq bind_body, dlist;
6015 struct gimplify_ctx gctx;
6016
6017 push_gimplify_context (&gctx);
6018
6019 block = make_node (BLOCK);
6020 bind = gimple_build_bind (NULL, NULL, block);
6021 gsi_replace (gsi_p, bind, true);
6022 bind_body = NULL;
6023 dlist = NULL;
6024 lower_rec_input_clauses (gimple_omp_single_clauses (single_stmt),
6025 &bind_body, &dlist, ctx);
6026 lower_omp (gimple_omp_body_ptr (single_stmt), ctx);
6027
6028 gimple_seq_add_stmt (&bind_body, single_stmt);
6029
6030 if (ctx->record_type)
6031 lower_omp_single_copy (single_stmt, &bind_body, ctx);
6032 else
6033 lower_omp_single_simple (single_stmt, &bind_body);
6034
6035 gimple_omp_set_body (single_stmt, NULL);
6036
6037 gimple_seq_add_seq (&bind_body, dlist);
6038
6039 bind_body = maybe_catch_exception (bind_body);
6040
6041 t = gimple_build_omp_return
6042 (!!find_omp_clause (gimple_omp_single_clauses (single_stmt),
6043 OMP_CLAUSE_NOWAIT));
6044 gimple_seq_add_stmt (&bind_body, t);
6045 gimple_bind_set_body (bind, bind_body);
6046
6047 pop_gimplify_context (bind);
6048
6049 gimple_bind_append_vars (bind, ctx->block_vars);
6050 BLOCK_VARS (block) = ctx->block_vars;
6051 if (BLOCK_VARS (block))
6052 TREE_USED (block) = 1;
6053 }
6054
6055
6056 /* Expand code for an OpenMP master directive. */
6057
6058 static void
6059 lower_omp_master (gimple_stmt_iterator *gsi_p, omp_context *ctx)
6060 {
6061 tree block, lab = NULL, x, bfn_decl;
6062 gimple stmt = gsi_stmt (*gsi_p), bind;
6063 location_t loc = gimple_location (stmt);
6064 gimple_seq tseq;
6065 struct gimplify_ctx gctx;
6066
6067 push_gimplify_context (&gctx);
6068
6069 block = make_node (BLOCK);
6070 bind = gimple_build_bind (NULL, NULL, block);
6071 gsi_replace (gsi_p, bind, true);
6072 gimple_bind_add_stmt (bind, stmt);
6073
6074 bfn_decl = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
6075 x = build_call_expr_loc (loc, bfn_decl, 0);
6076 x = build2 (EQ_EXPR, boolean_type_node, x, integer_zero_node);
6077 x = build3 (COND_EXPR, void_type_node, x, NULL, build_and_jump (&lab));
6078 tseq = NULL;
6079 gimplify_and_add (x, &tseq);
6080 gimple_bind_add_seq (bind, tseq);
6081
6082 lower_omp (gimple_omp_body_ptr (stmt), ctx);
6083 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
6084 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
6085 gimple_omp_set_body (stmt, NULL);
6086
6087 gimple_bind_add_stmt (bind, gimple_build_label (lab));
6088
6089 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
6090
6091 pop_gimplify_context (bind);
6092
6093 gimple_bind_append_vars (bind, ctx->block_vars);
6094 BLOCK_VARS (block) = ctx->block_vars;
6095 }
6096
6097
6098 /* Expand code for an OpenMP ordered directive. */
6099
6100 static void
6101 lower_omp_ordered (gimple_stmt_iterator *gsi_p, omp_context *ctx)
6102 {
6103 tree block;
6104 gimple stmt = gsi_stmt (*gsi_p), bind, x;
6105 struct gimplify_ctx gctx;
6106
6107 push_gimplify_context (&gctx);
6108
6109 block = make_node (BLOCK);
6110 bind = gimple_build_bind (NULL, NULL, block);
6111 gsi_replace (gsi_p, bind, true);
6112 gimple_bind_add_stmt (bind, stmt);
6113
6114 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_START),
6115 0);
6116 gimple_bind_add_stmt (bind, x);
6117
6118 lower_omp (gimple_omp_body_ptr (stmt), ctx);
6119 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
6120 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
6121 gimple_omp_set_body (stmt, NULL);
6122
6123 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_END), 0);
6124 gimple_bind_add_stmt (bind, x);
6125
6126 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
6127
6128 pop_gimplify_context (bind);
6129
6130 gimple_bind_append_vars (bind, ctx->block_vars);
6131 BLOCK_VARS (block) = gimple_bind_vars (bind);
6132 }
6133
6134
6135 /* Gimplify a GIMPLE_OMP_CRITICAL statement. This is a relatively simple
6136 substitution of a couple of function calls. But in the NAMED case,
6137 requires that languages coordinate a symbol name. It is therefore
6138 best put here in common code. */
6139
6140 static GTY((param1_is (tree), param2_is (tree)))
6141 splay_tree critical_name_mutexes;
6142
6143 static void
6144 lower_omp_critical (gimple_stmt_iterator *gsi_p, omp_context *ctx)
6145 {
6146 tree block;
6147 tree name, lock, unlock;
6148 gimple stmt = gsi_stmt (*gsi_p), bind;
6149 location_t loc = gimple_location (stmt);
6150 gimple_seq tbody;
6151 struct gimplify_ctx gctx;
6152
6153 name = gimple_omp_critical_name (stmt);
6154 if (name)
6155 {
6156 tree decl;
6157 splay_tree_node n;
6158
6159 if (!critical_name_mutexes)
6160 critical_name_mutexes
6161 = splay_tree_new_ggc (splay_tree_compare_pointers,
6162 ggc_alloc_splay_tree_tree_node_tree_node_splay_tree_s,
6163 ggc_alloc_splay_tree_tree_node_tree_node_splay_tree_node_s);
6164
6165 n = splay_tree_lookup (critical_name_mutexes, (splay_tree_key) name);
6166 if (n == NULL)
6167 {
6168 char *new_str;
6169
6170 decl = create_tmp_var_raw (ptr_type_node, NULL);
6171
6172 new_str = ACONCAT ((".gomp_critical_user_",
6173 IDENTIFIER_POINTER (name), NULL));
6174 DECL_NAME (decl) = get_identifier (new_str);
6175 TREE_PUBLIC (decl) = 1;
6176 TREE_STATIC (decl) = 1;
6177 DECL_COMMON (decl) = 1;
6178 DECL_ARTIFICIAL (decl) = 1;
6179 DECL_IGNORED_P (decl) = 1;
6180 varpool_finalize_decl (decl);
6181
6182 splay_tree_insert (critical_name_mutexes, (splay_tree_key) name,
6183 (splay_tree_value) decl);
6184 }
6185 else
6186 decl = (tree) n->value;
6187
6188 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_START);
6189 lock = build_call_expr_loc (loc, lock, 1, build_fold_addr_expr_loc (loc, decl));
6190
6191 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_END);
6192 unlock = build_call_expr_loc (loc, unlock, 1,
6193 build_fold_addr_expr_loc (loc, decl));
6194 }
6195 else
6196 {
6197 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_START);
6198 lock = build_call_expr_loc (loc, lock, 0);
6199
6200 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_END);
6201 unlock = build_call_expr_loc (loc, unlock, 0);
6202 }
6203
6204 push_gimplify_context (&gctx);
6205
6206 block = make_node (BLOCK);
6207 bind = gimple_build_bind (NULL, NULL, block);
6208 gsi_replace (gsi_p, bind, true);
6209 gimple_bind_add_stmt (bind, stmt);
6210
6211 tbody = gimple_bind_body (bind);
6212 gimplify_and_add (lock, &tbody);
6213 gimple_bind_set_body (bind, tbody);
6214
6215 lower_omp (gimple_omp_body_ptr (stmt), ctx);
6216 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
6217 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
6218 gimple_omp_set_body (stmt, NULL);
6219
6220 tbody = gimple_bind_body (bind);
6221 gimplify_and_add (unlock, &tbody);
6222 gimple_bind_set_body (bind, tbody);
6223
6224 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
6225
6226 pop_gimplify_context (bind);
6227 gimple_bind_append_vars (bind, ctx->block_vars);
6228 BLOCK_VARS (block) = gimple_bind_vars (bind);
6229 }
6230
6231
6232 /* A subroutine of lower_omp_for. Generate code to emit the predicate
6233 for a lastprivate clause. Given a loop control predicate of (V
6234 cond N2), we gate the clause on (!(V cond N2)). The lowered form
6235 is appended to *DLIST, iterator initialization is appended to
6236 *BODY_P. */
6237
6238 static void
6239 lower_omp_for_lastprivate (struct omp_for_data *fd, gimple_seq *body_p,
6240 gimple_seq *dlist, struct omp_context *ctx)
6241 {
6242 tree clauses, cond, vinit;
6243 enum tree_code cond_code;
6244 gimple_seq stmts;
6245
6246 cond_code = fd->loop.cond_code;
6247 cond_code = cond_code == LT_EXPR ? GE_EXPR : LE_EXPR;
6248
6249 /* When possible, use a strict equality expression. This can let VRP
6250 type optimizations deduce the value and remove a copy. */
6251 if (host_integerp (fd->loop.step, 0))
6252 {
6253 HOST_WIDE_INT step = TREE_INT_CST_LOW (fd->loop.step);
6254 if (step == 1 || step == -1)
6255 cond_code = EQ_EXPR;
6256 }
6257
6258 cond = build2 (cond_code, boolean_type_node, fd->loop.v, fd->loop.n2);
6259
6260 clauses = gimple_omp_for_clauses (fd->for_stmt);
6261 stmts = NULL;
6262 lower_lastprivate_clauses (clauses, cond, &stmts, ctx);
6263 if (!gimple_seq_empty_p (stmts))
6264 {
6265 gimple_seq_add_seq (&stmts, *dlist);
6266 *dlist = stmts;
6267
6268 /* Optimize: v = 0; is usually cheaper than v = some_other_constant. */
6269 vinit = fd->loop.n1;
6270 if (cond_code == EQ_EXPR
6271 && host_integerp (fd->loop.n2, 0)
6272 && ! integer_zerop (fd->loop.n2))
6273 vinit = build_int_cst (TREE_TYPE (fd->loop.v), 0);
6274
6275 /* Initialize the iterator variable, so that threads that don't execute
6276 any iterations don't execute the lastprivate clauses by accident. */
6277 gimplify_assign (fd->loop.v, vinit, body_p);
6278 }
6279 }
6280
6281
6282 /* Lower code for an OpenMP loop directive. */
6283
6284 static void
6285 lower_omp_for (gimple_stmt_iterator *gsi_p, omp_context *ctx)
6286 {
6287 tree *rhs_p, block;
6288 struct omp_for_data fd;
6289 gimple stmt = gsi_stmt (*gsi_p), new_stmt;
6290 gimple_seq omp_for_body, body, dlist;
6291 size_t i;
6292 struct gimplify_ctx gctx;
6293
6294 push_gimplify_context (&gctx);
6295
6296 lower_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
6297 lower_omp (gimple_omp_body_ptr (stmt), ctx);
6298
6299 block = make_node (BLOCK);
6300 new_stmt = gimple_build_bind (NULL, NULL, block);
6301 /* Replace at gsi right away, so that 'stmt' is no member
6302 of a sequence anymore as we're going to add to to a different
6303 one below. */
6304 gsi_replace (gsi_p, new_stmt, true);
6305
6306 /* Move declaration of temporaries in the loop body before we make
6307 it go away. */
6308 omp_for_body = gimple_omp_body (stmt);
6309 if (!gimple_seq_empty_p (omp_for_body)
6310 && gimple_code (gimple_seq_first_stmt (omp_for_body)) == GIMPLE_BIND)
6311 {
6312 tree vars = gimple_bind_vars (gimple_seq_first_stmt (omp_for_body));
6313 gimple_bind_append_vars (new_stmt, vars);
6314 }
6315
6316 /* The pre-body and input clauses go before the lowered GIMPLE_OMP_FOR. */
6317 dlist = NULL;
6318 body = NULL;
6319 lower_rec_input_clauses (gimple_omp_for_clauses (stmt), &body, &dlist, ctx);
6320 gimple_seq_add_seq (&body, gimple_omp_for_pre_body (stmt));
6321
6322 /* Lower the header expressions. At this point, we can assume that
6323 the header is of the form:
6324
6325 #pragma omp for (V = VAL1; V {<|>|<=|>=} VAL2; V = V [+-] VAL3)
6326
6327 We just need to make sure that VAL1, VAL2 and VAL3 are lowered
6328 using the .omp_data_s mapping, if needed. */
6329 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
6330 {
6331 rhs_p = gimple_omp_for_initial_ptr (stmt, i);
6332 if (!is_gimple_min_invariant (*rhs_p))
6333 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
6334
6335 rhs_p = gimple_omp_for_final_ptr (stmt, i);
6336 if (!is_gimple_min_invariant (*rhs_p))
6337 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
6338
6339 rhs_p = &TREE_OPERAND (gimple_omp_for_incr (stmt, i), 1);
6340 if (!is_gimple_min_invariant (*rhs_p))
6341 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
6342 }
6343
6344 /* Once lowered, extract the bounds and clauses. */
6345 extract_omp_for_data (stmt, &fd, NULL);
6346
6347 lower_omp_for_lastprivate (&fd, &body, &dlist, ctx);
6348
6349 gimple_seq_add_stmt (&body, stmt);
6350 gimple_seq_add_seq (&body, gimple_omp_body (stmt));
6351
6352 gimple_seq_add_stmt (&body, gimple_build_omp_continue (fd.loop.v,
6353 fd.loop.v));
6354
6355 /* After the loop, add exit clauses. */
6356 lower_reduction_clauses (gimple_omp_for_clauses (stmt), &body, ctx);
6357 gimple_seq_add_seq (&body, dlist);
6358
6359 body = maybe_catch_exception (body);
6360
6361 /* Region exit marker goes at the end of the loop body. */
6362 gimple_seq_add_stmt (&body, gimple_build_omp_return (fd.have_nowait));
6363
6364 pop_gimplify_context (new_stmt);
6365
6366 gimple_bind_append_vars (new_stmt, ctx->block_vars);
6367 BLOCK_VARS (block) = gimple_bind_vars (new_stmt);
6368 if (BLOCK_VARS (block))
6369 TREE_USED (block) = 1;
6370
6371 gimple_bind_set_body (new_stmt, body);
6372 gimple_omp_set_body (stmt, NULL);
6373 gimple_omp_for_set_pre_body (stmt, NULL);
6374 }
6375
6376 /* Callback for walk_stmts. Check if the current statement only contains
6377 GIMPLE_OMP_FOR or GIMPLE_OMP_PARALLEL. */
6378
6379 static tree
6380 check_combined_parallel (gimple_stmt_iterator *gsi_p,
6381 bool *handled_ops_p,
6382 struct walk_stmt_info *wi)
6383 {
6384 int *info = (int *) wi->info;
6385 gimple stmt = gsi_stmt (*gsi_p);
6386
6387 *handled_ops_p = true;
6388 switch (gimple_code (stmt))
6389 {
6390 WALK_SUBSTMTS;
6391
6392 case GIMPLE_OMP_FOR:
6393 case GIMPLE_OMP_SECTIONS:
6394 *info = *info == 0 ? 1 : -1;
6395 break;
6396 default:
6397 *info = -1;
6398 break;
6399 }
6400 return NULL;
6401 }
6402
6403 struct omp_taskcopy_context
6404 {
6405 /* This field must be at the beginning, as we do "inheritance": Some
6406 callback functions for tree-inline.c (e.g., omp_copy_decl)
6407 receive a copy_body_data pointer that is up-casted to an
6408 omp_context pointer. */
6409 copy_body_data cb;
6410 omp_context *ctx;
6411 };
6412
6413 static tree
6414 task_copyfn_copy_decl (tree var, copy_body_data *cb)
6415 {
6416 struct omp_taskcopy_context *tcctx = (struct omp_taskcopy_context *) cb;
6417
6418 if (splay_tree_lookup (tcctx->ctx->sfield_map, (splay_tree_key) var))
6419 return create_tmp_var (TREE_TYPE (var), NULL);
6420
6421 return var;
6422 }
6423
6424 static tree
6425 task_copyfn_remap_type (struct omp_taskcopy_context *tcctx, tree orig_type)
6426 {
6427 tree name, new_fields = NULL, type, f;
6428
6429 type = lang_hooks.types.make_type (RECORD_TYPE);
6430 name = DECL_NAME (TYPE_NAME (orig_type));
6431 name = build_decl (gimple_location (tcctx->ctx->stmt),
6432 TYPE_DECL, name, type);
6433 TYPE_NAME (type) = name;
6434
6435 for (f = TYPE_FIELDS (orig_type); f ; f = TREE_CHAIN (f))
6436 {
6437 tree new_f = copy_node (f);
6438 DECL_CONTEXT (new_f) = type;
6439 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &tcctx->cb);
6440 TREE_CHAIN (new_f) = new_fields;
6441 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &tcctx->cb, NULL);
6442 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r, &tcctx->cb, NULL);
6443 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
6444 &tcctx->cb, NULL);
6445 new_fields = new_f;
6446 *pointer_map_insert (tcctx->cb.decl_map, f) = new_f;
6447 }
6448 TYPE_FIELDS (type) = nreverse (new_fields);
6449 layout_type (type);
6450 return type;
6451 }
6452
6453 /* Create task copyfn. */
6454
6455 static void
6456 create_task_copyfn (gimple task_stmt, omp_context *ctx)
6457 {
6458 struct function *child_cfun;
6459 tree child_fn, t, c, src, dst, f, sf, arg, sarg, decl;
6460 tree record_type, srecord_type, bind, list;
6461 bool record_needs_remap = false, srecord_needs_remap = false;
6462 splay_tree_node n;
6463 struct omp_taskcopy_context tcctx;
6464 struct gimplify_ctx gctx;
6465 location_t loc = gimple_location (task_stmt);
6466
6467 child_fn = gimple_omp_task_copy_fn (task_stmt);
6468 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
6469 gcc_assert (child_cfun->cfg == NULL);
6470 DECL_SAVED_TREE (child_fn) = alloc_stmt_list ();
6471
6472 /* Reset DECL_CONTEXT on function arguments. */
6473 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
6474 DECL_CONTEXT (t) = child_fn;
6475
6476 /* Populate the function. */
6477 push_gimplify_context (&gctx);
6478 current_function_decl = child_fn;
6479
6480 bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
6481 TREE_SIDE_EFFECTS (bind) = 1;
6482 list = NULL;
6483 DECL_SAVED_TREE (child_fn) = bind;
6484 DECL_SOURCE_LOCATION (child_fn) = gimple_location (task_stmt);
6485
6486 /* Remap src and dst argument types if needed. */
6487 record_type = ctx->record_type;
6488 srecord_type = ctx->srecord_type;
6489 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
6490 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
6491 {
6492 record_needs_remap = true;
6493 break;
6494 }
6495 for (f = TYPE_FIELDS (srecord_type); f ; f = DECL_CHAIN (f))
6496 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
6497 {
6498 srecord_needs_remap = true;
6499 break;
6500 }
6501
6502 if (record_needs_remap || srecord_needs_remap)
6503 {
6504 memset (&tcctx, '\0', sizeof (tcctx));
6505 tcctx.cb.src_fn = ctx->cb.src_fn;
6506 tcctx.cb.dst_fn = child_fn;
6507 tcctx.cb.src_node = cgraph_get_node (tcctx.cb.src_fn);
6508 gcc_checking_assert (tcctx.cb.src_node);
6509 tcctx.cb.dst_node = tcctx.cb.src_node;
6510 tcctx.cb.src_cfun = ctx->cb.src_cfun;
6511 tcctx.cb.copy_decl = task_copyfn_copy_decl;
6512 tcctx.cb.eh_lp_nr = 0;
6513 tcctx.cb.transform_call_graph_edges = CB_CGE_MOVE;
6514 tcctx.cb.decl_map = pointer_map_create ();
6515 tcctx.ctx = ctx;
6516
6517 if (record_needs_remap)
6518 record_type = task_copyfn_remap_type (&tcctx, record_type);
6519 if (srecord_needs_remap)
6520 srecord_type = task_copyfn_remap_type (&tcctx, srecord_type);
6521 }
6522 else
6523 tcctx.cb.decl_map = NULL;
6524
6525 push_cfun (child_cfun);
6526
6527 arg = DECL_ARGUMENTS (child_fn);
6528 TREE_TYPE (arg) = build_pointer_type (record_type);
6529 sarg = DECL_CHAIN (arg);
6530 TREE_TYPE (sarg) = build_pointer_type (srecord_type);
6531
6532 /* First pass: initialize temporaries used in record_type and srecord_type
6533 sizes and field offsets. */
6534 if (tcctx.cb.decl_map)
6535 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
6536 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
6537 {
6538 tree *p;
6539
6540 decl = OMP_CLAUSE_DECL (c);
6541 p = (tree *) pointer_map_contains (tcctx.cb.decl_map, decl);
6542 if (p == NULL)
6543 continue;
6544 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
6545 sf = (tree) n->value;
6546 sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
6547 src = build_simple_mem_ref_loc (loc, sarg);
6548 src = omp_build_component_ref (src, sf);
6549 t = build2 (MODIFY_EXPR, TREE_TYPE (*p), *p, src);
6550 append_to_statement_list (t, &list);
6551 }
6552
6553 /* Second pass: copy shared var pointers and copy construct non-VLA
6554 firstprivate vars. */
6555 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
6556 switch (OMP_CLAUSE_CODE (c))
6557 {
6558 case OMP_CLAUSE_SHARED:
6559 decl = OMP_CLAUSE_DECL (c);
6560 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
6561 if (n == NULL)
6562 break;
6563 f = (tree) n->value;
6564 if (tcctx.cb.decl_map)
6565 f = *(tree *) pointer_map_contains (tcctx.cb.decl_map, f);
6566 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
6567 sf = (tree) n->value;
6568 if (tcctx.cb.decl_map)
6569 sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
6570 src = build_simple_mem_ref_loc (loc, sarg);
6571 src = omp_build_component_ref (src, sf);
6572 dst = build_simple_mem_ref_loc (loc, arg);
6573 dst = omp_build_component_ref (dst, f);
6574 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
6575 append_to_statement_list (t, &list);
6576 break;
6577 case OMP_CLAUSE_FIRSTPRIVATE:
6578 decl = OMP_CLAUSE_DECL (c);
6579 if (is_variable_sized (decl))
6580 break;
6581 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
6582 if (n == NULL)
6583 break;
6584 f = (tree) n->value;
6585 if (tcctx.cb.decl_map)
6586 f = *(tree *) pointer_map_contains (tcctx.cb.decl_map, f);
6587 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
6588 if (n != NULL)
6589 {
6590 sf = (tree) n->value;
6591 if (tcctx.cb.decl_map)
6592 sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
6593 src = build_simple_mem_ref_loc (loc, sarg);
6594 src = omp_build_component_ref (src, sf);
6595 if (use_pointer_for_field (decl, NULL) || is_reference (decl))
6596 src = build_simple_mem_ref_loc (loc, src);
6597 }
6598 else
6599 src = decl;
6600 dst = build_simple_mem_ref_loc (loc, arg);
6601 dst = omp_build_component_ref (dst, f);
6602 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
6603 append_to_statement_list (t, &list);
6604 break;
6605 case OMP_CLAUSE_PRIVATE:
6606 if (! OMP_CLAUSE_PRIVATE_OUTER_REF (c))
6607 break;
6608 decl = OMP_CLAUSE_DECL (c);
6609 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
6610 f = (tree) n->value;
6611 if (tcctx.cb.decl_map)
6612 f = *(tree *) pointer_map_contains (tcctx.cb.decl_map, f);
6613 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
6614 if (n != NULL)
6615 {
6616 sf = (tree) n->value;
6617 if (tcctx.cb.decl_map)
6618 sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
6619 src = build_simple_mem_ref_loc (loc, sarg);
6620 src = omp_build_component_ref (src, sf);
6621 if (use_pointer_for_field (decl, NULL))
6622 src = build_simple_mem_ref_loc (loc, src);
6623 }
6624 else
6625 src = decl;
6626 dst = build_simple_mem_ref_loc (loc, arg);
6627 dst = omp_build_component_ref (dst, f);
6628 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
6629 append_to_statement_list (t, &list);
6630 break;
6631 default:
6632 break;
6633 }
6634
6635 /* Last pass: handle VLA firstprivates. */
6636 if (tcctx.cb.decl_map)
6637 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
6638 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
6639 {
6640 tree ind, ptr, df;
6641
6642 decl = OMP_CLAUSE_DECL (c);
6643 if (!is_variable_sized (decl))
6644 continue;
6645 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
6646 if (n == NULL)
6647 continue;
6648 f = (tree) n->value;
6649 f = *(tree *) pointer_map_contains (tcctx.cb.decl_map, f);
6650 gcc_assert (DECL_HAS_VALUE_EXPR_P (decl));
6651 ind = DECL_VALUE_EXPR (decl);
6652 gcc_assert (TREE_CODE (ind) == INDIRECT_REF);
6653 gcc_assert (DECL_P (TREE_OPERAND (ind, 0)));
6654 n = splay_tree_lookup (ctx->sfield_map,
6655 (splay_tree_key) TREE_OPERAND (ind, 0));
6656 sf = (tree) n->value;
6657 sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
6658 src = build_simple_mem_ref_loc (loc, sarg);
6659 src = omp_build_component_ref (src, sf);
6660 src = build_simple_mem_ref_loc (loc, src);
6661 dst = build_simple_mem_ref_loc (loc, arg);
6662 dst = omp_build_component_ref (dst, f);
6663 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
6664 append_to_statement_list (t, &list);
6665 n = splay_tree_lookup (ctx->field_map,
6666 (splay_tree_key) TREE_OPERAND (ind, 0));
6667 df = (tree) n->value;
6668 df = *(tree *) pointer_map_contains (tcctx.cb.decl_map, df);
6669 ptr = build_simple_mem_ref_loc (loc, arg);
6670 ptr = omp_build_component_ref (ptr, df);
6671 t = build2 (MODIFY_EXPR, TREE_TYPE (ptr), ptr,
6672 build_fold_addr_expr_loc (loc, dst));
6673 append_to_statement_list (t, &list);
6674 }
6675
6676 t = build1 (RETURN_EXPR, void_type_node, NULL);
6677 append_to_statement_list (t, &list);
6678
6679 if (tcctx.cb.decl_map)
6680 pointer_map_destroy (tcctx.cb.decl_map);
6681 pop_gimplify_context (NULL);
6682 BIND_EXPR_BODY (bind) = list;
6683 pop_cfun ();
6684 current_function_decl = ctx->cb.src_fn;
6685 }
6686
6687 /* Lower the OpenMP parallel or task directive in the current statement
6688 in GSI_P. CTX holds context information for the directive. */
6689
6690 static void
6691 lower_omp_taskreg (gimple_stmt_iterator *gsi_p, omp_context *ctx)
6692 {
6693 tree clauses;
6694 tree child_fn, t;
6695 gimple stmt = gsi_stmt (*gsi_p);
6696 gimple par_bind, bind;
6697 gimple_seq par_body, olist, ilist, par_olist, par_ilist, new_body;
6698 struct gimplify_ctx gctx;
6699 location_t loc = gimple_location (stmt);
6700
6701 clauses = gimple_omp_taskreg_clauses (stmt);
6702 par_bind = gimple_seq_first_stmt (gimple_omp_body (stmt));
6703 par_body = gimple_bind_body (par_bind);
6704 child_fn = ctx->cb.dst_fn;
6705 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
6706 && !gimple_omp_parallel_combined_p (stmt))
6707 {
6708 struct walk_stmt_info wi;
6709 int ws_num = 0;
6710
6711 memset (&wi, 0, sizeof (wi));
6712 wi.info = &ws_num;
6713 wi.val_only = true;
6714 walk_gimple_seq (par_body, check_combined_parallel, NULL, &wi);
6715 if (ws_num == 1)
6716 gimple_omp_parallel_set_combined_p (stmt, true);
6717 }
6718 if (ctx->srecord_type)
6719 create_task_copyfn (stmt, ctx);
6720
6721 push_gimplify_context (&gctx);
6722
6723 par_olist = NULL;
6724 par_ilist = NULL;
6725 lower_rec_input_clauses (clauses, &par_ilist, &par_olist, ctx);
6726 lower_omp (&par_body, ctx);
6727 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL)
6728 lower_reduction_clauses (clauses, &par_olist, ctx);
6729
6730 /* Declare all the variables created by mapping and the variables
6731 declared in the scope of the parallel body. */
6732 record_vars_into (ctx->block_vars, child_fn);
6733 record_vars_into (gimple_bind_vars (par_bind), child_fn);
6734
6735 if (ctx->record_type)
6736 {
6737 ctx->sender_decl
6738 = create_tmp_var (ctx->srecord_type ? ctx->srecord_type
6739 : ctx->record_type, ".omp_data_o");
6740 DECL_NAMELESS (ctx->sender_decl) = 1;
6741 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
6742 gimple_omp_taskreg_set_data_arg (stmt, ctx->sender_decl);
6743 }
6744
6745 olist = NULL;
6746 ilist = NULL;
6747 lower_send_clauses (clauses, &ilist, &olist, ctx);
6748 lower_send_shared_vars (&ilist, &olist, ctx);
6749
6750 /* Once all the expansions are done, sequence all the different
6751 fragments inside gimple_omp_body. */
6752
6753 new_body = NULL;
6754
6755 if (ctx->record_type)
6756 {
6757 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
6758 /* fixup_child_record_type might have changed receiver_decl's type. */
6759 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
6760 gimple_seq_add_stmt (&new_body,
6761 gimple_build_assign (ctx->receiver_decl, t));
6762 }
6763
6764 gimple_seq_add_seq (&new_body, par_ilist);
6765 gimple_seq_add_seq (&new_body, par_body);
6766 gimple_seq_add_seq (&new_body, par_olist);
6767 new_body = maybe_catch_exception (new_body);
6768 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
6769 gimple_omp_set_body (stmt, new_body);
6770
6771 bind = gimple_build_bind (NULL, NULL, gimple_bind_block (par_bind));
6772 gsi_replace (gsi_p, bind, true);
6773 gimple_bind_add_seq (bind, ilist);
6774 gimple_bind_add_stmt (bind, stmt);
6775 gimple_bind_add_seq (bind, olist);
6776
6777 pop_gimplify_context (NULL);
6778 }
6779
6780 /* Callback for lower_omp_1. Return non-NULL if *tp needs to be
6781 regimplified. If DATA is non-NULL, lower_omp_1 is outside
6782 of OpenMP context, but with task_shared_vars set. */
6783
6784 static tree
6785 lower_omp_regimplify_p (tree *tp, int *walk_subtrees,
6786 void *data)
6787 {
6788 tree t = *tp;
6789
6790 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
6791 if (TREE_CODE (t) == VAR_DECL && data == NULL && DECL_HAS_VALUE_EXPR_P (t))
6792 return t;
6793
6794 if (task_shared_vars
6795 && DECL_P (t)
6796 && bitmap_bit_p (task_shared_vars, DECL_UID (t)))
6797 return t;
6798
6799 /* If a global variable has been privatized, TREE_CONSTANT on
6800 ADDR_EXPR might be wrong. */
6801 if (data == NULL && TREE_CODE (t) == ADDR_EXPR)
6802 recompute_tree_invariant_for_addr_expr (t);
6803
6804 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
6805 return NULL_TREE;
6806 }
6807
6808 static void
6809 lower_omp_1 (gimple_stmt_iterator *gsi_p, omp_context *ctx)
6810 {
6811 gimple stmt = gsi_stmt (*gsi_p);
6812 struct walk_stmt_info wi;
6813
6814 if (gimple_has_location (stmt))
6815 input_location = gimple_location (stmt);
6816
6817 if (task_shared_vars)
6818 memset (&wi, '\0', sizeof (wi));
6819
6820 /* If we have issued syntax errors, avoid doing any heavy lifting.
6821 Just replace the OpenMP directives with a NOP to avoid
6822 confusing RTL expansion. */
6823 if (seen_error () && is_gimple_omp (stmt))
6824 {
6825 gsi_replace (gsi_p, gimple_build_nop (), true);
6826 return;
6827 }
6828
6829 switch (gimple_code (stmt))
6830 {
6831 case GIMPLE_COND:
6832 if ((ctx || task_shared_vars)
6833 && (walk_tree (gimple_cond_lhs_ptr (stmt), lower_omp_regimplify_p,
6834 ctx ? NULL : &wi, NULL)
6835 || walk_tree (gimple_cond_rhs_ptr (stmt), lower_omp_regimplify_p,
6836 ctx ? NULL : &wi, NULL)))
6837 gimple_regimplify_operands (stmt, gsi_p);
6838 break;
6839 case GIMPLE_CATCH:
6840 lower_omp (gimple_catch_handler_ptr (stmt), ctx);
6841 break;
6842 case GIMPLE_EH_FILTER:
6843 lower_omp (gimple_eh_filter_failure_ptr (stmt), ctx);
6844 break;
6845 case GIMPLE_TRY:
6846 lower_omp (gimple_try_eval_ptr (stmt), ctx);
6847 lower_omp (gimple_try_cleanup_ptr (stmt), ctx);
6848 break;
6849 case GIMPLE_BIND:
6850 lower_omp (gimple_bind_body_ptr (stmt), ctx);
6851 break;
6852 case GIMPLE_OMP_PARALLEL:
6853 case GIMPLE_OMP_TASK:
6854 ctx = maybe_lookup_ctx (stmt);
6855 lower_omp_taskreg (gsi_p, ctx);
6856 break;
6857 case GIMPLE_OMP_FOR:
6858 ctx = maybe_lookup_ctx (stmt);
6859 gcc_assert (ctx);
6860 lower_omp_for (gsi_p, ctx);
6861 break;
6862 case GIMPLE_OMP_SECTIONS:
6863 ctx = maybe_lookup_ctx (stmt);
6864 gcc_assert (ctx);
6865 lower_omp_sections (gsi_p, ctx);
6866 break;
6867 case GIMPLE_OMP_SINGLE:
6868 ctx = maybe_lookup_ctx (stmt);
6869 gcc_assert (ctx);
6870 lower_omp_single (gsi_p, ctx);
6871 break;
6872 case GIMPLE_OMP_MASTER:
6873 ctx = maybe_lookup_ctx (stmt);
6874 gcc_assert (ctx);
6875 lower_omp_master (gsi_p, ctx);
6876 break;
6877 case GIMPLE_OMP_ORDERED:
6878 ctx = maybe_lookup_ctx (stmt);
6879 gcc_assert (ctx);
6880 lower_omp_ordered (gsi_p, ctx);
6881 break;
6882 case GIMPLE_OMP_CRITICAL:
6883 ctx = maybe_lookup_ctx (stmt);
6884 gcc_assert (ctx);
6885 lower_omp_critical (gsi_p, ctx);
6886 break;
6887 case GIMPLE_OMP_ATOMIC_LOAD:
6888 if ((ctx || task_shared_vars)
6889 && walk_tree (gimple_omp_atomic_load_rhs_ptr (stmt),
6890 lower_omp_regimplify_p, ctx ? NULL : &wi, NULL))
6891 gimple_regimplify_operands (stmt, gsi_p);
6892 break;
6893 default:
6894 if ((ctx || task_shared_vars)
6895 && walk_gimple_op (stmt, lower_omp_regimplify_p,
6896 ctx ? NULL : &wi))
6897 gimple_regimplify_operands (stmt, gsi_p);
6898 break;
6899 }
6900 }
6901
6902 static void
6903 lower_omp (gimple_seq *body, omp_context *ctx)
6904 {
6905 location_t saved_location = input_location;
6906 gimple_stmt_iterator gsi;
6907 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
6908 lower_omp_1 (&gsi, ctx);
6909 input_location = saved_location;
6910 }
6911 \f
6912 /* Main entry point. */
6913
6914 static unsigned int
6915 execute_lower_omp (void)
6916 {
6917 gimple_seq body;
6918
6919 /* This pass always runs, to provide PROP_gimple_lomp.
6920 But there is nothing to do unless -fopenmp is given. */
6921 if (flag_openmp == 0)
6922 return 0;
6923
6924 all_contexts = splay_tree_new (splay_tree_compare_pointers, 0,
6925 delete_omp_context);
6926
6927 body = gimple_body (current_function_decl);
6928 scan_omp (&body, NULL);
6929 gcc_assert (taskreg_nesting_level == 0);
6930
6931 if (all_contexts->root)
6932 {
6933 struct gimplify_ctx gctx;
6934
6935 if (task_shared_vars)
6936 push_gimplify_context (&gctx);
6937 lower_omp (&body, NULL);
6938 if (task_shared_vars)
6939 pop_gimplify_context (NULL);
6940 }
6941
6942 if (all_contexts)
6943 {
6944 splay_tree_delete (all_contexts);
6945 all_contexts = NULL;
6946 }
6947 BITMAP_FREE (task_shared_vars);
6948 return 0;
6949 }
6950
6951 struct gimple_opt_pass pass_lower_omp =
6952 {
6953 {
6954 GIMPLE_PASS,
6955 "omplower", /* name */
6956 NULL, /* gate */
6957 execute_lower_omp, /* execute */
6958 NULL, /* sub */
6959 NULL, /* next */
6960 0, /* static_pass_number */
6961 TV_NONE, /* tv_id */
6962 PROP_gimple_any, /* properties_required */
6963 PROP_gimple_lomp, /* properties_provided */
6964 0, /* properties_destroyed */
6965 0, /* todo_flags_start */
6966 0 /* todo_flags_finish */
6967 }
6968 };
6969 \f
6970 /* The following is a utility to diagnose OpenMP structured block violations.
6971 It is not part of the "omplower" pass, as that's invoked too late. It
6972 should be invoked by the respective front ends after gimplification. */
6973
6974 static splay_tree all_labels;
6975
6976 /* Check for mismatched contexts and generate an error if needed. Return
6977 true if an error is detected. */
6978
6979 static bool
6980 diagnose_sb_0 (gimple_stmt_iterator *gsi_p,
6981 gimple branch_ctx, gimple label_ctx)
6982 {
6983 if (label_ctx == branch_ctx)
6984 return false;
6985
6986
6987 /*
6988 Previously we kept track of the label's entire context in diagnose_sb_[12]
6989 so we could traverse it and issue a correct "exit" or "enter" error
6990 message upon a structured block violation.
6991
6992 We built the context by building a list with tree_cons'ing, but there is
6993 no easy counterpart in gimple tuples. It seems like far too much work
6994 for issuing exit/enter error messages. If someone really misses the
6995 distinct error message... patches welcome.
6996 */
6997
6998 #if 0
6999 /* Try to avoid confusing the user by producing and error message
7000 with correct "exit" or "enter" verbiage. We prefer "exit"
7001 unless we can show that LABEL_CTX is nested within BRANCH_CTX. */
7002 if (branch_ctx == NULL)
7003 exit_p = false;
7004 else
7005 {
7006 while (label_ctx)
7007 {
7008 if (TREE_VALUE (label_ctx) == branch_ctx)
7009 {
7010 exit_p = false;
7011 break;
7012 }
7013 label_ctx = TREE_CHAIN (label_ctx);
7014 }
7015 }
7016
7017 if (exit_p)
7018 error ("invalid exit from OpenMP structured block");
7019 else
7020 error ("invalid entry to OpenMP structured block");
7021 #endif
7022
7023 /* If it's obvious we have an invalid entry, be specific about the error. */
7024 if (branch_ctx == NULL)
7025 error ("invalid entry to OpenMP structured block");
7026 else
7027 /* Otherwise, be vague and lazy, but efficient. */
7028 error ("invalid branch to/from an OpenMP structured block");
7029
7030 gsi_replace (gsi_p, gimple_build_nop (), false);
7031 return true;
7032 }
7033
7034 /* Pass 1: Create a minimal tree of OpenMP structured blocks, and record
7035 where each label is found. */
7036
7037 static tree
7038 diagnose_sb_1 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
7039 struct walk_stmt_info *wi)
7040 {
7041 gimple context = (gimple) wi->info;
7042 gimple inner_context;
7043 gimple stmt = gsi_stmt (*gsi_p);
7044
7045 *handled_ops_p = true;
7046
7047 switch (gimple_code (stmt))
7048 {
7049 WALK_SUBSTMTS;
7050
7051 case GIMPLE_OMP_PARALLEL:
7052 case GIMPLE_OMP_TASK:
7053 case GIMPLE_OMP_SECTIONS:
7054 case GIMPLE_OMP_SINGLE:
7055 case GIMPLE_OMP_SECTION:
7056 case GIMPLE_OMP_MASTER:
7057 case GIMPLE_OMP_ORDERED:
7058 case GIMPLE_OMP_CRITICAL:
7059 /* The minimal context here is just the current OMP construct. */
7060 inner_context = stmt;
7061 wi->info = inner_context;
7062 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
7063 wi->info = context;
7064 break;
7065
7066 case GIMPLE_OMP_FOR:
7067 inner_context = stmt;
7068 wi->info = inner_context;
7069 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
7070 walk them. */
7071 walk_gimple_seq (gimple_omp_for_pre_body (stmt),
7072 diagnose_sb_1, NULL, wi);
7073 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
7074 wi->info = context;
7075 break;
7076
7077 case GIMPLE_LABEL:
7078 splay_tree_insert (all_labels, (splay_tree_key) gimple_label_label (stmt),
7079 (splay_tree_value) context);
7080 break;
7081
7082 default:
7083 break;
7084 }
7085
7086 return NULL_TREE;
7087 }
7088
7089 /* Pass 2: Check each branch and see if its context differs from that of
7090 the destination label's context. */
7091
7092 static tree
7093 diagnose_sb_2 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
7094 struct walk_stmt_info *wi)
7095 {
7096 gimple context = (gimple) wi->info;
7097 splay_tree_node n;
7098 gimple stmt = gsi_stmt (*gsi_p);
7099
7100 *handled_ops_p = true;
7101
7102 switch (gimple_code (stmt))
7103 {
7104 WALK_SUBSTMTS;
7105
7106 case GIMPLE_OMP_PARALLEL:
7107 case GIMPLE_OMP_TASK:
7108 case GIMPLE_OMP_SECTIONS:
7109 case GIMPLE_OMP_SINGLE:
7110 case GIMPLE_OMP_SECTION:
7111 case GIMPLE_OMP_MASTER:
7112 case GIMPLE_OMP_ORDERED:
7113 case GIMPLE_OMP_CRITICAL:
7114 wi->info = stmt;
7115 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
7116 wi->info = context;
7117 break;
7118
7119 case GIMPLE_OMP_FOR:
7120 wi->info = stmt;
7121 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
7122 walk them. */
7123 walk_gimple_seq_mod (gimple_omp_for_pre_body_ptr (stmt),
7124 diagnose_sb_2, NULL, wi);
7125 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
7126 wi->info = context;
7127 break;
7128
7129 case GIMPLE_COND:
7130 {
7131 tree lab = gimple_cond_true_label (stmt);
7132 if (lab)
7133 {
7134 n = splay_tree_lookup (all_labels,
7135 (splay_tree_key) lab);
7136 diagnose_sb_0 (gsi_p, context,
7137 n ? (gimple) n->value : NULL);
7138 }
7139 lab = gimple_cond_false_label (stmt);
7140 if (lab)
7141 {
7142 n = splay_tree_lookup (all_labels,
7143 (splay_tree_key) lab);
7144 diagnose_sb_0 (gsi_p, context,
7145 n ? (gimple) n->value : NULL);
7146 }
7147 }
7148 break;
7149
7150 case GIMPLE_GOTO:
7151 {
7152 tree lab = gimple_goto_dest (stmt);
7153 if (TREE_CODE (lab) != LABEL_DECL)
7154 break;
7155
7156 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
7157 diagnose_sb_0 (gsi_p, context, n ? (gimple) n->value : NULL);
7158 }
7159 break;
7160
7161 case GIMPLE_SWITCH:
7162 {
7163 unsigned int i;
7164 for (i = 0; i < gimple_switch_num_labels (stmt); ++i)
7165 {
7166 tree lab = CASE_LABEL (gimple_switch_label (stmt, i));
7167 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
7168 if (n && diagnose_sb_0 (gsi_p, context, (gimple) n->value))
7169 break;
7170 }
7171 }
7172 break;
7173
7174 case GIMPLE_RETURN:
7175 diagnose_sb_0 (gsi_p, context, NULL);
7176 break;
7177
7178 default:
7179 break;
7180 }
7181
7182 return NULL_TREE;
7183 }
7184
7185 static unsigned int
7186 diagnose_omp_structured_block_errors (void)
7187 {
7188 struct walk_stmt_info wi;
7189 gimple_seq body = gimple_body (current_function_decl);
7190
7191 all_labels = splay_tree_new (splay_tree_compare_pointers, 0, 0);
7192
7193 memset (&wi, 0, sizeof (wi));
7194 walk_gimple_seq (body, diagnose_sb_1, NULL, &wi);
7195
7196 memset (&wi, 0, sizeof (wi));
7197 wi.want_locations = true;
7198 walk_gimple_seq_mod (&body, diagnose_sb_2, NULL, &wi);
7199
7200 gimple_set_body (current_function_decl, body);
7201
7202 splay_tree_delete (all_labels);
7203 all_labels = NULL;
7204
7205 return 0;
7206 }
7207
7208 static bool
7209 gate_diagnose_omp_blocks (void)
7210 {
7211 return flag_openmp != 0;
7212 }
7213
7214 struct gimple_opt_pass pass_diagnose_omp_blocks =
7215 {
7216 {
7217 GIMPLE_PASS,
7218 "*diagnose_omp_blocks", /* name */
7219 gate_diagnose_omp_blocks, /* gate */
7220 diagnose_omp_structured_block_errors, /* execute */
7221 NULL, /* sub */
7222 NULL, /* next */
7223 0, /* static_pass_number */
7224 TV_NONE, /* tv_id */
7225 PROP_gimple_any, /* properties_required */
7226 0, /* properties_provided */
7227 0, /* properties_destroyed */
7228 0, /* todo_flags_start */
7229 0, /* todo_flags_finish */
7230 }
7231 };
7232
7233 #include "gt-omp-low.h"