gimple.h: Remove all includes.
[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 loop->latch = cont_bb;
6495 add_loop (loop, trip_loop);
6496 }
6497 }
6498 }
6499
6500
6501 /* A subroutine of expand_omp_for. Generate code for a simd non-worksharing
6502 loop. Given parameters:
6503
6504 for (V = N1; V cond N2; V += STEP) BODY;
6505
6506 where COND is "<" or ">", we generate pseudocode
6507
6508 V = N1;
6509 goto L1;
6510 L0:
6511 BODY;
6512 V += STEP;
6513 L1:
6514 if (V cond N2) goto L0; else goto L2;
6515 L2:
6516
6517 For collapsed loops, given parameters:
6518 collapse(3)
6519 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
6520 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
6521 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
6522 BODY;
6523
6524 we generate pseudocode
6525
6526 if (cond3 is <)
6527 adj = STEP3 - 1;
6528 else
6529 adj = STEP3 + 1;
6530 count3 = (adj + N32 - N31) / STEP3;
6531 if (cond2 is <)
6532 adj = STEP2 - 1;
6533 else
6534 adj = STEP2 + 1;
6535 count2 = (adj + N22 - N21) / STEP2;
6536 if (cond1 is <)
6537 adj = STEP1 - 1;
6538 else
6539 adj = STEP1 + 1;
6540 count1 = (adj + N12 - N11) / STEP1;
6541 count = count1 * count2 * count3;
6542 V = 0;
6543 V1 = N11;
6544 V2 = N21;
6545 V3 = N31;
6546 goto L1;
6547 L0:
6548 BODY;
6549 V += 1;
6550 V3 += STEP3;
6551 V2 += (V3 cond3 N32) ? 0 : STEP2;
6552 V3 = (V3 cond3 N32) ? V3 : N31;
6553 V1 += (V2 cond2 N22) ? 0 : STEP1;
6554 V2 = (V2 cond2 N22) ? V2 : N21;
6555 L1:
6556 if (V < count) goto L0; else goto L2;
6557 L2:
6558
6559 */
6560
6561 static void
6562 expand_omp_simd (struct omp_region *region, struct omp_for_data *fd)
6563 {
6564 tree type, t;
6565 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, l2_bb, l2_dom_bb;
6566 gimple_stmt_iterator gsi;
6567 gimple stmt;
6568 bool broken_loop = region->cont == NULL;
6569 edge e, ne;
6570 tree *counts = NULL;
6571 int i;
6572 tree safelen = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
6573 OMP_CLAUSE_SAFELEN);
6574 tree simduid = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
6575 OMP_CLAUSE__SIMDUID_);
6576 tree n1, n2;
6577
6578 type = TREE_TYPE (fd->loop.v);
6579 entry_bb = region->entry;
6580 cont_bb = region->cont;
6581 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
6582 gcc_assert (broken_loop
6583 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
6584 l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
6585 if (!broken_loop)
6586 {
6587 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
6588 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
6589 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
6590 l2_bb = BRANCH_EDGE (entry_bb)->dest;
6591 }
6592 else
6593 {
6594 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
6595 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
6596 l2_bb = single_succ (l1_bb);
6597 }
6598 exit_bb = region->exit;
6599 l2_dom_bb = NULL;
6600
6601 gsi = gsi_last_bb (entry_bb);
6602
6603 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6604 /* Not needed in SSA form right now. */
6605 gcc_assert (!gimple_in_ssa_p (cfun));
6606 if (fd->collapse > 1)
6607 {
6608 int first_zero_iter = -1;
6609 basic_block zero_iter_bb = l2_bb;
6610
6611 counts = XALLOCAVEC (tree, fd->collapse);
6612 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
6613 zero_iter_bb, first_zero_iter,
6614 l2_dom_bb);
6615 }
6616 if (l2_dom_bb == NULL)
6617 l2_dom_bb = l1_bb;
6618
6619 n1 = fd->loop.n1;
6620 n2 = fd->loop.n2;
6621 if (gimple_omp_for_combined_into_p (fd->for_stmt))
6622 {
6623 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
6624 OMP_CLAUSE__LOOPTEMP_);
6625 gcc_assert (innerc);
6626 n1 = OMP_CLAUSE_DECL (innerc);
6627 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6628 OMP_CLAUSE__LOOPTEMP_);
6629 gcc_assert (innerc);
6630 n2 = OMP_CLAUSE_DECL (innerc);
6631 expand_omp_build_assign (&gsi, fd->loop.v,
6632 fold_convert (type, n1));
6633 if (fd->collapse > 1)
6634 {
6635 gsi_prev (&gsi);
6636 expand_omp_for_init_vars (fd, &gsi, counts, NULL, n1);
6637 gsi_next (&gsi);
6638 }
6639 }
6640 else
6641 {
6642 expand_omp_build_assign (&gsi, fd->loop.v,
6643 fold_convert (type, fd->loop.n1));
6644 if (fd->collapse > 1)
6645 for (i = 0; i < fd->collapse; i++)
6646 {
6647 tree itype = TREE_TYPE (fd->loops[i].v);
6648 if (POINTER_TYPE_P (itype))
6649 itype = signed_type_for (itype);
6650 t = fold_convert (TREE_TYPE (fd->loops[i].v), fd->loops[i].n1);
6651 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
6652 }
6653 }
6654
6655 /* Remove the GIMPLE_OMP_FOR statement. */
6656 gsi_remove (&gsi, true);
6657
6658 if (!broken_loop)
6659 {
6660 /* Code to control the increment goes in the CONT_BB. */
6661 gsi = gsi_last_bb (cont_bb);
6662 stmt = gsi_stmt (gsi);
6663 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
6664
6665 if (POINTER_TYPE_P (type))
6666 t = fold_build_pointer_plus (fd->loop.v, fd->loop.step);
6667 else
6668 t = fold_build2 (PLUS_EXPR, type, fd->loop.v, fd->loop.step);
6669 expand_omp_build_assign (&gsi, fd->loop.v, t);
6670
6671 if (fd->collapse > 1)
6672 {
6673 i = fd->collapse - 1;
6674 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v)))
6675 {
6676 t = fold_convert (sizetype, fd->loops[i].step);
6677 t = fold_build_pointer_plus (fd->loops[i].v, t);
6678 }
6679 else
6680 {
6681 t = fold_convert (TREE_TYPE (fd->loops[i].v),
6682 fd->loops[i].step);
6683 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loops[i].v),
6684 fd->loops[i].v, t);
6685 }
6686 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
6687
6688 for (i = fd->collapse - 1; i > 0; i--)
6689 {
6690 tree itype = TREE_TYPE (fd->loops[i].v);
6691 tree itype2 = TREE_TYPE (fd->loops[i - 1].v);
6692 if (POINTER_TYPE_P (itype2))
6693 itype2 = signed_type_for (itype2);
6694 t = build3 (COND_EXPR, itype2,
6695 build2 (fd->loops[i].cond_code, boolean_type_node,
6696 fd->loops[i].v,
6697 fold_convert (itype, fd->loops[i].n2)),
6698 build_int_cst (itype2, 0),
6699 fold_convert (itype2, fd->loops[i - 1].step));
6700 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i - 1].v)))
6701 t = fold_build_pointer_plus (fd->loops[i - 1].v, t);
6702 else
6703 t = fold_build2 (PLUS_EXPR, itype2, fd->loops[i - 1].v, t);
6704 expand_omp_build_assign (&gsi, fd->loops[i - 1].v, t);
6705
6706 t = build3 (COND_EXPR, itype,
6707 build2 (fd->loops[i].cond_code, boolean_type_node,
6708 fd->loops[i].v,
6709 fold_convert (itype, fd->loops[i].n2)),
6710 fd->loops[i].v,
6711 fold_convert (itype, fd->loops[i].n1));
6712 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
6713 }
6714 }
6715
6716 /* Remove GIMPLE_OMP_CONTINUE. */
6717 gsi_remove (&gsi, true);
6718 }
6719
6720 /* Emit the condition in L1_BB. */
6721 gsi = gsi_start_bb (l1_bb);
6722
6723 t = fold_convert (type, n2);
6724 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6725 false, GSI_CONTINUE_LINKING);
6726 t = build2 (fd->loop.cond_code, boolean_type_node, fd->loop.v, t);
6727 stmt = gimple_build_cond_empty (t);
6728 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
6729 if (walk_tree (gimple_cond_lhs_ptr (stmt), expand_omp_regimplify_p,
6730 NULL, NULL)
6731 || walk_tree (gimple_cond_rhs_ptr (stmt), expand_omp_regimplify_p,
6732 NULL, NULL))
6733 {
6734 gsi = gsi_for_stmt (stmt);
6735 gimple_regimplify_operands (stmt, &gsi);
6736 }
6737
6738 /* Remove GIMPLE_OMP_RETURN. */
6739 gsi = gsi_last_bb (exit_bb);
6740 gsi_remove (&gsi, true);
6741
6742 /* Connect the new blocks. */
6743 remove_edge (FALLTHRU_EDGE (entry_bb));
6744
6745 if (!broken_loop)
6746 {
6747 remove_edge (BRANCH_EDGE (entry_bb));
6748 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
6749
6750 e = BRANCH_EDGE (l1_bb);
6751 ne = FALLTHRU_EDGE (l1_bb);
6752 e->flags = EDGE_TRUE_VALUE;
6753 }
6754 else
6755 {
6756 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
6757
6758 ne = single_succ_edge (l1_bb);
6759 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
6760
6761 }
6762 ne->flags = EDGE_FALSE_VALUE;
6763 e->probability = REG_BR_PROB_BASE * 7 / 8;
6764 ne->probability = REG_BR_PROB_BASE / 8;
6765
6766 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
6767 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
6768 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
6769
6770 if (!broken_loop)
6771 {
6772 struct loop *loop = alloc_loop ();
6773 loop->header = l1_bb;
6774 loop->latch = e->dest;
6775 add_loop (loop, l1_bb->loop_father);
6776 if (safelen == NULL_TREE)
6777 loop->safelen = INT_MAX;
6778 else
6779 {
6780 safelen = OMP_CLAUSE_SAFELEN_EXPR (safelen);
6781 if (!tree_fits_uhwi_p (safelen)
6782 || tree_to_uhwi (safelen) > INT_MAX)
6783 loop->safelen = INT_MAX;
6784 else
6785 loop->safelen = tree_to_uhwi (safelen);
6786 if (loop->safelen == 1)
6787 loop->safelen = 0;
6788 }
6789 if (simduid)
6790 {
6791 loop->simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
6792 cfun->has_simduid_loops = true;
6793 }
6794 /* If not -fno-tree-loop-vectorize, hint that we want to vectorize
6795 the loop. */
6796 if ((flag_tree_loop_vectorize
6797 || (!global_options_set.x_flag_tree_loop_vectorize
6798 && !global_options_set.x_flag_tree_vectorize))
6799 && loop->safelen > 1)
6800 {
6801 loop->force_vect = true;
6802 cfun->has_force_vect_loops = true;
6803 }
6804 }
6805 }
6806
6807
6808 /* Expand the OpenMP loop defined by REGION. */
6809
6810 static void
6811 expand_omp_for (struct omp_region *region, gimple inner_stmt)
6812 {
6813 struct omp_for_data fd;
6814 struct omp_for_data_loop *loops;
6815
6816 loops
6817 = (struct omp_for_data_loop *)
6818 alloca (gimple_omp_for_collapse (last_stmt (region->entry))
6819 * sizeof (struct omp_for_data_loop));
6820 extract_omp_for_data (last_stmt (region->entry), &fd, loops);
6821 region->sched_kind = fd.sched_kind;
6822
6823 gcc_assert (EDGE_COUNT (region->entry->succs) == 2);
6824 BRANCH_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
6825 FALLTHRU_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
6826 if (region->cont)
6827 {
6828 gcc_assert (EDGE_COUNT (region->cont->succs) == 2);
6829 BRANCH_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
6830 FALLTHRU_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
6831 }
6832 else
6833 /* If there isn't a continue then this is a degerate case where
6834 the introduction of abnormal edges during lowering will prevent
6835 original loops from being detected. Fix that up. */
6836 loops_state_set (LOOPS_NEED_FIXUP);
6837
6838 if (gimple_omp_for_kind (fd.for_stmt) & GF_OMP_FOR_KIND_SIMD)
6839 expand_omp_simd (region, &fd);
6840 else if (fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
6841 && !fd.have_ordered)
6842 {
6843 if (fd.chunk_size == NULL)
6844 expand_omp_for_static_nochunk (region, &fd, inner_stmt);
6845 else
6846 expand_omp_for_static_chunk (region, &fd, inner_stmt);
6847 }
6848 else
6849 {
6850 int fn_index, start_ix, next_ix;
6851
6852 gcc_assert (gimple_omp_for_kind (fd.for_stmt)
6853 == GF_OMP_FOR_KIND_FOR);
6854 if (fd.chunk_size == NULL
6855 && fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
6856 fd.chunk_size = integer_zero_node;
6857 gcc_assert (fd.sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
6858 fn_index = (fd.sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
6859 ? 3 : fd.sched_kind;
6860 fn_index += fd.have_ordered * 4;
6861 start_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_START) + fn_index;
6862 next_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_NEXT) + fn_index;
6863 if (fd.iter_type == long_long_unsigned_type_node)
6864 {
6865 start_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_START
6866 - (int)BUILT_IN_GOMP_LOOP_STATIC_START);
6867 next_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_NEXT
6868 - (int)BUILT_IN_GOMP_LOOP_STATIC_NEXT);
6869 }
6870 expand_omp_for_generic (region, &fd, (enum built_in_function) start_ix,
6871 (enum built_in_function) next_ix, inner_stmt);
6872 }
6873
6874 if (gimple_in_ssa_p (cfun))
6875 update_ssa (TODO_update_ssa_only_virtuals);
6876 }
6877
6878
6879 /* Expand code for an OpenMP sections directive. In pseudo code, we generate
6880
6881 v = GOMP_sections_start (n);
6882 L0:
6883 switch (v)
6884 {
6885 case 0:
6886 goto L2;
6887 case 1:
6888 section 1;
6889 goto L1;
6890 case 2:
6891 ...
6892 case n:
6893 ...
6894 default:
6895 abort ();
6896 }
6897 L1:
6898 v = GOMP_sections_next ();
6899 goto L0;
6900 L2:
6901 reduction;
6902
6903 If this is a combined parallel sections, replace the call to
6904 GOMP_sections_start with call to GOMP_sections_next. */
6905
6906 static void
6907 expand_omp_sections (struct omp_region *region)
6908 {
6909 tree t, u, vin = NULL, vmain, vnext, l2;
6910 unsigned len;
6911 basic_block entry_bb, l0_bb, l1_bb, l2_bb, default_bb;
6912 gimple_stmt_iterator si, switch_si;
6913 gimple sections_stmt, stmt, cont;
6914 edge_iterator ei;
6915 edge e;
6916 struct omp_region *inner;
6917 unsigned i, casei;
6918 bool exit_reachable = region->cont != NULL;
6919
6920 gcc_assert (region->exit != NULL);
6921 entry_bb = region->entry;
6922 l0_bb = single_succ (entry_bb);
6923 l1_bb = region->cont;
6924 l2_bb = region->exit;
6925 if (single_pred_p (l2_bb) && single_pred (l2_bb) == l0_bb)
6926 l2 = gimple_block_label (l2_bb);
6927 else
6928 {
6929 /* This can happen if there are reductions. */
6930 len = EDGE_COUNT (l0_bb->succs);
6931 gcc_assert (len > 0);
6932 e = EDGE_SUCC (l0_bb, len - 1);
6933 si = gsi_last_bb (e->dest);
6934 l2 = NULL_TREE;
6935 if (gsi_end_p (si)
6936 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
6937 l2 = gimple_block_label (e->dest);
6938 else
6939 FOR_EACH_EDGE (e, ei, l0_bb->succs)
6940 {
6941 si = gsi_last_bb (e->dest);
6942 if (gsi_end_p (si)
6943 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
6944 {
6945 l2 = gimple_block_label (e->dest);
6946 break;
6947 }
6948 }
6949 }
6950 if (exit_reachable)
6951 default_bb = create_empty_bb (l1_bb->prev_bb);
6952 else
6953 default_bb = create_empty_bb (l0_bb);
6954
6955 /* We will build a switch() with enough cases for all the
6956 GIMPLE_OMP_SECTION regions, a '0' case to handle the end of more work
6957 and a default case to abort if something goes wrong. */
6958 len = EDGE_COUNT (l0_bb->succs);
6959
6960 /* Use vec::quick_push on label_vec throughout, since we know the size
6961 in advance. */
6962 auto_vec<tree> label_vec (len);
6963
6964 /* The call to GOMP_sections_start goes in ENTRY_BB, replacing the
6965 GIMPLE_OMP_SECTIONS statement. */
6966 si = gsi_last_bb (entry_bb);
6967 sections_stmt = gsi_stmt (si);
6968 gcc_assert (gimple_code (sections_stmt) == GIMPLE_OMP_SECTIONS);
6969 vin = gimple_omp_sections_control (sections_stmt);
6970 if (!is_combined_parallel (region))
6971 {
6972 /* If we are not inside a combined parallel+sections region,
6973 call GOMP_sections_start. */
6974 t = build_int_cst (unsigned_type_node, len - 1);
6975 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_START);
6976 stmt = gimple_build_call (u, 1, t);
6977 }
6978 else
6979 {
6980 /* Otherwise, call GOMP_sections_next. */
6981 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
6982 stmt = gimple_build_call (u, 0);
6983 }
6984 gimple_call_set_lhs (stmt, vin);
6985 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
6986 gsi_remove (&si, true);
6987
6988 /* The switch() statement replacing GIMPLE_OMP_SECTIONS_SWITCH goes in
6989 L0_BB. */
6990 switch_si = gsi_last_bb (l0_bb);
6991 gcc_assert (gimple_code (gsi_stmt (switch_si)) == GIMPLE_OMP_SECTIONS_SWITCH);
6992 if (exit_reachable)
6993 {
6994 cont = last_stmt (l1_bb);
6995 gcc_assert (gimple_code (cont) == GIMPLE_OMP_CONTINUE);
6996 vmain = gimple_omp_continue_control_use (cont);
6997 vnext = gimple_omp_continue_control_def (cont);
6998 }
6999 else
7000 {
7001 vmain = vin;
7002 vnext = NULL_TREE;
7003 }
7004
7005 t = build_case_label (build_int_cst (unsigned_type_node, 0), NULL, l2);
7006 label_vec.quick_push (t);
7007 i = 1;
7008
7009 /* Convert each GIMPLE_OMP_SECTION into a CASE_LABEL_EXPR. */
7010 for (inner = region->inner, casei = 1;
7011 inner;
7012 inner = inner->next, i++, casei++)
7013 {
7014 basic_block s_entry_bb, s_exit_bb;
7015
7016 /* Skip optional reduction region. */
7017 if (inner->type == GIMPLE_OMP_ATOMIC_LOAD)
7018 {
7019 --i;
7020 --casei;
7021 continue;
7022 }
7023
7024 s_entry_bb = inner->entry;
7025 s_exit_bb = inner->exit;
7026
7027 t = gimple_block_label (s_entry_bb);
7028 u = build_int_cst (unsigned_type_node, casei);
7029 u = build_case_label (u, NULL, t);
7030 label_vec.quick_push (u);
7031
7032 si = gsi_last_bb (s_entry_bb);
7033 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SECTION);
7034 gcc_assert (i < len || gimple_omp_section_last_p (gsi_stmt (si)));
7035 gsi_remove (&si, true);
7036 single_succ_edge (s_entry_bb)->flags = EDGE_FALLTHRU;
7037
7038 if (s_exit_bb == NULL)
7039 continue;
7040
7041 si = gsi_last_bb (s_exit_bb);
7042 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
7043 gsi_remove (&si, true);
7044
7045 single_succ_edge (s_exit_bb)->flags = EDGE_FALLTHRU;
7046 }
7047
7048 /* Error handling code goes in DEFAULT_BB. */
7049 t = gimple_block_label (default_bb);
7050 u = build_case_label (NULL, NULL, t);
7051 make_edge (l0_bb, default_bb, 0);
7052 if (current_loops)
7053 add_bb_to_loop (default_bb, current_loops->tree_root);
7054
7055 stmt = gimple_build_switch (vmain, u, label_vec);
7056 gsi_insert_after (&switch_si, stmt, GSI_SAME_STMT);
7057 gsi_remove (&switch_si, true);
7058
7059 si = gsi_start_bb (default_bb);
7060 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
7061 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
7062
7063 if (exit_reachable)
7064 {
7065 tree bfn_decl;
7066
7067 /* Code to get the next section goes in L1_BB. */
7068 si = gsi_last_bb (l1_bb);
7069 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CONTINUE);
7070
7071 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
7072 stmt = gimple_build_call (bfn_decl, 0);
7073 gimple_call_set_lhs (stmt, vnext);
7074 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
7075 gsi_remove (&si, true);
7076
7077 single_succ_edge (l1_bb)->flags = EDGE_FALLTHRU;
7078 }
7079
7080 /* Cleanup function replaces GIMPLE_OMP_RETURN in EXIT_BB. */
7081 si = gsi_last_bb (l2_bb);
7082 if (gimple_omp_return_nowait_p (gsi_stmt (si)))
7083 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_NOWAIT);
7084 else if (gimple_omp_return_lhs (gsi_stmt (si)))
7085 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_CANCEL);
7086 else
7087 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END);
7088 stmt = gimple_build_call (t, 0);
7089 if (gimple_omp_return_lhs (gsi_stmt (si)))
7090 gimple_call_set_lhs (stmt, gimple_omp_return_lhs (gsi_stmt (si)));
7091 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
7092 gsi_remove (&si, true);
7093
7094 set_immediate_dominator (CDI_DOMINATORS, default_bb, l0_bb);
7095 }
7096
7097
7098 /* Expand code for an OpenMP single directive. We've already expanded
7099 much of the code, here we simply place the GOMP_barrier call. */
7100
7101 static void
7102 expand_omp_single (struct omp_region *region)
7103 {
7104 basic_block entry_bb, exit_bb;
7105 gimple_stmt_iterator si;
7106
7107 entry_bb = region->entry;
7108 exit_bb = region->exit;
7109
7110 si = gsi_last_bb (entry_bb);
7111 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE);
7112 gsi_remove (&si, true);
7113 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7114
7115 si = gsi_last_bb (exit_bb);
7116 if (!gimple_omp_return_nowait_p (gsi_stmt (si)))
7117 {
7118 tree t = gimple_omp_return_lhs (gsi_stmt (si));
7119 gsi_insert_after (&si, build_omp_barrier (t), GSI_SAME_STMT);
7120 }
7121 gsi_remove (&si, true);
7122 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
7123 }
7124
7125
7126 /* Generic expansion for OpenMP synchronization directives: master,
7127 ordered and critical. All we need to do here is remove the entry
7128 and exit markers for REGION. */
7129
7130 static void
7131 expand_omp_synch (struct omp_region *region)
7132 {
7133 basic_block entry_bb, exit_bb;
7134 gimple_stmt_iterator si;
7135
7136 entry_bb = region->entry;
7137 exit_bb = region->exit;
7138
7139 si = gsi_last_bb (entry_bb);
7140 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE
7141 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_MASTER
7142 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TASKGROUP
7143 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ORDERED
7144 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CRITICAL
7145 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TEAMS);
7146 gsi_remove (&si, true);
7147 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7148
7149 if (exit_bb)
7150 {
7151 si = gsi_last_bb (exit_bb);
7152 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
7153 gsi_remove (&si, true);
7154 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
7155 }
7156 }
7157
7158 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
7159 operation as a normal volatile load. */
7160
7161 static bool
7162 expand_omp_atomic_load (basic_block load_bb, tree addr,
7163 tree loaded_val, int index)
7164 {
7165 enum built_in_function tmpbase;
7166 gimple_stmt_iterator gsi;
7167 basic_block store_bb;
7168 location_t loc;
7169 gimple stmt;
7170 tree decl, call, type, itype;
7171
7172 gsi = gsi_last_bb (load_bb);
7173 stmt = gsi_stmt (gsi);
7174 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
7175 loc = gimple_location (stmt);
7176
7177 /* ??? If the target does not implement atomic_load_optab[mode], and mode
7178 is smaller than word size, then expand_atomic_load assumes that the load
7179 is atomic. We could avoid the builtin entirely in this case. */
7180
7181 tmpbase = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
7182 decl = builtin_decl_explicit (tmpbase);
7183 if (decl == NULL_TREE)
7184 return false;
7185
7186 type = TREE_TYPE (loaded_val);
7187 itype = TREE_TYPE (TREE_TYPE (decl));
7188
7189 call = build_call_expr_loc (loc, decl, 2, addr,
7190 build_int_cst (NULL,
7191 gimple_omp_atomic_seq_cst_p (stmt)
7192 ? MEMMODEL_SEQ_CST
7193 : MEMMODEL_RELAXED));
7194 if (!useless_type_conversion_p (type, itype))
7195 call = fold_build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
7196 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
7197
7198 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
7199 gsi_remove (&gsi, true);
7200
7201 store_bb = single_succ (load_bb);
7202 gsi = gsi_last_bb (store_bb);
7203 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
7204 gsi_remove (&gsi, true);
7205
7206 if (gimple_in_ssa_p (cfun))
7207 update_ssa (TODO_update_ssa_no_phi);
7208
7209 return true;
7210 }
7211
7212 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
7213 operation as a normal volatile store. */
7214
7215 static bool
7216 expand_omp_atomic_store (basic_block load_bb, tree addr,
7217 tree loaded_val, tree stored_val, int index)
7218 {
7219 enum built_in_function tmpbase;
7220 gimple_stmt_iterator gsi;
7221 basic_block store_bb = single_succ (load_bb);
7222 location_t loc;
7223 gimple stmt;
7224 tree decl, call, type, itype;
7225 enum machine_mode imode;
7226 bool exchange;
7227
7228 gsi = gsi_last_bb (load_bb);
7229 stmt = gsi_stmt (gsi);
7230 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
7231
7232 /* If the load value is needed, then this isn't a store but an exchange. */
7233 exchange = gimple_omp_atomic_need_value_p (stmt);
7234
7235 gsi = gsi_last_bb (store_bb);
7236 stmt = gsi_stmt (gsi);
7237 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE);
7238 loc = gimple_location (stmt);
7239
7240 /* ??? If the target does not implement atomic_store_optab[mode], and mode
7241 is smaller than word size, then expand_atomic_store assumes that the store
7242 is atomic. We could avoid the builtin entirely in this case. */
7243
7244 tmpbase = (exchange ? BUILT_IN_ATOMIC_EXCHANGE_N : BUILT_IN_ATOMIC_STORE_N);
7245 tmpbase = (enum built_in_function) ((int) tmpbase + index + 1);
7246 decl = builtin_decl_explicit (tmpbase);
7247 if (decl == NULL_TREE)
7248 return false;
7249
7250 type = TREE_TYPE (stored_val);
7251
7252 /* Dig out the type of the function's second argument. */
7253 itype = TREE_TYPE (decl);
7254 itype = TYPE_ARG_TYPES (itype);
7255 itype = TREE_CHAIN (itype);
7256 itype = TREE_VALUE (itype);
7257 imode = TYPE_MODE (itype);
7258
7259 if (exchange && !can_atomic_exchange_p (imode, true))
7260 return false;
7261
7262 if (!useless_type_conversion_p (itype, type))
7263 stored_val = fold_build1_loc (loc, VIEW_CONVERT_EXPR, itype, stored_val);
7264 call = build_call_expr_loc (loc, decl, 3, addr, stored_val,
7265 build_int_cst (NULL,
7266 gimple_omp_atomic_seq_cst_p (stmt)
7267 ? MEMMODEL_SEQ_CST
7268 : MEMMODEL_RELAXED));
7269 if (exchange)
7270 {
7271 if (!useless_type_conversion_p (type, itype))
7272 call = build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
7273 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
7274 }
7275
7276 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
7277 gsi_remove (&gsi, true);
7278
7279 /* Remove the GIMPLE_OMP_ATOMIC_LOAD that we verified above. */
7280 gsi = gsi_last_bb (load_bb);
7281 gsi_remove (&gsi, true);
7282
7283 if (gimple_in_ssa_p (cfun))
7284 update_ssa (TODO_update_ssa_no_phi);
7285
7286 return true;
7287 }
7288
7289 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
7290 operation as a __atomic_fetch_op builtin. INDEX is log2 of the
7291 size of the data type, and thus usable to find the index of the builtin
7292 decl. Returns false if the expression is not of the proper form. */
7293
7294 static bool
7295 expand_omp_atomic_fetch_op (basic_block load_bb,
7296 tree addr, tree loaded_val,
7297 tree stored_val, int index)
7298 {
7299 enum built_in_function oldbase, newbase, tmpbase;
7300 tree decl, itype, call;
7301 tree lhs, rhs;
7302 basic_block store_bb = single_succ (load_bb);
7303 gimple_stmt_iterator gsi;
7304 gimple stmt;
7305 location_t loc;
7306 enum tree_code code;
7307 bool need_old, need_new;
7308 enum machine_mode imode;
7309 bool seq_cst;
7310
7311 /* We expect to find the following sequences:
7312
7313 load_bb:
7314 GIMPLE_OMP_ATOMIC_LOAD (tmp, mem)
7315
7316 store_bb:
7317 val = tmp OP something; (or: something OP tmp)
7318 GIMPLE_OMP_STORE (val)
7319
7320 ???FIXME: Allow a more flexible sequence.
7321 Perhaps use data flow to pick the statements.
7322
7323 */
7324
7325 gsi = gsi_after_labels (store_bb);
7326 stmt = gsi_stmt (gsi);
7327 loc = gimple_location (stmt);
7328 if (!is_gimple_assign (stmt))
7329 return false;
7330 gsi_next (&gsi);
7331 if (gimple_code (gsi_stmt (gsi)) != GIMPLE_OMP_ATOMIC_STORE)
7332 return false;
7333 need_new = gimple_omp_atomic_need_value_p (gsi_stmt (gsi));
7334 need_old = gimple_omp_atomic_need_value_p (last_stmt (load_bb));
7335 seq_cst = gimple_omp_atomic_seq_cst_p (last_stmt (load_bb));
7336 gcc_checking_assert (!need_old || !need_new);
7337
7338 if (!operand_equal_p (gimple_assign_lhs (stmt), stored_val, 0))
7339 return false;
7340
7341 /* Check for one of the supported fetch-op operations. */
7342 code = gimple_assign_rhs_code (stmt);
7343 switch (code)
7344 {
7345 case PLUS_EXPR:
7346 case POINTER_PLUS_EXPR:
7347 oldbase = BUILT_IN_ATOMIC_FETCH_ADD_N;
7348 newbase = BUILT_IN_ATOMIC_ADD_FETCH_N;
7349 break;
7350 case MINUS_EXPR:
7351 oldbase = BUILT_IN_ATOMIC_FETCH_SUB_N;
7352 newbase = BUILT_IN_ATOMIC_SUB_FETCH_N;
7353 break;
7354 case BIT_AND_EXPR:
7355 oldbase = BUILT_IN_ATOMIC_FETCH_AND_N;
7356 newbase = BUILT_IN_ATOMIC_AND_FETCH_N;
7357 break;
7358 case BIT_IOR_EXPR:
7359 oldbase = BUILT_IN_ATOMIC_FETCH_OR_N;
7360 newbase = BUILT_IN_ATOMIC_OR_FETCH_N;
7361 break;
7362 case BIT_XOR_EXPR:
7363 oldbase = BUILT_IN_ATOMIC_FETCH_XOR_N;
7364 newbase = BUILT_IN_ATOMIC_XOR_FETCH_N;
7365 break;
7366 default:
7367 return false;
7368 }
7369
7370 /* Make sure the expression is of the proper form. */
7371 if (operand_equal_p (gimple_assign_rhs1 (stmt), loaded_val, 0))
7372 rhs = gimple_assign_rhs2 (stmt);
7373 else if (commutative_tree_code (gimple_assign_rhs_code (stmt))
7374 && operand_equal_p (gimple_assign_rhs2 (stmt), loaded_val, 0))
7375 rhs = gimple_assign_rhs1 (stmt);
7376 else
7377 return false;
7378
7379 tmpbase = ((enum built_in_function)
7380 ((need_new ? newbase : oldbase) + index + 1));
7381 decl = builtin_decl_explicit (tmpbase);
7382 if (decl == NULL_TREE)
7383 return false;
7384 itype = TREE_TYPE (TREE_TYPE (decl));
7385 imode = TYPE_MODE (itype);
7386
7387 /* We could test all of the various optabs involved, but the fact of the
7388 matter is that (with the exception of i486 vs i586 and xadd) all targets
7389 that support any atomic operaton optab also implements compare-and-swap.
7390 Let optabs.c take care of expanding any compare-and-swap loop. */
7391 if (!can_compare_and_swap_p (imode, true))
7392 return false;
7393
7394 gsi = gsi_last_bb (load_bb);
7395 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_LOAD);
7396
7397 /* OpenMP does not imply any barrier-like semantics on its atomic ops.
7398 It only requires that the operation happen atomically. Thus we can
7399 use the RELAXED memory model. */
7400 call = build_call_expr_loc (loc, decl, 3, addr,
7401 fold_convert_loc (loc, itype, rhs),
7402 build_int_cst (NULL,
7403 seq_cst ? MEMMODEL_SEQ_CST
7404 : MEMMODEL_RELAXED));
7405
7406 if (need_old || need_new)
7407 {
7408 lhs = need_old ? loaded_val : stored_val;
7409 call = fold_convert_loc (loc, TREE_TYPE (lhs), call);
7410 call = build2_loc (loc, MODIFY_EXPR, void_type_node, lhs, call);
7411 }
7412 else
7413 call = fold_convert_loc (loc, void_type_node, call);
7414 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
7415 gsi_remove (&gsi, true);
7416
7417 gsi = gsi_last_bb (store_bb);
7418 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
7419 gsi_remove (&gsi, true);
7420 gsi = gsi_last_bb (store_bb);
7421 gsi_remove (&gsi, true);
7422
7423 if (gimple_in_ssa_p (cfun))
7424 update_ssa (TODO_update_ssa_no_phi);
7425
7426 return true;
7427 }
7428
7429 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
7430
7431 oldval = *addr;
7432 repeat:
7433 newval = rhs; // with oldval replacing *addr in rhs
7434 oldval = __sync_val_compare_and_swap (addr, oldval, newval);
7435 if (oldval != newval)
7436 goto repeat;
7437
7438 INDEX is log2 of the size of the data type, and thus usable to find the
7439 index of the builtin decl. */
7440
7441 static bool
7442 expand_omp_atomic_pipeline (basic_block load_bb, basic_block store_bb,
7443 tree addr, tree loaded_val, tree stored_val,
7444 int index)
7445 {
7446 tree loadedi, storedi, initial, new_storedi, old_vali;
7447 tree type, itype, cmpxchg, iaddr;
7448 gimple_stmt_iterator si;
7449 basic_block loop_header = single_succ (load_bb);
7450 gimple phi, stmt;
7451 edge e;
7452 enum built_in_function fncode;
7453
7454 /* ??? We need a non-pointer interface to __atomic_compare_exchange in
7455 order to use the RELAXED memory model effectively. */
7456 fncode = (enum built_in_function)((int)BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_N
7457 + index + 1);
7458 cmpxchg = builtin_decl_explicit (fncode);
7459 if (cmpxchg == NULL_TREE)
7460 return false;
7461 type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
7462 itype = TREE_TYPE (TREE_TYPE (cmpxchg));
7463
7464 if (!can_compare_and_swap_p (TYPE_MODE (itype), true))
7465 return false;
7466
7467 /* Load the initial value, replacing the GIMPLE_OMP_ATOMIC_LOAD. */
7468 si = gsi_last_bb (load_bb);
7469 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
7470
7471 /* For floating-point values, we'll need to view-convert them to integers
7472 so that we can perform the atomic compare and swap. Simplify the
7473 following code by always setting up the "i"ntegral variables. */
7474 if (!INTEGRAL_TYPE_P (type) && !POINTER_TYPE_P (type))
7475 {
7476 tree iaddr_val;
7477
7478 iaddr = create_tmp_reg (build_pointer_type_for_mode (itype, ptr_mode,
7479 true), NULL);
7480 iaddr_val
7481 = force_gimple_operand_gsi (&si,
7482 fold_convert (TREE_TYPE (iaddr), addr),
7483 false, NULL_TREE, true, GSI_SAME_STMT);
7484 stmt = gimple_build_assign (iaddr, iaddr_val);
7485 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
7486 loadedi = create_tmp_var (itype, NULL);
7487 if (gimple_in_ssa_p (cfun))
7488 loadedi = make_ssa_name (loadedi, NULL);
7489 }
7490 else
7491 {
7492 iaddr = addr;
7493 loadedi = loaded_val;
7494 }
7495
7496 initial
7497 = force_gimple_operand_gsi (&si,
7498 build2 (MEM_REF, TREE_TYPE (TREE_TYPE (iaddr)),
7499 iaddr,
7500 build_int_cst (TREE_TYPE (iaddr), 0)),
7501 true, NULL_TREE, true, GSI_SAME_STMT);
7502
7503 /* Move the value to the LOADEDI temporary. */
7504 if (gimple_in_ssa_p (cfun))
7505 {
7506 gcc_assert (gimple_seq_empty_p (phi_nodes (loop_header)));
7507 phi = create_phi_node (loadedi, loop_header);
7508 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, single_succ_edge (load_bb)),
7509 initial);
7510 }
7511 else
7512 gsi_insert_before (&si,
7513 gimple_build_assign (loadedi, initial),
7514 GSI_SAME_STMT);
7515 if (loadedi != loaded_val)
7516 {
7517 gimple_stmt_iterator gsi2;
7518 tree x;
7519
7520 x = build1 (VIEW_CONVERT_EXPR, type, loadedi);
7521 gsi2 = gsi_start_bb (loop_header);
7522 if (gimple_in_ssa_p (cfun))
7523 {
7524 gimple stmt;
7525 x = force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
7526 true, GSI_SAME_STMT);
7527 stmt = gimple_build_assign (loaded_val, x);
7528 gsi_insert_before (&gsi2, stmt, GSI_SAME_STMT);
7529 }
7530 else
7531 {
7532 x = build2 (MODIFY_EXPR, TREE_TYPE (loaded_val), loaded_val, x);
7533 force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
7534 true, GSI_SAME_STMT);
7535 }
7536 }
7537 gsi_remove (&si, true);
7538
7539 si = gsi_last_bb (store_bb);
7540 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
7541
7542 if (iaddr == addr)
7543 storedi = stored_val;
7544 else
7545 storedi =
7546 force_gimple_operand_gsi (&si,
7547 build1 (VIEW_CONVERT_EXPR, itype,
7548 stored_val), true, NULL_TREE, true,
7549 GSI_SAME_STMT);
7550
7551 /* Build the compare&swap statement. */
7552 new_storedi = build_call_expr (cmpxchg, 3, iaddr, loadedi, storedi);
7553 new_storedi = force_gimple_operand_gsi (&si,
7554 fold_convert (TREE_TYPE (loadedi),
7555 new_storedi),
7556 true, NULL_TREE,
7557 true, GSI_SAME_STMT);
7558
7559 if (gimple_in_ssa_p (cfun))
7560 old_vali = loadedi;
7561 else
7562 {
7563 old_vali = create_tmp_var (TREE_TYPE (loadedi), NULL);
7564 stmt = gimple_build_assign (old_vali, loadedi);
7565 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
7566
7567 stmt = gimple_build_assign (loadedi, new_storedi);
7568 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
7569 }
7570
7571 /* Note that we always perform the comparison as an integer, even for
7572 floating point. This allows the atomic operation to properly
7573 succeed even with NaNs and -0.0. */
7574 stmt = gimple_build_cond_empty
7575 (build2 (NE_EXPR, boolean_type_node,
7576 new_storedi, old_vali));
7577 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
7578
7579 /* Update cfg. */
7580 e = single_succ_edge (store_bb);
7581 e->flags &= ~EDGE_FALLTHRU;
7582 e->flags |= EDGE_FALSE_VALUE;
7583
7584 e = make_edge (store_bb, loop_header, EDGE_TRUE_VALUE);
7585
7586 /* Copy the new value to loadedi (we already did that before the condition
7587 if we are not in SSA). */
7588 if (gimple_in_ssa_p (cfun))
7589 {
7590 phi = gimple_seq_first_stmt (phi_nodes (loop_header));
7591 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, e), new_storedi);
7592 }
7593
7594 /* Remove GIMPLE_OMP_ATOMIC_STORE. */
7595 gsi_remove (&si, true);
7596
7597 struct loop *loop = alloc_loop ();
7598 loop->header = loop_header;
7599 loop->latch = store_bb;
7600 add_loop (loop, loop_header->loop_father);
7601
7602 if (gimple_in_ssa_p (cfun))
7603 update_ssa (TODO_update_ssa_no_phi);
7604
7605 return true;
7606 }
7607
7608 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
7609
7610 GOMP_atomic_start ();
7611 *addr = rhs;
7612 GOMP_atomic_end ();
7613
7614 The result is not globally atomic, but works so long as all parallel
7615 references are within #pragma omp atomic directives. According to
7616 responses received from omp@openmp.org, appears to be within spec.
7617 Which makes sense, since that's how several other compilers handle
7618 this situation as well.
7619 LOADED_VAL and ADDR are the operands of GIMPLE_OMP_ATOMIC_LOAD we're
7620 expanding. STORED_VAL is the operand of the matching
7621 GIMPLE_OMP_ATOMIC_STORE.
7622
7623 We replace
7624 GIMPLE_OMP_ATOMIC_LOAD (loaded_val, addr) with
7625 loaded_val = *addr;
7626
7627 and replace
7628 GIMPLE_OMP_ATOMIC_STORE (stored_val) with
7629 *addr = stored_val;
7630 */
7631
7632 static bool
7633 expand_omp_atomic_mutex (basic_block load_bb, basic_block store_bb,
7634 tree addr, tree loaded_val, tree stored_val)
7635 {
7636 gimple_stmt_iterator si;
7637 gimple stmt;
7638 tree t;
7639
7640 si = gsi_last_bb (load_bb);
7641 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
7642
7643 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START);
7644 t = build_call_expr (t, 0);
7645 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
7646
7647 stmt = gimple_build_assign (loaded_val, build_simple_mem_ref (addr));
7648 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
7649 gsi_remove (&si, true);
7650
7651 si = gsi_last_bb (store_bb);
7652 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
7653
7654 stmt = gimple_build_assign (build_simple_mem_ref (unshare_expr (addr)),
7655 stored_val);
7656 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
7657
7658 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END);
7659 t = build_call_expr (t, 0);
7660 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
7661 gsi_remove (&si, true);
7662
7663 if (gimple_in_ssa_p (cfun))
7664 update_ssa (TODO_update_ssa_no_phi);
7665 return true;
7666 }
7667
7668 /* Expand an GIMPLE_OMP_ATOMIC statement. We try to expand
7669 using expand_omp_atomic_fetch_op. If it failed, we try to
7670 call expand_omp_atomic_pipeline, and if it fails too, the
7671 ultimate fallback is wrapping the operation in a mutex
7672 (expand_omp_atomic_mutex). REGION is the atomic region built
7673 by build_omp_regions_1(). */
7674
7675 static void
7676 expand_omp_atomic (struct omp_region *region)
7677 {
7678 basic_block load_bb = region->entry, store_bb = region->exit;
7679 gimple load = last_stmt (load_bb), store = last_stmt (store_bb);
7680 tree loaded_val = gimple_omp_atomic_load_lhs (load);
7681 tree addr = gimple_omp_atomic_load_rhs (load);
7682 tree stored_val = gimple_omp_atomic_store_val (store);
7683 tree type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
7684 HOST_WIDE_INT index;
7685
7686 /* Make sure the type is one of the supported sizes. */
7687 index = tree_to_uhwi (TYPE_SIZE_UNIT (type));
7688 index = exact_log2 (index);
7689 if (index >= 0 && index <= 4)
7690 {
7691 unsigned int align = TYPE_ALIGN_UNIT (type);
7692
7693 /* __sync builtins require strict data alignment. */
7694 if (exact_log2 (align) >= index)
7695 {
7696 /* Atomic load. */
7697 if (loaded_val == stored_val
7698 && (GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
7699 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
7700 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
7701 && expand_omp_atomic_load (load_bb, addr, loaded_val, index))
7702 return;
7703
7704 /* Atomic store. */
7705 if ((GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
7706 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
7707 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
7708 && store_bb == single_succ (load_bb)
7709 && first_stmt (store_bb) == store
7710 && expand_omp_atomic_store (load_bb, addr, loaded_val,
7711 stored_val, index))
7712 return;
7713
7714 /* When possible, use specialized atomic update functions. */
7715 if ((INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type))
7716 && store_bb == single_succ (load_bb)
7717 && expand_omp_atomic_fetch_op (load_bb, addr,
7718 loaded_val, stored_val, index))
7719 return;
7720
7721 /* If we don't have specialized __sync builtins, try and implement
7722 as a compare and swap loop. */
7723 if (expand_omp_atomic_pipeline (load_bb, store_bb, addr,
7724 loaded_val, stored_val, index))
7725 return;
7726 }
7727 }
7728
7729 /* The ultimate fallback is wrapping the operation in a mutex. */
7730 expand_omp_atomic_mutex (load_bb, store_bb, addr, loaded_val, stored_val);
7731 }
7732
7733
7734 /* Expand the OpenMP target{, data, update} directive starting at REGION. */
7735
7736 static void
7737 expand_omp_target (struct omp_region *region)
7738 {
7739 basic_block entry_bb, exit_bb, new_bb;
7740 struct function *child_cfun = NULL;
7741 tree child_fn = NULL_TREE, block, t;
7742 gimple_stmt_iterator gsi;
7743 gimple entry_stmt, stmt;
7744 edge e;
7745
7746 entry_stmt = last_stmt (region->entry);
7747 new_bb = region->entry;
7748 int kind = gimple_omp_target_kind (entry_stmt);
7749 if (kind == GF_OMP_TARGET_KIND_REGION)
7750 {
7751 child_fn = gimple_omp_target_child_fn (entry_stmt);
7752 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
7753 }
7754
7755 entry_bb = region->entry;
7756 exit_bb = region->exit;
7757
7758 if (kind == GF_OMP_TARGET_KIND_REGION)
7759 {
7760 unsigned srcidx, dstidx, num;
7761
7762 /* If the target region needs data sent from the parent
7763 function, then the very first statement (except possible
7764 tree profile counter updates) of the parallel body
7765 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
7766 &.OMP_DATA_O is passed as an argument to the child function,
7767 we need to replace it with the argument as seen by the child
7768 function.
7769
7770 In most cases, this will end up being the identity assignment
7771 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
7772 a function call that has been inlined, the original PARM_DECL
7773 .OMP_DATA_I may have been converted into a different local
7774 variable. In which case, we need to keep the assignment. */
7775 if (gimple_omp_target_data_arg (entry_stmt))
7776 {
7777 basic_block entry_succ_bb = single_succ (entry_bb);
7778 gimple_stmt_iterator gsi;
7779 tree arg;
7780 gimple tgtcopy_stmt = NULL;
7781 tree sender
7782 = TREE_VEC_ELT (gimple_omp_target_data_arg (entry_stmt), 0);
7783
7784 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
7785 {
7786 gcc_assert (!gsi_end_p (gsi));
7787 stmt = gsi_stmt (gsi);
7788 if (gimple_code (stmt) != GIMPLE_ASSIGN)
7789 continue;
7790
7791 if (gimple_num_ops (stmt) == 2)
7792 {
7793 tree arg = gimple_assign_rhs1 (stmt);
7794
7795 /* We're ignoring the subcode because we're
7796 effectively doing a STRIP_NOPS. */
7797
7798 if (TREE_CODE (arg) == ADDR_EXPR
7799 && TREE_OPERAND (arg, 0) == sender)
7800 {
7801 tgtcopy_stmt = stmt;
7802 break;
7803 }
7804 }
7805 }
7806
7807 gcc_assert (tgtcopy_stmt != NULL);
7808 arg = DECL_ARGUMENTS (child_fn);
7809
7810 gcc_assert (gimple_assign_lhs (tgtcopy_stmt) == arg);
7811 gsi_remove (&gsi, true);
7812 }
7813
7814 /* Declare local variables needed in CHILD_CFUN. */
7815 block = DECL_INITIAL (child_fn);
7816 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
7817 /* The gimplifier could record temporaries in target block
7818 rather than in containing function's local_decls chain,
7819 which would mean cgraph missed finalizing them. Do it now. */
7820 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
7821 if (TREE_CODE (t) == VAR_DECL
7822 && TREE_STATIC (t)
7823 && !DECL_EXTERNAL (t))
7824 varpool_finalize_decl (t);
7825 DECL_SAVED_TREE (child_fn) = NULL;
7826 /* We'll create a CFG for child_fn, so no gimple body is needed. */
7827 gimple_set_body (child_fn, NULL);
7828 TREE_USED (block) = 1;
7829
7830 /* Reset DECL_CONTEXT on function arguments. */
7831 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
7832 DECL_CONTEXT (t) = child_fn;
7833
7834 /* Split ENTRY_BB at GIMPLE_OMP_TARGET,
7835 so that it can be moved to the child function. */
7836 gsi = gsi_last_bb (entry_bb);
7837 stmt = gsi_stmt (gsi);
7838 gcc_assert (stmt && gimple_code (stmt) == GIMPLE_OMP_TARGET
7839 && gimple_omp_target_kind (stmt)
7840 == GF_OMP_TARGET_KIND_REGION);
7841 gsi_remove (&gsi, true);
7842 e = split_block (entry_bb, stmt);
7843 entry_bb = e->dest;
7844 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7845
7846 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
7847 if (exit_bb)
7848 {
7849 gsi = gsi_last_bb (exit_bb);
7850 gcc_assert (!gsi_end_p (gsi)
7851 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
7852 stmt = gimple_build_return (NULL);
7853 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
7854 gsi_remove (&gsi, true);
7855 }
7856
7857 /* Move the target region into CHILD_CFUN. */
7858
7859 block = gimple_block (entry_stmt);
7860
7861 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
7862 if (exit_bb)
7863 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
7864 /* When the OMP expansion process cannot guarantee an up-to-date
7865 loop tree arrange for the child function to fixup loops. */
7866 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
7867 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
7868
7869 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
7870 num = vec_safe_length (child_cfun->local_decls);
7871 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
7872 {
7873 t = (*child_cfun->local_decls)[srcidx];
7874 if (DECL_CONTEXT (t) == cfun->decl)
7875 continue;
7876 if (srcidx != dstidx)
7877 (*child_cfun->local_decls)[dstidx] = t;
7878 dstidx++;
7879 }
7880 if (dstidx != num)
7881 vec_safe_truncate (child_cfun->local_decls, dstidx);
7882
7883 /* Inform the callgraph about the new function. */
7884 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
7885 cgraph_add_new_function (child_fn, true);
7886
7887 /* Fix the callgraph edges for child_cfun. Those for cfun will be
7888 fixed in a following pass. */
7889 push_cfun (child_cfun);
7890 rebuild_cgraph_edges ();
7891
7892 /* Some EH regions might become dead, see PR34608. If
7893 pass_cleanup_cfg isn't the first pass to happen with the
7894 new child, these dead EH edges might cause problems.
7895 Clean them up now. */
7896 if (flag_exceptions)
7897 {
7898 basic_block bb;
7899 bool changed = false;
7900
7901 FOR_EACH_BB (bb)
7902 changed |= gimple_purge_dead_eh_edges (bb);
7903 if (changed)
7904 cleanup_tree_cfg ();
7905 }
7906 pop_cfun ();
7907 }
7908
7909 /* Emit a library call to launch the target region, or do data
7910 transfers. */
7911 tree t1, t2, t3, t4, device, cond, c, clauses;
7912 enum built_in_function start_ix;
7913 location_t clause_loc;
7914
7915 clauses = gimple_omp_target_clauses (entry_stmt);
7916
7917 if (kind == GF_OMP_TARGET_KIND_REGION)
7918 start_ix = BUILT_IN_GOMP_TARGET;
7919 else if (kind == GF_OMP_TARGET_KIND_DATA)
7920 start_ix = BUILT_IN_GOMP_TARGET_DATA;
7921 else
7922 start_ix = BUILT_IN_GOMP_TARGET_UPDATE;
7923
7924 /* By default, the value of DEVICE is -1 (let runtime library choose)
7925 and there is no conditional. */
7926 cond = NULL_TREE;
7927 device = build_int_cst (integer_type_node, -1);
7928
7929 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
7930 if (c)
7931 cond = OMP_CLAUSE_IF_EXPR (c);
7932
7933 c = find_omp_clause (clauses, OMP_CLAUSE_DEVICE);
7934 if (c)
7935 {
7936 device = OMP_CLAUSE_DEVICE_ID (c);
7937 clause_loc = OMP_CLAUSE_LOCATION (c);
7938 }
7939 else
7940 clause_loc = gimple_location (entry_stmt);
7941
7942 /* Ensure 'device' is of the correct type. */
7943 device = fold_convert_loc (clause_loc, integer_type_node, device);
7944
7945 /* If we found the clause 'if (cond)', build
7946 (cond ? device : -2). */
7947 if (cond)
7948 {
7949 cond = gimple_boolify (cond);
7950
7951 basic_block cond_bb, then_bb, else_bb;
7952 edge e;
7953 tree tmp_var;
7954
7955 tmp_var = create_tmp_var (TREE_TYPE (device), NULL);
7956 if (kind != GF_OMP_TARGET_KIND_REGION)
7957 {
7958 gsi = gsi_last_bb (new_bb);
7959 gsi_prev (&gsi);
7960 e = split_block (new_bb, gsi_stmt (gsi));
7961 }
7962 else
7963 e = split_block (new_bb, NULL);
7964 cond_bb = e->src;
7965 new_bb = e->dest;
7966 remove_edge (e);
7967
7968 then_bb = create_empty_bb (cond_bb);
7969 else_bb = create_empty_bb (then_bb);
7970 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
7971 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
7972
7973 stmt = gimple_build_cond_empty (cond);
7974 gsi = gsi_last_bb (cond_bb);
7975 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
7976
7977 gsi = gsi_start_bb (then_bb);
7978 stmt = gimple_build_assign (tmp_var, device);
7979 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
7980
7981 gsi = gsi_start_bb (else_bb);
7982 stmt = gimple_build_assign (tmp_var,
7983 build_int_cst (integer_type_node, -2));
7984 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
7985
7986 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
7987 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
7988 if (current_loops)
7989 {
7990 add_bb_to_loop (then_bb, cond_bb->loop_father);
7991 add_bb_to_loop (else_bb, cond_bb->loop_father);
7992 }
7993 make_edge (then_bb, new_bb, EDGE_FALLTHRU);
7994 make_edge (else_bb, new_bb, EDGE_FALLTHRU);
7995
7996 device = tmp_var;
7997 }
7998
7999 gsi = gsi_last_bb (new_bb);
8000 t = gimple_omp_target_data_arg (entry_stmt);
8001 if (t == NULL)
8002 {
8003 t1 = size_zero_node;
8004 t2 = build_zero_cst (ptr_type_node);
8005 t3 = t2;
8006 t4 = t2;
8007 }
8008 else
8009 {
8010 t1 = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (TREE_VEC_ELT (t, 1))));
8011 t1 = size_binop (PLUS_EXPR, t1, size_int (1));
8012 t2 = build_fold_addr_expr (TREE_VEC_ELT (t, 0));
8013 t3 = build_fold_addr_expr (TREE_VEC_ELT (t, 1));
8014 t4 = build_fold_addr_expr (TREE_VEC_ELT (t, 2));
8015 }
8016
8017 gimple g;
8018 /* FIXME: This will be address of
8019 extern char __OPENMP_TARGET__[] __attribute__((visibility ("hidden")))
8020 symbol, as soon as the linker plugin is able to create it for us. */
8021 tree openmp_target = build_zero_cst (ptr_type_node);
8022 if (kind == GF_OMP_TARGET_KIND_REGION)
8023 {
8024 tree fnaddr = build_fold_addr_expr (child_fn);
8025 g = gimple_build_call (builtin_decl_explicit (start_ix), 7,
8026 device, fnaddr, openmp_target, t1, t2, t3, t4);
8027 }
8028 else
8029 g = gimple_build_call (builtin_decl_explicit (start_ix), 6,
8030 device, openmp_target, t1, t2, t3, t4);
8031 gimple_set_location (g, gimple_location (entry_stmt));
8032 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
8033 if (kind != GF_OMP_TARGET_KIND_REGION)
8034 {
8035 g = gsi_stmt (gsi);
8036 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_TARGET);
8037 gsi_remove (&gsi, true);
8038 }
8039 if (kind == GF_OMP_TARGET_KIND_DATA && region->exit)
8040 {
8041 gsi = gsi_last_bb (region->exit);
8042 g = gsi_stmt (gsi);
8043 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_RETURN);
8044 gsi_remove (&gsi, true);
8045 }
8046 }
8047
8048
8049 /* Expand the parallel region tree rooted at REGION. Expansion
8050 proceeds in depth-first order. Innermost regions are expanded
8051 first. This way, parallel regions that require a new function to
8052 be created (e.g., GIMPLE_OMP_PARALLEL) can be expanded without having any
8053 internal dependencies in their body. */
8054
8055 static void
8056 expand_omp (struct omp_region *region)
8057 {
8058 while (region)
8059 {
8060 location_t saved_location;
8061 gimple inner_stmt = NULL;
8062
8063 /* First, determine whether this is a combined parallel+workshare
8064 region. */
8065 if (region->type == GIMPLE_OMP_PARALLEL)
8066 determine_parallel_type (region);
8067
8068 if (region->type == GIMPLE_OMP_FOR
8069 && gimple_omp_for_combined_p (last_stmt (region->entry)))
8070 inner_stmt = last_stmt (region->inner->entry);
8071
8072 if (region->inner)
8073 expand_omp (region->inner);
8074
8075 saved_location = input_location;
8076 if (gimple_has_location (last_stmt (region->entry)))
8077 input_location = gimple_location (last_stmt (region->entry));
8078
8079 switch (region->type)
8080 {
8081 case GIMPLE_OMP_PARALLEL:
8082 case GIMPLE_OMP_TASK:
8083 expand_omp_taskreg (region);
8084 break;
8085
8086 case GIMPLE_OMP_FOR:
8087 expand_omp_for (region, inner_stmt);
8088 break;
8089
8090 case GIMPLE_OMP_SECTIONS:
8091 expand_omp_sections (region);
8092 break;
8093
8094 case GIMPLE_OMP_SECTION:
8095 /* Individual omp sections are handled together with their
8096 parent GIMPLE_OMP_SECTIONS region. */
8097 break;
8098
8099 case GIMPLE_OMP_SINGLE:
8100 expand_omp_single (region);
8101 break;
8102
8103 case GIMPLE_OMP_MASTER:
8104 case GIMPLE_OMP_TASKGROUP:
8105 case GIMPLE_OMP_ORDERED:
8106 case GIMPLE_OMP_CRITICAL:
8107 case GIMPLE_OMP_TEAMS:
8108 expand_omp_synch (region);
8109 break;
8110
8111 case GIMPLE_OMP_ATOMIC_LOAD:
8112 expand_omp_atomic (region);
8113 break;
8114
8115 case GIMPLE_OMP_TARGET:
8116 expand_omp_target (region);
8117 break;
8118
8119 default:
8120 gcc_unreachable ();
8121 }
8122
8123 input_location = saved_location;
8124 region = region->next;
8125 }
8126 }
8127
8128
8129 /* Helper for build_omp_regions. Scan the dominator tree starting at
8130 block BB. PARENT is the region that contains BB. If SINGLE_TREE is
8131 true, the function ends once a single tree is built (otherwise, whole
8132 forest of OMP constructs may be built). */
8133
8134 static void
8135 build_omp_regions_1 (basic_block bb, struct omp_region *parent,
8136 bool single_tree)
8137 {
8138 gimple_stmt_iterator gsi;
8139 gimple stmt;
8140 basic_block son;
8141
8142 gsi = gsi_last_bb (bb);
8143 if (!gsi_end_p (gsi) && is_gimple_omp (gsi_stmt (gsi)))
8144 {
8145 struct omp_region *region;
8146 enum gimple_code code;
8147
8148 stmt = gsi_stmt (gsi);
8149 code = gimple_code (stmt);
8150 if (code == GIMPLE_OMP_RETURN)
8151 {
8152 /* STMT is the return point out of region PARENT. Mark it
8153 as the exit point and make PARENT the immediately
8154 enclosing region. */
8155 gcc_assert (parent);
8156 region = parent;
8157 region->exit = bb;
8158 parent = parent->outer;
8159 }
8160 else if (code == GIMPLE_OMP_ATOMIC_STORE)
8161 {
8162 /* GIMPLE_OMP_ATOMIC_STORE is analoguous to
8163 GIMPLE_OMP_RETURN, but matches with
8164 GIMPLE_OMP_ATOMIC_LOAD. */
8165 gcc_assert (parent);
8166 gcc_assert (parent->type == GIMPLE_OMP_ATOMIC_LOAD);
8167 region = parent;
8168 region->exit = bb;
8169 parent = parent->outer;
8170 }
8171
8172 else if (code == GIMPLE_OMP_CONTINUE)
8173 {
8174 gcc_assert (parent);
8175 parent->cont = bb;
8176 }
8177 else if (code == GIMPLE_OMP_SECTIONS_SWITCH)
8178 {
8179 /* GIMPLE_OMP_SECTIONS_SWITCH is part of
8180 GIMPLE_OMP_SECTIONS, and we do nothing for it. */
8181 ;
8182 }
8183 else if (code == GIMPLE_OMP_TARGET
8184 && gimple_omp_target_kind (stmt) == GF_OMP_TARGET_KIND_UPDATE)
8185 new_omp_region (bb, code, parent);
8186 else
8187 {
8188 /* Otherwise, this directive becomes the parent for a new
8189 region. */
8190 region = new_omp_region (bb, code, parent);
8191 parent = region;
8192 }
8193 }
8194
8195 if (single_tree && !parent)
8196 return;
8197
8198 for (son = first_dom_son (CDI_DOMINATORS, bb);
8199 son;
8200 son = next_dom_son (CDI_DOMINATORS, son))
8201 build_omp_regions_1 (son, parent, single_tree);
8202 }
8203
8204 /* Builds the tree of OMP regions rooted at ROOT, storing it to
8205 root_omp_region. */
8206
8207 static void
8208 build_omp_regions_root (basic_block root)
8209 {
8210 gcc_assert (root_omp_region == NULL);
8211 build_omp_regions_1 (root, NULL, true);
8212 gcc_assert (root_omp_region != NULL);
8213 }
8214
8215 /* Expands omp construct (and its subconstructs) starting in HEAD. */
8216
8217 void
8218 omp_expand_local (basic_block head)
8219 {
8220 build_omp_regions_root (head);
8221 if (dump_file && (dump_flags & TDF_DETAILS))
8222 {
8223 fprintf (dump_file, "\nOMP region tree\n\n");
8224 dump_omp_region (dump_file, root_omp_region, 0);
8225 fprintf (dump_file, "\n");
8226 }
8227
8228 remove_exit_barriers (root_omp_region);
8229 expand_omp (root_omp_region);
8230
8231 free_omp_regions ();
8232 }
8233
8234 /* Scan the CFG and build a tree of OMP regions. Return the root of
8235 the OMP region tree. */
8236
8237 static void
8238 build_omp_regions (void)
8239 {
8240 gcc_assert (root_omp_region == NULL);
8241 calculate_dominance_info (CDI_DOMINATORS);
8242 build_omp_regions_1 (ENTRY_BLOCK_PTR_FOR_FN (cfun), NULL, false);
8243 }
8244
8245 /* Main entry point for expanding OMP-GIMPLE into runtime calls. */
8246
8247 static unsigned int
8248 execute_expand_omp (void)
8249 {
8250 build_omp_regions ();
8251
8252 if (!root_omp_region)
8253 return 0;
8254
8255 if (dump_file)
8256 {
8257 fprintf (dump_file, "\nOMP region tree\n\n");
8258 dump_omp_region (dump_file, root_omp_region, 0);
8259 fprintf (dump_file, "\n");
8260 }
8261
8262 remove_exit_barriers (root_omp_region);
8263
8264 expand_omp (root_omp_region);
8265
8266 cleanup_tree_cfg ();
8267
8268 free_omp_regions ();
8269
8270 return 0;
8271 }
8272
8273 /* OMP expansion -- the default pass, run before creation of SSA form. */
8274
8275 static bool
8276 gate_expand_omp (void)
8277 {
8278 return ((flag_openmp != 0 || flag_openmp_simd != 0
8279 || flag_enable_cilkplus != 0) && !seen_error ());
8280 }
8281
8282 namespace {
8283
8284 const pass_data pass_data_expand_omp =
8285 {
8286 GIMPLE_PASS, /* type */
8287 "ompexp", /* name */
8288 OPTGROUP_NONE, /* optinfo_flags */
8289 true, /* has_gate */
8290 true, /* has_execute */
8291 TV_NONE, /* tv_id */
8292 PROP_gimple_any, /* properties_required */
8293 0, /* properties_provided */
8294 0, /* properties_destroyed */
8295 0, /* todo_flags_start */
8296 0, /* todo_flags_finish */
8297 };
8298
8299 class pass_expand_omp : public gimple_opt_pass
8300 {
8301 public:
8302 pass_expand_omp (gcc::context *ctxt)
8303 : gimple_opt_pass (pass_data_expand_omp, ctxt)
8304 {}
8305
8306 /* opt_pass methods: */
8307 bool gate () { return gate_expand_omp (); }
8308 unsigned int execute () { return execute_expand_omp (); }
8309
8310 }; // class pass_expand_omp
8311
8312 } // anon namespace
8313
8314 gimple_opt_pass *
8315 make_pass_expand_omp (gcc::context *ctxt)
8316 {
8317 return new pass_expand_omp (ctxt);
8318 }
8319 \f
8320 /* Routines to lower OpenMP directives into OMP-GIMPLE. */
8321
8322 /* If ctx is a worksharing context inside of a cancellable parallel
8323 region and it isn't nowait, add lhs to its GIMPLE_OMP_RETURN
8324 and conditional branch to parallel's cancel_label to handle
8325 cancellation in the implicit barrier. */
8326
8327 static void
8328 maybe_add_implicit_barrier_cancel (omp_context *ctx, gimple_seq *body)
8329 {
8330 gimple omp_return = gimple_seq_last_stmt (*body);
8331 gcc_assert (gimple_code (omp_return) == GIMPLE_OMP_RETURN);
8332 if (gimple_omp_return_nowait_p (omp_return))
8333 return;
8334 if (ctx->outer
8335 && gimple_code (ctx->outer->stmt) == GIMPLE_OMP_PARALLEL
8336 && ctx->outer->cancellable)
8337 {
8338 tree lhs = create_tmp_var (boolean_type_node, NULL);
8339 gimple_omp_return_set_lhs (omp_return, lhs);
8340 tree fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
8341 gimple g = gimple_build_cond (NE_EXPR, lhs, boolean_false_node,
8342 ctx->outer->cancel_label, fallthru_label);
8343 gimple_seq_add_stmt (body, g);
8344 gimple_seq_add_stmt (body, gimple_build_label (fallthru_label));
8345 }
8346 }
8347
8348 /* Lower the OpenMP sections directive in the current statement in GSI_P.
8349 CTX is the enclosing OMP context for the current statement. */
8350
8351 static void
8352 lower_omp_sections (gimple_stmt_iterator *gsi_p, omp_context *ctx)
8353 {
8354 tree block, control;
8355 gimple_stmt_iterator tgsi;
8356 gimple stmt, new_stmt, bind, t;
8357 gimple_seq ilist, dlist, olist, new_body;
8358
8359 stmt = gsi_stmt (*gsi_p);
8360
8361 push_gimplify_context ();
8362
8363 dlist = NULL;
8364 ilist = NULL;
8365 lower_rec_input_clauses (gimple_omp_sections_clauses (stmt),
8366 &ilist, &dlist, ctx, NULL);
8367
8368 new_body = gimple_omp_body (stmt);
8369 gimple_omp_set_body (stmt, NULL);
8370 tgsi = gsi_start (new_body);
8371 for (; !gsi_end_p (tgsi); gsi_next (&tgsi))
8372 {
8373 omp_context *sctx;
8374 gimple sec_start;
8375
8376 sec_start = gsi_stmt (tgsi);
8377 sctx = maybe_lookup_ctx (sec_start);
8378 gcc_assert (sctx);
8379
8380 lower_omp (gimple_omp_body_ptr (sec_start), sctx);
8381 gsi_insert_seq_after (&tgsi, gimple_omp_body (sec_start),
8382 GSI_CONTINUE_LINKING);
8383 gimple_omp_set_body (sec_start, NULL);
8384
8385 if (gsi_one_before_end_p (tgsi))
8386 {
8387 gimple_seq l = NULL;
8388 lower_lastprivate_clauses (gimple_omp_sections_clauses (stmt), NULL,
8389 &l, ctx);
8390 gsi_insert_seq_after (&tgsi, l, GSI_CONTINUE_LINKING);
8391 gimple_omp_section_set_last (sec_start);
8392 }
8393
8394 gsi_insert_after (&tgsi, gimple_build_omp_return (false),
8395 GSI_CONTINUE_LINKING);
8396 }
8397
8398 block = make_node (BLOCK);
8399 bind = gimple_build_bind (NULL, new_body, block);
8400
8401 olist = NULL;
8402 lower_reduction_clauses (gimple_omp_sections_clauses (stmt), &olist, ctx);
8403
8404 block = make_node (BLOCK);
8405 new_stmt = gimple_build_bind (NULL, NULL, block);
8406 gsi_replace (gsi_p, new_stmt, true);
8407
8408 pop_gimplify_context (new_stmt);
8409 gimple_bind_append_vars (new_stmt, ctx->block_vars);
8410 BLOCK_VARS (block) = gimple_bind_vars (bind);
8411 if (BLOCK_VARS (block))
8412 TREE_USED (block) = 1;
8413
8414 new_body = NULL;
8415 gimple_seq_add_seq (&new_body, ilist);
8416 gimple_seq_add_stmt (&new_body, stmt);
8417 gimple_seq_add_stmt (&new_body, gimple_build_omp_sections_switch ());
8418 gimple_seq_add_stmt (&new_body, bind);
8419
8420 control = create_tmp_var (unsigned_type_node, ".section");
8421 t = gimple_build_omp_continue (control, control);
8422 gimple_omp_sections_set_control (stmt, control);
8423 gimple_seq_add_stmt (&new_body, t);
8424
8425 gimple_seq_add_seq (&new_body, olist);
8426 if (ctx->cancellable)
8427 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
8428 gimple_seq_add_seq (&new_body, dlist);
8429
8430 new_body = maybe_catch_exception (new_body);
8431
8432 t = gimple_build_omp_return
8433 (!!find_omp_clause (gimple_omp_sections_clauses (stmt),
8434 OMP_CLAUSE_NOWAIT));
8435 gimple_seq_add_stmt (&new_body, t);
8436 maybe_add_implicit_barrier_cancel (ctx, &new_body);
8437
8438 gimple_bind_set_body (new_stmt, new_body);
8439 }
8440
8441
8442 /* A subroutine of lower_omp_single. Expand the simple form of
8443 a GIMPLE_OMP_SINGLE, without a copyprivate clause:
8444
8445 if (GOMP_single_start ())
8446 BODY;
8447 [ GOMP_barrier (); ] -> unless 'nowait' is present.
8448
8449 FIXME. It may be better to delay expanding the logic of this until
8450 pass_expand_omp. The expanded logic may make the job more difficult
8451 to a synchronization analysis pass. */
8452
8453 static void
8454 lower_omp_single_simple (gimple single_stmt, gimple_seq *pre_p)
8455 {
8456 location_t loc = gimple_location (single_stmt);
8457 tree tlabel = create_artificial_label (loc);
8458 tree flabel = create_artificial_label (loc);
8459 gimple call, cond;
8460 tree lhs, decl;
8461
8462 decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_START);
8463 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (decl)), NULL);
8464 call = gimple_build_call (decl, 0);
8465 gimple_call_set_lhs (call, lhs);
8466 gimple_seq_add_stmt (pre_p, call);
8467
8468 cond = gimple_build_cond (EQ_EXPR, lhs,
8469 fold_convert_loc (loc, TREE_TYPE (lhs),
8470 boolean_true_node),
8471 tlabel, flabel);
8472 gimple_seq_add_stmt (pre_p, cond);
8473 gimple_seq_add_stmt (pre_p, gimple_build_label (tlabel));
8474 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
8475 gimple_seq_add_stmt (pre_p, gimple_build_label (flabel));
8476 }
8477
8478
8479 /* A subroutine of lower_omp_single. Expand the simple form of
8480 a GIMPLE_OMP_SINGLE, with a copyprivate clause:
8481
8482 #pragma omp single copyprivate (a, b, c)
8483
8484 Create a new structure to hold copies of 'a', 'b' and 'c' and emit:
8485
8486 {
8487 if ((copyout_p = GOMP_single_copy_start ()) == NULL)
8488 {
8489 BODY;
8490 copyout.a = a;
8491 copyout.b = b;
8492 copyout.c = c;
8493 GOMP_single_copy_end (&copyout);
8494 }
8495 else
8496 {
8497 a = copyout_p->a;
8498 b = copyout_p->b;
8499 c = copyout_p->c;
8500 }
8501 GOMP_barrier ();
8502 }
8503
8504 FIXME. It may be better to delay expanding the logic of this until
8505 pass_expand_omp. The expanded logic may make the job more difficult
8506 to a synchronization analysis pass. */
8507
8508 static void
8509 lower_omp_single_copy (gimple single_stmt, gimple_seq *pre_p, omp_context *ctx)
8510 {
8511 tree ptr_type, t, l0, l1, l2, bfn_decl;
8512 gimple_seq copyin_seq;
8513 location_t loc = gimple_location (single_stmt);
8514
8515 ctx->sender_decl = create_tmp_var (ctx->record_type, ".omp_copy_o");
8516
8517 ptr_type = build_pointer_type (ctx->record_type);
8518 ctx->receiver_decl = create_tmp_var (ptr_type, ".omp_copy_i");
8519
8520 l0 = create_artificial_label (loc);
8521 l1 = create_artificial_label (loc);
8522 l2 = create_artificial_label (loc);
8523
8524 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_START);
8525 t = build_call_expr_loc (loc, bfn_decl, 0);
8526 t = fold_convert_loc (loc, ptr_type, t);
8527 gimplify_assign (ctx->receiver_decl, t, pre_p);
8528
8529 t = build2 (EQ_EXPR, boolean_type_node, ctx->receiver_decl,
8530 build_int_cst (ptr_type, 0));
8531 t = build3 (COND_EXPR, void_type_node, t,
8532 build_and_jump (&l0), build_and_jump (&l1));
8533 gimplify_and_add (t, pre_p);
8534
8535 gimple_seq_add_stmt (pre_p, gimple_build_label (l0));
8536
8537 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
8538
8539 copyin_seq = NULL;
8540 lower_copyprivate_clauses (gimple_omp_single_clauses (single_stmt), pre_p,
8541 &copyin_seq, ctx);
8542
8543 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
8544 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_END);
8545 t = build_call_expr_loc (loc, bfn_decl, 1, t);
8546 gimplify_and_add (t, pre_p);
8547
8548 t = build_and_jump (&l2);
8549 gimplify_and_add (t, pre_p);
8550
8551 gimple_seq_add_stmt (pre_p, gimple_build_label (l1));
8552
8553 gimple_seq_add_seq (pre_p, copyin_seq);
8554
8555 gimple_seq_add_stmt (pre_p, gimple_build_label (l2));
8556 }
8557
8558
8559 /* Expand code for an OpenMP single directive. */
8560
8561 static void
8562 lower_omp_single (gimple_stmt_iterator *gsi_p, omp_context *ctx)
8563 {
8564 tree block;
8565 gimple t, bind, single_stmt = gsi_stmt (*gsi_p);
8566 gimple_seq bind_body, bind_body_tail = NULL, dlist;
8567
8568 push_gimplify_context ();
8569
8570 block = make_node (BLOCK);
8571 bind = gimple_build_bind (NULL, NULL, block);
8572 gsi_replace (gsi_p, bind, true);
8573 bind_body = NULL;
8574 dlist = NULL;
8575 lower_rec_input_clauses (gimple_omp_single_clauses (single_stmt),
8576 &bind_body, &dlist, ctx, NULL);
8577 lower_omp (gimple_omp_body_ptr (single_stmt), ctx);
8578
8579 gimple_seq_add_stmt (&bind_body, single_stmt);
8580
8581 if (ctx->record_type)
8582 lower_omp_single_copy (single_stmt, &bind_body, ctx);
8583 else
8584 lower_omp_single_simple (single_stmt, &bind_body);
8585
8586 gimple_omp_set_body (single_stmt, NULL);
8587
8588 gimple_seq_add_seq (&bind_body, dlist);
8589
8590 bind_body = maybe_catch_exception (bind_body);
8591
8592 t = gimple_build_omp_return
8593 (!!find_omp_clause (gimple_omp_single_clauses (single_stmt),
8594 OMP_CLAUSE_NOWAIT));
8595 gimple_seq_add_stmt (&bind_body_tail, t);
8596 maybe_add_implicit_barrier_cancel (ctx, &bind_body_tail);
8597 if (ctx->record_type)
8598 {
8599 gimple_stmt_iterator gsi = gsi_start (bind_body_tail);
8600 tree clobber = build_constructor (ctx->record_type, NULL);
8601 TREE_THIS_VOLATILE (clobber) = 1;
8602 gsi_insert_after (&gsi, gimple_build_assign (ctx->sender_decl,
8603 clobber), GSI_SAME_STMT);
8604 }
8605 gimple_seq_add_seq (&bind_body, bind_body_tail);
8606 gimple_bind_set_body (bind, bind_body);
8607
8608 pop_gimplify_context (bind);
8609
8610 gimple_bind_append_vars (bind, ctx->block_vars);
8611 BLOCK_VARS (block) = ctx->block_vars;
8612 if (BLOCK_VARS (block))
8613 TREE_USED (block) = 1;
8614 }
8615
8616
8617 /* Expand code for an OpenMP master directive. */
8618
8619 static void
8620 lower_omp_master (gimple_stmt_iterator *gsi_p, omp_context *ctx)
8621 {
8622 tree block, lab = NULL, x, bfn_decl;
8623 gimple stmt = gsi_stmt (*gsi_p), bind;
8624 location_t loc = gimple_location (stmt);
8625 gimple_seq tseq;
8626
8627 push_gimplify_context ();
8628
8629 block = make_node (BLOCK);
8630 bind = gimple_build_bind (NULL, NULL, block);
8631 gsi_replace (gsi_p, bind, true);
8632 gimple_bind_add_stmt (bind, stmt);
8633
8634 bfn_decl = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
8635 x = build_call_expr_loc (loc, bfn_decl, 0);
8636 x = build2 (EQ_EXPR, boolean_type_node, x, integer_zero_node);
8637 x = build3 (COND_EXPR, void_type_node, x, NULL, build_and_jump (&lab));
8638 tseq = NULL;
8639 gimplify_and_add (x, &tseq);
8640 gimple_bind_add_seq (bind, tseq);
8641
8642 lower_omp (gimple_omp_body_ptr (stmt), ctx);
8643 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
8644 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
8645 gimple_omp_set_body (stmt, NULL);
8646
8647 gimple_bind_add_stmt (bind, gimple_build_label (lab));
8648
8649 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
8650
8651 pop_gimplify_context (bind);
8652
8653 gimple_bind_append_vars (bind, ctx->block_vars);
8654 BLOCK_VARS (block) = ctx->block_vars;
8655 }
8656
8657
8658 /* Expand code for an OpenMP taskgroup directive. */
8659
8660 static void
8661 lower_omp_taskgroup (gimple_stmt_iterator *gsi_p, omp_context *ctx)
8662 {
8663 gimple stmt = gsi_stmt (*gsi_p), bind, x;
8664 tree block = make_node (BLOCK);
8665
8666 bind = gimple_build_bind (NULL, NULL, block);
8667 gsi_replace (gsi_p, bind, true);
8668 gimple_bind_add_stmt (bind, stmt);
8669
8670 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_TASKGROUP_START),
8671 0);
8672 gimple_bind_add_stmt (bind, x);
8673
8674 lower_omp (gimple_omp_body_ptr (stmt), ctx);
8675 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
8676 gimple_omp_set_body (stmt, NULL);
8677
8678 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
8679
8680 gimple_bind_append_vars (bind, ctx->block_vars);
8681 BLOCK_VARS (block) = ctx->block_vars;
8682 }
8683
8684
8685 /* Expand code for an OpenMP ordered directive. */
8686
8687 static void
8688 lower_omp_ordered (gimple_stmt_iterator *gsi_p, omp_context *ctx)
8689 {
8690 tree block;
8691 gimple stmt = gsi_stmt (*gsi_p), bind, x;
8692
8693 push_gimplify_context ();
8694
8695 block = make_node (BLOCK);
8696 bind = gimple_build_bind (NULL, NULL, block);
8697 gsi_replace (gsi_p, bind, true);
8698 gimple_bind_add_stmt (bind, stmt);
8699
8700 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_START),
8701 0);
8702 gimple_bind_add_stmt (bind, x);
8703
8704 lower_omp (gimple_omp_body_ptr (stmt), ctx);
8705 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
8706 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
8707 gimple_omp_set_body (stmt, NULL);
8708
8709 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_END), 0);
8710 gimple_bind_add_stmt (bind, x);
8711
8712 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
8713
8714 pop_gimplify_context (bind);
8715
8716 gimple_bind_append_vars (bind, ctx->block_vars);
8717 BLOCK_VARS (block) = gimple_bind_vars (bind);
8718 }
8719
8720
8721 /* Gimplify a GIMPLE_OMP_CRITICAL statement. This is a relatively simple
8722 substitution of a couple of function calls. But in the NAMED case,
8723 requires that languages coordinate a symbol name. It is therefore
8724 best put here in common code. */
8725
8726 static GTY((param1_is (tree), param2_is (tree)))
8727 splay_tree critical_name_mutexes;
8728
8729 static void
8730 lower_omp_critical (gimple_stmt_iterator *gsi_p, omp_context *ctx)
8731 {
8732 tree block;
8733 tree name, lock, unlock;
8734 gimple stmt = gsi_stmt (*gsi_p), bind;
8735 location_t loc = gimple_location (stmt);
8736 gimple_seq tbody;
8737
8738 name = gimple_omp_critical_name (stmt);
8739 if (name)
8740 {
8741 tree decl;
8742 splay_tree_node n;
8743
8744 if (!critical_name_mutexes)
8745 critical_name_mutexes
8746 = splay_tree_new_ggc (splay_tree_compare_pointers,
8747 ggc_alloc_splay_tree_tree_node_tree_node_splay_tree_s,
8748 ggc_alloc_splay_tree_tree_node_tree_node_splay_tree_node_s);
8749
8750 n = splay_tree_lookup (critical_name_mutexes, (splay_tree_key) name);
8751 if (n == NULL)
8752 {
8753 char *new_str;
8754
8755 decl = create_tmp_var_raw (ptr_type_node, NULL);
8756
8757 new_str = ACONCAT ((".gomp_critical_user_",
8758 IDENTIFIER_POINTER (name), NULL));
8759 DECL_NAME (decl) = get_identifier (new_str);
8760 TREE_PUBLIC (decl) = 1;
8761 TREE_STATIC (decl) = 1;
8762 DECL_COMMON (decl) = 1;
8763 DECL_ARTIFICIAL (decl) = 1;
8764 DECL_IGNORED_P (decl) = 1;
8765 varpool_finalize_decl (decl);
8766
8767 splay_tree_insert (critical_name_mutexes, (splay_tree_key) name,
8768 (splay_tree_value) decl);
8769 }
8770 else
8771 decl = (tree) n->value;
8772
8773 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_START);
8774 lock = build_call_expr_loc (loc, lock, 1, build_fold_addr_expr_loc (loc, decl));
8775
8776 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_END);
8777 unlock = build_call_expr_loc (loc, unlock, 1,
8778 build_fold_addr_expr_loc (loc, decl));
8779 }
8780 else
8781 {
8782 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_START);
8783 lock = build_call_expr_loc (loc, lock, 0);
8784
8785 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_END);
8786 unlock = build_call_expr_loc (loc, unlock, 0);
8787 }
8788
8789 push_gimplify_context ();
8790
8791 block = make_node (BLOCK);
8792 bind = gimple_build_bind (NULL, NULL, block);
8793 gsi_replace (gsi_p, bind, true);
8794 gimple_bind_add_stmt (bind, stmt);
8795
8796 tbody = gimple_bind_body (bind);
8797 gimplify_and_add (lock, &tbody);
8798 gimple_bind_set_body (bind, tbody);
8799
8800 lower_omp (gimple_omp_body_ptr (stmt), ctx);
8801 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
8802 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
8803 gimple_omp_set_body (stmt, NULL);
8804
8805 tbody = gimple_bind_body (bind);
8806 gimplify_and_add (unlock, &tbody);
8807 gimple_bind_set_body (bind, tbody);
8808
8809 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
8810
8811 pop_gimplify_context (bind);
8812 gimple_bind_append_vars (bind, ctx->block_vars);
8813 BLOCK_VARS (block) = gimple_bind_vars (bind);
8814 }
8815
8816
8817 /* A subroutine of lower_omp_for. Generate code to emit the predicate
8818 for a lastprivate clause. Given a loop control predicate of (V
8819 cond N2), we gate the clause on (!(V cond N2)). The lowered form
8820 is appended to *DLIST, iterator initialization is appended to
8821 *BODY_P. */
8822
8823 static void
8824 lower_omp_for_lastprivate (struct omp_for_data *fd, gimple_seq *body_p,
8825 gimple_seq *dlist, struct omp_context *ctx)
8826 {
8827 tree clauses, cond, vinit;
8828 enum tree_code cond_code;
8829 gimple_seq stmts;
8830
8831 cond_code = fd->loop.cond_code;
8832 cond_code = cond_code == LT_EXPR ? GE_EXPR : LE_EXPR;
8833
8834 /* When possible, use a strict equality expression. This can let VRP
8835 type optimizations deduce the value and remove a copy. */
8836 if (tree_fits_shwi_p (fd->loop.step))
8837 {
8838 HOST_WIDE_INT step = tree_to_shwi (fd->loop.step);
8839 if (step == 1 || step == -1)
8840 cond_code = EQ_EXPR;
8841 }
8842
8843 cond = build2 (cond_code, boolean_type_node, fd->loop.v, fd->loop.n2);
8844
8845 clauses = gimple_omp_for_clauses (fd->for_stmt);
8846 stmts = NULL;
8847 lower_lastprivate_clauses (clauses, cond, &stmts, ctx);
8848 if (!gimple_seq_empty_p (stmts))
8849 {
8850 gimple_seq_add_seq (&stmts, *dlist);
8851 *dlist = stmts;
8852
8853 /* Optimize: v = 0; is usually cheaper than v = some_other_constant. */
8854 vinit = fd->loop.n1;
8855 if (cond_code == EQ_EXPR
8856 && tree_fits_shwi_p (fd->loop.n2)
8857 && ! integer_zerop (fd->loop.n2))
8858 vinit = build_int_cst (TREE_TYPE (fd->loop.v), 0);
8859 else
8860 vinit = unshare_expr (vinit);
8861
8862 /* Initialize the iterator variable, so that threads that don't execute
8863 any iterations don't execute the lastprivate clauses by accident. */
8864 gimplify_assign (fd->loop.v, vinit, body_p);
8865 }
8866 }
8867
8868
8869 /* Lower code for an OpenMP loop directive. */
8870
8871 static void
8872 lower_omp_for (gimple_stmt_iterator *gsi_p, omp_context *ctx)
8873 {
8874 tree *rhs_p, block;
8875 struct omp_for_data fd, *fdp = NULL;
8876 gimple stmt = gsi_stmt (*gsi_p), new_stmt;
8877 gimple_seq omp_for_body, body, dlist;
8878 size_t i;
8879
8880 push_gimplify_context ();
8881
8882 lower_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
8883
8884 block = make_node (BLOCK);
8885 new_stmt = gimple_build_bind (NULL, NULL, block);
8886 /* Replace at gsi right away, so that 'stmt' is no member
8887 of a sequence anymore as we're going to add to to a different
8888 one below. */
8889 gsi_replace (gsi_p, new_stmt, true);
8890
8891 /* Move declaration of temporaries in the loop body before we make
8892 it go away. */
8893 omp_for_body = gimple_omp_body (stmt);
8894 if (!gimple_seq_empty_p (omp_for_body)
8895 && gimple_code (gimple_seq_first_stmt (omp_for_body)) == GIMPLE_BIND)
8896 {
8897 tree vars = gimple_bind_vars (gimple_seq_first_stmt (omp_for_body));
8898 gimple_bind_append_vars (new_stmt, vars);
8899 }
8900
8901 if (gimple_omp_for_combined_into_p (stmt))
8902 {
8903 extract_omp_for_data (stmt, &fd, NULL);
8904 fdp = &fd;
8905
8906 /* We need two temporaries with fd.loop.v type (istart/iend)
8907 and then (fd.collapse - 1) temporaries with the same
8908 type for count2 ... countN-1 vars if not constant. */
8909 size_t count = 2;
8910 tree type = fd.iter_type;
8911 if (fd.collapse > 1
8912 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
8913 count += fd.collapse - 1;
8914 bool parallel_for = gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR;
8915 tree outerc = NULL, *pc = gimple_omp_for_clauses_ptr (stmt);
8916 tree clauses = *pc;
8917 if (parallel_for)
8918 outerc
8919 = find_omp_clause (gimple_omp_parallel_clauses (ctx->outer->stmt),
8920 OMP_CLAUSE__LOOPTEMP_);
8921 for (i = 0; i < count; i++)
8922 {
8923 tree temp;
8924 if (parallel_for)
8925 {
8926 gcc_assert (outerc);
8927 temp = lookup_decl (OMP_CLAUSE_DECL (outerc), ctx->outer);
8928 outerc = find_omp_clause (OMP_CLAUSE_CHAIN (outerc),
8929 OMP_CLAUSE__LOOPTEMP_);
8930 }
8931 else
8932 temp = create_tmp_var (type, NULL);
8933 *pc = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__LOOPTEMP_);
8934 OMP_CLAUSE_DECL (*pc) = temp;
8935 pc = &OMP_CLAUSE_CHAIN (*pc);
8936 }
8937 *pc = clauses;
8938 }
8939
8940 /* The pre-body and input clauses go before the lowered GIMPLE_OMP_FOR. */
8941 dlist = NULL;
8942 body = NULL;
8943 lower_rec_input_clauses (gimple_omp_for_clauses (stmt), &body, &dlist, ctx,
8944 fdp);
8945 gimple_seq_add_seq (&body, gimple_omp_for_pre_body (stmt));
8946
8947 lower_omp (gimple_omp_body_ptr (stmt), ctx);
8948
8949 /* Lower the header expressions. At this point, we can assume that
8950 the header is of the form:
8951
8952 #pragma omp for (V = VAL1; V {<|>|<=|>=} VAL2; V = V [+-] VAL3)
8953
8954 We just need to make sure that VAL1, VAL2 and VAL3 are lowered
8955 using the .omp_data_s mapping, if needed. */
8956 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
8957 {
8958 rhs_p = gimple_omp_for_initial_ptr (stmt, i);
8959 if (!is_gimple_min_invariant (*rhs_p))
8960 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
8961
8962 rhs_p = gimple_omp_for_final_ptr (stmt, i);
8963 if (!is_gimple_min_invariant (*rhs_p))
8964 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
8965
8966 rhs_p = &TREE_OPERAND (gimple_omp_for_incr (stmt, i), 1);
8967 if (!is_gimple_min_invariant (*rhs_p))
8968 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
8969 }
8970
8971 /* Once lowered, extract the bounds and clauses. */
8972 extract_omp_for_data (stmt, &fd, NULL);
8973
8974 lower_omp_for_lastprivate (&fd, &body, &dlist, ctx);
8975
8976 gimple_seq_add_stmt (&body, stmt);
8977 gimple_seq_add_seq (&body, gimple_omp_body (stmt));
8978
8979 gimple_seq_add_stmt (&body, gimple_build_omp_continue (fd.loop.v,
8980 fd.loop.v));
8981
8982 /* After the loop, add exit clauses. */
8983 lower_reduction_clauses (gimple_omp_for_clauses (stmt), &body, ctx);
8984
8985 if (ctx->cancellable)
8986 gimple_seq_add_stmt (&body, gimple_build_label (ctx->cancel_label));
8987
8988 gimple_seq_add_seq (&body, dlist);
8989
8990 body = maybe_catch_exception (body);
8991
8992 /* Region exit marker goes at the end of the loop body. */
8993 gimple_seq_add_stmt (&body, gimple_build_omp_return (fd.have_nowait));
8994 maybe_add_implicit_barrier_cancel (ctx, &body);
8995 pop_gimplify_context (new_stmt);
8996
8997 gimple_bind_append_vars (new_stmt, ctx->block_vars);
8998 BLOCK_VARS (block) = gimple_bind_vars (new_stmt);
8999 if (BLOCK_VARS (block))
9000 TREE_USED (block) = 1;
9001
9002 gimple_bind_set_body (new_stmt, body);
9003 gimple_omp_set_body (stmt, NULL);
9004 gimple_omp_for_set_pre_body (stmt, NULL);
9005 }
9006
9007 /* Callback for walk_stmts. Check if the current statement only contains
9008 GIMPLE_OMP_FOR or GIMPLE_OMP_PARALLEL. */
9009
9010 static tree
9011 check_combined_parallel (gimple_stmt_iterator *gsi_p,
9012 bool *handled_ops_p,
9013 struct walk_stmt_info *wi)
9014 {
9015 int *info = (int *) wi->info;
9016 gimple stmt = gsi_stmt (*gsi_p);
9017
9018 *handled_ops_p = true;
9019 switch (gimple_code (stmt))
9020 {
9021 WALK_SUBSTMTS;
9022
9023 case GIMPLE_OMP_FOR:
9024 case GIMPLE_OMP_SECTIONS:
9025 *info = *info == 0 ? 1 : -1;
9026 break;
9027 default:
9028 *info = -1;
9029 break;
9030 }
9031 return NULL;
9032 }
9033
9034 struct omp_taskcopy_context
9035 {
9036 /* This field must be at the beginning, as we do "inheritance": Some
9037 callback functions for tree-inline.c (e.g., omp_copy_decl)
9038 receive a copy_body_data pointer that is up-casted to an
9039 omp_context pointer. */
9040 copy_body_data cb;
9041 omp_context *ctx;
9042 };
9043
9044 static tree
9045 task_copyfn_copy_decl (tree var, copy_body_data *cb)
9046 {
9047 struct omp_taskcopy_context *tcctx = (struct omp_taskcopy_context *) cb;
9048
9049 if (splay_tree_lookup (tcctx->ctx->sfield_map, (splay_tree_key) var))
9050 return create_tmp_var (TREE_TYPE (var), NULL);
9051
9052 return var;
9053 }
9054
9055 static tree
9056 task_copyfn_remap_type (struct omp_taskcopy_context *tcctx, tree orig_type)
9057 {
9058 tree name, new_fields = NULL, type, f;
9059
9060 type = lang_hooks.types.make_type (RECORD_TYPE);
9061 name = DECL_NAME (TYPE_NAME (orig_type));
9062 name = build_decl (gimple_location (tcctx->ctx->stmt),
9063 TYPE_DECL, name, type);
9064 TYPE_NAME (type) = name;
9065
9066 for (f = TYPE_FIELDS (orig_type); f ; f = TREE_CHAIN (f))
9067 {
9068 tree new_f = copy_node (f);
9069 DECL_CONTEXT (new_f) = type;
9070 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &tcctx->cb);
9071 TREE_CHAIN (new_f) = new_fields;
9072 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &tcctx->cb, NULL);
9073 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r, &tcctx->cb, NULL);
9074 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
9075 &tcctx->cb, NULL);
9076 new_fields = new_f;
9077 *pointer_map_insert (tcctx->cb.decl_map, f) = new_f;
9078 }
9079 TYPE_FIELDS (type) = nreverse (new_fields);
9080 layout_type (type);
9081 return type;
9082 }
9083
9084 /* Create task copyfn. */
9085
9086 static void
9087 create_task_copyfn (gimple task_stmt, omp_context *ctx)
9088 {
9089 struct function *child_cfun;
9090 tree child_fn, t, c, src, dst, f, sf, arg, sarg, decl;
9091 tree record_type, srecord_type, bind, list;
9092 bool record_needs_remap = false, srecord_needs_remap = false;
9093 splay_tree_node n;
9094 struct omp_taskcopy_context tcctx;
9095 location_t loc = gimple_location (task_stmt);
9096
9097 child_fn = gimple_omp_task_copy_fn (task_stmt);
9098 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
9099 gcc_assert (child_cfun->cfg == NULL);
9100 DECL_SAVED_TREE (child_fn) = alloc_stmt_list ();
9101
9102 /* Reset DECL_CONTEXT on function arguments. */
9103 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
9104 DECL_CONTEXT (t) = child_fn;
9105
9106 /* Populate the function. */
9107 push_gimplify_context ();
9108 push_cfun (child_cfun);
9109
9110 bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
9111 TREE_SIDE_EFFECTS (bind) = 1;
9112 list = NULL;
9113 DECL_SAVED_TREE (child_fn) = bind;
9114 DECL_SOURCE_LOCATION (child_fn) = gimple_location (task_stmt);
9115
9116 /* Remap src and dst argument types if needed. */
9117 record_type = ctx->record_type;
9118 srecord_type = ctx->srecord_type;
9119 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
9120 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
9121 {
9122 record_needs_remap = true;
9123 break;
9124 }
9125 for (f = TYPE_FIELDS (srecord_type); f ; f = DECL_CHAIN (f))
9126 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
9127 {
9128 srecord_needs_remap = true;
9129 break;
9130 }
9131
9132 if (record_needs_remap || srecord_needs_remap)
9133 {
9134 memset (&tcctx, '\0', sizeof (tcctx));
9135 tcctx.cb.src_fn = ctx->cb.src_fn;
9136 tcctx.cb.dst_fn = child_fn;
9137 tcctx.cb.src_node = cgraph_get_node (tcctx.cb.src_fn);
9138 gcc_checking_assert (tcctx.cb.src_node);
9139 tcctx.cb.dst_node = tcctx.cb.src_node;
9140 tcctx.cb.src_cfun = ctx->cb.src_cfun;
9141 tcctx.cb.copy_decl = task_copyfn_copy_decl;
9142 tcctx.cb.eh_lp_nr = 0;
9143 tcctx.cb.transform_call_graph_edges = CB_CGE_MOVE;
9144 tcctx.cb.decl_map = pointer_map_create ();
9145 tcctx.ctx = ctx;
9146
9147 if (record_needs_remap)
9148 record_type = task_copyfn_remap_type (&tcctx, record_type);
9149 if (srecord_needs_remap)
9150 srecord_type = task_copyfn_remap_type (&tcctx, srecord_type);
9151 }
9152 else
9153 tcctx.cb.decl_map = NULL;
9154
9155 arg = DECL_ARGUMENTS (child_fn);
9156 TREE_TYPE (arg) = build_pointer_type (record_type);
9157 sarg = DECL_CHAIN (arg);
9158 TREE_TYPE (sarg) = build_pointer_type (srecord_type);
9159
9160 /* First pass: initialize temporaries used in record_type and srecord_type
9161 sizes and field offsets. */
9162 if (tcctx.cb.decl_map)
9163 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
9164 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
9165 {
9166 tree *p;
9167
9168 decl = OMP_CLAUSE_DECL (c);
9169 p = (tree *) pointer_map_contains (tcctx.cb.decl_map, decl);
9170 if (p == NULL)
9171 continue;
9172 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
9173 sf = (tree) n->value;
9174 sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
9175 src = build_simple_mem_ref_loc (loc, sarg);
9176 src = omp_build_component_ref (src, sf);
9177 t = build2 (MODIFY_EXPR, TREE_TYPE (*p), *p, src);
9178 append_to_statement_list (t, &list);
9179 }
9180
9181 /* Second pass: copy shared var pointers and copy construct non-VLA
9182 firstprivate vars. */
9183 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
9184 switch (OMP_CLAUSE_CODE (c))
9185 {
9186 case OMP_CLAUSE_SHARED:
9187 decl = OMP_CLAUSE_DECL (c);
9188 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
9189 if (n == NULL)
9190 break;
9191 f = (tree) n->value;
9192 if (tcctx.cb.decl_map)
9193 f = *(tree *) pointer_map_contains (tcctx.cb.decl_map, f);
9194 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
9195 sf = (tree) n->value;
9196 if (tcctx.cb.decl_map)
9197 sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
9198 src = build_simple_mem_ref_loc (loc, sarg);
9199 src = omp_build_component_ref (src, sf);
9200 dst = build_simple_mem_ref_loc (loc, arg);
9201 dst = omp_build_component_ref (dst, f);
9202 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
9203 append_to_statement_list (t, &list);
9204 break;
9205 case OMP_CLAUSE_FIRSTPRIVATE:
9206 decl = OMP_CLAUSE_DECL (c);
9207 if (is_variable_sized (decl))
9208 break;
9209 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
9210 if (n == NULL)
9211 break;
9212 f = (tree) n->value;
9213 if (tcctx.cb.decl_map)
9214 f = *(tree *) pointer_map_contains (tcctx.cb.decl_map, f);
9215 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
9216 if (n != NULL)
9217 {
9218 sf = (tree) n->value;
9219 if (tcctx.cb.decl_map)
9220 sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
9221 src = build_simple_mem_ref_loc (loc, sarg);
9222 src = omp_build_component_ref (src, sf);
9223 if (use_pointer_for_field (decl, NULL) || is_reference (decl))
9224 src = build_simple_mem_ref_loc (loc, src);
9225 }
9226 else
9227 src = decl;
9228 dst = build_simple_mem_ref_loc (loc, arg);
9229 dst = omp_build_component_ref (dst, f);
9230 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
9231 append_to_statement_list (t, &list);
9232 break;
9233 case OMP_CLAUSE_PRIVATE:
9234 if (! OMP_CLAUSE_PRIVATE_OUTER_REF (c))
9235 break;
9236 decl = OMP_CLAUSE_DECL (c);
9237 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
9238 f = (tree) n->value;
9239 if (tcctx.cb.decl_map)
9240 f = *(tree *) pointer_map_contains (tcctx.cb.decl_map, f);
9241 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
9242 if (n != NULL)
9243 {
9244 sf = (tree) n->value;
9245 if (tcctx.cb.decl_map)
9246 sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
9247 src = build_simple_mem_ref_loc (loc, sarg);
9248 src = omp_build_component_ref (src, sf);
9249 if (use_pointer_for_field (decl, NULL))
9250 src = build_simple_mem_ref_loc (loc, src);
9251 }
9252 else
9253 src = decl;
9254 dst = build_simple_mem_ref_loc (loc, arg);
9255 dst = omp_build_component_ref (dst, f);
9256 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
9257 append_to_statement_list (t, &list);
9258 break;
9259 default:
9260 break;
9261 }
9262
9263 /* Last pass: handle VLA firstprivates. */
9264 if (tcctx.cb.decl_map)
9265 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
9266 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
9267 {
9268 tree ind, ptr, df;
9269
9270 decl = OMP_CLAUSE_DECL (c);
9271 if (!is_variable_sized (decl))
9272 continue;
9273 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
9274 if (n == NULL)
9275 continue;
9276 f = (tree) n->value;
9277 f = *(tree *) pointer_map_contains (tcctx.cb.decl_map, f);
9278 gcc_assert (DECL_HAS_VALUE_EXPR_P (decl));
9279 ind = DECL_VALUE_EXPR (decl);
9280 gcc_assert (TREE_CODE (ind) == INDIRECT_REF);
9281 gcc_assert (DECL_P (TREE_OPERAND (ind, 0)));
9282 n = splay_tree_lookup (ctx->sfield_map,
9283 (splay_tree_key) TREE_OPERAND (ind, 0));
9284 sf = (tree) n->value;
9285 sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
9286 src = build_simple_mem_ref_loc (loc, sarg);
9287 src = omp_build_component_ref (src, sf);
9288 src = build_simple_mem_ref_loc (loc, src);
9289 dst = build_simple_mem_ref_loc (loc, arg);
9290 dst = omp_build_component_ref (dst, f);
9291 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
9292 append_to_statement_list (t, &list);
9293 n = splay_tree_lookup (ctx->field_map,
9294 (splay_tree_key) TREE_OPERAND (ind, 0));
9295 df = (tree) n->value;
9296 df = *(tree *) pointer_map_contains (tcctx.cb.decl_map, df);
9297 ptr = build_simple_mem_ref_loc (loc, arg);
9298 ptr = omp_build_component_ref (ptr, df);
9299 t = build2 (MODIFY_EXPR, TREE_TYPE (ptr), ptr,
9300 build_fold_addr_expr_loc (loc, dst));
9301 append_to_statement_list (t, &list);
9302 }
9303
9304 t = build1 (RETURN_EXPR, void_type_node, NULL);
9305 append_to_statement_list (t, &list);
9306
9307 if (tcctx.cb.decl_map)
9308 pointer_map_destroy (tcctx.cb.decl_map);
9309 pop_gimplify_context (NULL);
9310 BIND_EXPR_BODY (bind) = list;
9311 pop_cfun ();
9312 }
9313
9314 static void
9315 lower_depend_clauses (gimple stmt, gimple_seq *iseq, gimple_seq *oseq)
9316 {
9317 tree c, clauses;
9318 gimple g;
9319 size_t n_in = 0, n_out = 0, idx = 2, i;
9320
9321 clauses = find_omp_clause (gimple_omp_task_clauses (stmt),
9322 OMP_CLAUSE_DEPEND);
9323 gcc_assert (clauses);
9324 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
9325 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
9326 switch (OMP_CLAUSE_DEPEND_KIND (c))
9327 {
9328 case OMP_CLAUSE_DEPEND_IN:
9329 n_in++;
9330 break;
9331 case OMP_CLAUSE_DEPEND_OUT:
9332 case OMP_CLAUSE_DEPEND_INOUT:
9333 n_out++;
9334 break;
9335 default:
9336 gcc_unreachable ();
9337 }
9338 tree type = build_array_type_nelts (ptr_type_node, n_in + n_out + 2);
9339 tree array = create_tmp_var (type, NULL);
9340 tree r = build4 (ARRAY_REF, ptr_type_node, array, size_int (0), NULL_TREE,
9341 NULL_TREE);
9342 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_in + n_out));
9343 gimple_seq_add_stmt (iseq, g);
9344 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (1), NULL_TREE,
9345 NULL_TREE);
9346 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_out));
9347 gimple_seq_add_stmt (iseq, g);
9348 for (i = 0; i < 2; i++)
9349 {
9350 if ((i ? n_in : n_out) == 0)
9351 continue;
9352 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
9353 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
9354 && ((OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_IN) ^ i))
9355 {
9356 tree t = OMP_CLAUSE_DECL (c);
9357 t = fold_convert (ptr_type_node, t);
9358 gimplify_expr (&t, iseq, NULL, is_gimple_val, fb_rvalue);
9359 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (idx++),
9360 NULL_TREE, NULL_TREE);
9361 g = gimple_build_assign (r, t);
9362 gimple_seq_add_stmt (iseq, g);
9363 }
9364 }
9365 tree *p = gimple_omp_task_clauses_ptr (stmt);
9366 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_DEPEND);
9367 OMP_CLAUSE_DECL (c) = build_fold_addr_expr (array);
9368 OMP_CLAUSE_CHAIN (c) = *p;
9369 *p = c;
9370 tree clobber = build_constructor (type, NULL);
9371 TREE_THIS_VOLATILE (clobber) = 1;
9372 g = gimple_build_assign (array, clobber);
9373 gimple_seq_add_stmt (oseq, g);
9374 }
9375
9376 /* Lower the OpenMP parallel or task directive in the current statement
9377 in GSI_P. CTX holds context information for the directive. */
9378
9379 static void
9380 lower_omp_taskreg (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9381 {
9382 tree clauses;
9383 tree child_fn, t;
9384 gimple stmt = gsi_stmt (*gsi_p);
9385 gimple par_bind, bind, dep_bind = NULL;
9386 gimple_seq par_body, olist, ilist, par_olist, par_rlist, par_ilist, new_body;
9387 location_t loc = gimple_location (stmt);
9388
9389 clauses = gimple_omp_taskreg_clauses (stmt);
9390 par_bind = gimple_seq_first_stmt (gimple_omp_body (stmt));
9391 par_body = gimple_bind_body (par_bind);
9392 child_fn = ctx->cb.dst_fn;
9393 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
9394 && !gimple_omp_parallel_combined_p (stmt))
9395 {
9396 struct walk_stmt_info wi;
9397 int ws_num = 0;
9398
9399 memset (&wi, 0, sizeof (wi));
9400 wi.info = &ws_num;
9401 wi.val_only = true;
9402 walk_gimple_seq (par_body, check_combined_parallel, NULL, &wi);
9403 if (ws_num == 1)
9404 gimple_omp_parallel_set_combined_p (stmt, true);
9405 }
9406 gimple_seq dep_ilist = NULL;
9407 gimple_seq dep_olist = NULL;
9408 if (gimple_code (stmt) == GIMPLE_OMP_TASK
9409 && find_omp_clause (clauses, OMP_CLAUSE_DEPEND))
9410 {
9411 push_gimplify_context ();
9412 dep_bind = gimple_build_bind (NULL, NULL, make_node (BLOCK));
9413 lower_depend_clauses (stmt, &dep_ilist, &dep_olist);
9414 }
9415
9416 if (ctx->srecord_type)
9417 create_task_copyfn (stmt, ctx);
9418
9419 push_gimplify_context ();
9420
9421 par_olist = NULL;
9422 par_ilist = NULL;
9423 par_rlist = NULL;
9424 lower_rec_input_clauses (clauses, &par_ilist, &par_olist, ctx, NULL);
9425 lower_omp (&par_body, ctx);
9426 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL)
9427 lower_reduction_clauses (clauses, &par_rlist, ctx);
9428
9429 /* Declare all the variables created by mapping and the variables
9430 declared in the scope of the parallel body. */
9431 record_vars_into (ctx->block_vars, child_fn);
9432 record_vars_into (gimple_bind_vars (par_bind), child_fn);
9433
9434 if (ctx->record_type)
9435 {
9436 ctx->sender_decl
9437 = create_tmp_var (ctx->srecord_type ? ctx->srecord_type
9438 : ctx->record_type, ".omp_data_o");
9439 DECL_NAMELESS (ctx->sender_decl) = 1;
9440 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
9441 gimple_omp_taskreg_set_data_arg (stmt, ctx->sender_decl);
9442 }
9443
9444 olist = NULL;
9445 ilist = NULL;
9446 lower_send_clauses (clauses, &ilist, &olist, ctx);
9447 lower_send_shared_vars (&ilist, &olist, ctx);
9448
9449 if (ctx->record_type)
9450 {
9451 tree clobber = build_constructor (TREE_TYPE (ctx->sender_decl), NULL);
9452 TREE_THIS_VOLATILE (clobber) = 1;
9453 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
9454 clobber));
9455 }
9456
9457 /* Once all the expansions are done, sequence all the different
9458 fragments inside gimple_omp_body. */
9459
9460 new_body = NULL;
9461
9462 if (ctx->record_type)
9463 {
9464 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
9465 /* fixup_child_record_type might have changed receiver_decl's type. */
9466 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
9467 gimple_seq_add_stmt (&new_body,
9468 gimple_build_assign (ctx->receiver_decl, t));
9469 }
9470
9471 gimple_seq_add_seq (&new_body, par_ilist);
9472 gimple_seq_add_seq (&new_body, par_body);
9473 gimple_seq_add_seq (&new_body, par_rlist);
9474 if (ctx->cancellable)
9475 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
9476 gimple_seq_add_seq (&new_body, par_olist);
9477 new_body = maybe_catch_exception (new_body);
9478 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
9479 gimple_omp_set_body (stmt, new_body);
9480
9481 bind = gimple_build_bind (NULL, NULL, gimple_bind_block (par_bind));
9482 gsi_replace (gsi_p, dep_bind ? dep_bind : bind, true);
9483 gimple_bind_add_seq (bind, ilist);
9484 gimple_bind_add_stmt (bind, stmt);
9485 gimple_bind_add_seq (bind, olist);
9486
9487 pop_gimplify_context (NULL);
9488
9489 if (dep_bind)
9490 {
9491 gimple_bind_add_seq (dep_bind, dep_ilist);
9492 gimple_bind_add_stmt (dep_bind, bind);
9493 gimple_bind_add_seq (dep_bind, dep_olist);
9494 pop_gimplify_context (dep_bind);
9495 }
9496 }
9497
9498 /* Lower the OpenMP target directive in the current statement
9499 in GSI_P. CTX holds context information for the directive. */
9500
9501 static void
9502 lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9503 {
9504 tree clauses;
9505 tree child_fn, t, c;
9506 gimple stmt = gsi_stmt (*gsi_p);
9507 gimple tgt_bind = NULL, bind;
9508 gimple_seq tgt_body = NULL, olist, ilist, new_body;
9509 location_t loc = gimple_location (stmt);
9510 int kind = gimple_omp_target_kind (stmt);
9511 unsigned int map_cnt = 0;
9512
9513 clauses = gimple_omp_target_clauses (stmt);
9514 if (kind == GF_OMP_TARGET_KIND_REGION)
9515 {
9516 tgt_bind = gimple_seq_first_stmt (gimple_omp_body (stmt));
9517 tgt_body = gimple_bind_body (tgt_bind);
9518 }
9519 else if (kind == GF_OMP_TARGET_KIND_DATA)
9520 tgt_body = gimple_omp_body (stmt);
9521 child_fn = ctx->cb.dst_fn;
9522
9523 push_gimplify_context ();
9524
9525 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
9526 switch (OMP_CLAUSE_CODE (c))
9527 {
9528 tree var, x;
9529
9530 default:
9531 break;
9532 case OMP_CLAUSE_MAP:
9533 case OMP_CLAUSE_TO:
9534 case OMP_CLAUSE_FROM:
9535 var = OMP_CLAUSE_DECL (c);
9536 if (!DECL_P (var))
9537 {
9538 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP
9539 || !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
9540 map_cnt++;
9541 continue;
9542 }
9543
9544 if (DECL_SIZE (var)
9545 && TREE_CODE (DECL_SIZE (var)) != INTEGER_CST)
9546 {
9547 tree var2 = DECL_VALUE_EXPR (var);
9548 gcc_assert (TREE_CODE (var2) == INDIRECT_REF);
9549 var2 = TREE_OPERAND (var2, 0);
9550 gcc_assert (DECL_P (var2));
9551 var = var2;
9552 }
9553
9554 if (!maybe_lookup_field (var, ctx))
9555 continue;
9556
9557 if (kind == GF_OMP_TARGET_KIND_REGION)
9558 {
9559 x = build_receiver_ref (var, true, ctx);
9560 tree new_var = lookup_decl (var, ctx);
9561 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
9562 && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER
9563 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
9564 && TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
9565 x = build_simple_mem_ref (x);
9566 SET_DECL_VALUE_EXPR (new_var, x);
9567 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
9568 }
9569 map_cnt++;
9570 }
9571
9572 if (kind == GF_OMP_TARGET_KIND_REGION)
9573 {
9574 target_nesting_level++;
9575 lower_omp (&tgt_body, ctx);
9576 target_nesting_level--;
9577 }
9578 else if (kind == GF_OMP_TARGET_KIND_DATA)
9579 lower_omp (&tgt_body, ctx);
9580
9581 if (kind == GF_OMP_TARGET_KIND_REGION)
9582 {
9583 /* Declare all the variables created by mapping and the variables
9584 declared in the scope of the target body. */
9585 record_vars_into (ctx->block_vars, child_fn);
9586 record_vars_into (gimple_bind_vars (tgt_bind), child_fn);
9587 }
9588
9589 olist = NULL;
9590 ilist = NULL;
9591 if (ctx->record_type)
9592 {
9593 ctx->sender_decl
9594 = create_tmp_var (ctx->record_type, ".omp_data_arr");
9595 DECL_NAMELESS (ctx->sender_decl) = 1;
9596 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
9597 t = make_tree_vec (3);
9598 TREE_VEC_ELT (t, 0) = ctx->sender_decl;
9599 TREE_VEC_ELT (t, 1)
9600 = create_tmp_var (build_array_type_nelts (size_type_node, map_cnt),
9601 ".omp_data_sizes");
9602 DECL_NAMELESS (TREE_VEC_ELT (t, 1)) = 1;
9603 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 1)) = 1;
9604 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 1;
9605 TREE_VEC_ELT (t, 2)
9606 = create_tmp_var (build_array_type_nelts (unsigned_char_type_node,
9607 map_cnt),
9608 ".omp_data_kinds");
9609 DECL_NAMELESS (TREE_VEC_ELT (t, 2)) = 1;
9610 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 2)) = 1;
9611 TREE_STATIC (TREE_VEC_ELT (t, 2)) = 1;
9612 gimple_omp_target_set_data_arg (stmt, t);
9613
9614 vec<constructor_elt, va_gc> *vsize;
9615 vec<constructor_elt, va_gc> *vkind;
9616 vec_alloc (vsize, map_cnt);
9617 vec_alloc (vkind, map_cnt);
9618 unsigned int map_idx = 0;
9619
9620 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
9621 switch (OMP_CLAUSE_CODE (c))
9622 {
9623 tree ovar, nc;
9624
9625 default:
9626 break;
9627 case OMP_CLAUSE_MAP:
9628 case OMP_CLAUSE_TO:
9629 case OMP_CLAUSE_FROM:
9630 nc = c;
9631 ovar = OMP_CLAUSE_DECL (c);
9632 if (!DECL_P (ovar))
9633 {
9634 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
9635 && OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
9636 {
9637 gcc_checking_assert (OMP_CLAUSE_DECL (OMP_CLAUSE_CHAIN (c))
9638 == get_base_address (ovar));
9639 nc = OMP_CLAUSE_CHAIN (c);
9640 ovar = OMP_CLAUSE_DECL (nc);
9641 }
9642 else
9643 {
9644 tree x = build_sender_ref (ovar, ctx);
9645 tree v
9646 = build_fold_addr_expr_with_type (ovar, ptr_type_node);
9647 gimplify_assign (x, v, &ilist);
9648 nc = NULL_TREE;
9649 }
9650 }
9651 else
9652 {
9653 if (DECL_SIZE (ovar)
9654 && TREE_CODE (DECL_SIZE (ovar)) != INTEGER_CST)
9655 {
9656 tree ovar2 = DECL_VALUE_EXPR (ovar);
9657 gcc_assert (TREE_CODE (ovar2) == INDIRECT_REF);
9658 ovar2 = TREE_OPERAND (ovar2, 0);
9659 gcc_assert (DECL_P (ovar2));
9660 ovar = ovar2;
9661 }
9662 if (!maybe_lookup_field (ovar, ctx))
9663 continue;
9664 }
9665
9666 if (nc)
9667 {
9668 tree var = lookup_decl_in_outer_ctx (ovar, ctx);
9669 tree x = build_sender_ref (ovar, ctx);
9670 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
9671 && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER
9672 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
9673 && TREE_CODE (TREE_TYPE (ovar)) == ARRAY_TYPE)
9674 {
9675 gcc_assert (kind == GF_OMP_TARGET_KIND_REGION);
9676 tree avar
9677 = create_tmp_var (TREE_TYPE (TREE_TYPE (x)), NULL);
9678 mark_addressable (avar);
9679 gimplify_assign (avar, build_fold_addr_expr (var), &ilist);
9680 avar = build_fold_addr_expr (avar);
9681 gimplify_assign (x, avar, &ilist);
9682 }
9683 else if (is_gimple_reg (var))
9684 {
9685 gcc_assert (kind == GF_OMP_TARGET_KIND_REGION);
9686 tree avar = create_tmp_var (TREE_TYPE (var), NULL);
9687 mark_addressable (avar);
9688 if (OMP_CLAUSE_MAP_KIND (c) != OMP_CLAUSE_MAP_ALLOC
9689 && OMP_CLAUSE_MAP_KIND (c) != OMP_CLAUSE_MAP_FROM)
9690 gimplify_assign (avar, var, &ilist);
9691 avar = build_fold_addr_expr (avar);
9692 gimplify_assign (x, avar, &ilist);
9693 if ((OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_FROM
9694 || OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_TOFROM)
9695 && !TYPE_READONLY (TREE_TYPE (var)))
9696 {
9697 x = build_sender_ref (ovar, ctx);
9698 x = build_simple_mem_ref (x);
9699 gimplify_assign (var, x, &olist);
9700 }
9701 }
9702 else
9703 {
9704 var = build_fold_addr_expr (var);
9705 gimplify_assign (x, var, &ilist);
9706 }
9707 }
9708 tree s = OMP_CLAUSE_SIZE (c);
9709 if (s == NULL_TREE)
9710 s = TYPE_SIZE_UNIT (TREE_TYPE (ovar));
9711 s = fold_convert (size_type_node, s);
9712 tree purpose = size_int (map_idx++);
9713 CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
9714 if (TREE_CODE (s) != INTEGER_CST)
9715 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 0;
9716
9717 unsigned char tkind = 0;
9718 switch (OMP_CLAUSE_CODE (c))
9719 {
9720 case OMP_CLAUSE_MAP:
9721 tkind = OMP_CLAUSE_MAP_KIND (c);
9722 break;
9723 case OMP_CLAUSE_TO:
9724 tkind = OMP_CLAUSE_MAP_TO;
9725 break;
9726 case OMP_CLAUSE_FROM:
9727 tkind = OMP_CLAUSE_MAP_FROM;
9728 break;
9729 default:
9730 gcc_unreachable ();
9731 }
9732 unsigned int talign = TYPE_ALIGN_UNIT (TREE_TYPE (ovar));
9733 if (DECL_P (ovar) && DECL_ALIGN_UNIT (ovar) > talign)
9734 talign = DECL_ALIGN_UNIT (ovar);
9735 talign = ceil_log2 (talign);
9736 tkind |= talign << 3;
9737 CONSTRUCTOR_APPEND_ELT (vkind, purpose,
9738 build_int_cst (unsigned_char_type_node,
9739 tkind));
9740 if (nc && nc != c)
9741 c = nc;
9742 }
9743
9744 gcc_assert (map_idx == map_cnt);
9745
9746 DECL_INITIAL (TREE_VEC_ELT (t, 1))
9747 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)), vsize);
9748 DECL_INITIAL (TREE_VEC_ELT (t, 2))
9749 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 2)), vkind);
9750 if (!TREE_STATIC (TREE_VEC_ELT (t, 1)))
9751 {
9752 gimple_seq initlist = NULL;
9753 force_gimple_operand (build1 (DECL_EXPR, void_type_node,
9754 TREE_VEC_ELT (t, 1)),
9755 &initlist, true, NULL_TREE);
9756 gimple_seq_add_seq (&ilist, initlist);
9757 }
9758
9759 tree clobber = build_constructor (ctx->record_type, NULL);
9760 TREE_THIS_VOLATILE (clobber) = 1;
9761 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
9762 clobber));
9763 }
9764
9765 /* Once all the expansions are done, sequence all the different
9766 fragments inside gimple_omp_body. */
9767
9768 new_body = NULL;
9769
9770 if (ctx->record_type && kind == GF_OMP_TARGET_KIND_REGION)
9771 {
9772 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
9773 /* fixup_child_record_type might have changed receiver_decl's type. */
9774 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
9775 gimple_seq_add_stmt (&new_body,
9776 gimple_build_assign (ctx->receiver_decl, t));
9777 }
9778
9779 if (kind == GF_OMP_TARGET_KIND_REGION)
9780 {
9781 gimple_seq_add_seq (&new_body, tgt_body);
9782 new_body = maybe_catch_exception (new_body);
9783 }
9784 else if (kind == GF_OMP_TARGET_KIND_DATA)
9785 new_body = tgt_body;
9786 if (kind != GF_OMP_TARGET_KIND_UPDATE)
9787 {
9788 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
9789 gimple_omp_set_body (stmt, new_body);
9790 }
9791
9792 bind = gimple_build_bind (NULL, NULL,
9793 tgt_bind ? gimple_bind_block (tgt_bind)
9794 : NULL_TREE);
9795 gsi_replace (gsi_p, bind, true);
9796 gimple_bind_add_seq (bind, ilist);
9797 gimple_bind_add_stmt (bind, stmt);
9798 gimple_bind_add_seq (bind, olist);
9799
9800 pop_gimplify_context (NULL);
9801 }
9802
9803 /* Expand code for an OpenMP teams directive. */
9804
9805 static void
9806 lower_omp_teams (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9807 {
9808 gimple teams_stmt = gsi_stmt (*gsi_p);
9809 push_gimplify_context ();
9810
9811 tree block = make_node (BLOCK);
9812 gimple bind = gimple_build_bind (NULL, NULL, block);
9813 gsi_replace (gsi_p, bind, true);
9814 gimple_seq bind_body = NULL;
9815 gimple_seq dlist = NULL;
9816 gimple_seq olist = NULL;
9817
9818 tree num_teams = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
9819 OMP_CLAUSE_NUM_TEAMS);
9820 if (num_teams == NULL_TREE)
9821 num_teams = build_int_cst (unsigned_type_node, 0);
9822 else
9823 {
9824 num_teams = OMP_CLAUSE_NUM_TEAMS_EXPR (num_teams);
9825 num_teams = fold_convert (unsigned_type_node, num_teams);
9826 gimplify_expr (&num_teams, &bind_body, NULL, is_gimple_val, fb_rvalue);
9827 }
9828 tree thread_limit = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
9829 OMP_CLAUSE_THREAD_LIMIT);
9830 if (thread_limit == NULL_TREE)
9831 thread_limit = build_int_cst (unsigned_type_node, 0);
9832 else
9833 {
9834 thread_limit = OMP_CLAUSE_THREAD_LIMIT_EXPR (thread_limit);
9835 thread_limit = fold_convert (unsigned_type_node, thread_limit);
9836 gimplify_expr (&thread_limit, &bind_body, NULL, is_gimple_val,
9837 fb_rvalue);
9838 }
9839
9840 lower_rec_input_clauses (gimple_omp_teams_clauses (teams_stmt),
9841 &bind_body, &dlist, ctx, NULL);
9842 lower_omp (gimple_omp_body_ptr (teams_stmt), ctx);
9843 lower_reduction_clauses (gimple_omp_teams_clauses (teams_stmt), &olist, ctx);
9844 gimple_seq_add_stmt (&bind_body, teams_stmt);
9845
9846 location_t loc = gimple_location (teams_stmt);
9847 tree decl = builtin_decl_explicit (BUILT_IN_GOMP_TEAMS);
9848 gimple call = gimple_build_call (decl, 2, num_teams, thread_limit);
9849 gimple_set_location (call, loc);
9850 gimple_seq_add_stmt (&bind_body, call);
9851
9852 gimple_seq_add_seq (&bind_body, gimple_omp_body (teams_stmt));
9853 gimple_omp_set_body (teams_stmt, NULL);
9854 gimple_seq_add_seq (&bind_body, olist);
9855 gimple_seq_add_seq (&bind_body, dlist);
9856 gimple_seq_add_stmt (&bind_body, gimple_build_omp_return (true));
9857 gimple_bind_set_body (bind, bind_body);
9858
9859 pop_gimplify_context (bind);
9860
9861 gimple_bind_append_vars (bind, ctx->block_vars);
9862 BLOCK_VARS (block) = ctx->block_vars;
9863 if (BLOCK_VARS (block))
9864 TREE_USED (block) = 1;
9865 }
9866
9867
9868 /* Callback for lower_omp_1. Return non-NULL if *tp needs to be
9869 regimplified. If DATA is non-NULL, lower_omp_1 is outside
9870 of OpenMP context, but with task_shared_vars set. */
9871
9872 static tree
9873 lower_omp_regimplify_p (tree *tp, int *walk_subtrees,
9874 void *data)
9875 {
9876 tree t = *tp;
9877
9878 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
9879 if (TREE_CODE (t) == VAR_DECL && data == NULL && DECL_HAS_VALUE_EXPR_P (t))
9880 return t;
9881
9882 if (task_shared_vars
9883 && DECL_P (t)
9884 && bitmap_bit_p (task_shared_vars, DECL_UID (t)))
9885 return t;
9886
9887 /* If a global variable has been privatized, TREE_CONSTANT on
9888 ADDR_EXPR might be wrong. */
9889 if (data == NULL && TREE_CODE (t) == ADDR_EXPR)
9890 recompute_tree_invariant_for_addr_expr (t);
9891
9892 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
9893 return NULL_TREE;
9894 }
9895
9896 static void
9897 lower_omp_1 (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9898 {
9899 gimple stmt = gsi_stmt (*gsi_p);
9900 struct walk_stmt_info wi;
9901
9902 if (gimple_has_location (stmt))
9903 input_location = gimple_location (stmt);
9904
9905 if (task_shared_vars)
9906 memset (&wi, '\0', sizeof (wi));
9907
9908 /* If we have issued syntax errors, avoid doing any heavy lifting.
9909 Just replace the OpenMP directives with a NOP to avoid
9910 confusing RTL expansion. */
9911 if (seen_error () && is_gimple_omp (stmt))
9912 {
9913 gsi_replace (gsi_p, gimple_build_nop (), true);
9914 return;
9915 }
9916
9917 switch (gimple_code (stmt))
9918 {
9919 case GIMPLE_COND:
9920 if ((ctx || task_shared_vars)
9921 && (walk_tree (gimple_cond_lhs_ptr (stmt), lower_omp_regimplify_p,
9922 ctx ? NULL : &wi, NULL)
9923 || walk_tree (gimple_cond_rhs_ptr (stmt), lower_omp_regimplify_p,
9924 ctx ? NULL : &wi, NULL)))
9925 gimple_regimplify_operands (stmt, gsi_p);
9926 break;
9927 case GIMPLE_CATCH:
9928 lower_omp (gimple_catch_handler_ptr (stmt), ctx);
9929 break;
9930 case GIMPLE_EH_FILTER:
9931 lower_omp (gimple_eh_filter_failure_ptr (stmt), ctx);
9932 break;
9933 case GIMPLE_TRY:
9934 lower_omp (gimple_try_eval_ptr (stmt), ctx);
9935 lower_omp (gimple_try_cleanup_ptr (stmt), ctx);
9936 break;
9937 case GIMPLE_TRANSACTION:
9938 lower_omp (gimple_transaction_body_ptr (stmt), ctx);
9939 break;
9940 case GIMPLE_BIND:
9941 lower_omp (gimple_bind_body_ptr (stmt), ctx);
9942 break;
9943 case GIMPLE_OMP_PARALLEL:
9944 case GIMPLE_OMP_TASK:
9945 ctx = maybe_lookup_ctx (stmt);
9946 gcc_assert (ctx);
9947 if (ctx->cancellable)
9948 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
9949 lower_omp_taskreg (gsi_p, ctx);
9950 break;
9951 case GIMPLE_OMP_FOR:
9952 ctx = maybe_lookup_ctx (stmt);
9953 gcc_assert (ctx);
9954 if (ctx->cancellable)
9955 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
9956 lower_omp_for (gsi_p, ctx);
9957 break;
9958 case GIMPLE_OMP_SECTIONS:
9959 ctx = maybe_lookup_ctx (stmt);
9960 gcc_assert (ctx);
9961 if (ctx->cancellable)
9962 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
9963 lower_omp_sections (gsi_p, ctx);
9964 break;
9965 case GIMPLE_OMP_SINGLE:
9966 ctx = maybe_lookup_ctx (stmt);
9967 gcc_assert (ctx);
9968 lower_omp_single (gsi_p, ctx);
9969 break;
9970 case GIMPLE_OMP_MASTER:
9971 ctx = maybe_lookup_ctx (stmt);
9972 gcc_assert (ctx);
9973 lower_omp_master (gsi_p, ctx);
9974 break;
9975 case GIMPLE_OMP_TASKGROUP:
9976 ctx = maybe_lookup_ctx (stmt);
9977 gcc_assert (ctx);
9978 lower_omp_taskgroup (gsi_p, ctx);
9979 break;
9980 case GIMPLE_OMP_ORDERED:
9981 ctx = maybe_lookup_ctx (stmt);
9982 gcc_assert (ctx);
9983 lower_omp_ordered (gsi_p, ctx);
9984 break;
9985 case GIMPLE_OMP_CRITICAL:
9986 ctx = maybe_lookup_ctx (stmt);
9987 gcc_assert (ctx);
9988 lower_omp_critical (gsi_p, ctx);
9989 break;
9990 case GIMPLE_OMP_ATOMIC_LOAD:
9991 if ((ctx || task_shared_vars)
9992 && walk_tree (gimple_omp_atomic_load_rhs_ptr (stmt),
9993 lower_omp_regimplify_p, ctx ? NULL : &wi, NULL))
9994 gimple_regimplify_operands (stmt, gsi_p);
9995 break;
9996 case GIMPLE_OMP_TARGET:
9997 ctx = maybe_lookup_ctx (stmt);
9998 gcc_assert (ctx);
9999 lower_omp_target (gsi_p, ctx);
10000 break;
10001 case GIMPLE_OMP_TEAMS:
10002 ctx = maybe_lookup_ctx (stmt);
10003 gcc_assert (ctx);
10004 lower_omp_teams (gsi_p, ctx);
10005 break;
10006 case GIMPLE_CALL:
10007 tree fndecl;
10008 fndecl = gimple_call_fndecl (stmt);
10009 if (fndecl
10010 && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
10011 switch (DECL_FUNCTION_CODE (fndecl))
10012 {
10013 case BUILT_IN_GOMP_BARRIER:
10014 if (ctx == NULL)
10015 break;
10016 /* FALLTHRU */
10017 case BUILT_IN_GOMP_CANCEL:
10018 case BUILT_IN_GOMP_CANCELLATION_POINT:
10019 omp_context *cctx;
10020 cctx = ctx;
10021 if (gimple_code (cctx->stmt) == GIMPLE_OMP_SECTION)
10022 cctx = cctx->outer;
10023 gcc_assert (gimple_call_lhs (stmt) == NULL_TREE);
10024 if (!cctx->cancellable)
10025 {
10026 if (DECL_FUNCTION_CODE (fndecl)
10027 == BUILT_IN_GOMP_CANCELLATION_POINT)
10028 {
10029 stmt = gimple_build_nop ();
10030 gsi_replace (gsi_p, stmt, false);
10031 }
10032 break;
10033 }
10034 tree lhs;
10035 lhs = create_tmp_var (boolean_type_node, NULL);
10036 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_GOMP_BARRIER)
10037 {
10038 fndecl = builtin_decl_explicit (BUILT_IN_GOMP_BARRIER_CANCEL);
10039 gimple_call_set_fndecl (stmt, fndecl);
10040 gimple_call_set_fntype (stmt, TREE_TYPE (fndecl));
10041 }
10042 gimple_call_set_lhs (stmt, lhs);
10043 tree fallthru_label;
10044 fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
10045 gimple g;
10046 g = gimple_build_label (fallthru_label);
10047 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
10048 g = gimple_build_cond (NE_EXPR, lhs, boolean_false_node,
10049 cctx->cancel_label, fallthru_label);
10050 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
10051 break;
10052 default:
10053 break;
10054 }
10055 /* FALLTHRU */
10056 default:
10057 if ((ctx || task_shared_vars)
10058 && walk_gimple_op (stmt, lower_omp_regimplify_p,
10059 ctx ? NULL : &wi))
10060 gimple_regimplify_operands (stmt, gsi_p);
10061 break;
10062 }
10063 }
10064
10065 static void
10066 lower_omp (gimple_seq *body, omp_context *ctx)
10067 {
10068 location_t saved_location = input_location;
10069 gimple_stmt_iterator gsi;
10070 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
10071 lower_omp_1 (&gsi, ctx);
10072 /* Inside target region we haven't called fold_stmt during gimplification,
10073 because it can break code by adding decl references that weren't in the
10074 source. Call fold_stmt now. */
10075 if (target_nesting_level)
10076 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
10077 fold_stmt (&gsi);
10078 input_location = saved_location;
10079 }
10080 \f
10081 /* Main entry point. */
10082
10083 static unsigned int
10084 execute_lower_omp (void)
10085 {
10086 gimple_seq body;
10087
10088 /* This pass always runs, to provide PROP_gimple_lomp.
10089 But there is nothing to do unless -fopenmp is given. */
10090 if (flag_openmp == 0 && flag_openmp_simd == 0 && flag_enable_cilkplus == 0)
10091 return 0;
10092
10093 all_contexts = splay_tree_new (splay_tree_compare_pointers, 0,
10094 delete_omp_context);
10095
10096 body = gimple_body (current_function_decl);
10097 scan_omp (&body, NULL);
10098 gcc_assert (taskreg_nesting_level == 0);
10099
10100 if (all_contexts->root)
10101 {
10102 if (task_shared_vars)
10103 push_gimplify_context ();
10104 lower_omp (&body, NULL);
10105 if (task_shared_vars)
10106 pop_gimplify_context (NULL);
10107 }
10108
10109 if (all_contexts)
10110 {
10111 splay_tree_delete (all_contexts);
10112 all_contexts = NULL;
10113 }
10114 BITMAP_FREE (task_shared_vars);
10115 return 0;
10116 }
10117
10118 namespace {
10119
10120 const pass_data pass_data_lower_omp =
10121 {
10122 GIMPLE_PASS, /* type */
10123 "omplower", /* name */
10124 OPTGROUP_NONE, /* optinfo_flags */
10125 false, /* has_gate */
10126 true, /* has_execute */
10127 TV_NONE, /* tv_id */
10128 PROP_gimple_any, /* properties_required */
10129 PROP_gimple_lomp, /* properties_provided */
10130 0, /* properties_destroyed */
10131 0, /* todo_flags_start */
10132 0, /* todo_flags_finish */
10133 };
10134
10135 class pass_lower_omp : public gimple_opt_pass
10136 {
10137 public:
10138 pass_lower_omp (gcc::context *ctxt)
10139 : gimple_opt_pass (pass_data_lower_omp, ctxt)
10140 {}
10141
10142 /* opt_pass methods: */
10143 unsigned int execute () { return execute_lower_omp (); }
10144
10145 }; // class pass_lower_omp
10146
10147 } // anon namespace
10148
10149 gimple_opt_pass *
10150 make_pass_lower_omp (gcc::context *ctxt)
10151 {
10152 return new pass_lower_omp (ctxt);
10153 }
10154 \f
10155 /* The following is a utility to diagnose OpenMP structured block violations.
10156 It is not part of the "omplower" pass, as that's invoked too late. It
10157 should be invoked by the respective front ends after gimplification. */
10158
10159 static splay_tree all_labels;
10160
10161 /* Check for mismatched contexts and generate an error if needed. Return
10162 true if an error is detected. */
10163
10164 static bool
10165 diagnose_sb_0 (gimple_stmt_iterator *gsi_p,
10166 gimple branch_ctx, gimple label_ctx)
10167 {
10168 if (label_ctx == branch_ctx)
10169 return false;
10170
10171
10172 /*
10173 Previously we kept track of the label's entire context in diagnose_sb_[12]
10174 so we could traverse it and issue a correct "exit" or "enter" error
10175 message upon a structured block violation.
10176
10177 We built the context by building a list with tree_cons'ing, but there is
10178 no easy counterpart in gimple tuples. It seems like far too much work
10179 for issuing exit/enter error messages. If someone really misses the
10180 distinct error message... patches welcome.
10181 */
10182
10183 #if 0
10184 /* Try to avoid confusing the user by producing and error message
10185 with correct "exit" or "enter" verbiage. We prefer "exit"
10186 unless we can show that LABEL_CTX is nested within BRANCH_CTX. */
10187 if (branch_ctx == NULL)
10188 exit_p = false;
10189 else
10190 {
10191 while (label_ctx)
10192 {
10193 if (TREE_VALUE (label_ctx) == branch_ctx)
10194 {
10195 exit_p = false;
10196 break;
10197 }
10198 label_ctx = TREE_CHAIN (label_ctx);
10199 }
10200 }
10201
10202 if (exit_p)
10203 error ("invalid exit from OpenMP structured block");
10204 else
10205 error ("invalid entry to OpenMP structured block");
10206 #endif
10207
10208 bool cilkplus_block = false;
10209 if (flag_enable_cilkplus)
10210 {
10211 if ((branch_ctx
10212 && gimple_code (branch_ctx) == GIMPLE_OMP_FOR
10213 && gimple_omp_for_kind (branch_ctx) == GF_OMP_FOR_KIND_CILKSIMD)
10214 || (gimple_code (label_ctx) == GIMPLE_OMP_FOR
10215 && gimple_omp_for_kind (label_ctx) == GF_OMP_FOR_KIND_CILKSIMD))
10216 cilkplus_block = true;
10217 }
10218
10219 /* If it's obvious we have an invalid entry, be specific about the error. */
10220 if (branch_ctx == NULL)
10221 {
10222 if (cilkplus_block)
10223 error ("invalid entry to Cilk Plus structured block");
10224 else
10225 error ("invalid entry to OpenMP structured block");
10226 }
10227 else
10228 {
10229 /* Otherwise, be vague and lazy, but efficient. */
10230 if (cilkplus_block)
10231 error ("invalid branch to/from a Cilk Plus structured block");
10232 else
10233 error ("invalid branch to/from an OpenMP structured block");
10234 }
10235
10236 gsi_replace (gsi_p, gimple_build_nop (), false);
10237 return true;
10238 }
10239
10240 /* Pass 1: Create a minimal tree of OpenMP structured blocks, and record
10241 where each label is found. */
10242
10243 static tree
10244 diagnose_sb_1 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
10245 struct walk_stmt_info *wi)
10246 {
10247 gimple context = (gimple) wi->info;
10248 gimple inner_context;
10249 gimple stmt = gsi_stmt (*gsi_p);
10250
10251 *handled_ops_p = true;
10252
10253 switch (gimple_code (stmt))
10254 {
10255 WALK_SUBSTMTS;
10256
10257 case GIMPLE_OMP_PARALLEL:
10258 case GIMPLE_OMP_TASK:
10259 case GIMPLE_OMP_SECTIONS:
10260 case GIMPLE_OMP_SINGLE:
10261 case GIMPLE_OMP_SECTION:
10262 case GIMPLE_OMP_MASTER:
10263 case GIMPLE_OMP_ORDERED:
10264 case GIMPLE_OMP_CRITICAL:
10265 case GIMPLE_OMP_TARGET:
10266 case GIMPLE_OMP_TEAMS:
10267 case GIMPLE_OMP_TASKGROUP:
10268 /* The minimal context here is just the current OMP construct. */
10269 inner_context = stmt;
10270 wi->info = inner_context;
10271 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
10272 wi->info = context;
10273 break;
10274
10275 case GIMPLE_OMP_FOR:
10276 inner_context = stmt;
10277 wi->info = inner_context;
10278 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
10279 walk them. */
10280 walk_gimple_seq (gimple_omp_for_pre_body (stmt),
10281 diagnose_sb_1, NULL, wi);
10282 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
10283 wi->info = context;
10284 break;
10285
10286 case GIMPLE_LABEL:
10287 splay_tree_insert (all_labels, (splay_tree_key) gimple_label_label (stmt),
10288 (splay_tree_value) context);
10289 break;
10290
10291 default:
10292 break;
10293 }
10294
10295 return NULL_TREE;
10296 }
10297
10298 /* Pass 2: Check each branch and see if its context differs from that of
10299 the destination label's context. */
10300
10301 static tree
10302 diagnose_sb_2 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
10303 struct walk_stmt_info *wi)
10304 {
10305 gimple context = (gimple) wi->info;
10306 splay_tree_node n;
10307 gimple stmt = gsi_stmt (*gsi_p);
10308
10309 *handled_ops_p = true;
10310
10311 switch (gimple_code (stmt))
10312 {
10313 WALK_SUBSTMTS;
10314
10315 case GIMPLE_OMP_PARALLEL:
10316 case GIMPLE_OMP_TASK:
10317 case GIMPLE_OMP_SECTIONS:
10318 case GIMPLE_OMP_SINGLE:
10319 case GIMPLE_OMP_SECTION:
10320 case GIMPLE_OMP_MASTER:
10321 case GIMPLE_OMP_ORDERED:
10322 case GIMPLE_OMP_CRITICAL:
10323 case GIMPLE_OMP_TARGET:
10324 case GIMPLE_OMP_TEAMS:
10325 case GIMPLE_OMP_TASKGROUP:
10326 wi->info = stmt;
10327 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
10328 wi->info = context;
10329 break;
10330
10331 case GIMPLE_OMP_FOR:
10332 wi->info = stmt;
10333 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
10334 walk them. */
10335 walk_gimple_seq_mod (gimple_omp_for_pre_body_ptr (stmt),
10336 diagnose_sb_2, NULL, wi);
10337 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
10338 wi->info = context;
10339 break;
10340
10341 case GIMPLE_COND:
10342 {
10343 tree lab = gimple_cond_true_label (stmt);
10344 if (lab)
10345 {
10346 n = splay_tree_lookup (all_labels,
10347 (splay_tree_key) lab);
10348 diagnose_sb_0 (gsi_p, context,
10349 n ? (gimple) n->value : NULL);
10350 }
10351 lab = gimple_cond_false_label (stmt);
10352 if (lab)
10353 {
10354 n = splay_tree_lookup (all_labels,
10355 (splay_tree_key) lab);
10356 diagnose_sb_0 (gsi_p, context,
10357 n ? (gimple) n->value : NULL);
10358 }
10359 }
10360 break;
10361
10362 case GIMPLE_GOTO:
10363 {
10364 tree lab = gimple_goto_dest (stmt);
10365 if (TREE_CODE (lab) != LABEL_DECL)
10366 break;
10367
10368 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
10369 diagnose_sb_0 (gsi_p, context, n ? (gimple) n->value : NULL);
10370 }
10371 break;
10372
10373 case GIMPLE_SWITCH:
10374 {
10375 unsigned int i;
10376 for (i = 0; i < gimple_switch_num_labels (stmt); ++i)
10377 {
10378 tree lab = CASE_LABEL (gimple_switch_label (stmt, i));
10379 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
10380 if (n && diagnose_sb_0 (gsi_p, context, (gimple) n->value))
10381 break;
10382 }
10383 }
10384 break;
10385
10386 case GIMPLE_RETURN:
10387 diagnose_sb_0 (gsi_p, context, NULL);
10388 break;
10389
10390 default:
10391 break;
10392 }
10393
10394 return NULL_TREE;
10395 }
10396
10397 /* Called from tree-cfg.c::make_edges to create cfg edges for all GIMPLE_OMP
10398 codes. */
10399 bool
10400 make_gimple_omp_edges (basic_block bb, struct omp_region **region)
10401 {
10402 gimple last = last_stmt (bb);
10403 enum gimple_code code = gimple_code (last);
10404 struct omp_region *cur_region = *region;
10405 bool fallthru = false;
10406
10407 switch (code)
10408 {
10409 case GIMPLE_OMP_PARALLEL:
10410 case GIMPLE_OMP_TASK:
10411 case GIMPLE_OMP_FOR:
10412 case GIMPLE_OMP_SINGLE:
10413 case GIMPLE_OMP_TEAMS:
10414 case GIMPLE_OMP_MASTER:
10415 case GIMPLE_OMP_TASKGROUP:
10416 case GIMPLE_OMP_ORDERED:
10417 case GIMPLE_OMP_CRITICAL:
10418 case GIMPLE_OMP_SECTION:
10419 cur_region = new_omp_region (bb, code, cur_region);
10420 fallthru = true;
10421 break;
10422
10423 case GIMPLE_OMP_TARGET:
10424 cur_region = new_omp_region (bb, code, cur_region);
10425 fallthru = true;
10426 if (gimple_omp_target_kind (last) == GF_OMP_TARGET_KIND_UPDATE)
10427 cur_region = cur_region->outer;
10428 break;
10429
10430 case GIMPLE_OMP_SECTIONS:
10431 cur_region = new_omp_region (bb, code, cur_region);
10432 fallthru = true;
10433 break;
10434
10435 case GIMPLE_OMP_SECTIONS_SWITCH:
10436 fallthru = false;
10437 break;
10438
10439 case GIMPLE_OMP_ATOMIC_LOAD:
10440 case GIMPLE_OMP_ATOMIC_STORE:
10441 fallthru = true;
10442 break;
10443
10444 case GIMPLE_OMP_RETURN:
10445 /* In the case of a GIMPLE_OMP_SECTION, the edge will go
10446 somewhere other than the next block. This will be
10447 created later. */
10448 cur_region->exit = bb;
10449 fallthru = cur_region->type != GIMPLE_OMP_SECTION;
10450 cur_region = cur_region->outer;
10451 break;
10452
10453 case GIMPLE_OMP_CONTINUE:
10454 cur_region->cont = bb;
10455 switch (cur_region->type)
10456 {
10457 case GIMPLE_OMP_FOR:
10458 /* Mark all GIMPLE_OMP_FOR and GIMPLE_OMP_CONTINUE
10459 succs edges as abnormal to prevent splitting
10460 them. */
10461 single_succ_edge (cur_region->entry)->flags |= EDGE_ABNORMAL;
10462 /* Make the loopback edge. */
10463 make_edge (bb, single_succ (cur_region->entry),
10464 EDGE_ABNORMAL);
10465
10466 /* Create an edge from GIMPLE_OMP_FOR to exit, which
10467 corresponds to the case that the body of the loop
10468 is not executed at all. */
10469 make_edge (cur_region->entry, bb->next_bb, EDGE_ABNORMAL);
10470 make_edge (bb, bb->next_bb, EDGE_FALLTHRU | EDGE_ABNORMAL);
10471 fallthru = false;
10472 break;
10473
10474 case GIMPLE_OMP_SECTIONS:
10475 /* Wire up the edges into and out of the nested sections. */
10476 {
10477 basic_block switch_bb = single_succ (cur_region->entry);
10478
10479 struct omp_region *i;
10480 for (i = cur_region->inner; i ; i = i->next)
10481 {
10482 gcc_assert (i->type == GIMPLE_OMP_SECTION);
10483 make_edge (switch_bb, i->entry, 0);
10484 make_edge (i->exit, bb, EDGE_FALLTHRU);
10485 }
10486
10487 /* Make the loopback edge to the block with
10488 GIMPLE_OMP_SECTIONS_SWITCH. */
10489 make_edge (bb, switch_bb, 0);
10490
10491 /* Make the edge from the switch to exit. */
10492 make_edge (switch_bb, bb->next_bb, 0);
10493 fallthru = false;
10494 }
10495 break;
10496
10497 default:
10498 gcc_unreachable ();
10499 }
10500 break;
10501
10502 default:
10503 gcc_unreachable ();
10504 }
10505
10506 if (*region != cur_region)
10507 *region = cur_region;
10508
10509 return fallthru;
10510 }
10511
10512 static unsigned int
10513 diagnose_omp_structured_block_errors (void)
10514 {
10515 struct walk_stmt_info wi;
10516 gimple_seq body = gimple_body (current_function_decl);
10517
10518 all_labels = splay_tree_new (splay_tree_compare_pointers, 0, 0);
10519
10520 memset (&wi, 0, sizeof (wi));
10521 walk_gimple_seq (body, diagnose_sb_1, NULL, &wi);
10522
10523 memset (&wi, 0, sizeof (wi));
10524 wi.want_locations = true;
10525 walk_gimple_seq_mod (&body, diagnose_sb_2, NULL, &wi);
10526
10527 gimple_set_body (current_function_decl, body);
10528
10529 splay_tree_delete (all_labels);
10530 all_labels = NULL;
10531
10532 return 0;
10533 }
10534
10535 static bool
10536 gate_diagnose_omp_blocks (void)
10537 {
10538 return flag_openmp || flag_enable_cilkplus;
10539 }
10540
10541 namespace {
10542
10543 const pass_data pass_data_diagnose_omp_blocks =
10544 {
10545 GIMPLE_PASS, /* type */
10546 "*diagnose_omp_blocks", /* name */
10547 OPTGROUP_NONE, /* optinfo_flags */
10548 true, /* has_gate */
10549 true, /* has_execute */
10550 TV_NONE, /* tv_id */
10551 PROP_gimple_any, /* properties_required */
10552 0, /* properties_provided */
10553 0, /* properties_destroyed */
10554 0, /* todo_flags_start */
10555 0, /* todo_flags_finish */
10556 };
10557
10558 class pass_diagnose_omp_blocks : public gimple_opt_pass
10559 {
10560 public:
10561 pass_diagnose_omp_blocks (gcc::context *ctxt)
10562 : gimple_opt_pass (pass_data_diagnose_omp_blocks, ctxt)
10563 {}
10564
10565 /* opt_pass methods: */
10566 bool gate () { return gate_diagnose_omp_blocks (); }
10567 unsigned int execute () {
10568 return diagnose_omp_structured_block_errors ();
10569 }
10570
10571 }; // class pass_diagnose_omp_blocks
10572
10573 } // anon namespace
10574
10575 gimple_opt_pass *
10576 make_pass_diagnose_omp_blocks (gcc::context *ctxt)
10577 {
10578 return new pass_diagnose_omp_blocks (ctxt);
10579 }
10580
10581 #include "gt-omp-low.h"