re PR middle-end/59152 (ICE: loop 2's latch does not have an edge to its header with...
[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-2013 Free Software Foundation, Inc.
7
8 This file is part of GCC.
9
10 GCC is free software; you can redistribute it and/or modify it under
11 the terms of the GNU General Public License as published by the Free
12 Software Foundation; either version 3, or (at your option) any later
13 version.
14
15 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
16 WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18 for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with GCC; see the file COPYING3. If not see
22 <http://www.gnu.org/licenses/>. */
23
24 #include "config.h"
25 #include "system.h"
26 #include "coretypes.h"
27 #include "tm.h"
28 #include "tree.h"
29 #include "stringpool.h"
30 #include "stor-layout.h"
31 #include "rtl.h"
32 #include "pointer-set.h"
33 #include "basic-block.h"
34 #include "tree-ssa-alias.h"
35 #include "internal-fn.h"
36 #include "gimple-fold.h"
37 #include "gimple-expr.h"
38 #include "is-a.h"
39 #include "gimple.h"
40 #include "gimplify.h"
41 #include "gimple-iterator.h"
42 #include "gimplify-me.h"
43 #include "gimple-walk.h"
44 #include "tree-iterator.h"
45 #include "tree-inline.h"
46 #include "langhooks.h"
47 #include "diagnostic-core.h"
48 #include "gimple-ssa.h"
49 #include "cgraph.h"
50 #include "tree-cfg.h"
51 #include "tree-phinodes.h"
52 #include "ssa-iterators.h"
53 #include "tree-ssanames.h"
54 #include "tree-into-ssa.h"
55 #include "expr.h"
56 #include "tree-dfa.h"
57 #include "tree-ssa.h"
58 #include "flags.h"
59 #include "function.h"
60 #include "expr.h"
61 #include "tree-pass.h"
62 #include "except.h"
63 #include "splay-tree.h"
64 #include "optabs.h"
65 #include "cfgloop.h"
66 #include "target.h"
67 #include "omp-low.h"
68 #include "gimple-low.h"
69 #include "tree-cfgcleanup.h"
70 #include "tree-nested.h"
71
72
73 /* Lowering of OpenMP parallel and workshare constructs proceeds in two
74 phases. The first phase scans the function looking for OMP statements
75 and then for variables that must be replaced to satisfy data sharing
76 clauses. The second phase expands code for the constructs, as well as
77 re-gimplifying things when variables have been replaced with complex
78 expressions.
79
80 Final code generation is done by pass_expand_omp. The flowgraph is
81 scanned for parallel regions which are then moved to a new
82 function, to be invoked by the thread library. */
83
84 /* Parallel region information. Every parallel and workshare
85 directive is enclosed between two markers, the OMP_* directive
86 and a corresponding OMP_RETURN statement. */
87
88 struct omp_region
89 {
90 /* The enclosing region. */
91 struct omp_region *outer;
92
93 /* First child region. */
94 struct omp_region *inner;
95
96 /* Next peer region. */
97 struct omp_region *next;
98
99 /* Block containing the omp directive as its last stmt. */
100 basic_block entry;
101
102 /* Block containing the OMP_RETURN as its last stmt. */
103 basic_block exit;
104
105 /* Block containing the OMP_CONTINUE as its last stmt. */
106 basic_block cont;
107
108 /* If this is a combined parallel+workshare region, this is a list
109 of additional arguments needed by the combined parallel+workshare
110 library call. */
111 vec<tree, va_gc> *ws_args;
112
113 /* The code for the omp directive of this region. */
114 enum gimple_code type;
115
116 /* Schedule kind, only used for OMP_FOR type regions. */
117 enum omp_clause_schedule_kind sched_kind;
118
119 /* True if this is a combined parallel+workshare region. */
120 bool is_combined_parallel;
121 };
122
123 /* Context structure. Used to store information about each parallel
124 directive in the code. */
125
126 typedef struct omp_context
127 {
128 /* This field must be at the beginning, as we do "inheritance": Some
129 callback functions for tree-inline.c (e.g., omp_copy_decl)
130 receive a copy_body_data pointer that is up-casted to an
131 omp_context pointer. */
132 copy_body_data cb;
133
134 /* The tree of contexts corresponding to the encountered constructs. */
135 struct omp_context *outer;
136 gimple stmt;
137
138 /* Map variables to fields in a structure that allows communication
139 between sending and receiving threads. */
140 splay_tree field_map;
141 tree record_type;
142 tree sender_decl;
143 tree receiver_decl;
144
145 /* These are used just by task contexts, if task firstprivate fn is
146 needed. srecord_type is used to communicate from the thread
147 that encountered the task construct to task firstprivate fn,
148 record_type is allocated by GOMP_task, initialized by task firstprivate
149 fn and passed to the task body fn. */
150 splay_tree sfield_map;
151 tree srecord_type;
152
153 /* A chain of variables to add to the top-level block surrounding the
154 construct. In the case of a parallel, this is in the child function. */
155 tree block_vars;
156
157 /* Label to which GOMP_cancel{,llation_point} and explicit and implicit
158 barriers should jump to during omplower pass. */
159 tree cancel_label;
160
161 /* What to do with variables with implicitly determined sharing
162 attributes. */
163 enum omp_clause_default_kind default_kind;
164
165 /* Nesting depth of this context. Used to beautify error messages re
166 invalid gotos. The outermost ctx is depth 1, with depth 0 being
167 reserved for the main body of the function. */
168 int depth;
169
170 /* True if this parallel directive is nested within another. */
171 bool is_nested;
172
173 /* True if this construct can be cancelled. */
174 bool cancellable;
175 } omp_context;
176
177
178 struct omp_for_data_loop
179 {
180 tree v, n1, n2, step;
181 enum tree_code cond_code;
182 };
183
184 /* A structure describing the main elements of a parallel loop. */
185
186 struct omp_for_data
187 {
188 struct omp_for_data_loop loop;
189 tree chunk_size;
190 gimple for_stmt;
191 tree pre, iter_type;
192 int collapse;
193 bool have_nowait, have_ordered;
194 enum omp_clause_schedule_kind sched_kind;
195 struct omp_for_data_loop *loops;
196 };
197
198
199 static splay_tree all_contexts;
200 static int taskreg_nesting_level;
201 static int target_nesting_level;
202 static struct omp_region *root_omp_region;
203 static bitmap task_shared_vars;
204
205 static void scan_omp (gimple_seq *, omp_context *);
206 static tree scan_omp_1_op (tree *, int *, void *);
207
208 #define WALK_SUBSTMTS \
209 case GIMPLE_BIND: \
210 case GIMPLE_TRY: \
211 case GIMPLE_CATCH: \
212 case GIMPLE_EH_FILTER: \
213 case GIMPLE_TRANSACTION: \
214 /* The sub-statements for these should be walked. */ \
215 *handled_ops_p = false; \
216 break;
217
218 /* Convenience function for calling scan_omp_1_op on tree operands. */
219
220 static inline tree
221 scan_omp_op (tree *tp, omp_context *ctx)
222 {
223 struct walk_stmt_info wi;
224
225 memset (&wi, 0, sizeof (wi));
226 wi.info = ctx;
227 wi.want_locations = true;
228
229 return walk_tree (tp, scan_omp_1_op, &wi, NULL);
230 }
231
232 static void lower_omp (gimple_seq *, omp_context *);
233 static tree lookup_decl_in_outer_ctx (tree, omp_context *);
234 static tree maybe_lookup_decl_in_outer_ctx (tree, omp_context *);
235
236 /* Find an OpenMP clause of type KIND within CLAUSES. */
237
238 tree
239 find_omp_clause (tree clauses, enum omp_clause_code kind)
240 {
241 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
242 if (OMP_CLAUSE_CODE (clauses) == kind)
243 return clauses;
244
245 return NULL_TREE;
246 }
247
248 /* Return true if CTX is for an omp parallel. */
249
250 static inline bool
251 is_parallel_ctx (omp_context *ctx)
252 {
253 return gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL;
254 }
255
256
257 /* Return true if CTX is for an omp task. */
258
259 static inline bool
260 is_task_ctx (omp_context *ctx)
261 {
262 return gimple_code (ctx->stmt) == GIMPLE_OMP_TASK;
263 }
264
265
266 /* Return true if CTX is for an omp parallel or omp task. */
267
268 static inline bool
269 is_taskreg_ctx (omp_context *ctx)
270 {
271 return gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL
272 || gimple_code (ctx->stmt) == GIMPLE_OMP_TASK;
273 }
274
275
276 /* Return true if REGION is a combined parallel+workshare region. */
277
278 static inline bool
279 is_combined_parallel (struct omp_region *region)
280 {
281 return region->is_combined_parallel;
282 }
283
284
285 /* Extract the header elements of parallel loop FOR_STMT and store
286 them into *FD. */
287
288 static void
289 extract_omp_for_data (gimple for_stmt, struct omp_for_data *fd,
290 struct omp_for_data_loop *loops)
291 {
292 tree t, var, *collapse_iter, *collapse_count;
293 tree count = NULL_TREE, iter_type = long_integer_type_node;
294 struct omp_for_data_loop *loop;
295 int i;
296 struct omp_for_data_loop dummy_loop;
297 location_t loc = gimple_location (for_stmt);
298 bool simd = gimple_omp_for_kind (for_stmt) & GF_OMP_FOR_KIND_SIMD;
299 bool distribute = gimple_omp_for_kind (for_stmt)
300 == GF_OMP_FOR_KIND_DISTRIBUTE;
301
302 fd->for_stmt = for_stmt;
303 fd->pre = NULL;
304 fd->collapse = gimple_omp_for_collapse (for_stmt);
305 if (fd->collapse > 1)
306 fd->loops = loops;
307 else
308 fd->loops = &fd->loop;
309
310 fd->have_nowait = distribute || simd;
311 fd->have_ordered = false;
312 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
313 fd->chunk_size = NULL_TREE;
314 collapse_iter = NULL;
315 collapse_count = NULL;
316
317 for (t = gimple_omp_for_clauses (for_stmt); t ; t = OMP_CLAUSE_CHAIN (t))
318 switch (OMP_CLAUSE_CODE (t))
319 {
320 case OMP_CLAUSE_NOWAIT:
321 fd->have_nowait = true;
322 break;
323 case OMP_CLAUSE_ORDERED:
324 fd->have_ordered = true;
325 break;
326 case OMP_CLAUSE_SCHEDULE:
327 gcc_assert (!distribute);
328 fd->sched_kind = OMP_CLAUSE_SCHEDULE_KIND (t);
329 fd->chunk_size = OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (t);
330 break;
331 case OMP_CLAUSE_DIST_SCHEDULE:
332 gcc_assert (distribute);
333 fd->chunk_size = OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (t);
334 break;
335 case OMP_CLAUSE_COLLAPSE:
336 if (fd->collapse > 1)
337 {
338 collapse_iter = &OMP_CLAUSE_COLLAPSE_ITERVAR (t);
339 collapse_count = &OMP_CLAUSE_COLLAPSE_COUNT (t);
340 }
341 default:
342 break;
343 }
344
345 /* FIXME: for now map schedule(auto) to schedule(static).
346 There should be analysis to determine whether all iterations
347 are approximately the same amount of work (then schedule(static)
348 is best) or if it varies (then schedule(dynamic,N) is better). */
349 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_AUTO)
350 {
351 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
352 gcc_assert (fd->chunk_size == NULL);
353 }
354 gcc_assert (fd->collapse == 1 || collapse_iter != NULL);
355 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
356 gcc_assert (fd->chunk_size == NULL);
357 else if (fd->chunk_size == NULL)
358 {
359 /* We only need to compute a default chunk size for ordered
360 static loops and dynamic loops. */
361 if (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
362 || fd->have_ordered)
363 fd->chunk_size = (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
364 ? integer_zero_node : integer_one_node;
365 }
366
367 for (i = 0; i < fd->collapse; i++)
368 {
369 if (fd->collapse == 1)
370 loop = &fd->loop;
371 else if (loops != NULL)
372 loop = loops + i;
373 else
374 loop = &dummy_loop;
375
376 loop->v = gimple_omp_for_index (for_stmt, i);
377 gcc_assert (SSA_VAR_P (loop->v));
378 gcc_assert (TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
379 || TREE_CODE (TREE_TYPE (loop->v)) == POINTER_TYPE);
380 var = TREE_CODE (loop->v) == SSA_NAME ? SSA_NAME_VAR (loop->v) : loop->v;
381 loop->n1 = gimple_omp_for_initial (for_stmt, i);
382
383 loop->cond_code = gimple_omp_for_cond (for_stmt, i);
384 loop->n2 = gimple_omp_for_final (for_stmt, i);
385 switch (loop->cond_code)
386 {
387 case LT_EXPR:
388 case GT_EXPR:
389 break;
390 case NE_EXPR:
391 gcc_assert (gimple_omp_for_kind (for_stmt)
392 == GF_OMP_FOR_KIND_CILKSIMD);
393 break;
394 case LE_EXPR:
395 if (POINTER_TYPE_P (TREE_TYPE (loop->n2)))
396 loop->n2 = fold_build_pointer_plus_hwi_loc (loc, loop->n2, 1);
397 else
398 loop->n2 = fold_build2_loc (loc,
399 PLUS_EXPR, TREE_TYPE (loop->n2), loop->n2,
400 build_int_cst (TREE_TYPE (loop->n2), 1));
401 loop->cond_code = LT_EXPR;
402 break;
403 case GE_EXPR:
404 if (POINTER_TYPE_P (TREE_TYPE (loop->n2)))
405 loop->n2 = fold_build_pointer_plus_hwi_loc (loc, loop->n2, -1);
406 else
407 loop->n2 = fold_build2_loc (loc,
408 MINUS_EXPR, TREE_TYPE (loop->n2), loop->n2,
409 build_int_cst (TREE_TYPE (loop->n2), 1));
410 loop->cond_code = GT_EXPR;
411 break;
412 default:
413 gcc_unreachable ();
414 }
415
416 t = gimple_omp_for_incr (for_stmt, i);
417 gcc_assert (TREE_OPERAND (t, 0) == var);
418 switch (TREE_CODE (t))
419 {
420 case PLUS_EXPR:
421 loop->step = TREE_OPERAND (t, 1);
422 break;
423 case POINTER_PLUS_EXPR:
424 loop->step = fold_convert (ssizetype, TREE_OPERAND (t, 1));
425 break;
426 case MINUS_EXPR:
427 loop->step = TREE_OPERAND (t, 1);
428 loop->step = fold_build1_loc (loc,
429 NEGATE_EXPR, TREE_TYPE (loop->step),
430 loop->step);
431 break;
432 default:
433 gcc_unreachable ();
434 }
435
436 if (simd
437 || (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
438 && !fd->have_ordered))
439 {
440 if (fd->collapse == 1)
441 iter_type = TREE_TYPE (loop->v);
442 else if (i == 0
443 || TYPE_PRECISION (iter_type)
444 < TYPE_PRECISION (TREE_TYPE (loop->v)))
445 iter_type
446 = build_nonstandard_integer_type
447 (TYPE_PRECISION (TREE_TYPE (loop->v)), 1);
448 }
449 else if (iter_type != long_long_unsigned_type_node)
450 {
451 if (POINTER_TYPE_P (TREE_TYPE (loop->v)))
452 iter_type = long_long_unsigned_type_node;
453 else if (TYPE_UNSIGNED (TREE_TYPE (loop->v))
454 && TYPE_PRECISION (TREE_TYPE (loop->v))
455 >= TYPE_PRECISION (iter_type))
456 {
457 tree n;
458
459 if (loop->cond_code == LT_EXPR)
460 n = fold_build2_loc (loc,
461 PLUS_EXPR, TREE_TYPE (loop->v),
462 loop->n2, loop->step);
463 else
464 n = loop->n1;
465 if (TREE_CODE (n) != INTEGER_CST
466 || tree_int_cst_lt (TYPE_MAX_VALUE (iter_type), n))
467 iter_type = long_long_unsigned_type_node;
468 }
469 else if (TYPE_PRECISION (TREE_TYPE (loop->v))
470 > TYPE_PRECISION (iter_type))
471 {
472 tree n1, n2;
473
474 if (loop->cond_code == LT_EXPR)
475 {
476 n1 = loop->n1;
477 n2 = fold_build2_loc (loc,
478 PLUS_EXPR, TREE_TYPE (loop->v),
479 loop->n2, loop->step);
480 }
481 else
482 {
483 n1 = fold_build2_loc (loc,
484 MINUS_EXPR, TREE_TYPE (loop->v),
485 loop->n2, loop->step);
486 n2 = loop->n1;
487 }
488 if (TREE_CODE (n1) != INTEGER_CST
489 || TREE_CODE (n2) != INTEGER_CST
490 || !tree_int_cst_lt (TYPE_MIN_VALUE (iter_type), n1)
491 || !tree_int_cst_lt (n2, TYPE_MAX_VALUE (iter_type)))
492 iter_type = long_long_unsigned_type_node;
493 }
494 }
495
496 if (collapse_count && *collapse_count == NULL)
497 {
498 t = fold_binary (loop->cond_code, boolean_type_node,
499 fold_convert (TREE_TYPE (loop->v), loop->n1),
500 fold_convert (TREE_TYPE (loop->v), loop->n2));
501 if (t && integer_zerop (t))
502 count = build_zero_cst (long_long_unsigned_type_node);
503 else if ((i == 0 || count != NULL_TREE)
504 && TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
505 && TREE_CONSTANT (loop->n1)
506 && TREE_CONSTANT (loop->n2)
507 && TREE_CODE (loop->step) == INTEGER_CST)
508 {
509 tree itype = TREE_TYPE (loop->v);
510
511 if (POINTER_TYPE_P (itype))
512 itype = signed_type_for (itype);
513 t = build_int_cst (itype, (loop->cond_code == LT_EXPR ? -1 : 1));
514 t = fold_build2_loc (loc,
515 PLUS_EXPR, itype,
516 fold_convert_loc (loc, itype, loop->step), t);
517 t = fold_build2_loc (loc, PLUS_EXPR, itype, t,
518 fold_convert_loc (loc, itype, loop->n2));
519 t = fold_build2_loc (loc, MINUS_EXPR, itype, t,
520 fold_convert_loc (loc, itype, loop->n1));
521 if (TYPE_UNSIGNED (itype) && loop->cond_code == GT_EXPR)
522 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype,
523 fold_build1_loc (loc, NEGATE_EXPR, itype, t),
524 fold_build1_loc (loc, NEGATE_EXPR, itype,
525 fold_convert_loc (loc, itype,
526 loop->step)));
527 else
528 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, t,
529 fold_convert_loc (loc, itype, loop->step));
530 t = fold_convert_loc (loc, long_long_unsigned_type_node, t);
531 if (count != NULL_TREE)
532 count = fold_build2_loc (loc,
533 MULT_EXPR, long_long_unsigned_type_node,
534 count, t);
535 else
536 count = t;
537 if (TREE_CODE (count) != INTEGER_CST)
538 count = NULL_TREE;
539 }
540 else if (count && !integer_zerop (count))
541 count = NULL_TREE;
542 }
543 }
544
545 if (count
546 && !simd
547 && (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
548 || fd->have_ordered))
549 {
550 if (!tree_int_cst_lt (count, TYPE_MAX_VALUE (long_integer_type_node)))
551 iter_type = long_long_unsigned_type_node;
552 else
553 iter_type = long_integer_type_node;
554 }
555 else if (collapse_iter && *collapse_iter != NULL)
556 iter_type = TREE_TYPE (*collapse_iter);
557 fd->iter_type = iter_type;
558 if (collapse_iter && *collapse_iter == NULL)
559 *collapse_iter = create_tmp_var (iter_type, ".iter");
560 if (collapse_count && *collapse_count == NULL)
561 {
562 if (count)
563 *collapse_count = fold_convert_loc (loc, iter_type, count);
564 else
565 *collapse_count = create_tmp_var (iter_type, ".count");
566 }
567
568 if (fd->collapse > 1)
569 {
570 fd->loop.v = *collapse_iter;
571 fd->loop.n1 = build_int_cst (TREE_TYPE (fd->loop.v), 0);
572 fd->loop.n2 = *collapse_count;
573 fd->loop.step = build_int_cst (TREE_TYPE (fd->loop.v), 1);
574 fd->loop.cond_code = LT_EXPR;
575 }
576 }
577
578
579 /* Given two blocks PAR_ENTRY_BB and WS_ENTRY_BB such that WS_ENTRY_BB
580 is the immediate dominator of PAR_ENTRY_BB, return true if there
581 are no data dependencies that would prevent expanding the parallel
582 directive at PAR_ENTRY_BB as a combined parallel+workshare region.
583
584 When expanding a combined parallel+workshare region, the call to
585 the child function may need additional arguments in the case of
586 GIMPLE_OMP_FOR regions. In some cases, these arguments are
587 computed out of variables passed in from the parent to the child
588 via 'struct .omp_data_s'. For instance:
589
590 #pragma omp parallel for schedule (guided, i * 4)
591 for (j ...)
592
593 Is lowered into:
594
595 # BLOCK 2 (PAR_ENTRY_BB)
596 .omp_data_o.i = i;
597 #pragma omp parallel [child fn: bar.omp_fn.0 ( ..., D.1598)
598
599 # BLOCK 3 (WS_ENTRY_BB)
600 .omp_data_i = &.omp_data_o;
601 D.1667 = .omp_data_i->i;
602 D.1598 = D.1667 * 4;
603 #pragma omp for schedule (guided, D.1598)
604
605 When we outline the parallel region, the call to the child function
606 'bar.omp_fn.0' will need the value D.1598 in its argument list, but
607 that value is computed *after* the call site. So, in principle we
608 cannot do the transformation.
609
610 To see whether the code in WS_ENTRY_BB blocks the combined
611 parallel+workshare call, we collect all the variables used in the
612 GIMPLE_OMP_FOR header check whether they appear on the LHS of any
613 statement in WS_ENTRY_BB. If so, then we cannot emit the combined
614 call.
615
616 FIXME. If we had the SSA form built at this point, we could merely
617 hoist the code in block 3 into block 2 and be done with it. But at
618 this point we don't have dataflow information and though we could
619 hack something up here, it is really not worth the aggravation. */
620
621 static bool
622 workshare_safe_to_combine_p (basic_block ws_entry_bb)
623 {
624 struct omp_for_data fd;
625 gimple ws_stmt = last_stmt (ws_entry_bb);
626
627 if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
628 return true;
629
630 gcc_assert (gimple_code (ws_stmt) == GIMPLE_OMP_FOR);
631
632 extract_omp_for_data (ws_stmt, &fd, NULL);
633
634 if (fd.collapse > 1 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
635 return false;
636 if (fd.iter_type != long_integer_type_node)
637 return false;
638
639 /* FIXME. We give up too easily here. If any of these arguments
640 are not constants, they will likely involve variables that have
641 been mapped into fields of .omp_data_s for sharing with the child
642 function. With appropriate data flow, it would be possible to
643 see through this. */
644 if (!is_gimple_min_invariant (fd.loop.n1)
645 || !is_gimple_min_invariant (fd.loop.n2)
646 || !is_gimple_min_invariant (fd.loop.step)
647 || (fd.chunk_size && !is_gimple_min_invariant (fd.chunk_size)))
648 return false;
649
650 return true;
651 }
652
653
654 /* Collect additional arguments needed to emit a combined
655 parallel+workshare call. WS_STMT is the workshare directive being
656 expanded. */
657
658 static vec<tree, va_gc> *
659 get_ws_args_for (gimple par_stmt, gimple ws_stmt)
660 {
661 tree t;
662 location_t loc = gimple_location (ws_stmt);
663 vec<tree, va_gc> *ws_args;
664
665 if (gimple_code (ws_stmt) == GIMPLE_OMP_FOR)
666 {
667 struct omp_for_data fd;
668 tree n1, n2;
669
670 extract_omp_for_data (ws_stmt, &fd, NULL);
671 n1 = fd.loop.n1;
672 n2 = fd.loop.n2;
673
674 if (gimple_omp_for_combined_into_p (ws_stmt))
675 {
676 tree innerc
677 = find_omp_clause (gimple_omp_parallel_clauses (par_stmt),
678 OMP_CLAUSE__LOOPTEMP_);
679 gcc_assert (innerc);
680 n1 = OMP_CLAUSE_DECL (innerc);
681 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
682 OMP_CLAUSE__LOOPTEMP_);
683 gcc_assert (innerc);
684 n2 = OMP_CLAUSE_DECL (innerc);
685 }
686
687 vec_alloc (ws_args, 3 + (fd.chunk_size != 0));
688
689 t = fold_convert_loc (loc, long_integer_type_node, n1);
690 ws_args->quick_push (t);
691
692 t = fold_convert_loc (loc, long_integer_type_node, n2);
693 ws_args->quick_push (t);
694
695 t = fold_convert_loc (loc, long_integer_type_node, fd.loop.step);
696 ws_args->quick_push (t);
697
698 if (fd.chunk_size)
699 {
700 t = fold_convert_loc (loc, long_integer_type_node, fd.chunk_size);
701 ws_args->quick_push (t);
702 }
703
704 return ws_args;
705 }
706 else if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
707 {
708 /* Number of sections is equal to the number of edges from the
709 GIMPLE_OMP_SECTIONS_SWITCH statement, except for the one to
710 the exit of the sections region. */
711 basic_block bb = single_succ (gimple_bb (ws_stmt));
712 t = build_int_cst (unsigned_type_node, EDGE_COUNT (bb->succs) - 1);
713 vec_alloc (ws_args, 1);
714 ws_args->quick_push (t);
715 return ws_args;
716 }
717
718 gcc_unreachable ();
719 }
720
721
722 /* Discover whether REGION is a combined parallel+workshare region. */
723
724 static void
725 determine_parallel_type (struct omp_region *region)
726 {
727 basic_block par_entry_bb, par_exit_bb;
728 basic_block ws_entry_bb, ws_exit_bb;
729
730 if (region == NULL || region->inner == NULL
731 || region->exit == NULL || region->inner->exit == NULL
732 || region->inner->cont == NULL)
733 return;
734
735 /* We only support parallel+for and parallel+sections. */
736 if (region->type != GIMPLE_OMP_PARALLEL
737 || (region->inner->type != GIMPLE_OMP_FOR
738 && region->inner->type != GIMPLE_OMP_SECTIONS))
739 return;
740
741 /* Check for perfect nesting PAR_ENTRY_BB -> WS_ENTRY_BB and
742 WS_EXIT_BB -> PAR_EXIT_BB. */
743 par_entry_bb = region->entry;
744 par_exit_bb = region->exit;
745 ws_entry_bb = region->inner->entry;
746 ws_exit_bb = region->inner->exit;
747
748 if (single_succ (par_entry_bb) == ws_entry_bb
749 && single_succ (ws_exit_bb) == par_exit_bb
750 && workshare_safe_to_combine_p (ws_entry_bb)
751 && (gimple_omp_parallel_combined_p (last_stmt (par_entry_bb))
752 || (last_and_only_stmt (ws_entry_bb)
753 && last_and_only_stmt (par_exit_bb))))
754 {
755 gimple par_stmt = last_stmt (par_entry_bb);
756 gimple ws_stmt = last_stmt (ws_entry_bb);
757
758 if (region->inner->type == GIMPLE_OMP_FOR)
759 {
760 /* If this is a combined parallel loop, we need to determine
761 whether or not to use the combined library calls. There
762 are two cases where we do not apply the transformation:
763 static loops and any kind of ordered loop. In the first
764 case, we already open code the loop so there is no need
765 to do anything else. In the latter case, the combined
766 parallel loop call would still need extra synchronization
767 to implement ordered semantics, so there would not be any
768 gain in using the combined call. */
769 tree clauses = gimple_omp_for_clauses (ws_stmt);
770 tree c = find_omp_clause (clauses, OMP_CLAUSE_SCHEDULE);
771 if (c == NULL
772 || OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_STATIC
773 || find_omp_clause (clauses, OMP_CLAUSE_ORDERED))
774 {
775 region->is_combined_parallel = false;
776 region->inner->is_combined_parallel = false;
777 return;
778 }
779 }
780
781 region->is_combined_parallel = true;
782 region->inner->is_combined_parallel = true;
783 region->ws_args = get_ws_args_for (par_stmt, ws_stmt);
784 }
785 }
786
787
788 /* Return true if EXPR is variable sized. */
789
790 static inline bool
791 is_variable_sized (const_tree expr)
792 {
793 return !TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (expr)));
794 }
795
796 /* Return true if DECL is a reference type. */
797
798 static inline bool
799 is_reference (tree decl)
800 {
801 return lang_hooks.decls.omp_privatize_by_reference (decl);
802 }
803
804 /* Lookup variables in the decl or field splay trees. The "maybe" form
805 allows for the variable form to not have been entered, otherwise we
806 assert that the variable must have been entered. */
807
808 static inline tree
809 lookup_decl (tree var, omp_context *ctx)
810 {
811 tree *n;
812 n = (tree *) pointer_map_contains (ctx->cb.decl_map, var);
813 return *n;
814 }
815
816 static inline tree
817 maybe_lookup_decl (const_tree var, omp_context *ctx)
818 {
819 tree *n;
820 n = (tree *) pointer_map_contains (ctx->cb.decl_map, var);
821 return n ? *n : NULL_TREE;
822 }
823
824 static inline tree
825 lookup_field (tree var, omp_context *ctx)
826 {
827 splay_tree_node n;
828 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
829 return (tree) n->value;
830 }
831
832 static inline tree
833 lookup_sfield (tree var, omp_context *ctx)
834 {
835 splay_tree_node n;
836 n = splay_tree_lookup (ctx->sfield_map
837 ? ctx->sfield_map : ctx->field_map,
838 (splay_tree_key) var);
839 return (tree) n->value;
840 }
841
842 static inline tree
843 maybe_lookup_field (tree var, omp_context *ctx)
844 {
845 splay_tree_node n;
846 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
847 return n ? (tree) n->value : NULL_TREE;
848 }
849
850 /* Return true if DECL should be copied by pointer. SHARED_CTX is
851 the parallel context if DECL is to be shared. */
852
853 static bool
854 use_pointer_for_field (tree decl, omp_context *shared_ctx)
855 {
856 if (AGGREGATE_TYPE_P (TREE_TYPE (decl)))
857 return true;
858
859 /* We can only use copy-in/copy-out semantics for shared variables
860 when we know the value is not accessible from an outer scope. */
861 if (shared_ctx)
862 {
863 /* ??? Trivially accessible from anywhere. But why would we even
864 be passing an address in this case? Should we simply assert
865 this to be false, or should we have a cleanup pass that removes
866 these from the list of mappings? */
867 if (TREE_STATIC (decl) || DECL_EXTERNAL (decl))
868 return true;
869
870 /* For variables with DECL_HAS_VALUE_EXPR_P set, we cannot tell
871 without analyzing the expression whether or not its location
872 is accessible to anyone else. In the case of nested parallel
873 regions it certainly may be. */
874 if (TREE_CODE (decl) != RESULT_DECL && DECL_HAS_VALUE_EXPR_P (decl))
875 return true;
876
877 /* Do not use copy-in/copy-out for variables that have their
878 address taken. */
879 if (TREE_ADDRESSABLE (decl))
880 return true;
881
882 /* lower_send_shared_vars only uses copy-in, but not copy-out
883 for these. */
884 if (TREE_READONLY (decl)
885 || ((TREE_CODE (decl) == RESULT_DECL
886 || TREE_CODE (decl) == PARM_DECL)
887 && DECL_BY_REFERENCE (decl)))
888 return false;
889
890 /* Disallow copy-in/out in nested parallel if
891 decl is shared in outer parallel, otherwise
892 each thread could store the shared variable
893 in its own copy-in location, making the
894 variable no longer really shared. */
895 if (shared_ctx->is_nested)
896 {
897 omp_context *up;
898
899 for (up = shared_ctx->outer; up; up = up->outer)
900 if (is_taskreg_ctx (up) && maybe_lookup_decl (decl, up))
901 break;
902
903 if (up)
904 {
905 tree c;
906
907 for (c = gimple_omp_taskreg_clauses (up->stmt);
908 c; c = OMP_CLAUSE_CHAIN (c))
909 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
910 && OMP_CLAUSE_DECL (c) == decl)
911 break;
912
913 if (c)
914 goto maybe_mark_addressable_and_ret;
915 }
916 }
917
918 /* For tasks avoid using copy-in/out. As tasks can be
919 deferred or executed in different thread, when GOMP_task
920 returns, the task hasn't necessarily terminated. */
921 if (is_task_ctx (shared_ctx))
922 {
923 tree outer;
924 maybe_mark_addressable_and_ret:
925 outer = maybe_lookup_decl_in_outer_ctx (decl, shared_ctx);
926 if (is_gimple_reg (outer))
927 {
928 /* Taking address of OUTER in lower_send_shared_vars
929 might need regimplification of everything that uses the
930 variable. */
931 if (!task_shared_vars)
932 task_shared_vars = BITMAP_ALLOC (NULL);
933 bitmap_set_bit (task_shared_vars, DECL_UID (outer));
934 TREE_ADDRESSABLE (outer) = 1;
935 }
936 return true;
937 }
938 }
939
940 return false;
941 }
942
943 /* Construct a new automatic decl similar to VAR. */
944
945 static tree
946 omp_copy_decl_2 (tree var, tree name, tree type, omp_context *ctx)
947 {
948 tree copy = copy_var_decl (var, name, type);
949
950 DECL_CONTEXT (copy) = current_function_decl;
951 DECL_CHAIN (copy) = ctx->block_vars;
952 ctx->block_vars = copy;
953
954 return copy;
955 }
956
957 static tree
958 omp_copy_decl_1 (tree var, omp_context *ctx)
959 {
960 return omp_copy_decl_2 (var, DECL_NAME (var), TREE_TYPE (var), ctx);
961 }
962
963 /* Build COMPONENT_REF and set TREE_THIS_VOLATILE and TREE_READONLY on it
964 as appropriate. */
965 static tree
966 omp_build_component_ref (tree obj, tree field)
967 {
968 tree ret = build3 (COMPONENT_REF, TREE_TYPE (field), obj, field, NULL);
969 if (TREE_THIS_VOLATILE (field))
970 TREE_THIS_VOLATILE (ret) |= 1;
971 if (TREE_READONLY (field))
972 TREE_READONLY (ret) |= 1;
973 return ret;
974 }
975
976 /* Build tree nodes to access the field for VAR on the receiver side. */
977
978 static tree
979 build_receiver_ref (tree var, bool by_ref, omp_context *ctx)
980 {
981 tree x, field = lookup_field (var, ctx);
982
983 /* If the receiver record type was remapped in the child function,
984 remap the field into the new record type. */
985 x = maybe_lookup_field (field, ctx);
986 if (x != NULL)
987 field = x;
988
989 x = build_simple_mem_ref (ctx->receiver_decl);
990 x = omp_build_component_ref (x, field);
991 if (by_ref)
992 x = build_simple_mem_ref (x);
993
994 return x;
995 }
996
997 /* Build tree nodes to access VAR in the scope outer to CTX. In the case
998 of a parallel, this is a component reference; for workshare constructs
999 this is some variable. */
1000
1001 static tree
1002 build_outer_var_ref (tree var, omp_context *ctx)
1003 {
1004 tree x;
1005
1006 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx)))
1007 x = var;
1008 else if (is_variable_sized (var))
1009 {
1010 x = TREE_OPERAND (DECL_VALUE_EXPR (var), 0);
1011 x = build_outer_var_ref (x, ctx);
1012 x = build_simple_mem_ref (x);
1013 }
1014 else if (is_taskreg_ctx (ctx))
1015 {
1016 bool by_ref = use_pointer_for_field (var, NULL);
1017 x = build_receiver_ref (var, by_ref, ctx);
1018 }
1019 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
1020 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_KIND_SIMD)
1021 {
1022 /* #pragma omp simd isn't a worksharing construct, and can reference even
1023 private vars in its linear etc. clauses. */
1024 x = NULL_TREE;
1025 if (ctx->outer && is_taskreg_ctx (ctx))
1026 x = lookup_decl (var, ctx->outer);
1027 else if (ctx->outer)
1028 x = maybe_lookup_decl_in_outer_ctx (var, ctx);
1029 if (x == NULL_TREE)
1030 x = var;
1031 }
1032 else if (ctx->outer)
1033 x = lookup_decl (var, ctx->outer);
1034 else if (is_reference (var))
1035 /* This can happen with orphaned constructs. If var is reference, it is
1036 possible it is shared and as such valid. */
1037 x = var;
1038 else
1039 gcc_unreachable ();
1040
1041 if (is_reference (var))
1042 x = build_simple_mem_ref (x);
1043
1044 return x;
1045 }
1046
1047 /* Build tree nodes to access the field for VAR on the sender side. */
1048
1049 static tree
1050 build_sender_ref (tree var, omp_context *ctx)
1051 {
1052 tree field = lookup_sfield (var, ctx);
1053 return omp_build_component_ref (ctx->sender_decl, field);
1054 }
1055
1056 /* Add a new field for VAR inside the structure CTX->SENDER_DECL. */
1057
1058 static void
1059 install_var_field (tree var, bool by_ref, int mask, omp_context *ctx)
1060 {
1061 tree field, type, sfield = NULL_TREE;
1062
1063 gcc_assert ((mask & 1) == 0
1064 || !splay_tree_lookup (ctx->field_map, (splay_tree_key) var));
1065 gcc_assert ((mask & 2) == 0 || !ctx->sfield_map
1066 || !splay_tree_lookup (ctx->sfield_map, (splay_tree_key) var));
1067
1068 type = TREE_TYPE (var);
1069 if (mask & 4)
1070 {
1071 gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
1072 type = build_pointer_type (build_pointer_type (type));
1073 }
1074 else if (by_ref)
1075 type = build_pointer_type (type);
1076 else if ((mask & 3) == 1 && is_reference (var))
1077 type = TREE_TYPE (type);
1078
1079 field = build_decl (DECL_SOURCE_LOCATION (var),
1080 FIELD_DECL, DECL_NAME (var), type);
1081
1082 /* Remember what variable this field was created for. This does have a
1083 side effect of making dwarf2out ignore this member, so for helpful
1084 debugging we clear it later in delete_omp_context. */
1085 DECL_ABSTRACT_ORIGIN (field) = var;
1086 if (type == TREE_TYPE (var))
1087 {
1088 DECL_ALIGN (field) = DECL_ALIGN (var);
1089 DECL_USER_ALIGN (field) = DECL_USER_ALIGN (var);
1090 TREE_THIS_VOLATILE (field) = TREE_THIS_VOLATILE (var);
1091 }
1092 else
1093 DECL_ALIGN (field) = TYPE_ALIGN (type);
1094
1095 if ((mask & 3) == 3)
1096 {
1097 insert_field_into_struct (ctx->record_type, field);
1098 if (ctx->srecord_type)
1099 {
1100 sfield = build_decl (DECL_SOURCE_LOCATION (var),
1101 FIELD_DECL, DECL_NAME (var), type);
1102 DECL_ABSTRACT_ORIGIN (sfield) = var;
1103 DECL_ALIGN (sfield) = DECL_ALIGN (field);
1104 DECL_USER_ALIGN (sfield) = DECL_USER_ALIGN (field);
1105 TREE_THIS_VOLATILE (sfield) = TREE_THIS_VOLATILE (field);
1106 insert_field_into_struct (ctx->srecord_type, sfield);
1107 }
1108 }
1109 else
1110 {
1111 if (ctx->srecord_type == NULL_TREE)
1112 {
1113 tree t;
1114
1115 ctx->srecord_type = lang_hooks.types.make_type (RECORD_TYPE);
1116 ctx->sfield_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
1117 for (t = TYPE_FIELDS (ctx->record_type); t ; t = TREE_CHAIN (t))
1118 {
1119 sfield = build_decl (DECL_SOURCE_LOCATION (var),
1120 FIELD_DECL, DECL_NAME (t), TREE_TYPE (t));
1121 DECL_ABSTRACT_ORIGIN (sfield) = DECL_ABSTRACT_ORIGIN (t);
1122 insert_field_into_struct (ctx->srecord_type, sfield);
1123 splay_tree_insert (ctx->sfield_map,
1124 (splay_tree_key) DECL_ABSTRACT_ORIGIN (t),
1125 (splay_tree_value) sfield);
1126 }
1127 }
1128 sfield = field;
1129 insert_field_into_struct ((mask & 1) ? ctx->record_type
1130 : ctx->srecord_type, field);
1131 }
1132
1133 if (mask & 1)
1134 splay_tree_insert (ctx->field_map, (splay_tree_key) var,
1135 (splay_tree_value) field);
1136 if ((mask & 2) && ctx->sfield_map)
1137 splay_tree_insert (ctx->sfield_map, (splay_tree_key) var,
1138 (splay_tree_value) sfield);
1139 }
1140
1141 static tree
1142 install_var_local (tree var, omp_context *ctx)
1143 {
1144 tree new_var = omp_copy_decl_1 (var, ctx);
1145 insert_decl_map (&ctx->cb, var, new_var);
1146 return new_var;
1147 }
1148
1149 /* Adjust the replacement for DECL in CTX for the new context. This means
1150 copying the DECL_VALUE_EXPR, and fixing up the type. */
1151
1152 static void
1153 fixup_remapped_decl (tree decl, omp_context *ctx, bool private_debug)
1154 {
1155 tree new_decl, size;
1156
1157 new_decl = lookup_decl (decl, ctx);
1158
1159 TREE_TYPE (new_decl) = remap_type (TREE_TYPE (decl), &ctx->cb);
1160
1161 if ((!TREE_CONSTANT (DECL_SIZE (new_decl)) || private_debug)
1162 && DECL_HAS_VALUE_EXPR_P (decl))
1163 {
1164 tree ve = DECL_VALUE_EXPR (decl);
1165 walk_tree (&ve, copy_tree_body_r, &ctx->cb, NULL);
1166 SET_DECL_VALUE_EXPR (new_decl, ve);
1167 DECL_HAS_VALUE_EXPR_P (new_decl) = 1;
1168 }
1169
1170 if (!TREE_CONSTANT (DECL_SIZE (new_decl)))
1171 {
1172 size = remap_decl (DECL_SIZE (decl), &ctx->cb);
1173 if (size == error_mark_node)
1174 size = TYPE_SIZE (TREE_TYPE (new_decl));
1175 DECL_SIZE (new_decl) = size;
1176
1177 size = remap_decl (DECL_SIZE_UNIT (decl), &ctx->cb);
1178 if (size == error_mark_node)
1179 size = TYPE_SIZE_UNIT (TREE_TYPE (new_decl));
1180 DECL_SIZE_UNIT (new_decl) = size;
1181 }
1182 }
1183
1184 /* The callback for remap_decl. Search all containing contexts for a
1185 mapping of the variable; this avoids having to duplicate the splay
1186 tree ahead of time. We know a mapping doesn't already exist in the
1187 given context. Create new mappings to implement default semantics. */
1188
1189 static tree
1190 omp_copy_decl (tree var, copy_body_data *cb)
1191 {
1192 omp_context *ctx = (omp_context *) cb;
1193 tree new_var;
1194
1195 if (TREE_CODE (var) == LABEL_DECL)
1196 {
1197 new_var = create_artificial_label (DECL_SOURCE_LOCATION (var));
1198 DECL_CONTEXT (new_var) = current_function_decl;
1199 insert_decl_map (&ctx->cb, var, new_var);
1200 return new_var;
1201 }
1202
1203 while (!is_taskreg_ctx (ctx))
1204 {
1205 ctx = ctx->outer;
1206 if (ctx == NULL)
1207 return var;
1208 new_var = maybe_lookup_decl (var, ctx);
1209 if (new_var)
1210 return new_var;
1211 }
1212
1213 if (is_global_var (var) || decl_function_context (var) != ctx->cb.src_fn)
1214 return var;
1215
1216 return error_mark_node;
1217 }
1218
1219
1220 /* Return the parallel region associated with STMT. */
1221
1222 /* Debugging dumps for parallel regions. */
1223 void dump_omp_region (FILE *, struct omp_region *, int);
1224 void debug_omp_region (struct omp_region *);
1225 void debug_all_omp_regions (void);
1226
1227 /* Dump the parallel region tree rooted at REGION. */
1228
1229 void
1230 dump_omp_region (FILE *file, struct omp_region *region, int indent)
1231 {
1232 fprintf (file, "%*sbb %d: %s\n", indent, "", region->entry->index,
1233 gimple_code_name[region->type]);
1234
1235 if (region->inner)
1236 dump_omp_region (file, region->inner, indent + 4);
1237
1238 if (region->cont)
1239 {
1240 fprintf (file, "%*sbb %d: GIMPLE_OMP_CONTINUE\n", indent, "",
1241 region->cont->index);
1242 }
1243
1244 if (region->exit)
1245 fprintf (file, "%*sbb %d: GIMPLE_OMP_RETURN\n", indent, "",
1246 region->exit->index);
1247 else
1248 fprintf (file, "%*s[no exit marker]\n", indent, "");
1249
1250 if (region->next)
1251 dump_omp_region (file, region->next, indent);
1252 }
1253
1254 DEBUG_FUNCTION void
1255 debug_omp_region (struct omp_region *region)
1256 {
1257 dump_omp_region (stderr, region, 0);
1258 }
1259
1260 DEBUG_FUNCTION void
1261 debug_all_omp_regions (void)
1262 {
1263 dump_omp_region (stderr, root_omp_region, 0);
1264 }
1265
1266
1267 /* Create a new parallel region starting at STMT inside region PARENT. */
1268
1269 static struct omp_region *
1270 new_omp_region (basic_block bb, enum gimple_code type,
1271 struct omp_region *parent)
1272 {
1273 struct omp_region *region = XCNEW (struct omp_region);
1274
1275 region->outer = parent;
1276 region->entry = bb;
1277 region->type = type;
1278
1279 if (parent)
1280 {
1281 /* This is a nested region. Add it to the list of inner
1282 regions in PARENT. */
1283 region->next = parent->inner;
1284 parent->inner = region;
1285 }
1286 else
1287 {
1288 /* This is a toplevel region. Add it to the list of toplevel
1289 regions in ROOT_OMP_REGION. */
1290 region->next = root_omp_region;
1291 root_omp_region = region;
1292 }
1293
1294 return region;
1295 }
1296
1297 /* Release the memory associated with the region tree rooted at REGION. */
1298
1299 static void
1300 free_omp_region_1 (struct omp_region *region)
1301 {
1302 struct omp_region *i, *n;
1303
1304 for (i = region->inner; i ; i = n)
1305 {
1306 n = i->next;
1307 free_omp_region_1 (i);
1308 }
1309
1310 free (region);
1311 }
1312
1313 /* Release the memory for the entire omp region tree. */
1314
1315 void
1316 free_omp_regions (void)
1317 {
1318 struct omp_region *r, *n;
1319 for (r = root_omp_region; r ; r = n)
1320 {
1321 n = r->next;
1322 free_omp_region_1 (r);
1323 }
1324 root_omp_region = NULL;
1325 }
1326
1327
1328 /* Create a new context, with OUTER_CTX being the surrounding context. */
1329
1330 static omp_context *
1331 new_omp_context (gimple stmt, omp_context *outer_ctx)
1332 {
1333 omp_context *ctx = XCNEW (omp_context);
1334
1335 splay_tree_insert (all_contexts, (splay_tree_key) stmt,
1336 (splay_tree_value) ctx);
1337 ctx->stmt = stmt;
1338
1339 if (outer_ctx)
1340 {
1341 ctx->outer = outer_ctx;
1342 ctx->cb = outer_ctx->cb;
1343 ctx->cb.block = NULL;
1344 ctx->depth = outer_ctx->depth + 1;
1345 }
1346 else
1347 {
1348 ctx->cb.src_fn = current_function_decl;
1349 ctx->cb.dst_fn = current_function_decl;
1350 ctx->cb.src_node = cgraph_get_node (current_function_decl);
1351 gcc_checking_assert (ctx->cb.src_node);
1352 ctx->cb.dst_node = ctx->cb.src_node;
1353 ctx->cb.src_cfun = cfun;
1354 ctx->cb.copy_decl = omp_copy_decl;
1355 ctx->cb.eh_lp_nr = 0;
1356 ctx->cb.transform_call_graph_edges = CB_CGE_MOVE;
1357 ctx->depth = 1;
1358 }
1359
1360 ctx->cb.decl_map = pointer_map_create ();
1361
1362 return ctx;
1363 }
1364
1365 static gimple_seq maybe_catch_exception (gimple_seq);
1366
1367 /* Finalize task copyfn. */
1368
1369 static void
1370 finalize_task_copyfn (gimple task_stmt)
1371 {
1372 struct function *child_cfun;
1373 tree child_fn;
1374 gimple_seq seq = NULL, new_seq;
1375 gimple bind;
1376
1377 child_fn = gimple_omp_task_copy_fn (task_stmt);
1378 if (child_fn == NULL_TREE)
1379 return;
1380
1381 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
1382 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
1383
1384 push_cfun (child_cfun);
1385 bind = gimplify_body (child_fn, false);
1386 gimple_seq_add_stmt (&seq, bind);
1387 new_seq = maybe_catch_exception (seq);
1388 if (new_seq != seq)
1389 {
1390 bind = gimple_build_bind (NULL, new_seq, NULL);
1391 seq = NULL;
1392 gimple_seq_add_stmt (&seq, bind);
1393 }
1394 gimple_set_body (child_fn, seq);
1395 pop_cfun ();
1396
1397 /* Inform the callgraph about the new function. */
1398 cgraph_add_new_function (child_fn, false);
1399 }
1400
1401 /* Destroy a omp_context data structures. Called through the splay tree
1402 value delete callback. */
1403
1404 static void
1405 delete_omp_context (splay_tree_value value)
1406 {
1407 omp_context *ctx = (omp_context *) value;
1408
1409 pointer_map_destroy (ctx->cb.decl_map);
1410
1411 if (ctx->field_map)
1412 splay_tree_delete (ctx->field_map);
1413 if (ctx->sfield_map)
1414 splay_tree_delete (ctx->sfield_map);
1415
1416 /* We hijacked DECL_ABSTRACT_ORIGIN earlier. We need to clear it before
1417 it produces corrupt debug information. */
1418 if (ctx->record_type)
1419 {
1420 tree t;
1421 for (t = TYPE_FIELDS (ctx->record_type); t ; t = DECL_CHAIN (t))
1422 DECL_ABSTRACT_ORIGIN (t) = NULL;
1423 }
1424 if (ctx->srecord_type)
1425 {
1426 tree t;
1427 for (t = TYPE_FIELDS (ctx->srecord_type); t ; t = DECL_CHAIN (t))
1428 DECL_ABSTRACT_ORIGIN (t) = NULL;
1429 }
1430
1431 if (is_task_ctx (ctx))
1432 finalize_task_copyfn (ctx->stmt);
1433
1434 XDELETE (ctx);
1435 }
1436
1437 /* Fix up RECEIVER_DECL with a type that has been remapped to the child
1438 context. */
1439
1440 static void
1441 fixup_child_record_type (omp_context *ctx)
1442 {
1443 tree f, type = ctx->record_type;
1444
1445 /* ??? It isn't sufficient to just call remap_type here, because
1446 variably_modified_type_p doesn't work the way we expect for
1447 record types. Testing each field for whether it needs remapping
1448 and creating a new record by hand works, however. */
1449 for (f = TYPE_FIELDS (type); f ; f = DECL_CHAIN (f))
1450 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
1451 break;
1452 if (f)
1453 {
1454 tree name, new_fields = NULL;
1455
1456 type = lang_hooks.types.make_type (RECORD_TYPE);
1457 name = DECL_NAME (TYPE_NAME (ctx->record_type));
1458 name = build_decl (DECL_SOURCE_LOCATION (ctx->receiver_decl),
1459 TYPE_DECL, name, type);
1460 TYPE_NAME (type) = name;
1461
1462 for (f = TYPE_FIELDS (ctx->record_type); f ; f = DECL_CHAIN (f))
1463 {
1464 tree new_f = copy_node (f);
1465 DECL_CONTEXT (new_f) = type;
1466 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &ctx->cb);
1467 DECL_CHAIN (new_f) = new_fields;
1468 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &ctx->cb, NULL);
1469 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r,
1470 &ctx->cb, NULL);
1471 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
1472 &ctx->cb, NULL);
1473 new_fields = new_f;
1474
1475 /* Arrange to be able to look up the receiver field
1476 given the sender field. */
1477 splay_tree_insert (ctx->field_map, (splay_tree_key) f,
1478 (splay_tree_value) new_f);
1479 }
1480 TYPE_FIELDS (type) = nreverse (new_fields);
1481 layout_type (type);
1482 }
1483
1484 TREE_TYPE (ctx->receiver_decl) = build_pointer_type (type);
1485 }
1486
1487 /* Instantiate decls as necessary in CTX to satisfy the data sharing
1488 specified by CLAUSES. */
1489
1490 static void
1491 scan_sharing_clauses (tree clauses, omp_context *ctx)
1492 {
1493 tree c, decl;
1494 bool scan_array_reductions = false;
1495
1496 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1497 {
1498 bool by_ref;
1499
1500 switch (OMP_CLAUSE_CODE (c))
1501 {
1502 case OMP_CLAUSE_PRIVATE:
1503 decl = OMP_CLAUSE_DECL (c);
1504 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
1505 goto do_private;
1506 else if (!is_variable_sized (decl))
1507 install_var_local (decl, ctx);
1508 break;
1509
1510 case OMP_CLAUSE_SHARED:
1511 /* Ignore shared directives in teams construct. */
1512 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
1513 break;
1514 gcc_assert (is_taskreg_ctx (ctx));
1515 decl = OMP_CLAUSE_DECL (c);
1516 gcc_assert (!COMPLETE_TYPE_P (TREE_TYPE (decl))
1517 || !is_variable_sized (decl));
1518 /* Global variables don't need to be copied,
1519 the receiver side will use them directly. */
1520 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1521 break;
1522 by_ref = use_pointer_for_field (decl, ctx);
1523 if (! TREE_READONLY (decl)
1524 || TREE_ADDRESSABLE (decl)
1525 || by_ref
1526 || is_reference (decl))
1527 {
1528 install_var_field (decl, by_ref, 3, ctx);
1529 install_var_local (decl, ctx);
1530 break;
1531 }
1532 /* We don't need to copy const scalar vars back. */
1533 OMP_CLAUSE_SET_CODE (c, OMP_CLAUSE_FIRSTPRIVATE);
1534 goto do_private;
1535
1536 case OMP_CLAUSE_LASTPRIVATE:
1537 /* Let the corresponding firstprivate clause create
1538 the variable. */
1539 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1540 break;
1541 /* FALLTHRU */
1542
1543 case OMP_CLAUSE_FIRSTPRIVATE:
1544 case OMP_CLAUSE_REDUCTION:
1545 case OMP_CLAUSE_LINEAR:
1546 decl = OMP_CLAUSE_DECL (c);
1547 do_private:
1548 if (is_variable_sized (decl))
1549 {
1550 if (is_task_ctx (ctx))
1551 install_var_field (decl, false, 1, ctx);
1552 break;
1553 }
1554 else if (is_taskreg_ctx (ctx))
1555 {
1556 bool global
1557 = is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx));
1558 by_ref = use_pointer_for_field (decl, NULL);
1559
1560 if (is_task_ctx (ctx)
1561 && (global || by_ref || is_reference (decl)))
1562 {
1563 install_var_field (decl, false, 1, ctx);
1564 if (!global)
1565 install_var_field (decl, by_ref, 2, ctx);
1566 }
1567 else if (!global)
1568 install_var_field (decl, by_ref, 3, ctx);
1569 }
1570 install_var_local (decl, ctx);
1571 break;
1572
1573 case OMP_CLAUSE__LOOPTEMP_:
1574 gcc_assert (is_parallel_ctx (ctx));
1575 decl = OMP_CLAUSE_DECL (c);
1576 install_var_field (decl, false, 3, ctx);
1577 install_var_local (decl, ctx);
1578 break;
1579
1580 case OMP_CLAUSE_COPYPRIVATE:
1581 case OMP_CLAUSE_COPYIN:
1582 decl = OMP_CLAUSE_DECL (c);
1583 by_ref = use_pointer_for_field (decl, NULL);
1584 install_var_field (decl, by_ref, 3, ctx);
1585 break;
1586
1587 case OMP_CLAUSE_DEFAULT:
1588 ctx->default_kind = OMP_CLAUSE_DEFAULT_KIND (c);
1589 break;
1590
1591 case OMP_CLAUSE_FINAL:
1592 case OMP_CLAUSE_IF:
1593 case OMP_CLAUSE_NUM_THREADS:
1594 case OMP_CLAUSE_NUM_TEAMS:
1595 case OMP_CLAUSE_THREAD_LIMIT:
1596 case OMP_CLAUSE_DEVICE:
1597 case OMP_CLAUSE_SCHEDULE:
1598 case OMP_CLAUSE_DIST_SCHEDULE:
1599 case OMP_CLAUSE_DEPEND:
1600 if (ctx->outer)
1601 scan_omp_op (&OMP_CLAUSE_OPERAND (c, 0), ctx->outer);
1602 break;
1603
1604 case OMP_CLAUSE_TO:
1605 case OMP_CLAUSE_FROM:
1606 case OMP_CLAUSE_MAP:
1607 if (ctx->outer)
1608 scan_omp_op (&OMP_CLAUSE_SIZE (c), ctx->outer);
1609 decl = OMP_CLAUSE_DECL (c);
1610 /* Global variables with "omp declare target" attribute
1611 don't need to be copied, the receiver side will use them
1612 directly. */
1613 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1614 && DECL_P (decl)
1615 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
1616 && lookup_attribute ("omp declare target",
1617 DECL_ATTRIBUTES (decl)))
1618 break;
1619 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1620 && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER)
1621 {
1622 /* Ignore OMP_CLAUSE_MAP_POINTER kind for arrays in
1623 #pragma omp target data, there is nothing to map for
1624 those. */
1625 if (gimple_omp_target_kind (ctx->stmt) == GF_OMP_TARGET_KIND_DATA
1626 && !POINTER_TYPE_P (TREE_TYPE (decl)))
1627 break;
1628 }
1629 if (DECL_P (decl))
1630 {
1631 if (DECL_SIZE (decl)
1632 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
1633 {
1634 tree decl2 = DECL_VALUE_EXPR (decl);
1635 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
1636 decl2 = TREE_OPERAND (decl2, 0);
1637 gcc_assert (DECL_P (decl2));
1638 install_var_field (decl2, true, 3, ctx);
1639 install_var_local (decl2, ctx);
1640 install_var_local (decl, ctx);
1641 }
1642 else
1643 {
1644 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1645 && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER
1646 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
1647 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1648 install_var_field (decl, true, 7, ctx);
1649 else
1650 install_var_field (decl, true, 3, ctx);
1651 if (gimple_omp_target_kind (ctx->stmt)
1652 == GF_OMP_TARGET_KIND_REGION)
1653 install_var_local (decl, ctx);
1654 }
1655 }
1656 else
1657 {
1658 tree base = get_base_address (decl);
1659 tree nc = OMP_CLAUSE_CHAIN (c);
1660 if (DECL_P (base)
1661 && nc != NULL_TREE
1662 && OMP_CLAUSE_CODE (nc) == OMP_CLAUSE_MAP
1663 && OMP_CLAUSE_DECL (nc) == base
1664 && OMP_CLAUSE_MAP_KIND (nc) == OMP_CLAUSE_MAP_POINTER
1665 && integer_zerop (OMP_CLAUSE_SIZE (nc)))
1666 {
1667 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c) = 1;
1668 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (nc) = 1;
1669 }
1670 else
1671 {
1672 gcc_assert (!splay_tree_lookup (ctx->field_map,
1673 (splay_tree_key) decl));
1674 tree field
1675 = build_decl (OMP_CLAUSE_LOCATION (c),
1676 FIELD_DECL, NULL_TREE, ptr_type_node);
1677 DECL_ALIGN (field) = TYPE_ALIGN (ptr_type_node);
1678 insert_field_into_struct (ctx->record_type, field);
1679 splay_tree_insert (ctx->field_map, (splay_tree_key) decl,
1680 (splay_tree_value) field);
1681 }
1682 }
1683 break;
1684
1685 case OMP_CLAUSE_NOWAIT:
1686 case OMP_CLAUSE_ORDERED:
1687 case OMP_CLAUSE_COLLAPSE:
1688 case OMP_CLAUSE_UNTIED:
1689 case OMP_CLAUSE_MERGEABLE:
1690 case OMP_CLAUSE_PROC_BIND:
1691 case OMP_CLAUSE_SAFELEN:
1692 break;
1693
1694 case OMP_CLAUSE_ALIGNED:
1695 decl = OMP_CLAUSE_DECL (c);
1696 if (is_global_var (decl)
1697 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1698 install_var_local (decl, ctx);
1699 break;
1700
1701 default:
1702 gcc_unreachable ();
1703 }
1704 }
1705
1706 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1707 {
1708 switch (OMP_CLAUSE_CODE (c))
1709 {
1710 case OMP_CLAUSE_LASTPRIVATE:
1711 /* Let the corresponding firstprivate clause create
1712 the variable. */
1713 if (OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
1714 scan_array_reductions = true;
1715 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1716 break;
1717 /* FALLTHRU */
1718
1719 case OMP_CLAUSE_PRIVATE:
1720 case OMP_CLAUSE_FIRSTPRIVATE:
1721 case OMP_CLAUSE_REDUCTION:
1722 case OMP_CLAUSE_LINEAR:
1723 decl = OMP_CLAUSE_DECL (c);
1724 if (is_variable_sized (decl))
1725 install_var_local (decl, ctx);
1726 fixup_remapped_decl (decl, ctx,
1727 OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE
1728 && OMP_CLAUSE_PRIVATE_DEBUG (c));
1729 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1730 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1731 scan_array_reductions = true;
1732 break;
1733
1734 case OMP_CLAUSE_SHARED:
1735 /* Ignore shared directives in teams construct. */
1736 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
1737 break;
1738 decl = OMP_CLAUSE_DECL (c);
1739 if (! is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1740 fixup_remapped_decl (decl, ctx, false);
1741 break;
1742
1743 case OMP_CLAUSE_MAP:
1744 if (gimple_omp_target_kind (ctx->stmt) == GF_OMP_TARGET_KIND_DATA)
1745 break;
1746 decl = OMP_CLAUSE_DECL (c);
1747 if (DECL_P (decl)
1748 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
1749 && lookup_attribute ("omp declare target",
1750 DECL_ATTRIBUTES (decl)))
1751 break;
1752 if (DECL_P (decl))
1753 {
1754 if (OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER
1755 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
1756 && !COMPLETE_TYPE_P (TREE_TYPE (decl)))
1757 {
1758 tree new_decl = lookup_decl (decl, ctx);
1759 TREE_TYPE (new_decl)
1760 = remap_type (TREE_TYPE (decl), &ctx->cb);
1761 }
1762 else if (DECL_SIZE (decl)
1763 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
1764 {
1765 tree decl2 = DECL_VALUE_EXPR (decl);
1766 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
1767 decl2 = TREE_OPERAND (decl2, 0);
1768 gcc_assert (DECL_P (decl2));
1769 fixup_remapped_decl (decl2, ctx, false);
1770 fixup_remapped_decl (decl, ctx, true);
1771 }
1772 else
1773 fixup_remapped_decl (decl, ctx, false);
1774 }
1775 break;
1776
1777 case OMP_CLAUSE_COPYPRIVATE:
1778 case OMP_CLAUSE_COPYIN:
1779 case OMP_CLAUSE_DEFAULT:
1780 case OMP_CLAUSE_IF:
1781 case OMP_CLAUSE_NUM_THREADS:
1782 case OMP_CLAUSE_NUM_TEAMS:
1783 case OMP_CLAUSE_THREAD_LIMIT:
1784 case OMP_CLAUSE_DEVICE:
1785 case OMP_CLAUSE_SCHEDULE:
1786 case OMP_CLAUSE_DIST_SCHEDULE:
1787 case OMP_CLAUSE_NOWAIT:
1788 case OMP_CLAUSE_ORDERED:
1789 case OMP_CLAUSE_COLLAPSE:
1790 case OMP_CLAUSE_UNTIED:
1791 case OMP_CLAUSE_FINAL:
1792 case OMP_CLAUSE_MERGEABLE:
1793 case OMP_CLAUSE_PROC_BIND:
1794 case OMP_CLAUSE_SAFELEN:
1795 case OMP_CLAUSE_ALIGNED:
1796 case OMP_CLAUSE_DEPEND:
1797 case OMP_CLAUSE__LOOPTEMP_:
1798 case OMP_CLAUSE_TO:
1799 case OMP_CLAUSE_FROM:
1800 break;
1801
1802 default:
1803 gcc_unreachable ();
1804 }
1805 }
1806
1807 if (scan_array_reductions)
1808 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1809 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1810 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1811 {
1812 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c), ctx);
1813 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
1814 }
1815 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
1816 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
1817 scan_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
1818 }
1819
1820 /* Create a new name for omp child function. Returns an identifier. */
1821
1822 static GTY(()) unsigned int tmp_ompfn_id_num;
1823
1824 static tree
1825 create_omp_child_function_name (bool task_copy)
1826 {
1827 return (clone_function_name (current_function_decl,
1828 task_copy ? "_omp_cpyfn" : "_omp_fn"));
1829 }
1830
1831 /* Build a decl for the omp child function. It'll not contain a body
1832 yet, just the bare decl. */
1833
1834 static void
1835 create_omp_child_function (omp_context *ctx, bool task_copy)
1836 {
1837 tree decl, type, name, t;
1838
1839 name = create_omp_child_function_name (task_copy);
1840 if (task_copy)
1841 type = build_function_type_list (void_type_node, ptr_type_node,
1842 ptr_type_node, NULL_TREE);
1843 else
1844 type = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
1845
1846 decl = build_decl (gimple_location (ctx->stmt),
1847 FUNCTION_DECL, name, type);
1848
1849 if (!task_copy)
1850 ctx->cb.dst_fn = decl;
1851 else
1852 gimple_omp_task_set_copy_fn (ctx->stmt, decl);
1853
1854 TREE_STATIC (decl) = 1;
1855 TREE_USED (decl) = 1;
1856 DECL_ARTIFICIAL (decl) = 1;
1857 DECL_NAMELESS (decl) = 1;
1858 DECL_IGNORED_P (decl) = 0;
1859 TREE_PUBLIC (decl) = 0;
1860 DECL_UNINLINABLE (decl) = 1;
1861 DECL_EXTERNAL (decl) = 0;
1862 DECL_CONTEXT (decl) = NULL_TREE;
1863 DECL_INITIAL (decl) = make_node (BLOCK);
1864 bool target_p = false;
1865 if (lookup_attribute ("omp declare target",
1866 DECL_ATTRIBUTES (current_function_decl)))
1867 target_p = true;
1868 else
1869 {
1870 omp_context *octx;
1871 for (octx = ctx; octx; octx = octx->outer)
1872 if (gimple_code (octx->stmt) == GIMPLE_OMP_TARGET
1873 && gimple_omp_target_kind (octx->stmt)
1874 == GF_OMP_TARGET_KIND_REGION)
1875 {
1876 target_p = true;
1877 break;
1878 }
1879 }
1880 if (target_p)
1881 DECL_ATTRIBUTES (decl)
1882 = tree_cons (get_identifier ("omp declare target"),
1883 NULL_TREE, DECL_ATTRIBUTES (decl));
1884
1885 t = build_decl (DECL_SOURCE_LOCATION (decl),
1886 RESULT_DECL, NULL_TREE, void_type_node);
1887 DECL_ARTIFICIAL (t) = 1;
1888 DECL_IGNORED_P (t) = 1;
1889 DECL_CONTEXT (t) = decl;
1890 DECL_RESULT (decl) = t;
1891
1892 t = build_decl (DECL_SOURCE_LOCATION (decl),
1893 PARM_DECL, get_identifier (".omp_data_i"), ptr_type_node);
1894 DECL_ARTIFICIAL (t) = 1;
1895 DECL_NAMELESS (t) = 1;
1896 DECL_ARG_TYPE (t) = ptr_type_node;
1897 DECL_CONTEXT (t) = current_function_decl;
1898 TREE_USED (t) = 1;
1899 DECL_ARGUMENTS (decl) = t;
1900 if (!task_copy)
1901 ctx->receiver_decl = t;
1902 else
1903 {
1904 t = build_decl (DECL_SOURCE_LOCATION (decl),
1905 PARM_DECL, get_identifier (".omp_data_o"),
1906 ptr_type_node);
1907 DECL_ARTIFICIAL (t) = 1;
1908 DECL_NAMELESS (t) = 1;
1909 DECL_ARG_TYPE (t) = ptr_type_node;
1910 DECL_CONTEXT (t) = current_function_decl;
1911 TREE_USED (t) = 1;
1912 TREE_ADDRESSABLE (t) = 1;
1913 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
1914 DECL_ARGUMENTS (decl) = t;
1915 }
1916
1917 /* Allocate memory for the function structure. The call to
1918 allocate_struct_function clobbers CFUN, so we need to restore
1919 it afterward. */
1920 push_struct_function (decl);
1921 cfun->function_end_locus = gimple_location (ctx->stmt);
1922 pop_cfun ();
1923 }
1924
1925 /* Callback for walk_gimple_seq. Check if combined parallel
1926 contains gimple_omp_for_combined_into_p OMP_FOR. */
1927
1928 static tree
1929 find_combined_for (gimple_stmt_iterator *gsi_p,
1930 bool *handled_ops_p,
1931 struct walk_stmt_info *wi)
1932 {
1933 gimple stmt = gsi_stmt (*gsi_p);
1934
1935 *handled_ops_p = true;
1936 switch (gimple_code (stmt))
1937 {
1938 WALK_SUBSTMTS;
1939
1940 case GIMPLE_OMP_FOR:
1941 if (gimple_omp_for_combined_into_p (stmt)
1942 && gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR)
1943 {
1944 wi->info = stmt;
1945 return integer_zero_node;
1946 }
1947 break;
1948 default:
1949 break;
1950 }
1951 return NULL;
1952 }
1953
1954 /* Scan an OpenMP parallel directive. */
1955
1956 static void
1957 scan_omp_parallel (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
1958 {
1959 omp_context *ctx;
1960 tree name;
1961 gimple stmt = gsi_stmt (*gsi);
1962
1963 /* Ignore parallel directives with empty bodies, unless there
1964 are copyin clauses. */
1965 if (optimize > 0
1966 && empty_body_p (gimple_omp_body (stmt))
1967 && find_omp_clause (gimple_omp_parallel_clauses (stmt),
1968 OMP_CLAUSE_COPYIN) == NULL)
1969 {
1970 gsi_replace (gsi, gimple_build_nop (), false);
1971 return;
1972 }
1973
1974 if (gimple_omp_parallel_combined_p (stmt))
1975 {
1976 gimple for_stmt;
1977 struct walk_stmt_info wi;
1978
1979 memset (&wi, 0, sizeof (wi));
1980 wi.val_only = true;
1981 walk_gimple_seq (gimple_omp_body (stmt),
1982 find_combined_for, NULL, &wi);
1983 for_stmt = (gimple) wi.info;
1984 if (for_stmt)
1985 {
1986 struct omp_for_data fd;
1987 extract_omp_for_data (for_stmt, &fd, NULL);
1988 /* We need two temporaries with fd.loop.v type (istart/iend)
1989 and then (fd.collapse - 1) temporaries with the same
1990 type for count2 ... countN-1 vars if not constant. */
1991 size_t count = 2, i;
1992 tree type = fd.iter_type;
1993 if (fd.collapse > 1
1994 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
1995 count += fd.collapse - 1;
1996 for (i = 0; i < count; i++)
1997 {
1998 tree temp = create_tmp_var (type, NULL);
1999 tree c = build_omp_clause (UNKNOWN_LOCATION,
2000 OMP_CLAUSE__LOOPTEMP_);
2001 OMP_CLAUSE_DECL (c) = temp;
2002 OMP_CLAUSE_CHAIN (c) = gimple_omp_parallel_clauses (stmt);
2003 gimple_omp_parallel_set_clauses (stmt, c);
2004 }
2005 }
2006 }
2007
2008 ctx = new_omp_context (stmt, outer_ctx);
2009 if (taskreg_nesting_level > 1)
2010 ctx->is_nested = true;
2011 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2012 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2013 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2014 name = create_tmp_var_name (".omp_data_s");
2015 name = build_decl (gimple_location (stmt),
2016 TYPE_DECL, name, ctx->record_type);
2017 DECL_ARTIFICIAL (name) = 1;
2018 DECL_NAMELESS (name) = 1;
2019 TYPE_NAME (ctx->record_type) = name;
2020 create_omp_child_function (ctx, false);
2021 gimple_omp_parallel_set_child_fn (stmt, ctx->cb.dst_fn);
2022
2023 scan_sharing_clauses (gimple_omp_parallel_clauses (stmt), ctx);
2024 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2025
2026 if (TYPE_FIELDS (ctx->record_type) == NULL)
2027 ctx->record_type = ctx->receiver_decl = NULL;
2028 else
2029 {
2030 layout_type (ctx->record_type);
2031 fixup_child_record_type (ctx);
2032 }
2033 }
2034
2035 /* Scan an OpenMP task directive. */
2036
2037 static void
2038 scan_omp_task (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
2039 {
2040 omp_context *ctx;
2041 tree name, t;
2042 gimple stmt = gsi_stmt (*gsi);
2043 location_t loc = gimple_location (stmt);
2044
2045 /* Ignore task directives with empty bodies. */
2046 if (optimize > 0
2047 && empty_body_p (gimple_omp_body (stmt)))
2048 {
2049 gsi_replace (gsi, gimple_build_nop (), false);
2050 return;
2051 }
2052
2053 ctx = new_omp_context (stmt, outer_ctx);
2054 if (taskreg_nesting_level > 1)
2055 ctx->is_nested = true;
2056 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2057 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2058 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2059 name = create_tmp_var_name (".omp_data_s");
2060 name = build_decl (gimple_location (stmt),
2061 TYPE_DECL, name, ctx->record_type);
2062 DECL_ARTIFICIAL (name) = 1;
2063 DECL_NAMELESS (name) = 1;
2064 TYPE_NAME (ctx->record_type) = name;
2065 create_omp_child_function (ctx, false);
2066 gimple_omp_task_set_child_fn (stmt, ctx->cb.dst_fn);
2067
2068 scan_sharing_clauses (gimple_omp_task_clauses (stmt), ctx);
2069
2070 if (ctx->srecord_type)
2071 {
2072 name = create_tmp_var_name (".omp_data_a");
2073 name = build_decl (gimple_location (stmt),
2074 TYPE_DECL, name, ctx->srecord_type);
2075 DECL_ARTIFICIAL (name) = 1;
2076 DECL_NAMELESS (name) = 1;
2077 TYPE_NAME (ctx->srecord_type) = name;
2078 create_omp_child_function (ctx, true);
2079 }
2080
2081 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2082
2083 if (TYPE_FIELDS (ctx->record_type) == NULL)
2084 {
2085 ctx->record_type = ctx->receiver_decl = NULL;
2086 t = build_int_cst (long_integer_type_node, 0);
2087 gimple_omp_task_set_arg_size (stmt, t);
2088 t = build_int_cst (long_integer_type_node, 1);
2089 gimple_omp_task_set_arg_align (stmt, t);
2090 }
2091 else
2092 {
2093 tree *p, vla_fields = NULL_TREE, *q = &vla_fields;
2094 /* Move VLA fields to the end. */
2095 p = &TYPE_FIELDS (ctx->record_type);
2096 while (*p)
2097 if (!TYPE_SIZE_UNIT (TREE_TYPE (*p))
2098 || ! TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (*p))))
2099 {
2100 *q = *p;
2101 *p = TREE_CHAIN (*p);
2102 TREE_CHAIN (*q) = NULL_TREE;
2103 q = &TREE_CHAIN (*q);
2104 }
2105 else
2106 p = &DECL_CHAIN (*p);
2107 *p = vla_fields;
2108 layout_type (ctx->record_type);
2109 fixup_child_record_type (ctx);
2110 if (ctx->srecord_type)
2111 layout_type (ctx->srecord_type);
2112 t = fold_convert_loc (loc, long_integer_type_node,
2113 TYPE_SIZE_UNIT (ctx->record_type));
2114 gimple_omp_task_set_arg_size (stmt, t);
2115 t = build_int_cst (long_integer_type_node,
2116 TYPE_ALIGN_UNIT (ctx->record_type));
2117 gimple_omp_task_set_arg_align (stmt, t);
2118 }
2119 }
2120
2121
2122 /* Scan an OpenMP loop directive. */
2123
2124 static void
2125 scan_omp_for (gimple stmt, omp_context *outer_ctx)
2126 {
2127 omp_context *ctx;
2128 size_t i;
2129
2130 ctx = new_omp_context (stmt, outer_ctx);
2131
2132 scan_sharing_clauses (gimple_omp_for_clauses (stmt), ctx);
2133
2134 scan_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
2135 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
2136 {
2137 scan_omp_op (gimple_omp_for_index_ptr (stmt, i), ctx);
2138 scan_omp_op (gimple_omp_for_initial_ptr (stmt, i), ctx);
2139 scan_omp_op (gimple_omp_for_final_ptr (stmt, i), ctx);
2140 scan_omp_op (gimple_omp_for_incr_ptr (stmt, i), ctx);
2141 }
2142 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2143 }
2144
2145 /* Scan an OpenMP sections directive. */
2146
2147 static void
2148 scan_omp_sections (gimple stmt, omp_context *outer_ctx)
2149 {
2150 omp_context *ctx;
2151
2152 ctx = new_omp_context (stmt, outer_ctx);
2153 scan_sharing_clauses (gimple_omp_sections_clauses (stmt), ctx);
2154 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2155 }
2156
2157 /* Scan an OpenMP single directive. */
2158
2159 static void
2160 scan_omp_single (gimple stmt, omp_context *outer_ctx)
2161 {
2162 omp_context *ctx;
2163 tree name;
2164
2165 ctx = new_omp_context (stmt, outer_ctx);
2166 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2167 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2168 name = create_tmp_var_name (".omp_copy_s");
2169 name = build_decl (gimple_location (stmt),
2170 TYPE_DECL, name, ctx->record_type);
2171 TYPE_NAME (ctx->record_type) = name;
2172
2173 scan_sharing_clauses (gimple_omp_single_clauses (stmt), ctx);
2174 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2175
2176 if (TYPE_FIELDS (ctx->record_type) == NULL)
2177 ctx->record_type = NULL;
2178 else
2179 layout_type (ctx->record_type);
2180 }
2181
2182 /* Scan an OpenMP target{, data, update} directive. */
2183
2184 static void
2185 scan_omp_target (gimple stmt, omp_context *outer_ctx)
2186 {
2187 omp_context *ctx;
2188 tree name;
2189 int kind = gimple_omp_target_kind (stmt);
2190
2191 ctx = new_omp_context (stmt, outer_ctx);
2192 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2193 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2194 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2195 name = create_tmp_var_name (".omp_data_t");
2196 name = build_decl (gimple_location (stmt),
2197 TYPE_DECL, name, ctx->record_type);
2198 DECL_ARTIFICIAL (name) = 1;
2199 DECL_NAMELESS (name) = 1;
2200 TYPE_NAME (ctx->record_type) = name;
2201 if (kind == GF_OMP_TARGET_KIND_REGION)
2202 {
2203 create_omp_child_function (ctx, false);
2204 gimple_omp_target_set_child_fn (stmt, ctx->cb.dst_fn);
2205 }
2206
2207 scan_sharing_clauses (gimple_omp_target_clauses (stmt), ctx);
2208 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2209
2210 if (TYPE_FIELDS (ctx->record_type) == NULL)
2211 ctx->record_type = ctx->receiver_decl = NULL;
2212 else
2213 {
2214 TYPE_FIELDS (ctx->record_type)
2215 = nreverse (TYPE_FIELDS (ctx->record_type));
2216 #ifdef ENABLE_CHECKING
2217 tree field;
2218 unsigned int align = DECL_ALIGN (TYPE_FIELDS (ctx->record_type));
2219 for (field = TYPE_FIELDS (ctx->record_type);
2220 field;
2221 field = DECL_CHAIN (field))
2222 gcc_assert (DECL_ALIGN (field) == align);
2223 #endif
2224 layout_type (ctx->record_type);
2225 if (kind == GF_OMP_TARGET_KIND_REGION)
2226 fixup_child_record_type (ctx);
2227 }
2228 }
2229
2230 /* Scan an OpenMP teams directive. */
2231
2232 static void
2233 scan_omp_teams (gimple stmt, omp_context *outer_ctx)
2234 {
2235 omp_context *ctx = new_omp_context (stmt, outer_ctx);
2236 scan_sharing_clauses (gimple_omp_teams_clauses (stmt), ctx);
2237 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2238 }
2239
2240 /* Check OpenMP nesting restrictions. */
2241 static bool
2242 check_omp_nesting_restrictions (gimple stmt, omp_context *ctx)
2243 {
2244 if (ctx != NULL)
2245 {
2246 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
2247 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_KIND_SIMD)
2248 {
2249 error_at (gimple_location (stmt),
2250 "OpenMP constructs may not be nested inside simd region");
2251 return false;
2252 }
2253 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
2254 {
2255 if ((gimple_code (stmt) != GIMPLE_OMP_FOR
2256 || (gimple_omp_for_kind (stmt)
2257 != GF_OMP_FOR_KIND_DISTRIBUTE))
2258 && gimple_code (stmt) != GIMPLE_OMP_PARALLEL)
2259 {
2260 error_at (gimple_location (stmt),
2261 "only distribute or parallel constructs are allowed to "
2262 "be closely nested inside teams construct");
2263 return false;
2264 }
2265 }
2266 }
2267 switch (gimple_code (stmt))
2268 {
2269 case GIMPLE_OMP_FOR:
2270 if (gimple_omp_for_kind (stmt) & GF_OMP_FOR_KIND_SIMD)
2271 return true;
2272 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
2273 {
2274 if (ctx != NULL && gimple_code (ctx->stmt) != GIMPLE_OMP_TEAMS)
2275 {
2276 error_at (gimple_location (stmt),
2277 "distribute construct must be closely nested inside "
2278 "teams construct");
2279 return false;
2280 }
2281 return true;
2282 }
2283 /* FALLTHRU */
2284 case GIMPLE_CALL:
2285 if (is_gimple_call (stmt)
2286 && (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2287 == BUILT_IN_GOMP_CANCEL
2288 || DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2289 == BUILT_IN_GOMP_CANCELLATION_POINT))
2290 {
2291 const char *bad = NULL;
2292 const char *kind = NULL;
2293 if (ctx == NULL)
2294 {
2295 error_at (gimple_location (stmt), "orphaned %qs construct",
2296 DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2297 == BUILT_IN_GOMP_CANCEL
2298 ? "#pragma omp cancel"
2299 : "#pragma omp cancellation point");
2300 return false;
2301 }
2302 switch (tree_fits_shwi_p (gimple_call_arg (stmt, 0))
2303 ? tree_to_shwi (gimple_call_arg (stmt, 0))
2304 : 0)
2305 {
2306 case 1:
2307 if (gimple_code (ctx->stmt) != GIMPLE_OMP_PARALLEL)
2308 bad = "#pragma omp parallel";
2309 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2310 == BUILT_IN_GOMP_CANCEL
2311 && !integer_zerop (gimple_call_arg (stmt, 1)))
2312 ctx->cancellable = true;
2313 kind = "parallel";
2314 break;
2315 case 2:
2316 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
2317 || gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR)
2318 bad = "#pragma omp for";
2319 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2320 == BUILT_IN_GOMP_CANCEL
2321 && !integer_zerop (gimple_call_arg (stmt, 1)))
2322 {
2323 ctx->cancellable = true;
2324 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2325 OMP_CLAUSE_NOWAIT))
2326 warning_at (gimple_location (stmt), 0,
2327 "%<#pragma omp cancel for%> inside "
2328 "%<nowait%> for construct");
2329 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2330 OMP_CLAUSE_ORDERED))
2331 warning_at (gimple_location (stmt), 0,
2332 "%<#pragma omp cancel for%> inside "
2333 "%<ordered%> for construct");
2334 }
2335 kind = "for";
2336 break;
2337 case 4:
2338 if (gimple_code (ctx->stmt) != GIMPLE_OMP_SECTIONS
2339 && gimple_code (ctx->stmt) != GIMPLE_OMP_SECTION)
2340 bad = "#pragma omp sections";
2341 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2342 == BUILT_IN_GOMP_CANCEL
2343 && !integer_zerop (gimple_call_arg (stmt, 1)))
2344 {
2345 if (gimple_code (ctx->stmt) == GIMPLE_OMP_SECTIONS)
2346 {
2347 ctx->cancellable = true;
2348 if (find_omp_clause (gimple_omp_sections_clauses
2349 (ctx->stmt),
2350 OMP_CLAUSE_NOWAIT))
2351 warning_at (gimple_location (stmt), 0,
2352 "%<#pragma omp cancel sections%> inside "
2353 "%<nowait%> sections construct");
2354 }
2355 else
2356 {
2357 gcc_assert (ctx->outer
2358 && gimple_code (ctx->outer->stmt)
2359 == GIMPLE_OMP_SECTIONS);
2360 ctx->outer->cancellable = true;
2361 if (find_omp_clause (gimple_omp_sections_clauses
2362 (ctx->outer->stmt),
2363 OMP_CLAUSE_NOWAIT))
2364 warning_at (gimple_location (stmt), 0,
2365 "%<#pragma omp cancel sections%> inside "
2366 "%<nowait%> sections construct");
2367 }
2368 }
2369 kind = "sections";
2370 break;
2371 case 8:
2372 if (gimple_code (ctx->stmt) != GIMPLE_OMP_TASK)
2373 bad = "#pragma omp task";
2374 else
2375 ctx->cancellable = true;
2376 kind = "taskgroup";
2377 break;
2378 default:
2379 error_at (gimple_location (stmt), "invalid arguments");
2380 return false;
2381 }
2382 if (bad)
2383 {
2384 error_at (gimple_location (stmt),
2385 "%<%s %s%> construct not closely nested inside of %qs",
2386 DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2387 == BUILT_IN_GOMP_CANCEL
2388 ? "#pragma omp cancel"
2389 : "#pragma omp cancellation point", kind, bad);
2390 return false;
2391 }
2392 }
2393 /* FALLTHRU */
2394 case GIMPLE_OMP_SECTIONS:
2395 case GIMPLE_OMP_SINGLE:
2396 for (; ctx != NULL; ctx = ctx->outer)
2397 switch (gimple_code (ctx->stmt))
2398 {
2399 case GIMPLE_OMP_FOR:
2400 case GIMPLE_OMP_SECTIONS:
2401 case GIMPLE_OMP_SINGLE:
2402 case GIMPLE_OMP_ORDERED:
2403 case GIMPLE_OMP_MASTER:
2404 case GIMPLE_OMP_TASK:
2405 case GIMPLE_OMP_CRITICAL:
2406 if (is_gimple_call (stmt))
2407 {
2408 if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2409 != BUILT_IN_GOMP_BARRIER)
2410 return true;
2411 error_at (gimple_location (stmt),
2412 "barrier region may not be closely nested inside "
2413 "of work-sharing, critical, ordered, master or "
2414 "explicit task region");
2415 return false;
2416 }
2417 error_at (gimple_location (stmt),
2418 "work-sharing region may not be closely nested inside "
2419 "of work-sharing, critical, ordered, master or explicit "
2420 "task region");
2421 return false;
2422 case GIMPLE_OMP_PARALLEL:
2423 return true;
2424 default:
2425 break;
2426 }
2427 break;
2428 case GIMPLE_OMP_MASTER:
2429 for (; ctx != NULL; ctx = ctx->outer)
2430 switch (gimple_code (ctx->stmt))
2431 {
2432 case GIMPLE_OMP_FOR:
2433 case GIMPLE_OMP_SECTIONS:
2434 case GIMPLE_OMP_SINGLE:
2435 case GIMPLE_OMP_TASK:
2436 error_at (gimple_location (stmt),
2437 "master region may not be closely nested inside "
2438 "of work-sharing or explicit task region");
2439 return false;
2440 case GIMPLE_OMP_PARALLEL:
2441 return true;
2442 default:
2443 break;
2444 }
2445 break;
2446 case GIMPLE_OMP_ORDERED:
2447 for (; ctx != NULL; ctx = ctx->outer)
2448 switch (gimple_code (ctx->stmt))
2449 {
2450 case GIMPLE_OMP_CRITICAL:
2451 case GIMPLE_OMP_TASK:
2452 error_at (gimple_location (stmt),
2453 "ordered region may not be closely nested inside "
2454 "of critical or explicit task region");
2455 return false;
2456 case GIMPLE_OMP_FOR:
2457 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2458 OMP_CLAUSE_ORDERED) == NULL)
2459 {
2460 error_at (gimple_location (stmt),
2461 "ordered region must be closely nested inside "
2462 "a loop region with an ordered clause");
2463 return false;
2464 }
2465 return true;
2466 case GIMPLE_OMP_PARALLEL:
2467 error_at (gimple_location (stmt),
2468 "ordered region must be closely nested inside "
2469 "a loop region with an ordered clause");
2470 return false;
2471 default:
2472 break;
2473 }
2474 break;
2475 case GIMPLE_OMP_CRITICAL:
2476 for (; ctx != NULL; ctx = ctx->outer)
2477 if (gimple_code (ctx->stmt) == GIMPLE_OMP_CRITICAL
2478 && (gimple_omp_critical_name (stmt)
2479 == gimple_omp_critical_name (ctx->stmt)))
2480 {
2481 error_at (gimple_location (stmt),
2482 "critical region may not be nested inside a critical "
2483 "region with the same name");
2484 return false;
2485 }
2486 break;
2487 case GIMPLE_OMP_TEAMS:
2488 if (ctx == NULL
2489 || gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET
2490 || gimple_omp_target_kind (ctx->stmt) != GF_OMP_TARGET_KIND_REGION)
2491 {
2492 error_at (gimple_location (stmt),
2493 "teams construct not closely nested inside of target "
2494 "region");
2495 return false;
2496 }
2497 break;
2498 default:
2499 break;
2500 }
2501 return true;
2502 }
2503
2504
2505 /* Helper function scan_omp.
2506
2507 Callback for walk_tree or operators in walk_gimple_stmt used to
2508 scan for OpenMP directives in TP. */
2509
2510 static tree
2511 scan_omp_1_op (tree *tp, int *walk_subtrees, void *data)
2512 {
2513 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
2514 omp_context *ctx = (omp_context *) wi->info;
2515 tree t = *tp;
2516
2517 switch (TREE_CODE (t))
2518 {
2519 case VAR_DECL:
2520 case PARM_DECL:
2521 case LABEL_DECL:
2522 case RESULT_DECL:
2523 if (ctx)
2524 *tp = remap_decl (t, &ctx->cb);
2525 break;
2526
2527 default:
2528 if (ctx && TYPE_P (t))
2529 *tp = remap_type (t, &ctx->cb);
2530 else if (!DECL_P (t))
2531 {
2532 *walk_subtrees = 1;
2533 if (ctx)
2534 {
2535 tree tem = remap_type (TREE_TYPE (t), &ctx->cb);
2536 if (tem != TREE_TYPE (t))
2537 {
2538 if (TREE_CODE (t) == INTEGER_CST)
2539 *tp = build_int_cst_wide (tem,
2540 TREE_INT_CST_LOW (t),
2541 TREE_INT_CST_HIGH (t));
2542 else
2543 TREE_TYPE (t) = tem;
2544 }
2545 }
2546 }
2547 break;
2548 }
2549
2550 return NULL_TREE;
2551 }
2552
2553 /* Return true if FNDECL is a setjmp or a longjmp. */
2554
2555 static bool
2556 setjmp_or_longjmp_p (const_tree fndecl)
2557 {
2558 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
2559 && (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_SETJMP
2560 || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_LONGJMP))
2561 return true;
2562
2563 tree declname = DECL_NAME (fndecl);
2564 if (!declname)
2565 return false;
2566 const char *name = IDENTIFIER_POINTER (declname);
2567 return !strcmp (name, "setjmp") || !strcmp (name, "longjmp");
2568 }
2569
2570
2571 /* Helper function for scan_omp.
2572
2573 Callback for walk_gimple_stmt used to scan for OpenMP directives in
2574 the current statement in GSI. */
2575
2576 static tree
2577 scan_omp_1_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
2578 struct walk_stmt_info *wi)
2579 {
2580 gimple stmt = gsi_stmt (*gsi);
2581 omp_context *ctx = (omp_context *) wi->info;
2582
2583 if (gimple_has_location (stmt))
2584 input_location = gimple_location (stmt);
2585
2586 /* Check the OpenMP nesting restrictions. */
2587 bool remove = false;
2588 if (is_gimple_omp (stmt))
2589 remove = !check_omp_nesting_restrictions (stmt, ctx);
2590 else if (is_gimple_call (stmt))
2591 {
2592 tree fndecl = gimple_call_fndecl (stmt);
2593 if (fndecl)
2594 {
2595 if (setjmp_or_longjmp_p (fndecl)
2596 && ctx
2597 && gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
2598 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_KIND_SIMD)
2599 {
2600 remove = true;
2601 error_at (gimple_location (stmt),
2602 "setjmp/longjmp inside simd construct");
2603 }
2604 else if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
2605 switch (DECL_FUNCTION_CODE (fndecl))
2606 {
2607 case BUILT_IN_GOMP_BARRIER:
2608 case BUILT_IN_GOMP_CANCEL:
2609 case BUILT_IN_GOMP_CANCELLATION_POINT:
2610 case BUILT_IN_GOMP_TASKYIELD:
2611 case BUILT_IN_GOMP_TASKWAIT:
2612 case BUILT_IN_GOMP_TASKGROUP_START:
2613 case BUILT_IN_GOMP_TASKGROUP_END:
2614 remove = !check_omp_nesting_restrictions (stmt, ctx);
2615 break;
2616 default:
2617 break;
2618 }
2619 }
2620 }
2621 if (remove)
2622 {
2623 stmt = gimple_build_nop ();
2624 gsi_replace (gsi, stmt, false);
2625 }
2626
2627 *handled_ops_p = true;
2628
2629 switch (gimple_code (stmt))
2630 {
2631 case GIMPLE_OMP_PARALLEL:
2632 taskreg_nesting_level++;
2633 scan_omp_parallel (gsi, ctx);
2634 taskreg_nesting_level--;
2635 break;
2636
2637 case GIMPLE_OMP_TASK:
2638 taskreg_nesting_level++;
2639 scan_omp_task (gsi, ctx);
2640 taskreg_nesting_level--;
2641 break;
2642
2643 case GIMPLE_OMP_FOR:
2644 scan_omp_for (stmt, ctx);
2645 break;
2646
2647 case GIMPLE_OMP_SECTIONS:
2648 scan_omp_sections (stmt, ctx);
2649 break;
2650
2651 case GIMPLE_OMP_SINGLE:
2652 scan_omp_single (stmt, ctx);
2653 break;
2654
2655 case GIMPLE_OMP_SECTION:
2656 case GIMPLE_OMP_MASTER:
2657 case GIMPLE_OMP_TASKGROUP:
2658 case GIMPLE_OMP_ORDERED:
2659 case GIMPLE_OMP_CRITICAL:
2660 ctx = new_omp_context (stmt, ctx);
2661 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2662 break;
2663
2664 case GIMPLE_OMP_TARGET:
2665 scan_omp_target (stmt, ctx);
2666 break;
2667
2668 case GIMPLE_OMP_TEAMS:
2669 scan_omp_teams (stmt, ctx);
2670 break;
2671
2672 case GIMPLE_BIND:
2673 {
2674 tree var;
2675
2676 *handled_ops_p = false;
2677 if (ctx)
2678 for (var = gimple_bind_vars (stmt); var ; var = DECL_CHAIN (var))
2679 insert_decl_map (&ctx->cb, var, var);
2680 }
2681 break;
2682 default:
2683 *handled_ops_p = false;
2684 break;
2685 }
2686
2687 return NULL_TREE;
2688 }
2689
2690
2691 /* Scan all the statements starting at the current statement. CTX
2692 contains context information about the OpenMP directives and
2693 clauses found during the scan. */
2694
2695 static void
2696 scan_omp (gimple_seq *body_p, omp_context *ctx)
2697 {
2698 location_t saved_location;
2699 struct walk_stmt_info wi;
2700
2701 memset (&wi, 0, sizeof (wi));
2702 wi.info = ctx;
2703 wi.want_locations = true;
2704
2705 saved_location = input_location;
2706 walk_gimple_seq_mod (body_p, scan_omp_1_stmt, scan_omp_1_op, &wi);
2707 input_location = saved_location;
2708 }
2709 \f
2710 /* Re-gimplification and code generation routines. */
2711
2712 /* Build a call to GOMP_barrier. */
2713
2714 static gimple
2715 build_omp_barrier (tree lhs)
2716 {
2717 tree fndecl = builtin_decl_explicit (lhs ? BUILT_IN_GOMP_BARRIER_CANCEL
2718 : BUILT_IN_GOMP_BARRIER);
2719 gimple g = gimple_build_call (fndecl, 0);
2720 if (lhs)
2721 gimple_call_set_lhs (g, lhs);
2722 return g;
2723 }
2724
2725 /* If a context was created for STMT when it was scanned, return it. */
2726
2727 static omp_context *
2728 maybe_lookup_ctx (gimple stmt)
2729 {
2730 splay_tree_node n;
2731 n = splay_tree_lookup (all_contexts, (splay_tree_key) stmt);
2732 return n ? (omp_context *) n->value : NULL;
2733 }
2734
2735
2736 /* Find the mapping for DECL in CTX or the immediately enclosing
2737 context that has a mapping for DECL.
2738
2739 If CTX is a nested parallel directive, we may have to use the decl
2740 mappings created in CTX's parent context. Suppose that we have the
2741 following parallel nesting (variable UIDs showed for clarity):
2742
2743 iD.1562 = 0;
2744 #omp parallel shared(iD.1562) -> outer parallel
2745 iD.1562 = iD.1562 + 1;
2746
2747 #omp parallel shared (iD.1562) -> inner parallel
2748 iD.1562 = iD.1562 - 1;
2749
2750 Each parallel structure will create a distinct .omp_data_s structure
2751 for copying iD.1562 in/out of the directive:
2752
2753 outer parallel .omp_data_s.1.i -> iD.1562
2754 inner parallel .omp_data_s.2.i -> iD.1562
2755
2756 A shared variable mapping will produce a copy-out operation before
2757 the parallel directive and a copy-in operation after it. So, in
2758 this case we would have:
2759
2760 iD.1562 = 0;
2761 .omp_data_o.1.i = iD.1562;
2762 #omp parallel shared(iD.1562) -> outer parallel
2763 .omp_data_i.1 = &.omp_data_o.1
2764 .omp_data_i.1->i = .omp_data_i.1->i + 1;
2765
2766 .omp_data_o.2.i = iD.1562; -> **
2767 #omp parallel shared(iD.1562) -> inner parallel
2768 .omp_data_i.2 = &.omp_data_o.2
2769 .omp_data_i.2->i = .omp_data_i.2->i - 1;
2770
2771
2772 ** This is a problem. The symbol iD.1562 cannot be referenced
2773 inside the body of the outer parallel region. But since we are
2774 emitting this copy operation while expanding the inner parallel
2775 directive, we need to access the CTX structure of the outer
2776 parallel directive to get the correct mapping:
2777
2778 .omp_data_o.2.i = .omp_data_i.1->i
2779
2780 Since there may be other workshare or parallel directives enclosing
2781 the parallel directive, it may be necessary to walk up the context
2782 parent chain. This is not a problem in general because nested
2783 parallelism happens only rarely. */
2784
2785 static tree
2786 lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
2787 {
2788 tree t;
2789 omp_context *up;
2790
2791 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
2792 t = maybe_lookup_decl (decl, up);
2793
2794 gcc_assert (!ctx->is_nested || t || is_global_var (decl));
2795
2796 return t ? t : decl;
2797 }
2798
2799
2800 /* Similar to lookup_decl_in_outer_ctx, but return DECL if not found
2801 in outer contexts. */
2802
2803 static tree
2804 maybe_lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
2805 {
2806 tree t = NULL;
2807 omp_context *up;
2808
2809 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
2810 t = maybe_lookup_decl (decl, up);
2811
2812 return t ? t : decl;
2813 }
2814
2815
2816 /* Construct the initialization value for reduction CLAUSE. */
2817
2818 tree
2819 omp_reduction_init (tree clause, tree type)
2820 {
2821 location_t loc = OMP_CLAUSE_LOCATION (clause);
2822 switch (OMP_CLAUSE_REDUCTION_CODE (clause))
2823 {
2824 case PLUS_EXPR:
2825 case MINUS_EXPR:
2826 case BIT_IOR_EXPR:
2827 case BIT_XOR_EXPR:
2828 case TRUTH_OR_EXPR:
2829 case TRUTH_ORIF_EXPR:
2830 case TRUTH_XOR_EXPR:
2831 case NE_EXPR:
2832 return build_zero_cst (type);
2833
2834 case MULT_EXPR:
2835 case TRUTH_AND_EXPR:
2836 case TRUTH_ANDIF_EXPR:
2837 case EQ_EXPR:
2838 return fold_convert_loc (loc, type, integer_one_node);
2839
2840 case BIT_AND_EXPR:
2841 return fold_convert_loc (loc, type, integer_minus_one_node);
2842
2843 case MAX_EXPR:
2844 if (SCALAR_FLOAT_TYPE_P (type))
2845 {
2846 REAL_VALUE_TYPE max, min;
2847 if (HONOR_INFINITIES (TYPE_MODE (type)))
2848 {
2849 real_inf (&max);
2850 real_arithmetic (&min, NEGATE_EXPR, &max, NULL);
2851 }
2852 else
2853 real_maxval (&min, 1, TYPE_MODE (type));
2854 return build_real (type, min);
2855 }
2856 else
2857 {
2858 gcc_assert (INTEGRAL_TYPE_P (type));
2859 return TYPE_MIN_VALUE (type);
2860 }
2861
2862 case MIN_EXPR:
2863 if (SCALAR_FLOAT_TYPE_P (type))
2864 {
2865 REAL_VALUE_TYPE max;
2866 if (HONOR_INFINITIES (TYPE_MODE (type)))
2867 real_inf (&max);
2868 else
2869 real_maxval (&max, 0, TYPE_MODE (type));
2870 return build_real (type, max);
2871 }
2872 else
2873 {
2874 gcc_assert (INTEGRAL_TYPE_P (type));
2875 return TYPE_MAX_VALUE (type);
2876 }
2877
2878 default:
2879 gcc_unreachable ();
2880 }
2881 }
2882
2883 /* Return alignment to be assumed for var in CLAUSE, which should be
2884 OMP_CLAUSE_ALIGNED. */
2885
2886 static tree
2887 omp_clause_aligned_alignment (tree clause)
2888 {
2889 if (OMP_CLAUSE_ALIGNED_ALIGNMENT (clause))
2890 return OMP_CLAUSE_ALIGNED_ALIGNMENT (clause);
2891
2892 /* Otherwise return implementation defined alignment. */
2893 unsigned int al = 1;
2894 enum machine_mode mode, vmode;
2895 int vs = targetm.vectorize.autovectorize_vector_sizes ();
2896 if (vs)
2897 vs = 1 << floor_log2 (vs);
2898 static enum mode_class classes[]
2899 = { MODE_INT, MODE_VECTOR_INT, MODE_FLOAT, MODE_VECTOR_FLOAT };
2900 for (int i = 0; i < 4; i += 2)
2901 for (mode = GET_CLASS_NARROWEST_MODE (classes[i]);
2902 mode != VOIDmode;
2903 mode = GET_MODE_WIDER_MODE (mode))
2904 {
2905 vmode = targetm.vectorize.preferred_simd_mode (mode);
2906 if (GET_MODE_CLASS (vmode) != classes[i + 1])
2907 continue;
2908 while (vs
2909 && GET_MODE_SIZE (vmode) < vs
2910 && GET_MODE_2XWIDER_MODE (vmode) != VOIDmode)
2911 vmode = GET_MODE_2XWIDER_MODE (vmode);
2912
2913 tree type = lang_hooks.types.type_for_mode (mode, 1);
2914 if (type == NULL_TREE || TYPE_MODE (type) != mode)
2915 continue;
2916 type = build_vector_type (type, GET_MODE_SIZE (vmode)
2917 / GET_MODE_SIZE (mode));
2918 if (TYPE_MODE (type) != vmode)
2919 continue;
2920 if (TYPE_ALIGN_UNIT (type) > al)
2921 al = TYPE_ALIGN_UNIT (type);
2922 }
2923 return build_int_cst (integer_type_node, al);
2924 }
2925
2926 /* Return maximum possible vectorization factor for the target. */
2927
2928 static int
2929 omp_max_vf (void)
2930 {
2931 if (!optimize
2932 || optimize_debug
2933 || (!flag_tree_loop_vectorize
2934 && (global_options_set.x_flag_tree_loop_vectorize
2935 || global_options_set.x_flag_tree_vectorize)))
2936 return 1;
2937
2938 int vs = targetm.vectorize.autovectorize_vector_sizes ();
2939 if (vs)
2940 {
2941 vs = 1 << floor_log2 (vs);
2942 return vs;
2943 }
2944 enum machine_mode vqimode = targetm.vectorize.preferred_simd_mode (QImode);
2945 if (GET_MODE_CLASS (vqimode) == MODE_VECTOR_INT)
2946 return GET_MODE_NUNITS (vqimode);
2947 return 1;
2948 }
2949
2950 /* Helper function of lower_rec_input_clauses, used for #pragma omp simd
2951 privatization. */
2952
2953 static bool
2954 lower_rec_simd_input_clauses (tree new_var, omp_context *ctx, int &max_vf,
2955 tree &idx, tree &lane, tree &ivar, tree &lvar)
2956 {
2957 if (max_vf == 0)
2958 {
2959 max_vf = omp_max_vf ();
2960 if (max_vf > 1)
2961 {
2962 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2963 OMP_CLAUSE_SAFELEN);
2964 if (c
2965 && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c), max_vf) == -1)
2966 max_vf = tree_to_shwi (OMP_CLAUSE_SAFELEN_EXPR (c));
2967 }
2968 if (max_vf > 1)
2969 {
2970 idx = create_tmp_var (unsigned_type_node, NULL);
2971 lane = create_tmp_var (unsigned_type_node, NULL);
2972 }
2973 }
2974 if (max_vf == 1)
2975 return false;
2976
2977 tree atype = build_array_type_nelts (TREE_TYPE (new_var), max_vf);
2978 tree avar = create_tmp_var_raw (atype, NULL);
2979 if (TREE_ADDRESSABLE (new_var))
2980 TREE_ADDRESSABLE (avar) = 1;
2981 DECL_ATTRIBUTES (avar)
2982 = tree_cons (get_identifier ("omp simd array"), NULL,
2983 DECL_ATTRIBUTES (avar));
2984 gimple_add_tmp_var (avar);
2985 ivar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, idx,
2986 NULL_TREE, NULL_TREE);
2987 lvar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, lane,
2988 NULL_TREE, NULL_TREE);
2989 if (DECL_P (new_var))
2990 {
2991 SET_DECL_VALUE_EXPR (new_var, lvar);
2992 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
2993 }
2994 return true;
2995 }
2996
2997 /* Generate code to implement the input clauses, FIRSTPRIVATE and COPYIN,
2998 from the receiver (aka child) side and initializers for REFERENCE_TYPE
2999 private variables. Initialization statements go in ILIST, while calls
3000 to destructors go in DLIST. */
3001
3002 static void
3003 lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
3004 omp_context *ctx, struct omp_for_data *fd)
3005 {
3006 tree c, dtor, copyin_seq, x, ptr;
3007 bool copyin_by_ref = false;
3008 bool lastprivate_firstprivate = false;
3009 bool reduction_omp_orig_ref = false;
3010 int pass;
3011 bool is_simd = (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3012 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_KIND_SIMD);
3013 int max_vf = 0;
3014 tree lane = NULL_TREE, idx = NULL_TREE;
3015 tree ivar = NULL_TREE, lvar = NULL_TREE;
3016 gimple_seq llist[2] = { NULL, NULL };
3017
3018 copyin_seq = NULL;
3019
3020 /* Set max_vf=1 (which will later enforce safelen=1) in simd loops
3021 with data sharing clauses referencing variable sized vars. That
3022 is unnecessarily hard to support and very unlikely to result in
3023 vectorized code anyway. */
3024 if (is_simd)
3025 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
3026 switch (OMP_CLAUSE_CODE (c))
3027 {
3028 case OMP_CLAUSE_REDUCTION:
3029 case OMP_CLAUSE_PRIVATE:
3030 case OMP_CLAUSE_FIRSTPRIVATE:
3031 case OMP_CLAUSE_LASTPRIVATE:
3032 case OMP_CLAUSE_LINEAR:
3033 if (is_variable_sized (OMP_CLAUSE_DECL (c)))
3034 max_vf = 1;
3035 break;
3036 default:
3037 continue;
3038 }
3039
3040 /* Do all the fixed sized types in the first pass, and the variable sized
3041 types in the second pass. This makes sure that the scalar arguments to
3042 the variable sized types are processed before we use them in the
3043 variable sized operations. */
3044 for (pass = 0; pass < 2; ++pass)
3045 {
3046 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
3047 {
3048 enum omp_clause_code c_kind = OMP_CLAUSE_CODE (c);
3049 tree var, new_var;
3050 bool by_ref;
3051 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
3052
3053 switch (c_kind)
3054 {
3055 case OMP_CLAUSE_PRIVATE:
3056 if (OMP_CLAUSE_PRIVATE_DEBUG (c))
3057 continue;
3058 break;
3059 case OMP_CLAUSE_SHARED:
3060 /* Ignore shared directives in teams construct. */
3061 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
3062 continue;
3063 if (maybe_lookup_decl (OMP_CLAUSE_DECL (c), ctx) == NULL)
3064 {
3065 gcc_assert (is_global_var (OMP_CLAUSE_DECL (c)));
3066 continue;
3067 }
3068 case OMP_CLAUSE_FIRSTPRIVATE:
3069 case OMP_CLAUSE_COPYIN:
3070 case OMP_CLAUSE_LINEAR:
3071 break;
3072 case OMP_CLAUSE_REDUCTION:
3073 if (OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c))
3074 reduction_omp_orig_ref = true;
3075 break;
3076 case OMP_CLAUSE__LOOPTEMP_:
3077 /* Handle _looptemp_ clauses only on parallel. */
3078 if (fd)
3079 continue;
3080 break;
3081 case OMP_CLAUSE_LASTPRIVATE:
3082 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
3083 {
3084 lastprivate_firstprivate = true;
3085 if (pass != 0)
3086 continue;
3087 }
3088 break;
3089 case OMP_CLAUSE_ALIGNED:
3090 if (pass == 0)
3091 continue;
3092 var = OMP_CLAUSE_DECL (c);
3093 if (TREE_CODE (TREE_TYPE (var)) == POINTER_TYPE
3094 && !is_global_var (var))
3095 {
3096 new_var = maybe_lookup_decl (var, ctx);
3097 if (new_var == NULL_TREE)
3098 new_var = maybe_lookup_decl_in_outer_ctx (var, ctx);
3099 x = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
3100 x = build_call_expr_loc (clause_loc, x, 2, new_var,
3101 omp_clause_aligned_alignment (c));
3102 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
3103 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
3104 gimplify_and_add (x, ilist);
3105 }
3106 else if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE
3107 && is_global_var (var))
3108 {
3109 tree ptype = build_pointer_type (TREE_TYPE (var)), t, t2;
3110 new_var = lookup_decl (var, ctx);
3111 t = maybe_lookup_decl_in_outer_ctx (var, ctx);
3112 t = build_fold_addr_expr_loc (clause_loc, t);
3113 t2 = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
3114 t = build_call_expr_loc (clause_loc, t2, 2, t,
3115 omp_clause_aligned_alignment (c));
3116 t = fold_convert_loc (clause_loc, ptype, t);
3117 x = create_tmp_var (ptype, NULL);
3118 t = build2 (MODIFY_EXPR, ptype, x, t);
3119 gimplify_and_add (t, ilist);
3120 t = build_simple_mem_ref_loc (clause_loc, x);
3121 SET_DECL_VALUE_EXPR (new_var, t);
3122 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3123 }
3124 continue;
3125 default:
3126 continue;
3127 }
3128
3129 new_var = var = OMP_CLAUSE_DECL (c);
3130 if (c_kind != OMP_CLAUSE_COPYIN)
3131 new_var = lookup_decl (var, ctx);
3132
3133 if (c_kind == OMP_CLAUSE_SHARED || c_kind == OMP_CLAUSE_COPYIN)
3134 {
3135 if (pass != 0)
3136 continue;
3137 }
3138 else if (is_variable_sized (var))
3139 {
3140 /* For variable sized types, we need to allocate the
3141 actual storage here. Call alloca and store the
3142 result in the pointer decl that we created elsewhere. */
3143 if (pass == 0)
3144 continue;
3145
3146 if (c_kind != OMP_CLAUSE_FIRSTPRIVATE || !is_task_ctx (ctx))
3147 {
3148 gimple stmt;
3149 tree tmp, atmp;
3150
3151 ptr = DECL_VALUE_EXPR (new_var);
3152 gcc_assert (TREE_CODE (ptr) == INDIRECT_REF);
3153 ptr = TREE_OPERAND (ptr, 0);
3154 gcc_assert (DECL_P (ptr));
3155 x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
3156
3157 /* void *tmp = __builtin_alloca */
3158 atmp = builtin_decl_explicit (BUILT_IN_ALLOCA);
3159 stmt = gimple_build_call (atmp, 1, x);
3160 tmp = create_tmp_var_raw (ptr_type_node, NULL);
3161 gimple_add_tmp_var (tmp);
3162 gimple_call_set_lhs (stmt, tmp);
3163
3164 gimple_seq_add_stmt (ilist, stmt);
3165
3166 x = fold_convert_loc (clause_loc, TREE_TYPE (ptr), tmp);
3167 gimplify_assign (ptr, x, ilist);
3168 }
3169 }
3170 else if (is_reference (var))
3171 {
3172 /* For references that are being privatized for Fortran,
3173 allocate new backing storage for the new pointer
3174 variable. This allows us to avoid changing all the
3175 code that expects a pointer to something that expects
3176 a direct variable. */
3177 if (pass == 0)
3178 continue;
3179
3180 x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
3181 if (c_kind == OMP_CLAUSE_FIRSTPRIVATE && is_task_ctx (ctx))
3182 {
3183 x = build_receiver_ref (var, false, ctx);
3184 x = build_fold_addr_expr_loc (clause_loc, x);
3185 }
3186 else if (TREE_CONSTANT (x))
3187 {
3188 const char *name = NULL;
3189 if (DECL_NAME (var))
3190 name = IDENTIFIER_POINTER (DECL_NAME (new_var));
3191
3192 x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)),
3193 name);
3194 gimple_add_tmp_var (x);
3195 TREE_ADDRESSABLE (x) = 1;
3196 x = build_fold_addr_expr_loc (clause_loc, x);
3197 }
3198 else
3199 {
3200 tree atmp = builtin_decl_explicit (BUILT_IN_ALLOCA);
3201 x = build_call_expr_loc (clause_loc, atmp, 1, x);
3202 }
3203
3204 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
3205 gimplify_assign (new_var, x, ilist);
3206
3207 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
3208 }
3209 else if (c_kind == OMP_CLAUSE_REDUCTION
3210 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
3211 {
3212 if (pass == 0)
3213 continue;
3214 }
3215 else if (pass != 0)
3216 continue;
3217
3218 switch (OMP_CLAUSE_CODE (c))
3219 {
3220 case OMP_CLAUSE_SHARED:
3221 /* Ignore shared directives in teams construct. */
3222 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
3223 continue;
3224 /* Shared global vars are just accessed directly. */
3225 if (is_global_var (new_var))
3226 break;
3227 /* Set up the DECL_VALUE_EXPR for shared variables now. This
3228 needs to be delayed until after fixup_child_record_type so
3229 that we get the correct type during the dereference. */
3230 by_ref = use_pointer_for_field (var, ctx);
3231 x = build_receiver_ref (var, by_ref, ctx);
3232 SET_DECL_VALUE_EXPR (new_var, x);
3233 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3234
3235 /* ??? If VAR is not passed by reference, and the variable
3236 hasn't been initialized yet, then we'll get a warning for
3237 the store into the omp_data_s structure. Ideally, we'd be
3238 able to notice this and not store anything at all, but
3239 we're generating code too early. Suppress the warning. */
3240 if (!by_ref)
3241 TREE_NO_WARNING (var) = 1;
3242 break;
3243
3244 case OMP_CLAUSE_LASTPRIVATE:
3245 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
3246 break;
3247 /* FALLTHRU */
3248
3249 case OMP_CLAUSE_PRIVATE:
3250 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_PRIVATE)
3251 x = build_outer_var_ref (var, ctx);
3252 else if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
3253 {
3254 if (is_task_ctx (ctx))
3255 x = build_receiver_ref (var, false, ctx);
3256 else
3257 x = build_outer_var_ref (var, ctx);
3258 }
3259 else
3260 x = NULL;
3261 do_private:
3262 tree nx;
3263 nx = lang_hooks.decls.omp_clause_default_ctor (c, new_var, x);
3264 if (is_simd)
3265 {
3266 tree y = lang_hooks.decls.omp_clause_dtor (c, new_var);
3267 if ((TREE_ADDRESSABLE (new_var) || nx || y
3268 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE)
3269 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3270 idx, lane, ivar, lvar))
3271 {
3272 if (nx)
3273 x = lang_hooks.decls.omp_clause_default_ctor
3274 (c, unshare_expr (ivar), x);
3275 if (nx && x)
3276 gimplify_and_add (x, &llist[0]);
3277 if (y)
3278 {
3279 y = lang_hooks.decls.omp_clause_dtor (c, ivar);
3280 if (y)
3281 {
3282 gimple_seq tseq = NULL;
3283
3284 dtor = y;
3285 gimplify_stmt (&dtor, &tseq);
3286 gimple_seq_add_seq (&llist[1], tseq);
3287 }
3288 }
3289 break;
3290 }
3291 }
3292 if (nx)
3293 gimplify_and_add (nx, ilist);
3294 /* FALLTHRU */
3295
3296 do_dtor:
3297 x = lang_hooks.decls.omp_clause_dtor (c, new_var);
3298 if (x)
3299 {
3300 gimple_seq tseq = NULL;
3301
3302 dtor = x;
3303 gimplify_stmt (&dtor, &tseq);
3304 gimple_seq_add_seq (dlist, tseq);
3305 }
3306 break;
3307
3308 case OMP_CLAUSE_LINEAR:
3309 if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c))
3310 goto do_firstprivate;
3311 if (OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
3312 x = NULL;
3313 else
3314 x = build_outer_var_ref (var, ctx);
3315 goto do_private;
3316
3317 case OMP_CLAUSE_FIRSTPRIVATE:
3318 if (is_task_ctx (ctx))
3319 {
3320 if (is_reference (var) || is_variable_sized (var))
3321 goto do_dtor;
3322 else if (is_global_var (maybe_lookup_decl_in_outer_ctx (var,
3323 ctx))
3324 || use_pointer_for_field (var, NULL))
3325 {
3326 x = build_receiver_ref (var, false, ctx);
3327 SET_DECL_VALUE_EXPR (new_var, x);
3328 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3329 goto do_dtor;
3330 }
3331 }
3332 do_firstprivate:
3333 x = build_outer_var_ref (var, ctx);
3334 if (is_simd)
3335 {
3336 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
3337 && gimple_omp_for_combined_into_p (ctx->stmt))
3338 {
3339 tree stept = POINTER_TYPE_P (TREE_TYPE (x))
3340 ? sizetype : TREE_TYPE (x);
3341 tree t = fold_convert (stept,
3342 OMP_CLAUSE_LINEAR_STEP (c));
3343 tree c = find_omp_clause (clauses,
3344 OMP_CLAUSE__LOOPTEMP_);
3345 gcc_assert (c);
3346 tree l = OMP_CLAUSE_DECL (c);
3347 if (fd->collapse == 1)
3348 {
3349 tree n1 = fd->loop.n1;
3350 tree step = fd->loop.step;
3351 tree itype = TREE_TYPE (l);
3352 if (POINTER_TYPE_P (itype))
3353 itype = signed_type_for (itype);
3354 l = fold_build2 (MINUS_EXPR, itype, l, n1);
3355 if (TYPE_UNSIGNED (itype)
3356 && fd->loop.cond_code == GT_EXPR)
3357 l = fold_build2 (TRUNC_DIV_EXPR, itype,
3358 fold_build1 (NEGATE_EXPR,
3359 itype, l),
3360 fold_build1 (NEGATE_EXPR,
3361 itype, step));
3362 else
3363 l = fold_build2 (TRUNC_DIV_EXPR, itype, l, step);
3364 }
3365 t = fold_build2 (MULT_EXPR, stept,
3366 fold_convert (stept, l), t);
3367 if (POINTER_TYPE_P (TREE_TYPE (x)))
3368 x = fold_build2 (POINTER_PLUS_EXPR,
3369 TREE_TYPE (x), x, t);
3370 else
3371 x = fold_build2 (PLUS_EXPR, TREE_TYPE (x), x, t);
3372 }
3373
3374 if ((OMP_CLAUSE_CODE (c) != OMP_CLAUSE_LINEAR
3375 || TREE_ADDRESSABLE (new_var))
3376 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3377 idx, lane, ivar, lvar))
3378 {
3379 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR)
3380 {
3381 tree iv = create_tmp_var (TREE_TYPE (new_var), NULL);
3382 x = lang_hooks.decls.omp_clause_copy_ctor (c, iv, x);
3383 gimplify_and_add (x, ilist);
3384 gimple_stmt_iterator gsi
3385 = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
3386 gimple g
3387 = gimple_build_assign (unshare_expr (lvar), iv);
3388 gsi_insert_before_without_update (&gsi, g,
3389 GSI_SAME_STMT);
3390 tree stept = POINTER_TYPE_P (TREE_TYPE (x))
3391 ? sizetype : TREE_TYPE (x);
3392 tree t = fold_convert (stept,
3393 OMP_CLAUSE_LINEAR_STEP (c));
3394 enum tree_code code = PLUS_EXPR;
3395 if (POINTER_TYPE_P (TREE_TYPE (new_var)))
3396 code = POINTER_PLUS_EXPR;
3397 g = gimple_build_assign_with_ops (code, iv, iv, t);
3398 gsi_insert_before_without_update (&gsi, g,
3399 GSI_SAME_STMT);
3400 break;
3401 }
3402 x = lang_hooks.decls.omp_clause_copy_ctor
3403 (c, unshare_expr (ivar), x);
3404 gimplify_and_add (x, &llist[0]);
3405 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
3406 if (x)
3407 {
3408 gimple_seq tseq = NULL;
3409
3410 dtor = x;
3411 gimplify_stmt (&dtor, &tseq);
3412 gimple_seq_add_seq (&llist[1], tseq);
3413 }
3414 break;
3415 }
3416 }
3417 x = lang_hooks.decls.omp_clause_copy_ctor (c, new_var, x);
3418 gimplify_and_add (x, ilist);
3419 goto do_dtor;
3420
3421 case OMP_CLAUSE__LOOPTEMP_:
3422 gcc_assert (is_parallel_ctx (ctx));
3423 x = build_outer_var_ref (var, ctx);
3424 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
3425 gimplify_and_add (x, ilist);
3426 break;
3427
3428 case OMP_CLAUSE_COPYIN:
3429 by_ref = use_pointer_for_field (var, NULL);
3430 x = build_receiver_ref (var, by_ref, ctx);
3431 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, x);
3432 append_to_statement_list (x, &copyin_seq);
3433 copyin_by_ref |= by_ref;
3434 break;
3435
3436 case OMP_CLAUSE_REDUCTION:
3437 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
3438 {
3439 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
3440 gimple tseq;
3441 x = build_outer_var_ref (var, ctx);
3442
3443 if (is_reference (var)
3444 && !useless_type_conversion_p (TREE_TYPE (placeholder),
3445 TREE_TYPE (x)))
3446 x = build_fold_addr_expr_loc (clause_loc, x);
3447 SET_DECL_VALUE_EXPR (placeholder, x);
3448 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
3449 tree new_vard = new_var;
3450 if (is_reference (var))
3451 {
3452 gcc_assert (TREE_CODE (new_var) == MEM_REF);
3453 new_vard = TREE_OPERAND (new_var, 0);
3454 gcc_assert (DECL_P (new_vard));
3455 }
3456 if (is_simd
3457 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3458 idx, lane, ivar, lvar))
3459 {
3460 if (new_vard == new_var)
3461 {
3462 gcc_assert (DECL_VALUE_EXPR (new_var) == lvar);
3463 SET_DECL_VALUE_EXPR (new_var, ivar);
3464 }
3465 else
3466 {
3467 SET_DECL_VALUE_EXPR (new_vard,
3468 build_fold_addr_expr (ivar));
3469 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
3470 }
3471 x = lang_hooks.decls.omp_clause_default_ctor
3472 (c, unshare_expr (ivar),
3473 build_outer_var_ref (var, ctx));
3474 if (x)
3475 gimplify_and_add (x, &llist[0]);
3476 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
3477 {
3478 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
3479 lower_omp (&tseq, ctx);
3480 gimple_seq_add_seq (&llist[0], tseq);
3481 }
3482 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
3483 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
3484 lower_omp (&tseq, ctx);
3485 gimple_seq_add_seq (&llist[1], tseq);
3486 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
3487 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
3488 if (new_vard == new_var)
3489 SET_DECL_VALUE_EXPR (new_var, lvar);
3490 else
3491 SET_DECL_VALUE_EXPR (new_vard,
3492 build_fold_addr_expr (lvar));
3493 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
3494 if (x)
3495 {
3496 tseq = NULL;
3497 dtor = x;
3498 gimplify_stmt (&dtor, &tseq);
3499 gimple_seq_add_seq (&llist[1], tseq);
3500 }
3501 break;
3502 }
3503 x = lang_hooks.decls.omp_clause_default_ctor
3504 (c, new_var, unshare_expr (x));
3505 if (x)
3506 gimplify_and_add (x, ilist);
3507 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
3508 {
3509 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
3510 lower_omp (&tseq, ctx);
3511 gimple_seq_add_seq (ilist, tseq);
3512 }
3513 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
3514 if (is_simd)
3515 {
3516 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
3517 lower_omp (&tseq, ctx);
3518 gimple_seq_add_seq (dlist, tseq);
3519 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
3520 }
3521 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
3522 goto do_dtor;
3523 }
3524 else
3525 {
3526 x = omp_reduction_init (c, TREE_TYPE (new_var));
3527 gcc_assert (TREE_CODE (TREE_TYPE (new_var)) != ARRAY_TYPE);
3528 if (is_simd
3529 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3530 idx, lane, ivar, lvar))
3531 {
3532 enum tree_code code = OMP_CLAUSE_REDUCTION_CODE (c);
3533 tree ref = build_outer_var_ref (var, ctx);
3534
3535 gimplify_assign (unshare_expr (ivar), x, &llist[0]);
3536
3537 /* reduction(-:var) sums up the partial results, so it
3538 acts identically to reduction(+:var). */
3539 if (code == MINUS_EXPR)
3540 code = PLUS_EXPR;
3541
3542 x = build2 (code, TREE_TYPE (ref), ref, ivar);
3543 ref = build_outer_var_ref (var, ctx);
3544 gimplify_assign (ref, x, &llist[1]);
3545 }
3546 else
3547 {
3548 gimplify_assign (new_var, x, ilist);
3549 if (is_simd)
3550 gimplify_assign (build_outer_var_ref (var, ctx),
3551 new_var, dlist);
3552 }
3553 }
3554 break;
3555
3556 default:
3557 gcc_unreachable ();
3558 }
3559 }
3560 }
3561
3562 if (lane)
3563 {
3564 tree uid = create_tmp_var (ptr_type_node, "simduid");
3565 /* Don't want uninit warnings on simduid, it is always uninitialized,
3566 but we use it not for the value, but for the DECL_UID only. */
3567 TREE_NO_WARNING (uid) = 1;
3568 gimple g
3569 = gimple_build_call_internal (IFN_GOMP_SIMD_LANE, 1, uid);
3570 gimple_call_set_lhs (g, lane);
3571 gimple_stmt_iterator gsi = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
3572 gsi_insert_before_without_update (&gsi, g, GSI_SAME_STMT);
3573 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__SIMDUID_);
3574 OMP_CLAUSE__SIMDUID__DECL (c) = uid;
3575 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
3576 gimple_omp_for_set_clauses (ctx->stmt, c);
3577 g = gimple_build_assign_with_ops (INTEGER_CST, lane,
3578 build_int_cst (unsigned_type_node, 0),
3579 NULL_TREE);
3580 gimple_seq_add_stmt (ilist, g);
3581 for (int i = 0; i < 2; i++)
3582 if (llist[i])
3583 {
3584 tree vf = create_tmp_var (unsigned_type_node, NULL);
3585 g = gimple_build_call_internal (IFN_GOMP_SIMD_VF, 1, uid);
3586 gimple_call_set_lhs (g, vf);
3587 gimple_seq *seq = i == 0 ? ilist : dlist;
3588 gimple_seq_add_stmt (seq, g);
3589 tree t = build_int_cst (unsigned_type_node, 0);
3590 g = gimple_build_assign_with_ops (INTEGER_CST, idx, t, NULL_TREE);
3591 gimple_seq_add_stmt (seq, g);
3592 tree body = create_artificial_label (UNKNOWN_LOCATION);
3593 tree header = create_artificial_label (UNKNOWN_LOCATION);
3594 tree end = create_artificial_label (UNKNOWN_LOCATION);
3595 gimple_seq_add_stmt (seq, gimple_build_goto (header));
3596 gimple_seq_add_stmt (seq, gimple_build_label (body));
3597 gimple_seq_add_seq (seq, llist[i]);
3598 t = build_int_cst (unsigned_type_node, 1);
3599 g = gimple_build_assign_with_ops (PLUS_EXPR, idx, idx, t);
3600 gimple_seq_add_stmt (seq, g);
3601 gimple_seq_add_stmt (seq, gimple_build_label (header));
3602 g = gimple_build_cond (LT_EXPR, idx, vf, body, end);
3603 gimple_seq_add_stmt (seq, g);
3604 gimple_seq_add_stmt (seq, gimple_build_label (end));
3605 }
3606 }
3607
3608 /* The copyin sequence is not to be executed by the main thread, since
3609 that would result in self-copies. Perhaps not visible to scalars,
3610 but it certainly is to C++ operator=. */
3611 if (copyin_seq)
3612 {
3613 x = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM),
3614 0);
3615 x = build2 (NE_EXPR, boolean_type_node, x,
3616 build_int_cst (TREE_TYPE (x), 0));
3617 x = build3 (COND_EXPR, void_type_node, x, copyin_seq, NULL);
3618 gimplify_and_add (x, ilist);
3619 }
3620
3621 /* If any copyin variable is passed by reference, we must ensure the
3622 master thread doesn't modify it before it is copied over in all
3623 threads. Similarly for variables in both firstprivate and
3624 lastprivate clauses we need to ensure the lastprivate copying
3625 happens after firstprivate copying in all threads. And similarly
3626 for UDRs if initializer expression refers to omp_orig. */
3627 if (copyin_by_ref || lastprivate_firstprivate || reduction_omp_orig_ref)
3628 {
3629 /* Don't add any barrier for #pragma omp simd or
3630 #pragma omp distribute. */
3631 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
3632 || gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_KIND_FOR)
3633 gimple_seq_add_stmt (ilist, build_omp_barrier (NULL_TREE));
3634 }
3635
3636 /* If max_vf is non-zero, then we can use only a vectorization factor
3637 up to the max_vf we chose. So stick it into the safelen clause. */
3638 if (max_vf)
3639 {
3640 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3641 OMP_CLAUSE_SAFELEN);
3642 if (c == NULL_TREE
3643 || compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
3644 max_vf) == 1)
3645 {
3646 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_SAFELEN);
3647 OMP_CLAUSE_SAFELEN_EXPR (c) = build_int_cst (integer_type_node,
3648 max_vf);
3649 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
3650 gimple_omp_for_set_clauses (ctx->stmt, c);
3651 }
3652 }
3653 }
3654
3655
3656 /* Generate code to implement the LASTPRIVATE clauses. This is used for
3657 both parallel and workshare constructs. PREDICATE may be NULL if it's
3658 always true. */
3659
3660 static void
3661 lower_lastprivate_clauses (tree clauses, tree predicate, gimple_seq *stmt_list,
3662 omp_context *ctx)
3663 {
3664 tree x, c, label = NULL, orig_clauses = clauses;
3665 bool par_clauses = false;
3666 tree simduid = NULL, lastlane = NULL;
3667
3668 /* Early exit if there are no lastprivate or linear clauses. */
3669 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
3670 if (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LASTPRIVATE
3671 || (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LINEAR
3672 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (clauses)))
3673 break;
3674 if (clauses == NULL)
3675 {
3676 /* If this was a workshare clause, see if it had been combined
3677 with its parallel. In that case, look for the clauses on the
3678 parallel statement itself. */
3679 if (is_parallel_ctx (ctx))
3680 return;
3681
3682 ctx = ctx->outer;
3683 if (ctx == NULL || !is_parallel_ctx (ctx))
3684 return;
3685
3686 clauses = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
3687 OMP_CLAUSE_LASTPRIVATE);
3688 if (clauses == NULL)
3689 return;
3690 par_clauses = true;
3691 }
3692
3693 if (predicate)
3694 {
3695 gimple stmt;
3696 tree label_true, arm1, arm2;
3697
3698 label = create_artificial_label (UNKNOWN_LOCATION);
3699 label_true = create_artificial_label (UNKNOWN_LOCATION);
3700 arm1 = TREE_OPERAND (predicate, 0);
3701 arm2 = TREE_OPERAND (predicate, 1);
3702 gimplify_expr (&arm1, stmt_list, NULL, is_gimple_val, fb_rvalue);
3703 gimplify_expr (&arm2, stmt_list, NULL, is_gimple_val, fb_rvalue);
3704 stmt = gimple_build_cond (TREE_CODE (predicate), arm1, arm2,
3705 label_true, label);
3706 gimple_seq_add_stmt (stmt_list, stmt);
3707 gimple_seq_add_stmt (stmt_list, gimple_build_label (label_true));
3708 }
3709
3710 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3711 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_KIND_SIMD)
3712 {
3713 simduid = find_omp_clause (orig_clauses, OMP_CLAUSE__SIMDUID_);
3714 if (simduid)
3715 simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
3716 }
3717
3718 for (c = clauses; c ;)
3719 {
3720 tree var, new_var;
3721 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
3722
3723 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
3724 || (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
3725 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c)))
3726 {
3727 var = OMP_CLAUSE_DECL (c);
3728 new_var = lookup_decl (var, ctx);
3729
3730 if (simduid && DECL_HAS_VALUE_EXPR_P (new_var))
3731 {
3732 tree val = DECL_VALUE_EXPR (new_var);
3733 if (TREE_CODE (val) == ARRAY_REF
3734 && VAR_P (TREE_OPERAND (val, 0))
3735 && lookup_attribute ("omp simd array",
3736 DECL_ATTRIBUTES (TREE_OPERAND (val,
3737 0))))
3738 {
3739 if (lastlane == NULL)
3740 {
3741 lastlane = create_tmp_var (unsigned_type_node, NULL);
3742 gimple g
3743 = gimple_build_call_internal (IFN_GOMP_SIMD_LAST_LANE,
3744 2, simduid,
3745 TREE_OPERAND (val, 1));
3746 gimple_call_set_lhs (g, lastlane);
3747 gimple_seq_add_stmt (stmt_list, g);
3748 }
3749 new_var = build4 (ARRAY_REF, TREE_TYPE (val),
3750 TREE_OPERAND (val, 0), lastlane,
3751 NULL_TREE, NULL_TREE);
3752 }
3753 }
3754
3755 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
3756 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
3757 {
3758 lower_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
3759 gimple_seq_add_seq (stmt_list,
3760 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c));
3761 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c) = NULL;
3762 }
3763
3764 x = build_outer_var_ref (var, ctx);
3765 if (is_reference (var))
3766 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
3767 x = lang_hooks.decls.omp_clause_assign_op (c, x, new_var);
3768 gimplify_and_add (x, stmt_list);
3769 }
3770 c = OMP_CLAUSE_CHAIN (c);
3771 if (c == NULL && !par_clauses)
3772 {
3773 /* If this was a workshare clause, see if it had been combined
3774 with its parallel. In that case, continue looking for the
3775 clauses also on the parallel statement itself. */
3776 if (is_parallel_ctx (ctx))
3777 break;
3778
3779 ctx = ctx->outer;
3780 if (ctx == NULL || !is_parallel_ctx (ctx))
3781 break;
3782
3783 c = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
3784 OMP_CLAUSE_LASTPRIVATE);
3785 par_clauses = true;
3786 }
3787 }
3788
3789 if (label)
3790 gimple_seq_add_stmt (stmt_list, gimple_build_label (label));
3791 }
3792
3793
3794 /* Generate code to implement the REDUCTION clauses. */
3795
3796 static void
3797 lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp, omp_context *ctx)
3798 {
3799 gimple_seq sub_seq = NULL;
3800 gimple stmt;
3801 tree x, c;
3802 int count = 0;
3803
3804 /* SIMD reductions are handled in lower_rec_input_clauses. */
3805 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3806 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_KIND_SIMD)
3807 return;
3808
3809 /* First see if there is exactly one reduction clause. Use OMP_ATOMIC
3810 update in that case, otherwise use a lock. */
3811 for (c = clauses; c && count < 2; c = OMP_CLAUSE_CHAIN (c))
3812 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
3813 {
3814 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
3815 {
3816 /* Never use OMP_ATOMIC for array reductions or UDRs. */
3817 count = -1;
3818 break;
3819 }
3820 count++;
3821 }
3822
3823 if (count == 0)
3824 return;
3825
3826 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
3827 {
3828 tree var, ref, new_var;
3829 enum tree_code code;
3830 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
3831
3832 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
3833 continue;
3834
3835 var = OMP_CLAUSE_DECL (c);
3836 new_var = lookup_decl (var, ctx);
3837 if (is_reference (var))
3838 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
3839 ref = build_outer_var_ref (var, ctx);
3840 code = OMP_CLAUSE_REDUCTION_CODE (c);
3841
3842 /* reduction(-:var) sums up the partial results, so it acts
3843 identically to reduction(+:var). */
3844 if (code == MINUS_EXPR)
3845 code = PLUS_EXPR;
3846
3847 if (count == 1)
3848 {
3849 tree addr = build_fold_addr_expr_loc (clause_loc, ref);
3850
3851 addr = save_expr (addr);
3852 ref = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (addr)), addr);
3853 x = fold_build2_loc (clause_loc, code, TREE_TYPE (ref), ref, new_var);
3854 x = build2 (OMP_ATOMIC, void_type_node, addr, x);
3855 gimplify_and_add (x, stmt_seqp);
3856 return;
3857 }
3858
3859 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
3860 {
3861 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
3862
3863 if (is_reference (var)
3864 && !useless_type_conversion_p (TREE_TYPE (placeholder),
3865 TREE_TYPE (ref)))
3866 ref = build_fold_addr_expr_loc (clause_loc, ref);
3867 SET_DECL_VALUE_EXPR (placeholder, ref);
3868 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
3869 lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
3870 gimple_seq_add_seq (&sub_seq, OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
3871 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
3872 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
3873 }
3874 else
3875 {
3876 x = build2 (code, TREE_TYPE (ref), ref, new_var);
3877 ref = build_outer_var_ref (var, ctx);
3878 gimplify_assign (ref, x, &sub_seq);
3879 }
3880 }
3881
3882 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START),
3883 0);
3884 gimple_seq_add_stmt (stmt_seqp, stmt);
3885
3886 gimple_seq_add_seq (stmt_seqp, sub_seq);
3887
3888 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END),
3889 0);
3890 gimple_seq_add_stmt (stmt_seqp, stmt);
3891 }
3892
3893
3894 /* Generate code to implement the COPYPRIVATE clauses. */
3895
3896 static void
3897 lower_copyprivate_clauses (tree clauses, gimple_seq *slist, gimple_seq *rlist,
3898 omp_context *ctx)
3899 {
3900 tree c;
3901
3902 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
3903 {
3904 tree var, new_var, ref, x;
3905 bool by_ref;
3906 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
3907
3908 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYPRIVATE)
3909 continue;
3910
3911 var = OMP_CLAUSE_DECL (c);
3912 by_ref = use_pointer_for_field (var, NULL);
3913
3914 ref = build_sender_ref (var, ctx);
3915 x = new_var = lookup_decl_in_outer_ctx (var, ctx);
3916 if (by_ref)
3917 {
3918 x = build_fold_addr_expr_loc (clause_loc, new_var);
3919 x = fold_convert_loc (clause_loc, TREE_TYPE (ref), x);
3920 }
3921 gimplify_assign (ref, x, slist);
3922
3923 ref = build_receiver_ref (var, false, ctx);
3924 if (by_ref)
3925 {
3926 ref = fold_convert_loc (clause_loc,
3927 build_pointer_type (TREE_TYPE (new_var)),
3928 ref);
3929 ref = build_fold_indirect_ref_loc (clause_loc, ref);
3930 }
3931 if (is_reference (var))
3932 {
3933 ref = fold_convert_loc (clause_loc, TREE_TYPE (new_var), ref);
3934 ref = build_simple_mem_ref_loc (clause_loc, ref);
3935 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
3936 }
3937 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, ref);
3938 gimplify_and_add (x, rlist);
3939 }
3940 }
3941
3942
3943 /* Generate code to implement the clauses, FIRSTPRIVATE, COPYIN, LASTPRIVATE,
3944 and REDUCTION from the sender (aka parent) side. */
3945
3946 static void
3947 lower_send_clauses (tree clauses, gimple_seq *ilist, gimple_seq *olist,
3948 omp_context *ctx)
3949 {
3950 tree c;
3951
3952 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
3953 {
3954 tree val, ref, x, var;
3955 bool by_ref, do_in = false, do_out = false;
3956 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
3957
3958 switch (OMP_CLAUSE_CODE (c))
3959 {
3960 case OMP_CLAUSE_PRIVATE:
3961 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
3962 break;
3963 continue;
3964 case OMP_CLAUSE_FIRSTPRIVATE:
3965 case OMP_CLAUSE_COPYIN:
3966 case OMP_CLAUSE_LASTPRIVATE:
3967 case OMP_CLAUSE_REDUCTION:
3968 case OMP_CLAUSE__LOOPTEMP_:
3969 break;
3970 default:
3971 continue;
3972 }
3973
3974 val = OMP_CLAUSE_DECL (c);
3975 var = lookup_decl_in_outer_ctx (val, ctx);
3976
3977 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYIN
3978 && is_global_var (var))
3979 continue;
3980 if (is_variable_sized (val))
3981 continue;
3982 by_ref = use_pointer_for_field (val, NULL);
3983
3984 switch (OMP_CLAUSE_CODE (c))
3985 {
3986 case OMP_CLAUSE_PRIVATE:
3987 case OMP_CLAUSE_FIRSTPRIVATE:
3988 case OMP_CLAUSE_COPYIN:
3989 case OMP_CLAUSE__LOOPTEMP_:
3990 do_in = true;
3991 break;
3992
3993 case OMP_CLAUSE_LASTPRIVATE:
3994 if (by_ref || is_reference (val))
3995 {
3996 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
3997 continue;
3998 do_in = true;
3999 }
4000 else
4001 {
4002 do_out = true;
4003 if (lang_hooks.decls.omp_private_outer_ref (val))
4004 do_in = true;
4005 }
4006 break;
4007
4008 case OMP_CLAUSE_REDUCTION:
4009 do_in = true;
4010 do_out = !(by_ref || is_reference (val));
4011 break;
4012
4013 default:
4014 gcc_unreachable ();
4015 }
4016
4017 if (do_in)
4018 {
4019 ref = build_sender_ref (val, ctx);
4020 x = by_ref ? build_fold_addr_expr_loc (clause_loc, var) : var;
4021 gimplify_assign (ref, x, ilist);
4022 if (is_task_ctx (ctx))
4023 DECL_ABSTRACT_ORIGIN (TREE_OPERAND (ref, 1)) = NULL;
4024 }
4025
4026 if (do_out)
4027 {
4028 ref = build_sender_ref (val, ctx);
4029 gimplify_assign (var, ref, olist);
4030 }
4031 }
4032 }
4033
4034 /* Generate code to implement SHARED from the sender (aka parent)
4035 side. This is trickier, since GIMPLE_OMP_PARALLEL_CLAUSES doesn't
4036 list things that got automatically shared. */
4037
4038 static void
4039 lower_send_shared_vars (gimple_seq *ilist, gimple_seq *olist, omp_context *ctx)
4040 {
4041 tree var, ovar, nvar, f, x, record_type;
4042
4043 if (ctx->record_type == NULL)
4044 return;
4045
4046 record_type = ctx->srecord_type ? ctx->srecord_type : ctx->record_type;
4047 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
4048 {
4049 ovar = DECL_ABSTRACT_ORIGIN (f);
4050 nvar = maybe_lookup_decl (ovar, ctx);
4051 if (!nvar || !DECL_HAS_VALUE_EXPR_P (nvar))
4052 continue;
4053
4054 /* If CTX is a nested parallel directive. Find the immediately
4055 enclosing parallel or workshare construct that contains a
4056 mapping for OVAR. */
4057 var = lookup_decl_in_outer_ctx (ovar, ctx);
4058
4059 if (use_pointer_for_field (ovar, ctx))
4060 {
4061 x = build_sender_ref (ovar, ctx);
4062 var = build_fold_addr_expr (var);
4063 gimplify_assign (x, var, ilist);
4064 }
4065 else
4066 {
4067 x = build_sender_ref (ovar, ctx);
4068 gimplify_assign (x, var, ilist);
4069
4070 if (!TREE_READONLY (var)
4071 /* We don't need to receive a new reference to a result
4072 or parm decl. In fact we may not store to it as we will
4073 invalidate any pending RSO and generate wrong gimple
4074 during inlining. */
4075 && !((TREE_CODE (var) == RESULT_DECL
4076 || TREE_CODE (var) == PARM_DECL)
4077 && DECL_BY_REFERENCE (var)))
4078 {
4079 x = build_sender_ref (ovar, ctx);
4080 gimplify_assign (var, x, olist);
4081 }
4082 }
4083 }
4084 }
4085
4086
4087 /* A convenience function to build an empty GIMPLE_COND with just the
4088 condition. */
4089
4090 static gimple
4091 gimple_build_cond_empty (tree cond)
4092 {
4093 enum tree_code pred_code;
4094 tree lhs, rhs;
4095
4096 gimple_cond_get_ops_from_tree (cond, &pred_code, &lhs, &rhs);
4097 return gimple_build_cond (pred_code, lhs, rhs, NULL_TREE, NULL_TREE);
4098 }
4099
4100
4101 /* Build the function calls to GOMP_parallel_start etc to actually
4102 generate the parallel operation. REGION is the parallel region
4103 being expanded. BB is the block where to insert the code. WS_ARGS
4104 will be set if this is a call to a combined parallel+workshare
4105 construct, it contains the list of additional arguments needed by
4106 the workshare construct. */
4107
4108 static void
4109 expand_parallel_call (struct omp_region *region, basic_block bb,
4110 gimple entry_stmt, vec<tree, va_gc> *ws_args)
4111 {
4112 tree t, t1, t2, val, cond, c, clauses, flags;
4113 gimple_stmt_iterator gsi;
4114 gimple stmt;
4115 enum built_in_function start_ix;
4116 int start_ix2;
4117 location_t clause_loc;
4118 vec<tree, va_gc> *args;
4119
4120 clauses = gimple_omp_parallel_clauses (entry_stmt);
4121
4122 /* Determine what flavor of GOMP_parallel we will be
4123 emitting. */
4124 start_ix = BUILT_IN_GOMP_PARALLEL;
4125 if (is_combined_parallel (region))
4126 {
4127 switch (region->inner->type)
4128 {
4129 case GIMPLE_OMP_FOR:
4130 gcc_assert (region->inner->sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
4131 start_ix2 = ((int)BUILT_IN_GOMP_PARALLEL_LOOP_STATIC
4132 + (region->inner->sched_kind
4133 == OMP_CLAUSE_SCHEDULE_RUNTIME
4134 ? 3 : region->inner->sched_kind));
4135 start_ix = (enum built_in_function)start_ix2;
4136 break;
4137 case GIMPLE_OMP_SECTIONS:
4138 start_ix = BUILT_IN_GOMP_PARALLEL_SECTIONS;
4139 break;
4140 default:
4141 gcc_unreachable ();
4142 }
4143 }
4144
4145 /* By default, the value of NUM_THREADS is zero (selected at run time)
4146 and there is no conditional. */
4147 cond = NULL_TREE;
4148 val = build_int_cst (unsigned_type_node, 0);
4149 flags = build_int_cst (unsigned_type_node, 0);
4150
4151 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
4152 if (c)
4153 cond = OMP_CLAUSE_IF_EXPR (c);
4154
4155 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_THREADS);
4156 if (c)
4157 {
4158 val = OMP_CLAUSE_NUM_THREADS_EXPR (c);
4159 clause_loc = OMP_CLAUSE_LOCATION (c);
4160 }
4161 else
4162 clause_loc = gimple_location (entry_stmt);
4163
4164 c = find_omp_clause (clauses, OMP_CLAUSE_PROC_BIND);
4165 if (c)
4166 flags = build_int_cst (unsigned_type_node, OMP_CLAUSE_PROC_BIND_KIND (c));
4167
4168 /* Ensure 'val' is of the correct type. */
4169 val = fold_convert_loc (clause_loc, unsigned_type_node, val);
4170
4171 /* If we found the clause 'if (cond)', build either
4172 (cond != 0) or (cond ? val : 1u). */
4173 if (cond)
4174 {
4175 gimple_stmt_iterator gsi;
4176
4177 cond = gimple_boolify (cond);
4178
4179 if (integer_zerop (val))
4180 val = fold_build2_loc (clause_loc,
4181 EQ_EXPR, unsigned_type_node, cond,
4182 build_int_cst (TREE_TYPE (cond), 0));
4183 else
4184 {
4185 basic_block cond_bb, then_bb, else_bb;
4186 edge e, e_then, e_else;
4187 tree tmp_then, tmp_else, tmp_join, tmp_var;
4188
4189 tmp_var = create_tmp_var (TREE_TYPE (val), NULL);
4190 if (gimple_in_ssa_p (cfun))
4191 {
4192 tmp_then = make_ssa_name (tmp_var, NULL);
4193 tmp_else = make_ssa_name (tmp_var, NULL);
4194 tmp_join = make_ssa_name (tmp_var, NULL);
4195 }
4196 else
4197 {
4198 tmp_then = tmp_var;
4199 tmp_else = tmp_var;
4200 tmp_join = tmp_var;
4201 }
4202
4203 e = split_block (bb, NULL);
4204 cond_bb = e->src;
4205 bb = e->dest;
4206 remove_edge (e);
4207
4208 then_bb = create_empty_bb (cond_bb);
4209 else_bb = create_empty_bb (then_bb);
4210 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
4211 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
4212
4213 stmt = gimple_build_cond_empty (cond);
4214 gsi = gsi_start_bb (cond_bb);
4215 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4216
4217 gsi = gsi_start_bb (then_bb);
4218 stmt = gimple_build_assign (tmp_then, val);
4219 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4220
4221 gsi = gsi_start_bb (else_bb);
4222 stmt = gimple_build_assign
4223 (tmp_else, build_int_cst (unsigned_type_node, 1));
4224 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4225
4226 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
4227 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
4228 if (current_loops)
4229 {
4230 add_bb_to_loop (then_bb, cond_bb->loop_father);
4231 add_bb_to_loop (else_bb, cond_bb->loop_father);
4232 }
4233 e_then = make_edge (then_bb, bb, EDGE_FALLTHRU);
4234 e_else = make_edge (else_bb, bb, EDGE_FALLTHRU);
4235
4236 if (gimple_in_ssa_p (cfun))
4237 {
4238 gimple phi = create_phi_node (tmp_join, bb);
4239 add_phi_arg (phi, tmp_then, e_then, UNKNOWN_LOCATION);
4240 add_phi_arg (phi, tmp_else, e_else, UNKNOWN_LOCATION);
4241 }
4242
4243 val = tmp_join;
4244 }
4245
4246 gsi = gsi_start_bb (bb);
4247 val = force_gimple_operand_gsi (&gsi, val, true, NULL_TREE,
4248 false, GSI_CONTINUE_LINKING);
4249 }
4250
4251 gsi = gsi_last_bb (bb);
4252 t = gimple_omp_parallel_data_arg (entry_stmt);
4253 if (t == NULL)
4254 t1 = null_pointer_node;
4255 else
4256 t1 = build_fold_addr_expr (t);
4257 t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
4258
4259 vec_alloc (args, 4 + vec_safe_length (ws_args));
4260 args->quick_push (t2);
4261 args->quick_push (t1);
4262 args->quick_push (val);
4263 if (ws_args)
4264 args->splice (*ws_args);
4265 args->quick_push (flags);
4266
4267 t = build_call_expr_loc_vec (UNKNOWN_LOCATION,
4268 builtin_decl_explicit (start_ix), args);
4269
4270 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
4271 false, GSI_CONTINUE_LINKING);
4272 }
4273
4274
4275 /* Build the function call to GOMP_task to actually
4276 generate the task operation. BB is the block where to insert the code. */
4277
4278 static void
4279 expand_task_call (basic_block bb, gimple entry_stmt)
4280 {
4281 tree t, t1, t2, t3, flags, cond, c, c2, clauses, depend;
4282 gimple_stmt_iterator gsi;
4283 location_t loc = gimple_location (entry_stmt);
4284
4285 clauses = gimple_omp_task_clauses (entry_stmt);
4286
4287 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
4288 if (c)
4289 cond = gimple_boolify (OMP_CLAUSE_IF_EXPR (c));
4290 else
4291 cond = boolean_true_node;
4292
4293 c = find_omp_clause (clauses, OMP_CLAUSE_UNTIED);
4294 c2 = find_omp_clause (clauses, OMP_CLAUSE_MERGEABLE);
4295 depend = find_omp_clause (clauses, OMP_CLAUSE_DEPEND);
4296 flags = build_int_cst (unsigned_type_node,
4297 (c ? 1 : 0) + (c2 ? 4 : 0) + (depend ? 8 : 0));
4298
4299 c = find_omp_clause (clauses, OMP_CLAUSE_FINAL);
4300 if (c)
4301 {
4302 c = gimple_boolify (OMP_CLAUSE_FINAL_EXPR (c));
4303 c = fold_build3_loc (loc, COND_EXPR, unsigned_type_node, c,
4304 build_int_cst (unsigned_type_node, 2),
4305 build_int_cst (unsigned_type_node, 0));
4306 flags = fold_build2_loc (loc, PLUS_EXPR, unsigned_type_node, flags, c);
4307 }
4308 if (depend)
4309 depend = OMP_CLAUSE_DECL (depend);
4310 else
4311 depend = build_int_cst (ptr_type_node, 0);
4312
4313 gsi = gsi_last_bb (bb);
4314 t = gimple_omp_task_data_arg (entry_stmt);
4315 if (t == NULL)
4316 t2 = null_pointer_node;
4317 else
4318 t2 = build_fold_addr_expr_loc (loc, t);
4319 t1 = build_fold_addr_expr_loc (loc, gimple_omp_task_child_fn (entry_stmt));
4320 t = gimple_omp_task_copy_fn (entry_stmt);
4321 if (t == NULL)
4322 t3 = null_pointer_node;
4323 else
4324 t3 = build_fold_addr_expr_loc (loc, t);
4325
4326 t = build_call_expr (builtin_decl_explicit (BUILT_IN_GOMP_TASK),
4327 8, t1, t2, t3,
4328 gimple_omp_task_arg_size (entry_stmt),
4329 gimple_omp_task_arg_align (entry_stmt), cond, flags,
4330 depend);
4331
4332 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
4333 false, GSI_CONTINUE_LINKING);
4334 }
4335
4336
4337 /* If exceptions are enabled, wrap the statements in BODY in a MUST_NOT_THROW
4338 catch handler and return it. This prevents programs from violating the
4339 structured block semantics with throws. */
4340
4341 static gimple_seq
4342 maybe_catch_exception (gimple_seq body)
4343 {
4344 gimple g;
4345 tree decl;
4346
4347 if (!flag_exceptions)
4348 return body;
4349
4350 if (lang_hooks.eh_protect_cleanup_actions != NULL)
4351 decl = lang_hooks.eh_protect_cleanup_actions ();
4352 else
4353 decl = builtin_decl_explicit (BUILT_IN_TRAP);
4354
4355 g = gimple_build_eh_must_not_throw (decl);
4356 g = gimple_build_try (body, gimple_seq_alloc_with_stmt (g),
4357 GIMPLE_TRY_CATCH);
4358
4359 return gimple_seq_alloc_with_stmt (g);
4360 }
4361
4362 /* Chain all the DECLs in LIST by their TREE_CHAIN fields. */
4363
4364 static tree
4365 vec2chain (vec<tree, va_gc> *v)
4366 {
4367 tree chain = NULL_TREE, t;
4368 unsigned ix;
4369
4370 FOR_EACH_VEC_SAFE_ELT_REVERSE (v, ix, t)
4371 {
4372 DECL_CHAIN (t) = chain;
4373 chain = t;
4374 }
4375
4376 return chain;
4377 }
4378
4379
4380 /* Remove barriers in REGION->EXIT's block. Note that this is only
4381 valid for GIMPLE_OMP_PARALLEL regions. Since the end of a parallel region
4382 is an implicit barrier, any workshare inside the GIMPLE_OMP_PARALLEL that
4383 left a barrier at the end of the GIMPLE_OMP_PARALLEL region can now be
4384 removed. */
4385
4386 static void
4387 remove_exit_barrier (struct omp_region *region)
4388 {
4389 gimple_stmt_iterator gsi;
4390 basic_block exit_bb;
4391 edge_iterator ei;
4392 edge e;
4393 gimple stmt;
4394 int any_addressable_vars = -1;
4395
4396 exit_bb = region->exit;
4397
4398 /* If the parallel region doesn't return, we don't have REGION->EXIT
4399 block at all. */
4400 if (! exit_bb)
4401 return;
4402
4403 /* The last insn in the block will be the parallel's GIMPLE_OMP_RETURN. The
4404 workshare's GIMPLE_OMP_RETURN will be in a preceding block. The kinds of
4405 statements that can appear in between are extremely limited -- no
4406 memory operations at all. Here, we allow nothing at all, so the
4407 only thing we allow to precede this GIMPLE_OMP_RETURN is a label. */
4408 gsi = gsi_last_bb (exit_bb);
4409 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
4410 gsi_prev (&gsi);
4411 if (!gsi_end_p (gsi) && gimple_code (gsi_stmt (gsi)) != GIMPLE_LABEL)
4412 return;
4413
4414 FOR_EACH_EDGE (e, ei, exit_bb->preds)
4415 {
4416 gsi = gsi_last_bb (e->src);
4417 if (gsi_end_p (gsi))
4418 continue;
4419 stmt = gsi_stmt (gsi);
4420 if (gimple_code (stmt) == GIMPLE_OMP_RETURN
4421 && !gimple_omp_return_nowait_p (stmt))
4422 {
4423 /* OpenMP 3.0 tasks unfortunately prevent this optimization
4424 in many cases. If there could be tasks queued, the barrier
4425 might be needed to let the tasks run before some local
4426 variable of the parallel that the task uses as shared
4427 runs out of scope. The task can be spawned either
4428 from within current function (this would be easy to check)
4429 or from some function it calls and gets passed an address
4430 of such a variable. */
4431 if (any_addressable_vars < 0)
4432 {
4433 gimple parallel_stmt = last_stmt (region->entry);
4434 tree child_fun = gimple_omp_parallel_child_fn (parallel_stmt);
4435 tree local_decls, block, decl;
4436 unsigned ix;
4437
4438 any_addressable_vars = 0;
4439 FOR_EACH_LOCAL_DECL (DECL_STRUCT_FUNCTION (child_fun), ix, decl)
4440 if (TREE_ADDRESSABLE (decl))
4441 {
4442 any_addressable_vars = 1;
4443 break;
4444 }
4445 for (block = gimple_block (stmt);
4446 !any_addressable_vars
4447 && block
4448 && TREE_CODE (block) == BLOCK;
4449 block = BLOCK_SUPERCONTEXT (block))
4450 {
4451 for (local_decls = BLOCK_VARS (block);
4452 local_decls;
4453 local_decls = DECL_CHAIN (local_decls))
4454 if (TREE_ADDRESSABLE (local_decls))
4455 {
4456 any_addressable_vars = 1;
4457 break;
4458 }
4459 if (block == gimple_block (parallel_stmt))
4460 break;
4461 }
4462 }
4463 if (!any_addressable_vars)
4464 gimple_omp_return_set_nowait (stmt);
4465 }
4466 }
4467 }
4468
4469 static void
4470 remove_exit_barriers (struct omp_region *region)
4471 {
4472 if (region->type == GIMPLE_OMP_PARALLEL)
4473 remove_exit_barrier (region);
4474
4475 if (region->inner)
4476 {
4477 region = region->inner;
4478 remove_exit_barriers (region);
4479 while (region->next)
4480 {
4481 region = region->next;
4482 remove_exit_barriers (region);
4483 }
4484 }
4485 }
4486
4487 /* Optimize omp_get_thread_num () and omp_get_num_threads ()
4488 calls. These can't be declared as const functions, but
4489 within one parallel body they are constant, so they can be
4490 transformed there into __builtin_omp_get_{thread_num,num_threads} ()
4491 which are declared const. Similarly for task body, except
4492 that in untied task omp_get_thread_num () can change at any task
4493 scheduling point. */
4494
4495 static void
4496 optimize_omp_library_calls (gimple entry_stmt)
4497 {
4498 basic_block bb;
4499 gimple_stmt_iterator gsi;
4500 tree thr_num_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
4501 tree thr_num_id = DECL_ASSEMBLER_NAME (thr_num_tree);
4502 tree num_thr_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
4503 tree num_thr_id = DECL_ASSEMBLER_NAME (num_thr_tree);
4504 bool untied_task = (gimple_code (entry_stmt) == GIMPLE_OMP_TASK
4505 && find_omp_clause (gimple_omp_task_clauses (entry_stmt),
4506 OMP_CLAUSE_UNTIED) != NULL);
4507
4508 FOR_EACH_BB (bb)
4509 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
4510 {
4511 gimple call = gsi_stmt (gsi);
4512 tree decl;
4513
4514 if (is_gimple_call (call)
4515 && (decl = gimple_call_fndecl (call))
4516 && DECL_EXTERNAL (decl)
4517 && TREE_PUBLIC (decl)
4518 && DECL_INITIAL (decl) == NULL)
4519 {
4520 tree built_in;
4521
4522 if (DECL_NAME (decl) == thr_num_id)
4523 {
4524 /* In #pragma omp task untied omp_get_thread_num () can change
4525 during the execution of the task region. */
4526 if (untied_task)
4527 continue;
4528 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
4529 }
4530 else if (DECL_NAME (decl) == num_thr_id)
4531 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
4532 else
4533 continue;
4534
4535 if (DECL_ASSEMBLER_NAME (decl) != DECL_ASSEMBLER_NAME (built_in)
4536 || gimple_call_num_args (call) != 0)
4537 continue;
4538
4539 if (flag_exceptions && !TREE_NOTHROW (decl))
4540 continue;
4541
4542 if (TREE_CODE (TREE_TYPE (decl)) != FUNCTION_TYPE
4543 || !types_compatible_p (TREE_TYPE (TREE_TYPE (decl)),
4544 TREE_TYPE (TREE_TYPE (built_in))))
4545 continue;
4546
4547 gimple_call_set_fndecl (call, built_in);
4548 }
4549 }
4550 }
4551
4552 /* Callback for expand_omp_build_assign. Return non-NULL if *tp needs to be
4553 regimplified. */
4554
4555 static tree
4556 expand_omp_regimplify_p (tree *tp, int *walk_subtrees, void *)
4557 {
4558 tree t = *tp;
4559
4560 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
4561 if (TREE_CODE (t) == VAR_DECL && DECL_HAS_VALUE_EXPR_P (t))
4562 return t;
4563
4564 if (TREE_CODE (t) == ADDR_EXPR)
4565 recompute_tree_invariant_for_addr_expr (t);
4566
4567 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
4568 return NULL_TREE;
4569 }
4570
4571 /* Prepend TO = FROM assignment before *GSI_P. */
4572
4573 static void
4574 expand_omp_build_assign (gimple_stmt_iterator *gsi_p, tree to, tree from)
4575 {
4576 bool simple_p = DECL_P (to) && TREE_ADDRESSABLE (to);
4577 from = force_gimple_operand_gsi (gsi_p, from, simple_p, NULL_TREE,
4578 true, GSI_SAME_STMT);
4579 gimple stmt = gimple_build_assign (to, from);
4580 gsi_insert_before (gsi_p, stmt, GSI_SAME_STMT);
4581 if (walk_tree (&from, expand_omp_regimplify_p, NULL, NULL)
4582 || walk_tree (&to, expand_omp_regimplify_p, NULL, NULL))
4583 {
4584 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
4585 gimple_regimplify_operands (stmt, &gsi);
4586 }
4587 }
4588
4589 /* Expand the OpenMP parallel or task directive starting at REGION. */
4590
4591 static void
4592 expand_omp_taskreg (struct omp_region *region)
4593 {
4594 basic_block entry_bb, exit_bb, new_bb;
4595 struct function *child_cfun;
4596 tree child_fn, block, t;
4597 gimple_stmt_iterator gsi;
4598 gimple entry_stmt, stmt;
4599 edge e;
4600 vec<tree, va_gc> *ws_args;
4601
4602 entry_stmt = last_stmt (region->entry);
4603 child_fn = gimple_omp_taskreg_child_fn (entry_stmt);
4604 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
4605
4606 entry_bb = region->entry;
4607 exit_bb = region->exit;
4608
4609 if (is_combined_parallel (region))
4610 ws_args = region->ws_args;
4611 else
4612 ws_args = NULL;
4613
4614 if (child_cfun->cfg)
4615 {
4616 /* Due to inlining, it may happen that we have already outlined
4617 the region, in which case all we need to do is make the
4618 sub-graph unreachable and emit the parallel call. */
4619 edge entry_succ_e, exit_succ_e;
4620 gimple_stmt_iterator gsi;
4621
4622 entry_succ_e = single_succ_edge (entry_bb);
4623
4624 gsi = gsi_last_bb (entry_bb);
4625 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_PARALLEL
4626 || gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_TASK);
4627 gsi_remove (&gsi, true);
4628
4629 new_bb = entry_bb;
4630 if (exit_bb)
4631 {
4632 exit_succ_e = single_succ_edge (exit_bb);
4633 make_edge (new_bb, exit_succ_e->dest, EDGE_FALLTHRU);
4634 }
4635 remove_edge_and_dominated_blocks (entry_succ_e);
4636 }
4637 else
4638 {
4639 unsigned srcidx, dstidx, num;
4640
4641 /* If the parallel region needs data sent from the parent
4642 function, then the very first statement (except possible
4643 tree profile counter updates) of the parallel body
4644 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
4645 &.OMP_DATA_O is passed as an argument to the child function,
4646 we need to replace it with the argument as seen by the child
4647 function.
4648
4649 In most cases, this will end up being the identity assignment
4650 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
4651 a function call that has been inlined, the original PARM_DECL
4652 .OMP_DATA_I may have been converted into a different local
4653 variable. In which case, we need to keep the assignment. */
4654 if (gimple_omp_taskreg_data_arg (entry_stmt))
4655 {
4656 basic_block entry_succ_bb = single_succ (entry_bb);
4657 gimple_stmt_iterator gsi;
4658 tree arg, narg;
4659 gimple parcopy_stmt = NULL;
4660
4661 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
4662 {
4663 gimple stmt;
4664
4665 gcc_assert (!gsi_end_p (gsi));
4666 stmt = gsi_stmt (gsi);
4667 if (gimple_code (stmt) != GIMPLE_ASSIGN)
4668 continue;
4669
4670 if (gimple_num_ops (stmt) == 2)
4671 {
4672 tree arg = gimple_assign_rhs1 (stmt);
4673
4674 /* We're ignore the subcode because we're
4675 effectively doing a STRIP_NOPS. */
4676
4677 if (TREE_CODE (arg) == ADDR_EXPR
4678 && TREE_OPERAND (arg, 0)
4679 == gimple_omp_taskreg_data_arg (entry_stmt))
4680 {
4681 parcopy_stmt = stmt;
4682 break;
4683 }
4684 }
4685 }
4686
4687 gcc_assert (parcopy_stmt != NULL);
4688 arg = DECL_ARGUMENTS (child_fn);
4689
4690 if (!gimple_in_ssa_p (cfun))
4691 {
4692 if (gimple_assign_lhs (parcopy_stmt) == arg)
4693 gsi_remove (&gsi, true);
4694 else
4695 {
4696 /* ?? Is setting the subcode really necessary ?? */
4697 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (arg));
4698 gimple_assign_set_rhs1 (parcopy_stmt, arg);
4699 }
4700 }
4701 else
4702 {
4703 /* If we are in ssa form, we must load the value from the default
4704 definition of the argument. That should not be defined now,
4705 since the argument is not used uninitialized. */
4706 gcc_assert (ssa_default_def (cfun, arg) == NULL);
4707 narg = make_ssa_name (arg, gimple_build_nop ());
4708 set_ssa_default_def (cfun, arg, narg);
4709 /* ?? Is setting the subcode really necessary ?? */
4710 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (narg));
4711 gimple_assign_set_rhs1 (parcopy_stmt, narg);
4712 update_stmt (parcopy_stmt);
4713 }
4714 }
4715
4716 /* Declare local variables needed in CHILD_CFUN. */
4717 block = DECL_INITIAL (child_fn);
4718 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
4719 /* The gimplifier could record temporaries in parallel/task block
4720 rather than in containing function's local_decls chain,
4721 which would mean cgraph missed finalizing them. Do it now. */
4722 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
4723 if (TREE_CODE (t) == VAR_DECL
4724 && TREE_STATIC (t)
4725 && !DECL_EXTERNAL (t))
4726 varpool_finalize_decl (t);
4727 DECL_SAVED_TREE (child_fn) = NULL;
4728 /* We'll create a CFG for child_fn, so no gimple body is needed. */
4729 gimple_set_body (child_fn, NULL);
4730 TREE_USED (block) = 1;
4731
4732 /* Reset DECL_CONTEXT on function arguments. */
4733 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
4734 DECL_CONTEXT (t) = child_fn;
4735
4736 /* Split ENTRY_BB at GIMPLE_OMP_PARALLEL or GIMPLE_OMP_TASK,
4737 so that it can be moved to the child function. */
4738 gsi = gsi_last_bb (entry_bb);
4739 stmt = gsi_stmt (gsi);
4740 gcc_assert (stmt && (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
4741 || gimple_code (stmt) == GIMPLE_OMP_TASK));
4742 gsi_remove (&gsi, true);
4743 e = split_block (entry_bb, stmt);
4744 entry_bb = e->dest;
4745 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
4746
4747 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
4748 if (exit_bb)
4749 {
4750 gsi = gsi_last_bb (exit_bb);
4751 gcc_assert (!gsi_end_p (gsi)
4752 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
4753 stmt = gimple_build_return (NULL);
4754 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
4755 gsi_remove (&gsi, true);
4756 }
4757
4758 /* Move the parallel region into CHILD_CFUN. */
4759
4760 if (gimple_in_ssa_p (cfun))
4761 {
4762 init_tree_ssa (child_cfun);
4763 init_ssa_operands (child_cfun);
4764 child_cfun->gimple_df->in_ssa_p = true;
4765 block = NULL_TREE;
4766 }
4767 else
4768 block = gimple_block (entry_stmt);
4769
4770 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
4771 if (exit_bb)
4772 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
4773 /* When the OMP expansion process cannot guarantee an up-to-date
4774 loop tree arrange for the child function to fixup loops. */
4775 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
4776 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
4777
4778 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
4779 num = vec_safe_length (child_cfun->local_decls);
4780 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
4781 {
4782 t = (*child_cfun->local_decls)[srcidx];
4783 if (DECL_CONTEXT (t) == cfun->decl)
4784 continue;
4785 if (srcidx != dstidx)
4786 (*child_cfun->local_decls)[dstidx] = t;
4787 dstidx++;
4788 }
4789 if (dstidx != num)
4790 vec_safe_truncate (child_cfun->local_decls, dstidx);
4791
4792 /* Inform the callgraph about the new function. */
4793 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
4794 cgraph_add_new_function (child_fn, true);
4795
4796 /* Fix the callgraph edges for child_cfun. Those for cfun will be
4797 fixed in a following pass. */
4798 push_cfun (child_cfun);
4799 if (optimize)
4800 optimize_omp_library_calls (entry_stmt);
4801 rebuild_cgraph_edges ();
4802
4803 /* Some EH regions might become dead, see PR34608. If
4804 pass_cleanup_cfg isn't the first pass to happen with the
4805 new child, these dead EH edges might cause problems.
4806 Clean them up now. */
4807 if (flag_exceptions)
4808 {
4809 basic_block bb;
4810 bool changed = false;
4811
4812 FOR_EACH_BB (bb)
4813 changed |= gimple_purge_dead_eh_edges (bb);
4814 if (changed)
4815 cleanup_tree_cfg ();
4816 }
4817 if (gimple_in_ssa_p (cfun))
4818 update_ssa (TODO_update_ssa);
4819 pop_cfun ();
4820 }
4821
4822 /* Emit a library call to launch the children threads. */
4823 if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
4824 expand_parallel_call (region, new_bb, entry_stmt, ws_args);
4825 else
4826 expand_task_call (new_bb, entry_stmt);
4827 if (gimple_in_ssa_p (cfun))
4828 update_ssa (TODO_update_ssa_only_virtuals);
4829 }
4830
4831
4832 /* Helper function for expand_omp_{for_*,simd}. If this is the outermost
4833 of the combined collapse > 1 loop constructs, generate code like:
4834 if (__builtin_expect (N32 cond3 N31, 0)) goto ZERO_ITER_BB;
4835 if (cond3 is <)
4836 adj = STEP3 - 1;
4837 else
4838 adj = STEP3 + 1;
4839 count3 = (adj + N32 - N31) / STEP3;
4840 if (__builtin_expect (N22 cond2 N21, 0)) goto ZERO_ITER_BB;
4841 if (cond2 is <)
4842 adj = STEP2 - 1;
4843 else
4844 adj = STEP2 + 1;
4845 count2 = (adj + N22 - N21) / STEP2;
4846 if (__builtin_expect (N12 cond1 N11, 0)) goto ZERO_ITER_BB;
4847 if (cond1 is <)
4848 adj = STEP1 - 1;
4849 else
4850 adj = STEP1 + 1;
4851 count1 = (adj + N12 - N11) / STEP1;
4852 count = count1 * count2 * count3;
4853 Furthermore, if ZERO_ITER_BB is NULL, create a BB which does:
4854 count = 0;
4855 and set ZERO_ITER_BB to that bb. If this isn't the outermost
4856 of the combined loop constructs, just initialize COUNTS array
4857 from the _looptemp_ clauses. */
4858
4859 /* NOTE: It *could* be better to moosh all of the BBs together,
4860 creating one larger BB with all the computation and the unexpected
4861 jump at the end. I.e.
4862
4863 bool zero3, zero2, zero1, zero;
4864
4865 zero3 = N32 c3 N31;
4866 count3 = (N32 - N31) /[cl] STEP3;
4867 zero2 = N22 c2 N21;
4868 count2 = (N22 - N21) /[cl] STEP2;
4869 zero1 = N12 c1 N11;
4870 count1 = (N12 - N11) /[cl] STEP1;
4871 zero = zero3 || zero2 || zero1;
4872 count = count1 * count2 * count3;
4873 if (__builtin_expect(zero, false)) goto zero_iter_bb;
4874
4875 After all, we expect the zero=false, and thus we expect to have to
4876 evaluate all of the comparison expressions, so short-circuiting
4877 oughtn't be a win. Since the condition isn't protecting a
4878 denominator, we're not concerned about divide-by-zero, so we can
4879 fully evaluate count even if a numerator turned out to be wrong.
4880
4881 It seems like putting this all together would create much better
4882 scheduling opportunities, and less pressure on the chip's branch
4883 predictor. */
4884
4885 static void
4886 expand_omp_for_init_counts (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
4887 basic_block &entry_bb, tree *counts,
4888 basic_block &zero_iter_bb, int &first_zero_iter,
4889 basic_block &l2_dom_bb)
4890 {
4891 tree t, type = TREE_TYPE (fd->loop.v);
4892 gimple stmt;
4893 edge e, ne;
4894 int i;
4895
4896 /* Collapsed loops need work for expansion into SSA form. */
4897 gcc_assert (!gimple_in_ssa_p (cfun));
4898
4899 if (gimple_omp_for_combined_into_p (fd->for_stmt)
4900 && TREE_CODE (fd->loop.n2) != INTEGER_CST)
4901 {
4902 /* First two _looptemp_ clauses are for istart/iend, counts[0]
4903 isn't supposed to be handled, as the inner loop doesn't
4904 use it. */
4905 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
4906 OMP_CLAUSE__LOOPTEMP_);
4907 gcc_assert (innerc);
4908 for (i = 0; i < fd->collapse; i++)
4909 {
4910 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
4911 OMP_CLAUSE__LOOPTEMP_);
4912 gcc_assert (innerc);
4913 if (i)
4914 counts[i] = OMP_CLAUSE_DECL (innerc);
4915 else
4916 counts[0] = NULL_TREE;
4917 }
4918 return;
4919 }
4920
4921 for (i = 0; i < fd->collapse; i++)
4922 {
4923 tree itype = TREE_TYPE (fd->loops[i].v);
4924
4925 if (SSA_VAR_P (fd->loop.n2)
4926 && ((t = fold_binary (fd->loops[i].cond_code, boolean_type_node,
4927 fold_convert (itype, fd->loops[i].n1),
4928 fold_convert (itype, fd->loops[i].n2)))
4929 == NULL_TREE || !integer_onep (t)))
4930 {
4931 tree n1, n2;
4932 n1 = fold_convert (itype, unshare_expr (fd->loops[i].n1));
4933 n1 = force_gimple_operand_gsi (gsi, n1, true, NULL_TREE,
4934 true, GSI_SAME_STMT);
4935 n2 = fold_convert (itype, unshare_expr (fd->loops[i].n2));
4936 n2 = force_gimple_operand_gsi (gsi, n2, true, NULL_TREE,
4937 true, GSI_SAME_STMT);
4938 stmt = gimple_build_cond (fd->loops[i].cond_code, n1, n2,
4939 NULL_TREE, NULL_TREE);
4940 gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
4941 if (walk_tree (gimple_cond_lhs_ptr (stmt),
4942 expand_omp_regimplify_p, NULL, NULL)
4943 || walk_tree (gimple_cond_rhs_ptr (stmt),
4944 expand_omp_regimplify_p, NULL, NULL))
4945 {
4946 *gsi = gsi_for_stmt (stmt);
4947 gimple_regimplify_operands (stmt, gsi);
4948 }
4949 e = split_block (entry_bb, stmt);
4950 if (zero_iter_bb == NULL)
4951 {
4952 first_zero_iter = i;
4953 zero_iter_bb = create_empty_bb (entry_bb);
4954 if (current_loops)
4955 add_bb_to_loop (zero_iter_bb, entry_bb->loop_father);
4956 *gsi = gsi_after_labels (zero_iter_bb);
4957 stmt = gimple_build_assign (fd->loop.n2,
4958 build_zero_cst (type));
4959 gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
4960 set_immediate_dominator (CDI_DOMINATORS, zero_iter_bb,
4961 entry_bb);
4962 }
4963 ne = make_edge (entry_bb, zero_iter_bb, EDGE_FALSE_VALUE);
4964 ne->probability = REG_BR_PROB_BASE / 2000 - 1;
4965 e->flags = EDGE_TRUE_VALUE;
4966 e->probability = REG_BR_PROB_BASE - ne->probability;
4967 if (l2_dom_bb == NULL)
4968 l2_dom_bb = entry_bb;
4969 entry_bb = e->dest;
4970 *gsi = gsi_last_bb (entry_bb);
4971 }
4972
4973 if (POINTER_TYPE_P (itype))
4974 itype = signed_type_for (itype);
4975 t = build_int_cst (itype, (fd->loops[i].cond_code == LT_EXPR
4976 ? -1 : 1));
4977 t = fold_build2 (PLUS_EXPR, itype,
4978 fold_convert (itype, fd->loops[i].step), t);
4979 t = fold_build2 (PLUS_EXPR, itype, t,
4980 fold_convert (itype, fd->loops[i].n2));
4981 t = fold_build2 (MINUS_EXPR, itype, t,
4982 fold_convert (itype, fd->loops[i].n1));
4983 /* ?? We could probably use CEIL_DIV_EXPR instead of
4984 TRUNC_DIV_EXPR and adjusting by hand. Unless we can't
4985 generate the same code in the end because generically we
4986 don't know that the values involved must be negative for
4987 GT?? */
4988 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
4989 t = fold_build2 (TRUNC_DIV_EXPR, itype,
4990 fold_build1 (NEGATE_EXPR, itype, t),
4991 fold_build1 (NEGATE_EXPR, itype,
4992 fold_convert (itype,
4993 fd->loops[i].step)));
4994 else
4995 t = fold_build2 (TRUNC_DIV_EXPR, itype, t,
4996 fold_convert (itype, fd->loops[i].step));
4997 t = fold_convert (type, t);
4998 if (TREE_CODE (t) == INTEGER_CST)
4999 counts[i] = t;
5000 else
5001 {
5002 counts[i] = create_tmp_reg (type, ".count");
5003 expand_omp_build_assign (gsi, counts[i], t);
5004 }
5005 if (SSA_VAR_P (fd->loop.n2))
5006 {
5007 if (i == 0)
5008 t = counts[0];
5009 else
5010 t = fold_build2 (MULT_EXPR, type, fd->loop.n2, counts[i]);
5011 expand_omp_build_assign (gsi, fd->loop.n2, t);
5012 }
5013 }
5014 }
5015
5016
5017 /* Helper function for expand_omp_{for_*,simd}. Generate code like:
5018 T = V;
5019 V3 = N31 + (T % count3) * STEP3;
5020 T = T / count3;
5021 V2 = N21 + (T % count2) * STEP2;
5022 T = T / count2;
5023 V1 = N11 + T * STEP1;
5024 if this loop doesn't have an inner loop construct combined with it.
5025 If it does have an inner loop construct combined with it and the
5026 iteration count isn't known constant, store values from counts array
5027 into its _looptemp_ temporaries instead. */
5028
5029 static void
5030 expand_omp_for_init_vars (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
5031 tree *counts, gimple inner_stmt, tree startvar)
5032 {
5033 int i;
5034 if (gimple_omp_for_combined_p (fd->for_stmt))
5035 {
5036 /* If fd->loop.n2 is constant, then no propagation of the counts
5037 is needed, they are constant. */
5038 if (TREE_CODE (fd->loop.n2) == INTEGER_CST)
5039 return;
5040
5041 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
5042 ? gimple_omp_parallel_clauses (inner_stmt)
5043 : gimple_omp_for_clauses (inner_stmt);
5044 /* First two _looptemp_ clauses are for istart/iend, counts[0]
5045 isn't supposed to be handled, as the inner loop doesn't
5046 use it. */
5047 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
5048 gcc_assert (innerc);
5049 for (i = 0; i < fd->collapse; i++)
5050 {
5051 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5052 OMP_CLAUSE__LOOPTEMP_);
5053 gcc_assert (innerc);
5054 if (i)
5055 {
5056 tree tem = OMP_CLAUSE_DECL (innerc);
5057 tree t = fold_convert (TREE_TYPE (tem), counts[i]);
5058 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
5059 false, GSI_CONTINUE_LINKING);
5060 gimple stmt = gimple_build_assign (tem, t);
5061 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5062 }
5063 }
5064 return;
5065 }
5066
5067 tree type = TREE_TYPE (fd->loop.v);
5068 tree tem = create_tmp_reg (type, ".tem");
5069 gimple stmt = gimple_build_assign (tem, startvar);
5070 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5071
5072 for (i = fd->collapse - 1; i >= 0; i--)
5073 {
5074 tree vtype = TREE_TYPE (fd->loops[i].v), itype, t;
5075 itype = vtype;
5076 if (POINTER_TYPE_P (vtype))
5077 itype = signed_type_for (vtype);
5078 if (i != 0)
5079 t = fold_build2 (TRUNC_MOD_EXPR, type, tem, counts[i]);
5080 else
5081 t = tem;
5082 t = fold_convert (itype, t);
5083 t = fold_build2 (MULT_EXPR, itype, t,
5084 fold_convert (itype, fd->loops[i].step));
5085 if (POINTER_TYPE_P (vtype))
5086 t = fold_build_pointer_plus (fd->loops[i].n1, t);
5087 else
5088 t = fold_build2 (PLUS_EXPR, itype, fd->loops[i].n1, t);
5089 t = force_gimple_operand_gsi (gsi, t,
5090 DECL_P (fd->loops[i].v)
5091 && TREE_ADDRESSABLE (fd->loops[i].v),
5092 NULL_TREE, false,
5093 GSI_CONTINUE_LINKING);
5094 stmt = gimple_build_assign (fd->loops[i].v, t);
5095 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5096 if (i != 0)
5097 {
5098 t = fold_build2 (TRUNC_DIV_EXPR, type, tem, counts[i]);
5099 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
5100 false, GSI_CONTINUE_LINKING);
5101 stmt = gimple_build_assign (tem, t);
5102 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5103 }
5104 }
5105 }
5106
5107
5108 /* Helper function for expand_omp_for_*. Generate code like:
5109 L10:
5110 V3 += STEP3;
5111 if (V3 cond3 N32) goto BODY_BB; else goto L11;
5112 L11:
5113 V3 = N31;
5114 V2 += STEP2;
5115 if (V2 cond2 N22) goto BODY_BB; else goto L12;
5116 L12:
5117 V2 = N21;
5118 V1 += STEP1;
5119 goto BODY_BB; */
5120
5121 static basic_block
5122 extract_omp_for_update_vars (struct omp_for_data *fd, basic_block cont_bb,
5123 basic_block body_bb)
5124 {
5125 basic_block last_bb, bb, collapse_bb = NULL;
5126 int i;
5127 gimple_stmt_iterator gsi;
5128 edge e;
5129 tree t;
5130 gimple stmt;
5131
5132 last_bb = cont_bb;
5133 for (i = fd->collapse - 1; i >= 0; i--)
5134 {
5135 tree vtype = TREE_TYPE (fd->loops[i].v);
5136
5137 bb = create_empty_bb (last_bb);
5138 if (current_loops)
5139 add_bb_to_loop (bb, last_bb->loop_father);
5140 gsi = gsi_start_bb (bb);
5141
5142 if (i < fd->collapse - 1)
5143 {
5144 e = make_edge (last_bb, bb, EDGE_FALSE_VALUE);
5145 e->probability = REG_BR_PROB_BASE / 8;
5146
5147 t = fd->loops[i + 1].n1;
5148 t = force_gimple_operand_gsi (&gsi, t,
5149 DECL_P (fd->loops[i + 1].v)
5150 && TREE_ADDRESSABLE (fd->loops[i
5151 + 1].v),
5152 NULL_TREE, false,
5153 GSI_CONTINUE_LINKING);
5154 stmt = gimple_build_assign (fd->loops[i + 1].v, t);
5155 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5156 }
5157 else
5158 collapse_bb = bb;
5159
5160 set_immediate_dominator (CDI_DOMINATORS, bb, last_bb);
5161
5162 if (POINTER_TYPE_P (vtype))
5163 t = fold_build_pointer_plus (fd->loops[i].v, fd->loops[i].step);
5164 else
5165 t = fold_build2 (PLUS_EXPR, vtype, fd->loops[i].v, fd->loops[i].step);
5166 t = force_gimple_operand_gsi (&gsi, t,
5167 DECL_P (fd->loops[i].v)
5168 && TREE_ADDRESSABLE (fd->loops[i].v),
5169 NULL_TREE, false, GSI_CONTINUE_LINKING);
5170 stmt = gimple_build_assign (fd->loops[i].v, t);
5171 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5172
5173 if (i > 0)
5174 {
5175 t = fd->loops[i].n2;
5176 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5177 false, GSI_CONTINUE_LINKING);
5178 tree v = fd->loops[i].v;
5179 if (DECL_P (v) && TREE_ADDRESSABLE (v))
5180 v = force_gimple_operand_gsi (&gsi, v, true, NULL_TREE,
5181 false, GSI_CONTINUE_LINKING);
5182 t = fold_build2 (fd->loops[i].cond_code, boolean_type_node, v, t);
5183 stmt = gimple_build_cond_empty (t);
5184 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5185 e = make_edge (bb, body_bb, EDGE_TRUE_VALUE);
5186 e->probability = REG_BR_PROB_BASE * 7 / 8;
5187 }
5188 else
5189 make_edge (bb, body_bb, EDGE_FALLTHRU);
5190 last_bb = bb;
5191 }
5192
5193 return collapse_bb;
5194 }
5195
5196
5197 /* A subroutine of expand_omp_for. Generate code for a parallel
5198 loop with any schedule. Given parameters:
5199
5200 for (V = N1; V cond N2; V += STEP) BODY;
5201
5202 where COND is "<" or ">", we generate pseudocode
5203
5204 more = GOMP_loop_foo_start (N1, N2, STEP, CHUNK, &istart0, &iend0);
5205 if (more) goto L0; else goto L3;
5206 L0:
5207 V = istart0;
5208 iend = iend0;
5209 L1:
5210 BODY;
5211 V += STEP;
5212 if (V cond iend) goto L1; else goto L2;
5213 L2:
5214 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
5215 L3:
5216
5217 If this is a combined omp parallel loop, instead of the call to
5218 GOMP_loop_foo_start, we call GOMP_loop_foo_next.
5219 If this is gimple_omp_for_combined_p loop, then instead of assigning
5220 V and iend in L0 we assign the first two _looptemp_ clause decls of the
5221 inner GIMPLE_OMP_FOR and V += STEP; and
5222 if (V cond iend) goto L1; else goto L2; are removed.
5223
5224 For collapsed loops, given parameters:
5225 collapse(3)
5226 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
5227 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
5228 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
5229 BODY;
5230
5231 we generate pseudocode
5232
5233 if (__builtin_expect (N32 cond3 N31, 0)) goto Z0;
5234 if (cond3 is <)
5235 adj = STEP3 - 1;
5236 else
5237 adj = STEP3 + 1;
5238 count3 = (adj + N32 - N31) / STEP3;
5239 if (__builtin_expect (N22 cond2 N21, 0)) goto Z0;
5240 if (cond2 is <)
5241 adj = STEP2 - 1;
5242 else
5243 adj = STEP2 + 1;
5244 count2 = (adj + N22 - N21) / STEP2;
5245 if (__builtin_expect (N12 cond1 N11, 0)) goto Z0;
5246 if (cond1 is <)
5247 adj = STEP1 - 1;
5248 else
5249 adj = STEP1 + 1;
5250 count1 = (adj + N12 - N11) / STEP1;
5251 count = count1 * count2 * count3;
5252 goto Z1;
5253 Z0:
5254 count = 0;
5255 Z1:
5256 more = GOMP_loop_foo_start (0, count, 1, CHUNK, &istart0, &iend0);
5257 if (more) goto L0; else goto L3;
5258 L0:
5259 V = istart0;
5260 T = V;
5261 V3 = N31 + (T % count3) * STEP3;
5262 T = T / count3;
5263 V2 = N21 + (T % count2) * STEP2;
5264 T = T / count2;
5265 V1 = N11 + T * STEP1;
5266 iend = iend0;
5267 L1:
5268 BODY;
5269 V += 1;
5270 if (V < iend) goto L10; else goto L2;
5271 L10:
5272 V3 += STEP3;
5273 if (V3 cond3 N32) goto L1; else goto L11;
5274 L11:
5275 V3 = N31;
5276 V2 += STEP2;
5277 if (V2 cond2 N22) goto L1; else goto L12;
5278 L12:
5279 V2 = N21;
5280 V1 += STEP1;
5281 goto L1;
5282 L2:
5283 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
5284 L3:
5285
5286 */
5287
5288 static void
5289 expand_omp_for_generic (struct omp_region *region,
5290 struct omp_for_data *fd,
5291 enum built_in_function start_fn,
5292 enum built_in_function next_fn,
5293 gimple inner_stmt)
5294 {
5295 tree type, istart0, iend0, iend;
5296 tree t, vmain, vback, bias = NULL_TREE;
5297 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, collapse_bb;
5298 basic_block l2_bb = NULL, l3_bb = NULL;
5299 gimple_stmt_iterator gsi;
5300 gimple stmt;
5301 bool in_combined_parallel = is_combined_parallel (region);
5302 bool broken_loop = region->cont == NULL;
5303 edge e, ne;
5304 tree *counts = NULL;
5305 int i;
5306
5307 gcc_assert (!broken_loop || !in_combined_parallel);
5308 gcc_assert (fd->iter_type == long_integer_type_node
5309 || !in_combined_parallel);
5310
5311 type = TREE_TYPE (fd->loop.v);
5312 istart0 = create_tmp_var (fd->iter_type, ".istart0");
5313 iend0 = create_tmp_var (fd->iter_type, ".iend0");
5314 TREE_ADDRESSABLE (istart0) = 1;
5315 TREE_ADDRESSABLE (iend0) = 1;
5316
5317 /* See if we need to bias by LLONG_MIN. */
5318 if (fd->iter_type == long_long_unsigned_type_node
5319 && TREE_CODE (type) == INTEGER_TYPE
5320 && !TYPE_UNSIGNED (type))
5321 {
5322 tree n1, n2;
5323
5324 if (fd->loop.cond_code == LT_EXPR)
5325 {
5326 n1 = fd->loop.n1;
5327 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
5328 }
5329 else
5330 {
5331 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
5332 n2 = fd->loop.n1;
5333 }
5334 if (TREE_CODE (n1) != INTEGER_CST
5335 || TREE_CODE (n2) != INTEGER_CST
5336 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
5337 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
5338 }
5339
5340 entry_bb = region->entry;
5341 cont_bb = region->cont;
5342 collapse_bb = NULL;
5343 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
5344 gcc_assert (broken_loop
5345 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
5346 l0_bb = split_edge (FALLTHRU_EDGE (entry_bb));
5347 l1_bb = single_succ (l0_bb);
5348 if (!broken_loop)
5349 {
5350 l2_bb = create_empty_bb (cont_bb);
5351 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l1_bb);
5352 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
5353 }
5354 else
5355 l2_bb = NULL;
5356 l3_bb = BRANCH_EDGE (entry_bb)->dest;
5357 exit_bb = region->exit;
5358
5359 gsi = gsi_last_bb (entry_bb);
5360
5361 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
5362 if (fd->collapse > 1)
5363 {
5364 int first_zero_iter = -1;
5365 basic_block zero_iter_bb = NULL, l2_dom_bb = NULL;
5366
5367 counts = XALLOCAVEC (tree, fd->collapse);
5368 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
5369 zero_iter_bb, first_zero_iter,
5370 l2_dom_bb);
5371
5372 if (zero_iter_bb)
5373 {
5374 /* Some counts[i] vars might be uninitialized if
5375 some loop has zero iterations. But the body shouldn't
5376 be executed in that case, so just avoid uninit warnings. */
5377 for (i = first_zero_iter; i < fd->collapse; i++)
5378 if (SSA_VAR_P (counts[i]))
5379 TREE_NO_WARNING (counts[i]) = 1;
5380 gsi_prev (&gsi);
5381 e = split_block (entry_bb, gsi_stmt (gsi));
5382 entry_bb = e->dest;
5383 make_edge (zero_iter_bb, entry_bb, EDGE_FALLTHRU);
5384 gsi = gsi_last_bb (entry_bb);
5385 set_immediate_dominator (CDI_DOMINATORS, entry_bb,
5386 get_immediate_dominator (CDI_DOMINATORS,
5387 zero_iter_bb));
5388 }
5389 }
5390 if (in_combined_parallel)
5391 {
5392 /* In a combined parallel loop, emit a call to
5393 GOMP_loop_foo_next. */
5394 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
5395 build_fold_addr_expr (istart0),
5396 build_fold_addr_expr (iend0));
5397 }
5398 else
5399 {
5400 tree t0, t1, t2, t3, t4;
5401 /* If this is not a combined parallel loop, emit a call to
5402 GOMP_loop_foo_start in ENTRY_BB. */
5403 t4 = build_fold_addr_expr (iend0);
5404 t3 = build_fold_addr_expr (istart0);
5405 t2 = fold_convert (fd->iter_type, fd->loop.step);
5406 t1 = fd->loop.n2;
5407 t0 = fd->loop.n1;
5408 if (gimple_omp_for_combined_into_p (fd->for_stmt))
5409 {
5410 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
5411 OMP_CLAUSE__LOOPTEMP_);
5412 gcc_assert (innerc);
5413 t0 = OMP_CLAUSE_DECL (innerc);
5414 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5415 OMP_CLAUSE__LOOPTEMP_);
5416 gcc_assert (innerc);
5417 t1 = OMP_CLAUSE_DECL (innerc);
5418 }
5419 if (POINTER_TYPE_P (TREE_TYPE (t0))
5420 && TYPE_PRECISION (TREE_TYPE (t0))
5421 != TYPE_PRECISION (fd->iter_type))
5422 {
5423 /* Avoid casting pointers to integer of a different size. */
5424 tree itype = signed_type_for (type);
5425 t1 = fold_convert (fd->iter_type, fold_convert (itype, t1));
5426 t0 = fold_convert (fd->iter_type, fold_convert (itype, t0));
5427 }
5428 else
5429 {
5430 t1 = fold_convert (fd->iter_type, t1);
5431 t0 = fold_convert (fd->iter_type, t0);
5432 }
5433 if (bias)
5434 {
5435 t1 = fold_build2 (PLUS_EXPR, fd->iter_type, t1, bias);
5436 t0 = fold_build2 (PLUS_EXPR, fd->iter_type, t0, bias);
5437 }
5438 if (fd->iter_type == long_integer_type_node)
5439 {
5440 if (fd->chunk_size)
5441 {
5442 t = fold_convert (fd->iter_type, fd->chunk_size);
5443 t = build_call_expr (builtin_decl_explicit (start_fn),
5444 6, t0, t1, t2, t, t3, t4);
5445 }
5446 else
5447 t = build_call_expr (builtin_decl_explicit (start_fn),
5448 5, t0, t1, t2, t3, t4);
5449 }
5450 else
5451 {
5452 tree t5;
5453 tree c_bool_type;
5454 tree bfn_decl;
5455
5456 /* The GOMP_loop_ull_*start functions have additional boolean
5457 argument, true for < loops and false for > loops.
5458 In Fortran, the C bool type can be different from
5459 boolean_type_node. */
5460 bfn_decl = builtin_decl_explicit (start_fn);
5461 c_bool_type = TREE_TYPE (TREE_TYPE (bfn_decl));
5462 t5 = build_int_cst (c_bool_type,
5463 fd->loop.cond_code == LT_EXPR ? 1 : 0);
5464 if (fd->chunk_size)
5465 {
5466 tree bfn_decl = builtin_decl_explicit (start_fn);
5467 t = fold_convert (fd->iter_type, fd->chunk_size);
5468 t = build_call_expr (bfn_decl, 7, t5, t0, t1, t2, t, t3, t4);
5469 }
5470 else
5471 t = build_call_expr (builtin_decl_explicit (start_fn),
5472 6, t5, t0, t1, t2, t3, t4);
5473 }
5474 }
5475 if (TREE_TYPE (t) != boolean_type_node)
5476 t = fold_build2 (NE_EXPR, boolean_type_node,
5477 t, build_int_cst (TREE_TYPE (t), 0));
5478 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5479 true, GSI_SAME_STMT);
5480 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
5481
5482 /* Remove the GIMPLE_OMP_FOR statement. */
5483 gsi_remove (&gsi, true);
5484
5485 /* Iteration setup for sequential loop goes in L0_BB. */
5486 tree startvar = fd->loop.v;
5487 tree endvar = NULL_TREE;
5488
5489 if (gimple_omp_for_combined_p (fd->for_stmt))
5490 {
5491 gcc_assert (gimple_code (inner_stmt) == GIMPLE_OMP_FOR
5492 && gimple_omp_for_kind (inner_stmt)
5493 == GF_OMP_FOR_KIND_SIMD);
5494 tree innerc = find_omp_clause (gimple_omp_for_clauses (inner_stmt),
5495 OMP_CLAUSE__LOOPTEMP_);
5496 gcc_assert (innerc);
5497 startvar = OMP_CLAUSE_DECL (innerc);
5498 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5499 OMP_CLAUSE__LOOPTEMP_);
5500 gcc_assert (innerc);
5501 endvar = OMP_CLAUSE_DECL (innerc);
5502 }
5503
5504 gsi = gsi_start_bb (l0_bb);
5505 t = istart0;
5506 if (bias)
5507 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
5508 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
5509 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
5510 t = fold_convert (TREE_TYPE (startvar), t);
5511 t = force_gimple_operand_gsi (&gsi, t,
5512 DECL_P (startvar)
5513 && TREE_ADDRESSABLE (startvar),
5514 NULL_TREE, false, GSI_CONTINUE_LINKING);
5515 stmt = gimple_build_assign (startvar, t);
5516 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5517
5518 t = iend0;
5519 if (bias)
5520 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
5521 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
5522 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
5523 t = fold_convert (TREE_TYPE (startvar), t);
5524 iend = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5525 false, GSI_CONTINUE_LINKING);
5526 if (endvar)
5527 {
5528 stmt = gimple_build_assign (endvar, iend);
5529 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5530 }
5531 if (fd->collapse > 1)
5532 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
5533
5534 if (!broken_loop)
5535 {
5536 /* Code to control the increment and predicate for the sequential
5537 loop goes in the CONT_BB. */
5538 gsi = gsi_last_bb (cont_bb);
5539 stmt = gsi_stmt (gsi);
5540 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
5541 vmain = gimple_omp_continue_control_use (stmt);
5542 vback = gimple_omp_continue_control_def (stmt);
5543
5544 if (!gimple_omp_for_combined_p (fd->for_stmt))
5545 {
5546 if (POINTER_TYPE_P (type))
5547 t = fold_build_pointer_plus (vmain, fd->loop.step);
5548 else
5549 t = fold_build2 (PLUS_EXPR, type, vmain, fd->loop.step);
5550 t = force_gimple_operand_gsi (&gsi, t,
5551 DECL_P (vback)
5552 && TREE_ADDRESSABLE (vback),
5553 NULL_TREE, true, GSI_SAME_STMT);
5554 stmt = gimple_build_assign (vback, t);
5555 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
5556
5557 t = build2 (fd->loop.cond_code, boolean_type_node,
5558 DECL_P (vback) && TREE_ADDRESSABLE (vback) ? t : vback,
5559 iend);
5560 stmt = gimple_build_cond_empty (t);
5561 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
5562 }
5563
5564 /* Remove GIMPLE_OMP_CONTINUE. */
5565 gsi_remove (&gsi, true);
5566
5567 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
5568 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, l1_bb);
5569
5570 /* Emit code to get the next parallel iteration in L2_BB. */
5571 gsi = gsi_start_bb (l2_bb);
5572
5573 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
5574 build_fold_addr_expr (istart0),
5575 build_fold_addr_expr (iend0));
5576 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5577 false, GSI_CONTINUE_LINKING);
5578 if (TREE_TYPE (t) != boolean_type_node)
5579 t = fold_build2 (NE_EXPR, boolean_type_node,
5580 t, build_int_cst (TREE_TYPE (t), 0));
5581 stmt = gimple_build_cond_empty (t);
5582 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5583 }
5584
5585 /* Add the loop cleanup function. */
5586 gsi = gsi_last_bb (exit_bb);
5587 if (gimple_omp_return_nowait_p (gsi_stmt (gsi)))
5588 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_NOWAIT);
5589 else if (gimple_omp_return_lhs (gsi_stmt (gsi)))
5590 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_CANCEL);
5591 else
5592 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END);
5593 stmt = gimple_build_call (t, 0);
5594 if (gimple_omp_return_lhs (gsi_stmt (gsi)))
5595 gimple_call_set_lhs (stmt, gimple_omp_return_lhs (gsi_stmt (gsi)));
5596 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
5597 gsi_remove (&gsi, true);
5598
5599 /* Connect the new blocks. */
5600 find_edge (entry_bb, l0_bb)->flags = EDGE_TRUE_VALUE;
5601 find_edge (entry_bb, l3_bb)->flags = EDGE_FALSE_VALUE;
5602
5603 if (!broken_loop)
5604 {
5605 gimple_seq phis;
5606
5607 e = find_edge (cont_bb, l3_bb);
5608 ne = make_edge (l2_bb, l3_bb, EDGE_FALSE_VALUE);
5609
5610 phis = phi_nodes (l3_bb);
5611 for (gsi = gsi_start (phis); !gsi_end_p (gsi); gsi_next (&gsi))
5612 {
5613 gimple phi = gsi_stmt (gsi);
5614 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, ne),
5615 PHI_ARG_DEF_FROM_EDGE (phi, e));
5616 }
5617 remove_edge (e);
5618
5619 make_edge (cont_bb, l2_bb, EDGE_FALSE_VALUE);
5620 if (current_loops)
5621 add_bb_to_loop (l2_bb, cont_bb->loop_father);
5622 e = find_edge (cont_bb, l1_bb);
5623 if (gimple_omp_for_combined_p (fd->for_stmt))
5624 {
5625 remove_edge (e);
5626 e = NULL;
5627 }
5628 else if (fd->collapse > 1)
5629 {
5630 remove_edge (e);
5631 e = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
5632 }
5633 else
5634 e->flags = EDGE_TRUE_VALUE;
5635 if (e)
5636 {
5637 e->probability = REG_BR_PROB_BASE * 7 / 8;
5638 find_edge (cont_bb, l2_bb)->probability = REG_BR_PROB_BASE / 8;
5639 }
5640 else
5641 {
5642 e = find_edge (cont_bb, l2_bb);
5643 e->flags = EDGE_FALLTHRU;
5644 }
5645 make_edge (l2_bb, l0_bb, EDGE_TRUE_VALUE);
5646
5647 set_immediate_dominator (CDI_DOMINATORS, l2_bb,
5648 recompute_dominator (CDI_DOMINATORS, l2_bb));
5649 set_immediate_dominator (CDI_DOMINATORS, l3_bb,
5650 recompute_dominator (CDI_DOMINATORS, l3_bb));
5651 set_immediate_dominator (CDI_DOMINATORS, l0_bb,
5652 recompute_dominator (CDI_DOMINATORS, l0_bb));
5653 set_immediate_dominator (CDI_DOMINATORS, l1_bb,
5654 recompute_dominator (CDI_DOMINATORS, l1_bb));
5655
5656 struct loop *outer_loop = alloc_loop ();
5657 outer_loop->header = l0_bb;
5658 outer_loop->latch = l2_bb;
5659 add_loop (outer_loop, l0_bb->loop_father);
5660
5661 if (!gimple_omp_for_combined_p (fd->for_stmt))
5662 {
5663 struct loop *loop = alloc_loop ();
5664 loop->header = l1_bb;
5665 /* The loop may have multiple latches. */
5666 add_loop (loop, outer_loop);
5667 }
5668 }
5669 }
5670
5671
5672 /* A subroutine of expand_omp_for. Generate code for a parallel
5673 loop with static schedule and no specified chunk size. Given
5674 parameters:
5675
5676 for (V = N1; V cond N2; V += STEP) BODY;
5677
5678 where COND is "<" or ">", we generate pseudocode
5679
5680 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
5681 if (cond is <)
5682 adj = STEP - 1;
5683 else
5684 adj = STEP + 1;
5685 if ((__typeof (V)) -1 > 0 && cond is >)
5686 n = -(adj + N2 - N1) / -STEP;
5687 else
5688 n = (adj + N2 - N1) / STEP;
5689 q = n / nthreads;
5690 tt = n % nthreads;
5691 if (threadid < tt) goto L3; else goto L4;
5692 L3:
5693 tt = 0;
5694 q = q + 1;
5695 L4:
5696 s0 = q * threadid + tt;
5697 e0 = s0 + q;
5698 V = s0 * STEP + N1;
5699 if (s0 >= e0) goto L2; else goto L0;
5700 L0:
5701 e = e0 * STEP + N1;
5702 L1:
5703 BODY;
5704 V += STEP;
5705 if (V cond e) goto L1;
5706 L2:
5707 */
5708
5709 static void
5710 expand_omp_for_static_nochunk (struct omp_region *region,
5711 struct omp_for_data *fd,
5712 gimple inner_stmt)
5713 {
5714 tree n, q, s0, e0, e, t, tt, nthreads, threadid;
5715 tree type, itype, vmain, vback;
5716 basic_block entry_bb, second_bb, third_bb, exit_bb, seq_start_bb;
5717 basic_block body_bb, cont_bb, collapse_bb = NULL;
5718 basic_block fin_bb;
5719 gimple_stmt_iterator gsi;
5720 gimple stmt;
5721 edge ep;
5722 enum built_in_function get_num_threads = BUILT_IN_OMP_GET_NUM_THREADS;
5723 enum built_in_function get_thread_num = BUILT_IN_OMP_GET_THREAD_NUM;
5724 bool broken_loop = region->cont == NULL;
5725 tree *counts = NULL;
5726 tree n1, n2, step;
5727
5728 itype = type = TREE_TYPE (fd->loop.v);
5729 if (POINTER_TYPE_P (type))
5730 itype = signed_type_for (type);
5731
5732 entry_bb = region->entry;
5733 cont_bb = region->cont;
5734 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
5735 fin_bb = BRANCH_EDGE (entry_bb)->dest;
5736 gcc_assert (broken_loop
5737 || (fin_bb == FALLTHRU_EDGE (cont_bb)->dest));
5738 seq_start_bb = split_edge (FALLTHRU_EDGE (entry_bb));
5739 body_bb = single_succ (seq_start_bb);
5740 if (!broken_loop)
5741 {
5742 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
5743 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
5744 }
5745 exit_bb = region->exit;
5746
5747 /* Iteration space partitioning goes in ENTRY_BB. */
5748 gsi = gsi_last_bb (entry_bb);
5749 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
5750
5751 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
5752 {
5753 get_num_threads = BUILT_IN_OMP_GET_NUM_TEAMS;
5754 get_thread_num = BUILT_IN_OMP_GET_TEAM_NUM;
5755 }
5756
5757 if (fd->collapse > 1)
5758 {
5759 int first_zero_iter = -1;
5760 basic_block l2_dom_bb = NULL;
5761
5762 counts = XALLOCAVEC (tree, fd->collapse);
5763 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
5764 fin_bb, first_zero_iter,
5765 l2_dom_bb);
5766 t = NULL_TREE;
5767 }
5768 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
5769 t = integer_one_node;
5770 else
5771 t = fold_binary (fd->loop.cond_code, boolean_type_node,
5772 fold_convert (type, fd->loop.n1),
5773 fold_convert (type, fd->loop.n2));
5774 if (fd->collapse == 1
5775 && TYPE_UNSIGNED (type)
5776 && (t == NULL_TREE || !integer_onep (t)))
5777 {
5778 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
5779 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
5780 true, GSI_SAME_STMT);
5781 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
5782 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
5783 true, GSI_SAME_STMT);
5784 stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
5785 NULL_TREE, NULL_TREE);
5786 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
5787 if (walk_tree (gimple_cond_lhs_ptr (stmt),
5788 expand_omp_regimplify_p, NULL, NULL)
5789 || walk_tree (gimple_cond_rhs_ptr (stmt),
5790 expand_omp_regimplify_p, NULL, NULL))
5791 {
5792 gsi = gsi_for_stmt (stmt);
5793 gimple_regimplify_operands (stmt, &gsi);
5794 }
5795 ep = split_block (entry_bb, stmt);
5796 ep->flags = EDGE_TRUE_VALUE;
5797 entry_bb = ep->dest;
5798 ep->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
5799 ep = make_edge (ep->src, fin_bb, EDGE_FALSE_VALUE);
5800 ep->probability = REG_BR_PROB_BASE / 2000 - 1;
5801 if (gimple_in_ssa_p (cfun))
5802 {
5803 int dest_idx = find_edge (entry_bb, fin_bb)->dest_idx;
5804 for (gsi = gsi_start_phis (fin_bb);
5805 !gsi_end_p (gsi); gsi_next (&gsi))
5806 {
5807 gimple phi = gsi_stmt (gsi);
5808 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
5809 ep, UNKNOWN_LOCATION);
5810 }
5811 }
5812 gsi = gsi_last_bb (entry_bb);
5813 }
5814
5815 t = build_call_expr (builtin_decl_explicit (get_num_threads), 0);
5816 t = fold_convert (itype, t);
5817 nthreads = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5818 true, GSI_SAME_STMT);
5819
5820 t = build_call_expr (builtin_decl_explicit (get_thread_num), 0);
5821 t = fold_convert (itype, t);
5822 threadid = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5823 true, GSI_SAME_STMT);
5824
5825 n1 = fd->loop.n1;
5826 n2 = fd->loop.n2;
5827 step = fd->loop.step;
5828 if (gimple_omp_for_combined_into_p (fd->for_stmt))
5829 {
5830 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
5831 OMP_CLAUSE__LOOPTEMP_);
5832 gcc_assert (innerc);
5833 n1 = OMP_CLAUSE_DECL (innerc);
5834 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5835 OMP_CLAUSE__LOOPTEMP_);
5836 gcc_assert (innerc);
5837 n2 = OMP_CLAUSE_DECL (innerc);
5838 }
5839 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
5840 true, NULL_TREE, true, GSI_SAME_STMT);
5841 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
5842 true, NULL_TREE, true, GSI_SAME_STMT);
5843 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
5844 true, NULL_TREE, true, GSI_SAME_STMT);
5845
5846 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
5847 t = fold_build2 (PLUS_EXPR, itype, step, t);
5848 t = fold_build2 (PLUS_EXPR, itype, t, n2);
5849 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
5850 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
5851 t = fold_build2 (TRUNC_DIV_EXPR, itype,
5852 fold_build1 (NEGATE_EXPR, itype, t),
5853 fold_build1 (NEGATE_EXPR, itype, step));
5854 else
5855 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
5856 t = fold_convert (itype, t);
5857 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
5858
5859 q = create_tmp_reg (itype, "q");
5860 t = fold_build2 (TRUNC_DIV_EXPR, itype, n, nthreads);
5861 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
5862 gsi_insert_before (&gsi, gimple_build_assign (q, t), GSI_SAME_STMT);
5863
5864 tt = create_tmp_reg (itype, "tt");
5865 t = fold_build2 (TRUNC_MOD_EXPR, itype, n, nthreads);
5866 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
5867 gsi_insert_before (&gsi, gimple_build_assign (tt, t), GSI_SAME_STMT);
5868
5869 t = build2 (LT_EXPR, boolean_type_node, threadid, tt);
5870 stmt = gimple_build_cond_empty (t);
5871 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
5872
5873 second_bb = split_block (entry_bb, stmt)->dest;
5874 gsi = gsi_last_bb (second_bb);
5875 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
5876
5877 gsi_insert_before (&gsi, gimple_build_assign (tt, build_int_cst (itype, 0)),
5878 GSI_SAME_STMT);
5879 stmt = gimple_build_assign_with_ops (PLUS_EXPR, q, q,
5880 build_int_cst (itype, 1));
5881 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
5882
5883 third_bb = split_block (second_bb, stmt)->dest;
5884 gsi = gsi_last_bb (third_bb);
5885 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
5886
5887 t = build2 (MULT_EXPR, itype, q, threadid);
5888 t = build2 (PLUS_EXPR, itype, t, tt);
5889 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
5890
5891 t = fold_build2 (PLUS_EXPR, itype, s0, q);
5892 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
5893
5894 t = build2 (GE_EXPR, boolean_type_node, s0, e0);
5895 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
5896
5897 /* Remove the GIMPLE_OMP_FOR statement. */
5898 gsi_remove (&gsi, true);
5899
5900 /* Setup code for sequential iteration goes in SEQ_START_BB. */
5901 gsi = gsi_start_bb (seq_start_bb);
5902
5903 tree startvar = fd->loop.v;
5904 tree endvar = NULL_TREE;
5905
5906 if (gimple_omp_for_combined_p (fd->for_stmt))
5907 {
5908 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
5909 ? gimple_omp_parallel_clauses (inner_stmt)
5910 : gimple_omp_for_clauses (inner_stmt);
5911 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
5912 gcc_assert (innerc);
5913 startvar = OMP_CLAUSE_DECL (innerc);
5914 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5915 OMP_CLAUSE__LOOPTEMP_);
5916 gcc_assert (innerc);
5917 endvar = OMP_CLAUSE_DECL (innerc);
5918 }
5919 t = fold_convert (itype, s0);
5920 t = fold_build2 (MULT_EXPR, itype, t, step);
5921 if (POINTER_TYPE_P (type))
5922 t = fold_build_pointer_plus (n1, t);
5923 else
5924 t = fold_build2 (PLUS_EXPR, type, t, n1);
5925 t = fold_convert (TREE_TYPE (startvar), t);
5926 t = force_gimple_operand_gsi (&gsi, t,
5927 DECL_P (startvar)
5928 && TREE_ADDRESSABLE (startvar),
5929 NULL_TREE, false, GSI_CONTINUE_LINKING);
5930 stmt = gimple_build_assign (startvar, t);
5931 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5932
5933 t = fold_convert (itype, e0);
5934 t = fold_build2 (MULT_EXPR, itype, t, step);
5935 if (POINTER_TYPE_P (type))
5936 t = fold_build_pointer_plus (n1, t);
5937 else
5938 t = fold_build2 (PLUS_EXPR, type, t, n1);
5939 t = fold_convert (TREE_TYPE (startvar), t);
5940 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5941 false, GSI_CONTINUE_LINKING);
5942 if (endvar)
5943 {
5944 stmt = gimple_build_assign (endvar, e);
5945 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5946 }
5947 if (fd->collapse > 1)
5948 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
5949
5950 if (!broken_loop)
5951 {
5952 /* The code controlling the sequential loop replaces the
5953 GIMPLE_OMP_CONTINUE. */
5954 gsi = gsi_last_bb (cont_bb);
5955 stmt = gsi_stmt (gsi);
5956 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
5957 vmain = gimple_omp_continue_control_use (stmt);
5958 vback = gimple_omp_continue_control_def (stmt);
5959
5960 if (!gimple_omp_for_combined_p (fd->for_stmt))
5961 {
5962 if (POINTER_TYPE_P (type))
5963 t = fold_build_pointer_plus (vmain, step);
5964 else
5965 t = fold_build2 (PLUS_EXPR, type, vmain, step);
5966 t = force_gimple_operand_gsi (&gsi, t,
5967 DECL_P (vback)
5968 && TREE_ADDRESSABLE (vback),
5969 NULL_TREE, true, GSI_SAME_STMT);
5970 stmt = gimple_build_assign (vback, t);
5971 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
5972
5973 t = build2 (fd->loop.cond_code, boolean_type_node,
5974 DECL_P (vback) && TREE_ADDRESSABLE (vback)
5975 ? t : vback, e);
5976 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
5977 }
5978
5979 /* Remove the GIMPLE_OMP_CONTINUE statement. */
5980 gsi_remove (&gsi, true);
5981
5982 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
5983 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
5984 }
5985
5986 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
5987 gsi = gsi_last_bb (exit_bb);
5988 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
5989 {
5990 t = gimple_omp_return_lhs (gsi_stmt (gsi));
5991 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
5992 }
5993 gsi_remove (&gsi, true);
5994
5995 /* Connect all the blocks. */
5996 ep = make_edge (entry_bb, third_bb, EDGE_FALSE_VALUE);
5997 ep->probability = REG_BR_PROB_BASE / 4 * 3;
5998 ep = find_edge (entry_bb, second_bb);
5999 ep->flags = EDGE_TRUE_VALUE;
6000 ep->probability = REG_BR_PROB_BASE / 4;
6001 find_edge (third_bb, seq_start_bb)->flags = EDGE_FALSE_VALUE;
6002 find_edge (third_bb, fin_bb)->flags = EDGE_TRUE_VALUE;
6003
6004 if (!broken_loop)
6005 {
6006 ep = find_edge (cont_bb, body_bb);
6007 if (gimple_omp_for_combined_p (fd->for_stmt))
6008 {
6009 remove_edge (ep);
6010 ep = NULL;
6011 }
6012 else if (fd->collapse > 1)
6013 {
6014 remove_edge (ep);
6015 ep = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
6016 }
6017 else
6018 ep->flags = EDGE_TRUE_VALUE;
6019 find_edge (cont_bb, fin_bb)->flags
6020 = ep ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
6021 }
6022
6023 set_immediate_dominator (CDI_DOMINATORS, second_bb, entry_bb);
6024 set_immediate_dominator (CDI_DOMINATORS, third_bb, entry_bb);
6025 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb, third_bb);
6026
6027 set_immediate_dominator (CDI_DOMINATORS, body_bb,
6028 recompute_dominator (CDI_DOMINATORS, body_bb));
6029 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
6030 recompute_dominator (CDI_DOMINATORS, fin_bb));
6031
6032 if (!broken_loop && !gimple_omp_for_combined_p (fd->for_stmt))
6033 {
6034 struct loop *loop = alloc_loop ();
6035 loop->header = body_bb;
6036 if (collapse_bb == NULL)
6037 loop->latch = cont_bb;
6038 add_loop (loop, body_bb->loop_father);
6039 }
6040 }
6041
6042
6043 /* A subroutine of expand_omp_for. Generate code for a parallel
6044 loop with static schedule and a specified chunk size. Given
6045 parameters:
6046
6047 for (V = N1; V cond N2; V += STEP) BODY;
6048
6049 where COND is "<" or ">", we generate pseudocode
6050
6051 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
6052 if (cond is <)
6053 adj = STEP - 1;
6054 else
6055 adj = STEP + 1;
6056 if ((__typeof (V)) -1 > 0 && cond is >)
6057 n = -(adj + N2 - N1) / -STEP;
6058 else
6059 n = (adj + N2 - N1) / STEP;
6060 trip = 0;
6061 V = threadid * CHUNK * STEP + N1; -- this extra definition of V is
6062 here so that V is defined
6063 if the loop is not entered
6064 L0:
6065 s0 = (trip * nthreads + threadid) * CHUNK;
6066 e0 = min(s0 + CHUNK, n);
6067 if (s0 < n) goto L1; else goto L4;
6068 L1:
6069 V = s0 * STEP + N1;
6070 e = e0 * STEP + N1;
6071 L2:
6072 BODY;
6073 V += STEP;
6074 if (V cond e) goto L2; else goto L3;
6075 L3:
6076 trip += 1;
6077 goto L0;
6078 L4:
6079 */
6080
6081 static void
6082 expand_omp_for_static_chunk (struct omp_region *region,
6083 struct omp_for_data *fd, gimple inner_stmt)
6084 {
6085 tree n, s0, e0, e, t;
6086 tree trip_var, trip_init, trip_main, trip_back, nthreads, threadid;
6087 tree type, itype, v_main, v_back, v_extra;
6088 basic_block entry_bb, exit_bb, body_bb, seq_start_bb, iter_part_bb;
6089 basic_block trip_update_bb = NULL, cont_bb, collapse_bb = NULL, fin_bb;
6090 gimple_stmt_iterator si;
6091 gimple stmt;
6092 edge se;
6093 enum built_in_function get_num_threads = BUILT_IN_OMP_GET_NUM_THREADS;
6094 enum built_in_function get_thread_num = BUILT_IN_OMP_GET_THREAD_NUM;
6095 bool broken_loop = region->cont == NULL;
6096 tree *counts = NULL;
6097 tree n1, n2, step;
6098
6099 itype = type = TREE_TYPE (fd->loop.v);
6100 if (POINTER_TYPE_P (type))
6101 itype = signed_type_for (type);
6102
6103 entry_bb = region->entry;
6104 se = split_block (entry_bb, last_stmt (entry_bb));
6105 entry_bb = se->src;
6106 iter_part_bb = se->dest;
6107 cont_bb = region->cont;
6108 gcc_assert (EDGE_COUNT (iter_part_bb->succs) == 2);
6109 fin_bb = BRANCH_EDGE (iter_part_bb)->dest;
6110 gcc_assert (broken_loop
6111 || fin_bb == FALLTHRU_EDGE (cont_bb)->dest);
6112 seq_start_bb = split_edge (FALLTHRU_EDGE (iter_part_bb));
6113 body_bb = single_succ (seq_start_bb);
6114 if (!broken_loop)
6115 {
6116 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
6117 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
6118 trip_update_bb = split_edge (FALLTHRU_EDGE (cont_bb));
6119 }
6120 exit_bb = region->exit;
6121
6122 /* Trip and adjustment setup goes in ENTRY_BB. */
6123 si = gsi_last_bb (entry_bb);
6124 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_FOR);
6125
6126 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
6127 {
6128 get_num_threads = BUILT_IN_OMP_GET_NUM_TEAMS;
6129 get_thread_num = BUILT_IN_OMP_GET_TEAM_NUM;
6130 }
6131
6132 if (fd->collapse > 1)
6133 {
6134 int first_zero_iter = -1;
6135 basic_block l2_dom_bb = NULL;
6136
6137 counts = XALLOCAVEC (tree, fd->collapse);
6138 expand_omp_for_init_counts (fd, &si, entry_bb, counts,
6139 fin_bb, first_zero_iter,
6140 l2_dom_bb);
6141 t = NULL_TREE;
6142 }
6143 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
6144 t = integer_one_node;
6145 else
6146 t = fold_binary (fd->loop.cond_code, boolean_type_node,
6147 fold_convert (type, fd->loop.n1),
6148 fold_convert (type, fd->loop.n2));
6149 if (fd->collapse == 1
6150 && TYPE_UNSIGNED (type)
6151 && (t == NULL_TREE || !integer_onep (t)))
6152 {
6153 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
6154 n1 = force_gimple_operand_gsi (&si, n1, true, NULL_TREE,
6155 true, GSI_SAME_STMT);
6156 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
6157 n2 = force_gimple_operand_gsi (&si, n2, true, NULL_TREE,
6158 true, GSI_SAME_STMT);
6159 stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
6160 NULL_TREE, NULL_TREE);
6161 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
6162 if (walk_tree (gimple_cond_lhs_ptr (stmt),
6163 expand_omp_regimplify_p, NULL, NULL)
6164 || walk_tree (gimple_cond_rhs_ptr (stmt),
6165 expand_omp_regimplify_p, NULL, NULL))
6166 {
6167 si = gsi_for_stmt (stmt);
6168 gimple_regimplify_operands (stmt, &si);
6169 }
6170 se = split_block (entry_bb, stmt);
6171 se->flags = EDGE_TRUE_VALUE;
6172 entry_bb = se->dest;
6173 se->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
6174 se = make_edge (se->src, fin_bb, EDGE_FALSE_VALUE);
6175 se->probability = REG_BR_PROB_BASE / 2000 - 1;
6176 if (gimple_in_ssa_p (cfun))
6177 {
6178 int dest_idx = find_edge (entry_bb, fin_bb)->dest_idx;
6179 for (si = gsi_start_phis (fin_bb);
6180 !gsi_end_p (si); gsi_next (&si))
6181 {
6182 gimple phi = gsi_stmt (si);
6183 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
6184 se, UNKNOWN_LOCATION);
6185 }
6186 }
6187 si = gsi_last_bb (entry_bb);
6188 }
6189
6190 t = build_call_expr (builtin_decl_explicit (get_num_threads), 0);
6191 t = fold_convert (itype, t);
6192 nthreads = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
6193 true, GSI_SAME_STMT);
6194
6195 t = build_call_expr (builtin_decl_explicit (get_thread_num), 0);
6196 t = fold_convert (itype, t);
6197 threadid = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
6198 true, GSI_SAME_STMT);
6199
6200 n1 = fd->loop.n1;
6201 n2 = fd->loop.n2;
6202 step = fd->loop.step;
6203 if (gimple_omp_for_combined_into_p (fd->for_stmt))
6204 {
6205 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
6206 OMP_CLAUSE__LOOPTEMP_);
6207 gcc_assert (innerc);
6208 n1 = OMP_CLAUSE_DECL (innerc);
6209 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6210 OMP_CLAUSE__LOOPTEMP_);
6211 gcc_assert (innerc);
6212 n2 = OMP_CLAUSE_DECL (innerc);
6213 }
6214 n1 = force_gimple_operand_gsi (&si, fold_convert (type, n1),
6215 true, NULL_TREE, true, GSI_SAME_STMT);
6216 n2 = force_gimple_operand_gsi (&si, fold_convert (itype, n2),
6217 true, NULL_TREE, true, GSI_SAME_STMT);
6218 step = force_gimple_operand_gsi (&si, fold_convert (itype, step),
6219 true, NULL_TREE, true, GSI_SAME_STMT);
6220 fd->chunk_size
6221 = force_gimple_operand_gsi (&si, fold_convert (itype, fd->chunk_size),
6222 true, NULL_TREE, true, GSI_SAME_STMT);
6223
6224 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
6225 t = fold_build2 (PLUS_EXPR, itype, step, t);
6226 t = fold_build2 (PLUS_EXPR, itype, t, n2);
6227 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
6228 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
6229 t = fold_build2 (TRUNC_DIV_EXPR, itype,
6230 fold_build1 (NEGATE_EXPR, itype, t),
6231 fold_build1 (NEGATE_EXPR, itype, step));
6232 else
6233 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
6234 t = fold_convert (itype, t);
6235 n = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
6236 true, GSI_SAME_STMT);
6237
6238 trip_var = create_tmp_reg (itype, ".trip");
6239 if (gimple_in_ssa_p (cfun))
6240 {
6241 trip_init = make_ssa_name (trip_var, NULL);
6242 trip_main = make_ssa_name (trip_var, NULL);
6243 trip_back = make_ssa_name (trip_var, NULL);
6244 }
6245 else
6246 {
6247 trip_init = trip_var;
6248 trip_main = trip_var;
6249 trip_back = trip_var;
6250 }
6251
6252 stmt = gimple_build_assign (trip_init, build_int_cst (itype, 0));
6253 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
6254
6255 t = fold_build2 (MULT_EXPR, itype, threadid, fd->chunk_size);
6256 t = fold_build2 (MULT_EXPR, itype, t, step);
6257 if (POINTER_TYPE_P (type))
6258 t = fold_build_pointer_plus (n1, t);
6259 else
6260 t = fold_build2 (PLUS_EXPR, type, t, n1);
6261 v_extra = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
6262 true, GSI_SAME_STMT);
6263
6264 /* Remove the GIMPLE_OMP_FOR. */
6265 gsi_remove (&si, true);
6266
6267 /* Iteration space partitioning goes in ITER_PART_BB. */
6268 si = gsi_last_bb (iter_part_bb);
6269
6270 t = fold_build2 (MULT_EXPR, itype, trip_main, nthreads);
6271 t = fold_build2 (PLUS_EXPR, itype, t, threadid);
6272 t = fold_build2 (MULT_EXPR, itype, t, fd->chunk_size);
6273 s0 = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
6274 false, GSI_CONTINUE_LINKING);
6275
6276 t = fold_build2 (PLUS_EXPR, itype, s0, fd->chunk_size);
6277 t = fold_build2 (MIN_EXPR, itype, t, n);
6278 e0 = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
6279 false, GSI_CONTINUE_LINKING);
6280
6281 t = build2 (LT_EXPR, boolean_type_node, s0, n);
6282 gsi_insert_after (&si, gimple_build_cond_empty (t), GSI_CONTINUE_LINKING);
6283
6284 /* Setup code for sequential iteration goes in SEQ_START_BB. */
6285 si = gsi_start_bb (seq_start_bb);
6286
6287 tree startvar = fd->loop.v;
6288 tree endvar = NULL_TREE;
6289
6290 if (gimple_omp_for_combined_p (fd->for_stmt))
6291 {
6292 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
6293 ? gimple_omp_parallel_clauses (inner_stmt)
6294 : gimple_omp_for_clauses (inner_stmt);
6295 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
6296 gcc_assert (innerc);
6297 startvar = OMP_CLAUSE_DECL (innerc);
6298 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6299 OMP_CLAUSE__LOOPTEMP_);
6300 gcc_assert (innerc);
6301 endvar = OMP_CLAUSE_DECL (innerc);
6302 }
6303
6304 t = fold_convert (itype, s0);
6305 t = fold_build2 (MULT_EXPR, itype, t, step);
6306 if (POINTER_TYPE_P (type))
6307 t = fold_build_pointer_plus (n1, t);
6308 else
6309 t = fold_build2 (PLUS_EXPR, type, t, n1);
6310 t = fold_convert (TREE_TYPE (startvar), t);
6311 t = force_gimple_operand_gsi (&si, t,
6312 DECL_P (startvar)
6313 && TREE_ADDRESSABLE (startvar),
6314 NULL_TREE, false, GSI_CONTINUE_LINKING);
6315 stmt = gimple_build_assign (startvar, t);
6316 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
6317
6318 t = fold_convert (itype, e0);
6319 t = fold_build2 (MULT_EXPR, itype, t, step);
6320 if (POINTER_TYPE_P (type))
6321 t = fold_build_pointer_plus (n1, t);
6322 else
6323 t = fold_build2 (PLUS_EXPR, type, t, n1);
6324 t = fold_convert (TREE_TYPE (startvar), t);
6325 e = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
6326 false, GSI_CONTINUE_LINKING);
6327 if (endvar)
6328 {
6329 stmt = gimple_build_assign (endvar, e);
6330 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
6331 }
6332 if (fd->collapse > 1)
6333 expand_omp_for_init_vars (fd, &si, counts, inner_stmt, startvar);
6334
6335 if (!broken_loop)
6336 {
6337 /* The code controlling the sequential loop goes in CONT_BB,
6338 replacing the GIMPLE_OMP_CONTINUE. */
6339 si = gsi_last_bb (cont_bb);
6340 stmt = gsi_stmt (si);
6341 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
6342 v_main = gimple_omp_continue_control_use (stmt);
6343 v_back = gimple_omp_continue_control_def (stmt);
6344
6345 if (!gimple_omp_for_combined_p (fd->for_stmt))
6346 {
6347 if (POINTER_TYPE_P (type))
6348 t = fold_build_pointer_plus (v_main, step);
6349 else
6350 t = fold_build2 (PLUS_EXPR, type, v_main, step);
6351 if (DECL_P (v_back) && TREE_ADDRESSABLE (v_back))
6352 t = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
6353 true, GSI_SAME_STMT);
6354 stmt = gimple_build_assign (v_back, t);
6355 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
6356
6357 t = build2 (fd->loop.cond_code, boolean_type_node,
6358 DECL_P (v_back) && TREE_ADDRESSABLE (v_back)
6359 ? t : v_back, e);
6360 gsi_insert_before (&si, gimple_build_cond_empty (t), GSI_SAME_STMT);
6361 }
6362
6363 /* Remove GIMPLE_OMP_CONTINUE. */
6364 gsi_remove (&si, true);
6365
6366 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
6367 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
6368
6369 /* Trip update code goes into TRIP_UPDATE_BB. */
6370 si = gsi_start_bb (trip_update_bb);
6371
6372 t = build_int_cst (itype, 1);
6373 t = build2 (PLUS_EXPR, itype, trip_main, t);
6374 stmt = gimple_build_assign (trip_back, t);
6375 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
6376 }
6377
6378 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
6379 si = gsi_last_bb (exit_bb);
6380 if (!gimple_omp_return_nowait_p (gsi_stmt (si)))
6381 {
6382 t = gimple_omp_return_lhs (gsi_stmt (si));
6383 gsi_insert_after (&si, build_omp_barrier (t), GSI_SAME_STMT);
6384 }
6385 gsi_remove (&si, true);
6386
6387 /* Connect the new blocks. */
6388 find_edge (iter_part_bb, seq_start_bb)->flags = EDGE_TRUE_VALUE;
6389 find_edge (iter_part_bb, fin_bb)->flags = EDGE_FALSE_VALUE;
6390
6391 if (!broken_loop)
6392 {
6393 se = find_edge (cont_bb, body_bb);
6394 if (gimple_omp_for_combined_p (fd->for_stmt))
6395 {
6396 remove_edge (se);
6397 se = NULL;
6398 }
6399 else if (fd->collapse > 1)
6400 {
6401 remove_edge (se);
6402 se = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
6403 }
6404 else
6405 se->flags = EDGE_TRUE_VALUE;
6406 find_edge (cont_bb, trip_update_bb)->flags
6407 = se ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
6408
6409 redirect_edge_and_branch (single_succ_edge (trip_update_bb), iter_part_bb);
6410 }
6411
6412 if (gimple_in_ssa_p (cfun))
6413 {
6414 gimple_stmt_iterator psi;
6415 gimple phi;
6416 edge re, ene;
6417 edge_var_map_vector *head;
6418 edge_var_map *vm;
6419 size_t i;
6420
6421 gcc_assert (fd->collapse == 1 && !broken_loop);
6422
6423 /* When we redirect the edge from trip_update_bb to iter_part_bb, we
6424 remove arguments of the phi nodes in fin_bb. We need to create
6425 appropriate phi nodes in iter_part_bb instead. */
6426 se = single_pred_edge (fin_bb);
6427 re = single_succ_edge (trip_update_bb);
6428 head = redirect_edge_var_map_vector (re);
6429 ene = single_succ_edge (entry_bb);
6430
6431 psi = gsi_start_phis (fin_bb);
6432 for (i = 0; !gsi_end_p (psi) && head->iterate (i, &vm);
6433 gsi_next (&psi), ++i)
6434 {
6435 gimple nphi;
6436 source_location locus;
6437
6438 phi = gsi_stmt (psi);
6439 t = gimple_phi_result (phi);
6440 gcc_assert (t == redirect_edge_var_map_result (vm));
6441 nphi = create_phi_node (t, iter_part_bb);
6442
6443 t = PHI_ARG_DEF_FROM_EDGE (phi, se);
6444 locus = gimple_phi_arg_location_from_edge (phi, se);
6445
6446 /* A special case -- fd->loop.v is not yet computed in
6447 iter_part_bb, we need to use v_extra instead. */
6448 if (t == fd->loop.v)
6449 t = v_extra;
6450 add_phi_arg (nphi, t, ene, locus);
6451 locus = redirect_edge_var_map_location (vm);
6452 add_phi_arg (nphi, redirect_edge_var_map_def (vm), re, locus);
6453 }
6454 gcc_assert (!gsi_end_p (psi) && i == head->length ());
6455 redirect_edge_var_map_clear (re);
6456 while (1)
6457 {
6458 psi = gsi_start_phis (fin_bb);
6459 if (gsi_end_p (psi))
6460 break;
6461 remove_phi_node (&psi, false);
6462 }
6463
6464 /* Make phi node for trip. */
6465 phi = create_phi_node (trip_main, iter_part_bb);
6466 add_phi_arg (phi, trip_back, single_succ_edge (trip_update_bb),
6467 UNKNOWN_LOCATION);
6468 add_phi_arg (phi, trip_init, single_succ_edge (entry_bb),
6469 UNKNOWN_LOCATION);
6470 }
6471
6472 if (!broken_loop)
6473 set_immediate_dominator (CDI_DOMINATORS, trip_update_bb, cont_bb);
6474 set_immediate_dominator (CDI_DOMINATORS, iter_part_bb,
6475 recompute_dominator (CDI_DOMINATORS, iter_part_bb));
6476 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
6477 recompute_dominator (CDI_DOMINATORS, fin_bb));
6478 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb,
6479 recompute_dominator (CDI_DOMINATORS, seq_start_bb));
6480 set_immediate_dominator (CDI_DOMINATORS, body_bb,
6481 recompute_dominator (CDI_DOMINATORS, body_bb));
6482
6483 if (!broken_loop)
6484 {
6485 struct loop *trip_loop = alloc_loop ();
6486 trip_loop->header = iter_part_bb;
6487 trip_loop->latch = trip_update_bb;
6488 add_loop (trip_loop, iter_part_bb->loop_father);
6489
6490 if (!gimple_omp_for_combined_p (fd->for_stmt))
6491 {
6492 struct loop *loop = alloc_loop ();
6493 loop->header = body_bb;
6494 if (collapse_bb == NULL)
6495 loop->latch = cont_bb;
6496 add_loop (loop, trip_loop);
6497 }
6498 }
6499 }
6500
6501
6502 /* A subroutine of expand_omp_for. Generate code for a simd non-worksharing
6503 loop. Given parameters:
6504
6505 for (V = N1; V cond N2; V += STEP) BODY;
6506
6507 where COND is "<" or ">", we generate pseudocode
6508
6509 V = N1;
6510 goto L1;
6511 L0:
6512 BODY;
6513 V += STEP;
6514 L1:
6515 if (V cond N2) goto L0; else goto L2;
6516 L2:
6517
6518 For collapsed loops, given parameters:
6519 collapse(3)
6520 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
6521 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
6522 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
6523 BODY;
6524
6525 we generate pseudocode
6526
6527 if (cond3 is <)
6528 adj = STEP3 - 1;
6529 else
6530 adj = STEP3 + 1;
6531 count3 = (adj + N32 - N31) / STEP3;
6532 if (cond2 is <)
6533 adj = STEP2 - 1;
6534 else
6535 adj = STEP2 + 1;
6536 count2 = (adj + N22 - N21) / STEP2;
6537 if (cond1 is <)
6538 adj = STEP1 - 1;
6539 else
6540 adj = STEP1 + 1;
6541 count1 = (adj + N12 - N11) / STEP1;
6542 count = count1 * count2 * count3;
6543 V = 0;
6544 V1 = N11;
6545 V2 = N21;
6546 V3 = N31;
6547 goto L1;
6548 L0:
6549 BODY;
6550 V += 1;
6551 V3 += STEP3;
6552 V2 += (V3 cond3 N32) ? 0 : STEP2;
6553 V3 = (V3 cond3 N32) ? V3 : N31;
6554 V1 += (V2 cond2 N22) ? 0 : STEP1;
6555 V2 = (V2 cond2 N22) ? V2 : N21;
6556 L1:
6557 if (V < count) goto L0; else goto L2;
6558 L2:
6559
6560 */
6561
6562 static void
6563 expand_omp_simd (struct omp_region *region, struct omp_for_data *fd)
6564 {
6565 tree type, t;
6566 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, l2_bb, l2_dom_bb;
6567 gimple_stmt_iterator gsi;
6568 gimple stmt;
6569 bool broken_loop = region->cont == NULL;
6570 edge e, ne;
6571 tree *counts = NULL;
6572 int i;
6573 tree safelen = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
6574 OMP_CLAUSE_SAFELEN);
6575 tree simduid = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
6576 OMP_CLAUSE__SIMDUID_);
6577 tree n1, n2;
6578
6579 type = TREE_TYPE (fd->loop.v);
6580 entry_bb = region->entry;
6581 cont_bb = region->cont;
6582 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
6583 gcc_assert (broken_loop
6584 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
6585 l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
6586 if (!broken_loop)
6587 {
6588 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
6589 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
6590 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
6591 l2_bb = BRANCH_EDGE (entry_bb)->dest;
6592 }
6593 else
6594 {
6595 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
6596 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
6597 l2_bb = single_succ (l1_bb);
6598 }
6599 exit_bb = region->exit;
6600 l2_dom_bb = NULL;
6601
6602 gsi = gsi_last_bb (entry_bb);
6603
6604 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6605 /* Not needed in SSA form right now. */
6606 gcc_assert (!gimple_in_ssa_p (cfun));
6607 if (fd->collapse > 1)
6608 {
6609 int first_zero_iter = -1;
6610 basic_block zero_iter_bb = l2_bb;
6611
6612 counts = XALLOCAVEC (tree, fd->collapse);
6613 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
6614 zero_iter_bb, first_zero_iter,
6615 l2_dom_bb);
6616 }
6617 if (l2_dom_bb == NULL)
6618 l2_dom_bb = l1_bb;
6619
6620 n1 = fd->loop.n1;
6621 n2 = fd->loop.n2;
6622 if (gimple_omp_for_combined_into_p (fd->for_stmt))
6623 {
6624 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
6625 OMP_CLAUSE__LOOPTEMP_);
6626 gcc_assert (innerc);
6627 n1 = OMP_CLAUSE_DECL (innerc);
6628 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6629 OMP_CLAUSE__LOOPTEMP_);
6630 gcc_assert (innerc);
6631 n2 = OMP_CLAUSE_DECL (innerc);
6632 expand_omp_build_assign (&gsi, fd->loop.v,
6633 fold_convert (type, n1));
6634 if (fd->collapse > 1)
6635 {
6636 gsi_prev (&gsi);
6637 expand_omp_for_init_vars (fd, &gsi, counts, NULL, n1);
6638 gsi_next (&gsi);
6639 }
6640 }
6641 else
6642 {
6643 expand_omp_build_assign (&gsi, fd->loop.v,
6644 fold_convert (type, fd->loop.n1));
6645 if (fd->collapse > 1)
6646 for (i = 0; i < fd->collapse; i++)
6647 {
6648 tree itype = TREE_TYPE (fd->loops[i].v);
6649 if (POINTER_TYPE_P (itype))
6650 itype = signed_type_for (itype);
6651 t = fold_convert (TREE_TYPE (fd->loops[i].v), fd->loops[i].n1);
6652 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
6653 }
6654 }
6655
6656 /* Remove the GIMPLE_OMP_FOR statement. */
6657 gsi_remove (&gsi, true);
6658
6659 if (!broken_loop)
6660 {
6661 /* Code to control the increment goes in the CONT_BB. */
6662 gsi = gsi_last_bb (cont_bb);
6663 stmt = gsi_stmt (gsi);
6664 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
6665
6666 if (POINTER_TYPE_P (type))
6667 t = fold_build_pointer_plus (fd->loop.v, fd->loop.step);
6668 else
6669 t = fold_build2 (PLUS_EXPR, type, fd->loop.v, fd->loop.step);
6670 expand_omp_build_assign (&gsi, fd->loop.v, t);
6671
6672 if (fd->collapse > 1)
6673 {
6674 i = fd->collapse - 1;
6675 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v)))
6676 {
6677 t = fold_convert (sizetype, fd->loops[i].step);
6678 t = fold_build_pointer_plus (fd->loops[i].v, t);
6679 }
6680 else
6681 {
6682 t = fold_convert (TREE_TYPE (fd->loops[i].v),
6683 fd->loops[i].step);
6684 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loops[i].v),
6685 fd->loops[i].v, t);
6686 }
6687 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
6688
6689 for (i = fd->collapse - 1; i > 0; i--)
6690 {
6691 tree itype = TREE_TYPE (fd->loops[i].v);
6692 tree itype2 = TREE_TYPE (fd->loops[i - 1].v);
6693 if (POINTER_TYPE_P (itype2))
6694 itype2 = signed_type_for (itype2);
6695 t = build3 (COND_EXPR, itype2,
6696 build2 (fd->loops[i].cond_code, boolean_type_node,
6697 fd->loops[i].v,
6698 fold_convert (itype, fd->loops[i].n2)),
6699 build_int_cst (itype2, 0),
6700 fold_convert (itype2, fd->loops[i - 1].step));
6701 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i - 1].v)))
6702 t = fold_build_pointer_plus (fd->loops[i - 1].v, t);
6703 else
6704 t = fold_build2 (PLUS_EXPR, itype2, fd->loops[i - 1].v, t);
6705 expand_omp_build_assign (&gsi, fd->loops[i - 1].v, t);
6706
6707 t = build3 (COND_EXPR, itype,
6708 build2 (fd->loops[i].cond_code, boolean_type_node,
6709 fd->loops[i].v,
6710 fold_convert (itype, fd->loops[i].n2)),
6711 fd->loops[i].v,
6712 fold_convert (itype, fd->loops[i].n1));
6713 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
6714 }
6715 }
6716
6717 /* Remove GIMPLE_OMP_CONTINUE. */
6718 gsi_remove (&gsi, true);
6719 }
6720
6721 /* Emit the condition in L1_BB. */
6722 gsi = gsi_start_bb (l1_bb);
6723
6724 t = fold_convert (type, n2);
6725 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6726 false, GSI_CONTINUE_LINKING);
6727 t = build2 (fd->loop.cond_code, boolean_type_node, fd->loop.v, t);
6728 stmt = gimple_build_cond_empty (t);
6729 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
6730 if (walk_tree (gimple_cond_lhs_ptr (stmt), expand_omp_regimplify_p,
6731 NULL, NULL)
6732 || walk_tree (gimple_cond_rhs_ptr (stmt), expand_omp_regimplify_p,
6733 NULL, NULL))
6734 {
6735 gsi = gsi_for_stmt (stmt);
6736 gimple_regimplify_operands (stmt, &gsi);
6737 }
6738
6739 /* Remove GIMPLE_OMP_RETURN. */
6740 gsi = gsi_last_bb (exit_bb);
6741 gsi_remove (&gsi, true);
6742
6743 /* Connect the new blocks. */
6744 remove_edge (FALLTHRU_EDGE (entry_bb));
6745
6746 if (!broken_loop)
6747 {
6748 remove_edge (BRANCH_EDGE (entry_bb));
6749 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
6750
6751 e = BRANCH_EDGE (l1_bb);
6752 ne = FALLTHRU_EDGE (l1_bb);
6753 e->flags = EDGE_TRUE_VALUE;
6754 }
6755 else
6756 {
6757 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
6758
6759 ne = single_succ_edge (l1_bb);
6760 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
6761
6762 }
6763 ne->flags = EDGE_FALSE_VALUE;
6764 e->probability = REG_BR_PROB_BASE * 7 / 8;
6765 ne->probability = REG_BR_PROB_BASE / 8;
6766
6767 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
6768 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
6769 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
6770
6771 if (!broken_loop)
6772 {
6773 struct loop *loop = alloc_loop ();
6774 loop->header = l1_bb;
6775 loop->latch = cont_bb;
6776 add_loop (loop, l1_bb->loop_father);
6777 if (safelen == NULL_TREE)
6778 loop->safelen = INT_MAX;
6779 else
6780 {
6781 safelen = OMP_CLAUSE_SAFELEN_EXPR (safelen);
6782 if (!tree_fits_uhwi_p (safelen)
6783 || tree_to_uhwi (safelen) > INT_MAX)
6784 loop->safelen = INT_MAX;
6785 else
6786 loop->safelen = tree_to_uhwi (safelen);
6787 if (loop->safelen == 1)
6788 loop->safelen = 0;
6789 }
6790 if (simduid)
6791 {
6792 loop->simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
6793 cfun->has_simduid_loops = true;
6794 }
6795 /* If not -fno-tree-loop-vectorize, hint that we want to vectorize
6796 the loop. */
6797 if ((flag_tree_loop_vectorize
6798 || (!global_options_set.x_flag_tree_loop_vectorize
6799 && !global_options_set.x_flag_tree_vectorize))
6800 && loop->safelen > 1)
6801 {
6802 loop->force_vect = true;
6803 cfun->has_force_vect_loops = true;
6804 }
6805 }
6806 }
6807
6808
6809 /* Expand the OpenMP loop defined by REGION. */
6810
6811 static void
6812 expand_omp_for (struct omp_region *region, gimple inner_stmt)
6813 {
6814 struct omp_for_data fd;
6815 struct omp_for_data_loop *loops;
6816
6817 loops
6818 = (struct omp_for_data_loop *)
6819 alloca (gimple_omp_for_collapse (last_stmt (region->entry))
6820 * sizeof (struct omp_for_data_loop));
6821 extract_omp_for_data (last_stmt (region->entry), &fd, loops);
6822 region->sched_kind = fd.sched_kind;
6823
6824 gcc_assert (EDGE_COUNT (region->entry->succs) == 2);
6825 BRANCH_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
6826 FALLTHRU_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
6827 if (region->cont)
6828 {
6829 gcc_assert (EDGE_COUNT (region->cont->succs) == 2);
6830 BRANCH_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
6831 FALLTHRU_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
6832 }
6833 else
6834 /* If there isn't a continue then this is a degerate case where
6835 the introduction of abnormal edges during lowering will prevent
6836 original loops from being detected. Fix that up. */
6837 loops_state_set (LOOPS_NEED_FIXUP);
6838
6839 if (gimple_omp_for_kind (fd.for_stmt) & GF_OMP_FOR_KIND_SIMD)
6840 expand_omp_simd (region, &fd);
6841 else if (fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
6842 && !fd.have_ordered)
6843 {
6844 if (fd.chunk_size == NULL)
6845 expand_omp_for_static_nochunk (region, &fd, inner_stmt);
6846 else
6847 expand_omp_for_static_chunk (region, &fd, inner_stmt);
6848 }
6849 else
6850 {
6851 int fn_index, start_ix, next_ix;
6852
6853 gcc_assert (gimple_omp_for_kind (fd.for_stmt)
6854 == GF_OMP_FOR_KIND_FOR);
6855 if (fd.chunk_size == NULL
6856 && fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
6857 fd.chunk_size = integer_zero_node;
6858 gcc_assert (fd.sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
6859 fn_index = (fd.sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
6860 ? 3 : fd.sched_kind;
6861 fn_index += fd.have_ordered * 4;
6862 start_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_START) + fn_index;
6863 next_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_NEXT) + fn_index;
6864 if (fd.iter_type == long_long_unsigned_type_node)
6865 {
6866 start_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_START
6867 - (int)BUILT_IN_GOMP_LOOP_STATIC_START);
6868 next_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_NEXT
6869 - (int)BUILT_IN_GOMP_LOOP_STATIC_NEXT);
6870 }
6871 expand_omp_for_generic (region, &fd, (enum built_in_function) start_ix,
6872 (enum built_in_function) next_ix, inner_stmt);
6873 }
6874
6875 if (gimple_in_ssa_p (cfun))
6876 update_ssa (TODO_update_ssa_only_virtuals);
6877 }
6878
6879
6880 /* Expand code for an OpenMP sections directive. In pseudo code, we generate
6881
6882 v = GOMP_sections_start (n);
6883 L0:
6884 switch (v)
6885 {
6886 case 0:
6887 goto L2;
6888 case 1:
6889 section 1;
6890 goto L1;
6891 case 2:
6892 ...
6893 case n:
6894 ...
6895 default:
6896 abort ();
6897 }
6898 L1:
6899 v = GOMP_sections_next ();
6900 goto L0;
6901 L2:
6902 reduction;
6903
6904 If this is a combined parallel sections, replace the call to
6905 GOMP_sections_start with call to GOMP_sections_next. */
6906
6907 static void
6908 expand_omp_sections (struct omp_region *region)
6909 {
6910 tree t, u, vin = NULL, vmain, vnext, l2;
6911 unsigned len;
6912 basic_block entry_bb, l0_bb, l1_bb, l2_bb, default_bb;
6913 gimple_stmt_iterator si, switch_si;
6914 gimple sections_stmt, stmt, cont;
6915 edge_iterator ei;
6916 edge e;
6917 struct omp_region *inner;
6918 unsigned i, casei;
6919 bool exit_reachable = region->cont != NULL;
6920
6921 gcc_assert (region->exit != NULL);
6922 entry_bb = region->entry;
6923 l0_bb = single_succ (entry_bb);
6924 l1_bb = region->cont;
6925 l2_bb = region->exit;
6926 if (single_pred_p (l2_bb) && single_pred (l2_bb) == l0_bb)
6927 l2 = gimple_block_label (l2_bb);
6928 else
6929 {
6930 /* This can happen if there are reductions. */
6931 len = EDGE_COUNT (l0_bb->succs);
6932 gcc_assert (len > 0);
6933 e = EDGE_SUCC (l0_bb, len - 1);
6934 si = gsi_last_bb (e->dest);
6935 l2 = NULL_TREE;
6936 if (gsi_end_p (si)
6937 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
6938 l2 = gimple_block_label (e->dest);
6939 else
6940 FOR_EACH_EDGE (e, ei, l0_bb->succs)
6941 {
6942 si = gsi_last_bb (e->dest);
6943 if (gsi_end_p (si)
6944 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
6945 {
6946 l2 = gimple_block_label (e->dest);
6947 break;
6948 }
6949 }
6950 }
6951 if (exit_reachable)
6952 default_bb = create_empty_bb (l1_bb->prev_bb);
6953 else
6954 default_bb = create_empty_bb (l0_bb);
6955
6956 /* We will build a switch() with enough cases for all the
6957 GIMPLE_OMP_SECTION regions, a '0' case to handle the end of more work
6958 and a default case to abort if something goes wrong. */
6959 len = EDGE_COUNT (l0_bb->succs);
6960
6961 /* Use vec::quick_push on label_vec throughout, since we know the size
6962 in advance. */
6963 auto_vec<tree> label_vec (len);
6964
6965 /* The call to GOMP_sections_start goes in ENTRY_BB, replacing the
6966 GIMPLE_OMP_SECTIONS statement. */
6967 si = gsi_last_bb (entry_bb);
6968 sections_stmt = gsi_stmt (si);
6969 gcc_assert (gimple_code (sections_stmt) == GIMPLE_OMP_SECTIONS);
6970 vin = gimple_omp_sections_control (sections_stmt);
6971 if (!is_combined_parallel (region))
6972 {
6973 /* If we are not inside a combined parallel+sections region,
6974 call GOMP_sections_start. */
6975 t = build_int_cst (unsigned_type_node, len - 1);
6976 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_START);
6977 stmt = gimple_build_call (u, 1, t);
6978 }
6979 else
6980 {
6981 /* Otherwise, call GOMP_sections_next. */
6982 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
6983 stmt = gimple_build_call (u, 0);
6984 }
6985 gimple_call_set_lhs (stmt, vin);
6986 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
6987 gsi_remove (&si, true);
6988
6989 /* The switch() statement replacing GIMPLE_OMP_SECTIONS_SWITCH goes in
6990 L0_BB. */
6991 switch_si = gsi_last_bb (l0_bb);
6992 gcc_assert (gimple_code (gsi_stmt (switch_si)) == GIMPLE_OMP_SECTIONS_SWITCH);
6993 if (exit_reachable)
6994 {
6995 cont = last_stmt (l1_bb);
6996 gcc_assert (gimple_code (cont) == GIMPLE_OMP_CONTINUE);
6997 vmain = gimple_omp_continue_control_use (cont);
6998 vnext = gimple_omp_continue_control_def (cont);
6999 }
7000 else
7001 {
7002 vmain = vin;
7003 vnext = NULL_TREE;
7004 }
7005
7006 t = build_case_label (build_int_cst (unsigned_type_node, 0), NULL, l2);
7007 label_vec.quick_push (t);
7008 i = 1;
7009
7010 /* Convert each GIMPLE_OMP_SECTION into a CASE_LABEL_EXPR. */
7011 for (inner = region->inner, casei = 1;
7012 inner;
7013 inner = inner->next, i++, casei++)
7014 {
7015 basic_block s_entry_bb, s_exit_bb;
7016
7017 /* Skip optional reduction region. */
7018 if (inner->type == GIMPLE_OMP_ATOMIC_LOAD)
7019 {
7020 --i;
7021 --casei;
7022 continue;
7023 }
7024
7025 s_entry_bb = inner->entry;
7026 s_exit_bb = inner->exit;
7027
7028 t = gimple_block_label (s_entry_bb);
7029 u = build_int_cst (unsigned_type_node, casei);
7030 u = build_case_label (u, NULL, t);
7031 label_vec.quick_push (u);
7032
7033 si = gsi_last_bb (s_entry_bb);
7034 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SECTION);
7035 gcc_assert (i < len || gimple_omp_section_last_p (gsi_stmt (si)));
7036 gsi_remove (&si, true);
7037 single_succ_edge (s_entry_bb)->flags = EDGE_FALLTHRU;
7038
7039 if (s_exit_bb == NULL)
7040 continue;
7041
7042 si = gsi_last_bb (s_exit_bb);
7043 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
7044 gsi_remove (&si, true);
7045
7046 single_succ_edge (s_exit_bb)->flags = EDGE_FALLTHRU;
7047 }
7048
7049 /* Error handling code goes in DEFAULT_BB. */
7050 t = gimple_block_label (default_bb);
7051 u = build_case_label (NULL, NULL, t);
7052 make_edge (l0_bb, default_bb, 0);
7053 if (current_loops)
7054 add_bb_to_loop (default_bb, current_loops->tree_root);
7055
7056 stmt = gimple_build_switch (vmain, u, label_vec);
7057 gsi_insert_after (&switch_si, stmt, GSI_SAME_STMT);
7058 gsi_remove (&switch_si, true);
7059
7060 si = gsi_start_bb (default_bb);
7061 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
7062 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
7063
7064 if (exit_reachable)
7065 {
7066 tree bfn_decl;
7067
7068 /* Code to get the next section goes in L1_BB. */
7069 si = gsi_last_bb (l1_bb);
7070 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CONTINUE);
7071
7072 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
7073 stmt = gimple_build_call (bfn_decl, 0);
7074 gimple_call_set_lhs (stmt, vnext);
7075 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
7076 gsi_remove (&si, true);
7077
7078 single_succ_edge (l1_bb)->flags = EDGE_FALLTHRU;
7079 }
7080
7081 /* Cleanup function replaces GIMPLE_OMP_RETURN in EXIT_BB. */
7082 si = gsi_last_bb (l2_bb);
7083 if (gimple_omp_return_nowait_p (gsi_stmt (si)))
7084 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_NOWAIT);
7085 else if (gimple_omp_return_lhs (gsi_stmt (si)))
7086 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_CANCEL);
7087 else
7088 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END);
7089 stmt = gimple_build_call (t, 0);
7090 if (gimple_omp_return_lhs (gsi_stmt (si)))
7091 gimple_call_set_lhs (stmt, gimple_omp_return_lhs (gsi_stmt (si)));
7092 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
7093 gsi_remove (&si, true);
7094
7095 set_immediate_dominator (CDI_DOMINATORS, default_bb, l0_bb);
7096 }
7097
7098
7099 /* Expand code for an OpenMP single directive. We've already expanded
7100 much of the code, here we simply place the GOMP_barrier call. */
7101
7102 static void
7103 expand_omp_single (struct omp_region *region)
7104 {
7105 basic_block entry_bb, exit_bb;
7106 gimple_stmt_iterator si;
7107
7108 entry_bb = region->entry;
7109 exit_bb = region->exit;
7110
7111 si = gsi_last_bb (entry_bb);
7112 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE);
7113 gsi_remove (&si, true);
7114 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7115
7116 si = gsi_last_bb (exit_bb);
7117 if (!gimple_omp_return_nowait_p (gsi_stmt (si)))
7118 {
7119 tree t = gimple_omp_return_lhs (gsi_stmt (si));
7120 gsi_insert_after (&si, build_omp_barrier (t), GSI_SAME_STMT);
7121 }
7122 gsi_remove (&si, true);
7123 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
7124 }
7125
7126
7127 /* Generic expansion for OpenMP synchronization directives: master,
7128 ordered and critical. All we need to do here is remove the entry
7129 and exit markers for REGION. */
7130
7131 static void
7132 expand_omp_synch (struct omp_region *region)
7133 {
7134 basic_block entry_bb, exit_bb;
7135 gimple_stmt_iterator si;
7136
7137 entry_bb = region->entry;
7138 exit_bb = region->exit;
7139
7140 si = gsi_last_bb (entry_bb);
7141 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE
7142 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_MASTER
7143 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TASKGROUP
7144 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ORDERED
7145 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CRITICAL
7146 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TEAMS);
7147 gsi_remove (&si, true);
7148 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7149
7150 if (exit_bb)
7151 {
7152 si = gsi_last_bb (exit_bb);
7153 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
7154 gsi_remove (&si, true);
7155 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
7156 }
7157 }
7158
7159 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
7160 operation as a normal volatile load. */
7161
7162 static bool
7163 expand_omp_atomic_load (basic_block load_bb, tree addr,
7164 tree loaded_val, int index)
7165 {
7166 enum built_in_function tmpbase;
7167 gimple_stmt_iterator gsi;
7168 basic_block store_bb;
7169 location_t loc;
7170 gimple stmt;
7171 tree decl, call, type, itype;
7172
7173 gsi = gsi_last_bb (load_bb);
7174 stmt = gsi_stmt (gsi);
7175 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
7176 loc = gimple_location (stmt);
7177
7178 /* ??? If the target does not implement atomic_load_optab[mode], and mode
7179 is smaller than word size, then expand_atomic_load assumes that the load
7180 is atomic. We could avoid the builtin entirely in this case. */
7181
7182 tmpbase = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
7183 decl = builtin_decl_explicit (tmpbase);
7184 if (decl == NULL_TREE)
7185 return false;
7186
7187 type = TREE_TYPE (loaded_val);
7188 itype = TREE_TYPE (TREE_TYPE (decl));
7189
7190 call = build_call_expr_loc (loc, decl, 2, addr,
7191 build_int_cst (NULL,
7192 gimple_omp_atomic_seq_cst_p (stmt)
7193 ? MEMMODEL_SEQ_CST
7194 : MEMMODEL_RELAXED));
7195 if (!useless_type_conversion_p (type, itype))
7196 call = fold_build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
7197 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
7198
7199 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
7200 gsi_remove (&gsi, true);
7201
7202 store_bb = single_succ (load_bb);
7203 gsi = gsi_last_bb (store_bb);
7204 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
7205 gsi_remove (&gsi, true);
7206
7207 if (gimple_in_ssa_p (cfun))
7208 update_ssa (TODO_update_ssa_no_phi);
7209
7210 return true;
7211 }
7212
7213 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
7214 operation as a normal volatile store. */
7215
7216 static bool
7217 expand_omp_atomic_store (basic_block load_bb, tree addr,
7218 tree loaded_val, tree stored_val, int index)
7219 {
7220 enum built_in_function tmpbase;
7221 gimple_stmt_iterator gsi;
7222 basic_block store_bb = single_succ (load_bb);
7223 location_t loc;
7224 gimple stmt;
7225 tree decl, call, type, itype;
7226 enum machine_mode imode;
7227 bool exchange;
7228
7229 gsi = gsi_last_bb (load_bb);
7230 stmt = gsi_stmt (gsi);
7231 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
7232
7233 /* If the load value is needed, then this isn't a store but an exchange. */
7234 exchange = gimple_omp_atomic_need_value_p (stmt);
7235
7236 gsi = gsi_last_bb (store_bb);
7237 stmt = gsi_stmt (gsi);
7238 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE);
7239 loc = gimple_location (stmt);
7240
7241 /* ??? If the target does not implement atomic_store_optab[mode], and mode
7242 is smaller than word size, then expand_atomic_store assumes that the store
7243 is atomic. We could avoid the builtin entirely in this case. */
7244
7245 tmpbase = (exchange ? BUILT_IN_ATOMIC_EXCHANGE_N : BUILT_IN_ATOMIC_STORE_N);
7246 tmpbase = (enum built_in_function) ((int) tmpbase + index + 1);
7247 decl = builtin_decl_explicit (tmpbase);
7248 if (decl == NULL_TREE)
7249 return false;
7250
7251 type = TREE_TYPE (stored_val);
7252
7253 /* Dig out the type of the function's second argument. */
7254 itype = TREE_TYPE (decl);
7255 itype = TYPE_ARG_TYPES (itype);
7256 itype = TREE_CHAIN (itype);
7257 itype = TREE_VALUE (itype);
7258 imode = TYPE_MODE (itype);
7259
7260 if (exchange && !can_atomic_exchange_p (imode, true))
7261 return false;
7262
7263 if (!useless_type_conversion_p (itype, type))
7264 stored_val = fold_build1_loc (loc, VIEW_CONVERT_EXPR, itype, stored_val);
7265 call = build_call_expr_loc (loc, decl, 3, addr, stored_val,
7266 build_int_cst (NULL,
7267 gimple_omp_atomic_seq_cst_p (stmt)
7268 ? MEMMODEL_SEQ_CST
7269 : MEMMODEL_RELAXED));
7270 if (exchange)
7271 {
7272 if (!useless_type_conversion_p (type, itype))
7273 call = build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
7274 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
7275 }
7276
7277 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
7278 gsi_remove (&gsi, true);
7279
7280 /* Remove the GIMPLE_OMP_ATOMIC_LOAD that we verified above. */
7281 gsi = gsi_last_bb (load_bb);
7282 gsi_remove (&gsi, true);
7283
7284 if (gimple_in_ssa_p (cfun))
7285 update_ssa (TODO_update_ssa_no_phi);
7286
7287 return true;
7288 }
7289
7290 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
7291 operation as a __atomic_fetch_op builtin. INDEX is log2 of the
7292 size of the data type, and thus usable to find the index of the builtin
7293 decl. Returns false if the expression is not of the proper form. */
7294
7295 static bool
7296 expand_omp_atomic_fetch_op (basic_block load_bb,
7297 tree addr, tree loaded_val,
7298 tree stored_val, int index)
7299 {
7300 enum built_in_function oldbase, newbase, tmpbase;
7301 tree decl, itype, call;
7302 tree lhs, rhs;
7303 basic_block store_bb = single_succ (load_bb);
7304 gimple_stmt_iterator gsi;
7305 gimple stmt;
7306 location_t loc;
7307 enum tree_code code;
7308 bool need_old, need_new;
7309 enum machine_mode imode;
7310 bool seq_cst;
7311
7312 /* We expect to find the following sequences:
7313
7314 load_bb:
7315 GIMPLE_OMP_ATOMIC_LOAD (tmp, mem)
7316
7317 store_bb:
7318 val = tmp OP something; (or: something OP tmp)
7319 GIMPLE_OMP_STORE (val)
7320
7321 ???FIXME: Allow a more flexible sequence.
7322 Perhaps use data flow to pick the statements.
7323
7324 */
7325
7326 gsi = gsi_after_labels (store_bb);
7327 stmt = gsi_stmt (gsi);
7328 loc = gimple_location (stmt);
7329 if (!is_gimple_assign (stmt))
7330 return false;
7331 gsi_next (&gsi);
7332 if (gimple_code (gsi_stmt (gsi)) != GIMPLE_OMP_ATOMIC_STORE)
7333 return false;
7334 need_new = gimple_omp_atomic_need_value_p (gsi_stmt (gsi));
7335 need_old = gimple_omp_atomic_need_value_p (last_stmt (load_bb));
7336 seq_cst = gimple_omp_atomic_seq_cst_p (last_stmt (load_bb));
7337 gcc_checking_assert (!need_old || !need_new);
7338
7339 if (!operand_equal_p (gimple_assign_lhs (stmt), stored_val, 0))
7340 return false;
7341
7342 /* Check for one of the supported fetch-op operations. */
7343 code = gimple_assign_rhs_code (stmt);
7344 switch (code)
7345 {
7346 case PLUS_EXPR:
7347 case POINTER_PLUS_EXPR:
7348 oldbase = BUILT_IN_ATOMIC_FETCH_ADD_N;
7349 newbase = BUILT_IN_ATOMIC_ADD_FETCH_N;
7350 break;
7351 case MINUS_EXPR:
7352 oldbase = BUILT_IN_ATOMIC_FETCH_SUB_N;
7353 newbase = BUILT_IN_ATOMIC_SUB_FETCH_N;
7354 break;
7355 case BIT_AND_EXPR:
7356 oldbase = BUILT_IN_ATOMIC_FETCH_AND_N;
7357 newbase = BUILT_IN_ATOMIC_AND_FETCH_N;
7358 break;
7359 case BIT_IOR_EXPR:
7360 oldbase = BUILT_IN_ATOMIC_FETCH_OR_N;
7361 newbase = BUILT_IN_ATOMIC_OR_FETCH_N;
7362 break;
7363 case BIT_XOR_EXPR:
7364 oldbase = BUILT_IN_ATOMIC_FETCH_XOR_N;
7365 newbase = BUILT_IN_ATOMIC_XOR_FETCH_N;
7366 break;
7367 default:
7368 return false;
7369 }
7370
7371 /* Make sure the expression is of the proper form. */
7372 if (operand_equal_p (gimple_assign_rhs1 (stmt), loaded_val, 0))
7373 rhs = gimple_assign_rhs2 (stmt);
7374 else if (commutative_tree_code (gimple_assign_rhs_code (stmt))
7375 && operand_equal_p (gimple_assign_rhs2 (stmt), loaded_val, 0))
7376 rhs = gimple_assign_rhs1 (stmt);
7377 else
7378 return false;
7379
7380 tmpbase = ((enum built_in_function)
7381 ((need_new ? newbase : oldbase) + index + 1));
7382 decl = builtin_decl_explicit (tmpbase);
7383 if (decl == NULL_TREE)
7384 return false;
7385 itype = TREE_TYPE (TREE_TYPE (decl));
7386 imode = TYPE_MODE (itype);
7387
7388 /* We could test all of the various optabs involved, but the fact of the
7389 matter is that (with the exception of i486 vs i586 and xadd) all targets
7390 that support any atomic operaton optab also implements compare-and-swap.
7391 Let optabs.c take care of expanding any compare-and-swap loop. */
7392 if (!can_compare_and_swap_p (imode, true))
7393 return false;
7394
7395 gsi = gsi_last_bb (load_bb);
7396 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_LOAD);
7397
7398 /* OpenMP does not imply any barrier-like semantics on its atomic ops.
7399 It only requires that the operation happen atomically. Thus we can
7400 use the RELAXED memory model. */
7401 call = build_call_expr_loc (loc, decl, 3, addr,
7402 fold_convert_loc (loc, itype, rhs),
7403 build_int_cst (NULL,
7404 seq_cst ? MEMMODEL_SEQ_CST
7405 : MEMMODEL_RELAXED));
7406
7407 if (need_old || need_new)
7408 {
7409 lhs = need_old ? loaded_val : stored_val;
7410 call = fold_convert_loc (loc, TREE_TYPE (lhs), call);
7411 call = build2_loc (loc, MODIFY_EXPR, void_type_node, lhs, call);
7412 }
7413 else
7414 call = fold_convert_loc (loc, void_type_node, call);
7415 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
7416 gsi_remove (&gsi, true);
7417
7418 gsi = gsi_last_bb (store_bb);
7419 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
7420 gsi_remove (&gsi, true);
7421 gsi = gsi_last_bb (store_bb);
7422 gsi_remove (&gsi, true);
7423
7424 if (gimple_in_ssa_p (cfun))
7425 update_ssa (TODO_update_ssa_no_phi);
7426
7427 return true;
7428 }
7429
7430 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
7431
7432 oldval = *addr;
7433 repeat:
7434 newval = rhs; // with oldval replacing *addr in rhs
7435 oldval = __sync_val_compare_and_swap (addr, oldval, newval);
7436 if (oldval != newval)
7437 goto repeat;
7438
7439 INDEX is log2 of the size of the data type, and thus usable to find the
7440 index of the builtin decl. */
7441
7442 static bool
7443 expand_omp_atomic_pipeline (basic_block load_bb, basic_block store_bb,
7444 tree addr, tree loaded_val, tree stored_val,
7445 int index)
7446 {
7447 tree loadedi, storedi, initial, new_storedi, old_vali;
7448 tree type, itype, cmpxchg, iaddr;
7449 gimple_stmt_iterator si;
7450 basic_block loop_header = single_succ (load_bb);
7451 gimple phi, stmt;
7452 edge e;
7453 enum built_in_function fncode;
7454
7455 /* ??? We need a non-pointer interface to __atomic_compare_exchange in
7456 order to use the RELAXED memory model effectively. */
7457 fncode = (enum built_in_function)((int)BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_N
7458 + index + 1);
7459 cmpxchg = builtin_decl_explicit (fncode);
7460 if (cmpxchg == NULL_TREE)
7461 return false;
7462 type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
7463 itype = TREE_TYPE (TREE_TYPE (cmpxchg));
7464
7465 if (!can_compare_and_swap_p (TYPE_MODE (itype), true))
7466 return false;
7467
7468 /* Load the initial value, replacing the GIMPLE_OMP_ATOMIC_LOAD. */
7469 si = gsi_last_bb (load_bb);
7470 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
7471
7472 /* For floating-point values, we'll need to view-convert them to integers
7473 so that we can perform the atomic compare and swap. Simplify the
7474 following code by always setting up the "i"ntegral variables. */
7475 if (!INTEGRAL_TYPE_P (type) && !POINTER_TYPE_P (type))
7476 {
7477 tree iaddr_val;
7478
7479 iaddr = create_tmp_reg (build_pointer_type_for_mode (itype, ptr_mode,
7480 true), NULL);
7481 iaddr_val
7482 = force_gimple_operand_gsi (&si,
7483 fold_convert (TREE_TYPE (iaddr), addr),
7484 false, NULL_TREE, true, GSI_SAME_STMT);
7485 stmt = gimple_build_assign (iaddr, iaddr_val);
7486 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
7487 loadedi = create_tmp_var (itype, NULL);
7488 if (gimple_in_ssa_p (cfun))
7489 loadedi = make_ssa_name (loadedi, NULL);
7490 }
7491 else
7492 {
7493 iaddr = addr;
7494 loadedi = loaded_val;
7495 }
7496
7497 initial
7498 = force_gimple_operand_gsi (&si,
7499 build2 (MEM_REF, TREE_TYPE (TREE_TYPE (iaddr)),
7500 iaddr,
7501 build_int_cst (TREE_TYPE (iaddr), 0)),
7502 true, NULL_TREE, true, GSI_SAME_STMT);
7503
7504 /* Move the value to the LOADEDI temporary. */
7505 if (gimple_in_ssa_p (cfun))
7506 {
7507 gcc_assert (gimple_seq_empty_p (phi_nodes (loop_header)));
7508 phi = create_phi_node (loadedi, loop_header);
7509 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, single_succ_edge (load_bb)),
7510 initial);
7511 }
7512 else
7513 gsi_insert_before (&si,
7514 gimple_build_assign (loadedi, initial),
7515 GSI_SAME_STMT);
7516 if (loadedi != loaded_val)
7517 {
7518 gimple_stmt_iterator gsi2;
7519 tree x;
7520
7521 x = build1 (VIEW_CONVERT_EXPR, type, loadedi);
7522 gsi2 = gsi_start_bb (loop_header);
7523 if (gimple_in_ssa_p (cfun))
7524 {
7525 gimple stmt;
7526 x = force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
7527 true, GSI_SAME_STMT);
7528 stmt = gimple_build_assign (loaded_val, x);
7529 gsi_insert_before (&gsi2, stmt, GSI_SAME_STMT);
7530 }
7531 else
7532 {
7533 x = build2 (MODIFY_EXPR, TREE_TYPE (loaded_val), loaded_val, x);
7534 force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
7535 true, GSI_SAME_STMT);
7536 }
7537 }
7538 gsi_remove (&si, true);
7539
7540 si = gsi_last_bb (store_bb);
7541 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
7542
7543 if (iaddr == addr)
7544 storedi = stored_val;
7545 else
7546 storedi =
7547 force_gimple_operand_gsi (&si,
7548 build1 (VIEW_CONVERT_EXPR, itype,
7549 stored_val), true, NULL_TREE, true,
7550 GSI_SAME_STMT);
7551
7552 /* Build the compare&swap statement. */
7553 new_storedi = build_call_expr (cmpxchg, 3, iaddr, loadedi, storedi);
7554 new_storedi = force_gimple_operand_gsi (&si,
7555 fold_convert (TREE_TYPE (loadedi),
7556 new_storedi),
7557 true, NULL_TREE,
7558 true, GSI_SAME_STMT);
7559
7560 if (gimple_in_ssa_p (cfun))
7561 old_vali = loadedi;
7562 else
7563 {
7564 old_vali = create_tmp_var (TREE_TYPE (loadedi), NULL);
7565 stmt = gimple_build_assign (old_vali, loadedi);
7566 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
7567
7568 stmt = gimple_build_assign (loadedi, new_storedi);
7569 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
7570 }
7571
7572 /* Note that we always perform the comparison as an integer, even for
7573 floating point. This allows the atomic operation to properly
7574 succeed even with NaNs and -0.0. */
7575 stmt = gimple_build_cond_empty
7576 (build2 (NE_EXPR, boolean_type_node,
7577 new_storedi, old_vali));
7578 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
7579
7580 /* Update cfg. */
7581 e = single_succ_edge (store_bb);
7582 e->flags &= ~EDGE_FALLTHRU;
7583 e->flags |= EDGE_FALSE_VALUE;
7584
7585 e = make_edge (store_bb, loop_header, EDGE_TRUE_VALUE);
7586
7587 /* Copy the new value to loadedi (we already did that before the condition
7588 if we are not in SSA). */
7589 if (gimple_in_ssa_p (cfun))
7590 {
7591 phi = gimple_seq_first_stmt (phi_nodes (loop_header));
7592 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, e), new_storedi);
7593 }
7594
7595 /* Remove GIMPLE_OMP_ATOMIC_STORE. */
7596 gsi_remove (&si, true);
7597
7598 struct loop *loop = alloc_loop ();
7599 loop->header = loop_header;
7600 loop->latch = store_bb;
7601 add_loop (loop, loop_header->loop_father);
7602
7603 if (gimple_in_ssa_p (cfun))
7604 update_ssa (TODO_update_ssa_no_phi);
7605
7606 return true;
7607 }
7608
7609 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
7610
7611 GOMP_atomic_start ();
7612 *addr = rhs;
7613 GOMP_atomic_end ();
7614
7615 The result is not globally atomic, but works so long as all parallel
7616 references are within #pragma omp atomic directives. According to
7617 responses received from omp@openmp.org, appears to be within spec.
7618 Which makes sense, since that's how several other compilers handle
7619 this situation as well.
7620 LOADED_VAL and ADDR are the operands of GIMPLE_OMP_ATOMIC_LOAD we're
7621 expanding. STORED_VAL is the operand of the matching
7622 GIMPLE_OMP_ATOMIC_STORE.
7623
7624 We replace
7625 GIMPLE_OMP_ATOMIC_LOAD (loaded_val, addr) with
7626 loaded_val = *addr;
7627
7628 and replace
7629 GIMPLE_OMP_ATOMIC_STORE (stored_val) with
7630 *addr = stored_val;
7631 */
7632
7633 static bool
7634 expand_omp_atomic_mutex (basic_block load_bb, basic_block store_bb,
7635 tree addr, tree loaded_val, tree stored_val)
7636 {
7637 gimple_stmt_iterator si;
7638 gimple stmt;
7639 tree t;
7640
7641 si = gsi_last_bb (load_bb);
7642 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
7643
7644 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START);
7645 t = build_call_expr (t, 0);
7646 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
7647
7648 stmt = gimple_build_assign (loaded_val, build_simple_mem_ref (addr));
7649 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
7650 gsi_remove (&si, true);
7651
7652 si = gsi_last_bb (store_bb);
7653 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
7654
7655 stmt = gimple_build_assign (build_simple_mem_ref (unshare_expr (addr)),
7656 stored_val);
7657 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
7658
7659 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END);
7660 t = build_call_expr (t, 0);
7661 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
7662 gsi_remove (&si, true);
7663
7664 if (gimple_in_ssa_p (cfun))
7665 update_ssa (TODO_update_ssa_no_phi);
7666 return true;
7667 }
7668
7669 /* Expand an GIMPLE_OMP_ATOMIC statement. We try to expand
7670 using expand_omp_atomic_fetch_op. If it failed, we try to
7671 call expand_omp_atomic_pipeline, and if it fails too, the
7672 ultimate fallback is wrapping the operation in a mutex
7673 (expand_omp_atomic_mutex). REGION is the atomic region built
7674 by build_omp_regions_1(). */
7675
7676 static void
7677 expand_omp_atomic (struct omp_region *region)
7678 {
7679 basic_block load_bb = region->entry, store_bb = region->exit;
7680 gimple load = last_stmt (load_bb), store = last_stmt (store_bb);
7681 tree loaded_val = gimple_omp_atomic_load_lhs (load);
7682 tree addr = gimple_omp_atomic_load_rhs (load);
7683 tree stored_val = gimple_omp_atomic_store_val (store);
7684 tree type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
7685 HOST_WIDE_INT index;
7686
7687 /* Make sure the type is one of the supported sizes. */
7688 index = tree_to_uhwi (TYPE_SIZE_UNIT (type));
7689 index = exact_log2 (index);
7690 if (index >= 0 && index <= 4)
7691 {
7692 unsigned int align = TYPE_ALIGN_UNIT (type);
7693
7694 /* __sync builtins require strict data alignment. */
7695 if (exact_log2 (align) >= index)
7696 {
7697 /* Atomic load. */
7698 if (loaded_val == stored_val
7699 && (GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
7700 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
7701 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
7702 && expand_omp_atomic_load (load_bb, addr, loaded_val, index))
7703 return;
7704
7705 /* Atomic store. */
7706 if ((GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
7707 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
7708 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
7709 && store_bb == single_succ (load_bb)
7710 && first_stmt (store_bb) == store
7711 && expand_omp_atomic_store (load_bb, addr, loaded_val,
7712 stored_val, index))
7713 return;
7714
7715 /* When possible, use specialized atomic update functions. */
7716 if ((INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type))
7717 && store_bb == single_succ (load_bb)
7718 && expand_omp_atomic_fetch_op (load_bb, addr,
7719 loaded_val, stored_val, index))
7720 return;
7721
7722 /* If we don't have specialized __sync builtins, try and implement
7723 as a compare and swap loop. */
7724 if (expand_omp_atomic_pipeline (load_bb, store_bb, addr,
7725 loaded_val, stored_val, index))
7726 return;
7727 }
7728 }
7729
7730 /* The ultimate fallback is wrapping the operation in a mutex. */
7731 expand_omp_atomic_mutex (load_bb, store_bb, addr, loaded_val, stored_val);
7732 }
7733
7734
7735 /* Expand the OpenMP target{, data, update} directive starting at REGION. */
7736
7737 static void
7738 expand_omp_target (struct omp_region *region)
7739 {
7740 basic_block entry_bb, exit_bb, new_bb;
7741 struct function *child_cfun = NULL;
7742 tree child_fn = NULL_TREE, block, t;
7743 gimple_stmt_iterator gsi;
7744 gimple entry_stmt, stmt;
7745 edge e;
7746
7747 entry_stmt = last_stmt (region->entry);
7748 new_bb = region->entry;
7749 int kind = gimple_omp_target_kind (entry_stmt);
7750 if (kind == GF_OMP_TARGET_KIND_REGION)
7751 {
7752 child_fn = gimple_omp_target_child_fn (entry_stmt);
7753 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
7754 }
7755
7756 entry_bb = region->entry;
7757 exit_bb = region->exit;
7758
7759 if (kind == GF_OMP_TARGET_KIND_REGION)
7760 {
7761 unsigned srcidx, dstidx, num;
7762
7763 /* If the target region needs data sent from the parent
7764 function, then the very first statement (except possible
7765 tree profile counter updates) of the parallel body
7766 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
7767 &.OMP_DATA_O is passed as an argument to the child function,
7768 we need to replace it with the argument as seen by the child
7769 function.
7770
7771 In most cases, this will end up being the identity assignment
7772 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
7773 a function call that has been inlined, the original PARM_DECL
7774 .OMP_DATA_I may have been converted into a different local
7775 variable. In which case, we need to keep the assignment. */
7776 if (gimple_omp_target_data_arg (entry_stmt))
7777 {
7778 basic_block entry_succ_bb = single_succ (entry_bb);
7779 gimple_stmt_iterator gsi;
7780 tree arg;
7781 gimple tgtcopy_stmt = NULL;
7782 tree sender
7783 = TREE_VEC_ELT (gimple_omp_target_data_arg (entry_stmt), 0);
7784
7785 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
7786 {
7787 gcc_assert (!gsi_end_p (gsi));
7788 stmt = gsi_stmt (gsi);
7789 if (gimple_code (stmt) != GIMPLE_ASSIGN)
7790 continue;
7791
7792 if (gimple_num_ops (stmt) == 2)
7793 {
7794 tree arg = gimple_assign_rhs1 (stmt);
7795
7796 /* We're ignoring the subcode because we're
7797 effectively doing a STRIP_NOPS. */
7798
7799 if (TREE_CODE (arg) == ADDR_EXPR
7800 && TREE_OPERAND (arg, 0) == sender)
7801 {
7802 tgtcopy_stmt = stmt;
7803 break;
7804 }
7805 }
7806 }
7807
7808 gcc_assert (tgtcopy_stmt != NULL);
7809 arg = DECL_ARGUMENTS (child_fn);
7810
7811 gcc_assert (gimple_assign_lhs (tgtcopy_stmt) == arg);
7812 gsi_remove (&gsi, true);
7813 }
7814
7815 /* Declare local variables needed in CHILD_CFUN. */
7816 block = DECL_INITIAL (child_fn);
7817 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
7818 /* The gimplifier could record temporaries in target block
7819 rather than in containing function's local_decls chain,
7820 which would mean cgraph missed finalizing them. Do it now. */
7821 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
7822 if (TREE_CODE (t) == VAR_DECL
7823 && TREE_STATIC (t)
7824 && !DECL_EXTERNAL (t))
7825 varpool_finalize_decl (t);
7826 DECL_SAVED_TREE (child_fn) = NULL;
7827 /* We'll create a CFG for child_fn, so no gimple body is needed. */
7828 gimple_set_body (child_fn, NULL);
7829 TREE_USED (block) = 1;
7830
7831 /* Reset DECL_CONTEXT on function arguments. */
7832 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
7833 DECL_CONTEXT (t) = child_fn;
7834
7835 /* Split ENTRY_BB at GIMPLE_OMP_TARGET,
7836 so that it can be moved to the child function. */
7837 gsi = gsi_last_bb (entry_bb);
7838 stmt = gsi_stmt (gsi);
7839 gcc_assert (stmt && gimple_code (stmt) == GIMPLE_OMP_TARGET
7840 && gimple_omp_target_kind (stmt)
7841 == GF_OMP_TARGET_KIND_REGION);
7842 gsi_remove (&gsi, true);
7843 e = split_block (entry_bb, stmt);
7844 entry_bb = e->dest;
7845 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7846
7847 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
7848 if (exit_bb)
7849 {
7850 gsi = gsi_last_bb (exit_bb);
7851 gcc_assert (!gsi_end_p (gsi)
7852 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
7853 stmt = gimple_build_return (NULL);
7854 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
7855 gsi_remove (&gsi, true);
7856 }
7857
7858 /* Move the target region into CHILD_CFUN. */
7859
7860 block = gimple_block (entry_stmt);
7861
7862 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
7863 if (exit_bb)
7864 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
7865 /* When the OMP expansion process cannot guarantee an up-to-date
7866 loop tree arrange for the child function to fixup loops. */
7867 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
7868 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
7869
7870 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
7871 num = vec_safe_length (child_cfun->local_decls);
7872 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
7873 {
7874 t = (*child_cfun->local_decls)[srcidx];
7875 if (DECL_CONTEXT (t) == cfun->decl)
7876 continue;
7877 if (srcidx != dstidx)
7878 (*child_cfun->local_decls)[dstidx] = t;
7879 dstidx++;
7880 }
7881 if (dstidx != num)
7882 vec_safe_truncate (child_cfun->local_decls, dstidx);
7883
7884 /* Inform the callgraph about the new function. */
7885 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
7886 cgraph_add_new_function (child_fn, true);
7887
7888 /* Fix the callgraph edges for child_cfun. Those for cfun will be
7889 fixed in a following pass. */
7890 push_cfun (child_cfun);
7891 rebuild_cgraph_edges ();
7892
7893 /* Some EH regions might become dead, see PR34608. If
7894 pass_cleanup_cfg isn't the first pass to happen with the
7895 new child, these dead EH edges might cause problems.
7896 Clean them up now. */
7897 if (flag_exceptions)
7898 {
7899 basic_block bb;
7900 bool changed = false;
7901
7902 FOR_EACH_BB (bb)
7903 changed |= gimple_purge_dead_eh_edges (bb);
7904 if (changed)
7905 cleanup_tree_cfg ();
7906 }
7907 pop_cfun ();
7908 }
7909
7910 /* Emit a library call to launch the target region, or do data
7911 transfers. */
7912 tree t1, t2, t3, t4, device, cond, c, clauses;
7913 enum built_in_function start_ix;
7914 location_t clause_loc;
7915
7916 clauses = gimple_omp_target_clauses (entry_stmt);
7917
7918 if (kind == GF_OMP_TARGET_KIND_REGION)
7919 start_ix = BUILT_IN_GOMP_TARGET;
7920 else if (kind == GF_OMP_TARGET_KIND_DATA)
7921 start_ix = BUILT_IN_GOMP_TARGET_DATA;
7922 else
7923 start_ix = BUILT_IN_GOMP_TARGET_UPDATE;
7924
7925 /* By default, the value of DEVICE is -1 (let runtime library choose)
7926 and there is no conditional. */
7927 cond = NULL_TREE;
7928 device = build_int_cst (integer_type_node, -1);
7929
7930 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
7931 if (c)
7932 cond = OMP_CLAUSE_IF_EXPR (c);
7933
7934 c = find_omp_clause (clauses, OMP_CLAUSE_DEVICE);
7935 if (c)
7936 {
7937 device = OMP_CLAUSE_DEVICE_ID (c);
7938 clause_loc = OMP_CLAUSE_LOCATION (c);
7939 }
7940 else
7941 clause_loc = gimple_location (entry_stmt);
7942
7943 /* Ensure 'device' is of the correct type. */
7944 device = fold_convert_loc (clause_loc, integer_type_node, device);
7945
7946 /* If we found the clause 'if (cond)', build
7947 (cond ? device : -2). */
7948 if (cond)
7949 {
7950 cond = gimple_boolify (cond);
7951
7952 basic_block cond_bb, then_bb, else_bb;
7953 edge e;
7954 tree tmp_var;
7955
7956 tmp_var = create_tmp_var (TREE_TYPE (device), NULL);
7957 if (kind != GF_OMP_TARGET_KIND_REGION)
7958 {
7959 gsi = gsi_last_bb (new_bb);
7960 gsi_prev (&gsi);
7961 e = split_block (new_bb, gsi_stmt (gsi));
7962 }
7963 else
7964 e = split_block (new_bb, NULL);
7965 cond_bb = e->src;
7966 new_bb = e->dest;
7967 remove_edge (e);
7968
7969 then_bb = create_empty_bb (cond_bb);
7970 else_bb = create_empty_bb (then_bb);
7971 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
7972 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
7973
7974 stmt = gimple_build_cond_empty (cond);
7975 gsi = gsi_last_bb (cond_bb);
7976 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
7977
7978 gsi = gsi_start_bb (then_bb);
7979 stmt = gimple_build_assign (tmp_var, device);
7980 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
7981
7982 gsi = gsi_start_bb (else_bb);
7983 stmt = gimple_build_assign (tmp_var,
7984 build_int_cst (integer_type_node, -2));
7985 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
7986
7987 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
7988 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
7989 if (current_loops)
7990 {
7991 add_bb_to_loop (then_bb, cond_bb->loop_father);
7992 add_bb_to_loop (else_bb, cond_bb->loop_father);
7993 }
7994 make_edge (then_bb, new_bb, EDGE_FALLTHRU);
7995 make_edge (else_bb, new_bb, EDGE_FALLTHRU);
7996
7997 device = tmp_var;
7998 }
7999
8000 gsi = gsi_last_bb (new_bb);
8001 t = gimple_omp_target_data_arg (entry_stmt);
8002 if (t == NULL)
8003 {
8004 t1 = size_zero_node;
8005 t2 = build_zero_cst (ptr_type_node);
8006 t3 = t2;
8007 t4 = t2;
8008 }
8009 else
8010 {
8011 t1 = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (TREE_VEC_ELT (t, 1))));
8012 t1 = size_binop (PLUS_EXPR, t1, size_int (1));
8013 t2 = build_fold_addr_expr (TREE_VEC_ELT (t, 0));
8014 t3 = build_fold_addr_expr (TREE_VEC_ELT (t, 1));
8015 t4 = build_fold_addr_expr (TREE_VEC_ELT (t, 2));
8016 }
8017
8018 gimple g;
8019 /* FIXME: This will be address of
8020 extern char __OPENMP_TARGET__[] __attribute__((visibility ("hidden")))
8021 symbol, as soon as the linker plugin is able to create it for us. */
8022 tree openmp_target = build_zero_cst (ptr_type_node);
8023 if (kind == GF_OMP_TARGET_KIND_REGION)
8024 {
8025 tree fnaddr = build_fold_addr_expr (child_fn);
8026 g = gimple_build_call (builtin_decl_explicit (start_ix), 7,
8027 device, fnaddr, openmp_target, t1, t2, t3, t4);
8028 }
8029 else
8030 g = gimple_build_call (builtin_decl_explicit (start_ix), 6,
8031 device, openmp_target, t1, t2, t3, t4);
8032 gimple_set_location (g, gimple_location (entry_stmt));
8033 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
8034 if (kind != GF_OMP_TARGET_KIND_REGION)
8035 {
8036 g = gsi_stmt (gsi);
8037 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_TARGET);
8038 gsi_remove (&gsi, true);
8039 }
8040 if (kind == GF_OMP_TARGET_KIND_DATA && region->exit)
8041 {
8042 gsi = gsi_last_bb (region->exit);
8043 g = gsi_stmt (gsi);
8044 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_RETURN);
8045 gsi_remove (&gsi, true);
8046 }
8047 }
8048
8049
8050 /* Expand the parallel region tree rooted at REGION. Expansion
8051 proceeds in depth-first order. Innermost regions are expanded
8052 first. This way, parallel regions that require a new function to
8053 be created (e.g., GIMPLE_OMP_PARALLEL) can be expanded without having any
8054 internal dependencies in their body. */
8055
8056 static void
8057 expand_omp (struct omp_region *region)
8058 {
8059 while (region)
8060 {
8061 location_t saved_location;
8062 gimple inner_stmt = NULL;
8063
8064 /* First, determine whether this is a combined parallel+workshare
8065 region. */
8066 if (region->type == GIMPLE_OMP_PARALLEL)
8067 determine_parallel_type (region);
8068
8069 if (region->type == GIMPLE_OMP_FOR
8070 && gimple_omp_for_combined_p (last_stmt (region->entry)))
8071 inner_stmt = last_stmt (region->inner->entry);
8072
8073 if (region->inner)
8074 expand_omp (region->inner);
8075
8076 saved_location = input_location;
8077 if (gimple_has_location (last_stmt (region->entry)))
8078 input_location = gimple_location (last_stmt (region->entry));
8079
8080 switch (region->type)
8081 {
8082 case GIMPLE_OMP_PARALLEL:
8083 case GIMPLE_OMP_TASK:
8084 expand_omp_taskreg (region);
8085 break;
8086
8087 case GIMPLE_OMP_FOR:
8088 expand_omp_for (region, inner_stmt);
8089 break;
8090
8091 case GIMPLE_OMP_SECTIONS:
8092 expand_omp_sections (region);
8093 break;
8094
8095 case GIMPLE_OMP_SECTION:
8096 /* Individual omp sections are handled together with their
8097 parent GIMPLE_OMP_SECTIONS region. */
8098 break;
8099
8100 case GIMPLE_OMP_SINGLE:
8101 expand_omp_single (region);
8102 break;
8103
8104 case GIMPLE_OMP_MASTER:
8105 case GIMPLE_OMP_TASKGROUP:
8106 case GIMPLE_OMP_ORDERED:
8107 case GIMPLE_OMP_CRITICAL:
8108 case GIMPLE_OMP_TEAMS:
8109 expand_omp_synch (region);
8110 break;
8111
8112 case GIMPLE_OMP_ATOMIC_LOAD:
8113 expand_omp_atomic (region);
8114 break;
8115
8116 case GIMPLE_OMP_TARGET:
8117 expand_omp_target (region);
8118 break;
8119
8120 default:
8121 gcc_unreachable ();
8122 }
8123
8124 input_location = saved_location;
8125 region = region->next;
8126 }
8127 }
8128
8129
8130 /* Helper for build_omp_regions. Scan the dominator tree starting at
8131 block BB. PARENT is the region that contains BB. If SINGLE_TREE is
8132 true, the function ends once a single tree is built (otherwise, whole
8133 forest of OMP constructs may be built). */
8134
8135 static void
8136 build_omp_regions_1 (basic_block bb, struct omp_region *parent,
8137 bool single_tree)
8138 {
8139 gimple_stmt_iterator gsi;
8140 gimple stmt;
8141 basic_block son;
8142
8143 gsi = gsi_last_bb (bb);
8144 if (!gsi_end_p (gsi) && is_gimple_omp (gsi_stmt (gsi)))
8145 {
8146 struct omp_region *region;
8147 enum gimple_code code;
8148
8149 stmt = gsi_stmt (gsi);
8150 code = gimple_code (stmt);
8151 if (code == GIMPLE_OMP_RETURN)
8152 {
8153 /* STMT is the return point out of region PARENT. Mark it
8154 as the exit point and make PARENT the immediately
8155 enclosing region. */
8156 gcc_assert (parent);
8157 region = parent;
8158 region->exit = bb;
8159 parent = parent->outer;
8160 }
8161 else if (code == GIMPLE_OMP_ATOMIC_STORE)
8162 {
8163 /* GIMPLE_OMP_ATOMIC_STORE is analoguous to
8164 GIMPLE_OMP_RETURN, but matches with
8165 GIMPLE_OMP_ATOMIC_LOAD. */
8166 gcc_assert (parent);
8167 gcc_assert (parent->type == GIMPLE_OMP_ATOMIC_LOAD);
8168 region = parent;
8169 region->exit = bb;
8170 parent = parent->outer;
8171 }
8172
8173 else if (code == GIMPLE_OMP_CONTINUE)
8174 {
8175 gcc_assert (parent);
8176 parent->cont = bb;
8177 }
8178 else if (code == GIMPLE_OMP_SECTIONS_SWITCH)
8179 {
8180 /* GIMPLE_OMP_SECTIONS_SWITCH is part of
8181 GIMPLE_OMP_SECTIONS, and we do nothing for it. */
8182 ;
8183 }
8184 else if (code == GIMPLE_OMP_TARGET
8185 && gimple_omp_target_kind (stmt) == GF_OMP_TARGET_KIND_UPDATE)
8186 new_omp_region (bb, code, parent);
8187 else
8188 {
8189 /* Otherwise, this directive becomes the parent for a new
8190 region. */
8191 region = new_omp_region (bb, code, parent);
8192 parent = region;
8193 }
8194 }
8195
8196 if (single_tree && !parent)
8197 return;
8198
8199 for (son = first_dom_son (CDI_DOMINATORS, bb);
8200 son;
8201 son = next_dom_son (CDI_DOMINATORS, son))
8202 build_omp_regions_1 (son, parent, single_tree);
8203 }
8204
8205 /* Builds the tree of OMP regions rooted at ROOT, storing it to
8206 root_omp_region. */
8207
8208 static void
8209 build_omp_regions_root (basic_block root)
8210 {
8211 gcc_assert (root_omp_region == NULL);
8212 build_omp_regions_1 (root, NULL, true);
8213 gcc_assert (root_omp_region != NULL);
8214 }
8215
8216 /* Expands omp construct (and its subconstructs) starting in HEAD. */
8217
8218 void
8219 omp_expand_local (basic_block head)
8220 {
8221 build_omp_regions_root (head);
8222 if (dump_file && (dump_flags & TDF_DETAILS))
8223 {
8224 fprintf (dump_file, "\nOMP region tree\n\n");
8225 dump_omp_region (dump_file, root_omp_region, 0);
8226 fprintf (dump_file, "\n");
8227 }
8228
8229 remove_exit_barriers (root_omp_region);
8230 expand_omp (root_omp_region);
8231
8232 free_omp_regions ();
8233 }
8234
8235 /* Scan the CFG and build a tree of OMP regions. Return the root of
8236 the OMP region tree. */
8237
8238 static void
8239 build_omp_regions (void)
8240 {
8241 gcc_assert (root_omp_region == NULL);
8242 calculate_dominance_info (CDI_DOMINATORS);
8243 build_omp_regions_1 (ENTRY_BLOCK_PTR_FOR_FN (cfun), NULL, false);
8244 }
8245
8246 /* Main entry point for expanding OMP-GIMPLE into runtime calls. */
8247
8248 static unsigned int
8249 execute_expand_omp (void)
8250 {
8251 build_omp_regions ();
8252
8253 if (!root_omp_region)
8254 return 0;
8255
8256 if (dump_file)
8257 {
8258 fprintf (dump_file, "\nOMP region tree\n\n");
8259 dump_omp_region (dump_file, root_omp_region, 0);
8260 fprintf (dump_file, "\n");
8261 }
8262
8263 remove_exit_barriers (root_omp_region);
8264
8265 expand_omp (root_omp_region);
8266
8267 cleanup_tree_cfg ();
8268
8269 free_omp_regions ();
8270
8271 return 0;
8272 }
8273
8274 /* OMP expansion -- the default pass, run before creation of SSA form. */
8275
8276 static bool
8277 gate_expand_omp (void)
8278 {
8279 return ((flag_openmp != 0 || flag_openmp_simd != 0
8280 || flag_enable_cilkplus != 0) && !seen_error ());
8281 }
8282
8283 namespace {
8284
8285 const pass_data pass_data_expand_omp =
8286 {
8287 GIMPLE_PASS, /* type */
8288 "ompexp", /* name */
8289 OPTGROUP_NONE, /* optinfo_flags */
8290 true, /* has_gate */
8291 true, /* has_execute */
8292 TV_NONE, /* tv_id */
8293 PROP_gimple_any, /* properties_required */
8294 0, /* properties_provided */
8295 0, /* properties_destroyed */
8296 0, /* todo_flags_start */
8297 0, /* todo_flags_finish */
8298 };
8299
8300 class pass_expand_omp : public gimple_opt_pass
8301 {
8302 public:
8303 pass_expand_omp (gcc::context *ctxt)
8304 : gimple_opt_pass (pass_data_expand_omp, ctxt)
8305 {}
8306
8307 /* opt_pass methods: */
8308 bool gate () { return gate_expand_omp (); }
8309 unsigned int execute () { return execute_expand_omp (); }
8310
8311 }; // class pass_expand_omp
8312
8313 } // anon namespace
8314
8315 gimple_opt_pass *
8316 make_pass_expand_omp (gcc::context *ctxt)
8317 {
8318 return new pass_expand_omp (ctxt);
8319 }
8320 \f
8321 /* Routines to lower OpenMP directives into OMP-GIMPLE. */
8322
8323 /* If ctx is a worksharing context inside of a cancellable parallel
8324 region and it isn't nowait, add lhs to its GIMPLE_OMP_RETURN
8325 and conditional branch to parallel's cancel_label to handle
8326 cancellation in the implicit barrier. */
8327
8328 static void
8329 maybe_add_implicit_barrier_cancel (omp_context *ctx, gimple_seq *body)
8330 {
8331 gimple omp_return = gimple_seq_last_stmt (*body);
8332 gcc_assert (gimple_code (omp_return) == GIMPLE_OMP_RETURN);
8333 if (gimple_omp_return_nowait_p (omp_return))
8334 return;
8335 if (ctx->outer
8336 && gimple_code (ctx->outer->stmt) == GIMPLE_OMP_PARALLEL
8337 && ctx->outer->cancellable)
8338 {
8339 tree lhs = create_tmp_var (boolean_type_node, NULL);
8340 gimple_omp_return_set_lhs (omp_return, lhs);
8341 tree fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
8342 gimple g = gimple_build_cond (NE_EXPR, lhs, boolean_false_node,
8343 ctx->outer->cancel_label, fallthru_label);
8344 gimple_seq_add_stmt (body, g);
8345 gimple_seq_add_stmt (body, gimple_build_label (fallthru_label));
8346 }
8347 }
8348
8349 /* Lower the OpenMP sections directive in the current statement in GSI_P.
8350 CTX is the enclosing OMP context for the current statement. */
8351
8352 static void
8353 lower_omp_sections (gimple_stmt_iterator *gsi_p, omp_context *ctx)
8354 {
8355 tree block, control;
8356 gimple_stmt_iterator tgsi;
8357 gimple stmt, new_stmt, bind, t;
8358 gimple_seq ilist, dlist, olist, new_body;
8359
8360 stmt = gsi_stmt (*gsi_p);
8361
8362 push_gimplify_context ();
8363
8364 dlist = NULL;
8365 ilist = NULL;
8366 lower_rec_input_clauses (gimple_omp_sections_clauses (stmt),
8367 &ilist, &dlist, ctx, NULL);
8368
8369 new_body = gimple_omp_body (stmt);
8370 gimple_omp_set_body (stmt, NULL);
8371 tgsi = gsi_start (new_body);
8372 for (; !gsi_end_p (tgsi); gsi_next (&tgsi))
8373 {
8374 omp_context *sctx;
8375 gimple sec_start;
8376
8377 sec_start = gsi_stmt (tgsi);
8378 sctx = maybe_lookup_ctx (sec_start);
8379 gcc_assert (sctx);
8380
8381 lower_omp (gimple_omp_body_ptr (sec_start), sctx);
8382 gsi_insert_seq_after (&tgsi, gimple_omp_body (sec_start),
8383 GSI_CONTINUE_LINKING);
8384 gimple_omp_set_body (sec_start, NULL);
8385
8386 if (gsi_one_before_end_p (tgsi))
8387 {
8388 gimple_seq l = NULL;
8389 lower_lastprivate_clauses (gimple_omp_sections_clauses (stmt), NULL,
8390 &l, ctx);
8391 gsi_insert_seq_after (&tgsi, l, GSI_CONTINUE_LINKING);
8392 gimple_omp_section_set_last (sec_start);
8393 }
8394
8395 gsi_insert_after (&tgsi, gimple_build_omp_return (false),
8396 GSI_CONTINUE_LINKING);
8397 }
8398
8399 block = make_node (BLOCK);
8400 bind = gimple_build_bind (NULL, new_body, block);
8401
8402 olist = NULL;
8403 lower_reduction_clauses (gimple_omp_sections_clauses (stmt), &olist, ctx);
8404
8405 block = make_node (BLOCK);
8406 new_stmt = gimple_build_bind (NULL, NULL, block);
8407 gsi_replace (gsi_p, new_stmt, true);
8408
8409 pop_gimplify_context (new_stmt);
8410 gimple_bind_append_vars (new_stmt, ctx->block_vars);
8411 BLOCK_VARS (block) = gimple_bind_vars (bind);
8412 if (BLOCK_VARS (block))
8413 TREE_USED (block) = 1;
8414
8415 new_body = NULL;
8416 gimple_seq_add_seq (&new_body, ilist);
8417 gimple_seq_add_stmt (&new_body, stmt);
8418 gimple_seq_add_stmt (&new_body, gimple_build_omp_sections_switch ());
8419 gimple_seq_add_stmt (&new_body, bind);
8420
8421 control = create_tmp_var (unsigned_type_node, ".section");
8422 t = gimple_build_omp_continue (control, control);
8423 gimple_omp_sections_set_control (stmt, control);
8424 gimple_seq_add_stmt (&new_body, t);
8425
8426 gimple_seq_add_seq (&new_body, olist);
8427 if (ctx->cancellable)
8428 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
8429 gimple_seq_add_seq (&new_body, dlist);
8430
8431 new_body = maybe_catch_exception (new_body);
8432
8433 t = gimple_build_omp_return
8434 (!!find_omp_clause (gimple_omp_sections_clauses (stmt),
8435 OMP_CLAUSE_NOWAIT));
8436 gimple_seq_add_stmt (&new_body, t);
8437 maybe_add_implicit_barrier_cancel (ctx, &new_body);
8438
8439 gimple_bind_set_body (new_stmt, new_body);
8440 }
8441
8442
8443 /* A subroutine of lower_omp_single. Expand the simple form of
8444 a GIMPLE_OMP_SINGLE, without a copyprivate clause:
8445
8446 if (GOMP_single_start ())
8447 BODY;
8448 [ GOMP_barrier (); ] -> unless 'nowait' is present.
8449
8450 FIXME. It may be better to delay expanding the logic of this until
8451 pass_expand_omp. The expanded logic may make the job more difficult
8452 to a synchronization analysis pass. */
8453
8454 static void
8455 lower_omp_single_simple (gimple single_stmt, gimple_seq *pre_p)
8456 {
8457 location_t loc = gimple_location (single_stmt);
8458 tree tlabel = create_artificial_label (loc);
8459 tree flabel = create_artificial_label (loc);
8460 gimple call, cond;
8461 tree lhs, decl;
8462
8463 decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_START);
8464 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (decl)), NULL);
8465 call = gimple_build_call (decl, 0);
8466 gimple_call_set_lhs (call, lhs);
8467 gimple_seq_add_stmt (pre_p, call);
8468
8469 cond = gimple_build_cond (EQ_EXPR, lhs,
8470 fold_convert_loc (loc, TREE_TYPE (lhs),
8471 boolean_true_node),
8472 tlabel, flabel);
8473 gimple_seq_add_stmt (pre_p, cond);
8474 gimple_seq_add_stmt (pre_p, gimple_build_label (tlabel));
8475 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
8476 gimple_seq_add_stmt (pre_p, gimple_build_label (flabel));
8477 }
8478
8479
8480 /* A subroutine of lower_omp_single. Expand the simple form of
8481 a GIMPLE_OMP_SINGLE, with a copyprivate clause:
8482
8483 #pragma omp single copyprivate (a, b, c)
8484
8485 Create a new structure to hold copies of 'a', 'b' and 'c' and emit:
8486
8487 {
8488 if ((copyout_p = GOMP_single_copy_start ()) == NULL)
8489 {
8490 BODY;
8491 copyout.a = a;
8492 copyout.b = b;
8493 copyout.c = c;
8494 GOMP_single_copy_end (&copyout);
8495 }
8496 else
8497 {
8498 a = copyout_p->a;
8499 b = copyout_p->b;
8500 c = copyout_p->c;
8501 }
8502 GOMP_barrier ();
8503 }
8504
8505 FIXME. It may be better to delay expanding the logic of this until
8506 pass_expand_omp. The expanded logic may make the job more difficult
8507 to a synchronization analysis pass. */
8508
8509 static void
8510 lower_omp_single_copy (gimple single_stmt, gimple_seq *pre_p, omp_context *ctx)
8511 {
8512 tree ptr_type, t, l0, l1, l2, bfn_decl;
8513 gimple_seq copyin_seq;
8514 location_t loc = gimple_location (single_stmt);
8515
8516 ctx->sender_decl = create_tmp_var (ctx->record_type, ".omp_copy_o");
8517
8518 ptr_type = build_pointer_type (ctx->record_type);
8519 ctx->receiver_decl = create_tmp_var (ptr_type, ".omp_copy_i");
8520
8521 l0 = create_artificial_label (loc);
8522 l1 = create_artificial_label (loc);
8523 l2 = create_artificial_label (loc);
8524
8525 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_START);
8526 t = build_call_expr_loc (loc, bfn_decl, 0);
8527 t = fold_convert_loc (loc, ptr_type, t);
8528 gimplify_assign (ctx->receiver_decl, t, pre_p);
8529
8530 t = build2 (EQ_EXPR, boolean_type_node, ctx->receiver_decl,
8531 build_int_cst (ptr_type, 0));
8532 t = build3 (COND_EXPR, void_type_node, t,
8533 build_and_jump (&l0), build_and_jump (&l1));
8534 gimplify_and_add (t, pre_p);
8535
8536 gimple_seq_add_stmt (pre_p, gimple_build_label (l0));
8537
8538 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
8539
8540 copyin_seq = NULL;
8541 lower_copyprivate_clauses (gimple_omp_single_clauses (single_stmt), pre_p,
8542 &copyin_seq, ctx);
8543
8544 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
8545 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_END);
8546 t = build_call_expr_loc (loc, bfn_decl, 1, t);
8547 gimplify_and_add (t, pre_p);
8548
8549 t = build_and_jump (&l2);
8550 gimplify_and_add (t, pre_p);
8551
8552 gimple_seq_add_stmt (pre_p, gimple_build_label (l1));
8553
8554 gimple_seq_add_seq (pre_p, copyin_seq);
8555
8556 gimple_seq_add_stmt (pre_p, gimple_build_label (l2));
8557 }
8558
8559
8560 /* Expand code for an OpenMP single directive. */
8561
8562 static void
8563 lower_omp_single (gimple_stmt_iterator *gsi_p, omp_context *ctx)
8564 {
8565 tree block;
8566 gimple t, bind, single_stmt = gsi_stmt (*gsi_p);
8567 gimple_seq bind_body, bind_body_tail = NULL, dlist;
8568
8569 push_gimplify_context ();
8570
8571 block = make_node (BLOCK);
8572 bind = gimple_build_bind (NULL, NULL, block);
8573 gsi_replace (gsi_p, bind, true);
8574 bind_body = NULL;
8575 dlist = NULL;
8576 lower_rec_input_clauses (gimple_omp_single_clauses (single_stmt),
8577 &bind_body, &dlist, ctx, NULL);
8578 lower_omp (gimple_omp_body_ptr (single_stmt), ctx);
8579
8580 gimple_seq_add_stmt (&bind_body, single_stmt);
8581
8582 if (ctx->record_type)
8583 lower_omp_single_copy (single_stmt, &bind_body, ctx);
8584 else
8585 lower_omp_single_simple (single_stmt, &bind_body);
8586
8587 gimple_omp_set_body (single_stmt, NULL);
8588
8589 gimple_seq_add_seq (&bind_body, dlist);
8590
8591 bind_body = maybe_catch_exception (bind_body);
8592
8593 t = gimple_build_omp_return
8594 (!!find_omp_clause (gimple_omp_single_clauses (single_stmt),
8595 OMP_CLAUSE_NOWAIT));
8596 gimple_seq_add_stmt (&bind_body_tail, t);
8597 maybe_add_implicit_barrier_cancel (ctx, &bind_body_tail);
8598 if (ctx->record_type)
8599 {
8600 gimple_stmt_iterator gsi = gsi_start (bind_body_tail);
8601 tree clobber = build_constructor (ctx->record_type, NULL);
8602 TREE_THIS_VOLATILE (clobber) = 1;
8603 gsi_insert_after (&gsi, gimple_build_assign (ctx->sender_decl,
8604 clobber), GSI_SAME_STMT);
8605 }
8606 gimple_seq_add_seq (&bind_body, bind_body_tail);
8607 gimple_bind_set_body (bind, bind_body);
8608
8609 pop_gimplify_context (bind);
8610
8611 gimple_bind_append_vars (bind, ctx->block_vars);
8612 BLOCK_VARS (block) = ctx->block_vars;
8613 if (BLOCK_VARS (block))
8614 TREE_USED (block) = 1;
8615 }
8616
8617
8618 /* Expand code for an OpenMP master directive. */
8619
8620 static void
8621 lower_omp_master (gimple_stmt_iterator *gsi_p, omp_context *ctx)
8622 {
8623 tree block, lab = NULL, x, bfn_decl;
8624 gimple stmt = gsi_stmt (*gsi_p), bind;
8625 location_t loc = gimple_location (stmt);
8626 gimple_seq tseq;
8627
8628 push_gimplify_context ();
8629
8630 block = make_node (BLOCK);
8631 bind = gimple_build_bind (NULL, NULL, block);
8632 gsi_replace (gsi_p, bind, true);
8633 gimple_bind_add_stmt (bind, stmt);
8634
8635 bfn_decl = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
8636 x = build_call_expr_loc (loc, bfn_decl, 0);
8637 x = build2 (EQ_EXPR, boolean_type_node, x, integer_zero_node);
8638 x = build3 (COND_EXPR, void_type_node, x, NULL, build_and_jump (&lab));
8639 tseq = NULL;
8640 gimplify_and_add (x, &tseq);
8641 gimple_bind_add_seq (bind, tseq);
8642
8643 lower_omp (gimple_omp_body_ptr (stmt), ctx);
8644 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
8645 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
8646 gimple_omp_set_body (stmt, NULL);
8647
8648 gimple_bind_add_stmt (bind, gimple_build_label (lab));
8649
8650 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
8651
8652 pop_gimplify_context (bind);
8653
8654 gimple_bind_append_vars (bind, ctx->block_vars);
8655 BLOCK_VARS (block) = ctx->block_vars;
8656 }
8657
8658
8659 /* Expand code for an OpenMP taskgroup directive. */
8660
8661 static void
8662 lower_omp_taskgroup (gimple_stmt_iterator *gsi_p, omp_context *ctx)
8663 {
8664 gimple stmt = gsi_stmt (*gsi_p), bind, x;
8665 tree block = make_node (BLOCK);
8666
8667 bind = gimple_build_bind (NULL, NULL, block);
8668 gsi_replace (gsi_p, bind, true);
8669 gimple_bind_add_stmt (bind, stmt);
8670
8671 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_TASKGROUP_START),
8672 0);
8673 gimple_bind_add_stmt (bind, x);
8674
8675 lower_omp (gimple_omp_body_ptr (stmt), ctx);
8676 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
8677 gimple_omp_set_body (stmt, NULL);
8678
8679 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
8680
8681 gimple_bind_append_vars (bind, ctx->block_vars);
8682 BLOCK_VARS (block) = ctx->block_vars;
8683 }
8684
8685
8686 /* Expand code for an OpenMP ordered directive. */
8687
8688 static void
8689 lower_omp_ordered (gimple_stmt_iterator *gsi_p, omp_context *ctx)
8690 {
8691 tree block;
8692 gimple stmt = gsi_stmt (*gsi_p), bind, x;
8693
8694 push_gimplify_context ();
8695
8696 block = make_node (BLOCK);
8697 bind = gimple_build_bind (NULL, NULL, block);
8698 gsi_replace (gsi_p, bind, true);
8699 gimple_bind_add_stmt (bind, stmt);
8700
8701 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_START),
8702 0);
8703 gimple_bind_add_stmt (bind, x);
8704
8705 lower_omp (gimple_omp_body_ptr (stmt), ctx);
8706 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
8707 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
8708 gimple_omp_set_body (stmt, NULL);
8709
8710 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_END), 0);
8711 gimple_bind_add_stmt (bind, x);
8712
8713 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
8714
8715 pop_gimplify_context (bind);
8716
8717 gimple_bind_append_vars (bind, ctx->block_vars);
8718 BLOCK_VARS (block) = gimple_bind_vars (bind);
8719 }
8720
8721
8722 /* Gimplify a GIMPLE_OMP_CRITICAL statement. This is a relatively simple
8723 substitution of a couple of function calls. But in the NAMED case,
8724 requires that languages coordinate a symbol name. It is therefore
8725 best put here in common code. */
8726
8727 static GTY((param1_is (tree), param2_is (tree)))
8728 splay_tree critical_name_mutexes;
8729
8730 static void
8731 lower_omp_critical (gimple_stmt_iterator *gsi_p, omp_context *ctx)
8732 {
8733 tree block;
8734 tree name, lock, unlock;
8735 gimple stmt = gsi_stmt (*gsi_p), bind;
8736 location_t loc = gimple_location (stmt);
8737 gimple_seq tbody;
8738
8739 name = gimple_omp_critical_name (stmt);
8740 if (name)
8741 {
8742 tree decl;
8743 splay_tree_node n;
8744
8745 if (!critical_name_mutexes)
8746 critical_name_mutexes
8747 = splay_tree_new_ggc (splay_tree_compare_pointers,
8748 ggc_alloc_splay_tree_tree_node_tree_node_splay_tree_s,
8749 ggc_alloc_splay_tree_tree_node_tree_node_splay_tree_node_s);
8750
8751 n = splay_tree_lookup (critical_name_mutexes, (splay_tree_key) name);
8752 if (n == NULL)
8753 {
8754 char *new_str;
8755
8756 decl = create_tmp_var_raw (ptr_type_node, NULL);
8757
8758 new_str = ACONCAT ((".gomp_critical_user_",
8759 IDENTIFIER_POINTER (name), NULL));
8760 DECL_NAME (decl) = get_identifier (new_str);
8761 TREE_PUBLIC (decl) = 1;
8762 TREE_STATIC (decl) = 1;
8763 DECL_COMMON (decl) = 1;
8764 DECL_ARTIFICIAL (decl) = 1;
8765 DECL_IGNORED_P (decl) = 1;
8766 varpool_finalize_decl (decl);
8767
8768 splay_tree_insert (critical_name_mutexes, (splay_tree_key) name,
8769 (splay_tree_value) decl);
8770 }
8771 else
8772 decl = (tree) n->value;
8773
8774 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_START);
8775 lock = build_call_expr_loc (loc, lock, 1, build_fold_addr_expr_loc (loc, decl));
8776
8777 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_END);
8778 unlock = build_call_expr_loc (loc, unlock, 1,
8779 build_fold_addr_expr_loc (loc, decl));
8780 }
8781 else
8782 {
8783 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_START);
8784 lock = build_call_expr_loc (loc, lock, 0);
8785
8786 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_END);
8787 unlock = build_call_expr_loc (loc, unlock, 0);
8788 }
8789
8790 push_gimplify_context ();
8791
8792 block = make_node (BLOCK);
8793 bind = gimple_build_bind (NULL, NULL, block);
8794 gsi_replace (gsi_p, bind, true);
8795 gimple_bind_add_stmt (bind, stmt);
8796
8797 tbody = gimple_bind_body (bind);
8798 gimplify_and_add (lock, &tbody);
8799 gimple_bind_set_body (bind, tbody);
8800
8801 lower_omp (gimple_omp_body_ptr (stmt), ctx);
8802 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
8803 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
8804 gimple_omp_set_body (stmt, NULL);
8805
8806 tbody = gimple_bind_body (bind);
8807 gimplify_and_add (unlock, &tbody);
8808 gimple_bind_set_body (bind, tbody);
8809
8810 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
8811
8812 pop_gimplify_context (bind);
8813 gimple_bind_append_vars (bind, ctx->block_vars);
8814 BLOCK_VARS (block) = gimple_bind_vars (bind);
8815 }
8816
8817
8818 /* A subroutine of lower_omp_for. Generate code to emit the predicate
8819 for a lastprivate clause. Given a loop control predicate of (V
8820 cond N2), we gate the clause on (!(V cond N2)). The lowered form
8821 is appended to *DLIST, iterator initialization is appended to
8822 *BODY_P. */
8823
8824 static void
8825 lower_omp_for_lastprivate (struct omp_for_data *fd, gimple_seq *body_p,
8826 gimple_seq *dlist, struct omp_context *ctx)
8827 {
8828 tree clauses, cond, vinit;
8829 enum tree_code cond_code;
8830 gimple_seq stmts;
8831
8832 cond_code = fd->loop.cond_code;
8833 cond_code = cond_code == LT_EXPR ? GE_EXPR : LE_EXPR;
8834
8835 /* When possible, use a strict equality expression. This can let VRP
8836 type optimizations deduce the value and remove a copy. */
8837 if (tree_fits_shwi_p (fd->loop.step))
8838 {
8839 HOST_WIDE_INT step = tree_to_shwi (fd->loop.step);
8840 if (step == 1 || step == -1)
8841 cond_code = EQ_EXPR;
8842 }
8843
8844 cond = build2 (cond_code, boolean_type_node, fd->loop.v, fd->loop.n2);
8845
8846 clauses = gimple_omp_for_clauses (fd->for_stmt);
8847 stmts = NULL;
8848 lower_lastprivate_clauses (clauses, cond, &stmts, ctx);
8849 if (!gimple_seq_empty_p (stmts))
8850 {
8851 gimple_seq_add_seq (&stmts, *dlist);
8852 *dlist = stmts;
8853
8854 /* Optimize: v = 0; is usually cheaper than v = some_other_constant. */
8855 vinit = fd->loop.n1;
8856 if (cond_code == EQ_EXPR
8857 && tree_fits_shwi_p (fd->loop.n2)
8858 && ! integer_zerop (fd->loop.n2))
8859 vinit = build_int_cst (TREE_TYPE (fd->loop.v), 0);
8860 else
8861 vinit = unshare_expr (vinit);
8862
8863 /* Initialize the iterator variable, so that threads that don't execute
8864 any iterations don't execute the lastprivate clauses by accident. */
8865 gimplify_assign (fd->loop.v, vinit, body_p);
8866 }
8867 }
8868
8869
8870 /* Lower code for an OpenMP loop directive. */
8871
8872 static void
8873 lower_omp_for (gimple_stmt_iterator *gsi_p, omp_context *ctx)
8874 {
8875 tree *rhs_p, block;
8876 struct omp_for_data fd, *fdp = NULL;
8877 gimple stmt = gsi_stmt (*gsi_p), new_stmt;
8878 gimple_seq omp_for_body, body, dlist;
8879 size_t i;
8880
8881 push_gimplify_context ();
8882
8883 lower_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
8884
8885 block = make_node (BLOCK);
8886 new_stmt = gimple_build_bind (NULL, NULL, block);
8887 /* Replace at gsi right away, so that 'stmt' is no member
8888 of a sequence anymore as we're going to add to to a different
8889 one below. */
8890 gsi_replace (gsi_p, new_stmt, true);
8891
8892 /* Move declaration of temporaries in the loop body before we make
8893 it go away. */
8894 omp_for_body = gimple_omp_body (stmt);
8895 if (!gimple_seq_empty_p (omp_for_body)
8896 && gimple_code (gimple_seq_first_stmt (omp_for_body)) == GIMPLE_BIND)
8897 {
8898 tree vars = gimple_bind_vars (gimple_seq_first_stmt (omp_for_body));
8899 gimple_bind_append_vars (new_stmt, vars);
8900 }
8901
8902 if (gimple_omp_for_combined_into_p (stmt))
8903 {
8904 extract_omp_for_data (stmt, &fd, NULL);
8905 fdp = &fd;
8906
8907 /* We need two temporaries with fd.loop.v type (istart/iend)
8908 and then (fd.collapse - 1) temporaries with the same
8909 type for count2 ... countN-1 vars if not constant. */
8910 size_t count = 2;
8911 tree type = fd.iter_type;
8912 if (fd.collapse > 1
8913 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
8914 count += fd.collapse - 1;
8915 bool parallel_for = gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR;
8916 tree outerc = NULL, *pc = gimple_omp_for_clauses_ptr (stmt);
8917 tree clauses = *pc;
8918 if (parallel_for)
8919 outerc
8920 = find_omp_clause (gimple_omp_parallel_clauses (ctx->outer->stmt),
8921 OMP_CLAUSE__LOOPTEMP_);
8922 for (i = 0; i < count; i++)
8923 {
8924 tree temp;
8925 if (parallel_for)
8926 {
8927 gcc_assert (outerc);
8928 temp = lookup_decl (OMP_CLAUSE_DECL (outerc), ctx->outer);
8929 outerc = find_omp_clause (OMP_CLAUSE_CHAIN (outerc),
8930 OMP_CLAUSE__LOOPTEMP_);
8931 }
8932 else
8933 temp = create_tmp_var (type, NULL);
8934 *pc = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__LOOPTEMP_);
8935 OMP_CLAUSE_DECL (*pc) = temp;
8936 pc = &OMP_CLAUSE_CHAIN (*pc);
8937 }
8938 *pc = clauses;
8939 }
8940
8941 /* The pre-body and input clauses go before the lowered GIMPLE_OMP_FOR. */
8942 dlist = NULL;
8943 body = NULL;
8944 lower_rec_input_clauses (gimple_omp_for_clauses (stmt), &body, &dlist, ctx,
8945 fdp);
8946 gimple_seq_add_seq (&body, gimple_omp_for_pre_body (stmt));
8947
8948 lower_omp (gimple_omp_body_ptr (stmt), ctx);
8949
8950 /* Lower the header expressions. At this point, we can assume that
8951 the header is of the form:
8952
8953 #pragma omp for (V = VAL1; V {<|>|<=|>=} VAL2; V = V [+-] VAL3)
8954
8955 We just need to make sure that VAL1, VAL2 and VAL3 are lowered
8956 using the .omp_data_s mapping, if needed. */
8957 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
8958 {
8959 rhs_p = gimple_omp_for_initial_ptr (stmt, i);
8960 if (!is_gimple_min_invariant (*rhs_p))
8961 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
8962
8963 rhs_p = gimple_omp_for_final_ptr (stmt, i);
8964 if (!is_gimple_min_invariant (*rhs_p))
8965 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
8966
8967 rhs_p = &TREE_OPERAND (gimple_omp_for_incr (stmt, i), 1);
8968 if (!is_gimple_min_invariant (*rhs_p))
8969 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
8970 }
8971
8972 /* Once lowered, extract the bounds and clauses. */
8973 extract_omp_for_data (stmt, &fd, NULL);
8974
8975 lower_omp_for_lastprivate (&fd, &body, &dlist, ctx);
8976
8977 gimple_seq_add_stmt (&body, stmt);
8978 gimple_seq_add_seq (&body, gimple_omp_body (stmt));
8979
8980 gimple_seq_add_stmt (&body, gimple_build_omp_continue (fd.loop.v,
8981 fd.loop.v));
8982
8983 /* After the loop, add exit clauses. */
8984 lower_reduction_clauses (gimple_omp_for_clauses (stmt), &body, ctx);
8985
8986 if (ctx->cancellable)
8987 gimple_seq_add_stmt (&body, gimple_build_label (ctx->cancel_label));
8988
8989 gimple_seq_add_seq (&body, dlist);
8990
8991 body = maybe_catch_exception (body);
8992
8993 /* Region exit marker goes at the end of the loop body. */
8994 gimple_seq_add_stmt (&body, gimple_build_omp_return (fd.have_nowait));
8995 maybe_add_implicit_barrier_cancel (ctx, &body);
8996 pop_gimplify_context (new_stmt);
8997
8998 gimple_bind_append_vars (new_stmt, ctx->block_vars);
8999 BLOCK_VARS (block) = gimple_bind_vars (new_stmt);
9000 if (BLOCK_VARS (block))
9001 TREE_USED (block) = 1;
9002
9003 gimple_bind_set_body (new_stmt, body);
9004 gimple_omp_set_body (stmt, NULL);
9005 gimple_omp_for_set_pre_body (stmt, NULL);
9006 }
9007
9008 /* Callback for walk_stmts. Check if the current statement only contains
9009 GIMPLE_OMP_FOR or GIMPLE_OMP_PARALLEL. */
9010
9011 static tree
9012 check_combined_parallel (gimple_stmt_iterator *gsi_p,
9013 bool *handled_ops_p,
9014 struct walk_stmt_info *wi)
9015 {
9016 int *info = (int *) wi->info;
9017 gimple stmt = gsi_stmt (*gsi_p);
9018
9019 *handled_ops_p = true;
9020 switch (gimple_code (stmt))
9021 {
9022 WALK_SUBSTMTS;
9023
9024 case GIMPLE_OMP_FOR:
9025 case GIMPLE_OMP_SECTIONS:
9026 *info = *info == 0 ? 1 : -1;
9027 break;
9028 default:
9029 *info = -1;
9030 break;
9031 }
9032 return NULL;
9033 }
9034
9035 struct omp_taskcopy_context
9036 {
9037 /* This field must be at the beginning, as we do "inheritance": Some
9038 callback functions for tree-inline.c (e.g., omp_copy_decl)
9039 receive a copy_body_data pointer that is up-casted to an
9040 omp_context pointer. */
9041 copy_body_data cb;
9042 omp_context *ctx;
9043 };
9044
9045 static tree
9046 task_copyfn_copy_decl (tree var, copy_body_data *cb)
9047 {
9048 struct omp_taskcopy_context *tcctx = (struct omp_taskcopy_context *) cb;
9049
9050 if (splay_tree_lookup (tcctx->ctx->sfield_map, (splay_tree_key) var))
9051 return create_tmp_var (TREE_TYPE (var), NULL);
9052
9053 return var;
9054 }
9055
9056 static tree
9057 task_copyfn_remap_type (struct omp_taskcopy_context *tcctx, tree orig_type)
9058 {
9059 tree name, new_fields = NULL, type, f;
9060
9061 type = lang_hooks.types.make_type (RECORD_TYPE);
9062 name = DECL_NAME (TYPE_NAME (orig_type));
9063 name = build_decl (gimple_location (tcctx->ctx->stmt),
9064 TYPE_DECL, name, type);
9065 TYPE_NAME (type) = name;
9066
9067 for (f = TYPE_FIELDS (orig_type); f ; f = TREE_CHAIN (f))
9068 {
9069 tree new_f = copy_node (f);
9070 DECL_CONTEXT (new_f) = type;
9071 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &tcctx->cb);
9072 TREE_CHAIN (new_f) = new_fields;
9073 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &tcctx->cb, NULL);
9074 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r, &tcctx->cb, NULL);
9075 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
9076 &tcctx->cb, NULL);
9077 new_fields = new_f;
9078 *pointer_map_insert (tcctx->cb.decl_map, f) = new_f;
9079 }
9080 TYPE_FIELDS (type) = nreverse (new_fields);
9081 layout_type (type);
9082 return type;
9083 }
9084
9085 /* Create task copyfn. */
9086
9087 static void
9088 create_task_copyfn (gimple task_stmt, omp_context *ctx)
9089 {
9090 struct function *child_cfun;
9091 tree child_fn, t, c, src, dst, f, sf, arg, sarg, decl;
9092 tree record_type, srecord_type, bind, list;
9093 bool record_needs_remap = false, srecord_needs_remap = false;
9094 splay_tree_node n;
9095 struct omp_taskcopy_context tcctx;
9096 location_t loc = gimple_location (task_stmt);
9097
9098 child_fn = gimple_omp_task_copy_fn (task_stmt);
9099 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
9100 gcc_assert (child_cfun->cfg == NULL);
9101 DECL_SAVED_TREE (child_fn) = alloc_stmt_list ();
9102
9103 /* Reset DECL_CONTEXT on function arguments. */
9104 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
9105 DECL_CONTEXT (t) = child_fn;
9106
9107 /* Populate the function. */
9108 push_gimplify_context ();
9109 push_cfun (child_cfun);
9110
9111 bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
9112 TREE_SIDE_EFFECTS (bind) = 1;
9113 list = NULL;
9114 DECL_SAVED_TREE (child_fn) = bind;
9115 DECL_SOURCE_LOCATION (child_fn) = gimple_location (task_stmt);
9116
9117 /* Remap src and dst argument types if needed. */
9118 record_type = ctx->record_type;
9119 srecord_type = ctx->srecord_type;
9120 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
9121 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
9122 {
9123 record_needs_remap = true;
9124 break;
9125 }
9126 for (f = TYPE_FIELDS (srecord_type); f ; f = DECL_CHAIN (f))
9127 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
9128 {
9129 srecord_needs_remap = true;
9130 break;
9131 }
9132
9133 if (record_needs_remap || srecord_needs_remap)
9134 {
9135 memset (&tcctx, '\0', sizeof (tcctx));
9136 tcctx.cb.src_fn = ctx->cb.src_fn;
9137 tcctx.cb.dst_fn = child_fn;
9138 tcctx.cb.src_node = cgraph_get_node (tcctx.cb.src_fn);
9139 gcc_checking_assert (tcctx.cb.src_node);
9140 tcctx.cb.dst_node = tcctx.cb.src_node;
9141 tcctx.cb.src_cfun = ctx->cb.src_cfun;
9142 tcctx.cb.copy_decl = task_copyfn_copy_decl;
9143 tcctx.cb.eh_lp_nr = 0;
9144 tcctx.cb.transform_call_graph_edges = CB_CGE_MOVE;
9145 tcctx.cb.decl_map = pointer_map_create ();
9146 tcctx.ctx = ctx;
9147
9148 if (record_needs_remap)
9149 record_type = task_copyfn_remap_type (&tcctx, record_type);
9150 if (srecord_needs_remap)
9151 srecord_type = task_copyfn_remap_type (&tcctx, srecord_type);
9152 }
9153 else
9154 tcctx.cb.decl_map = NULL;
9155
9156 arg = DECL_ARGUMENTS (child_fn);
9157 TREE_TYPE (arg) = build_pointer_type (record_type);
9158 sarg = DECL_CHAIN (arg);
9159 TREE_TYPE (sarg) = build_pointer_type (srecord_type);
9160
9161 /* First pass: initialize temporaries used in record_type and srecord_type
9162 sizes and field offsets. */
9163 if (tcctx.cb.decl_map)
9164 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
9165 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
9166 {
9167 tree *p;
9168
9169 decl = OMP_CLAUSE_DECL (c);
9170 p = (tree *) pointer_map_contains (tcctx.cb.decl_map, decl);
9171 if (p == NULL)
9172 continue;
9173 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
9174 sf = (tree) n->value;
9175 sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
9176 src = build_simple_mem_ref_loc (loc, sarg);
9177 src = omp_build_component_ref (src, sf);
9178 t = build2 (MODIFY_EXPR, TREE_TYPE (*p), *p, src);
9179 append_to_statement_list (t, &list);
9180 }
9181
9182 /* Second pass: copy shared var pointers and copy construct non-VLA
9183 firstprivate vars. */
9184 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
9185 switch (OMP_CLAUSE_CODE (c))
9186 {
9187 case OMP_CLAUSE_SHARED:
9188 decl = OMP_CLAUSE_DECL (c);
9189 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
9190 if (n == NULL)
9191 break;
9192 f = (tree) n->value;
9193 if (tcctx.cb.decl_map)
9194 f = *(tree *) pointer_map_contains (tcctx.cb.decl_map, f);
9195 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
9196 sf = (tree) n->value;
9197 if (tcctx.cb.decl_map)
9198 sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
9199 src = build_simple_mem_ref_loc (loc, sarg);
9200 src = omp_build_component_ref (src, sf);
9201 dst = build_simple_mem_ref_loc (loc, arg);
9202 dst = omp_build_component_ref (dst, f);
9203 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
9204 append_to_statement_list (t, &list);
9205 break;
9206 case OMP_CLAUSE_FIRSTPRIVATE:
9207 decl = OMP_CLAUSE_DECL (c);
9208 if (is_variable_sized (decl))
9209 break;
9210 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
9211 if (n == NULL)
9212 break;
9213 f = (tree) n->value;
9214 if (tcctx.cb.decl_map)
9215 f = *(tree *) pointer_map_contains (tcctx.cb.decl_map, f);
9216 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
9217 if (n != NULL)
9218 {
9219 sf = (tree) n->value;
9220 if (tcctx.cb.decl_map)
9221 sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
9222 src = build_simple_mem_ref_loc (loc, sarg);
9223 src = omp_build_component_ref (src, sf);
9224 if (use_pointer_for_field (decl, NULL) || is_reference (decl))
9225 src = build_simple_mem_ref_loc (loc, src);
9226 }
9227 else
9228 src = decl;
9229 dst = build_simple_mem_ref_loc (loc, arg);
9230 dst = omp_build_component_ref (dst, f);
9231 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
9232 append_to_statement_list (t, &list);
9233 break;
9234 case OMP_CLAUSE_PRIVATE:
9235 if (! OMP_CLAUSE_PRIVATE_OUTER_REF (c))
9236 break;
9237 decl = OMP_CLAUSE_DECL (c);
9238 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
9239 f = (tree) n->value;
9240 if (tcctx.cb.decl_map)
9241 f = *(tree *) pointer_map_contains (tcctx.cb.decl_map, f);
9242 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
9243 if (n != NULL)
9244 {
9245 sf = (tree) n->value;
9246 if (tcctx.cb.decl_map)
9247 sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
9248 src = build_simple_mem_ref_loc (loc, sarg);
9249 src = omp_build_component_ref (src, sf);
9250 if (use_pointer_for_field (decl, NULL))
9251 src = build_simple_mem_ref_loc (loc, src);
9252 }
9253 else
9254 src = decl;
9255 dst = build_simple_mem_ref_loc (loc, arg);
9256 dst = omp_build_component_ref (dst, f);
9257 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
9258 append_to_statement_list (t, &list);
9259 break;
9260 default:
9261 break;
9262 }
9263
9264 /* Last pass: handle VLA firstprivates. */
9265 if (tcctx.cb.decl_map)
9266 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
9267 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
9268 {
9269 tree ind, ptr, df;
9270
9271 decl = OMP_CLAUSE_DECL (c);
9272 if (!is_variable_sized (decl))
9273 continue;
9274 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
9275 if (n == NULL)
9276 continue;
9277 f = (tree) n->value;
9278 f = *(tree *) pointer_map_contains (tcctx.cb.decl_map, f);
9279 gcc_assert (DECL_HAS_VALUE_EXPR_P (decl));
9280 ind = DECL_VALUE_EXPR (decl);
9281 gcc_assert (TREE_CODE (ind) == INDIRECT_REF);
9282 gcc_assert (DECL_P (TREE_OPERAND (ind, 0)));
9283 n = splay_tree_lookup (ctx->sfield_map,
9284 (splay_tree_key) TREE_OPERAND (ind, 0));
9285 sf = (tree) n->value;
9286 sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
9287 src = build_simple_mem_ref_loc (loc, sarg);
9288 src = omp_build_component_ref (src, sf);
9289 src = build_simple_mem_ref_loc (loc, src);
9290 dst = build_simple_mem_ref_loc (loc, arg);
9291 dst = omp_build_component_ref (dst, f);
9292 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
9293 append_to_statement_list (t, &list);
9294 n = splay_tree_lookup (ctx->field_map,
9295 (splay_tree_key) TREE_OPERAND (ind, 0));
9296 df = (tree) n->value;
9297 df = *(tree *) pointer_map_contains (tcctx.cb.decl_map, df);
9298 ptr = build_simple_mem_ref_loc (loc, arg);
9299 ptr = omp_build_component_ref (ptr, df);
9300 t = build2 (MODIFY_EXPR, TREE_TYPE (ptr), ptr,
9301 build_fold_addr_expr_loc (loc, dst));
9302 append_to_statement_list (t, &list);
9303 }
9304
9305 t = build1 (RETURN_EXPR, void_type_node, NULL);
9306 append_to_statement_list (t, &list);
9307
9308 if (tcctx.cb.decl_map)
9309 pointer_map_destroy (tcctx.cb.decl_map);
9310 pop_gimplify_context (NULL);
9311 BIND_EXPR_BODY (bind) = list;
9312 pop_cfun ();
9313 }
9314
9315 static void
9316 lower_depend_clauses (gimple stmt, gimple_seq *iseq, gimple_seq *oseq)
9317 {
9318 tree c, clauses;
9319 gimple g;
9320 size_t n_in = 0, n_out = 0, idx = 2, i;
9321
9322 clauses = find_omp_clause (gimple_omp_task_clauses (stmt),
9323 OMP_CLAUSE_DEPEND);
9324 gcc_assert (clauses);
9325 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
9326 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
9327 switch (OMP_CLAUSE_DEPEND_KIND (c))
9328 {
9329 case OMP_CLAUSE_DEPEND_IN:
9330 n_in++;
9331 break;
9332 case OMP_CLAUSE_DEPEND_OUT:
9333 case OMP_CLAUSE_DEPEND_INOUT:
9334 n_out++;
9335 break;
9336 default:
9337 gcc_unreachable ();
9338 }
9339 tree type = build_array_type_nelts (ptr_type_node, n_in + n_out + 2);
9340 tree array = create_tmp_var (type, NULL);
9341 tree r = build4 (ARRAY_REF, ptr_type_node, array, size_int (0), NULL_TREE,
9342 NULL_TREE);
9343 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_in + n_out));
9344 gimple_seq_add_stmt (iseq, g);
9345 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (1), NULL_TREE,
9346 NULL_TREE);
9347 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_out));
9348 gimple_seq_add_stmt (iseq, g);
9349 for (i = 0; i < 2; i++)
9350 {
9351 if ((i ? n_in : n_out) == 0)
9352 continue;
9353 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
9354 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
9355 && ((OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_IN) ^ i))
9356 {
9357 tree t = OMP_CLAUSE_DECL (c);
9358 t = fold_convert (ptr_type_node, t);
9359 gimplify_expr (&t, iseq, NULL, is_gimple_val, fb_rvalue);
9360 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (idx++),
9361 NULL_TREE, NULL_TREE);
9362 g = gimple_build_assign (r, t);
9363 gimple_seq_add_stmt (iseq, g);
9364 }
9365 }
9366 tree *p = gimple_omp_task_clauses_ptr (stmt);
9367 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_DEPEND);
9368 OMP_CLAUSE_DECL (c) = build_fold_addr_expr (array);
9369 OMP_CLAUSE_CHAIN (c) = *p;
9370 *p = c;
9371 tree clobber = build_constructor (type, NULL);
9372 TREE_THIS_VOLATILE (clobber) = 1;
9373 g = gimple_build_assign (array, clobber);
9374 gimple_seq_add_stmt (oseq, g);
9375 }
9376
9377 /* Lower the OpenMP parallel or task directive in the current statement
9378 in GSI_P. CTX holds context information for the directive. */
9379
9380 static void
9381 lower_omp_taskreg (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9382 {
9383 tree clauses;
9384 tree child_fn, t;
9385 gimple stmt = gsi_stmt (*gsi_p);
9386 gimple par_bind, bind, dep_bind = NULL;
9387 gimple_seq par_body, olist, ilist, par_olist, par_rlist, par_ilist, new_body;
9388 location_t loc = gimple_location (stmt);
9389
9390 clauses = gimple_omp_taskreg_clauses (stmt);
9391 par_bind = gimple_seq_first_stmt (gimple_omp_body (stmt));
9392 par_body = gimple_bind_body (par_bind);
9393 child_fn = ctx->cb.dst_fn;
9394 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
9395 && !gimple_omp_parallel_combined_p (stmt))
9396 {
9397 struct walk_stmt_info wi;
9398 int ws_num = 0;
9399
9400 memset (&wi, 0, sizeof (wi));
9401 wi.info = &ws_num;
9402 wi.val_only = true;
9403 walk_gimple_seq (par_body, check_combined_parallel, NULL, &wi);
9404 if (ws_num == 1)
9405 gimple_omp_parallel_set_combined_p (stmt, true);
9406 }
9407 gimple_seq dep_ilist = NULL;
9408 gimple_seq dep_olist = NULL;
9409 if (gimple_code (stmt) == GIMPLE_OMP_TASK
9410 && find_omp_clause (clauses, OMP_CLAUSE_DEPEND))
9411 {
9412 push_gimplify_context ();
9413 dep_bind = gimple_build_bind (NULL, NULL, make_node (BLOCK));
9414 lower_depend_clauses (stmt, &dep_ilist, &dep_olist);
9415 }
9416
9417 if (ctx->srecord_type)
9418 create_task_copyfn (stmt, ctx);
9419
9420 push_gimplify_context ();
9421
9422 par_olist = NULL;
9423 par_ilist = NULL;
9424 par_rlist = NULL;
9425 lower_rec_input_clauses (clauses, &par_ilist, &par_olist, ctx, NULL);
9426 lower_omp (&par_body, ctx);
9427 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL)
9428 lower_reduction_clauses (clauses, &par_rlist, ctx);
9429
9430 /* Declare all the variables created by mapping and the variables
9431 declared in the scope of the parallel body. */
9432 record_vars_into (ctx->block_vars, child_fn);
9433 record_vars_into (gimple_bind_vars (par_bind), child_fn);
9434
9435 if (ctx->record_type)
9436 {
9437 ctx->sender_decl
9438 = create_tmp_var (ctx->srecord_type ? ctx->srecord_type
9439 : ctx->record_type, ".omp_data_o");
9440 DECL_NAMELESS (ctx->sender_decl) = 1;
9441 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
9442 gimple_omp_taskreg_set_data_arg (stmt, ctx->sender_decl);
9443 }
9444
9445 olist = NULL;
9446 ilist = NULL;
9447 lower_send_clauses (clauses, &ilist, &olist, ctx);
9448 lower_send_shared_vars (&ilist, &olist, ctx);
9449
9450 if (ctx->record_type)
9451 {
9452 tree clobber = build_constructor (TREE_TYPE (ctx->sender_decl), NULL);
9453 TREE_THIS_VOLATILE (clobber) = 1;
9454 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
9455 clobber));
9456 }
9457
9458 /* Once all the expansions are done, sequence all the different
9459 fragments inside gimple_omp_body. */
9460
9461 new_body = NULL;
9462
9463 if (ctx->record_type)
9464 {
9465 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
9466 /* fixup_child_record_type might have changed receiver_decl's type. */
9467 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
9468 gimple_seq_add_stmt (&new_body,
9469 gimple_build_assign (ctx->receiver_decl, t));
9470 }
9471
9472 gimple_seq_add_seq (&new_body, par_ilist);
9473 gimple_seq_add_seq (&new_body, par_body);
9474 gimple_seq_add_seq (&new_body, par_rlist);
9475 if (ctx->cancellable)
9476 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
9477 gimple_seq_add_seq (&new_body, par_olist);
9478 new_body = maybe_catch_exception (new_body);
9479 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
9480 gimple_omp_set_body (stmt, new_body);
9481
9482 bind = gimple_build_bind (NULL, NULL, gimple_bind_block (par_bind));
9483 gsi_replace (gsi_p, dep_bind ? dep_bind : bind, true);
9484 gimple_bind_add_seq (bind, ilist);
9485 gimple_bind_add_stmt (bind, stmt);
9486 gimple_bind_add_seq (bind, olist);
9487
9488 pop_gimplify_context (NULL);
9489
9490 if (dep_bind)
9491 {
9492 gimple_bind_add_seq (dep_bind, dep_ilist);
9493 gimple_bind_add_stmt (dep_bind, bind);
9494 gimple_bind_add_seq (dep_bind, dep_olist);
9495 pop_gimplify_context (dep_bind);
9496 }
9497 }
9498
9499 /* Lower the OpenMP target directive in the current statement
9500 in GSI_P. CTX holds context information for the directive. */
9501
9502 static void
9503 lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9504 {
9505 tree clauses;
9506 tree child_fn, t, c;
9507 gimple stmt = gsi_stmt (*gsi_p);
9508 gimple tgt_bind = NULL, bind;
9509 gimple_seq tgt_body = NULL, olist, ilist, new_body;
9510 location_t loc = gimple_location (stmt);
9511 int kind = gimple_omp_target_kind (stmt);
9512 unsigned int map_cnt = 0;
9513
9514 clauses = gimple_omp_target_clauses (stmt);
9515 if (kind == GF_OMP_TARGET_KIND_REGION)
9516 {
9517 tgt_bind = gimple_seq_first_stmt (gimple_omp_body (stmt));
9518 tgt_body = gimple_bind_body (tgt_bind);
9519 }
9520 else if (kind == GF_OMP_TARGET_KIND_DATA)
9521 tgt_body = gimple_omp_body (stmt);
9522 child_fn = ctx->cb.dst_fn;
9523
9524 push_gimplify_context ();
9525
9526 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
9527 switch (OMP_CLAUSE_CODE (c))
9528 {
9529 tree var, x;
9530
9531 default:
9532 break;
9533 case OMP_CLAUSE_MAP:
9534 case OMP_CLAUSE_TO:
9535 case OMP_CLAUSE_FROM:
9536 var = OMP_CLAUSE_DECL (c);
9537 if (!DECL_P (var))
9538 {
9539 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP
9540 || !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
9541 map_cnt++;
9542 continue;
9543 }
9544
9545 if (DECL_SIZE (var)
9546 && TREE_CODE (DECL_SIZE (var)) != INTEGER_CST)
9547 {
9548 tree var2 = DECL_VALUE_EXPR (var);
9549 gcc_assert (TREE_CODE (var2) == INDIRECT_REF);
9550 var2 = TREE_OPERAND (var2, 0);
9551 gcc_assert (DECL_P (var2));
9552 var = var2;
9553 }
9554
9555 if (!maybe_lookup_field (var, ctx))
9556 continue;
9557
9558 if (kind == GF_OMP_TARGET_KIND_REGION)
9559 {
9560 x = build_receiver_ref (var, true, ctx);
9561 tree new_var = lookup_decl (var, ctx);
9562 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
9563 && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER
9564 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
9565 && TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
9566 x = build_simple_mem_ref (x);
9567 SET_DECL_VALUE_EXPR (new_var, x);
9568 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
9569 }
9570 map_cnt++;
9571 }
9572
9573 if (kind == GF_OMP_TARGET_KIND_REGION)
9574 {
9575 target_nesting_level++;
9576 lower_omp (&tgt_body, ctx);
9577 target_nesting_level--;
9578 }
9579 else if (kind == GF_OMP_TARGET_KIND_DATA)
9580 lower_omp (&tgt_body, ctx);
9581
9582 if (kind == GF_OMP_TARGET_KIND_REGION)
9583 {
9584 /* Declare all the variables created by mapping and the variables
9585 declared in the scope of the target body. */
9586 record_vars_into (ctx->block_vars, child_fn);
9587 record_vars_into (gimple_bind_vars (tgt_bind), child_fn);
9588 }
9589
9590 olist = NULL;
9591 ilist = NULL;
9592 if (ctx->record_type)
9593 {
9594 ctx->sender_decl
9595 = create_tmp_var (ctx->record_type, ".omp_data_arr");
9596 DECL_NAMELESS (ctx->sender_decl) = 1;
9597 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
9598 t = make_tree_vec (3);
9599 TREE_VEC_ELT (t, 0) = ctx->sender_decl;
9600 TREE_VEC_ELT (t, 1)
9601 = create_tmp_var (build_array_type_nelts (size_type_node, map_cnt),
9602 ".omp_data_sizes");
9603 DECL_NAMELESS (TREE_VEC_ELT (t, 1)) = 1;
9604 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 1)) = 1;
9605 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 1;
9606 TREE_VEC_ELT (t, 2)
9607 = create_tmp_var (build_array_type_nelts (unsigned_char_type_node,
9608 map_cnt),
9609 ".omp_data_kinds");
9610 DECL_NAMELESS (TREE_VEC_ELT (t, 2)) = 1;
9611 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 2)) = 1;
9612 TREE_STATIC (TREE_VEC_ELT (t, 2)) = 1;
9613 gimple_omp_target_set_data_arg (stmt, t);
9614
9615 vec<constructor_elt, va_gc> *vsize;
9616 vec<constructor_elt, va_gc> *vkind;
9617 vec_alloc (vsize, map_cnt);
9618 vec_alloc (vkind, map_cnt);
9619 unsigned int map_idx = 0;
9620
9621 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
9622 switch (OMP_CLAUSE_CODE (c))
9623 {
9624 tree ovar, nc;
9625
9626 default:
9627 break;
9628 case OMP_CLAUSE_MAP:
9629 case OMP_CLAUSE_TO:
9630 case OMP_CLAUSE_FROM:
9631 nc = c;
9632 ovar = OMP_CLAUSE_DECL (c);
9633 if (!DECL_P (ovar))
9634 {
9635 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
9636 && OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
9637 {
9638 gcc_checking_assert (OMP_CLAUSE_DECL (OMP_CLAUSE_CHAIN (c))
9639 == get_base_address (ovar));
9640 nc = OMP_CLAUSE_CHAIN (c);
9641 ovar = OMP_CLAUSE_DECL (nc);
9642 }
9643 else
9644 {
9645 tree x = build_sender_ref (ovar, ctx);
9646 tree v
9647 = build_fold_addr_expr_with_type (ovar, ptr_type_node);
9648 gimplify_assign (x, v, &ilist);
9649 nc = NULL_TREE;
9650 }
9651 }
9652 else
9653 {
9654 if (DECL_SIZE (ovar)
9655 && TREE_CODE (DECL_SIZE (ovar)) != INTEGER_CST)
9656 {
9657 tree ovar2 = DECL_VALUE_EXPR (ovar);
9658 gcc_assert (TREE_CODE (ovar2) == INDIRECT_REF);
9659 ovar2 = TREE_OPERAND (ovar2, 0);
9660 gcc_assert (DECL_P (ovar2));
9661 ovar = ovar2;
9662 }
9663 if (!maybe_lookup_field (ovar, ctx))
9664 continue;
9665 }
9666
9667 if (nc)
9668 {
9669 tree var = lookup_decl_in_outer_ctx (ovar, ctx);
9670 tree x = build_sender_ref (ovar, ctx);
9671 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
9672 && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER
9673 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
9674 && TREE_CODE (TREE_TYPE (ovar)) == ARRAY_TYPE)
9675 {
9676 gcc_assert (kind == GF_OMP_TARGET_KIND_REGION);
9677 tree avar
9678 = create_tmp_var (TREE_TYPE (TREE_TYPE (x)), NULL);
9679 mark_addressable (avar);
9680 gimplify_assign (avar, build_fold_addr_expr (var), &ilist);
9681 avar = build_fold_addr_expr (avar);
9682 gimplify_assign (x, avar, &ilist);
9683 }
9684 else if (is_gimple_reg (var))
9685 {
9686 gcc_assert (kind == GF_OMP_TARGET_KIND_REGION);
9687 tree avar = create_tmp_var (TREE_TYPE (var), NULL);
9688 mark_addressable (avar);
9689 if (OMP_CLAUSE_MAP_KIND (c) != OMP_CLAUSE_MAP_ALLOC
9690 && OMP_CLAUSE_MAP_KIND (c) != OMP_CLAUSE_MAP_FROM)
9691 gimplify_assign (avar, var, &ilist);
9692 avar = build_fold_addr_expr (avar);
9693 gimplify_assign (x, avar, &ilist);
9694 if ((OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_FROM
9695 || OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_TOFROM)
9696 && !TYPE_READONLY (TREE_TYPE (var)))
9697 {
9698 x = build_sender_ref (ovar, ctx);
9699 x = build_simple_mem_ref (x);
9700 gimplify_assign (var, x, &olist);
9701 }
9702 }
9703 else
9704 {
9705 var = build_fold_addr_expr (var);
9706 gimplify_assign (x, var, &ilist);
9707 }
9708 }
9709 tree s = OMP_CLAUSE_SIZE (c);
9710 if (s == NULL_TREE)
9711 s = TYPE_SIZE_UNIT (TREE_TYPE (ovar));
9712 s = fold_convert (size_type_node, s);
9713 tree purpose = size_int (map_idx++);
9714 CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
9715 if (TREE_CODE (s) != INTEGER_CST)
9716 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 0;
9717
9718 unsigned char tkind = 0;
9719 switch (OMP_CLAUSE_CODE (c))
9720 {
9721 case OMP_CLAUSE_MAP:
9722 tkind = OMP_CLAUSE_MAP_KIND (c);
9723 break;
9724 case OMP_CLAUSE_TO:
9725 tkind = OMP_CLAUSE_MAP_TO;
9726 break;
9727 case OMP_CLAUSE_FROM:
9728 tkind = OMP_CLAUSE_MAP_FROM;
9729 break;
9730 default:
9731 gcc_unreachable ();
9732 }
9733 unsigned int talign = TYPE_ALIGN_UNIT (TREE_TYPE (ovar));
9734 if (DECL_P (ovar) && DECL_ALIGN_UNIT (ovar) > talign)
9735 talign = DECL_ALIGN_UNIT (ovar);
9736 talign = ceil_log2 (talign);
9737 tkind |= talign << 3;
9738 CONSTRUCTOR_APPEND_ELT (vkind, purpose,
9739 build_int_cst (unsigned_char_type_node,
9740 tkind));
9741 if (nc && nc != c)
9742 c = nc;
9743 }
9744
9745 gcc_assert (map_idx == map_cnt);
9746
9747 DECL_INITIAL (TREE_VEC_ELT (t, 1))
9748 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)), vsize);
9749 DECL_INITIAL (TREE_VEC_ELT (t, 2))
9750 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 2)), vkind);
9751 if (!TREE_STATIC (TREE_VEC_ELT (t, 1)))
9752 {
9753 gimple_seq initlist = NULL;
9754 force_gimple_operand (build1 (DECL_EXPR, void_type_node,
9755 TREE_VEC_ELT (t, 1)),
9756 &initlist, true, NULL_TREE);
9757 gimple_seq_add_seq (&ilist, initlist);
9758 }
9759
9760 tree clobber = build_constructor (ctx->record_type, NULL);
9761 TREE_THIS_VOLATILE (clobber) = 1;
9762 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
9763 clobber));
9764 }
9765
9766 /* Once all the expansions are done, sequence all the different
9767 fragments inside gimple_omp_body. */
9768
9769 new_body = NULL;
9770
9771 if (ctx->record_type && kind == GF_OMP_TARGET_KIND_REGION)
9772 {
9773 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
9774 /* fixup_child_record_type might have changed receiver_decl's type. */
9775 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
9776 gimple_seq_add_stmt (&new_body,
9777 gimple_build_assign (ctx->receiver_decl, t));
9778 }
9779
9780 if (kind == GF_OMP_TARGET_KIND_REGION)
9781 {
9782 gimple_seq_add_seq (&new_body, tgt_body);
9783 new_body = maybe_catch_exception (new_body);
9784 }
9785 else if (kind == GF_OMP_TARGET_KIND_DATA)
9786 new_body = tgt_body;
9787 if (kind != GF_OMP_TARGET_KIND_UPDATE)
9788 {
9789 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
9790 gimple_omp_set_body (stmt, new_body);
9791 }
9792
9793 bind = gimple_build_bind (NULL, NULL,
9794 tgt_bind ? gimple_bind_block (tgt_bind)
9795 : NULL_TREE);
9796 gsi_replace (gsi_p, bind, true);
9797 gimple_bind_add_seq (bind, ilist);
9798 gimple_bind_add_stmt (bind, stmt);
9799 gimple_bind_add_seq (bind, olist);
9800
9801 pop_gimplify_context (NULL);
9802 }
9803
9804 /* Expand code for an OpenMP teams directive. */
9805
9806 static void
9807 lower_omp_teams (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9808 {
9809 gimple teams_stmt = gsi_stmt (*gsi_p);
9810 push_gimplify_context ();
9811
9812 tree block = make_node (BLOCK);
9813 gimple bind = gimple_build_bind (NULL, NULL, block);
9814 gsi_replace (gsi_p, bind, true);
9815 gimple_seq bind_body = NULL;
9816 gimple_seq dlist = NULL;
9817 gimple_seq olist = NULL;
9818
9819 tree num_teams = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
9820 OMP_CLAUSE_NUM_TEAMS);
9821 if (num_teams == NULL_TREE)
9822 num_teams = build_int_cst (unsigned_type_node, 0);
9823 else
9824 {
9825 num_teams = OMP_CLAUSE_NUM_TEAMS_EXPR (num_teams);
9826 num_teams = fold_convert (unsigned_type_node, num_teams);
9827 gimplify_expr (&num_teams, &bind_body, NULL, is_gimple_val, fb_rvalue);
9828 }
9829 tree thread_limit = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
9830 OMP_CLAUSE_THREAD_LIMIT);
9831 if (thread_limit == NULL_TREE)
9832 thread_limit = build_int_cst (unsigned_type_node, 0);
9833 else
9834 {
9835 thread_limit = OMP_CLAUSE_THREAD_LIMIT_EXPR (thread_limit);
9836 thread_limit = fold_convert (unsigned_type_node, thread_limit);
9837 gimplify_expr (&thread_limit, &bind_body, NULL, is_gimple_val,
9838 fb_rvalue);
9839 }
9840
9841 lower_rec_input_clauses (gimple_omp_teams_clauses (teams_stmt),
9842 &bind_body, &dlist, ctx, NULL);
9843 lower_omp (gimple_omp_body_ptr (teams_stmt), ctx);
9844 lower_reduction_clauses (gimple_omp_teams_clauses (teams_stmt), &olist, ctx);
9845 gimple_seq_add_stmt (&bind_body, teams_stmt);
9846
9847 location_t loc = gimple_location (teams_stmt);
9848 tree decl = builtin_decl_explicit (BUILT_IN_GOMP_TEAMS);
9849 gimple call = gimple_build_call (decl, 2, num_teams, thread_limit);
9850 gimple_set_location (call, loc);
9851 gimple_seq_add_stmt (&bind_body, call);
9852
9853 gimple_seq_add_seq (&bind_body, gimple_omp_body (teams_stmt));
9854 gimple_omp_set_body (teams_stmt, NULL);
9855 gimple_seq_add_seq (&bind_body, olist);
9856 gimple_seq_add_seq (&bind_body, dlist);
9857 gimple_seq_add_stmt (&bind_body, gimple_build_omp_return (true));
9858 gimple_bind_set_body (bind, bind_body);
9859
9860 pop_gimplify_context (bind);
9861
9862 gimple_bind_append_vars (bind, ctx->block_vars);
9863 BLOCK_VARS (block) = ctx->block_vars;
9864 if (BLOCK_VARS (block))
9865 TREE_USED (block) = 1;
9866 }
9867
9868
9869 /* Callback for lower_omp_1. Return non-NULL if *tp needs to be
9870 regimplified. If DATA is non-NULL, lower_omp_1 is outside
9871 of OpenMP context, but with task_shared_vars set. */
9872
9873 static tree
9874 lower_omp_regimplify_p (tree *tp, int *walk_subtrees,
9875 void *data)
9876 {
9877 tree t = *tp;
9878
9879 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
9880 if (TREE_CODE (t) == VAR_DECL && data == NULL && DECL_HAS_VALUE_EXPR_P (t))
9881 return t;
9882
9883 if (task_shared_vars
9884 && DECL_P (t)
9885 && bitmap_bit_p (task_shared_vars, DECL_UID (t)))
9886 return t;
9887
9888 /* If a global variable has been privatized, TREE_CONSTANT on
9889 ADDR_EXPR might be wrong. */
9890 if (data == NULL && TREE_CODE (t) == ADDR_EXPR)
9891 recompute_tree_invariant_for_addr_expr (t);
9892
9893 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
9894 return NULL_TREE;
9895 }
9896
9897 static void
9898 lower_omp_1 (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9899 {
9900 gimple stmt = gsi_stmt (*gsi_p);
9901 struct walk_stmt_info wi;
9902
9903 if (gimple_has_location (stmt))
9904 input_location = gimple_location (stmt);
9905
9906 if (task_shared_vars)
9907 memset (&wi, '\0', sizeof (wi));
9908
9909 /* If we have issued syntax errors, avoid doing any heavy lifting.
9910 Just replace the OpenMP directives with a NOP to avoid
9911 confusing RTL expansion. */
9912 if (seen_error () && is_gimple_omp (stmt))
9913 {
9914 gsi_replace (gsi_p, gimple_build_nop (), true);
9915 return;
9916 }
9917
9918 switch (gimple_code (stmt))
9919 {
9920 case GIMPLE_COND:
9921 if ((ctx || task_shared_vars)
9922 && (walk_tree (gimple_cond_lhs_ptr (stmt), lower_omp_regimplify_p,
9923 ctx ? NULL : &wi, NULL)
9924 || walk_tree (gimple_cond_rhs_ptr (stmt), lower_omp_regimplify_p,
9925 ctx ? NULL : &wi, NULL)))
9926 gimple_regimplify_operands (stmt, gsi_p);
9927 break;
9928 case GIMPLE_CATCH:
9929 lower_omp (gimple_catch_handler_ptr (stmt), ctx);
9930 break;
9931 case GIMPLE_EH_FILTER:
9932 lower_omp (gimple_eh_filter_failure_ptr (stmt), ctx);
9933 break;
9934 case GIMPLE_TRY:
9935 lower_omp (gimple_try_eval_ptr (stmt), ctx);
9936 lower_omp (gimple_try_cleanup_ptr (stmt), ctx);
9937 break;
9938 case GIMPLE_TRANSACTION:
9939 lower_omp (gimple_transaction_body_ptr (stmt), ctx);
9940 break;
9941 case GIMPLE_BIND:
9942 lower_omp (gimple_bind_body_ptr (stmt), ctx);
9943 break;
9944 case GIMPLE_OMP_PARALLEL:
9945 case GIMPLE_OMP_TASK:
9946 ctx = maybe_lookup_ctx (stmt);
9947 gcc_assert (ctx);
9948 if (ctx->cancellable)
9949 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
9950 lower_omp_taskreg (gsi_p, ctx);
9951 break;
9952 case GIMPLE_OMP_FOR:
9953 ctx = maybe_lookup_ctx (stmt);
9954 gcc_assert (ctx);
9955 if (ctx->cancellable)
9956 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
9957 lower_omp_for (gsi_p, ctx);
9958 break;
9959 case GIMPLE_OMP_SECTIONS:
9960 ctx = maybe_lookup_ctx (stmt);
9961 gcc_assert (ctx);
9962 if (ctx->cancellable)
9963 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
9964 lower_omp_sections (gsi_p, ctx);
9965 break;
9966 case GIMPLE_OMP_SINGLE:
9967 ctx = maybe_lookup_ctx (stmt);
9968 gcc_assert (ctx);
9969 lower_omp_single (gsi_p, ctx);
9970 break;
9971 case GIMPLE_OMP_MASTER:
9972 ctx = maybe_lookup_ctx (stmt);
9973 gcc_assert (ctx);
9974 lower_omp_master (gsi_p, ctx);
9975 break;
9976 case GIMPLE_OMP_TASKGROUP:
9977 ctx = maybe_lookup_ctx (stmt);
9978 gcc_assert (ctx);
9979 lower_omp_taskgroup (gsi_p, ctx);
9980 break;
9981 case GIMPLE_OMP_ORDERED:
9982 ctx = maybe_lookup_ctx (stmt);
9983 gcc_assert (ctx);
9984 lower_omp_ordered (gsi_p, ctx);
9985 break;
9986 case GIMPLE_OMP_CRITICAL:
9987 ctx = maybe_lookup_ctx (stmt);
9988 gcc_assert (ctx);
9989 lower_omp_critical (gsi_p, ctx);
9990 break;
9991 case GIMPLE_OMP_ATOMIC_LOAD:
9992 if ((ctx || task_shared_vars)
9993 && walk_tree (gimple_omp_atomic_load_rhs_ptr (stmt),
9994 lower_omp_regimplify_p, ctx ? NULL : &wi, NULL))
9995 gimple_regimplify_operands (stmt, gsi_p);
9996 break;
9997 case GIMPLE_OMP_TARGET:
9998 ctx = maybe_lookup_ctx (stmt);
9999 gcc_assert (ctx);
10000 lower_omp_target (gsi_p, ctx);
10001 break;
10002 case GIMPLE_OMP_TEAMS:
10003 ctx = maybe_lookup_ctx (stmt);
10004 gcc_assert (ctx);
10005 lower_omp_teams (gsi_p, ctx);
10006 break;
10007 case GIMPLE_CALL:
10008 tree fndecl;
10009 fndecl = gimple_call_fndecl (stmt);
10010 if (fndecl
10011 && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
10012 switch (DECL_FUNCTION_CODE (fndecl))
10013 {
10014 case BUILT_IN_GOMP_BARRIER:
10015 if (ctx == NULL)
10016 break;
10017 /* FALLTHRU */
10018 case BUILT_IN_GOMP_CANCEL:
10019 case BUILT_IN_GOMP_CANCELLATION_POINT:
10020 omp_context *cctx;
10021 cctx = ctx;
10022 if (gimple_code (cctx->stmt) == GIMPLE_OMP_SECTION)
10023 cctx = cctx->outer;
10024 gcc_assert (gimple_call_lhs (stmt) == NULL_TREE);
10025 if (!cctx->cancellable)
10026 {
10027 if (DECL_FUNCTION_CODE (fndecl)
10028 == BUILT_IN_GOMP_CANCELLATION_POINT)
10029 {
10030 stmt = gimple_build_nop ();
10031 gsi_replace (gsi_p, stmt, false);
10032 }
10033 break;
10034 }
10035 tree lhs;
10036 lhs = create_tmp_var (boolean_type_node, NULL);
10037 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_GOMP_BARRIER)
10038 {
10039 fndecl = builtin_decl_explicit (BUILT_IN_GOMP_BARRIER_CANCEL);
10040 gimple_call_set_fndecl (stmt, fndecl);
10041 gimple_call_set_fntype (stmt, TREE_TYPE (fndecl));
10042 }
10043 gimple_call_set_lhs (stmt, lhs);
10044 tree fallthru_label;
10045 fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
10046 gimple g;
10047 g = gimple_build_label (fallthru_label);
10048 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
10049 g = gimple_build_cond (NE_EXPR, lhs, boolean_false_node,
10050 cctx->cancel_label, fallthru_label);
10051 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
10052 break;
10053 default:
10054 break;
10055 }
10056 /* FALLTHRU */
10057 default:
10058 if ((ctx || task_shared_vars)
10059 && walk_gimple_op (stmt, lower_omp_regimplify_p,
10060 ctx ? NULL : &wi))
10061 gimple_regimplify_operands (stmt, gsi_p);
10062 break;
10063 }
10064 }
10065
10066 static void
10067 lower_omp (gimple_seq *body, omp_context *ctx)
10068 {
10069 location_t saved_location = input_location;
10070 gimple_stmt_iterator gsi;
10071 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
10072 lower_omp_1 (&gsi, ctx);
10073 /* Inside target region we haven't called fold_stmt during gimplification,
10074 because it can break code by adding decl references that weren't in the
10075 source. Call fold_stmt now. */
10076 if (target_nesting_level)
10077 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
10078 fold_stmt (&gsi);
10079 input_location = saved_location;
10080 }
10081 \f
10082 /* Main entry point. */
10083
10084 static unsigned int
10085 execute_lower_omp (void)
10086 {
10087 gimple_seq body;
10088
10089 /* This pass always runs, to provide PROP_gimple_lomp.
10090 But there is nothing to do unless -fopenmp is given. */
10091 if (flag_openmp == 0 && flag_openmp_simd == 0 && flag_enable_cilkplus == 0)
10092 return 0;
10093
10094 all_contexts = splay_tree_new (splay_tree_compare_pointers, 0,
10095 delete_omp_context);
10096
10097 body = gimple_body (current_function_decl);
10098 scan_omp (&body, NULL);
10099 gcc_assert (taskreg_nesting_level == 0);
10100
10101 if (all_contexts->root)
10102 {
10103 if (task_shared_vars)
10104 push_gimplify_context ();
10105 lower_omp (&body, NULL);
10106 if (task_shared_vars)
10107 pop_gimplify_context (NULL);
10108 }
10109
10110 if (all_contexts)
10111 {
10112 splay_tree_delete (all_contexts);
10113 all_contexts = NULL;
10114 }
10115 BITMAP_FREE (task_shared_vars);
10116 return 0;
10117 }
10118
10119 namespace {
10120
10121 const pass_data pass_data_lower_omp =
10122 {
10123 GIMPLE_PASS, /* type */
10124 "omplower", /* name */
10125 OPTGROUP_NONE, /* optinfo_flags */
10126 false, /* has_gate */
10127 true, /* has_execute */
10128 TV_NONE, /* tv_id */
10129 PROP_gimple_any, /* properties_required */
10130 PROP_gimple_lomp, /* properties_provided */
10131 0, /* properties_destroyed */
10132 0, /* todo_flags_start */
10133 0, /* todo_flags_finish */
10134 };
10135
10136 class pass_lower_omp : public gimple_opt_pass
10137 {
10138 public:
10139 pass_lower_omp (gcc::context *ctxt)
10140 : gimple_opt_pass (pass_data_lower_omp, ctxt)
10141 {}
10142
10143 /* opt_pass methods: */
10144 unsigned int execute () { return execute_lower_omp (); }
10145
10146 }; // class pass_lower_omp
10147
10148 } // anon namespace
10149
10150 gimple_opt_pass *
10151 make_pass_lower_omp (gcc::context *ctxt)
10152 {
10153 return new pass_lower_omp (ctxt);
10154 }
10155 \f
10156 /* The following is a utility to diagnose OpenMP structured block violations.
10157 It is not part of the "omplower" pass, as that's invoked too late. It
10158 should be invoked by the respective front ends after gimplification. */
10159
10160 static splay_tree all_labels;
10161
10162 /* Check for mismatched contexts and generate an error if needed. Return
10163 true if an error is detected. */
10164
10165 static bool
10166 diagnose_sb_0 (gimple_stmt_iterator *gsi_p,
10167 gimple branch_ctx, gimple label_ctx)
10168 {
10169 if (label_ctx == branch_ctx)
10170 return false;
10171
10172
10173 /*
10174 Previously we kept track of the label's entire context in diagnose_sb_[12]
10175 so we could traverse it and issue a correct "exit" or "enter" error
10176 message upon a structured block violation.
10177
10178 We built the context by building a list with tree_cons'ing, but there is
10179 no easy counterpart in gimple tuples. It seems like far too much work
10180 for issuing exit/enter error messages. If someone really misses the
10181 distinct error message... patches welcome.
10182 */
10183
10184 #if 0
10185 /* Try to avoid confusing the user by producing and error message
10186 with correct "exit" or "enter" verbiage. We prefer "exit"
10187 unless we can show that LABEL_CTX is nested within BRANCH_CTX. */
10188 if (branch_ctx == NULL)
10189 exit_p = false;
10190 else
10191 {
10192 while (label_ctx)
10193 {
10194 if (TREE_VALUE (label_ctx) == branch_ctx)
10195 {
10196 exit_p = false;
10197 break;
10198 }
10199 label_ctx = TREE_CHAIN (label_ctx);
10200 }
10201 }
10202
10203 if (exit_p)
10204 error ("invalid exit from OpenMP structured block");
10205 else
10206 error ("invalid entry to OpenMP structured block");
10207 #endif
10208
10209 bool cilkplus_block = false;
10210 if (flag_enable_cilkplus)
10211 {
10212 if ((branch_ctx
10213 && gimple_code (branch_ctx) == GIMPLE_OMP_FOR
10214 && gimple_omp_for_kind (branch_ctx) == GF_OMP_FOR_KIND_CILKSIMD)
10215 || (gimple_code (label_ctx) == GIMPLE_OMP_FOR
10216 && gimple_omp_for_kind (label_ctx) == GF_OMP_FOR_KIND_CILKSIMD))
10217 cilkplus_block = true;
10218 }
10219
10220 /* If it's obvious we have an invalid entry, be specific about the error. */
10221 if (branch_ctx == NULL)
10222 {
10223 if (cilkplus_block)
10224 error ("invalid entry to Cilk Plus structured block");
10225 else
10226 error ("invalid entry to OpenMP structured block");
10227 }
10228 else
10229 {
10230 /* Otherwise, be vague and lazy, but efficient. */
10231 if (cilkplus_block)
10232 error ("invalid branch to/from a Cilk Plus structured block");
10233 else
10234 error ("invalid branch to/from an OpenMP structured block");
10235 }
10236
10237 gsi_replace (gsi_p, gimple_build_nop (), false);
10238 return true;
10239 }
10240
10241 /* Pass 1: Create a minimal tree of OpenMP structured blocks, and record
10242 where each label is found. */
10243
10244 static tree
10245 diagnose_sb_1 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
10246 struct walk_stmt_info *wi)
10247 {
10248 gimple context = (gimple) wi->info;
10249 gimple inner_context;
10250 gimple stmt = gsi_stmt (*gsi_p);
10251
10252 *handled_ops_p = true;
10253
10254 switch (gimple_code (stmt))
10255 {
10256 WALK_SUBSTMTS;
10257
10258 case GIMPLE_OMP_PARALLEL:
10259 case GIMPLE_OMP_TASK:
10260 case GIMPLE_OMP_SECTIONS:
10261 case GIMPLE_OMP_SINGLE:
10262 case GIMPLE_OMP_SECTION:
10263 case GIMPLE_OMP_MASTER:
10264 case GIMPLE_OMP_ORDERED:
10265 case GIMPLE_OMP_CRITICAL:
10266 case GIMPLE_OMP_TARGET:
10267 case GIMPLE_OMP_TEAMS:
10268 case GIMPLE_OMP_TASKGROUP:
10269 /* The minimal context here is just the current OMP construct. */
10270 inner_context = stmt;
10271 wi->info = inner_context;
10272 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
10273 wi->info = context;
10274 break;
10275
10276 case GIMPLE_OMP_FOR:
10277 inner_context = stmt;
10278 wi->info = inner_context;
10279 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
10280 walk them. */
10281 walk_gimple_seq (gimple_omp_for_pre_body (stmt),
10282 diagnose_sb_1, NULL, wi);
10283 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
10284 wi->info = context;
10285 break;
10286
10287 case GIMPLE_LABEL:
10288 splay_tree_insert (all_labels, (splay_tree_key) gimple_label_label (stmt),
10289 (splay_tree_value) context);
10290 break;
10291
10292 default:
10293 break;
10294 }
10295
10296 return NULL_TREE;
10297 }
10298
10299 /* Pass 2: Check each branch and see if its context differs from that of
10300 the destination label's context. */
10301
10302 static tree
10303 diagnose_sb_2 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
10304 struct walk_stmt_info *wi)
10305 {
10306 gimple context = (gimple) wi->info;
10307 splay_tree_node n;
10308 gimple stmt = gsi_stmt (*gsi_p);
10309
10310 *handled_ops_p = true;
10311
10312 switch (gimple_code (stmt))
10313 {
10314 WALK_SUBSTMTS;
10315
10316 case GIMPLE_OMP_PARALLEL:
10317 case GIMPLE_OMP_TASK:
10318 case GIMPLE_OMP_SECTIONS:
10319 case GIMPLE_OMP_SINGLE:
10320 case GIMPLE_OMP_SECTION:
10321 case GIMPLE_OMP_MASTER:
10322 case GIMPLE_OMP_ORDERED:
10323 case GIMPLE_OMP_CRITICAL:
10324 case GIMPLE_OMP_TARGET:
10325 case GIMPLE_OMP_TEAMS:
10326 case GIMPLE_OMP_TASKGROUP:
10327 wi->info = stmt;
10328 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
10329 wi->info = context;
10330 break;
10331
10332 case GIMPLE_OMP_FOR:
10333 wi->info = stmt;
10334 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
10335 walk them. */
10336 walk_gimple_seq_mod (gimple_omp_for_pre_body_ptr (stmt),
10337 diagnose_sb_2, NULL, wi);
10338 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
10339 wi->info = context;
10340 break;
10341
10342 case GIMPLE_COND:
10343 {
10344 tree lab = gimple_cond_true_label (stmt);
10345 if (lab)
10346 {
10347 n = splay_tree_lookup (all_labels,
10348 (splay_tree_key) lab);
10349 diagnose_sb_0 (gsi_p, context,
10350 n ? (gimple) n->value : NULL);
10351 }
10352 lab = gimple_cond_false_label (stmt);
10353 if (lab)
10354 {
10355 n = splay_tree_lookup (all_labels,
10356 (splay_tree_key) lab);
10357 diagnose_sb_0 (gsi_p, context,
10358 n ? (gimple) n->value : NULL);
10359 }
10360 }
10361 break;
10362
10363 case GIMPLE_GOTO:
10364 {
10365 tree lab = gimple_goto_dest (stmt);
10366 if (TREE_CODE (lab) != LABEL_DECL)
10367 break;
10368
10369 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
10370 diagnose_sb_0 (gsi_p, context, n ? (gimple) n->value : NULL);
10371 }
10372 break;
10373
10374 case GIMPLE_SWITCH:
10375 {
10376 unsigned int i;
10377 for (i = 0; i < gimple_switch_num_labels (stmt); ++i)
10378 {
10379 tree lab = CASE_LABEL (gimple_switch_label (stmt, i));
10380 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
10381 if (n && diagnose_sb_0 (gsi_p, context, (gimple) n->value))
10382 break;
10383 }
10384 }
10385 break;
10386
10387 case GIMPLE_RETURN:
10388 diagnose_sb_0 (gsi_p, context, NULL);
10389 break;
10390
10391 default:
10392 break;
10393 }
10394
10395 return NULL_TREE;
10396 }
10397
10398 /* Called from tree-cfg.c::make_edges to create cfg edges for all GIMPLE_OMP
10399 codes. */
10400 bool
10401 make_gimple_omp_edges (basic_block bb, struct omp_region **region)
10402 {
10403 gimple last = last_stmt (bb);
10404 enum gimple_code code = gimple_code (last);
10405 struct omp_region *cur_region = *region;
10406 bool fallthru = false;
10407
10408 switch (code)
10409 {
10410 case GIMPLE_OMP_PARALLEL:
10411 case GIMPLE_OMP_TASK:
10412 case GIMPLE_OMP_FOR:
10413 case GIMPLE_OMP_SINGLE:
10414 case GIMPLE_OMP_TEAMS:
10415 case GIMPLE_OMP_MASTER:
10416 case GIMPLE_OMP_TASKGROUP:
10417 case GIMPLE_OMP_ORDERED:
10418 case GIMPLE_OMP_CRITICAL:
10419 case GIMPLE_OMP_SECTION:
10420 cur_region = new_omp_region (bb, code, cur_region);
10421 fallthru = true;
10422 break;
10423
10424 case GIMPLE_OMP_TARGET:
10425 cur_region = new_omp_region (bb, code, cur_region);
10426 fallthru = true;
10427 if (gimple_omp_target_kind (last) == GF_OMP_TARGET_KIND_UPDATE)
10428 cur_region = cur_region->outer;
10429 break;
10430
10431 case GIMPLE_OMP_SECTIONS:
10432 cur_region = new_omp_region (bb, code, cur_region);
10433 fallthru = true;
10434 break;
10435
10436 case GIMPLE_OMP_SECTIONS_SWITCH:
10437 fallthru = false;
10438 break;
10439
10440 case GIMPLE_OMP_ATOMIC_LOAD:
10441 case GIMPLE_OMP_ATOMIC_STORE:
10442 fallthru = true;
10443 break;
10444
10445 case GIMPLE_OMP_RETURN:
10446 /* In the case of a GIMPLE_OMP_SECTION, the edge will go
10447 somewhere other than the next block. This will be
10448 created later. */
10449 cur_region->exit = bb;
10450 fallthru = cur_region->type != GIMPLE_OMP_SECTION;
10451 cur_region = cur_region->outer;
10452 break;
10453
10454 case GIMPLE_OMP_CONTINUE:
10455 cur_region->cont = bb;
10456 switch (cur_region->type)
10457 {
10458 case GIMPLE_OMP_FOR:
10459 /* Mark all GIMPLE_OMP_FOR and GIMPLE_OMP_CONTINUE
10460 succs edges as abnormal to prevent splitting
10461 them. */
10462 single_succ_edge (cur_region->entry)->flags |= EDGE_ABNORMAL;
10463 /* Make the loopback edge. */
10464 make_edge (bb, single_succ (cur_region->entry),
10465 EDGE_ABNORMAL);
10466
10467 /* Create an edge from GIMPLE_OMP_FOR to exit, which
10468 corresponds to the case that the body of the loop
10469 is not executed at all. */
10470 make_edge (cur_region->entry, bb->next_bb, EDGE_ABNORMAL);
10471 make_edge (bb, bb->next_bb, EDGE_FALLTHRU | EDGE_ABNORMAL);
10472 fallthru = false;
10473 break;
10474
10475 case GIMPLE_OMP_SECTIONS:
10476 /* Wire up the edges into and out of the nested sections. */
10477 {
10478 basic_block switch_bb = single_succ (cur_region->entry);
10479
10480 struct omp_region *i;
10481 for (i = cur_region->inner; i ; i = i->next)
10482 {
10483 gcc_assert (i->type == GIMPLE_OMP_SECTION);
10484 make_edge (switch_bb, i->entry, 0);
10485 make_edge (i->exit, bb, EDGE_FALLTHRU);
10486 }
10487
10488 /* Make the loopback edge to the block with
10489 GIMPLE_OMP_SECTIONS_SWITCH. */
10490 make_edge (bb, switch_bb, 0);
10491
10492 /* Make the edge from the switch to exit. */
10493 make_edge (switch_bb, bb->next_bb, 0);
10494 fallthru = false;
10495 }
10496 break;
10497
10498 default:
10499 gcc_unreachable ();
10500 }
10501 break;
10502
10503 default:
10504 gcc_unreachable ();
10505 }
10506
10507 if (*region != cur_region)
10508 *region = cur_region;
10509
10510 return fallthru;
10511 }
10512
10513 static unsigned int
10514 diagnose_omp_structured_block_errors (void)
10515 {
10516 struct walk_stmt_info wi;
10517 gimple_seq body = gimple_body (current_function_decl);
10518
10519 all_labels = splay_tree_new (splay_tree_compare_pointers, 0, 0);
10520
10521 memset (&wi, 0, sizeof (wi));
10522 walk_gimple_seq (body, diagnose_sb_1, NULL, &wi);
10523
10524 memset (&wi, 0, sizeof (wi));
10525 wi.want_locations = true;
10526 walk_gimple_seq_mod (&body, diagnose_sb_2, NULL, &wi);
10527
10528 gimple_set_body (current_function_decl, body);
10529
10530 splay_tree_delete (all_labels);
10531 all_labels = NULL;
10532
10533 return 0;
10534 }
10535
10536 static bool
10537 gate_diagnose_omp_blocks (void)
10538 {
10539 return flag_openmp || flag_enable_cilkplus;
10540 }
10541
10542 namespace {
10543
10544 const pass_data pass_data_diagnose_omp_blocks =
10545 {
10546 GIMPLE_PASS, /* type */
10547 "*diagnose_omp_blocks", /* name */
10548 OPTGROUP_NONE, /* optinfo_flags */
10549 true, /* has_gate */
10550 true, /* has_execute */
10551 TV_NONE, /* tv_id */
10552 PROP_gimple_any, /* properties_required */
10553 0, /* properties_provided */
10554 0, /* properties_destroyed */
10555 0, /* todo_flags_start */
10556 0, /* todo_flags_finish */
10557 };
10558
10559 class pass_diagnose_omp_blocks : public gimple_opt_pass
10560 {
10561 public:
10562 pass_diagnose_omp_blocks (gcc::context *ctxt)
10563 : gimple_opt_pass (pass_data_diagnose_omp_blocks, ctxt)
10564 {}
10565
10566 /* opt_pass methods: */
10567 bool gate () { return gate_diagnose_omp_blocks (); }
10568 unsigned int execute () {
10569 return diagnose_omp_structured_block_errors ();
10570 }
10571
10572 }; // class pass_diagnose_omp_blocks
10573
10574 } // anon namespace
10575
10576 gimple_opt_pass *
10577 make_pass_diagnose_omp_blocks (gcc::context *ctxt)
10578 {
10579 return new pass_diagnose_omp_blocks (ctxt);
10580 }
10581
10582 #include "gt-omp-low.h"