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