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