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