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