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