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