]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/omp-low.c
Handle simple latch in expand_omp_for_generic
[thirdparty/gcc.git] / gcc / omp-low.c
CommitLineData
ca4c3545 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
1e8e9920 5 Contributed by Diego Novillo <dnovillo@redhat.com>
6
d353bf18 7 Copyright (C) 2005-2015 Free Software Foundation, Inc.
1e8e9920 8
9This file is part of GCC.
10
11GCC is free software; you can redistribute it and/or modify it under
12the terms of the GNU General Public License as published by the Free
8c4c00c1 13Software Foundation; either version 3, or (at your option) any later
1e8e9920 14version.
15
16GCC is distributed in the hope that it will be useful, but WITHOUT ANY
17WARRANTY; without even the implied warranty of MERCHANTABILITY or
18FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19for more details.
20
21You should have received a copy of the GNU General Public License
8c4c00c1 22along with GCC; see the file COPYING3. If not see
23<http://www.gnu.org/licenses/>. */
1e8e9920 24
25#include "config.h"
26#include "system.h"
27#include "coretypes.h"
9ef16211 28#include "backend.h"
d040a5b0 29#include "cfghooks.h"
1e8e9920 30#include "tree.h"
9ef16211 31#include "gimple.h"
32#include "rtl.h"
33#include "ssa.h"
34#include "alias.h"
b20a8bb4 35#include "fold-const.h"
9ed99284 36#include "stor-layout.h"
94ea8568 37#include "cfganal.h"
bc61cadb 38#include "internal-fn.h"
39#include "gimple-fold.h"
a8783bee 40#include "gimplify.h"
dcf1a1ec 41#include "gimple-iterator.h"
e795d6e1 42#include "gimplify-me.h"
dcf1a1ec 43#include "gimple-walk.h"
75a70cf9 44#include "tree-iterator.h"
1e8e9920 45#include "tree-inline.h"
46#include "langhooks.h"
852f689e 47#include "diagnostic-core.h"
073c1fd5 48#include "cgraph.h"
49#include "tree-cfg.h"
073c1fd5 50#include "tree-into-ssa.h"
d53441c8 51#include "flags.h"
d53441c8 52#include "insn-config.h"
53#include "expmed.h"
54#include "dojump.h"
55#include "explow.h"
56#include "calls.h"
57#include "emit-rtl.h"
58#include "varasm.h"
59#include "stmt.h"
9ed99284 60#include "expr.h"
073c1fd5 61#include "tree-dfa.h"
69ee5dbb 62#include "tree-ssa.h"
1e8e9920 63#include "tree-pass.h"
1e8e9920 64#include "except.h"
e3022db7 65#include "splay-tree.h"
34517c64 66#include "insn-codes.h"
cb7f680b 67#include "optabs.h"
68#include "cfgloop.h"
3d483a94 69#include "target.h"
dccabdd1 70#include "common/common-target.h"
7740abd8 71#include "omp-low.h"
424a4a92 72#include "gimple-low.h"
73#include "tree-cfgcleanup.h"
d09768a4 74#include "pretty-print.h"
1140c305 75#include "alloc-pool.h"
2cc80ac3 76#include "symbol-summary.h"
d09768a4 77#include "ipa-prop.h"
e797f49f 78#include "tree-nested.h"
d09768a4 79#include "tree-eh.h"
40750995 80#include "cilk.h"
b0c5e347 81#include "context.h"
dccabdd1 82#include "lto-section-names.h"
ca4c3545 83#include "gomp-constants.h"
1e8e9920 84
ca4c3545 85/* Lowering of OMP parallel and workshare constructs proceeds in two
1e8e9920 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
334ec2d8 89 re-gimplifying things when variables have been replaced with complex
1e8e9920 90 expressions.
91
d134bccc 92 Final code generation is done by pass_expand_omp. The flowgraph is
ca4c3545 93 scanned for regions which are then moved to a new
94 function, to be invoked by the thread library, or offloaded. */
1e8e9920 95
ca4c3545 96/* OMP region information. Every parallel and workshare
7740abd8 97 directive is enclosed between two markers, the OMP_* directive
98 and a corresponding OMP_RETURN statement. */
99
100struct 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
ca4c3545 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
1e8e9920 141/* Context structure. Used to store information about each parallel
142 directive in the code. */
143
6dc50383 144struct omp_context
1e8e9920 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;
42acab1c 154 gimple *stmt;
1e8e9920 155
48e1416a 156 /* Map variables to fields in a structure that allows communication
1e8e9920 157 between sending and receiving threads. */
158 splay_tree field_map;
159 tree record_type;
160 tree sender_decl;
161 tree receiver_decl;
162
fd6481cf 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
1e8e9920 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
ca4c3545 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
bc7bff74 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
1e8e9920 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
1e8e9920 193 /* True if this parallel directive is nested within another. */
194 bool is_nested;
bc7bff74 195
196 /* True if this construct can be cancelled. */
197 bool cancellable;
ca4c3545 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;
6dc50383 206};
1e8e9920 207
ca4c3545 208/* A structure holding the elements of:
209 for (V = N1; V cond N2; V += STEP) [...] */
1e8e9920 210
fd6481cf 211struct omp_for_data_loop
212{
213 tree v, n1, n2, step;
214 enum tree_code cond_code;
215};
216
773c5ba7 217/* A structure describing the main elements of a parallel loop. */
1e8e9920 218
773c5ba7 219struct omp_for_data
1e8e9920 220{
fd6481cf 221 struct omp_for_data_loop loop;
75a70cf9 222 tree chunk_size;
1a91d914 223 gomp_for *for_stmt;
fd6481cf 224 tree pre, iter_type;
225 int collapse;
1e8e9920 226 bool have_nowait, have_ordered;
227 enum omp_clause_schedule_kind sched_kind;
fd6481cf 228 struct omp_for_data_loop *loops;
1e8e9920 229};
230
773c5ba7 231
1e8e9920 232static splay_tree all_contexts;
fd6481cf 233static int taskreg_nesting_level;
bc7bff74 234static int target_nesting_level;
7740abd8 235static struct omp_region *root_omp_region;
fd6481cf 236static bitmap task_shared_vars;
37eaded9 237static vec<omp_context *> taskreg_contexts;
1e8e9920 238
ab129075 239static void scan_omp (gimple_seq *, omp_context *);
75a70cf9 240static 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: \
4c0315d0 247 case GIMPLE_TRANSACTION: \
75a70cf9 248 /* The sub-statements for these should be walked. */ \
249 *handled_ops_p = false; \
250 break;
251
ca4c3545 252/* Helper function to get the name of the array containing the partial
253 reductions for OpenACC reductions. */
254static const char *
255oacc_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
269static tree
270oacc_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
dccabdd1 312/* Holds offload tables with decls. */
313vec<tree, va_gc> *offload_funcs, *offload_vars;
314
75a70cf9 315/* Convenience function for calling scan_omp_1_op on tree operands. */
316
317static inline tree
318scan_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
e3a19533 329static void lower_omp (gimple_seq *, omp_context *);
f49d7bb5 330static tree lookup_decl_in_outer_ctx (tree, omp_context *);
331static tree maybe_lookup_decl_in_outer_ctx (tree, omp_context *);
1e8e9920 332
ca4c3545 333/* Find an OMP clause of type KIND within CLAUSES. */
1e8e9920 334
79acaae1 335tree
590c3166 336find_omp_clause (tree clauses, enum omp_clause_code kind)
1e8e9920 337{
338 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
55d6e7cd 339 if (OMP_CLAUSE_CODE (clauses) == kind)
1e8e9920 340 return clauses;
341
342 return NULL_TREE;
343}
344
345/* Return true if CTX is for an omp parallel. */
346
347static inline bool
348is_parallel_ctx (omp_context *ctx)
349{
75a70cf9 350 return gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL;
1e8e9920 351}
352
773c5ba7 353
fd6481cf 354/* Return true if CTX is for an omp task. */
355
356static inline bool
357is_task_ctx (omp_context *ctx)
358{
75a70cf9 359 return gimple_code (ctx->stmt) == GIMPLE_OMP_TASK;
fd6481cf 360}
361
362
363/* Return true if CTX is for an omp parallel or omp task. */
364
365static inline bool
366is_taskreg_ctx (omp_context *ctx)
367{
75a70cf9 368 return gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL
369 || gimple_code (ctx->stmt) == GIMPLE_OMP_TASK;
fd6481cf 370}
371
372
773c5ba7 373/* Return true if REGION is a combined parallel+workshare region. */
1e8e9920 374
375static inline bool
773c5ba7 376is_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
385static void
1a91d914 386extract_omp_for_data (gomp_for *for_stmt, struct omp_for_data *fd,
fd6481cf 387 struct omp_for_data_loop *loops)
773c5ba7 388{
fd6481cf 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;
389dd41b 394 location_t loc = gimple_location (for_stmt);
10c55644 395 bool simd = gimple_omp_for_kind (for_stmt) & GF_OMP_FOR_SIMD;
bc7bff74 396 bool distribute = gimple_omp_for_kind (for_stmt)
397 == GF_OMP_FOR_KIND_DISTRIBUTE;
773c5ba7 398
399 fd->for_stmt = for_stmt;
400 fd->pre = NULL;
75a70cf9 401 fd->collapse = gimple_omp_for_collapse (for_stmt);
fd6481cf 402 if (fd->collapse > 1)
403 fd->loops = loops;
404 else
405 fd->loops = &fd->loop;
773c5ba7 406
bc7bff74 407 fd->have_nowait = distribute || simd;
408 fd->have_ordered = false;
773c5ba7 409 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
410 fd->chunk_size = NULL_TREE;
40750995 411 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_CILKFOR)
412 fd->sched_kind = OMP_CLAUSE_SCHEDULE_CILKFOR;
fd6481cf 413 collapse_iter = NULL;
414 collapse_count = NULL;
773c5ba7 415
75a70cf9 416 for (t = gimple_omp_for_clauses (for_stmt); t ; t = OMP_CLAUSE_CHAIN (t))
55d6e7cd 417 switch (OMP_CLAUSE_CODE (t))
773c5ba7 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:
bc7bff74 426 gcc_assert (!distribute);
773c5ba7 427 fd->sched_kind = OMP_CLAUSE_SCHEDULE_KIND (t);
428 fd->chunk_size = OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (t);
429 break;
bc7bff74 430 case OMP_CLAUSE_DIST_SCHEDULE:
431 gcc_assert (distribute);
432 fd->chunk_size = OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (t);
433 break;
fd6481cf 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 }
757abb46 440 break;
773c5ba7 441 default:
442 break;
443 }
444
fd6481cf 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)
bde357c8 448 is best) or if it varies (then schedule(dynamic,N) is better). */
fd6481cf 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);
773c5ba7 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. */
fd6481cf 461 if (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
bc7bff74 462 || fd->have_ordered)
773c5ba7 463 fd->chunk_size = (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
464 ? integer_zero_node : integer_one_node;
465 }
fd6481cf 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
75a70cf9 476 loop->v = gimple_omp_for_index (for_stmt, i);
fd6481cf 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;
75a70cf9 481 loop->n1 = gimple_omp_for_initial (for_stmt, i);
fd6481cf 482
75a70cf9 483 loop->cond_code = gimple_omp_for_cond (for_stmt, i);
484 loop->n2 = gimple_omp_for_final (for_stmt, i);
fd6481cf 485 switch (loop->cond_code)
486 {
487 case LT_EXPR:
488 case GT_EXPR:
489 break;
f2697631 490 case NE_EXPR:
491 gcc_assert (gimple_omp_for_kind (for_stmt)
40750995 492 == GF_OMP_FOR_KIND_CILKSIMD
493 || (gimple_omp_for_kind (for_stmt)
494 == GF_OMP_FOR_KIND_CILKFOR));
f2697631 495 break;
fd6481cf 496 case LE_EXPR:
497 if (POINTER_TYPE_P (TREE_TYPE (loop->n2)))
2cc66f2a 498 loop->n2 = fold_build_pointer_plus_hwi_loc (loc, loop->n2, 1);
fd6481cf 499 else
389dd41b 500 loop->n2 = fold_build2_loc (loc,
501 PLUS_EXPR, TREE_TYPE (loop->n2), loop->n2,
fd6481cf 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)))
2cc66f2a 507 loop->n2 = fold_build_pointer_plus_hwi_loc (loc, loop->n2, -1);
fd6481cf 508 else
389dd41b 509 loop->n2 = fold_build2_loc (loc,
510 MINUS_EXPR, TREE_TYPE (loop->n2), loop->n2,
fd6481cf 511 build_int_cst (TREE_TYPE (loop->n2), 1));
512 loop->cond_code = GT_EXPR;
513 break;
514 default:
515 gcc_unreachable ();
516 }
517
75a70cf9 518 t = gimple_omp_for_incr (for_stmt, i);
fd6481cf 519 gcc_assert (TREE_OPERAND (t, 0) == var);
520 switch (TREE_CODE (t))
521 {
522 case PLUS_EXPR:
fd6481cf 523 loop->step = TREE_OPERAND (t, 1);
524 break;
85d86b55 525 case POINTER_PLUS_EXPR:
526 loop->step = fold_convert (ssizetype, TREE_OPERAND (t, 1));
527 break;
fd6481cf 528 case MINUS_EXPR:
529 loop->step = TREE_OPERAND (t, 1);
389dd41b 530 loop->step = fold_build1_loc (loc,
531 NEGATE_EXPR, TREE_TYPE (loop->step),
fd6481cf 532 loop->step);
533 break;
534 default:
535 gcc_unreachable ();
536 }
537
bc7bff74 538 if (simd
539 || (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
540 && !fd->have_ordered))
3d483a94 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
bc7bff74 549 (TYPE_PRECISION (TREE_TYPE (loop->v)), 1);
3d483a94 550 }
551 else if (iter_type != long_long_unsigned_type_node)
fd6481cf 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)
389dd41b 562 n = fold_build2_loc (loc,
563 PLUS_EXPR, TREE_TYPE (loop->v),
fd6481cf 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;
389dd41b 579 n2 = fold_build2_loc (loc,
580 PLUS_EXPR, TREE_TYPE (loop->v),
fd6481cf 581 loop->n2, loop->step);
582 }
583 else
584 {
389dd41b 585 n1 = fold_build2_loc (loc,
586 MINUS_EXPR, TREE_TYPE (loop->v),
fd6481cf 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 {
8e6b4515 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)
fd6481cf 610 {
611 tree itype = TREE_TYPE (loop->v);
612
613 if (POINTER_TYPE_P (itype))
3cea8318 614 itype = signed_type_for (itype);
fd6481cf 615 t = build_int_cst (itype, (loop->cond_code == LT_EXPR ? -1 : 1));
389dd41b 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));
fd6481cf 623 if (TYPE_UNSIGNED (itype) && loop->cond_code == GT_EXPR)
389dd41b 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)));
fd6481cf 629 else
389dd41b 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);
fd6481cf 633 if (count != NULL_TREE)
389dd41b 634 count = fold_build2_loc (loc,
635 MULT_EXPR, long_long_unsigned_type_node,
fd6481cf 636 count, t);
637 else
638 count = t;
639 if (TREE_CODE (count) != INTEGER_CST)
640 count = NULL_TREE;
641 }
8e6b4515 642 else if (count && !integer_zerop (count))
fd6481cf 643 count = NULL_TREE;
644 }
645 }
646
3d483a94 647 if (count
bc7bff74 648 && !simd
649 && (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
650 || fd->have_ordered))
fd6481cf 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)
389dd41b 665 *collapse_count = fold_convert_loc (loc, iter_type, count);
fd6481cf 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 }
ca4c3545 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 }
773c5ba7 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
75a70cf9 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:
773c5ba7 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)
48e1416a 709
773c5ba7 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
75a70cf9 723 GIMPLE_OMP_FOR header check whether they appear on the LHS of any
773c5ba7 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
732static bool
f018d957 733workshare_safe_to_combine_p (basic_block ws_entry_bb)
773c5ba7 734{
735 struct omp_for_data fd;
42acab1c 736 gimple *ws_stmt = last_stmt (ws_entry_bb);
773c5ba7 737
75a70cf9 738 if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
773c5ba7 739 return true;
740
75a70cf9 741 gcc_assert (gimple_code (ws_stmt) == GIMPLE_OMP_FOR);
773c5ba7 742
1a91d914 743 extract_omp_for_data (as_a <gomp_for *> (ws_stmt), &fd, NULL);
fd6481cf 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;
773c5ba7 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. */
fd6481cf 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)
773c5ba7 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
f1f41a6c 769static vec<tree, va_gc> *
42acab1c 770get_ws_args_for (gimple *par_stmt, gimple *ws_stmt)
773c5ba7 771{
772 tree t;
389dd41b 773 location_t loc = gimple_location (ws_stmt);
f1f41a6c 774 vec<tree, va_gc> *ws_args;
773c5ba7 775
1a91d914 776 if (gomp_for *for_stmt = dyn_cast <gomp_for *> (ws_stmt))
773c5ba7 777 {
778 struct omp_for_data fd;
bc7bff74 779 tree n1, n2;
773c5ba7 780
1a91d914 781 extract_omp_for_data (for_stmt, &fd, NULL);
bc7bff74 782 n1 = fd.loop.n1;
783 n2 = fd.loop.n2;
784
1a91d914 785 if (gimple_omp_for_combined_into_p (for_stmt))
bc7bff74 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 }
773c5ba7 797
f1f41a6c 798 vec_alloc (ws_args, 3 + (fd.chunk_size != 0));
773c5ba7 799
bc7bff74 800 t = fold_convert_loc (loc, long_integer_type_node, n1);
f1f41a6c 801 ws_args->quick_push (t);
773c5ba7 802
bc7bff74 803 t = fold_convert_loc (loc, long_integer_type_node, n2);
f1f41a6c 804 ws_args->quick_push (t);
773c5ba7 805
414c3a2c 806 t = fold_convert_loc (loc, long_integer_type_node, fd.loop.step);
f1f41a6c 807 ws_args->quick_push (t);
414c3a2c 808
809 if (fd.chunk_size)
810 {
811 t = fold_convert_loc (loc, long_integer_type_node, fd.chunk_size);
f1f41a6c 812 ws_args->quick_push (t);
414c3a2c 813 }
773c5ba7 814
815 return ws_args;
816 }
75a70cf9 817 else if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
773c5ba7 818 {
ac6e3339 819 /* Number of sections is equal to the number of edges from the
75a70cf9 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));
ac6e3339 823 t = build_int_cst (unsigned_type_node, EDGE_COUNT (bb->succs) - 1);
f1f41a6c 824 vec_alloc (ws_args, 1);
825 ws_args->quick_push (t);
414c3a2c 826 return ws_args;
773c5ba7 827 }
828
829 gcc_unreachable ();
830}
831
832
833/* Discover whether REGION is a combined parallel+workshare region. */
834
835static void
836determine_parallel_type (struct omp_region *region)
1e8e9920 837{
773c5ba7 838 basic_block par_entry_bb, par_exit_bb;
839 basic_block ws_entry_bb, ws_exit_bb;
840
03ed154b 841 if (region == NULL || region->inner == NULL
ac6e3339 842 || region->exit == NULL || region->inner->exit == NULL
843 || region->inner->cont == NULL)
773c5ba7 844 return;
845
846 /* We only support parallel+for and parallel+sections. */
75a70cf9 847 if (region->type != GIMPLE_OMP_PARALLEL
848 || (region->inner->type != GIMPLE_OMP_FOR
849 && region->inner->type != GIMPLE_OMP_SECTIONS))
773c5ba7 850 return;
851
852 /* Check for perfect nesting PAR_ENTRY_BB -> WS_ENTRY_BB and
853 WS_EXIT_BB -> PAR_EXIT_BB. */
61e47ac8 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;
773c5ba7 858
859 if (single_succ (par_entry_bb) == ws_entry_bb
860 && single_succ (ws_exit_bb) == par_exit_bb
f018d957 861 && workshare_safe_to_combine_p (ws_entry_bb)
75a70cf9 862 && (gimple_omp_parallel_combined_p (last_stmt (par_entry_bb))
de7ef844 863 || (last_and_only_stmt (ws_entry_bb)
864 && last_and_only_stmt (par_exit_bb))))
773c5ba7 865 {
42acab1c 866 gimple *par_stmt = last_stmt (par_entry_bb);
867 gimple *ws_stmt = last_stmt (ws_entry_bb);
61e47ac8 868
75a70cf9 869 if (region->inner->type == GIMPLE_OMP_FOR)
773c5ba7 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. */
75a70cf9 880 tree clauses = gimple_omp_for_clauses (ws_stmt);
773c5ba7 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;
bc7bff74 894 region->ws_args = get_ws_args_for (par_stmt, ws_stmt);
773c5ba7 895 }
1e8e9920 896}
897
773c5ba7 898
1e8e9920 899/* Return true if EXPR is variable sized. */
900
901static inline bool
1f1872fd 902is_variable_sized (const_tree expr)
1e8e9920 903{
904 return !TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (expr)));
905}
906
907/* Return true if DECL is a reference type. */
908
909static inline bool
910is_reference (tree decl)
911{
912 return lang_hooks.decls.omp_privatize_by_reference (decl);
913}
914
ca4c3545 915/* Return the type of a decl. If the decl is reference type,
916 return its base type. */
917static inline tree
918get_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
1e8e9920 927 allows for the variable form to not have been entered, otherwise we
928 assert that the variable must have been entered. */
929
930static inline tree
931lookup_decl (tree var, omp_context *ctx)
932{
06ecf488 933 tree *n = ctx->cb.decl_map->get (var);
e3022db7 934 return *n;
1e8e9920 935}
936
937static inline tree
e8a588af 938maybe_lookup_decl (const_tree var, omp_context *ctx)
1e8e9920 939{
06ecf488 940 tree *n = ctx->cb.decl_map->get (const_cast<tree> (var));
e3022db7 941 return n ? *n : NULL_TREE;
1e8e9920 942}
943
944static inline tree
945lookup_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
fd6481cf 952static inline tree
953lookup_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
1e8e9920 962static inline tree
963maybe_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
ca4c3545 970static inline tree
971lookup_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
978static inline tree
979maybe_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
e8a588af 987/* Return true if DECL should be copied by pointer. SHARED_CTX is
988 the parallel context if DECL is to be shared. */
1e8e9920 989
990static bool
fd6481cf 991use_pointer_for_field (tree decl, omp_context *shared_ctx)
1e8e9920 992{
993 if (AGGREGATE_TYPE_P (TREE_TYPE (decl)))
994 return true;
995
554f2707 996 /* We can only use copy-in/copy-out semantics for shared variables
1e8e9920 997 when we know the value is not accessible from an outer scope. */
e8a588af 998 if (shared_ctx)
1e8e9920 999 {
ca4c3545 1000 gcc_assert (!is_gimple_omp_oacc (shared_ctx->stmt));
1001
1e8e9920 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. */
df2c34fc 1013 if (TREE_CODE (decl) != RESULT_DECL && DECL_HAS_VALUE_EXPR_P (decl))
1e8e9920 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;
e8a588af 1020
b8214689 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
e8a588af 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. */
b8214689 1034 if (shared_ctx->is_nested)
e8a588af 1035 {
1036 omp_context *up;
1037
1038 for (up = shared_ctx->outer; up; up = up->outer)
0cb159ec 1039 if (is_taskreg_ctx (up) && maybe_lookup_decl (decl, up))
e8a588af 1040 break;
1041
0cb159ec 1042 if (up)
e8a588af 1043 {
1044 tree c;
1045
75a70cf9 1046 for (c = gimple_omp_taskreg_clauses (up->stmt);
e8a588af 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)
784ad964 1053 goto maybe_mark_addressable_and_ret;
e8a588af 1054 }
1055 }
fd6481cf 1056
b8214689 1057 /* For tasks avoid using copy-in/out. As tasks can be
fd6481cf 1058 deferred or executed in different thread, when GOMP_task
1059 returns, the task hasn't necessarily terminated. */
b8214689 1060 if (is_task_ctx (shared_ctx))
fd6481cf 1061 {
784ad964 1062 tree outer;
1063 maybe_mark_addressable_and_ret:
1064 outer = maybe_lookup_decl_in_outer_ctx (decl, shared_ctx);
fd6481cf 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 }
1e8e9920 1077 }
1078
1079 return false;
1080}
1081
79acaae1 1082/* Construct a new automatic decl similar to VAR. */
1083
1084static tree
1085omp_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;
1767a056 1090 DECL_CHAIN (copy) = ctx->block_vars;
1e8e9920 1091 ctx->block_vars = copy;
1092
1093 return copy;
1094}
1095
1096static tree
1097omp_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
445d06b6 1102/* Build COMPONENT_REF and set TREE_THIS_VOLATILE and TREE_READONLY on it
1103 as appropriate. */
1104static tree
1105omp_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
1e8e9920 1115/* Build tree nodes to access the field for VAR on the receiver side. */
1116
1117static tree
1118build_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
182cf5a9 1128 x = build_simple_mem_ref (ctx->receiver_decl);
75c20a2e 1129 TREE_THIS_NOTRAP (x) = 1;
445d06b6 1130 x = omp_build_component_ref (x, field);
1e8e9920 1131 if (by_ref)
182cf5a9 1132 x = build_simple_mem_ref (x);
1e8e9920 1133
1134 return x;
1135}
1136
1137/* Build tree nodes to access VAR in the scope outer to CTX. In the case
1138 of a parallel, this is a component reference; for workshare constructs
1139 this is some variable. */
1140
1141static tree
1142build_outer_var_ref (tree var, omp_context *ctx)
1143{
1144 tree x;
1145
f49d7bb5 1146 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx)))
1e8e9920 1147 x = var;
1148 else if (is_variable_sized (var))
1149 {
1150 x = TREE_OPERAND (DECL_VALUE_EXPR (var), 0);
1151 x = build_outer_var_ref (x, ctx);
182cf5a9 1152 x = build_simple_mem_ref (x);
1e8e9920 1153 }
fd6481cf 1154 else if (is_taskreg_ctx (ctx))
1e8e9920 1155 {
e8a588af 1156 bool by_ref = use_pointer_for_field (var, NULL);
1e8e9920 1157 x = build_receiver_ref (var, by_ref, ctx);
1158 }
3d483a94 1159 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
10c55644 1160 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
3d483a94 1161 {
1162 /* #pragma omp simd isn't a worksharing construct, and can reference even
1163 private vars in its linear etc. clauses. */
1164 x = NULL_TREE;
1165 if (ctx->outer && is_taskreg_ctx (ctx))
1166 x = lookup_decl (var, ctx->outer);
1167 else if (ctx->outer)
84cb1020 1168 x = maybe_lookup_decl_in_outer_ctx (var, ctx);
3d483a94 1169 if (x == NULL_TREE)
1170 x = var;
1171 }
1e8e9920 1172 else if (ctx->outer)
1173 x = lookup_decl (var, ctx->outer);
9438af57 1174 else if (is_reference (var))
1175 /* This can happen with orphaned constructs. If var is reference, it is
1176 possible it is shared and as such valid. */
1177 x = var;
1e8e9920 1178 else
1179 gcc_unreachable ();
1180
1181 if (is_reference (var))
182cf5a9 1182 x = build_simple_mem_ref (x);
1e8e9920 1183
1184 return x;
1185}
1186
1187/* Build tree nodes to access the field for VAR on the sender side. */
1188
1189static tree
1190build_sender_ref (tree var, omp_context *ctx)
1191{
fd6481cf 1192 tree field = lookup_sfield (var, ctx);
445d06b6 1193 return omp_build_component_ref (ctx->sender_decl, field);
1e8e9920 1194}
1195
1196/* Add a new field for VAR inside the structure CTX->SENDER_DECL. */
1197
1198static void
fd6481cf 1199install_var_field (tree var, bool by_ref, int mask, omp_context *ctx)
1e8e9920 1200{
fd6481cf 1201 tree field, type, sfield = NULL_TREE;
1e8e9920 1202
fd6481cf 1203 gcc_assert ((mask & 1) == 0
1204 || !splay_tree_lookup (ctx->field_map, (splay_tree_key) var));
1205 gcc_assert ((mask & 2) == 0 || !ctx->sfield_map
1206 || !splay_tree_lookup (ctx->sfield_map, (splay_tree_key) var));
ca4c3545 1207 gcc_assert ((mask & 3) == 3
1208 || !is_gimple_omp_oacc (ctx->stmt));
1e8e9920 1209
1210 type = TREE_TYPE (var);
bc7bff74 1211 if (mask & 4)
1212 {
1213 gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
1214 type = build_pointer_type (build_pointer_type (type));
1215 }
1216 else if (by_ref)
1e8e9920 1217 type = build_pointer_type (type);
fd6481cf 1218 else if ((mask & 3) == 1 && is_reference (var))
1219 type = TREE_TYPE (type);
1e8e9920 1220
e60a6f7b 1221 field = build_decl (DECL_SOURCE_LOCATION (var),
1222 FIELD_DECL, DECL_NAME (var), type);
1e8e9920 1223
1224 /* Remember what variable this field was created for. This does have a
1225 side effect of making dwarf2out ignore this member, so for helpful
1226 debugging we clear it later in delete_omp_context. */
1227 DECL_ABSTRACT_ORIGIN (field) = var;
fd6481cf 1228 if (type == TREE_TYPE (var))
1229 {
1230 DECL_ALIGN (field) = DECL_ALIGN (var);
1231 DECL_USER_ALIGN (field) = DECL_USER_ALIGN (var);
1232 TREE_THIS_VOLATILE (field) = TREE_THIS_VOLATILE (var);
1233 }
1234 else
1235 DECL_ALIGN (field) = TYPE_ALIGN (type);
1e8e9920 1236
fd6481cf 1237 if ((mask & 3) == 3)
1238 {
1239 insert_field_into_struct (ctx->record_type, field);
1240 if (ctx->srecord_type)
1241 {
e60a6f7b 1242 sfield = build_decl (DECL_SOURCE_LOCATION (var),
1243 FIELD_DECL, DECL_NAME (var), type);
fd6481cf 1244 DECL_ABSTRACT_ORIGIN (sfield) = var;
1245 DECL_ALIGN (sfield) = DECL_ALIGN (field);
1246 DECL_USER_ALIGN (sfield) = DECL_USER_ALIGN (field);
1247 TREE_THIS_VOLATILE (sfield) = TREE_THIS_VOLATILE (field);
1248 insert_field_into_struct (ctx->srecord_type, sfield);
1249 }
1250 }
1251 else
1252 {
1253 if (ctx->srecord_type == NULL_TREE)
1254 {
1255 tree t;
1256
1257 ctx->srecord_type = lang_hooks.types.make_type (RECORD_TYPE);
1258 ctx->sfield_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
1259 for (t = TYPE_FIELDS (ctx->record_type); t ; t = TREE_CHAIN (t))
1260 {
e60a6f7b 1261 sfield = build_decl (DECL_SOURCE_LOCATION (var),
1262 FIELD_DECL, DECL_NAME (t), TREE_TYPE (t));
fd6481cf 1263 DECL_ABSTRACT_ORIGIN (sfield) = DECL_ABSTRACT_ORIGIN (t);
1264 insert_field_into_struct (ctx->srecord_type, sfield);
1265 splay_tree_insert (ctx->sfield_map,
1266 (splay_tree_key) DECL_ABSTRACT_ORIGIN (t),
1267 (splay_tree_value) sfield);
1268 }
1269 }
1270 sfield = field;
1271 insert_field_into_struct ((mask & 1) ? ctx->record_type
1272 : ctx->srecord_type, field);
1273 }
1e8e9920 1274
fd6481cf 1275 if (mask & 1)
1276 splay_tree_insert (ctx->field_map, (splay_tree_key) var,
1277 (splay_tree_value) field);
1278 if ((mask & 2) && ctx->sfield_map)
1279 splay_tree_insert (ctx->sfield_map, (splay_tree_key) var,
1280 (splay_tree_value) sfield);
1e8e9920 1281}
1282
1283static tree
1284install_var_local (tree var, omp_context *ctx)
1285{
1286 tree new_var = omp_copy_decl_1 (var, ctx);
1287 insert_decl_map (&ctx->cb, var, new_var);
1288 return new_var;
1289}
1290
1291/* Adjust the replacement for DECL in CTX for the new context. This means
1292 copying the DECL_VALUE_EXPR, and fixing up the type. */
1293
1294static void
1295fixup_remapped_decl (tree decl, omp_context *ctx, bool private_debug)
1296{
1297 tree new_decl, size;
1298
1299 new_decl = lookup_decl (decl, ctx);
1300
1301 TREE_TYPE (new_decl) = remap_type (TREE_TYPE (decl), &ctx->cb);
1302
1303 if ((!TREE_CONSTANT (DECL_SIZE (new_decl)) || private_debug)
1304 && DECL_HAS_VALUE_EXPR_P (decl))
1305 {
1306 tree ve = DECL_VALUE_EXPR (decl);
75a70cf9 1307 walk_tree (&ve, copy_tree_body_r, &ctx->cb, NULL);
1e8e9920 1308 SET_DECL_VALUE_EXPR (new_decl, ve);
1309 DECL_HAS_VALUE_EXPR_P (new_decl) = 1;
1310 }
1311
1312 if (!TREE_CONSTANT (DECL_SIZE (new_decl)))
1313 {
1314 size = remap_decl (DECL_SIZE (decl), &ctx->cb);
1315 if (size == error_mark_node)
1316 size = TYPE_SIZE (TREE_TYPE (new_decl));
1317 DECL_SIZE (new_decl) = size;
1318
1319 size = remap_decl (DECL_SIZE_UNIT (decl), &ctx->cb);
1320 if (size == error_mark_node)
1321 size = TYPE_SIZE_UNIT (TREE_TYPE (new_decl));
1322 DECL_SIZE_UNIT (new_decl) = size;
1323 }
1324}
1325
1326/* The callback for remap_decl. Search all containing contexts for a
1327 mapping of the variable; this avoids having to duplicate the splay
1328 tree ahead of time. We know a mapping doesn't already exist in the
1329 given context. Create new mappings to implement default semantics. */
1330
1331static tree
1332omp_copy_decl (tree var, copy_body_data *cb)
1333{
1334 omp_context *ctx = (omp_context *) cb;
1335 tree new_var;
1336
1e8e9920 1337 if (TREE_CODE (var) == LABEL_DECL)
1338 {
e60a6f7b 1339 new_var = create_artificial_label (DECL_SOURCE_LOCATION (var));
773c5ba7 1340 DECL_CONTEXT (new_var) = current_function_decl;
1e8e9920 1341 insert_decl_map (&ctx->cb, var, new_var);
1342 return new_var;
1343 }
1344
fd6481cf 1345 while (!is_taskreg_ctx (ctx))
1e8e9920 1346 {
1347 ctx = ctx->outer;
1348 if (ctx == NULL)
1349 return var;
1350 new_var = maybe_lookup_decl (var, ctx);
1351 if (new_var)
1352 return new_var;
1353 }
1354
f49d7bb5 1355 if (is_global_var (var) || decl_function_context (var) != ctx->cb.src_fn)
1356 return var;
1357
1e8e9920 1358 return error_mark_node;
1359}
1360
773c5ba7 1361
773c5ba7 1362/* Debugging dumps for parallel regions. */
1363void dump_omp_region (FILE *, struct omp_region *, int);
1364void debug_omp_region (struct omp_region *);
1365void debug_all_omp_regions (void);
1366
1367/* Dump the parallel region tree rooted at REGION. */
1368
1369void
1370dump_omp_region (FILE *file, struct omp_region *region, int indent)
1371{
61e47ac8 1372 fprintf (file, "%*sbb %d: %s\n", indent, "", region->entry->index,
75a70cf9 1373 gimple_code_name[region->type]);
773c5ba7 1374
1375 if (region->inner)
1376 dump_omp_region (file, region->inner, indent + 4);
1377
61e47ac8 1378 if (region->cont)
1379 {
75a70cf9 1380 fprintf (file, "%*sbb %d: GIMPLE_OMP_CONTINUE\n", indent, "",
61e47ac8 1381 region->cont->index);
1382 }
48e1416a 1383
773c5ba7 1384 if (region->exit)
75a70cf9 1385 fprintf (file, "%*sbb %d: GIMPLE_OMP_RETURN\n", indent, "",
61e47ac8 1386 region->exit->index);
773c5ba7 1387 else
61e47ac8 1388 fprintf (file, "%*s[no exit marker]\n", indent, "");
773c5ba7 1389
1390 if (region->next)
61e47ac8 1391 dump_omp_region (file, region->next, indent);
773c5ba7 1392}
1393
4b987fac 1394DEBUG_FUNCTION void
773c5ba7 1395debug_omp_region (struct omp_region *region)
1396{
1397 dump_omp_region (stderr, region, 0);
1398}
1399
4b987fac 1400DEBUG_FUNCTION void
773c5ba7 1401debug_all_omp_regions (void)
1402{
1403 dump_omp_region (stderr, root_omp_region, 0);
1404}
1405
1406
1407/* Create a new parallel region starting at STMT inside region PARENT. */
1408
7740abd8 1409static struct omp_region *
75a70cf9 1410new_omp_region (basic_block bb, enum gimple_code type,
1411 struct omp_region *parent)
773c5ba7 1412{
4077bf7a 1413 struct omp_region *region = XCNEW (struct omp_region);
773c5ba7 1414
1415 region->outer = parent;
61e47ac8 1416 region->entry = bb;
1417 region->type = type;
773c5ba7 1418
1419 if (parent)
1420 {
1421 /* This is a nested region. Add it to the list of inner
1422 regions in PARENT. */
1423 region->next = parent->inner;
1424 parent->inner = region;
1425 }
61e47ac8 1426 else
773c5ba7 1427 {
1428 /* This is a toplevel region. Add it to the list of toplevel
1429 regions in ROOT_OMP_REGION. */
1430 region->next = root_omp_region;
1431 root_omp_region = region;
1432 }
61e47ac8 1433
1434 return region;
1435}
1436
1437/* Release the memory associated with the region tree rooted at REGION. */
1438
1439static void
1440free_omp_region_1 (struct omp_region *region)
1441{
1442 struct omp_region *i, *n;
1443
1444 for (i = region->inner; i ; i = n)
773c5ba7 1445 {
61e47ac8 1446 n = i->next;
1447 free_omp_region_1 (i);
773c5ba7 1448 }
1449
61e47ac8 1450 free (region);
1451}
773c5ba7 1452
61e47ac8 1453/* Release the memory for the entire omp region tree. */
1454
1455void
1456free_omp_regions (void)
1457{
1458 struct omp_region *r, *n;
1459 for (r = root_omp_region; r ; r = n)
1460 {
1461 n = r->next;
1462 free_omp_region_1 (r);
1463 }
1464 root_omp_region = NULL;
773c5ba7 1465}
1466
1467
1e8e9920 1468/* Create a new context, with OUTER_CTX being the surrounding context. */
1469
1470static omp_context *
42acab1c 1471new_omp_context (gimple *stmt, omp_context *outer_ctx)
1e8e9920 1472{
1473 omp_context *ctx = XCNEW (omp_context);
1474
1475 splay_tree_insert (all_contexts, (splay_tree_key) stmt,
1476 (splay_tree_value) ctx);
1477 ctx->stmt = stmt;
1478
1479 if (outer_ctx)
1480 {
1481 ctx->outer = outer_ctx;
1482 ctx->cb = outer_ctx->cb;
1483 ctx->cb.block = NULL;
1484 ctx->depth = outer_ctx->depth + 1;
ca4c3545 1485 ctx->reduction_map = outer_ctx->reduction_map;
1e8e9920 1486 }
1487 else
1488 {
1489 ctx->cb.src_fn = current_function_decl;
1490 ctx->cb.dst_fn = current_function_decl;
415d1b9a 1491 ctx->cb.src_node = cgraph_node::get (current_function_decl);
53f79206 1492 gcc_checking_assert (ctx->cb.src_node);
1e8e9920 1493 ctx->cb.dst_node = ctx->cb.src_node;
1494 ctx->cb.src_cfun = cfun;
1495 ctx->cb.copy_decl = omp_copy_decl;
e38def9c 1496 ctx->cb.eh_lp_nr = 0;
1e8e9920 1497 ctx->cb.transform_call_graph_edges = CB_CGE_MOVE;
1498 ctx->depth = 1;
1499 }
1500
06ecf488 1501 ctx->cb.decl_map = new hash_map<tree, tree>;
1e8e9920 1502
1503 return ctx;
1504}
1505
75a70cf9 1506static gimple_seq maybe_catch_exception (gimple_seq);
f6430caa 1507
1508/* Finalize task copyfn. */
1509
1510static void
1a91d914 1511finalize_task_copyfn (gomp_task *task_stmt)
f6430caa 1512{
1513 struct function *child_cfun;
9078126c 1514 tree child_fn;
e3a19533 1515 gimple_seq seq = NULL, new_seq;
1a91d914 1516 gbind *bind;
f6430caa 1517
75a70cf9 1518 child_fn = gimple_omp_task_copy_fn (task_stmt);
f6430caa 1519 if (child_fn == NULL_TREE)
1520 return;
1521
1522 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
82b40354 1523 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
f6430caa 1524
f6430caa 1525 push_cfun (child_cfun);
7e3aae05 1526 bind = gimplify_body (child_fn, false);
75a70cf9 1527 gimple_seq_add_stmt (&seq, bind);
1528 new_seq = maybe_catch_exception (seq);
1529 if (new_seq != seq)
1530 {
1531 bind = gimple_build_bind (NULL, new_seq, NULL);
e3a19533 1532 seq = NULL;
75a70cf9 1533 gimple_seq_add_stmt (&seq, bind);
1534 }
1535 gimple_set_body (child_fn, seq);
f6430caa 1536 pop_cfun ();
f6430caa 1537
82b40354 1538 /* Inform the callgraph about the new function. */
47300487 1539 cgraph_node *node = cgraph_node::get_create (child_fn);
1540 node->parallelized_function = 1;
415d1b9a 1541 cgraph_node::add_new_function (child_fn, false);
f6430caa 1542}
1543
1e8e9920 1544/* Destroy a omp_context data structures. Called through the splay tree
1545 value delete callback. */
1546
1547static void
1548delete_omp_context (splay_tree_value value)
1549{
1550 omp_context *ctx = (omp_context *) value;
1551
06ecf488 1552 delete ctx->cb.decl_map;
1e8e9920 1553
1554 if (ctx->field_map)
1555 splay_tree_delete (ctx->field_map);
fd6481cf 1556 if (ctx->sfield_map)
1557 splay_tree_delete (ctx->sfield_map);
42d49354 1558 /* Reduction map is copied to nested contexts, so only delete it in the
1559 owner. */
ca4c3545 1560 if (ctx->reduction_map
42d49354 1561 && gimple_code (ctx->stmt) == GIMPLE_OMP_TARGET
1562 && is_gimple_omp_offloaded (ctx->stmt)
1563 && is_gimple_omp_oacc (ctx->stmt))
ca4c3545 1564 splay_tree_delete (ctx->reduction_map);
1e8e9920 1565
1566 /* We hijacked DECL_ABSTRACT_ORIGIN earlier. We need to clear it before
1567 it produces corrupt debug information. */
1568 if (ctx->record_type)
1569 {
1570 tree t;
1767a056 1571 for (t = TYPE_FIELDS (ctx->record_type); t ; t = DECL_CHAIN (t))
1e8e9920 1572 DECL_ABSTRACT_ORIGIN (t) = NULL;
1573 }
fd6481cf 1574 if (ctx->srecord_type)
1575 {
1576 tree t;
1767a056 1577 for (t = TYPE_FIELDS (ctx->srecord_type); t ; t = DECL_CHAIN (t))
fd6481cf 1578 DECL_ABSTRACT_ORIGIN (t) = NULL;
1579 }
1e8e9920 1580
f6430caa 1581 if (is_task_ctx (ctx))
1a91d914 1582 finalize_task_copyfn (as_a <gomp_task *> (ctx->stmt));
f6430caa 1583
1e8e9920 1584 XDELETE (ctx);
1585}
1586
1587/* Fix up RECEIVER_DECL with a type that has been remapped to the child
1588 context. */
1589
1590static void
1591fixup_child_record_type (omp_context *ctx)
1592{
1593 tree f, type = ctx->record_type;
1594
1595 /* ??? It isn't sufficient to just call remap_type here, because
1596 variably_modified_type_p doesn't work the way we expect for
1597 record types. Testing each field for whether it needs remapping
1598 and creating a new record by hand works, however. */
1767a056 1599 for (f = TYPE_FIELDS (type); f ; f = DECL_CHAIN (f))
1e8e9920 1600 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
1601 break;
1602 if (f)
1603 {
1604 tree name, new_fields = NULL;
1605
1606 type = lang_hooks.types.make_type (RECORD_TYPE);
1607 name = DECL_NAME (TYPE_NAME (ctx->record_type));
e60a6f7b 1608 name = build_decl (DECL_SOURCE_LOCATION (ctx->receiver_decl),
1609 TYPE_DECL, name, type);
1e8e9920 1610 TYPE_NAME (type) = name;
1611
1767a056 1612 for (f = TYPE_FIELDS (ctx->record_type); f ; f = DECL_CHAIN (f))
1e8e9920 1613 {
1614 tree new_f = copy_node (f);
1615 DECL_CONTEXT (new_f) = type;
1616 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &ctx->cb);
1767a056 1617 DECL_CHAIN (new_f) = new_fields;
75a70cf9 1618 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &ctx->cb, NULL);
1619 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r,
1620 &ctx->cb, NULL);
1621 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
1622 &ctx->cb, NULL);
1e8e9920 1623 new_fields = new_f;
1624
1625 /* Arrange to be able to look up the receiver field
1626 given the sender field. */
1627 splay_tree_insert (ctx->field_map, (splay_tree_key) f,
1628 (splay_tree_value) new_f);
1629 }
1630 TYPE_FIELDS (type) = nreverse (new_fields);
1631 layout_type (type);
1632 }
1633
5455b100 1634 TREE_TYPE (ctx->receiver_decl)
1635 = build_qualified_type (build_reference_type (type), TYPE_QUAL_RESTRICT);
1e8e9920 1636}
1637
1638/* Instantiate decls as necessary in CTX to satisfy the data sharing
1639 specified by CLAUSES. */
1640
1641static void
1642scan_sharing_clauses (tree clauses, omp_context *ctx)
1643{
1644 tree c, decl;
1645 bool scan_array_reductions = false;
1646
1647 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1648 {
1649 bool by_ref;
1650
55d6e7cd 1651 switch (OMP_CLAUSE_CODE (c))
1e8e9920 1652 {
1653 case OMP_CLAUSE_PRIVATE:
1654 decl = OMP_CLAUSE_DECL (c);
fd6481cf 1655 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
1656 goto do_private;
1657 else if (!is_variable_sized (decl))
1e8e9920 1658 install_var_local (decl, ctx);
1659 break;
1660
1661 case OMP_CLAUSE_SHARED:
5fddcf34 1662 decl = OMP_CLAUSE_DECL (c);
bc7bff74 1663 /* Ignore shared directives in teams construct. */
1664 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
5fddcf34 1665 {
1666 /* Global variables don't need to be copied,
1667 the receiver side will use them directly. */
1668 tree odecl = maybe_lookup_decl_in_outer_ctx (decl, ctx);
1669 if (is_global_var (odecl))
1670 break;
1671 insert_decl_map (&ctx->cb, decl, odecl);
1672 break;
1673 }
fd6481cf 1674 gcc_assert (is_taskreg_ctx (ctx));
e7327393 1675 gcc_assert (!COMPLETE_TYPE_P (TREE_TYPE (decl))
1676 || !is_variable_sized (decl));
f49d7bb5 1677 /* Global variables don't need to be copied,
1678 the receiver side will use them directly. */
1679 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1680 break;
fd6481cf 1681 by_ref = use_pointer_for_field (decl, ctx);
1e8e9920 1682 if (! TREE_READONLY (decl)
1683 || TREE_ADDRESSABLE (decl)
1684 || by_ref
1685 || is_reference (decl))
1686 {
fd6481cf 1687 install_var_field (decl, by_ref, 3, ctx);
1e8e9920 1688 install_var_local (decl, ctx);
1689 break;
1690 }
1691 /* We don't need to copy const scalar vars back. */
55d6e7cd 1692 OMP_CLAUSE_SET_CODE (c, OMP_CLAUSE_FIRSTPRIVATE);
1e8e9920 1693 goto do_private;
1694
1695 case OMP_CLAUSE_LASTPRIVATE:
1696 /* Let the corresponding firstprivate clause create
1697 the variable. */
1698 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1699 break;
1700 /* FALLTHRU */
1701
1702 case OMP_CLAUSE_FIRSTPRIVATE:
ca4c3545 1703 if (is_gimple_omp_oacc (ctx->stmt))
1704 {
1705 sorry ("clause not supported yet");
1706 break;
1707 }
1708 /* FALLTHRU */
1e8e9920 1709 case OMP_CLAUSE_REDUCTION:
3d483a94 1710 case OMP_CLAUSE_LINEAR:
1e8e9920 1711 decl = OMP_CLAUSE_DECL (c);
1712 do_private:
1713 if (is_variable_sized (decl))
1e8e9920 1714 {
fd6481cf 1715 if (is_task_ctx (ctx))
1716 install_var_field (decl, false, 1, ctx);
1717 break;
1718 }
1719 else if (is_taskreg_ctx (ctx))
1720 {
1721 bool global
1722 = is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx));
e8a588af 1723 by_ref = use_pointer_for_field (decl, NULL);
fd6481cf 1724
1725 if (is_task_ctx (ctx)
1726 && (global || by_ref || is_reference (decl)))
1727 {
1728 install_var_field (decl, false, 1, ctx);
1729 if (!global)
1730 install_var_field (decl, by_ref, 2, ctx);
1731 }
1732 else if (!global)
1733 install_var_field (decl, by_ref, 3, ctx);
1e8e9920 1734 }
1735 install_var_local (decl, ctx);
ca4c3545 1736 if (is_gimple_omp_oacc (ctx->stmt)
1737 && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
1738 {
1739 /* Create a decl for the reduction array. */
1740 tree var = OMP_CLAUSE_DECL (c);
1741 tree type = get_base_type (var);
1742 tree ptype = build_pointer_type (type);
1743 tree array = create_tmp_var (ptype,
1744 oacc_get_reduction_array_id (var));
1745 omp_context *c = (ctx->field_map ? ctx : ctx->outer);
1746 install_var_field (array, true, 3, c);
1747 install_var_local (array, c);
1748
1749 /* Insert it into the current context. */
1750 splay_tree_insert (ctx->reduction_map, (splay_tree_key)
1751 oacc_get_reduction_array_id (var),
1752 (splay_tree_value) array);
1753 splay_tree_insert (ctx->reduction_map,
1754 (splay_tree_key) array,
1755 (splay_tree_value) array);
1756 }
1e8e9920 1757 break;
1758
bc7bff74 1759 case OMP_CLAUSE__LOOPTEMP_:
1760 gcc_assert (is_parallel_ctx (ctx));
1761 decl = OMP_CLAUSE_DECL (c);
1762 install_var_field (decl, false, 3, ctx);
1763 install_var_local (decl, ctx);
1764 break;
1765
1e8e9920 1766 case OMP_CLAUSE_COPYPRIVATE:
1e8e9920 1767 case OMP_CLAUSE_COPYIN:
1768 decl = OMP_CLAUSE_DECL (c);
e8a588af 1769 by_ref = use_pointer_for_field (decl, NULL);
fd6481cf 1770 install_var_field (decl, by_ref, 3, ctx);
1e8e9920 1771 break;
1772
1773 case OMP_CLAUSE_DEFAULT:
1774 ctx->default_kind = OMP_CLAUSE_DEFAULT_KIND (c);
1775 break;
1776
2169f33b 1777 case OMP_CLAUSE_FINAL:
1e8e9920 1778 case OMP_CLAUSE_IF:
1779 case OMP_CLAUSE_NUM_THREADS:
bc7bff74 1780 case OMP_CLAUSE_NUM_TEAMS:
1781 case OMP_CLAUSE_THREAD_LIMIT:
1782 case OMP_CLAUSE_DEVICE:
1e8e9920 1783 case OMP_CLAUSE_SCHEDULE:
bc7bff74 1784 case OMP_CLAUSE_DIST_SCHEDULE:
1785 case OMP_CLAUSE_DEPEND:
40750995 1786 case OMP_CLAUSE__CILK_FOR_COUNT_:
ca4c3545 1787 case OMP_CLAUSE_NUM_GANGS:
1788 case OMP_CLAUSE_NUM_WORKERS:
1789 case OMP_CLAUSE_VECTOR_LENGTH:
1e8e9920 1790 if (ctx->outer)
75a70cf9 1791 scan_omp_op (&OMP_CLAUSE_OPERAND (c, 0), ctx->outer);
1e8e9920 1792 break;
1793
bc7bff74 1794 case OMP_CLAUSE_TO:
1795 case OMP_CLAUSE_FROM:
1796 case OMP_CLAUSE_MAP:
1797 if (ctx->outer)
1798 scan_omp_op (&OMP_CLAUSE_SIZE (c), ctx->outer);
1799 decl = OMP_CLAUSE_DECL (c);
1800 /* Global variables with "omp declare target" attribute
1801 don't need to be copied, the receiver side will use them
1802 directly. */
1803 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1804 && DECL_P (decl)
1805 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
b0c5e347 1806 && varpool_node::get_create (decl)->offloadable)
bc7bff74 1807 break;
1808 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
ca4c3545 1809 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER)
bc7bff74 1810 {
ca4c3545 1811 /* Ignore GOMP_MAP_POINTER kind for arrays in regions that are
1812 not offloaded; there is nothing to map for those. */
1813 if (!is_gimple_omp_offloaded (ctx->stmt)
c1a114c2 1814 && !POINTER_TYPE_P (TREE_TYPE (decl))
1815 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
bc7bff74 1816 break;
1817 }
1818 if (DECL_P (decl))
1819 {
1820 if (DECL_SIZE (decl)
1821 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
1822 {
1823 tree decl2 = DECL_VALUE_EXPR (decl);
1824 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
1825 decl2 = TREE_OPERAND (decl2, 0);
1826 gcc_assert (DECL_P (decl2));
1827 install_var_field (decl2, true, 3, ctx);
1828 install_var_local (decl2, ctx);
1829 install_var_local (decl, ctx);
1830 }
1831 else
1832 {
1833 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
ca4c3545 1834 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
bc7bff74 1835 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
1836 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1837 install_var_field (decl, true, 7, ctx);
1838 else
1839 install_var_field (decl, true, 3, ctx);
ca4c3545 1840 if (is_gimple_omp_offloaded (ctx->stmt))
bc7bff74 1841 install_var_local (decl, ctx);
1842 }
1843 }
1844 else
1845 {
1846 tree base = get_base_address (decl);
1847 tree nc = OMP_CLAUSE_CHAIN (c);
1848 if (DECL_P (base)
1849 && nc != NULL_TREE
1850 && OMP_CLAUSE_CODE (nc) == OMP_CLAUSE_MAP
1851 && OMP_CLAUSE_DECL (nc) == base
ca4c3545 1852 && OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_POINTER
bc7bff74 1853 && integer_zerop (OMP_CLAUSE_SIZE (nc)))
1854 {
1855 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c) = 1;
1856 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (nc) = 1;
1857 }
1858 else
1859 {
691447ab 1860 if (ctx->outer)
1861 {
1862 scan_omp_op (&OMP_CLAUSE_DECL (c), ctx->outer);
1863 decl = OMP_CLAUSE_DECL (c);
1864 }
bc7bff74 1865 gcc_assert (!splay_tree_lookup (ctx->field_map,
1866 (splay_tree_key) decl));
1867 tree field
1868 = build_decl (OMP_CLAUSE_LOCATION (c),
1869 FIELD_DECL, NULL_TREE, ptr_type_node);
1870 DECL_ALIGN (field) = TYPE_ALIGN (ptr_type_node);
1871 insert_field_into_struct (ctx->record_type, field);
1872 splay_tree_insert (ctx->field_map, (splay_tree_key) decl,
1873 (splay_tree_value) field);
1874 }
1875 }
1876 break;
1877
1e8e9920 1878 case OMP_CLAUSE_NOWAIT:
1879 case OMP_CLAUSE_ORDERED:
fd6481cf 1880 case OMP_CLAUSE_COLLAPSE:
1881 case OMP_CLAUSE_UNTIED:
2169f33b 1882 case OMP_CLAUSE_MERGEABLE:
bc7bff74 1883 case OMP_CLAUSE_PROC_BIND:
3d483a94 1884 case OMP_CLAUSE_SAFELEN:
ca4c3545 1885 case OMP_CLAUSE_ASYNC:
1886 case OMP_CLAUSE_WAIT:
1887 case OMP_CLAUSE_GANG:
1888 case OMP_CLAUSE_WORKER:
1889 case OMP_CLAUSE_VECTOR:
1e8e9920 1890 break;
1891
bc7bff74 1892 case OMP_CLAUSE_ALIGNED:
1893 decl = OMP_CLAUSE_DECL (c);
1894 if (is_global_var (decl)
1895 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1896 install_var_local (decl, ctx);
1897 break;
1898
ca4c3545 1899 case OMP_CLAUSE_DEVICE_RESIDENT:
1900 case OMP_CLAUSE_USE_DEVICE:
1901 case OMP_CLAUSE__CACHE_:
1902 case OMP_CLAUSE_INDEPENDENT:
1903 case OMP_CLAUSE_AUTO:
1904 case OMP_CLAUSE_SEQ:
1905 sorry ("Clause not supported yet");
1906 break;
1907
1e8e9920 1908 default:
1909 gcc_unreachable ();
1910 }
1911 }
1912
1913 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1914 {
55d6e7cd 1915 switch (OMP_CLAUSE_CODE (c))
1e8e9920 1916 {
1917 case OMP_CLAUSE_LASTPRIVATE:
1918 /* Let the corresponding firstprivate clause create
1919 the variable. */
75a70cf9 1920 if (OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
fd6481cf 1921 scan_array_reductions = true;
1e8e9920 1922 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1923 break;
1924 /* FALLTHRU */
1925
1e8e9920 1926 case OMP_CLAUSE_FIRSTPRIVATE:
ca4c3545 1927 if (is_gimple_omp_oacc (ctx->stmt))
1928 {
1929 sorry ("clause not supported yet");
1930 break;
1931 }
1932 /* FALLTHRU */
1933 case OMP_CLAUSE_PRIVATE:
1e8e9920 1934 case OMP_CLAUSE_REDUCTION:
3d483a94 1935 case OMP_CLAUSE_LINEAR:
1e8e9920 1936 decl = OMP_CLAUSE_DECL (c);
1937 if (is_variable_sized (decl))
1938 install_var_local (decl, ctx);
1939 fixup_remapped_decl (decl, ctx,
55d6e7cd 1940 OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE
1e8e9920 1941 && OMP_CLAUSE_PRIVATE_DEBUG (c));
55d6e7cd 1942 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1e8e9920 1943 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1944 scan_array_reductions = true;
2b536a17 1945 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
1946 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
1947 scan_array_reductions = true;
1e8e9920 1948 break;
1949
1950 case OMP_CLAUSE_SHARED:
bc7bff74 1951 /* Ignore shared directives in teams construct. */
1952 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
1953 break;
1e8e9920 1954 decl = OMP_CLAUSE_DECL (c);
f49d7bb5 1955 if (! is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1956 fixup_remapped_decl (decl, ctx, false);
1e8e9920 1957 break;
1958
bc7bff74 1959 case OMP_CLAUSE_MAP:
ca4c3545 1960 if (!is_gimple_omp_offloaded (ctx->stmt))
bc7bff74 1961 break;
1962 decl = OMP_CLAUSE_DECL (c);
1963 if (DECL_P (decl)
1964 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
b0c5e347 1965 && varpool_node::get_create (decl)->offloadable)
bc7bff74 1966 break;
1967 if (DECL_P (decl))
1968 {
ca4c3545 1969 if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
bc7bff74 1970 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
1971 && !COMPLETE_TYPE_P (TREE_TYPE (decl)))
1972 {
1973 tree new_decl = lookup_decl (decl, ctx);
1974 TREE_TYPE (new_decl)
1975 = remap_type (TREE_TYPE (decl), &ctx->cb);
1976 }
1977 else if (DECL_SIZE (decl)
1978 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
1979 {
1980 tree decl2 = DECL_VALUE_EXPR (decl);
1981 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
1982 decl2 = TREE_OPERAND (decl2, 0);
1983 gcc_assert (DECL_P (decl2));
1984 fixup_remapped_decl (decl2, ctx, false);
1985 fixup_remapped_decl (decl, ctx, true);
1986 }
1987 else
1988 fixup_remapped_decl (decl, ctx, false);
1989 }
1990 break;
1991
1e8e9920 1992 case OMP_CLAUSE_COPYPRIVATE:
1993 case OMP_CLAUSE_COPYIN:
1994 case OMP_CLAUSE_DEFAULT:
1995 case OMP_CLAUSE_IF:
1996 case OMP_CLAUSE_NUM_THREADS:
bc7bff74 1997 case OMP_CLAUSE_NUM_TEAMS:
1998 case OMP_CLAUSE_THREAD_LIMIT:
1999 case OMP_CLAUSE_DEVICE:
1e8e9920 2000 case OMP_CLAUSE_SCHEDULE:
bc7bff74 2001 case OMP_CLAUSE_DIST_SCHEDULE:
1e8e9920 2002 case OMP_CLAUSE_NOWAIT:
2003 case OMP_CLAUSE_ORDERED:
fd6481cf 2004 case OMP_CLAUSE_COLLAPSE:
2005 case OMP_CLAUSE_UNTIED:
2169f33b 2006 case OMP_CLAUSE_FINAL:
2007 case OMP_CLAUSE_MERGEABLE:
bc7bff74 2008 case OMP_CLAUSE_PROC_BIND:
3d483a94 2009 case OMP_CLAUSE_SAFELEN:
bc7bff74 2010 case OMP_CLAUSE_ALIGNED:
2011 case OMP_CLAUSE_DEPEND:
2012 case OMP_CLAUSE__LOOPTEMP_:
2013 case OMP_CLAUSE_TO:
2014 case OMP_CLAUSE_FROM:
40750995 2015 case OMP_CLAUSE__CILK_FOR_COUNT_:
ca4c3545 2016 case OMP_CLAUSE_ASYNC:
2017 case OMP_CLAUSE_WAIT:
2018 case OMP_CLAUSE_NUM_GANGS:
2019 case OMP_CLAUSE_NUM_WORKERS:
2020 case OMP_CLAUSE_VECTOR_LENGTH:
2021 case OMP_CLAUSE_GANG:
2022 case OMP_CLAUSE_WORKER:
2023 case OMP_CLAUSE_VECTOR:
2024 break;
2025
2026 case OMP_CLAUSE_DEVICE_RESIDENT:
2027 case OMP_CLAUSE_USE_DEVICE:
2028 case OMP_CLAUSE__CACHE_:
2029 case OMP_CLAUSE_INDEPENDENT:
2030 case OMP_CLAUSE_AUTO:
2031 case OMP_CLAUSE_SEQ:
2032 sorry ("Clause not supported yet");
1e8e9920 2033 break;
2034
2035 default:
2036 gcc_unreachable ();
2037 }
2038 }
2039
ca4c3545 2040 gcc_checking_assert (!scan_array_reductions
2041 || !is_gimple_omp_oacc (ctx->stmt));
1e8e9920 2042 if (scan_array_reductions)
2043 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
55d6e7cd 2044 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1e8e9920 2045 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
2046 {
ab129075 2047 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c), ctx);
2048 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
1e8e9920 2049 }
fd6481cf 2050 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
75a70cf9 2051 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
ab129075 2052 scan_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
2b536a17 2053 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
2054 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
2055 scan_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
1e8e9920 2056}
2057
40750995 2058/* Create a new name for omp child function. Returns an identifier. If
2059 IS_CILK_FOR is true then the suffix for the child function is
2060 "_cilk_for_fn." */
1e8e9920 2061
1e8e9920 2062static tree
40750995 2063create_omp_child_function_name (bool task_copy, bool is_cilk_for)
1e8e9920 2064{
40750995 2065 if (is_cilk_for)
2066 return clone_function_name (current_function_decl, "_cilk_for_fn");
2067 return clone_function_name (current_function_decl,
2068 task_copy ? "_omp_cpyfn" : "_omp_fn");
2069}
2070
2071/* Returns the type of the induction variable for the child function for
2072 _Cilk_for and the types for _high and _low variables based on TYPE. */
2073
2074static tree
2075cilk_for_check_loop_diff_type (tree type)
2076{
2077 if (TYPE_PRECISION (type) <= TYPE_PRECISION (uint32_type_node))
2078 {
2079 if (TYPE_UNSIGNED (type))
2080 return uint32_type_node;
2081 else
2082 return integer_type_node;
2083 }
2084 else
2085 {
2086 if (TYPE_UNSIGNED (type))
2087 return uint64_type_node;
2088 else
2089 return long_long_integer_type_node;
2090 }
1e8e9920 2091}
2092
2093/* Build a decl for the omp child function. It'll not contain a body
2094 yet, just the bare decl. */
2095
2096static void
fd6481cf 2097create_omp_child_function (omp_context *ctx, bool task_copy)
1e8e9920 2098{
2099 tree decl, type, name, t;
2100
40750995 2101 tree cilk_for_count
2102 = (flag_cilkplus && gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL)
2103 ? find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
2104 OMP_CLAUSE__CILK_FOR_COUNT_) : NULL_TREE;
2105 tree cilk_var_type = NULL_TREE;
2106
2107 name = create_omp_child_function_name (task_copy,
2108 cilk_for_count != NULL_TREE);
fd6481cf 2109 if (task_copy)
2110 type = build_function_type_list (void_type_node, ptr_type_node,
2111 ptr_type_node, NULL_TREE);
40750995 2112 else if (cilk_for_count)
2113 {
2114 type = TREE_TYPE (OMP_CLAUSE_OPERAND (cilk_for_count, 0));
2115 cilk_var_type = cilk_for_check_loop_diff_type (type);
2116 type = build_function_type_list (void_type_node, ptr_type_node,
2117 cilk_var_type, cilk_var_type, NULL_TREE);
2118 }
fd6481cf 2119 else
2120 type = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
1e8e9920 2121
40750995 2122 decl = build_decl (gimple_location (ctx->stmt), FUNCTION_DECL, name, type);
1e8e9920 2123
ca4c3545 2124 gcc_checking_assert (!is_gimple_omp_oacc (ctx->stmt)
2125 || !task_copy);
fd6481cf 2126 if (!task_copy)
2127 ctx->cb.dst_fn = decl;
2128 else
75a70cf9 2129 gimple_omp_task_set_copy_fn (ctx->stmt, decl);
1e8e9920 2130
2131 TREE_STATIC (decl) = 1;
2132 TREE_USED (decl) = 1;
2133 DECL_ARTIFICIAL (decl) = 1;
2134 DECL_IGNORED_P (decl) = 0;
2135 TREE_PUBLIC (decl) = 0;
2136 DECL_UNINLINABLE (decl) = 1;
2137 DECL_EXTERNAL (decl) = 0;
2138 DECL_CONTEXT (decl) = NULL_TREE;
773c5ba7 2139 DECL_INITIAL (decl) = make_node (BLOCK);
b0c5e347 2140 if (cgraph_node::get (current_function_decl)->offloadable)
2141 cgraph_node::get_create (decl)->offloadable = 1;
bc7bff74 2142 else
2143 {
2144 omp_context *octx;
2145 for (octx = ctx; octx; octx = octx->outer)
ca4c3545 2146 if (is_gimple_omp_offloaded (octx->stmt))
bc7bff74 2147 {
b0c5e347 2148 cgraph_node::get_create (decl)->offloadable = 1;
7114ebdd 2149#ifdef ENABLE_OFFLOADING
b0c5e347 2150 g->have_offload = true;
7114ebdd 2151#endif
bc7bff74 2152 break;
2153 }
2154 }
1e8e9920 2155
ec12b31a 2156 if (cgraph_node::get_create (decl)->offloadable
2157 && !lookup_attribute ("omp declare target",
2158 DECL_ATTRIBUTES (current_function_decl)))
2159 DECL_ATTRIBUTES (decl)
2160 = tree_cons (get_identifier ("omp target entrypoint"),
2161 NULL_TREE, DECL_ATTRIBUTES (decl));
2162
e60a6f7b 2163 t = build_decl (DECL_SOURCE_LOCATION (decl),
2164 RESULT_DECL, NULL_TREE, void_type_node);
1e8e9920 2165 DECL_ARTIFICIAL (t) = 1;
2166 DECL_IGNORED_P (t) = 1;
8e5b4ed6 2167 DECL_CONTEXT (t) = decl;
1e8e9920 2168 DECL_RESULT (decl) = t;
2169
40750995 2170 /* _Cilk_for's child function requires two extra parameters called
2171 __low and __high that are set the by Cilk runtime when it calls this
2172 function. */
2173 if (cilk_for_count)
2174 {
2175 t = build_decl (DECL_SOURCE_LOCATION (decl),
2176 PARM_DECL, get_identifier ("__high"), cilk_var_type);
2177 DECL_ARTIFICIAL (t) = 1;
2178 DECL_NAMELESS (t) = 1;
2179 DECL_ARG_TYPE (t) = ptr_type_node;
2180 DECL_CONTEXT (t) = current_function_decl;
2181 TREE_USED (t) = 1;
2182 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2183 DECL_ARGUMENTS (decl) = t;
2184
2185 t = build_decl (DECL_SOURCE_LOCATION (decl),
2186 PARM_DECL, get_identifier ("__low"), cilk_var_type);
2187 DECL_ARTIFICIAL (t) = 1;
2188 DECL_NAMELESS (t) = 1;
2189 DECL_ARG_TYPE (t) = ptr_type_node;
2190 DECL_CONTEXT (t) = current_function_decl;
2191 TREE_USED (t) = 1;
2192 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2193 DECL_ARGUMENTS (decl) = t;
2194 }
2195
2196 tree data_name = get_identifier (".omp_data_i");
2197 t = build_decl (DECL_SOURCE_LOCATION (decl), PARM_DECL, data_name,
2198 ptr_type_node);
1e8e9920 2199 DECL_ARTIFICIAL (t) = 1;
84bfaaeb 2200 DECL_NAMELESS (t) = 1;
1e8e9920 2201 DECL_ARG_TYPE (t) = ptr_type_node;
773c5ba7 2202 DECL_CONTEXT (t) = current_function_decl;
1e8e9920 2203 TREE_USED (t) = 1;
40750995 2204 if (cilk_for_count)
2205 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
1e8e9920 2206 DECL_ARGUMENTS (decl) = t;
fd6481cf 2207 if (!task_copy)
2208 ctx->receiver_decl = t;
2209 else
2210 {
e60a6f7b 2211 t = build_decl (DECL_SOURCE_LOCATION (decl),
2212 PARM_DECL, get_identifier (".omp_data_o"),
fd6481cf 2213 ptr_type_node);
2214 DECL_ARTIFICIAL (t) = 1;
84bfaaeb 2215 DECL_NAMELESS (t) = 1;
fd6481cf 2216 DECL_ARG_TYPE (t) = ptr_type_node;
2217 DECL_CONTEXT (t) = current_function_decl;
2218 TREE_USED (t) = 1;
86f2ad37 2219 TREE_ADDRESSABLE (t) = 1;
1767a056 2220 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
fd6481cf 2221 DECL_ARGUMENTS (decl) = t;
2222 }
1e8e9920 2223
48e1416a 2224 /* Allocate memory for the function structure. The call to
773c5ba7 2225 allocate_struct_function clobbers CFUN, so we need to restore
1e8e9920 2226 it afterward. */
87d4aa85 2227 push_struct_function (decl);
75a70cf9 2228 cfun->function_end_locus = gimple_location (ctx->stmt);
87d4aa85 2229 pop_cfun ();
1e8e9920 2230}
2231
bc7bff74 2232/* Callback for walk_gimple_seq. Check if combined parallel
2233 contains gimple_omp_for_combined_into_p OMP_FOR. */
2234
2235static tree
2236find_combined_for (gimple_stmt_iterator *gsi_p,
2237 bool *handled_ops_p,
2238 struct walk_stmt_info *wi)
2239{
42acab1c 2240 gimple *stmt = gsi_stmt (*gsi_p);
bc7bff74 2241
2242 *handled_ops_p = true;
2243 switch (gimple_code (stmt))
2244 {
2245 WALK_SUBSTMTS;
2246
2247 case GIMPLE_OMP_FOR:
2248 if (gimple_omp_for_combined_into_p (stmt)
2249 && gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR)
2250 {
2251 wi->info = stmt;
2252 return integer_zero_node;
2253 }
2254 break;
2255 default:
2256 break;
2257 }
2258 return NULL;
2259}
2260
1e8e9920 2261/* Scan an OpenMP parallel directive. */
2262
2263static void
75a70cf9 2264scan_omp_parallel (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
1e8e9920 2265{
2266 omp_context *ctx;
2267 tree name;
1a91d914 2268 gomp_parallel *stmt = as_a <gomp_parallel *> (gsi_stmt (*gsi));
1e8e9920 2269
2270 /* Ignore parallel directives with empty bodies, unless there
2271 are copyin clauses. */
2272 if (optimize > 0
75a70cf9 2273 && empty_body_p (gimple_omp_body (stmt))
2274 && find_omp_clause (gimple_omp_parallel_clauses (stmt),
2275 OMP_CLAUSE_COPYIN) == NULL)
1e8e9920 2276 {
75a70cf9 2277 gsi_replace (gsi, gimple_build_nop (), false);
1e8e9920 2278 return;
2279 }
2280
bc7bff74 2281 if (gimple_omp_parallel_combined_p (stmt))
2282 {
bc7bff74 2283 struct walk_stmt_info wi;
2284
2285 memset (&wi, 0, sizeof (wi));
2286 wi.val_only = true;
2287 walk_gimple_seq (gimple_omp_body (stmt),
2288 find_combined_for, NULL, &wi);
1a91d914 2289 if (wi.info)
bc7bff74 2290 {
42acab1c 2291 gomp_for *for_stmt = as_a <gomp_for *> ((gimple *) wi.info);
bc7bff74 2292 struct omp_for_data fd;
2293 extract_omp_for_data (for_stmt, &fd, NULL);
2294 /* We need two temporaries with fd.loop.v type (istart/iend)
2295 and then (fd.collapse - 1) temporaries with the same
2296 type for count2 ... countN-1 vars if not constant. */
2297 size_t count = 2, i;
2298 tree type = fd.iter_type;
2299 if (fd.collapse > 1
2300 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
2301 count += fd.collapse - 1;
2302 for (i = 0; i < count; i++)
2303 {
f9e245b2 2304 tree temp = create_tmp_var (type);
bc7bff74 2305 tree c = build_omp_clause (UNKNOWN_LOCATION,
2306 OMP_CLAUSE__LOOPTEMP_);
691447ab 2307 insert_decl_map (&outer_ctx->cb, temp, temp);
bc7bff74 2308 OMP_CLAUSE_DECL (c) = temp;
2309 OMP_CLAUSE_CHAIN (c) = gimple_omp_parallel_clauses (stmt);
2310 gimple_omp_parallel_set_clauses (stmt, c);
2311 }
2312 }
2313 }
2314
75a70cf9 2315 ctx = new_omp_context (stmt, outer_ctx);
37eaded9 2316 taskreg_contexts.safe_push (ctx);
fd6481cf 2317 if (taskreg_nesting_level > 1)
773c5ba7 2318 ctx->is_nested = true;
1e8e9920 2319 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
1e8e9920 2320 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2321 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
1e8e9920 2322 name = create_tmp_var_name (".omp_data_s");
e60a6f7b 2323 name = build_decl (gimple_location (stmt),
2324 TYPE_DECL, name, ctx->record_type);
84bfaaeb 2325 DECL_ARTIFICIAL (name) = 1;
2326 DECL_NAMELESS (name) = 1;
1e8e9920 2327 TYPE_NAME (ctx->record_type) = name;
240131b5 2328 TYPE_ARTIFICIAL (ctx->record_type) = 1;
fd6481cf 2329 create_omp_child_function (ctx, false);
75a70cf9 2330 gimple_omp_parallel_set_child_fn (stmt, ctx->cb.dst_fn);
1e8e9920 2331
75a70cf9 2332 scan_sharing_clauses (gimple_omp_parallel_clauses (stmt), ctx);
ab129075 2333 scan_omp (gimple_omp_body_ptr (stmt), ctx);
1e8e9920 2334
2335 if (TYPE_FIELDS (ctx->record_type) == NULL)
2336 ctx->record_type = ctx->receiver_decl = NULL;
1e8e9920 2337}
2338
fd6481cf 2339/* Scan an OpenMP task directive. */
2340
2341static void
75a70cf9 2342scan_omp_task (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
fd6481cf 2343{
2344 omp_context *ctx;
75a70cf9 2345 tree name, t;
1a91d914 2346 gomp_task *stmt = as_a <gomp_task *> (gsi_stmt (*gsi));
fd6481cf 2347
2348 /* Ignore task directives with empty bodies. */
2349 if (optimize > 0
75a70cf9 2350 && empty_body_p (gimple_omp_body (stmt)))
fd6481cf 2351 {
75a70cf9 2352 gsi_replace (gsi, gimple_build_nop (), false);
fd6481cf 2353 return;
2354 }
2355
75a70cf9 2356 ctx = new_omp_context (stmt, outer_ctx);
37eaded9 2357 taskreg_contexts.safe_push (ctx);
fd6481cf 2358 if (taskreg_nesting_level > 1)
2359 ctx->is_nested = true;
2360 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2361 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2362 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2363 name = create_tmp_var_name (".omp_data_s");
e60a6f7b 2364 name = build_decl (gimple_location (stmt),
2365 TYPE_DECL, name, ctx->record_type);
84bfaaeb 2366 DECL_ARTIFICIAL (name) = 1;
2367 DECL_NAMELESS (name) = 1;
fd6481cf 2368 TYPE_NAME (ctx->record_type) = name;
240131b5 2369 TYPE_ARTIFICIAL (ctx->record_type) = 1;
fd6481cf 2370 create_omp_child_function (ctx, false);
75a70cf9 2371 gimple_omp_task_set_child_fn (stmt, ctx->cb.dst_fn);
fd6481cf 2372
75a70cf9 2373 scan_sharing_clauses (gimple_omp_task_clauses (stmt), ctx);
fd6481cf 2374
2375 if (ctx->srecord_type)
2376 {
2377 name = create_tmp_var_name (".omp_data_a");
e60a6f7b 2378 name = build_decl (gimple_location (stmt),
2379 TYPE_DECL, name, ctx->srecord_type);
84bfaaeb 2380 DECL_ARTIFICIAL (name) = 1;
2381 DECL_NAMELESS (name) = 1;
fd6481cf 2382 TYPE_NAME (ctx->srecord_type) = name;
240131b5 2383 TYPE_ARTIFICIAL (ctx->srecord_type) = 1;
fd6481cf 2384 create_omp_child_function (ctx, true);
2385 }
2386
ab129075 2387 scan_omp (gimple_omp_body_ptr (stmt), ctx);
fd6481cf 2388
2389 if (TYPE_FIELDS (ctx->record_type) == NULL)
2390 {
2391 ctx->record_type = ctx->receiver_decl = NULL;
75a70cf9 2392 t = build_int_cst (long_integer_type_node, 0);
2393 gimple_omp_task_set_arg_size (stmt, t);
2394 t = build_int_cst (long_integer_type_node, 1);
2395 gimple_omp_task_set_arg_align (stmt, t);
fd6481cf 2396 }
37eaded9 2397}
2398
2399
2400/* If any decls have been made addressable during scan_omp,
2401 adjust their fields if needed, and layout record types
2402 of parallel/task constructs. */
2403
2404static void
2405finish_taskreg_scan (omp_context *ctx)
2406{
2407 if (ctx->record_type == NULL_TREE)
2408 return;
2409
2410 /* If any task_shared_vars were needed, verify all
2411 OMP_CLAUSE_SHARED clauses on GIMPLE_OMP_{PARALLEL,TASK}
2412 statements if use_pointer_for_field hasn't changed
2413 because of that. If it did, update field types now. */
2414 if (task_shared_vars)
2415 {
2416 tree c;
2417
2418 for (c = gimple_omp_taskreg_clauses (ctx->stmt);
2419 c; c = OMP_CLAUSE_CHAIN (c))
2420 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED)
2421 {
2422 tree decl = OMP_CLAUSE_DECL (c);
2423
2424 /* Global variables don't need to be copied,
2425 the receiver side will use them directly. */
2426 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
2427 continue;
2428 if (!bitmap_bit_p (task_shared_vars, DECL_UID (decl))
2429 || !use_pointer_for_field (decl, ctx))
2430 continue;
2431 tree field = lookup_field (decl, ctx);
2432 if (TREE_CODE (TREE_TYPE (field)) == POINTER_TYPE
2433 && TREE_TYPE (TREE_TYPE (field)) == TREE_TYPE (decl))
2434 continue;
2435 TREE_TYPE (field) = build_pointer_type (TREE_TYPE (decl));
2436 TREE_THIS_VOLATILE (field) = 0;
2437 DECL_USER_ALIGN (field) = 0;
2438 DECL_ALIGN (field) = TYPE_ALIGN (TREE_TYPE (field));
2439 if (TYPE_ALIGN (ctx->record_type) < DECL_ALIGN (field))
2440 TYPE_ALIGN (ctx->record_type) = DECL_ALIGN (field);
2441 if (ctx->srecord_type)
2442 {
2443 tree sfield = lookup_sfield (decl, ctx);
2444 TREE_TYPE (sfield) = TREE_TYPE (field);
2445 TREE_THIS_VOLATILE (sfield) = 0;
2446 DECL_USER_ALIGN (sfield) = 0;
2447 DECL_ALIGN (sfield) = DECL_ALIGN (field);
2448 if (TYPE_ALIGN (ctx->srecord_type) < DECL_ALIGN (sfield))
2449 TYPE_ALIGN (ctx->srecord_type) = DECL_ALIGN (sfield);
2450 }
2451 }
2452 }
2453
2454 if (gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL)
2455 {
2456 layout_type (ctx->record_type);
2457 fixup_child_record_type (ctx);
2458 }
fd6481cf 2459 else
2460 {
37eaded9 2461 location_t loc = gimple_location (ctx->stmt);
fd6481cf 2462 tree *p, vla_fields = NULL_TREE, *q = &vla_fields;
2463 /* Move VLA fields to the end. */
2464 p = &TYPE_FIELDS (ctx->record_type);
2465 while (*p)
2466 if (!TYPE_SIZE_UNIT (TREE_TYPE (*p))
2467 || ! TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (*p))))
2468 {
2469 *q = *p;
2470 *p = TREE_CHAIN (*p);
2471 TREE_CHAIN (*q) = NULL_TREE;
2472 q = &TREE_CHAIN (*q);
2473 }
2474 else
1767a056 2475 p = &DECL_CHAIN (*p);
fd6481cf 2476 *p = vla_fields;
2477 layout_type (ctx->record_type);
2478 fixup_child_record_type (ctx);
2479 if (ctx->srecord_type)
2480 layout_type (ctx->srecord_type);
37eaded9 2481 tree t = fold_convert_loc (loc, long_integer_type_node,
2482 TYPE_SIZE_UNIT (ctx->record_type));
2483 gimple_omp_task_set_arg_size (ctx->stmt, t);
75a70cf9 2484 t = build_int_cst (long_integer_type_node,
fd6481cf 2485 TYPE_ALIGN_UNIT (ctx->record_type));
37eaded9 2486 gimple_omp_task_set_arg_align (ctx->stmt, t);
fd6481cf 2487 }
2488}
2489
1e8e9920 2490
ca4c3545 2491static omp_context *
2492enclosing_target_ctx (omp_context *ctx)
2493{
2494 while (ctx != NULL
2495 && gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET)
2496 ctx = ctx->outer;
2497 gcc_assert (ctx != NULL);
2498 return ctx;
2499}
2500
2501static bool
42acab1c 2502oacc_loop_or_target_p (gimple *stmt)
ca4c3545 2503{
2504 enum gimple_code outer_type = gimple_code (stmt);
2505 return ((outer_type == GIMPLE_OMP_TARGET
2506 && ((gimple_omp_target_kind (stmt)
2507 == GF_OMP_TARGET_KIND_OACC_PARALLEL)
2508 || (gimple_omp_target_kind (stmt)
2509 == GF_OMP_TARGET_KIND_OACC_KERNELS)))
2510 || (outer_type == GIMPLE_OMP_FOR
2511 && gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_OACC_LOOP));
2512}
2513
2514/* Scan a GIMPLE_OMP_FOR. */
1e8e9920 2515
2516static void
1a91d914 2517scan_omp_for (gomp_for *stmt, omp_context *outer_ctx)
1e8e9920 2518{
ca4c3545 2519 enum gimple_code outer_type = GIMPLE_ERROR_MARK;
773c5ba7 2520 omp_context *ctx;
75a70cf9 2521 size_t i;
ca4c3545 2522 tree clauses = gimple_omp_for_clauses (stmt);
2523
2524 if (outer_ctx)
2525 outer_type = gimple_code (outer_ctx->stmt);
1e8e9920 2526
773c5ba7 2527 ctx = new_omp_context (stmt, outer_ctx);
1e8e9920 2528
ca4c3545 2529 if (is_gimple_omp_oacc (stmt))
2530 {
2531 if (outer_ctx && outer_type == GIMPLE_OMP_FOR)
2532 ctx->gwv_this = outer_ctx->gwv_this;
2533 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
2534 {
2535 int val;
2536 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_GANG)
2537 val = MASK_GANG;
2538 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_WORKER)
2539 val = MASK_WORKER;
2540 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_VECTOR)
2541 val = MASK_VECTOR;
2542 else
2543 continue;
2544 ctx->gwv_this |= val;
2545 if (!outer_ctx)
2546 {
2547 /* Skip; not nested inside a region. */
2548 continue;
2549 }
2550 if (!oacc_loop_or_target_p (outer_ctx->stmt))
2551 {
2552 /* Skip; not nested inside an OpenACC region. */
2553 continue;
2554 }
2555 if (outer_type == GIMPLE_OMP_FOR)
2556 outer_ctx->gwv_below |= val;
2557 if (OMP_CLAUSE_OPERAND (c, 0) != NULL_TREE)
2558 {
2559 omp_context *enclosing = enclosing_target_ctx (outer_ctx);
2560 if (gimple_omp_target_kind (enclosing->stmt)
2561 == GF_OMP_TARGET_KIND_OACC_PARALLEL)
2562 error_at (gimple_location (stmt),
2563 "no arguments allowed to gang, worker and vector clauses inside parallel");
2564 }
2565 }
2566 }
2567
2568 scan_sharing_clauses (clauses, ctx);
1e8e9920 2569
ab129075 2570 scan_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
75a70cf9 2571 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
fd6481cf 2572 {
75a70cf9 2573 scan_omp_op (gimple_omp_for_index_ptr (stmt, i), ctx);
2574 scan_omp_op (gimple_omp_for_initial_ptr (stmt, i), ctx);
2575 scan_omp_op (gimple_omp_for_final_ptr (stmt, i), ctx);
2576 scan_omp_op (gimple_omp_for_incr_ptr (stmt, i), ctx);
fd6481cf 2577 }
ab129075 2578 scan_omp (gimple_omp_body_ptr (stmt), ctx);
ca4c3545 2579
2580 if (is_gimple_omp_oacc (stmt))
2581 {
2582 if (ctx->gwv_this & ctx->gwv_below)
2583 error_at (gimple_location (stmt),
2584 "gang, worker and vector may occur only once in a loop nest");
2585 else if (ctx->gwv_below != 0
2586 && ctx->gwv_this > ctx->gwv_below)
2587 error_at (gimple_location (stmt),
2588 "gang, worker and vector must occur in this order in a loop nest");
2589 if (outer_ctx && outer_type == GIMPLE_OMP_FOR)
2590 outer_ctx->gwv_below |= ctx->gwv_below;
2591 }
1e8e9920 2592}
2593
2594/* Scan an OpenMP sections directive. */
2595
2596static void
1a91d914 2597scan_omp_sections (gomp_sections *stmt, omp_context *outer_ctx)
1e8e9920 2598{
1e8e9920 2599 omp_context *ctx;
2600
2601 ctx = new_omp_context (stmt, outer_ctx);
75a70cf9 2602 scan_sharing_clauses (gimple_omp_sections_clauses (stmt), ctx);
ab129075 2603 scan_omp (gimple_omp_body_ptr (stmt), ctx);
1e8e9920 2604}
2605
2606/* Scan an OpenMP single directive. */
2607
2608static void
1a91d914 2609scan_omp_single (gomp_single *stmt, omp_context *outer_ctx)
1e8e9920 2610{
1e8e9920 2611 omp_context *ctx;
2612 tree name;
2613
2614 ctx = new_omp_context (stmt, outer_ctx);
2615 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2616 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2617 name = create_tmp_var_name (".omp_copy_s");
e60a6f7b 2618 name = build_decl (gimple_location (stmt),
2619 TYPE_DECL, name, ctx->record_type);
1e8e9920 2620 TYPE_NAME (ctx->record_type) = name;
2621
75a70cf9 2622 scan_sharing_clauses (gimple_omp_single_clauses (stmt), ctx);
ab129075 2623 scan_omp (gimple_omp_body_ptr (stmt), ctx);
1e8e9920 2624
2625 if (TYPE_FIELDS (ctx->record_type) == NULL)
2626 ctx->record_type = NULL;
2627 else
2628 layout_type (ctx->record_type);
2629}
2630
ca4c3545 2631/* Scan a GIMPLE_OMP_TARGET. */
bc7bff74 2632
2633static void
1a91d914 2634scan_omp_target (gomp_target *stmt, omp_context *outer_ctx)
bc7bff74 2635{
2636 omp_context *ctx;
2637 tree name;
ca4c3545 2638 bool offloaded = is_gimple_omp_offloaded (stmt);
2639 tree clauses = gimple_omp_target_clauses (stmt);
bc7bff74 2640
2641 ctx = new_omp_context (stmt, outer_ctx);
2642 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2643 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2644 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2645 name = create_tmp_var_name (".omp_data_t");
2646 name = build_decl (gimple_location (stmt),
2647 TYPE_DECL, name, ctx->record_type);
2648 DECL_ARTIFICIAL (name) = 1;
2649 DECL_NAMELESS (name) = 1;
2650 TYPE_NAME (ctx->record_type) = name;
240131b5 2651 TYPE_ARTIFICIAL (ctx->record_type) = 1;
ca4c3545 2652 if (offloaded)
bc7bff74 2653 {
ca4c3545 2654 if (is_gimple_omp_oacc (stmt))
2655 ctx->reduction_map = splay_tree_new (splay_tree_compare_pointers,
2656 0, 0);
2657
bc7bff74 2658 create_omp_child_function (ctx, false);
2659 gimple_omp_target_set_child_fn (stmt, ctx->cb.dst_fn);
2660 }
2661
ca4c3545 2662 if (is_gimple_omp_oacc (stmt))
2663 {
2664 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
2665 {
2666 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_NUM_GANGS)
2667 ctx->gwv_this |= MASK_GANG;
2668 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_NUM_WORKERS)
2669 ctx->gwv_this |= MASK_WORKER;
2670 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_VECTOR_LENGTH)
2671 ctx->gwv_this |= MASK_VECTOR;
2672 }
2673 }
2674
2675 scan_sharing_clauses (clauses, ctx);
bc7bff74 2676 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2677
2678 if (TYPE_FIELDS (ctx->record_type) == NULL)
2679 ctx->record_type = ctx->receiver_decl = NULL;
2680 else
2681 {
2682 TYPE_FIELDS (ctx->record_type)
2683 = nreverse (TYPE_FIELDS (ctx->record_type));
2684#ifdef ENABLE_CHECKING
2685 tree field;
2686 unsigned int align = DECL_ALIGN (TYPE_FIELDS (ctx->record_type));
2687 for (field = TYPE_FIELDS (ctx->record_type);
2688 field;
2689 field = DECL_CHAIN (field))
2690 gcc_assert (DECL_ALIGN (field) == align);
2691#endif
2692 layout_type (ctx->record_type);
ca4c3545 2693 if (offloaded)
bc7bff74 2694 fixup_child_record_type (ctx);
2695 }
2696}
2697
2698/* Scan an OpenMP teams directive. */
2699
2700static void
1a91d914 2701scan_omp_teams (gomp_teams *stmt, omp_context *outer_ctx)
bc7bff74 2702{
2703 omp_context *ctx = new_omp_context (stmt, outer_ctx);
2704 scan_sharing_clauses (gimple_omp_teams_clauses (stmt), ctx);
2705 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2706}
1e8e9920 2707
ca4c3545 2708/* Check nesting restrictions. */
ab129075 2709static bool
42acab1c 2710check_omp_nesting_restrictions (gimple *stmt, omp_context *ctx)
c1d127dd 2711{
ca4c3545 2712 /* No nesting of non-OpenACC STMT (that is, an OpenMP one, or a GOMP builtin)
2713 inside an OpenACC CTX. */
2714 if (!(is_gimple_omp (stmt)
2715 && is_gimple_omp_oacc (stmt)))
2716 {
2717 for (omp_context *ctx_ = ctx; ctx_ != NULL; ctx_ = ctx_->outer)
2718 if (is_gimple_omp (ctx_->stmt)
2719 && is_gimple_omp_oacc (ctx_->stmt))
2720 {
2721 error_at (gimple_location (stmt),
2722 "non-OpenACC construct inside of OpenACC region");
2723 return false;
2724 }
2725 }
2726
3d483a94 2727 if (ctx != NULL)
2728 {
2729 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
10c55644 2730 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
3d483a94 2731 {
2732 error_at (gimple_location (stmt),
2733 "OpenMP constructs may not be nested inside simd region");
2734 return false;
2735 }
bc7bff74 2736 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
2737 {
2738 if ((gimple_code (stmt) != GIMPLE_OMP_FOR
2739 || (gimple_omp_for_kind (stmt)
2740 != GF_OMP_FOR_KIND_DISTRIBUTE))
2741 && gimple_code (stmt) != GIMPLE_OMP_PARALLEL)
2742 {
2743 error_at (gimple_location (stmt),
2744 "only distribute or parallel constructs are allowed to "
2745 "be closely nested inside teams construct");
2746 return false;
2747 }
2748 }
3d483a94 2749 }
75a70cf9 2750 switch (gimple_code (stmt))
c1d127dd 2751 {
75a70cf9 2752 case GIMPLE_OMP_FOR:
10c55644 2753 if (gimple_omp_for_kind (stmt) & GF_OMP_FOR_SIMD)
3d483a94 2754 return true;
bc7bff74 2755 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
2756 {
2757 if (ctx != NULL && gimple_code (ctx->stmt) != GIMPLE_OMP_TEAMS)
2758 {
2759 error_at (gimple_location (stmt),
2760 "distribute construct must be closely nested inside "
2761 "teams construct");
2762 return false;
2763 }
2764 return true;
2765 }
2766 /* FALLTHRU */
2767 case GIMPLE_CALL:
2768 if (is_gimple_call (stmt)
2769 && (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2770 == BUILT_IN_GOMP_CANCEL
2771 || DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2772 == BUILT_IN_GOMP_CANCELLATION_POINT))
2773 {
2774 const char *bad = NULL;
2775 const char *kind = NULL;
2776 if (ctx == NULL)
2777 {
2778 error_at (gimple_location (stmt), "orphaned %qs construct",
2779 DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2780 == BUILT_IN_GOMP_CANCEL
2781 ? "#pragma omp cancel"
2782 : "#pragma omp cancellation point");
2783 return false;
2784 }
6b409616 2785 switch (tree_fits_shwi_p (gimple_call_arg (stmt, 0))
2786 ? tree_to_shwi (gimple_call_arg (stmt, 0))
bc7bff74 2787 : 0)
2788 {
2789 case 1:
2790 if (gimple_code (ctx->stmt) != GIMPLE_OMP_PARALLEL)
2791 bad = "#pragma omp parallel";
2792 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2793 == BUILT_IN_GOMP_CANCEL
2794 && !integer_zerop (gimple_call_arg (stmt, 1)))
2795 ctx->cancellable = true;
2796 kind = "parallel";
2797 break;
2798 case 2:
2799 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
2800 || gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR)
2801 bad = "#pragma omp for";
2802 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2803 == BUILT_IN_GOMP_CANCEL
2804 && !integer_zerop (gimple_call_arg (stmt, 1)))
2805 {
2806 ctx->cancellable = true;
2807 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2808 OMP_CLAUSE_NOWAIT))
2809 warning_at (gimple_location (stmt), 0,
2810 "%<#pragma omp cancel for%> inside "
2811 "%<nowait%> for construct");
2812 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2813 OMP_CLAUSE_ORDERED))
2814 warning_at (gimple_location (stmt), 0,
2815 "%<#pragma omp cancel for%> inside "
2816 "%<ordered%> for construct");
2817 }
2818 kind = "for";
2819 break;
2820 case 4:
2821 if (gimple_code (ctx->stmt) != GIMPLE_OMP_SECTIONS
2822 && gimple_code (ctx->stmt) != GIMPLE_OMP_SECTION)
2823 bad = "#pragma omp sections";
2824 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2825 == BUILT_IN_GOMP_CANCEL
2826 && !integer_zerop (gimple_call_arg (stmt, 1)))
2827 {
2828 if (gimple_code (ctx->stmt) == GIMPLE_OMP_SECTIONS)
2829 {
2830 ctx->cancellable = true;
2831 if (find_omp_clause (gimple_omp_sections_clauses
2832 (ctx->stmt),
2833 OMP_CLAUSE_NOWAIT))
2834 warning_at (gimple_location (stmt), 0,
2835 "%<#pragma omp cancel sections%> inside "
2836 "%<nowait%> sections construct");
2837 }
2838 else
2839 {
2840 gcc_assert (ctx->outer
2841 && gimple_code (ctx->outer->stmt)
2842 == GIMPLE_OMP_SECTIONS);
2843 ctx->outer->cancellable = true;
2844 if (find_omp_clause (gimple_omp_sections_clauses
2845 (ctx->outer->stmt),
2846 OMP_CLAUSE_NOWAIT))
2847 warning_at (gimple_location (stmt), 0,
2848 "%<#pragma omp cancel sections%> inside "
2849 "%<nowait%> sections construct");
2850 }
2851 }
2852 kind = "sections";
2853 break;
2854 case 8:
2855 if (gimple_code (ctx->stmt) != GIMPLE_OMP_TASK)
2856 bad = "#pragma omp task";
2857 else
2858 ctx->cancellable = true;
2859 kind = "taskgroup";
2860 break;
2861 default:
2862 error_at (gimple_location (stmt), "invalid arguments");
2863 return false;
2864 }
2865 if (bad)
2866 {
2867 error_at (gimple_location (stmt),
2868 "%<%s %s%> construct not closely nested inside of %qs",
2869 DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2870 == BUILT_IN_GOMP_CANCEL
2871 ? "#pragma omp cancel"
2872 : "#pragma omp cancellation point", kind, bad);
2873 return false;
2874 }
2875 }
3d483a94 2876 /* FALLTHRU */
75a70cf9 2877 case GIMPLE_OMP_SECTIONS:
2878 case GIMPLE_OMP_SINGLE:
c1d127dd 2879 for (; ctx != NULL; ctx = ctx->outer)
75a70cf9 2880 switch (gimple_code (ctx->stmt))
c1d127dd 2881 {
75a70cf9 2882 case GIMPLE_OMP_FOR:
2883 case GIMPLE_OMP_SECTIONS:
2884 case GIMPLE_OMP_SINGLE:
2885 case GIMPLE_OMP_ORDERED:
2886 case GIMPLE_OMP_MASTER:
2887 case GIMPLE_OMP_TASK:
bc7bff74 2888 case GIMPLE_OMP_CRITICAL:
75a70cf9 2889 if (is_gimple_call (stmt))
fd6481cf 2890 {
bc7bff74 2891 if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2892 != BUILT_IN_GOMP_BARRIER)
2893 return true;
ab129075 2894 error_at (gimple_location (stmt),
2895 "barrier region may not be closely nested inside "
2896 "of work-sharing, critical, ordered, master or "
2897 "explicit task region");
2898 return false;
fd6481cf 2899 }
ab129075 2900 error_at (gimple_location (stmt),
2901 "work-sharing region may not be closely nested inside "
2902 "of work-sharing, critical, ordered, master or explicit "
2903 "task region");
2904 return false;
75a70cf9 2905 case GIMPLE_OMP_PARALLEL:
ab129075 2906 return true;
c1d127dd 2907 default:
2908 break;
2909 }
2910 break;
75a70cf9 2911 case GIMPLE_OMP_MASTER:
c1d127dd 2912 for (; ctx != NULL; ctx = ctx->outer)
75a70cf9 2913 switch (gimple_code (ctx->stmt))
c1d127dd 2914 {
75a70cf9 2915 case GIMPLE_OMP_FOR:
2916 case GIMPLE_OMP_SECTIONS:
2917 case GIMPLE_OMP_SINGLE:
2918 case GIMPLE_OMP_TASK:
ab129075 2919 error_at (gimple_location (stmt),
2920 "master region may not be closely nested inside "
2921 "of work-sharing or explicit task region");
2922 return false;
75a70cf9 2923 case GIMPLE_OMP_PARALLEL:
ab129075 2924 return true;
c1d127dd 2925 default:
2926 break;
2927 }
2928 break;
75a70cf9 2929 case GIMPLE_OMP_ORDERED:
c1d127dd 2930 for (; ctx != NULL; ctx = ctx->outer)
75a70cf9 2931 switch (gimple_code (ctx->stmt))
c1d127dd 2932 {
75a70cf9 2933 case GIMPLE_OMP_CRITICAL:
2934 case GIMPLE_OMP_TASK:
ab129075 2935 error_at (gimple_location (stmt),
2936 "ordered region may not be closely nested inside "
2937 "of critical or explicit task region");
2938 return false;
75a70cf9 2939 case GIMPLE_OMP_FOR:
2940 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
c1d127dd 2941 OMP_CLAUSE_ORDERED) == NULL)
ab129075 2942 {
2943 error_at (gimple_location (stmt),
2944 "ordered region must be closely nested inside "
c1d127dd 2945 "a loop region with an ordered clause");
ab129075 2946 return false;
2947 }
2948 return true;
75a70cf9 2949 case GIMPLE_OMP_PARALLEL:
bc7bff74 2950 error_at (gimple_location (stmt),
2951 "ordered region must be closely nested inside "
2952 "a loop region with an ordered clause");
2953 return false;
c1d127dd 2954 default:
2955 break;
2956 }
2957 break;
75a70cf9 2958 case GIMPLE_OMP_CRITICAL:
1a91d914 2959 {
2960 tree this_stmt_name
2961 = gimple_omp_critical_name (as_a <gomp_critical *> (stmt));
2962 for (; ctx != NULL; ctx = ctx->outer)
2963 if (gomp_critical *other_crit
2964 = dyn_cast <gomp_critical *> (ctx->stmt))
2965 if (this_stmt_name == gimple_omp_critical_name (other_crit))
2966 {
2967 error_at (gimple_location (stmt),
2968 "critical region may not be nested inside a critical "
2969 "region with the same name");
2970 return false;
2971 }
2972 }
c1d127dd 2973 break;
bc7bff74 2974 case GIMPLE_OMP_TEAMS:
2975 if (ctx == NULL
2976 || gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET
2977 || gimple_omp_target_kind (ctx->stmt) != GF_OMP_TARGET_KIND_REGION)
2978 {
2979 error_at (gimple_location (stmt),
2980 "teams construct not closely nested inside of target "
2981 "region");
2982 return false;
2983 }
2984 break;
691447ab 2985 case GIMPLE_OMP_TARGET:
2986 for (; ctx != NULL; ctx = ctx->outer)
ca4c3545 2987 {
2988 if (gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET)
2989 {
2990 if (is_gimple_omp (stmt)
2991 && is_gimple_omp_oacc (stmt)
2992 && is_gimple_omp (ctx->stmt))
2993 {
2994 error_at (gimple_location (stmt),
2995 "OpenACC construct inside of non-OpenACC region");
2996 return false;
2997 }
2998 continue;
2999 }
3000
3001 const char *stmt_name, *ctx_stmt_name;
3002 switch (gimple_omp_target_kind (stmt))
3003 {
3004 case GF_OMP_TARGET_KIND_REGION: stmt_name = "target"; break;
3005 case GF_OMP_TARGET_KIND_DATA: stmt_name = "target data"; break;
3006 case GF_OMP_TARGET_KIND_UPDATE: stmt_name = "target update"; break;
3007 case GF_OMP_TARGET_KIND_OACC_PARALLEL: stmt_name = "parallel"; break;
3008 case GF_OMP_TARGET_KIND_OACC_KERNELS: stmt_name = "kernels"; break;
3009 case GF_OMP_TARGET_KIND_OACC_DATA: stmt_name = "data"; break;
3010 case GF_OMP_TARGET_KIND_OACC_UPDATE: stmt_name = "update"; break;
3011 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA: stmt_name = "enter/exit data"; break;
3012 default: gcc_unreachable ();
3013 }
3014 switch (gimple_omp_target_kind (ctx->stmt))
3015 {
3016 case GF_OMP_TARGET_KIND_REGION: ctx_stmt_name = "target"; break;
3017 case GF_OMP_TARGET_KIND_DATA: ctx_stmt_name = "target data"; break;
3018 case GF_OMP_TARGET_KIND_OACC_PARALLEL: ctx_stmt_name = "parallel"; break;
3019 case GF_OMP_TARGET_KIND_OACC_KERNELS: ctx_stmt_name = "kernels"; break;
3020 case GF_OMP_TARGET_KIND_OACC_DATA: ctx_stmt_name = "data"; break;
3021 default: gcc_unreachable ();
3022 }
3023
3024 /* OpenACC/OpenMP mismatch? */
3025 if (is_gimple_omp_oacc (stmt)
3026 != is_gimple_omp_oacc (ctx->stmt))
3027 {
3028 error_at (gimple_location (stmt),
3029 "%s %s construct inside of %s %s region",
3030 (is_gimple_omp_oacc (stmt)
3031 ? "OpenACC" : "OpenMP"), stmt_name,
3032 (is_gimple_omp_oacc (ctx->stmt)
3033 ? "OpenACC" : "OpenMP"), ctx_stmt_name);
3034 return false;
3035 }
3036 if (is_gimple_omp_offloaded (ctx->stmt))
3037 {
3038 /* No GIMPLE_OMP_TARGET inside offloaded OpenACC CTX. */
3039 if (is_gimple_omp_oacc (ctx->stmt))
3040 {
3041 error_at (gimple_location (stmt),
3042 "%s construct inside of %s region",
3043 stmt_name, ctx_stmt_name);
3044 return false;
3045 }
3046 else
3047 {
3048 gcc_checking_assert (!is_gimple_omp_oacc (stmt));
3049 warning_at (gimple_location (stmt), 0,
3050 "%s construct inside of %s region",
3051 stmt_name, ctx_stmt_name);
3052 }
3053 }
3054 }
691447ab 3055 break;
c1d127dd 3056 default:
3057 break;
3058 }
ab129075 3059 return true;
c1d127dd 3060}
3061
3062
75a70cf9 3063/* Helper function scan_omp.
3064
3065 Callback for walk_tree or operators in walk_gimple_stmt used to
ca4c3545 3066 scan for OMP directives in TP. */
1e8e9920 3067
3068static tree
75a70cf9 3069scan_omp_1_op (tree *tp, int *walk_subtrees, void *data)
1e8e9920 3070{
4077bf7a 3071 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
3072 omp_context *ctx = (omp_context *) wi->info;
1e8e9920 3073 tree t = *tp;
3074
75a70cf9 3075 switch (TREE_CODE (t))
3076 {
3077 case VAR_DECL:
3078 case PARM_DECL:
3079 case LABEL_DECL:
3080 case RESULT_DECL:
3081 if (ctx)
3082 *tp = remap_decl (t, &ctx->cb);
3083 break;
3084
3085 default:
3086 if (ctx && TYPE_P (t))
3087 *tp = remap_type (t, &ctx->cb);
3088 else if (!DECL_P (t))
7cf869dd 3089 {
3090 *walk_subtrees = 1;
3091 if (ctx)
182cf5a9 3092 {
3093 tree tem = remap_type (TREE_TYPE (t), &ctx->cb);
3094 if (tem != TREE_TYPE (t))
3095 {
3096 if (TREE_CODE (t) == INTEGER_CST)
e913b5cd 3097 *tp = wide_int_to_tree (tem, t);
182cf5a9 3098 else
3099 TREE_TYPE (t) = tem;
3100 }
3101 }
7cf869dd 3102 }
75a70cf9 3103 break;
3104 }
3105
3106 return NULL_TREE;
3107}
3108
f2697631 3109/* Return true if FNDECL is a setjmp or a longjmp. */
3110
3111static bool
3112setjmp_or_longjmp_p (const_tree fndecl)
3113{
3114 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
3115 && (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_SETJMP
3116 || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_LONGJMP))
3117 return true;
3118
3119 tree declname = DECL_NAME (fndecl);
3120 if (!declname)
3121 return false;
3122 const char *name = IDENTIFIER_POINTER (declname);
3123 return !strcmp (name, "setjmp") || !strcmp (name, "longjmp");
3124}
3125
75a70cf9 3126
3127/* Helper function for scan_omp.
3128
ca4c3545 3129 Callback for walk_gimple_stmt used to scan for OMP directives in
75a70cf9 3130 the current statement in GSI. */
3131
3132static tree
3133scan_omp_1_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
3134 struct walk_stmt_info *wi)
3135{
42acab1c 3136 gimple *stmt = gsi_stmt (*gsi);
75a70cf9 3137 omp_context *ctx = (omp_context *) wi->info;
3138
3139 if (gimple_has_location (stmt))
3140 input_location = gimple_location (stmt);
1e8e9920 3141
ca4c3545 3142 /* Check the nesting restrictions. */
bc7bff74 3143 bool remove = false;
3144 if (is_gimple_omp (stmt))
3145 remove = !check_omp_nesting_restrictions (stmt, ctx);
3146 else if (is_gimple_call (stmt))
3147 {
3148 tree fndecl = gimple_call_fndecl (stmt);
f2697631 3149 if (fndecl)
3150 {
3151 if (setjmp_or_longjmp_p (fndecl)
3152 && ctx
3153 && gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
10c55644 3154 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
f2697631 3155 {
3156 remove = true;
3157 error_at (gimple_location (stmt),
3158 "setjmp/longjmp inside simd construct");
3159 }
3160 else if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
3161 switch (DECL_FUNCTION_CODE (fndecl))
3162 {
3163 case BUILT_IN_GOMP_BARRIER:
3164 case BUILT_IN_GOMP_CANCEL:
3165 case BUILT_IN_GOMP_CANCELLATION_POINT:
3166 case BUILT_IN_GOMP_TASKYIELD:
3167 case BUILT_IN_GOMP_TASKWAIT:
3168 case BUILT_IN_GOMP_TASKGROUP_START:
3169 case BUILT_IN_GOMP_TASKGROUP_END:
3170 remove = !check_omp_nesting_restrictions (stmt, ctx);
3171 break;
3172 default:
3173 break;
3174 }
3175 }
bc7bff74 3176 }
3177 if (remove)
3178 {
3179 stmt = gimple_build_nop ();
3180 gsi_replace (gsi, stmt, false);
fd6481cf 3181 }
c1d127dd 3182
75a70cf9 3183 *handled_ops_p = true;
3184
3185 switch (gimple_code (stmt))
1e8e9920 3186 {
75a70cf9 3187 case GIMPLE_OMP_PARALLEL:
fd6481cf 3188 taskreg_nesting_level++;
75a70cf9 3189 scan_omp_parallel (gsi, ctx);
fd6481cf 3190 taskreg_nesting_level--;
3191 break;
3192
75a70cf9 3193 case GIMPLE_OMP_TASK:
fd6481cf 3194 taskreg_nesting_level++;
75a70cf9 3195 scan_omp_task (gsi, ctx);
fd6481cf 3196 taskreg_nesting_level--;
1e8e9920 3197 break;
3198
75a70cf9 3199 case GIMPLE_OMP_FOR:
1a91d914 3200 scan_omp_for (as_a <gomp_for *> (stmt), ctx);
1e8e9920 3201 break;
3202
75a70cf9 3203 case GIMPLE_OMP_SECTIONS:
1a91d914 3204 scan_omp_sections (as_a <gomp_sections *> (stmt), ctx);
1e8e9920 3205 break;
3206
75a70cf9 3207 case GIMPLE_OMP_SINGLE:
1a91d914 3208 scan_omp_single (as_a <gomp_single *> (stmt), ctx);
1e8e9920 3209 break;
3210
75a70cf9 3211 case GIMPLE_OMP_SECTION:
3212 case GIMPLE_OMP_MASTER:
bc7bff74 3213 case GIMPLE_OMP_TASKGROUP:
75a70cf9 3214 case GIMPLE_OMP_ORDERED:
3215 case GIMPLE_OMP_CRITICAL:
3216 ctx = new_omp_context (stmt, ctx);
ab129075 3217 scan_omp (gimple_omp_body_ptr (stmt), ctx);
1e8e9920 3218 break;
3219
bc7bff74 3220 case GIMPLE_OMP_TARGET:
1a91d914 3221 scan_omp_target (as_a <gomp_target *> (stmt), ctx);
bc7bff74 3222 break;
3223
3224 case GIMPLE_OMP_TEAMS:
1a91d914 3225 scan_omp_teams (as_a <gomp_teams *> (stmt), ctx);
bc7bff74 3226 break;
3227
75a70cf9 3228 case GIMPLE_BIND:
1e8e9920 3229 {
3230 tree var;
1e8e9920 3231
75a70cf9 3232 *handled_ops_p = false;
3233 if (ctx)
1a91d914 3234 for (var = gimple_bind_vars (as_a <gbind *> (stmt));
3235 var ;
3236 var = DECL_CHAIN (var))
75a70cf9 3237 insert_decl_map (&ctx->cb, var, var);
1e8e9920 3238 }
3239 break;
1e8e9920 3240 default:
75a70cf9 3241 *handled_ops_p = false;
1e8e9920 3242 break;
3243 }
3244
3245 return NULL_TREE;
3246}
3247
3248
75a70cf9 3249/* Scan all the statements starting at the current statement. CTX
ca4c3545 3250 contains context information about the OMP directives and
75a70cf9 3251 clauses found during the scan. */
1e8e9920 3252
3253static void
ab129075 3254scan_omp (gimple_seq *body_p, omp_context *ctx)
1e8e9920 3255{
3256 location_t saved_location;
3257 struct walk_stmt_info wi;
3258
3259 memset (&wi, 0, sizeof (wi));
1e8e9920 3260 wi.info = ctx;
1e8e9920 3261 wi.want_locations = true;
3262
3263 saved_location = input_location;
ab129075 3264 walk_gimple_seq_mod (body_p, scan_omp_1_stmt, scan_omp_1_op, &wi);
1e8e9920 3265 input_location = saved_location;
3266}
3267\f
3268/* Re-gimplification and code generation routines. */
3269
3270/* Build a call to GOMP_barrier. */
3271
42acab1c 3272static gimple *
bc7bff74 3273build_omp_barrier (tree lhs)
3274{
3275 tree fndecl = builtin_decl_explicit (lhs ? BUILT_IN_GOMP_BARRIER_CANCEL
3276 : BUILT_IN_GOMP_BARRIER);
1a91d914 3277 gcall *g = gimple_build_call (fndecl, 0);
bc7bff74 3278 if (lhs)
3279 gimple_call_set_lhs (g, lhs);
3280 return g;
1e8e9920 3281}
3282
3283/* If a context was created for STMT when it was scanned, return it. */
3284
3285static omp_context *
42acab1c 3286maybe_lookup_ctx (gimple *stmt)
1e8e9920 3287{
3288 splay_tree_node n;
3289 n = splay_tree_lookup (all_contexts, (splay_tree_key) stmt);
3290 return n ? (omp_context *) n->value : NULL;
3291}
3292
773c5ba7 3293
3294/* Find the mapping for DECL in CTX or the immediately enclosing
3295 context that has a mapping for DECL.
3296
3297 If CTX is a nested parallel directive, we may have to use the decl
3298 mappings created in CTX's parent context. Suppose that we have the
3299 following parallel nesting (variable UIDs showed for clarity):
3300
3301 iD.1562 = 0;
3302 #omp parallel shared(iD.1562) -> outer parallel
3303 iD.1562 = iD.1562 + 1;
3304
3305 #omp parallel shared (iD.1562) -> inner parallel
3306 iD.1562 = iD.1562 - 1;
3307
3308 Each parallel structure will create a distinct .omp_data_s structure
3309 for copying iD.1562 in/out of the directive:
3310
3311 outer parallel .omp_data_s.1.i -> iD.1562
3312 inner parallel .omp_data_s.2.i -> iD.1562
3313
3314 A shared variable mapping will produce a copy-out operation before
3315 the parallel directive and a copy-in operation after it. So, in
3316 this case we would have:
3317
3318 iD.1562 = 0;
3319 .omp_data_o.1.i = iD.1562;
3320 #omp parallel shared(iD.1562) -> outer parallel
3321 .omp_data_i.1 = &.omp_data_o.1
3322 .omp_data_i.1->i = .omp_data_i.1->i + 1;
3323
3324 .omp_data_o.2.i = iD.1562; -> **
3325 #omp parallel shared(iD.1562) -> inner parallel
3326 .omp_data_i.2 = &.omp_data_o.2
3327 .omp_data_i.2->i = .omp_data_i.2->i - 1;
3328
3329
3330 ** This is a problem. The symbol iD.1562 cannot be referenced
3331 inside the body of the outer parallel region. But since we are
3332 emitting this copy operation while expanding the inner parallel
3333 directive, we need to access the CTX structure of the outer
3334 parallel directive to get the correct mapping:
3335
3336 .omp_data_o.2.i = .omp_data_i.1->i
3337
3338 Since there may be other workshare or parallel directives enclosing
3339 the parallel directive, it may be necessary to walk up the context
3340 parent chain. This is not a problem in general because nested
3341 parallelism happens only rarely. */
3342
3343static tree
3344lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
3345{
3346 tree t;
3347 omp_context *up;
3348
773c5ba7 3349 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
3350 t = maybe_lookup_decl (decl, up);
3351
87b31375 3352 gcc_assert (!ctx->is_nested || t || is_global_var (decl));
773c5ba7 3353
c37594c7 3354 return t ? t : decl;
773c5ba7 3355}
3356
3357
f49d7bb5 3358/* Similar to lookup_decl_in_outer_ctx, but return DECL if not found
3359 in outer contexts. */
3360
3361static tree
3362maybe_lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
3363{
3364 tree t = NULL;
3365 omp_context *up;
3366
87b31375 3367 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
3368 t = maybe_lookup_decl (decl, up);
f49d7bb5 3369
3370 return t ? t : decl;
3371}
3372
3373
df67b98c 3374/* Construct the initialization value for reduction operation OP. */
1e8e9920 3375
3376tree
df67b98c 3377omp_reduction_init_op (location_t loc, enum tree_code op, tree type)
1e8e9920 3378{
df67b98c 3379 switch (op)
1e8e9920 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:
385f3f36 3389 return build_zero_cst (type);
1e8e9920 3390
3391 case MULT_EXPR:
3392 case TRUTH_AND_EXPR:
3393 case TRUTH_ANDIF_EXPR:
3394 case EQ_EXPR:
389dd41b 3395 return fold_convert_loc (loc, type, integer_one_node);
1e8e9920 3396
3397 case BIT_AND_EXPR:
389dd41b 3398 return fold_convert_loc (loc, type, integer_minus_one_node);
1e8e9920 3399
3400 case MAX_EXPR:
3401 if (SCALAR_FLOAT_TYPE_P (type))
3402 {
3403 REAL_VALUE_TYPE max, min;
fe994837 3404 if (HONOR_INFINITIES (type))
1e8e9920 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 }
5902cce5 3413 else if (POINTER_TYPE_P (type))
3414 {
3415 wide_int min
3416 = wi::min_value (TYPE_PRECISION (type), TYPE_SIGN (type));
3417 return wide_int_to_tree (type, min);
3418 }
1e8e9920 3419 else
3420 {
3421 gcc_assert (INTEGRAL_TYPE_P (type));
3422 return TYPE_MIN_VALUE (type);
3423 }
3424
3425 case MIN_EXPR:
3426 if (SCALAR_FLOAT_TYPE_P (type))
3427 {
3428 REAL_VALUE_TYPE max;
fe994837 3429 if (HONOR_INFINITIES (type))
1e8e9920 3430 real_inf (&max);
3431 else
3432 real_maxval (&max, 0, TYPE_MODE (type));
3433 return build_real (type, max);
3434 }
5902cce5 3435 else if (POINTER_TYPE_P (type))
3436 {
3437 wide_int max
3438 = wi::max_value (TYPE_PRECISION (type), TYPE_SIGN (type));
3439 return wide_int_to_tree (type, max);
3440 }
1e8e9920 3441 else
3442 {
3443 gcc_assert (INTEGRAL_TYPE_P (type));
3444 return TYPE_MAX_VALUE (type);
3445 }
3446
3447 default:
3448 gcc_unreachable ();
3449 }
3450}
3451
df67b98c 3452/* Construct the initialization value for reduction CLAUSE. */
3453
3454tree
3455omp_reduction_init (tree clause, tree type)
3456{
3457 return omp_reduction_init_op (OMP_CLAUSE_LOCATION (clause),
3458 OMP_CLAUSE_REDUCTION_CODE (clause), type);
3459}
3460
bc7bff74 3461/* Return alignment to be assumed for var in CLAUSE, which should be
3462 OMP_CLAUSE_ALIGNED. */
3463
3464static tree
3465omp_clause_aligned_alignment (tree clause)
3466{
3467 if (OMP_CLAUSE_ALIGNED_ALIGNMENT (clause))
3468 return OMP_CLAUSE_ALIGNED_ALIGNMENT (clause);
3469
3470 /* Otherwise return implementation defined alignment. */
3471 unsigned int al = 1;
3754d046 3472 machine_mode mode, vmode;
bc7bff74 3473 int vs = targetm.vectorize.autovectorize_vector_sizes ();
3474 if (vs)
3475 vs = 1 << floor_log2 (vs);
3476 static enum mode_class classes[]
3477 = { MODE_INT, MODE_VECTOR_INT, MODE_FLOAT, MODE_VECTOR_FLOAT };
3478 for (int i = 0; i < 4; i += 2)
3479 for (mode = GET_CLASS_NARROWEST_MODE (classes[i]);
3480 mode != VOIDmode;
3481 mode = GET_MODE_WIDER_MODE (mode))
3482 {
3483 vmode = targetm.vectorize.preferred_simd_mode (mode);
3484 if (GET_MODE_CLASS (vmode) != classes[i + 1])
3485 continue;
3486 while (vs
3487 && GET_MODE_SIZE (vmode) < vs
3488 && GET_MODE_2XWIDER_MODE (vmode) != VOIDmode)
3489 vmode = GET_MODE_2XWIDER_MODE (vmode);
3490
3491 tree type = lang_hooks.types.type_for_mode (mode, 1);
3492 if (type == NULL_TREE || TYPE_MODE (type) != mode)
3493 continue;
3494 type = build_vector_type (type, GET_MODE_SIZE (vmode)
3495 / GET_MODE_SIZE (mode));
3496 if (TYPE_MODE (type) != vmode)
3497 continue;
3498 if (TYPE_ALIGN_UNIT (type) > al)
3499 al = TYPE_ALIGN_UNIT (type);
3500 }
3501 return build_int_cst (integer_type_node, al);
3502}
3503
3d483a94 3504/* Return maximum possible vectorization factor for the target. */
3505
3506static int
3507omp_max_vf (void)
3508{
3509 if (!optimize
3510 || optimize_debug
ad45e43e 3511 || !flag_tree_loop_optimize
043115ec 3512 || (!flag_tree_loop_vectorize
3513 && (global_options_set.x_flag_tree_loop_vectorize
3514 || global_options_set.x_flag_tree_vectorize)))
3d483a94 3515 return 1;
3516
3517 int vs = targetm.vectorize.autovectorize_vector_sizes ();
3518 if (vs)
3519 {
3520 vs = 1 << floor_log2 (vs);
3521 return vs;
3522 }
3754d046 3523 machine_mode vqimode = targetm.vectorize.preferred_simd_mode (QImode);
3d483a94 3524 if (GET_MODE_CLASS (vqimode) == MODE_VECTOR_INT)
3525 return GET_MODE_NUNITS (vqimode);
3526 return 1;
3527}
3528
3529/* Helper function of lower_rec_input_clauses, used for #pragma omp simd
3530 privatization. */
3531
3532static bool
3533lower_rec_simd_input_clauses (tree new_var, omp_context *ctx, int &max_vf,
3534 tree &idx, tree &lane, tree &ivar, tree &lvar)
3535{
3536 if (max_vf == 0)
3537 {
3538 max_vf = omp_max_vf ();
3539 if (max_vf > 1)
3540 {
3541 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3542 OMP_CLAUSE_SAFELEN);
c3f3b68d 3543 if (c && TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c)) != INTEGER_CST)
3544 max_vf = 1;
3545 else if (c && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
3546 max_vf) == -1)
d85a2013 3547 max_vf = tree_to_shwi (OMP_CLAUSE_SAFELEN_EXPR (c));
3d483a94 3548 }
3549 if (max_vf > 1)
3550 {
f9e245b2 3551 idx = create_tmp_var (unsigned_type_node);
3552 lane = create_tmp_var (unsigned_type_node);
3d483a94 3553 }
3554 }
3555 if (max_vf == 1)
3556 return false;
3557
3558 tree atype = build_array_type_nelts (TREE_TYPE (new_var), max_vf);
f9e245b2 3559 tree avar = create_tmp_var_raw (atype);
3d483a94 3560 if (TREE_ADDRESSABLE (new_var))
3561 TREE_ADDRESSABLE (avar) = 1;
3562 DECL_ATTRIBUTES (avar)
3563 = tree_cons (get_identifier ("omp simd array"), NULL,
3564 DECL_ATTRIBUTES (avar));
3565 gimple_add_tmp_var (avar);
3566 ivar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, idx,
3567 NULL_TREE, NULL_TREE);
3568 lvar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, lane,
3569 NULL_TREE, NULL_TREE);
bc7bff74 3570 if (DECL_P (new_var))
3571 {
3572 SET_DECL_VALUE_EXPR (new_var, lvar);
3573 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3574 }
3d483a94 3575 return true;
3576}
3577
2712b6de 3578/* Helper function of lower_rec_input_clauses. For a reference
3579 in simd reduction, add an underlying variable it will reference. */
3580
3581static void
3582handle_simd_reference (location_t loc, tree new_vard, gimple_seq *ilist)
3583{
3584 tree z = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_vard)));
3585 if (TREE_CONSTANT (z))
3586 {
3587 const char *name = NULL;
3588 if (DECL_NAME (new_vard))
3589 name = IDENTIFIER_POINTER (DECL_NAME (new_vard));
3590
3591 z = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_vard)), name);
3592 gimple_add_tmp_var (z);
3593 TREE_ADDRESSABLE (z) = 1;
3594 z = build_fold_addr_expr_loc (loc, z);
3595 gimplify_assign (new_vard, z, ilist);
3596 }
3597}
3598
1e8e9920 3599/* Generate code to implement the input clauses, FIRSTPRIVATE and COPYIN,
3600 from the receiver (aka child) side and initializers for REFERENCE_TYPE
3601 private variables. Initialization statements go in ILIST, while calls
3602 to destructors go in DLIST. */
3603
3604static void
75a70cf9 3605lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
bc7bff74 3606 omp_context *ctx, struct omp_for_data *fd)
1e8e9920 3607{
c2f47e15 3608 tree c, dtor, copyin_seq, x, ptr;
1e8e9920 3609 bool copyin_by_ref = false;
f49d7bb5 3610 bool lastprivate_firstprivate = false;
bc7bff74 3611 bool reduction_omp_orig_ref = false;
1e8e9920 3612 int pass;
3d483a94 3613 bool is_simd = (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
10c55644 3614 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD);
3d483a94 3615 int max_vf = 0;
3616 tree lane = NULL_TREE, idx = NULL_TREE;
3617 tree ivar = NULL_TREE, lvar = NULL_TREE;
3618 gimple_seq llist[2] = { NULL, NULL };
1e8e9920 3619
1e8e9920 3620 copyin_seq = NULL;
3621
3d483a94 3622 /* Set max_vf=1 (which will later enforce safelen=1) in simd loops
3623 with data sharing clauses referencing variable sized vars. That
3624 is unnecessarily hard to support and very unlikely to result in
3625 vectorized code anyway. */
3626 if (is_simd)
3627 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
3628 switch (OMP_CLAUSE_CODE (c))
3629 {
9580cb79 3630 case OMP_CLAUSE_LINEAR:
3631 if (OMP_CLAUSE_LINEAR_ARRAY (c))
3632 max_vf = 1;
3633 /* FALLTHRU */
3d483a94 3634 case OMP_CLAUSE_REDUCTION:
3d483a94 3635 case OMP_CLAUSE_PRIVATE:
3636 case OMP_CLAUSE_FIRSTPRIVATE:
3637 case OMP_CLAUSE_LASTPRIVATE:
3d483a94 3638 if (is_variable_sized (OMP_CLAUSE_DECL (c)))
3639 max_vf = 1;
3640 break;
3641 default:
3642 continue;
3643 }
3644
1e8e9920 3645 /* Do all the fixed sized types in the first pass, and the variable sized
3646 types in the second pass. This makes sure that the scalar arguments to
48e1416a 3647 the variable sized types are processed before we use them in the
1e8e9920 3648 variable sized operations. */
3649 for (pass = 0; pass < 2; ++pass)
3650 {
3651 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
3652 {
55d6e7cd 3653 enum omp_clause_code c_kind = OMP_CLAUSE_CODE (c);
1e8e9920 3654 tree var, new_var;
3655 bool by_ref;
389dd41b 3656 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
1e8e9920 3657
3658 switch (c_kind)
3659 {
3660 case OMP_CLAUSE_PRIVATE:
3661 if (OMP_CLAUSE_PRIVATE_DEBUG (c))
3662 continue;
3663 break;
3664 case OMP_CLAUSE_SHARED:
bc7bff74 3665 /* Ignore shared directives in teams construct. */
3666 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
3667 continue;
f49d7bb5 3668 if (maybe_lookup_decl (OMP_CLAUSE_DECL (c), ctx) == NULL)
3669 {
3670 gcc_assert (is_global_var (OMP_CLAUSE_DECL (c)));
3671 continue;
3672 }
1e8e9920 3673 case OMP_CLAUSE_FIRSTPRIVATE:
1e8e9920 3674 case OMP_CLAUSE_COPYIN:
bc7bff74 3675 case OMP_CLAUSE_LINEAR:
3676 break;
1e8e9920 3677 case OMP_CLAUSE_REDUCTION:
bc7bff74 3678 if (OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c))
3679 reduction_omp_orig_ref = true;
1e8e9920 3680 break;
bc7bff74 3681 case OMP_CLAUSE__LOOPTEMP_:
3682 /* Handle _looptemp_ clauses only on parallel. */
3683 if (fd)
3684 continue;
3d483a94 3685 break;
df2c34fc 3686 case OMP_CLAUSE_LASTPRIVATE:
f49d7bb5 3687 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
3688 {
3689 lastprivate_firstprivate = true;
3690 if (pass != 0)
3691 continue;
3692 }
cf5f881f 3693 /* Even without corresponding firstprivate, if
3694 decl is Fortran allocatable, it needs outer var
3695 reference. */
3696 else if (pass == 0
3697 && lang_hooks.decls.omp_private_outer_ref
3698 (OMP_CLAUSE_DECL (c)))
3699 lastprivate_firstprivate = true;
df2c34fc 3700 break;
bc7bff74 3701 case OMP_CLAUSE_ALIGNED:
3702 if (pass == 0)
3703 continue;
3704 var = OMP_CLAUSE_DECL (c);
3705 if (TREE_CODE (TREE_TYPE (var)) == POINTER_TYPE
3706 && !is_global_var (var))
3707 {
3708 new_var = maybe_lookup_decl (var, ctx);
3709 if (new_var == NULL_TREE)
3710 new_var = maybe_lookup_decl_in_outer_ctx (var, ctx);
3711 x = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
3712 x = build_call_expr_loc (clause_loc, x, 2, new_var,
3713 omp_clause_aligned_alignment (c));
3714 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
3715 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
3716 gimplify_and_add (x, ilist);
3717 }
3718 else if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE
3719 && is_global_var (var))
3720 {
3721 tree ptype = build_pointer_type (TREE_TYPE (var)), t, t2;
3722 new_var = lookup_decl (var, ctx);
3723 t = maybe_lookup_decl_in_outer_ctx (var, ctx);
3724 t = build_fold_addr_expr_loc (clause_loc, t);
3725 t2 = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
3726 t = build_call_expr_loc (clause_loc, t2, 2, t,
3727 omp_clause_aligned_alignment (c));
3728 t = fold_convert_loc (clause_loc, ptype, t);
f9e245b2 3729 x = create_tmp_var (ptype);
bc7bff74 3730 t = build2 (MODIFY_EXPR, ptype, x, t);
3731 gimplify_and_add (t, ilist);
3732 t = build_simple_mem_ref_loc (clause_loc, x);
3733 SET_DECL_VALUE_EXPR (new_var, t);
3734 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3735 }
3736 continue;
1e8e9920 3737 default:
3738 continue;
3739 }
3740
3741 new_var = var = OMP_CLAUSE_DECL (c);
3742 if (c_kind != OMP_CLAUSE_COPYIN)
3743 new_var = lookup_decl (var, ctx);
3744
3745 if (c_kind == OMP_CLAUSE_SHARED || c_kind == OMP_CLAUSE_COPYIN)
3746 {
3747 if (pass != 0)
3748 continue;
3749 }
1e8e9920 3750 else if (is_variable_sized (var))
3751 {
773c5ba7 3752 /* For variable sized types, we need to allocate the
3753 actual storage here. Call alloca and store the
3754 result in the pointer decl that we created elsewhere. */
1e8e9920 3755 if (pass == 0)
3756 continue;
3757
fd6481cf 3758 if (c_kind != OMP_CLAUSE_FIRSTPRIVATE || !is_task_ctx (ctx))
3759 {
1a91d914 3760 gcall *stmt;
b9a16870 3761 tree tmp, atmp;
75a70cf9 3762
fd6481cf 3763 ptr = DECL_VALUE_EXPR (new_var);
3764 gcc_assert (TREE_CODE (ptr) == INDIRECT_REF);
3765 ptr = TREE_OPERAND (ptr, 0);
3766 gcc_assert (DECL_P (ptr));
3767 x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
75a70cf9 3768
3769 /* void *tmp = __builtin_alloca */
b9a16870 3770 atmp = builtin_decl_explicit (BUILT_IN_ALLOCA);
3771 stmt = gimple_build_call (atmp, 1, x);
f9e245b2 3772 tmp = create_tmp_var_raw (ptr_type_node);
75a70cf9 3773 gimple_add_tmp_var (tmp);
3774 gimple_call_set_lhs (stmt, tmp);
3775
3776 gimple_seq_add_stmt (ilist, stmt);
3777
389dd41b 3778 x = fold_convert_loc (clause_loc, TREE_TYPE (ptr), tmp);
75a70cf9 3779 gimplify_assign (ptr, x, ilist);
fd6481cf 3780 }
1e8e9920 3781 }
1e8e9920 3782 else if (is_reference (var))
3783 {
773c5ba7 3784 /* For references that are being privatized for Fortran,
3785 allocate new backing storage for the new pointer
3786 variable. This allows us to avoid changing all the
3787 code that expects a pointer to something that expects
bc7bff74 3788 a direct variable. */
1e8e9920 3789 if (pass == 0)
3790 continue;
3791
3792 x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
fd6481cf 3793 if (c_kind == OMP_CLAUSE_FIRSTPRIVATE && is_task_ctx (ctx))
3794 {
3795 x = build_receiver_ref (var, false, ctx);
389dd41b 3796 x = build_fold_addr_expr_loc (clause_loc, x);
fd6481cf 3797 }
3798 else if (TREE_CONSTANT (x))
1e8e9920 3799 {
2712b6de 3800 /* For reduction in SIMD loop, defer adding the
3801 initialization of the reference, because if we decide
3802 to use SIMD array for it, the initilization could cause
3803 expansion ICE. */
3804 if (c_kind == OMP_CLAUSE_REDUCTION && is_simd)
09d1c205 3805 x = NULL_TREE;
3806 else
3807 {
3808 const char *name = NULL;
3809 if (DECL_NAME (var))
3810 name = IDENTIFIER_POINTER (DECL_NAME (new_var));
3811
3812 x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)),
3813 name);
3814 gimple_add_tmp_var (x);
3815 TREE_ADDRESSABLE (x) = 1;
3816 x = build_fold_addr_expr_loc (clause_loc, x);
3817 }
1e8e9920 3818 }
3819 else
3820 {
b9a16870 3821 tree atmp = builtin_decl_explicit (BUILT_IN_ALLOCA);
3822 x = build_call_expr_loc (clause_loc, atmp, 1, x);
1e8e9920 3823 }
3824
09d1c205 3825 if (x)
3826 {
3827 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
3828 gimplify_assign (new_var, x, ilist);
3829 }
1e8e9920 3830
182cf5a9 3831 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
1e8e9920 3832 }
3833 else if (c_kind == OMP_CLAUSE_REDUCTION
3834 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
3835 {
3836 if (pass == 0)
3837 continue;
3838 }
3839 else if (pass != 0)
3840 continue;
3841
55d6e7cd 3842 switch (OMP_CLAUSE_CODE (c))
1e8e9920 3843 {
3844 case OMP_CLAUSE_SHARED:
bc7bff74 3845 /* Ignore shared directives in teams construct. */
3846 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
3847 continue;
f49d7bb5 3848 /* Shared global vars are just accessed directly. */
3849 if (is_global_var (new_var))
3850 break;
1e8e9920 3851 /* Set up the DECL_VALUE_EXPR for shared variables now. This
3852 needs to be delayed until after fixup_child_record_type so
3853 that we get the correct type during the dereference. */
e8a588af 3854 by_ref = use_pointer_for_field (var, ctx);
1e8e9920 3855 x = build_receiver_ref (var, by_ref, ctx);
3856 SET_DECL_VALUE_EXPR (new_var, x);
3857 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3858
3859 /* ??? If VAR is not passed by reference, and the variable
3860 hasn't been initialized yet, then we'll get a warning for
3861 the store into the omp_data_s structure. Ideally, we'd be
48e1416a 3862 able to notice this and not store anything at all, but
1e8e9920 3863 we're generating code too early. Suppress the warning. */
3864 if (!by_ref)
3865 TREE_NO_WARNING (var) = 1;
3866 break;
3867
3868 case OMP_CLAUSE_LASTPRIVATE:
3869 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
3870 break;
3871 /* FALLTHRU */
3872
3873 case OMP_CLAUSE_PRIVATE:
fd6481cf 3874 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_PRIVATE)
3875 x = build_outer_var_ref (var, ctx);
3876 else if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
3877 {
3878 if (is_task_ctx (ctx))
3879 x = build_receiver_ref (var, false, ctx);
3880 else
3881 x = build_outer_var_ref (var, ctx);
3882 }
3883 else
3884 x = NULL;
3d483a94 3885 do_private:
bc7bff74 3886 tree nx;
3887 nx = lang_hooks.decls.omp_clause_default_ctor (c, new_var, x);
3d483a94 3888 if (is_simd)
3889 {
3890 tree y = lang_hooks.decls.omp_clause_dtor (c, new_var);
bc7bff74 3891 if ((TREE_ADDRESSABLE (new_var) || nx || y
3d483a94 3892 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE)
3893 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3894 idx, lane, ivar, lvar))
3895 {
bc7bff74 3896 if (nx)
3d483a94 3897 x = lang_hooks.decls.omp_clause_default_ctor
3898 (c, unshare_expr (ivar), x);
bc7bff74 3899 if (nx && x)
3d483a94 3900 gimplify_and_add (x, &llist[0]);
3901 if (y)
3902 {
3903 y = lang_hooks.decls.omp_clause_dtor (c, ivar);
3904 if (y)
3905 {
3906 gimple_seq tseq = NULL;
3907
3908 dtor = y;
3909 gimplify_stmt (&dtor, &tseq);
3910 gimple_seq_add_seq (&llist[1], tseq);
3911 }
3912 }
3913 break;
3914 }
3915 }
bc7bff74 3916 if (nx)
3917 gimplify_and_add (nx, ilist);
1e8e9920 3918 /* FALLTHRU */
3919
3920 do_dtor:
3921 x = lang_hooks.decls.omp_clause_dtor (c, new_var);
3922 if (x)
3923 {
75a70cf9 3924 gimple_seq tseq = NULL;
3925
1e8e9920 3926 dtor = x;
75a70cf9 3927 gimplify_stmt (&dtor, &tseq);
e3a19533 3928 gimple_seq_add_seq (dlist, tseq);
1e8e9920 3929 }
3930 break;
3931
3d483a94 3932 case OMP_CLAUSE_LINEAR:
3933 if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c))
3934 goto do_firstprivate;
3935 if (OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
3936 x = NULL;
3937 else
3938 x = build_outer_var_ref (var, ctx);
3939 goto do_private;
3940
1e8e9920 3941 case OMP_CLAUSE_FIRSTPRIVATE:
fd6481cf 3942 if (is_task_ctx (ctx))
3943 {
3944 if (is_reference (var) || is_variable_sized (var))
3945 goto do_dtor;
3946 else if (is_global_var (maybe_lookup_decl_in_outer_ctx (var,
3947 ctx))
3948 || use_pointer_for_field (var, NULL))
3949 {
3950 x = build_receiver_ref (var, false, ctx);
3951 SET_DECL_VALUE_EXPR (new_var, x);
3952 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3953 goto do_dtor;
3954 }
3955 }
3d483a94 3956 do_firstprivate:
1e8e9920 3957 x = build_outer_var_ref (var, ctx);
3d483a94 3958 if (is_simd)
3959 {
bc7bff74 3960 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
3961 && gimple_omp_for_combined_into_p (ctx->stmt))
3962 {
9580cb79 3963 tree t = OMP_CLAUSE_LINEAR_STEP (c);
3964 tree stept = TREE_TYPE (t);
3965 tree ct = find_omp_clause (clauses,
3966 OMP_CLAUSE__LOOPTEMP_);
3967 gcc_assert (ct);
3968 tree l = OMP_CLAUSE_DECL (ct);
e471cc6f 3969 tree n1 = fd->loop.n1;
3970 tree step = fd->loop.step;
3971 tree itype = TREE_TYPE (l);
3972 if (POINTER_TYPE_P (itype))
3973 itype = signed_type_for (itype);
3974 l = fold_build2 (MINUS_EXPR, itype, l, n1);
3975 if (TYPE_UNSIGNED (itype)
3976 && fd->loop.cond_code == GT_EXPR)
3977 l = fold_build2 (TRUNC_DIV_EXPR, itype,
3978 fold_build1 (NEGATE_EXPR, itype, l),
3979 fold_build1 (NEGATE_EXPR,
3980 itype, step));
3981 else
3982 l = fold_build2 (TRUNC_DIV_EXPR, itype, l, step);
bc7bff74 3983 t = fold_build2 (MULT_EXPR, stept,
3984 fold_convert (stept, l), t);
9580cb79 3985
3986 if (OMP_CLAUSE_LINEAR_ARRAY (c))
3987 {
3988 x = lang_hooks.decls.omp_clause_linear_ctor
3989 (c, new_var, x, t);
3990 gimplify_and_add (x, ilist);
3991 goto do_dtor;
3992 }
3993
bc7bff74 3994 if (POINTER_TYPE_P (TREE_TYPE (x)))
3995 x = fold_build2 (POINTER_PLUS_EXPR,
3996 TREE_TYPE (x), x, t);
3997 else
3998 x = fold_build2 (PLUS_EXPR, TREE_TYPE (x), x, t);
3999 }
4000
3d483a94 4001 if ((OMP_CLAUSE_CODE (c) != OMP_CLAUSE_LINEAR
4002 || TREE_ADDRESSABLE (new_var))
4003 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
4004 idx, lane, ivar, lvar))
4005 {
4006 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR)
4007 {
f9e245b2 4008 tree iv = create_tmp_var (TREE_TYPE (new_var));
3d483a94 4009 x = lang_hooks.decls.omp_clause_copy_ctor (c, iv, x);
4010 gimplify_and_add (x, ilist);
4011 gimple_stmt_iterator gsi
4012 = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
1a91d914 4013 gassign *g
3d483a94 4014 = gimple_build_assign (unshare_expr (lvar), iv);
4015 gsi_insert_before_without_update (&gsi, g,
4016 GSI_SAME_STMT);
9580cb79 4017 tree t = OMP_CLAUSE_LINEAR_STEP (c);
3d483a94 4018 enum tree_code code = PLUS_EXPR;
4019 if (POINTER_TYPE_P (TREE_TYPE (new_var)))
4020 code = POINTER_PLUS_EXPR;
e9cf809e 4021 g = gimple_build_assign (iv, code, iv, t);
3d483a94 4022 gsi_insert_before_without_update (&gsi, g,
4023 GSI_SAME_STMT);
4024 break;
4025 }
4026 x = lang_hooks.decls.omp_clause_copy_ctor
4027 (c, unshare_expr (ivar), x);
4028 gimplify_and_add (x, &llist[0]);
4029 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
4030 if (x)
4031 {
4032 gimple_seq tseq = NULL;
4033
4034 dtor = x;
4035 gimplify_stmt (&dtor, &tseq);
4036 gimple_seq_add_seq (&llist[1], tseq);
4037 }
4038 break;
4039 }
4040 }
1e8e9920 4041 x = lang_hooks.decls.omp_clause_copy_ctor (c, new_var, x);
4042 gimplify_and_add (x, ilist);
4043 goto do_dtor;
1e8e9920 4044
bc7bff74 4045 case OMP_CLAUSE__LOOPTEMP_:
4046 gcc_assert (is_parallel_ctx (ctx));
4047 x = build_outer_var_ref (var, ctx);
4048 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
4049 gimplify_and_add (x, ilist);
4050 break;
4051
1e8e9920 4052 case OMP_CLAUSE_COPYIN:
e8a588af 4053 by_ref = use_pointer_for_field (var, NULL);
1e8e9920 4054 x = build_receiver_ref (var, by_ref, ctx);
4055 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, x);
4056 append_to_statement_list (x, &copyin_seq);
4057 copyin_by_ref |= by_ref;
4058 break;
4059
4060 case OMP_CLAUSE_REDUCTION:
4061 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4062 {
fd6481cf 4063 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
42acab1c 4064 gimple *tseq;
fd6481cf 4065 x = build_outer_var_ref (var, ctx);
4066
bc7bff74 4067 if (is_reference (var)
4068 && !useless_type_conversion_p (TREE_TYPE (placeholder),
4069 TREE_TYPE (x)))
389dd41b 4070 x = build_fold_addr_expr_loc (clause_loc, x);
fd6481cf 4071 SET_DECL_VALUE_EXPR (placeholder, x);
4072 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
bc7bff74 4073 tree new_vard = new_var;
4074 if (is_reference (var))
4075 {
4076 gcc_assert (TREE_CODE (new_var) == MEM_REF);
4077 new_vard = TREE_OPERAND (new_var, 0);
4078 gcc_assert (DECL_P (new_vard));
4079 }
3d483a94 4080 if (is_simd
4081 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
4082 idx, lane, ivar, lvar))
4083 {
bc7bff74 4084 if (new_vard == new_var)
4085 {
4086 gcc_assert (DECL_VALUE_EXPR (new_var) == lvar);
4087 SET_DECL_VALUE_EXPR (new_var, ivar);
4088 }
4089 else
4090 {
4091 SET_DECL_VALUE_EXPR (new_vard,
4092 build_fold_addr_expr (ivar));
4093 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
4094 }
4095 x = lang_hooks.decls.omp_clause_default_ctor
4096 (c, unshare_expr (ivar),
4097 build_outer_var_ref (var, ctx));
4098 if (x)
4099 gimplify_and_add (x, &llist[0]);
4100 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
4101 {
4102 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
4103 lower_omp (&tseq, ctx);
4104 gimple_seq_add_seq (&llist[0], tseq);
4105 }
4106 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
4107 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
4108 lower_omp (&tseq, ctx);
4109 gimple_seq_add_seq (&llist[1], tseq);
4110 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
4111 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
4112 if (new_vard == new_var)
4113 SET_DECL_VALUE_EXPR (new_var, lvar);
4114 else
4115 SET_DECL_VALUE_EXPR (new_vard,
4116 build_fold_addr_expr (lvar));
4117 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
4118 if (x)
4119 {
4120 tseq = NULL;
4121 dtor = x;
4122 gimplify_stmt (&dtor, &tseq);
4123 gimple_seq_add_seq (&llist[1], tseq);
4124 }
4125 break;
4126 }
09d1c205 4127 /* If this is a reference to constant size reduction var
4128 with placeholder, we haven't emitted the initializer
4129 for it because it is undesirable if SIMD arrays are used.
4130 But if they aren't used, we need to emit the deferred
4131 initialization now. */
4132 else if (is_reference (var) && is_simd)
2712b6de 4133 handle_simd_reference (clause_loc, new_vard, ilist);
bc7bff74 4134 x = lang_hooks.decls.omp_clause_default_ctor
cf5f881f 4135 (c, unshare_expr (new_var),
4136 build_outer_var_ref (var, ctx));
bc7bff74 4137 if (x)
4138 gimplify_and_add (x, ilist);
4139 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
4140 {
4141 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
4142 lower_omp (&tseq, ctx);
4143 gimple_seq_add_seq (ilist, tseq);
4144 }
75a70cf9 4145 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
bc7bff74 4146 if (is_simd)
4147 {
4148 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
4149 lower_omp (&tseq, ctx);
4150 gimple_seq_add_seq (dlist, tseq);
4151 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
4152 }
fd6481cf 4153 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
bc7bff74 4154 goto do_dtor;
1e8e9920 4155 }
4156 else
4157 {
4158 x = omp_reduction_init (c, TREE_TYPE (new_var));
4159 gcc_assert (TREE_CODE (TREE_TYPE (new_var)) != ARRAY_TYPE);
c22ad515 4160 enum tree_code code = OMP_CLAUSE_REDUCTION_CODE (c);
4161
4162 /* reduction(-:var) sums up the partial results, so it
4163 acts identically to reduction(+:var). */
4164 if (code == MINUS_EXPR)
4165 code = PLUS_EXPR;
4166
2712b6de 4167 tree new_vard = new_var;
4168 if (is_simd && is_reference (var))
4169 {
4170 gcc_assert (TREE_CODE (new_var) == MEM_REF);
4171 new_vard = TREE_OPERAND (new_var, 0);
4172 gcc_assert (DECL_P (new_vard));
4173 }
3d483a94 4174 if (is_simd
4175 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
4176 idx, lane, ivar, lvar))
4177 {
3d483a94 4178 tree ref = build_outer_var_ref (var, ctx);
4179
4180 gimplify_assign (unshare_expr (ivar), x, &llist[0]);
4181
3d483a94 4182 x = build2 (code, TREE_TYPE (ref), ref, ivar);
4183 ref = build_outer_var_ref (var, ctx);
4184 gimplify_assign (ref, x, &llist[1]);
2712b6de 4185
4186 if (new_vard != new_var)
4187 {
4188 SET_DECL_VALUE_EXPR (new_vard,
4189 build_fold_addr_expr (lvar));
4190 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
4191 }
3d483a94 4192 }
4193 else
4194 {
2712b6de 4195 if (is_reference (var) && is_simd)
4196 handle_simd_reference (clause_loc, new_vard, ilist);
3d483a94 4197 gimplify_assign (new_var, x, ilist);
4198 if (is_simd)
c22ad515 4199 {
4200 tree ref = build_outer_var_ref (var, ctx);
4201
4202 x = build2 (code, TREE_TYPE (ref), ref, new_var);
4203 ref = build_outer_var_ref (var, ctx);
4204 gimplify_assign (ref, x, dlist);
4205 }
3d483a94 4206 }
1e8e9920 4207 }
4208 break;
4209
4210 default:
4211 gcc_unreachable ();
4212 }
4213 }
4214 }
4215
3d483a94 4216 if (lane)
4217 {
4218 tree uid = create_tmp_var (ptr_type_node, "simduid");
8e1a382d 4219 /* Don't want uninit warnings on simduid, it is always uninitialized,
4220 but we use it not for the value, but for the DECL_UID only. */
4221 TREE_NO_WARNING (uid) = 1;
42acab1c 4222 gimple *g
3d483a94 4223 = gimple_build_call_internal (IFN_GOMP_SIMD_LANE, 1, uid);
4224 gimple_call_set_lhs (g, lane);
4225 gimple_stmt_iterator gsi = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
4226 gsi_insert_before_without_update (&gsi, g, GSI_SAME_STMT);
4227 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__SIMDUID_);
4228 OMP_CLAUSE__SIMDUID__DECL (c) = uid;
4229 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
4230 gimple_omp_for_set_clauses (ctx->stmt, c);
e9cf809e 4231 g = gimple_build_assign (lane, INTEGER_CST,
4232 build_int_cst (unsigned_type_node, 0));
3d483a94 4233 gimple_seq_add_stmt (ilist, g);
4234 for (int i = 0; i < 2; i++)
4235 if (llist[i])
4236 {
f9e245b2 4237 tree vf = create_tmp_var (unsigned_type_node);
3d483a94 4238 g = gimple_build_call_internal (IFN_GOMP_SIMD_VF, 1, uid);
4239 gimple_call_set_lhs (g, vf);
4240 gimple_seq *seq = i == 0 ? ilist : dlist;
4241 gimple_seq_add_stmt (seq, g);
4242 tree t = build_int_cst (unsigned_type_node, 0);
e9cf809e 4243 g = gimple_build_assign (idx, INTEGER_CST, t);
3d483a94 4244 gimple_seq_add_stmt (seq, g);
4245 tree body = create_artificial_label (UNKNOWN_LOCATION);
4246 tree header = create_artificial_label (UNKNOWN_LOCATION);
4247 tree end = create_artificial_label (UNKNOWN_LOCATION);
4248 gimple_seq_add_stmt (seq, gimple_build_goto (header));
4249 gimple_seq_add_stmt (seq, gimple_build_label (body));
4250 gimple_seq_add_seq (seq, llist[i]);
4251 t = build_int_cst (unsigned_type_node, 1);
e9cf809e 4252 g = gimple_build_assign (idx, PLUS_EXPR, idx, t);
3d483a94 4253 gimple_seq_add_stmt (seq, g);
4254 gimple_seq_add_stmt (seq, gimple_build_label (header));
4255 g = gimple_build_cond (LT_EXPR, idx, vf, body, end);
4256 gimple_seq_add_stmt (seq, g);
4257 gimple_seq_add_stmt (seq, gimple_build_label (end));
4258 }
4259 }
4260
1e8e9920 4261 /* The copyin sequence is not to be executed by the main thread, since
4262 that would result in self-copies. Perhaps not visible to scalars,
4263 but it certainly is to C++ operator=. */
4264 if (copyin_seq)
4265 {
b9a16870 4266 x = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM),
4267 0);
1e8e9920 4268 x = build2 (NE_EXPR, boolean_type_node, x,
4269 build_int_cst (TREE_TYPE (x), 0));
4270 x = build3 (COND_EXPR, void_type_node, x, copyin_seq, NULL);
4271 gimplify_and_add (x, ilist);
4272 }
4273
4274 /* If any copyin variable is passed by reference, we must ensure the
4275 master thread doesn't modify it before it is copied over in all
f49d7bb5 4276 threads. Similarly for variables in both firstprivate and
4277 lastprivate clauses we need to ensure the lastprivate copying
bc7bff74 4278 happens after firstprivate copying in all threads. And similarly
4279 for UDRs if initializer expression refers to omp_orig. */
4280 if (copyin_by_ref || lastprivate_firstprivate || reduction_omp_orig_ref)
3d483a94 4281 {
4282 /* Don't add any barrier for #pragma omp simd or
4283 #pragma omp distribute. */
4284 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
7c01fa6c 4285 || gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_FOR)
bc7bff74 4286 gimple_seq_add_stmt (ilist, build_omp_barrier (NULL_TREE));
3d483a94 4287 }
4288
4289 /* If max_vf is non-zero, then we can use only a vectorization factor
4290 up to the max_vf we chose. So stick it into the safelen clause. */
4291 if (max_vf)
4292 {
4293 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
4294 OMP_CLAUSE_SAFELEN);
4295 if (c == NULL_TREE
c3f3b68d 4296 || (TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c)) == INTEGER_CST
4297 && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
4298 max_vf) == 1))
3d483a94 4299 {
4300 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_SAFELEN);
4301 OMP_CLAUSE_SAFELEN_EXPR (c) = build_int_cst (integer_type_node,
4302 max_vf);
4303 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
4304 gimple_omp_for_set_clauses (ctx->stmt, c);
4305 }
4306 }
1e8e9920 4307}
4308
773c5ba7 4309
1e8e9920 4310/* Generate code to implement the LASTPRIVATE clauses. This is used for
4311 both parallel and workshare constructs. PREDICATE may be NULL if it's
4312 always true. */
4313
4314static void
75a70cf9 4315lower_lastprivate_clauses (tree clauses, tree predicate, gimple_seq *stmt_list,
bc7bff74 4316 omp_context *ctx)
1e8e9920 4317{
3d483a94 4318 tree x, c, label = NULL, orig_clauses = clauses;
fd6481cf 4319 bool par_clauses = false;
3d483a94 4320 tree simduid = NULL, lastlane = NULL;
1e8e9920 4321
3d483a94 4322 /* Early exit if there are no lastprivate or linear clauses. */
4323 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
4324 if (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LASTPRIVATE
4325 || (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LINEAR
4326 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (clauses)))
4327 break;
1e8e9920 4328 if (clauses == NULL)
4329 {
4330 /* If this was a workshare clause, see if it had been combined
4331 with its parallel. In that case, look for the clauses on the
4332 parallel statement itself. */
4333 if (is_parallel_ctx (ctx))
4334 return;
4335
4336 ctx = ctx->outer;
4337 if (ctx == NULL || !is_parallel_ctx (ctx))
4338 return;
4339
75a70cf9 4340 clauses = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
1e8e9920 4341 OMP_CLAUSE_LASTPRIVATE);
4342 if (clauses == NULL)
4343 return;
fd6481cf 4344 par_clauses = true;
1e8e9920 4345 }
4346
75a70cf9 4347 if (predicate)
4348 {
1a91d914 4349 gcond *stmt;
75a70cf9 4350 tree label_true, arm1, arm2;
4351
e60a6f7b 4352 label = create_artificial_label (UNKNOWN_LOCATION);
4353 label_true = create_artificial_label (UNKNOWN_LOCATION);
75a70cf9 4354 arm1 = TREE_OPERAND (predicate, 0);
4355 arm2 = TREE_OPERAND (predicate, 1);
4356 gimplify_expr (&arm1, stmt_list, NULL, is_gimple_val, fb_rvalue);
4357 gimplify_expr (&arm2, stmt_list, NULL, is_gimple_val, fb_rvalue);
4358 stmt = gimple_build_cond (TREE_CODE (predicate), arm1, arm2,
4359 label_true, label);
4360 gimple_seq_add_stmt (stmt_list, stmt);
4361 gimple_seq_add_stmt (stmt_list, gimple_build_label (label_true));
4362 }
1e8e9920 4363
3d483a94 4364 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
10c55644 4365 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
3d483a94 4366 {
4367 simduid = find_omp_clause (orig_clauses, OMP_CLAUSE__SIMDUID_);
4368 if (simduid)
4369 simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
4370 }
4371
fd6481cf 4372 for (c = clauses; c ;)
1e8e9920 4373 {
4374 tree var, new_var;
389dd41b 4375 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
1e8e9920 4376
3d483a94 4377 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
4378 || (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
4379 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c)))
fd6481cf 4380 {
4381 var = OMP_CLAUSE_DECL (c);
4382 new_var = lookup_decl (var, ctx);
1e8e9920 4383
3d483a94 4384 if (simduid && DECL_HAS_VALUE_EXPR_P (new_var))
4385 {
4386 tree val = DECL_VALUE_EXPR (new_var);
4387 if (TREE_CODE (val) == ARRAY_REF
4388 && VAR_P (TREE_OPERAND (val, 0))
4389 && lookup_attribute ("omp simd array",
4390 DECL_ATTRIBUTES (TREE_OPERAND (val,
4391 0))))
4392 {
4393 if (lastlane == NULL)
4394 {
f9e245b2 4395 lastlane = create_tmp_var (unsigned_type_node);
1a91d914 4396 gcall *g
3d483a94 4397 = gimple_build_call_internal (IFN_GOMP_SIMD_LAST_LANE,
4398 2, simduid,
4399 TREE_OPERAND (val, 1));
4400 gimple_call_set_lhs (g, lastlane);
4401 gimple_seq_add_stmt (stmt_list, g);
4402 }
4403 new_var = build4 (ARRAY_REF, TREE_TYPE (val),
4404 TREE_OPERAND (val, 0), lastlane,
4405 NULL_TREE, NULL_TREE);
4406 }
4407 }
4408
4409 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
4410 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
75a70cf9 4411 {
e3a19533 4412 lower_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
75a70cf9 4413 gimple_seq_add_seq (stmt_list,
4414 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c));
3d483a94 4415 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c) = NULL;
75a70cf9 4416 }
2b536a17 4417 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
4418 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
4419 {
4420 lower_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
4421 gimple_seq_add_seq (stmt_list,
4422 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c));
4423 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c) = NULL;
4424 }
1e8e9920 4425
fd6481cf 4426 x = build_outer_var_ref (var, ctx);
4427 if (is_reference (var))
182cf5a9 4428 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
fd6481cf 4429 x = lang_hooks.decls.omp_clause_assign_op (c, x, new_var);
75a70cf9 4430 gimplify_and_add (x, stmt_list);
fd6481cf 4431 }
4432 c = OMP_CLAUSE_CHAIN (c);
4433 if (c == NULL && !par_clauses)
4434 {
4435 /* If this was a workshare clause, see if it had been combined
4436 with its parallel. In that case, continue looking for the
4437 clauses also on the parallel statement itself. */
4438 if (is_parallel_ctx (ctx))
4439 break;
4440
4441 ctx = ctx->outer;
4442 if (ctx == NULL || !is_parallel_ctx (ctx))
4443 break;
4444
75a70cf9 4445 c = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
fd6481cf 4446 OMP_CLAUSE_LASTPRIVATE);
4447 par_clauses = true;
4448 }
1e8e9920 4449 }
4450
75a70cf9 4451 if (label)
4452 gimple_seq_add_stmt (stmt_list, gimple_build_label (label));
1e8e9920 4453}
4454
ca4c3545 4455static void
4456oacc_lower_reduction_var_helper (gimple_seq *stmt_seqp, omp_context *ctx,
4457 tree tid, tree var, tree new_var)
4458{
4459 /* The atomic add at the end of the sum creates unnecessary
4460 write contention on accelerators. To work around this,
4461 create an array to store the partial reductions. Later, in
4462 lower_omp_for (for openacc), the values of array will be
4463 combined. */
4464
4465 tree t = NULL_TREE, array, x;
4466 tree type = get_base_type (var);
42acab1c 4467 gimple *stmt;
ca4c3545 4468
4469 /* Now insert the partial reductions into the array. */
4470
4471 /* Find the reduction array. */
4472
4473 tree ptype = build_pointer_type (type);
4474
4475 t = lookup_oacc_reduction (oacc_get_reduction_array_id (var), ctx);
4476 t = build_receiver_ref (t, false, ctx->outer);
4477
4478 array = create_tmp_var (ptype);
4479 gimplify_assign (array, t, stmt_seqp);
4480
4481 tree ptr = create_tmp_var (TREE_TYPE (array));
4482
4483 /* Find the reduction array. */
4484
4485 /* testing a unary conversion. */
4486 tree offset = create_tmp_var (sizetype);
4487 gimplify_assign (offset, TYPE_SIZE_UNIT (type),
4488 stmt_seqp);
4489 t = create_tmp_var (sizetype);
4490 gimplify_assign (t, unshare_expr (fold_build1 (NOP_EXPR, sizetype, tid)),
4491 stmt_seqp);
4492 stmt = gimple_build_assign (offset, MULT_EXPR, offset, t);
4493 gimple_seq_add_stmt (stmt_seqp, stmt);
4494
4495 /* Offset expression. Does the POINTER_PLUS_EXPR take care
4496 of adding sizeof(var) to the array? */
4497 ptr = create_tmp_var (ptype);
4498 stmt = gimple_build_assign (unshare_expr (ptr), POINTER_PLUS_EXPR, array,
4499 offset);
4500 gimple_seq_add_stmt (stmt_seqp, stmt);
4501
4502 /* Move the local sum to gfc$sum[i]. */
4503 x = unshare_expr (build_simple_mem_ref (ptr));
4504 stmt = gimplify_assign (x, new_var, stmt_seqp);
4505}
773c5ba7 4506
1e8e9920 4507/* Generate code to implement the REDUCTION clauses. */
4508
4509static void
75a70cf9 4510lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp, omp_context *ctx)
1e8e9920 4511{
75a70cf9 4512 gimple_seq sub_seq = NULL;
42acab1c 4513 gimple *stmt;
ca4c3545 4514 tree x, c, tid = NULL_TREE;
1e8e9920 4515 int count = 0;
4516
3d483a94 4517 /* SIMD reductions are handled in lower_rec_input_clauses. */
4518 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
10c55644 4519 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
3d483a94 4520 return;
4521
1e8e9920 4522 /* First see if there is exactly one reduction clause. Use OMP_ATOMIC
4523 update in that case, otherwise use a lock. */
4524 for (c = clauses; c && count < 2; c = OMP_CLAUSE_CHAIN (c))
55d6e7cd 4525 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
1e8e9920 4526 {
4527 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4528 {
bc7bff74 4529 /* Never use OMP_ATOMIC for array reductions or UDRs. */
1e8e9920 4530 count = -1;
4531 break;
4532 }
4533 count++;
4534 }
4535
4536 if (count == 0)
4537 return;
4538
ca4c3545 4539 /* Initialize thread info for OpenACC. */
4540 if (is_gimple_omp_oacc (ctx->stmt))
4541 {
4542 /* Get the current thread id. */
4543 tree call = builtin_decl_explicit (BUILT_IN_GOACC_GET_THREAD_NUM);
4544 tid = create_tmp_var (TREE_TYPE (TREE_TYPE (call)));
42acab1c 4545 gimple *stmt = gimple_build_call (call, 0);
ca4c3545 4546 gimple_call_set_lhs (stmt, tid);
4547 gimple_seq_add_stmt (stmt_seqp, stmt);
4548 }
4549
1e8e9920 4550 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4551 {
4552 tree var, ref, new_var;
4553 enum tree_code code;
389dd41b 4554 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
1e8e9920 4555
55d6e7cd 4556 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
1e8e9920 4557 continue;
4558
4559 var = OMP_CLAUSE_DECL (c);
4560 new_var = lookup_decl (var, ctx);
4561 if (is_reference (var))
182cf5a9 4562 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
1e8e9920 4563 ref = build_outer_var_ref (var, ctx);
4564 code = OMP_CLAUSE_REDUCTION_CODE (c);
773c5ba7 4565
4566 /* reduction(-:var) sums up the partial results, so it acts
4567 identically to reduction(+:var). */
1e8e9920 4568 if (code == MINUS_EXPR)
4569 code = PLUS_EXPR;
4570
ca4c3545 4571 if (is_gimple_omp_oacc (ctx->stmt))
4572 {
4573 gcc_checking_assert (!OMP_CLAUSE_REDUCTION_PLACEHOLDER (c));
4574
4575 oacc_lower_reduction_var_helper (stmt_seqp, ctx, tid, var, new_var);
4576 }
4577 else if (count == 1)
1e8e9920 4578 {
389dd41b 4579 tree addr = build_fold_addr_expr_loc (clause_loc, ref);
1e8e9920 4580
4581 addr = save_expr (addr);
4582 ref = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (addr)), addr);
389dd41b 4583 x = fold_build2_loc (clause_loc, code, TREE_TYPE (ref), ref, new_var);
1e8e9920 4584 x = build2 (OMP_ATOMIC, void_type_node, addr, x);
75a70cf9 4585 gimplify_and_add (x, stmt_seqp);
1e8e9920 4586 return;
4587 }
ca4c3545 4588 else if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1e8e9920 4589 {
4590 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
4591
bc7bff74 4592 if (is_reference (var)
4593 && !useless_type_conversion_p (TREE_TYPE (placeholder),
4594 TREE_TYPE (ref)))
389dd41b 4595 ref = build_fold_addr_expr_loc (clause_loc, ref);
1e8e9920 4596 SET_DECL_VALUE_EXPR (placeholder, ref);
4597 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
e3a19533 4598 lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
75a70cf9 4599 gimple_seq_add_seq (&sub_seq, OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
4600 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
1e8e9920 4601 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
4602 }
4603 else
4604 {
4605 x = build2 (code, TREE_TYPE (ref), ref, new_var);
4606 ref = build_outer_var_ref (var, ctx);
75a70cf9 4607 gimplify_assign (ref, x, &sub_seq);
1e8e9920 4608 }
4609 }
4610
ca4c3545 4611 if (is_gimple_omp_oacc (ctx->stmt))
4612 return;
4613
b9a16870 4614 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START),
4615 0);
75a70cf9 4616 gimple_seq_add_stmt (stmt_seqp, stmt);
1e8e9920 4617
75a70cf9 4618 gimple_seq_add_seq (stmt_seqp, sub_seq);
1e8e9920 4619
b9a16870 4620 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END),
4621 0);
75a70cf9 4622 gimple_seq_add_stmt (stmt_seqp, stmt);
1e8e9920 4623}
4624
773c5ba7 4625
1e8e9920 4626/* Generate code to implement the COPYPRIVATE clauses. */
4627
4628static void
75a70cf9 4629lower_copyprivate_clauses (tree clauses, gimple_seq *slist, gimple_seq *rlist,
1e8e9920 4630 omp_context *ctx)
4631{
4632 tree c;
4633
4634 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4635 {
cb561506 4636 tree var, new_var, ref, x;
1e8e9920 4637 bool by_ref;
389dd41b 4638 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
1e8e9920 4639
55d6e7cd 4640 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYPRIVATE)
1e8e9920 4641 continue;
4642
4643 var = OMP_CLAUSE_DECL (c);
e8a588af 4644 by_ref = use_pointer_for_field (var, NULL);
1e8e9920 4645
4646 ref = build_sender_ref (var, ctx);
cb561506 4647 x = new_var = lookup_decl_in_outer_ctx (var, ctx);
4648 if (by_ref)
4649 {
4650 x = build_fold_addr_expr_loc (clause_loc, new_var);
4651 x = fold_convert_loc (clause_loc, TREE_TYPE (ref), x);
4652 }
75a70cf9 4653 gimplify_assign (ref, x, slist);
1e8e9920 4654
cb561506 4655 ref = build_receiver_ref (var, false, ctx);
4656 if (by_ref)
4657 {
4658 ref = fold_convert_loc (clause_loc,
4659 build_pointer_type (TREE_TYPE (new_var)),
4660 ref);
4661 ref = build_fold_indirect_ref_loc (clause_loc, ref);
4662 }
1e8e9920 4663 if (is_reference (var))
4664 {
cb561506 4665 ref = fold_convert_loc (clause_loc, TREE_TYPE (new_var), ref);
182cf5a9 4666 ref = build_simple_mem_ref_loc (clause_loc, ref);
4667 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
1e8e9920 4668 }
cb561506 4669 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, ref);
1e8e9920 4670 gimplify_and_add (x, rlist);
4671 }
4672}
4673
773c5ba7 4674
1e8e9920 4675/* Generate code to implement the clauses, FIRSTPRIVATE, COPYIN, LASTPRIVATE,
4676 and REDUCTION from the sender (aka parent) side. */
4677
4678static void
75a70cf9 4679lower_send_clauses (tree clauses, gimple_seq *ilist, gimple_seq *olist,
4680 omp_context *ctx)
1e8e9920 4681{
4682 tree c;
4683
4684 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4685 {
773c5ba7 4686 tree val, ref, x, var;
1e8e9920 4687 bool by_ref, do_in = false, do_out = false;
389dd41b 4688 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
1e8e9920 4689
55d6e7cd 4690 switch (OMP_CLAUSE_CODE (c))
1e8e9920 4691 {
fd6481cf 4692 case OMP_CLAUSE_PRIVATE:
4693 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
4694 break;
4695 continue;
1e8e9920 4696 case OMP_CLAUSE_FIRSTPRIVATE:
4697 case OMP_CLAUSE_COPYIN:
4698 case OMP_CLAUSE_LASTPRIVATE:
4699 case OMP_CLAUSE_REDUCTION:
bc7bff74 4700 case OMP_CLAUSE__LOOPTEMP_:
1e8e9920 4701 break;
4702 default:
4703 continue;
4704 }
4705
87b31375 4706 val = OMP_CLAUSE_DECL (c);
4707 var = lookup_decl_in_outer_ctx (val, ctx);
773c5ba7 4708
f49d7bb5 4709 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYIN
4710 && is_global_var (var))
4711 continue;
1e8e9920 4712 if (is_variable_sized (val))
4713 continue;
e8a588af 4714 by_ref = use_pointer_for_field (val, NULL);
1e8e9920 4715
55d6e7cd 4716 switch (OMP_CLAUSE_CODE (c))
1e8e9920 4717 {
fd6481cf 4718 case OMP_CLAUSE_PRIVATE:
1e8e9920 4719 case OMP_CLAUSE_FIRSTPRIVATE:
4720 case OMP_CLAUSE_COPYIN:
bc7bff74 4721 case OMP_CLAUSE__LOOPTEMP_:
1e8e9920 4722 do_in = true;
4723 break;
4724
4725 case OMP_CLAUSE_LASTPRIVATE:
4726 if (by_ref || is_reference (val))
4727 {
4728 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
4729 continue;
4730 do_in = true;
4731 }
4732 else
fd6481cf 4733 {
4734 do_out = true;
4735 if (lang_hooks.decls.omp_private_outer_ref (val))
4736 do_in = true;
4737 }
1e8e9920 4738 break;
4739
4740 case OMP_CLAUSE_REDUCTION:
4741 do_in = true;
4742 do_out = !(by_ref || is_reference (val));
4743 break;
4744
4745 default:
4746 gcc_unreachable ();
4747 }
4748
4749 if (do_in)
4750 {
4751 ref = build_sender_ref (val, ctx);
389dd41b 4752 x = by_ref ? build_fold_addr_expr_loc (clause_loc, var) : var;
75a70cf9 4753 gimplify_assign (ref, x, ilist);
fd6481cf 4754 if (is_task_ctx (ctx))
4755 DECL_ABSTRACT_ORIGIN (TREE_OPERAND (ref, 1)) = NULL;
1e8e9920 4756 }
773c5ba7 4757
1e8e9920 4758 if (do_out)
4759 {
4760 ref = build_sender_ref (val, ctx);
75a70cf9 4761 gimplify_assign (var, ref, olist);
1e8e9920 4762 }
4763 }
4764}
4765
75a70cf9 4766/* Generate code to implement SHARED from the sender (aka parent)
4767 side. This is trickier, since GIMPLE_OMP_PARALLEL_CLAUSES doesn't
4768 list things that got automatically shared. */
1e8e9920 4769
4770static void
75a70cf9 4771lower_send_shared_vars (gimple_seq *ilist, gimple_seq *olist, omp_context *ctx)
1e8e9920 4772{
fd6481cf 4773 tree var, ovar, nvar, f, x, record_type;
1e8e9920 4774
4775 if (ctx->record_type == NULL)
4776 return;
773c5ba7 4777
fd6481cf 4778 record_type = ctx->srecord_type ? ctx->srecord_type : ctx->record_type;
1767a056 4779 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
1e8e9920 4780 {
4781 ovar = DECL_ABSTRACT_ORIGIN (f);
4782 nvar = maybe_lookup_decl (ovar, ctx);
4783 if (!nvar || !DECL_HAS_VALUE_EXPR_P (nvar))
4784 continue;
4785
773c5ba7 4786 /* If CTX is a nested parallel directive. Find the immediately
4787 enclosing parallel or workshare construct that contains a
4788 mapping for OVAR. */
87b31375 4789 var = lookup_decl_in_outer_ctx (ovar, ctx);
773c5ba7 4790
e8a588af 4791 if (use_pointer_for_field (ovar, ctx))
1e8e9920 4792 {
4793 x = build_sender_ref (ovar, ctx);
773c5ba7 4794 var = build_fold_addr_expr (var);
75a70cf9 4795 gimplify_assign (x, var, ilist);
1e8e9920 4796 }
4797 else
4798 {
4799 x = build_sender_ref (ovar, ctx);
75a70cf9 4800 gimplify_assign (x, var, ilist);
1e8e9920 4801
d2263ebb 4802 if (!TREE_READONLY (var)
4803 /* We don't need to receive a new reference to a result
4804 or parm decl. In fact we may not store to it as we will
4805 invalidate any pending RSO and generate wrong gimple
4806 during inlining. */
4807 && !((TREE_CODE (var) == RESULT_DECL
4808 || TREE_CODE (var) == PARM_DECL)
4809 && DECL_BY_REFERENCE (var)))
fd6481cf 4810 {
4811 x = build_sender_ref (ovar, ctx);
75a70cf9 4812 gimplify_assign (var, x, olist);
fd6481cf 4813 }
1e8e9920 4814 }
4815 }
4816}
4817
75a70cf9 4818
4819/* A convenience function to build an empty GIMPLE_COND with just the
4820 condition. */
4821
1a91d914 4822static gcond *
75a70cf9 4823gimple_build_cond_empty (tree cond)
4824{
4825 enum tree_code pred_code;
4826 tree lhs, rhs;
4827
4828 gimple_cond_get_ops_from_tree (cond, &pred_code, &lhs, &rhs);
4829 return gimple_build_cond (pred_code, lhs, rhs, NULL_TREE, NULL_TREE);
4830}
4831
4832
48e1416a 4833/* Build the function calls to GOMP_parallel_start etc to actually
773c5ba7 4834 generate the parallel operation. REGION is the parallel region
4835 being expanded. BB is the block where to insert the code. WS_ARGS
4836 will be set if this is a call to a combined parallel+workshare
4837 construct, it contains the list of additional arguments needed by
4838 the workshare construct. */
1e8e9920 4839
4840static void
61e47ac8 4841expand_parallel_call (struct omp_region *region, basic_block bb,
1a91d914 4842 gomp_parallel *entry_stmt,
4843 vec<tree, va_gc> *ws_args)
1e8e9920 4844{
bc7bff74 4845 tree t, t1, t2, val, cond, c, clauses, flags;
75a70cf9 4846 gimple_stmt_iterator gsi;
42acab1c 4847 gimple *stmt;
b9a16870 4848 enum built_in_function start_ix;
4849 int start_ix2;
389dd41b 4850 location_t clause_loc;
f1f41a6c 4851 vec<tree, va_gc> *args;
773c5ba7 4852
75a70cf9 4853 clauses = gimple_omp_parallel_clauses (entry_stmt);
773c5ba7 4854
bc7bff74 4855 /* Determine what flavor of GOMP_parallel we will be
773c5ba7 4856 emitting. */
bc7bff74 4857 start_ix = BUILT_IN_GOMP_PARALLEL;
773c5ba7 4858 if (is_combined_parallel (region))
4859 {
61e47ac8 4860 switch (region->inner->type)
773c5ba7 4861 {
75a70cf9 4862 case GIMPLE_OMP_FOR:
fd6481cf 4863 gcc_assert (region->inner->sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
bc7bff74 4864 start_ix2 = ((int)BUILT_IN_GOMP_PARALLEL_LOOP_STATIC
b9a16870 4865 + (region->inner->sched_kind
4866 == OMP_CLAUSE_SCHEDULE_RUNTIME
4867 ? 3 : region->inner->sched_kind));
4868 start_ix = (enum built_in_function)start_ix2;
61e47ac8 4869 break;
75a70cf9 4870 case GIMPLE_OMP_SECTIONS:
bc7bff74 4871 start_ix = BUILT_IN_GOMP_PARALLEL_SECTIONS;
61e47ac8 4872 break;
4873 default:
4874 gcc_unreachable ();
773c5ba7 4875 }
773c5ba7 4876 }
1e8e9920 4877
4878 /* By default, the value of NUM_THREADS is zero (selected at run time)
4879 and there is no conditional. */
4880 cond = NULL_TREE;
4881 val = build_int_cst (unsigned_type_node, 0);
bc7bff74 4882 flags = build_int_cst (unsigned_type_node, 0);
1e8e9920 4883
4884 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
4885 if (c)
4886 cond = OMP_CLAUSE_IF_EXPR (c);
4887
4888 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_THREADS);
4889 if (c)
389dd41b 4890 {
4891 val = OMP_CLAUSE_NUM_THREADS_EXPR (c);
4892 clause_loc = OMP_CLAUSE_LOCATION (c);
4893 }
4894 else
4895 clause_loc = gimple_location (entry_stmt);
1e8e9920 4896
bc7bff74 4897 c = find_omp_clause (clauses, OMP_CLAUSE_PROC_BIND);
4898 if (c)
4899 flags = build_int_cst (unsigned_type_node, OMP_CLAUSE_PROC_BIND_KIND (c));
4900
1e8e9920 4901 /* Ensure 'val' is of the correct type. */
389dd41b 4902 val = fold_convert_loc (clause_loc, unsigned_type_node, val);
1e8e9920 4903
4904 /* If we found the clause 'if (cond)', build either
4905 (cond != 0) or (cond ? val : 1u). */
4906 if (cond)
4907 {
773c5ba7 4908 cond = gimple_boolify (cond);
4909
1e8e9920 4910 if (integer_zerop (val))
389dd41b 4911 val = fold_build2_loc (clause_loc,
4912 EQ_EXPR, unsigned_type_node, cond,
79acaae1 4913 build_int_cst (TREE_TYPE (cond), 0));
1e8e9920 4914 else
773c5ba7 4915 {
4916 basic_block cond_bb, then_bb, else_bb;
79acaae1 4917 edge e, e_then, e_else;
75a70cf9 4918 tree tmp_then, tmp_else, tmp_join, tmp_var;
79acaae1 4919
f9e245b2 4920 tmp_var = create_tmp_var (TREE_TYPE (val));
79acaae1 4921 if (gimple_in_ssa_p (cfun))
4922 {
f9e245b2 4923 tmp_then = make_ssa_name (tmp_var);
4924 tmp_else = make_ssa_name (tmp_var);
4925 tmp_join = make_ssa_name (tmp_var);
79acaae1 4926 }
4927 else
4928 {
4929 tmp_then = tmp_var;
4930 tmp_else = tmp_var;
4931 tmp_join = tmp_var;
4932 }
773c5ba7 4933
4302d619 4934 e = split_block_after_labels (bb);
773c5ba7 4935 cond_bb = e->src;
4936 bb = e->dest;
4937 remove_edge (e);
4938
4939 then_bb = create_empty_bb (cond_bb);
4940 else_bb = create_empty_bb (then_bb);
79acaae1 4941 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
4942 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
773c5ba7 4943
75a70cf9 4944 stmt = gimple_build_cond_empty (cond);
4945 gsi = gsi_start_bb (cond_bb);
4946 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
773c5ba7 4947
75a70cf9 4948 gsi = gsi_start_bb (then_bb);
4949 stmt = gimple_build_assign (tmp_then, val);
4950 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
773c5ba7 4951
75a70cf9 4952 gsi = gsi_start_bb (else_bb);
4953 stmt = gimple_build_assign
4954 (tmp_else, build_int_cst (unsigned_type_node, 1));
4955 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
773c5ba7 4956
4957 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
4958 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
b3083327 4959 add_bb_to_loop (then_bb, cond_bb->loop_father);
4960 add_bb_to_loop (else_bb, cond_bb->loop_father);
79acaae1 4961 e_then = make_edge (then_bb, bb, EDGE_FALLTHRU);
4962 e_else = make_edge (else_bb, bb, EDGE_FALLTHRU);
773c5ba7 4963
79acaae1 4964 if (gimple_in_ssa_p (cfun))
4965 {
1a91d914 4966 gphi *phi = create_phi_node (tmp_join, bb);
60d535d2 4967 add_phi_arg (phi, tmp_then, e_then, UNKNOWN_LOCATION);
4968 add_phi_arg (phi, tmp_else, e_else, UNKNOWN_LOCATION);
79acaae1 4969 }
4970
4971 val = tmp_join;
773c5ba7 4972 }
4973
75a70cf9 4974 gsi = gsi_start_bb (bb);
4975 val = force_gimple_operand_gsi (&gsi, val, true, NULL_TREE,
4976 false, GSI_CONTINUE_LINKING);
1e8e9920 4977 }
4978
75a70cf9 4979 gsi = gsi_last_bb (bb);
4980 t = gimple_omp_parallel_data_arg (entry_stmt);
1e8e9920 4981 if (t == NULL)
c2f47e15 4982 t1 = null_pointer_node;
1e8e9920 4983 else
c2f47e15 4984 t1 = build_fold_addr_expr (t);
75a70cf9 4985 t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
773c5ba7 4986
bc7bff74 4987 vec_alloc (args, 4 + vec_safe_length (ws_args));
f1f41a6c 4988 args->quick_push (t2);
4989 args->quick_push (t1);
4990 args->quick_push (val);
4991 if (ws_args)
4992 args->splice (*ws_args);
bc7bff74 4993 args->quick_push (flags);
414c3a2c 4994
4995 t = build_call_expr_loc_vec (UNKNOWN_LOCATION,
b9a16870 4996 builtin_decl_explicit (start_ix), args);
773c5ba7 4997
75a70cf9 4998 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
4999 false, GSI_CONTINUE_LINKING);
1e8e9920 5000}
5001
40750995 5002/* Insert a function call whose name is FUNC_NAME with the information from
5003 ENTRY_STMT into the basic_block BB. */
5004
5005static void
1a91d914 5006expand_cilk_for_call (basic_block bb, gomp_parallel *entry_stmt,
40750995 5007 vec <tree, va_gc> *ws_args)
5008{
5009 tree t, t1, t2;
5010 gimple_stmt_iterator gsi;
5011 vec <tree, va_gc> *args;
5012
5013 gcc_assert (vec_safe_length (ws_args) == 2);
5014 tree func_name = (*ws_args)[0];
5015 tree grain = (*ws_args)[1];
5016
5017 tree clauses = gimple_omp_parallel_clauses (entry_stmt);
5018 tree count = find_omp_clause (clauses, OMP_CLAUSE__CILK_FOR_COUNT_);
5019 gcc_assert (count != NULL_TREE);
5020 count = OMP_CLAUSE_OPERAND (count, 0);
5021
5022 gsi = gsi_last_bb (bb);
5023 t = gimple_omp_parallel_data_arg (entry_stmt);
5024 if (t == NULL)
5025 t1 = null_pointer_node;
5026 else
5027 t1 = build_fold_addr_expr (t);
5028 t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
5029
5030 vec_alloc (args, 4);
5031 args->quick_push (t2);
5032 args->quick_push (t1);
5033 args->quick_push (count);
5034 args->quick_push (grain);
5035 t = build_call_expr_loc_vec (UNKNOWN_LOCATION, func_name, args);
5036
5037 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, false,
5038 GSI_CONTINUE_LINKING);
5039}
773c5ba7 5040
fd6481cf 5041/* Build the function call to GOMP_task to actually
5042 generate the task operation. BB is the block where to insert the code. */
5043
5044static void
1a91d914 5045expand_task_call (basic_block bb, gomp_task *entry_stmt)
fd6481cf 5046{
bc7bff74 5047 tree t, t1, t2, t3, flags, cond, c, c2, clauses, depend;
75a70cf9 5048 gimple_stmt_iterator gsi;
389dd41b 5049 location_t loc = gimple_location (entry_stmt);
fd6481cf 5050
75a70cf9 5051 clauses = gimple_omp_task_clauses (entry_stmt);
fd6481cf 5052
fd6481cf 5053 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
5054 if (c)
5055 cond = gimple_boolify (OMP_CLAUSE_IF_EXPR (c));
5056 else
5057 cond = boolean_true_node;
5058
5059 c = find_omp_clause (clauses, OMP_CLAUSE_UNTIED);
2169f33b 5060 c2 = find_omp_clause (clauses, OMP_CLAUSE_MERGEABLE);
bc7bff74 5061 depend = find_omp_clause (clauses, OMP_CLAUSE_DEPEND);
2169f33b 5062 flags = build_int_cst (unsigned_type_node,
bc7bff74 5063 (c ? 1 : 0) + (c2 ? 4 : 0) + (depend ? 8 : 0));
2169f33b 5064
5065 c = find_omp_clause (clauses, OMP_CLAUSE_FINAL);
5066 if (c)
5067 {
5068 c = gimple_boolify (OMP_CLAUSE_FINAL_EXPR (c));
5069 c = fold_build3_loc (loc, COND_EXPR, unsigned_type_node, c,
5070 build_int_cst (unsigned_type_node, 2),
5071 build_int_cst (unsigned_type_node, 0));
5072 flags = fold_build2_loc (loc, PLUS_EXPR, unsigned_type_node, flags, c);
5073 }
bc7bff74 5074 if (depend)
5075 depend = OMP_CLAUSE_DECL (depend);
5076 else
5077 depend = build_int_cst (ptr_type_node, 0);
fd6481cf 5078
75a70cf9 5079 gsi = gsi_last_bb (bb);
5080 t = gimple_omp_task_data_arg (entry_stmt);
fd6481cf 5081 if (t == NULL)
5082 t2 = null_pointer_node;
5083 else
389dd41b 5084 t2 = build_fold_addr_expr_loc (loc, t);
5085 t1 = build_fold_addr_expr_loc (loc, gimple_omp_task_child_fn (entry_stmt));
75a70cf9 5086 t = gimple_omp_task_copy_fn (entry_stmt);
fd6481cf 5087 if (t == NULL)
5088 t3 = null_pointer_node;
5089 else
389dd41b 5090 t3 = build_fold_addr_expr_loc (loc, t);
fd6481cf 5091
b9a16870 5092 t = build_call_expr (builtin_decl_explicit (BUILT_IN_GOMP_TASK),
bc7bff74 5093 8, t1, t2, t3,
75a70cf9 5094 gimple_omp_task_arg_size (entry_stmt),
bc7bff74 5095 gimple_omp_task_arg_align (entry_stmt), cond, flags,
5096 depend);
fd6481cf 5097
75a70cf9 5098 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5099 false, GSI_CONTINUE_LINKING);
fd6481cf 5100}
5101
5102
75a70cf9 5103/* If exceptions are enabled, wrap the statements in BODY in a MUST_NOT_THROW
5104 catch handler and return it. This prevents programs from violating the
5105 structured block semantics with throws. */
1e8e9920 5106
75a70cf9 5107static gimple_seq
5108maybe_catch_exception (gimple_seq body)
1e8e9920 5109{
42acab1c 5110 gimple *g;
e38def9c 5111 tree decl;
1e8e9920 5112
5113 if (!flag_exceptions)
75a70cf9 5114 return body;
1e8e9920 5115
596981c8 5116 if (lang_hooks.eh_protect_cleanup_actions != NULL)
5117 decl = lang_hooks.eh_protect_cleanup_actions ();
1e8e9920 5118 else
b9a16870 5119 decl = builtin_decl_explicit (BUILT_IN_TRAP);
75a70cf9 5120
e38def9c 5121 g = gimple_build_eh_must_not_throw (decl);
5122 g = gimple_build_try (body, gimple_seq_alloc_with_stmt (g),
75a70cf9 5123 GIMPLE_TRY_CATCH);
1e8e9920 5124
e38def9c 5125 return gimple_seq_alloc_with_stmt (g);
1e8e9920 5126}
5127
773c5ba7 5128/* Chain all the DECLs in LIST by their TREE_CHAIN fields. */
1e8e9920 5129
773c5ba7 5130static tree
f1f41a6c 5131vec2chain (vec<tree, va_gc> *v)
1e8e9920 5132{
2ab2ce89 5133 tree chain = NULL_TREE, t;
5134 unsigned ix;
1e8e9920 5135
f1f41a6c 5136 FOR_EACH_VEC_SAFE_ELT_REVERSE (v, ix, t)
773c5ba7 5137 {
1767a056 5138 DECL_CHAIN (t) = chain;
2ab2ce89 5139 chain = t;
773c5ba7 5140 }
1e8e9920 5141
2ab2ce89 5142 return chain;
773c5ba7 5143}
1e8e9920 5144
1e8e9920 5145
773c5ba7 5146/* Remove barriers in REGION->EXIT's block. Note that this is only
75a70cf9 5147 valid for GIMPLE_OMP_PARALLEL regions. Since the end of a parallel region
5148 is an implicit barrier, any workshare inside the GIMPLE_OMP_PARALLEL that
5149 left a barrier at the end of the GIMPLE_OMP_PARALLEL region can now be
773c5ba7 5150 removed. */
1e8e9920 5151
773c5ba7 5152static void
5153remove_exit_barrier (struct omp_region *region)
5154{
75a70cf9 5155 gimple_stmt_iterator gsi;
773c5ba7 5156 basic_block exit_bb;
61e47ac8 5157 edge_iterator ei;
5158 edge e;
42acab1c 5159 gimple *stmt;
4a04f4b4 5160 int any_addressable_vars = -1;
1e8e9920 5161
61e47ac8 5162 exit_bb = region->exit;
1e8e9920 5163
5056ba1a 5164 /* If the parallel region doesn't return, we don't have REGION->EXIT
5165 block at all. */
5166 if (! exit_bb)
5167 return;
5168
75a70cf9 5169 /* The last insn in the block will be the parallel's GIMPLE_OMP_RETURN. The
5170 workshare's GIMPLE_OMP_RETURN will be in a preceding block. The kinds of
61e47ac8 5171 statements that can appear in between are extremely limited -- no
5172 memory operations at all. Here, we allow nothing at all, so the
75a70cf9 5173 only thing we allow to precede this GIMPLE_OMP_RETURN is a label. */
5174 gsi = gsi_last_bb (exit_bb);
5175 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
5176 gsi_prev (&gsi);
5177 if (!gsi_end_p (gsi) && gimple_code (gsi_stmt (gsi)) != GIMPLE_LABEL)
773c5ba7 5178 return;
1e8e9920 5179
61e47ac8 5180 FOR_EACH_EDGE (e, ei, exit_bb->preds)
5181 {
75a70cf9 5182 gsi = gsi_last_bb (e->src);
5183 if (gsi_end_p (gsi))
61e47ac8 5184 continue;
75a70cf9 5185 stmt = gsi_stmt (gsi);
4a04f4b4 5186 if (gimple_code (stmt) == GIMPLE_OMP_RETURN
5187 && !gimple_omp_return_nowait_p (stmt))
5188 {
5189 /* OpenMP 3.0 tasks unfortunately prevent this optimization
5190 in many cases. If there could be tasks queued, the barrier
5191 might be needed to let the tasks run before some local
5192 variable of the parallel that the task uses as shared
5193 runs out of scope. The task can be spawned either
5194 from within current function (this would be easy to check)
5195 or from some function it calls and gets passed an address
5196 of such a variable. */
5197 if (any_addressable_vars < 0)
5198 {
1a91d914 5199 gomp_parallel *parallel_stmt
5200 = as_a <gomp_parallel *> (last_stmt (region->entry));
4a04f4b4 5201 tree child_fun = gimple_omp_parallel_child_fn (parallel_stmt);
2ab2ce89 5202 tree local_decls, block, decl;
5203 unsigned ix;
4a04f4b4 5204
5205 any_addressable_vars = 0;
2ab2ce89 5206 FOR_EACH_LOCAL_DECL (DECL_STRUCT_FUNCTION (child_fun), ix, decl)
5207 if (TREE_ADDRESSABLE (decl))
4a04f4b4 5208 {
5209 any_addressable_vars = 1;
5210 break;
5211 }
5212 for (block = gimple_block (stmt);
5213 !any_addressable_vars
5214 && block
5215 && TREE_CODE (block) == BLOCK;
5216 block = BLOCK_SUPERCONTEXT (block))
5217 {
5218 for (local_decls = BLOCK_VARS (block);
5219 local_decls;
1767a056 5220 local_decls = DECL_CHAIN (local_decls))
4a04f4b4 5221 if (TREE_ADDRESSABLE (local_decls))
5222 {
5223 any_addressable_vars = 1;
5224 break;
5225 }
5226 if (block == gimple_block (parallel_stmt))
5227 break;
5228 }
5229 }
5230 if (!any_addressable_vars)
5231 gimple_omp_return_set_nowait (stmt);
5232 }
61e47ac8 5233 }
1e8e9920 5234}
5235
61e47ac8 5236static void
5237remove_exit_barriers (struct omp_region *region)
5238{
75a70cf9 5239 if (region->type == GIMPLE_OMP_PARALLEL)
61e47ac8 5240 remove_exit_barrier (region);
5241
5242 if (region->inner)
5243 {
5244 region = region->inner;
5245 remove_exit_barriers (region);
5246 while (region->next)
5247 {
5248 region = region->next;
5249 remove_exit_barriers (region);
5250 }
5251 }
5252}
773c5ba7 5253
658b4427 5254/* Optimize omp_get_thread_num () and omp_get_num_threads ()
5255 calls. These can't be declared as const functions, but
5256 within one parallel body they are constant, so they can be
5257 transformed there into __builtin_omp_get_{thread_num,num_threads} ()
fd6481cf 5258 which are declared const. Similarly for task body, except
5259 that in untied task omp_get_thread_num () can change at any task
5260 scheduling point. */
658b4427 5261
5262static void
42acab1c 5263optimize_omp_library_calls (gimple *entry_stmt)
658b4427 5264{
5265 basic_block bb;
75a70cf9 5266 gimple_stmt_iterator gsi;
b9a16870 5267 tree thr_num_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
5268 tree thr_num_id = DECL_ASSEMBLER_NAME (thr_num_tree);
5269 tree num_thr_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
5270 tree num_thr_id = DECL_ASSEMBLER_NAME (num_thr_tree);
75a70cf9 5271 bool untied_task = (gimple_code (entry_stmt) == GIMPLE_OMP_TASK
5272 && find_omp_clause (gimple_omp_task_clauses (entry_stmt),
fd6481cf 5273 OMP_CLAUSE_UNTIED) != NULL);
658b4427 5274
fc00614f 5275 FOR_EACH_BB_FN (bb, cfun)
75a70cf9 5276 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
658b4427 5277 {
42acab1c 5278 gimple *call = gsi_stmt (gsi);
658b4427 5279 tree decl;
5280
75a70cf9 5281 if (is_gimple_call (call)
5282 && (decl = gimple_call_fndecl (call))
658b4427 5283 && DECL_EXTERNAL (decl)
5284 && TREE_PUBLIC (decl)
5285 && DECL_INITIAL (decl) == NULL)
5286 {
5287 tree built_in;
5288
5289 if (DECL_NAME (decl) == thr_num_id)
fd6481cf 5290 {
5291 /* In #pragma omp task untied omp_get_thread_num () can change
5292 during the execution of the task region. */
5293 if (untied_task)
5294 continue;
b9a16870 5295 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
fd6481cf 5296 }
658b4427 5297 else if (DECL_NAME (decl) == num_thr_id)
b9a16870 5298 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
658b4427 5299 else
5300 continue;
5301
5302 if (DECL_ASSEMBLER_NAME (decl) != DECL_ASSEMBLER_NAME (built_in)
75a70cf9 5303 || gimple_call_num_args (call) != 0)
658b4427 5304 continue;
5305
5306 if (flag_exceptions && !TREE_NOTHROW (decl))
5307 continue;
5308
5309 if (TREE_CODE (TREE_TYPE (decl)) != FUNCTION_TYPE
1ea6a73c 5310 || !types_compatible_p (TREE_TYPE (TREE_TYPE (decl)),
5311 TREE_TYPE (TREE_TYPE (built_in))))
658b4427 5312 continue;
5313
0acacf9e 5314 gimple_call_set_fndecl (call, built_in);
658b4427 5315 }
5316 }
5317}
5318
8e6b4515 5319/* Callback for expand_omp_build_assign. Return non-NULL if *tp needs to be
5320 regimplified. */
5321
5322static tree
5323expand_omp_regimplify_p (tree *tp, int *walk_subtrees, void *)
5324{
5325 tree t = *tp;
5326
5327 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
5328 if (TREE_CODE (t) == VAR_DECL && DECL_HAS_VALUE_EXPR_P (t))
5329 return t;
5330
5331 if (TREE_CODE (t) == ADDR_EXPR)
5332 recompute_tree_invariant_for_addr_expr (t);
5333
5334 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
5335 return NULL_TREE;
5336}
5337
3d483a94 5338/* Prepend TO = FROM assignment before *GSI_P. */
5339
5340static void
5341expand_omp_build_assign (gimple_stmt_iterator *gsi_p, tree to, tree from)
5342{
5343 bool simple_p = DECL_P (to) && TREE_ADDRESSABLE (to);
5344 from = force_gimple_operand_gsi (gsi_p, from, simple_p, NULL_TREE,
5345 true, GSI_SAME_STMT);
42acab1c 5346 gimple *stmt = gimple_build_assign (to, from);
3d483a94 5347 gsi_insert_before (gsi_p, stmt, GSI_SAME_STMT);
5348 if (walk_tree (&from, expand_omp_regimplify_p, NULL, NULL)
5349 || walk_tree (&to, expand_omp_regimplify_p, NULL, NULL))
5350 {
5351 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
5352 gimple_regimplify_operands (stmt, &gsi);
5353 }
5354}
5355
fd6481cf 5356/* Expand the OpenMP parallel or task directive starting at REGION. */
1e8e9920 5357
5358static void
fd6481cf 5359expand_omp_taskreg (struct omp_region *region)
1e8e9920 5360{
773c5ba7 5361 basic_block entry_bb, exit_bb, new_bb;
87d4aa85 5362 struct function *child_cfun;
414c3a2c 5363 tree child_fn, block, t;
75a70cf9 5364 gimple_stmt_iterator gsi;
42acab1c 5365 gimple *entry_stmt, *stmt;
773c5ba7 5366 edge e;
f1f41a6c 5367 vec<tree, va_gc> *ws_args;
773c5ba7 5368
61e47ac8 5369 entry_stmt = last_stmt (region->entry);
75a70cf9 5370 child_fn = gimple_omp_taskreg_child_fn (entry_stmt);
773c5ba7 5371 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
773c5ba7 5372
61e47ac8 5373 entry_bb = region->entry;
b25f70fd 5374 if (gimple_code (entry_stmt) == GIMPLE_OMP_TASK)
5375 exit_bb = region->cont;
5376 else
5377 exit_bb = region->exit;
773c5ba7 5378
40750995 5379 bool is_cilk_for
5380 = (flag_cilkplus
5381 && gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL
5382 && find_omp_clause (gimple_omp_parallel_clauses (entry_stmt),
5383 OMP_CLAUSE__CILK_FOR_COUNT_) != NULL_TREE);
5384
5385 if (is_cilk_for)
5386 /* If it is a _Cilk_for statement, it is modelled *like* a parallel for,
5387 and the inner statement contains the name of the built-in function
5388 and grain. */
5389 ws_args = region->inner->ws_args;
5390 else if (is_combined_parallel (region))
61e47ac8 5391 ws_args = region->ws_args;
773c5ba7 5392 else
414c3a2c 5393 ws_args = NULL;
1e8e9920 5394
61e47ac8 5395 if (child_cfun->cfg)
1e8e9920 5396 {
773c5ba7 5397 /* Due to inlining, it may happen that we have already outlined
5398 the region, in which case all we need to do is make the
5399 sub-graph unreachable and emit the parallel call. */
5400 edge entry_succ_e, exit_succ_e;
773c5ba7 5401
5402 entry_succ_e = single_succ_edge (entry_bb);
773c5ba7 5403
75a70cf9 5404 gsi = gsi_last_bb (entry_bb);
5405 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_PARALLEL
5406 || gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_TASK);
5407 gsi_remove (&gsi, true);
773c5ba7 5408
5409 new_bb = entry_bb;
03ed154b 5410 if (exit_bb)
5411 {
5412 exit_succ_e = single_succ_edge (exit_bb);
5413 make_edge (new_bb, exit_succ_e->dest, EDGE_FALLTHRU);
5414 }
79acaae1 5415 remove_edge_and_dominated_blocks (entry_succ_e);
1e8e9920 5416 }
773c5ba7 5417 else
5418 {
501bdd19 5419 unsigned srcidx, dstidx, num;
2ab2ce89 5420
773c5ba7 5421 /* If the parallel region needs data sent from the parent
3480139d 5422 function, then the very first statement (except possible
5423 tree profile counter updates) of the parallel body
773c5ba7 5424 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
5425 &.OMP_DATA_O is passed as an argument to the child function,
5426 we need to replace it with the argument as seen by the child
5427 function.
5428
5429 In most cases, this will end up being the identity assignment
5430 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
5431 a function call that has been inlined, the original PARM_DECL
5432 .OMP_DATA_I may have been converted into a different local
5433 variable. In which case, we need to keep the assignment. */
75a70cf9 5434 if (gimple_omp_taskreg_data_arg (entry_stmt))
773c5ba7 5435 {
b25f70fd 5436 basic_block entry_succ_bb
5437 = single_succ_p (entry_bb) ? single_succ (entry_bb)
5438 : FALLTHRU_EDGE (entry_bb)->dest;
883f001d 5439 tree arg;
42acab1c 5440 gimple *parcopy_stmt = NULL;
1e8e9920 5441
75a70cf9 5442 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
3480139d 5443 {
42acab1c 5444 gimple *stmt;
3480139d 5445
75a70cf9 5446 gcc_assert (!gsi_end_p (gsi));
5447 stmt = gsi_stmt (gsi);
5448 if (gimple_code (stmt) != GIMPLE_ASSIGN)
cc6b725b 5449 continue;
5450
75a70cf9 5451 if (gimple_num_ops (stmt) == 2)
3480139d 5452 {
75a70cf9 5453 tree arg = gimple_assign_rhs1 (stmt);
5454
5455 /* We're ignore the subcode because we're
5456 effectively doing a STRIP_NOPS. */
5457
5458 if (TREE_CODE (arg) == ADDR_EXPR
5459 && TREE_OPERAND (arg, 0)
5460 == gimple_omp_taskreg_data_arg (entry_stmt))
5461 {
5462 parcopy_stmt = stmt;
5463 break;
5464 }
3480139d 5465 }
5466 }
79acaae1 5467
75a70cf9 5468 gcc_assert (parcopy_stmt != NULL);
79acaae1 5469 arg = DECL_ARGUMENTS (child_fn);
5470
5471 if (!gimple_in_ssa_p (cfun))
5472 {
75a70cf9 5473 if (gimple_assign_lhs (parcopy_stmt) == arg)
5474 gsi_remove (&gsi, true);
79acaae1 5475 else
75a70cf9 5476 {
5477 /* ?? Is setting the subcode really necessary ?? */
5478 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (arg));
5479 gimple_assign_set_rhs1 (parcopy_stmt, arg);
5480 }
79acaae1 5481 }
5482 else
5483 {
883f001d 5484 tree lhs = gimple_assign_lhs (parcopy_stmt);
5485 gcc_assert (SSA_NAME_VAR (lhs) == arg);
5486 /* We'd like to set the rhs to the default def in the child_fn,
5487 but it's too early to create ssa names in the child_fn.
5488 Instead, we set the rhs to the parm. In
5489 move_sese_region_to_fn, we introduce a default def for the
5490 parm, map the parm to it's default def, and once we encounter
5491 this stmt, replace the parm with the default def. */
5492 gimple_assign_set_rhs1 (parcopy_stmt, arg);
79acaae1 5493 update_stmt (parcopy_stmt);
5494 }
773c5ba7 5495 }
5496
5497 /* Declare local variables needed in CHILD_CFUN. */
5498 block = DECL_INITIAL (child_fn);
2ab2ce89 5499 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
e1a7ccb9 5500 /* The gimplifier could record temporaries in parallel/task block
5501 rather than in containing function's local_decls chain,
5502 which would mean cgraph missed finalizing them. Do it now. */
1767a056 5503 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
e1a7ccb9 5504 if (TREE_CODE (t) == VAR_DECL
5505 && TREE_STATIC (t)
5506 && !DECL_EXTERNAL (t))
97221fd7 5507 varpool_node::finalize_decl (t);
75a70cf9 5508 DECL_SAVED_TREE (child_fn) = NULL;
e3a19533 5509 /* We'll create a CFG for child_fn, so no gimple body is needed. */
5510 gimple_set_body (child_fn, NULL);
1d22f541 5511 TREE_USED (block) = 1;
773c5ba7 5512
79acaae1 5513 /* Reset DECL_CONTEXT on function arguments. */
1767a056 5514 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
773c5ba7 5515 DECL_CONTEXT (t) = child_fn;
5516
75a70cf9 5517 /* Split ENTRY_BB at GIMPLE_OMP_PARALLEL or GIMPLE_OMP_TASK,
5518 so that it can be moved to the child function. */
5519 gsi = gsi_last_bb (entry_bb);
5520 stmt = gsi_stmt (gsi);
5521 gcc_assert (stmt && (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
5522 || gimple_code (stmt) == GIMPLE_OMP_TASK));
75a70cf9 5523 e = split_block (entry_bb, stmt);
923635e7 5524 gsi_remove (&gsi, true);
773c5ba7 5525 entry_bb = e->dest;
b25f70fd 5526 edge e2 = NULL;
5527 if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
5528 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
5529 else
5530 {
5531 e2 = make_edge (e->src, BRANCH_EDGE (entry_bb)->dest, EDGE_ABNORMAL);
5532 gcc_assert (e2->dest == region->exit);
5533 remove_edge (BRANCH_EDGE (entry_bb));
5534 set_immediate_dominator (CDI_DOMINATORS, e2->dest, e->src);
5535 gsi = gsi_last_bb (region->exit);
5536 gcc_assert (!gsi_end_p (gsi)
5537 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
5538 gsi_remove (&gsi, true);
5539 }
773c5ba7 5540
b25f70fd 5541 /* Convert GIMPLE_OMP_{RETURN,CONTINUE} into a RETURN_EXPR. */
5056ba1a 5542 if (exit_bb)
5543 {
75a70cf9 5544 gsi = gsi_last_bb (exit_bb);
5545 gcc_assert (!gsi_end_p (gsi)
b25f70fd 5546 && (gimple_code (gsi_stmt (gsi))
5547 == (e2 ? GIMPLE_OMP_CONTINUE : GIMPLE_OMP_RETURN)));
75a70cf9 5548 stmt = gimple_build_return (NULL);
5549 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
5550 gsi_remove (&gsi, true);
5056ba1a 5551 }
79acaae1 5552
5553 /* Move the parallel region into CHILD_CFUN. */
48e1416a 5554
79acaae1 5555 if (gimple_in_ssa_p (cfun))
5556 {
bcaa2770 5557 init_tree_ssa (child_cfun);
5084b2e4 5558 init_ssa_operands (child_cfun);
5559 child_cfun->gimple_df->in_ssa_p = true;
1d22f541 5560 block = NULL_TREE;
79acaae1 5561 }
1d22f541 5562 else
75a70cf9 5563 block = gimple_block (entry_stmt);
1d22f541 5564
5565 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
79acaae1 5566 if (exit_bb)
5567 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
b25f70fd 5568 if (e2)
5569 {
5570 basic_block dest_bb = e2->dest;
5571 if (!exit_bb)
5572 make_edge (new_bb, dest_bb, EDGE_FALLTHRU);
5573 remove_edge (e2);
5574 set_immediate_dominator (CDI_DOMINATORS, dest_bb, new_bb);
5575 }
04c2922b 5576 /* When the OMP expansion process cannot guarantee an up-to-date
5577 loop tree arrange for the child function to fixup loops. */
5578 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
5579 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
79acaae1 5580
1d22f541 5581 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
f1f41a6c 5582 num = vec_safe_length (child_cfun->local_decls);
501bdd19 5583 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
5584 {
f1f41a6c 5585 t = (*child_cfun->local_decls)[srcidx];
501bdd19 5586 if (DECL_CONTEXT (t) == cfun->decl)
5587 continue;
5588 if (srcidx != dstidx)
f1f41a6c 5589 (*child_cfun->local_decls)[dstidx] = t;
501bdd19 5590 dstidx++;
5591 }
5592 if (dstidx != num)
f1f41a6c 5593 vec_safe_truncate (child_cfun->local_decls, dstidx);
1d22f541 5594
79acaae1 5595 /* Inform the callgraph about the new function. */
9918db44 5596 child_cfun->curr_properties = cfun->curr_properties;
5597 child_cfun->has_simduid_loops |= cfun->has_simduid_loops;
5598 child_cfun->has_force_vectorize_loops |= cfun->has_force_vectorize_loops;
47300487 5599 cgraph_node *node = cgraph_node::get_create (child_fn);
5600 node->parallelized_function = 1;
415d1b9a 5601 cgraph_node::add_new_function (child_fn, true);
79acaae1 5602
5603 /* Fix the callgraph edges for child_cfun. Those for cfun will be
5604 fixed in a following pass. */
5605 push_cfun (child_cfun);
658b4427 5606 if (optimize)
fd6481cf 5607 optimize_omp_library_calls (entry_stmt);
35ee1c66 5608 cgraph_edge::rebuild_edges ();
fbe86b1b 5609
5610 /* Some EH regions might become dead, see PR34608. If
5611 pass_cleanup_cfg isn't the first pass to happen with the
5612 new child, these dead EH edges might cause problems.
5613 Clean them up now. */
5614 if (flag_exceptions)
5615 {
5616 basic_block bb;
fbe86b1b 5617 bool changed = false;
5618
fc00614f 5619 FOR_EACH_BB_FN (bb, cfun)
75a70cf9 5620 changed |= gimple_purge_dead_eh_edges (bb);
fbe86b1b 5621 if (changed)
5622 cleanup_tree_cfg ();
fbe86b1b 5623 }
dd277d48 5624 if (gimple_in_ssa_p (cfun))
5625 update_ssa (TODO_update_ssa);
86a932e0 5626#ifdef ENABLE_CHECKING
5627 if (!loops_state_satisfies_p (LOOPS_NEED_FIXUP))
5628 verify_loop_structure ();
5629#endif
79acaae1 5630 pop_cfun ();
773c5ba7 5631 }
48e1416a 5632
773c5ba7 5633 /* Emit a library call to launch the children threads. */
40750995 5634 if (is_cilk_for)
1a91d914 5635 expand_cilk_for_call (new_bb,
5636 as_a <gomp_parallel *> (entry_stmt), ws_args);
40750995 5637 else if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
1a91d914 5638 expand_parallel_call (region, new_bb,
5639 as_a <gomp_parallel *> (entry_stmt), ws_args);
fd6481cf 5640 else
1a91d914 5641 expand_task_call (new_bb, as_a <gomp_task *> (entry_stmt));
083152fb 5642 if (gimple_in_ssa_p (cfun))
5643 update_ssa (TODO_update_ssa_only_virtuals);
1e8e9920 5644}
5645
773c5ba7 5646
3d483a94 5647/* Helper function for expand_omp_{for_*,simd}. If this is the outermost
5648 of the combined collapse > 1 loop constructs, generate code like:
5649 if (__builtin_expect (N32 cond3 N31, 0)) goto ZERO_ITER_BB;
5650 if (cond3 is <)
5651 adj = STEP3 - 1;
5652 else
5653 adj = STEP3 + 1;
5654 count3 = (adj + N32 - N31) / STEP3;
5655 if (__builtin_expect (N22 cond2 N21, 0)) goto ZERO_ITER_BB;
5656 if (cond2 is <)
5657 adj = STEP2 - 1;
5658 else
5659 adj = STEP2 + 1;
5660 count2 = (adj + N22 - N21) / STEP2;
5661 if (__builtin_expect (N12 cond1 N11, 0)) goto ZERO_ITER_BB;
5662 if (cond1 is <)
5663 adj = STEP1 - 1;
5664 else
5665 adj = STEP1 + 1;
5666 count1 = (adj + N12 - N11) / STEP1;
5667 count = count1 * count2 * count3;
5668 Furthermore, if ZERO_ITER_BB is NULL, create a BB which does:
5669 count = 0;
bc7bff74 5670 and set ZERO_ITER_BB to that bb. If this isn't the outermost
5671 of the combined loop constructs, just initialize COUNTS array
5672 from the _looptemp_ clauses. */
3d483a94 5673
5674/* NOTE: It *could* be better to moosh all of the BBs together,
5675 creating one larger BB with all the computation and the unexpected
5676 jump at the end. I.e.
5677
5678 bool zero3, zero2, zero1, zero;
5679
5680 zero3 = N32 c3 N31;
5681 count3 = (N32 - N31) /[cl] STEP3;
5682 zero2 = N22 c2 N21;
5683 count2 = (N22 - N21) /[cl] STEP2;
5684 zero1 = N12 c1 N11;
5685 count1 = (N12 - N11) /[cl] STEP1;
5686 zero = zero3 || zero2 || zero1;
5687 count = count1 * count2 * count3;
5688 if (__builtin_expect(zero, false)) goto zero_iter_bb;
5689
5690 After all, we expect the zero=false, and thus we expect to have to
5691 evaluate all of the comparison expressions, so short-circuiting
5692 oughtn't be a win. Since the condition isn't protecting a
5693 denominator, we're not concerned about divide-by-zero, so we can
5694 fully evaluate count even if a numerator turned out to be wrong.
5695
5696 It seems like putting this all together would create much better
5697 scheduling opportunities, and less pressure on the chip's branch
5698 predictor. */
5699
5700static void
5701expand_omp_for_init_counts (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
5702 basic_block &entry_bb, tree *counts,
5703 basic_block &zero_iter_bb, int &first_zero_iter,
5704 basic_block &l2_dom_bb)
5705{
5706 tree t, type = TREE_TYPE (fd->loop.v);
3d483a94 5707 edge e, ne;
5708 int i;
5709
5710 /* Collapsed loops need work for expansion into SSA form. */
5711 gcc_assert (!gimple_in_ssa_p (cfun));
5712
bc7bff74 5713 if (gimple_omp_for_combined_into_p (fd->for_stmt)
5714 && TREE_CODE (fd->loop.n2) != INTEGER_CST)
5715 {
5716 /* First two _looptemp_ clauses are for istart/iend, counts[0]
5717 isn't supposed to be handled, as the inner loop doesn't
5718 use it. */
5719 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
5720 OMP_CLAUSE__LOOPTEMP_);
5721 gcc_assert (innerc);
5722 for (i = 0; i < fd->collapse; i++)
5723 {
5724 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5725 OMP_CLAUSE__LOOPTEMP_);
5726 gcc_assert (innerc);
5727 if (i)
5728 counts[i] = OMP_CLAUSE_DECL (innerc);
5729 else
5730 counts[0] = NULL_TREE;
5731 }
5732 return;
5733 }
5734
3d483a94 5735 for (i = 0; i < fd->collapse; i++)
5736 {
5737 tree itype = TREE_TYPE (fd->loops[i].v);
5738
5739 if (SSA_VAR_P (fd->loop.n2)
5740 && ((t = fold_binary (fd->loops[i].cond_code, boolean_type_node,
5741 fold_convert (itype, fd->loops[i].n1),
5742 fold_convert (itype, fd->loops[i].n2)))
5743 == NULL_TREE || !integer_onep (t)))
5744 {
1a91d914 5745 gcond *cond_stmt;
3d483a94 5746 tree n1, n2;
5747 n1 = fold_convert (itype, unshare_expr (fd->loops[i].n1));
5748 n1 = force_gimple_operand_gsi (gsi, n1, true, NULL_TREE,
5749 true, GSI_SAME_STMT);
5750 n2 = fold_convert (itype, unshare_expr (fd->loops[i].n2));
5751 n2 = force_gimple_operand_gsi (gsi, n2, true, NULL_TREE,
5752 true, GSI_SAME_STMT);
1a91d914 5753 cond_stmt = gimple_build_cond (fd->loops[i].cond_code, n1, n2,
5754 NULL_TREE, NULL_TREE);
5755 gsi_insert_before (gsi, cond_stmt, GSI_SAME_STMT);
5756 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
3d483a94 5757 expand_omp_regimplify_p, NULL, NULL)
1a91d914 5758 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
3d483a94 5759 expand_omp_regimplify_p, NULL, NULL))
5760 {
1a91d914 5761 *gsi = gsi_for_stmt (cond_stmt);
5762 gimple_regimplify_operands (cond_stmt, gsi);
3d483a94 5763 }
1a91d914 5764 e = split_block (entry_bb, cond_stmt);
3d483a94 5765 if (zero_iter_bb == NULL)
5766 {
1a91d914 5767 gassign *assign_stmt;
3d483a94 5768 first_zero_iter = i;
5769 zero_iter_bb = create_empty_bb (entry_bb);
b3083327 5770 add_bb_to_loop (zero_iter_bb, entry_bb->loop_father);
3d483a94 5771 *gsi = gsi_after_labels (zero_iter_bb);
1a91d914 5772 assign_stmt = gimple_build_assign (fd->loop.n2,
5773 build_zero_cst (type));
5774 gsi_insert_before (gsi, assign_stmt, GSI_SAME_STMT);
3d483a94 5775 set_immediate_dominator (CDI_DOMINATORS, zero_iter_bb,
5776 entry_bb);
5777 }
5778 ne = make_edge (entry_bb, zero_iter_bb, EDGE_FALSE_VALUE);
5779 ne->probability = REG_BR_PROB_BASE / 2000 - 1;
5780 e->flags = EDGE_TRUE_VALUE;
5781 e->probability = REG_BR_PROB_BASE - ne->probability;
5782 if (l2_dom_bb == NULL)
5783 l2_dom_bb = entry_bb;
5784 entry_bb = e->dest;
5785 *gsi = gsi_last_bb (entry_bb);
5786 }
5787
5788 if (POINTER_TYPE_P (itype))
5789 itype = signed_type_for (itype);
5790 t = build_int_cst (itype, (fd->loops[i].cond_code == LT_EXPR
5791 ? -1 : 1));
5792 t = fold_build2 (PLUS_EXPR, itype,
5793 fold_convert (itype, fd->loops[i].step), t);
5794 t = fold_build2 (PLUS_EXPR, itype, t,
5795 fold_convert (itype, fd->loops[i].n2));
5796 t = fold_build2 (MINUS_EXPR, itype, t,
5797 fold_convert (itype, fd->loops[i].n1));
5798 /* ?? We could probably use CEIL_DIV_EXPR instead of
5799 TRUNC_DIV_EXPR and adjusting by hand. Unless we can't
5800 generate the same code in the end because generically we
5801 don't know that the values involved must be negative for
5802 GT?? */
5803 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
5804 t = fold_build2 (TRUNC_DIV_EXPR, itype,
5805 fold_build1 (NEGATE_EXPR, itype, t),
5806 fold_build1 (NEGATE_EXPR, itype,
5807 fold_convert (itype,
5808 fd->loops[i].step)));
5809 else
5810 t = fold_build2 (TRUNC_DIV_EXPR, itype, t,
5811 fold_convert (itype, fd->loops[i].step));
5812 t = fold_convert (type, t);
5813 if (TREE_CODE (t) == INTEGER_CST)
5814 counts[i] = t;
5815 else
5816 {
5817 counts[i] = create_tmp_reg (type, ".count");
5818 expand_omp_build_assign (gsi, counts[i], t);
5819 }
5820 if (SSA_VAR_P (fd->loop.n2))
5821 {
5822 if (i == 0)
5823 t = counts[0];
5824 else
5825 t = fold_build2 (MULT_EXPR, type, fd->loop.n2, counts[i]);
5826 expand_omp_build_assign (gsi, fd->loop.n2, t);
5827 }
5828 }
5829}
5830
5831
5832/* Helper function for expand_omp_{for_*,simd}. Generate code like:
5833 T = V;
5834 V3 = N31 + (T % count3) * STEP3;
5835 T = T / count3;
5836 V2 = N21 + (T % count2) * STEP2;
5837 T = T / count2;
5838 V1 = N11 + T * STEP1;
bc7bff74 5839 if this loop doesn't have an inner loop construct combined with it.
5840 If it does have an inner loop construct combined with it and the
5841 iteration count isn't known constant, store values from counts array
5842 into its _looptemp_ temporaries instead. */
3d483a94 5843
5844static void
5845expand_omp_for_init_vars (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
42acab1c 5846 tree *counts, gimple *inner_stmt, tree startvar)
3d483a94 5847{
5848 int i;
bc7bff74 5849 if (gimple_omp_for_combined_p (fd->for_stmt))
5850 {
5851 /* If fd->loop.n2 is constant, then no propagation of the counts
5852 is needed, they are constant. */
5853 if (TREE_CODE (fd->loop.n2) == INTEGER_CST)
5854 return;
5855
5856 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
5857 ? gimple_omp_parallel_clauses (inner_stmt)
5858 : gimple_omp_for_clauses (inner_stmt);
5859 /* First two _looptemp_ clauses are for istart/iend, counts[0]
5860 isn't supposed to be handled, as the inner loop doesn't
5861 use it. */
5862 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
5863 gcc_assert (innerc);
5864 for (i = 0; i < fd->collapse; i++)
5865 {
5866 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5867 OMP_CLAUSE__LOOPTEMP_);
5868 gcc_assert (innerc);
5869 if (i)
5870 {
5871 tree tem = OMP_CLAUSE_DECL (innerc);
5872 tree t = fold_convert (TREE_TYPE (tem), counts[i]);
5873 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
5874 false, GSI_CONTINUE_LINKING);
1a91d914 5875 gassign *stmt = gimple_build_assign (tem, t);
bc7bff74 5876 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5877 }
5878 }
5879 return;
5880 }
5881
3d483a94 5882 tree type = TREE_TYPE (fd->loop.v);
5883 tree tem = create_tmp_reg (type, ".tem");
1a91d914 5884 gassign *stmt = gimple_build_assign (tem, startvar);
3d483a94 5885 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5886
5887 for (i = fd->collapse - 1; i >= 0; i--)
5888 {
5889 tree vtype = TREE_TYPE (fd->loops[i].v), itype, t;
5890 itype = vtype;
5891 if (POINTER_TYPE_P (vtype))
5892 itype = signed_type_for (vtype);
5893 if (i != 0)
5894 t = fold_build2 (TRUNC_MOD_EXPR, type, tem, counts[i]);
5895 else
5896 t = tem;
5897 t = fold_convert (itype, t);
5898 t = fold_build2 (MULT_EXPR, itype, t,
5899 fold_convert (itype, fd->loops[i].step));
5900 if (POINTER_TYPE_P (vtype))
5901 t = fold_build_pointer_plus (fd->loops[i].n1, t);
5902 else
5903 t = fold_build2 (PLUS_EXPR, itype, fd->loops[i].n1, t);
5904 t = force_gimple_operand_gsi (gsi, t,
5905 DECL_P (fd->loops[i].v)
5906 && TREE_ADDRESSABLE (fd->loops[i].v),
5907 NULL_TREE, false,
5908 GSI_CONTINUE_LINKING);
5909 stmt = gimple_build_assign (fd->loops[i].v, t);
5910 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5911 if (i != 0)
5912 {
5913 t = fold_build2 (TRUNC_DIV_EXPR, type, tem, counts[i]);
5914 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
5915 false, GSI_CONTINUE_LINKING);
5916 stmt = gimple_build_assign (tem, t);
5917 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5918 }
5919 }
5920}
5921
5922
5923/* Helper function for expand_omp_for_*. Generate code like:
5924 L10:
5925 V3 += STEP3;
5926 if (V3 cond3 N32) goto BODY_BB; else goto L11;
5927 L11:
5928 V3 = N31;
5929 V2 += STEP2;
5930 if (V2 cond2 N22) goto BODY_BB; else goto L12;
5931 L12:
5932 V2 = N21;
5933 V1 += STEP1;
5934 goto BODY_BB; */
5935
5936static basic_block
5937extract_omp_for_update_vars (struct omp_for_data *fd, basic_block cont_bb,
5938 basic_block body_bb)
5939{
5940 basic_block last_bb, bb, collapse_bb = NULL;
5941 int i;
5942 gimple_stmt_iterator gsi;
5943 edge e;
5944 tree t;
42acab1c 5945 gimple *stmt;
3d483a94 5946
5947 last_bb = cont_bb;
5948 for (i = fd->collapse - 1; i >= 0; i--)
5949 {
5950 tree vtype = TREE_TYPE (fd->loops[i].v);
5951
5952 bb = create_empty_bb (last_bb);
b3083327 5953 add_bb_to_loop (bb, last_bb->loop_father);
3d483a94 5954 gsi = gsi_start_bb (bb);
5955
5956 if (i < fd->collapse - 1)
5957 {
5958 e = make_edge (last_bb, bb, EDGE_FALSE_VALUE);
5959 e->probability = REG_BR_PROB_BASE / 8;
5960
5961 t = fd->loops[i + 1].n1;
5962 t = force_gimple_operand_gsi (&gsi, t,
5963 DECL_P (fd->loops[i + 1].v)
5964 && TREE_ADDRESSABLE (fd->loops[i
5965 + 1].v),
5966 NULL_TREE, false,
5967 GSI_CONTINUE_LINKING);
5968 stmt = gimple_build_assign (fd->loops[i + 1].v, t);
5969 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5970 }
5971 else
5972 collapse_bb = bb;
5973
5974 set_immediate_dominator (CDI_DOMINATORS, bb, last_bb);
5975
5976 if (POINTER_TYPE_P (vtype))
5977 t = fold_build_pointer_plus (fd->loops[i].v, fd->loops[i].step);
5978 else
5979 t = fold_build2 (PLUS_EXPR, vtype, fd->loops[i].v, fd->loops[i].step);
5980 t = force_gimple_operand_gsi (&gsi, t,
5981 DECL_P (fd->loops[i].v)
5982 && TREE_ADDRESSABLE (fd->loops[i].v),
5983 NULL_TREE, false, GSI_CONTINUE_LINKING);
5984 stmt = gimple_build_assign (fd->loops[i].v, t);
5985 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5986
5987 if (i > 0)
5988 {
5989 t = fd->loops[i].n2;
5990 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5991 false, GSI_CONTINUE_LINKING);
5992 tree v = fd->loops[i].v;
5993 if (DECL_P (v) && TREE_ADDRESSABLE (v))
5994 v = force_gimple_operand_gsi (&gsi, v, true, NULL_TREE,
5995 false, GSI_CONTINUE_LINKING);
5996 t = fold_build2 (fd->loops[i].cond_code, boolean_type_node, v, t);
5997 stmt = gimple_build_cond_empty (t);
5998 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5999 e = make_edge (bb, body_bb, EDGE_TRUE_VALUE);
6000 e->probability = REG_BR_PROB_BASE * 7 / 8;
6001 }
6002 else
6003 make_edge (bb, body_bb, EDGE_FALLTHRU);
6004 last_bb = bb;
6005 }
6006
6007 return collapse_bb;
6008}
6009
6010
773c5ba7 6011/* A subroutine of expand_omp_for. Generate code for a parallel
1e8e9920 6012 loop with any schedule. Given parameters:
6013
6014 for (V = N1; V cond N2; V += STEP) BODY;
6015
6016 where COND is "<" or ">", we generate pseudocode
6017
6018 more = GOMP_loop_foo_start (N1, N2, STEP, CHUNK, &istart0, &iend0);
773c5ba7 6019 if (more) goto L0; else goto L3;
1e8e9920 6020 L0:
6021 V = istart0;
6022 iend = iend0;
6023 L1:
6024 BODY;
6025 V += STEP;
773c5ba7 6026 if (V cond iend) goto L1; else goto L2;
1e8e9920 6027 L2:
773c5ba7 6028 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
6029 L3:
1e8e9920 6030
773c5ba7 6031 If this is a combined omp parallel loop, instead of the call to
fd6481cf 6032 GOMP_loop_foo_start, we call GOMP_loop_foo_next.
bc7bff74 6033 If this is gimple_omp_for_combined_p loop, then instead of assigning
6034 V and iend in L0 we assign the first two _looptemp_ clause decls of the
6035 inner GIMPLE_OMP_FOR and V += STEP; and
6036 if (V cond iend) goto L1; else goto L2; are removed.
fd6481cf 6037
6038 For collapsed loops, given parameters:
6039 collapse(3)
6040 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
6041 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
6042 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
6043 BODY;
6044
6045 we generate pseudocode
6046
8e6b4515 6047 if (__builtin_expect (N32 cond3 N31, 0)) goto Z0;
fd6481cf 6048 if (cond3 is <)
6049 adj = STEP3 - 1;
6050 else
6051 adj = STEP3 + 1;
6052 count3 = (adj + N32 - N31) / STEP3;
8e6b4515 6053 if (__builtin_expect (N22 cond2 N21, 0)) goto Z0;
fd6481cf 6054 if (cond2 is <)
6055 adj = STEP2 - 1;
6056 else
6057 adj = STEP2 + 1;
6058 count2 = (adj + N22 - N21) / STEP2;
8e6b4515 6059 if (__builtin_expect (N12 cond1 N11, 0)) goto Z0;
fd6481cf 6060 if (cond1 is <)
6061 adj = STEP1 - 1;
6062 else
6063 adj = STEP1 + 1;
6064 count1 = (adj + N12 - N11) / STEP1;
6065 count = count1 * count2 * count3;
8e6b4515 6066 goto Z1;
6067 Z0:
6068 count = 0;
6069 Z1:
fd6481cf 6070 more = GOMP_loop_foo_start (0, count, 1, CHUNK, &istart0, &iend0);
6071 if (more) goto L0; else goto L3;
6072 L0:
6073 V = istart0;
6074 T = V;
6075 V3 = N31 + (T % count3) * STEP3;
6076 T = T / count3;
6077 V2 = N21 + (T % count2) * STEP2;
6078 T = T / count2;
6079 V1 = N11 + T * STEP1;
6080 iend = iend0;
6081 L1:
6082 BODY;
6083 V += 1;
6084 if (V < iend) goto L10; else goto L2;
6085 L10:
6086 V3 += STEP3;
6087 if (V3 cond3 N32) goto L1; else goto L11;
6088 L11:
6089 V3 = N31;
6090 V2 += STEP2;
6091 if (V2 cond2 N22) goto L1; else goto L12;
6092 L12:
6093 V2 = N21;
6094 V1 += STEP1;
6095 goto L1;
6096 L2:
6097 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
6098 L3:
6099
6100 */
1e8e9920 6101
61e47ac8 6102static void
773c5ba7 6103expand_omp_for_generic (struct omp_region *region,
6104 struct omp_for_data *fd,
1e8e9920 6105 enum built_in_function start_fn,
bc7bff74 6106 enum built_in_function next_fn,
42acab1c 6107 gimple *inner_stmt)
1e8e9920 6108{
75a70cf9 6109 tree type, istart0, iend0, iend;
fd6481cf 6110 tree t, vmain, vback, bias = NULL_TREE;
6111 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, collapse_bb;
03ed154b 6112 basic_block l2_bb = NULL, l3_bb = NULL;
75a70cf9 6113 gimple_stmt_iterator gsi;
1a91d914 6114 gassign *assign_stmt;
773c5ba7 6115 bool in_combined_parallel = is_combined_parallel (region);
ac6e3339 6116 bool broken_loop = region->cont == NULL;
79acaae1 6117 edge e, ne;
fd6481cf 6118 tree *counts = NULL;
6119 int i;
ac6e3339 6120
6121 gcc_assert (!broken_loop || !in_combined_parallel);
fd6481cf 6122 gcc_assert (fd->iter_type == long_integer_type_node
6123 || !in_combined_parallel);
1e8e9920 6124
fd6481cf 6125 type = TREE_TYPE (fd->loop.v);
6126 istart0 = create_tmp_var (fd->iter_type, ".istart0");
6127 iend0 = create_tmp_var (fd->iter_type, ".iend0");
6d63fc03 6128 TREE_ADDRESSABLE (istart0) = 1;
6129 TREE_ADDRESSABLE (iend0) = 1;
1e8e9920 6130
fd6481cf 6131 /* See if we need to bias by LLONG_MIN. */
6132 if (fd->iter_type == long_long_unsigned_type_node
6133 && TREE_CODE (type) == INTEGER_TYPE
6134 && !TYPE_UNSIGNED (type))
6135 {
6136 tree n1, n2;
6137
6138 if (fd->loop.cond_code == LT_EXPR)
6139 {
6140 n1 = fd->loop.n1;
6141 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
6142 }
6143 else
6144 {
6145 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
6146 n2 = fd->loop.n1;
6147 }
6148 if (TREE_CODE (n1) != INTEGER_CST
6149 || TREE_CODE (n2) != INTEGER_CST
6150 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
6151 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
6152 }
6153
61e47ac8 6154 entry_bb = region->entry;
03ed154b 6155 cont_bb = region->cont;
fd6481cf 6156 collapse_bb = NULL;
ac6e3339 6157 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
6158 gcc_assert (broken_loop
6159 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
6160 l0_bb = split_edge (FALLTHRU_EDGE (entry_bb));
6161 l1_bb = single_succ (l0_bb);
6162 if (!broken_loop)
03ed154b 6163 {
6164 l2_bb = create_empty_bb (cont_bb);
95cd5725 6165 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l1_bb
6166 || (single_succ_edge (BRANCH_EDGE (cont_bb)->dest)->dest
6167 == l1_bb));
ac6e3339 6168 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
03ed154b 6169 }
ac6e3339 6170 else
6171 l2_bb = NULL;
6172 l3_bb = BRANCH_EDGE (entry_bb)->dest;
6173 exit_bb = region->exit;
773c5ba7 6174
75a70cf9 6175 gsi = gsi_last_bb (entry_bb);
fd6481cf 6176
75a70cf9 6177 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
fd6481cf 6178 if (fd->collapse > 1)
6179 {
8e6b4515 6180 int first_zero_iter = -1;
3d483a94 6181 basic_block zero_iter_bb = NULL, l2_dom_bb = NULL;
8e6b4515 6182
3d483a94 6183 counts = XALLOCAVEC (tree, fd->collapse);
6184 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
6185 zero_iter_bb, first_zero_iter,
6186 l2_dom_bb);
fd6481cf 6187
8e6b4515 6188 if (zero_iter_bb)
6189 {
6190 /* Some counts[i] vars might be uninitialized if
6191 some loop has zero iterations. But the body shouldn't
6192 be executed in that case, so just avoid uninit warnings. */
6193 for (i = first_zero_iter; i < fd->collapse; i++)
6194 if (SSA_VAR_P (counts[i]))
6195 TREE_NO_WARNING (counts[i]) = 1;
6196 gsi_prev (&gsi);
6197 e = split_block (entry_bb, gsi_stmt (gsi));
6198 entry_bb = e->dest;
6199 make_edge (zero_iter_bb, entry_bb, EDGE_FALLTHRU);
6200 gsi = gsi_last_bb (entry_bb);
6201 set_immediate_dominator (CDI_DOMINATORS, entry_bb,
6202 get_immediate_dominator (CDI_DOMINATORS,
6203 zero_iter_bb));
6204 }
fd6481cf 6205 }
79acaae1 6206 if (in_combined_parallel)
6207 {
6208 /* In a combined parallel loop, emit a call to
6209 GOMP_loop_foo_next. */
b9a16870 6210 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
79acaae1 6211 build_fold_addr_expr (istart0),
6212 build_fold_addr_expr (iend0));
6213 }
6214 else
1e8e9920 6215 {
c2f47e15 6216 tree t0, t1, t2, t3, t4;
773c5ba7 6217 /* If this is not a combined parallel loop, emit a call to
6218 GOMP_loop_foo_start in ENTRY_BB. */
c2f47e15 6219 t4 = build_fold_addr_expr (iend0);
6220 t3 = build_fold_addr_expr (istart0);
fd6481cf 6221 t2 = fold_convert (fd->iter_type, fd->loop.step);
3d483a94 6222 t1 = fd->loop.n2;
6223 t0 = fd->loop.n1;
bc7bff74 6224 if (gimple_omp_for_combined_into_p (fd->for_stmt))
6225 {
6226 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
6227 OMP_CLAUSE__LOOPTEMP_);
6228 gcc_assert (innerc);
6229 t0 = OMP_CLAUSE_DECL (innerc);
6230 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6231 OMP_CLAUSE__LOOPTEMP_);
6232 gcc_assert (innerc);
6233 t1 = OMP_CLAUSE_DECL (innerc);
6234 }
3d483a94 6235 if (POINTER_TYPE_P (TREE_TYPE (t0))
6236 && TYPE_PRECISION (TREE_TYPE (t0))
6237 != TYPE_PRECISION (fd->iter_type))
c799f233 6238 {
6239 /* Avoid casting pointers to integer of a different size. */
3cea8318 6240 tree itype = signed_type_for (type);
3d483a94 6241 t1 = fold_convert (fd->iter_type, fold_convert (itype, t1));
6242 t0 = fold_convert (fd->iter_type, fold_convert (itype, t0));
c799f233 6243 }
6244 else
6245 {
3d483a94 6246 t1 = fold_convert (fd->iter_type, t1);
6247 t0 = fold_convert (fd->iter_type, t0);
c799f233 6248 }
fd6481cf 6249 if (bias)
1e8e9920 6250 {
fd6481cf 6251 t1 = fold_build2 (PLUS_EXPR, fd->iter_type, t1, bias);
6252 t0 = fold_build2 (PLUS_EXPR, fd->iter_type, t0, bias);
6253 }
6254 if (fd->iter_type == long_integer_type_node)
6255 {
6256 if (fd->chunk_size)
6257 {
6258 t = fold_convert (fd->iter_type, fd->chunk_size);
b9a16870 6259 t = build_call_expr (builtin_decl_explicit (start_fn),
6260 6, t0, t1, t2, t, t3, t4);
fd6481cf 6261 }
6262 else
b9a16870 6263 t = build_call_expr (builtin_decl_explicit (start_fn),
6264 5, t0, t1, t2, t3, t4);
1e8e9920 6265 }
c2f47e15 6266 else
fd6481cf 6267 {
6268 tree t5;
6269 tree c_bool_type;
b9a16870 6270 tree bfn_decl;
fd6481cf 6271
6272 /* The GOMP_loop_ull_*start functions have additional boolean
6273 argument, true for < loops and false for > loops.
6274 In Fortran, the C bool type can be different from
6275 boolean_type_node. */
b9a16870 6276 bfn_decl = builtin_decl_explicit (start_fn);
6277 c_bool_type = TREE_TYPE (TREE_TYPE (bfn_decl));
fd6481cf 6278 t5 = build_int_cst (c_bool_type,
6279 fd->loop.cond_code == LT_EXPR ? 1 : 0);
6280 if (fd->chunk_size)
6281 {
b9a16870 6282 tree bfn_decl = builtin_decl_explicit (start_fn);
fd6481cf 6283 t = fold_convert (fd->iter_type, fd->chunk_size);
b9a16870 6284 t = build_call_expr (bfn_decl, 7, t5, t0, t1, t2, t, t3, t4);
fd6481cf 6285 }
6286 else
b9a16870 6287 t = build_call_expr (builtin_decl_explicit (start_fn),
6288 6, t5, t0, t1, t2, t3, t4);
fd6481cf 6289 }
1e8e9920 6290 }
fd6481cf 6291 if (TREE_TYPE (t) != boolean_type_node)
6292 t = fold_build2 (NE_EXPR, boolean_type_node,
6293 t, build_int_cst (TREE_TYPE (t), 0));
75a70cf9 6294 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6295 true, GSI_SAME_STMT);
6296 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
79acaae1 6297
75a70cf9 6298 /* Remove the GIMPLE_OMP_FOR statement. */
6299 gsi_remove (&gsi, true);
1e8e9920 6300
773c5ba7 6301 /* Iteration setup for sequential loop goes in L0_BB. */
3d483a94 6302 tree startvar = fd->loop.v;
6303 tree endvar = NULL_TREE;
6304
bc7bff74 6305 if (gimple_omp_for_combined_p (fd->for_stmt))
6306 {
6307 gcc_assert (gimple_code (inner_stmt) == GIMPLE_OMP_FOR
6308 && gimple_omp_for_kind (inner_stmt)
6309 == GF_OMP_FOR_KIND_SIMD);
6310 tree innerc = find_omp_clause (gimple_omp_for_clauses (inner_stmt),
6311 OMP_CLAUSE__LOOPTEMP_);
6312 gcc_assert (innerc);
6313 startvar = OMP_CLAUSE_DECL (innerc);
6314 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6315 OMP_CLAUSE__LOOPTEMP_);
6316 gcc_assert (innerc);
6317 endvar = OMP_CLAUSE_DECL (innerc);
6318 }
6319
75a70cf9 6320 gsi = gsi_start_bb (l0_bb);
1efcacec 6321 t = istart0;
fd6481cf 6322 if (bias)
1efcacec 6323 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
3d483a94 6324 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
6325 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
6326 t = fold_convert (TREE_TYPE (startvar), t);
4abecb72 6327 t = force_gimple_operand_gsi (&gsi, t,
3d483a94 6328 DECL_P (startvar)
6329 && TREE_ADDRESSABLE (startvar),
4abecb72 6330 NULL_TREE, false, GSI_CONTINUE_LINKING);
1a91d914 6331 assign_stmt = gimple_build_assign (startvar, t);
6332 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
1e8e9920 6333
1efcacec 6334 t = iend0;
fd6481cf 6335 if (bias)
1efcacec 6336 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
3d483a94 6337 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
6338 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
6339 t = fold_convert (TREE_TYPE (startvar), t);
75a70cf9 6340 iend = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6341 false, GSI_CONTINUE_LINKING);
3d483a94 6342 if (endvar)
fd6481cf 6343 {
1a91d914 6344 assign_stmt = gimple_build_assign (endvar, iend);
6345 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
d44f2f7c 6346 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (iend)))
1a91d914 6347 assign_stmt = gimple_build_assign (fd->loop.v, iend);
d44f2f7c 6348 else
e9cf809e 6349 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, iend);
1a91d914 6350 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
fd6481cf 6351 }
3d483a94 6352 if (fd->collapse > 1)
bc7bff74 6353 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
773c5ba7 6354
ac6e3339 6355 if (!broken_loop)
03ed154b 6356 {
ac6e3339 6357 /* Code to control the increment and predicate for the sequential
6358 loop goes in the CONT_BB. */
75a70cf9 6359 gsi = gsi_last_bb (cont_bb);
1a91d914 6360 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
6361 gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
6362 vmain = gimple_omp_continue_control_use (cont_stmt);
6363 vback = gimple_omp_continue_control_def (cont_stmt);
79acaae1 6364
bc7bff74 6365 if (!gimple_omp_for_combined_p (fd->for_stmt))
3d483a94 6366 {
6367 if (POINTER_TYPE_P (type))
6368 t = fold_build_pointer_plus (vmain, fd->loop.step);
6369 else
6370 t = fold_build2 (PLUS_EXPR, type, vmain, fd->loop.step);
6371 t = force_gimple_operand_gsi (&gsi, t,
6372 DECL_P (vback)
6373 && TREE_ADDRESSABLE (vback),
6374 NULL_TREE, true, GSI_SAME_STMT);
1a91d914 6375 assign_stmt = gimple_build_assign (vback, t);
6376 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
3d483a94 6377
6378 t = build2 (fd->loop.cond_code, boolean_type_node,
6379 DECL_P (vback) && TREE_ADDRESSABLE (vback) ? t : vback,
6380 iend);
1a91d914 6381 gcond *cond_stmt = gimple_build_cond_empty (t);
6382 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
3d483a94 6383 }
773c5ba7 6384
75a70cf9 6385 /* Remove GIMPLE_OMP_CONTINUE. */
6386 gsi_remove (&gsi, true);
773c5ba7 6387
bc7bff74 6388 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
3d483a94 6389 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, l1_bb);
fd6481cf 6390
ac6e3339 6391 /* Emit code to get the next parallel iteration in L2_BB. */
75a70cf9 6392 gsi = gsi_start_bb (l2_bb);
773c5ba7 6393
b9a16870 6394 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
ac6e3339 6395 build_fold_addr_expr (istart0),
6396 build_fold_addr_expr (iend0));
75a70cf9 6397 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6398 false, GSI_CONTINUE_LINKING);
fd6481cf 6399 if (TREE_TYPE (t) != boolean_type_node)
6400 t = fold_build2 (NE_EXPR, boolean_type_node,
6401 t, build_int_cst (TREE_TYPE (t), 0));
1a91d914 6402 gcond *cond_stmt = gimple_build_cond_empty (t);
6403 gsi_insert_after (&gsi, cond_stmt, GSI_CONTINUE_LINKING);
ac6e3339 6404 }
1e8e9920 6405
61e47ac8 6406 /* Add the loop cleanup function. */
75a70cf9 6407 gsi = gsi_last_bb (exit_bb);
6408 if (gimple_omp_return_nowait_p (gsi_stmt (gsi)))
b9a16870 6409 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_NOWAIT);
bc7bff74 6410 else if (gimple_omp_return_lhs (gsi_stmt (gsi)))
6411 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_CANCEL);
61e47ac8 6412 else
b9a16870 6413 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END);
1a91d914 6414 gcall *call_stmt = gimple_build_call (t, 0);
bc7bff74 6415 if (gimple_omp_return_lhs (gsi_stmt (gsi)))
1a91d914 6416 gimple_call_set_lhs (call_stmt, gimple_omp_return_lhs (gsi_stmt (gsi)));
6417 gsi_insert_after (&gsi, call_stmt, GSI_SAME_STMT);
75a70cf9 6418 gsi_remove (&gsi, true);
773c5ba7 6419
6420 /* Connect the new blocks. */
79acaae1 6421 find_edge (entry_bb, l0_bb)->flags = EDGE_TRUE_VALUE;
6422 find_edge (entry_bb, l3_bb)->flags = EDGE_FALSE_VALUE;
1e8e9920 6423
ac6e3339 6424 if (!broken_loop)
6425 {
75a70cf9 6426 gimple_seq phis;
6427
79acaae1 6428 e = find_edge (cont_bb, l3_bb);
6429 ne = make_edge (l2_bb, l3_bb, EDGE_FALSE_VALUE);
6430
75a70cf9 6431 phis = phi_nodes (l3_bb);
6432 for (gsi = gsi_start (phis); !gsi_end_p (gsi); gsi_next (&gsi))
6433 {
42acab1c 6434 gimple *phi = gsi_stmt (gsi);
75a70cf9 6435 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, ne),
6436 PHI_ARG_DEF_FROM_EDGE (phi, e));
6437 }
79acaae1 6438 remove_edge (e);
6439
ac6e3339 6440 make_edge (cont_bb, l2_bb, EDGE_FALSE_VALUE);
b3083327 6441 add_bb_to_loop (l2_bb, cont_bb->loop_father);
3d483a94 6442 e = find_edge (cont_bb, l1_bb);
95cd5725 6443 if (e == NULL)
6444 {
6445 e = BRANCH_EDGE (cont_bb);
6446 gcc_assert (single_succ (e->dest) == l1_bb);
6447 }
bc7bff74 6448 if (gimple_omp_for_combined_p (fd->for_stmt))
6449 {
6450 remove_edge (e);
6451 e = NULL;
6452 }
3d483a94 6453 else if (fd->collapse > 1)
fd6481cf 6454 {
fd6481cf 6455 remove_edge (e);
6456 e = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
6457 }
6458 else
3d483a94 6459 e->flags = EDGE_TRUE_VALUE;
6460 if (e)
fd6481cf 6461 {
3d483a94 6462 e->probability = REG_BR_PROB_BASE * 7 / 8;
6463 find_edge (cont_bb, l2_bb)->probability = REG_BR_PROB_BASE / 8;
6464 }
6465 else
6466 {
6467 e = find_edge (cont_bb, l2_bb);
6468 e->flags = EDGE_FALLTHRU;
fd6481cf 6469 }
ac6e3339 6470 make_edge (l2_bb, l0_bb, EDGE_TRUE_VALUE);
79acaae1 6471
6472 set_immediate_dominator (CDI_DOMINATORS, l2_bb,
6473 recompute_dominator (CDI_DOMINATORS, l2_bb));
6474 set_immediate_dominator (CDI_DOMINATORS, l3_bb,
6475 recompute_dominator (CDI_DOMINATORS, l3_bb));
6476 set_immediate_dominator (CDI_DOMINATORS, l0_bb,
6477 recompute_dominator (CDI_DOMINATORS, l0_bb));
6478 set_immediate_dominator (CDI_DOMINATORS, l1_bb,
6479 recompute_dominator (CDI_DOMINATORS, l1_bb));
04c2922b 6480
6481 struct loop *outer_loop = alloc_loop ();
6482 outer_loop->header = l0_bb;
6483 outer_loop->latch = l2_bb;
6484 add_loop (outer_loop, l0_bb->loop_father);
6485
bc7bff74 6486 if (!gimple_omp_for_combined_p (fd->for_stmt))
3d483a94 6487 {
6488 struct loop *loop = alloc_loop ();
6489 loop->header = l1_bb;
6490 /* The loop may have multiple latches. */
6491 add_loop (loop, outer_loop);
6492 }
ac6e3339 6493 }
1e8e9920 6494}
6495
6496
773c5ba7 6497/* A subroutine of expand_omp_for. Generate code for a parallel
6498 loop with static schedule and no specified chunk size. Given
6499 parameters:
1e8e9920 6500
6501 for (V = N1; V cond N2; V += STEP) BODY;
6502
6503 where COND is "<" or ">", we generate pseudocode
6504
8e6b4515 6505 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
1e8e9920 6506 if (cond is <)
6507 adj = STEP - 1;
6508 else
6509 adj = STEP + 1;
fd6481cf 6510 if ((__typeof (V)) -1 > 0 && cond is >)
6511 n = -(adj + N2 - N1) / -STEP;
6512 else
6513 n = (adj + N2 - N1) / STEP;
1e8e9920 6514 q = n / nthreads;
31712e83 6515 tt = n % nthreads;
6516 if (threadid < tt) goto L3; else goto L4;
6517 L3:
6518 tt = 0;
6519 q = q + 1;
6520 L4:
6521 s0 = q * threadid + tt;
6522 e0 = s0 + q;
79acaae1 6523 V = s0 * STEP + N1;
1e8e9920 6524 if (s0 >= e0) goto L2; else goto L0;
6525 L0:
1e8e9920 6526 e = e0 * STEP + N1;
6527 L1:
6528 BODY;
6529 V += STEP;
6530 if (V cond e) goto L1;
1e8e9920 6531 L2:
6532*/
6533
61e47ac8 6534static void
773c5ba7 6535expand_omp_for_static_nochunk (struct omp_region *region,
bc7bff74 6536 struct omp_for_data *fd,
42acab1c 6537 gimple *inner_stmt)
1e8e9920 6538{
31712e83 6539 tree n, q, s0, e0, e, t, tt, nthreads, threadid;
fd6481cf 6540 tree type, itype, vmain, vback;
31712e83 6541 basic_block entry_bb, second_bb, third_bb, exit_bb, seq_start_bb;
bc7bff74 6542 basic_block body_bb, cont_bb, collapse_bb = NULL;
61e47ac8 6543 basic_block fin_bb;
75a70cf9 6544 gimple_stmt_iterator gsi;
31712e83 6545 edge ep;
bc7bff74 6546 bool broken_loop = region->cont == NULL;
6547 tree *counts = NULL;
6548 tree n1, n2, step;
1e8e9920 6549
ca4c3545 6550 gcc_checking_assert ((gimple_omp_for_kind (fd->for_stmt)
6551 != GF_OMP_FOR_KIND_OACC_LOOP)
6552 || !inner_stmt);
6553
fd6481cf 6554 itype = type = TREE_TYPE (fd->loop.v);
6555 if (POINTER_TYPE_P (type))
3cea8318 6556 itype = signed_type_for (type);
1e8e9920 6557
61e47ac8 6558 entry_bb = region->entry;
61e47ac8 6559 cont_bb = region->cont;
ac6e3339 6560 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
bc7bff74 6561 fin_bb = BRANCH_EDGE (entry_bb)->dest;
6562 gcc_assert (broken_loop
6563 || (fin_bb == FALLTHRU_EDGE (cont_bb)->dest));
ac6e3339 6564 seq_start_bb = split_edge (FALLTHRU_EDGE (entry_bb));
6565 body_bb = single_succ (seq_start_bb);
bc7bff74 6566 if (!broken_loop)
6567 {
86a932e0 6568 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb
6569 || single_succ (BRANCH_EDGE (cont_bb)->dest) == body_bb);
bc7bff74 6570 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
6571 }
61e47ac8 6572 exit_bb = region->exit;
6573
773c5ba7 6574 /* Iteration space partitioning goes in ENTRY_BB. */
75a70cf9 6575 gsi = gsi_last_bb (entry_bb);
6576 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
61e47ac8 6577
bc7bff74 6578 if (fd->collapse > 1)
6579 {
6580 int first_zero_iter = -1;
6581 basic_block l2_dom_bb = NULL;
6582
6583 counts = XALLOCAVEC (tree, fd->collapse);
6584 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
6585 fin_bb, first_zero_iter,
6586 l2_dom_bb);
6587 t = NULL_TREE;
6588 }
6589 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
6590 t = integer_one_node;
6591 else
6592 t = fold_binary (fd->loop.cond_code, boolean_type_node,
6593 fold_convert (type, fd->loop.n1),
6594 fold_convert (type, fd->loop.n2));
6595 if (fd->collapse == 1
6596 && TYPE_UNSIGNED (type)
8e6b4515 6597 && (t == NULL_TREE || !integer_onep (t)))
6598 {
8e6b4515 6599 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
6600 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
6601 true, GSI_SAME_STMT);
6602 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
6603 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
6604 true, GSI_SAME_STMT);
1a91d914 6605 gcond *cond_stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
6606 NULL_TREE, NULL_TREE);
6607 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
6608 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
8e6b4515 6609 expand_omp_regimplify_p, NULL, NULL)
1a91d914 6610 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
8e6b4515 6611 expand_omp_regimplify_p, NULL, NULL))
6612 {
1a91d914 6613 gsi = gsi_for_stmt (cond_stmt);
6614 gimple_regimplify_operands (cond_stmt, &gsi);
8e6b4515 6615 }
1a91d914 6616 ep = split_block (entry_bb, cond_stmt);
8e6b4515 6617 ep->flags = EDGE_TRUE_VALUE;
6618 entry_bb = ep->dest;
6619 ep->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
6620 ep = make_edge (ep->src, fin_bb, EDGE_FALSE_VALUE);
6621 ep->probability = REG_BR_PROB_BASE / 2000 - 1;
6622 if (gimple_in_ssa_p (cfun))
6623 {
6624 int dest_idx = find_edge (entry_bb, fin_bb)->dest_idx;
1a91d914 6625 for (gphi_iterator gpi = gsi_start_phis (fin_bb);
6626 !gsi_end_p (gpi); gsi_next (&gpi))
8e6b4515 6627 {
1a91d914 6628 gphi *phi = gpi.phi ();
8e6b4515 6629 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
6630 ep, UNKNOWN_LOCATION);
6631 }
6632 }
6633 gsi = gsi_last_bb (entry_bb);
6634 }
6635
ca4c3545 6636 switch (gimple_omp_for_kind (fd->for_stmt))
6637 {
6638 case GF_OMP_FOR_KIND_FOR:
6639 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
6640 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
6641 break;
6642 case GF_OMP_FOR_KIND_DISTRIBUTE:
6643 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_TEAMS);
6644 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_TEAM_NUM);
6645 break;
6646 case GF_OMP_FOR_KIND_OACC_LOOP:
6647 nthreads = builtin_decl_explicit (BUILT_IN_GOACC_GET_NUM_THREADS);
6648 threadid = builtin_decl_explicit (BUILT_IN_GOACC_GET_THREAD_NUM);
6649 break;
6650 default:
6651 gcc_unreachable ();
6652 }
6653 nthreads = build_call_expr (nthreads, 0);
6654 nthreads = fold_convert (itype, nthreads);
6655 nthreads = force_gimple_operand_gsi (&gsi, nthreads, true, NULL_TREE,
75a70cf9 6656 true, GSI_SAME_STMT);
ca4c3545 6657 threadid = build_call_expr (threadid, 0);
6658 threadid = fold_convert (itype, threadid);
6659 threadid = force_gimple_operand_gsi (&gsi, threadid, true, NULL_TREE,
75a70cf9 6660 true, GSI_SAME_STMT);
1e8e9920 6661
bc7bff74 6662 n1 = fd->loop.n1;
6663 n2 = fd->loop.n2;
6664 step = fd->loop.step;
6665 if (gimple_omp_for_combined_into_p (fd->for_stmt))
6666 {
6667 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
6668 OMP_CLAUSE__LOOPTEMP_);
6669 gcc_assert (innerc);
6670 n1 = OMP_CLAUSE_DECL (innerc);
6671 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6672 OMP_CLAUSE__LOOPTEMP_);
6673 gcc_assert (innerc);
6674 n2 = OMP_CLAUSE_DECL (innerc);
6675 }
6676 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
6677 true, NULL_TREE, true, GSI_SAME_STMT);
6678 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
6679 true, NULL_TREE, true, GSI_SAME_STMT);
6680 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
6681 true, NULL_TREE, true, GSI_SAME_STMT);
fd6481cf 6682
6683 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
bc7bff74 6684 t = fold_build2 (PLUS_EXPR, itype, step, t);
6685 t = fold_build2 (PLUS_EXPR, itype, t, n2);
6686 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
fd6481cf 6687 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
6688 t = fold_build2 (TRUNC_DIV_EXPR, itype,
6689 fold_build1 (NEGATE_EXPR, itype, t),
bc7bff74 6690 fold_build1 (NEGATE_EXPR, itype, step));
fd6481cf 6691 else
bc7bff74 6692 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
fd6481cf 6693 t = fold_convert (itype, t);
75a70cf9 6694 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
1e8e9920 6695
072f7ab1 6696 q = create_tmp_reg (itype, "q");
fd6481cf 6697 t = fold_build2 (TRUNC_DIV_EXPR, itype, n, nthreads);
31712e83 6698 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
6699 gsi_insert_before (&gsi, gimple_build_assign (q, t), GSI_SAME_STMT);
6700
072f7ab1 6701 tt = create_tmp_reg (itype, "tt");
31712e83 6702 t = fold_build2 (TRUNC_MOD_EXPR, itype, n, nthreads);
6703 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
6704 gsi_insert_before (&gsi, gimple_build_assign (tt, t), GSI_SAME_STMT);
1e8e9920 6705
31712e83 6706 t = build2 (LT_EXPR, boolean_type_node, threadid, tt);
1a91d914 6707 gcond *cond_stmt = gimple_build_cond_empty (t);
6708 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
31712e83 6709
1a91d914 6710 second_bb = split_block (entry_bb, cond_stmt)->dest;
31712e83 6711 gsi = gsi_last_bb (second_bb);
6712 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6713
6714 gsi_insert_before (&gsi, gimple_build_assign (tt, build_int_cst (itype, 0)),
6715 GSI_SAME_STMT);
1a91d914 6716 gassign *assign_stmt
e9cf809e 6717 = gimple_build_assign (q, PLUS_EXPR, q, build_int_cst (itype, 1));
1a91d914 6718 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
31712e83 6719
1a91d914 6720 third_bb = split_block (second_bb, assign_stmt)->dest;
31712e83 6721 gsi = gsi_last_bb (third_bb);
6722 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
1e8e9920 6723
fd6481cf 6724 t = build2 (MULT_EXPR, itype, q, threadid);
31712e83 6725 t = build2 (PLUS_EXPR, itype, t, tt);
75a70cf9 6726 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
1e8e9920 6727
fd6481cf 6728 t = fold_build2 (PLUS_EXPR, itype, s0, q);
75a70cf9 6729 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
79acaae1 6730
1e8e9920 6731 t = build2 (GE_EXPR, boolean_type_node, s0, e0);
75a70cf9 6732 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
773c5ba7 6733
75a70cf9 6734 /* Remove the GIMPLE_OMP_FOR statement. */
6735 gsi_remove (&gsi, true);
773c5ba7 6736
6737 /* Setup code for sequential iteration goes in SEQ_START_BB. */
75a70cf9 6738 gsi = gsi_start_bb (seq_start_bb);
1e8e9920 6739
bc7bff74 6740 tree startvar = fd->loop.v;
6741 tree endvar = NULL_TREE;
6742
6743 if (gimple_omp_for_combined_p (fd->for_stmt))
6744 {
6745 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
6746 ? gimple_omp_parallel_clauses (inner_stmt)
6747 : gimple_omp_for_clauses (inner_stmt);
6748 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
6749 gcc_assert (innerc);
6750 startvar = OMP_CLAUSE_DECL (innerc);
6751 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6752 OMP_CLAUSE__LOOPTEMP_);
6753 gcc_assert (innerc);
6754 endvar = OMP_CLAUSE_DECL (innerc);
6755 }
fd6481cf 6756 t = fold_convert (itype, s0);
bc7bff74 6757 t = fold_build2 (MULT_EXPR, itype, t, step);
fd6481cf 6758 if (POINTER_TYPE_P (type))
bc7bff74 6759 t = fold_build_pointer_plus (n1, t);
fd6481cf 6760 else
bc7bff74 6761 t = fold_build2 (PLUS_EXPR, type, t, n1);
6762 t = fold_convert (TREE_TYPE (startvar), t);
4abecb72 6763 t = force_gimple_operand_gsi (&gsi, t,
bc7bff74 6764 DECL_P (startvar)
6765 && TREE_ADDRESSABLE (startvar),
4abecb72 6766 NULL_TREE, false, GSI_CONTINUE_LINKING);
1a91d914 6767 assign_stmt = gimple_build_assign (startvar, t);
6768 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
48e1416a 6769
fd6481cf 6770 t = fold_convert (itype, e0);
bc7bff74 6771 t = fold_build2 (MULT_EXPR, itype, t, step);
fd6481cf 6772 if (POINTER_TYPE_P (type))
bc7bff74 6773 t = fold_build_pointer_plus (n1, t);
fd6481cf 6774 else
bc7bff74 6775 t = fold_build2 (PLUS_EXPR, type, t, n1);
6776 t = fold_convert (TREE_TYPE (startvar), t);
75a70cf9 6777 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6778 false, GSI_CONTINUE_LINKING);
bc7bff74 6779 if (endvar)
6780 {
1a91d914 6781 assign_stmt = gimple_build_assign (endvar, e);
6782 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
d44f2f7c 6783 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
1a91d914 6784 assign_stmt = gimple_build_assign (fd->loop.v, e);
d44f2f7c 6785 else
e9cf809e 6786 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, e);
1a91d914 6787 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
bc7bff74 6788 }
6789 if (fd->collapse > 1)
6790 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
1e8e9920 6791
bc7bff74 6792 if (!broken_loop)
6793 {
6794 /* The code controlling the sequential loop replaces the
6795 GIMPLE_OMP_CONTINUE. */
6796 gsi = gsi_last_bb (cont_bb);
1a91d914 6797 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
6798 gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
6799 vmain = gimple_omp_continue_control_use (cont_stmt);
6800 vback = gimple_omp_continue_control_def (cont_stmt);
79acaae1 6801
bc7bff74 6802 if (!gimple_omp_for_combined_p (fd->for_stmt))
6803 {
6804 if (POINTER_TYPE_P (type))
6805 t = fold_build_pointer_plus (vmain, step);
6806 else
6807 t = fold_build2 (PLUS_EXPR, type, vmain, step);
6808 t = force_gimple_operand_gsi (&gsi, t,
6809 DECL_P (vback)
6810 && TREE_ADDRESSABLE (vback),
6811 NULL_TREE, true, GSI_SAME_STMT);
1a91d914 6812 assign_stmt = gimple_build_assign (vback, t);
6813 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
79acaae1 6814
bc7bff74 6815 t = build2 (fd->loop.cond_code, boolean_type_node,
6816 DECL_P (vback) && TREE_ADDRESSABLE (vback)
6817 ? t : vback, e);
6818 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
6819 }
1e8e9920 6820
bc7bff74 6821 /* Remove the GIMPLE_OMP_CONTINUE statement. */
6822 gsi_remove (&gsi, true);
6823
6824 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
6825 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
6826 }
773c5ba7 6827
75a70cf9 6828 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
6829 gsi = gsi_last_bb (exit_bb);
6830 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
bc7bff74 6831 {
6832 t = gimple_omp_return_lhs (gsi_stmt (gsi));
ca4c3545 6833 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_OACC_LOOP)
6834 gcc_checking_assert (t == NULL_TREE);
6835 else
6836 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
bc7bff74 6837 }
75a70cf9 6838 gsi_remove (&gsi, true);
773c5ba7 6839
6840 /* Connect all the blocks. */
31712e83 6841 ep = make_edge (entry_bb, third_bb, EDGE_FALSE_VALUE);
6842 ep->probability = REG_BR_PROB_BASE / 4 * 3;
6843 ep = find_edge (entry_bb, second_bb);
6844 ep->flags = EDGE_TRUE_VALUE;
6845 ep->probability = REG_BR_PROB_BASE / 4;
6846 find_edge (third_bb, seq_start_bb)->flags = EDGE_FALSE_VALUE;
6847 find_edge (third_bb, fin_bb)->flags = EDGE_TRUE_VALUE;
79acaae1 6848
bc7bff74 6849 if (!broken_loop)
6850 {
6851 ep = find_edge (cont_bb, body_bb);
86a932e0 6852 if (ep == NULL)
6853 {
6854 ep = BRANCH_EDGE (cont_bb);
6855 gcc_assert (single_succ (ep->dest) == body_bb);
6856 }
bc7bff74 6857 if (gimple_omp_for_combined_p (fd->for_stmt))
6858 {
6859 remove_edge (ep);
6860 ep = NULL;
6861 }
6862 else if (fd->collapse > 1)
6863 {
6864 remove_edge (ep);
6865 ep = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
6866 }
6867 else
6868 ep->flags = EDGE_TRUE_VALUE;
6869 find_edge (cont_bb, fin_bb)->flags
6870 = ep ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
6871 }
48e1416a 6872
31712e83 6873 set_immediate_dominator (CDI_DOMINATORS, second_bb, entry_bb);
6874 set_immediate_dominator (CDI_DOMINATORS, third_bb, entry_bb);
6875 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb, third_bb);
bc7bff74 6876
79acaae1 6877 set_immediate_dominator (CDI_DOMINATORS, body_bb,
6878 recompute_dominator (CDI_DOMINATORS, body_bb));
6879 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
6880 recompute_dominator (CDI_DOMINATORS, fin_bb));
04c2922b 6881
86a932e0 6882 struct loop *loop = body_bb->loop_father;
6883 if (loop != entry_bb->loop_father)
6884 {
6885 gcc_assert (loop->header == body_bb);
6886 gcc_assert (broken_loop
6887 || loop->latch == region->cont
6888 || single_pred (loop->latch) == region->cont);
6889 return;
6890 }
6891
bc7bff74 6892 if (!broken_loop && !gimple_omp_for_combined_p (fd->for_stmt))
6893 {
86a932e0 6894 loop = alloc_loop ();
bc7bff74 6895 loop->header = body_bb;
6896 if (collapse_bb == NULL)
6897 loop->latch = cont_bb;
6898 add_loop (loop, body_bb->loop_father);
6899 }
1e8e9920 6900}
6901
281001a9 6902/* Return phi in E->DEST with ARG on edge E. */
6903
6904static gphi *
6905find_phi_with_arg_on_edge (tree arg, edge e)
6906{
6907 basic_block bb = e->dest;
6908
6909 for (gphi_iterator gpi = gsi_start_phis (bb);
6910 !gsi_end_p (gpi);
6911 gsi_next (&gpi))
6912 {
6913 gphi *phi = gpi.phi ();
6914 if (PHI_ARG_DEF_FROM_EDGE (phi, e) == arg)
6915 return phi;
6916 }
6917
6918 return NULL;
6919}
773c5ba7 6920
6921/* A subroutine of expand_omp_for. Generate code for a parallel
6922 loop with static schedule and a specified chunk size. Given
6923 parameters:
1e8e9920 6924
6925 for (V = N1; V cond N2; V += STEP) BODY;
6926
6927 where COND is "<" or ">", we generate pseudocode
6928
8e6b4515 6929 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
1e8e9920 6930 if (cond is <)
6931 adj = STEP - 1;
6932 else
6933 adj = STEP + 1;
fd6481cf 6934 if ((__typeof (V)) -1 > 0 && cond is >)
6935 n = -(adj + N2 - N1) / -STEP;
6936 else
6937 n = (adj + N2 - N1) / STEP;
1e8e9920 6938 trip = 0;
79acaae1 6939 V = threadid * CHUNK * STEP + N1; -- this extra definition of V is
6940 here so that V is defined
6941 if the loop is not entered
1e8e9920 6942 L0:
6943 s0 = (trip * nthreads + threadid) * CHUNK;
6944 e0 = min(s0 + CHUNK, n);
6945 if (s0 < n) goto L1; else goto L4;
6946 L1:
6947 V = s0 * STEP + N1;
6948 e = e0 * STEP + N1;
6949 L2:
6950 BODY;
6951 V += STEP;
6952 if (V cond e) goto L2; else goto L3;
6953 L3:
6954 trip += 1;
6955 goto L0;
6956 L4:
1e8e9920 6957*/
6958
61e47ac8 6959static void
bc7bff74 6960expand_omp_for_static_chunk (struct omp_region *region,
42acab1c 6961 struct omp_for_data *fd, gimple *inner_stmt)
1e8e9920 6962{
75a70cf9 6963 tree n, s0, e0, e, t;
79acaae1 6964 tree trip_var, trip_init, trip_main, trip_back, nthreads, threadid;
93481288 6965 tree type, itype, vmain, vback, vextra;
773c5ba7 6966 basic_block entry_bb, exit_bb, body_bb, seq_start_bb, iter_part_bb;
bc7bff74 6967 basic_block trip_update_bb = NULL, cont_bb, collapse_bb = NULL, fin_bb;
93481288 6968 gimple_stmt_iterator gsi;
75a70cf9 6969 edge se;
bc7bff74 6970 bool broken_loop = region->cont == NULL;
6971 tree *counts = NULL;
6972 tree n1, n2, step;
1e8e9920 6973
ca4c3545 6974 gcc_checking_assert ((gimple_omp_for_kind (fd->for_stmt)
6975 != GF_OMP_FOR_KIND_OACC_LOOP)
6976 || !inner_stmt);
6977
fd6481cf 6978 itype = type = TREE_TYPE (fd->loop.v);
6979 if (POINTER_TYPE_P (type))
3cea8318 6980 itype = signed_type_for (type);
1e8e9920 6981
61e47ac8 6982 entry_bb = region->entry;
ac6e3339 6983 se = split_block (entry_bb, last_stmt (entry_bb));
6984 entry_bb = se->src;
6985 iter_part_bb = se->dest;
61e47ac8 6986 cont_bb = region->cont;
ac6e3339 6987 gcc_assert (EDGE_COUNT (iter_part_bb->succs) == 2);
bc7bff74 6988 fin_bb = BRANCH_EDGE (iter_part_bb)->dest;
6989 gcc_assert (broken_loop
6990 || fin_bb == FALLTHRU_EDGE (cont_bb)->dest);
ac6e3339 6991 seq_start_bb = split_edge (FALLTHRU_EDGE (iter_part_bb));
6992 body_bb = single_succ (seq_start_bb);
bc7bff74 6993 if (!broken_loop)
6994 {
fc1d58e3 6995 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb
6996 || single_succ (BRANCH_EDGE (cont_bb)->dest) == body_bb);
bc7bff74 6997 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
6998 trip_update_bb = split_edge (FALLTHRU_EDGE (cont_bb));
6999 }
61e47ac8 7000 exit_bb = region->exit;
773c5ba7 7001
773c5ba7 7002 /* Trip and adjustment setup goes in ENTRY_BB. */
93481288 7003 gsi = gsi_last_bb (entry_bb);
7004 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
773c5ba7 7005
bc7bff74 7006 if (fd->collapse > 1)
7007 {
7008 int first_zero_iter = -1;
7009 basic_block l2_dom_bb = NULL;
7010
7011 counts = XALLOCAVEC (tree, fd->collapse);
93481288 7012 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
bc7bff74 7013 fin_bb, first_zero_iter,
7014 l2_dom_bb);
7015 t = NULL_TREE;
7016 }
7017 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
7018 t = integer_one_node;
7019 else
7020 t = fold_binary (fd->loop.cond_code, boolean_type_node,
7021 fold_convert (type, fd->loop.n1),
7022 fold_convert (type, fd->loop.n2));
7023 if (fd->collapse == 1
7024 && TYPE_UNSIGNED (type)
8e6b4515 7025 && (t == NULL_TREE || !integer_onep (t)))
7026 {
8e6b4515 7027 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
93481288 7028 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
8e6b4515 7029 true, GSI_SAME_STMT);
7030 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
93481288 7031 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
8e6b4515 7032 true, GSI_SAME_STMT);
1a91d914 7033 gcond *cond_stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
7034 NULL_TREE, NULL_TREE);
7035 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
7036 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
8e6b4515 7037 expand_omp_regimplify_p, NULL, NULL)
1a91d914 7038 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
8e6b4515 7039 expand_omp_regimplify_p, NULL, NULL))
7040 {
1a91d914 7041 gsi = gsi_for_stmt (cond_stmt);
7042 gimple_regimplify_operands (cond_stmt, &gsi);
8e6b4515 7043 }
1a91d914 7044 se = split_block (entry_bb, cond_stmt);
8e6b4515 7045 se->flags = EDGE_TRUE_VALUE;
7046 entry_bb = se->dest;
7047 se->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
7048 se = make_edge (se->src, fin_bb, EDGE_FALSE_VALUE);
7049 se->probability = REG_BR_PROB_BASE / 2000 - 1;
7050 if (gimple_in_ssa_p (cfun))
7051 {
264aa959 7052 int dest_idx = find_edge (iter_part_bb, fin_bb)->dest_idx;
1a91d914 7053 for (gphi_iterator gpi = gsi_start_phis (fin_bb);
7054 !gsi_end_p (gpi); gsi_next (&gpi))
8e6b4515 7055 {
1a91d914 7056 gphi *phi = gpi.phi ();
8e6b4515 7057 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
7058 se, UNKNOWN_LOCATION);
7059 }
7060 }
93481288 7061 gsi = gsi_last_bb (entry_bb);
8e6b4515 7062 }
7063
ca4c3545 7064 switch (gimple_omp_for_kind (fd->for_stmt))
7065 {
7066 case GF_OMP_FOR_KIND_FOR:
7067 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
7068 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
7069 break;
7070 case GF_OMP_FOR_KIND_DISTRIBUTE:
7071 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_TEAMS);
7072 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_TEAM_NUM);
7073 break;
7074 case GF_OMP_FOR_KIND_OACC_LOOP:
7075 nthreads = builtin_decl_explicit (BUILT_IN_GOACC_GET_NUM_THREADS);
7076 threadid = builtin_decl_explicit (BUILT_IN_GOACC_GET_THREAD_NUM);
7077 break;
7078 default:
7079 gcc_unreachable ();
7080 }
7081 nthreads = build_call_expr (nthreads, 0);
7082 nthreads = fold_convert (itype, nthreads);
7083 nthreads = force_gimple_operand_gsi (&gsi, nthreads, true, NULL_TREE,
75a70cf9 7084 true, GSI_SAME_STMT);
ca4c3545 7085 threadid = build_call_expr (threadid, 0);
7086 threadid = fold_convert (itype, threadid);
7087 threadid = force_gimple_operand_gsi (&gsi, threadid, true, NULL_TREE,
75a70cf9 7088 true, GSI_SAME_STMT);
79acaae1 7089
bc7bff74 7090 n1 = fd->loop.n1;
7091 n2 = fd->loop.n2;
7092 step = fd->loop.step;
7093 if (gimple_omp_for_combined_into_p (fd->for_stmt))
7094 {
7095 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7096 OMP_CLAUSE__LOOPTEMP_);
7097 gcc_assert (innerc);
7098 n1 = OMP_CLAUSE_DECL (innerc);
7099 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7100 OMP_CLAUSE__LOOPTEMP_);
7101 gcc_assert (innerc);
7102 n2 = OMP_CLAUSE_DECL (innerc);
7103 }
93481288 7104 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
bc7bff74 7105 true, NULL_TREE, true, GSI_SAME_STMT);
93481288 7106 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
bc7bff74 7107 true, NULL_TREE, true, GSI_SAME_STMT);
93481288 7108 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
bc7bff74 7109 true, NULL_TREE, true, GSI_SAME_STMT);
79acaae1 7110 fd->chunk_size
93481288 7111 = force_gimple_operand_gsi (&gsi, fold_convert (itype, fd->chunk_size),
75a70cf9 7112 true, NULL_TREE, true, GSI_SAME_STMT);
fd6481cf 7113
7114 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
bc7bff74 7115 t = fold_build2 (PLUS_EXPR, itype, step, t);
7116 t = fold_build2 (PLUS_EXPR, itype, t, n2);
7117 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
fd6481cf 7118 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
7119 t = fold_build2 (TRUNC_DIV_EXPR, itype,
7120 fold_build1 (NEGATE_EXPR, itype, t),
bc7bff74 7121 fold_build1 (NEGATE_EXPR, itype, step));
fd6481cf 7122 else
bc7bff74 7123 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
fd6481cf 7124 t = fold_convert (itype, t);
93481288 7125 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
75a70cf9 7126 true, GSI_SAME_STMT);
79acaae1 7127
083152fb 7128 trip_var = create_tmp_reg (itype, ".trip");
79acaae1 7129 if (gimple_in_ssa_p (cfun))
7130 {
f9e245b2 7131 trip_init = make_ssa_name (trip_var);
7132 trip_main = make_ssa_name (trip_var);
7133 trip_back = make_ssa_name (trip_var);
79acaae1 7134 }
1e8e9920 7135 else
79acaae1 7136 {
7137 trip_init = trip_var;
7138 trip_main = trip_var;
7139 trip_back = trip_var;
7140 }
1e8e9920 7141
1a91d914 7142 gassign *assign_stmt
7143 = gimple_build_assign (trip_init, build_int_cst (itype, 0));
7144 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
773c5ba7 7145
fd6481cf 7146 t = fold_build2 (MULT_EXPR, itype, threadid, fd->chunk_size);
bc7bff74 7147 t = fold_build2 (MULT_EXPR, itype, t, step);
fd6481cf 7148 if (POINTER_TYPE_P (type))
bc7bff74 7149 t = fold_build_pointer_plus (n1, t);
fd6481cf 7150 else
bc7bff74 7151 t = fold_build2 (PLUS_EXPR, type, t, n1);
93481288 7152 vextra = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7153 true, GSI_SAME_STMT);
79acaae1 7154
75a70cf9 7155 /* Remove the GIMPLE_OMP_FOR. */
93481288 7156 gsi_remove (&gsi, true);
773c5ba7 7157
7158 /* Iteration space partitioning goes in ITER_PART_BB. */
93481288 7159 gsi = gsi_last_bb (iter_part_bb);
1e8e9920 7160
fd6481cf 7161 t = fold_build2 (MULT_EXPR, itype, trip_main, nthreads);
7162 t = fold_build2 (PLUS_EXPR, itype, t, threadid);
7163 t = fold_build2 (MULT_EXPR, itype, t, fd->chunk_size);
93481288 7164 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
75a70cf9 7165 false, GSI_CONTINUE_LINKING);
1e8e9920 7166
fd6481cf 7167 t = fold_build2 (PLUS_EXPR, itype, s0, fd->chunk_size);
7168 t = fold_build2 (MIN_EXPR, itype, t, n);
93481288 7169 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
75a70cf9 7170 false, GSI_CONTINUE_LINKING);
1e8e9920 7171
7172 t = build2 (LT_EXPR, boolean_type_node, s0, n);
93481288 7173 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_CONTINUE_LINKING);
773c5ba7 7174
7175 /* Setup code for sequential iteration goes in SEQ_START_BB. */
93481288 7176 gsi = gsi_start_bb (seq_start_bb);
1e8e9920 7177
bc7bff74 7178 tree startvar = fd->loop.v;
7179 tree endvar = NULL_TREE;
7180
7181 if (gimple_omp_for_combined_p (fd->for_stmt))
7182 {
7183 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
7184 ? gimple_omp_parallel_clauses (inner_stmt)
7185 : gimple_omp_for_clauses (inner_stmt);
7186 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
7187 gcc_assert (innerc);
7188 startvar = OMP_CLAUSE_DECL (innerc);
7189 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7190 OMP_CLAUSE__LOOPTEMP_);
7191 gcc_assert (innerc);
7192 endvar = OMP_CLAUSE_DECL (innerc);
7193 }
7194
fd6481cf 7195 t = fold_convert (itype, s0);
bc7bff74 7196 t = fold_build2 (MULT_EXPR, itype, t, step);
fd6481cf 7197 if (POINTER_TYPE_P (type))
bc7bff74 7198 t = fold_build_pointer_plus (n1, t);
fd6481cf 7199 else
bc7bff74 7200 t = fold_build2 (PLUS_EXPR, type, t, n1);
7201 t = fold_convert (TREE_TYPE (startvar), t);
93481288 7202 t = force_gimple_operand_gsi (&gsi, t,
bc7bff74 7203 DECL_P (startvar)
7204 && TREE_ADDRESSABLE (startvar),
4abecb72 7205 NULL_TREE, false, GSI_CONTINUE_LINKING);
1a91d914 7206 assign_stmt = gimple_build_assign (startvar, t);
7207 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
1e8e9920 7208
fd6481cf 7209 t = fold_convert (itype, e0);
bc7bff74 7210 t = fold_build2 (MULT_EXPR, itype, t, step);
fd6481cf 7211 if (POINTER_TYPE_P (type))
bc7bff74 7212 t = fold_build_pointer_plus (n1, t);
fd6481cf 7213 else
bc7bff74 7214 t = fold_build2 (PLUS_EXPR, type, t, n1);
7215 t = fold_convert (TREE_TYPE (startvar), t);
93481288 7216 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
75a70cf9 7217 false, GSI_CONTINUE_LINKING);
bc7bff74 7218 if (endvar)
7219 {
1a91d914 7220 assign_stmt = gimple_build_assign (endvar, e);
7221 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
d44f2f7c 7222 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
1a91d914 7223 assign_stmt = gimple_build_assign (fd->loop.v, e);
d44f2f7c 7224 else
e9cf809e 7225 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, e);
1a91d914 7226 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
bc7bff74 7227 }
7228 if (fd->collapse > 1)
93481288 7229 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
bc7bff74 7230
7231 if (!broken_loop)
7232 {
7233 /* The code controlling the sequential loop goes in CONT_BB,
7234 replacing the GIMPLE_OMP_CONTINUE. */
93481288 7235 gsi = gsi_last_bb (cont_bb);
1a91d914 7236 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
7237 vmain = gimple_omp_continue_control_use (cont_stmt);
7238 vback = gimple_omp_continue_control_def (cont_stmt);
1e8e9920 7239
bc7bff74 7240 if (!gimple_omp_for_combined_p (fd->for_stmt))
7241 {
7242 if (POINTER_TYPE_P (type))
93481288 7243 t = fold_build_pointer_plus (vmain, step);
bc7bff74 7244 else
93481288 7245 t = fold_build2 (PLUS_EXPR, type, vmain, step);
7246 if (DECL_P (vback) && TREE_ADDRESSABLE (vback))
7247 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
bc7bff74 7248 true, GSI_SAME_STMT);
1a91d914 7249 assign_stmt = gimple_build_assign (vback, t);
7250 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
79acaae1 7251
345f9789 7252 if (tree_int_cst_equal (fd->chunk_size, integer_one_node))
7253 t = build2 (EQ_EXPR, boolean_type_node,
7254 build_int_cst (itype, 0),
7255 build_int_cst (itype, 1));
7256 else
7257 t = build2 (fd->loop.cond_code, boolean_type_node,
7258 DECL_P (vback) && TREE_ADDRESSABLE (vback)
7259 ? t : vback, e);
93481288 7260 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
bc7bff74 7261 }
79acaae1 7262
bc7bff74 7263 /* Remove GIMPLE_OMP_CONTINUE. */
93481288 7264 gsi_remove (&gsi, true);
48e1416a 7265
bc7bff74 7266 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
7267 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
773c5ba7 7268
bc7bff74 7269 /* Trip update code goes into TRIP_UPDATE_BB. */
93481288 7270 gsi = gsi_start_bb (trip_update_bb);
1e8e9920 7271
bc7bff74 7272 t = build_int_cst (itype, 1);
7273 t = build2 (PLUS_EXPR, itype, trip_main, t);
1a91d914 7274 assign_stmt = gimple_build_assign (trip_back, t);
7275 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
bc7bff74 7276 }
1e8e9920 7277
75a70cf9 7278 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
93481288 7279 gsi = gsi_last_bb (exit_bb);
7280 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
bc7bff74 7281 {
93481288 7282 t = gimple_omp_return_lhs (gsi_stmt (gsi));
ca4c3545 7283 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_OACC_LOOP)
7284 gcc_checking_assert (t == NULL_TREE);
7285 else
7286 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
bc7bff74 7287 }
93481288 7288 gsi_remove (&gsi, true);
1e8e9920 7289
773c5ba7 7290 /* Connect the new blocks. */
ac6e3339 7291 find_edge (iter_part_bb, seq_start_bb)->flags = EDGE_TRUE_VALUE;
7292 find_edge (iter_part_bb, fin_bb)->flags = EDGE_FALSE_VALUE;
79acaae1 7293
bc7bff74 7294 if (!broken_loop)
7295 {
7296 se = find_edge (cont_bb, body_bb);
fc1d58e3 7297 if (se == NULL)
7298 {
7299 se = BRANCH_EDGE (cont_bb);
7300 gcc_assert (single_succ (se->dest) == body_bb);
7301 }
bc7bff74 7302 if (gimple_omp_for_combined_p (fd->for_stmt))
7303 {
7304 remove_edge (se);
7305 se = NULL;
7306 }
7307 else if (fd->collapse > 1)
7308 {
7309 remove_edge (se);
7310 se = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
7311 }
7312 else
7313 se->flags = EDGE_TRUE_VALUE;
7314 find_edge (cont_bb, trip_update_bb)->flags
7315 = se ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
79acaae1 7316
bc7bff74 7317 redirect_edge_and_branch (single_succ_edge (trip_update_bb), iter_part_bb);
7318 }
79acaae1 7319
7320 if (gimple_in_ssa_p (cfun))
7321 {
1a91d914 7322 gphi_iterator psi;
7323 gphi *phi;
75a70cf9 7324 edge re, ene;
75a70cf9 7325 edge_var_map *vm;
7326 size_t i;
7327
bc7bff74 7328 gcc_assert (fd->collapse == 1 && !broken_loop);
7329
79acaae1 7330 /* When we redirect the edge from trip_update_bb to iter_part_bb, we
7331 remove arguments of the phi nodes in fin_bb. We need to create
7332 appropriate phi nodes in iter_part_bb instead. */
264aa959 7333 se = find_edge (iter_part_bb, fin_bb);
79acaae1 7334 re = single_succ_edge (trip_update_bb);
06ecf488 7335 vec<edge_var_map> *head = redirect_edge_var_map_vector (re);
79acaae1 7336 ene = single_succ_edge (entry_bb);
7337
75a70cf9 7338 psi = gsi_start_phis (fin_bb);
f1f41a6c 7339 for (i = 0; !gsi_end_p (psi) && head->iterate (i, &vm);
75a70cf9 7340 gsi_next (&psi), ++i)
79acaae1 7341 {
1a91d914 7342 gphi *nphi;
efbcb6de 7343 source_location locus;
75a70cf9 7344
1a91d914 7345 phi = psi.phi ();
75a70cf9 7346 t = gimple_phi_result (phi);
7347 gcc_assert (t == redirect_edge_var_map_result (vm));
264aa959 7348
7349 if (!single_pred_p (fin_bb))
7350 t = copy_ssa_name (t, phi);
7351
79acaae1 7352 nphi = create_phi_node (t, iter_part_bb);
79acaae1 7353
7354 t = PHI_ARG_DEF_FROM_EDGE (phi, se);
efbcb6de 7355 locus = gimple_phi_arg_location_from_edge (phi, se);
7356
fd6481cf 7357 /* A special case -- fd->loop.v is not yet computed in
93481288 7358 iter_part_bb, we need to use vextra instead. */
fd6481cf 7359 if (t == fd->loop.v)
93481288 7360 t = vextra;
60d535d2 7361 add_phi_arg (nphi, t, ene, locus);
efbcb6de 7362 locus = redirect_edge_var_map_location (vm);
281001a9 7363 tree back_arg = redirect_edge_var_map_def (vm);
7364 add_phi_arg (nphi, back_arg, re, locus);
7365 edge ce = find_edge (cont_bb, body_bb);
7366 if (ce == NULL)
7367 {
7368 ce = BRANCH_EDGE (cont_bb);
7369 gcc_assert (single_succ (ce->dest) == body_bb);
7370 ce = single_succ_edge (ce->dest);
7371 }
7372 gphi *inner_loop_phi = find_phi_with_arg_on_edge (back_arg, ce);
7373 gcc_assert (inner_loop_phi != NULL);
7374 add_phi_arg (inner_loop_phi, gimple_phi_result (nphi),
7375 find_edge (seq_start_bb, body_bb), locus);
264aa959 7376
7377 if (!single_pred_p (fin_bb))
7378 add_phi_arg (phi, gimple_phi_result (nphi), se, locus);
75a70cf9 7379 }
4d556e29 7380 gcc_assert (gsi_end_p (psi) && (head == NULL || i == head->length ()));
75a70cf9 7381 redirect_edge_var_map_clear (re);
264aa959 7382 if (single_pred_p (fin_bb))
7383 while (1)
7384 {
7385 psi = gsi_start_phis (fin_bb);
7386 if (gsi_end_p (psi))
7387 break;
7388 remove_phi_node (&psi, false);
7389 }
79acaae1 7390
7391 /* Make phi node for trip. */
7392 phi = create_phi_node (trip_main, iter_part_bb);
efbcb6de 7393 add_phi_arg (phi, trip_back, single_succ_edge (trip_update_bb),
60d535d2 7394 UNKNOWN_LOCATION);
efbcb6de 7395 add_phi_arg (phi, trip_init, single_succ_edge (entry_bb),
60d535d2 7396 UNKNOWN_LOCATION);
79acaae1 7397 }
7398
bc7bff74 7399 if (!broken_loop)
7400 set_immediate_dominator (CDI_DOMINATORS, trip_update_bb, cont_bb);
79acaae1 7401 set_immediate_dominator (CDI_DOMINATORS, iter_part_bb,
7402 recompute_dominator (CDI_DOMINATORS, iter_part_bb));
7403 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
7404 recompute_dominator (CDI_DOMINATORS, fin_bb));
7405 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb,
7406 recompute_dominator (CDI_DOMINATORS, seq_start_bb));
7407 set_immediate_dominator (CDI_DOMINATORS, body_bb,
7408 recompute_dominator (CDI_DOMINATORS, body_bb));
04c2922b 7409
bc7bff74 7410 if (!broken_loop)
7411 {
fc1d58e3 7412 struct loop *loop = body_bb->loop_father;
bc7bff74 7413 struct loop *trip_loop = alloc_loop ();
7414 trip_loop->header = iter_part_bb;
7415 trip_loop->latch = trip_update_bb;
7416 add_loop (trip_loop, iter_part_bb->loop_father);
04c2922b 7417
fc1d58e3 7418 if (loop != entry_bb->loop_father)
7419 {
7420 gcc_assert (loop->header == body_bb);
7421 gcc_assert (loop->latch == region->cont
7422 || single_pred (loop->latch) == region->cont);
7423 trip_loop->inner = loop;
7424 return;
7425 }
7426
bc7bff74 7427 if (!gimple_omp_for_combined_p (fd->for_stmt))
7428 {
fc1d58e3 7429 loop = alloc_loop ();
bc7bff74 7430 loop->header = body_bb;
33ee4d72 7431 if (collapse_bb == NULL)
7432 loop->latch = cont_bb;
bc7bff74 7433 add_loop (loop, trip_loop);
7434 }
7435 }
1e8e9920 7436}
7437
40750995 7438/* A subroutine of expand_omp_for. Generate code for _Cilk_for loop.
7439 Given parameters:
7440 for (V = N1; V cond N2; V += STEP) BODY;
7441
7442 where COND is "<" or ">" or "!=", we generate pseudocode
7443
7444 for (ind_var = low; ind_var < high; ind_var++)
7445 {
7446 V = n1 + (ind_var * STEP)
7447
7448 <BODY>
7449 }
7450
7451 In the above pseudocode, low and high are function parameters of the
7452 child function. In the function below, we are inserting a temp.
7453 variable that will be making a call to two OMP functions that will not be
7454 found in the body of _Cilk_for (since OMP_FOR cannot be mixed
7455 with _Cilk_for). These functions are replaced with low and high
7456 by the function that handles taskreg. */
7457
7458
7459static void
7460expand_cilk_for (struct omp_region *region, struct omp_for_data *fd)
7461{
7462 bool broken_loop = region->cont == NULL;
7463 basic_block entry_bb = region->entry;
7464 basic_block cont_bb = region->cont;
7465
7466 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
7467 gcc_assert (broken_loop
7468 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
7469 basic_block l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
7470 basic_block l1_bb, l2_bb;
7471
7472 if (!broken_loop)
7473 {
7474 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
7475 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
7476 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
7477 l2_bb = BRANCH_EDGE (entry_bb)->dest;
7478 }
7479 else
7480 {
7481 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
7482 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
7483 l2_bb = single_succ (l1_bb);
7484 }
7485 basic_block exit_bb = region->exit;
7486 basic_block l2_dom_bb = NULL;
7487
7488 gimple_stmt_iterator gsi = gsi_last_bb (entry_bb);
7489
7490 /* Below statements until the "tree high_val = ..." are pseudo statements
7491 used to pass information to be used by expand_omp_taskreg.
7492 low_val and high_val will be replaced by the __low and __high
7493 parameter from the child function.
7494
7495 The call_exprs part is a place-holder, it is mainly used
7496 to distinctly identify to the top-level part that this is
7497 where we should put low and high (reasoning given in header
7498 comment). */
7499
7500 tree child_fndecl
1a91d914 7501 = gimple_omp_parallel_child_fn (
7502 as_a <gomp_parallel *> (last_stmt (region->outer->entry)));
40750995 7503 tree t, low_val = NULL_TREE, high_val = NULL_TREE;
7504 for (t = DECL_ARGUMENTS (child_fndecl); t; t = TREE_CHAIN (t))
7505 {
7506 if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__high"))
7507 high_val = t;
7508 else if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__low"))
7509 low_val = t;
7510 }
7511 gcc_assert (low_val && high_val);
7512
7513 tree type = TREE_TYPE (low_val);
7514 tree ind_var = create_tmp_reg (type, "__cilk_ind_var");
7515 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
7516
7517 /* Not needed in SSA form right now. */
7518 gcc_assert (!gimple_in_ssa_p (cfun));
7519 if (l2_dom_bb == NULL)
7520 l2_dom_bb = l1_bb;
7521
7522 tree n1 = low_val;
7523 tree n2 = high_val;
7524
42acab1c 7525 gimple *stmt = gimple_build_assign (ind_var, n1);
40750995 7526
7527 /* Replace the GIMPLE_OMP_FOR statement. */
7528 gsi_replace (&gsi, stmt, true);
7529
7530 if (!broken_loop)
7531 {
7532 /* Code to control the increment goes in the CONT_BB. */
7533 gsi = gsi_last_bb (cont_bb);
7534 stmt = gsi_stmt (gsi);
7535 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
e9cf809e 7536 stmt = gimple_build_assign (ind_var, PLUS_EXPR, ind_var,
7537 build_one_cst (type));
40750995 7538
7539 /* Replace GIMPLE_OMP_CONTINUE. */
7540 gsi_replace (&gsi, stmt, true);
7541 }
7542
7543 /* Emit the condition in L1_BB. */
7544 gsi = gsi_after_labels (l1_bb);
7545 t = fold_build2 (MULT_EXPR, TREE_TYPE (fd->loop.step),
7546 fold_convert (TREE_TYPE (fd->loop.step), ind_var),
7547 fd->loop.step);
7548 if (POINTER_TYPE_P (TREE_TYPE (fd->loop.n1)))
7549 t = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (fd->loop.n1),
7550 fd->loop.n1, fold_convert (sizetype, t));
7551 else
7552 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loop.n1),
7553 fd->loop.n1, fold_convert (TREE_TYPE (fd->loop.n1), t));
7554 t = fold_convert (TREE_TYPE (fd->loop.v), t);
7555 expand_omp_build_assign (&gsi, fd->loop.v, t);
7556
7557 /* The condition is always '<' since the runtime will fill in the low
7558 and high values. */
7559 stmt = gimple_build_cond (LT_EXPR, ind_var, n2, NULL_TREE, NULL_TREE);
7560 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
7561
7562 /* Remove GIMPLE_OMP_RETURN. */
7563 gsi = gsi_last_bb (exit_bb);
7564 gsi_remove (&gsi, true);
7565
7566 /* Connect the new blocks. */
7567 remove_edge (FALLTHRU_EDGE (entry_bb));
7568
7569 edge e, ne;
7570 if (!broken_loop)
7571 {
7572 remove_edge (BRANCH_EDGE (entry_bb));
7573 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
7574
7575 e = BRANCH_EDGE (l1_bb);
7576 ne = FALLTHRU_EDGE (l1_bb);
7577 e->flags = EDGE_TRUE_VALUE;
7578 }
7579 else
7580 {
7581 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7582
7583 ne = single_succ_edge (l1_bb);
7584 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
7585
7586 }
7587 ne->flags = EDGE_FALSE_VALUE;
7588 e->probability = REG_BR_PROB_BASE * 7 / 8;
7589 ne->probability = REG_BR_PROB_BASE / 8;
7590
7591 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
7592 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
7593 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
7594
7595 if (!broken_loop)
7596 {
7597 struct loop *loop = alloc_loop ();
7598 loop->header = l1_bb;
7599 loop->latch = cont_bb;
7600 add_loop (loop, l1_bb->loop_father);
7601 loop->safelen = INT_MAX;
7602 }
7603
7604 /* Pick the correct library function based on the precision of the
7605 induction variable type. */
7606 tree lib_fun = NULL_TREE;
7607 if (TYPE_PRECISION (type) == 32)
7608 lib_fun = cilk_for_32_fndecl;
7609 else if (TYPE_PRECISION (type) == 64)
7610 lib_fun = cilk_for_64_fndecl;
7611 else
7612 gcc_unreachable ();
7613
7614 gcc_assert (fd->sched_kind == OMP_CLAUSE_SCHEDULE_CILKFOR);
7615
7616 /* WS_ARGS contains the library function flavor to call:
7617 __libcilkrts_cilk_for_64 or __libcilkrts_cilk_for_32), and the
7618 user-defined grain value. If the user does not define one, then zero
7619 is passed in by the parser. */
7620 vec_alloc (region->ws_args, 2);
7621 region->ws_args->quick_push (lib_fun);
7622 region->ws_args->quick_push (fd->chunk_size);
7623}
bc7bff74 7624
3d483a94 7625/* A subroutine of expand_omp_for. Generate code for a simd non-worksharing
7626 loop. Given parameters:
7627
7628 for (V = N1; V cond N2; V += STEP) BODY;
7629
7630 where COND is "<" or ">", we generate pseudocode
7631
7632 V = N1;
7633 goto L1;
7634 L0:
7635 BODY;
7636 V += STEP;
7637 L1:
7638 if (V cond N2) goto L0; else goto L2;
7639 L2:
7640
7641 For collapsed loops, given parameters:
7642 collapse(3)
7643 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
7644 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
7645 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
7646 BODY;
7647
7648 we generate pseudocode
7649
7650 if (cond3 is <)
7651 adj = STEP3 - 1;
7652 else
7653 adj = STEP3 + 1;
7654 count3 = (adj + N32 - N31) / STEP3;
7655 if (cond2 is <)
7656 adj = STEP2 - 1;
7657 else
7658 adj = STEP2 + 1;
7659 count2 = (adj + N22 - N21) / STEP2;
7660 if (cond1 is <)
7661 adj = STEP1 - 1;
7662 else
7663 adj = STEP1 + 1;
7664 count1 = (adj + N12 - N11) / STEP1;
7665 count = count1 * count2 * count3;
7666 V = 0;
7667 V1 = N11;
7668 V2 = N21;
7669 V3 = N31;
7670 goto L1;
7671 L0:
7672 BODY;
7673 V += 1;
7674 V3 += STEP3;
7675 V2 += (V3 cond3 N32) ? 0 : STEP2;
7676 V3 = (V3 cond3 N32) ? V3 : N31;
7677 V1 += (V2 cond2 N22) ? 0 : STEP1;
7678 V2 = (V2 cond2 N22) ? V2 : N21;
7679 L1:
7680 if (V < count) goto L0; else goto L2;
7681 L2:
7682
7683 */
7684
7685static void
7686expand_omp_simd (struct omp_region *region, struct omp_for_data *fd)
7687{
7688 tree type, t;
7689 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, l2_bb, l2_dom_bb;
7690 gimple_stmt_iterator gsi;
42acab1c 7691 gimple *stmt;
1a91d914 7692 gcond *cond_stmt;
3d483a94 7693 bool broken_loop = region->cont == NULL;
7694 edge e, ne;
7695 tree *counts = NULL;
7696 int i;
7697 tree safelen = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7698 OMP_CLAUSE_SAFELEN);
7699 tree simduid = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7700 OMP_CLAUSE__SIMDUID_);
bc7bff74 7701 tree n1, n2;
3d483a94 7702
7703 type = TREE_TYPE (fd->loop.v);
7704 entry_bb = region->entry;
7705 cont_bb = region->cont;
7706 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
7707 gcc_assert (broken_loop
7708 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
7709 l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
7710 if (!broken_loop)
7711 {
7712 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
7713 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
7714 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
7715 l2_bb = BRANCH_EDGE (entry_bb)->dest;
7716 }
7717 else
7718 {
7719 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
7720 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
7721 l2_bb = single_succ (l1_bb);
7722 }
7723 exit_bb = region->exit;
7724 l2_dom_bb = NULL;
7725
7726 gsi = gsi_last_bb (entry_bb);
7727
7728 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
7729 /* Not needed in SSA form right now. */
7730 gcc_assert (!gimple_in_ssa_p (cfun));
7731 if (fd->collapse > 1)
7732 {
7733 int first_zero_iter = -1;
7734 basic_block zero_iter_bb = l2_bb;
7735
7736 counts = XALLOCAVEC (tree, fd->collapse);
7737 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
7738 zero_iter_bb, first_zero_iter,
7739 l2_dom_bb);
7740 }
7741 if (l2_dom_bb == NULL)
7742 l2_dom_bb = l1_bb;
7743
bc7bff74 7744 n1 = fd->loop.n1;
3d483a94 7745 n2 = fd->loop.n2;
bc7bff74 7746 if (gimple_omp_for_combined_into_p (fd->for_stmt))
7747 {
7748 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7749 OMP_CLAUSE__LOOPTEMP_);
7750 gcc_assert (innerc);
7751 n1 = OMP_CLAUSE_DECL (innerc);
7752 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7753 OMP_CLAUSE__LOOPTEMP_);
7754 gcc_assert (innerc);
7755 n2 = OMP_CLAUSE_DECL (innerc);
7756 expand_omp_build_assign (&gsi, fd->loop.v,
7757 fold_convert (type, n1));
7758 if (fd->collapse > 1)
7759 {
7760 gsi_prev (&gsi);
7761 expand_omp_for_init_vars (fd, &gsi, counts, NULL, n1);
7762 gsi_next (&gsi);
7763 }
7764 }
3d483a94 7765 else
7766 {
7767 expand_omp_build_assign (&gsi, fd->loop.v,
7768 fold_convert (type, fd->loop.n1));
7769 if (fd->collapse > 1)
7770 for (i = 0; i < fd->collapse; i++)
7771 {
7772 tree itype = TREE_TYPE (fd->loops[i].v);
7773 if (POINTER_TYPE_P (itype))
7774 itype = signed_type_for (itype);
7775 t = fold_convert (TREE_TYPE (fd->loops[i].v), fd->loops[i].n1);
7776 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
7777 }
7778 }
7779
7780 /* Remove the GIMPLE_OMP_FOR statement. */
7781 gsi_remove (&gsi, true);
7782
7783 if (!broken_loop)
7784 {
7785 /* Code to control the increment goes in the CONT_BB. */
7786 gsi = gsi_last_bb (cont_bb);
7787 stmt = gsi_stmt (gsi);
7788 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
7789
7790 if (POINTER_TYPE_P (type))
7791 t = fold_build_pointer_plus (fd->loop.v, fd->loop.step);
7792 else
7793 t = fold_build2 (PLUS_EXPR, type, fd->loop.v, fd->loop.step);
7794 expand_omp_build_assign (&gsi, fd->loop.v, t);
7795
7796 if (fd->collapse > 1)
7797 {
7798 i = fd->collapse - 1;
7799 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v)))
7800 {
7801 t = fold_convert (sizetype, fd->loops[i].step);
7802 t = fold_build_pointer_plus (fd->loops[i].v, t);
7803 }
7804 else
7805 {
7806 t = fold_convert (TREE_TYPE (fd->loops[i].v),
7807 fd->loops[i].step);
7808 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loops[i].v),
7809 fd->loops[i].v, t);
7810 }
7811 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
7812
7813 for (i = fd->collapse - 1; i > 0; i--)
7814 {
7815 tree itype = TREE_TYPE (fd->loops[i].v);
7816 tree itype2 = TREE_TYPE (fd->loops[i - 1].v);
7817 if (POINTER_TYPE_P (itype2))
7818 itype2 = signed_type_for (itype2);
7819 t = build3 (COND_EXPR, itype2,
7820 build2 (fd->loops[i].cond_code, boolean_type_node,
7821 fd->loops[i].v,
7822 fold_convert (itype, fd->loops[i].n2)),
7823 build_int_cst (itype2, 0),
7824 fold_convert (itype2, fd->loops[i - 1].step));
7825 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i - 1].v)))
7826 t = fold_build_pointer_plus (fd->loops[i - 1].v, t);
7827 else
7828 t = fold_build2 (PLUS_EXPR, itype2, fd->loops[i - 1].v, t);
7829 expand_omp_build_assign (&gsi, fd->loops[i - 1].v, t);
7830
7831 t = build3 (COND_EXPR, itype,
7832 build2 (fd->loops[i].cond_code, boolean_type_node,
7833 fd->loops[i].v,
7834 fold_convert (itype, fd->loops[i].n2)),
7835 fd->loops[i].v,
7836 fold_convert (itype, fd->loops[i].n1));
7837 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
7838 }
7839 }
7840
7841 /* Remove GIMPLE_OMP_CONTINUE. */
7842 gsi_remove (&gsi, true);
7843 }
7844
7845 /* Emit the condition in L1_BB. */
7846 gsi = gsi_start_bb (l1_bb);
7847
7848 t = fold_convert (type, n2);
7849 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7850 false, GSI_CONTINUE_LINKING);
7851 t = build2 (fd->loop.cond_code, boolean_type_node, fd->loop.v, t);
1a91d914 7852 cond_stmt = gimple_build_cond_empty (t);
7853 gsi_insert_after (&gsi, cond_stmt, GSI_CONTINUE_LINKING);
7854 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt), expand_omp_regimplify_p,
3d483a94 7855 NULL, NULL)
1a91d914 7856 || walk_tree (gimple_cond_rhs_ptr (cond_stmt), expand_omp_regimplify_p,
3d483a94 7857 NULL, NULL))
7858 {
1a91d914 7859 gsi = gsi_for_stmt (cond_stmt);
7860 gimple_regimplify_operands (cond_stmt, &gsi);
3d483a94 7861 }
7862
7863 /* Remove GIMPLE_OMP_RETURN. */
7864 gsi = gsi_last_bb (exit_bb);
7865 gsi_remove (&gsi, true);
7866
7867 /* Connect the new blocks. */
7868 remove_edge (FALLTHRU_EDGE (entry_bb));
7869
7870 if (!broken_loop)
7871 {
7872 remove_edge (BRANCH_EDGE (entry_bb));
7873 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
7874
7875 e = BRANCH_EDGE (l1_bb);
7876 ne = FALLTHRU_EDGE (l1_bb);
7877 e->flags = EDGE_TRUE_VALUE;
7878 }
7879 else
7880 {
7881 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7882
7883 ne = single_succ_edge (l1_bb);
7884 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
7885
7886 }
7887 ne->flags = EDGE_FALSE_VALUE;
7888 e->probability = REG_BR_PROB_BASE * 7 / 8;
7889 ne->probability = REG_BR_PROB_BASE / 8;
7890
7891 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
7892 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
7893 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
7894
7895 if (!broken_loop)
7896 {
7897 struct loop *loop = alloc_loop ();
7898 loop->header = l1_bb;
33ee4d72 7899 loop->latch = cont_bb;
3d483a94 7900 add_loop (loop, l1_bb->loop_father);
7901 if (safelen == NULL_TREE)
7902 loop->safelen = INT_MAX;
7903 else
7904 {
7905 safelen = OMP_CLAUSE_SAFELEN_EXPR (safelen);
c3f3b68d 7906 if (TREE_CODE (safelen) != INTEGER_CST)
7907 loop->safelen = 0;
7908 else if (!tree_fits_uhwi_p (safelen)
7909 || tree_to_uhwi (safelen) > INT_MAX)
3d483a94 7910 loop->safelen = INT_MAX;
7911 else
d85a2013 7912 loop->safelen = tree_to_uhwi (safelen);
3d483a94 7913 if (loop->safelen == 1)
7914 loop->safelen = 0;
7915 }
7916 if (simduid)
7917 {
7918 loop->simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
7919 cfun->has_simduid_loops = true;
7920 }
043115ec 7921 /* If not -fno-tree-loop-vectorize, hint that we want to vectorize
3d483a94 7922 the loop. */
043115ec 7923 if ((flag_tree_loop_vectorize
7924 || (!global_options_set.x_flag_tree_loop_vectorize
7925 && !global_options_set.x_flag_tree_vectorize))
ad45e43e 7926 && flag_tree_loop_optimize
3d483a94 7927 && loop->safelen > 1)
7928 {
4c73695b 7929 loop->force_vectorize = true;
7930 cfun->has_force_vectorize_loops = true;
3d483a94 7931 }
7932 }
9918db44 7933 else if (simduid)
7934 cfun->has_simduid_loops = true;
3d483a94 7935}
7936
1e8e9920 7937
ca4c3545 7938/* Expand the OMP loop defined by REGION. */
1e8e9920 7939
773c5ba7 7940static void
42acab1c 7941expand_omp_for (struct omp_region *region, gimple *inner_stmt)
773c5ba7 7942{
7943 struct omp_for_data fd;
fd6481cf 7944 struct omp_for_data_loop *loops;
1e8e9920 7945
fd6481cf 7946 loops
7947 = (struct omp_for_data_loop *)
75a70cf9 7948 alloca (gimple_omp_for_collapse (last_stmt (region->entry))
fd6481cf 7949 * sizeof (struct omp_for_data_loop));
1a91d914 7950 extract_omp_for_data (as_a <gomp_for *> (last_stmt (region->entry)),
7951 &fd, loops);
f77459c5 7952 region->sched_kind = fd.sched_kind;
1e8e9920 7953
b3a3ddec 7954 gcc_assert (EDGE_COUNT (region->entry->succs) == 2);
7955 BRANCH_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
7956 FALLTHRU_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
7957 if (region->cont)
7958 {
7959 gcc_assert (EDGE_COUNT (region->cont->succs) == 2);
7960 BRANCH_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
7961 FALLTHRU_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
7962 }
04c2922b 7963 else
75de4aa2 7964 /* If there isn't a continue then this is a degerate case where
04c2922b 7965 the introduction of abnormal edges during lowering will prevent
7966 original loops from being detected. Fix that up. */
7967 loops_state_set (LOOPS_NEED_FIXUP);
b3a3ddec 7968
10c55644 7969 if (gimple_omp_for_kind (fd.for_stmt) & GF_OMP_FOR_SIMD)
3d483a94 7970 expand_omp_simd (region, &fd);
40750995 7971 else if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_CILKFOR)
7972 expand_cilk_for (region, &fd);
3d483a94 7973 else if (fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
bc7bff74 7974 && !fd.have_ordered)
1e8e9920 7975 {
7976 if (fd.chunk_size == NULL)
bc7bff74 7977 expand_omp_for_static_nochunk (region, &fd, inner_stmt);
1e8e9920 7978 else
bc7bff74 7979 expand_omp_for_static_chunk (region, &fd, inner_stmt);
1e8e9920 7980 }
7981 else
7982 {
fd6481cf 7983 int fn_index, start_ix, next_ix;
7984
3d483a94 7985 gcc_assert (gimple_omp_for_kind (fd.for_stmt)
7986 == GF_OMP_FOR_KIND_FOR);
0416ca72 7987 if (fd.chunk_size == NULL
7988 && fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
7989 fd.chunk_size = integer_zero_node;
fd6481cf 7990 gcc_assert (fd.sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
7991 fn_index = (fd.sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
75a70cf9 7992 ? 3 : fd.sched_kind;
fd6481cf 7993 fn_index += fd.have_ordered * 4;
b9a16870 7994 start_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_START) + fn_index;
7995 next_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_NEXT) + fn_index;
fd6481cf 7996 if (fd.iter_type == long_long_unsigned_type_node)
7997 {
b9a16870 7998 start_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_START
7999 - (int)BUILT_IN_GOMP_LOOP_STATIC_START);
8000 next_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_NEXT
8001 - (int)BUILT_IN_GOMP_LOOP_STATIC_NEXT);
fd6481cf 8002 }
b9c74b4d 8003 expand_omp_for_generic (region, &fd, (enum built_in_function) start_ix,
bc7bff74 8004 (enum built_in_function) next_ix, inner_stmt);
1e8e9920 8005 }
28c92cbb 8006
083152fb 8007 if (gimple_in_ssa_p (cfun))
8008 update_ssa (TODO_update_ssa_only_virtuals);
1e8e9920 8009}
8010
1e8e9920 8011
8012/* Expand code for an OpenMP sections directive. In pseudo code, we generate
8013
1e8e9920 8014 v = GOMP_sections_start (n);
8015 L0:
8016 switch (v)
8017 {
8018 case 0:
8019 goto L2;
8020 case 1:
8021 section 1;
8022 goto L1;
8023 case 2:
8024 ...
8025 case n:
8026 ...
1e8e9920 8027 default:
8028 abort ();
8029 }
8030 L1:
8031 v = GOMP_sections_next ();
8032 goto L0;
8033 L2:
8034 reduction;
8035
773c5ba7 8036 If this is a combined parallel sections, replace the call to
79acaae1 8037 GOMP_sections_start with call to GOMP_sections_next. */
1e8e9920 8038
8039static void
773c5ba7 8040expand_omp_sections (struct omp_region *region)
1e8e9920 8041{
f018d957 8042 tree t, u, vin = NULL, vmain, vnext, l2;
75a70cf9 8043 unsigned len;
ac6e3339 8044 basic_block entry_bb, l0_bb, l1_bb, l2_bb, default_bb;
75a70cf9 8045 gimple_stmt_iterator si, switch_si;
1a91d914 8046 gomp_sections *sections_stmt;
42acab1c 8047 gimple *stmt;
1a91d914 8048 gomp_continue *cont;
9884aaf8 8049 edge_iterator ei;
8050 edge e;
61e47ac8 8051 struct omp_region *inner;
75a70cf9 8052 unsigned i, casei;
ac6e3339 8053 bool exit_reachable = region->cont != NULL;
1e8e9920 8054
d244d9de 8055 gcc_assert (region->exit != NULL);
61e47ac8 8056 entry_bb = region->entry;
ac6e3339 8057 l0_bb = single_succ (entry_bb);
61e47ac8 8058 l1_bb = region->cont;
ac6e3339 8059 l2_bb = region->exit;
d244d9de 8060 if (single_pred_p (l2_bb) && single_pred (l2_bb) == l0_bb)
8061 l2 = gimple_block_label (l2_bb);
8062 else
03ed154b 8063 {
d244d9de 8064 /* This can happen if there are reductions. */
8065 len = EDGE_COUNT (l0_bb->succs);
8066 gcc_assert (len > 0);
8067 e = EDGE_SUCC (l0_bb, len - 1);
8068 si = gsi_last_bb (e->dest);
8069 l2 = NULL_TREE;
8070 if (gsi_end_p (si)
8071 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
8072 l2 = gimple_block_label (e->dest);
9884aaf8 8073 else
d244d9de 8074 FOR_EACH_EDGE (e, ei, l0_bb->succs)
8075 {
8076 si = gsi_last_bb (e->dest);
8077 if (gsi_end_p (si)
8078 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
9884aaf8 8079 {
d244d9de 8080 l2 = gimple_block_label (e->dest);
8081 break;
9884aaf8 8082 }
d244d9de 8083 }
03ed154b 8084 }
d244d9de 8085 if (exit_reachable)
8086 default_bb = create_empty_bb (l1_bb->prev_bb);
03ed154b 8087 else
d244d9de 8088 default_bb = create_empty_bb (l0_bb);
773c5ba7 8089
8090 /* We will build a switch() with enough cases for all the
75a70cf9 8091 GIMPLE_OMP_SECTION regions, a '0' case to handle the end of more work
773c5ba7 8092 and a default case to abort if something goes wrong. */
ac6e3339 8093 len = EDGE_COUNT (l0_bb->succs);
75a70cf9 8094
f1f41a6c 8095 /* Use vec::quick_push on label_vec throughout, since we know the size
75a70cf9 8096 in advance. */
c2078b80 8097 auto_vec<tree> label_vec (len);
1e8e9920 8098
61e47ac8 8099 /* The call to GOMP_sections_start goes in ENTRY_BB, replacing the
75a70cf9 8100 GIMPLE_OMP_SECTIONS statement. */
8101 si = gsi_last_bb (entry_bb);
1a91d914 8102 sections_stmt = as_a <gomp_sections *> (gsi_stmt (si));
75a70cf9 8103 gcc_assert (gimple_code (sections_stmt) == GIMPLE_OMP_SECTIONS);
8104 vin = gimple_omp_sections_control (sections_stmt);
773c5ba7 8105 if (!is_combined_parallel (region))
1e8e9920 8106 {
773c5ba7 8107 /* If we are not inside a combined parallel+sections region,
8108 call GOMP_sections_start. */
39cb6d68 8109 t = build_int_cst (unsigned_type_node, len - 1);
b9a16870 8110 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_START);
75a70cf9 8111 stmt = gimple_build_call (u, 1, t);
1e8e9920 8112 }
79acaae1 8113 else
8114 {
8115 /* Otherwise, call GOMP_sections_next. */
b9a16870 8116 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
75a70cf9 8117 stmt = gimple_build_call (u, 0);
79acaae1 8118 }
75a70cf9 8119 gimple_call_set_lhs (stmt, vin);
8120 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
8121 gsi_remove (&si, true);
8122
8123 /* The switch() statement replacing GIMPLE_OMP_SECTIONS_SWITCH goes in
8124 L0_BB. */
8125 switch_si = gsi_last_bb (l0_bb);
8126 gcc_assert (gimple_code (gsi_stmt (switch_si)) == GIMPLE_OMP_SECTIONS_SWITCH);
79acaae1 8127 if (exit_reachable)
8128 {
1a91d914 8129 cont = as_a <gomp_continue *> (last_stmt (l1_bb));
75a70cf9 8130 gcc_assert (gimple_code (cont) == GIMPLE_OMP_CONTINUE);
8131 vmain = gimple_omp_continue_control_use (cont);
8132 vnext = gimple_omp_continue_control_def (cont);
79acaae1 8133 }
8134 else
8135 {
8136 vmain = vin;
8137 vnext = NULL_TREE;
8138 }
1e8e9920 8139
d244d9de 8140 t = build_case_label (build_int_cst (unsigned_type_node, 0), NULL, l2);
f1f41a6c 8141 label_vec.quick_push (t);
d244d9de 8142 i = 1;
03ed154b 8143
75a70cf9 8144 /* Convert each GIMPLE_OMP_SECTION into a CASE_LABEL_EXPR. */
ac6e3339 8145 for (inner = region->inner, casei = 1;
8146 inner;
8147 inner = inner->next, i++, casei++)
1e8e9920 8148 {
773c5ba7 8149 basic_block s_entry_bb, s_exit_bb;
8150
9884aaf8 8151 /* Skip optional reduction region. */
75a70cf9 8152 if (inner->type == GIMPLE_OMP_ATOMIC_LOAD)
9884aaf8 8153 {
8154 --i;
8155 --casei;
8156 continue;
8157 }
8158
61e47ac8 8159 s_entry_bb = inner->entry;
8160 s_exit_bb = inner->exit;
1e8e9920 8161
75a70cf9 8162 t = gimple_block_label (s_entry_bb);
ac6e3339 8163 u = build_int_cst (unsigned_type_node, casei);
b6e3dd65 8164 u = build_case_label (u, NULL, t);
f1f41a6c 8165 label_vec.quick_push (u);
61e47ac8 8166
75a70cf9 8167 si = gsi_last_bb (s_entry_bb);
8168 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SECTION);
8169 gcc_assert (i < len || gimple_omp_section_last_p (gsi_stmt (si)));
8170 gsi_remove (&si, true);
61e47ac8 8171 single_succ_edge (s_entry_bb)->flags = EDGE_FALLTHRU;
03ed154b 8172
8173 if (s_exit_bb == NULL)
8174 continue;
8175
75a70cf9 8176 si = gsi_last_bb (s_exit_bb);
8177 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
8178 gsi_remove (&si, true);
03ed154b 8179
773c5ba7 8180 single_succ_edge (s_exit_bb)->flags = EDGE_FALLTHRU;
1e8e9920 8181 }
8182
773c5ba7 8183 /* Error handling code goes in DEFAULT_BB. */
75a70cf9 8184 t = gimple_block_label (default_bb);
b6e3dd65 8185 u = build_case_label (NULL, NULL, t);
61e47ac8 8186 make_edge (l0_bb, default_bb, 0);
b3083327 8187 add_bb_to_loop (default_bb, current_loops->tree_root);
1e8e9920 8188
49a70175 8189 stmt = gimple_build_switch (vmain, u, label_vec);
75a70cf9 8190 gsi_insert_after (&switch_si, stmt, GSI_SAME_STMT);
8191 gsi_remove (&switch_si, true);
75a70cf9 8192
8193 si = gsi_start_bb (default_bb);
b9a16870 8194 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
75a70cf9 8195 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
773c5ba7 8196
ac6e3339 8197 if (exit_reachable)
03ed154b 8198 {
b9a16870 8199 tree bfn_decl;
8200
ac6e3339 8201 /* Code to get the next section goes in L1_BB. */
75a70cf9 8202 si = gsi_last_bb (l1_bb);
8203 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CONTINUE);
1e8e9920 8204
b9a16870 8205 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
8206 stmt = gimple_build_call (bfn_decl, 0);
75a70cf9 8207 gimple_call_set_lhs (stmt, vnext);
8208 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
8209 gsi_remove (&si, true);
773c5ba7 8210
ac6e3339 8211 single_succ_edge (l1_bb)->flags = EDGE_FALLTHRU;
03ed154b 8212 }
773c5ba7 8213
d244d9de 8214 /* Cleanup function replaces GIMPLE_OMP_RETURN in EXIT_BB. */
8215 si = gsi_last_bb (l2_bb);
8216 if (gimple_omp_return_nowait_p (gsi_stmt (si)))
8217 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_NOWAIT);
bc7bff74 8218 else if (gimple_omp_return_lhs (gsi_stmt (si)))
8219 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_CANCEL);
d244d9de 8220 else
8221 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END);
8222 stmt = gimple_build_call (t, 0);
bc7bff74 8223 if (gimple_omp_return_lhs (gsi_stmt (si)))
8224 gimple_call_set_lhs (stmt, gimple_omp_return_lhs (gsi_stmt (si)));
d244d9de 8225 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
8226 gsi_remove (&si, true);
8227
79acaae1 8228 set_immediate_dominator (CDI_DOMINATORS, default_bb, l0_bb);
773c5ba7 8229}
1e8e9920 8230
1e8e9920 8231
61e47ac8 8232/* Expand code for an OpenMP single directive. We've already expanded
8233 much of the code, here we simply place the GOMP_barrier call. */
8234
8235static void
8236expand_omp_single (struct omp_region *region)
8237{
8238 basic_block entry_bb, exit_bb;
75a70cf9 8239 gimple_stmt_iterator si;
61e47ac8 8240
8241 entry_bb = region->entry;
8242 exit_bb = region->exit;
8243
75a70cf9 8244 si = gsi_last_bb (entry_bb);
75a70cf9 8245 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE);
8246 gsi_remove (&si, true);
61e47ac8 8247 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
8248
75a70cf9 8249 si = gsi_last_bb (exit_bb);
bc7bff74 8250 if (!gimple_omp_return_nowait_p (gsi_stmt (si)))
8251 {
8252 tree t = gimple_omp_return_lhs (gsi_stmt (si));
8253 gsi_insert_after (&si, build_omp_barrier (t), GSI_SAME_STMT);
8254 }
75a70cf9 8255 gsi_remove (&si, true);
61e47ac8 8256 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
8257}
8258
8259
8260/* Generic expansion for OpenMP synchronization directives: master,
8261 ordered and critical. All we need to do here is remove the entry
8262 and exit markers for REGION. */
773c5ba7 8263
8264static void
8265expand_omp_synch (struct omp_region *region)
8266{
8267 basic_block entry_bb, exit_bb;
75a70cf9 8268 gimple_stmt_iterator si;
773c5ba7 8269
61e47ac8 8270 entry_bb = region->entry;
8271 exit_bb = region->exit;
773c5ba7 8272
75a70cf9 8273 si = gsi_last_bb (entry_bb);
8274 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE
8275 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_MASTER
bc7bff74 8276 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TASKGROUP
75a70cf9 8277 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ORDERED
bc7bff74 8278 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CRITICAL
8279 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TEAMS);
75a70cf9 8280 gsi_remove (&si, true);
773c5ba7 8281 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
8282
03ed154b 8283 if (exit_bb)
8284 {
75a70cf9 8285 si = gsi_last_bb (exit_bb);
8286 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
8287 gsi_remove (&si, true);
03ed154b 8288 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
8289 }
773c5ba7 8290}
1e8e9920 8291
2169f33b 8292/* A subroutine of expand_omp_atomic. Attempt to implement the atomic
8293 operation as a normal volatile load. */
8294
8295static bool
3ec11c49 8296expand_omp_atomic_load (basic_block load_bb, tree addr,
8297 tree loaded_val, int index)
2169f33b 8298{
3ec11c49 8299 enum built_in_function tmpbase;
8300 gimple_stmt_iterator gsi;
8301 basic_block store_bb;
8302 location_t loc;
42acab1c 8303 gimple *stmt;
3ec11c49 8304 tree decl, call, type, itype;
8305
8306 gsi = gsi_last_bb (load_bb);
8307 stmt = gsi_stmt (gsi);
8308 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
8309 loc = gimple_location (stmt);
8310
8311 /* ??? If the target does not implement atomic_load_optab[mode], and mode
8312 is smaller than word size, then expand_atomic_load assumes that the load
8313 is atomic. We could avoid the builtin entirely in this case. */
8314
8315 tmpbase = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
8316 decl = builtin_decl_explicit (tmpbase);
8317 if (decl == NULL_TREE)
8318 return false;
8319
8320 type = TREE_TYPE (loaded_val);
8321 itype = TREE_TYPE (TREE_TYPE (decl));
8322
8323 call = build_call_expr_loc (loc, decl, 2, addr,
bc7bff74 8324 build_int_cst (NULL,
8325 gimple_omp_atomic_seq_cst_p (stmt)
8326 ? MEMMODEL_SEQ_CST
8327 : MEMMODEL_RELAXED));
3ec11c49 8328 if (!useless_type_conversion_p (type, itype))
8329 call = fold_build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
8330 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
8331
8332 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
8333 gsi_remove (&gsi, true);
8334
8335 store_bb = single_succ (load_bb);
8336 gsi = gsi_last_bb (store_bb);
8337 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
8338 gsi_remove (&gsi, true);
8339
8340 if (gimple_in_ssa_p (cfun))
8341 update_ssa (TODO_update_ssa_no_phi);
8342
8343 return true;
2169f33b 8344}
8345
8346/* A subroutine of expand_omp_atomic. Attempt to implement the atomic
8347 operation as a normal volatile store. */
8348
8349static bool
3ec11c49 8350expand_omp_atomic_store (basic_block load_bb, tree addr,
8351 tree loaded_val, tree stored_val, int index)
2169f33b 8352{
3ec11c49 8353 enum built_in_function tmpbase;
8354 gimple_stmt_iterator gsi;
8355 basic_block store_bb = single_succ (load_bb);
8356 location_t loc;
42acab1c 8357 gimple *stmt;
3ec11c49 8358 tree decl, call, type, itype;
3754d046 8359 machine_mode imode;
3ec11c49 8360 bool exchange;
8361
8362 gsi = gsi_last_bb (load_bb);
8363 stmt = gsi_stmt (gsi);
8364 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
8365
8366 /* If the load value is needed, then this isn't a store but an exchange. */
8367 exchange = gimple_omp_atomic_need_value_p (stmt);
8368
8369 gsi = gsi_last_bb (store_bb);
8370 stmt = gsi_stmt (gsi);
8371 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE);
8372 loc = gimple_location (stmt);
8373
8374 /* ??? If the target does not implement atomic_store_optab[mode], and mode
8375 is smaller than word size, then expand_atomic_store assumes that the store
8376 is atomic. We could avoid the builtin entirely in this case. */
8377
8378 tmpbase = (exchange ? BUILT_IN_ATOMIC_EXCHANGE_N : BUILT_IN_ATOMIC_STORE_N);
8379 tmpbase = (enum built_in_function) ((int) tmpbase + index + 1);
8380 decl = builtin_decl_explicit (tmpbase);
8381 if (decl == NULL_TREE)
8382 return false;
8383
8384 type = TREE_TYPE (stored_val);
8385
8386 /* Dig out the type of the function's second argument. */
8387 itype = TREE_TYPE (decl);
8388 itype = TYPE_ARG_TYPES (itype);
8389 itype = TREE_CHAIN (itype);
8390 itype = TREE_VALUE (itype);
8391 imode = TYPE_MODE (itype);
8392
8393 if (exchange && !can_atomic_exchange_p (imode, true))
8394 return false;
8395
8396 if (!useless_type_conversion_p (itype, type))
8397 stored_val = fold_build1_loc (loc, VIEW_CONVERT_EXPR, itype, stored_val);
8398 call = build_call_expr_loc (loc, decl, 3, addr, stored_val,
bc7bff74 8399 build_int_cst (NULL,
8400 gimple_omp_atomic_seq_cst_p (stmt)
8401 ? MEMMODEL_SEQ_CST
8402 : MEMMODEL_RELAXED));
3ec11c49 8403 if (exchange)
8404 {
8405 if (!useless_type_conversion_p (type, itype))
8406 call = build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
8407 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
8408 }
8409
8410 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
8411 gsi_remove (&gsi, true);
8412
8413 /* Remove the GIMPLE_OMP_ATOMIC_LOAD that we verified above. */
8414 gsi = gsi_last_bb (load_bb);
8415 gsi_remove (&gsi, true);
8416
8417 if (gimple_in_ssa_p (cfun))
8418 update_ssa (TODO_update_ssa_no_phi);
8419
8420 return true;
2169f33b 8421}
8422
cb7f680b 8423/* A subroutine of expand_omp_atomic. Attempt to implement the atomic
1cd6e20d 8424 operation as a __atomic_fetch_op builtin. INDEX is log2 of the
cb7f680b 8425 size of the data type, and thus usable to find the index of the builtin
8426 decl. Returns false if the expression is not of the proper form. */
8427
8428static bool
8429expand_omp_atomic_fetch_op (basic_block load_bb,
8430 tree addr, tree loaded_val,
8431 tree stored_val, int index)
8432{
b9a16870 8433 enum built_in_function oldbase, newbase, tmpbase;
cb7f680b 8434 tree decl, itype, call;
2169f33b 8435 tree lhs, rhs;
cb7f680b 8436 basic_block store_bb = single_succ (load_bb);
75a70cf9 8437 gimple_stmt_iterator gsi;
42acab1c 8438 gimple *stmt;
389dd41b 8439 location_t loc;
1cd6e20d 8440 enum tree_code code;
2169f33b 8441 bool need_old, need_new;
3754d046 8442 machine_mode imode;
bc7bff74 8443 bool seq_cst;
cb7f680b 8444
8445 /* We expect to find the following sequences:
48e1416a 8446
cb7f680b 8447 load_bb:
75a70cf9 8448 GIMPLE_OMP_ATOMIC_LOAD (tmp, mem)
cb7f680b 8449
8450 store_bb:
8451 val = tmp OP something; (or: something OP tmp)
48e1416a 8452 GIMPLE_OMP_STORE (val)
cb7f680b 8453
48e1416a 8454 ???FIXME: Allow a more flexible sequence.
cb7f680b 8455 Perhaps use data flow to pick the statements.
48e1416a 8456
cb7f680b 8457 */
8458
75a70cf9 8459 gsi = gsi_after_labels (store_bb);
8460 stmt = gsi_stmt (gsi);
389dd41b 8461 loc = gimple_location (stmt);
75a70cf9 8462 if (!is_gimple_assign (stmt))
cb7f680b 8463 return false;
75a70cf9 8464 gsi_next (&gsi);
8465 if (gimple_code (gsi_stmt (gsi)) != GIMPLE_OMP_ATOMIC_STORE)
cb7f680b 8466 return false;
2169f33b 8467 need_new = gimple_omp_atomic_need_value_p (gsi_stmt (gsi));
8468 need_old = gimple_omp_atomic_need_value_p (last_stmt (load_bb));
bc7bff74 8469 seq_cst = gimple_omp_atomic_seq_cst_p (last_stmt (load_bb));
2169f33b 8470 gcc_checking_assert (!need_old || !need_new);
cb7f680b 8471
75a70cf9 8472 if (!operand_equal_p (gimple_assign_lhs (stmt), stored_val, 0))
cb7f680b 8473 return false;
8474
cb7f680b 8475 /* Check for one of the supported fetch-op operations. */
1cd6e20d 8476 code = gimple_assign_rhs_code (stmt);
8477 switch (code)
cb7f680b 8478 {
8479 case PLUS_EXPR:
8480 case POINTER_PLUS_EXPR:
1cd6e20d 8481 oldbase = BUILT_IN_ATOMIC_FETCH_ADD_N;
8482 newbase = BUILT_IN_ATOMIC_ADD_FETCH_N;
cb7f680b 8483 break;
8484 case MINUS_EXPR:
1cd6e20d 8485 oldbase = BUILT_IN_ATOMIC_FETCH_SUB_N;
8486 newbase = BUILT_IN_ATOMIC_SUB_FETCH_N;
cb7f680b 8487 break;
8488 case BIT_AND_EXPR:
1cd6e20d 8489 oldbase = BUILT_IN_ATOMIC_FETCH_AND_N;
8490 newbase = BUILT_IN_ATOMIC_AND_FETCH_N;
cb7f680b 8491 break;
8492 case BIT_IOR_EXPR:
1cd6e20d 8493 oldbase = BUILT_IN_ATOMIC_FETCH_OR_N;
8494 newbase = BUILT_IN_ATOMIC_OR_FETCH_N;
cb7f680b 8495 break;
8496 case BIT_XOR_EXPR:
1cd6e20d 8497 oldbase = BUILT_IN_ATOMIC_FETCH_XOR_N;
8498 newbase = BUILT_IN_ATOMIC_XOR_FETCH_N;
cb7f680b 8499 break;
8500 default:
8501 return false;
8502 }
1cd6e20d 8503
cb7f680b 8504 /* Make sure the expression is of the proper form. */
75a70cf9 8505 if (operand_equal_p (gimple_assign_rhs1 (stmt), loaded_val, 0))
8506 rhs = gimple_assign_rhs2 (stmt);
8507 else if (commutative_tree_code (gimple_assign_rhs_code (stmt))
8508 && operand_equal_p (gimple_assign_rhs2 (stmt), loaded_val, 0))
8509 rhs = gimple_assign_rhs1 (stmt);
cb7f680b 8510 else
8511 return false;
8512
b9a16870 8513 tmpbase = ((enum built_in_function)
8514 ((need_new ? newbase : oldbase) + index + 1));
8515 decl = builtin_decl_explicit (tmpbase);
0f94f46b 8516 if (decl == NULL_TREE)
8517 return false;
cb7f680b 8518 itype = TREE_TYPE (TREE_TYPE (decl));
1cd6e20d 8519 imode = TYPE_MODE (itype);
cb7f680b 8520
1cd6e20d 8521 /* We could test all of the various optabs involved, but the fact of the
8522 matter is that (with the exception of i486 vs i586 and xadd) all targets
8523 that support any atomic operaton optab also implements compare-and-swap.
8524 Let optabs.c take care of expanding any compare-and-swap loop. */
29139cdc 8525 if (!can_compare_and_swap_p (imode, true))
cb7f680b 8526 return false;
8527
75a70cf9 8528 gsi = gsi_last_bb (load_bb);
8529 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_LOAD);
1cd6e20d 8530
8531 /* OpenMP does not imply any barrier-like semantics on its atomic ops.
8532 It only requires that the operation happen atomically. Thus we can
8533 use the RELAXED memory model. */
8534 call = build_call_expr_loc (loc, decl, 3, addr,
8535 fold_convert_loc (loc, itype, rhs),
bc7bff74 8536 build_int_cst (NULL,
8537 seq_cst ? MEMMODEL_SEQ_CST
8538 : MEMMODEL_RELAXED));
1cd6e20d 8539
2169f33b 8540 if (need_old || need_new)
8541 {
8542 lhs = need_old ? loaded_val : stored_val;
8543 call = fold_convert_loc (loc, TREE_TYPE (lhs), call);
8544 call = build2_loc (loc, MODIFY_EXPR, void_type_node, lhs, call);
8545 }
8546 else
8547 call = fold_convert_loc (loc, void_type_node, call);
75a70cf9 8548 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
8549 gsi_remove (&gsi, true);
cb7f680b 8550
75a70cf9 8551 gsi = gsi_last_bb (store_bb);
8552 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
8553 gsi_remove (&gsi, true);
8554 gsi = gsi_last_bb (store_bb);
8555 gsi_remove (&gsi, true);
cb7f680b 8556
8557 if (gimple_in_ssa_p (cfun))
8558 update_ssa (TODO_update_ssa_no_phi);
8559
8560 return true;
8561}
8562
8563/* A subroutine of expand_omp_atomic. Implement the atomic operation as:
8564
8565 oldval = *addr;
8566 repeat:
8567 newval = rhs; // with oldval replacing *addr in rhs
8568 oldval = __sync_val_compare_and_swap (addr, oldval, newval);
8569 if (oldval != newval)
8570 goto repeat;
8571
8572 INDEX is log2 of the size of the data type, and thus usable to find the
8573 index of the builtin decl. */
8574
8575static bool
8576expand_omp_atomic_pipeline (basic_block load_bb, basic_block store_bb,
8577 tree addr, tree loaded_val, tree stored_val,
8578 int index)
8579{
790368c5 8580 tree loadedi, storedi, initial, new_storedi, old_vali;
cb7f680b 8581 tree type, itype, cmpxchg, iaddr;
75a70cf9 8582 gimple_stmt_iterator si;
cb7f680b 8583 basic_block loop_header = single_succ (load_bb);
42acab1c 8584 gimple *phi, *stmt;
cb7f680b 8585 edge e;
b9a16870 8586 enum built_in_function fncode;
cb7f680b 8587
1cd6e20d 8588 /* ??? We need a non-pointer interface to __atomic_compare_exchange in
8589 order to use the RELAXED memory model effectively. */
b9a16870 8590 fncode = (enum built_in_function)((int)BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_N
8591 + index + 1);
8592 cmpxchg = builtin_decl_explicit (fncode);
0f94f46b 8593 if (cmpxchg == NULL_TREE)
8594 return false;
cb7f680b 8595 type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
8596 itype = TREE_TYPE (TREE_TYPE (cmpxchg));
8597
29139cdc 8598 if (!can_compare_and_swap_p (TYPE_MODE (itype), true))
cb7f680b 8599 return false;
8600
75a70cf9 8601 /* Load the initial value, replacing the GIMPLE_OMP_ATOMIC_LOAD. */
8602 si = gsi_last_bb (load_bb);
8603 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
8604
790368c5 8605 /* For floating-point values, we'll need to view-convert them to integers
8606 so that we can perform the atomic compare and swap. Simplify the
8607 following code by always setting up the "i"ntegral variables. */
8608 if (!INTEGRAL_TYPE_P (type) && !POINTER_TYPE_P (type))
8609 {
75a70cf9 8610 tree iaddr_val;
8611
072f7ab1 8612 iaddr = create_tmp_reg (build_pointer_type_for_mode (itype, ptr_mode,
f9e245b2 8613 true));
75a70cf9 8614 iaddr_val
8615 = force_gimple_operand_gsi (&si,
8616 fold_convert (TREE_TYPE (iaddr), addr),
8617 false, NULL_TREE, true, GSI_SAME_STMT);
8618 stmt = gimple_build_assign (iaddr, iaddr_val);
8619 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
f9e245b2 8620 loadedi = create_tmp_var (itype);
790368c5 8621 if (gimple_in_ssa_p (cfun))
f9e245b2 8622 loadedi = make_ssa_name (loadedi);
790368c5 8623 }
8624 else
8625 {
8626 iaddr = addr;
8627 loadedi = loaded_val;
8628 }
75a70cf9 8629
2ed72821 8630 fncode = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
8631 tree loaddecl = builtin_decl_explicit (fncode);
8632 if (loaddecl)
8633 initial
8634 = fold_convert (TREE_TYPE (TREE_TYPE (iaddr)),
8635 build_call_expr (loaddecl, 2, iaddr,
8636 build_int_cst (NULL_TREE,
8637 MEMMODEL_RELAXED)));
8638 else
8639 initial = build2 (MEM_REF, TREE_TYPE (TREE_TYPE (iaddr)), iaddr,
8640 build_int_cst (TREE_TYPE (iaddr), 0));
8641
182cf5a9 8642 initial
2ed72821 8643 = force_gimple_operand_gsi (&si, initial, true, NULL_TREE, true,
8644 GSI_SAME_STMT);
790368c5 8645
8646 /* Move the value to the LOADEDI temporary. */
cb7f680b 8647 if (gimple_in_ssa_p (cfun))
8648 {
75a70cf9 8649 gcc_assert (gimple_seq_empty_p (phi_nodes (loop_header)));
790368c5 8650 phi = create_phi_node (loadedi, loop_header);
cb7f680b 8651 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, single_succ_edge (load_bb)),
8652 initial);
8653 }
8654 else
75a70cf9 8655 gsi_insert_before (&si,
8656 gimple_build_assign (loadedi, initial),
8657 GSI_SAME_STMT);
790368c5 8658 if (loadedi != loaded_val)
8659 {
75a70cf9 8660 gimple_stmt_iterator gsi2;
8661 tree x;
790368c5 8662
8663 x = build1 (VIEW_CONVERT_EXPR, type, loadedi);
75a70cf9 8664 gsi2 = gsi_start_bb (loop_header);
790368c5 8665 if (gimple_in_ssa_p (cfun))
8666 {
1a91d914 8667 gassign *stmt;
75a70cf9 8668 x = force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
8669 true, GSI_SAME_STMT);
8670 stmt = gimple_build_assign (loaded_val, x);
8671 gsi_insert_before (&gsi2, stmt, GSI_SAME_STMT);
790368c5 8672 }
8673 else
8674 {
75a70cf9 8675 x = build2 (MODIFY_EXPR, TREE_TYPE (loaded_val), loaded_val, x);
8676 force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
8677 true, GSI_SAME_STMT);
790368c5 8678 }
8679 }
75a70cf9 8680 gsi_remove (&si, true);
cb7f680b 8681
75a70cf9 8682 si = gsi_last_bb (store_bb);
8683 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
cb7f680b 8684
790368c5 8685 if (iaddr == addr)
8686 storedi = stored_val;
cb7f680b 8687 else
790368c5 8688 storedi =
75a70cf9 8689 force_gimple_operand_gsi (&si,
790368c5 8690 build1 (VIEW_CONVERT_EXPR, itype,
8691 stored_val), true, NULL_TREE, true,
75a70cf9 8692 GSI_SAME_STMT);
cb7f680b 8693
8694 /* Build the compare&swap statement. */
8695 new_storedi = build_call_expr (cmpxchg, 3, iaddr, loadedi, storedi);
75a70cf9 8696 new_storedi = force_gimple_operand_gsi (&si,
87f9ffa4 8697 fold_convert (TREE_TYPE (loadedi),
8698 new_storedi),
cb7f680b 8699 true, NULL_TREE,
75a70cf9 8700 true, GSI_SAME_STMT);
cb7f680b 8701
8702 if (gimple_in_ssa_p (cfun))
8703 old_vali = loadedi;
8704 else
8705 {
f9e245b2 8706 old_vali = create_tmp_var (TREE_TYPE (loadedi));
75a70cf9 8707 stmt = gimple_build_assign (old_vali, loadedi);
8708 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
cb7f680b 8709
75a70cf9 8710 stmt = gimple_build_assign (loadedi, new_storedi);
8711 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
cb7f680b 8712 }
8713
8714 /* Note that we always perform the comparison as an integer, even for
48e1416a 8715 floating point. This allows the atomic operation to properly
cb7f680b 8716 succeed even with NaNs and -0.0. */
75a70cf9 8717 stmt = gimple_build_cond_empty
8718 (build2 (NE_EXPR, boolean_type_node,
8719 new_storedi, old_vali));
8720 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
cb7f680b 8721
8722 /* Update cfg. */
8723 e = single_succ_edge (store_bb);
8724 e->flags &= ~EDGE_FALLTHRU;
8725 e->flags |= EDGE_FALSE_VALUE;
8726
8727 e = make_edge (store_bb, loop_header, EDGE_TRUE_VALUE);
8728
790368c5 8729 /* Copy the new value to loadedi (we already did that before the condition
cb7f680b 8730 if we are not in SSA). */
8731 if (gimple_in_ssa_p (cfun))
8732 {
75a70cf9 8733 phi = gimple_seq_first_stmt (phi_nodes (loop_header));
790368c5 8734 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, e), new_storedi);
cb7f680b 8735 }
8736
75a70cf9 8737 /* Remove GIMPLE_OMP_ATOMIC_STORE. */
8738 gsi_remove (&si, true);
cb7f680b 8739
04c2922b 8740 struct loop *loop = alloc_loop ();
8741 loop->header = loop_header;
5f037457 8742 loop->latch = store_bb;
04c2922b 8743 add_loop (loop, loop_header->loop_father);
8744
cb7f680b 8745 if (gimple_in_ssa_p (cfun))
8746 update_ssa (TODO_update_ssa_no_phi);
8747
8748 return true;
8749}
8750
8751/* A subroutine of expand_omp_atomic. Implement the atomic operation as:
8752
8753 GOMP_atomic_start ();
8754 *addr = rhs;
8755 GOMP_atomic_end ();
8756
8757 The result is not globally atomic, but works so long as all parallel
8758 references are within #pragma omp atomic directives. According to
8759 responses received from omp@openmp.org, appears to be within spec.
8760 Which makes sense, since that's how several other compilers handle
48e1416a 8761 this situation as well.
75a70cf9 8762 LOADED_VAL and ADDR are the operands of GIMPLE_OMP_ATOMIC_LOAD we're
8763 expanding. STORED_VAL is the operand of the matching
8764 GIMPLE_OMP_ATOMIC_STORE.
cb7f680b 8765
48e1416a 8766 We replace
8767 GIMPLE_OMP_ATOMIC_LOAD (loaded_val, addr) with
cb7f680b 8768 loaded_val = *addr;
8769
8770 and replace
3ec11c49 8771 GIMPLE_OMP_ATOMIC_STORE (stored_val) with
48e1416a 8772 *addr = stored_val;
cb7f680b 8773*/
8774
8775static bool
8776expand_omp_atomic_mutex (basic_block load_bb, basic_block store_bb,
8777 tree addr, tree loaded_val, tree stored_val)
8778{
75a70cf9 8779 gimple_stmt_iterator si;
1a91d914 8780 gassign *stmt;
cb7f680b 8781 tree t;
8782
75a70cf9 8783 si = gsi_last_bb (load_bb);
8784 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
cb7f680b 8785
b9a16870 8786 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START);
414c3a2c 8787 t = build_call_expr (t, 0);
75a70cf9 8788 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
cb7f680b 8789
182cf5a9 8790 stmt = gimple_build_assign (loaded_val, build_simple_mem_ref (addr));
75a70cf9 8791 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8792 gsi_remove (&si, true);
cb7f680b 8793
75a70cf9 8794 si = gsi_last_bb (store_bb);
8795 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
cb7f680b 8796
182cf5a9 8797 stmt = gimple_build_assign (build_simple_mem_ref (unshare_expr (addr)),
8798 stored_val);
75a70cf9 8799 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
cb7f680b 8800
b9a16870 8801 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END);
414c3a2c 8802 t = build_call_expr (t, 0);
75a70cf9 8803 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
8804 gsi_remove (&si, true);
cb7f680b 8805
8806 if (gimple_in_ssa_p (cfun))
8807 update_ssa (TODO_update_ssa_no_phi);
8808 return true;
8809}
8810
48e1416a 8811/* Expand an GIMPLE_OMP_ATOMIC statement. We try to expand
8812 using expand_omp_atomic_fetch_op. If it failed, we try to
cb7f680b 8813 call expand_omp_atomic_pipeline, and if it fails too, the
8814 ultimate fallback is wrapping the operation in a mutex
48e1416a 8815 (expand_omp_atomic_mutex). REGION is the atomic region built
8816 by build_omp_regions_1(). */
cb7f680b 8817
8818static void
8819expand_omp_atomic (struct omp_region *region)
8820{
8821 basic_block load_bb = region->entry, store_bb = region->exit;
1a91d914 8822 gomp_atomic_load *load = as_a <gomp_atomic_load *> (last_stmt (load_bb));
8823 gomp_atomic_store *store = as_a <gomp_atomic_store *> (last_stmt (store_bb));
75a70cf9 8824 tree loaded_val = gimple_omp_atomic_load_lhs (load);
8825 tree addr = gimple_omp_atomic_load_rhs (load);
8826 tree stored_val = gimple_omp_atomic_store_val (store);
cb7f680b 8827 tree type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
8828 HOST_WIDE_INT index;
8829
8830 /* Make sure the type is one of the supported sizes. */
e913b5cd 8831 index = tree_to_uhwi (TYPE_SIZE_UNIT (type));
cb7f680b 8832 index = exact_log2 (index);
8833 if (index >= 0 && index <= 4)
8834 {
8835 unsigned int align = TYPE_ALIGN_UNIT (type);
8836
8837 /* __sync builtins require strict data alignment. */
dcf7024c 8838 if (exact_log2 (align) >= index)
cb7f680b 8839 {
3ec11c49 8840 /* Atomic load. */
2169f33b 8841 if (loaded_val == stored_val
8842 && (GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
8843 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
8844 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
3ec11c49 8845 && expand_omp_atomic_load (load_bb, addr, loaded_val, index))
2169f33b 8846 return;
8847
3ec11c49 8848 /* Atomic store. */
2169f33b 8849 if ((GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
8850 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
8851 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
8852 && store_bb == single_succ (load_bb)
8853 && first_stmt (store_bb) == store
3ec11c49 8854 && expand_omp_atomic_store (load_bb, addr, loaded_val,
8855 stored_val, index))
2169f33b 8856 return;
8857
cb7f680b 8858 /* When possible, use specialized atomic update functions. */
8859 if ((INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type))
3ec11c49 8860 && store_bb == single_succ (load_bb)
8861 && expand_omp_atomic_fetch_op (load_bb, addr,
8862 loaded_val, stored_val, index))
8863 return;
cb7f680b 8864
8865 /* If we don't have specialized __sync builtins, try and implement
8866 as a compare and swap loop. */
8867 if (expand_omp_atomic_pipeline (load_bb, store_bb, addr,
8868 loaded_val, stored_val, index))
8869 return;
8870 }
8871 }
8872
8873 /* The ultimate fallback is wrapping the operation in a mutex. */
8874 expand_omp_atomic_mutex (load_bb, store_bb, addr, loaded_val, stored_val);
8875}
8876
1e8e9920 8877
e561d5e1 8878/* Encode an oacc launc argument. This matches the GOMP_LAUNCH_PACK
8879 macro on gomp-constants.h. We do not check for overflow. */
8880
8881static tree
8882oacc_launch_pack (unsigned code, tree device, unsigned op)
8883{
8884 tree res;
8885
8886 res = build_int_cst (unsigned_type_node, GOMP_LAUNCH_PACK (code, 0, op));
8887 if (device)
8888 {
8889 device = fold_build2 (LSHIFT_EXPR, unsigned_type_node,
8890 device, build_int_cst (unsigned_type_node,
8891 GOMP_LAUNCH_DEVICE_SHIFT));
8892 res = fold_build2 (BIT_IOR_EXPR, unsigned_type_node, res, device);
8893 }
8894 return res;
8895}
8896
8897/* Look for compute grid dimension clauses and convert to an attribute
8898 attached to FN. This permits the target-side code to (a) massage
8899 the dimensions, (b) emit that data and (c) optimize. Non-constant
8900 dimensions are pushed onto ARGS.
8901
8902 The attribute value is a TREE_LIST. A set of dimensions is
8903 represented as a list of INTEGER_CST. Those that are runtime
8904 expres are represented as an INTEGER_CST of zero.
8905
8906 TOOO. Normally the attribute will just contain a single such list. If
8907 however it contains a list of lists, this will represent the use of
8908 device_type. Each member of the outer list is an assoc list of
8909 dimensions, keyed by the device type. The first entry will be the
8910 default. Well, that's the plan. */
8911
8912#define OACC_FN_ATTRIB "oacc function"
8913
8914/* Replace any existing oacc fn attribute with updated dimensions. */
8915
8916void
8917replace_oacc_fn_attrib (tree fn, tree dims)
8918{
8919 tree ident = get_identifier (OACC_FN_ATTRIB);
8920 tree attribs = DECL_ATTRIBUTES (fn);
8921
8922 /* If we happen to be present as the first attrib, drop it. */
8923 if (attribs && TREE_PURPOSE (attribs) == ident)
8924 attribs = TREE_CHAIN (attribs);
8925 DECL_ATTRIBUTES (fn) = tree_cons (ident, dims, attribs);
8926}
8927
8928/* Scan CLAUSES for launch dimensions and attach them to the oacc
8929 function attribute. Push any that are non-constant onto the ARGS
8930 list, along with an appropriate GOMP_LAUNCH_DIM tag. */
8931
8932static void
8933set_oacc_fn_attrib (tree fn, tree clauses, vec<tree> *args)
8934{
8935 /* Must match GOMP_DIM ordering. */
8936 static const omp_clause_code ids[]
8937 = { OMP_CLAUSE_NUM_GANGS, OMP_CLAUSE_NUM_WORKERS,
8938 OMP_CLAUSE_VECTOR_LENGTH };
8939 unsigned ix;
8940 tree dims[GOMP_DIM_MAX];
8941 tree attr = NULL_TREE;
8942 unsigned non_const = 0;
8943
8944 for (ix = GOMP_DIM_MAX; ix--;)
8945 {
8946 tree clause = find_omp_clause (clauses, ids[ix]);
8947 tree dim = NULL_TREE;
8948
8949 if (clause)
8950 dim = OMP_CLAUSE_EXPR (clause, ids[ix]);
8951 dims[ix] = dim;
8952 if (dim && TREE_CODE (dim) != INTEGER_CST)
8953 {
8954 dim = integer_zero_node;
8955 non_const |= GOMP_DIM_MASK (ix);
8956 }
8957 attr = tree_cons (NULL_TREE, dim, attr);
8958 }
8959
8960 replace_oacc_fn_attrib (fn, attr);
8961
8962 if (non_const)
8963 {
8964 /* Push a dynamic argument set. */
8965 args->safe_push (oacc_launch_pack (GOMP_LAUNCH_DIM,
8966 NULL_TREE, non_const));
8967 for (unsigned ix = 0; ix != GOMP_DIM_MAX; ix++)
8968 if (non_const & GOMP_DIM_MASK (ix))
8969 args->safe_push (dims[ix]);
8970 }
8971}
8972
8973/* Retrieve the oacc function attrib and return it. Non-oacc
8974 functions will return NULL. */
8975
8976tree
8977get_oacc_fn_attrib (tree fn)
8978{
8979 return lookup_attribute (OACC_FN_ATTRIB, DECL_ATTRIBUTES (fn));
8980}
8981
ca4c3545 8982/* Expand the GIMPLE_OMP_TARGET starting at REGION. */
773c5ba7 8983
8984static void
bc7bff74 8985expand_omp_target (struct omp_region *region)
773c5ba7 8986{
bc7bff74 8987 basic_block entry_bb, exit_bb, new_bb;
ca4c3545 8988 struct function *child_cfun;
8989 tree child_fn, block, t;
bc7bff74 8990 gimple_stmt_iterator gsi;
1a91d914 8991 gomp_target *entry_stmt;
42acab1c 8992 gimple *stmt;
bc7bff74 8993 edge e;
ca4c3545 8994 bool offloaded, data_region;
bc7bff74 8995
1a91d914 8996 entry_stmt = as_a <gomp_target *> (last_stmt (region->entry));
bc7bff74 8997 new_bb = region->entry;
ca4c3545 8998
8999 offloaded = is_gimple_omp_offloaded (entry_stmt);
9000 switch (gimple_omp_target_kind (entry_stmt))
9001 {
ca4c3545 9002 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
9003 case GF_OMP_TARGET_KIND_OACC_KERNELS:
e561d5e1 9004 case GF_OMP_TARGET_KIND_REGION:
9005 case GF_OMP_TARGET_KIND_UPDATE:
ca4c3545 9006 case GF_OMP_TARGET_KIND_OACC_UPDATE:
9007 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
9008 data_region = false;
9009 break;
9010 case GF_OMP_TARGET_KIND_DATA:
9011 case GF_OMP_TARGET_KIND_OACC_DATA:
9012 data_region = true;
9013 break;
9014 default:
9015 gcc_unreachable ();
9016 }
9017
9018 child_fn = NULL_TREE;
9019 child_cfun = NULL;
9020 if (offloaded)
bc7bff74 9021 {
9022 child_fn = gimple_omp_target_child_fn (entry_stmt);
9023 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
9024 }
9025
ca4c3545 9026 /* Supported by expand_omp_taskreg, but not here. */
9027 if (child_cfun != NULL)
9028 gcc_checking_assert (!child_cfun->cfg);
9029 gcc_checking_assert (!gimple_in_ssa_p (cfun));
9030
bc7bff74 9031 entry_bb = region->entry;
9032 exit_bb = region->exit;
9033
ca4c3545 9034 if (offloaded)
bc7bff74 9035 {
9036 unsigned srcidx, dstidx, num;
9037
ca4c3545 9038 /* If the offloading region needs data sent from the parent
bc7bff74 9039 function, then the very first statement (except possible
ca4c3545 9040 tree profile counter updates) of the offloading body
bc7bff74 9041 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
9042 &.OMP_DATA_O is passed as an argument to the child function,
9043 we need to replace it with the argument as seen by the child
9044 function.
9045
9046 In most cases, this will end up being the identity assignment
ca4c3545 9047 .OMP_DATA_I = .OMP_DATA_I. However, if the offloading body had
bc7bff74 9048 a function call that has been inlined, the original PARM_DECL
9049 .OMP_DATA_I may have been converted into a different local
9050 variable. In which case, we need to keep the assignment. */
ca4c3545 9051 tree data_arg = gimple_omp_target_data_arg (entry_stmt);
9052 if (data_arg)
bc7bff74 9053 {
9054 basic_block entry_succ_bb = single_succ (entry_bb);
9055 gimple_stmt_iterator gsi;
9056 tree arg;
42acab1c 9057 gimple *tgtcopy_stmt = NULL;
ca4c3545 9058 tree sender = TREE_VEC_ELT (data_arg, 0);
bc7bff74 9059
9060 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
9061 {
9062 gcc_assert (!gsi_end_p (gsi));
9063 stmt = gsi_stmt (gsi);
9064 if (gimple_code (stmt) != GIMPLE_ASSIGN)
9065 continue;
9066
9067 if (gimple_num_ops (stmt) == 2)
9068 {
9069 tree arg = gimple_assign_rhs1 (stmt);
9070
9071 /* We're ignoring the subcode because we're
9072 effectively doing a STRIP_NOPS. */
9073
9074 if (TREE_CODE (arg) == ADDR_EXPR
9075 && TREE_OPERAND (arg, 0) == sender)
9076 {
9077 tgtcopy_stmt = stmt;
9078 break;
9079 }
9080 }
9081 }
9082
9083 gcc_assert (tgtcopy_stmt != NULL);
9084 arg = DECL_ARGUMENTS (child_fn);
9085
9086 gcc_assert (gimple_assign_lhs (tgtcopy_stmt) == arg);
9087 gsi_remove (&gsi, true);
9088 }
9089
9090 /* Declare local variables needed in CHILD_CFUN. */
9091 block = DECL_INITIAL (child_fn);
9092 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
ca4c3545 9093 /* The gimplifier could record temporaries in the offloading block
bc7bff74 9094 rather than in containing function's local_decls chain,
9095 which would mean cgraph missed finalizing them. Do it now. */
9096 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
9097 if (TREE_CODE (t) == VAR_DECL
9098 && TREE_STATIC (t)
9099 && !DECL_EXTERNAL (t))
97221fd7 9100 varpool_node::finalize_decl (t);
bc7bff74 9101 DECL_SAVED_TREE (child_fn) = NULL;
9102 /* We'll create a CFG for child_fn, so no gimple body is needed. */
9103 gimple_set_body (child_fn, NULL);
9104 TREE_USED (block) = 1;
9105
9106 /* Reset DECL_CONTEXT on function arguments. */
9107 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
9108 DECL_CONTEXT (t) = child_fn;
9109
ca4c3545 9110 /* Split ENTRY_BB at GIMPLE_*,
bc7bff74 9111 so that it can be moved to the child function. */
9112 gsi = gsi_last_bb (entry_bb);
9113 stmt = gsi_stmt (gsi);
ca4c3545 9114 gcc_assert (stmt
9115 && gimple_code (stmt) == gimple_code (entry_stmt));
bc7bff74 9116 e = split_block (entry_bb, stmt);
923635e7 9117 gsi_remove (&gsi, true);
bc7bff74 9118 entry_bb = e->dest;
9119 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
9120
9121 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
9122 if (exit_bb)
9123 {
9124 gsi = gsi_last_bb (exit_bb);
9125 gcc_assert (!gsi_end_p (gsi)
9126 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
9127 stmt = gimple_build_return (NULL);
9128 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
9129 gsi_remove (&gsi, true);
9130 }
9131
ca4c3545 9132 /* Move the offloading region into CHILD_CFUN. */
bc7bff74 9133
9134 block = gimple_block (entry_stmt);
9135
9136 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
9137 if (exit_bb)
9138 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
9139 /* When the OMP expansion process cannot guarantee an up-to-date
9140 loop tree arrange for the child function to fixup loops. */
9141 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
9142 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
9143
9144 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
9145 num = vec_safe_length (child_cfun->local_decls);
9146 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
9147 {
9148 t = (*child_cfun->local_decls)[srcidx];
9149 if (DECL_CONTEXT (t) == cfun->decl)
9150 continue;
9151 if (srcidx != dstidx)
9152 (*child_cfun->local_decls)[dstidx] = t;
9153 dstidx++;
9154 }
9155 if (dstidx != num)
9156 vec_safe_truncate (child_cfun->local_decls, dstidx);
9157
9158 /* Inform the callgraph about the new function. */
613f2c38 9159 child_cfun->curr_properties = cfun->curr_properties;
9160 child_cfun->has_simduid_loops |= cfun->has_simduid_loops;
9161 child_cfun->has_force_vectorize_loops |= cfun->has_force_vectorize_loops;
6a77ed3d 9162 cgraph_node *node = cgraph_node::get_create (child_fn);
9163 node->parallelized_function = 1;
415d1b9a 9164 cgraph_node::add_new_function (child_fn, true);
bc7bff74 9165
7114ebdd 9166#ifdef ENABLE_OFFLOADING
dccabdd1 9167 /* Add the new function to the offload table. */
9168 vec_safe_push (offload_funcs, child_fn);
7114ebdd 9169#endif
dccabdd1 9170
bc7bff74 9171 /* Fix the callgraph edges for child_cfun. Those for cfun will be
9172 fixed in a following pass. */
9173 push_cfun (child_cfun);
35ee1c66 9174 cgraph_edge::rebuild_edges ();
bc7bff74 9175
7114ebdd 9176#ifdef ENABLE_OFFLOADING
b0c5e347 9177 /* Prevent IPA from removing child_fn as unreachable, since there are no
9178 refs from the parent function to child_fn in offload LTO mode. */
569b71d0 9179 cgraph_node::get (child_fn)->mark_force_output ();
7114ebdd 9180#endif
b0c5e347 9181
bc7bff74 9182 /* Some EH regions might become dead, see PR34608. If
9183 pass_cleanup_cfg isn't the first pass to happen with the
9184 new child, these dead EH edges might cause problems.
9185 Clean them up now. */
9186 if (flag_exceptions)
9187 {
9188 basic_block bb;
9189 bool changed = false;
9190
fc00614f 9191 FOR_EACH_BB_FN (bb, cfun)
bc7bff74 9192 changed |= gimple_purge_dead_eh_edges (bb);
9193 if (changed)
9194 cleanup_tree_cfg ();
9195 }
86a932e0 9196#ifdef ENABLE_CHECKING
9197 if (!loops_state_satisfies_p (LOOPS_NEED_FIXUP))
9198 verify_loop_structure ();
9199#endif
bc7bff74 9200 pop_cfun ();
9201 }
9202
ca4c3545 9203 /* Emit a library call to launch the offloading region, or do data
bc7bff74 9204 transfers. */
9205 tree t1, t2, t3, t4, device, cond, c, clauses;
9206 enum built_in_function start_ix;
9207 location_t clause_loc;
9208
ca4c3545 9209 switch (gimple_omp_target_kind (entry_stmt))
9210 {
9211 case GF_OMP_TARGET_KIND_REGION:
9212 start_ix = BUILT_IN_GOMP_TARGET;
9213 break;
9214 case GF_OMP_TARGET_KIND_DATA:
9215 start_ix = BUILT_IN_GOMP_TARGET_DATA;
9216 break;
9217 case GF_OMP_TARGET_KIND_UPDATE:
9218 start_ix = BUILT_IN_GOMP_TARGET_UPDATE;
9219 break;
9220 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
9221 case GF_OMP_TARGET_KIND_OACC_KERNELS:
9222 start_ix = BUILT_IN_GOACC_PARALLEL;
9223 break;
9224 case GF_OMP_TARGET_KIND_OACC_DATA:
9225 start_ix = BUILT_IN_GOACC_DATA_START;
9226 break;
9227 case GF_OMP_TARGET_KIND_OACC_UPDATE:
9228 start_ix = BUILT_IN_GOACC_UPDATE;
9229 break;
9230 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
9231 start_ix = BUILT_IN_GOACC_ENTER_EXIT_DATA;
9232 break;
9233 default:
9234 gcc_unreachable ();
9235 }
bc7bff74 9236
ca4c3545 9237 clauses = gimple_omp_target_clauses (entry_stmt);
bc7bff74 9238
ca4c3545 9239 /* By default, the value of DEVICE is GOMP_DEVICE_ICV (let runtime
9240 library choose) and there is no conditional. */
bc7bff74 9241 cond = NULL_TREE;
ca4c3545 9242 device = build_int_cst (integer_type_node, GOMP_DEVICE_ICV);
bc7bff74 9243
9244 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
9245 if (c)
9246 cond = OMP_CLAUSE_IF_EXPR (c);
9247
9248 c = find_omp_clause (clauses, OMP_CLAUSE_DEVICE);
9249 if (c)
9250 {
ca4c3545 9251 /* Even if we pass it to all library function calls, it is currently only
9252 defined/used for the OpenMP target ones. */
9253 gcc_checking_assert (start_ix == BUILT_IN_GOMP_TARGET
9254 || start_ix == BUILT_IN_GOMP_TARGET_DATA
9255 || start_ix == BUILT_IN_GOMP_TARGET_UPDATE);
9256
bc7bff74 9257 device = OMP_CLAUSE_DEVICE_ID (c);
9258 clause_loc = OMP_CLAUSE_LOCATION (c);
9259 }
9260 else
9261 clause_loc = gimple_location (entry_stmt);
9262
9263 /* Ensure 'device' is of the correct type. */
9264 device = fold_convert_loc (clause_loc, integer_type_node, device);
9265
9266 /* If we found the clause 'if (cond)', build
ca4c3545 9267 (cond ? device : GOMP_DEVICE_HOST_FALLBACK). */
bc7bff74 9268 if (cond)
9269 {
9270 cond = gimple_boolify (cond);
9271
9272 basic_block cond_bb, then_bb, else_bb;
9273 edge e;
9274 tree tmp_var;
9275
f9e245b2 9276 tmp_var = create_tmp_var (TREE_TYPE (device));
ca4c3545 9277 if (offloaded)
4302d619 9278 e = split_block_after_labels (new_bb);
ca4c3545 9279 else
bc7bff74 9280 {
9281 gsi = gsi_last_bb (new_bb);
9282 gsi_prev (&gsi);
9283 e = split_block (new_bb, gsi_stmt (gsi));
9284 }
bc7bff74 9285 cond_bb = e->src;
9286 new_bb = e->dest;
9287 remove_edge (e);
9288
9289 then_bb = create_empty_bb (cond_bb);
9290 else_bb = create_empty_bb (then_bb);
9291 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
9292 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
9293
9294 stmt = gimple_build_cond_empty (cond);
9295 gsi = gsi_last_bb (cond_bb);
9296 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
9297
9298 gsi = gsi_start_bb (then_bb);
9299 stmt = gimple_build_assign (tmp_var, device);
9300 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
9301
9302 gsi = gsi_start_bb (else_bb);
9303 stmt = gimple_build_assign (tmp_var,
ca4c3545 9304 build_int_cst (integer_type_node,
9305 GOMP_DEVICE_HOST_FALLBACK));
bc7bff74 9306 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
9307
9308 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
9309 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
b3083327 9310 add_bb_to_loop (then_bb, cond_bb->loop_father);
9311 add_bb_to_loop (else_bb, cond_bb->loop_father);
bc7bff74 9312 make_edge (then_bb, new_bb, EDGE_FALLTHRU);
9313 make_edge (else_bb, new_bb, EDGE_FALLTHRU);
9314
9315 device = tmp_var;
9316 }
9317
9318 gsi = gsi_last_bb (new_bb);
9319 t = gimple_omp_target_data_arg (entry_stmt);
9320 if (t == NULL)
9321 {
9322 t1 = size_zero_node;
9323 t2 = build_zero_cst (ptr_type_node);
9324 t3 = t2;
9325 t4 = t2;
9326 }
9327 else
9328 {
9329 t1 = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (TREE_VEC_ELT (t, 1))));
9330 t1 = size_binop (PLUS_EXPR, t1, size_int (1));
9331 t2 = build_fold_addr_expr (TREE_VEC_ELT (t, 0));
9332 t3 = build_fold_addr_expr (TREE_VEC_ELT (t, 1));
9333 t4 = build_fold_addr_expr (TREE_VEC_ELT (t, 2));
9334 }
9335
42acab1c 9336 gimple *g;
e561d5e1 9337 bool tagging = false;
ca4c3545 9338 /* The maximum number used by any start_ix, without varargs. */
02c05c9b 9339 auto_vec<tree, 11> args;
9340 args.quick_push (device);
ca4c3545 9341 if (offloaded)
02c05c9b 9342 args.quick_push (build_fold_addr_expr (child_fn));
dc19c8fd 9343 switch (start_ix)
9344 {
9345 case BUILT_IN_GOMP_TARGET:
9346 case BUILT_IN_GOMP_TARGET_DATA:
9347 case BUILT_IN_GOMP_TARGET_UPDATE:
9348 /* This const void * is part of the current ABI, but we're not actually
9349 using it. */
02c05c9b 9350 args.quick_push (build_zero_cst (ptr_type_node));
dc19c8fd 9351 break;
9352 case BUILT_IN_GOACC_DATA_START:
9353 case BUILT_IN_GOACC_ENTER_EXIT_DATA:
9354 case BUILT_IN_GOACC_PARALLEL:
9355 case BUILT_IN_GOACC_UPDATE:
9356 break;
9357 default:
9358 gcc_unreachable ();
9359 }
02c05c9b 9360 args.quick_push (t1);
9361 args.quick_push (t2);
9362 args.quick_push (t3);
9363 args.quick_push (t4);
ca4c3545 9364 switch (start_ix)
9365 {
9366 case BUILT_IN_GOACC_DATA_START:
9367 case BUILT_IN_GOMP_TARGET:
9368 case BUILT_IN_GOMP_TARGET_DATA:
9369 case BUILT_IN_GOMP_TARGET_UPDATE:
9370 break;
9371 case BUILT_IN_GOACC_PARALLEL:
9372 {
e561d5e1 9373 set_oacc_fn_attrib (child_fn, clauses, &args);
9374 tagging = true;
ca4c3545 9375 }
9376 /* FALLTHRU */
9377 case BUILT_IN_GOACC_ENTER_EXIT_DATA:
9378 case BUILT_IN_GOACC_UPDATE:
9379 {
e561d5e1 9380 tree t_async = NULL_TREE;
9381
9382 /* If present, use the value specified by the respective
ca4c3545 9383 clause, making sure that is of the correct type. */
9384 c = find_omp_clause (clauses, OMP_CLAUSE_ASYNC);
9385 if (c)
9386 t_async = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
9387 integer_type_node,
9388 OMP_CLAUSE_ASYNC_EXPR (c));
e561d5e1 9389 else if (!tagging)
9390 /* Default values for t_async. */
9391 t_async = fold_convert_loc (gimple_location (entry_stmt),
9392 integer_type_node,
9393 build_int_cst (integer_type_node,
9394 GOMP_ASYNC_SYNC));
9395 if (tagging && t_async)
ca4c3545 9396 {
e561d5e1 9397 unsigned HOST_WIDE_INT i_async;
ca4c3545 9398
e561d5e1 9399 if (TREE_CODE (t_async) == INTEGER_CST)
ca4c3545 9400 {
e561d5e1 9401 /* See if we can pack the async arg in to the tag's
9402 operand. */
9403 i_async = TREE_INT_CST_LOW (t_async);
9404
9405 if (i_async < GOMP_LAUNCH_OP_MAX)
9406 t_async = NULL_TREE;
ca4c3545 9407 }
e561d5e1 9408 if (t_async)
9409 i_async = GOMP_LAUNCH_OP_MAX;
9410 args.safe_push (oacc_launch_pack
9411 (GOMP_LAUNCH_ASYNC, NULL_TREE, i_async));
9412 }
9413 if (t_async)
9414 args.safe_push (t_async);
ca4c3545 9415
e561d5e1 9416 /* Save the argument index, and ... */
9417 unsigned t_wait_idx = args.length ();
9418 unsigned num_waits = 0;
9419 c = find_omp_clause (clauses, OMP_CLAUSE_WAIT);
9420 if (!tagging || c)
9421 /* ... push a placeholder. */
9422 args.safe_push (integer_zero_node);
9423
9424 for (; c; c = OMP_CLAUSE_CHAIN (c))
9425 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_WAIT)
9426 {
9427 args.safe_push (fold_convert_loc (OMP_CLAUSE_LOCATION (c),
9428 integer_type_node,
9429 OMP_CLAUSE_WAIT_EXPR (c)));
9430 num_waits++;
9431 }
9432
9433 if (!tagging || num_waits)
9434 {
9435 tree len;
9436
9437 /* Now that we know the number, update the placeholder. */
9438 if (tagging)
9439 len = oacc_launch_pack (GOMP_LAUNCH_WAIT, NULL_TREE, num_waits);
9440 else
9441 len = build_int_cst (integer_type_node, num_waits);
9442 len = fold_convert_loc (gimple_location (entry_stmt),
9443 unsigned_type_node, len);
9444 args[t_wait_idx] = len;
ca4c3545 9445 }
9446 }
9447 break;
9448 default:
9449 gcc_unreachable ();
bc7bff74 9450 }
e561d5e1 9451 if (tagging)
9452 /* Push terminal marker - zero. */
9453 args.safe_push (oacc_launch_pack (0, NULL_TREE, 0));
ca4c3545 9454
02c05c9b 9455 g = gimple_build_call_vec (builtin_decl_explicit (start_ix), args);
bc7bff74 9456 gimple_set_location (g, gimple_location (entry_stmt));
9457 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
ca4c3545 9458 if (!offloaded)
bc7bff74 9459 {
9460 g = gsi_stmt (gsi);
9461 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_TARGET);
9462 gsi_remove (&gsi, true);
9463 }
ca4c3545 9464 if (data_region
9465 && region->exit)
bc7bff74 9466 {
9467 gsi = gsi_last_bb (region->exit);
9468 g = gsi_stmt (gsi);
9469 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_RETURN);
9470 gsi_remove (&gsi, true);
9471 }
9472}
9473
9474
9475/* Expand the parallel region tree rooted at REGION. Expansion
9476 proceeds in depth-first order. Innermost regions are expanded
9477 first. This way, parallel regions that require a new function to
75a70cf9 9478 be created (e.g., GIMPLE_OMP_PARALLEL) can be expanded without having any
773c5ba7 9479 internal dependencies in their body. */
9480
9481static void
9482expand_omp (struct omp_region *region)
9483{
9484 while (region)
9485 {
1d22f541 9486 location_t saved_location;
42acab1c 9487 gimple *inner_stmt = NULL;
1d22f541 9488
d1d5b012 9489 /* First, determine whether this is a combined parallel+workshare
9490 region. */
75a70cf9 9491 if (region->type == GIMPLE_OMP_PARALLEL)
d1d5b012 9492 determine_parallel_type (region);
9493
bc7bff74 9494 if (region->type == GIMPLE_OMP_FOR
9495 && gimple_omp_for_combined_p (last_stmt (region->entry)))
9496 inner_stmt = last_stmt (region->inner->entry);
9497
773c5ba7 9498 if (region->inner)
9499 expand_omp (region->inner);
9500
1d22f541 9501 saved_location = input_location;
75a70cf9 9502 if (gimple_has_location (last_stmt (region->entry)))
9503 input_location = gimple_location (last_stmt (region->entry));
1d22f541 9504
61e47ac8 9505 switch (region->type)
773c5ba7 9506 {
75a70cf9 9507 case GIMPLE_OMP_PARALLEL:
9508 case GIMPLE_OMP_TASK:
fd6481cf 9509 expand_omp_taskreg (region);
9510 break;
9511
75a70cf9 9512 case GIMPLE_OMP_FOR:
bc7bff74 9513 expand_omp_for (region, inner_stmt);
61e47ac8 9514 break;
773c5ba7 9515
75a70cf9 9516 case GIMPLE_OMP_SECTIONS:
61e47ac8 9517 expand_omp_sections (region);
9518 break;
773c5ba7 9519
75a70cf9 9520 case GIMPLE_OMP_SECTION:
61e47ac8 9521 /* Individual omp sections are handled together with their
75a70cf9 9522 parent GIMPLE_OMP_SECTIONS region. */
61e47ac8 9523 break;
773c5ba7 9524
75a70cf9 9525 case GIMPLE_OMP_SINGLE:
61e47ac8 9526 expand_omp_single (region);
9527 break;
773c5ba7 9528
75a70cf9 9529 case GIMPLE_OMP_MASTER:
bc7bff74 9530 case GIMPLE_OMP_TASKGROUP:
75a70cf9 9531 case GIMPLE_OMP_ORDERED:
9532 case GIMPLE_OMP_CRITICAL:
bc7bff74 9533 case GIMPLE_OMP_TEAMS:
61e47ac8 9534 expand_omp_synch (region);
9535 break;
773c5ba7 9536
75a70cf9 9537 case GIMPLE_OMP_ATOMIC_LOAD:
cb7f680b 9538 expand_omp_atomic (region);
9539 break;
9540
bc7bff74 9541 case GIMPLE_OMP_TARGET:
9542 expand_omp_target (region);
9543 break;
9544
61e47ac8 9545 default:
9546 gcc_unreachable ();
9547 }
cc5982dc 9548
1d22f541 9549 input_location = saved_location;
773c5ba7 9550 region = region->next;
9551 }
9552}
9553
9554
9555/* Helper for build_omp_regions. Scan the dominator tree starting at
28c92cbb 9556 block BB. PARENT is the region that contains BB. If SINGLE_TREE is
9557 true, the function ends once a single tree is built (otherwise, whole
9558 forest of OMP constructs may be built). */
773c5ba7 9559
9560static void
28c92cbb 9561build_omp_regions_1 (basic_block bb, struct omp_region *parent,
9562 bool single_tree)
773c5ba7 9563{
75a70cf9 9564 gimple_stmt_iterator gsi;
42acab1c 9565 gimple *stmt;
773c5ba7 9566 basic_block son;
9567
75a70cf9 9568 gsi = gsi_last_bb (bb);
9569 if (!gsi_end_p (gsi) && is_gimple_omp (gsi_stmt (gsi)))
773c5ba7 9570 {
9571 struct omp_region *region;
75a70cf9 9572 enum gimple_code code;
773c5ba7 9573
75a70cf9 9574 stmt = gsi_stmt (gsi);
9575 code = gimple_code (stmt);
9576 if (code == GIMPLE_OMP_RETURN)
773c5ba7 9577 {
9578 /* STMT is the return point out of region PARENT. Mark it
9579 as the exit point and make PARENT the immediately
9580 enclosing region. */
9581 gcc_assert (parent);
9582 region = parent;
61e47ac8 9583 region->exit = bb;
773c5ba7 9584 parent = parent->outer;
773c5ba7 9585 }
75a70cf9 9586 else if (code == GIMPLE_OMP_ATOMIC_STORE)
cb7f680b 9587 {
75a70cf9 9588 /* GIMPLE_OMP_ATOMIC_STORE is analoguous to
9589 GIMPLE_OMP_RETURN, but matches with
9590 GIMPLE_OMP_ATOMIC_LOAD. */
cb7f680b 9591 gcc_assert (parent);
75a70cf9 9592 gcc_assert (parent->type == GIMPLE_OMP_ATOMIC_LOAD);
cb7f680b 9593 region = parent;
9594 region->exit = bb;
9595 parent = parent->outer;
9596 }
75a70cf9 9597 else if (code == GIMPLE_OMP_CONTINUE)
61e47ac8 9598 {
9599 gcc_assert (parent);
9600 parent->cont = bb;
9601 }
75a70cf9 9602 else if (code == GIMPLE_OMP_SECTIONS_SWITCH)
ac6e3339 9603 {
75a70cf9 9604 /* GIMPLE_OMP_SECTIONS_SWITCH is part of
9605 GIMPLE_OMP_SECTIONS, and we do nothing for it. */
ac6e3339 9606 }
773c5ba7 9607 else
9608 {
61e47ac8 9609 region = new_omp_region (bb, code, parent);
ca4c3545 9610 /* Otherwise... */
9611 if (code == GIMPLE_OMP_TARGET)
9612 {
9613 switch (gimple_omp_target_kind (stmt))
9614 {
9615 case GF_OMP_TARGET_KIND_REGION:
9616 case GF_OMP_TARGET_KIND_DATA:
9617 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
9618 case GF_OMP_TARGET_KIND_OACC_KERNELS:
9619 case GF_OMP_TARGET_KIND_OACC_DATA:
9620 break;
9621 case GF_OMP_TARGET_KIND_UPDATE:
9622 case GF_OMP_TARGET_KIND_OACC_UPDATE:
9623 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
9624 /* ..., other than for those stand-alone directives... */
9625 region = NULL;
9626 break;
9627 default:
9628 gcc_unreachable ();
9629 }
9630 }
9631 /* ..., this directive becomes the parent for a new region. */
9632 if (region)
9633 parent = region;
773c5ba7 9634 }
773c5ba7 9635 }
9636
28c92cbb 9637 if (single_tree && !parent)
9638 return;
9639
773c5ba7 9640 for (son = first_dom_son (CDI_DOMINATORS, bb);
9641 son;
9642 son = next_dom_son (CDI_DOMINATORS, son))
28c92cbb 9643 build_omp_regions_1 (son, parent, single_tree);
9644}
9645
9646/* Builds the tree of OMP regions rooted at ROOT, storing it to
9647 root_omp_region. */
9648
9649static void
9650build_omp_regions_root (basic_block root)
9651{
9652 gcc_assert (root_omp_region == NULL);
9653 build_omp_regions_1 (root, NULL, true);
9654 gcc_assert (root_omp_region != NULL);
773c5ba7 9655}
9656
28c92cbb 9657/* Expands omp construct (and its subconstructs) starting in HEAD. */
9658
9659void
9660omp_expand_local (basic_block head)
9661{
9662 build_omp_regions_root (head);
9663 if (dump_file && (dump_flags & TDF_DETAILS))
9664 {
9665 fprintf (dump_file, "\nOMP region tree\n\n");
9666 dump_omp_region (dump_file, root_omp_region, 0);
9667 fprintf (dump_file, "\n");
9668 }
9669
9670 remove_exit_barriers (root_omp_region);
9671 expand_omp (root_omp_region);
9672
9673 free_omp_regions ();
9674}
773c5ba7 9675
9676/* Scan the CFG and build a tree of OMP regions. Return the root of
9677 the OMP region tree. */
9678
9679static void
9680build_omp_regions (void)
9681{
61e47ac8 9682 gcc_assert (root_omp_region == NULL);
773c5ba7 9683 calculate_dominance_info (CDI_DOMINATORS);
34154e27 9684 build_omp_regions_1 (ENTRY_BLOCK_PTR_FOR_FN (cfun), NULL, false);
773c5ba7 9685}
9686
773c5ba7 9687/* Main entry point for expanding OMP-GIMPLE into runtime calls. */
9688
2a1990e9 9689static unsigned int
773c5ba7 9690execute_expand_omp (void)
9691{
9692 build_omp_regions ();
9693
61e47ac8 9694 if (!root_omp_region)
9695 return 0;
773c5ba7 9696
61e47ac8 9697 if (dump_file)
9698 {
9699 fprintf (dump_file, "\nOMP region tree\n\n");
9700 dump_omp_region (dump_file, root_omp_region, 0);
9701 fprintf (dump_file, "\n");
773c5ba7 9702 }
61e47ac8 9703
9704 remove_exit_barriers (root_omp_region);
9705
9706 expand_omp (root_omp_region);
9707
86a932e0 9708#ifdef ENABLE_CHECKING
9709 if (!loops_state_satisfies_p (LOOPS_NEED_FIXUP))
9710 verify_loop_structure ();
9711#endif
61e47ac8 9712 cleanup_tree_cfg ();
9713
9714 free_omp_regions ();
9715
2a1990e9 9716 return 0;
773c5ba7 9717}
9718
79acaae1 9719/* OMP expansion -- the default pass, run before creation of SSA form. */
9720
7620bc82 9721namespace {
9722
9723const pass_data pass_data_expand_omp =
cbe8bda8 9724{
9725 GIMPLE_PASS, /* type */
9726 "ompexp", /* name */
9727 OPTGROUP_NONE, /* optinfo_flags */
cbe8bda8 9728 TV_NONE, /* tv_id */
9729 PROP_gimple_any, /* properties_required */
8917c50b 9730 PROP_gimple_eomp, /* properties_provided */
cbe8bda8 9731 0, /* properties_destroyed */
9732 0, /* todo_flags_start */
9733 0, /* todo_flags_finish */
773c5ba7 9734};
cbe8bda8 9735
7620bc82 9736class pass_expand_omp : public gimple_opt_pass
cbe8bda8 9737{
9738public:
9af5ce0c 9739 pass_expand_omp (gcc::context *ctxt)
9740 : gimple_opt_pass (pass_data_expand_omp, ctxt)
cbe8bda8 9741 {}
9742
9743 /* opt_pass methods: */
8917c50b 9744 virtual unsigned int execute (function *)
31315c24 9745 {
ca4c3545 9746 bool gate = ((flag_cilkplus != 0 || flag_openacc != 0 || flag_openmp != 0
9747 || flag_openmp_simd != 0)
9748 && !seen_error ());
31315c24 9749
8917c50b 9750 /* This pass always runs, to provide PROP_gimple_eomp.
ca4c3545 9751 But often, there is nothing to do. */
8917c50b 9752 if (!gate)
9753 return 0;
9754
9755 return execute_expand_omp ();
9756 }
cbe8bda8 9757
9758}; // class pass_expand_omp
9759
7620bc82 9760} // anon namespace
9761
cbe8bda8 9762gimple_opt_pass *
9763make_pass_expand_omp (gcc::context *ctxt)
9764{
9765 return new pass_expand_omp (ctxt);
9766}
8917c50b 9767
7620bc82 9768namespace {
9769
9770const pass_data pass_data_expand_omp_ssa =
8917c50b 9771{
9772 GIMPLE_PASS, /* type */
9773 "ompexpssa", /* name */
9774 OPTGROUP_NONE, /* optinfo_flags */
9775 TV_NONE, /* tv_id */
9776 PROP_cfg | PROP_ssa, /* properties_required */
9777 PROP_gimple_eomp, /* properties_provided */
9778 0, /* properties_destroyed */
9779 0, /* todo_flags_start */
9780 TODO_cleanup_cfg | TODO_rebuild_alias, /* todo_flags_finish */
9781};
9782
7620bc82 9783class pass_expand_omp_ssa : public gimple_opt_pass
8917c50b 9784{
9785public:
9786 pass_expand_omp_ssa (gcc::context *ctxt)
9787 : gimple_opt_pass (pass_data_expand_omp_ssa, ctxt)
9788 {}
9789
9790 /* opt_pass methods: */
9791 virtual bool gate (function *fun)
9792 {
9793 return !(fun->curr_properties & PROP_gimple_eomp);
9794 }
9795 virtual unsigned int execute (function *) { return execute_expand_omp (); }
9796
9797}; // class pass_expand_omp_ssa
9798
7620bc82 9799} // anon namespace
9800
8917c50b 9801gimple_opt_pass *
9802make_pass_expand_omp_ssa (gcc::context *ctxt)
9803{
9804 return new pass_expand_omp_ssa (ctxt);
9805}
773c5ba7 9806\f
ca4c3545 9807/* Routines to lower OMP directives into OMP-GIMPLE. */
9808
9809/* Helper function to preform, potentially COMPLEX_TYPE, operation and
9810 convert it to gimple. */
9811static void
9812oacc_gimple_assign (tree dest, tree_code op, tree src, gimple_seq *seq)
9813{
42acab1c 9814 gimple *stmt;
ca4c3545 9815
9816 if (TREE_CODE (TREE_TYPE (dest)) != COMPLEX_TYPE)
9817 {
9818 stmt = gimple_build_assign (dest, op, dest, src);
9819 gimple_seq_add_stmt (seq, stmt);
9820 return;
9821 }
9822
9823 tree t = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9824 tree rdest = fold_build1 (REALPART_EXPR, TREE_TYPE (TREE_TYPE (dest)), dest);
9825 gimplify_assign (t, rdest, seq);
9826 rdest = t;
9827
9828 t = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9829 tree idest = fold_build1 (IMAGPART_EXPR, TREE_TYPE (TREE_TYPE (dest)), dest);
9830 gimplify_assign (t, idest, seq);
9831 idest = t;
9832
9833 t = create_tmp_var (TREE_TYPE (TREE_TYPE (src)));
9834 tree rsrc = fold_build1 (REALPART_EXPR, TREE_TYPE (TREE_TYPE (src)), src);
9835 gimplify_assign (t, rsrc, seq);
9836 rsrc = t;
9837
9838 t = create_tmp_var (TREE_TYPE (TREE_TYPE (src)));
9839 tree isrc = fold_build1 (IMAGPART_EXPR, TREE_TYPE (TREE_TYPE (src)), src);
9840 gimplify_assign (t, isrc, seq);
9841 isrc = t;
9842
9843 tree r = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9844 tree i = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9845 tree result;
9846
9847 if (op == PLUS_EXPR)
9848 {
9849 stmt = gimple_build_assign (r, op, rdest, rsrc);
9850 gimple_seq_add_stmt (seq, stmt);
9851
9852 stmt = gimple_build_assign (i, op, idest, isrc);
9853 gimple_seq_add_stmt (seq, stmt);
9854 }
9855 else if (op == MULT_EXPR)
9856 {
9857 /* Let x = a + ib = dest, y = c + id = src.
9858 x * y = (ac - bd) + i(ad + bc) */
9859 tree ac = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9860 tree bd = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9861 tree ad = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9862 tree bc = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9863
9864 stmt = gimple_build_assign (ac, MULT_EXPR, rdest, rsrc);
9865 gimple_seq_add_stmt (seq, stmt);
9866
9867 stmt = gimple_build_assign (bd, MULT_EXPR, idest, isrc);
9868 gimple_seq_add_stmt (seq, stmt);
9869
9870 stmt = gimple_build_assign (r, MINUS_EXPR, ac, bd);
9871 gimple_seq_add_stmt (seq, stmt);
9872
9873 stmt = gimple_build_assign (ad, MULT_EXPR, rdest, isrc);
9874 gimple_seq_add_stmt (seq, stmt);
9875
9876 stmt = gimple_build_assign (bd, MULT_EXPR, idest, rsrc);
9877 gimple_seq_add_stmt (seq, stmt);
9878
9879 stmt = gimple_build_assign (i, PLUS_EXPR, ad, bc);
9880 gimple_seq_add_stmt (seq, stmt);
9881 }
9882 else
9883 gcc_unreachable ();
9884
9885 result = build2 (COMPLEX_EXPR, TREE_TYPE (dest), r, i);
9886 gimplify_assign (dest, result, seq);
9887}
9888
9889/* Helper function to initialize local data for the reduction arrays.
9890 The reduction arrays need to be placed inside the calling function
9891 for accelerators, or else the host won't be able to preform the final
9892 reduction. */
9893
9894static void
9895oacc_initialize_reduction_data (tree clauses, tree nthreads,
9896 gimple_seq *stmt_seqp, omp_context *ctx)
9897{
9898 tree c, t, oc;
42acab1c 9899 gimple *stmt;
ca4c3545 9900 omp_context *octx;
9901
9902 /* Find the innermost OpenACC parallel context. */
9903 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TARGET
9904 && (gimple_omp_target_kind (ctx->stmt)
9905 == GF_OMP_TARGET_KIND_OACC_PARALLEL))
9906 octx = ctx;
9907 else
9908 octx = ctx->outer;
9909 gcc_checking_assert (gimple_code (octx->stmt) == GIMPLE_OMP_TARGET
9910 && (gimple_omp_target_kind (octx->stmt)
9911 == GF_OMP_TARGET_KIND_OACC_PARALLEL));
9912
9913 /* Extract the clauses. */
9914 oc = gimple_omp_target_clauses (octx->stmt);
9915
9916 /* Find the last outer clause. */
9917 for (; oc && OMP_CLAUSE_CHAIN (oc); oc = OMP_CLAUSE_CHAIN (oc))
9918 ;
9919
9920 /* Allocate arrays for each reduction variable. */
9921 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
9922 {
9923 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
9924 continue;
9925
9926 tree var = OMP_CLAUSE_DECL (c);
9927 tree type = get_base_type (var);
9928 tree array = lookup_oacc_reduction (oacc_get_reduction_array_id (var),
9929 ctx);
9930 tree size, call;
9931
9932 /* Calculate size of the reduction array. */
9933 t = create_tmp_var (TREE_TYPE (nthreads));
9934 stmt = gimple_build_assign (t, MULT_EXPR, nthreads,
9935 fold_convert (TREE_TYPE (nthreads),
9936 TYPE_SIZE_UNIT (type)));
9937 gimple_seq_add_stmt (stmt_seqp, stmt);
9938
9939 size = create_tmp_var (sizetype);
9940 gimplify_assign (size, fold_build1 (NOP_EXPR, sizetype, t), stmt_seqp);
9941
9942 /* Now allocate memory for it. */
9943 call = unshare_expr (builtin_decl_explicit (BUILT_IN_ALLOCA));
9944 stmt = gimple_build_call (call, 1, size);
9945 gimple_call_set_lhs (stmt, array);
9946 gimple_seq_add_stmt (stmt_seqp, stmt);
9947
9948 /* Map this array into the accelerator. */
9949
9950 /* Add the reduction array to the list of clauses. */
9951 tree x = array;
9952 t = build_omp_clause (gimple_location (ctx->stmt), OMP_CLAUSE_MAP);
9953 OMP_CLAUSE_SET_MAP_KIND (t, GOMP_MAP_FORCE_FROM);
9954 OMP_CLAUSE_DECL (t) = x;
9955 OMP_CLAUSE_CHAIN (t) = NULL;
9956 if (oc)
9957 OMP_CLAUSE_CHAIN (oc) = t;
9958 else
9959 gimple_omp_target_set_clauses (as_a <gomp_target *> (octx->stmt), t);
9960 OMP_CLAUSE_SIZE (t) = size;
9961 oc = t;
9962 }
9963}
9964
9965/* Helper function to process the array of partial reductions. Nthreads
9966 indicates the number of threads. Unfortunately, GOACC_GET_NUM_THREADS
9967 cannot be used here, because nthreads on the host may be different than
9968 on the accelerator. */
9969
9970static void
9971oacc_finalize_reduction_data (tree clauses, tree nthreads,
9972 gimple_seq *stmt_seqp, omp_context *ctx)
9973{
9974 tree c, x, var, array, loop_header, loop_body, loop_exit, type;
42acab1c 9975 gimple *stmt;
ca4c3545 9976
9977 /* Create for loop.
9978
9979 let var = the original reduction variable
9980 let array = reduction variable array
9981
9982 for (i = 0; i < nthreads; i++)
9983 var op= array[i]
9984 */
9985
9986 loop_header = create_artificial_label (UNKNOWN_LOCATION);
9987 loop_body = create_artificial_label (UNKNOWN_LOCATION);
9988 loop_exit = create_artificial_label (UNKNOWN_LOCATION);
9989
9990 /* Create and initialize an index variable. */
9991 tree ix = create_tmp_var (sizetype);
9992 gimplify_assign (ix, fold_build1 (NOP_EXPR, sizetype, integer_zero_node),
9993 stmt_seqp);
9994
9995 /* Insert the loop header label here. */
9996 gimple_seq_add_stmt (stmt_seqp, gimple_build_label (loop_header));
9997
9998 /* Exit loop if ix >= nthreads. */
9999 x = create_tmp_var (sizetype);
10000 gimplify_assign (x, fold_build1 (NOP_EXPR, sizetype, nthreads), stmt_seqp);
10001 stmt = gimple_build_cond (GE_EXPR, ix, x, loop_exit, loop_body);
10002 gimple_seq_add_stmt (stmt_seqp, stmt);
10003
10004 /* Insert the loop body label here. */
10005 gimple_seq_add_stmt (stmt_seqp, gimple_build_label (loop_body));
10006
10007 /* Collapse each reduction array, one element at a time. */
10008 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
10009 {
10010 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
10011 continue;
10012
10013 tree_code reduction_code = OMP_CLAUSE_REDUCTION_CODE (c);
10014
10015 /* reduction(-:var) sums up the partial results, so it acts
10016 identically to reduction(+:var). */
10017 if (reduction_code == MINUS_EXPR)
10018 reduction_code = PLUS_EXPR;
10019
10020 /* Set up reduction variable var. */
10021 var = OMP_CLAUSE_DECL (c);
10022 type = get_base_type (var);
10023 array = lookup_oacc_reduction (oacc_get_reduction_array_id
10024 (OMP_CLAUSE_DECL (c)), ctx);
10025
10026 /* Calculate the array offset. */
10027 tree offset = create_tmp_var (sizetype);
10028 gimplify_assign (offset, TYPE_SIZE_UNIT (type), stmt_seqp);
10029 stmt = gimple_build_assign (offset, MULT_EXPR, offset, ix);
10030 gimple_seq_add_stmt (stmt_seqp, stmt);
10031
10032 tree ptr = create_tmp_var (TREE_TYPE (array));
10033 stmt = gimple_build_assign (ptr, POINTER_PLUS_EXPR, array, offset);
10034 gimple_seq_add_stmt (stmt_seqp, stmt);
10035
10036 /* Extract array[ix] into mem. */
10037 tree mem = create_tmp_var (type);
10038 gimplify_assign (mem, build_simple_mem_ref (ptr), stmt_seqp);
10039
10040 /* Find the original reduction variable. */
10041 if (is_reference (var))
10042 var = build_simple_mem_ref (var);
10043
10044 tree t = create_tmp_var (type);
10045
10046 x = lang_hooks.decls.omp_clause_assign_op (c, t, var);
10047 gimplify_and_add (unshare_expr(x), stmt_seqp);
10048
10049 /* var = var op mem */
10050 switch (OMP_CLAUSE_REDUCTION_CODE (c))
10051 {
10052 case TRUTH_ANDIF_EXPR:
10053 case TRUTH_ORIF_EXPR:
10054 t = fold_build2 (OMP_CLAUSE_REDUCTION_CODE (c), integer_type_node,
10055 t, mem);
10056 gimplify_and_add (t, stmt_seqp);
10057 break;
10058 default:
10059 /* The lhs isn't a gimple_reg when var is COMPLEX_TYPE. */
10060 oacc_gimple_assign (t, OMP_CLAUSE_REDUCTION_CODE (c), mem,
10061 stmt_seqp);
10062 }
10063
10064 t = fold_build1 (NOP_EXPR, TREE_TYPE (var), t);
10065 x = lang_hooks.decls.omp_clause_assign_op (c, var, t);
10066 gimplify_and_add (unshare_expr(x), stmt_seqp);
10067 }
10068
10069 /* Increment the induction variable. */
10070 tree one = fold_build1 (NOP_EXPR, sizetype, integer_one_node);
10071 stmt = gimple_build_assign (ix, PLUS_EXPR, ix, one);
10072 gimple_seq_add_stmt (stmt_seqp, stmt);
10073
10074 /* Go back to the top of the loop. */
10075 gimple_seq_add_stmt (stmt_seqp, gimple_build_goto (loop_header));
10076
10077 /* Place the loop exit label here. */
10078 gimple_seq_add_stmt (stmt_seqp, gimple_build_label (loop_exit));
10079}
10080
10081/* Scan through all of the gimple stmts searching for an OMP_FOR_EXPR, and
10082 scan that for reductions. */
10083
10084static void
10085oacc_process_reduction_data (gimple_seq *body, gimple_seq *in_stmt_seqp,
10086 gimple_seq *out_stmt_seqp, omp_context *ctx)
10087{
10088 gimple_stmt_iterator gsi;
10089 gimple_seq inner = NULL;
10090
10091 /* A collapse clause may have inserted a new bind block. */
10092 gsi = gsi_start (*body);
10093 while (!gsi_end_p (gsi))
10094 {
42acab1c 10095 gimple *stmt = gsi_stmt (gsi);
ca4c3545 10096 if (gbind *bind_stmt = dyn_cast <gbind *> (stmt))
10097 {
10098 inner = gimple_bind_body (bind_stmt);
10099 body = &inner;
10100 gsi = gsi_start (*body);
10101 }
10102 else if (dyn_cast <gomp_for *> (stmt))
10103 break;
10104 else
10105 gsi_next (&gsi);
10106 }
10107
10108 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
10109 {
10110 tree clauses, nthreads, t, c, acc_device, acc_device_host, call,
10111 enter, exit;
10112 bool reduction_found = false;
10113
42acab1c 10114 gimple *stmt = gsi_stmt (gsi);
ca4c3545 10115
10116 switch (gimple_code (stmt))
10117 {
10118 case GIMPLE_OMP_FOR:
10119 clauses = gimple_omp_for_clauses (stmt);
10120
10121 /* Search for a reduction clause. */
10122 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
10123 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
10124 {
10125 reduction_found = true;
10126 break;
10127 }
10128
10129 if (!reduction_found)
10130 break;
10131
10132 ctx = maybe_lookup_ctx (stmt);
10133 t = NULL_TREE;
10134
10135 /* Extract the number of threads. */
10136 nthreads = create_tmp_var (sizetype);
10137 t = oacc_max_threads (ctx);
10138 gimplify_assign (nthreads, t, in_stmt_seqp);
10139
10140 /* Determine if this is kernel will be executed on the host. */
10141 call = builtin_decl_explicit (BUILT_IN_ACC_GET_DEVICE_TYPE);
10142 acc_device = create_tmp_var (integer_type_node, ".acc_device_type");
10143 stmt = gimple_build_call (call, 0);
10144 gimple_call_set_lhs (stmt, acc_device);
10145 gimple_seq_add_stmt (in_stmt_seqp, stmt);
10146
10147 /* Set nthreads = 1 for ACC_DEVICE_TYPE=host. */
10148 acc_device_host = create_tmp_var (integer_type_node,
10149 ".acc_device_host");
10150 gimplify_assign (acc_device_host,
10151 build_int_cst (integer_type_node,
10152 GOMP_DEVICE_HOST),
10153 in_stmt_seqp);
10154
10155 enter = create_artificial_label (UNKNOWN_LOCATION);
10156 exit = create_artificial_label (UNKNOWN_LOCATION);
10157
ca4c3545 10158 stmt = gimple_build_cond (EQ_EXPR, acc_device, acc_device_host,
10159 enter, exit);
10160 gimple_seq_add_stmt (in_stmt_seqp, stmt);
10161 gimple_seq_add_stmt (in_stmt_seqp, gimple_build_label (enter));
10162 gimplify_assign (nthreads, fold_build1 (NOP_EXPR, sizetype,
10163 integer_one_node),
10164 in_stmt_seqp);
10165 gimple_seq_add_stmt (in_stmt_seqp, gimple_build_label (exit));
10166
10167 oacc_initialize_reduction_data (clauses, nthreads, in_stmt_seqp,
10168 ctx);
10169 oacc_finalize_reduction_data (clauses, nthreads, out_stmt_seqp, ctx);
10170 break;
10171 default:
10172 // Scan for other directives which support reduction here.
10173 break;
10174 }
10175 }
10176}
773c5ba7 10177
bc7bff74 10178/* If ctx is a worksharing context inside of a cancellable parallel
10179 region and it isn't nowait, add lhs to its GIMPLE_OMP_RETURN
10180 and conditional branch to parallel's cancel_label to handle
10181 cancellation in the implicit barrier. */
10182
10183static void
10184maybe_add_implicit_barrier_cancel (omp_context *ctx, gimple_seq *body)
10185{
42acab1c 10186 gimple *omp_return = gimple_seq_last_stmt (*body);
bc7bff74 10187 gcc_assert (gimple_code (omp_return) == GIMPLE_OMP_RETURN);
10188 if (gimple_omp_return_nowait_p (omp_return))
10189 return;
10190 if (ctx->outer
10191 && gimple_code (ctx->outer->stmt) == GIMPLE_OMP_PARALLEL
10192 && ctx->outer->cancellable)
10193 {
15b28553 10194 tree fndecl = builtin_decl_explicit (BUILT_IN_GOMP_CANCEL);
10195 tree c_bool_type = TREE_TYPE (TREE_TYPE (fndecl));
f9e245b2 10196 tree lhs = create_tmp_var (c_bool_type);
bc7bff74 10197 gimple_omp_return_set_lhs (omp_return, lhs);
10198 tree fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
42acab1c 10199 gimple *g = gimple_build_cond (NE_EXPR, lhs,
15b28553 10200 fold_convert (c_bool_type,
10201 boolean_false_node),
bc7bff74 10202 ctx->outer->cancel_label, fallthru_label);
10203 gimple_seq_add_stmt (body, g);
10204 gimple_seq_add_stmt (body, gimple_build_label (fallthru_label));
10205 }
10206}
10207
75a70cf9 10208/* Lower the OpenMP sections directive in the current statement in GSI_P.
10209 CTX is the enclosing OMP context for the current statement. */
773c5ba7 10210
10211static void
75a70cf9 10212lower_omp_sections (gimple_stmt_iterator *gsi_p, omp_context *ctx)
773c5ba7 10213{
75a70cf9 10214 tree block, control;
10215 gimple_stmt_iterator tgsi;
1a91d914 10216 gomp_sections *stmt;
42acab1c 10217 gimple *t;
1a91d914 10218 gbind *new_stmt, *bind;
e3a19533 10219 gimple_seq ilist, dlist, olist, new_body;
773c5ba7 10220
1a91d914 10221 stmt = as_a <gomp_sections *> (gsi_stmt (*gsi_p));
773c5ba7 10222
8a4a28a8 10223 push_gimplify_context ();
773c5ba7 10224
10225 dlist = NULL;
10226 ilist = NULL;
75a70cf9 10227 lower_rec_input_clauses (gimple_omp_sections_clauses (stmt),
bc7bff74 10228 &ilist, &dlist, ctx, NULL);
773c5ba7 10229
e3a19533 10230 new_body = gimple_omp_body (stmt);
10231 gimple_omp_set_body (stmt, NULL);
10232 tgsi = gsi_start (new_body);
10233 for (; !gsi_end_p (tgsi); gsi_next (&tgsi))
773c5ba7 10234 {
10235 omp_context *sctx;
42acab1c 10236 gimple *sec_start;
773c5ba7 10237
75a70cf9 10238 sec_start = gsi_stmt (tgsi);
773c5ba7 10239 sctx = maybe_lookup_ctx (sec_start);
10240 gcc_assert (sctx);
10241
e3a19533 10242 lower_omp (gimple_omp_body_ptr (sec_start), sctx);
10243 gsi_insert_seq_after (&tgsi, gimple_omp_body (sec_start),
10244 GSI_CONTINUE_LINKING);
75a70cf9 10245 gimple_omp_set_body (sec_start, NULL);
773c5ba7 10246
e3a19533 10247 if (gsi_one_before_end_p (tgsi))
773c5ba7 10248 {
75a70cf9 10249 gimple_seq l = NULL;
10250 lower_lastprivate_clauses (gimple_omp_sections_clauses (stmt), NULL,
773c5ba7 10251 &l, ctx);
e3a19533 10252 gsi_insert_seq_after (&tgsi, l, GSI_CONTINUE_LINKING);
75a70cf9 10253 gimple_omp_section_set_last (sec_start);
773c5ba7 10254 }
48e1416a 10255
e3a19533 10256 gsi_insert_after (&tgsi, gimple_build_omp_return (false),
10257 GSI_CONTINUE_LINKING);
773c5ba7 10258 }
1e8e9920 10259
10260 block = make_node (BLOCK);
e3a19533 10261 bind = gimple_build_bind (NULL, new_body, block);
1e8e9920 10262
75a70cf9 10263 olist = NULL;
10264 lower_reduction_clauses (gimple_omp_sections_clauses (stmt), &olist, ctx);
773c5ba7 10265
1d22f541 10266 block = make_node (BLOCK);
75a70cf9 10267 new_stmt = gimple_build_bind (NULL, NULL, block);
e3a19533 10268 gsi_replace (gsi_p, new_stmt, true);
773c5ba7 10269
1d22f541 10270 pop_gimplify_context (new_stmt);
75a70cf9 10271 gimple_bind_append_vars (new_stmt, ctx->block_vars);
10272 BLOCK_VARS (block) = gimple_bind_vars (bind);
1d22f541 10273 if (BLOCK_VARS (block))
10274 TREE_USED (block) = 1;
10275
75a70cf9 10276 new_body = NULL;
10277 gimple_seq_add_seq (&new_body, ilist);
10278 gimple_seq_add_stmt (&new_body, stmt);
10279 gimple_seq_add_stmt (&new_body, gimple_build_omp_sections_switch ());
10280 gimple_seq_add_stmt (&new_body, bind);
61e47ac8 10281
ac6e3339 10282 control = create_tmp_var (unsigned_type_node, ".section");
75a70cf9 10283 t = gimple_build_omp_continue (control, control);
10284 gimple_omp_sections_set_control (stmt, control);
10285 gimple_seq_add_stmt (&new_body, t);
61e47ac8 10286
75a70cf9 10287 gimple_seq_add_seq (&new_body, olist);
bc7bff74 10288 if (ctx->cancellable)
10289 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
75a70cf9 10290 gimple_seq_add_seq (&new_body, dlist);
773c5ba7 10291
75a70cf9 10292 new_body = maybe_catch_exception (new_body);
aade31a0 10293
75a70cf9 10294 t = gimple_build_omp_return
10295 (!!find_omp_clause (gimple_omp_sections_clauses (stmt),
10296 OMP_CLAUSE_NOWAIT));
10297 gimple_seq_add_stmt (&new_body, t);
bc7bff74 10298 maybe_add_implicit_barrier_cancel (ctx, &new_body);
61e47ac8 10299
75a70cf9 10300 gimple_bind_set_body (new_stmt, new_body);
1e8e9920 10301}
10302
10303
773c5ba7 10304/* A subroutine of lower_omp_single. Expand the simple form of
75a70cf9 10305 a GIMPLE_OMP_SINGLE, without a copyprivate clause:
1e8e9920 10306
10307 if (GOMP_single_start ())
10308 BODY;
10309 [ GOMP_barrier (); ] -> unless 'nowait' is present.
773c5ba7 10310
10311 FIXME. It may be better to delay expanding the logic of this until
10312 pass_expand_omp. The expanded logic may make the job more difficult
10313 to a synchronization analysis pass. */
1e8e9920 10314
10315static void
1a91d914 10316lower_omp_single_simple (gomp_single *single_stmt, gimple_seq *pre_p)
1e8e9920 10317{
e60a6f7b 10318 location_t loc = gimple_location (single_stmt);
10319 tree tlabel = create_artificial_label (loc);
10320 tree flabel = create_artificial_label (loc);
42acab1c 10321 gimple *call, *cond;
75a70cf9 10322 tree lhs, decl;
10323
b9a16870 10324 decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_START);
f9e245b2 10325 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (decl)));
75a70cf9 10326 call = gimple_build_call (decl, 0);
10327 gimple_call_set_lhs (call, lhs);
10328 gimple_seq_add_stmt (pre_p, call);
10329
10330 cond = gimple_build_cond (EQ_EXPR, lhs,
389dd41b 10331 fold_convert_loc (loc, TREE_TYPE (lhs),
10332 boolean_true_node),
75a70cf9 10333 tlabel, flabel);
10334 gimple_seq_add_stmt (pre_p, cond);
10335 gimple_seq_add_stmt (pre_p, gimple_build_label (tlabel));
10336 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
10337 gimple_seq_add_stmt (pre_p, gimple_build_label (flabel));
1e8e9920 10338}
10339
773c5ba7 10340
10341/* A subroutine of lower_omp_single. Expand the simple form of
75a70cf9 10342 a GIMPLE_OMP_SINGLE, with a copyprivate clause:
1e8e9920 10343
10344 #pragma omp single copyprivate (a, b, c)
10345
10346 Create a new structure to hold copies of 'a', 'b' and 'c' and emit:
10347
10348 {
10349 if ((copyout_p = GOMP_single_copy_start ()) == NULL)
10350 {
10351 BODY;
10352 copyout.a = a;
10353 copyout.b = b;
10354 copyout.c = c;
10355 GOMP_single_copy_end (&copyout);
10356 }
10357 else
10358 {
10359 a = copyout_p->a;
10360 b = copyout_p->b;
10361 c = copyout_p->c;
10362 }
10363 GOMP_barrier ();
10364 }
773c5ba7 10365
10366 FIXME. It may be better to delay expanding the logic of this until
10367 pass_expand_omp. The expanded logic may make the job more difficult
10368 to a synchronization analysis pass. */
1e8e9920 10369
10370static void
1a91d914 10371lower_omp_single_copy (gomp_single *single_stmt, gimple_seq *pre_p,
10372 omp_context *ctx)
1e8e9920 10373{
b9a16870 10374 tree ptr_type, t, l0, l1, l2, bfn_decl;
75a70cf9 10375 gimple_seq copyin_seq;
e60a6f7b 10376 location_t loc = gimple_location (single_stmt);
1e8e9920 10377
10378 ctx->sender_decl = create_tmp_var (ctx->record_type, ".omp_copy_o");
10379
10380 ptr_type = build_pointer_type (ctx->record_type);
10381 ctx->receiver_decl = create_tmp_var (ptr_type, ".omp_copy_i");
10382
e60a6f7b 10383 l0 = create_artificial_label (loc);
10384 l1 = create_artificial_label (loc);
10385 l2 = create_artificial_label (loc);
1e8e9920 10386
b9a16870 10387 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_START);
10388 t = build_call_expr_loc (loc, bfn_decl, 0);
389dd41b 10389 t = fold_convert_loc (loc, ptr_type, t);
75a70cf9 10390 gimplify_assign (ctx->receiver_decl, t, pre_p);
1e8e9920 10391
10392 t = build2 (EQ_EXPR, boolean_type_node, ctx->receiver_decl,
10393 build_int_cst (ptr_type, 0));
10394 t = build3 (COND_EXPR, void_type_node, t,
10395 build_and_jump (&l0), build_and_jump (&l1));
10396 gimplify_and_add (t, pre_p);
10397
75a70cf9 10398 gimple_seq_add_stmt (pre_p, gimple_build_label (l0));
1e8e9920 10399
75a70cf9 10400 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
1e8e9920 10401
10402 copyin_seq = NULL;
75a70cf9 10403 lower_copyprivate_clauses (gimple_omp_single_clauses (single_stmt), pre_p,
1e8e9920 10404 &copyin_seq, ctx);
10405
389dd41b 10406 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
b9a16870 10407 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_END);
10408 t = build_call_expr_loc (loc, bfn_decl, 1, t);
1e8e9920 10409 gimplify_and_add (t, pre_p);
10410
10411 t = build_and_jump (&l2);
10412 gimplify_and_add (t, pre_p);
10413
75a70cf9 10414 gimple_seq_add_stmt (pre_p, gimple_build_label (l1));
1e8e9920 10415
75a70cf9 10416 gimple_seq_add_seq (pre_p, copyin_seq);
1e8e9920 10417
75a70cf9 10418 gimple_seq_add_stmt (pre_p, gimple_build_label (l2));
1e8e9920 10419}
10420
773c5ba7 10421
1e8e9920 10422/* Expand code for an OpenMP single directive. */
10423
10424static void
75a70cf9 10425lower_omp_single (gimple_stmt_iterator *gsi_p, omp_context *ctx)
1e8e9920 10426{
75a70cf9 10427 tree block;
42acab1c 10428 gimple *t;
1a91d914 10429 gomp_single *single_stmt = as_a <gomp_single *> (gsi_stmt (*gsi_p));
10430 gbind *bind;
bc7bff74 10431 gimple_seq bind_body, bind_body_tail = NULL, dlist;
1e8e9920 10432
8a4a28a8 10433 push_gimplify_context ();
1e8e9920 10434
e3a19533 10435 block = make_node (BLOCK);
10436 bind = gimple_build_bind (NULL, NULL, block);
10437 gsi_replace (gsi_p, bind, true);
75a70cf9 10438 bind_body = NULL;
e3a19533 10439 dlist = NULL;
75a70cf9 10440 lower_rec_input_clauses (gimple_omp_single_clauses (single_stmt),
bc7bff74 10441 &bind_body, &dlist, ctx, NULL);
e3a19533 10442 lower_omp (gimple_omp_body_ptr (single_stmt), ctx);
1e8e9920 10443
75a70cf9 10444 gimple_seq_add_stmt (&bind_body, single_stmt);
1e8e9920 10445
10446 if (ctx->record_type)
75a70cf9 10447 lower_omp_single_copy (single_stmt, &bind_body, ctx);
1e8e9920 10448 else
75a70cf9 10449 lower_omp_single_simple (single_stmt, &bind_body);
10450
10451 gimple_omp_set_body (single_stmt, NULL);
1e8e9920 10452
75a70cf9 10453 gimple_seq_add_seq (&bind_body, dlist);
61e47ac8 10454
75a70cf9 10455 bind_body = maybe_catch_exception (bind_body);
61e47ac8 10456
48e1416a 10457 t = gimple_build_omp_return
75a70cf9 10458 (!!find_omp_clause (gimple_omp_single_clauses (single_stmt),
10459 OMP_CLAUSE_NOWAIT));
bc7bff74 10460 gimple_seq_add_stmt (&bind_body_tail, t);
10461 maybe_add_implicit_barrier_cancel (ctx, &bind_body_tail);
10462 if (ctx->record_type)
10463 {
10464 gimple_stmt_iterator gsi = gsi_start (bind_body_tail);
10465 tree clobber = build_constructor (ctx->record_type, NULL);
10466 TREE_THIS_VOLATILE (clobber) = 1;
10467 gsi_insert_after (&gsi, gimple_build_assign (ctx->sender_decl,
10468 clobber), GSI_SAME_STMT);
10469 }
10470 gimple_seq_add_seq (&bind_body, bind_body_tail);
e3a19533 10471 gimple_bind_set_body (bind, bind_body);
61e47ac8 10472
1e8e9920 10473 pop_gimplify_context (bind);
773c5ba7 10474
75a70cf9 10475 gimple_bind_append_vars (bind, ctx->block_vars);
10476 BLOCK_VARS (block) = ctx->block_vars;
1d22f541 10477 if (BLOCK_VARS (block))
10478 TREE_USED (block) = 1;
1e8e9920 10479}
10480
773c5ba7 10481
1e8e9920 10482/* Expand code for an OpenMP master directive. */
10483
10484static void
75a70cf9 10485lower_omp_master (gimple_stmt_iterator *gsi_p, omp_context *ctx)
1e8e9920 10486{
b9a16870 10487 tree block, lab = NULL, x, bfn_decl;
42acab1c 10488 gimple *stmt = gsi_stmt (*gsi_p);
1a91d914 10489 gbind *bind;
389dd41b 10490 location_t loc = gimple_location (stmt);
75a70cf9 10491 gimple_seq tseq;
1e8e9920 10492
8a4a28a8 10493 push_gimplify_context ();
1e8e9920 10494
10495 block = make_node (BLOCK);
e3a19533 10496 bind = gimple_build_bind (NULL, NULL, block);
10497 gsi_replace (gsi_p, bind, true);
10498 gimple_bind_add_stmt (bind, stmt);
61e47ac8 10499
b9a16870 10500 bfn_decl = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
10501 x = build_call_expr_loc (loc, bfn_decl, 0);
1e8e9920 10502 x = build2 (EQ_EXPR, boolean_type_node, x, integer_zero_node);
10503 x = build3 (COND_EXPR, void_type_node, x, NULL, build_and_jump (&lab));
75a70cf9 10504 tseq = NULL;
10505 gimplify_and_add (x, &tseq);
10506 gimple_bind_add_seq (bind, tseq);
1e8e9920 10507
e3a19533 10508 lower_omp (gimple_omp_body_ptr (stmt), ctx);
75a70cf9 10509 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
10510 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
10511 gimple_omp_set_body (stmt, NULL);
1e8e9920 10512
75a70cf9 10513 gimple_bind_add_stmt (bind, gimple_build_label (lab));
61e47ac8 10514
75a70cf9 10515 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
61e47ac8 10516
1e8e9920 10517 pop_gimplify_context (bind);
773c5ba7 10518
75a70cf9 10519 gimple_bind_append_vars (bind, ctx->block_vars);
10520 BLOCK_VARS (block) = ctx->block_vars;
1e8e9920 10521}
10522
773c5ba7 10523
bc7bff74 10524/* Expand code for an OpenMP taskgroup directive. */
10525
10526static void
10527lower_omp_taskgroup (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10528{
42acab1c 10529 gimple *stmt = gsi_stmt (*gsi_p);
1a91d914 10530 gcall *x;
10531 gbind *bind;
bc7bff74 10532 tree block = make_node (BLOCK);
10533
10534 bind = gimple_build_bind (NULL, NULL, block);
10535 gsi_replace (gsi_p, bind, true);
10536 gimple_bind_add_stmt (bind, stmt);
10537
10538 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_TASKGROUP_START),
10539 0);
10540 gimple_bind_add_stmt (bind, x);
10541
10542 lower_omp (gimple_omp_body_ptr (stmt), ctx);
10543 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
10544 gimple_omp_set_body (stmt, NULL);
10545
10546 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
10547
10548 gimple_bind_append_vars (bind, ctx->block_vars);
10549 BLOCK_VARS (block) = ctx->block_vars;
10550}
10551
10552
1e8e9920 10553/* Expand code for an OpenMP ordered directive. */
10554
10555static void
75a70cf9 10556lower_omp_ordered (gimple_stmt_iterator *gsi_p, omp_context *ctx)
1e8e9920 10557{
75a70cf9 10558 tree block;
42acab1c 10559 gimple *stmt = gsi_stmt (*gsi_p);
1a91d914 10560 gcall *x;
10561 gbind *bind;
1e8e9920 10562
8a4a28a8 10563 push_gimplify_context ();
1e8e9920 10564
10565 block = make_node (BLOCK);
e3a19533 10566 bind = gimple_build_bind (NULL, NULL, block);
10567 gsi_replace (gsi_p, bind, true);
10568 gimple_bind_add_stmt (bind, stmt);
61e47ac8 10569
b9a16870 10570 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_START),
10571 0);
75a70cf9 10572 gimple_bind_add_stmt (bind, x);
1e8e9920 10573
e3a19533 10574 lower_omp (gimple_omp_body_ptr (stmt), ctx);
75a70cf9 10575 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
10576 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
10577 gimple_omp_set_body (stmt, NULL);
1e8e9920 10578
b9a16870 10579 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_END), 0);
75a70cf9 10580 gimple_bind_add_stmt (bind, x);
61e47ac8 10581
75a70cf9 10582 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
61e47ac8 10583
1e8e9920 10584 pop_gimplify_context (bind);
773c5ba7 10585
75a70cf9 10586 gimple_bind_append_vars (bind, ctx->block_vars);
10587 BLOCK_VARS (block) = gimple_bind_vars (bind);
1e8e9920 10588}
10589
1e8e9920 10590
75a70cf9 10591/* Gimplify a GIMPLE_OMP_CRITICAL statement. This is a relatively simple
1e8e9920 10592 substitution of a couple of function calls. But in the NAMED case,
10593 requires that languages coordinate a symbol name. It is therefore
10594 best put here in common code. */
10595
d4786b13 10596static GTY(()) hash_map<tree, tree> *critical_name_mutexes;
1e8e9920 10597
10598static void
75a70cf9 10599lower_omp_critical (gimple_stmt_iterator *gsi_p, omp_context *ctx)
1e8e9920 10600{
75a70cf9 10601 tree block;
10602 tree name, lock, unlock;
1a91d914 10603 gomp_critical *stmt = as_a <gomp_critical *> (gsi_stmt (*gsi_p));
10604 gbind *bind;
389dd41b 10605 location_t loc = gimple_location (stmt);
75a70cf9 10606 gimple_seq tbody;
1e8e9920 10607
75a70cf9 10608 name = gimple_omp_critical_name (stmt);
1e8e9920 10609 if (name)
10610 {
c2f47e15 10611 tree decl;
1e8e9920 10612
10613 if (!critical_name_mutexes)
d4786b13 10614 critical_name_mutexes = hash_map<tree, tree>::create_ggc (10);
1e8e9920 10615
d4786b13 10616 tree *n = critical_name_mutexes->get (name);
1e8e9920 10617 if (n == NULL)
10618 {
10619 char *new_str;
10620
f9e245b2 10621 decl = create_tmp_var_raw (ptr_type_node);
1e8e9920 10622
10623 new_str = ACONCAT ((".gomp_critical_user_",
10624 IDENTIFIER_POINTER (name), NULL));
10625 DECL_NAME (decl) = get_identifier (new_str);
10626 TREE_PUBLIC (decl) = 1;
10627 TREE_STATIC (decl) = 1;
10628 DECL_COMMON (decl) = 1;
10629 DECL_ARTIFICIAL (decl) = 1;
10630 DECL_IGNORED_P (decl) = 1;
b0c5e347 10631
97221fd7 10632 varpool_node::finalize_decl (decl);
1e8e9920 10633
d4786b13 10634 critical_name_mutexes->put (name, decl);
1e8e9920 10635 }
10636 else
d4786b13 10637 decl = *n;
1e8e9920 10638
ca4c3545 10639 /* If '#pragma omp critical' is inside offloaded region or
351fb0ce 10640 inside function marked as offloadable, the symbol must be
10641 marked as offloadable too. */
10642 omp_context *octx;
10643 if (cgraph_node::get (current_function_decl)->offloadable)
10644 varpool_node::get_create (decl)->offloadable = 1;
10645 else
10646 for (octx = ctx->outer; octx; octx = octx->outer)
ca4c3545 10647 if (is_gimple_omp_offloaded (octx->stmt))
351fb0ce 10648 {
10649 varpool_node::get_create (decl)->offloadable = 1;
10650 break;
10651 }
10652
b9a16870 10653 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_START);
389dd41b 10654 lock = build_call_expr_loc (loc, lock, 1, build_fold_addr_expr_loc (loc, decl));
1e8e9920 10655
b9a16870 10656 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_END);
389dd41b 10657 unlock = build_call_expr_loc (loc, unlock, 1,
10658 build_fold_addr_expr_loc (loc, decl));
1e8e9920 10659 }
10660 else
10661 {
b9a16870 10662 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_START);
389dd41b 10663 lock = build_call_expr_loc (loc, lock, 0);
1e8e9920 10664
b9a16870 10665 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_END);
389dd41b 10666 unlock = build_call_expr_loc (loc, unlock, 0);
1e8e9920 10667 }
10668
8a4a28a8 10669 push_gimplify_context ();
1e8e9920 10670
10671 block = make_node (BLOCK);
e3a19533 10672 bind = gimple_build_bind (NULL, NULL, block);
10673 gsi_replace (gsi_p, bind, true);
10674 gimple_bind_add_stmt (bind, stmt);
61e47ac8 10675
75a70cf9 10676 tbody = gimple_bind_body (bind);
10677 gimplify_and_add (lock, &tbody);
10678 gimple_bind_set_body (bind, tbody);
1e8e9920 10679
e3a19533 10680 lower_omp (gimple_omp_body_ptr (stmt), ctx);
75a70cf9 10681 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
10682 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
10683 gimple_omp_set_body (stmt, NULL);
1e8e9920 10684
75a70cf9 10685 tbody = gimple_bind_body (bind);
10686 gimplify_and_add (unlock, &tbody);
10687 gimple_bind_set_body (bind, tbody);
61e47ac8 10688
75a70cf9 10689 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
1e8e9920 10690
10691 pop_gimplify_context (bind);
75a70cf9 10692 gimple_bind_append_vars (bind, ctx->block_vars);
10693 BLOCK_VARS (block) = gimple_bind_vars (bind);
773c5ba7 10694}
10695
10696
10697/* A subroutine of lower_omp_for. Generate code to emit the predicate
10698 for a lastprivate clause. Given a loop control predicate of (V
10699 cond N2), we gate the clause on (!(V cond N2)). The lowered form
1e4afe3c 10700 is appended to *DLIST, iterator initialization is appended to
10701 *BODY_P. */
773c5ba7 10702
10703static void
75a70cf9 10704lower_omp_for_lastprivate (struct omp_for_data *fd, gimple_seq *body_p,
10705 gimple_seq *dlist, struct omp_context *ctx)
773c5ba7 10706{
75a70cf9 10707 tree clauses, cond, vinit;
773c5ba7 10708 enum tree_code cond_code;
75a70cf9 10709 gimple_seq stmts;
48e1416a 10710
fd6481cf 10711 cond_code = fd->loop.cond_code;
773c5ba7 10712 cond_code = cond_code == LT_EXPR ? GE_EXPR : LE_EXPR;
10713
10714 /* When possible, use a strict equality expression. This can let VRP
10715 type optimizations deduce the value and remove a copy. */
e913b5cd 10716 if (tree_fits_shwi_p (fd->loop.step))
773c5ba7 10717 {
e913b5cd 10718 HOST_WIDE_INT step = tree_to_shwi (fd->loop.step);
773c5ba7 10719 if (step == 1 || step == -1)
10720 cond_code = EQ_EXPR;
10721 }
10722
d7729e26 10723 tree n2 = fd->loop.n2;
10724 if (fd->collapse > 1
10725 && TREE_CODE (n2) != INTEGER_CST
10726 && gimple_omp_for_combined_into_p (fd->for_stmt)
10727 && gimple_code (ctx->outer->stmt) == GIMPLE_OMP_FOR)
10728 {
10729 gomp_for *gfor = as_a <gomp_for *> (ctx->outer->stmt);
10730 if (gimple_omp_for_kind (gfor) == GF_OMP_FOR_KIND_FOR)
10731 {
10732 struct omp_for_data outer_fd;
10733 extract_omp_for_data (gfor, &outer_fd, NULL);
10734 n2 = fold_convert (TREE_TYPE (n2), outer_fd.loop.n2);
10735 }
10736 }
10737 cond = build2 (cond_code, boolean_type_node, fd->loop.v, n2);
773c5ba7 10738
75a70cf9 10739 clauses = gimple_omp_for_clauses (fd->for_stmt);
1e4afe3c 10740 stmts = NULL;
10741 lower_lastprivate_clauses (clauses, cond, &stmts, ctx);
75a70cf9 10742 if (!gimple_seq_empty_p (stmts))
1e4afe3c 10743 {
75a70cf9 10744 gimple_seq_add_seq (&stmts, *dlist);
fd6481cf 10745 *dlist = stmts;
1e4afe3c 10746
10747 /* Optimize: v = 0; is usually cheaper than v = some_other_constant. */
fd6481cf 10748 vinit = fd->loop.n1;
1e4afe3c 10749 if (cond_code == EQ_EXPR
e913b5cd 10750 && tree_fits_shwi_p (fd->loop.n2)
fd6481cf 10751 && ! integer_zerop (fd->loop.n2))
10752 vinit = build_int_cst (TREE_TYPE (fd->loop.v), 0);
3d483a94 10753 else
10754 vinit = unshare_expr (vinit);
1e4afe3c 10755
10756 /* Initialize the iterator variable, so that threads that don't execute
10757 any iterations don't execute the lastprivate clauses by accident. */
75a70cf9 10758 gimplify_assign (fd->loop.v, vinit, body_p);
1e4afe3c 10759 }
773c5ba7 10760}
10761
10762
ca4c3545 10763/* Lower code for an OMP loop directive. */
773c5ba7 10764
10765static void
75a70cf9 10766lower_omp_for (gimple_stmt_iterator *gsi_p, omp_context *ctx)
773c5ba7 10767{
75a70cf9 10768 tree *rhs_p, block;
bc7bff74 10769 struct omp_for_data fd, *fdp = NULL;
1a91d914 10770 gomp_for *stmt = as_a <gomp_for *> (gsi_stmt (*gsi_p));
10771 gbind *new_stmt;
f018d957 10772 gimple_seq omp_for_body, body, dlist;
75a70cf9 10773 size_t i;
773c5ba7 10774
8a4a28a8 10775 push_gimplify_context ();
773c5ba7 10776
e3a19533 10777 lower_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
773c5ba7 10778
1d22f541 10779 block = make_node (BLOCK);
75a70cf9 10780 new_stmt = gimple_build_bind (NULL, NULL, block);
e3a19533 10781 /* Replace at gsi right away, so that 'stmt' is no member
47ae02b7 10782 of a sequence anymore as we're going to add to a different
e3a19533 10783 one below. */
10784 gsi_replace (gsi_p, new_stmt, true);
1d22f541 10785
773c5ba7 10786 /* Move declaration of temporaries in the loop body before we make
10787 it go away. */
75a70cf9 10788 omp_for_body = gimple_omp_body (stmt);
10789 if (!gimple_seq_empty_p (omp_for_body)
10790 && gimple_code (gimple_seq_first_stmt (omp_for_body)) == GIMPLE_BIND)
10791 {
1a91d914 10792 gbind *inner_bind
10793 = as_a <gbind *> (gimple_seq_first_stmt (omp_for_body));
6d5a8d89 10794 tree vars = gimple_bind_vars (inner_bind);
75a70cf9 10795 gimple_bind_append_vars (new_stmt, vars);
6d5a8d89 10796 /* bind_vars/BLOCK_VARS are being moved to new_stmt/block, don't
10797 keep them on the inner_bind and it's block. */
10798 gimple_bind_set_vars (inner_bind, NULL_TREE);
10799 if (gimple_bind_block (inner_bind))
10800 BLOCK_VARS (gimple_bind_block (inner_bind)) = NULL_TREE;
75a70cf9 10801 }
773c5ba7 10802
bc7bff74 10803 if (gimple_omp_for_combined_into_p (stmt))
10804 {
10805 extract_omp_for_data (stmt, &fd, NULL);
10806 fdp = &fd;
10807
10808 /* We need two temporaries with fd.loop.v type (istart/iend)
10809 and then (fd.collapse - 1) temporaries with the same
10810 type for count2 ... countN-1 vars if not constant. */
10811 size_t count = 2;
10812 tree type = fd.iter_type;
10813 if (fd.collapse > 1
10814 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
10815 count += fd.collapse - 1;
10816 bool parallel_for = gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR;
10817 tree outerc = NULL, *pc = gimple_omp_for_clauses_ptr (stmt);
10818 tree clauses = *pc;
10819 if (parallel_for)
10820 outerc
10821 = find_omp_clause (gimple_omp_parallel_clauses (ctx->outer->stmt),
10822 OMP_CLAUSE__LOOPTEMP_);
10823 for (i = 0; i < count; i++)
10824 {
10825 tree temp;
10826 if (parallel_for)
10827 {
10828 gcc_assert (outerc);
10829 temp = lookup_decl (OMP_CLAUSE_DECL (outerc), ctx->outer);
10830 outerc = find_omp_clause (OMP_CLAUSE_CHAIN (outerc),
10831 OMP_CLAUSE__LOOPTEMP_);
10832 }
10833 else
691447ab 10834 {
f9e245b2 10835 temp = create_tmp_var (type);
691447ab 10836 insert_decl_map (&ctx->outer->cb, temp, temp);
10837 }
bc7bff74 10838 *pc = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__LOOPTEMP_);
10839 OMP_CLAUSE_DECL (*pc) = temp;
10840 pc = &OMP_CLAUSE_CHAIN (*pc);
10841 }
10842 *pc = clauses;
10843 }
10844
75a70cf9 10845 /* The pre-body and input clauses go before the lowered GIMPLE_OMP_FOR. */
773c5ba7 10846 dlist = NULL;
75a70cf9 10847 body = NULL;
bc7bff74 10848 lower_rec_input_clauses (gimple_omp_for_clauses (stmt), &body, &dlist, ctx,
10849 fdp);
75a70cf9 10850 gimple_seq_add_seq (&body, gimple_omp_for_pre_body (stmt));
773c5ba7 10851
3d483a94 10852 lower_omp (gimple_omp_body_ptr (stmt), ctx);
10853
773c5ba7 10854 /* Lower the header expressions. At this point, we can assume that
10855 the header is of the form:
10856
10857 #pragma omp for (V = VAL1; V {<|>|<=|>=} VAL2; V = V [+-] VAL3)
10858
10859 We just need to make sure that VAL1, VAL2 and VAL3 are lowered
10860 using the .omp_data_s mapping, if needed. */
75a70cf9 10861 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
fd6481cf 10862 {
75a70cf9 10863 rhs_p = gimple_omp_for_initial_ptr (stmt, i);
fd6481cf 10864 if (!is_gimple_min_invariant (*rhs_p))
75a70cf9 10865 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
fd6481cf 10866
75a70cf9 10867 rhs_p = gimple_omp_for_final_ptr (stmt, i);
fd6481cf 10868 if (!is_gimple_min_invariant (*rhs_p))
75a70cf9 10869 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
fd6481cf 10870
75a70cf9 10871 rhs_p = &TREE_OPERAND (gimple_omp_for_incr (stmt, i), 1);
fd6481cf 10872 if (!is_gimple_min_invariant (*rhs_p))
75a70cf9 10873 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
fd6481cf 10874 }
773c5ba7 10875
10876 /* Once lowered, extract the bounds and clauses. */
fd6481cf 10877 extract_omp_for_data (stmt, &fd, NULL);
773c5ba7 10878
75a70cf9 10879 lower_omp_for_lastprivate (&fd, &body, &dlist, ctx);
773c5ba7 10880
75a70cf9 10881 gimple_seq_add_stmt (&body, stmt);
10882 gimple_seq_add_seq (&body, gimple_omp_body (stmt));
61e47ac8 10883
75a70cf9 10884 gimple_seq_add_stmt (&body, gimple_build_omp_continue (fd.loop.v,
10885 fd.loop.v));
61e47ac8 10886
773c5ba7 10887 /* After the loop, add exit clauses. */
75a70cf9 10888 lower_reduction_clauses (gimple_omp_for_clauses (stmt), &body, ctx);
bc7bff74 10889
10890 if (ctx->cancellable)
10891 gimple_seq_add_stmt (&body, gimple_build_label (ctx->cancel_label));
10892
75a70cf9 10893 gimple_seq_add_seq (&body, dlist);
773c5ba7 10894
75a70cf9 10895 body = maybe_catch_exception (body);
aade31a0 10896
61e47ac8 10897 /* Region exit marker goes at the end of the loop body. */
75a70cf9 10898 gimple_seq_add_stmt (&body, gimple_build_omp_return (fd.have_nowait));
bc7bff74 10899 maybe_add_implicit_barrier_cancel (ctx, &body);
1d22f541 10900 pop_gimplify_context (new_stmt);
75a70cf9 10901
10902 gimple_bind_append_vars (new_stmt, ctx->block_vars);
10903 BLOCK_VARS (block) = gimple_bind_vars (new_stmt);
1d22f541 10904 if (BLOCK_VARS (block))
10905 TREE_USED (block) = 1;
773c5ba7 10906
75a70cf9 10907 gimple_bind_set_body (new_stmt, body);
10908 gimple_omp_set_body (stmt, NULL);
10909 gimple_omp_for_set_pre_body (stmt, NULL);
1e8e9920 10910}
10911
48e1416a 10912/* Callback for walk_stmts. Check if the current statement only contains
a7dfc4fe 10913 GIMPLE_OMP_FOR or GIMPLE_OMP_SECTIONS. */
de7ef844 10914
10915static tree
75a70cf9 10916check_combined_parallel (gimple_stmt_iterator *gsi_p,
10917 bool *handled_ops_p,
10918 struct walk_stmt_info *wi)
de7ef844 10919{
4077bf7a 10920 int *info = (int *) wi->info;
42acab1c 10921 gimple *stmt = gsi_stmt (*gsi_p);
de7ef844 10922
75a70cf9 10923 *handled_ops_p = true;
10924 switch (gimple_code (stmt))
de7ef844 10925 {
75a70cf9 10926 WALK_SUBSTMTS;
10927
10928 case GIMPLE_OMP_FOR:
10929 case GIMPLE_OMP_SECTIONS:
de7ef844 10930 *info = *info == 0 ? 1 : -1;
10931 break;
10932 default:
10933 *info = -1;
10934 break;
10935 }
10936 return NULL;
10937}
773c5ba7 10938
fd6481cf 10939struct omp_taskcopy_context
10940{
10941 /* This field must be at the beginning, as we do "inheritance": Some
10942 callback functions for tree-inline.c (e.g., omp_copy_decl)
10943 receive a copy_body_data pointer that is up-casted to an
10944 omp_context pointer. */
10945 copy_body_data cb;
10946 omp_context *ctx;
10947};
10948
10949static tree
10950task_copyfn_copy_decl (tree var, copy_body_data *cb)
10951{
10952 struct omp_taskcopy_context *tcctx = (struct omp_taskcopy_context *) cb;
10953
10954 if (splay_tree_lookup (tcctx->ctx->sfield_map, (splay_tree_key) var))
f9e245b2 10955 return create_tmp_var (TREE_TYPE (var));
fd6481cf 10956
10957 return var;
10958}
10959
10960static tree
10961task_copyfn_remap_type (struct omp_taskcopy_context *tcctx, tree orig_type)
10962{
10963 tree name, new_fields = NULL, type, f;
10964
10965 type = lang_hooks.types.make_type (RECORD_TYPE);
10966 name = DECL_NAME (TYPE_NAME (orig_type));
e60a6f7b 10967 name = build_decl (gimple_location (tcctx->ctx->stmt),
10968 TYPE_DECL, name, type);
fd6481cf 10969 TYPE_NAME (type) = name;
10970
10971 for (f = TYPE_FIELDS (orig_type); f ; f = TREE_CHAIN (f))
10972 {
10973 tree new_f = copy_node (f);
10974 DECL_CONTEXT (new_f) = type;
10975 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &tcctx->cb);
10976 TREE_CHAIN (new_f) = new_fields;
75a70cf9 10977 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &tcctx->cb, NULL);
10978 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r, &tcctx->cb, NULL);
10979 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
10980 &tcctx->cb, NULL);
fd6481cf 10981 new_fields = new_f;
06ecf488 10982 tcctx->cb.decl_map->put (f, new_f);
fd6481cf 10983 }
10984 TYPE_FIELDS (type) = nreverse (new_fields);
10985 layout_type (type);
10986 return type;
10987}
10988
10989/* Create task copyfn. */
10990
10991static void
1a91d914 10992create_task_copyfn (gomp_task *task_stmt, omp_context *ctx)
fd6481cf 10993{
10994 struct function *child_cfun;
10995 tree child_fn, t, c, src, dst, f, sf, arg, sarg, decl;
10996 tree record_type, srecord_type, bind, list;
10997 bool record_needs_remap = false, srecord_needs_remap = false;
10998 splay_tree_node n;
10999 struct omp_taskcopy_context tcctx;
389dd41b 11000 location_t loc = gimple_location (task_stmt);
fd6481cf 11001
75a70cf9 11002 child_fn = gimple_omp_task_copy_fn (task_stmt);
fd6481cf 11003 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
11004 gcc_assert (child_cfun->cfg == NULL);
fd6481cf 11005 DECL_SAVED_TREE (child_fn) = alloc_stmt_list ();
11006
11007 /* Reset DECL_CONTEXT on function arguments. */
1767a056 11008 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
fd6481cf 11009 DECL_CONTEXT (t) = child_fn;
11010
11011 /* Populate the function. */
8a4a28a8 11012 push_gimplify_context ();
9078126c 11013 push_cfun (child_cfun);
fd6481cf 11014
11015 bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
11016 TREE_SIDE_EFFECTS (bind) = 1;
11017 list = NULL;
11018 DECL_SAVED_TREE (child_fn) = bind;
75a70cf9 11019 DECL_SOURCE_LOCATION (child_fn) = gimple_location (task_stmt);
fd6481cf 11020
11021 /* Remap src and dst argument types if needed. */
11022 record_type = ctx->record_type;
11023 srecord_type = ctx->srecord_type;
1767a056 11024 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
fd6481cf 11025 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
11026 {
11027 record_needs_remap = true;
11028 break;
11029 }
1767a056 11030 for (f = TYPE_FIELDS (srecord_type); f ; f = DECL_CHAIN (f))
fd6481cf 11031 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
11032 {
11033 srecord_needs_remap = true;
11034 break;
11035 }
11036
11037 if (record_needs_remap || srecord_needs_remap)
11038 {
11039 memset (&tcctx, '\0', sizeof (tcctx));
11040 tcctx.cb.src_fn = ctx->cb.src_fn;
11041 tcctx.cb.dst_fn = child_fn;
415d1b9a 11042 tcctx.cb.src_node = cgraph_node::get (tcctx.cb.src_fn);
53f79206 11043 gcc_checking_assert (tcctx.cb.src_node);
fd6481cf 11044 tcctx.cb.dst_node = tcctx.cb.src_node;
11045 tcctx.cb.src_cfun = ctx->cb.src_cfun;
11046 tcctx.cb.copy_decl = task_copyfn_copy_decl;
e38def9c 11047 tcctx.cb.eh_lp_nr = 0;
fd6481cf 11048 tcctx.cb.transform_call_graph_edges = CB_CGE_MOVE;
06ecf488 11049 tcctx.cb.decl_map = new hash_map<tree, tree>;
fd6481cf 11050 tcctx.ctx = ctx;
11051
11052 if (record_needs_remap)
11053 record_type = task_copyfn_remap_type (&tcctx, record_type);
11054 if (srecord_needs_remap)
11055 srecord_type = task_copyfn_remap_type (&tcctx, srecord_type);
11056 }
11057 else
11058 tcctx.cb.decl_map = NULL;
11059
fd6481cf 11060 arg = DECL_ARGUMENTS (child_fn);
11061 TREE_TYPE (arg) = build_pointer_type (record_type);
1767a056 11062 sarg = DECL_CHAIN (arg);
fd6481cf 11063 TREE_TYPE (sarg) = build_pointer_type (srecord_type);
11064
11065 /* First pass: initialize temporaries used in record_type and srecord_type
11066 sizes and field offsets. */
11067 if (tcctx.cb.decl_map)
75a70cf9 11068 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
fd6481cf 11069 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
11070 {
11071 tree *p;
11072
11073 decl = OMP_CLAUSE_DECL (c);
06ecf488 11074 p = tcctx.cb.decl_map->get (decl);
fd6481cf 11075 if (p == NULL)
11076 continue;
11077 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
11078 sf = (tree) n->value;
06ecf488 11079 sf = *tcctx.cb.decl_map->get (sf);
182cf5a9 11080 src = build_simple_mem_ref_loc (loc, sarg);
445d06b6 11081 src = omp_build_component_ref (src, sf);
75a70cf9 11082 t = build2 (MODIFY_EXPR, TREE_TYPE (*p), *p, src);
fd6481cf 11083 append_to_statement_list (t, &list);
11084 }
11085
11086 /* Second pass: copy shared var pointers and copy construct non-VLA
11087 firstprivate vars. */
75a70cf9 11088 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
fd6481cf 11089 switch (OMP_CLAUSE_CODE (c))
11090 {
11091 case OMP_CLAUSE_SHARED:
11092 decl = OMP_CLAUSE_DECL (c);
11093 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
11094 if (n == NULL)
11095 break;
11096 f = (tree) n->value;
11097 if (tcctx.cb.decl_map)
06ecf488 11098 f = *tcctx.cb.decl_map->get (f);
fd6481cf 11099 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
11100 sf = (tree) n->value;
11101 if (tcctx.cb.decl_map)
06ecf488 11102 sf = *tcctx.cb.decl_map->get (sf);
182cf5a9 11103 src = build_simple_mem_ref_loc (loc, sarg);
445d06b6 11104 src = omp_build_component_ref (src, sf);
182cf5a9 11105 dst = build_simple_mem_ref_loc (loc, arg);
445d06b6 11106 dst = omp_build_component_ref (dst, f);
75a70cf9 11107 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
fd6481cf 11108 append_to_statement_list (t, &list);
11109 break;
11110 case OMP_CLAUSE_FIRSTPRIVATE:
11111 decl = OMP_CLAUSE_DECL (c);
11112 if (is_variable_sized (decl))
11113 break;
11114 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
11115 if (n == NULL)
11116 break;
11117 f = (tree) n->value;
11118 if (tcctx.cb.decl_map)
06ecf488 11119 f = *tcctx.cb.decl_map->get (f);
fd6481cf 11120 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
11121 if (n != NULL)
11122 {
11123 sf = (tree) n->value;
11124 if (tcctx.cb.decl_map)
06ecf488 11125 sf = *tcctx.cb.decl_map->get (sf);
182cf5a9 11126 src = build_simple_mem_ref_loc (loc, sarg);
445d06b6 11127 src = omp_build_component_ref (src, sf);
fd6481cf 11128 if (use_pointer_for_field (decl, NULL) || is_reference (decl))
182cf5a9 11129 src = build_simple_mem_ref_loc (loc, src);
fd6481cf 11130 }
11131 else
11132 src = decl;
182cf5a9 11133 dst = build_simple_mem_ref_loc (loc, arg);
445d06b6 11134 dst = omp_build_component_ref (dst, f);
fd6481cf 11135 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
11136 append_to_statement_list (t, &list);
11137 break;
11138 case OMP_CLAUSE_PRIVATE:
11139 if (! OMP_CLAUSE_PRIVATE_OUTER_REF (c))
11140 break;
11141 decl = OMP_CLAUSE_DECL (c);
11142 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
11143 f = (tree) n->value;
11144 if (tcctx.cb.decl_map)
06ecf488 11145 f = *tcctx.cb.decl_map->get (f);
fd6481cf 11146 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
11147 if (n != NULL)
11148 {
11149 sf = (tree) n->value;
11150 if (tcctx.cb.decl_map)
06ecf488 11151 sf = *tcctx.cb.decl_map->get (sf);
182cf5a9 11152 src = build_simple_mem_ref_loc (loc, sarg);
445d06b6 11153 src = omp_build_component_ref (src, sf);
fd6481cf 11154 if (use_pointer_for_field (decl, NULL))
182cf5a9 11155 src = build_simple_mem_ref_loc (loc, src);
fd6481cf 11156 }
11157 else
11158 src = decl;
182cf5a9 11159 dst = build_simple_mem_ref_loc (loc, arg);
445d06b6 11160 dst = omp_build_component_ref (dst, f);
75a70cf9 11161 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
fd6481cf 11162 append_to_statement_list (t, &list);
11163 break;
11164 default:
11165 break;
11166 }
11167
11168 /* Last pass: handle VLA firstprivates. */
11169 if (tcctx.cb.decl_map)
75a70cf9 11170 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
fd6481cf 11171 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
11172 {
11173 tree ind, ptr, df;
11174
11175 decl = OMP_CLAUSE_DECL (c);
11176 if (!is_variable_sized (decl))
11177 continue;
11178 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
11179 if (n == NULL)
11180 continue;
11181 f = (tree) n->value;
06ecf488 11182 f = *tcctx.cb.decl_map->get (f);
fd6481cf 11183 gcc_assert (DECL_HAS_VALUE_EXPR_P (decl));
11184 ind = DECL_VALUE_EXPR (decl);
11185 gcc_assert (TREE_CODE (ind) == INDIRECT_REF);
11186 gcc_assert (DECL_P (TREE_OPERAND (ind, 0)));
11187 n = splay_tree_lookup (ctx->sfield_map,
11188 (splay_tree_key) TREE_OPERAND (ind, 0));
11189 sf = (tree) n->value;
06ecf488 11190 sf = *tcctx.cb.decl_map->get (sf);
182cf5a9 11191 src = build_simple_mem_ref_loc (loc, sarg);
445d06b6 11192 src = omp_build_component_ref (src, sf);
182cf5a9 11193 src = build_simple_mem_ref_loc (loc, src);
11194 dst = build_simple_mem_ref_loc (loc, arg);
445d06b6 11195 dst = omp_build_component_ref (dst, f);
fd6481cf 11196 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
11197 append_to_statement_list (t, &list);
11198 n = splay_tree_lookup (ctx->field_map,
11199 (splay_tree_key) TREE_OPERAND (ind, 0));
11200 df = (tree) n->value;
06ecf488 11201 df = *tcctx.cb.decl_map->get (df);
182cf5a9 11202 ptr = build_simple_mem_ref_loc (loc, arg);
445d06b6 11203 ptr = omp_build_component_ref (ptr, df);
75a70cf9 11204 t = build2 (MODIFY_EXPR, TREE_TYPE (ptr), ptr,
389dd41b 11205 build_fold_addr_expr_loc (loc, dst));
fd6481cf 11206 append_to_statement_list (t, &list);
11207 }
11208
11209 t = build1 (RETURN_EXPR, void_type_node, NULL);
11210 append_to_statement_list (t, &list);
11211
11212 if (tcctx.cb.decl_map)
06ecf488 11213 delete tcctx.cb.decl_map;
fd6481cf 11214 pop_gimplify_context (NULL);
11215 BIND_EXPR_BODY (bind) = list;
11216 pop_cfun ();
fd6481cf 11217}
11218
bc7bff74 11219static void
42acab1c 11220lower_depend_clauses (gimple *stmt, gimple_seq *iseq, gimple_seq *oseq)
bc7bff74 11221{
11222 tree c, clauses;
42acab1c 11223 gimple *g;
bc7bff74 11224 size_t n_in = 0, n_out = 0, idx = 2, i;
11225
11226 clauses = find_omp_clause (gimple_omp_task_clauses (stmt),
11227 OMP_CLAUSE_DEPEND);
11228 gcc_assert (clauses);
11229 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
11230 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
11231 switch (OMP_CLAUSE_DEPEND_KIND (c))
11232 {
11233 case OMP_CLAUSE_DEPEND_IN:
11234 n_in++;
11235 break;
11236 case OMP_CLAUSE_DEPEND_OUT:
11237 case OMP_CLAUSE_DEPEND_INOUT:
11238 n_out++;
11239 break;
11240 default:
11241 gcc_unreachable ();
11242 }
11243 tree type = build_array_type_nelts (ptr_type_node, n_in + n_out + 2);
f9e245b2 11244 tree array = create_tmp_var (type);
bc7bff74 11245 tree r = build4 (ARRAY_REF, ptr_type_node, array, size_int (0), NULL_TREE,
11246 NULL_TREE);
11247 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_in + n_out));
11248 gimple_seq_add_stmt (iseq, g);
11249 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (1), NULL_TREE,
11250 NULL_TREE);
11251 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_out));
11252 gimple_seq_add_stmt (iseq, g);
11253 for (i = 0; i < 2; i++)
11254 {
11255 if ((i ? n_in : n_out) == 0)
11256 continue;
11257 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
11258 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
11259 && ((OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_IN) ^ i))
11260 {
11261 tree t = OMP_CLAUSE_DECL (c);
11262 t = fold_convert (ptr_type_node, t);
11263 gimplify_expr (&t, iseq, NULL, is_gimple_val, fb_rvalue);
11264 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (idx++),
11265 NULL_TREE, NULL_TREE);
11266 g = gimple_build_assign (r, t);
11267 gimple_seq_add_stmt (iseq, g);
11268 }
11269 }
11270 tree *p = gimple_omp_task_clauses_ptr (stmt);
11271 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_DEPEND);
11272 OMP_CLAUSE_DECL (c) = build_fold_addr_expr (array);
11273 OMP_CLAUSE_CHAIN (c) = *p;
11274 *p = c;
11275 tree clobber = build_constructor (type, NULL);
11276 TREE_THIS_VOLATILE (clobber) = 1;
11277 g = gimple_build_assign (array, clobber);
11278 gimple_seq_add_stmt (oseq, g);
11279}
11280
75a70cf9 11281/* Lower the OpenMP parallel or task directive in the current statement
11282 in GSI_P. CTX holds context information for the directive. */
773c5ba7 11283
11284static void
75a70cf9 11285lower_omp_taskreg (gimple_stmt_iterator *gsi_p, omp_context *ctx)
773c5ba7 11286{
75a70cf9 11287 tree clauses;
11288 tree child_fn, t;
42acab1c 11289 gimple *stmt = gsi_stmt (*gsi_p);
1a91d914 11290 gbind *par_bind, *bind, *dep_bind = NULL;
bc7bff74 11291 gimple_seq par_body, olist, ilist, par_olist, par_rlist, par_ilist, new_body;
389dd41b 11292 location_t loc = gimple_location (stmt);
773c5ba7 11293
75a70cf9 11294 clauses = gimple_omp_taskreg_clauses (stmt);
1a91d914 11295 par_bind
11296 = as_a <gbind *> (gimple_seq_first_stmt (gimple_omp_body (stmt)));
75a70cf9 11297 par_body = gimple_bind_body (par_bind);
773c5ba7 11298 child_fn = ctx->cb.dst_fn;
75a70cf9 11299 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
11300 && !gimple_omp_parallel_combined_p (stmt))
de7ef844 11301 {
11302 struct walk_stmt_info wi;
11303 int ws_num = 0;
11304
11305 memset (&wi, 0, sizeof (wi));
de7ef844 11306 wi.info = &ws_num;
11307 wi.val_only = true;
75a70cf9 11308 walk_gimple_seq (par_body, check_combined_parallel, NULL, &wi);
de7ef844 11309 if (ws_num == 1)
75a70cf9 11310 gimple_omp_parallel_set_combined_p (stmt, true);
de7ef844 11311 }
bc7bff74 11312 gimple_seq dep_ilist = NULL;
11313 gimple_seq dep_olist = NULL;
11314 if (gimple_code (stmt) == GIMPLE_OMP_TASK
11315 && find_omp_clause (clauses, OMP_CLAUSE_DEPEND))
11316 {
8a4a28a8 11317 push_gimplify_context ();
bc7bff74 11318 dep_bind = gimple_build_bind (NULL, NULL, make_node (BLOCK));
11319 lower_depend_clauses (stmt, &dep_ilist, &dep_olist);
11320 }
11321
fd6481cf 11322 if (ctx->srecord_type)
1a91d914 11323 create_task_copyfn (as_a <gomp_task *> (stmt), ctx);
773c5ba7 11324
8a4a28a8 11325 push_gimplify_context ();
773c5ba7 11326
75a70cf9 11327 par_olist = NULL;
11328 par_ilist = NULL;
bc7bff74 11329 par_rlist = NULL;
11330 lower_rec_input_clauses (clauses, &par_ilist, &par_olist, ctx, NULL);
e3a19533 11331 lower_omp (&par_body, ctx);
75a70cf9 11332 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL)
bc7bff74 11333 lower_reduction_clauses (clauses, &par_rlist, ctx);
773c5ba7 11334
11335 /* Declare all the variables created by mapping and the variables
11336 declared in the scope of the parallel body. */
11337 record_vars_into (ctx->block_vars, child_fn);
75a70cf9 11338 record_vars_into (gimple_bind_vars (par_bind), child_fn);
773c5ba7 11339
11340 if (ctx->record_type)
11341 {
fd6481cf 11342 ctx->sender_decl
11343 = create_tmp_var (ctx->srecord_type ? ctx->srecord_type
11344 : ctx->record_type, ".omp_data_o");
84bfaaeb 11345 DECL_NAMELESS (ctx->sender_decl) = 1;
86f2ad37 11346 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
75a70cf9 11347 gimple_omp_taskreg_set_data_arg (stmt, ctx->sender_decl);
773c5ba7 11348 }
11349
75a70cf9 11350 olist = NULL;
11351 ilist = NULL;
773c5ba7 11352 lower_send_clauses (clauses, &ilist, &olist, ctx);
11353 lower_send_shared_vars (&ilist, &olist, ctx);
11354
bc7bff74 11355 if (ctx->record_type)
11356 {
11357 tree clobber = build_constructor (TREE_TYPE (ctx->sender_decl), NULL);
11358 TREE_THIS_VOLATILE (clobber) = 1;
11359 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
11360 clobber));
11361 }
11362
773c5ba7 11363 /* Once all the expansions are done, sequence all the different
75a70cf9 11364 fragments inside gimple_omp_body. */
773c5ba7 11365
75a70cf9 11366 new_body = NULL;
773c5ba7 11367
11368 if (ctx->record_type)
11369 {
389dd41b 11370 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
cc6b725b 11371 /* fixup_child_record_type might have changed receiver_decl's type. */
389dd41b 11372 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
75a70cf9 11373 gimple_seq_add_stmt (&new_body,
11374 gimple_build_assign (ctx->receiver_decl, t));
773c5ba7 11375 }
11376
75a70cf9 11377 gimple_seq_add_seq (&new_body, par_ilist);
11378 gimple_seq_add_seq (&new_body, par_body);
bc7bff74 11379 gimple_seq_add_seq (&new_body, par_rlist);
11380 if (ctx->cancellable)
11381 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
75a70cf9 11382 gimple_seq_add_seq (&new_body, par_olist);
11383 new_body = maybe_catch_exception (new_body);
b25f70fd 11384 if (gimple_code (stmt) == GIMPLE_OMP_TASK)
11385 gimple_seq_add_stmt (&new_body,
11386 gimple_build_omp_continue (integer_zero_node,
11387 integer_zero_node));
75a70cf9 11388 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
11389 gimple_omp_set_body (stmt, new_body);
773c5ba7 11390
75a70cf9 11391 bind = gimple_build_bind (NULL, NULL, gimple_bind_block (par_bind));
bc7bff74 11392 gsi_replace (gsi_p, dep_bind ? dep_bind : bind, true);
11393 gimple_bind_add_seq (bind, ilist);
11394 gimple_bind_add_stmt (bind, stmt);
11395 gimple_bind_add_seq (bind, olist);
11396
11397 pop_gimplify_context (NULL);
11398
11399 if (dep_bind)
11400 {
11401 gimple_bind_add_seq (dep_bind, dep_ilist);
11402 gimple_bind_add_stmt (dep_bind, bind);
11403 gimple_bind_add_seq (dep_bind, dep_olist);
11404 pop_gimplify_context (dep_bind);
11405 }
11406}
11407
ca4c3545 11408/* Lower the GIMPLE_OMP_TARGET in the current statement
bc7bff74 11409 in GSI_P. CTX holds context information for the directive. */
11410
11411static void
11412lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
11413{
11414 tree clauses;
11415 tree child_fn, t, c;
1a91d914 11416 gomp_target *stmt = as_a <gomp_target *> (gsi_stmt (*gsi_p));
ca4c3545 11417 gbind *tgt_bind, *bind;
11418 gimple_seq tgt_body, olist, ilist, orlist, irlist, new_body;
bc7bff74 11419 location_t loc = gimple_location (stmt);
ca4c3545 11420 bool offloaded, data_region;
bc7bff74 11421 unsigned int map_cnt = 0;
11422
ca4c3545 11423 offloaded = is_gimple_omp_offloaded (stmt);
11424 switch (gimple_omp_target_kind (stmt))
11425 {
11426 case GF_OMP_TARGET_KIND_REGION:
11427 case GF_OMP_TARGET_KIND_UPDATE:
11428 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
11429 case GF_OMP_TARGET_KIND_OACC_KERNELS:
11430 case GF_OMP_TARGET_KIND_OACC_UPDATE:
11431 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
11432 data_region = false;
11433 break;
11434 case GF_OMP_TARGET_KIND_DATA:
11435 case GF_OMP_TARGET_KIND_OACC_DATA:
11436 data_region = true;
11437 break;
11438 default:
11439 gcc_unreachable ();
11440 }
11441
bc7bff74 11442 clauses = gimple_omp_target_clauses (stmt);
ca4c3545 11443
11444 tgt_bind = NULL;
11445 tgt_body = NULL;
11446 if (offloaded)
bc7bff74 11447 {
1a91d914 11448 tgt_bind = gimple_seq_first_stmt_as_a_bind (gimple_omp_body (stmt));
bc7bff74 11449 tgt_body = gimple_bind_body (tgt_bind);
11450 }
ca4c3545 11451 else if (data_region)
bc7bff74 11452 tgt_body = gimple_omp_body (stmt);
11453 child_fn = ctx->cb.dst_fn;
11454
8a4a28a8 11455 push_gimplify_context ();
bc7bff74 11456
ca4c3545 11457 irlist = NULL;
11458 orlist = NULL;
11459 if (offloaded
11460 && is_gimple_omp_oacc (stmt))
11461 oacc_process_reduction_data (&tgt_body, &irlist, &orlist, ctx);
11462
bc7bff74 11463 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
11464 switch (OMP_CLAUSE_CODE (c))
11465 {
11466 tree var, x;
11467
11468 default:
11469 break;
11470 case OMP_CLAUSE_MAP:
ca4c3545 11471#ifdef ENABLE_CHECKING
11472 /* First check what we're prepared to handle in the following. */
11473 switch (OMP_CLAUSE_MAP_KIND (c))
11474 {
11475 case GOMP_MAP_ALLOC:
11476 case GOMP_MAP_TO:
11477 case GOMP_MAP_FROM:
11478 case GOMP_MAP_TOFROM:
11479 case GOMP_MAP_POINTER:
11480 case GOMP_MAP_TO_PSET:
11481 break;
11482 case GOMP_MAP_FORCE_ALLOC:
11483 case GOMP_MAP_FORCE_TO:
11484 case GOMP_MAP_FORCE_FROM:
11485 case GOMP_MAP_FORCE_TOFROM:
11486 case GOMP_MAP_FORCE_PRESENT:
11487 case GOMP_MAP_FORCE_DEALLOC:
11488 case GOMP_MAP_FORCE_DEVICEPTR:
11489 gcc_assert (is_gimple_omp_oacc (stmt));
11490 break;
11491 default:
11492 gcc_unreachable ();
11493 }
11494#endif
11495 /* FALLTHRU */
bc7bff74 11496 case OMP_CLAUSE_TO:
11497 case OMP_CLAUSE_FROM:
11498 var = OMP_CLAUSE_DECL (c);
11499 if (!DECL_P (var))
11500 {
11501 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP
11502 || !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
11503 map_cnt++;
11504 continue;
11505 }
11506
11507 if (DECL_SIZE (var)
11508 && TREE_CODE (DECL_SIZE (var)) != INTEGER_CST)
11509 {
11510 tree var2 = DECL_VALUE_EXPR (var);
11511 gcc_assert (TREE_CODE (var2) == INDIRECT_REF);
11512 var2 = TREE_OPERAND (var2, 0);
11513 gcc_assert (DECL_P (var2));
11514 var = var2;
11515 }
11516
11517 if (!maybe_lookup_field (var, ctx))
11518 continue;
11519
ca4c3545 11520 if (offloaded)
bc7bff74 11521 {
11522 x = build_receiver_ref (var, true, ctx);
11523 tree new_var = lookup_decl (var, ctx);
ca4c3545 11524 if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
bc7bff74 11525 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
11526 && TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
11527 x = build_simple_mem_ref (x);
11528 SET_DECL_VALUE_EXPR (new_var, x);
11529 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
11530 }
11531 map_cnt++;
11532 }
11533
ca4c3545 11534 if (offloaded)
bc7bff74 11535 {
11536 target_nesting_level++;
11537 lower_omp (&tgt_body, ctx);
11538 target_nesting_level--;
11539 }
ca4c3545 11540 else if (data_region)
bc7bff74 11541 lower_omp (&tgt_body, ctx);
11542
ca4c3545 11543 if (offloaded)
bc7bff74 11544 {
11545 /* Declare all the variables created by mapping and the variables
11546 declared in the scope of the target body. */
11547 record_vars_into (ctx->block_vars, child_fn);
11548 record_vars_into (gimple_bind_vars (tgt_bind), child_fn);
11549 }
11550
11551 olist = NULL;
11552 ilist = NULL;
11553 if (ctx->record_type)
11554 {
11555 ctx->sender_decl
11556 = create_tmp_var (ctx->record_type, ".omp_data_arr");
11557 DECL_NAMELESS (ctx->sender_decl) = 1;
11558 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
11559 t = make_tree_vec (3);
11560 TREE_VEC_ELT (t, 0) = ctx->sender_decl;
11561 TREE_VEC_ELT (t, 1)
11562 = create_tmp_var (build_array_type_nelts (size_type_node, map_cnt),
11563 ".omp_data_sizes");
11564 DECL_NAMELESS (TREE_VEC_ELT (t, 1)) = 1;
11565 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 1)) = 1;
11566 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 1;
ca4c3545 11567 tree tkind_type;
11568 int talign_shift;
11569 if (is_gimple_omp_oacc (stmt))
11570 {
11571 tkind_type = short_unsigned_type_node;
11572 talign_shift = 8;
11573 }
11574 else
11575 {
11576 tkind_type = unsigned_char_type_node;
11577 talign_shift = 3;
11578 }
bc7bff74 11579 TREE_VEC_ELT (t, 2)
ca4c3545 11580 = create_tmp_var (build_array_type_nelts (tkind_type, map_cnt),
bc7bff74 11581 ".omp_data_kinds");
11582 DECL_NAMELESS (TREE_VEC_ELT (t, 2)) = 1;
11583 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 2)) = 1;
11584 TREE_STATIC (TREE_VEC_ELT (t, 2)) = 1;
11585 gimple_omp_target_set_data_arg (stmt, t);
11586
11587 vec<constructor_elt, va_gc> *vsize;
11588 vec<constructor_elt, va_gc> *vkind;
11589 vec_alloc (vsize, map_cnt);
11590 vec_alloc (vkind, map_cnt);
11591 unsigned int map_idx = 0;
11592
11593 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
11594 switch (OMP_CLAUSE_CODE (c))
11595 {
11596 tree ovar, nc;
11597
11598 default:
11599 break;
11600 case OMP_CLAUSE_MAP:
11601 case OMP_CLAUSE_TO:
11602 case OMP_CLAUSE_FROM:
11603 nc = c;
11604 ovar = OMP_CLAUSE_DECL (c);
11605 if (!DECL_P (ovar))
11606 {
11607 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
11608 && OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
11609 {
11610 gcc_checking_assert (OMP_CLAUSE_DECL (OMP_CLAUSE_CHAIN (c))
11611 == get_base_address (ovar));
11612 nc = OMP_CLAUSE_CHAIN (c);
11613 ovar = OMP_CLAUSE_DECL (nc);
11614 }
11615 else
11616 {
11617 tree x = build_sender_ref (ovar, ctx);
11618 tree v
11619 = build_fold_addr_expr_with_type (ovar, ptr_type_node);
11620 gimplify_assign (x, v, &ilist);
11621 nc = NULL_TREE;
11622 }
11623 }
11624 else
11625 {
11626 if (DECL_SIZE (ovar)
11627 && TREE_CODE (DECL_SIZE (ovar)) != INTEGER_CST)
11628 {
11629 tree ovar2 = DECL_VALUE_EXPR (ovar);
11630 gcc_assert (TREE_CODE (ovar2) == INDIRECT_REF);
11631 ovar2 = TREE_OPERAND (ovar2, 0);
11632 gcc_assert (DECL_P (ovar2));
11633 ovar = ovar2;
11634 }
11635 if (!maybe_lookup_field (ovar, ctx))
11636 continue;
11637 }
11638
4f3b8d78 11639 unsigned int talign = TYPE_ALIGN_UNIT (TREE_TYPE (ovar));
11640 if (DECL_P (ovar) && DECL_ALIGN_UNIT (ovar) > talign)
11641 talign = DECL_ALIGN_UNIT (ovar);
bc7bff74 11642 if (nc)
11643 {
11644 tree var = lookup_decl_in_outer_ctx (ovar, ctx);
11645 tree x = build_sender_ref (ovar, ctx);
ca4c3545 11646 if (maybe_lookup_oacc_reduction (var, ctx))
11647 {
11648 gcc_checking_assert (offloaded
11649 && is_gimple_omp_oacc (stmt));
11650 gimplify_assign (x, var, &ilist);
11651 }
11652 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
11653 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
11654 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
11655 && TREE_CODE (TREE_TYPE (ovar)) == ARRAY_TYPE)
bc7bff74 11656 {
ca4c3545 11657 gcc_assert (offloaded);
bc7bff74 11658 tree avar
f9e245b2 11659 = create_tmp_var (TREE_TYPE (TREE_TYPE (x)));
bc7bff74 11660 mark_addressable (avar);
11661 gimplify_assign (avar, build_fold_addr_expr (var), &ilist);
4f3b8d78 11662 talign = DECL_ALIGN_UNIT (avar);
bc7bff74 11663 avar = build_fold_addr_expr (avar);
11664 gimplify_assign (x, avar, &ilist);
11665 }
11666 else if (is_gimple_reg (var))
11667 {
ca4c3545 11668 gcc_assert (offloaded);
f9e245b2 11669 tree avar = create_tmp_var (TREE_TYPE (var));
bc7bff74 11670 mark_addressable (avar);
ca4c3545 11671 enum gomp_map_kind map_kind = OMP_CLAUSE_MAP_KIND (c);
11672 if (GOMP_MAP_COPY_TO_P (map_kind)
11673 || map_kind == GOMP_MAP_POINTER
11674 || map_kind == GOMP_MAP_TO_PSET
11675 || map_kind == GOMP_MAP_FORCE_DEVICEPTR)
bc7bff74 11676 gimplify_assign (avar, var, &ilist);
11677 avar = build_fold_addr_expr (avar);
11678 gimplify_assign (x, avar, &ilist);
ca4c3545 11679 if ((GOMP_MAP_COPY_FROM_P (map_kind)
11680 || map_kind == GOMP_MAP_FORCE_DEVICEPTR)
bc7bff74 11681 && !TYPE_READONLY (TREE_TYPE (var)))
11682 {
11683 x = build_sender_ref (ovar, ctx);
11684 x = build_simple_mem_ref (x);
11685 gimplify_assign (var, x, &olist);
11686 }
11687 }
11688 else
11689 {
11690 var = build_fold_addr_expr (var);
11691 gimplify_assign (x, var, &ilist);
11692 }
11693 }
11694 tree s = OMP_CLAUSE_SIZE (c);
11695 if (s == NULL_TREE)
11696 s = TYPE_SIZE_UNIT (TREE_TYPE (ovar));
11697 s = fold_convert (size_type_node, s);
11698 tree purpose = size_int (map_idx++);
11699 CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
11700 if (TREE_CODE (s) != INTEGER_CST)
11701 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 0;
11702
ca4c3545 11703 unsigned HOST_WIDE_INT tkind;
bc7bff74 11704 switch (OMP_CLAUSE_CODE (c))
11705 {
11706 case OMP_CLAUSE_MAP:
11707 tkind = OMP_CLAUSE_MAP_KIND (c);
11708 break;
11709 case OMP_CLAUSE_TO:
ca4c3545 11710 tkind = GOMP_MAP_TO;
bc7bff74 11711 break;
11712 case OMP_CLAUSE_FROM:
ca4c3545 11713 tkind = GOMP_MAP_FROM;
bc7bff74 11714 break;
11715 default:
11716 gcc_unreachable ();
11717 }
ca4c3545 11718 gcc_checking_assert (tkind
11719 < (HOST_WIDE_INT_C (1U) << talign_shift));
bc7bff74 11720 talign = ceil_log2 (talign);
ca4c3545 11721 tkind |= talign << talign_shift;
11722 gcc_checking_assert (tkind
11723 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
bc7bff74 11724 CONSTRUCTOR_APPEND_ELT (vkind, purpose,
ca4c3545 11725 build_int_cstu (tkind_type, tkind));
bc7bff74 11726 if (nc && nc != c)
11727 c = nc;
11728 }
11729
11730 gcc_assert (map_idx == map_cnt);
11731
11732 DECL_INITIAL (TREE_VEC_ELT (t, 1))
11733 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)), vsize);
11734 DECL_INITIAL (TREE_VEC_ELT (t, 2))
11735 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 2)), vkind);
11736 if (!TREE_STATIC (TREE_VEC_ELT (t, 1)))
11737 {
11738 gimple_seq initlist = NULL;
11739 force_gimple_operand (build1 (DECL_EXPR, void_type_node,
11740 TREE_VEC_ELT (t, 1)),
11741 &initlist, true, NULL_TREE);
11742 gimple_seq_add_seq (&ilist, initlist);
d8e1e68d 11743
11744 tree clobber = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)),
11745 NULL);
11746 TREE_THIS_VOLATILE (clobber) = 1;
11747 gimple_seq_add_stmt (&olist,
11748 gimple_build_assign (TREE_VEC_ELT (t, 1),
11749 clobber));
bc7bff74 11750 }
11751
11752 tree clobber = build_constructor (ctx->record_type, NULL);
11753 TREE_THIS_VOLATILE (clobber) = 1;
11754 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
11755 clobber));
11756 }
11757
11758 /* Once all the expansions are done, sequence all the different
11759 fragments inside gimple_omp_body. */
11760
11761 new_body = NULL;
11762
ca4c3545 11763 if (offloaded
11764 && ctx->record_type)
bc7bff74 11765 {
11766 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
11767 /* fixup_child_record_type might have changed receiver_decl's type. */
11768 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
11769 gimple_seq_add_stmt (&new_body,
11770 gimple_build_assign (ctx->receiver_decl, t));
11771 }
11772
ca4c3545 11773 if (offloaded)
bc7bff74 11774 {
11775 gimple_seq_add_seq (&new_body, tgt_body);
11776 new_body = maybe_catch_exception (new_body);
11777 }
ca4c3545 11778 else if (data_region)
bc7bff74 11779 new_body = tgt_body;
ca4c3545 11780 if (offloaded || data_region)
bc7bff74 11781 {
11782 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
11783 gimple_omp_set_body (stmt, new_body);
11784 }
11785
11786 bind = gimple_build_bind (NULL, NULL,
11787 tgt_bind ? gimple_bind_block (tgt_bind)
11788 : NULL_TREE);
75a70cf9 11789 gsi_replace (gsi_p, bind, true);
ca4c3545 11790 gimple_bind_add_seq (bind, irlist);
e3a19533 11791 gimple_bind_add_seq (bind, ilist);
11792 gimple_bind_add_stmt (bind, stmt);
11793 gimple_bind_add_seq (bind, olist);
ca4c3545 11794 gimple_bind_add_seq (bind, orlist);
773c5ba7 11795
75a70cf9 11796 pop_gimplify_context (NULL);
773c5ba7 11797}
11798
bc7bff74 11799/* Expand code for an OpenMP teams directive. */
11800
11801static void
11802lower_omp_teams (gimple_stmt_iterator *gsi_p, omp_context *ctx)
11803{
1a91d914 11804 gomp_teams *teams_stmt = as_a <gomp_teams *> (gsi_stmt (*gsi_p));
8a4a28a8 11805 push_gimplify_context ();
bc7bff74 11806
11807 tree block = make_node (BLOCK);
1a91d914 11808 gbind *bind = gimple_build_bind (NULL, NULL, block);
bc7bff74 11809 gsi_replace (gsi_p, bind, true);
11810 gimple_seq bind_body = NULL;
11811 gimple_seq dlist = NULL;
11812 gimple_seq olist = NULL;
11813
11814 tree num_teams = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
11815 OMP_CLAUSE_NUM_TEAMS);
11816 if (num_teams == NULL_TREE)
11817 num_teams = build_int_cst (unsigned_type_node, 0);
11818 else
11819 {
11820 num_teams = OMP_CLAUSE_NUM_TEAMS_EXPR (num_teams);
11821 num_teams = fold_convert (unsigned_type_node, num_teams);
11822 gimplify_expr (&num_teams, &bind_body, NULL, is_gimple_val, fb_rvalue);
11823 }
11824 tree thread_limit = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
11825 OMP_CLAUSE_THREAD_LIMIT);
11826 if (thread_limit == NULL_TREE)
11827 thread_limit = build_int_cst (unsigned_type_node, 0);
11828 else
11829 {
11830 thread_limit = OMP_CLAUSE_THREAD_LIMIT_EXPR (thread_limit);
11831 thread_limit = fold_convert (unsigned_type_node, thread_limit);
11832 gimplify_expr (&thread_limit, &bind_body, NULL, is_gimple_val,
11833 fb_rvalue);
11834 }
11835
11836 lower_rec_input_clauses (gimple_omp_teams_clauses (teams_stmt),
11837 &bind_body, &dlist, ctx, NULL);
11838 lower_omp (gimple_omp_body_ptr (teams_stmt), ctx);
11839 lower_reduction_clauses (gimple_omp_teams_clauses (teams_stmt), &olist, ctx);
11840 gimple_seq_add_stmt (&bind_body, teams_stmt);
11841
11842 location_t loc = gimple_location (teams_stmt);
11843 tree decl = builtin_decl_explicit (BUILT_IN_GOMP_TEAMS);
42acab1c 11844 gimple *call = gimple_build_call (decl, 2, num_teams, thread_limit);
bc7bff74 11845 gimple_set_location (call, loc);
11846 gimple_seq_add_stmt (&bind_body, call);
11847
11848 gimple_seq_add_seq (&bind_body, gimple_omp_body (teams_stmt));
11849 gimple_omp_set_body (teams_stmt, NULL);
11850 gimple_seq_add_seq (&bind_body, olist);
11851 gimple_seq_add_seq (&bind_body, dlist);
11852 gimple_seq_add_stmt (&bind_body, gimple_build_omp_return (true));
11853 gimple_bind_set_body (bind, bind_body);
11854
11855 pop_gimplify_context (bind);
11856
11857 gimple_bind_append_vars (bind, ctx->block_vars);
11858 BLOCK_VARS (block) = ctx->block_vars;
11859 if (BLOCK_VARS (block))
11860 TREE_USED (block) = 1;
11861}
11862
11863
a4890dc9 11864/* Callback for lower_omp_1. Return non-NULL if *tp needs to be
75a70cf9 11865 regimplified. If DATA is non-NULL, lower_omp_1 is outside
ca4c3545 11866 of OMP context, but with task_shared_vars set. */
46515c92 11867
11868static tree
75a70cf9 11869lower_omp_regimplify_p (tree *tp, int *walk_subtrees,
11870 void *data)
46515c92 11871{
a4890dc9 11872 tree t = *tp;
46515c92 11873
a4890dc9 11874 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
75a70cf9 11875 if (TREE_CODE (t) == VAR_DECL && data == NULL && DECL_HAS_VALUE_EXPR_P (t))
9f49e155 11876 return t;
11877
11878 if (task_shared_vars
11879 && DECL_P (t)
11880 && bitmap_bit_p (task_shared_vars, DECL_UID (t)))
a4890dc9 11881 return t;
46515c92 11882
a4890dc9 11883 /* If a global variable has been privatized, TREE_CONSTANT on
11884 ADDR_EXPR might be wrong. */
75a70cf9 11885 if (data == NULL && TREE_CODE (t) == ADDR_EXPR)
a4890dc9 11886 recompute_tree_invariant_for_addr_expr (t);
46515c92 11887
a4890dc9 11888 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
11889 return NULL_TREE;
46515c92 11890}
773c5ba7 11891
a4890dc9 11892static void
75a70cf9 11893lower_omp_1 (gimple_stmt_iterator *gsi_p, omp_context *ctx)
1e8e9920 11894{
42acab1c 11895 gimple *stmt = gsi_stmt (*gsi_p);
75a70cf9 11896 struct walk_stmt_info wi;
1a91d914 11897 gcall *call_stmt;
1e8e9920 11898
75a70cf9 11899 if (gimple_has_location (stmt))
11900 input_location = gimple_location (stmt);
a4890dc9 11901
75a70cf9 11902 if (task_shared_vars)
11903 memset (&wi, '\0', sizeof (wi));
a4890dc9 11904
773c5ba7 11905 /* If we have issued syntax errors, avoid doing any heavy lifting.
ca4c3545 11906 Just replace the OMP directives with a NOP to avoid
773c5ba7 11907 confusing RTL expansion. */
852f689e 11908 if (seen_error () && is_gimple_omp (stmt))
773c5ba7 11909 {
75a70cf9 11910 gsi_replace (gsi_p, gimple_build_nop (), true);
a4890dc9 11911 return;
773c5ba7 11912 }
11913
75a70cf9 11914 switch (gimple_code (stmt))
1e8e9920 11915 {
75a70cf9 11916 case GIMPLE_COND:
1a91d914 11917 {
11918 gcond *cond_stmt = as_a <gcond *> (stmt);
11919 if ((ctx || task_shared_vars)
11920 && (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
11921 lower_omp_regimplify_p,
11922 ctx ? NULL : &wi, NULL)
11923 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
11924 lower_omp_regimplify_p,
11925 ctx ? NULL : &wi, NULL)))
11926 gimple_regimplify_operands (cond_stmt, gsi_p);
11927 }
a4890dc9 11928 break;
75a70cf9 11929 case GIMPLE_CATCH:
1a91d914 11930 lower_omp (gimple_catch_handler_ptr (as_a <gcatch *> (stmt)), ctx);
a4890dc9 11931 break;
75a70cf9 11932 case GIMPLE_EH_FILTER:
e3a19533 11933 lower_omp (gimple_eh_filter_failure_ptr (stmt), ctx);
a4890dc9 11934 break;
75a70cf9 11935 case GIMPLE_TRY:
e3a19533 11936 lower_omp (gimple_try_eval_ptr (stmt), ctx);
11937 lower_omp (gimple_try_cleanup_ptr (stmt), ctx);
a4890dc9 11938 break;
35215227 11939 case GIMPLE_TRANSACTION:
1a91d914 11940 lower_omp (gimple_transaction_body_ptr (
11941 as_a <gtransaction *> (stmt)),
11942 ctx);
35215227 11943 break;
75a70cf9 11944 case GIMPLE_BIND:
1a91d914 11945 lower_omp (gimple_bind_body_ptr (as_a <gbind *> (stmt)), ctx);
a4890dc9 11946 break;
75a70cf9 11947 case GIMPLE_OMP_PARALLEL:
11948 case GIMPLE_OMP_TASK:
11949 ctx = maybe_lookup_ctx (stmt);
bc7bff74 11950 gcc_assert (ctx);
11951 if (ctx->cancellable)
11952 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
75a70cf9 11953 lower_omp_taskreg (gsi_p, ctx);
a4890dc9 11954 break;
75a70cf9 11955 case GIMPLE_OMP_FOR:
11956 ctx = maybe_lookup_ctx (stmt);
1e8e9920 11957 gcc_assert (ctx);
bc7bff74 11958 if (ctx->cancellable)
11959 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
75a70cf9 11960 lower_omp_for (gsi_p, ctx);
1e8e9920 11961 break;
75a70cf9 11962 case GIMPLE_OMP_SECTIONS:
11963 ctx = maybe_lookup_ctx (stmt);
1e8e9920 11964 gcc_assert (ctx);
bc7bff74 11965 if (ctx->cancellable)
11966 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
75a70cf9 11967 lower_omp_sections (gsi_p, ctx);
1e8e9920 11968 break;
75a70cf9 11969 case GIMPLE_OMP_SINGLE:
11970 ctx = maybe_lookup_ctx (stmt);
1e8e9920 11971 gcc_assert (ctx);
75a70cf9 11972 lower_omp_single (gsi_p, ctx);
1e8e9920 11973 break;
75a70cf9 11974 case GIMPLE_OMP_MASTER:
11975 ctx = maybe_lookup_ctx (stmt);
1e8e9920 11976 gcc_assert (ctx);
75a70cf9 11977 lower_omp_master (gsi_p, ctx);
1e8e9920 11978 break;
bc7bff74 11979 case GIMPLE_OMP_TASKGROUP:
11980 ctx = maybe_lookup_ctx (stmt);
11981 gcc_assert (ctx);
11982 lower_omp_taskgroup (gsi_p, ctx);
11983 break;
75a70cf9 11984 case GIMPLE_OMP_ORDERED:
11985 ctx = maybe_lookup_ctx (stmt);
1e8e9920 11986 gcc_assert (ctx);
75a70cf9 11987 lower_omp_ordered (gsi_p, ctx);
1e8e9920 11988 break;
75a70cf9 11989 case GIMPLE_OMP_CRITICAL:
11990 ctx = maybe_lookup_ctx (stmt);
1e8e9920 11991 gcc_assert (ctx);
75a70cf9 11992 lower_omp_critical (gsi_p, ctx);
11993 break;
11994 case GIMPLE_OMP_ATOMIC_LOAD:
11995 if ((ctx || task_shared_vars)
1a91d914 11996 && walk_tree (gimple_omp_atomic_load_rhs_ptr (
11997 as_a <gomp_atomic_load *> (stmt)),
75a70cf9 11998 lower_omp_regimplify_p, ctx ? NULL : &wi, NULL))
11999 gimple_regimplify_operands (stmt, gsi_p);
1e8e9920 12000 break;
bc7bff74 12001 case GIMPLE_OMP_TARGET:
12002 ctx = maybe_lookup_ctx (stmt);
12003 gcc_assert (ctx);
12004 lower_omp_target (gsi_p, ctx);
12005 break;
12006 case GIMPLE_OMP_TEAMS:
12007 ctx = maybe_lookup_ctx (stmt);
12008 gcc_assert (ctx);
12009 lower_omp_teams (gsi_p, ctx);
12010 break;
12011 case GIMPLE_CALL:
12012 tree fndecl;
1a91d914 12013 call_stmt = as_a <gcall *> (stmt);
12014 fndecl = gimple_call_fndecl (call_stmt);
bc7bff74 12015 if (fndecl
12016 && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
12017 switch (DECL_FUNCTION_CODE (fndecl))
12018 {
12019 case BUILT_IN_GOMP_BARRIER:
12020 if (ctx == NULL)
12021 break;
12022 /* FALLTHRU */
12023 case BUILT_IN_GOMP_CANCEL:
12024 case BUILT_IN_GOMP_CANCELLATION_POINT:
12025 omp_context *cctx;
12026 cctx = ctx;
12027 if (gimple_code (cctx->stmt) == GIMPLE_OMP_SECTION)
12028 cctx = cctx->outer;
1a91d914 12029 gcc_assert (gimple_call_lhs (call_stmt) == NULL_TREE);
bc7bff74 12030 if (!cctx->cancellable)
12031 {
12032 if (DECL_FUNCTION_CODE (fndecl)
12033 == BUILT_IN_GOMP_CANCELLATION_POINT)
12034 {
12035 stmt = gimple_build_nop ();
12036 gsi_replace (gsi_p, stmt, false);
12037 }
12038 break;
12039 }
bc7bff74 12040 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_GOMP_BARRIER)
12041 {
12042 fndecl = builtin_decl_explicit (BUILT_IN_GOMP_BARRIER_CANCEL);
1a91d914 12043 gimple_call_set_fndecl (call_stmt, fndecl);
12044 gimple_call_set_fntype (call_stmt, TREE_TYPE (fndecl));
bc7bff74 12045 }
15b28553 12046 tree lhs;
f9e245b2 12047 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (fndecl)));
1a91d914 12048 gimple_call_set_lhs (call_stmt, lhs);
bc7bff74 12049 tree fallthru_label;
12050 fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
42acab1c 12051 gimple *g;
bc7bff74 12052 g = gimple_build_label (fallthru_label);
12053 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
15b28553 12054 g = gimple_build_cond (NE_EXPR, lhs,
12055 fold_convert (TREE_TYPE (lhs),
12056 boolean_false_node),
bc7bff74 12057 cctx->cancel_label, fallthru_label);
12058 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
12059 break;
12060 default:
12061 break;
12062 }
12063 /* FALLTHRU */
a4890dc9 12064 default:
fd6481cf 12065 if ((ctx || task_shared_vars)
75a70cf9 12066 && walk_gimple_op (stmt, lower_omp_regimplify_p,
12067 ctx ? NULL : &wi))
ef8cfd4d 12068 {
12069 /* Just remove clobbers, this should happen only if we have
12070 "privatized" local addressable variables in SIMD regions,
12071 the clobber isn't needed in that case and gimplifying address
12072 of the ARRAY_REF into a pointer and creating MEM_REF based
12073 clobber would create worse code than we get with the clobber
12074 dropped. */
12075 if (gimple_clobber_p (stmt))
12076 {
12077 gsi_replace (gsi_p, gimple_build_nop (), true);
12078 break;
12079 }
12080 gimple_regimplify_operands (stmt, gsi_p);
12081 }
1e8e9920 12082 break;
1e8e9920 12083 }
1e8e9920 12084}
12085
12086static void
e3a19533 12087lower_omp (gimple_seq *body, omp_context *ctx)
1e8e9920 12088{
1d22f541 12089 location_t saved_location = input_location;
e3a19533 12090 gimple_stmt_iterator gsi;
12091 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
75a70cf9 12092 lower_omp_1 (&gsi, ctx);
ca4c3545 12093 /* During gimplification, we haven't folded statments inside offloading
c3a81971 12094 or taskreg regions (gimplify.c:maybe_fold_stmt); do that now. */
12095 if (target_nesting_level || taskreg_nesting_level)
bc7bff74 12096 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
12097 fold_stmt (&gsi);
1d22f541 12098 input_location = saved_location;
1e8e9920 12099}
12100\f
12101/* Main entry point. */
12102
2a1990e9 12103static unsigned int
1e8e9920 12104execute_lower_omp (void)
12105{
75a70cf9 12106 gimple_seq body;
37eaded9 12107 int i;
12108 omp_context *ctx;
75a70cf9 12109
41709826 12110 /* This pass always runs, to provide PROP_gimple_lomp.
ca4c3545 12111 But often, there is nothing to do. */
12112 if (flag_cilkplus == 0 && flag_openacc == 0 && flag_openmp == 0
12113 && flag_openmp_simd == 0)
41709826 12114 return 0;
12115
1e8e9920 12116 all_contexts = splay_tree_new (splay_tree_compare_pointers, 0,
12117 delete_omp_context);
12118
75a70cf9 12119 body = gimple_body (current_function_decl);
ab129075 12120 scan_omp (&body, NULL);
fd6481cf 12121 gcc_assert (taskreg_nesting_level == 0);
37eaded9 12122 FOR_EACH_VEC_ELT (taskreg_contexts, i, ctx)
12123 finish_taskreg_scan (ctx);
12124 taskreg_contexts.release ();
1e8e9920 12125
12126 if (all_contexts->root)
fd6481cf 12127 {
12128 if (task_shared_vars)
8a4a28a8 12129 push_gimplify_context ();
e3a19533 12130 lower_omp (&body, NULL);
fd6481cf 12131 if (task_shared_vars)
12132 pop_gimplify_context (NULL);
12133 }
1e8e9920 12134
773c5ba7 12135 if (all_contexts)
12136 {
12137 splay_tree_delete (all_contexts);
12138 all_contexts = NULL;
12139 }
fd6481cf 12140 BITMAP_FREE (task_shared_vars);
2a1990e9 12141 return 0;
1e8e9920 12142}
12143
7620bc82 12144namespace {
12145
12146const pass_data pass_data_lower_omp =
cbe8bda8 12147{
12148 GIMPLE_PASS, /* type */
12149 "omplower", /* name */
12150 OPTGROUP_NONE, /* optinfo_flags */
cbe8bda8 12151 TV_NONE, /* tv_id */
12152 PROP_gimple_any, /* properties_required */
12153 PROP_gimple_lomp, /* properties_provided */
12154 0, /* properties_destroyed */
12155 0, /* todo_flags_start */
12156 0, /* todo_flags_finish */
1e8e9920 12157};
cbe8bda8 12158
7620bc82 12159class pass_lower_omp : public gimple_opt_pass
cbe8bda8 12160{
12161public:
9af5ce0c 12162 pass_lower_omp (gcc::context *ctxt)
12163 : gimple_opt_pass (pass_data_lower_omp, ctxt)
cbe8bda8 12164 {}
12165
12166 /* opt_pass methods: */
65b0537f 12167 virtual unsigned int execute (function *) { return execute_lower_omp (); }
cbe8bda8 12168
12169}; // class pass_lower_omp
12170
7620bc82 12171} // anon namespace
12172
cbe8bda8 12173gimple_opt_pass *
12174make_pass_lower_omp (gcc::context *ctxt)
12175{
12176 return new pass_lower_omp (ctxt);
12177}
1e8e9920 12178\f
ca4c3545 12179/* The following is a utility to diagnose structured block violations.
61e47ac8 12180 It is not part of the "omplower" pass, as that's invoked too late. It
12181 should be invoked by the respective front ends after gimplification. */
1e8e9920 12182
12183static splay_tree all_labels;
12184
12185/* Check for mismatched contexts and generate an error if needed. Return
12186 true if an error is detected. */
12187
12188static bool
75a70cf9 12189diagnose_sb_0 (gimple_stmt_iterator *gsi_p,
42acab1c 12190 gimple *branch_ctx, gimple *label_ctx)
1e8e9920 12191{
ca4c3545 12192 gcc_checking_assert (!branch_ctx || is_gimple_omp (branch_ctx));
12193 gcc_checking_assert (!label_ctx || is_gimple_omp (label_ctx));
12194
75a70cf9 12195 if (label_ctx == branch_ctx)
1e8e9920 12196 return false;
12197
ca4c3545 12198 const char* kind = NULL;
12199
12200 if (flag_cilkplus)
12201 {
12202 if ((branch_ctx
12203 && gimple_code (branch_ctx) == GIMPLE_OMP_FOR
12204 && gimple_omp_for_kind (branch_ctx) == GF_OMP_FOR_KIND_CILKSIMD)
12205 || (label_ctx
12206 && gimple_code (label_ctx) == GIMPLE_OMP_FOR
12207 && gimple_omp_for_kind (label_ctx) == GF_OMP_FOR_KIND_CILKSIMD))
12208 kind = "Cilk Plus";
12209 }
12210 if (flag_openacc)
12211 {
12212 if ((branch_ctx && is_gimple_omp_oacc (branch_ctx))
12213 || (label_ctx && is_gimple_omp_oacc (label_ctx)))
12214 {
12215 gcc_checking_assert (kind == NULL);
12216 kind = "OpenACC";
12217 }
12218 }
12219 if (kind == NULL)
12220 {
12221 gcc_checking_assert (flag_openmp);
12222 kind = "OpenMP";
12223 }
48e1416a 12224
75a70cf9 12225 /*
12226 Previously we kept track of the label's entire context in diagnose_sb_[12]
12227 so we could traverse it and issue a correct "exit" or "enter" error
12228 message upon a structured block violation.
12229
12230 We built the context by building a list with tree_cons'ing, but there is
12231 no easy counterpart in gimple tuples. It seems like far too much work
12232 for issuing exit/enter error messages. If someone really misses the
12233 distinct error message... patches welcome.
12234 */
48e1416a 12235
75a70cf9 12236#if 0
1e8e9920 12237 /* Try to avoid confusing the user by producing and error message
f0b5f617 12238 with correct "exit" or "enter" verbiage. We prefer "exit"
1e8e9920 12239 unless we can show that LABEL_CTX is nested within BRANCH_CTX. */
12240 if (branch_ctx == NULL)
12241 exit_p = false;
12242 else
12243 {
12244 while (label_ctx)
12245 {
12246 if (TREE_VALUE (label_ctx) == branch_ctx)
12247 {
12248 exit_p = false;
12249 break;
12250 }
12251 label_ctx = TREE_CHAIN (label_ctx);
12252 }
12253 }
12254
12255 if (exit_p)
ca4c3545 12256 error ("invalid exit from %s structured block", kind);
1e8e9920 12257 else
ca4c3545 12258 error ("invalid entry to %s structured block", kind);
75a70cf9 12259#endif
1e8e9920 12260
75a70cf9 12261 /* If it's obvious we have an invalid entry, be specific about the error. */
12262 if (branch_ctx == NULL)
ca4c3545 12263 error ("invalid entry to %s structured block", kind);
75a70cf9 12264 else
f2697631 12265 {
12266 /* Otherwise, be vague and lazy, but efficient. */
ca4c3545 12267 error ("invalid branch to/from %s structured block", kind);
f2697631 12268 }
75a70cf9 12269
12270 gsi_replace (gsi_p, gimple_build_nop (), false);
1e8e9920 12271 return true;
12272}
12273
ca4c3545 12274/* Pass 1: Create a minimal tree of structured blocks, and record
75a70cf9 12275 where each label is found. */
1e8e9920 12276
12277static tree
75a70cf9 12278diagnose_sb_1 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
12279 struct walk_stmt_info *wi)
1e8e9920 12280{
42acab1c 12281 gimple *context = (gimple *) wi->info;
12282 gimple *inner_context;
12283 gimple *stmt = gsi_stmt (*gsi_p);
1e8e9920 12284
75a70cf9 12285 *handled_ops_p = true;
12286
ca4c3545 12287 switch (gimple_code (stmt))
1e8e9920 12288 {
75a70cf9 12289 WALK_SUBSTMTS;
48e1416a 12290
75a70cf9 12291 case GIMPLE_OMP_PARALLEL:
12292 case GIMPLE_OMP_TASK:
12293 case GIMPLE_OMP_SECTIONS:
12294 case GIMPLE_OMP_SINGLE:
12295 case GIMPLE_OMP_SECTION:
12296 case GIMPLE_OMP_MASTER:
12297 case GIMPLE_OMP_ORDERED:
12298 case GIMPLE_OMP_CRITICAL:
bc7bff74 12299 case GIMPLE_OMP_TARGET:
12300 case GIMPLE_OMP_TEAMS:
12301 case GIMPLE_OMP_TASKGROUP:
75a70cf9 12302 /* The minimal context here is just the current OMP construct. */
12303 inner_context = stmt;
1e8e9920 12304 wi->info = inner_context;
75a70cf9 12305 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
1e8e9920 12306 wi->info = context;
12307 break;
12308
75a70cf9 12309 case GIMPLE_OMP_FOR:
12310 inner_context = stmt;
1e8e9920 12311 wi->info = inner_context;
75a70cf9 12312 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
12313 walk them. */
12314 walk_gimple_seq (gimple_omp_for_pre_body (stmt),
12315 diagnose_sb_1, NULL, wi);
12316 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
1e8e9920 12317 wi->info = context;
12318 break;
12319
75a70cf9 12320 case GIMPLE_LABEL:
1a91d914 12321 splay_tree_insert (all_labels,
12322 (splay_tree_key) gimple_label_label (
12323 as_a <glabel *> (stmt)),
1e8e9920 12324 (splay_tree_value) context);
12325 break;
12326
12327 default:
12328 break;
12329 }
12330
12331 return NULL_TREE;
12332}
12333
12334/* Pass 2: Check each branch and see if its context differs from that of
12335 the destination label's context. */
12336
12337static tree
75a70cf9 12338diagnose_sb_2 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
12339 struct walk_stmt_info *wi)
1e8e9920 12340{
42acab1c 12341 gimple *context = (gimple *) wi->info;
1e8e9920 12342 splay_tree_node n;
42acab1c 12343 gimple *stmt = gsi_stmt (*gsi_p);
1e8e9920 12344
75a70cf9 12345 *handled_ops_p = true;
12346
12347 switch (gimple_code (stmt))
1e8e9920 12348 {
75a70cf9 12349 WALK_SUBSTMTS;
12350
12351 case GIMPLE_OMP_PARALLEL:
12352 case GIMPLE_OMP_TASK:
12353 case GIMPLE_OMP_SECTIONS:
12354 case GIMPLE_OMP_SINGLE:
12355 case GIMPLE_OMP_SECTION:
12356 case GIMPLE_OMP_MASTER:
12357 case GIMPLE_OMP_ORDERED:
12358 case GIMPLE_OMP_CRITICAL:
bc7bff74 12359 case GIMPLE_OMP_TARGET:
12360 case GIMPLE_OMP_TEAMS:
12361 case GIMPLE_OMP_TASKGROUP:
75a70cf9 12362 wi->info = stmt;
e3a19533 12363 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
1e8e9920 12364 wi->info = context;
12365 break;
12366
75a70cf9 12367 case GIMPLE_OMP_FOR:
12368 wi->info = stmt;
12369 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
12370 walk them. */
e3a19533 12371 walk_gimple_seq_mod (gimple_omp_for_pre_body_ptr (stmt),
12372 diagnose_sb_2, NULL, wi);
12373 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
1e8e9920 12374 wi->info = context;
12375 break;
12376
0e1818e7 12377 case GIMPLE_COND:
12378 {
1a91d914 12379 gcond *cond_stmt = as_a <gcond *> (stmt);
12380 tree lab = gimple_cond_true_label (cond_stmt);
0e1818e7 12381 if (lab)
12382 {
12383 n = splay_tree_lookup (all_labels,
12384 (splay_tree_key) lab);
12385 diagnose_sb_0 (gsi_p, context,
42acab1c 12386 n ? (gimple *) n->value : NULL);
0e1818e7 12387 }
1a91d914 12388 lab = gimple_cond_false_label (cond_stmt);
0e1818e7 12389 if (lab)
12390 {
12391 n = splay_tree_lookup (all_labels,
12392 (splay_tree_key) lab);
12393 diagnose_sb_0 (gsi_p, context,
42acab1c 12394 n ? (gimple *) n->value : NULL);
0e1818e7 12395 }
12396 }
12397 break;
12398
75a70cf9 12399 case GIMPLE_GOTO:
1e8e9920 12400 {
75a70cf9 12401 tree lab = gimple_goto_dest (stmt);
1e8e9920 12402 if (TREE_CODE (lab) != LABEL_DECL)
12403 break;
12404
12405 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
42acab1c 12406 diagnose_sb_0 (gsi_p, context, n ? (gimple *) n->value : NULL);
1e8e9920 12407 }
12408 break;
12409
75a70cf9 12410 case GIMPLE_SWITCH:
1e8e9920 12411 {
1a91d914 12412 gswitch *switch_stmt = as_a <gswitch *> (stmt);
75a70cf9 12413 unsigned int i;
1a91d914 12414 for (i = 0; i < gimple_switch_num_labels (switch_stmt); ++i)
1e8e9920 12415 {
1a91d914 12416 tree lab = CASE_LABEL (gimple_switch_label (switch_stmt, i));
1e8e9920 12417 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
42acab1c 12418 if (n && diagnose_sb_0 (gsi_p, context, (gimple *) n->value))
1e8e9920 12419 break;
12420 }
12421 }
12422 break;
12423
75a70cf9 12424 case GIMPLE_RETURN:
12425 diagnose_sb_0 (gsi_p, context, NULL);
1e8e9920 12426 break;
12427
12428 default:
12429 break;
12430 }
12431
12432 return NULL_TREE;
12433}
12434
ca4c3545 12435/* Called from tree-cfg.c::make_edges to create cfg edges for all relevant
12436 GIMPLE_* codes. */
7740abd8 12437bool
b2c0e0b7 12438make_gimple_omp_edges (basic_block bb, struct omp_region **region,
12439 int *region_idx)
7740abd8 12440{
42acab1c 12441 gimple *last = last_stmt (bb);
7740abd8 12442 enum gimple_code code = gimple_code (last);
12443 struct omp_region *cur_region = *region;
12444 bool fallthru = false;
12445
12446 switch (code)
12447 {
12448 case GIMPLE_OMP_PARALLEL:
12449 case GIMPLE_OMP_TASK:
12450 case GIMPLE_OMP_FOR:
12451 case GIMPLE_OMP_SINGLE:
12452 case GIMPLE_OMP_TEAMS:
12453 case GIMPLE_OMP_MASTER:
12454 case GIMPLE_OMP_TASKGROUP:
12455 case GIMPLE_OMP_ORDERED:
12456 case GIMPLE_OMP_CRITICAL:
12457 case GIMPLE_OMP_SECTION:
12458 cur_region = new_omp_region (bb, code, cur_region);
12459 fallthru = true;
12460 break;
12461
12462 case GIMPLE_OMP_TARGET:
12463 cur_region = new_omp_region (bb, code, cur_region);
12464 fallthru = true;
ca4c3545 12465 switch (gimple_omp_target_kind (last))
12466 {
12467 case GF_OMP_TARGET_KIND_REGION:
12468 case GF_OMP_TARGET_KIND_DATA:
12469 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
12470 case GF_OMP_TARGET_KIND_OACC_KERNELS:
12471 case GF_OMP_TARGET_KIND_OACC_DATA:
12472 break;
12473 case GF_OMP_TARGET_KIND_UPDATE:
12474 case GF_OMP_TARGET_KIND_OACC_UPDATE:
12475 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
12476 cur_region = cur_region->outer;
12477 break;
12478 default:
12479 gcc_unreachable ();
12480 }
7740abd8 12481 break;
12482
12483 case GIMPLE_OMP_SECTIONS:
12484 cur_region = new_omp_region (bb, code, cur_region);
12485 fallthru = true;
12486 break;
12487
12488 case GIMPLE_OMP_SECTIONS_SWITCH:
12489 fallthru = false;
12490 break;
12491
12492 case GIMPLE_OMP_ATOMIC_LOAD:
12493 case GIMPLE_OMP_ATOMIC_STORE:
12494 fallthru = true;
12495 break;
12496
12497 case GIMPLE_OMP_RETURN:
12498 /* In the case of a GIMPLE_OMP_SECTION, the edge will go
12499 somewhere other than the next block. This will be
12500 created later. */
12501 cur_region->exit = bb;
b25f70fd 12502 if (cur_region->type == GIMPLE_OMP_TASK)
12503 /* Add an edge corresponding to not scheduling the task
12504 immediately. */
12505 make_edge (cur_region->entry, bb, EDGE_ABNORMAL);
7740abd8 12506 fallthru = cur_region->type != GIMPLE_OMP_SECTION;
12507 cur_region = cur_region->outer;
12508 break;
12509
12510 case GIMPLE_OMP_CONTINUE:
12511 cur_region->cont = bb;
12512 switch (cur_region->type)
12513 {
12514 case GIMPLE_OMP_FOR:
12515 /* Mark all GIMPLE_OMP_FOR and GIMPLE_OMP_CONTINUE
12516 succs edges as abnormal to prevent splitting
12517 them. */
12518 single_succ_edge (cur_region->entry)->flags |= EDGE_ABNORMAL;
12519 /* Make the loopback edge. */
12520 make_edge (bb, single_succ (cur_region->entry),
12521 EDGE_ABNORMAL);
12522
12523 /* Create an edge from GIMPLE_OMP_FOR to exit, which
12524 corresponds to the case that the body of the loop
12525 is not executed at all. */
12526 make_edge (cur_region->entry, bb->next_bb, EDGE_ABNORMAL);
12527 make_edge (bb, bb->next_bb, EDGE_FALLTHRU | EDGE_ABNORMAL);
12528 fallthru = false;
12529 break;
12530
12531 case GIMPLE_OMP_SECTIONS:
12532 /* Wire up the edges into and out of the nested sections. */
12533 {
12534 basic_block switch_bb = single_succ (cur_region->entry);
12535
12536 struct omp_region *i;
12537 for (i = cur_region->inner; i ; i = i->next)
12538 {
12539 gcc_assert (i->type == GIMPLE_OMP_SECTION);
12540 make_edge (switch_bb, i->entry, 0);
12541 make_edge (i->exit, bb, EDGE_FALLTHRU);
12542 }
12543
12544 /* Make the loopback edge to the block with
12545 GIMPLE_OMP_SECTIONS_SWITCH. */
12546 make_edge (bb, switch_bb, 0);
12547
12548 /* Make the edge from the switch to exit. */
12549 make_edge (switch_bb, bb->next_bb, 0);
12550 fallthru = false;
12551 }
12552 break;
12553
b25f70fd 12554 case GIMPLE_OMP_TASK:
12555 fallthru = true;
12556 break;
12557
7740abd8 12558 default:
12559 gcc_unreachable ();
12560 }
12561 break;
12562
12563 default:
12564 gcc_unreachable ();
12565 }
12566
12567 if (*region != cur_region)
b2c0e0b7 12568 {
12569 *region = cur_region;
12570 if (cur_region)
12571 *region_idx = cur_region->entry->index;
12572 else
12573 *region_idx = 0;
12574 }
7740abd8 12575
12576 return fallthru;
12577}
12578
bfec3452 12579static unsigned int
12580diagnose_omp_structured_block_errors (void)
1e8e9920 12581{
1e8e9920 12582 struct walk_stmt_info wi;
bfec3452 12583 gimple_seq body = gimple_body (current_function_decl);
1e8e9920 12584
12585 all_labels = splay_tree_new (splay_tree_compare_pointers, 0, 0);
12586
12587 memset (&wi, 0, sizeof (wi));
75a70cf9 12588 walk_gimple_seq (body, diagnose_sb_1, NULL, &wi);
1e8e9920 12589
12590 memset (&wi, 0, sizeof (wi));
1e8e9920 12591 wi.want_locations = true;
e3a19533 12592 walk_gimple_seq_mod (&body, diagnose_sb_2, NULL, &wi);
12593
12594 gimple_set_body (current_function_decl, body);
1e8e9920 12595
12596 splay_tree_delete (all_labels);
12597 all_labels = NULL;
12598
bfec3452 12599 return 0;
1e8e9920 12600}
12601
7620bc82 12602namespace {
12603
12604const pass_data pass_data_diagnose_omp_blocks =
cbe8bda8 12605{
12606 GIMPLE_PASS, /* type */
12607 "*diagnose_omp_blocks", /* name */
12608 OPTGROUP_NONE, /* optinfo_flags */
cbe8bda8 12609 TV_NONE, /* tv_id */
12610 PROP_gimple_any, /* properties_required */
12611 0, /* properties_provided */
12612 0, /* properties_destroyed */
12613 0, /* todo_flags_start */
12614 0, /* todo_flags_finish */
bfec3452 12615};
12616
7620bc82 12617class pass_diagnose_omp_blocks : public gimple_opt_pass
cbe8bda8 12618{
12619public:
9af5ce0c 12620 pass_diagnose_omp_blocks (gcc::context *ctxt)
12621 : gimple_opt_pass (pass_data_diagnose_omp_blocks, ctxt)
cbe8bda8 12622 {}
12623
12624 /* opt_pass methods: */
ca4c3545 12625 virtual bool gate (function *)
12626 {
12627 return flag_cilkplus || flag_openacc || flag_openmp;
12628 }
65b0537f 12629 virtual unsigned int execute (function *)
12630 {
12631 return diagnose_omp_structured_block_errors ();
12632 }
cbe8bda8 12633
12634}; // class pass_diagnose_omp_blocks
12635
7620bc82 12636} // anon namespace
12637
cbe8bda8 12638gimple_opt_pass *
12639make_pass_diagnose_omp_blocks (gcc::context *ctxt)
12640{
12641 return new pass_diagnose_omp_blocks (ctxt);
12642}
d09768a4 12643\f
12644/* SIMD clone supporting code. */
12645
12646/* Allocate a fresh `simd_clone' and return it. NARGS is the number
12647 of arguments to reserve space for. */
12648
12649static struct cgraph_simd_clone *
12650simd_clone_struct_alloc (int nargs)
12651{
12652 struct cgraph_simd_clone *clone_info;
12653 size_t len = (sizeof (struct cgraph_simd_clone)
12654 + nargs * sizeof (struct cgraph_simd_clone_arg));
12655 clone_info = (struct cgraph_simd_clone *)
ea7d8c7a 12656 ggc_internal_cleared_alloc (len);
d09768a4 12657 return clone_info;
12658}
12659
12660/* Make a copy of the `struct cgraph_simd_clone' in FROM to TO. */
12661
12662static inline void
12663simd_clone_struct_copy (struct cgraph_simd_clone *to,
12664 struct cgraph_simd_clone *from)
12665{
12666 memcpy (to, from, (sizeof (struct cgraph_simd_clone)
46c0fd4b 12667 + ((from->nargs - from->inbranch)
12668 * sizeof (struct cgraph_simd_clone_arg))));
d09768a4 12669}
12670
12671/* Return vector of parameter types of function FNDECL. This uses
12672 TYPE_ARG_TYPES if available, otherwise falls back to types of
12673 DECL_ARGUMENTS types. */
12674
12675vec<tree>
12676simd_clone_vector_of_formal_parm_types (tree fndecl)
12677{
12678 if (TYPE_ARG_TYPES (TREE_TYPE (fndecl)))
12679 return ipa_get_vector_of_formal_parm_types (TREE_TYPE (fndecl));
12680 vec<tree> args = ipa_get_vector_of_formal_parms (fndecl);
12681 unsigned int i;
12682 tree arg;
12683 FOR_EACH_VEC_ELT (args, i, arg)
12684 args[i] = TREE_TYPE (args[i]);
12685 return args;
12686}
12687
12688/* Given a simd function in NODE, extract the simd specific
12689 information from the OMP clauses passed in CLAUSES, and return
12690 the struct cgraph_simd_clone * if it should be cloned. *INBRANCH_SPECIFIED
12691 is set to TRUE if the `inbranch' or `notinbranch' clause specified,
12692 otherwise set to FALSE. */
12693
12694static struct cgraph_simd_clone *
12695simd_clone_clauses_extract (struct cgraph_node *node, tree clauses,
12696 bool *inbranch_specified)
12697{
12698 vec<tree> args = simd_clone_vector_of_formal_parm_types (node->decl);
12699 tree t;
12700 int n;
12701 *inbranch_specified = false;
12702
12703 n = args.length ();
12704 if (n > 0 && args.last () == void_type_node)
12705 n--;
12706
12707 /* To distinguish from an OpenMP simd clone, Cilk Plus functions to
12708 be cloned have a distinctive artificial label in addition to "omp
12709 declare simd". */
12710 bool cilk_clone
a89e6c15 12711 = (flag_cilkplus
74acc703 12712 && lookup_attribute ("cilk simd function",
d09768a4 12713 DECL_ATTRIBUTES (node->decl)));
12714
12715 /* Allocate one more than needed just in case this is an in-branch
12716 clone which will require a mask argument. */
12717 struct cgraph_simd_clone *clone_info = simd_clone_struct_alloc (n + 1);
12718 clone_info->nargs = n;
12719 clone_info->cilk_elemental = cilk_clone;
12720
12721 if (!clauses)
12722 {
12723 args.release ();
12724 return clone_info;
12725 }
12726 clauses = TREE_VALUE (clauses);
12727 if (!clauses || TREE_CODE (clauses) != OMP_CLAUSE)
12728 return clone_info;
12729
12730 for (t = clauses; t; t = OMP_CLAUSE_CHAIN (t))
12731 {
12732 switch (OMP_CLAUSE_CODE (t))
12733 {
12734 case OMP_CLAUSE_INBRANCH:
12735 clone_info->inbranch = 1;
12736 *inbranch_specified = true;
12737 break;
12738 case OMP_CLAUSE_NOTINBRANCH:
12739 clone_info->inbranch = 0;
12740 *inbranch_specified = true;
12741 break;
12742 case OMP_CLAUSE_SIMDLEN:
12743 clone_info->simdlen
12744 = TREE_INT_CST_LOW (OMP_CLAUSE_SIMDLEN_EXPR (t));
12745 break;
12746 case OMP_CLAUSE_LINEAR:
12747 {
12748 tree decl = OMP_CLAUSE_DECL (t);
12749 tree step = OMP_CLAUSE_LINEAR_STEP (t);
12750 int argno = TREE_INT_CST_LOW (decl);
12751 if (OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (t))
12752 {
12753 clone_info->args[argno].arg_type
12754 = SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP;
12755 clone_info->args[argno].linear_step = tree_to_shwi (step);
12756 gcc_assert (clone_info->args[argno].linear_step >= 0
12757 && clone_info->args[argno].linear_step < n);
12758 }
12759 else
12760 {
12761 if (POINTER_TYPE_P (args[argno]))
12762 step = fold_convert (ssizetype, step);
12763 if (!tree_fits_shwi_p (step))
12764 {
12765 warning_at (OMP_CLAUSE_LOCATION (t), 0,
12766 "ignoring large linear step");
12767 args.release ();
12768 return NULL;
12769 }
12770 else if (integer_zerop (step))
12771 {
12772 warning_at (OMP_CLAUSE_LOCATION (t), 0,
12773 "ignoring zero linear step");
12774 args.release ();
12775 return NULL;
12776 }
12777 else
12778 {
12779 clone_info->args[argno].arg_type
12780 = SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP;
12781 clone_info->args[argno].linear_step = tree_to_shwi (step);
12782 }
12783 }
12784 break;
12785 }
12786 case OMP_CLAUSE_UNIFORM:
12787 {
12788 tree decl = OMP_CLAUSE_DECL (t);
12789 int argno = tree_to_uhwi (decl);
12790 clone_info->args[argno].arg_type
12791 = SIMD_CLONE_ARG_TYPE_UNIFORM;
12792 break;
12793 }
12794 case OMP_CLAUSE_ALIGNED:
12795 {
12796 tree decl = OMP_CLAUSE_DECL (t);
12797 int argno = tree_to_uhwi (decl);
12798 clone_info->args[argno].alignment
12799 = TREE_INT_CST_LOW (OMP_CLAUSE_ALIGNED_ALIGNMENT (t));
12800 break;
12801 }
12802 default:
12803 break;
12804 }
12805 }
12806 args.release ();
12807 return clone_info;
12808}
12809
12810/* Given a SIMD clone in NODE, calculate the characteristic data
12811 type and return the coresponding type. The characteristic data
12812 type is computed as described in the Intel Vector ABI. */
12813
12814static tree
12815simd_clone_compute_base_data_type (struct cgraph_node *node,
12816 struct cgraph_simd_clone *clone_info)
12817{
12818 tree type = integer_type_node;
12819 tree fndecl = node->decl;
12820
12821 /* a) For non-void function, the characteristic data type is the
12822 return type. */
12823 if (TREE_CODE (TREE_TYPE (TREE_TYPE (fndecl))) != VOID_TYPE)
12824 type = TREE_TYPE (TREE_TYPE (fndecl));
12825
12826 /* b) If the function has any non-uniform, non-linear parameters,
12827 then the characteristic data type is the type of the first
12828 such parameter. */
12829 else
12830 {
12831 vec<tree> map = simd_clone_vector_of_formal_parm_types (fndecl);
12832 for (unsigned int i = 0; i < clone_info->nargs; ++i)
12833 if (clone_info->args[i].arg_type == SIMD_CLONE_ARG_TYPE_VECTOR)
12834 {
12835 type = map[i];
12836 break;
12837 }
12838 map.release ();
12839 }
12840
12841 /* c) If the characteristic data type determined by a) or b) above
12842 is struct, union, or class type which is pass-by-value (except
12843 for the type that maps to the built-in complex data type), the
12844 characteristic data type is int. */
12845 if (RECORD_OR_UNION_TYPE_P (type)
12846 && !aggregate_value_p (type, NULL)
12847 && TREE_CODE (type) != COMPLEX_TYPE)
12848 return integer_type_node;
12849
12850 /* d) If none of the above three classes is applicable, the
12851 characteristic data type is int. */
12852
12853 return type;
12854
12855 /* e) For Intel Xeon Phi native and offload compilation, if the
12856 resulting characteristic data type is 8-bit or 16-bit integer
12857 data type, the characteristic data type is int. */
12858 /* Well, we don't handle Xeon Phi yet. */
12859}
12860
12861static tree
12862simd_clone_mangle (struct cgraph_node *node,
12863 struct cgraph_simd_clone *clone_info)
12864{
12865 char vecsize_mangle = clone_info->vecsize_mangle;
12866 char mask = clone_info->inbranch ? 'M' : 'N';
12867 unsigned int simdlen = clone_info->simdlen;
12868 unsigned int n;
12869 pretty_printer pp;
12870
12871 gcc_assert (vecsize_mangle && simdlen);
12872
12873 pp_string (&pp, "_ZGV");
12874 pp_character (&pp, vecsize_mangle);
12875 pp_character (&pp, mask);
12876 pp_decimal_int (&pp, simdlen);
12877
12878 for (n = 0; n < clone_info->nargs; ++n)
12879 {
12880 struct cgraph_simd_clone_arg arg = clone_info->args[n];
12881
12882 if (arg.arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM)
12883 pp_character (&pp, 'u');
12884 else if (arg.arg_type == SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP)
12885 {
12886 gcc_assert (arg.linear_step != 0);
12887 pp_character (&pp, 'l');
12888 if (arg.linear_step > 1)
12889 pp_unsigned_wide_integer (&pp, arg.linear_step);
12890 else if (arg.linear_step < 0)
12891 {
12892 pp_character (&pp, 'n');
12893 pp_unsigned_wide_integer (&pp, (-(unsigned HOST_WIDE_INT)
12894 arg.linear_step));
12895 }
12896 }
12897 else if (arg.arg_type == SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP)
12898 {
12899 pp_character (&pp, 's');
12900 pp_unsigned_wide_integer (&pp, arg.linear_step);
12901 }
12902 else
12903 pp_character (&pp, 'v');
12904 if (arg.alignment)
12905 {
12906 pp_character (&pp, 'a');
12907 pp_decimal_int (&pp, arg.alignment);
12908 }
12909 }
12910
12911 pp_underscore (&pp);
4e4baaad 12912 const char *str = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (node->decl));
12913 if (*str == '*')
12914 ++str;
12915 pp_string (&pp, str);
12916 str = pp_formatted_text (&pp);
d09768a4 12917
12918 /* If there already is a SIMD clone with the same mangled name, don't
12919 add another one. This can happen e.g. for
12920 #pragma omp declare simd
12921 #pragma omp declare simd simdlen(8)
12922 int foo (int, int);
12923 if the simdlen is assumed to be 8 for the first one, etc. */
12924 for (struct cgraph_node *clone = node->simd_clones; clone;
12925 clone = clone->simdclone->next_clone)
12926 if (strcmp (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (clone->decl)),
12927 str) == 0)
12928 return NULL_TREE;
12929
12930 return get_identifier (str);
12931}
12932
12933/* Create a simd clone of OLD_NODE and return it. */
12934
12935static struct cgraph_node *
12936simd_clone_create (struct cgraph_node *old_node)
12937{
12938 struct cgraph_node *new_node;
12939 if (old_node->definition)
ea0695f9 12940 {
415d1b9a 12941 if (!old_node->has_gimple_body_p ())
ea0695f9 12942 return NULL;
415d1b9a 12943 old_node->get_body ();
12944 new_node = old_node->create_version_clone_with_body (vNULL, NULL, NULL,
12945 false, NULL, NULL,
12946 "simdclone");
ea0695f9 12947 }
d09768a4 12948 else
12949 {
12950 tree old_decl = old_node->decl;
12951 tree new_decl = copy_node (old_node->decl);
12952 DECL_NAME (new_decl) = clone_function_name (old_decl, "simdclone");
12953 SET_DECL_ASSEMBLER_NAME (new_decl, DECL_NAME (new_decl));
12954 SET_DECL_RTL (new_decl, NULL);
12955 DECL_STATIC_CONSTRUCTOR (new_decl) = 0;
12956 DECL_STATIC_DESTRUCTOR (new_decl) = 0;
415d1b9a 12957 new_node = old_node->create_version_clone (new_decl, vNULL, NULL);
35ee1c66 12958 symtab->call_cgraph_insertion_hooks (new_node);
d09768a4 12959 }
12960 if (new_node == NULL)
12961 return new_node;
12962
12963 TREE_PUBLIC (new_node->decl) = TREE_PUBLIC (old_node->decl);
12964
12965 /* The function cgraph_function_versioning () will force the new
12966 symbol local. Undo this, and inherit external visability from
12967 the old node. */
12968 new_node->local.local = old_node->local.local;
12969 new_node->externally_visible = old_node->externally_visible;
12970
12971 return new_node;
12972}
12973
12974/* Adjust the return type of the given function to its appropriate
12975 vector counterpart. Returns a simd array to be used throughout the
12976 function as a return value. */
12977
12978static tree
12979simd_clone_adjust_return_type (struct cgraph_node *node)
12980{
12981 tree fndecl = node->decl;
12982 tree orig_rettype = TREE_TYPE (TREE_TYPE (fndecl));
12983 unsigned int veclen;
12984 tree t;
12985
12986 /* Adjust the function return type. */
12987 if (orig_rettype == void_type_node)
12988 return NULL_TREE;
12989 TREE_TYPE (fndecl) = build_distinct_type_copy (TREE_TYPE (fndecl));
fdf7662c 12990 t = TREE_TYPE (TREE_TYPE (fndecl));
12991 if (INTEGRAL_TYPE_P (t) || POINTER_TYPE_P (t))
d09768a4 12992 veclen = node->simdclone->vecsize_int;
12993 else
12994 veclen = node->simdclone->vecsize_float;
fdf7662c 12995 veclen /= GET_MODE_BITSIZE (TYPE_MODE (t));
d09768a4 12996 if (veclen > node->simdclone->simdlen)
12997 veclen = node->simdclone->simdlen;
fdf7662c 12998 if (POINTER_TYPE_P (t))
12999 t = pointer_sized_int_node;
d09768a4 13000 if (veclen == node->simdclone->simdlen)
fdf7662c 13001 t = build_vector_type (t, node->simdclone->simdlen);
d09768a4 13002 else
13003 {
fdf7662c 13004 t = build_vector_type (t, veclen);
d09768a4 13005 t = build_array_type_nelts (t, node->simdclone->simdlen / veclen);
d09768a4 13006 }
fdf7662c 13007 TREE_TYPE (TREE_TYPE (fndecl)) = t;
d09768a4 13008 if (!node->definition)
13009 return NULL_TREE;
13010
13011 t = DECL_RESULT (fndecl);
13012 /* Adjust the DECL_RESULT. */
13013 gcc_assert (TREE_TYPE (t) != void_type_node);
13014 TREE_TYPE (t) = TREE_TYPE (TREE_TYPE (fndecl));
13015 relayout_decl (t);
13016
13017 tree atype = build_array_type_nelts (orig_rettype,
13018 node->simdclone->simdlen);
13019 if (veclen != node->simdclone->simdlen)
13020 return build1 (VIEW_CONVERT_EXPR, atype, t);
13021
13022 /* Set up a SIMD array to use as the return value. */
13023 tree retval = create_tmp_var_raw (atype, "retval");
13024 gimple_add_tmp_var (retval);
13025 return retval;
13026}
13027
13028/* Each vector argument has a corresponding array to be used locally
13029 as part of the eventual loop. Create such temporary array and
13030 return it.
13031
13032 PREFIX is the prefix to be used for the temporary.
13033
13034 TYPE is the inner element type.
13035
13036 SIMDLEN is the number of elements. */
13037
13038static tree
13039create_tmp_simd_array (const char *prefix, tree type, int simdlen)
13040{
13041 tree atype = build_array_type_nelts (type, simdlen);
13042 tree avar = create_tmp_var_raw (atype, prefix);
13043 gimple_add_tmp_var (avar);
13044 return avar;
13045}
13046
13047/* Modify the function argument types to their corresponding vector
13048 counterparts if appropriate. Also, create one array for each simd
13049 argument to be used locally when using the function arguments as
13050 part of the loop.
13051
13052 NODE is the function whose arguments are to be adjusted.
13053
13054 Returns an adjustment vector that will be filled describing how the
13055 argument types will be adjusted. */
13056
13057static ipa_parm_adjustment_vec
13058simd_clone_adjust_argument_types (struct cgraph_node *node)
13059{
13060 vec<tree> args;
13061 ipa_parm_adjustment_vec adjustments;
13062
13063 if (node->definition)
13064 args = ipa_get_vector_of_formal_parms (node->decl);
13065 else
13066 args = simd_clone_vector_of_formal_parm_types (node->decl);
13067 adjustments.create (args.length ());
13068 unsigned i, j, veclen;
13069 struct ipa_parm_adjustment adj;
13070 for (i = 0; i < node->simdclone->nargs; ++i)
13071 {
13072 memset (&adj, 0, sizeof (adj));
13073 tree parm = args[i];
13074 tree parm_type = node->definition ? TREE_TYPE (parm) : parm;
13075 adj.base_index = i;
13076 adj.base = parm;
13077
13078 node->simdclone->args[i].orig_arg = node->definition ? parm : NULL_TREE;
13079 node->simdclone->args[i].orig_type = parm_type;
13080
13081 if (node->simdclone->args[i].arg_type != SIMD_CLONE_ARG_TYPE_VECTOR)
13082 {
13083 /* No adjustment necessary for scalar arguments. */
13084 adj.op = IPA_PARM_OP_COPY;
13085 }
13086 else
13087 {
13088 if (INTEGRAL_TYPE_P (parm_type) || POINTER_TYPE_P (parm_type))
13089 veclen = node->simdclone->vecsize_int;
13090 else
13091 veclen = node->simdclone->vecsize_float;
13092 veclen /= GET_MODE_BITSIZE (TYPE_MODE (parm_type));
13093 if (veclen > node->simdclone->simdlen)
13094 veclen = node->simdclone->simdlen;
13095 adj.arg_prefix = "simd";
fdf7662c 13096 if (POINTER_TYPE_P (parm_type))
13097 adj.type = build_vector_type (pointer_sized_int_node, veclen);
13098 else
13099 adj.type = build_vector_type (parm_type, veclen);
d09768a4 13100 node->simdclone->args[i].vector_type = adj.type;
13101 for (j = veclen; j < node->simdclone->simdlen; j += veclen)
13102 {
13103 adjustments.safe_push (adj);
13104 if (j == veclen)
13105 {
13106 memset (&adj, 0, sizeof (adj));
13107 adj.op = IPA_PARM_OP_NEW;
13108 adj.arg_prefix = "simd";
13109 adj.base_index = i;
13110 adj.type = node->simdclone->args[i].vector_type;
13111 }
13112 }
13113
13114 if (node->definition)
13115 node->simdclone->args[i].simd_array
13116 = create_tmp_simd_array (IDENTIFIER_POINTER (DECL_NAME (parm)),
13117 parm_type, node->simdclone->simdlen);
13118 }
13119 adjustments.safe_push (adj);
13120 }
13121
13122 if (node->simdclone->inbranch)
13123 {
13124 tree base_type
13125 = simd_clone_compute_base_data_type (node->simdclone->origin,
13126 node->simdclone);
13127
13128 memset (&adj, 0, sizeof (adj));
13129 adj.op = IPA_PARM_OP_NEW;
13130 adj.arg_prefix = "mask";
13131
13132 adj.base_index = i;
13133 if (INTEGRAL_TYPE_P (base_type) || POINTER_TYPE_P (base_type))
13134 veclen = node->simdclone->vecsize_int;
13135 else
13136 veclen = node->simdclone->vecsize_float;
13137 veclen /= GET_MODE_BITSIZE (TYPE_MODE (base_type));
13138 if (veclen > node->simdclone->simdlen)
13139 veclen = node->simdclone->simdlen;
fdf7662c 13140 if (POINTER_TYPE_P (base_type))
13141 adj.type = build_vector_type (pointer_sized_int_node, veclen);
13142 else
13143 adj.type = build_vector_type (base_type, veclen);
d09768a4 13144 adjustments.safe_push (adj);
13145
13146 for (j = veclen; j < node->simdclone->simdlen; j += veclen)
13147 adjustments.safe_push (adj);
13148
13149 /* We have previously allocated one extra entry for the mask. Use
13150 it and fill it. */
13151 struct cgraph_simd_clone *sc = node->simdclone;
13152 sc->nargs++;
13153 if (node->definition)
13154 {
13155 sc->args[i].orig_arg
13156 = build_decl (UNKNOWN_LOCATION, PARM_DECL, NULL, base_type);
13157 sc->args[i].simd_array
13158 = create_tmp_simd_array ("mask", base_type, sc->simdlen);
13159 }
13160 sc->args[i].orig_type = base_type;
13161 sc->args[i].arg_type = SIMD_CLONE_ARG_TYPE_MASK;
13162 }
13163
13164 if (node->definition)
13165 ipa_modify_formal_parameters (node->decl, adjustments);
13166 else
13167 {
13168 tree new_arg_types = NULL_TREE, new_reversed;
13169 bool last_parm_void = false;
13170 if (args.length () > 0 && args.last () == void_type_node)
13171 last_parm_void = true;
13172
13173 gcc_assert (TYPE_ARG_TYPES (TREE_TYPE (node->decl)));
13174 j = adjustments.length ();
13175 for (i = 0; i < j; i++)
13176 {
13177 struct ipa_parm_adjustment *adj = &adjustments[i];
13178 tree ptype;
13179 if (adj->op == IPA_PARM_OP_COPY)
13180 ptype = args[adj->base_index];
13181 else
13182 ptype = adj->type;
13183 new_arg_types = tree_cons (NULL_TREE, ptype, new_arg_types);
13184 }
13185 new_reversed = nreverse (new_arg_types);
13186 if (last_parm_void)
13187 {
13188 if (new_reversed)
13189 TREE_CHAIN (new_arg_types) = void_list_node;
13190 else
13191 new_reversed = void_list_node;
13192 }
13193
13194 tree new_type = build_distinct_type_copy (TREE_TYPE (node->decl));
13195 TYPE_ARG_TYPES (new_type) = new_reversed;
13196 TREE_TYPE (node->decl) = new_type;
13197
13198 adjustments.release ();
13199 }
13200 args.release ();
13201 return adjustments;
13202}
13203
13204/* Initialize and copy the function arguments in NODE to their
13205 corresponding local simd arrays. Returns a fresh gimple_seq with
13206 the instruction sequence generated. */
13207
13208static gimple_seq
13209simd_clone_init_simd_arrays (struct cgraph_node *node,
13210 ipa_parm_adjustment_vec adjustments)
13211{
13212 gimple_seq seq = NULL;
13213 unsigned i = 0, j = 0, k;
13214
13215 for (tree arg = DECL_ARGUMENTS (node->decl);
13216 arg;
13217 arg = DECL_CHAIN (arg), i++, j++)
13218 {
13219 if (adjustments[j].op == IPA_PARM_OP_COPY)
13220 continue;
13221
13222 node->simdclone->args[i].vector_arg = arg;
13223
13224 tree array = node->simdclone->args[i].simd_array;
13225 if (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg)) == node->simdclone->simdlen)
13226 {
13227 tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
13228 tree ptr = build_fold_addr_expr (array);
13229 tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
13230 build_int_cst (ptype, 0));
13231 t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
13232 gimplify_and_add (t, &seq);
13233 }
13234 else
13235 {
13236 unsigned int simdlen = TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg));
13237 tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
13238 for (k = 0; k < node->simdclone->simdlen; k += simdlen)
13239 {
13240 tree ptr = build_fold_addr_expr (array);
13241 int elemsize;
13242 if (k)
13243 {
13244 arg = DECL_CHAIN (arg);
13245 j++;
13246 }
13247 elemsize
13248 = GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (arg))));
13249 tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
13250 build_int_cst (ptype, k * elemsize));
13251 t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
13252 gimplify_and_add (t, &seq);
13253 }
13254 }
13255 }
13256 return seq;
13257}
13258
13259/* Callback info for ipa_simd_modify_stmt_ops below. */
13260
13261struct modify_stmt_info {
13262 ipa_parm_adjustment_vec adjustments;
42acab1c 13263 gimple *stmt;
d09768a4 13264 /* True if the parent statement was modified by
13265 ipa_simd_modify_stmt_ops. */
13266 bool modified;
13267};
13268
13269/* Callback for walk_gimple_op.
13270
13271 Adjust operands from a given statement as specified in the
13272 adjustments vector in the callback data. */
13273
13274static tree
13275ipa_simd_modify_stmt_ops (tree *tp, int *walk_subtrees, void *data)
13276{
13277 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
2d78e89f 13278 struct modify_stmt_info *info = (struct modify_stmt_info *) wi->info;
13279 tree *orig_tp = tp;
13280 if (TREE_CODE (*tp) == ADDR_EXPR)
13281 tp = &TREE_OPERAND (*tp, 0);
13282 struct ipa_parm_adjustment *cand = NULL;
13283 if (TREE_CODE (*tp) == PARM_DECL)
13284 cand = ipa_get_adjustment_candidate (&tp, NULL, info->adjustments, true);
13285 else
d09768a4 13286 {
d09768a4 13287 if (TYPE_P (*tp))
13288 *walk_subtrees = 0;
d09768a4 13289 }
d09768a4 13290
2d78e89f 13291 tree repl = NULL_TREE;
13292 if (cand)
13293 repl = unshare_expr (cand->new_decl);
13294 else
d09768a4 13295 {
2d78e89f 13296 if (tp != orig_tp)
13297 {
13298 *walk_subtrees = 0;
13299 bool modified = info->modified;
13300 info->modified = false;
13301 walk_tree (tp, ipa_simd_modify_stmt_ops, wi, wi->pset);
13302 if (!info->modified)
13303 {
13304 info->modified = modified;
13305 return NULL_TREE;
13306 }
13307 info->modified = modified;
13308 repl = *tp;
13309 }
13310 else
13311 return NULL_TREE;
d09768a4 13312 }
2d78e89f 13313
13314 if (tp != orig_tp)
d09768a4 13315 {
2d78e89f 13316 repl = build_fold_addr_expr (repl);
42acab1c 13317 gimple *stmt;
9c1dd4d9 13318 if (is_gimple_debug (info->stmt))
13319 {
13320 tree vexpr = make_node (DEBUG_EXPR_DECL);
13321 stmt = gimple_build_debug_source_bind (vexpr, repl, NULL);
13322 DECL_ARTIFICIAL (vexpr) = 1;
13323 TREE_TYPE (vexpr) = TREE_TYPE (repl);
13324 DECL_MODE (vexpr) = TYPE_MODE (TREE_TYPE (repl));
13325 repl = vexpr;
13326 }
13327 else
13328 {
f9e245b2 13329 stmt = gimple_build_assign (make_ssa_name (TREE_TYPE (repl)), repl);
9c1dd4d9 13330 repl = gimple_assign_lhs (stmt);
13331 }
2d78e89f 13332 gimple_stmt_iterator gsi = gsi_for_stmt (info->stmt);
d09768a4 13333 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
2d78e89f 13334 *orig_tp = repl;
d09768a4 13335 }
2d78e89f 13336 else if (!useless_type_conversion_p (TREE_TYPE (*tp), TREE_TYPE (repl)))
d09768a4 13337 {
13338 tree vce = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (*tp), repl);
13339 *tp = vce;
13340 }
13341 else
13342 *tp = repl;
13343
13344 info->modified = true;
d09768a4 13345 return NULL_TREE;
13346}
13347
13348/* Traverse the function body and perform all modifications as
13349 described in ADJUSTMENTS. At function return, ADJUSTMENTS will be
13350 modified such that the replacement/reduction value will now be an
13351 offset into the corresponding simd_array.
13352
13353 This function will replace all function argument uses with their
13354 corresponding simd array elements, and ajust the return values
13355 accordingly. */
13356
13357static void
13358ipa_simd_modify_function_body (struct cgraph_node *node,
13359 ipa_parm_adjustment_vec adjustments,
13360 tree retval_array, tree iter)
13361{
13362 basic_block bb;
2d78e89f 13363 unsigned int i, j, l;
d09768a4 13364
13365 /* Re-use the adjustments array, but this time use it to replace
13366 every function argument use to an offset into the corresponding
13367 simd_array. */
13368 for (i = 0, j = 0; i < node->simdclone->nargs; ++i, ++j)
13369 {
13370 if (!node->simdclone->args[i].vector_arg)
13371 continue;
13372
13373 tree basetype = TREE_TYPE (node->simdclone->args[i].orig_arg);
13374 tree vectype = TREE_TYPE (node->simdclone->args[i].vector_arg);
13375 adjustments[j].new_decl
13376 = build4 (ARRAY_REF,
13377 basetype,
13378 node->simdclone->args[i].simd_array,
13379 iter,
13380 NULL_TREE, NULL_TREE);
13381 if (adjustments[j].op == IPA_PARM_OP_NONE
13382 && TYPE_VECTOR_SUBPARTS (vectype) < node->simdclone->simdlen)
13383 j += node->simdclone->simdlen / TYPE_VECTOR_SUBPARTS (vectype) - 1;
13384 }
13385
2d78e89f 13386 l = adjustments.length ();
13387 for (i = 1; i < num_ssa_names; i++)
13388 {
13389 tree name = ssa_name (i);
13390 if (name
13391 && SSA_NAME_VAR (name)
13392 && TREE_CODE (SSA_NAME_VAR (name)) == PARM_DECL)
13393 {
13394 for (j = 0; j < l; j++)
13395 if (SSA_NAME_VAR (name) == adjustments[j].base
13396 && adjustments[j].new_decl)
13397 {
13398 tree base_var;
13399 if (adjustments[j].new_ssa_base == NULL_TREE)
13400 {
13401 base_var
13402 = copy_var_decl (adjustments[j].base,
13403 DECL_NAME (adjustments[j].base),
13404 TREE_TYPE (adjustments[j].base));
13405 adjustments[j].new_ssa_base = base_var;
13406 }
13407 else
13408 base_var = adjustments[j].new_ssa_base;
13409 if (SSA_NAME_IS_DEFAULT_DEF (name))
13410 {
13411 bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
13412 gimple_stmt_iterator gsi = gsi_after_labels (bb);
13413 tree new_decl = unshare_expr (adjustments[j].new_decl);
13414 set_ssa_default_def (cfun, adjustments[j].base, NULL_TREE);
13415 SET_SSA_NAME_VAR_OR_IDENTIFIER (name, base_var);
13416 SSA_NAME_IS_DEFAULT_DEF (name) = 0;
42acab1c 13417 gimple *stmt = gimple_build_assign (name, new_decl);
2d78e89f 13418 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
13419 }
13420 else
13421 SET_SSA_NAME_VAR_OR_IDENTIFIER (name, base_var);
13422 }
13423 }
13424 }
13425
d09768a4 13426 struct modify_stmt_info info;
13427 info.adjustments = adjustments;
13428
13429 FOR_EACH_BB_FN (bb, DECL_STRUCT_FUNCTION (node->decl))
13430 {
13431 gimple_stmt_iterator gsi;
13432
13433 gsi = gsi_start_bb (bb);
13434 while (!gsi_end_p (gsi))
13435 {
42acab1c 13436 gimple *stmt = gsi_stmt (gsi);
d09768a4 13437 info.stmt = stmt;
13438 struct walk_stmt_info wi;
13439
13440 memset (&wi, 0, sizeof (wi));
13441 info.modified = false;
13442 wi.info = &info;
13443 walk_gimple_op (stmt, ipa_simd_modify_stmt_ops, &wi);
13444
1a91d914 13445 if (greturn *return_stmt = dyn_cast <greturn *> (stmt))
d09768a4 13446 {
1a91d914 13447 tree retval = gimple_return_retval (return_stmt);
d09768a4 13448 if (!retval)
13449 {
13450 gsi_remove (&gsi, true);
13451 continue;
13452 }
13453
13454 /* Replace `return foo' with `retval_array[iter] = foo'. */
13455 tree ref = build4 (ARRAY_REF, TREE_TYPE (retval),
13456 retval_array, iter, NULL, NULL);
13457 stmt = gimple_build_assign (ref, retval);
13458 gsi_replace (&gsi, stmt, true);
13459 info.modified = true;
13460 }
13461
13462 if (info.modified)
13463 {
13464 update_stmt (stmt);
13465 if (maybe_clean_eh_stmt (stmt))
13466 gimple_purge_dead_eh_edges (gimple_bb (stmt));
13467 }
13468 gsi_next (&gsi);
13469 }
13470 }
13471}
13472
13473/* Adjust the argument types in NODE to their appropriate vector
13474 counterparts. */
13475
13476static void
13477simd_clone_adjust (struct cgraph_node *node)
13478{
13479 push_cfun (DECL_STRUCT_FUNCTION (node->decl));
13480
13481 targetm.simd_clone.adjust (node);
13482
13483 tree retval = simd_clone_adjust_return_type (node);
13484 ipa_parm_adjustment_vec adjustments
13485 = simd_clone_adjust_argument_types (node);
13486
13487 push_gimplify_context ();
13488
13489 gimple_seq seq = simd_clone_init_simd_arrays (node, adjustments);
13490
13491 /* Adjust all uses of vector arguments accordingly. Adjust all
13492 return values accordingly. */
13493 tree iter = create_tmp_var (unsigned_type_node, "iter");
f9e245b2 13494 tree iter1 = make_ssa_name (iter);
13495 tree iter2 = make_ssa_name (iter);
d09768a4 13496 ipa_simd_modify_function_body (node, adjustments, retval, iter1);
13497
13498 /* Initialize the iteration variable. */
13499 basic_block entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
13500 basic_block body_bb = split_block_after_labels (entry_bb)->dest;
13501 gimple_stmt_iterator gsi = gsi_after_labels (entry_bb);
13502 /* Insert the SIMD array and iv initialization at function
13503 entry. */
13504 gsi_insert_seq_before (&gsi, seq, GSI_NEW_STMT);
13505
13506 pop_gimplify_context (NULL);
13507
13508 /* Create a new BB right before the original exit BB, to hold the
13509 iteration increment and the condition/branch. */
13510 basic_block orig_exit = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), 0)->src;
13511 basic_block incr_bb = create_empty_bb (orig_exit);
343ee723 13512 add_bb_to_loop (incr_bb, body_bb->loop_father);
d09768a4 13513 /* The succ of orig_exit was EXIT_BLOCK_PTR_FOR_FN (cfun), with an empty
13514 flag. Set it now to be a FALLTHRU_EDGE. */
13515 gcc_assert (EDGE_COUNT (orig_exit->succs) == 1);
13516 EDGE_SUCC (orig_exit, 0)->flags |= EDGE_FALLTHRU;
13517 for (unsigned i = 0;
13518 i < EDGE_COUNT (EXIT_BLOCK_PTR_FOR_FN (cfun)->preds); ++i)
13519 {
13520 edge e = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), i);
13521 redirect_edge_succ (e, incr_bb);
13522 }
13523 edge e = make_edge (incr_bb, EXIT_BLOCK_PTR_FOR_FN (cfun), 0);
13524 e->probability = REG_BR_PROB_BASE;
13525 gsi = gsi_last_bb (incr_bb);
42acab1c 13526 gimple *g = gimple_build_assign (iter2, PLUS_EXPR, iter1,
e9cf809e 13527 build_int_cst (unsigned_type_node, 1));
d09768a4 13528 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13529
13530 /* Mostly annotate the loop for the vectorizer (the rest is done below). */
13531 struct loop *loop = alloc_loop ();
4c73695b 13532 cfun->has_force_vectorize_loops = true;
d09768a4 13533 loop->safelen = node->simdclone->simdlen;
4c73695b 13534 loop->force_vectorize = true;
d09768a4 13535 loop->header = body_bb;
d09768a4 13536
13537 /* Branch around the body if the mask applies. */
13538 if (node->simdclone->inbranch)
13539 {
13540 gimple_stmt_iterator gsi = gsi_last_bb (loop->header);
13541 tree mask_array
13542 = node->simdclone->args[node->simdclone->nargs - 1].simd_array;
f9e245b2 13543 tree mask = make_ssa_name (TREE_TYPE (TREE_TYPE (mask_array)));
d09768a4 13544 tree aref = build4 (ARRAY_REF,
13545 TREE_TYPE (TREE_TYPE (mask_array)),
13546 mask_array, iter1,
13547 NULL, NULL);
13548 g = gimple_build_assign (mask, aref);
13549 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13550 int bitsize = GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (aref)));
13551 if (!INTEGRAL_TYPE_P (TREE_TYPE (aref)))
13552 {
13553 aref = build1 (VIEW_CONVERT_EXPR,
13554 build_nonstandard_integer_type (bitsize, 0), mask);
f9e245b2 13555 mask = make_ssa_name (TREE_TYPE (aref));
d09768a4 13556 g = gimple_build_assign (mask, aref);
13557 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13558 }
13559
13560 g = gimple_build_cond (EQ_EXPR, mask, build_zero_cst (TREE_TYPE (mask)),
13561 NULL, NULL);
13562 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13563 make_edge (loop->header, incr_bb, EDGE_TRUE_VALUE);
13564 FALLTHRU_EDGE (loop->header)->flags = EDGE_FALSE_VALUE;
13565 }
13566
13567 /* Generate the condition. */
13568 g = gimple_build_cond (LT_EXPR,
13569 iter2,
13570 build_int_cst (unsigned_type_node,
13571 node->simdclone->simdlen),
13572 NULL, NULL);
13573 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13574 e = split_block (incr_bb, gsi_stmt (gsi));
13575 basic_block latch_bb = e->dest;
343ee723 13576 basic_block new_exit_bb;
4302d619 13577 new_exit_bb = split_block_after_labels (latch_bb)->dest;
d09768a4 13578 loop->latch = latch_bb;
13579
13580 redirect_edge_succ (FALLTHRU_EDGE (latch_bb), body_bb);
13581
13582 make_edge (incr_bb, new_exit_bb, EDGE_FALSE_VALUE);
13583 /* The successor of incr_bb is already pointing to latch_bb; just
13584 change the flags.
13585 make_edge (incr_bb, latch_bb, EDGE_TRUE_VALUE); */
13586 FALLTHRU_EDGE (incr_bb)->flags = EDGE_TRUE_VALUE;
13587
1a91d914 13588 gphi *phi = create_phi_node (iter1, body_bb);
d09768a4 13589 edge preheader_edge = find_edge (entry_bb, body_bb);
13590 edge latch_edge = single_succ_edge (latch_bb);
13591 add_phi_arg (phi, build_zero_cst (unsigned_type_node), preheader_edge,
13592 UNKNOWN_LOCATION);
13593 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
13594
13595 /* Generate the new return. */
13596 gsi = gsi_last_bb (new_exit_bb);
13597 if (retval
13598 && TREE_CODE (retval) == VIEW_CONVERT_EXPR
13599 && TREE_CODE (TREE_OPERAND (retval, 0)) == RESULT_DECL)
13600 retval = TREE_OPERAND (retval, 0);
13601 else if (retval)
13602 {
13603 retval = build1 (VIEW_CONVERT_EXPR,
13604 TREE_TYPE (TREE_TYPE (node->decl)),
13605 retval);
13606 retval = force_gimple_operand_gsi (&gsi, retval, true, NULL,
13607 false, GSI_CONTINUE_LINKING);
13608 }
13609 g = gimple_build_return (retval);
13610 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13611
13612 /* Handle aligned clauses by replacing default defs of the aligned
13613 uniform args with __builtin_assume_aligned (arg_N(D), alignment)
13614 lhs. Handle linear by adding PHIs. */
13615 for (unsigned i = 0; i < node->simdclone->nargs; i++)
97a82d40 13616 if (node->simdclone->args[i].arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM
13617 && (TREE_ADDRESSABLE (node->simdclone->args[i].orig_arg)
13618 || !is_gimple_reg_type
13619 (TREE_TYPE (node->simdclone->args[i].orig_arg))))
13620 {
13621 tree orig_arg = node->simdclone->args[i].orig_arg;
13622 if (is_gimple_reg_type (TREE_TYPE (orig_arg)))
13623 iter1 = make_ssa_name (TREE_TYPE (orig_arg));
13624 else
13625 {
13626 iter1 = create_tmp_var_raw (TREE_TYPE (orig_arg));
13627 gimple_add_tmp_var (iter1);
13628 }
13629 gsi = gsi_after_labels (entry_bb);
13630 g = gimple_build_assign (iter1, orig_arg);
13631 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
13632 gsi = gsi_after_labels (body_bb);
13633 g = gimple_build_assign (orig_arg, iter1);
13634 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
13635 }
13636 else if (node->simdclone->args[i].arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM
13637 && DECL_BY_REFERENCE (node->simdclone->args[i].orig_arg)
13638 && TREE_CODE (TREE_TYPE (node->simdclone->args[i].orig_arg))
13639 == REFERENCE_TYPE
13640 && TREE_ADDRESSABLE
13641 (TREE_TYPE (TREE_TYPE (node->simdclone->args[i].orig_arg))))
13642 {
13643 tree orig_arg = node->simdclone->args[i].orig_arg;
13644 tree def = ssa_default_def (cfun, orig_arg);
13645 if (def && !has_zero_uses (def))
13646 {
13647 iter1 = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (orig_arg)));
13648 gimple_add_tmp_var (iter1);
13649 gsi = gsi_after_labels (entry_bb);
13650 g = gimple_build_assign (iter1, build_simple_mem_ref (def));
13651 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
13652 gsi = gsi_after_labels (body_bb);
13653 g = gimple_build_assign (build_simple_mem_ref (def), iter1);
13654 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
13655 }
13656 }
13657 else if (node->simdclone->args[i].alignment
13658 && node->simdclone->args[i].arg_type
13659 == SIMD_CLONE_ARG_TYPE_UNIFORM
13660 && (node->simdclone->args[i].alignment
13661 & (node->simdclone->args[i].alignment - 1)) == 0
13662 && TREE_CODE (TREE_TYPE (node->simdclone->args[i].orig_arg))
13663 == POINTER_TYPE)
d09768a4 13664 {
13665 unsigned int alignment = node->simdclone->args[i].alignment;
13666 tree orig_arg = node->simdclone->args[i].orig_arg;
13667 tree def = ssa_default_def (cfun, orig_arg);
6db33a3d 13668 if (def && !has_zero_uses (def))
d09768a4 13669 {
13670 tree fn = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
13671 gimple_seq seq = NULL;
13672 bool need_cvt = false;
1a91d914 13673 gcall *call
d09768a4 13674 = gimple_build_call (fn, 2, def, size_int (alignment));
13675 g = call;
13676 if (!useless_type_conversion_p (TREE_TYPE (orig_arg),
13677 ptr_type_node))
13678 need_cvt = true;
f9e245b2 13679 tree t = make_ssa_name (need_cvt ? ptr_type_node : orig_arg);
d09768a4 13680 gimple_call_set_lhs (g, t);
13681 gimple_seq_add_stmt_without_update (&seq, g);
13682 if (need_cvt)
13683 {
f9e245b2 13684 t = make_ssa_name (orig_arg);
e9cf809e 13685 g = gimple_build_assign (t, NOP_EXPR, gimple_call_lhs (g));
d09768a4 13686 gimple_seq_add_stmt_without_update (&seq, g);
13687 }
13688 gsi_insert_seq_on_edge_immediate
13689 (single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun)), seq);
13690
13691 entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
13692 int freq = compute_call_stmt_bb_frequency (current_function_decl,
13693 entry_bb);
415d1b9a 13694 node->create_edge (cgraph_node::get_create (fn),
13695 call, entry_bb->count, freq);
d09768a4 13696
13697 imm_use_iterator iter;
13698 use_operand_p use_p;
42acab1c 13699 gimple *use_stmt;
d09768a4 13700 tree repl = gimple_get_lhs (g);
13701 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
13702 if (is_gimple_debug (use_stmt) || use_stmt == call)
13703 continue;
13704 else
13705 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
13706 SET_USE (use_p, repl);
13707 }
13708 }
13709 else if (node->simdclone->args[i].arg_type
13710 == SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP)
13711 {
13712 tree orig_arg = node->simdclone->args[i].orig_arg;
d09768a4 13713 gcc_assert (INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
13714 || POINTER_TYPE_P (TREE_TYPE (orig_arg)));
97a82d40 13715 tree def = NULL_TREE;
13716 if (TREE_ADDRESSABLE (orig_arg))
13717 {
13718 def = make_ssa_name (TREE_TYPE (orig_arg));
13719 iter1 = make_ssa_name (TREE_TYPE (orig_arg));
13720 iter2 = make_ssa_name (TREE_TYPE (orig_arg));
13721 gsi = gsi_after_labels (entry_bb);
13722 g = gimple_build_assign (def, orig_arg);
13723 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
13724 }
13725 else
13726 {
13727 def = ssa_default_def (cfun, orig_arg);
13728 if (!def || has_zero_uses (def))
13729 def = NULL_TREE;
13730 else
13731 {
13732 iter1 = make_ssa_name (orig_arg);
13733 iter2 = make_ssa_name (orig_arg);
13734 }
13735 }
13736 if (def)
d09768a4 13737 {
d09768a4 13738 phi = create_phi_node (iter1, body_bb);
13739 add_phi_arg (phi, def, preheader_edge, UNKNOWN_LOCATION);
13740 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
13741 enum tree_code code = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
13742 ? PLUS_EXPR : POINTER_PLUS_EXPR;
13743 tree addtype = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
13744 ? TREE_TYPE (orig_arg) : sizetype;
13745 tree addcst
13746 = build_int_cst (addtype, node->simdclone->args[i].linear_step);
e9cf809e 13747 g = gimple_build_assign (iter2, code, iter1, addcst);
d09768a4 13748 gsi = gsi_last_bb (incr_bb);
13749 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
13750
13751 imm_use_iterator iter;
13752 use_operand_p use_p;
42acab1c 13753 gimple *use_stmt;
97a82d40 13754 if (TREE_ADDRESSABLE (orig_arg))
13755 {
13756 gsi = gsi_after_labels (body_bb);
13757 g = gimple_build_assign (orig_arg, iter1);
13758 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
13759 }
13760 else
13761 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
13762 if (use_stmt == phi)
13763 continue;
13764 else
13765 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
13766 SET_USE (use_p, iter1);
d09768a4 13767 }
13768 }
13769
13770 calculate_dominance_info (CDI_DOMINATORS);
13771 add_loop (loop, loop->header->loop_father);
13772 update_ssa (TODO_update_ssa);
13773
13774 pop_cfun ();
13775}
13776
13777/* If the function in NODE is tagged as an elemental SIMD function,
13778 create the appropriate SIMD clones. */
13779
13780static void
13781expand_simd_clones (struct cgraph_node *node)
13782{
d09768a4 13783 tree attr = lookup_attribute ("omp declare simd",
13784 DECL_ATTRIBUTES (node->decl));
ea0695f9 13785 if (attr == NULL_TREE
13786 || node->global.inlined_to
13787 || lookup_attribute ("noclone", DECL_ATTRIBUTES (node->decl)))
d09768a4 13788 return;
ea0695f9 13789
d09768a4 13790 /* Ignore
13791 #pragma omp declare simd
13792 extern int foo ();
13793 in C, there we don't know the argument types at all. */
13794 if (!node->definition
13795 && TYPE_ARG_TYPES (TREE_TYPE (node->decl)) == NULL_TREE)
13796 return;
13797
13798 do
13799 {
13800 /* Start with parsing the "omp declare simd" attribute(s). */
13801 bool inbranch_clause_specified;
13802 struct cgraph_simd_clone *clone_info
13803 = simd_clone_clauses_extract (node, TREE_VALUE (attr),
13804 &inbranch_clause_specified);
13805 if (clone_info == NULL)
13806 continue;
13807
13808 int orig_simdlen = clone_info->simdlen;
13809 tree base_type = simd_clone_compute_base_data_type (node, clone_info);
13810 /* The target can return 0 (no simd clones should be created),
13811 1 (just one ISA of simd clones should be created) or higher
13812 count of ISA variants. In that case, clone_info is initialized
13813 for the first ISA variant. */
13814 int count
13815 = targetm.simd_clone.compute_vecsize_and_simdlen (node, clone_info,
13816 base_type, 0);
13817 if (count == 0)
13818 continue;
13819
13820 /* Loop over all COUNT ISA variants, and if !INBRANCH_CLAUSE_SPECIFIED,
13821 also create one inbranch and one !inbranch clone of it. */
13822 for (int i = 0; i < count * 2; i++)
13823 {
13824 struct cgraph_simd_clone *clone = clone_info;
13825 if (inbranch_clause_specified && (i & 1) != 0)
13826 continue;
13827
13828 if (i != 0)
13829 {
13830 clone = simd_clone_struct_alloc (clone_info->nargs
d09768a4 13831 + ((i & 1) != 0));
13832 simd_clone_struct_copy (clone, clone_info);
13833 /* Undo changes targetm.simd_clone.compute_vecsize_and_simdlen
13834 and simd_clone_adjust_argument_types did to the first
13835 clone's info. */
13836 clone->nargs -= clone_info->inbranch;
13837 clone->simdlen = orig_simdlen;
13838 /* And call the target hook again to get the right ISA. */
13839 targetm.simd_clone.compute_vecsize_and_simdlen (node, clone,
13840 base_type,
13841 i / 2);
13842 if ((i & 1) != 0)
13843 clone->inbranch = 1;
13844 }
13845
13846 /* simd_clone_mangle might fail if such a clone has been created
13847 already. */
13848 tree id = simd_clone_mangle (node, clone);
13849 if (id == NULL_TREE)
13850 continue;
13851
13852 /* Only when we are sure we want to create the clone actually
13853 clone the function (or definitions) or create another
13854 extern FUNCTION_DECL (for prototypes without definitions). */
13855 struct cgraph_node *n = simd_clone_create (node);
13856 if (n == NULL)
13857 continue;
13858
13859 n->simdclone = clone;
13860 clone->origin = node;
13861 clone->next_clone = NULL;
13862 if (node->simd_clones == NULL)
13863 {
13864 clone->prev_clone = n;
13865 node->simd_clones = n;
13866 }
13867 else
13868 {
13869 clone->prev_clone = node->simd_clones->simdclone->prev_clone;
13870 clone->prev_clone->simdclone->next_clone = n;
13871 node->simd_clones->simdclone->prev_clone = n;
13872 }
35ee1c66 13873 symtab->change_decl_assembler_name (n->decl, id);
d09768a4 13874 /* And finally adjust the return type, parameters and for
13875 definitions also function body. */
13876 if (node->definition)
13877 simd_clone_adjust (n);
13878 else
13879 {
13880 simd_clone_adjust_return_type (n);
13881 simd_clone_adjust_argument_types (n);
13882 }
13883 }
13884 }
13885 while ((attr = lookup_attribute ("omp declare simd", TREE_CHAIN (attr))));
13886}
13887
13888/* Entry point for IPA simd clone creation pass. */
13889
13890static unsigned int
13891ipa_omp_simd_clone (void)
13892{
13893 struct cgraph_node *node;
13894 FOR_EACH_FUNCTION (node)
13895 expand_simd_clones (node);
13896 return 0;
13897}
13898
7620bc82 13899namespace {
13900
13901const pass_data pass_data_omp_simd_clone =
d09768a4 13902{
13903 SIMPLE_IPA_PASS, /* type */
13904 "simdclone", /* name */
13905 OPTGROUP_NONE, /* optinfo_flags */
d09768a4 13906 TV_NONE, /* tv_id */
13907 ( PROP_ssa | PROP_cfg ), /* properties_required */
13908 0, /* properties_provided */
13909 0, /* properties_destroyed */
13910 0, /* todo_flags_start */
13911 0, /* todo_flags_finish */
13912};
13913
7620bc82 13914class pass_omp_simd_clone : public simple_ipa_opt_pass
d09768a4 13915{
13916public:
13917 pass_omp_simd_clone(gcc::context *ctxt)
13918 : simple_ipa_opt_pass(pass_data_omp_simd_clone, ctxt)
13919 {}
13920
13921 /* opt_pass methods: */
31315c24 13922 virtual bool gate (function *);
65b0537f 13923 virtual unsigned int execute (function *) { return ipa_omp_simd_clone (); }
d09768a4 13924};
13925
31315c24 13926bool
13927pass_omp_simd_clone::gate (function *)
13928{
13929 return ((flag_openmp || flag_openmp_simd
13930 || flag_cilkplus
13931 || (in_lto_p && !flag_wpa))
13932 && (targetm.simd_clone.compute_vecsize_and_simdlen != NULL));
13933}
13934
7620bc82 13935} // anon namespace
13936
d09768a4 13937simple_ipa_opt_pass *
13938make_pass_omp_simd_clone (gcc::context *ctxt)
13939{
13940 return new pass_omp_simd_clone (ctxt);
13941}
cbe8bda8 13942
dccabdd1 13943/* Helper function for omp_finish_file routine. Takes decls from V_DECLS and
13944 adds their addresses and sizes to constructor-vector V_CTOR. */
13945static void
13946add_decls_addresses_to_decl_constructor (vec<tree, va_gc> *v_decls,
13947 vec<constructor_elt, va_gc> *v_ctor)
13948{
13949 unsigned len = vec_safe_length (v_decls);
13950 for (unsigned i = 0; i < len; i++)
13951 {
13952 tree it = (*v_decls)[i];
13953 bool is_function = TREE_CODE (it) != VAR_DECL;
13954
13955 CONSTRUCTOR_APPEND_ELT (v_ctor, NULL_TREE, build_fold_addr_expr (it));
13956 if (!is_function)
13957 CONSTRUCTOR_APPEND_ELT (v_ctor, NULL_TREE,
13958 fold_convert (const_ptr_type_node,
13959 DECL_SIZE_UNIT (it)));
13960 }
13961}
13962
13963/* Create new symbols containing (address, size) pairs for global variables,
13964 marked with "omp declare target" attribute, as well as addresses for the
ca4c3545 13965 functions, which are outlined offloading regions. */
dccabdd1 13966void
13967omp_finish_file (void)
13968{
13969 unsigned num_funcs = vec_safe_length (offload_funcs);
13970 unsigned num_vars = vec_safe_length (offload_vars);
13971
13972 if (num_funcs == 0 && num_vars == 0)
13973 return;
13974
13975 if (targetm_common.have_named_sections)
13976 {
13977 vec<constructor_elt, va_gc> *v_f, *v_v;
13978 vec_alloc (v_f, num_funcs);
13979 vec_alloc (v_v, num_vars * 2);
13980
13981 add_decls_addresses_to_decl_constructor (offload_funcs, v_f);
13982 add_decls_addresses_to_decl_constructor (offload_vars, v_v);
13983
13984 tree vars_decl_type = build_array_type_nelts (pointer_sized_int_node,
13985 num_vars * 2);
13986 tree funcs_decl_type = build_array_type_nelts (pointer_sized_int_node,
13987 num_funcs);
13988 TYPE_ALIGN (vars_decl_type) = TYPE_ALIGN (pointer_sized_int_node);
13989 TYPE_ALIGN (funcs_decl_type) = TYPE_ALIGN (pointer_sized_int_node);
13990 tree ctor_v = build_constructor (vars_decl_type, v_v);
13991 tree ctor_f = build_constructor (funcs_decl_type, v_f);
13992 TREE_CONSTANT (ctor_v) = TREE_CONSTANT (ctor_f) = 1;
13993 TREE_STATIC (ctor_v) = TREE_STATIC (ctor_f) = 1;
13994 tree funcs_decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
13995 get_identifier (".offload_func_table"),
13996 funcs_decl_type);
13997 tree vars_decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
13998 get_identifier (".offload_var_table"),
13999 vars_decl_type);
14000 TREE_STATIC (funcs_decl) = TREE_STATIC (vars_decl) = 1;
14001 /* Do not align tables more than TYPE_ALIGN (pointer_sized_int_node),
14002 otherwise a joint table in a binary will contain padding between
14003 tables from multiple object files. */
14004 DECL_USER_ALIGN (funcs_decl) = DECL_USER_ALIGN (vars_decl) = 1;
14005 DECL_ALIGN (funcs_decl) = TYPE_ALIGN (funcs_decl_type);
14006 DECL_ALIGN (vars_decl) = TYPE_ALIGN (vars_decl_type);
14007 DECL_INITIAL (funcs_decl) = ctor_f;
14008 DECL_INITIAL (vars_decl) = ctor_v;
14009 set_decl_section_name (funcs_decl, OFFLOAD_FUNC_TABLE_SECTION_NAME);
14010 set_decl_section_name (vars_decl, OFFLOAD_VAR_TABLE_SECTION_NAME);
14011
14012 varpool_node::finalize_decl (vars_decl);
14013 varpool_node::finalize_decl (funcs_decl);
7114ebdd 14014 }
dccabdd1 14015 else
14016 {
14017 for (unsigned i = 0; i < num_funcs; i++)
14018 {
14019 tree it = (*offload_funcs)[i];
14020 targetm.record_offload_symbol (it);
14021 }
14022 for (unsigned i = 0; i < num_vars; i++)
14023 {
14024 tree it = (*offload_vars)[i];
14025 targetm.record_offload_symbol (it);
14026 }
14027 }
14028}
14029
0bb0f256 14030/* Validate and update the dimensions for offloaded FN. ATTRS is the
14031 raw attribute. DIMS is an array of dimensions, which is returned.
14032 Returns the function level dimensionality -- the level at which an
14033 offload routine wishes to partition a loop. */
14034
14035static int
14036oacc_validate_dims (tree fn, tree attrs, int *dims)
14037{
14038 tree purpose[GOMP_DIM_MAX];
14039 unsigned ix;
14040 tree pos = TREE_VALUE (attrs);
14041 int fn_level = -1;
14042
14043 /* Make sure the attribute creator attached the dimension
14044 information. */
14045 gcc_assert (pos);
14046
14047 for (ix = 0; ix != GOMP_DIM_MAX; ix++)
14048 {
14049 purpose[ix] = TREE_PURPOSE (pos);
14050
14051 if (purpose[ix])
14052 {
14053 if (integer_zerop (purpose[ix]))
14054 fn_level = ix + 1;
14055 else if (fn_level < 0)
14056 fn_level = ix;
14057 }
14058
14059 tree val = TREE_VALUE (pos);
14060 dims[ix] = val ? TREE_INT_CST_LOW (val) : -1;
14061 pos = TREE_CHAIN (pos);
14062 }
14063
14064 bool changed = targetm.goacc.validate_dims (fn, dims, fn_level);
14065
14066 /* Default anything left to 1. */
14067 for (ix = 0; ix != GOMP_DIM_MAX; ix++)
14068 if (dims[ix] < 0)
14069 {
14070 dims[ix] = 1;
14071 changed = true;
14072 }
14073
14074 if (changed)
14075 {
14076 /* Replace the attribute with new values. */
14077 pos = NULL_TREE;
14078 for (ix = GOMP_DIM_MAX; ix--;)
14079 pos = tree_cons (purpose[ix],
14080 build_int_cst (integer_type_node, dims[ix]),
14081 pos);
14082 replace_oacc_fn_attrib (fn, pos);
14083 }
14084
14085 return fn_level;
14086}
14087
14088/* Main entry point for oacc transformations which run on the device
14089 compiler after LTO, so we know what the target device is at this
14090 point (including the host fallback). */
14091
14092static unsigned int
14093execute_oacc_device_lower ()
14094{
14095 tree attrs = get_oacc_fn_attrib (current_function_decl);
14096 int dims[GOMP_DIM_MAX];
14097
14098 if (!attrs)
14099 /* Not an offloaded function. */
14100 return 0;
14101
14102 oacc_validate_dims (current_function_decl, attrs, dims);
14103
14104 return 0;
14105}
14106
14107/* Default launch dimension validator. Force everything to 1. A
14108 backend that wants to provide larger dimensions must override this
14109 hook. */
14110
14111bool
14112default_goacc_validate_dims (tree ARG_UNUSED (decl), int *dims,
14113 int ARG_UNUSED (fn_level))
14114{
14115 bool changed = false;
14116
14117 for (unsigned ix = 0; ix != GOMP_DIM_MAX; ix++)
14118 {
14119 if (dims[ix] != 1)
14120 {
14121 dims[ix] = 1;
14122 changed = true;
14123 }
14124 }
14125
14126 return changed;
14127}
14128
14129namespace {
14130
14131const pass_data pass_data_oacc_device_lower =
14132{
14133 GIMPLE_PASS, /* type */
14134 "oaccdevlow", /* name */
14135 OPTGROUP_NONE, /* optinfo_flags */
14136 TV_NONE, /* tv_id */
14137 PROP_cfg, /* properties_required */
14138 0 /* Possibly PROP_gimple_eomp. */, /* properties_provided */
14139 0, /* properties_destroyed */
14140 0, /* todo_flags_start */
14141 TODO_update_ssa | TODO_cleanup_cfg, /* todo_flags_finish */
14142};
14143
14144class pass_oacc_device_lower : public gimple_opt_pass
14145{
14146public:
14147 pass_oacc_device_lower (gcc::context *ctxt)
14148 : gimple_opt_pass (pass_data_oacc_device_lower, ctxt)
14149 {}
14150
14151 /* opt_pass methods: */
14152 virtual unsigned int execute (function *)
14153 {
14154 bool gate = (flag_openacc != 0 && !seen_error ());
14155
14156 if (!gate)
14157 return 0;
14158
14159 return execute_oacc_device_lower ();
14160 }
14161
14162}; // class pass_oacc_transform
14163
14164} // anon namespace
14165
14166gimple_opt_pass *
14167make_pass_oacc_device_lower (gcc::context *ctxt)
14168{
14169 return new pass_oacc_device_lower (ctxt);
14170}
14171
1e8e9920 14172#include "gt-omp-low.h"