]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/omp-low.c
Mark function parallelized_function before add_new_function
[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"
28#include "tm.h"
b20a8bb4 29#include "input.h"
30#include "alias.h"
31#include "symtab.h"
1e8e9920 32#include "tree.h"
b20a8bb4 33#include "fold-const.h"
9ed99284 34#include "stringpool.h"
35#include "stor-layout.h"
1e8e9920 36#include "rtl.h"
94ea8568 37#include "predict.h"
94ea8568 38#include "hard-reg-set.h"
94ea8568 39#include "function.h"
40#include "dominance.h"
41#include "cfg.h"
42#include "cfganal.h"
bc61cadb 43#include "basic-block.h"
44#include "tree-ssa-alias.h"
45#include "internal-fn.h"
46#include "gimple-fold.h"
47#include "gimple-expr.h"
48#include "is-a.h"
75a70cf9 49#include "gimple.h"
a8783bee 50#include "gimplify.h"
dcf1a1ec 51#include "gimple-iterator.h"
e795d6e1 52#include "gimplify-me.h"
dcf1a1ec 53#include "gimple-walk.h"
75a70cf9 54#include "tree-iterator.h"
1e8e9920 55#include "tree-inline.h"
56#include "langhooks.h"
852f689e 57#include "diagnostic-core.h"
073c1fd5 58#include "gimple-ssa.h"
1140c305 59#include "plugin-api.h"
60#include "ipa-ref.h"
073c1fd5 61#include "cgraph.h"
62#include "tree-cfg.h"
63#include "tree-phinodes.h"
64#include "ssa-iterators.h"
65#include "tree-ssanames.h"
66#include "tree-into-ssa.h"
d53441c8 67#include "flags.h"
d53441c8 68#include "insn-config.h"
69#include "expmed.h"
70#include "dojump.h"
71#include "explow.h"
72#include "calls.h"
73#include "emit-rtl.h"
74#include "varasm.h"
75#include "stmt.h"
9ed99284 76#include "expr.h"
073c1fd5 77#include "tree-dfa.h"
69ee5dbb 78#include "tree-ssa.h"
1e8e9920 79#include "tree-pass.h"
1e8e9920 80#include "except.h"
e3022db7 81#include "splay-tree.h"
34517c64 82#include "insn-codes.h"
cb7f680b 83#include "optabs.h"
84#include "cfgloop.h"
3d483a94 85#include "target.h"
dccabdd1 86#include "common/common-target.h"
7740abd8 87#include "omp-low.h"
424a4a92 88#include "gimple-low.h"
89#include "tree-cfgcleanup.h"
d09768a4 90#include "pretty-print.h"
1140c305 91#include "alloc-pool.h"
2cc80ac3 92#include "symbol-summary.h"
d09768a4 93#include "ipa-prop.h"
e797f49f 94#include "tree-nested.h"
d09768a4 95#include "tree-eh.h"
40750995 96#include "cilk.h"
b0c5e347 97#include "context.h"
dccabdd1 98#include "lto-section-names.h"
ca4c3545 99#include "gomp-constants.h"
1e8e9920 100
75a70cf9 101
ca4c3545 102/* Lowering of OMP parallel and workshare constructs proceeds in two
1e8e9920 103 phases. The first phase scans the function looking for OMP statements
104 and then for variables that must be replaced to satisfy data sharing
105 clauses. The second phase expands code for the constructs, as well as
334ec2d8 106 re-gimplifying things when variables have been replaced with complex
1e8e9920 107 expressions.
108
d134bccc 109 Final code generation is done by pass_expand_omp. The flowgraph is
ca4c3545 110 scanned for regions which are then moved to a new
111 function, to be invoked by the thread library, or offloaded. */
1e8e9920 112
ca4c3545 113/* OMP region information. Every parallel and workshare
7740abd8 114 directive is enclosed between two markers, the OMP_* directive
115 and a corresponding OMP_RETURN statement. */
116
117struct omp_region
118{
119 /* The enclosing region. */
120 struct omp_region *outer;
121
122 /* First child region. */
123 struct omp_region *inner;
124
125 /* Next peer region. */
126 struct omp_region *next;
127
128 /* Block containing the omp directive as its last stmt. */
129 basic_block entry;
130
131 /* Block containing the OMP_RETURN as its last stmt. */
132 basic_block exit;
133
134 /* Block containing the OMP_CONTINUE as its last stmt. */
135 basic_block cont;
136
137 /* If this is a combined parallel+workshare region, this is a list
138 of additional arguments needed by the combined parallel+workshare
139 library call. */
140 vec<tree, va_gc> *ws_args;
141
142 /* The code for the omp directive of this region. */
143 enum gimple_code type;
144
145 /* Schedule kind, only used for OMP_FOR type regions. */
146 enum omp_clause_schedule_kind sched_kind;
147
148 /* True if this is a combined parallel+workshare region. */
149 bool is_combined_parallel;
150};
151
ca4c3545 152/* Levels of parallelism as defined by OpenACC. Increasing numbers
153 correspond to deeper loop nesting levels. */
154#define MASK_GANG 1
155#define MASK_WORKER 2
156#define MASK_VECTOR 4
157
1e8e9920 158/* Context structure. Used to store information about each parallel
159 directive in the code. */
160
161typedef struct omp_context
162{
163 /* This field must be at the beginning, as we do "inheritance": Some
164 callback functions for tree-inline.c (e.g., omp_copy_decl)
165 receive a copy_body_data pointer that is up-casted to an
166 omp_context pointer. */
167 copy_body_data cb;
168
169 /* The tree of contexts corresponding to the encountered constructs. */
170 struct omp_context *outer;
75a70cf9 171 gimple stmt;
1e8e9920 172
48e1416a 173 /* Map variables to fields in a structure that allows communication
1e8e9920 174 between sending and receiving threads. */
175 splay_tree field_map;
176 tree record_type;
177 tree sender_decl;
178 tree receiver_decl;
179
fd6481cf 180 /* These are used just by task contexts, if task firstprivate fn is
181 needed. srecord_type is used to communicate from the thread
182 that encountered the task construct to task firstprivate fn,
183 record_type is allocated by GOMP_task, initialized by task firstprivate
184 fn and passed to the task body fn. */
185 splay_tree sfield_map;
186 tree srecord_type;
187
1e8e9920 188 /* A chain of variables to add to the top-level block surrounding the
189 construct. In the case of a parallel, this is in the child function. */
190 tree block_vars;
191
ca4c3545 192 /* A map of reduction pointer variables. For accelerators, each
193 reduction variable is replaced with an array. Each thread, in turn,
194 is assigned to a slot on that array. */
195 splay_tree reduction_map;
196
bc7bff74 197 /* Label to which GOMP_cancel{,llation_point} and explicit and implicit
198 barriers should jump to during omplower pass. */
199 tree cancel_label;
200
1e8e9920 201 /* What to do with variables with implicitly determined sharing
202 attributes. */
203 enum omp_clause_default_kind default_kind;
204
205 /* Nesting depth of this context. Used to beautify error messages re
206 invalid gotos. The outermost ctx is depth 1, with depth 0 being
207 reserved for the main body of the function. */
208 int depth;
209
1e8e9920 210 /* True if this parallel directive is nested within another. */
211 bool is_nested;
bc7bff74 212
213 /* True if this construct can be cancelled. */
214 bool cancellable;
ca4c3545 215
216 /* For OpenACC loops, a mask of gang, worker and vector used at
217 levels below this one. */
218 int gwv_below;
219 /* For OpenACC loops, a mask of gang, worker and vector used at
220 this level and above. For parallel and kernels clauses, a mask
221 indicating which of num_gangs/num_workers/num_vectors was used. */
222 int gwv_this;
1e8e9920 223} omp_context;
224
ca4c3545 225/* A structure holding the elements of:
226 for (V = N1; V cond N2; V += STEP) [...] */
1e8e9920 227
fd6481cf 228struct omp_for_data_loop
229{
230 tree v, n1, n2, step;
231 enum tree_code cond_code;
232};
233
773c5ba7 234/* A structure describing the main elements of a parallel loop. */
1e8e9920 235
773c5ba7 236struct omp_for_data
1e8e9920 237{
fd6481cf 238 struct omp_for_data_loop loop;
75a70cf9 239 tree chunk_size;
1a91d914 240 gomp_for *for_stmt;
fd6481cf 241 tree pre, iter_type;
242 int collapse;
1e8e9920 243 bool have_nowait, have_ordered;
244 enum omp_clause_schedule_kind sched_kind;
fd6481cf 245 struct omp_for_data_loop *loops;
1e8e9920 246};
247
773c5ba7 248
1e8e9920 249static splay_tree all_contexts;
fd6481cf 250static int taskreg_nesting_level;
bc7bff74 251static int target_nesting_level;
7740abd8 252static struct omp_region *root_omp_region;
fd6481cf 253static bitmap task_shared_vars;
37eaded9 254static vec<omp_context *> taskreg_contexts;
1e8e9920 255
ab129075 256static void scan_omp (gimple_seq *, omp_context *);
75a70cf9 257static tree scan_omp_1_op (tree *, int *, void *);
258
259#define WALK_SUBSTMTS \
260 case GIMPLE_BIND: \
261 case GIMPLE_TRY: \
262 case GIMPLE_CATCH: \
263 case GIMPLE_EH_FILTER: \
4c0315d0 264 case GIMPLE_TRANSACTION: \
75a70cf9 265 /* The sub-statements for these should be walked. */ \
266 *handled_ops_p = false; \
267 break;
268
ca4c3545 269/* Helper function to get the name of the array containing the partial
270 reductions for OpenACC reductions. */
271static const char *
272oacc_get_reduction_array_id (tree node)
273{
274 const char *id = IDENTIFIER_POINTER (DECL_NAME (node));
275 int len = strlen ("OACC") + strlen (id);
276 char *temp_name = XALLOCAVEC (char, len + 1);
277 snprintf (temp_name, len + 1, "OACC%s", id);
278 return IDENTIFIER_POINTER (get_identifier (temp_name));
279}
280
281/* Determine the number of threads OpenACC threads used to determine the
282 size of the array of partial reductions. Currently, this is num_gangs
283 * vector_length. This value may be different than GOACC_GET_NUM_THREADS,
284 because it is independed of the device used. */
285
286static tree
287oacc_max_threads (omp_context *ctx)
288{
289 tree nthreads, vector_length, gangs, clauses;
290
291 gangs = fold_convert (sizetype, integer_one_node);
292 vector_length = gangs;
293
294 /* The reduction clause may be nested inside a loop directive.
295 Scan for the innermost vector_length clause. */
296 for (omp_context *oc = ctx; oc; oc = oc->outer)
297 {
298 if (gimple_code (oc->stmt) != GIMPLE_OMP_TARGET
299 || (gimple_omp_target_kind (oc->stmt)
300 != GF_OMP_TARGET_KIND_OACC_PARALLEL))
301 continue;
302
303 clauses = gimple_omp_target_clauses (oc->stmt);
304
305 vector_length = find_omp_clause (clauses, OMP_CLAUSE_VECTOR_LENGTH);
306 if (vector_length)
307 vector_length = fold_convert_loc (OMP_CLAUSE_LOCATION (vector_length),
308 sizetype,
309 OMP_CLAUSE_VECTOR_LENGTH_EXPR
310 (vector_length));
311 else
312 vector_length = fold_convert (sizetype, integer_one_node);
313
314 gangs = find_omp_clause (clauses, OMP_CLAUSE_NUM_GANGS);
315 if (gangs)
316 gangs = fold_convert_loc (OMP_CLAUSE_LOCATION (gangs), sizetype,
317 OMP_CLAUSE_NUM_GANGS_EXPR (gangs));
318 else
319 gangs = fold_convert (sizetype, integer_one_node);
320
321 break;
322 }
323
324 nthreads = fold_build2 (MULT_EXPR, sizetype, gangs, vector_length);
325
326 return nthreads;
327}
328
dccabdd1 329/* Holds offload tables with decls. */
330vec<tree, va_gc> *offload_funcs, *offload_vars;
331
75a70cf9 332/* Convenience function for calling scan_omp_1_op on tree operands. */
333
334static inline tree
335scan_omp_op (tree *tp, omp_context *ctx)
336{
337 struct walk_stmt_info wi;
338
339 memset (&wi, 0, sizeof (wi));
340 wi.info = ctx;
341 wi.want_locations = true;
342
343 return walk_tree (tp, scan_omp_1_op, &wi, NULL);
344}
345
e3a19533 346static void lower_omp (gimple_seq *, omp_context *);
f49d7bb5 347static tree lookup_decl_in_outer_ctx (tree, omp_context *);
348static tree maybe_lookup_decl_in_outer_ctx (tree, omp_context *);
1e8e9920 349
ca4c3545 350/* Find an OMP clause of type KIND within CLAUSES. */
1e8e9920 351
79acaae1 352tree
590c3166 353find_omp_clause (tree clauses, enum omp_clause_code kind)
1e8e9920 354{
355 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
55d6e7cd 356 if (OMP_CLAUSE_CODE (clauses) == kind)
1e8e9920 357 return clauses;
358
359 return NULL_TREE;
360}
361
362/* Return true if CTX is for an omp parallel. */
363
364static inline bool
365is_parallel_ctx (omp_context *ctx)
366{
75a70cf9 367 return gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL;
1e8e9920 368}
369
773c5ba7 370
fd6481cf 371/* Return true if CTX is for an omp task. */
372
373static inline bool
374is_task_ctx (omp_context *ctx)
375{
75a70cf9 376 return gimple_code (ctx->stmt) == GIMPLE_OMP_TASK;
fd6481cf 377}
378
379
380/* Return true if CTX is for an omp parallel or omp task. */
381
382static inline bool
383is_taskreg_ctx (omp_context *ctx)
384{
75a70cf9 385 return gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL
386 || gimple_code (ctx->stmt) == GIMPLE_OMP_TASK;
fd6481cf 387}
388
389
773c5ba7 390/* Return true if REGION is a combined parallel+workshare region. */
1e8e9920 391
392static inline bool
773c5ba7 393is_combined_parallel (struct omp_region *region)
394{
395 return region->is_combined_parallel;
396}
397
398
399/* Extract the header elements of parallel loop FOR_STMT and store
400 them into *FD. */
401
402static void
1a91d914 403extract_omp_for_data (gomp_for *for_stmt, struct omp_for_data *fd,
fd6481cf 404 struct omp_for_data_loop *loops)
773c5ba7 405{
fd6481cf 406 tree t, var, *collapse_iter, *collapse_count;
407 tree count = NULL_TREE, iter_type = long_integer_type_node;
408 struct omp_for_data_loop *loop;
409 int i;
410 struct omp_for_data_loop dummy_loop;
389dd41b 411 location_t loc = gimple_location (for_stmt);
10c55644 412 bool simd = gimple_omp_for_kind (for_stmt) & GF_OMP_FOR_SIMD;
bc7bff74 413 bool distribute = gimple_omp_for_kind (for_stmt)
414 == GF_OMP_FOR_KIND_DISTRIBUTE;
773c5ba7 415
416 fd->for_stmt = for_stmt;
417 fd->pre = NULL;
75a70cf9 418 fd->collapse = gimple_omp_for_collapse (for_stmt);
fd6481cf 419 if (fd->collapse > 1)
420 fd->loops = loops;
421 else
422 fd->loops = &fd->loop;
773c5ba7 423
bc7bff74 424 fd->have_nowait = distribute || simd;
425 fd->have_ordered = false;
773c5ba7 426 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
427 fd->chunk_size = NULL_TREE;
40750995 428 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_CILKFOR)
429 fd->sched_kind = OMP_CLAUSE_SCHEDULE_CILKFOR;
fd6481cf 430 collapse_iter = NULL;
431 collapse_count = NULL;
773c5ba7 432
75a70cf9 433 for (t = gimple_omp_for_clauses (for_stmt); t ; t = OMP_CLAUSE_CHAIN (t))
55d6e7cd 434 switch (OMP_CLAUSE_CODE (t))
773c5ba7 435 {
436 case OMP_CLAUSE_NOWAIT:
437 fd->have_nowait = true;
438 break;
439 case OMP_CLAUSE_ORDERED:
440 fd->have_ordered = true;
441 break;
442 case OMP_CLAUSE_SCHEDULE:
bc7bff74 443 gcc_assert (!distribute);
773c5ba7 444 fd->sched_kind = OMP_CLAUSE_SCHEDULE_KIND (t);
445 fd->chunk_size = OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (t);
446 break;
bc7bff74 447 case OMP_CLAUSE_DIST_SCHEDULE:
448 gcc_assert (distribute);
449 fd->chunk_size = OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (t);
450 break;
fd6481cf 451 case OMP_CLAUSE_COLLAPSE:
452 if (fd->collapse > 1)
453 {
454 collapse_iter = &OMP_CLAUSE_COLLAPSE_ITERVAR (t);
455 collapse_count = &OMP_CLAUSE_COLLAPSE_COUNT (t);
456 }
757abb46 457 break;
773c5ba7 458 default:
459 break;
460 }
461
fd6481cf 462 /* FIXME: for now map schedule(auto) to schedule(static).
463 There should be analysis to determine whether all iterations
464 are approximately the same amount of work (then schedule(static)
bde357c8 465 is best) or if it varies (then schedule(dynamic,N) is better). */
fd6481cf 466 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_AUTO)
467 {
468 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
469 gcc_assert (fd->chunk_size == NULL);
470 }
471 gcc_assert (fd->collapse == 1 || collapse_iter != NULL);
773c5ba7 472 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
473 gcc_assert (fd->chunk_size == NULL);
474 else if (fd->chunk_size == NULL)
475 {
476 /* We only need to compute a default chunk size for ordered
477 static loops and dynamic loops. */
fd6481cf 478 if (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
bc7bff74 479 || fd->have_ordered)
773c5ba7 480 fd->chunk_size = (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
481 ? integer_zero_node : integer_one_node;
482 }
fd6481cf 483
484 for (i = 0; i < fd->collapse; i++)
485 {
486 if (fd->collapse == 1)
487 loop = &fd->loop;
488 else if (loops != NULL)
489 loop = loops + i;
490 else
491 loop = &dummy_loop;
492
75a70cf9 493 loop->v = gimple_omp_for_index (for_stmt, i);
fd6481cf 494 gcc_assert (SSA_VAR_P (loop->v));
495 gcc_assert (TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
496 || TREE_CODE (TREE_TYPE (loop->v)) == POINTER_TYPE);
497 var = TREE_CODE (loop->v) == SSA_NAME ? SSA_NAME_VAR (loop->v) : loop->v;
75a70cf9 498 loop->n1 = gimple_omp_for_initial (for_stmt, i);
fd6481cf 499
75a70cf9 500 loop->cond_code = gimple_omp_for_cond (for_stmt, i);
501 loop->n2 = gimple_omp_for_final (for_stmt, i);
fd6481cf 502 switch (loop->cond_code)
503 {
504 case LT_EXPR:
505 case GT_EXPR:
506 break;
f2697631 507 case NE_EXPR:
508 gcc_assert (gimple_omp_for_kind (for_stmt)
40750995 509 == GF_OMP_FOR_KIND_CILKSIMD
510 || (gimple_omp_for_kind (for_stmt)
511 == GF_OMP_FOR_KIND_CILKFOR));
f2697631 512 break;
fd6481cf 513 case LE_EXPR:
514 if (POINTER_TYPE_P (TREE_TYPE (loop->n2)))
2cc66f2a 515 loop->n2 = fold_build_pointer_plus_hwi_loc (loc, loop->n2, 1);
fd6481cf 516 else
389dd41b 517 loop->n2 = fold_build2_loc (loc,
518 PLUS_EXPR, TREE_TYPE (loop->n2), loop->n2,
fd6481cf 519 build_int_cst (TREE_TYPE (loop->n2), 1));
520 loop->cond_code = LT_EXPR;
521 break;
522 case GE_EXPR:
523 if (POINTER_TYPE_P (TREE_TYPE (loop->n2)))
2cc66f2a 524 loop->n2 = fold_build_pointer_plus_hwi_loc (loc, loop->n2, -1);
fd6481cf 525 else
389dd41b 526 loop->n2 = fold_build2_loc (loc,
527 MINUS_EXPR, TREE_TYPE (loop->n2), loop->n2,
fd6481cf 528 build_int_cst (TREE_TYPE (loop->n2), 1));
529 loop->cond_code = GT_EXPR;
530 break;
531 default:
532 gcc_unreachable ();
533 }
534
75a70cf9 535 t = gimple_omp_for_incr (for_stmt, i);
fd6481cf 536 gcc_assert (TREE_OPERAND (t, 0) == var);
537 switch (TREE_CODE (t))
538 {
539 case PLUS_EXPR:
fd6481cf 540 loop->step = TREE_OPERAND (t, 1);
541 break;
85d86b55 542 case POINTER_PLUS_EXPR:
543 loop->step = fold_convert (ssizetype, TREE_OPERAND (t, 1));
544 break;
fd6481cf 545 case MINUS_EXPR:
546 loop->step = TREE_OPERAND (t, 1);
389dd41b 547 loop->step = fold_build1_loc (loc,
548 NEGATE_EXPR, TREE_TYPE (loop->step),
fd6481cf 549 loop->step);
550 break;
551 default:
552 gcc_unreachable ();
553 }
554
bc7bff74 555 if (simd
556 || (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
557 && !fd->have_ordered))
3d483a94 558 {
559 if (fd->collapse == 1)
560 iter_type = TREE_TYPE (loop->v);
561 else if (i == 0
562 || TYPE_PRECISION (iter_type)
563 < TYPE_PRECISION (TREE_TYPE (loop->v)))
564 iter_type
565 = build_nonstandard_integer_type
bc7bff74 566 (TYPE_PRECISION (TREE_TYPE (loop->v)), 1);
3d483a94 567 }
568 else if (iter_type != long_long_unsigned_type_node)
fd6481cf 569 {
570 if (POINTER_TYPE_P (TREE_TYPE (loop->v)))
571 iter_type = long_long_unsigned_type_node;
572 else if (TYPE_UNSIGNED (TREE_TYPE (loop->v))
573 && TYPE_PRECISION (TREE_TYPE (loop->v))
574 >= TYPE_PRECISION (iter_type))
575 {
576 tree n;
577
578 if (loop->cond_code == LT_EXPR)
389dd41b 579 n = fold_build2_loc (loc,
580 PLUS_EXPR, TREE_TYPE (loop->v),
fd6481cf 581 loop->n2, loop->step);
582 else
583 n = loop->n1;
584 if (TREE_CODE (n) != INTEGER_CST
585 || tree_int_cst_lt (TYPE_MAX_VALUE (iter_type), n))
586 iter_type = long_long_unsigned_type_node;
587 }
588 else if (TYPE_PRECISION (TREE_TYPE (loop->v))
589 > TYPE_PRECISION (iter_type))
590 {
591 tree n1, n2;
592
593 if (loop->cond_code == LT_EXPR)
594 {
595 n1 = loop->n1;
389dd41b 596 n2 = fold_build2_loc (loc,
597 PLUS_EXPR, TREE_TYPE (loop->v),
fd6481cf 598 loop->n2, loop->step);
599 }
600 else
601 {
389dd41b 602 n1 = fold_build2_loc (loc,
603 MINUS_EXPR, TREE_TYPE (loop->v),
fd6481cf 604 loop->n2, loop->step);
605 n2 = loop->n1;
606 }
607 if (TREE_CODE (n1) != INTEGER_CST
608 || TREE_CODE (n2) != INTEGER_CST
609 || !tree_int_cst_lt (TYPE_MIN_VALUE (iter_type), n1)
610 || !tree_int_cst_lt (n2, TYPE_MAX_VALUE (iter_type)))
611 iter_type = long_long_unsigned_type_node;
612 }
613 }
614
615 if (collapse_count && *collapse_count == NULL)
616 {
8e6b4515 617 t = fold_binary (loop->cond_code, boolean_type_node,
618 fold_convert (TREE_TYPE (loop->v), loop->n1),
619 fold_convert (TREE_TYPE (loop->v), loop->n2));
620 if (t && integer_zerop (t))
621 count = build_zero_cst (long_long_unsigned_type_node);
622 else if ((i == 0 || count != NULL_TREE)
623 && TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
624 && TREE_CONSTANT (loop->n1)
625 && TREE_CONSTANT (loop->n2)
626 && TREE_CODE (loop->step) == INTEGER_CST)
fd6481cf 627 {
628 tree itype = TREE_TYPE (loop->v);
629
630 if (POINTER_TYPE_P (itype))
3cea8318 631 itype = signed_type_for (itype);
fd6481cf 632 t = build_int_cst (itype, (loop->cond_code == LT_EXPR ? -1 : 1));
389dd41b 633 t = fold_build2_loc (loc,
634 PLUS_EXPR, itype,
635 fold_convert_loc (loc, itype, loop->step), t);
636 t = fold_build2_loc (loc, PLUS_EXPR, itype, t,
637 fold_convert_loc (loc, itype, loop->n2));
638 t = fold_build2_loc (loc, MINUS_EXPR, itype, t,
639 fold_convert_loc (loc, itype, loop->n1));
fd6481cf 640 if (TYPE_UNSIGNED (itype) && loop->cond_code == GT_EXPR)
389dd41b 641 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype,
642 fold_build1_loc (loc, NEGATE_EXPR, itype, t),
643 fold_build1_loc (loc, NEGATE_EXPR, itype,
644 fold_convert_loc (loc, itype,
645 loop->step)));
fd6481cf 646 else
389dd41b 647 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, t,
648 fold_convert_loc (loc, itype, loop->step));
649 t = fold_convert_loc (loc, long_long_unsigned_type_node, t);
fd6481cf 650 if (count != NULL_TREE)
389dd41b 651 count = fold_build2_loc (loc,
652 MULT_EXPR, long_long_unsigned_type_node,
fd6481cf 653 count, t);
654 else
655 count = t;
656 if (TREE_CODE (count) != INTEGER_CST)
657 count = NULL_TREE;
658 }
8e6b4515 659 else if (count && !integer_zerop (count))
fd6481cf 660 count = NULL_TREE;
661 }
662 }
663
3d483a94 664 if (count
bc7bff74 665 && !simd
666 && (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
667 || fd->have_ordered))
fd6481cf 668 {
669 if (!tree_int_cst_lt (count, TYPE_MAX_VALUE (long_integer_type_node)))
670 iter_type = long_long_unsigned_type_node;
671 else
672 iter_type = long_integer_type_node;
673 }
674 else if (collapse_iter && *collapse_iter != NULL)
675 iter_type = TREE_TYPE (*collapse_iter);
676 fd->iter_type = iter_type;
677 if (collapse_iter && *collapse_iter == NULL)
678 *collapse_iter = create_tmp_var (iter_type, ".iter");
679 if (collapse_count && *collapse_count == NULL)
680 {
681 if (count)
389dd41b 682 *collapse_count = fold_convert_loc (loc, iter_type, count);
fd6481cf 683 else
684 *collapse_count = create_tmp_var (iter_type, ".count");
685 }
686
687 if (fd->collapse > 1)
688 {
689 fd->loop.v = *collapse_iter;
690 fd->loop.n1 = build_int_cst (TREE_TYPE (fd->loop.v), 0);
691 fd->loop.n2 = *collapse_count;
692 fd->loop.step = build_int_cst (TREE_TYPE (fd->loop.v), 1);
693 fd->loop.cond_code = LT_EXPR;
694 }
ca4c3545 695
696 /* For OpenACC loops, force a chunk size of one, as this avoids the default
697 scheduling where several subsequent iterations are being executed by the
698 same thread. */
699 if (gimple_omp_for_kind (for_stmt) == GF_OMP_FOR_KIND_OACC_LOOP)
700 {
701 gcc_assert (fd->chunk_size == NULL_TREE);
702 fd->chunk_size = build_int_cst (TREE_TYPE (fd->loop.v), 1);
703 }
773c5ba7 704}
705
706
707/* Given two blocks PAR_ENTRY_BB and WS_ENTRY_BB such that WS_ENTRY_BB
708 is the immediate dominator of PAR_ENTRY_BB, return true if there
709 are no data dependencies that would prevent expanding the parallel
710 directive at PAR_ENTRY_BB as a combined parallel+workshare region.
711
712 When expanding a combined parallel+workshare region, the call to
713 the child function may need additional arguments in the case of
75a70cf9 714 GIMPLE_OMP_FOR regions. In some cases, these arguments are
715 computed out of variables passed in from the parent to the child
716 via 'struct .omp_data_s'. For instance:
773c5ba7 717
718 #pragma omp parallel for schedule (guided, i * 4)
719 for (j ...)
720
721 Is lowered into:
722
723 # BLOCK 2 (PAR_ENTRY_BB)
724 .omp_data_o.i = i;
725 #pragma omp parallel [child fn: bar.omp_fn.0 ( ..., D.1598)
48e1416a 726
773c5ba7 727 # BLOCK 3 (WS_ENTRY_BB)
728 .omp_data_i = &.omp_data_o;
729 D.1667 = .omp_data_i->i;
730 D.1598 = D.1667 * 4;
731 #pragma omp for schedule (guided, D.1598)
732
733 When we outline the parallel region, the call to the child function
734 'bar.omp_fn.0' will need the value D.1598 in its argument list, but
735 that value is computed *after* the call site. So, in principle we
736 cannot do the transformation.
737
738 To see whether the code in WS_ENTRY_BB blocks the combined
739 parallel+workshare call, we collect all the variables used in the
75a70cf9 740 GIMPLE_OMP_FOR header check whether they appear on the LHS of any
773c5ba7 741 statement in WS_ENTRY_BB. If so, then we cannot emit the combined
742 call.
743
744 FIXME. If we had the SSA form built at this point, we could merely
745 hoist the code in block 3 into block 2 and be done with it. But at
746 this point we don't have dataflow information and though we could
747 hack something up here, it is really not worth the aggravation. */
748
749static bool
f018d957 750workshare_safe_to_combine_p (basic_block ws_entry_bb)
773c5ba7 751{
752 struct omp_for_data fd;
f018d957 753 gimple ws_stmt = last_stmt (ws_entry_bb);
773c5ba7 754
75a70cf9 755 if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
773c5ba7 756 return true;
757
75a70cf9 758 gcc_assert (gimple_code (ws_stmt) == GIMPLE_OMP_FOR);
773c5ba7 759
1a91d914 760 extract_omp_for_data (as_a <gomp_for *> (ws_stmt), &fd, NULL);
fd6481cf 761
762 if (fd.collapse > 1 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
763 return false;
764 if (fd.iter_type != long_integer_type_node)
765 return false;
773c5ba7 766
767 /* FIXME. We give up too easily here. If any of these arguments
768 are not constants, they will likely involve variables that have
769 been mapped into fields of .omp_data_s for sharing with the child
770 function. With appropriate data flow, it would be possible to
771 see through this. */
fd6481cf 772 if (!is_gimple_min_invariant (fd.loop.n1)
773 || !is_gimple_min_invariant (fd.loop.n2)
774 || !is_gimple_min_invariant (fd.loop.step)
773c5ba7 775 || (fd.chunk_size && !is_gimple_min_invariant (fd.chunk_size)))
776 return false;
777
778 return true;
779}
780
781
782/* Collect additional arguments needed to emit a combined
783 parallel+workshare call. WS_STMT is the workshare directive being
784 expanded. */
785
f1f41a6c 786static vec<tree, va_gc> *
bc7bff74 787get_ws_args_for (gimple par_stmt, gimple ws_stmt)
773c5ba7 788{
789 tree t;
389dd41b 790 location_t loc = gimple_location (ws_stmt);
f1f41a6c 791 vec<tree, va_gc> *ws_args;
773c5ba7 792
1a91d914 793 if (gomp_for *for_stmt = dyn_cast <gomp_for *> (ws_stmt))
773c5ba7 794 {
795 struct omp_for_data fd;
bc7bff74 796 tree n1, n2;
773c5ba7 797
1a91d914 798 extract_omp_for_data (for_stmt, &fd, NULL);
bc7bff74 799 n1 = fd.loop.n1;
800 n2 = fd.loop.n2;
801
1a91d914 802 if (gimple_omp_for_combined_into_p (for_stmt))
bc7bff74 803 {
804 tree innerc
805 = find_omp_clause (gimple_omp_parallel_clauses (par_stmt),
806 OMP_CLAUSE__LOOPTEMP_);
807 gcc_assert (innerc);
808 n1 = OMP_CLAUSE_DECL (innerc);
809 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
810 OMP_CLAUSE__LOOPTEMP_);
811 gcc_assert (innerc);
812 n2 = OMP_CLAUSE_DECL (innerc);
813 }
773c5ba7 814
f1f41a6c 815 vec_alloc (ws_args, 3 + (fd.chunk_size != 0));
773c5ba7 816
bc7bff74 817 t = fold_convert_loc (loc, long_integer_type_node, n1);
f1f41a6c 818 ws_args->quick_push (t);
773c5ba7 819
bc7bff74 820 t = fold_convert_loc (loc, long_integer_type_node, n2);
f1f41a6c 821 ws_args->quick_push (t);
773c5ba7 822
414c3a2c 823 t = fold_convert_loc (loc, long_integer_type_node, fd.loop.step);
f1f41a6c 824 ws_args->quick_push (t);
414c3a2c 825
826 if (fd.chunk_size)
827 {
828 t = fold_convert_loc (loc, long_integer_type_node, fd.chunk_size);
f1f41a6c 829 ws_args->quick_push (t);
414c3a2c 830 }
773c5ba7 831
832 return ws_args;
833 }
75a70cf9 834 else if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
773c5ba7 835 {
ac6e3339 836 /* Number of sections is equal to the number of edges from the
75a70cf9 837 GIMPLE_OMP_SECTIONS_SWITCH statement, except for the one to
838 the exit of the sections region. */
839 basic_block bb = single_succ (gimple_bb (ws_stmt));
ac6e3339 840 t = build_int_cst (unsigned_type_node, EDGE_COUNT (bb->succs) - 1);
f1f41a6c 841 vec_alloc (ws_args, 1);
842 ws_args->quick_push (t);
414c3a2c 843 return ws_args;
773c5ba7 844 }
845
846 gcc_unreachable ();
847}
848
849
850/* Discover whether REGION is a combined parallel+workshare region. */
851
852static void
853determine_parallel_type (struct omp_region *region)
1e8e9920 854{
773c5ba7 855 basic_block par_entry_bb, par_exit_bb;
856 basic_block ws_entry_bb, ws_exit_bb;
857
03ed154b 858 if (region == NULL || region->inner == NULL
ac6e3339 859 || region->exit == NULL || region->inner->exit == NULL
860 || region->inner->cont == NULL)
773c5ba7 861 return;
862
863 /* We only support parallel+for and parallel+sections. */
75a70cf9 864 if (region->type != GIMPLE_OMP_PARALLEL
865 || (region->inner->type != GIMPLE_OMP_FOR
866 && region->inner->type != GIMPLE_OMP_SECTIONS))
773c5ba7 867 return;
868
869 /* Check for perfect nesting PAR_ENTRY_BB -> WS_ENTRY_BB and
870 WS_EXIT_BB -> PAR_EXIT_BB. */
61e47ac8 871 par_entry_bb = region->entry;
872 par_exit_bb = region->exit;
873 ws_entry_bb = region->inner->entry;
874 ws_exit_bb = region->inner->exit;
773c5ba7 875
876 if (single_succ (par_entry_bb) == ws_entry_bb
877 && single_succ (ws_exit_bb) == par_exit_bb
f018d957 878 && workshare_safe_to_combine_p (ws_entry_bb)
75a70cf9 879 && (gimple_omp_parallel_combined_p (last_stmt (par_entry_bb))
de7ef844 880 || (last_and_only_stmt (ws_entry_bb)
881 && last_and_only_stmt (par_exit_bb))))
773c5ba7 882 {
bc7bff74 883 gimple par_stmt = last_stmt (par_entry_bb);
75a70cf9 884 gimple ws_stmt = last_stmt (ws_entry_bb);
61e47ac8 885
75a70cf9 886 if (region->inner->type == GIMPLE_OMP_FOR)
773c5ba7 887 {
888 /* If this is a combined parallel loop, we need to determine
889 whether or not to use the combined library calls. There
890 are two cases where we do not apply the transformation:
891 static loops and any kind of ordered loop. In the first
892 case, we already open code the loop so there is no need
893 to do anything else. In the latter case, the combined
894 parallel loop call would still need extra synchronization
895 to implement ordered semantics, so there would not be any
896 gain in using the combined call. */
75a70cf9 897 tree clauses = gimple_omp_for_clauses (ws_stmt);
773c5ba7 898 tree c = find_omp_clause (clauses, OMP_CLAUSE_SCHEDULE);
899 if (c == NULL
900 || OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_STATIC
901 || find_omp_clause (clauses, OMP_CLAUSE_ORDERED))
902 {
903 region->is_combined_parallel = false;
904 region->inner->is_combined_parallel = false;
905 return;
906 }
907 }
908
909 region->is_combined_parallel = true;
910 region->inner->is_combined_parallel = true;
bc7bff74 911 region->ws_args = get_ws_args_for (par_stmt, ws_stmt);
773c5ba7 912 }
1e8e9920 913}
914
773c5ba7 915
1e8e9920 916/* Return true if EXPR is variable sized. */
917
918static inline bool
1f1872fd 919is_variable_sized (const_tree expr)
1e8e9920 920{
921 return !TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (expr)));
922}
923
924/* Return true if DECL is a reference type. */
925
926static inline bool
927is_reference (tree decl)
928{
929 return lang_hooks.decls.omp_privatize_by_reference (decl);
930}
931
ca4c3545 932/* Return the type of a decl. If the decl is reference type,
933 return its base type. */
934static inline tree
935get_base_type (tree decl)
936{
937 tree type = TREE_TYPE (decl);
938 if (is_reference (decl))
939 type = TREE_TYPE (type);
940 return type;
941}
942
943/* Lookup variables. The "maybe" form
1e8e9920 944 allows for the variable form to not have been entered, otherwise we
945 assert that the variable must have been entered. */
946
947static inline tree
948lookup_decl (tree var, omp_context *ctx)
949{
06ecf488 950 tree *n = ctx->cb.decl_map->get (var);
e3022db7 951 return *n;
1e8e9920 952}
953
954static inline tree
e8a588af 955maybe_lookup_decl (const_tree var, omp_context *ctx)
1e8e9920 956{
06ecf488 957 tree *n = ctx->cb.decl_map->get (const_cast<tree> (var));
e3022db7 958 return n ? *n : NULL_TREE;
1e8e9920 959}
960
961static inline tree
962lookup_field (tree var, omp_context *ctx)
963{
964 splay_tree_node n;
965 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
966 return (tree) n->value;
967}
968
fd6481cf 969static inline tree
970lookup_sfield (tree var, omp_context *ctx)
971{
972 splay_tree_node n;
973 n = splay_tree_lookup (ctx->sfield_map
974 ? ctx->sfield_map : ctx->field_map,
975 (splay_tree_key) var);
976 return (tree) n->value;
977}
978
1e8e9920 979static inline tree
980maybe_lookup_field (tree var, omp_context *ctx)
981{
982 splay_tree_node n;
983 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
984 return n ? (tree) n->value : NULL_TREE;
985}
986
ca4c3545 987static inline tree
988lookup_oacc_reduction (const char *id, omp_context *ctx)
989{
990 splay_tree_node n;
991 n = splay_tree_lookup (ctx->reduction_map, (splay_tree_key) id);
992 return (tree) n->value;
993}
994
995static inline tree
996maybe_lookup_oacc_reduction (tree var, omp_context *ctx)
997{
998 splay_tree_node n = NULL;
999 if (ctx->reduction_map)
1000 n = splay_tree_lookup (ctx->reduction_map, (splay_tree_key) var);
1001 return n ? (tree) n->value : NULL_TREE;
1002}
1003
e8a588af 1004/* Return true if DECL should be copied by pointer. SHARED_CTX is
1005 the parallel context if DECL is to be shared. */
1e8e9920 1006
1007static bool
fd6481cf 1008use_pointer_for_field (tree decl, omp_context *shared_ctx)
1e8e9920 1009{
1010 if (AGGREGATE_TYPE_P (TREE_TYPE (decl)))
1011 return true;
1012
554f2707 1013 /* We can only use copy-in/copy-out semantics for shared variables
1e8e9920 1014 when we know the value is not accessible from an outer scope. */
e8a588af 1015 if (shared_ctx)
1e8e9920 1016 {
ca4c3545 1017 gcc_assert (!is_gimple_omp_oacc (shared_ctx->stmt));
1018
1e8e9920 1019 /* ??? Trivially accessible from anywhere. But why would we even
1020 be passing an address in this case? Should we simply assert
1021 this to be false, or should we have a cleanup pass that removes
1022 these from the list of mappings? */
1023 if (TREE_STATIC (decl) || DECL_EXTERNAL (decl))
1024 return true;
1025
1026 /* For variables with DECL_HAS_VALUE_EXPR_P set, we cannot tell
1027 without analyzing the expression whether or not its location
1028 is accessible to anyone else. In the case of nested parallel
1029 regions it certainly may be. */
df2c34fc 1030 if (TREE_CODE (decl) != RESULT_DECL && DECL_HAS_VALUE_EXPR_P (decl))
1e8e9920 1031 return true;
1032
1033 /* Do not use copy-in/copy-out for variables that have their
1034 address taken. */
1035 if (TREE_ADDRESSABLE (decl))
1036 return true;
e8a588af 1037
b8214689 1038 /* lower_send_shared_vars only uses copy-in, but not copy-out
1039 for these. */
1040 if (TREE_READONLY (decl)
1041 || ((TREE_CODE (decl) == RESULT_DECL
1042 || TREE_CODE (decl) == PARM_DECL)
1043 && DECL_BY_REFERENCE (decl)))
1044 return false;
1045
e8a588af 1046 /* Disallow copy-in/out in nested parallel if
1047 decl is shared in outer parallel, otherwise
1048 each thread could store the shared variable
1049 in its own copy-in location, making the
1050 variable no longer really shared. */
b8214689 1051 if (shared_ctx->is_nested)
e8a588af 1052 {
1053 omp_context *up;
1054
1055 for (up = shared_ctx->outer; up; up = up->outer)
0cb159ec 1056 if (is_taskreg_ctx (up) && maybe_lookup_decl (decl, up))
e8a588af 1057 break;
1058
0cb159ec 1059 if (up)
e8a588af 1060 {
1061 tree c;
1062
75a70cf9 1063 for (c = gimple_omp_taskreg_clauses (up->stmt);
e8a588af 1064 c; c = OMP_CLAUSE_CHAIN (c))
1065 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
1066 && OMP_CLAUSE_DECL (c) == decl)
1067 break;
1068
1069 if (c)
784ad964 1070 goto maybe_mark_addressable_and_ret;
e8a588af 1071 }
1072 }
fd6481cf 1073
b8214689 1074 /* For tasks avoid using copy-in/out. As tasks can be
fd6481cf 1075 deferred or executed in different thread, when GOMP_task
1076 returns, the task hasn't necessarily terminated. */
b8214689 1077 if (is_task_ctx (shared_ctx))
fd6481cf 1078 {
784ad964 1079 tree outer;
1080 maybe_mark_addressable_and_ret:
1081 outer = maybe_lookup_decl_in_outer_ctx (decl, shared_ctx);
fd6481cf 1082 if (is_gimple_reg (outer))
1083 {
1084 /* Taking address of OUTER in lower_send_shared_vars
1085 might need regimplification of everything that uses the
1086 variable. */
1087 if (!task_shared_vars)
1088 task_shared_vars = BITMAP_ALLOC (NULL);
1089 bitmap_set_bit (task_shared_vars, DECL_UID (outer));
1090 TREE_ADDRESSABLE (outer) = 1;
1091 }
1092 return true;
1093 }
1e8e9920 1094 }
1095
1096 return false;
1097}
1098
79acaae1 1099/* Construct a new automatic decl similar to VAR. */
1100
1101static tree
1102omp_copy_decl_2 (tree var, tree name, tree type, omp_context *ctx)
1103{
1104 tree copy = copy_var_decl (var, name, type);
1105
1106 DECL_CONTEXT (copy) = current_function_decl;
1767a056 1107 DECL_CHAIN (copy) = ctx->block_vars;
1e8e9920 1108 ctx->block_vars = copy;
1109
1110 return copy;
1111}
1112
1113static tree
1114omp_copy_decl_1 (tree var, omp_context *ctx)
1115{
1116 return omp_copy_decl_2 (var, DECL_NAME (var), TREE_TYPE (var), ctx);
1117}
1118
445d06b6 1119/* Build COMPONENT_REF and set TREE_THIS_VOLATILE and TREE_READONLY on it
1120 as appropriate. */
1121static tree
1122omp_build_component_ref (tree obj, tree field)
1123{
1124 tree ret = build3 (COMPONENT_REF, TREE_TYPE (field), obj, field, NULL);
1125 if (TREE_THIS_VOLATILE (field))
1126 TREE_THIS_VOLATILE (ret) |= 1;
1127 if (TREE_READONLY (field))
1128 TREE_READONLY (ret) |= 1;
1129 return ret;
1130}
1131
1e8e9920 1132/* Build tree nodes to access the field for VAR on the receiver side. */
1133
1134static tree
1135build_receiver_ref (tree var, bool by_ref, omp_context *ctx)
1136{
1137 tree x, field = lookup_field (var, ctx);
1138
1139 /* If the receiver record type was remapped in the child function,
1140 remap the field into the new record type. */
1141 x = maybe_lookup_field (field, ctx);
1142 if (x != NULL)
1143 field = x;
1144
182cf5a9 1145 x = build_simple_mem_ref (ctx->receiver_decl);
445d06b6 1146 x = omp_build_component_ref (x, field);
1e8e9920 1147 if (by_ref)
182cf5a9 1148 x = build_simple_mem_ref (x);
1e8e9920 1149
1150 return x;
1151}
1152
1153/* Build tree nodes to access VAR in the scope outer to CTX. In the case
1154 of a parallel, this is a component reference; for workshare constructs
1155 this is some variable. */
1156
1157static tree
1158build_outer_var_ref (tree var, omp_context *ctx)
1159{
1160 tree x;
1161
f49d7bb5 1162 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx)))
1e8e9920 1163 x = var;
1164 else if (is_variable_sized (var))
1165 {
1166 x = TREE_OPERAND (DECL_VALUE_EXPR (var), 0);
1167 x = build_outer_var_ref (x, ctx);
182cf5a9 1168 x = build_simple_mem_ref (x);
1e8e9920 1169 }
fd6481cf 1170 else if (is_taskreg_ctx (ctx))
1e8e9920 1171 {
e8a588af 1172 bool by_ref = use_pointer_for_field (var, NULL);
1e8e9920 1173 x = build_receiver_ref (var, by_ref, ctx);
1174 }
3d483a94 1175 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
10c55644 1176 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
3d483a94 1177 {
1178 /* #pragma omp simd isn't a worksharing construct, and can reference even
1179 private vars in its linear etc. clauses. */
1180 x = NULL_TREE;
1181 if (ctx->outer && is_taskreg_ctx (ctx))
1182 x = lookup_decl (var, ctx->outer);
1183 else if (ctx->outer)
84cb1020 1184 x = maybe_lookup_decl_in_outer_ctx (var, ctx);
3d483a94 1185 if (x == NULL_TREE)
1186 x = var;
1187 }
1e8e9920 1188 else if (ctx->outer)
1189 x = lookup_decl (var, ctx->outer);
9438af57 1190 else if (is_reference (var))
1191 /* This can happen with orphaned constructs. If var is reference, it is
1192 possible it is shared and as such valid. */
1193 x = var;
1e8e9920 1194 else
1195 gcc_unreachable ();
1196
1197 if (is_reference (var))
182cf5a9 1198 x = build_simple_mem_ref (x);
1e8e9920 1199
1200 return x;
1201}
1202
1203/* Build tree nodes to access the field for VAR on the sender side. */
1204
1205static tree
1206build_sender_ref (tree var, omp_context *ctx)
1207{
fd6481cf 1208 tree field = lookup_sfield (var, ctx);
445d06b6 1209 return omp_build_component_ref (ctx->sender_decl, field);
1e8e9920 1210}
1211
1212/* Add a new field for VAR inside the structure CTX->SENDER_DECL. */
1213
1214static void
fd6481cf 1215install_var_field (tree var, bool by_ref, int mask, omp_context *ctx)
1e8e9920 1216{
fd6481cf 1217 tree field, type, sfield = NULL_TREE;
1e8e9920 1218
fd6481cf 1219 gcc_assert ((mask & 1) == 0
1220 || !splay_tree_lookup (ctx->field_map, (splay_tree_key) var));
1221 gcc_assert ((mask & 2) == 0 || !ctx->sfield_map
1222 || !splay_tree_lookup (ctx->sfield_map, (splay_tree_key) var));
ca4c3545 1223 gcc_assert ((mask & 3) == 3
1224 || !is_gimple_omp_oacc (ctx->stmt));
1e8e9920 1225
1226 type = TREE_TYPE (var);
bc7bff74 1227 if (mask & 4)
1228 {
1229 gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
1230 type = build_pointer_type (build_pointer_type (type));
1231 }
1232 else if (by_ref)
1e8e9920 1233 type = build_pointer_type (type);
fd6481cf 1234 else if ((mask & 3) == 1 && is_reference (var))
1235 type = TREE_TYPE (type);
1e8e9920 1236
e60a6f7b 1237 field = build_decl (DECL_SOURCE_LOCATION (var),
1238 FIELD_DECL, DECL_NAME (var), type);
1e8e9920 1239
1240 /* Remember what variable this field was created for. This does have a
1241 side effect of making dwarf2out ignore this member, so for helpful
1242 debugging we clear it later in delete_omp_context. */
1243 DECL_ABSTRACT_ORIGIN (field) = var;
fd6481cf 1244 if (type == TREE_TYPE (var))
1245 {
1246 DECL_ALIGN (field) = DECL_ALIGN (var);
1247 DECL_USER_ALIGN (field) = DECL_USER_ALIGN (var);
1248 TREE_THIS_VOLATILE (field) = TREE_THIS_VOLATILE (var);
1249 }
1250 else
1251 DECL_ALIGN (field) = TYPE_ALIGN (type);
1e8e9920 1252
fd6481cf 1253 if ((mask & 3) == 3)
1254 {
1255 insert_field_into_struct (ctx->record_type, field);
1256 if (ctx->srecord_type)
1257 {
e60a6f7b 1258 sfield = build_decl (DECL_SOURCE_LOCATION (var),
1259 FIELD_DECL, DECL_NAME (var), type);
fd6481cf 1260 DECL_ABSTRACT_ORIGIN (sfield) = var;
1261 DECL_ALIGN (sfield) = DECL_ALIGN (field);
1262 DECL_USER_ALIGN (sfield) = DECL_USER_ALIGN (field);
1263 TREE_THIS_VOLATILE (sfield) = TREE_THIS_VOLATILE (field);
1264 insert_field_into_struct (ctx->srecord_type, sfield);
1265 }
1266 }
1267 else
1268 {
1269 if (ctx->srecord_type == NULL_TREE)
1270 {
1271 tree t;
1272
1273 ctx->srecord_type = lang_hooks.types.make_type (RECORD_TYPE);
1274 ctx->sfield_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
1275 for (t = TYPE_FIELDS (ctx->record_type); t ; t = TREE_CHAIN (t))
1276 {
e60a6f7b 1277 sfield = build_decl (DECL_SOURCE_LOCATION (var),
1278 FIELD_DECL, DECL_NAME (t), TREE_TYPE (t));
fd6481cf 1279 DECL_ABSTRACT_ORIGIN (sfield) = DECL_ABSTRACT_ORIGIN (t);
1280 insert_field_into_struct (ctx->srecord_type, sfield);
1281 splay_tree_insert (ctx->sfield_map,
1282 (splay_tree_key) DECL_ABSTRACT_ORIGIN (t),
1283 (splay_tree_value) sfield);
1284 }
1285 }
1286 sfield = field;
1287 insert_field_into_struct ((mask & 1) ? ctx->record_type
1288 : ctx->srecord_type, field);
1289 }
1e8e9920 1290
fd6481cf 1291 if (mask & 1)
1292 splay_tree_insert (ctx->field_map, (splay_tree_key) var,
1293 (splay_tree_value) field);
1294 if ((mask & 2) && ctx->sfield_map)
1295 splay_tree_insert (ctx->sfield_map, (splay_tree_key) var,
1296 (splay_tree_value) sfield);
1e8e9920 1297}
1298
1299static tree
1300install_var_local (tree var, omp_context *ctx)
1301{
1302 tree new_var = omp_copy_decl_1 (var, ctx);
1303 insert_decl_map (&ctx->cb, var, new_var);
1304 return new_var;
1305}
1306
1307/* Adjust the replacement for DECL in CTX for the new context. This means
1308 copying the DECL_VALUE_EXPR, and fixing up the type. */
1309
1310static void
1311fixup_remapped_decl (tree decl, omp_context *ctx, bool private_debug)
1312{
1313 tree new_decl, size;
1314
1315 new_decl = lookup_decl (decl, ctx);
1316
1317 TREE_TYPE (new_decl) = remap_type (TREE_TYPE (decl), &ctx->cb);
1318
1319 if ((!TREE_CONSTANT (DECL_SIZE (new_decl)) || private_debug)
1320 && DECL_HAS_VALUE_EXPR_P (decl))
1321 {
1322 tree ve = DECL_VALUE_EXPR (decl);
75a70cf9 1323 walk_tree (&ve, copy_tree_body_r, &ctx->cb, NULL);
1e8e9920 1324 SET_DECL_VALUE_EXPR (new_decl, ve);
1325 DECL_HAS_VALUE_EXPR_P (new_decl) = 1;
1326 }
1327
1328 if (!TREE_CONSTANT (DECL_SIZE (new_decl)))
1329 {
1330 size = remap_decl (DECL_SIZE (decl), &ctx->cb);
1331 if (size == error_mark_node)
1332 size = TYPE_SIZE (TREE_TYPE (new_decl));
1333 DECL_SIZE (new_decl) = size;
1334
1335 size = remap_decl (DECL_SIZE_UNIT (decl), &ctx->cb);
1336 if (size == error_mark_node)
1337 size = TYPE_SIZE_UNIT (TREE_TYPE (new_decl));
1338 DECL_SIZE_UNIT (new_decl) = size;
1339 }
1340}
1341
1342/* The callback for remap_decl. Search all containing contexts for a
1343 mapping of the variable; this avoids having to duplicate the splay
1344 tree ahead of time. We know a mapping doesn't already exist in the
1345 given context. Create new mappings to implement default semantics. */
1346
1347static tree
1348omp_copy_decl (tree var, copy_body_data *cb)
1349{
1350 omp_context *ctx = (omp_context *) cb;
1351 tree new_var;
1352
1e8e9920 1353 if (TREE_CODE (var) == LABEL_DECL)
1354 {
e60a6f7b 1355 new_var = create_artificial_label (DECL_SOURCE_LOCATION (var));
773c5ba7 1356 DECL_CONTEXT (new_var) = current_function_decl;
1e8e9920 1357 insert_decl_map (&ctx->cb, var, new_var);
1358 return new_var;
1359 }
1360
fd6481cf 1361 while (!is_taskreg_ctx (ctx))
1e8e9920 1362 {
1363 ctx = ctx->outer;
1364 if (ctx == NULL)
1365 return var;
1366 new_var = maybe_lookup_decl (var, ctx);
1367 if (new_var)
1368 return new_var;
1369 }
1370
f49d7bb5 1371 if (is_global_var (var) || decl_function_context (var) != ctx->cb.src_fn)
1372 return var;
1373
1e8e9920 1374 return error_mark_node;
1375}
1376
773c5ba7 1377
773c5ba7 1378/* Debugging dumps for parallel regions. */
1379void dump_omp_region (FILE *, struct omp_region *, int);
1380void debug_omp_region (struct omp_region *);
1381void debug_all_omp_regions (void);
1382
1383/* Dump the parallel region tree rooted at REGION. */
1384
1385void
1386dump_omp_region (FILE *file, struct omp_region *region, int indent)
1387{
61e47ac8 1388 fprintf (file, "%*sbb %d: %s\n", indent, "", region->entry->index,
75a70cf9 1389 gimple_code_name[region->type]);
773c5ba7 1390
1391 if (region->inner)
1392 dump_omp_region (file, region->inner, indent + 4);
1393
61e47ac8 1394 if (region->cont)
1395 {
75a70cf9 1396 fprintf (file, "%*sbb %d: GIMPLE_OMP_CONTINUE\n", indent, "",
61e47ac8 1397 region->cont->index);
1398 }
48e1416a 1399
773c5ba7 1400 if (region->exit)
75a70cf9 1401 fprintf (file, "%*sbb %d: GIMPLE_OMP_RETURN\n", indent, "",
61e47ac8 1402 region->exit->index);
773c5ba7 1403 else
61e47ac8 1404 fprintf (file, "%*s[no exit marker]\n", indent, "");
773c5ba7 1405
1406 if (region->next)
61e47ac8 1407 dump_omp_region (file, region->next, indent);
773c5ba7 1408}
1409
4b987fac 1410DEBUG_FUNCTION void
773c5ba7 1411debug_omp_region (struct omp_region *region)
1412{
1413 dump_omp_region (stderr, region, 0);
1414}
1415
4b987fac 1416DEBUG_FUNCTION void
773c5ba7 1417debug_all_omp_regions (void)
1418{
1419 dump_omp_region (stderr, root_omp_region, 0);
1420}
1421
1422
1423/* Create a new parallel region starting at STMT inside region PARENT. */
1424
7740abd8 1425static struct omp_region *
75a70cf9 1426new_omp_region (basic_block bb, enum gimple_code type,
1427 struct omp_region *parent)
773c5ba7 1428{
4077bf7a 1429 struct omp_region *region = XCNEW (struct omp_region);
773c5ba7 1430
1431 region->outer = parent;
61e47ac8 1432 region->entry = bb;
1433 region->type = type;
773c5ba7 1434
1435 if (parent)
1436 {
1437 /* This is a nested region. Add it to the list of inner
1438 regions in PARENT. */
1439 region->next = parent->inner;
1440 parent->inner = region;
1441 }
61e47ac8 1442 else
773c5ba7 1443 {
1444 /* This is a toplevel region. Add it to the list of toplevel
1445 regions in ROOT_OMP_REGION. */
1446 region->next = root_omp_region;
1447 root_omp_region = region;
1448 }
61e47ac8 1449
1450 return region;
1451}
1452
1453/* Release the memory associated with the region tree rooted at REGION. */
1454
1455static void
1456free_omp_region_1 (struct omp_region *region)
1457{
1458 struct omp_region *i, *n;
1459
1460 for (i = region->inner; i ; i = n)
773c5ba7 1461 {
61e47ac8 1462 n = i->next;
1463 free_omp_region_1 (i);
773c5ba7 1464 }
1465
61e47ac8 1466 free (region);
1467}
773c5ba7 1468
61e47ac8 1469/* Release the memory for the entire omp region tree. */
1470
1471void
1472free_omp_regions (void)
1473{
1474 struct omp_region *r, *n;
1475 for (r = root_omp_region; r ; r = n)
1476 {
1477 n = r->next;
1478 free_omp_region_1 (r);
1479 }
1480 root_omp_region = NULL;
773c5ba7 1481}
1482
1483
1e8e9920 1484/* Create a new context, with OUTER_CTX being the surrounding context. */
1485
1486static omp_context *
75a70cf9 1487new_omp_context (gimple stmt, omp_context *outer_ctx)
1e8e9920 1488{
1489 omp_context *ctx = XCNEW (omp_context);
1490
1491 splay_tree_insert (all_contexts, (splay_tree_key) stmt,
1492 (splay_tree_value) ctx);
1493 ctx->stmt = stmt;
1494
1495 if (outer_ctx)
1496 {
1497 ctx->outer = outer_ctx;
1498 ctx->cb = outer_ctx->cb;
1499 ctx->cb.block = NULL;
1500 ctx->depth = outer_ctx->depth + 1;
ca4c3545 1501 ctx->reduction_map = outer_ctx->reduction_map;
1e8e9920 1502 }
1503 else
1504 {
1505 ctx->cb.src_fn = current_function_decl;
1506 ctx->cb.dst_fn = current_function_decl;
415d1b9a 1507 ctx->cb.src_node = cgraph_node::get (current_function_decl);
53f79206 1508 gcc_checking_assert (ctx->cb.src_node);
1e8e9920 1509 ctx->cb.dst_node = ctx->cb.src_node;
1510 ctx->cb.src_cfun = cfun;
1511 ctx->cb.copy_decl = omp_copy_decl;
e38def9c 1512 ctx->cb.eh_lp_nr = 0;
1e8e9920 1513 ctx->cb.transform_call_graph_edges = CB_CGE_MOVE;
1514 ctx->depth = 1;
1515 }
1516
06ecf488 1517 ctx->cb.decl_map = new hash_map<tree, tree>;
1e8e9920 1518
1519 return ctx;
1520}
1521
75a70cf9 1522static gimple_seq maybe_catch_exception (gimple_seq);
f6430caa 1523
1524/* Finalize task copyfn. */
1525
1526static void
1a91d914 1527finalize_task_copyfn (gomp_task *task_stmt)
f6430caa 1528{
1529 struct function *child_cfun;
9078126c 1530 tree child_fn;
e3a19533 1531 gimple_seq seq = NULL, new_seq;
1a91d914 1532 gbind *bind;
f6430caa 1533
75a70cf9 1534 child_fn = gimple_omp_task_copy_fn (task_stmt);
f6430caa 1535 if (child_fn == NULL_TREE)
1536 return;
1537
1538 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
82b40354 1539 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
f6430caa 1540
f6430caa 1541 push_cfun (child_cfun);
7e3aae05 1542 bind = gimplify_body (child_fn, false);
75a70cf9 1543 gimple_seq_add_stmt (&seq, bind);
1544 new_seq = maybe_catch_exception (seq);
1545 if (new_seq != seq)
1546 {
1547 bind = gimple_build_bind (NULL, new_seq, NULL);
e3a19533 1548 seq = NULL;
75a70cf9 1549 gimple_seq_add_stmt (&seq, bind);
1550 }
1551 gimple_set_body (child_fn, seq);
f6430caa 1552 pop_cfun ();
f6430caa 1553
82b40354 1554 /* Inform the callgraph about the new function. */
47300487 1555 cgraph_node *node = cgraph_node::get_create (child_fn);
1556 node->parallelized_function = 1;
415d1b9a 1557 cgraph_node::add_new_function (child_fn, false);
f6430caa 1558}
1559
1e8e9920 1560/* Destroy a omp_context data structures. Called through the splay tree
1561 value delete callback. */
1562
1563static void
1564delete_omp_context (splay_tree_value value)
1565{
1566 omp_context *ctx = (omp_context *) value;
1567
06ecf488 1568 delete ctx->cb.decl_map;
1e8e9920 1569
1570 if (ctx->field_map)
1571 splay_tree_delete (ctx->field_map);
fd6481cf 1572 if (ctx->sfield_map)
1573 splay_tree_delete (ctx->sfield_map);
42d49354 1574 /* Reduction map is copied to nested contexts, so only delete it in the
1575 owner. */
ca4c3545 1576 if (ctx->reduction_map
42d49354 1577 && gimple_code (ctx->stmt) == GIMPLE_OMP_TARGET
1578 && is_gimple_omp_offloaded (ctx->stmt)
1579 && is_gimple_omp_oacc (ctx->stmt))
ca4c3545 1580 splay_tree_delete (ctx->reduction_map);
1e8e9920 1581
1582 /* We hijacked DECL_ABSTRACT_ORIGIN earlier. We need to clear it before
1583 it produces corrupt debug information. */
1584 if (ctx->record_type)
1585 {
1586 tree t;
1767a056 1587 for (t = TYPE_FIELDS (ctx->record_type); t ; t = DECL_CHAIN (t))
1e8e9920 1588 DECL_ABSTRACT_ORIGIN (t) = NULL;
1589 }
fd6481cf 1590 if (ctx->srecord_type)
1591 {
1592 tree t;
1767a056 1593 for (t = TYPE_FIELDS (ctx->srecord_type); t ; t = DECL_CHAIN (t))
fd6481cf 1594 DECL_ABSTRACT_ORIGIN (t) = NULL;
1595 }
1e8e9920 1596
f6430caa 1597 if (is_task_ctx (ctx))
1a91d914 1598 finalize_task_copyfn (as_a <gomp_task *> (ctx->stmt));
f6430caa 1599
1e8e9920 1600 XDELETE (ctx);
1601}
1602
1603/* Fix up RECEIVER_DECL with a type that has been remapped to the child
1604 context. */
1605
1606static void
1607fixup_child_record_type (omp_context *ctx)
1608{
1609 tree f, type = ctx->record_type;
1610
1611 /* ??? It isn't sufficient to just call remap_type here, because
1612 variably_modified_type_p doesn't work the way we expect for
1613 record types. Testing each field for whether it needs remapping
1614 and creating a new record by hand works, however. */
1767a056 1615 for (f = TYPE_FIELDS (type); f ; f = DECL_CHAIN (f))
1e8e9920 1616 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
1617 break;
1618 if (f)
1619 {
1620 tree name, new_fields = NULL;
1621
1622 type = lang_hooks.types.make_type (RECORD_TYPE);
1623 name = DECL_NAME (TYPE_NAME (ctx->record_type));
e60a6f7b 1624 name = build_decl (DECL_SOURCE_LOCATION (ctx->receiver_decl),
1625 TYPE_DECL, name, type);
1e8e9920 1626 TYPE_NAME (type) = name;
1627
1767a056 1628 for (f = TYPE_FIELDS (ctx->record_type); f ; f = DECL_CHAIN (f))
1e8e9920 1629 {
1630 tree new_f = copy_node (f);
1631 DECL_CONTEXT (new_f) = type;
1632 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &ctx->cb);
1767a056 1633 DECL_CHAIN (new_f) = new_fields;
75a70cf9 1634 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &ctx->cb, NULL);
1635 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r,
1636 &ctx->cb, NULL);
1637 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
1638 &ctx->cb, NULL);
1e8e9920 1639 new_fields = new_f;
1640
1641 /* Arrange to be able to look up the receiver field
1642 given the sender field. */
1643 splay_tree_insert (ctx->field_map, (splay_tree_key) f,
1644 (splay_tree_value) new_f);
1645 }
1646 TYPE_FIELDS (type) = nreverse (new_fields);
1647 layout_type (type);
1648 }
1649
5455b100 1650 TREE_TYPE (ctx->receiver_decl)
1651 = build_qualified_type (build_reference_type (type), TYPE_QUAL_RESTRICT);
1e8e9920 1652}
1653
1654/* Instantiate decls as necessary in CTX to satisfy the data sharing
1655 specified by CLAUSES. */
1656
1657static void
1658scan_sharing_clauses (tree clauses, omp_context *ctx)
1659{
1660 tree c, decl;
1661 bool scan_array_reductions = false;
1662
1663 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1664 {
1665 bool by_ref;
1666
55d6e7cd 1667 switch (OMP_CLAUSE_CODE (c))
1e8e9920 1668 {
1669 case OMP_CLAUSE_PRIVATE:
1670 decl = OMP_CLAUSE_DECL (c);
fd6481cf 1671 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
1672 goto do_private;
1673 else if (!is_variable_sized (decl))
1e8e9920 1674 install_var_local (decl, ctx);
1675 break;
1676
1677 case OMP_CLAUSE_SHARED:
5fddcf34 1678 decl = OMP_CLAUSE_DECL (c);
bc7bff74 1679 /* Ignore shared directives in teams construct. */
1680 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
5fddcf34 1681 {
1682 /* Global variables don't need to be copied,
1683 the receiver side will use them directly. */
1684 tree odecl = maybe_lookup_decl_in_outer_ctx (decl, ctx);
1685 if (is_global_var (odecl))
1686 break;
1687 insert_decl_map (&ctx->cb, decl, odecl);
1688 break;
1689 }
fd6481cf 1690 gcc_assert (is_taskreg_ctx (ctx));
e7327393 1691 gcc_assert (!COMPLETE_TYPE_P (TREE_TYPE (decl))
1692 || !is_variable_sized (decl));
f49d7bb5 1693 /* Global variables don't need to be copied,
1694 the receiver side will use them directly. */
1695 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1696 break;
fd6481cf 1697 by_ref = use_pointer_for_field (decl, ctx);
1e8e9920 1698 if (! TREE_READONLY (decl)
1699 || TREE_ADDRESSABLE (decl)
1700 || by_ref
1701 || is_reference (decl))
1702 {
fd6481cf 1703 install_var_field (decl, by_ref, 3, ctx);
1e8e9920 1704 install_var_local (decl, ctx);
1705 break;
1706 }
1707 /* We don't need to copy const scalar vars back. */
55d6e7cd 1708 OMP_CLAUSE_SET_CODE (c, OMP_CLAUSE_FIRSTPRIVATE);
1e8e9920 1709 goto do_private;
1710
1711 case OMP_CLAUSE_LASTPRIVATE:
1712 /* Let the corresponding firstprivate clause create
1713 the variable. */
1714 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1715 break;
1716 /* FALLTHRU */
1717
1718 case OMP_CLAUSE_FIRSTPRIVATE:
ca4c3545 1719 if (is_gimple_omp_oacc (ctx->stmt))
1720 {
1721 sorry ("clause not supported yet");
1722 break;
1723 }
1724 /* FALLTHRU */
1e8e9920 1725 case OMP_CLAUSE_REDUCTION:
3d483a94 1726 case OMP_CLAUSE_LINEAR:
1e8e9920 1727 decl = OMP_CLAUSE_DECL (c);
1728 do_private:
1729 if (is_variable_sized (decl))
1e8e9920 1730 {
fd6481cf 1731 if (is_task_ctx (ctx))
1732 install_var_field (decl, false, 1, ctx);
1733 break;
1734 }
1735 else if (is_taskreg_ctx (ctx))
1736 {
1737 bool global
1738 = is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx));
e8a588af 1739 by_ref = use_pointer_for_field (decl, NULL);
fd6481cf 1740
1741 if (is_task_ctx (ctx)
1742 && (global || by_ref || is_reference (decl)))
1743 {
1744 install_var_field (decl, false, 1, ctx);
1745 if (!global)
1746 install_var_field (decl, by_ref, 2, ctx);
1747 }
1748 else if (!global)
1749 install_var_field (decl, by_ref, 3, ctx);
1e8e9920 1750 }
1751 install_var_local (decl, ctx);
ca4c3545 1752 if (is_gimple_omp_oacc (ctx->stmt)
1753 && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
1754 {
1755 /* Create a decl for the reduction array. */
1756 tree var = OMP_CLAUSE_DECL (c);
1757 tree type = get_base_type (var);
1758 tree ptype = build_pointer_type (type);
1759 tree array = create_tmp_var (ptype,
1760 oacc_get_reduction_array_id (var));
1761 omp_context *c = (ctx->field_map ? ctx : ctx->outer);
1762 install_var_field (array, true, 3, c);
1763 install_var_local (array, c);
1764
1765 /* Insert it into the current context. */
1766 splay_tree_insert (ctx->reduction_map, (splay_tree_key)
1767 oacc_get_reduction_array_id (var),
1768 (splay_tree_value) array);
1769 splay_tree_insert (ctx->reduction_map,
1770 (splay_tree_key) array,
1771 (splay_tree_value) array);
1772 }
1e8e9920 1773 break;
1774
bc7bff74 1775 case OMP_CLAUSE__LOOPTEMP_:
1776 gcc_assert (is_parallel_ctx (ctx));
1777 decl = OMP_CLAUSE_DECL (c);
1778 install_var_field (decl, false, 3, ctx);
1779 install_var_local (decl, ctx);
1780 break;
1781
1e8e9920 1782 case OMP_CLAUSE_COPYPRIVATE:
1e8e9920 1783 case OMP_CLAUSE_COPYIN:
1784 decl = OMP_CLAUSE_DECL (c);
e8a588af 1785 by_ref = use_pointer_for_field (decl, NULL);
fd6481cf 1786 install_var_field (decl, by_ref, 3, ctx);
1e8e9920 1787 break;
1788
1789 case OMP_CLAUSE_DEFAULT:
1790 ctx->default_kind = OMP_CLAUSE_DEFAULT_KIND (c);
1791 break;
1792
2169f33b 1793 case OMP_CLAUSE_FINAL:
1e8e9920 1794 case OMP_CLAUSE_IF:
1795 case OMP_CLAUSE_NUM_THREADS:
bc7bff74 1796 case OMP_CLAUSE_NUM_TEAMS:
1797 case OMP_CLAUSE_THREAD_LIMIT:
1798 case OMP_CLAUSE_DEVICE:
1e8e9920 1799 case OMP_CLAUSE_SCHEDULE:
bc7bff74 1800 case OMP_CLAUSE_DIST_SCHEDULE:
1801 case OMP_CLAUSE_DEPEND:
40750995 1802 case OMP_CLAUSE__CILK_FOR_COUNT_:
ca4c3545 1803 case OMP_CLAUSE_NUM_GANGS:
1804 case OMP_CLAUSE_NUM_WORKERS:
1805 case OMP_CLAUSE_VECTOR_LENGTH:
1e8e9920 1806 if (ctx->outer)
75a70cf9 1807 scan_omp_op (&OMP_CLAUSE_OPERAND (c, 0), ctx->outer);
1e8e9920 1808 break;
1809
bc7bff74 1810 case OMP_CLAUSE_TO:
1811 case OMP_CLAUSE_FROM:
1812 case OMP_CLAUSE_MAP:
1813 if (ctx->outer)
1814 scan_omp_op (&OMP_CLAUSE_SIZE (c), ctx->outer);
1815 decl = OMP_CLAUSE_DECL (c);
1816 /* Global variables with "omp declare target" attribute
1817 don't need to be copied, the receiver side will use them
1818 directly. */
1819 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1820 && DECL_P (decl)
1821 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
b0c5e347 1822 && varpool_node::get_create (decl)->offloadable)
bc7bff74 1823 break;
1824 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
ca4c3545 1825 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER)
bc7bff74 1826 {
ca4c3545 1827 /* Ignore GOMP_MAP_POINTER kind for arrays in regions that are
1828 not offloaded; there is nothing to map for those. */
1829 if (!is_gimple_omp_offloaded (ctx->stmt)
c1a114c2 1830 && !POINTER_TYPE_P (TREE_TYPE (decl))
1831 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
bc7bff74 1832 break;
1833 }
1834 if (DECL_P (decl))
1835 {
1836 if (DECL_SIZE (decl)
1837 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
1838 {
1839 tree decl2 = DECL_VALUE_EXPR (decl);
1840 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
1841 decl2 = TREE_OPERAND (decl2, 0);
1842 gcc_assert (DECL_P (decl2));
1843 install_var_field (decl2, true, 3, ctx);
1844 install_var_local (decl2, ctx);
1845 install_var_local (decl, ctx);
1846 }
1847 else
1848 {
1849 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
ca4c3545 1850 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
bc7bff74 1851 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
1852 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1853 install_var_field (decl, true, 7, ctx);
1854 else
1855 install_var_field (decl, true, 3, ctx);
ca4c3545 1856 if (is_gimple_omp_offloaded (ctx->stmt))
bc7bff74 1857 install_var_local (decl, ctx);
1858 }
1859 }
1860 else
1861 {
1862 tree base = get_base_address (decl);
1863 tree nc = OMP_CLAUSE_CHAIN (c);
1864 if (DECL_P (base)
1865 && nc != NULL_TREE
1866 && OMP_CLAUSE_CODE (nc) == OMP_CLAUSE_MAP
1867 && OMP_CLAUSE_DECL (nc) == base
ca4c3545 1868 && OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_POINTER
bc7bff74 1869 && integer_zerop (OMP_CLAUSE_SIZE (nc)))
1870 {
1871 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c) = 1;
1872 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (nc) = 1;
1873 }
1874 else
1875 {
691447ab 1876 if (ctx->outer)
1877 {
1878 scan_omp_op (&OMP_CLAUSE_DECL (c), ctx->outer);
1879 decl = OMP_CLAUSE_DECL (c);
1880 }
bc7bff74 1881 gcc_assert (!splay_tree_lookup (ctx->field_map,
1882 (splay_tree_key) decl));
1883 tree field
1884 = build_decl (OMP_CLAUSE_LOCATION (c),
1885 FIELD_DECL, NULL_TREE, ptr_type_node);
1886 DECL_ALIGN (field) = TYPE_ALIGN (ptr_type_node);
1887 insert_field_into_struct (ctx->record_type, field);
1888 splay_tree_insert (ctx->field_map, (splay_tree_key) decl,
1889 (splay_tree_value) field);
1890 }
1891 }
1892 break;
1893
1e8e9920 1894 case OMP_CLAUSE_NOWAIT:
1895 case OMP_CLAUSE_ORDERED:
fd6481cf 1896 case OMP_CLAUSE_COLLAPSE:
1897 case OMP_CLAUSE_UNTIED:
2169f33b 1898 case OMP_CLAUSE_MERGEABLE:
bc7bff74 1899 case OMP_CLAUSE_PROC_BIND:
3d483a94 1900 case OMP_CLAUSE_SAFELEN:
ca4c3545 1901 case OMP_CLAUSE_ASYNC:
1902 case OMP_CLAUSE_WAIT:
1903 case OMP_CLAUSE_GANG:
1904 case OMP_CLAUSE_WORKER:
1905 case OMP_CLAUSE_VECTOR:
1e8e9920 1906 break;
1907
bc7bff74 1908 case OMP_CLAUSE_ALIGNED:
1909 decl = OMP_CLAUSE_DECL (c);
1910 if (is_global_var (decl)
1911 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1912 install_var_local (decl, ctx);
1913 break;
1914
ca4c3545 1915 case OMP_CLAUSE_DEVICE_RESIDENT:
1916 case OMP_CLAUSE_USE_DEVICE:
1917 case OMP_CLAUSE__CACHE_:
1918 case OMP_CLAUSE_INDEPENDENT:
1919 case OMP_CLAUSE_AUTO:
1920 case OMP_CLAUSE_SEQ:
1921 sorry ("Clause not supported yet");
1922 break;
1923
1e8e9920 1924 default:
1925 gcc_unreachable ();
1926 }
1927 }
1928
1929 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1930 {
55d6e7cd 1931 switch (OMP_CLAUSE_CODE (c))
1e8e9920 1932 {
1933 case OMP_CLAUSE_LASTPRIVATE:
1934 /* Let the corresponding firstprivate clause create
1935 the variable. */
75a70cf9 1936 if (OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
fd6481cf 1937 scan_array_reductions = true;
1e8e9920 1938 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1939 break;
1940 /* FALLTHRU */
1941
1e8e9920 1942 case OMP_CLAUSE_FIRSTPRIVATE:
ca4c3545 1943 if (is_gimple_omp_oacc (ctx->stmt))
1944 {
1945 sorry ("clause not supported yet");
1946 break;
1947 }
1948 /* FALLTHRU */
1949 case OMP_CLAUSE_PRIVATE:
1e8e9920 1950 case OMP_CLAUSE_REDUCTION:
3d483a94 1951 case OMP_CLAUSE_LINEAR:
1e8e9920 1952 decl = OMP_CLAUSE_DECL (c);
1953 if (is_variable_sized (decl))
1954 install_var_local (decl, ctx);
1955 fixup_remapped_decl (decl, ctx,
55d6e7cd 1956 OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE
1e8e9920 1957 && OMP_CLAUSE_PRIVATE_DEBUG (c));
55d6e7cd 1958 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1e8e9920 1959 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1960 scan_array_reductions = true;
2b536a17 1961 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
1962 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
1963 scan_array_reductions = true;
1e8e9920 1964 break;
1965
1966 case OMP_CLAUSE_SHARED:
bc7bff74 1967 /* Ignore shared directives in teams construct. */
1968 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
1969 break;
1e8e9920 1970 decl = OMP_CLAUSE_DECL (c);
f49d7bb5 1971 if (! is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1972 fixup_remapped_decl (decl, ctx, false);
1e8e9920 1973 break;
1974
bc7bff74 1975 case OMP_CLAUSE_MAP:
ca4c3545 1976 if (!is_gimple_omp_offloaded (ctx->stmt))
bc7bff74 1977 break;
1978 decl = OMP_CLAUSE_DECL (c);
1979 if (DECL_P (decl)
1980 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
b0c5e347 1981 && varpool_node::get_create (decl)->offloadable)
bc7bff74 1982 break;
1983 if (DECL_P (decl))
1984 {
ca4c3545 1985 if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
bc7bff74 1986 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
1987 && !COMPLETE_TYPE_P (TREE_TYPE (decl)))
1988 {
1989 tree new_decl = lookup_decl (decl, ctx);
1990 TREE_TYPE (new_decl)
1991 = remap_type (TREE_TYPE (decl), &ctx->cb);
1992 }
1993 else if (DECL_SIZE (decl)
1994 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
1995 {
1996 tree decl2 = DECL_VALUE_EXPR (decl);
1997 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
1998 decl2 = TREE_OPERAND (decl2, 0);
1999 gcc_assert (DECL_P (decl2));
2000 fixup_remapped_decl (decl2, ctx, false);
2001 fixup_remapped_decl (decl, ctx, true);
2002 }
2003 else
2004 fixup_remapped_decl (decl, ctx, false);
2005 }
2006 break;
2007
1e8e9920 2008 case OMP_CLAUSE_COPYPRIVATE:
2009 case OMP_CLAUSE_COPYIN:
2010 case OMP_CLAUSE_DEFAULT:
2011 case OMP_CLAUSE_IF:
2012 case OMP_CLAUSE_NUM_THREADS:
bc7bff74 2013 case OMP_CLAUSE_NUM_TEAMS:
2014 case OMP_CLAUSE_THREAD_LIMIT:
2015 case OMP_CLAUSE_DEVICE:
1e8e9920 2016 case OMP_CLAUSE_SCHEDULE:
bc7bff74 2017 case OMP_CLAUSE_DIST_SCHEDULE:
1e8e9920 2018 case OMP_CLAUSE_NOWAIT:
2019 case OMP_CLAUSE_ORDERED:
fd6481cf 2020 case OMP_CLAUSE_COLLAPSE:
2021 case OMP_CLAUSE_UNTIED:
2169f33b 2022 case OMP_CLAUSE_FINAL:
2023 case OMP_CLAUSE_MERGEABLE:
bc7bff74 2024 case OMP_CLAUSE_PROC_BIND:
3d483a94 2025 case OMP_CLAUSE_SAFELEN:
bc7bff74 2026 case OMP_CLAUSE_ALIGNED:
2027 case OMP_CLAUSE_DEPEND:
2028 case OMP_CLAUSE__LOOPTEMP_:
2029 case OMP_CLAUSE_TO:
2030 case OMP_CLAUSE_FROM:
40750995 2031 case OMP_CLAUSE__CILK_FOR_COUNT_:
ca4c3545 2032 case OMP_CLAUSE_ASYNC:
2033 case OMP_CLAUSE_WAIT:
2034 case OMP_CLAUSE_NUM_GANGS:
2035 case OMP_CLAUSE_NUM_WORKERS:
2036 case OMP_CLAUSE_VECTOR_LENGTH:
2037 case OMP_CLAUSE_GANG:
2038 case OMP_CLAUSE_WORKER:
2039 case OMP_CLAUSE_VECTOR:
2040 break;
2041
2042 case OMP_CLAUSE_DEVICE_RESIDENT:
2043 case OMP_CLAUSE_USE_DEVICE:
2044 case OMP_CLAUSE__CACHE_:
2045 case OMP_CLAUSE_INDEPENDENT:
2046 case OMP_CLAUSE_AUTO:
2047 case OMP_CLAUSE_SEQ:
2048 sorry ("Clause not supported yet");
1e8e9920 2049 break;
2050
2051 default:
2052 gcc_unreachable ();
2053 }
2054 }
2055
ca4c3545 2056 gcc_checking_assert (!scan_array_reductions
2057 || !is_gimple_omp_oacc (ctx->stmt));
1e8e9920 2058 if (scan_array_reductions)
2059 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
55d6e7cd 2060 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1e8e9920 2061 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
2062 {
ab129075 2063 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c), ctx);
2064 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
1e8e9920 2065 }
fd6481cf 2066 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
75a70cf9 2067 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
ab129075 2068 scan_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
2b536a17 2069 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
2070 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
2071 scan_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
1e8e9920 2072}
2073
40750995 2074/* Create a new name for omp child function. Returns an identifier. If
2075 IS_CILK_FOR is true then the suffix for the child function is
2076 "_cilk_for_fn." */
1e8e9920 2077
1e8e9920 2078static tree
40750995 2079create_omp_child_function_name (bool task_copy, bool is_cilk_for)
1e8e9920 2080{
40750995 2081 if (is_cilk_for)
2082 return clone_function_name (current_function_decl, "_cilk_for_fn");
2083 return clone_function_name (current_function_decl,
2084 task_copy ? "_omp_cpyfn" : "_omp_fn");
2085}
2086
2087/* Returns the type of the induction variable for the child function for
2088 _Cilk_for and the types for _high and _low variables based on TYPE. */
2089
2090static tree
2091cilk_for_check_loop_diff_type (tree type)
2092{
2093 if (TYPE_PRECISION (type) <= TYPE_PRECISION (uint32_type_node))
2094 {
2095 if (TYPE_UNSIGNED (type))
2096 return uint32_type_node;
2097 else
2098 return integer_type_node;
2099 }
2100 else
2101 {
2102 if (TYPE_UNSIGNED (type))
2103 return uint64_type_node;
2104 else
2105 return long_long_integer_type_node;
2106 }
1e8e9920 2107}
2108
2109/* Build a decl for the omp child function. It'll not contain a body
2110 yet, just the bare decl. */
2111
2112static void
fd6481cf 2113create_omp_child_function (omp_context *ctx, bool task_copy)
1e8e9920 2114{
2115 tree decl, type, name, t;
2116
40750995 2117 tree cilk_for_count
2118 = (flag_cilkplus && gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL)
2119 ? find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
2120 OMP_CLAUSE__CILK_FOR_COUNT_) : NULL_TREE;
2121 tree cilk_var_type = NULL_TREE;
2122
2123 name = create_omp_child_function_name (task_copy,
2124 cilk_for_count != NULL_TREE);
fd6481cf 2125 if (task_copy)
2126 type = build_function_type_list (void_type_node, ptr_type_node,
2127 ptr_type_node, NULL_TREE);
40750995 2128 else if (cilk_for_count)
2129 {
2130 type = TREE_TYPE (OMP_CLAUSE_OPERAND (cilk_for_count, 0));
2131 cilk_var_type = cilk_for_check_loop_diff_type (type);
2132 type = build_function_type_list (void_type_node, ptr_type_node,
2133 cilk_var_type, cilk_var_type, NULL_TREE);
2134 }
fd6481cf 2135 else
2136 type = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
1e8e9920 2137
40750995 2138 decl = build_decl (gimple_location (ctx->stmt), FUNCTION_DECL, name, type);
1e8e9920 2139
ca4c3545 2140 gcc_checking_assert (!is_gimple_omp_oacc (ctx->stmt)
2141 || !task_copy);
fd6481cf 2142 if (!task_copy)
2143 ctx->cb.dst_fn = decl;
2144 else
75a70cf9 2145 gimple_omp_task_set_copy_fn (ctx->stmt, decl);
1e8e9920 2146
2147 TREE_STATIC (decl) = 1;
2148 TREE_USED (decl) = 1;
2149 DECL_ARTIFICIAL (decl) = 1;
2150 DECL_IGNORED_P (decl) = 0;
2151 TREE_PUBLIC (decl) = 0;
2152 DECL_UNINLINABLE (decl) = 1;
2153 DECL_EXTERNAL (decl) = 0;
2154 DECL_CONTEXT (decl) = NULL_TREE;
773c5ba7 2155 DECL_INITIAL (decl) = make_node (BLOCK);
b0c5e347 2156 if (cgraph_node::get (current_function_decl)->offloadable)
2157 cgraph_node::get_create (decl)->offloadable = 1;
bc7bff74 2158 else
2159 {
2160 omp_context *octx;
2161 for (octx = ctx; octx; octx = octx->outer)
ca4c3545 2162 if (is_gimple_omp_offloaded (octx->stmt))
bc7bff74 2163 {
b0c5e347 2164 cgraph_node::get_create (decl)->offloadable = 1;
7114ebdd 2165#ifdef ENABLE_OFFLOADING
b0c5e347 2166 g->have_offload = true;
7114ebdd 2167#endif
bc7bff74 2168 break;
2169 }
2170 }
1e8e9920 2171
ec12b31a 2172 if (cgraph_node::get_create (decl)->offloadable
2173 && !lookup_attribute ("omp declare target",
2174 DECL_ATTRIBUTES (current_function_decl)))
2175 DECL_ATTRIBUTES (decl)
2176 = tree_cons (get_identifier ("omp target entrypoint"),
2177 NULL_TREE, DECL_ATTRIBUTES (decl));
2178
e60a6f7b 2179 t = build_decl (DECL_SOURCE_LOCATION (decl),
2180 RESULT_DECL, NULL_TREE, void_type_node);
1e8e9920 2181 DECL_ARTIFICIAL (t) = 1;
2182 DECL_IGNORED_P (t) = 1;
8e5b4ed6 2183 DECL_CONTEXT (t) = decl;
1e8e9920 2184 DECL_RESULT (decl) = t;
2185
40750995 2186 /* _Cilk_for's child function requires two extra parameters called
2187 __low and __high that are set the by Cilk runtime when it calls this
2188 function. */
2189 if (cilk_for_count)
2190 {
2191 t = build_decl (DECL_SOURCE_LOCATION (decl),
2192 PARM_DECL, get_identifier ("__high"), cilk_var_type);
2193 DECL_ARTIFICIAL (t) = 1;
2194 DECL_NAMELESS (t) = 1;
2195 DECL_ARG_TYPE (t) = ptr_type_node;
2196 DECL_CONTEXT (t) = current_function_decl;
2197 TREE_USED (t) = 1;
2198 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2199 DECL_ARGUMENTS (decl) = t;
2200
2201 t = build_decl (DECL_SOURCE_LOCATION (decl),
2202 PARM_DECL, get_identifier ("__low"), cilk_var_type);
2203 DECL_ARTIFICIAL (t) = 1;
2204 DECL_NAMELESS (t) = 1;
2205 DECL_ARG_TYPE (t) = ptr_type_node;
2206 DECL_CONTEXT (t) = current_function_decl;
2207 TREE_USED (t) = 1;
2208 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2209 DECL_ARGUMENTS (decl) = t;
2210 }
2211
2212 tree data_name = get_identifier (".omp_data_i");
2213 t = build_decl (DECL_SOURCE_LOCATION (decl), PARM_DECL, data_name,
2214 ptr_type_node);
1e8e9920 2215 DECL_ARTIFICIAL (t) = 1;
84bfaaeb 2216 DECL_NAMELESS (t) = 1;
1e8e9920 2217 DECL_ARG_TYPE (t) = ptr_type_node;
773c5ba7 2218 DECL_CONTEXT (t) = current_function_decl;
1e8e9920 2219 TREE_USED (t) = 1;
40750995 2220 if (cilk_for_count)
2221 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
1e8e9920 2222 DECL_ARGUMENTS (decl) = t;
fd6481cf 2223 if (!task_copy)
2224 ctx->receiver_decl = t;
2225 else
2226 {
e60a6f7b 2227 t = build_decl (DECL_SOURCE_LOCATION (decl),
2228 PARM_DECL, get_identifier (".omp_data_o"),
fd6481cf 2229 ptr_type_node);
2230 DECL_ARTIFICIAL (t) = 1;
84bfaaeb 2231 DECL_NAMELESS (t) = 1;
fd6481cf 2232 DECL_ARG_TYPE (t) = ptr_type_node;
2233 DECL_CONTEXT (t) = current_function_decl;
2234 TREE_USED (t) = 1;
86f2ad37 2235 TREE_ADDRESSABLE (t) = 1;
1767a056 2236 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
fd6481cf 2237 DECL_ARGUMENTS (decl) = t;
2238 }
1e8e9920 2239
48e1416a 2240 /* Allocate memory for the function structure. The call to
773c5ba7 2241 allocate_struct_function clobbers CFUN, so we need to restore
1e8e9920 2242 it afterward. */
87d4aa85 2243 push_struct_function (decl);
75a70cf9 2244 cfun->function_end_locus = gimple_location (ctx->stmt);
87d4aa85 2245 pop_cfun ();
1e8e9920 2246}
2247
bc7bff74 2248/* Callback for walk_gimple_seq. Check if combined parallel
2249 contains gimple_omp_for_combined_into_p OMP_FOR. */
2250
2251static tree
2252find_combined_for (gimple_stmt_iterator *gsi_p,
2253 bool *handled_ops_p,
2254 struct walk_stmt_info *wi)
2255{
2256 gimple stmt = gsi_stmt (*gsi_p);
2257
2258 *handled_ops_p = true;
2259 switch (gimple_code (stmt))
2260 {
2261 WALK_SUBSTMTS;
2262
2263 case GIMPLE_OMP_FOR:
2264 if (gimple_omp_for_combined_into_p (stmt)
2265 && gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR)
2266 {
2267 wi->info = stmt;
2268 return integer_zero_node;
2269 }
2270 break;
2271 default:
2272 break;
2273 }
2274 return NULL;
2275}
2276
1e8e9920 2277/* Scan an OpenMP parallel directive. */
2278
2279static void
75a70cf9 2280scan_omp_parallel (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
1e8e9920 2281{
2282 omp_context *ctx;
2283 tree name;
1a91d914 2284 gomp_parallel *stmt = as_a <gomp_parallel *> (gsi_stmt (*gsi));
1e8e9920 2285
2286 /* Ignore parallel directives with empty bodies, unless there
2287 are copyin clauses. */
2288 if (optimize > 0
75a70cf9 2289 && empty_body_p (gimple_omp_body (stmt))
2290 && find_omp_clause (gimple_omp_parallel_clauses (stmt),
2291 OMP_CLAUSE_COPYIN) == NULL)
1e8e9920 2292 {
75a70cf9 2293 gsi_replace (gsi, gimple_build_nop (), false);
1e8e9920 2294 return;
2295 }
2296
bc7bff74 2297 if (gimple_omp_parallel_combined_p (stmt))
2298 {
bc7bff74 2299 struct walk_stmt_info wi;
2300
2301 memset (&wi, 0, sizeof (wi));
2302 wi.val_only = true;
2303 walk_gimple_seq (gimple_omp_body (stmt),
2304 find_combined_for, NULL, &wi);
1a91d914 2305 if (wi.info)
bc7bff74 2306 {
1a91d914 2307 gomp_for *for_stmt = as_a <gomp_for *> ((gimple) wi.info);
bc7bff74 2308 struct omp_for_data fd;
2309 extract_omp_for_data (for_stmt, &fd, NULL);
2310 /* We need two temporaries with fd.loop.v type (istart/iend)
2311 and then (fd.collapse - 1) temporaries with the same
2312 type for count2 ... countN-1 vars if not constant. */
2313 size_t count = 2, i;
2314 tree type = fd.iter_type;
2315 if (fd.collapse > 1
2316 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
2317 count += fd.collapse - 1;
2318 for (i = 0; i < count; i++)
2319 {
f9e245b2 2320 tree temp = create_tmp_var (type);
bc7bff74 2321 tree c = build_omp_clause (UNKNOWN_LOCATION,
2322 OMP_CLAUSE__LOOPTEMP_);
691447ab 2323 insert_decl_map (&outer_ctx->cb, temp, temp);
bc7bff74 2324 OMP_CLAUSE_DECL (c) = temp;
2325 OMP_CLAUSE_CHAIN (c) = gimple_omp_parallel_clauses (stmt);
2326 gimple_omp_parallel_set_clauses (stmt, c);
2327 }
2328 }
2329 }
2330
75a70cf9 2331 ctx = new_omp_context (stmt, outer_ctx);
37eaded9 2332 taskreg_contexts.safe_push (ctx);
fd6481cf 2333 if (taskreg_nesting_level > 1)
773c5ba7 2334 ctx->is_nested = true;
1e8e9920 2335 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
1e8e9920 2336 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2337 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
1e8e9920 2338 name = create_tmp_var_name (".omp_data_s");
e60a6f7b 2339 name = build_decl (gimple_location (stmt),
2340 TYPE_DECL, name, ctx->record_type);
84bfaaeb 2341 DECL_ARTIFICIAL (name) = 1;
2342 DECL_NAMELESS (name) = 1;
1e8e9920 2343 TYPE_NAME (ctx->record_type) = name;
240131b5 2344 TYPE_ARTIFICIAL (ctx->record_type) = 1;
fd6481cf 2345 create_omp_child_function (ctx, false);
75a70cf9 2346 gimple_omp_parallel_set_child_fn (stmt, ctx->cb.dst_fn);
1e8e9920 2347
75a70cf9 2348 scan_sharing_clauses (gimple_omp_parallel_clauses (stmt), ctx);
ab129075 2349 scan_omp (gimple_omp_body_ptr (stmt), ctx);
1e8e9920 2350
2351 if (TYPE_FIELDS (ctx->record_type) == NULL)
2352 ctx->record_type = ctx->receiver_decl = NULL;
1e8e9920 2353}
2354
fd6481cf 2355/* Scan an OpenMP task directive. */
2356
2357static void
75a70cf9 2358scan_omp_task (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
fd6481cf 2359{
2360 omp_context *ctx;
75a70cf9 2361 tree name, t;
1a91d914 2362 gomp_task *stmt = as_a <gomp_task *> (gsi_stmt (*gsi));
fd6481cf 2363
2364 /* Ignore task directives with empty bodies. */
2365 if (optimize > 0
75a70cf9 2366 && empty_body_p (gimple_omp_body (stmt)))
fd6481cf 2367 {
75a70cf9 2368 gsi_replace (gsi, gimple_build_nop (), false);
fd6481cf 2369 return;
2370 }
2371
75a70cf9 2372 ctx = new_omp_context (stmt, outer_ctx);
37eaded9 2373 taskreg_contexts.safe_push (ctx);
fd6481cf 2374 if (taskreg_nesting_level > 1)
2375 ctx->is_nested = true;
2376 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2377 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2378 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2379 name = create_tmp_var_name (".omp_data_s");
e60a6f7b 2380 name = build_decl (gimple_location (stmt),
2381 TYPE_DECL, name, ctx->record_type);
84bfaaeb 2382 DECL_ARTIFICIAL (name) = 1;
2383 DECL_NAMELESS (name) = 1;
fd6481cf 2384 TYPE_NAME (ctx->record_type) = name;
240131b5 2385 TYPE_ARTIFICIAL (ctx->record_type) = 1;
fd6481cf 2386 create_omp_child_function (ctx, false);
75a70cf9 2387 gimple_omp_task_set_child_fn (stmt, ctx->cb.dst_fn);
fd6481cf 2388
75a70cf9 2389 scan_sharing_clauses (gimple_omp_task_clauses (stmt), ctx);
fd6481cf 2390
2391 if (ctx->srecord_type)
2392 {
2393 name = create_tmp_var_name (".omp_data_a");
e60a6f7b 2394 name = build_decl (gimple_location (stmt),
2395 TYPE_DECL, name, ctx->srecord_type);
84bfaaeb 2396 DECL_ARTIFICIAL (name) = 1;
2397 DECL_NAMELESS (name) = 1;
fd6481cf 2398 TYPE_NAME (ctx->srecord_type) = name;
240131b5 2399 TYPE_ARTIFICIAL (ctx->srecord_type) = 1;
fd6481cf 2400 create_omp_child_function (ctx, true);
2401 }
2402
ab129075 2403 scan_omp (gimple_omp_body_ptr (stmt), ctx);
fd6481cf 2404
2405 if (TYPE_FIELDS (ctx->record_type) == NULL)
2406 {
2407 ctx->record_type = ctx->receiver_decl = NULL;
75a70cf9 2408 t = build_int_cst (long_integer_type_node, 0);
2409 gimple_omp_task_set_arg_size (stmt, t);
2410 t = build_int_cst (long_integer_type_node, 1);
2411 gimple_omp_task_set_arg_align (stmt, t);
fd6481cf 2412 }
37eaded9 2413}
2414
2415
2416/* If any decls have been made addressable during scan_omp,
2417 adjust their fields if needed, and layout record types
2418 of parallel/task constructs. */
2419
2420static void
2421finish_taskreg_scan (omp_context *ctx)
2422{
2423 if (ctx->record_type == NULL_TREE)
2424 return;
2425
2426 /* If any task_shared_vars were needed, verify all
2427 OMP_CLAUSE_SHARED clauses on GIMPLE_OMP_{PARALLEL,TASK}
2428 statements if use_pointer_for_field hasn't changed
2429 because of that. If it did, update field types now. */
2430 if (task_shared_vars)
2431 {
2432 tree c;
2433
2434 for (c = gimple_omp_taskreg_clauses (ctx->stmt);
2435 c; c = OMP_CLAUSE_CHAIN (c))
2436 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED)
2437 {
2438 tree decl = OMP_CLAUSE_DECL (c);
2439
2440 /* Global variables don't need to be copied,
2441 the receiver side will use them directly. */
2442 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
2443 continue;
2444 if (!bitmap_bit_p (task_shared_vars, DECL_UID (decl))
2445 || !use_pointer_for_field (decl, ctx))
2446 continue;
2447 tree field = lookup_field (decl, ctx);
2448 if (TREE_CODE (TREE_TYPE (field)) == POINTER_TYPE
2449 && TREE_TYPE (TREE_TYPE (field)) == TREE_TYPE (decl))
2450 continue;
2451 TREE_TYPE (field) = build_pointer_type (TREE_TYPE (decl));
2452 TREE_THIS_VOLATILE (field) = 0;
2453 DECL_USER_ALIGN (field) = 0;
2454 DECL_ALIGN (field) = TYPE_ALIGN (TREE_TYPE (field));
2455 if (TYPE_ALIGN (ctx->record_type) < DECL_ALIGN (field))
2456 TYPE_ALIGN (ctx->record_type) = DECL_ALIGN (field);
2457 if (ctx->srecord_type)
2458 {
2459 tree sfield = lookup_sfield (decl, ctx);
2460 TREE_TYPE (sfield) = TREE_TYPE (field);
2461 TREE_THIS_VOLATILE (sfield) = 0;
2462 DECL_USER_ALIGN (sfield) = 0;
2463 DECL_ALIGN (sfield) = DECL_ALIGN (field);
2464 if (TYPE_ALIGN (ctx->srecord_type) < DECL_ALIGN (sfield))
2465 TYPE_ALIGN (ctx->srecord_type) = DECL_ALIGN (sfield);
2466 }
2467 }
2468 }
2469
2470 if (gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL)
2471 {
2472 layout_type (ctx->record_type);
2473 fixup_child_record_type (ctx);
2474 }
fd6481cf 2475 else
2476 {
37eaded9 2477 location_t loc = gimple_location (ctx->stmt);
fd6481cf 2478 tree *p, vla_fields = NULL_TREE, *q = &vla_fields;
2479 /* Move VLA fields to the end. */
2480 p = &TYPE_FIELDS (ctx->record_type);
2481 while (*p)
2482 if (!TYPE_SIZE_UNIT (TREE_TYPE (*p))
2483 || ! TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (*p))))
2484 {
2485 *q = *p;
2486 *p = TREE_CHAIN (*p);
2487 TREE_CHAIN (*q) = NULL_TREE;
2488 q = &TREE_CHAIN (*q);
2489 }
2490 else
1767a056 2491 p = &DECL_CHAIN (*p);
fd6481cf 2492 *p = vla_fields;
2493 layout_type (ctx->record_type);
2494 fixup_child_record_type (ctx);
2495 if (ctx->srecord_type)
2496 layout_type (ctx->srecord_type);
37eaded9 2497 tree t = fold_convert_loc (loc, long_integer_type_node,
2498 TYPE_SIZE_UNIT (ctx->record_type));
2499 gimple_omp_task_set_arg_size (ctx->stmt, t);
75a70cf9 2500 t = build_int_cst (long_integer_type_node,
fd6481cf 2501 TYPE_ALIGN_UNIT (ctx->record_type));
37eaded9 2502 gimple_omp_task_set_arg_align (ctx->stmt, t);
fd6481cf 2503 }
2504}
2505
1e8e9920 2506
ca4c3545 2507static omp_context *
2508enclosing_target_ctx (omp_context *ctx)
2509{
2510 while (ctx != NULL
2511 && gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET)
2512 ctx = ctx->outer;
2513 gcc_assert (ctx != NULL);
2514 return ctx;
2515}
2516
2517static bool
2518oacc_loop_or_target_p (gimple stmt)
2519{
2520 enum gimple_code outer_type = gimple_code (stmt);
2521 return ((outer_type == GIMPLE_OMP_TARGET
2522 && ((gimple_omp_target_kind (stmt)
2523 == GF_OMP_TARGET_KIND_OACC_PARALLEL)
2524 || (gimple_omp_target_kind (stmt)
2525 == GF_OMP_TARGET_KIND_OACC_KERNELS)))
2526 || (outer_type == GIMPLE_OMP_FOR
2527 && gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_OACC_LOOP));
2528}
2529
2530/* Scan a GIMPLE_OMP_FOR. */
1e8e9920 2531
2532static void
1a91d914 2533scan_omp_for (gomp_for *stmt, omp_context *outer_ctx)
1e8e9920 2534{
ca4c3545 2535 enum gimple_code outer_type = GIMPLE_ERROR_MARK;
773c5ba7 2536 omp_context *ctx;
75a70cf9 2537 size_t i;
ca4c3545 2538 tree clauses = gimple_omp_for_clauses (stmt);
2539
2540 if (outer_ctx)
2541 outer_type = gimple_code (outer_ctx->stmt);
1e8e9920 2542
773c5ba7 2543 ctx = new_omp_context (stmt, outer_ctx);
1e8e9920 2544
ca4c3545 2545 if (is_gimple_omp_oacc (stmt))
2546 {
2547 if (outer_ctx && outer_type == GIMPLE_OMP_FOR)
2548 ctx->gwv_this = outer_ctx->gwv_this;
2549 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
2550 {
2551 int val;
2552 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_GANG)
2553 val = MASK_GANG;
2554 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_WORKER)
2555 val = MASK_WORKER;
2556 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_VECTOR)
2557 val = MASK_VECTOR;
2558 else
2559 continue;
2560 ctx->gwv_this |= val;
2561 if (!outer_ctx)
2562 {
2563 /* Skip; not nested inside a region. */
2564 continue;
2565 }
2566 if (!oacc_loop_or_target_p (outer_ctx->stmt))
2567 {
2568 /* Skip; not nested inside an OpenACC region. */
2569 continue;
2570 }
2571 if (outer_type == GIMPLE_OMP_FOR)
2572 outer_ctx->gwv_below |= val;
2573 if (OMP_CLAUSE_OPERAND (c, 0) != NULL_TREE)
2574 {
2575 omp_context *enclosing = enclosing_target_ctx (outer_ctx);
2576 if (gimple_omp_target_kind (enclosing->stmt)
2577 == GF_OMP_TARGET_KIND_OACC_PARALLEL)
2578 error_at (gimple_location (stmt),
2579 "no arguments allowed to gang, worker and vector clauses inside parallel");
2580 }
2581 }
2582 }
2583
2584 scan_sharing_clauses (clauses, ctx);
1e8e9920 2585
ab129075 2586 scan_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
75a70cf9 2587 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
fd6481cf 2588 {
75a70cf9 2589 scan_omp_op (gimple_omp_for_index_ptr (stmt, i), ctx);
2590 scan_omp_op (gimple_omp_for_initial_ptr (stmt, i), ctx);
2591 scan_omp_op (gimple_omp_for_final_ptr (stmt, i), ctx);
2592 scan_omp_op (gimple_omp_for_incr_ptr (stmt, i), ctx);
fd6481cf 2593 }
ab129075 2594 scan_omp (gimple_omp_body_ptr (stmt), ctx);
ca4c3545 2595
2596 if (is_gimple_omp_oacc (stmt))
2597 {
2598 if (ctx->gwv_this & ctx->gwv_below)
2599 error_at (gimple_location (stmt),
2600 "gang, worker and vector may occur only once in a loop nest");
2601 else if (ctx->gwv_below != 0
2602 && ctx->gwv_this > ctx->gwv_below)
2603 error_at (gimple_location (stmt),
2604 "gang, worker and vector must occur in this order in a loop nest");
2605 if (outer_ctx && outer_type == GIMPLE_OMP_FOR)
2606 outer_ctx->gwv_below |= ctx->gwv_below;
2607 }
1e8e9920 2608}
2609
2610/* Scan an OpenMP sections directive. */
2611
2612static void
1a91d914 2613scan_omp_sections (gomp_sections *stmt, omp_context *outer_ctx)
1e8e9920 2614{
1e8e9920 2615 omp_context *ctx;
2616
2617 ctx = new_omp_context (stmt, outer_ctx);
75a70cf9 2618 scan_sharing_clauses (gimple_omp_sections_clauses (stmt), ctx);
ab129075 2619 scan_omp (gimple_omp_body_ptr (stmt), ctx);
1e8e9920 2620}
2621
2622/* Scan an OpenMP single directive. */
2623
2624static void
1a91d914 2625scan_omp_single (gomp_single *stmt, omp_context *outer_ctx)
1e8e9920 2626{
1e8e9920 2627 omp_context *ctx;
2628 tree name;
2629
2630 ctx = new_omp_context (stmt, outer_ctx);
2631 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2632 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2633 name = create_tmp_var_name (".omp_copy_s");
e60a6f7b 2634 name = build_decl (gimple_location (stmt),
2635 TYPE_DECL, name, ctx->record_type);
1e8e9920 2636 TYPE_NAME (ctx->record_type) = name;
2637
75a70cf9 2638 scan_sharing_clauses (gimple_omp_single_clauses (stmt), ctx);
ab129075 2639 scan_omp (gimple_omp_body_ptr (stmt), ctx);
1e8e9920 2640
2641 if (TYPE_FIELDS (ctx->record_type) == NULL)
2642 ctx->record_type = NULL;
2643 else
2644 layout_type (ctx->record_type);
2645}
2646
ca4c3545 2647/* Scan a GIMPLE_OMP_TARGET. */
bc7bff74 2648
2649static void
1a91d914 2650scan_omp_target (gomp_target *stmt, omp_context *outer_ctx)
bc7bff74 2651{
2652 omp_context *ctx;
2653 tree name;
ca4c3545 2654 bool offloaded = is_gimple_omp_offloaded (stmt);
2655 tree clauses = gimple_omp_target_clauses (stmt);
bc7bff74 2656
2657 ctx = new_omp_context (stmt, outer_ctx);
2658 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2659 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2660 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2661 name = create_tmp_var_name (".omp_data_t");
2662 name = build_decl (gimple_location (stmt),
2663 TYPE_DECL, name, ctx->record_type);
2664 DECL_ARTIFICIAL (name) = 1;
2665 DECL_NAMELESS (name) = 1;
2666 TYPE_NAME (ctx->record_type) = name;
240131b5 2667 TYPE_ARTIFICIAL (ctx->record_type) = 1;
ca4c3545 2668 if (offloaded)
bc7bff74 2669 {
ca4c3545 2670 if (is_gimple_omp_oacc (stmt))
2671 ctx->reduction_map = splay_tree_new (splay_tree_compare_pointers,
2672 0, 0);
2673
bc7bff74 2674 create_omp_child_function (ctx, false);
2675 gimple_omp_target_set_child_fn (stmt, ctx->cb.dst_fn);
2676 }
2677
ca4c3545 2678 if (is_gimple_omp_oacc (stmt))
2679 {
2680 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
2681 {
2682 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_NUM_GANGS)
2683 ctx->gwv_this |= MASK_GANG;
2684 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_NUM_WORKERS)
2685 ctx->gwv_this |= MASK_WORKER;
2686 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_VECTOR_LENGTH)
2687 ctx->gwv_this |= MASK_VECTOR;
2688 }
2689 }
2690
2691 scan_sharing_clauses (clauses, ctx);
bc7bff74 2692 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2693
2694 if (TYPE_FIELDS (ctx->record_type) == NULL)
2695 ctx->record_type = ctx->receiver_decl = NULL;
2696 else
2697 {
2698 TYPE_FIELDS (ctx->record_type)
2699 = nreverse (TYPE_FIELDS (ctx->record_type));
2700#ifdef ENABLE_CHECKING
2701 tree field;
2702 unsigned int align = DECL_ALIGN (TYPE_FIELDS (ctx->record_type));
2703 for (field = TYPE_FIELDS (ctx->record_type);
2704 field;
2705 field = DECL_CHAIN (field))
2706 gcc_assert (DECL_ALIGN (field) == align);
2707#endif
2708 layout_type (ctx->record_type);
ca4c3545 2709 if (offloaded)
bc7bff74 2710 fixup_child_record_type (ctx);
2711 }
2712}
2713
2714/* Scan an OpenMP teams directive. */
2715
2716static void
1a91d914 2717scan_omp_teams (gomp_teams *stmt, omp_context *outer_ctx)
bc7bff74 2718{
2719 omp_context *ctx = new_omp_context (stmt, outer_ctx);
2720 scan_sharing_clauses (gimple_omp_teams_clauses (stmt), ctx);
2721 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2722}
1e8e9920 2723
ca4c3545 2724/* Check nesting restrictions. */
ab129075 2725static bool
2726check_omp_nesting_restrictions (gimple stmt, omp_context *ctx)
c1d127dd 2727{
ca4c3545 2728 /* No nesting of non-OpenACC STMT (that is, an OpenMP one, or a GOMP builtin)
2729 inside an OpenACC CTX. */
2730 if (!(is_gimple_omp (stmt)
2731 && is_gimple_omp_oacc (stmt)))
2732 {
2733 for (omp_context *ctx_ = ctx; ctx_ != NULL; ctx_ = ctx_->outer)
2734 if (is_gimple_omp (ctx_->stmt)
2735 && is_gimple_omp_oacc (ctx_->stmt))
2736 {
2737 error_at (gimple_location (stmt),
2738 "non-OpenACC construct inside of OpenACC region");
2739 return false;
2740 }
2741 }
2742
3d483a94 2743 if (ctx != NULL)
2744 {
2745 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
10c55644 2746 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
3d483a94 2747 {
2748 error_at (gimple_location (stmt),
2749 "OpenMP constructs may not be nested inside simd region");
2750 return false;
2751 }
bc7bff74 2752 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
2753 {
2754 if ((gimple_code (stmt) != GIMPLE_OMP_FOR
2755 || (gimple_omp_for_kind (stmt)
2756 != GF_OMP_FOR_KIND_DISTRIBUTE))
2757 && gimple_code (stmt) != GIMPLE_OMP_PARALLEL)
2758 {
2759 error_at (gimple_location (stmt),
2760 "only distribute or parallel constructs are allowed to "
2761 "be closely nested inside teams construct");
2762 return false;
2763 }
2764 }
3d483a94 2765 }
75a70cf9 2766 switch (gimple_code (stmt))
c1d127dd 2767 {
75a70cf9 2768 case GIMPLE_OMP_FOR:
10c55644 2769 if (gimple_omp_for_kind (stmt) & GF_OMP_FOR_SIMD)
3d483a94 2770 return true;
bc7bff74 2771 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
2772 {
2773 if (ctx != NULL && gimple_code (ctx->stmt) != GIMPLE_OMP_TEAMS)
2774 {
2775 error_at (gimple_location (stmt),
2776 "distribute construct must be closely nested inside "
2777 "teams construct");
2778 return false;
2779 }
2780 return true;
2781 }
2782 /* FALLTHRU */
2783 case GIMPLE_CALL:
2784 if (is_gimple_call (stmt)
2785 && (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2786 == BUILT_IN_GOMP_CANCEL
2787 || DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2788 == BUILT_IN_GOMP_CANCELLATION_POINT))
2789 {
2790 const char *bad = NULL;
2791 const char *kind = NULL;
2792 if (ctx == NULL)
2793 {
2794 error_at (gimple_location (stmt), "orphaned %qs construct",
2795 DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2796 == BUILT_IN_GOMP_CANCEL
2797 ? "#pragma omp cancel"
2798 : "#pragma omp cancellation point");
2799 return false;
2800 }
6b409616 2801 switch (tree_fits_shwi_p (gimple_call_arg (stmt, 0))
2802 ? tree_to_shwi (gimple_call_arg (stmt, 0))
bc7bff74 2803 : 0)
2804 {
2805 case 1:
2806 if (gimple_code (ctx->stmt) != GIMPLE_OMP_PARALLEL)
2807 bad = "#pragma omp parallel";
2808 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2809 == BUILT_IN_GOMP_CANCEL
2810 && !integer_zerop (gimple_call_arg (stmt, 1)))
2811 ctx->cancellable = true;
2812 kind = "parallel";
2813 break;
2814 case 2:
2815 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
2816 || gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR)
2817 bad = "#pragma omp for";
2818 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2819 == BUILT_IN_GOMP_CANCEL
2820 && !integer_zerop (gimple_call_arg (stmt, 1)))
2821 {
2822 ctx->cancellable = true;
2823 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2824 OMP_CLAUSE_NOWAIT))
2825 warning_at (gimple_location (stmt), 0,
2826 "%<#pragma omp cancel for%> inside "
2827 "%<nowait%> for construct");
2828 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2829 OMP_CLAUSE_ORDERED))
2830 warning_at (gimple_location (stmt), 0,
2831 "%<#pragma omp cancel for%> inside "
2832 "%<ordered%> for construct");
2833 }
2834 kind = "for";
2835 break;
2836 case 4:
2837 if (gimple_code (ctx->stmt) != GIMPLE_OMP_SECTIONS
2838 && gimple_code (ctx->stmt) != GIMPLE_OMP_SECTION)
2839 bad = "#pragma omp sections";
2840 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2841 == BUILT_IN_GOMP_CANCEL
2842 && !integer_zerop (gimple_call_arg (stmt, 1)))
2843 {
2844 if (gimple_code (ctx->stmt) == GIMPLE_OMP_SECTIONS)
2845 {
2846 ctx->cancellable = true;
2847 if (find_omp_clause (gimple_omp_sections_clauses
2848 (ctx->stmt),
2849 OMP_CLAUSE_NOWAIT))
2850 warning_at (gimple_location (stmt), 0,
2851 "%<#pragma omp cancel sections%> inside "
2852 "%<nowait%> sections construct");
2853 }
2854 else
2855 {
2856 gcc_assert (ctx->outer
2857 && gimple_code (ctx->outer->stmt)
2858 == GIMPLE_OMP_SECTIONS);
2859 ctx->outer->cancellable = true;
2860 if (find_omp_clause (gimple_omp_sections_clauses
2861 (ctx->outer->stmt),
2862 OMP_CLAUSE_NOWAIT))
2863 warning_at (gimple_location (stmt), 0,
2864 "%<#pragma omp cancel sections%> inside "
2865 "%<nowait%> sections construct");
2866 }
2867 }
2868 kind = "sections";
2869 break;
2870 case 8:
2871 if (gimple_code (ctx->stmt) != GIMPLE_OMP_TASK)
2872 bad = "#pragma omp task";
2873 else
2874 ctx->cancellable = true;
2875 kind = "taskgroup";
2876 break;
2877 default:
2878 error_at (gimple_location (stmt), "invalid arguments");
2879 return false;
2880 }
2881 if (bad)
2882 {
2883 error_at (gimple_location (stmt),
2884 "%<%s %s%> construct not closely nested inside of %qs",
2885 DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2886 == BUILT_IN_GOMP_CANCEL
2887 ? "#pragma omp cancel"
2888 : "#pragma omp cancellation point", kind, bad);
2889 return false;
2890 }
2891 }
3d483a94 2892 /* FALLTHRU */
75a70cf9 2893 case GIMPLE_OMP_SECTIONS:
2894 case GIMPLE_OMP_SINGLE:
c1d127dd 2895 for (; ctx != NULL; ctx = ctx->outer)
75a70cf9 2896 switch (gimple_code (ctx->stmt))
c1d127dd 2897 {
75a70cf9 2898 case GIMPLE_OMP_FOR:
2899 case GIMPLE_OMP_SECTIONS:
2900 case GIMPLE_OMP_SINGLE:
2901 case GIMPLE_OMP_ORDERED:
2902 case GIMPLE_OMP_MASTER:
2903 case GIMPLE_OMP_TASK:
bc7bff74 2904 case GIMPLE_OMP_CRITICAL:
75a70cf9 2905 if (is_gimple_call (stmt))
fd6481cf 2906 {
bc7bff74 2907 if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2908 != BUILT_IN_GOMP_BARRIER)
2909 return true;
ab129075 2910 error_at (gimple_location (stmt),
2911 "barrier region may not be closely nested inside "
2912 "of work-sharing, critical, ordered, master or "
2913 "explicit task region");
2914 return false;
fd6481cf 2915 }
ab129075 2916 error_at (gimple_location (stmt),
2917 "work-sharing region may not be closely nested inside "
2918 "of work-sharing, critical, ordered, master or explicit "
2919 "task region");
2920 return false;
75a70cf9 2921 case GIMPLE_OMP_PARALLEL:
ab129075 2922 return true;
c1d127dd 2923 default:
2924 break;
2925 }
2926 break;
75a70cf9 2927 case GIMPLE_OMP_MASTER:
c1d127dd 2928 for (; ctx != NULL; ctx = ctx->outer)
75a70cf9 2929 switch (gimple_code (ctx->stmt))
c1d127dd 2930 {
75a70cf9 2931 case GIMPLE_OMP_FOR:
2932 case GIMPLE_OMP_SECTIONS:
2933 case GIMPLE_OMP_SINGLE:
2934 case GIMPLE_OMP_TASK:
ab129075 2935 error_at (gimple_location (stmt),
2936 "master region may not be closely nested inside "
2937 "of work-sharing or explicit task region");
2938 return false;
75a70cf9 2939 case GIMPLE_OMP_PARALLEL:
ab129075 2940 return true;
c1d127dd 2941 default:
2942 break;
2943 }
2944 break;
75a70cf9 2945 case GIMPLE_OMP_ORDERED:
c1d127dd 2946 for (; ctx != NULL; ctx = ctx->outer)
75a70cf9 2947 switch (gimple_code (ctx->stmt))
c1d127dd 2948 {
75a70cf9 2949 case GIMPLE_OMP_CRITICAL:
2950 case GIMPLE_OMP_TASK:
ab129075 2951 error_at (gimple_location (stmt),
2952 "ordered region may not be closely nested inside "
2953 "of critical or explicit task region");
2954 return false;
75a70cf9 2955 case GIMPLE_OMP_FOR:
2956 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
c1d127dd 2957 OMP_CLAUSE_ORDERED) == NULL)
ab129075 2958 {
2959 error_at (gimple_location (stmt),
2960 "ordered region must be closely nested inside "
c1d127dd 2961 "a loop region with an ordered clause");
ab129075 2962 return false;
2963 }
2964 return true;
75a70cf9 2965 case GIMPLE_OMP_PARALLEL:
bc7bff74 2966 error_at (gimple_location (stmt),
2967 "ordered region must be closely nested inside "
2968 "a loop region with an ordered clause");
2969 return false;
c1d127dd 2970 default:
2971 break;
2972 }
2973 break;
75a70cf9 2974 case GIMPLE_OMP_CRITICAL:
1a91d914 2975 {
2976 tree this_stmt_name
2977 = gimple_omp_critical_name (as_a <gomp_critical *> (stmt));
2978 for (; ctx != NULL; ctx = ctx->outer)
2979 if (gomp_critical *other_crit
2980 = dyn_cast <gomp_critical *> (ctx->stmt))
2981 if (this_stmt_name == gimple_omp_critical_name (other_crit))
2982 {
2983 error_at (gimple_location (stmt),
2984 "critical region may not be nested inside a critical "
2985 "region with the same name");
2986 return false;
2987 }
2988 }
c1d127dd 2989 break;
bc7bff74 2990 case GIMPLE_OMP_TEAMS:
2991 if (ctx == NULL
2992 || gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET
2993 || gimple_omp_target_kind (ctx->stmt) != GF_OMP_TARGET_KIND_REGION)
2994 {
2995 error_at (gimple_location (stmt),
2996 "teams construct not closely nested inside of target "
2997 "region");
2998 return false;
2999 }
3000 break;
691447ab 3001 case GIMPLE_OMP_TARGET:
3002 for (; ctx != NULL; ctx = ctx->outer)
ca4c3545 3003 {
3004 if (gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET)
3005 {
3006 if (is_gimple_omp (stmt)
3007 && is_gimple_omp_oacc (stmt)
3008 && is_gimple_omp (ctx->stmt))
3009 {
3010 error_at (gimple_location (stmt),
3011 "OpenACC construct inside of non-OpenACC region");
3012 return false;
3013 }
3014 continue;
3015 }
3016
3017 const char *stmt_name, *ctx_stmt_name;
3018 switch (gimple_omp_target_kind (stmt))
3019 {
3020 case GF_OMP_TARGET_KIND_REGION: stmt_name = "target"; break;
3021 case GF_OMP_TARGET_KIND_DATA: stmt_name = "target data"; break;
3022 case GF_OMP_TARGET_KIND_UPDATE: stmt_name = "target update"; break;
3023 case GF_OMP_TARGET_KIND_OACC_PARALLEL: stmt_name = "parallel"; break;
3024 case GF_OMP_TARGET_KIND_OACC_KERNELS: stmt_name = "kernels"; break;
3025 case GF_OMP_TARGET_KIND_OACC_DATA: stmt_name = "data"; break;
3026 case GF_OMP_TARGET_KIND_OACC_UPDATE: stmt_name = "update"; break;
3027 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA: stmt_name = "enter/exit data"; break;
3028 default: gcc_unreachable ();
3029 }
3030 switch (gimple_omp_target_kind (ctx->stmt))
3031 {
3032 case GF_OMP_TARGET_KIND_REGION: ctx_stmt_name = "target"; break;
3033 case GF_OMP_TARGET_KIND_DATA: ctx_stmt_name = "target data"; break;
3034 case GF_OMP_TARGET_KIND_OACC_PARALLEL: ctx_stmt_name = "parallel"; break;
3035 case GF_OMP_TARGET_KIND_OACC_KERNELS: ctx_stmt_name = "kernels"; break;
3036 case GF_OMP_TARGET_KIND_OACC_DATA: ctx_stmt_name = "data"; break;
3037 default: gcc_unreachable ();
3038 }
3039
3040 /* OpenACC/OpenMP mismatch? */
3041 if (is_gimple_omp_oacc (stmt)
3042 != is_gimple_omp_oacc (ctx->stmt))
3043 {
3044 error_at (gimple_location (stmt),
3045 "%s %s construct inside of %s %s region",
3046 (is_gimple_omp_oacc (stmt)
3047 ? "OpenACC" : "OpenMP"), stmt_name,
3048 (is_gimple_omp_oacc (ctx->stmt)
3049 ? "OpenACC" : "OpenMP"), ctx_stmt_name);
3050 return false;
3051 }
3052 if (is_gimple_omp_offloaded (ctx->stmt))
3053 {
3054 /* No GIMPLE_OMP_TARGET inside offloaded OpenACC CTX. */
3055 if (is_gimple_omp_oacc (ctx->stmt))
3056 {
3057 error_at (gimple_location (stmt),
3058 "%s construct inside of %s region",
3059 stmt_name, ctx_stmt_name);
3060 return false;
3061 }
3062 else
3063 {
3064 gcc_checking_assert (!is_gimple_omp_oacc (stmt));
3065 warning_at (gimple_location (stmt), 0,
3066 "%s construct inside of %s region",
3067 stmt_name, ctx_stmt_name);
3068 }
3069 }
3070 }
691447ab 3071 break;
c1d127dd 3072 default:
3073 break;
3074 }
ab129075 3075 return true;
c1d127dd 3076}
3077
3078
75a70cf9 3079/* Helper function scan_omp.
3080
3081 Callback for walk_tree or operators in walk_gimple_stmt used to
ca4c3545 3082 scan for OMP directives in TP. */
1e8e9920 3083
3084static tree
75a70cf9 3085scan_omp_1_op (tree *tp, int *walk_subtrees, void *data)
1e8e9920 3086{
4077bf7a 3087 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
3088 omp_context *ctx = (omp_context *) wi->info;
1e8e9920 3089 tree t = *tp;
3090
75a70cf9 3091 switch (TREE_CODE (t))
3092 {
3093 case VAR_DECL:
3094 case PARM_DECL:
3095 case LABEL_DECL:
3096 case RESULT_DECL:
3097 if (ctx)
3098 *tp = remap_decl (t, &ctx->cb);
3099 break;
3100
3101 default:
3102 if (ctx && TYPE_P (t))
3103 *tp = remap_type (t, &ctx->cb);
3104 else if (!DECL_P (t))
7cf869dd 3105 {
3106 *walk_subtrees = 1;
3107 if (ctx)
182cf5a9 3108 {
3109 tree tem = remap_type (TREE_TYPE (t), &ctx->cb);
3110 if (tem != TREE_TYPE (t))
3111 {
3112 if (TREE_CODE (t) == INTEGER_CST)
e913b5cd 3113 *tp = wide_int_to_tree (tem, t);
182cf5a9 3114 else
3115 TREE_TYPE (t) = tem;
3116 }
3117 }
7cf869dd 3118 }
75a70cf9 3119 break;
3120 }
3121
3122 return NULL_TREE;
3123}
3124
f2697631 3125/* Return true if FNDECL is a setjmp or a longjmp. */
3126
3127static bool
3128setjmp_or_longjmp_p (const_tree fndecl)
3129{
3130 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
3131 && (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_SETJMP
3132 || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_LONGJMP))
3133 return true;
3134
3135 tree declname = DECL_NAME (fndecl);
3136 if (!declname)
3137 return false;
3138 const char *name = IDENTIFIER_POINTER (declname);
3139 return !strcmp (name, "setjmp") || !strcmp (name, "longjmp");
3140}
3141
75a70cf9 3142
3143/* Helper function for scan_omp.
3144
ca4c3545 3145 Callback for walk_gimple_stmt used to scan for OMP directives in
75a70cf9 3146 the current statement in GSI. */
3147
3148static tree
3149scan_omp_1_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
3150 struct walk_stmt_info *wi)
3151{
3152 gimple stmt = gsi_stmt (*gsi);
3153 omp_context *ctx = (omp_context *) wi->info;
3154
3155 if (gimple_has_location (stmt))
3156 input_location = gimple_location (stmt);
1e8e9920 3157
ca4c3545 3158 /* Check the nesting restrictions. */
bc7bff74 3159 bool remove = false;
3160 if (is_gimple_omp (stmt))
3161 remove = !check_omp_nesting_restrictions (stmt, ctx);
3162 else if (is_gimple_call (stmt))
3163 {
3164 tree fndecl = gimple_call_fndecl (stmt);
f2697631 3165 if (fndecl)
3166 {
3167 if (setjmp_or_longjmp_p (fndecl)
3168 && ctx
3169 && gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
10c55644 3170 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
f2697631 3171 {
3172 remove = true;
3173 error_at (gimple_location (stmt),
3174 "setjmp/longjmp inside simd construct");
3175 }
3176 else if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
3177 switch (DECL_FUNCTION_CODE (fndecl))
3178 {
3179 case BUILT_IN_GOMP_BARRIER:
3180 case BUILT_IN_GOMP_CANCEL:
3181 case BUILT_IN_GOMP_CANCELLATION_POINT:
3182 case BUILT_IN_GOMP_TASKYIELD:
3183 case BUILT_IN_GOMP_TASKWAIT:
3184 case BUILT_IN_GOMP_TASKGROUP_START:
3185 case BUILT_IN_GOMP_TASKGROUP_END:
3186 remove = !check_omp_nesting_restrictions (stmt, ctx);
3187 break;
3188 default:
3189 break;
3190 }
3191 }
bc7bff74 3192 }
3193 if (remove)
3194 {
3195 stmt = gimple_build_nop ();
3196 gsi_replace (gsi, stmt, false);
fd6481cf 3197 }
c1d127dd 3198
75a70cf9 3199 *handled_ops_p = true;
3200
3201 switch (gimple_code (stmt))
1e8e9920 3202 {
75a70cf9 3203 case GIMPLE_OMP_PARALLEL:
fd6481cf 3204 taskreg_nesting_level++;
75a70cf9 3205 scan_omp_parallel (gsi, ctx);
fd6481cf 3206 taskreg_nesting_level--;
3207 break;
3208
75a70cf9 3209 case GIMPLE_OMP_TASK:
fd6481cf 3210 taskreg_nesting_level++;
75a70cf9 3211 scan_omp_task (gsi, ctx);
fd6481cf 3212 taskreg_nesting_level--;
1e8e9920 3213 break;
3214
75a70cf9 3215 case GIMPLE_OMP_FOR:
1a91d914 3216 scan_omp_for (as_a <gomp_for *> (stmt), ctx);
1e8e9920 3217 break;
3218
75a70cf9 3219 case GIMPLE_OMP_SECTIONS:
1a91d914 3220 scan_omp_sections (as_a <gomp_sections *> (stmt), ctx);
1e8e9920 3221 break;
3222
75a70cf9 3223 case GIMPLE_OMP_SINGLE:
1a91d914 3224 scan_omp_single (as_a <gomp_single *> (stmt), ctx);
1e8e9920 3225 break;
3226
75a70cf9 3227 case GIMPLE_OMP_SECTION:
3228 case GIMPLE_OMP_MASTER:
bc7bff74 3229 case GIMPLE_OMP_TASKGROUP:
75a70cf9 3230 case GIMPLE_OMP_ORDERED:
3231 case GIMPLE_OMP_CRITICAL:
3232 ctx = new_omp_context (stmt, ctx);
ab129075 3233 scan_omp (gimple_omp_body_ptr (stmt), ctx);
1e8e9920 3234 break;
3235
bc7bff74 3236 case GIMPLE_OMP_TARGET:
1a91d914 3237 scan_omp_target (as_a <gomp_target *> (stmt), ctx);
bc7bff74 3238 break;
3239
3240 case GIMPLE_OMP_TEAMS:
1a91d914 3241 scan_omp_teams (as_a <gomp_teams *> (stmt), ctx);
bc7bff74 3242 break;
3243
75a70cf9 3244 case GIMPLE_BIND:
1e8e9920 3245 {
3246 tree var;
1e8e9920 3247
75a70cf9 3248 *handled_ops_p = false;
3249 if (ctx)
1a91d914 3250 for (var = gimple_bind_vars (as_a <gbind *> (stmt));
3251 var ;
3252 var = DECL_CHAIN (var))
75a70cf9 3253 insert_decl_map (&ctx->cb, var, var);
1e8e9920 3254 }
3255 break;
1e8e9920 3256 default:
75a70cf9 3257 *handled_ops_p = false;
1e8e9920 3258 break;
3259 }
3260
3261 return NULL_TREE;
3262}
3263
3264
75a70cf9 3265/* Scan all the statements starting at the current statement. CTX
ca4c3545 3266 contains context information about the OMP directives and
75a70cf9 3267 clauses found during the scan. */
1e8e9920 3268
3269static void
ab129075 3270scan_omp (gimple_seq *body_p, omp_context *ctx)
1e8e9920 3271{
3272 location_t saved_location;
3273 struct walk_stmt_info wi;
3274
3275 memset (&wi, 0, sizeof (wi));
1e8e9920 3276 wi.info = ctx;
1e8e9920 3277 wi.want_locations = true;
3278
3279 saved_location = input_location;
ab129075 3280 walk_gimple_seq_mod (body_p, scan_omp_1_stmt, scan_omp_1_op, &wi);
1e8e9920 3281 input_location = saved_location;
3282}
3283\f
3284/* Re-gimplification and code generation routines. */
3285
3286/* Build a call to GOMP_barrier. */
3287
bc7bff74 3288static gimple
3289build_omp_barrier (tree lhs)
3290{
3291 tree fndecl = builtin_decl_explicit (lhs ? BUILT_IN_GOMP_BARRIER_CANCEL
3292 : BUILT_IN_GOMP_BARRIER);
1a91d914 3293 gcall *g = gimple_build_call (fndecl, 0);
bc7bff74 3294 if (lhs)
3295 gimple_call_set_lhs (g, lhs);
3296 return g;
1e8e9920 3297}
3298
3299/* If a context was created for STMT when it was scanned, return it. */
3300
3301static omp_context *
75a70cf9 3302maybe_lookup_ctx (gimple stmt)
1e8e9920 3303{
3304 splay_tree_node n;
3305 n = splay_tree_lookup (all_contexts, (splay_tree_key) stmt);
3306 return n ? (omp_context *) n->value : NULL;
3307}
3308
773c5ba7 3309
3310/* Find the mapping for DECL in CTX or the immediately enclosing
3311 context that has a mapping for DECL.
3312
3313 If CTX is a nested parallel directive, we may have to use the decl
3314 mappings created in CTX's parent context. Suppose that we have the
3315 following parallel nesting (variable UIDs showed for clarity):
3316
3317 iD.1562 = 0;
3318 #omp parallel shared(iD.1562) -> outer parallel
3319 iD.1562 = iD.1562 + 1;
3320
3321 #omp parallel shared (iD.1562) -> inner parallel
3322 iD.1562 = iD.1562 - 1;
3323
3324 Each parallel structure will create a distinct .omp_data_s structure
3325 for copying iD.1562 in/out of the directive:
3326
3327 outer parallel .omp_data_s.1.i -> iD.1562
3328 inner parallel .omp_data_s.2.i -> iD.1562
3329
3330 A shared variable mapping will produce a copy-out operation before
3331 the parallel directive and a copy-in operation after it. So, in
3332 this case we would have:
3333
3334 iD.1562 = 0;
3335 .omp_data_o.1.i = iD.1562;
3336 #omp parallel shared(iD.1562) -> outer parallel
3337 .omp_data_i.1 = &.omp_data_o.1
3338 .omp_data_i.1->i = .omp_data_i.1->i + 1;
3339
3340 .omp_data_o.2.i = iD.1562; -> **
3341 #omp parallel shared(iD.1562) -> inner parallel
3342 .omp_data_i.2 = &.omp_data_o.2
3343 .omp_data_i.2->i = .omp_data_i.2->i - 1;
3344
3345
3346 ** This is a problem. The symbol iD.1562 cannot be referenced
3347 inside the body of the outer parallel region. But since we are
3348 emitting this copy operation while expanding the inner parallel
3349 directive, we need to access the CTX structure of the outer
3350 parallel directive to get the correct mapping:
3351
3352 .omp_data_o.2.i = .omp_data_i.1->i
3353
3354 Since there may be other workshare or parallel directives enclosing
3355 the parallel directive, it may be necessary to walk up the context
3356 parent chain. This is not a problem in general because nested
3357 parallelism happens only rarely. */
3358
3359static tree
3360lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
3361{
3362 tree t;
3363 omp_context *up;
3364
773c5ba7 3365 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
3366 t = maybe_lookup_decl (decl, up);
3367
87b31375 3368 gcc_assert (!ctx->is_nested || t || is_global_var (decl));
773c5ba7 3369
c37594c7 3370 return t ? t : decl;
773c5ba7 3371}
3372
3373
f49d7bb5 3374/* Similar to lookup_decl_in_outer_ctx, but return DECL if not found
3375 in outer contexts. */
3376
3377static tree
3378maybe_lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
3379{
3380 tree t = NULL;
3381 omp_context *up;
3382
87b31375 3383 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
3384 t = maybe_lookup_decl (decl, up);
f49d7bb5 3385
3386 return t ? t : decl;
3387}
3388
3389
1e8e9920 3390/* Construct the initialization value for reduction CLAUSE. */
3391
3392tree
3393omp_reduction_init (tree clause, tree type)
3394{
389dd41b 3395 location_t loc = OMP_CLAUSE_LOCATION (clause);
1e8e9920 3396 switch (OMP_CLAUSE_REDUCTION_CODE (clause))
3397 {
3398 case PLUS_EXPR:
3399 case MINUS_EXPR:
3400 case BIT_IOR_EXPR:
3401 case BIT_XOR_EXPR:
3402 case TRUTH_OR_EXPR:
3403 case TRUTH_ORIF_EXPR:
3404 case TRUTH_XOR_EXPR:
3405 case NE_EXPR:
385f3f36 3406 return build_zero_cst (type);
1e8e9920 3407
3408 case MULT_EXPR:
3409 case TRUTH_AND_EXPR:
3410 case TRUTH_ANDIF_EXPR:
3411 case EQ_EXPR:
389dd41b 3412 return fold_convert_loc (loc, type, integer_one_node);
1e8e9920 3413
3414 case BIT_AND_EXPR:
389dd41b 3415 return fold_convert_loc (loc, type, integer_minus_one_node);
1e8e9920 3416
3417 case MAX_EXPR:
3418 if (SCALAR_FLOAT_TYPE_P (type))
3419 {
3420 REAL_VALUE_TYPE max, min;
fe994837 3421 if (HONOR_INFINITIES (type))
1e8e9920 3422 {
3423 real_inf (&max);
3424 real_arithmetic (&min, NEGATE_EXPR, &max, NULL);
3425 }
3426 else
3427 real_maxval (&min, 1, TYPE_MODE (type));
3428 return build_real (type, min);
3429 }
3430 else
3431 {
3432 gcc_assert (INTEGRAL_TYPE_P (type));
3433 return TYPE_MIN_VALUE (type);
3434 }
3435
3436 case MIN_EXPR:
3437 if (SCALAR_FLOAT_TYPE_P (type))
3438 {
3439 REAL_VALUE_TYPE max;
fe994837 3440 if (HONOR_INFINITIES (type))
1e8e9920 3441 real_inf (&max);
3442 else
3443 real_maxval (&max, 0, TYPE_MODE (type));
3444 return build_real (type, max);
3445 }
3446 else
3447 {
3448 gcc_assert (INTEGRAL_TYPE_P (type));
3449 return TYPE_MAX_VALUE (type);
3450 }
3451
3452 default:
3453 gcc_unreachable ();
3454 }
3455}
3456
bc7bff74 3457/* Return alignment to be assumed for var in CLAUSE, which should be
3458 OMP_CLAUSE_ALIGNED. */
3459
3460static tree
3461omp_clause_aligned_alignment (tree clause)
3462{
3463 if (OMP_CLAUSE_ALIGNED_ALIGNMENT (clause))
3464 return OMP_CLAUSE_ALIGNED_ALIGNMENT (clause);
3465
3466 /* Otherwise return implementation defined alignment. */
3467 unsigned int al = 1;
3754d046 3468 machine_mode mode, vmode;
bc7bff74 3469 int vs = targetm.vectorize.autovectorize_vector_sizes ();
3470 if (vs)
3471 vs = 1 << floor_log2 (vs);
3472 static enum mode_class classes[]
3473 = { MODE_INT, MODE_VECTOR_INT, MODE_FLOAT, MODE_VECTOR_FLOAT };
3474 for (int i = 0; i < 4; i += 2)
3475 for (mode = GET_CLASS_NARROWEST_MODE (classes[i]);
3476 mode != VOIDmode;
3477 mode = GET_MODE_WIDER_MODE (mode))
3478 {
3479 vmode = targetm.vectorize.preferred_simd_mode (mode);
3480 if (GET_MODE_CLASS (vmode) != classes[i + 1])
3481 continue;
3482 while (vs
3483 && GET_MODE_SIZE (vmode) < vs
3484 && GET_MODE_2XWIDER_MODE (vmode) != VOIDmode)
3485 vmode = GET_MODE_2XWIDER_MODE (vmode);
3486
3487 tree type = lang_hooks.types.type_for_mode (mode, 1);
3488 if (type == NULL_TREE || TYPE_MODE (type) != mode)
3489 continue;
3490 type = build_vector_type (type, GET_MODE_SIZE (vmode)
3491 / GET_MODE_SIZE (mode));
3492 if (TYPE_MODE (type) != vmode)
3493 continue;
3494 if (TYPE_ALIGN_UNIT (type) > al)
3495 al = TYPE_ALIGN_UNIT (type);
3496 }
3497 return build_int_cst (integer_type_node, al);
3498}
3499
3d483a94 3500/* Return maximum possible vectorization factor for the target. */
3501
3502static int
3503omp_max_vf (void)
3504{
3505 if (!optimize
3506 || optimize_debug
ad45e43e 3507 || !flag_tree_loop_optimize
043115ec 3508 || (!flag_tree_loop_vectorize
3509 && (global_options_set.x_flag_tree_loop_vectorize
3510 || global_options_set.x_flag_tree_vectorize)))
3d483a94 3511 return 1;
3512
3513 int vs = targetm.vectorize.autovectorize_vector_sizes ();
3514 if (vs)
3515 {
3516 vs = 1 << floor_log2 (vs);
3517 return vs;
3518 }
3754d046 3519 machine_mode vqimode = targetm.vectorize.preferred_simd_mode (QImode);
3d483a94 3520 if (GET_MODE_CLASS (vqimode) == MODE_VECTOR_INT)
3521 return GET_MODE_NUNITS (vqimode);
3522 return 1;
3523}
3524
3525/* Helper function of lower_rec_input_clauses, used for #pragma omp simd
3526 privatization. */
3527
3528static bool
3529lower_rec_simd_input_clauses (tree new_var, omp_context *ctx, int &max_vf,
3530 tree &idx, tree &lane, tree &ivar, tree &lvar)
3531{
3532 if (max_vf == 0)
3533 {
3534 max_vf = omp_max_vf ();
3535 if (max_vf > 1)
3536 {
3537 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3538 OMP_CLAUSE_SAFELEN);
c3f3b68d 3539 if (c && TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c)) != INTEGER_CST)
3540 max_vf = 1;
3541 else if (c && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
3542 max_vf) == -1)
d85a2013 3543 max_vf = tree_to_shwi (OMP_CLAUSE_SAFELEN_EXPR (c));
3d483a94 3544 }
3545 if (max_vf > 1)
3546 {
f9e245b2 3547 idx = create_tmp_var (unsigned_type_node);
3548 lane = create_tmp_var (unsigned_type_node);
3d483a94 3549 }
3550 }
3551 if (max_vf == 1)
3552 return false;
3553
3554 tree atype = build_array_type_nelts (TREE_TYPE (new_var), max_vf);
f9e245b2 3555 tree avar = create_tmp_var_raw (atype);
3d483a94 3556 if (TREE_ADDRESSABLE (new_var))
3557 TREE_ADDRESSABLE (avar) = 1;
3558 DECL_ATTRIBUTES (avar)
3559 = tree_cons (get_identifier ("omp simd array"), NULL,
3560 DECL_ATTRIBUTES (avar));
3561 gimple_add_tmp_var (avar);
3562 ivar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, idx,
3563 NULL_TREE, NULL_TREE);
3564 lvar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, lane,
3565 NULL_TREE, NULL_TREE);
bc7bff74 3566 if (DECL_P (new_var))
3567 {
3568 SET_DECL_VALUE_EXPR (new_var, lvar);
3569 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3570 }
3d483a94 3571 return true;
3572}
3573
2712b6de 3574/* Helper function of lower_rec_input_clauses. For a reference
3575 in simd reduction, add an underlying variable it will reference. */
3576
3577static void
3578handle_simd_reference (location_t loc, tree new_vard, gimple_seq *ilist)
3579{
3580 tree z = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_vard)));
3581 if (TREE_CONSTANT (z))
3582 {
3583 const char *name = NULL;
3584 if (DECL_NAME (new_vard))
3585 name = IDENTIFIER_POINTER (DECL_NAME (new_vard));
3586
3587 z = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_vard)), name);
3588 gimple_add_tmp_var (z);
3589 TREE_ADDRESSABLE (z) = 1;
3590 z = build_fold_addr_expr_loc (loc, z);
3591 gimplify_assign (new_vard, z, ilist);
3592 }
3593}
3594
1e8e9920 3595/* Generate code to implement the input clauses, FIRSTPRIVATE and COPYIN,
3596 from the receiver (aka child) side and initializers for REFERENCE_TYPE
3597 private variables. Initialization statements go in ILIST, while calls
3598 to destructors go in DLIST. */
3599
3600static void
75a70cf9 3601lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
bc7bff74 3602 omp_context *ctx, struct omp_for_data *fd)
1e8e9920 3603{
c2f47e15 3604 tree c, dtor, copyin_seq, x, ptr;
1e8e9920 3605 bool copyin_by_ref = false;
f49d7bb5 3606 bool lastprivate_firstprivate = false;
bc7bff74 3607 bool reduction_omp_orig_ref = false;
1e8e9920 3608 int pass;
3d483a94 3609 bool is_simd = (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
10c55644 3610 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD);
3d483a94 3611 int max_vf = 0;
3612 tree lane = NULL_TREE, idx = NULL_TREE;
3613 tree ivar = NULL_TREE, lvar = NULL_TREE;
3614 gimple_seq llist[2] = { NULL, NULL };
1e8e9920 3615
1e8e9920 3616 copyin_seq = NULL;
3617
3d483a94 3618 /* Set max_vf=1 (which will later enforce safelen=1) in simd loops
3619 with data sharing clauses referencing variable sized vars. That
3620 is unnecessarily hard to support and very unlikely to result in
3621 vectorized code anyway. */
3622 if (is_simd)
3623 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
3624 switch (OMP_CLAUSE_CODE (c))
3625 {
9580cb79 3626 case OMP_CLAUSE_LINEAR:
3627 if (OMP_CLAUSE_LINEAR_ARRAY (c))
3628 max_vf = 1;
3629 /* FALLTHRU */
3d483a94 3630 case OMP_CLAUSE_REDUCTION:
3d483a94 3631 case OMP_CLAUSE_PRIVATE:
3632 case OMP_CLAUSE_FIRSTPRIVATE:
3633 case OMP_CLAUSE_LASTPRIVATE:
3d483a94 3634 if (is_variable_sized (OMP_CLAUSE_DECL (c)))
3635 max_vf = 1;
3636 break;
3637 default:
3638 continue;
3639 }
3640
1e8e9920 3641 /* Do all the fixed sized types in the first pass, and the variable sized
3642 types in the second pass. This makes sure that the scalar arguments to
48e1416a 3643 the variable sized types are processed before we use them in the
1e8e9920 3644 variable sized operations. */
3645 for (pass = 0; pass < 2; ++pass)
3646 {
3647 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
3648 {
55d6e7cd 3649 enum omp_clause_code c_kind = OMP_CLAUSE_CODE (c);
1e8e9920 3650 tree var, new_var;
3651 bool by_ref;
389dd41b 3652 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
1e8e9920 3653
3654 switch (c_kind)
3655 {
3656 case OMP_CLAUSE_PRIVATE:
3657 if (OMP_CLAUSE_PRIVATE_DEBUG (c))
3658 continue;
3659 break;
3660 case OMP_CLAUSE_SHARED:
bc7bff74 3661 /* Ignore shared directives in teams construct. */
3662 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
3663 continue;
f49d7bb5 3664 if (maybe_lookup_decl (OMP_CLAUSE_DECL (c), ctx) == NULL)
3665 {
3666 gcc_assert (is_global_var (OMP_CLAUSE_DECL (c)));
3667 continue;
3668 }
1e8e9920 3669 case OMP_CLAUSE_FIRSTPRIVATE:
1e8e9920 3670 case OMP_CLAUSE_COPYIN:
bc7bff74 3671 case OMP_CLAUSE_LINEAR:
3672 break;
1e8e9920 3673 case OMP_CLAUSE_REDUCTION:
bc7bff74 3674 if (OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c))
3675 reduction_omp_orig_ref = true;
1e8e9920 3676 break;
bc7bff74 3677 case OMP_CLAUSE__LOOPTEMP_:
3678 /* Handle _looptemp_ clauses only on parallel. */
3679 if (fd)
3680 continue;
3d483a94 3681 break;
df2c34fc 3682 case OMP_CLAUSE_LASTPRIVATE:
f49d7bb5 3683 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
3684 {
3685 lastprivate_firstprivate = true;
3686 if (pass != 0)
3687 continue;
3688 }
cf5f881f 3689 /* Even without corresponding firstprivate, if
3690 decl is Fortran allocatable, it needs outer var
3691 reference. */
3692 else if (pass == 0
3693 && lang_hooks.decls.omp_private_outer_ref
3694 (OMP_CLAUSE_DECL (c)))
3695 lastprivate_firstprivate = true;
df2c34fc 3696 break;
bc7bff74 3697 case OMP_CLAUSE_ALIGNED:
3698 if (pass == 0)
3699 continue;
3700 var = OMP_CLAUSE_DECL (c);
3701 if (TREE_CODE (TREE_TYPE (var)) == POINTER_TYPE
3702 && !is_global_var (var))
3703 {
3704 new_var = maybe_lookup_decl (var, ctx);
3705 if (new_var == NULL_TREE)
3706 new_var = maybe_lookup_decl_in_outer_ctx (var, ctx);
3707 x = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
3708 x = build_call_expr_loc (clause_loc, x, 2, new_var,
3709 omp_clause_aligned_alignment (c));
3710 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
3711 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
3712 gimplify_and_add (x, ilist);
3713 }
3714 else if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE
3715 && is_global_var (var))
3716 {
3717 tree ptype = build_pointer_type (TREE_TYPE (var)), t, t2;
3718 new_var = lookup_decl (var, ctx);
3719 t = maybe_lookup_decl_in_outer_ctx (var, ctx);
3720 t = build_fold_addr_expr_loc (clause_loc, t);
3721 t2 = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
3722 t = build_call_expr_loc (clause_loc, t2, 2, t,
3723 omp_clause_aligned_alignment (c));
3724 t = fold_convert_loc (clause_loc, ptype, t);
f9e245b2 3725 x = create_tmp_var (ptype);
bc7bff74 3726 t = build2 (MODIFY_EXPR, ptype, x, t);
3727 gimplify_and_add (t, ilist);
3728 t = build_simple_mem_ref_loc (clause_loc, x);
3729 SET_DECL_VALUE_EXPR (new_var, t);
3730 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3731 }
3732 continue;
1e8e9920 3733 default:
3734 continue;
3735 }
3736
3737 new_var = var = OMP_CLAUSE_DECL (c);
3738 if (c_kind != OMP_CLAUSE_COPYIN)
3739 new_var = lookup_decl (var, ctx);
3740
3741 if (c_kind == OMP_CLAUSE_SHARED || c_kind == OMP_CLAUSE_COPYIN)
3742 {
3743 if (pass != 0)
3744 continue;
3745 }
1e8e9920 3746 else if (is_variable_sized (var))
3747 {
773c5ba7 3748 /* For variable sized types, we need to allocate the
3749 actual storage here. Call alloca and store the
3750 result in the pointer decl that we created elsewhere. */
1e8e9920 3751 if (pass == 0)
3752 continue;
3753
fd6481cf 3754 if (c_kind != OMP_CLAUSE_FIRSTPRIVATE || !is_task_ctx (ctx))
3755 {
1a91d914 3756 gcall *stmt;
b9a16870 3757 tree tmp, atmp;
75a70cf9 3758
fd6481cf 3759 ptr = DECL_VALUE_EXPR (new_var);
3760 gcc_assert (TREE_CODE (ptr) == INDIRECT_REF);
3761 ptr = TREE_OPERAND (ptr, 0);
3762 gcc_assert (DECL_P (ptr));
3763 x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
75a70cf9 3764
3765 /* void *tmp = __builtin_alloca */
b9a16870 3766 atmp = builtin_decl_explicit (BUILT_IN_ALLOCA);
3767 stmt = gimple_build_call (atmp, 1, x);
f9e245b2 3768 tmp = create_tmp_var_raw (ptr_type_node);
75a70cf9 3769 gimple_add_tmp_var (tmp);
3770 gimple_call_set_lhs (stmt, tmp);
3771
3772 gimple_seq_add_stmt (ilist, stmt);
3773
389dd41b 3774 x = fold_convert_loc (clause_loc, TREE_TYPE (ptr), tmp);
75a70cf9 3775 gimplify_assign (ptr, x, ilist);
fd6481cf 3776 }
1e8e9920 3777 }
1e8e9920 3778 else if (is_reference (var))
3779 {
773c5ba7 3780 /* For references that are being privatized for Fortran,
3781 allocate new backing storage for the new pointer
3782 variable. This allows us to avoid changing all the
3783 code that expects a pointer to something that expects
bc7bff74 3784 a direct variable. */
1e8e9920 3785 if (pass == 0)
3786 continue;
3787
3788 x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
fd6481cf 3789 if (c_kind == OMP_CLAUSE_FIRSTPRIVATE && is_task_ctx (ctx))
3790 {
3791 x = build_receiver_ref (var, false, ctx);
389dd41b 3792 x = build_fold_addr_expr_loc (clause_loc, x);
fd6481cf 3793 }
3794 else if (TREE_CONSTANT (x))
1e8e9920 3795 {
2712b6de 3796 /* For reduction in SIMD loop, defer adding the
3797 initialization of the reference, because if we decide
3798 to use SIMD array for it, the initilization could cause
3799 expansion ICE. */
3800 if (c_kind == OMP_CLAUSE_REDUCTION && is_simd)
09d1c205 3801 x = NULL_TREE;
3802 else
3803 {
3804 const char *name = NULL;
3805 if (DECL_NAME (var))
3806 name = IDENTIFIER_POINTER (DECL_NAME (new_var));
3807
3808 x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)),
3809 name);
3810 gimple_add_tmp_var (x);
3811 TREE_ADDRESSABLE (x) = 1;
3812 x = build_fold_addr_expr_loc (clause_loc, x);
3813 }
1e8e9920 3814 }
3815 else
3816 {
b9a16870 3817 tree atmp = builtin_decl_explicit (BUILT_IN_ALLOCA);
3818 x = build_call_expr_loc (clause_loc, atmp, 1, x);
1e8e9920 3819 }
3820
09d1c205 3821 if (x)
3822 {
3823 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
3824 gimplify_assign (new_var, x, ilist);
3825 }
1e8e9920 3826
182cf5a9 3827 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
1e8e9920 3828 }
3829 else if (c_kind == OMP_CLAUSE_REDUCTION
3830 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
3831 {
3832 if (pass == 0)
3833 continue;
3834 }
3835 else if (pass != 0)
3836 continue;
3837
55d6e7cd 3838 switch (OMP_CLAUSE_CODE (c))
1e8e9920 3839 {
3840 case OMP_CLAUSE_SHARED:
bc7bff74 3841 /* Ignore shared directives in teams construct. */
3842 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
3843 continue;
f49d7bb5 3844 /* Shared global vars are just accessed directly. */
3845 if (is_global_var (new_var))
3846 break;
1e8e9920 3847 /* Set up the DECL_VALUE_EXPR for shared variables now. This
3848 needs to be delayed until after fixup_child_record_type so
3849 that we get the correct type during the dereference. */
e8a588af 3850 by_ref = use_pointer_for_field (var, ctx);
1e8e9920 3851 x = build_receiver_ref (var, by_ref, ctx);
3852 SET_DECL_VALUE_EXPR (new_var, x);
3853 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3854
3855 /* ??? If VAR is not passed by reference, and the variable
3856 hasn't been initialized yet, then we'll get a warning for
3857 the store into the omp_data_s structure. Ideally, we'd be
48e1416a 3858 able to notice this and not store anything at all, but
1e8e9920 3859 we're generating code too early. Suppress the warning. */
3860 if (!by_ref)
3861 TREE_NO_WARNING (var) = 1;
3862 break;
3863
3864 case OMP_CLAUSE_LASTPRIVATE:
3865 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
3866 break;
3867 /* FALLTHRU */
3868
3869 case OMP_CLAUSE_PRIVATE:
fd6481cf 3870 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_PRIVATE)
3871 x = build_outer_var_ref (var, ctx);
3872 else if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
3873 {
3874 if (is_task_ctx (ctx))
3875 x = build_receiver_ref (var, false, ctx);
3876 else
3877 x = build_outer_var_ref (var, ctx);
3878 }
3879 else
3880 x = NULL;
3d483a94 3881 do_private:
bc7bff74 3882 tree nx;
3883 nx = lang_hooks.decls.omp_clause_default_ctor (c, new_var, x);
3d483a94 3884 if (is_simd)
3885 {
3886 tree y = lang_hooks.decls.omp_clause_dtor (c, new_var);
bc7bff74 3887 if ((TREE_ADDRESSABLE (new_var) || nx || y
3d483a94 3888 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE)
3889 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3890 idx, lane, ivar, lvar))
3891 {
bc7bff74 3892 if (nx)
3d483a94 3893 x = lang_hooks.decls.omp_clause_default_ctor
3894 (c, unshare_expr (ivar), x);
bc7bff74 3895 if (nx && x)
3d483a94 3896 gimplify_and_add (x, &llist[0]);
3897 if (y)
3898 {
3899 y = lang_hooks.decls.omp_clause_dtor (c, ivar);
3900 if (y)
3901 {
3902 gimple_seq tseq = NULL;
3903
3904 dtor = y;
3905 gimplify_stmt (&dtor, &tseq);
3906 gimple_seq_add_seq (&llist[1], tseq);
3907 }
3908 }
3909 break;
3910 }
3911 }
bc7bff74 3912 if (nx)
3913 gimplify_and_add (nx, ilist);
1e8e9920 3914 /* FALLTHRU */
3915
3916 do_dtor:
3917 x = lang_hooks.decls.omp_clause_dtor (c, new_var);
3918 if (x)
3919 {
75a70cf9 3920 gimple_seq tseq = NULL;
3921
1e8e9920 3922 dtor = x;
75a70cf9 3923 gimplify_stmt (&dtor, &tseq);
e3a19533 3924 gimple_seq_add_seq (dlist, tseq);
1e8e9920 3925 }
3926 break;
3927
3d483a94 3928 case OMP_CLAUSE_LINEAR:
3929 if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c))
3930 goto do_firstprivate;
3931 if (OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
3932 x = NULL;
3933 else
3934 x = build_outer_var_ref (var, ctx);
3935 goto do_private;
3936
1e8e9920 3937 case OMP_CLAUSE_FIRSTPRIVATE:
fd6481cf 3938 if (is_task_ctx (ctx))
3939 {
3940 if (is_reference (var) || is_variable_sized (var))
3941 goto do_dtor;
3942 else if (is_global_var (maybe_lookup_decl_in_outer_ctx (var,
3943 ctx))
3944 || use_pointer_for_field (var, NULL))
3945 {
3946 x = build_receiver_ref (var, false, ctx);
3947 SET_DECL_VALUE_EXPR (new_var, x);
3948 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3949 goto do_dtor;
3950 }
3951 }
3d483a94 3952 do_firstprivate:
1e8e9920 3953 x = build_outer_var_ref (var, ctx);
3d483a94 3954 if (is_simd)
3955 {
bc7bff74 3956 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
3957 && gimple_omp_for_combined_into_p (ctx->stmt))
3958 {
9580cb79 3959 tree t = OMP_CLAUSE_LINEAR_STEP (c);
3960 tree stept = TREE_TYPE (t);
3961 tree ct = find_omp_clause (clauses,
3962 OMP_CLAUSE__LOOPTEMP_);
3963 gcc_assert (ct);
3964 tree l = OMP_CLAUSE_DECL (ct);
e471cc6f 3965 tree n1 = fd->loop.n1;
3966 tree step = fd->loop.step;
3967 tree itype = TREE_TYPE (l);
3968 if (POINTER_TYPE_P (itype))
3969 itype = signed_type_for (itype);
3970 l = fold_build2 (MINUS_EXPR, itype, l, n1);
3971 if (TYPE_UNSIGNED (itype)
3972 && fd->loop.cond_code == GT_EXPR)
3973 l = fold_build2 (TRUNC_DIV_EXPR, itype,
3974 fold_build1 (NEGATE_EXPR, itype, l),
3975 fold_build1 (NEGATE_EXPR,
3976 itype, step));
3977 else
3978 l = fold_build2 (TRUNC_DIV_EXPR, itype, l, step);
bc7bff74 3979 t = fold_build2 (MULT_EXPR, stept,
3980 fold_convert (stept, l), t);
9580cb79 3981
3982 if (OMP_CLAUSE_LINEAR_ARRAY (c))
3983 {
3984 x = lang_hooks.decls.omp_clause_linear_ctor
3985 (c, new_var, x, t);
3986 gimplify_and_add (x, ilist);
3987 goto do_dtor;
3988 }
3989
bc7bff74 3990 if (POINTER_TYPE_P (TREE_TYPE (x)))
3991 x = fold_build2 (POINTER_PLUS_EXPR,
3992 TREE_TYPE (x), x, t);
3993 else
3994 x = fold_build2 (PLUS_EXPR, TREE_TYPE (x), x, t);
3995 }
3996
3d483a94 3997 if ((OMP_CLAUSE_CODE (c) != OMP_CLAUSE_LINEAR
3998 || TREE_ADDRESSABLE (new_var))
3999 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
4000 idx, lane, ivar, lvar))
4001 {
4002 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR)
4003 {
f9e245b2 4004 tree iv = create_tmp_var (TREE_TYPE (new_var));
3d483a94 4005 x = lang_hooks.decls.omp_clause_copy_ctor (c, iv, x);
4006 gimplify_and_add (x, ilist);
4007 gimple_stmt_iterator gsi
4008 = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
1a91d914 4009 gassign *g
3d483a94 4010 = gimple_build_assign (unshare_expr (lvar), iv);
4011 gsi_insert_before_without_update (&gsi, g,
4012 GSI_SAME_STMT);
9580cb79 4013 tree t = OMP_CLAUSE_LINEAR_STEP (c);
3d483a94 4014 enum tree_code code = PLUS_EXPR;
4015 if (POINTER_TYPE_P (TREE_TYPE (new_var)))
4016 code = POINTER_PLUS_EXPR;
e9cf809e 4017 g = gimple_build_assign (iv, code, iv, t);
3d483a94 4018 gsi_insert_before_without_update (&gsi, g,
4019 GSI_SAME_STMT);
4020 break;
4021 }
4022 x = lang_hooks.decls.omp_clause_copy_ctor
4023 (c, unshare_expr (ivar), x);
4024 gimplify_and_add (x, &llist[0]);
4025 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
4026 if (x)
4027 {
4028 gimple_seq tseq = NULL;
4029
4030 dtor = x;
4031 gimplify_stmt (&dtor, &tseq);
4032 gimple_seq_add_seq (&llist[1], tseq);
4033 }
4034 break;
4035 }
4036 }
1e8e9920 4037 x = lang_hooks.decls.omp_clause_copy_ctor (c, new_var, x);
4038 gimplify_and_add (x, ilist);
4039 goto do_dtor;
1e8e9920 4040
bc7bff74 4041 case OMP_CLAUSE__LOOPTEMP_:
4042 gcc_assert (is_parallel_ctx (ctx));
4043 x = build_outer_var_ref (var, ctx);
4044 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
4045 gimplify_and_add (x, ilist);
4046 break;
4047
1e8e9920 4048 case OMP_CLAUSE_COPYIN:
e8a588af 4049 by_ref = use_pointer_for_field (var, NULL);
1e8e9920 4050 x = build_receiver_ref (var, by_ref, ctx);
4051 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, x);
4052 append_to_statement_list (x, &copyin_seq);
4053 copyin_by_ref |= by_ref;
4054 break;
4055
4056 case OMP_CLAUSE_REDUCTION:
4057 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4058 {
fd6481cf 4059 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
bc7bff74 4060 gimple tseq;
fd6481cf 4061 x = build_outer_var_ref (var, ctx);
4062
bc7bff74 4063 if (is_reference (var)
4064 && !useless_type_conversion_p (TREE_TYPE (placeholder),
4065 TREE_TYPE (x)))
389dd41b 4066 x = build_fold_addr_expr_loc (clause_loc, x);
fd6481cf 4067 SET_DECL_VALUE_EXPR (placeholder, x);
4068 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
bc7bff74 4069 tree new_vard = new_var;
4070 if (is_reference (var))
4071 {
4072 gcc_assert (TREE_CODE (new_var) == MEM_REF);
4073 new_vard = TREE_OPERAND (new_var, 0);
4074 gcc_assert (DECL_P (new_vard));
4075 }
3d483a94 4076 if (is_simd
4077 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
4078 idx, lane, ivar, lvar))
4079 {
bc7bff74 4080 if (new_vard == new_var)
4081 {
4082 gcc_assert (DECL_VALUE_EXPR (new_var) == lvar);
4083 SET_DECL_VALUE_EXPR (new_var, ivar);
4084 }
4085 else
4086 {
4087 SET_DECL_VALUE_EXPR (new_vard,
4088 build_fold_addr_expr (ivar));
4089 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
4090 }
4091 x = lang_hooks.decls.omp_clause_default_ctor
4092 (c, unshare_expr (ivar),
4093 build_outer_var_ref (var, ctx));
4094 if (x)
4095 gimplify_and_add (x, &llist[0]);
4096 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
4097 {
4098 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
4099 lower_omp (&tseq, ctx);
4100 gimple_seq_add_seq (&llist[0], tseq);
4101 }
4102 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
4103 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
4104 lower_omp (&tseq, ctx);
4105 gimple_seq_add_seq (&llist[1], tseq);
4106 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
4107 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
4108 if (new_vard == new_var)
4109 SET_DECL_VALUE_EXPR (new_var, lvar);
4110 else
4111 SET_DECL_VALUE_EXPR (new_vard,
4112 build_fold_addr_expr (lvar));
4113 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
4114 if (x)
4115 {
4116 tseq = NULL;
4117 dtor = x;
4118 gimplify_stmt (&dtor, &tseq);
4119 gimple_seq_add_seq (&llist[1], tseq);
4120 }
4121 break;
4122 }
09d1c205 4123 /* If this is a reference to constant size reduction var
4124 with placeholder, we haven't emitted the initializer
4125 for it because it is undesirable if SIMD arrays are used.
4126 But if they aren't used, we need to emit the deferred
4127 initialization now. */
4128 else if (is_reference (var) && is_simd)
2712b6de 4129 handle_simd_reference (clause_loc, new_vard, ilist);
bc7bff74 4130 x = lang_hooks.decls.omp_clause_default_ctor
cf5f881f 4131 (c, unshare_expr (new_var),
4132 build_outer_var_ref (var, ctx));
bc7bff74 4133 if (x)
4134 gimplify_and_add (x, ilist);
4135 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
4136 {
4137 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
4138 lower_omp (&tseq, ctx);
4139 gimple_seq_add_seq (ilist, tseq);
4140 }
75a70cf9 4141 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
bc7bff74 4142 if (is_simd)
4143 {
4144 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
4145 lower_omp (&tseq, ctx);
4146 gimple_seq_add_seq (dlist, tseq);
4147 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
4148 }
fd6481cf 4149 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
bc7bff74 4150 goto do_dtor;
1e8e9920 4151 }
4152 else
4153 {
4154 x = omp_reduction_init (c, TREE_TYPE (new_var));
4155 gcc_assert (TREE_CODE (TREE_TYPE (new_var)) != ARRAY_TYPE);
c22ad515 4156 enum tree_code code = OMP_CLAUSE_REDUCTION_CODE (c);
4157
4158 /* reduction(-:var) sums up the partial results, so it
4159 acts identically to reduction(+:var). */
4160 if (code == MINUS_EXPR)
4161 code = PLUS_EXPR;
4162
2712b6de 4163 tree new_vard = new_var;
4164 if (is_simd && is_reference (var))
4165 {
4166 gcc_assert (TREE_CODE (new_var) == MEM_REF);
4167 new_vard = TREE_OPERAND (new_var, 0);
4168 gcc_assert (DECL_P (new_vard));
4169 }
3d483a94 4170 if (is_simd
4171 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
4172 idx, lane, ivar, lvar))
4173 {
3d483a94 4174 tree ref = build_outer_var_ref (var, ctx);
4175
4176 gimplify_assign (unshare_expr (ivar), x, &llist[0]);
4177
3d483a94 4178 x = build2 (code, TREE_TYPE (ref), ref, ivar);
4179 ref = build_outer_var_ref (var, ctx);
4180 gimplify_assign (ref, x, &llist[1]);
2712b6de 4181
4182 if (new_vard != new_var)
4183 {
4184 SET_DECL_VALUE_EXPR (new_vard,
4185 build_fold_addr_expr (lvar));
4186 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
4187 }
3d483a94 4188 }
4189 else
4190 {
2712b6de 4191 if (is_reference (var) && is_simd)
4192 handle_simd_reference (clause_loc, new_vard, ilist);
3d483a94 4193 gimplify_assign (new_var, x, ilist);
4194 if (is_simd)
c22ad515 4195 {
4196 tree ref = build_outer_var_ref (var, ctx);
4197
4198 x = build2 (code, TREE_TYPE (ref), ref, new_var);
4199 ref = build_outer_var_ref (var, ctx);
4200 gimplify_assign (ref, x, dlist);
4201 }
3d483a94 4202 }
1e8e9920 4203 }
4204 break;
4205
4206 default:
4207 gcc_unreachable ();
4208 }
4209 }
4210 }
4211
3d483a94 4212 if (lane)
4213 {
4214 tree uid = create_tmp_var (ptr_type_node, "simduid");
8e1a382d 4215 /* Don't want uninit warnings on simduid, it is always uninitialized,
4216 but we use it not for the value, but for the DECL_UID only. */
4217 TREE_NO_WARNING (uid) = 1;
3d483a94 4218 gimple g
4219 = gimple_build_call_internal (IFN_GOMP_SIMD_LANE, 1, uid);
4220 gimple_call_set_lhs (g, lane);
4221 gimple_stmt_iterator gsi = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
4222 gsi_insert_before_without_update (&gsi, g, GSI_SAME_STMT);
4223 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__SIMDUID_);
4224 OMP_CLAUSE__SIMDUID__DECL (c) = uid;
4225 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
4226 gimple_omp_for_set_clauses (ctx->stmt, c);
e9cf809e 4227 g = gimple_build_assign (lane, INTEGER_CST,
4228 build_int_cst (unsigned_type_node, 0));
3d483a94 4229 gimple_seq_add_stmt (ilist, g);
4230 for (int i = 0; i < 2; i++)
4231 if (llist[i])
4232 {
f9e245b2 4233 tree vf = create_tmp_var (unsigned_type_node);
3d483a94 4234 g = gimple_build_call_internal (IFN_GOMP_SIMD_VF, 1, uid);
4235 gimple_call_set_lhs (g, vf);
4236 gimple_seq *seq = i == 0 ? ilist : dlist;
4237 gimple_seq_add_stmt (seq, g);
4238 tree t = build_int_cst (unsigned_type_node, 0);
e9cf809e 4239 g = gimple_build_assign (idx, INTEGER_CST, t);
3d483a94 4240 gimple_seq_add_stmt (seq, g);
4241 tree body = create_artificial_label (UNKNOWN_LOCATION);
4242 tree header = create_artificial_label (UNKNOWN_LOCATION);
4243 tree end = create_artificial_label (UNKNOWN_LOCATION);
4244 gimple_seq_add_stmt (seq, gimple_build_goto (header));
4245 gimple_seq_add_stmt (seq, gimple_build_label (body));
4246 gimple_seq_add_seq (seq, llist[i]);
4247 t = build_int_cst (unsigned_type_node, 1);
e9cf809e 4248 g = gimple_build_assign (idx, PLUS_EXPR, idx, t);
3d483a94 4249 gimple_seq_add_stmt (seq, g);
4250 gimple_seq_add_stmt (seq, gimple_build_label (header));
4251 g = gimple_build_cond (LT_EXPR, idx, vf, body, end);
4252 gimple_seq_add_stmt (seq, g);
4253 gimple_seq_add_stmt (seq, gimple_build_label (end));
4254 }
4255 }
4256
1e8e9920 4257 /* The copyin sequence is not to be executed by the main thread, since
4258 that would result in self-copies. Perhaps not visible to scalars,
4259 but it certainly is to C++ operator=. */
4260 if (copyin_seq)
4261 {
b9a16870 4262 x = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM),
4263 0);
1e8e9920 4264 x = build2 (NE_EXPR, boolean_type_node, x,
4265 build_int_cst (TREE_TYPE (x), 0));
4266 x = build3 (COND_EXPR, void_type_node, x, copyin_seq, NULL);
4267 gimplify_and_add (x, ilist);
4268 }
4269
4270 /* If any copyin variable is passed by reference, we must ensure the
4271 master thread doesn't modify it before it is copied over in all
f49d7bb5 4272 threads. Similarly for variables in both firstprivate and
4273 lastprivate clauses we need to ensure the lastprivate copying
bc7bff74 4274 happens after firstprivate copying in all threads. And similarly
4275 for UDRs if initializer expression refers to omp_orig. */
4276 if (copyin_by_ref || lastprivate_firstprivate || reduction_omp_orig_ref)
3d483a94 4277 {
4278 /* Don't add any barrier for #pragma omp simd or
4279 #pragma omp distribute. */
4280 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
7c01fa6c 4281 || gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_FOR)
bc7bff74 4282 gimple_seq_add_stmt (ilist, build_omp_barrier (NULL_TREE));
3d483a94 4283 }
4284
4285 /* If max_vf is non-zero, then we can use only a vectorization factor
4286 up to the max_vf we chose. So stick it into the safelen clause. */
4287 if (max_vf)
4288 {
4289 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
4290 OMP_CLAUSE_SAFELEN);
4291 if (c == NULL_TREE
c3f3b68d 4292 || (TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c)) == INTEGER_CST
4293 && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
4294 max_vf) == 1))
3d483a94 4295 {
4296 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_SAFELEN);
4297 OMP_CLAUSE_SAFELEN_EXPR (c) = build_int_cst (integer_type_node,
4298 max_vf);
4299 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
4300 gimple_omp_for_set_clauses (ctx->stmt, c);
4301 }
4302 }
1e8e9920 4303}
4304
773c5ba7 4305
1e8e9920 4306/* Generate code to implement the LASTPRIVATE clauses. This is used for
4307 both parallel and workshare constructs. PREDICATE may be NULL if it's
4308 always true. */
4309
4310static void
75a70cf9 4311lower_lastprivate_clauses (tree clauses, tree predicate, gimple_seq *stmt_list,
bc7bff74 4312 omp_context *ctx)
1e8e9920 4313{
3d483a94 4314 tree x, c, label = NULL, orig_clauses = clauses;
fd6481cf 4315 bool par_clauses = false;
3d483a94 4316 tree simduid = NULL, lastlane = NULL;
1e8e9920 4317
3d483a94 4318 /* Early exit if there are no lastprivate or linear clauses. */
4319 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
4320 if (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LASTPRIVATE
4321 || (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LINEAR
4322 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (clauses)))
4323 break;
1e8e9920 4324 if (clauses == NULL)
4325 {
4326 /* If this was a workshare clause, see if it had been combined
4327 with its parallel. In that case, look for the clauses on the
4328 parallel statement itself. */
4329 if (is_parallel_ctx (ctx))
4330 return;
4331
4332 ctx = ctx->outer;
4333 if (ctx == NULL || !is_parallel_ctx (ctx))
4334 return;
4335
75a70cf9 4336 clauses = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
1e8e9920 4337 OMP_CLAUSE_LASTPRIVATE);
4338 if (clauses == NULL)
4339 return;
fd6481cf 4340 par_clauses = true;
1e8e9920 4341 }
4342
75a70cf9 4343 if (predicate)
4344 {
1a91d914 4345 gcond *stmt;
75a70cf9 4346 tree label_true, arm1, arm2;
4347
e60a6f7b 4348 label = create_artificial_label (UNKNOWN_LOCATION);
4349 label_true = create_artificial_label (UNKNOWN_LOCATION);
75a70cf9 4350 arm1 = TREE_OPERAND (predicate, 0);
4351 arm2 = TREE_OPERAND (predicate, 1);
4352 gimplify_expr (&arm1, stmt_list, NULL, is_gimple_val, fb_rvalue);
4353 gimplify_expr (&arm2, stmt_list, NULL, is_gimple_val, fb_rvalue);
4354 stmt = gimple_build_cond (TREE_CODE (predicate), arm1, arm2,
4355 label_true, label);
4356 gimple_seq_add_stmt (stmt_list, stmt);
4357 gimple_seq_add_stmt (stmt_list, gimple_build_label (label_true));
4358 }
1e8e9920 4359
3d483a94 4360 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
10c55644 4361 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
3d483a94 4362 {
4363 simduid = find_omp_clause (orig_clauses, OMP_CLAUSE__SIMDUID_);
4364 if (simduid)
4365 simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
4366 }
4367
fd6481cf 4368 for (c = clauses; c ;)
1e8e9920 4369 {
4370 tree var, new_var;
389dd41b 4371 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
1e8e9920 4372
3d483a94 4373 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
4374 || (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
4375 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c)))
fd6481cf 4376 {
4377 var = OMP_CLAUSE_DECL (c);
4378 new_var = lookup_decl (var, ctx);
1e8e9920 4379
3d483a94 4380 if (simduid && DECL_HAS_VALUE_EXPR_P (new_var))
4381 {
4382 tree val = DECL_VALUE_EXPR (new_var);
4383 if (TREE_CODE (val) == ARRAY_REF
4384 && VAR_P (TREE_OPERAND (val, 0))
4385 && lookup_attribute ("omp simd array",
4386 DECL_ATTRIBUTES (TREE_OPERAND (val,
4387 0))))
4388 {
4389 if (lastlane == NULL)
4390 {
f9e245b2 4391 lastlane = create_tmp_var (unsigned_type_node);
1a91d914 4392 gcall *g
3d483a94 4393 = gimple_build_call_internal (IFN_GOMP_SIMD_LAST_LANE,
4394 2, simduid,
4395 TREE_OPERAND (val, 1));
4396 gimple_call_set_lhs (g, lastlane);
4397 gimple_seq_add_stmt (stmt_list, g);
4398 }
4399 new_var = build4 (ARRAY_REF, TREE_TYPE (val),
4400 TREE_OPERAND (val, 0), lastlane,
4401 NULL_TREE, NULL_TREE);
4402 }
4403 }
4404
4405 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
4406 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
75a70cf9 4407 {
e3a19533 4408 lower_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
75a70cf9 4409 gimple_seq_add_seq (stmt_list,
4410 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c));
3d483a94 4411 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c) = NULL;
75a70cf9 4412 }
2b536a17 4413 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
4414 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
4415 {
4416 lower_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
4417 gimple_seq_add_seq (stmt_list,
4418 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c));
4419 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c) = NULL;
4420 }
1e8e9920 4421
fd6481cf 4422 x = build_outer_var_ref (var, ctx);
4423 if (is_reference (var))
182cf5a9 4424 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
fd6481cf 4425 x = lang_hooks.decls.omp_clause_assign_op (c, x, new_var);
75a70cf9 4426 gimplify_and_add (x, stmt_list);
fd6481cf 4427 }
4428 c = OMP_CLAUSE_CHAIN (c);
4429 if (c == NULL && !par_clauses)
4430 {
4431 /* If this was a workshare clause, see if it had been combined
4432 with its parallel. In that case, continue looking for the
4433 clauses also on the parallel statement itself. */
4434 if (is_parallel_ctx (ctx))
4435 break;
4436
4437 ctx = ctx->outer;
4438 if (ctx == NULL || !is_parallel_ctx (ctx))
4439 break;
4440
75a70cf9 4441 c = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
fd6481cf 4442 OMP_CLAUSE_LASTPRIVATE);
4443 par_clauses = true;
4444 }
1e8e9920 4445 }
4446
75a70cf9 4447 if (label)
4448 gimple_seq_add_stmt (stmt_list, gimple_build_label (label));
1e8e9920 4449}
4450
ca4c3545 4451static void
4452oacc_lower_reduction_var_helper (gimple_seq *stmt_seqp, omp_context *ctx,
4453 tree tid, tree var, tree new_var)
4454{
4455 /* The atomic add at the end of the sum creates unnecessary
4456 write contention on accelerators. To work around this,
4457 create an array to store the partial reductions. Later, in
4458 lower_omp_for (for openacc), the values of array will be
4459 combined. */
4460
4461 tree t = NULL_TREE, array, x;
4462 tree type = get_base_type (var);
4463 gimple stmt;
4464
4465 /* Now insert the partial reductions into the array. */
4466
4467 /* Find the reduction array. */
4468
4469 tree ptype = build_pointer_type (type);
4470
4471 t = lookup_oacc_reduction (oacc_get_reduction_array_id (var), ctx);
4472 t = build_receiver_ref (t, false, ctx->outer);
4473
4474 array = create_tmp_var (ptype);
4475 gimplify_assign (array, t, stmt_seqp);
4476
4477 tree ptr = create_tmp_var (TREE_TYPE (array));
4478
4479 /* Find the reduction array. */
4480
4481 /* testing a unary conversion. */
4482 tree offset = create_tmp_var (sizetype);
4483 gimplify_assign (offset, TYPE_SIZE_UNIT (type),
4484 stmt_seqp);
4485 t = create_tmp_var (sizetype);
4486 gimplify_assign (t, unshare_expr (fold_build1 (NOP_EXPR, sizetype, tid)),
4487 stmt_seqp);
4488 stmt = gimple_build_assign (offset, MULT_EXPR, offset, t);
4489 gimple_seq_add_stmt (stmt_seqp, stmt);
4490
4491 /* Offset expression. Does the POINTER_PLUS_EXPR take care
4492 of adding sizeof(var) to the array? */
4493 ptr = create_tmp_var (ptype);
4494 stmt = gimple_build_assign (unshare_expr (ptr), POINTER_PLUS_EXPR, array,
4495 offset);
4496 gimple_seq_add_stmt (stmt_seqp, stmt);
4497
4498 /* Move the local sum to gfc$sum[i]. */
4499 x = unshare_expr (build_simple_mem_ref (ptr));
4500 stmt = gimplify_assign (x, new_var, stmt_seqp);
4501}
773c5ba7 4502
1e8e9920 4503/* Generate code to implement the REDUCTION clauses. */
4504
4505static void
75a70cf9 4506lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp, omp_context *ctx)
1e8e9920 4507{
75a70cf9 4508 gimple_seq sub_seq = NULL;
4509 gimple stmt;
ca4c3545 4510 tree x, c, tid = NULL_TREE;
1e8e9920 4511 int count = 0;
4512
3d483a94 4513 /* SIMD reductions are handled in lower_rec_input_clauses. */
4514 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
10c55644 4515 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
3d483a94 4516 return;
4517
1e8e9920 4518 /* First see if there is exactly one reduction clause. Use OMP_ATOMIC
4519 update in that case, otherwise use a lock. */
4520 for (c = clauses; c && count < 2; c = OMP_CLAUSE_CHAIN (c))
55d6e7cd 4521 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
1e8e9920 4522 {
4523 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4524 {
bc7bff74 4525 /* Never use OMP_ATOMIC for array reductions or UDRs. */
1e8e9920 4526 count = -1;
4527 break;
4528 }
4529 count++;
4530 }
4531
4532 if (count == 0)
4533 return;
4534
ca4c3545 4535 /* Initialize thread info for OpenACC. */
4536 if (is_gimple_omp_oacc (ctx->stmt))
4537 {
4538 /* Get the current thread id. */
4539 tree call = builtin_decl_explicit (BUILT_IN_GOACC_GET_THREAD_NUM);
4540 tid = create_tmp_var (TREE_TYPE (TREE_TYPE (call)));
4541 gimple stmt = gimple_build_call (call, 0);
4542 gimple_call_set_lhs (stmt, tid);
4543 gimple_seq_add_stmt (stmt_seqp, stmt);
4544 }
4545
1e8e9920 4546 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4547 {
4548 tree var, ref, new_var;
4549 enum tree_code code;
389dd41b 4550 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
1e8e9920 4551
55d6e7cd 4552 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
1e8e9920 4553 continue;
4554
4555 var = OMP_CLAUSE_DECL (c);
4556 new_var = lookup_decl (var, ctx);
4557 if (is_reference (var))
182cf5a9 4558 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
1e8e9920 4559 ref = build_outer_var_ref (var, ctx);
4560 code = OMP_CLAUSE_REDUCTION_CODE (c);
773c5ba7 4561
4562 /* reduction(-:var) sums up the partial results, so it acts
4563 identically to reduction(+:var). */
1e8e9920 4564 if (code == MINUS_EXPR)
4565 code = PLUS_EXPR;
4566
ca4c3545 4567 if (is_gimple_omp_oacc (ctx->stmt))
4568 {
4569 gcc_checking_assert (!OMP_CLAUSE_REDUCTION_PLACEHOLDER (c));
4570
4571 oacc_lower_reduction_var_helper (stmt_seqp, ctx, tid, var, new_var);
4572 }
4573 else if (count == 1)
1e8e9920 4574 {
389dd41b 4575 tree addr = build_fold_addr_expr_loc (clause_loc, ref);
1e8e9920 4576
4577 addr = save_expr (addr);
4578 ref = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (addr)), addr);
389dd41b 4579 x = fold_build2_loc (clause_loc, code, TREE_TYPE (ref), ref, new_var);
1e8e9920 4580 x = build2 (OMP_ATOMIC, void_type_node, addr, x);
75a70cf9 4581 gimplify_and_add (x, stmt_seqp);
1e8e9920 4582 return;
4583 }
ca4c3545 4584 else if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1e8e9920 4585 {
4586 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
4587
bc7bff74 4588 if (is_reference (var)
4589 && !useless_type_conversion_p (TREE_TYPE (placeholder),
4590 TREE_TYPE (ref)))
389dd41b 4591 ref = build_fold_addr_expr_loc (clause_loc, ref);
1e8e9920 4592 SET_DECL_VALUE_EXPR (placeholder, ref);
4593 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
e3a19533 4594 lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
75a70cf9 4595 gimple_seq_add_seq (&sub_seq, OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
4596 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
1e8e9920 4597 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
4598 }
4599 else
4600 {
4601 x = build2 (code, TREE_TYPE (ref), ref, new_var);
4602 ref = build_outer_var_ref (var, ctx);
75a70cf9 4603 gimplify_assign (ref, x, &sub_seq);
1e8e9920 4604 }
4605 }
4606
ca4c3545 4607 if (is_gimple_omp_oacc (ctx->stmt))
4608 return;
4609
b9a16870 4610 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START),
4611 0);
75a70cf9 4612 gimple_seq_add_stmt (stmt_seqp, stmt);
1e8e9920 4613
75a70cf9 4614 gimple_seq_add_seq (stmt_seqp, sub_seq);
1e8e9920 4615
b9a16870 4616 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END),
4617 0);
75a70cf9 4618 gimple_seq_add_stmt (stmt_seqp, stmt);
1e8e9920 4619}
4620
773c5ba7 4621
1e8e9920 4622/* Generate code to implement the COPYPRIVATE clauses. */
4623
4624static void
75a70cf9 4625lower_copyprivate_clauses (tree clauses, gimple_seq *slist, gimple_seq *rlist,
1e8e9920 4626 omp_context *ctx)
4627{
4628 tree c;
4629
4630 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4631 {
cb561506 4632 tree var, new_var, ref, x;
1e8e9920 4633 bool by_ref;
389dd41b 4634 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
1e8e9920 4635
55d6e7cd 4636 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYPRIVATE)
1e8e9920 4637 continue;
4638
4639 var = OMP_CLAUSE_DECL (c);
e8a588af 4640 by_ref = use_pointer_for_field (var, NULL);
1e8e9920 4641
4642 ref = build_sender_ref (var, ctx);
cb561506 4643 x = new_var = lookup_decl_in_outer_ctx (var, ctx);
4644 if (by_ref)
4645 {
4646 x = build_fold_addr_expr_loc (clause_loc, new_var);
4647 x = fold_convert_loc (clause_loc, TREE_TYPE (ref), x);
4648 }
75a70cf9 4649 gimplify_assign (ref, x, slist);
1e8e9920 4650
cb561506 4651 ref = build_receiver_ref (var, false, ctx);
4652 if (by_ref)
4653 {
4654 ref = fold_convert_loc (clause_loc,
4655 build_pointer_type (TREE_TYPE (new_var)),
4656 ref);
4657 ref = build_fold_indirect_ref_loc (clause_loc, ref);
4658 }
1e8e9920 4659 if (is_reference (var))
4660 {
cb561506 4661 ref = fold_convert_loc (clause_loc, TREE_TYPE (new_var), ref);
182cf5a9 4662 ref = build_simple_mem_ref_loc (clause_loc, ref);
4663 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
1e8e9920 4664 }
cb561506 4665 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, ref);
1e8e9920 4666 gimplify_and_add (x, rlist);
4667 }
4668}
4669
773c5ba7 4670
1e8e9920 4671/* Generate code to implement the clauses, FIRSTPRIVATE, COPYIN, LASTPRIVATE,
4672 and REDUCTION from the sender (aka parent) side. */
4673
4674static void
75a70cf9 4675lower_send_clauses (tree clauses, gimple_seq *ilist, gimple_seq *olist,
4676 omp_context *ctx)
1e8e9920 4677{
4678 tree c;
4679
4680 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4681 {
773c5ba7 4682 tree val, ref, x, var;
1e8e9920 4683 bool by_ref, do_in = false, do_out = false;
389dd41b 4684 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
1e8e9920 4685
55d6e7cd 4686 switch (OMP_CLAUSE_CODE (c))
1e8e9920 4687 {
fd6481cf 4688 case OMP_CLAUSE_PRIVATE:
4689 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
4690 break;
4691 continue;
1e8e9920 4692 case OMP_CLAUSE_FIRSTPRIVATE:
4693 case OMP_CLAUSE_COPYIN:
4694 case OMP_CLAUSE_LASTPRIVATE:
4695 case OMP_CLAUSE_REDUCTION:
bc7bff74 4696 case OMP_CLAUSE__LOOPTEMP_:
1e8e9920 4697 break;
4698 default:
4699 continue;
4700 }
4701
87b31375 4702 val = OMP_CLAUSE_DECL (c);
4703 var = lookup_decl_in_outer_ctx (val, ctx);
773c5ba7 4704
f49d7bb5 4705 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYIN
4706 && is_global_var (var))
4707 continue;
1e8e9920 4708 if (is_variable_sized (val))
4709 continue;
e8a588af 4710 by_ref = use_pointer_for_field (val, NULL);
1e8e9920 4711
55d6e7cd 4712 switch (OMP_CLAUSE_CODE (c))
1e8e9920 4713 {
fd6481cf 4714 case OMP_CLAUSE_PRIVATE:
1e8e9920 4715 case OMP_CLAUSE_FIRSTPRIVATE:
4716 case OMP_CLAUSE_COPYIN:
bc7bff74 4717 case OMP_CLAUSE__LOOPTEMP_:
1e8e9920 4718 do_in = true;
4719 break;
4720
4721 case OMP_CLAUSE_LASTPRIVATE:
4722 if (by_ref || is_reference (val))
4723 {
4724 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
4725 continue;
4726 do_in = true;
4727 }
4728 else
fd6481cf 4729 {
4730 do_out = true;
4731 if (lang_hooks.decls.omp_private_outer_ref (val))
4732 do_in = true;
4733 }
1e8e9920 4734 break;
4735
4736 case OMP_CLAUSE_REDUCTION:
4737 do_in = true;
4738 do_out = !(by_ref || is_reference (val));
4739 break;
4740
4741 default:
4742 gcc_unreachable ();
4743 }
4744
4745 if (do_in)
4746 {
4747 ref = build_sender_ref (val, ctx);
389dd41b 4748 x = by_ref ? build_fold_addr_expr_loc (clause_loc, var) : var;
75a70cf9 4749 gimplify_assign (ref, x, ilist);
fd6481cf 4750 if (is_task_ctx (ctx))
4751 DECL_ABSTRACT_ORIGIN (TREE_OPERAND (ref, 1)) = NULL;
1e8e9920 4752 }
773c5ba7 4753
1e8e9920 4754 if (do_out)
4755 {
4756 ref = build_sender_ref (val, ctx);
75a70cf9 4757 gimplify_assign (var, ref, olist);
1e8e9920 4758 }
4759 }
4760}
4761
75a70cf9 4762/* Generate code to implement SHARED from the sender (aka parent)
4763 side. This is trickier, since GIMPLE_OMP_PARALLEL_CLAUSES doesn't
4764 list things that got automatically shared. */
1e8e9920 4765
4766static void
75a70cf9 4767lower_send_shared_vars (gimple_seq *ilist, gimple_seq *olist, omp_context *ctx)
1e8e9920 4768{
fd6481cf 4769 tree var, ovar, nvar, f, x, record_type;
1e8e9920 4770
4771 if (ctx->record_type == NULL)
4772 return;
773c5ba7 4773
fd6481cf 4774 record_type = ctx->srecord_type ? ctx->srecord_type : ctx->record_type;
1767a056 4775 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
1e8e9920 4776 {
4777 ovar = DECL_ABSTRACT_ORIGIN (f);
4778 nvar = maybe_lookup_decl (ovar, ctx);
4779 if (!nvar || !DECL_HAS_VALUE_EXPR_P (nvar))
4780 continue;
4781
773c5ba7 4782 /* If CTX is a nested parallel directive. Find the immediately
4783 enclosing parallel or workshare construct that contains a
4784 mapping for OVAR. */
87b31375 4785 var = lookup_decl_in_outer_ctx (ovar, ctx);
773c5ba7 4786
e8a588af 4787 if (use_pointer_for_field (ovar, ctx))
1e8e9920 4788 {
4789 x = build_sender_ref (ovar, ctx);
773c5ba7 4790 var = build_fold_addr_expr (var);
75a70cf9 4791 gimplify_assign (x, var, ilist);
1e8e9920 4792 }
4793 else
4794 {
4795 x = build_sender_ref (ovar, ctx);
75a70cf9 4796 gimplify_assign (x, var, ilist);
1e8e9920 4797
d2263ebb 4798 if (!TREE_READONLY (var)
4799 /* We don't need to receive a new reference to a result
4800 or parm decl. In fact we may not store to it as we will
4801 invalidate any pending RSO and generate wrong gimple
4802 during inlining. */
4803 && !((TREE_CODE (var) == RESULT_DECL
4804 || TREE_CODE (var) == PARM_DECL)
4805 && DECL_BY_REFERENCE (var)))
fd6481cf 4806 {
4807 x = build_sender_ref (ovar, ctx);
75a70cf9 4808 gimplify_assign (var, x, olist);
fd6481cf 4809 }
1e8e9920 4810 }
4811 }
4812}
4813
75a70cf9 4814
4815/* A convenience function to build an empty GIMPLE_COND with just the
4816 condition. */
4817
1a91d914 4818static gcond *
75a70cf9 4819gimple_build_cond_empty (tree cond)
4820{
4821 enum tree_code pred_code;
4822 tree lhs, rhs;
4823
4824 gimple_cond_get_ops_from_tree (cond, &pred_code, &lhs, &rhs);
4825 return gimple_build_cond (pred_code, lhs, rhs, NULL_TREE, NULL_TREE);
4826}
4827
4828
48e1416a 4829/* Build the function calls to GOMP_parallel_start etc to actually
773c5ba7 4830 generate the parallel operation. REGION is the parallel region
4831 being expanded. BB is the block where to insert the code. WS_ARGS
4832 will be set if this is a call to a combined parallel+workshare
4833 construct, it contains the list of additional arguments needed by
4834 the workshare construct. */
1e8e9920 4835
4836static void
61e47ac8 4837expand_parallel_call (struct omp_region *region, basic_block bb,
1a91d914 4838 gomp_parallel *entry_stmt,
4839 vec<tree, va_gc> *ws_args)
1e8e9920 4840{
bc7bff74 4841 tree t, t1, t2, val, cond, c, clauses, flags;
75a70cf9 4842 gimple_stmt_iterator gsi;
4843 gimple stmt;
b9a16870 4844 enum built_in_function start_ix;
4845 int start_ix2;
389dd41b 4846 location_t clause_loc;
f1f41a6c 4847 vec<tree, va_gc> *args;
773c5ba7 4848
75a70cf9 4849 clauses = gimple_omp_parallel_clauses (entry_stmt);
773c5ba7 4850
bc7bff74 4851 /* Determine what flavor of GOMP_parallel we will be
773c5ba7 4852 emitting. */
bc7bff74 4853 start_ix = BUILT_IN_GOMP_PARALLEL;
773c5ba7 4854 if (is_combined_parallel (region))
4855 {
61e47ac8 4856 switch (region->inner->type)
773c5ba7 4857 {
75a70cf9 4858 case GIMPLE_OMP_FOR:
fd6481cf 4859 gcc_assert (region->inner->sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
bc7bff74 4860 start_ix2 = ((int)BUILT_IN_GOMP_PARALLEL_LOOP_STATIC
b9a16870 4861 + (region->inner->sched_kind
4862 == OMP_CLAUSE_SCHEDULE_RUNTIME
4863 ? 3 : region->inner->sched_kind));
4864 start_ix = (enum built_in_function)start_ix2;
61e47ac8 4865 break;
75a70cf9 4866 case GIMPLE_OMP_SECTIONS:
bc7bff74 4867 start_ix = BUILT_IN_GOMP_PARALLEL_SECTIONS;
61e47ac8 4868 break;
4869 default:
4870 gcc_unreachable ();
773c5ba7 4871 }
773c5ba7 4872 }
1e8e9920 4873
4874 /* By default, the value of NUM_THREADS is zero (selected at run time)
4875 and there is no conditional. */
4876 cond = NULL_TREE;
4877 val = build_int_cst (unsigned_type_node, 0);
bc7bff74 4878 flags = build_int_cst (unsigned_type_node, 0);
1e8e9920 4879
4880 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
4881 if (c)
4882 cond = OMP_CLAUSE_IF_EXPR (c);
4883
4884 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_THREADS);
4885 if (c)
389dd41b 4886 {
4887 val = OMP_CLAUSE_NUM_THREADS_EXPR (c);
4888 clause_loc = OMP_CLAUSE_LOCATION (c);
4889 }
4890 else
4891 clause_loc = gimple_location (entry_stmt);
1e8e9920 4892
bc7bff74 4893 c = find_omp_clause (clauses, OMP_CLAUSE_PROC_BIND);
4894 if (c)
4895 flags = build_int_cst (unsigned_type_node, OMP_CLAUSE_PROC_BIND_KIND (c));
4896
1e8e9920 4897 /* Ensure 'val' is of the correct type. */
389dd41b 4898 val = fold_convert_loc (clause_loc, unsigned_type_node, val);
1e8e9920 4899
4900 /* If we found the clause 'if (cond)', build either
4901 (cond != 0) or (cond ? val : 1u). */
4902 if (cond)
4903 {
773c5ba7 4904 cond = gimple_boolify (cond);
4905
1e8e9920 4906 if (integer_zerop (val))
389dd41b 4907 val = fold_build2_loc (clause_loc,
4908 EQ_EXPR, unsigned_type_node, cond,
79acaae1 4909 build_int_cst (TREE_TYPE (cond), 0));
1e8e9920 4910 else
773c5ba7 4911 {
4912 basic_block cond_bb, then_bb, else_bb;
79acaae1 4913 edge e, e_then, e_else;
75a70cf9 4914 tree tmp_then, tmp_else, tmp_join, tmp_var;
79acaae1 4915
f9e245b2 4916 tmp_var = create_tmp_var (TREE_TYPE (val));
79acaae1 4917 if (gimple_in_ssa_p (cfun))
4918 {
f9e245b2 4919 tmp_then = make_ssa_name (tmp_var);
4920 tmp_else = make_ssa_name (tmp_var);
4921 tmp_join = make_ssa_name (tmp_var);
79acaae1 4922 }
4923 else
4924 {
4925 tmp_then = tmp_var;
4926 tmp_else = tmp_var;
4927 tmp_join = tmp_var;
4928 }
773c5ba7 4929
4302d619 4930 e = split_block_after_labels (bb);
773c5ba7 4931 cond_bb = e->src;
4932 bb = e->dest;
4933 remove_edge (e);
4934
4935 then_bb = create_empty_bb (cond_bb);
4936 else_bb = create_empty_bb (then_bb);
79acaae1 4937 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
4938 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
773c5ba7 4939
75a70cf9 4940 stmt = gimple_build_cond_empty (cond);
4941 gsi = gsi_start_bb (cond_bb);
4942 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
773c5ba7 4943
75a70cf9 4944 gsi = gsi_start_bb (then_bb);
4945 stmt = gimple_build_assign (tmp_then, val);
4946 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
773c5ba7 4947
75a70cf9 4948 gsi = gsi_start_bb (else_bb);
4949 stmt = gimple_build_assign
4950 (tmp_else, build_int_cst (unsigned_type_node, 1));
4951 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
773c5ba7 4952
4953 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
4954 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
b3083327 4955 add_bb_to_loop (then_bb, cond_bb->loop_father);
4956 add_bb_to_loop (else_bb, cond_bb->loop_father);
79acaae1 4957 e_then = make_edge (then_bb, bb, EDGE_FALLTHRU);
4958 e_else = make_edge (else_bb, bb, EDGE_FALLTHRU);
773c5ba7 4959
79acaae1 4960 if (gimple_in_ssa_p (cfun))
4961 {
1a91d914 4962 gphi *phi = create_phi_node (tmp_join, bb);
60d535d2 4963 add_phi_arg (phi, tmp_then, e_then, UNKNOWN_LOCATION);
4964 add_phi_arg (phi, tmp_else, e_else, UNKNOWN_LOCATION);
79acaae1 4965 }
4966
4967 val = tmp_join;
773c5ba7 4968 }
4969
75a70cf9 4970 gsi = gsi_start_bb (bb);
4971 val = force_gimple_operand_gsi (&gsi, val, true, NULL_TREE,
4972 false, GSI_CONTINUE_LINKING);
1e8e9920 4973 }
4974
75a70cf9 4975 gsi = gsi_last_bb (bb);
4976 t = gimple_omp_parallel_data_arg (entry_stmt);
1e8e9920 4977 if (t == NULL)
c2f47e15 4978 t1 = null_pointer_node;
1e8e9920 4979 else
c2f47e15 4980 t1 = build_fold_addr_expr (t);
75a70cf9 4981 t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
773c5ba7 4982
bc7bff74 4983 vec_alloc (args, 4 + vec_safe_length (ws_args));
f1f41a6c 4984 args->quick_push (t2);
4985 args->quick_push (t1);
4986 args->quick_push (val);
4987 if (ws_args)
4988 args->splice (*ws_args);
bc7bff74 4989 args->quick_push (flags);
414c3a2c 4990
4991 t = build_call_expr_loc_vec (UNKNOWN_LOCATION,
b9a16870 4992 builtin_decl_explicit (start_ix), args);
773c5ba7 4993
75a70cf9 4994 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
4995 false, GSI_CONTINUE_LINKING);
1e8e9920 4996}
4997
40750995 4998/* Insert a function call whose name is FUNC_NAME with the information from
4999 ENTRY_STMT into the basic_block BB. */
5000
5001static void
1a91d914 5002expand_cilk_for_call (basic_block bb, gomp_parallel *entry_stmt,
40750995 5003 vec <tree, va_gc> *ws_args)
5004{
5005 tree t, t1, t2;
5006 gimple_stmt_iterator gsi;
5007 vec <tree, va_gc> *args;
5008
5009 gcc_assert (vec_safe_length (ws_args) == 2);
5010 tree func_name = (*ws_args)[0];
5011 tree grain = (*ws_args)[1];
5012
5013 tree clauses = gimple_omp_parallel_clauses (entry_stmt);
5014 tree count = find_omp_clause (clauses, OMP_CLAUSE__CILK_FOR_COUNT_);
5015 gcc_assert (count != NULL_TREE);
5016 count = OMP_CLAUSE_OPERAND (count, 0);
5017
5018 gsi = gsi_last_bb (bb);
5019 t = gimple_omp_parallel_data_arg (entry_stmt);
5020 if (t == NULL)
5021 t1 = null_pointer_node;
5022 else
5023 t1 = build_fold_addr_expr (t);
5024 t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
5025
5026 vec_alloc (args, 4);
5027 args->quick_push (t2);
5028 args->quick_push (t1);
5029 args->quick_push (count);
5030 args->quick_push (grain);
5031 t = build_call_expr_loc_vec (UNKNOWN_LOCATION, func_name, args);
5032
5033 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, false,
5034 GSI_CONTINUE_LINKING);
5035}
773c5ba7 5036
fd6481cf 5037/* Build the function call to GOMP_task to actually
5038 generate the task operation. BB is the block where to insert the code. */
5039
5040static void
1a91d914 5041expand_task_call (basic_block bb, gomp_task *entry_stmt)
fd6481cf 5042{
bc7bff74 5043 tree t, t1, t2, t3, flags, cond, c, c2, clauses, depend;
75a70cf9 5044 gimple_stmt_iterator gsi;
389dd41b 5045 location_t loc = gimple_location (entry_stmt);
fd6481cf 5046
75a70cf9 5047 clauses = gimple_omp_task_clauses (entry_stmt);
fd6481cf 5048
fd6481cf 5049 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
5050 if (c)
5051 cond = gimple_boolify (OMP_CLAUSE_IF_EXPR (c));
5052 else
5053 cond = boolean_true_node;
5054
5055 c = find_omp_clause (clauses, OMP_CLAUSE_UNTIED);
2169f33b 5056 c2 = find_omp_clause (clauses, OMP_CLAUSE_MERGEABLE);
bc7bff74 5057 depend = find_omp_clause (clauses, OMP_CLAUSE_DEPEND);
2169f33b 5058 flags = build_int_cst (unsigned_type_node,
bc7bff74 5059 (c ? 1 : 0) + (c2 ? 4 : 0) + (depend ? 8 : 0));
2169f33b 5060
5061 c = find_omp_clause (clauses, OMP_CLAUSE_FINAL);
5062 if (c)
5063 {
5064 c = gimple_boolify (OMP_CLAUSE_FINAL_EXPR (c));
5065 c = fold_build3_loc (loc, COND_EXPR, unsigned_type_node, c,
5066 build_int_cst (unsigned_type_node, 2),
5067 build_int_cst (unsigned_type_node, 0));
5068 flags = fold_build2_loc (loc, PLUS_EXPR, unsigned_type_node, flags, c);
5069 }
bc7bff74 5070 if (depend)
5071 depend = OMP_CLAUSE_DECL (depend);
5072 else
5073 depend = build_int_cst (ptr_type_node, 0);
fd6481cf 5074
75a70cf9 5075 gsi = gsi_last_bb (bb);
5076 t = gimple_omp_task_data_arg (entry_stmt);
fd6481cf 5077 if (t == NULL)
5078 t2 = null_pointer_node;
5079 else
389dd41b 5080 t2 = build_fold_addr_expr_loc (loc, t);
5081 t1 = build_fold_addr_expr_loc (loc, gimple_omp_task_child_fn (entry_stmt));
75a70cf9 5082 t = gimple_omp_task_copy_fn (entry_stmt);
fd6481cf 5083 if (t == NULL)
5084 t3 = null_pointer_node;
5085 else
389dd41b 5086 t3 = build_fold_addr_expr_loc (loc, t);
fd6481cf 5087
b9a16870 5088 t = build_call_expr (builtin_decl_explicit (BUILT_IN_GOMP_TASK),
bc7bff74 5089 8, t1, t2, t3,
75a70cf9 5090 gimple_omp_task_arg_size (entry_stmt),
bc7bff74 5091 gimple_omp_task_arg_align (entry_stmt), cond, flags,
5092 depend);
fd6481cf 5093
75a70cf9 5094 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5095 false, GSI_CONTINUE_LINKING);
fd6481cf 5096}
5097
5098
75a70cf9 5099/* If exceptions are enabled, wrap the statements in BODY in a MUST_NOT_THROW
5100 catch handler and return it. This prevents programs from violating the
5101 structured block semantics with throws. */
1e8e9920 5102
75a70cf9 5103static gimple_seq
5104maybe_catch_exception (gimple_seq body)
1e8e9920 5105{
e38def9c 5106 gimple g;
5107 tree decl;
1e8e9920 5108
5109 if (!flag_exceptions)
75a70cf9 5110 return body;
1e8e9920 5111
596981c8 5112 if (lang_hooks.eh_protect_cleanup_actions != NULL)
5113 decl = lang_hooks.eh_protect_cleanup_actions ();
1e8e9920 5114 else
b9a16870 5115 decl = builtin_decl_explicit (BUILT_IN_TRAP);
75a70cf9 5116
e38def9c 5117 g = gimple_build_eh_must_not_throw (decl);
5118 g = gimple_build_try (body, gimple_seq_alloc_with_stmt (g),
75a70cf9 5119 GIMPLE_TRY_CATCH);
1e8e9920 5120
e38def9c 5121 return gimple_seq_alloc_with_stmt (g);
1e8e9920 5122}
5123
773c5ba7 5124/* Chain all the DECLs in LIST by their TREE_CHAIN fields. */
1e8e9920 5125
773c5ba7 5126static tree
f1f41a6c 5127vec2chain (vec<tree, va_gc> *v)
1e8e9920 5128{
2ab2ce89 5129 tree chain = NULL_TREE, t;
5130 unsigned ix;
1e8e9920 5131
f1f41a6c 5132 FOR_EACH_VEC_SAFE_ELT_REVERSE (v, ix, t)
773c5ba7 5133 {
1767a056 5134 DECL_CHAIN (t) = chain;
2ab2ce89 5135 chain = t;
773c5ba7 5136 }
1e8e9920 5137
2ab2ce89 5138 return chain;
773c5ba7 5139}
1e8e9920 5140
1e8e9920 5141
773c5ba7 5142/* Remove barriers in REGION->EXIT's block. Note that this is only
75a70cf9 5143 valid for GIMPLE_OMP_PARALLEL regions. Since the end of a parallel region
5144 is an implicit barrier, any workshare inside the GIMPLE_OMP_PARALLEL that
5145 left a barrier at the end of the GIMPLE_OMP_PARALLEL region can now be
773c5ba7 5146 removed. */
1e8e9920 5147
773c5ba7 5148static void
5149remove_exit_barrier (struct omp_region *region)
5150{
75a70cf9 5151 gimple_stmt_iterator gsi;
773c5ba7 5152 basic_block exit_bb;
61e47ac8 5153 edge_iterator ei;
5154 edge e;
75a70cf9 5155 gimple stmt;
4a04f4b4 5156 int any_addressable_vars = -1;
1e8e9920 5157
61e47ac8 5158 exit_bb = region->exit;
1e8e9920 5159
5056ba1a 5160 /* If the parallel region doesn't return, we don't have REGION->EXIT
5161 block at all. */
5162 if (! exit_bb)
5163 return;
5164
75a70cf9 5165 /* The last insn in the block will be the parallel's GIMPLE_OMP_RETURN. The
5166 workshare's GIMPLE_OMP_RETURN will be in a preceding block. The kinds of
61e47ac8 5167 statements that can appear in between are extremely limited -- no
5168 memory operations at all. Here, we allow nothing at all, so the
75a70cf9 5169 only thing we allow to precede this GIMPLE_OMP_RETURN is a label. */
5170 gsi = gsi_last_bb (exit_bb);
5171 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
5172 gsi_prev (&gsi);
5173 if (!gsi_end_p (gsi) && gimple_code (gsi_stmt (gsi)) != GIMPLE_LABEL)
773c5ba7 5174 return;
1e8e9920 5175
61e47ac8 5176 FOR_EACH_EDGE (e, ei, exit_bb->preds)
5177 {
75a70cf9 5178 gsi = gsi_last_bb (e->src);
5179 if (gsi_end_p (gsi))
61e47ac8 5180 continue;
75a70cf9 5181 stmt = gsi_stmt (gsi);
4a04f4b4 5182 if (gimple_code (stmt) == GIMPLE_OMP_RETURN
5183 && !gimple_omp_return_nowait_p (stmt))
5184 {
5185 /* OpenMP 3.0 tasks unfortunately prevent this optimization
5186 in many cases. If there could be tasks queued, the barrier
5187 might be needed to let the tasks run before some local
5188 variable of the parallel that the task uses as shared
5189 runs out of scope. The task can be spawned either
5190 from within current function (this would be easy to check)
5191 or from some function it calls and gets passed an address
5192 of such a variable. */
5193 if (any_addressable_vars < 0)
5194 {
1a91d914 5195 gomp_parallel *parallel_stmt
5196 = as_a <gomp_parallel *> (last_stmt (region->entry));
4a04f4b4 5197 tree child_fun = gimple_omp_parallel_child_fn (parallel_stmt);
2ab2ce89 5198 tree local_decls, block, decl;
5199 unsigned ix;
4a04f4b4 5200
5201 any_addressable_vars = 0;
2ab2ce89 5202 FOR_EACH_LOCAL_DECL (DECL_STRUCT_FUNCTION (child_fun), ix, decl)
5203 if (TREE_ADDRESSABLE (decl))
4a04f4b4 5204 {
5205 any_addressable_vars = 1;
5206 break;
5207 }
5208 for (block = gimple_block (stmt);
5209 !any_addressable_vars
5210 && block
5211 && TREE_CODE (block) == BLOCK;
5212 block = BLOCK_SUPERCONTEXT (block))
5213 {
5214 for (local_decls = BLOCK_VARS (block);
5215 local_decls;
1767a056 5216 local_decls = DECL_CHAIN (local_decls))
4a04f4b4 5217 if (TREE_ADDRESSABLE (local_decls))
5218 {
5219 any_addressable_vars = 1;
5220 break;
5221 }
5222 if (block == gimple_block (parallel_stmt))
5223 break;
5224 }
5225 }
5226 if (!any_addressable_vars)
5227 gimple_omp_return_set_nowait (stmt);
5228 }
61e47ac8 5229 }
1e8e9920 5230}
5231
61e47ac8 5232static void
5233remove_exit_barriers (struct omp_region *region)
5234{
75a70cf9 5235 if (region->type == GIMPLE_OMP_PARALLEL)
61e47ac8 5236 remove_exit_barrier (region);
5237
5238 if (region->inner)
5239 {
5240 region = region->inner;
5241 remove_exit_barriers (region);
5242 while (region->next)
5243 {
5244 region = region->next;
5245 remove_exit_barriers (region);
5246 }
5247 }
5248}
773c5ba7 5249
658b4427 5250/* Optimize omp_get_thread_num () and omp_get_num_threads ()
5251 calls. These can't be declared as const functions, but
5252 within one parallel body they are constant, so they can be
5253 transformed there into __builtin_omp_get_{thread_num,num_threads} ()
fd6481cf 5254 which are declared const. Similarly for task body, except
5255 that in untied task omp_get_thread_num () can change at any task
5256 scheduling point. */
658b4427 5257
5258static void
75a70cf9 5259optimize_omp_library_calls (gimple entry_stmt)
658b4427 5260{
5261 basic_block bb;
75a70cf9 5262 gimple_stmt_iterator gsi;
b9a16870 5263 tree thr_num_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
5264 tree thr_num_id = DECL_ASSEMBLER_NAME (thr_num_tree);
5265 tree num_thr_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
5266 tree num_thr_id = DECL_ASSEMBLER_NAME (num_thr_tree);
75a70cf9 5267 bool untied_task = (gimple_code (entry_stmt) == GIMPLE_OMP_TASK
5268 && find_omp_clause (gimple_omp_task_clauses (entry_stmt),
fd6481cf 5269 OMP_CLAUSE_UNTIED) != NULL);
658b4427 5270
fc00614f 5271 FOR_EACH_BB_FN (bb, cfun)
75a70cf9 5272 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
658b4427 5273 {
75a70cf9 5274 gimple call = gsi_stmt (gsi);
658b4427 5275 tree decl;
5276
75a70cf9 5277 if (is_gimple_call (call)
5278 && (decl = gimple_call_fndecl (call))
658b4427 5279 && DECL_EXTERNAL (decl)
5280 && TREE_PUBLIC (decl)
5281 && DECL_INITIAL (decl) == NULL)
5282 {
5283 tree built_in;
5284
5285 if (DECL_NAME (decl) == thr_num_id)
fd6481cf 5286 {
5287 /* In #pragma omp task untied omp_get_thread_num () can change
5288 during the execution of the task region. */
5289 if (untied_task)
5290 continue;
b9a16870 5291 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
fd6481cf 5292 }
658b4427 5293 else if (DECL_NAME (decl) == num_thr_id)
b9a16870 5294 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
658b4427 5295 else
5296 continue;
5297
5298 if (DECL_ASSEMBLER_NAME (decl) != DECL_ASSEMBLER_NAME (built_in)
75a70cf9 5299 || gimple_call_num_args (call) != 0)
658b4427 5300 continue;
5301
5302 if (flag_exceptions && !TREE_NOTHROW (decl))
5303 continue;
5304
5305 if (TREE_CODE (TREE_TYPE (decl)) != FUNCTION_TYPE
1ea6a73c 5306 || !types_compatible_p (TREE_TYPE (TREE_TYPE (decl)),
5307 TREE_TYPE (TREE_TYPE (built_in))))
658b4427 5308 continue;
5309
0acacf9e 5310 gimple_call_set_fndecl (call, built_in);
658b4427 5311 }
5312 }
5313}
5314
8e6b4515 5315/* Callback for expand_omp_build_assign. Return non-NULL if *tp needs to be
5316 regimplified. */
5317
5318static tree
5319expand_omp_regimplify_p (tree *tp, int *walk_subtrees, void *)
5320{
5321 tree t = *tp;
5322
5323 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
5324 if (TREE_CODE (t) == VAR_DECL && DECL_HAS_VALUE_EXPR_P (t))
5325 return t;
5326
5327 if (TREE_CODE (t) == ADDR_EXPR)
5328 recompute_tree_invariant_for_addr_expr (t);
5329
5330 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
5331 return NULL_TREE;
5332}
5333
3d483a94 5334/* Prepend TO = FROM assignment before *GSI_P. */
5335
5336static void
5337expand_omp_build_assign (gimple_stmt_iterator *gsi_p, tree to, tree from)
5338{
5339 bool simple_p = DECL_P (to) && TREE_ADDRESSABLE (to);
5340 from = force_gimple_operand_gsi (gsi_p, from, simple_p, NULL_TREE,
5341 true, GSI_SAME_STMT);
5342 gimple stmt = gimple_build_assign (to, from);
5343 gsi_insert_before (gsi_p, stmt, GSI_SAME_STMT);
5344 if (walk_tree (&from, expand_omp_regimplify_p, NULL, NULL)
5345 || walk_tree (&to, expand_omp_regimplify_p, NULL, NULL))
5346 {
5347 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
5348 gimple_regimplify_operands (stmt, &gsi);
5349 }
5350}
5351
fd6481cf 5352/* Expand the OpenMP parallel or task directive starting at REGION. */
1e8e9920 5353
5354static void
fd6481cf 5355expand_omp_taskreg (struct omp_region *region)
1e8e9920 5356{
773c5ba7 5357 basic_block entry_bb, exit_bb, new_bb;
87d4aa85 5358 struct function *child_cfun;
414c3a2c 5359 tree child_fn, block, t;
75a70cf9 5360 gimple_stmt_iterator gsi;
5361 gimple entry_stmt, stmt;
773c5ba7 5362 edge e;
f1f41a6c 5363 vec<tree, va_gc> *ws_args;
773c5ba7 5364
61e47ac8 5365 entry_stmt = last_stmt (region->entry);
75a70cf9 5366 child_fn = gimple_omp_taskreg_child_fn (entry_stmt);
773c5ba7 5367 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
773c5ba7 5368
61e47ac8 5369 entry_bb = region->entry;
b25f70fd 5370 if (gimple_code (entry_stmt) == GIMPLE_OMP_TASK)
5371 exit_bb = region->cont;
5372 else
5373 exit_bb = region->exit;
773c5ba7 5374
40750995 5375 bool is_cilk_for
5376 = (flag_cilkplus
5377 && gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL
5378 && find_omp_clause (gimple_omp_parallel_clauses (entry_stmt),
5379 OMP_CLAUSE__CILK_FOR_COUNT_) != NULL_TREE);
5380
5381 if (is_cilk_for)
5382 /* If it is a _Cilk_for statement, it is modelled *like* a parallel for,
5383 and the inner statement contains the name of the built-in function
5384 and grain. */
5385 ws_args = region->inner->ws_args;
5386 else if (is_combined_parallel (region))
61e47ac8 5387 ws_args = region->ws_args;
773c5ba7 5388 else
414c3a2c 5389 ws_args = NULL;
1e8e9920 5390
61e47ac8 5391 if (child_cfun->cfg)
1e8e9920 5392 {
773c5ba7 5393 /* Due to inlining, it may happen that we have already outlined
5394 the region, in which case all we need to do is make the
5395 sub-graph unreachable and emit the parallel call. */
5396 edge entry_succ_e, exit_succ_e;
773c5ba7 5397
5398 entry_succ_e = single_succ_edge (entry_bb);
773c5ba7 5399
75a70cf9 5400 gsi = gsi_last_bb (entry_bb);
5401 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_PARALLEL
5402 || gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_TASK);
5403 gsi_remove (&gsi, true);
773c5ba7 5404
5405 new_bb = entry_bb;
03ed154b 5406 if (exit_bb)
5407 {
5408 exit_succ_e = single_succ_edge (exit_bb);
5409 make_edge (new_bb, exit_succ_e->dest, EDGE_FALLTHRU);
5410 }
79acaae1 5411 remove_edge_and_dominated_blocks (entry_succ_e);
1e8e9920 5412 }
773c5ba7 5413 else
5414 {
501bdd19 5415 unsigned srcidx, dstidx, num;
2ab2ce89 5416
773c5ba7 5417 /* If the parallel region needs data sent from the parent
3480139d 5418 function, then the very first statement (except possible
5419 tree profile counter updates) of the parallel body
773c5ba7 5420 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
5421 &.OMP_DATA_O is passed as an argument to the child function,
5422 we need to replace it with the argument as seen by the child
5423 function.
5424
5425 In most cases, this will end up being the identity assignment
5426 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
5427 a function call that has been inlined, the original PARM_DECL
5428 .OMP_DATA_I may have been converted into a different local
5429 variable. In which case, we need to keep the assignment. */
75a70cf9 5430 if (gimple_omp_taskreg_data_arg (entry_stmt))
773c5ba7 5431 {
b25f70fd 5432 basic_block entry_succ_bb
5433 = single_succ_p (entry_bb) ? single_succ (entry_bb)
5434 : FALLTHRU_EDGE (entry_bb)->dest;
75a70cf9 5435 tree arg, narg;
5436 gimple parcopy_stmt = NULL;
1e8e9920 5437
75a70cf9 5438 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
3480139d 5439 {
75a70cf9 5440 gimple stmt;
3480139d 5441
75a70cf9 5442 gcc_assert (!gsi_end_p (gsi));
5443 stmt = gsi_stmt (gsi);
5444 if (gimple_code (stmt) != GIMPLE_ASSIGN)
cc6b725b 5445 continue;
5446
75a70cf9 5447 if (gimple_num_ops (stmt) == 2)
3480139d 5448 {
75a70cf9 5449 tree arg = gimple_assign_rhs1 (stmt);
5450
5451 /* We're ignore the subcode because we're
5452 effectively doing a STRIP_NOPS. */
5453
5454 if (TREE_CODE (arg) == ADDR_EXPR
5455 && TREE_OPERAND (arg, 0)
5456 == gimple_omp_taskreg_data_arg (entry_stmt))
5457 {
5458 parcopy_stmt = stmt;
5459 break;
5460 }
3480139d 5461 }
5462 }
79acaae1 5463
75a70cf9 5464 gcc_assert (parcopy_stmt != NULL);
79acaae1 5465 arg = DECL_ARGUMENTS (child_fn);
5466
5467 if (!gimple_in_ssa_p (cfun))
5468 {
75a70cf9 5469 if (gimple_assign_lhs (parcopy_stmt) == arg)
5470 gsi_remove (&gsi, true);
79acaae1 5471 else
75a70cf9 5472 {
5473 /* ?? Is setting the subcode really necessary ?? */
5474 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (arg));
5475 gimple_assign_set_rhs1 (parcopy_stmt, arg);
5476 }
79acaae1 5477 }
5478 else
5479 {
5480 /* If we are in ssa form, we must load the value from the default
5481 definition of the argument. That should not be defined now,
5482 since the argument is not used uninitialized. */
c6dfe037 5483 gcc_assert (ssa_default_def (cfun, arg) == NULL);
75a70cf9 5484 narg = make_ssa_name (arg, gimple_build_nop ());
c6dfe037 5485 set_ssa_default_def (cfun, arg, narg);
75a70cf9 5486 /* ?? Is setting the subcode really necessary ?? */
5487 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (narg));
5488 gimple_assign_set_rhs1 (parcopy_stmt, narg);
79acaae1 5489 update_stmt (parcopy_stmt);
5490 }
773c5ba7 5491 }
5492
5493 /* Declare local variables needed in CHILD_CFUN. */
5494 block = DECL_INITIAL (child_fn);
2ab2ce89 5495 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
e1a7ccb9 5496 /* The gimplifier could record temporaries in parallel/task block
5497 rather than in containing function's local_decls chain,
5498 which would mean cgraph missed finalizing them. Do it now. */
1767a056 5499 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
e1a7ccb9 5500 if (TREE_CODE (t) == VAR_DECL
5501 && TREE_STATIC (t)
5502 && !DECL_EXTERNAL (t))
97221fd7 5503 varpool_node::finalize_decl (t);
75a70cf9 5504 DECL_SAVED_TREE (child_fn) = NULL;
e3a19533 5505 /* We'll create a CFG for child_fn, so no gimple body is needed. */
5506 gimple_set_body (child_fn, NULL);
1d22f541 5507 TREE_USED (block) = 1;
773c5ba7 5508
79acaae1 5509 /* Reset DECL_CONTEXT on function arguments. */
1767a056 5510 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
773c5ba7 5511 DECL_CONTEXT (t) = child_fn;
5512
75a70cf9 5513 /* Split ENTRY_BB at GIMPLE_OMP_PARALLEL or GIMPLE_OMP_TASK,
5514 so that it can be moved to the child function. */
5515 gsi = gsi_last_bb (entry_bb);
5516 stmt = gsi_stmt (gsi);
5517 gcc_assert (stmt && (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
5518 || gimple_code (stmt) == GIMPLE_OMP_TASK));
75a70cf9 5519 e = split_block (entry_bb, stmt);
923635e7 5520 gsi_remove (&gsi, true);
773c5ba7 5521 entry_bb = e->dest;
b25f70fd 5522 edge e2 = NULL;
5523 if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
5524 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
5525 else
5526 {
5527 e2 = make_edge (e->src, BRANCH_EDGE (entry_bb)->dest, EDGE_ABNORMAL);
5528 gcc_assert (e2->dest == region->exit);
5529 remove_edge (BRANCH_EDGE (entry_bb));
5530 set_immediate_dominator (CDI_DOMINATORS, e2->dest, e->src);
5531 gsi = gsi_last_bb (region->exit);
5532 gcc_assert (!gsi_end_p (gsi)
5533 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
5534 gsi_remove (&gsi, true);
5535 }
773c5ba7 5536
b25f70fd 5537 /* Convert GIMPLE_OMP_{RETURN,CONTINUE} into a RETURN_EXPR. */
5056ba1a 5538 if (exit_bb)
5539 {
75a70cf9 5540 gsi = gsi_last_bb (exit_bb);
5541 gcc_assert (!gsi_end_p (gsi)
b25f70fd 5542 && (gimple_code (gsi_stmt (gsi))
5543 == (e2 ? GIMPLE_OMP_CONTINUE : GIMPLE_OMP_RETURN)));
75a70cf9 5544 stmt = gimple_build_return (NULL);
5545 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
5546 gsi_remove (&gsi, true);
5056ba1a 5547 }
79acaae1 5548
5549 /* Move the parallel region into CHILD_CFUN. */
48e1416a 5550
79acaae1 5551 if (gimple_in_ssa_p (cfun))
5552 {
bcaa2770 5553 init_tree_ssa (child_cfun);
5084b2e4 5554 init_ssa_operands (child_cfun);
5555 child_cfun->gimple_df->in_ssa_p = true;
1d22f541 5556 block = NULL_TREE;
79acaae1 5557 }
1d22f541 5558 else
75a70cf9 5559 block = gimple_block (entry_stmt);
1d22f541 5560
5561 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
79acaae1 5562 if (exit_bb)
5563 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
b25f70fd 5564 if (e2)
5565 {
5566 basic_block dest_bb = e2->dest;
5567 if (!exit_bb)
5568 make_edge (new_bb, dest_bb, EDGE_FALLTHRU);
5569 remove_edge (e2);
5570 set_immediate_dominator (CDI_DOMINATORS, dest_bb, new_bb);
5571 }
04c2922b 5572 /* When the OMP expansion process cannot guarantee an up-to-date
5573 loop tree arrange for the child function to fixup loops. */
5574 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
5575 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
79acaae1 5576
1d22f541 5577 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
f1f41a6c 5578 num = vec_safe_length (child_cfun->local_decls);
501bdd19 5579 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
5580 {
f1f41a6c 5581 t = (*child_cfun->local_decls)[srcidx];
501bdd19 5582 if (DECL_CONTEXT (t) == cfun->decl)
5583 continue;
5584 if (srcidx != dstidx)
f1f41a6c 5585 (*child_cfun->local_decls)[dstidx] = t;
501bdd19 5586 dstidx++;
5587 }
5588 if (dstidx != num)
f1f41a6c 5589 vec_safe_truncate (child_cfun->local_decls, dstidx);
1d22f541 5590
79acaae1 5591 /* Inform the callgraph about the new function. */
82b40354 5592 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
47300487 5593 cgraph_node *node = cgraph_node::get_create (child_fn);
5594 node->parallelized_function = 1;
415d1b9a 5595 cgraph_node::add_new_function (child_fn, true);
79acaae1 5596
5597 /* Fix the callgraph edges for child_cfun. Those for cfun will be
5598 fixed in a following pass. */
5599 push_cfun (child_cfun);
658b4427 5600 if (optimize)
fd6481cf 5601 optimize_omp_library_calls (entry_stmt);
35ee1c66 5602 cgraph_edge::rebuild_edges ();
fbe86b1b 5603
5604 /* Some EH regions might become dead, see PR34608. If
5605 pass_cleanup_cfg isn't the first pass to happen with the
5606 new child, these dead EH edges might cause problems.
5607 Clean them up now. */
5608 if (flag_exceptions)
5609 {
5610 basic_block bb;
fbe86b1b 5611 bool changed = false;
5612
fc00614f 5613 FOR_EACH_BB_FN (bb, cfun)
75a70cf9 5614 changed |= gimple_purge_dead_eh_edges (bb);
fbe86b1b 5615 if (changed)
5616 cleanup_tree_cfg ();
fbe86b1b 5617 }
dd277d48 5618 if (gimple_in_ssa_p (cfun))
5619 update_ssa (TODO_update_ssa);
79acaae1 5620 pop_cfun ();
773c5ba7 5621 }
48e1416a 5622
773c5ba7 5623 /* Emit a library call to launch the children threads. */
40750995 5624 if (is_cilk_for)
1a91d914 5625 expand_cilk_for_call (new_bb,
5626 as_a <gomp_parallel *> (entry_stmt), ws_args);
40750995 5627 else if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
1a91d914 5628 expand_parallel_call (region, new_bb,
5629 as_a <gomp_parallel *> (entry_stmt), ws_args);
fd6481cf 5630 else
1a91d914 5631 expand_task_call (new_bb, as_a <gomp_task *> (entry_stmt));
083152fb 5632 if (gimple_in_ssa_p (cfun))
5633 update_ssa (TODO_update_ssa_only_virtuals);
1e8e9920 5634}
5635
773c5ba7 5636
3d483a94 5637/* Helper function for expand_omp_{for_*,simd}. If this is the outermost
5638 of the combined collapse > 1 loop constructs, generate code like:
5639 if (__builtin_expect (N32 cond3 N31, 0)) goto ZERO_ITER_BB;
5640 if (cond3 is <)
5641 adj = STEP3 - 1;
5642 else
5643 adj = STEP3 + 1;
5644 count3 = (adj + N32 - N31) / STEP3;
5645 if (__builtin_expect (N22 cond2 N21, 0)) goto ZERO_ITER_BB;
5646 if (cond2 is <)
5647 adj = STEP2 - 1;
5648 else
5649 adj = STEP2 + 1;
5650 count2 = (adj + N22 - N21) / STEP2;
5651 if (__builtin_expect (N12 cond1 N11, 0)) goto ZERO_ITER_BB;
5652 if (cond1 is <)
5653 adj = STEP1 - 1;
5654 else
5655 adj = STEP1 + 1;
5656 count1 = (adj + N12 - N11) / STEP1;
5657 count = count1 * count2 * count3;
5658 Furthermore, if ZERO_ITER_BB is NULL, create a BB which does:
5659 count = 0;
bc7bff74 5660 and set ZERO_ITER_BB to that bb. If this isn't the outermost
5661 of the combined loop constructs, just initialize COUNTS array
5662 from the _looptemp_ clauses. */
3d483a94 5663
5664/* NOTE: It *could* be better to moosh all of the BBs together,
5665 creating one larger BB with all the computation and the unexpected
5666 jump at the end. I.e.
5667
5668 bool zero3, zero2, zero1, zero;
5669
5670 zero3 = N32 c3 N31;
5671 count3 = (N32 - N31) /[cl] STEP3;
5672 zero2 = N22 c2 N21;
5673 count2 = (N22 - N21) /[cl] STEP2;
5674 zero1 = N12 c1 N11;
5675 count1 = (N12 - N11) /[cl] STEP1;
5676 zero = zero3 || zero2 || zero1;
5677 count = count1 * count2 * count3;
5678 if (__builtin_expect(zero, false)) goto zero_iter_bb;
5679
5680 After all, we expect the zero=false, and thus we expect to have to
5681 evaluate all of the comparison expressions, so short-circuiting
5682 oughtn't be a win. Since the condition isn't protecting a
5683 denominator, we're not concerned about divide-by-zero, so we can
5684 fully evaluate count even if a numerator turned out to be wrong.
5685
5686 It seems like putting this all together would create much better
5687 scheduling opportunities, and less pressure on the chip's branch
5688 predictor. */
5689
5690static void
5691expand_omp_for_init_counts (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
5692 basic_block &entry_bb, tree *counts,
5693 basic_block &zero_iter_bb, int &first_zero_iter,
5694 basic_block &l2_dom_bb)
5695{
5696 tree t, type = TREE_TYPE (fd->loop.v);
3d483a94 5697 edge e, ne;
5698 int i;
5699
5700 /* Collapsed loops need work for expansion into SSA form. */
5701 gcc_assert (!gimple_in_ssa_p (cfun));
5702
bc7bff74 5703 if (gimple_omp_for_combined_into_p (fd->for_stmt)
5704 && TREE_CODE (fd->loop.n2) != INTEGER_CST)
5705 {
5706 /* First two _looptemp_ clauses are for istart/iend, counts[0]
5707 isn't supposed to be handled, as the inner loop doesn't
5708 use it. */
5709 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
5710 OMP_CLAUSE__LOOPTEMP_);
5711 gcc_assert (innerc);
5712 for (i = 0; i < fd->collapse; i++)
5713 {
5714 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5715 OMP_CLAUSE__LOOPTEMP_);
5716 gcc_assert (innerc);
5717 if (i)
5718 counts[i] = OMP_CLAUSE_DECL (innerc);
5719 else
5720 counts[0] = NULL_TREE;
5721 }
5722 return;
5723 }
5724
3d483a94 5725 for (i = 0; i < fd->collapse; i++)
5726 {
5727 tree itype = TREE_TYPE (fd->loops[i].v);
5728
5729 if (SSA_VAR_P (fd->loop.n2)
5730 && ((t = fold_binary (fd->loops[i].cond_code, boolean_type_node,
5731 fold_convert (itype, fd->loops[i].n1),
5732 fold_convert (itype, fd->loops[i].n2)))
5733 == NULL_TREE || !integer_onep (t)))
5734 {
1a91d914 5735 gcond *cond_stmt;
3d483a94 5736 tree n1, n2;
5737 n1 = fold_convert (itype, unshare_expr (fd->loops[i].n1));
5738 n1 = force_gimple_operand_gsi (gsi, n1, true, NULL_TREE,
5739 true, GSI_SAME_STMT);
5740 n2 = fold_convert (itype, unshare_expr (fd->loops[i].n2));
5741 n2 = force_gimple_operand_gsi (gsi, n2, true, NULL_TREE,
5742 true, GSI_SAME_STMT);
1a91d914 5743 cond_stmt = gimple_build_cond (fd->loops[i].cond_code, n1, n2,
5744 NULL_TREE, NULL_TREE);
5745 gsi_insert_before (gsi, cond_stmt, GSI_SAME_STMT);
5746 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
3d483a94 5747 expand_omp_regimplify_p, NULL, NULL)
1a91d914 5748 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
3d483a94 5749 expand_omp_regimplify_p, NULL, NULL))
5750 {
1a91d914 5751 *gsi = gsi_for_stmt (cond_stmt);
5752 gimple_regimplify_operands (cond_stmt, gsi);
3d483a94 5753 }
1a91d914 5754 e = split_block (entry_bb, cond_stmt);
3d483a94 5755 if (zero_iter_bb == NULL)
5756 {
1a91d914 5757 gassign *assign_stmt;
3d483a94 5758 first_zero_iter = i;
5759 zero_iter_bb = create_empty_bb (entry_bb);
b3083327 5760 add_bb_to_loop (zero_iter_bb, entry_bb->loop_father);
3d483a94 5761 *gsi = gsi_after_labels (zero_iter_bb);
1a91d914 5762 assign_stmt = gimple_build_assign (fd->loop.n2,
5763 build_zero_cst (type));
5764 gsi_insert_before (gsi, assign_stmt, GSI_SAME_STMT);
3d483a94 5765 set_immediate_dominator (CDI_DOMINATORS, zero_iter_bb,
5766 entry_bb);
5767 }
5768 ne = make_edge (entry_bb, zero_iter_bb, EDGE_FALSE_VALUE);
5769 ne->probability = REG_BR_PROB_BASE / 2000 - 1;
5770 e->flags = EDGE_TRUE_VALUE;
5771 e->probability = REG_BR_PROB_BASE - ne->probability;
5772 if (l2_dom_bb == NULL)
5773 l2_dom_bb = entry_bb;
5774 entry_bb = e->dest;
5775 *gsi = gsi_last_bb (entry_bb);
5776 }
5777
5778 if (POINTER_TYPE_P (itype))
5779 itype = signed_type_for (itype);
5780 t = build_int_cst (itype, (fd->loops[i].cond_code == LT_EXPR
5781 ? -1 : 1));
5782 t = fold_build2 (PLUS_EXPR, itype,
5783 fold_convert (itype, fd->loops[i].step), t);
5784 t = fold_build2 (PLUS_EXPR, itype, t,
5785 fold_convert (itype, fd->loops[i].n2));
5786 t = fold_build2 (MINUS_EXPR, itype, t,
5787 fold_convert (itype, fd->loops[i].n1));
5788 /* ?? We could probably use CEIL_DIV_EXPR instead of
5789 TRUNC_DIV_EXPR and adjusting by hand. Unless we can't
5790 generate the same code in the end because generically we
5791 don't know that the values involved must be negative for
5792 GT?? */
5793 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
5794 t = fold_build2 (TRUNC_DIV_EXPR, itype,
5795 fold_build1 (NEGATE_EXPR, itype, t),
5796 fold_build1 (NEGATE_EXPR, itype,
5797 fold_convert (itype,
5798 fd->loops[i].step)));
5799 else
5800 t = fold_build2 (TRUNC_DIV_EXPR, itype, t,
5801 fold_convert (itype, fd->loops[i].step));
5802 t = fold_convert (type, t);
5803 if (TREE_CODE (t) == INTEGER_CST)
5804 counts[i] = t;
5805 else
5806 {
5807 counts[i] = create_tmp_reg (type, ".count");
5808 expand_omp_build_assign (gsi, counts[i], t);
5809 }
5810 if (SSA_VAR_P (fd->loop.n2))
5811 {
5812 if (i == 0)
5813 t = counts[0];
5814 else
5815 t = fold_build2 (MULT_EXPR, type, fd->loop.n2, counts[i]);
5816 expand_omp_build_assign (gsi, fd->loop.n2, t);
5817 }
5818 }
5819}
5820
5821
5822/* Helper function for expand_omp_{for_*,simd}. Generate code like:
5823 T = V;
5824 V3 = N31 + (T % count3) * STEP3;
5825 T = T / count3;
5826 V2 = N21 + (T % count2) * STEP2;
5827 T = T / count2;
5828 V1 = N11 + T * STEP1;
bc7bff74 5829 if this loop doesn't have an inner loop construct combined with it.
5830 If it does have an inner loop construct combined with it and the
5831 iteration count isn't known constant, store values from counts array
5832 into its _looptemp_ temporaries instead. */
3d483a94 5833
5834static void
5835expand_omp_for_init_vars (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
bc7bff74 5836 tree *counts, gimple inner_stmt, tree startvar)
3d483a94 5837{
5838 int i;
bc7bff74 5839 if (gimple_omp_for_combined_p (fd->for_stmt))
5840 {
5841 /* If fd->loop.n2 is constant, then no propagation of the counts
5842 is needed, they are constant. */
5843 if (TREE_CODE (fd->loop.n2) == INTEGER_CST)
5844 return;
5845
5846 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
5847 ? gimple_omp_parallel_clauses (inner_stmt)
5848 : gimple_omp_for_clauses (inner_stmt);
5849 /* First two _looptemp_ clauses are for istart/iend, counts[0]
5850 isn't supposed to be handled, as the inner loop doesn't
5851 use it. */
5852 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
5853 gcc_assert (innerc);
5854 for (i = 0; i < fd->collapse; i++)
5855 {
5856 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5857 OMP_CLAUSE__LOOPTEMP_);
5858 gcc_assert (innerc);
5859 if (i)
5860 {
5861 tree tem = OMP_CLAUSE_DECL (innerc);
5862 tree t = fold_convert (TREE_TYPE (tem), counts[i]);
5863 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
5864 false, GSI_CONTINUE_LINKING);
1a91d914 5865 gassign *stmt = gimple_build_assign (tem, t);
bc7bff74 5866 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5867 }
5868 }
5869 return;
5870 }
5871
3d483a94 5872 tree type = TREE_TYPE (fd->loop.v);
5873 tree tem = create_tmp_reg (type, ".tem");
1a91d914 5874 gassign *stmt = gimple_build_assign (tem, startvar);
3d483a94 5875 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5876
5877 for (i = fd->collapse - 1; i >= 0; i--)
5878 {
5879 tree vtype = TREE_TYPE (fd->loops[i].v), itype, t;
5880 itype = vtype;
5881 if (POINTER_TYPE_P (vtype))
5882 itype = signed_type_for (vtype);
5883 if (i != 0)
5884 t = fold_build2 (TRUNC_MOD_EXPR, type, tem, counts[i]);
5885 else
5886 t = tem;
5887 t = fold_convert (itype, t);
5888 t = fold_build2 (MULT_EXPR, itype, t,
5889 fold_convert (itype, fd->loops[i].step));
5890 if (POINTER_TYPE_P (vtype))
5891 t = fold_build_pointer_plus (fd->loops[i].n1, t);
5892 else
5893 t = fold_build2 (PLUS_EXPR, itype, fd->loops[i].n1, t);
5894 t = force_gimple_operand_gsi (gsi, t,
5895 DECL_P (fd->loops[i].v)
5896 && TREE_ADDRESSABLE (fd->loops[i].v),
5897 NULL_TREE, false,
5898 GSI_CONTINUE_LINKING);
5899 stmt = gimple_build_assign (fd->loops[i].v, t);
5900 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5901 if (i != 0)
5902 {
5903 t = fold_build2 (TRUNC_DIV_EXPR, type, tem, counts[i]);
5904 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
5905 false, GSI_CONTINUE_LINKING);
5906 stmt = gimple_build_assign (tem, t);
5907 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5908 }
5909 }
5910}
5911
5912
5913/* Helper function for expand_omp_for_*. Generate code like:
5914 L10:
5915 V3 += STEP3;
5916 if (V3 cond3 N32) goto BODY_BB; else goto L11;
5917 L11:
5918 V3 = N31;
5919 V2 += STEP2;
5920 if (V2 cond2 N22) goto BODY_BB; else goto L12;
5921 L12:
5922 V2 = N21;
5923 V1 += STEP1;
5924 goto BODY_BB; */
5925
5926static basic_block
5927extract_omp_for_update_vars (struct omp_for_data *fd, basic_block cont_bb,
5928 basic_block body_bb)
5929{
5930 basic_block last_bb, bb, collapse_bb = NULL;
5931 int i;
5932 gimple_stmt_iterator gsi;
5933 edge e;
5934 tree t;
5935 gimple stmt;
5936
5937 last_bb = cont_bb;
5938 for (i = fd->collapse - 1; i >= 0; i--)
5939 {
5940 tree vtype = TREE_TYPE (fd->loops[i].v);
5941
5942 bb = create_empty_bb (last_bb);
b3083327 5943 add_bb_to_loop (bb, last_bb->loop_father);
3d483a94 5944 gsi = gsi_start_bb (bb);
5945
5946 if (i < fd->collapse - 1)
5947 {
5948 e = make_edge (last_bb, bb, EDGE_FALSE_VALUE);
5949 e->probability = REG_BR_PROB_BASE / 8;
5950
5951 t = fd->loops[i + 1].n1;
5952 t = force_gimple_operand_gsi (&gsi, t,
5953 DECL_P (fd->loops[i + 1].v)
5954 && TREE_ADDRESSABLE (fd->loops[i
5955 + 1].v),
5956 NULL_TREE, false,
5957 GSI_CONTINUE_LINKING);
5958 stmt = gimple_build_assign (fd->loops[i + 1].v, t);
5959 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5960 }
5961 else
5962 collapse_bb = bb;
5963
5964 set_immediate_dominator (CDI_DOMINATORS, bb, last_bb);
5965
5966 if (POINTER_TYPE_P (vtype))
5967 t = fold_build_pointer_plus (fd->loops[i].v, fd->loops[i].step);
5968 else
5969 t = fold_build2 (PLUS_EXPR, vtype, fd->loops[i].v, fd->loops[i].step);
5970 t = force_gimple_operand_gsi (&gsi, t,
5971 DECL_P (fd->loops[i].v)
5972 && TREE_ADDRESSABLE (fd->loops[i].v),
5973 NULL_TREE, false, GSI_CONTINUE_LINKING);
5974 stmt = gimple_build_assign (fd->loops[i].v, t);
5975 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5976
5977 if (i > 0)
5978 {
5979 t = fd->loops[i].n2;
5980 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5981 false, GSI_CONTINUE_LINKING);
5982 tree v = fd->loops[i].v;
5983 if (DECL_P (v) && TREE_ADDRESSABLE (v))
5984 v = force_gimple_operand_gsi (&gsi, v, true, NULL_TREE,
5985 false, GSI_CONTINUE_LINKING);
5986 t = fold_build2 (fd->loops[i].cond_code, boolean_type_node, v, t);
5987 stmt = gimple_build_cond_empty (t);
5988 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5989 e = make_edge (bb, body_bb, EDGE_TRUE_VALUE);
5990 e->probability = REG_BR_PROB_BASE * 7 / 8;
5991 }
5992 else
5993 make_edge (bb, body_bb, EDGE_FALLTHRU);
5994 last_bb = bb;
5995 }
5996
5997 return collapse_bb;
5998}
5999
6000
773c5ba7 6001/* A subroutine of expand_omp_for. Generate code for a parallel
1e8e9920 6002 loop with any schedule. Given parameters:
6003
6004 for (V = N1; V cond N2; V += STEP) BODY;
6005
6006 where COND is "<" or ">", we generate pseudocode
6007
6008 more = GOMP_loop_foo_start (N1, N2, STEP, CHUNK, &istart0, &iend0);
773c5ba7 6009 if (more) goto L0; else goto L3;
1e8e9920 6010 L0:
6011 V = istart0;
6012 iend = iend0;
6013 L1:
6014 BODY;
6015 V += STEP;
773c5ba7 6016 if (V cond iend) goto L1; else goto L2;
1e8e9920 6017 L2:
773c5ba7 6018 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
6019 L3:
1e8e9920 6020
773c5ba7 6021 If this is a combined omp parallel loop, instead of the call to
fd6481cf 6022 GOMP_loop_foo_start, we call GOMP_loop_foo_next.
bc7bff74 6023 If this is gimple_omp_for_combined_p loop, then instead of assigning
6024 V and iend in L0 we assign the first two _looptemp_ clause decls of the
6025 inner GIMPLE_OMP_FOR and V += STEP; and
6026 if (V cond iend) goto L1; else goto L2; are removed.
fd6481cf 6027
6028 For collapsed loops, given parameters:
6029 collapse(3)
6030 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
6031 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
6032 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
6033 BODY;
6034
6035 we generate pseudocode
6036
8e6b4515 6037 if (__builtin_expect (N32 cond3 N31, 0)) goto Z0;
fd6481cf 6038 if (cond3 is <)
6039 adj = STEP3 - 1;
6040 else
6041 adj = STEP3 + 1;
6042 count3 = (adj + N32 - N31) / STEP3;
8e6b4515 6043 if (__builtin_expect (N22 cond2 N21, 0)) goto Z0;
fd6481cf 6044 if (cond2 is <)
6045 adj = STEP2 - 1;
6046 else
6047 adj = STEP2 + 1;
6048 count2 = (adj + N22 - N21) / STEP2;
8e6b4515 6049 if (__builtin_expect (N12 cond1 N11, 0)) goto Z0;
fd6481cf 6050 if (cond1 is <)
6051 adj = STEP1 - 1;
6052 else
6053 adj = STEP1 + 1;
6054 count1 = (adj + N12 - N11) / STEP1;
6055 count = count1 * count2 * count3;
8e6b4515 6056 goto Z1;
6057 Z0:
6058 count = 0;
6059 Z1:
fd6481cf 6060 more = GOMP_loop_foo_start (0, count, 1, CHUNK, &istart0, &iend0);
6061 if (more) goto L0; else goto L3;
6062 L0:
6063 V = istart0;
6064 T = V;
6065 V3 = N31 + (T % count3) * STEP3;
6066 T = T / count3;
6067 V2 = N21 + (T % count2) * STEP2;
6068 T = T / count2;
6069 V1 = N11 + T * STEP1;
6070 iend = iend0;
6071 L1:
6072 BODY;
6073 V += 1;
6074 if (V < iend) goto L10; else goto L2;
6075 L10:
6076 V3 += STEP3;
6077 if (V3 cond3 N32) goto L1; else goto L11;
6078 L11:
6079 V3 = N31;
6080 V2 += STEP2;
6081 if (V2 cond2 N22) goto L1; else goto L12;
6082 L12:
6083 V2 = N21;
6084 V1 += STEP1;
6085 goto L1;
6086 L2:
6087 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
6088 L3:
6089
6090 */
1e8e9920 6091
61e47ac8 6092static void
773c5ba7 6093expand_omp_for_generic (struct omp_region *region,
6094 struct omp_for_data *fd,
1e8e9920 6095 enum built_in_function start_fn,
bc7bff74 6096 enum built_in_function next_fn,
6097 gimple inner_stmt)
1e8e9920 6098{
75a70cf9 6099 tree type, istart0, iend0, iend;
fd6481cf 6100 tree t, vmain, vback, bias = NULL_TREE;
6101 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, collapse_bb;
03ed154b 6102 basic_block l2_bb = NULL, l3_bb = NULL;
75a70cf9 6103 gimple_stmt_iterator gsi;
1a91d914 6104 gassign *assign_stmt;
773c5ba7 6105 bool in_combined_parallel = is_combined_parallel (region);
ac6e3339 6106 bool broken_loop = region->cont == NULL;
79acaae1 6107 edge e, ne;
fd6481cf 6108 tree *counts = NULL;
6109 int i;
ac6e3339 6110
6111 gcc_assert (!broken_loop || !in_combined_parallel);
fd6481cf 6112 gcc_assert (fd->iter_type == long_integer_type_node
6113 || !in_combined_parallel);
1e8e9920 6114
fd6481cf 6115 type = TREE_TYPE (fd->loop.v);
6116 istart0 = create_tmp_var (fd->iter_type, ".istart0");
6117 iend0 = create_tmp_var (fd->iter_type, ".iend0");
6d63fc03 6118 TREE_ADDRESSABLE (istart0) = 1;
6119 TREE_ADDRESSABLE (iend0) = 1;
1e8e9920 6120
fd6481cf 6121 /* See if we need to bias by LLONG_MIN. */
6122 if (fd->iter_type == long_long_unsigned_type_node
6123 && TREE_CODE (type) == INTEGER_TYPE
6124 && !TYPE_UNSIGNED (type))
6125 {
6126 tree n1, n2;
6127
6128 if (fd->loop.cond_code == LT_EXPR)
6129 {
6130 n1 = fd->loop.n1;
6131 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
6132 }
6133 else
6134 {
6135 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
6136 n2 = fd->loop.n1;
6137 }
6138 if (TREE_CODE (n1) != INTEGER_CST
6139 || TREE_CODE (n2) != INTEGER_CST
6140 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
6141 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
6142 }
6143
61e47ac8 6144 entry_bb = region->entry;
03ed154b 6145 cont_bb = region->cont;
fd6481cf 6146 collapse_bb = NULL;
ac6e3339 6147 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
6148 gcc_assert (broken_loop
6149 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
6150 l0_bb = split_edge (FALLTHRU_EDGE (entry_bb));
6151 l1_bb = single_succ (l0_bb);
6152 if (!broken_loop)
03ed154b 6153 {
6154 l2_bb = create_empty_bb (cont_bb);
ac6e3339 6155 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l1_bb);
6156 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
03ed154b 6157 }
ac6e3339 6158 else
6159 l2_bb = NULL;
6160 l3_bb = BRANCH_EDGE (entry_bb)->dest;
6161 exit_bb = region->exit;
773c5ba7 6162
75a70cf9 6163 gsi = gsi_last_bb (entry_bb);
fd6481cf 6164
75a70cf9 6165 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
fd6481cf 6166 if (fd->collapse > 1)
6167 {
8e6b4515 6168 int first_zero_iter = -1;
3d483a94 6169 basic_block zero_iter_bb = NULL, l2_dom_bb = NULL;
8e6b4515 6170
3d483a94 6171 counts = XALLOCAVEC (tree, fd->collapse);
6172 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
6173 zero_iter_bb, first_zero_iter,
6174 l2_dom_bb);
fd6481cf 6175
8e6b4515 6176 if (zero_iter_bb)
6177 {
6178 /* Some counts[i] vars might be uninitialized if
6179 some loop has zero iterations. But the body shouldn't
6180 be executed in that case, so just avoid uninit warnings. */
6181 for (i = first_zero_iter; i < fd->collapse; i++)
6182 if (SSA_VAR_P (counts[i]))
6183 TREE_NO_WARNING (counts[i]) = 1;
6184 gsi_prev (&gsi);
6185 e = split_block (entry_bb, gsi_stmt (gsi));
6186 entry_bb = e->dest;
6187 make_edge (zero_iter_bb, entry_bb, EDGE_FALLTHRU);
6188 gsi = gsi_last_bb (entry_bb);
6189 set_immediate_dominator (CDI_DOMINATORS, entry_bb,
6190 get_immediate_dominator (CDI_DOMINATORS,
6191 zero_iter_bb));
6192 }
fd6481cf 6193 }
79acaae1 6194 if (in_combined_parallel)
6195 {
6196 /* In a combined parallel loop, emit a call to
6197 GOMP_loop_foo_next. */
b9a16870 6198 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
79acaae1 6199 build_fold_addr_expr (istart0),
6200 build_fold_addr_expr (iend0));
6201 }
6202 else
1e8e9920 6203 {
c2f47e15 6204 tree t0, t1, t2, t3, t4;
773c5ba7 6205 /* If this is not a combined parallel loop, emit a call to
6206 GOMP_loop_foo_start in ENTRY_BB. */
c2f47e15 6207 t4 = build_fold_addr_expr (iend0);
6208 t3 = build_fold_addr_expr (istart0);
fd6481cf 6209 t2 = fold_convert (fd->iter_type, fd->loop.step);
3d483a94 6210 t1 = fd->loop.n2;
6211 t0 = fd->loop.n1;
bc7bff74 6212 if (gimple_omp_for_combined_into_p (fd->for_stmt))
6213 {
6214 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
6215 OMP_CLAUSE__LOOPTEMP_);
6216 gcc_assert (innerc);
6217 t0 = OMP_CLAUSE_DECL (innerc);
6218 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6219 OMP_CLAUSE__LOOPTEMP_);
6220 gcc_assert (innerc);
6221 t1 = OMP_CLAUSE_DECL (innerc);
6222 }
3d483a94 6223 if (POINTER_TYPE_P (TREE_TYPE (t0))
6224 && TYPE_PRECISION (TREE_TYPE (t0))
6225 != TYPE_PRECISION (fd->iter_type))
c799f233 6226 {
6227 /* Avoid casting pointers to integer of a different size. */
3cea8318 6228 tree itype = signed_type_for (type);
3d483a94 6229 t1 = fold_convert (fd->iter_type, fold_convert (itype, t1));
6230 t0 = fold_convert (fd->iter_type, fold_convert (itype, t0));
c799f233 6231 }
6232 else
6233 {
3d483a94 6234 t1 = fold_convert (fd->iter_type, t1);
6235 t0 = fold_convert (fd->iter_type, t0);
c799f233 6236 }
fd6481cf 6237 if (bias)
1e8e9920 6238 {
fd6481cf 6239 t1 = fold_build2 (PLUS_EXPR, fd->iter_type, t1, bias);
6240 t0 = fold_build2 (PLUS_EXPR, fd->iter_type, t0, bias);
6241 }
6242 if (fd->iter_type == long_integer_type_node)
6243 {
6244 if (fd->chunk_size)
6245 {
6246 t = fold_convert (fd->iter_type, fd->chunk_size);
b9a16870 6247 t = build_call_expr (builtin_decl_explicit (start_fn),
6248 6, t0, t1, t2, t, t3, t4);
fd6481cf 6249 }
6250 else
b9a16870 6251 t = build_call_expr (builtin_decl_explicit (start_fn),
6252 5, t0, t1, t2, t3, t4);
1e8e9920 6253 }
c2f47e15 6254 else
fd6481cf 6255 {
6256 tree t5;
6257 tree c_bool_type;
b9a16870 6258 tree bfn_decl;
fd6481cf 6259
6260 /* The GOMP_loop_ull_*start functions have additional boolean
6261 argument, true for < loops and false for > loops.
6262 In Fortran, the C bool type can be different from
6263 boolean_type_node. */
b9a16870 6264 bfn_decl = builtin_decl_explicit (start_fn);
6265 c_bool_type = TREE_TYPE (TREE_TYPE (bfn_decl));
fd6481cf 6266 t5 = build_int_cst (c_bool_type,
6267 fd->loop.cond_code == LT_EXPR ? 1 : 0);
6268 if (fd->chunk_size)
6269 {
b9a16870 6270 tree bfn_decl = builtin_decl_explicit (start_fn);
fd6481cf 6271 t = fold_convert (fd->iter_type, fd->chunk_size);
b9a16870 6272 t = build_call_expr (bfn_decl, 7, t5, t0, t1, t2, t, t3, t4);
fd6481cf 6273 }
6274 else
b9a16870 6275 t = build_call_expr (builtin_decl_explicit (start_fn),
6276 6, t5, t0, t1, t2, t3, t4);
fd6481cf 6277 }
1e8e9920 6278 }
fd6481cf 6279 if (TREE_TYPE (t) != boolean_type_node)
6280 t = fold_build2 (NE_EXPR, boolean_type_node,
6281 t, build_int_cst (TREE_TYPE (t), 0));
75a70cf9 6282 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6283 true, GSI_SAME_STMT);
6284 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
79acaae1 6285
75a70cf9 6286 /* Remove the GIMPLE_OMP_FOR statement. */
6287 gsi_remove (&gsi, true);
1e8e9920 6288
773c5ba7 6289 /* Iteration setup for sequential loop goes in L0_BB. */
3d483a94 6290 tree startvar = fd->loop.v;
6291 tree endvar = NULL_TREE;
6292
bc7bff74 6293 if (gimple_omp_for_combined_p (fd->for_stmt))
6294 {
6295 gcc_assert (gimple_code (inner_stmt) == GIMPLE_OMP_FOR
6296 && gimple_omp_for_kind (inner_stmt)
6297 == GF_OMP_FOR_KIND_SIMD);
6298 tree innerc = find_omp_clause (gimple_omp_for_clauses (inner_stmt),
6299 OMP_CLAUSE__LOOPTEMP_);
6300 gcc_assert (innerc);
6301 startvar = OMP_CLAUSE_DECL (innerc);
6302 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6303 OMP_CLAUSE__LOOPTEMP_);
6304 gcc_assert (innerc);
6305 endvar = OMP_CLAUSE_DECL (innerc);
6306 }
6307
75a70cf9 6308 gsi = gsi_start_bb (l0_bb);
1efcacec 6309 t = istart0;
fd6481cf 6310 if (bias)
1efcacec 6311 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
3d483a94 6312 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
6313 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
6314 t = fold_convert (TREE_TYPE (startvar), t);
4abecb72 6315 t = force_gimple_operand_gsi (&gsi, t,
3d483a94 6316 DECL_P (startvar)
6317 && TREE_ADDRESSABLE (startvar),
4abecb72 6318 NULL_TREE, false, GSI_CONTINUE_LINKING);
1a91d914 6319 assign_stmt = gimple_build_assign (startvar, t);
6320 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
1e8e9920 6321
1efcacec 6322 t = iend0;
fd6481cf 6323 if (bias)
1efcacec 6324 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
3d483a94 6325 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
6326 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
6327 t = fold_convert (TREE_TYPE (startvar), t);
75a70cf9 6328 iend = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6329 false, GSI_CONTINUE_LINKING);
3d483a94 6330 if (endvar)
fd6481cf 6331 {
1a91d914 6332 assign_stmt = gimple_build_assign (endvar, iend);
6333 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
d44f2f7c 6334 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (iend)))
1a91d914 6335 assign_stmt = gimple_build_assign (fd->loop.v, iend);
d44f2f7c 6336 else
e9cf809e 6337 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, iend);
1a91d914 6338 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
fd6481cf 6339 }
3d483a94 6340 if (fd->collapse > 1)
bc7bff74 6341 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
773c5ba7 6342
ac6e3339 6343 if (!broken_loop)
03ed154b 6344 {
ac6e3339 6345 /* Code to control the increment and predicate for the sequential
6346 loop goes in the CONT_BB. */
75a70cf9 6347 gsi = gsi_last_bb (cont_bb);
1a91d914 6348 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
6349 gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
6350 vmain = gimple_omp_continue_control_use (cont_stmt);
6351 vback = gimple_omp_continue_control_def (cont_stmt);
79acaae1 6352
bc7bff74 6353 if (!gimple_omp_for_combined_p (fd->for_stmt))
3d483a94 6354 {
6355 if (POINTER_TYPE_P (type))
6356 t = fold_build_pointer_plus (vmain, fd->loop.step);
6357 else
6358 t = fold_build2 (PLUS_EXPR, type, vmain, fd->loop.step);
6359 t = force_gimple_operand_gsi (&gsi, t,
6360 DECL_P (vback)
6361 && TREE_ADDRESSABLE (vback),
6362 NULL_TREE, true, GSI_SAME_STMT);
1a91d914 6363 assign_stmt = gimple_build_assign (vback, t);
6364 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
3d483a94 6365
6366 t = build2 (fd->loop.cond_code, boolean_type_node,
6367 DECL_P (vback) && TREE_ADDRESSABLE (vback) ? t : vback,
6368 iend);
1a91d914 6369 gcond *cond_stmt = gimple_build_cond_empty (t);
6370 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
3d483a94 6371 }
773c5ba7 6372
75a70cf9 6373 /* Remove GIMPLE_OMP_CONTINUE. */
6374 gsi_remove (&gsi, true);
773c5ba7 6375
bc7bff74 6376 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
3d483a94 6377 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, l1_bb);
fd6481cf 6378
ac6e3339 6379 /* Emit code to get the next parallel iteration in L2_BB. */
75a70cf9 6380 gsi = gsi_start_bb (l2_bb);
773c5ba7 6381
b9a16870 6382 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
ac6e3339 6383 build_fold_addr_expr (istart0),
6384 build_fold_addr_expr (iend0));
75a70cf9 6385 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6386 false, GSI_CONTINUE_LINKING);
fd6481cf 6387 if (TREE_TYPE (t) != boolean_type_node)
6388 t = fold_build2 (NE_EXPR, boolean_type_node,
6389 t, build_int_cst (TREE_TYPE (t), 0));
1a91d914 6390 gcond *cond_stmt = gimple_build_cond_empty (t);
6391 gsi_insert_after (&gsi, cond_stmt, GSI_CONTINUE_LINKING);
ac6e3339 6392 }
1e8e9920 6393
61e47ac8 6394 /* Add the loop cleanup function. */
75a70cf9 6395 gsi = gsi_last_bb (exit_bb);
6396 if (gimple_omp_return_nowait_p (gsi_stmt (gsi)))
b9a16870 6397 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_NOWAIT);
bc7bff74 6398 else if (gimple_omp_return_lhs (gsi_stmt (gsi)))
6399 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_CANCEL);
61e47ac8 6400 else
b9a16870 6401 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END);
1a91d914 6402 gcall *call_stmt = gimple_build_call (t, 0);
bc7bff74 6403 if (gimple_omp_return_lhs (gsi_stmt (gsi)))
1a91d914 6404 gimple_call_set_lhs (call_stmt, gimple_omp_return_lhs (gsi_stmt (gsi)));
6405 gsi_insert_after (&gsi, call_stmt, GSI_SAME_STMT);
75a70cf9 6406 gsi_remove (&gsi, true);
773c5ba7 6407
6408 /* Connect the new blocks. */
79acaae1 6409 find_edge (entry_bb, l0_bb)->flags = EDGE_TRUE_VALUE;
6410 find_edge (entry_bb, l3_bb)->flags = EDGE_FALSE_VALUE;
1e8e9920 6411
ac6e3339 6412 if (!broken_loop)
6413 {
75a70cf9 6414 gimple_seq phis;
6415
79acaae1 6416 e = find_edge (cont_bb, l3_bb);
6417 ne = make_edge (l2_bb, l3_bb, EDGE_FALSE_VALUE);
6418
75a70cf9 6419 phis = phi_nodes (l3_bb);
6420 for (gsi = gsi_start (phis); !gsi_end_p (gsi); gsi_next (&gsi))
6421 {
6422 gimple phi = gsi_stmt (gsi);
6423 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, ne),
6424 PHI_ARG_DEF_FROM_EDGE (phi, e));
6425 }
79acaae1 6426 remove_edge (e);
6427
ac6e3339 6428 make_edge (cont_bb, l2_bb, EDGE_FALSE_VALUE);
b3083327 6429 add_bb_to_loop (l2_bb, cont_bb->loop_father);
3d483a94 6430 e = find_edge (cont_bb, l1_bb);
bc7bff74 6431 if (gimple_omp_for_combined_p (fd->for_stmt))
6432 {
6433 remove_edge (e);
6434 e = NULL;
6435 }
3d483a94 6436 else if (fd->collapse > 1)
fd6481cf 6437 {
fd6481cf 6438 remove_edge (e);
6439 e = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
6440 }
6441 else
3d483a94 6442 e->flags = EDGE_TRUE_VALUE;
6443 if (e)
fd6481cf 6444 {
3d483a94 6445 e->probability = REG_BR_PROB_BASE * 7 / 8;
6446 find_edge (cont_bb, l2_bb)->probability = REG_BR_PROB_BASE / 8;
6447 }
6448 else
6449 {
6450 e = find_edge (cont_bb, l2_bb);
6451 e->flags = EDGE_FALLTHRU;
fd6481cf 6452 }
ac6e3339 6453 make_edge (l2_bb, l0_bb, EDGE_TRUE_VALUE);
79acaae1 6454
6455 set_immediate_dominator (CDI_DOMINATORS, l2_bb,
6456 recompute_dominator (CDI_DOMINATORS, l2_bb));
6457 set_immediate_dominator (CDI_DOMINATORS, l3_bb,
6458 recompute_dominator (CDI_DOMINATORS, l3_bb));
6459 set_immediate_dominator (CDI_DOMINATORS, l0_bb,
6460 recompute_dominator (CDI_DOMINATORS, l0_bb));
6461 set_immediate_dominator (CDI_DOMINATORS, l1_bb,
6462 recompute_dominator (CDI_DOMINATORS, l1_bb));
04c2922b 6463
6464 struct loop *outer_loop = alloc_loop ();
6465 outer_loop->header = l0_bb;
6466 outer_loop->latch = l2_bb;
6467 add_loop (outer_loop, l0_bb->loop_father);
6468
bc7bff74 6469 if (!gimple_omp_for_combined_p (fd->for_stmt))
3d483a94 6470 {
6471 struct loop *loop = alloc_loop ();
6472 loop->header = l1_bb;
6473 /* The loop may have multiple latches. */
6474 add_loop (loop, outer_loop);
6475 }
ac6e3339 6476 }
1e8e9920 6477}
6478
6479
773c5ba7 6480/* A subroutine of expand_omp_for. Generate code for a parallel
6481 loop with static schedule and no specified chunk size. Given
6482 parameters:
1e8e9920 6483
6484 for (V = N1; V cond N2; V += STEP) BODY;
6485
6486 where COND is "<" or ">", we generate pseudocode
6487
8e6b4515 6488 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
1e8e9920 6489 if (cond is <)
6490 adj = STEP - 1;
6491 else
6492 adj = STEP + 1;
fd6481cf 6493 if ((__typeof (V)) -1 > 0 && cond is >)
6494 n = -(adj + N2 - N1) / -STEP;
6495 else
6496 n = (adj + N2 - N1) / STEP;
1e8e9920 6497 q = n / nthreads;
31712e83 6498 tt = n % nthreads;
6499 if (threadid < tt) goto L3; else goto L4;
6500 L3:
6501 tt = 0;
6502 q = q + 1;
6503 L4:
6504 s0 = q * threadid + tt;
6505 e0 = s0 + q;
79acaae1 6506 V = s0 * STEP + N1;
1e8e9920 6507 if (s0 >= e0) goto L2; else goto L0;
6508 L0:
1e8e9920 6509 e = e0 * STEP + N1;
6510 L1:
6511 BODY;
6512 V += STEP;
6513 if (V cond e) goto L1;
1e8e9920 6514 L2:
6515*/
6516
61e47ac8 6517static void
773c5ba7 6518expand_omp_for_static_nochunk (struct omp_region *region,
bc7bff74 6519 struct omp_for_data *fd,
6520 gimple inner_stmt)
1e8e9920 6521{
31712e83 6522 tree n, q, s0, e0, e, t, tt, nthreads, threadid;
fd6481cf 6523 tree type, itype, vmain, vback;
31712e83 6524 basic_block entry_bb, second_bb, third_bb, exit_bb, seq_start_bb;
bc7bff74 6525 basic_block body_bb, cont_bb, collapse_bb = NULL;
61e47ac8 6526 basic_block fin_bb;
75a70cf9 6527 gimple_stmt_iterator gsi;
31712e83 6528 edge ep;
bc7bff74 6529 bool broken_loop = region->cont == NULL;
6530 tree *counts = NULL;
6531 tree n1, n2, step;
1e8e9920 6532
ca4c3545 6533 gcc_checking_assert ((gimple_omp_for_kind (fd->for_stmt)
6534 != GF_OMP_FOR_KIND_OACC_LOOP)
6535 || !inner_stmt);
6536
fd6481cf 6537 itype = type = TREE_TYPE (fd->loop.v);
6538 if (POINTER_TYPE_P (type))
3cea8318 6539 itype = signed_type_for (type);
1e8e9920 6540
61e47ac8 6541 entry_bb = region->entry;
61e47ac8 6542 cont_bb = region->cont;
ac6e3339 6543 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
bc7bff74 6544 fin_bb = BRANCH_EDGE (entry_bb)->dest;
6545 gcc_assert (broken_loop
6546 || (fin_bb == FALLTHRU_EDGE (cont_bb)->dest));
ac6e3339 6547 seq_start_bb = split_edge (FALLTHRU_EDGE (entry_bb));
6548 body_bb = single_succ (seq_start_bb);
bc7bff74 6549 if (!broken_loop)
6550 {
6551 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
6552 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
6553 }
61e47ac8 6554 exit_bb = region->exit;
6555
773c5ba7 6556 /* Iteration space partitioning goes in ENTRY_BB. */
75a70cf9 6557 gsi = gsi_last_bb (entry_bb);
6558 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
61e47ac8 6559
bc7bff74 6560 if (fd->collapse > 1)
6561 {
6562 int first_zero_iter = -1;
6563 basic_block l2_dom_bb = NULL;
6564
6565 counts = XALLOCAVEC (tree, fd->collapse);
6566 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
6567 fin_bb, first_zero_iter,
6568 l2_dom_bb);
6569 t = NULL_TREE;
6570 }
6571 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
6572 t = integer_one_node;
6573 else
6574 t = fold_binary (fd->loop.cond_code, boolean_type_node,
6575 fold_convert (type, fd->loop.n1),
6576 fold_convert (type, fd->loop.n2));
6577 if (fd->collapse == 1
6578 && TYPE_UNSIGNED (type)
8e6b4515 6579 && (t == NULL_TREE || !integer_onep (t)))
6580 {
8e6b4515 6581 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
6582 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
6583 true, GSI_SAME_STMT);
6584 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
6585 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
6586 true, GSI_SAME_STMT);
1a91d914 6587 gcond *cond_stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
6588 NULL_TREE, NULL_TREE);
6589 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
6590 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
8e6b4515 6591 expand_omp_regimplify_p, NULL, NULL)
1a91d914 6592 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
8e6b4515 6593 expand_omp_regimplify_p, NULL, NULL))
6594 {
1a91d914 6595 gsi = gsi_for_stmt (cond_stmt);
6596 gimple_regimplify_operands (cond_stmt, &gsi);
8e6b4515 6597 }
1a91d914 6598 ep = split_block (entry_bb, cond_stmt);
8e6b4515 6599 ep->flags = EDGE_TRUE_VALUE;
6600 entry_bb = ep->dest;
6601 ep->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
6602 ep = make_edge (ep->src, fin_bb, EDGE_FALSE_VALUE);
6603 ep->probability = REG_BR_PROB_BASE / 2000 - 1;
6604 if (gimple_in_ssa_p (cfun))
6605 {
6606 int dest_idx = find_edge (entry_bb, fin_bb)->dest_idx;
1a91d914 6607 for (gphi_iterator gpi = gsi_start_phis (fin_bb);
6608 !gsi_end_p (gpi); gsi_next (&gpi))
8e6b4515 6609 {
1a91d914 6610 gphi *phi = gpi.phi ();
8e6b4515 6611 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
6612 ep, UNKNOWN_LOCATION);
6613 }
6614 }
6615 gsi = gsi_last_bb (entry_bb);
6616 }
6617
ca4c3545 6618 switch (gimple_omp_for_kind (fd->for_stmt))
6619 {
6620 case GF_OMP_FOR_KIND_FOR:
6621 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
6622 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
6623 break;
6624 case GF_OMP_FOR_KIND_DISTRIBUTE:
6625 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_TEAMS);
6626 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_TEAM_NUM);
6627 break;
6628 case GF_OMP_FOR_KIND_OACC_LOOP:
6629 nthreads = builtin_decl_explicit (BUILT_IN_GOACC_GET_NUM_THREADS);
6630 threadid = builtin_decl_explicit (BUILT_IN_GOACC_GET_THREAD_NUM);
6631 break;
6632 default:
6633 gcc_unreachable ();
6634 }
6635 nthreads = build_call_expr (nthreads, 0);
6636 nthreads = fold_convert (itype, nthreads);
6637 nthreads = force_gimple_operand_gsi (&gsi, nthreads, true, NULL_TREE,
75a70cf9 6638 true, GSI_SAME_STMT);
ca4c3545 6639 threadid = build_call_expr (threadid, 0);
6640 threadid = fold_convert (itype, threadid);
6641 threadid = force_gimple_operand_gsi (&gsi, threadid, true, NULL_TREE,
75a70cf9 6642 true, GSI_SAME_STMT);
1e8e9920 6643
bc7bff74 6644 n1 = fd->loop.n1;
6645 n2 = fd->loop.n2;
6646 step = fd->loop.step;
6647 if (gimple_omp_for_combined_into_p (fd->for_stmt))
6648 {
6649 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
6650 OMP_CLAUSE__LOOPTEMP_);
6651 gcc_assert (innerc);
6652 n1 = OMP_CLAUSE_DECL (innerc);
6653 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6654 OMP_CLAUSE__LOOPTEMP_);
6655 gcc_assert (innerc);
6656 n2 = OMP_CLAUSE_DECL (innerc);
6657 }
6658 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
6659 true, NULL_TREE, true, GSI_SAME_STMT);
6660 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
6661 true, NULL_TREE, true, GSI_SAME_STMT);
6662 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
6663 true, NULL_TREE, true, GSI_SAME_STMT);
fd6481cf 6664
6665 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
bc7bff74 6666 t = fold_build2 (PLUS_EXPR, itype, step, t);
6667 t = fold_build2 (PLUS_EXPR, itype, t, n2);
6668 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
fd6481cf 6669 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
6670 t = fold_build2 (TRUNC_DIV_EXPR, itype,
6671 fold_build1 (NEGATE_EXPR, itype, t),
bc7bff74 6672 fold_build1 (NEGATE_EXPR, itype, step));
fd6481cf 6673 else
bc7bff74 6674 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
fd6481cf 6675 t = fold_convert (itype, t);
75a70cf9 6676 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
1e8e9920 6677
072f7ab1 6678 q = create_tmp_reg (itype, "q");
fd6481cf 6679 t = fold_build2 (TRUNC_DIV_EXPR, itype, n, nthreads);
31712e83 6680 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
6681 gsi_insert_before (&gsi, gimple_build_assign (q, t), GSI_SAME_STMT);
6682
072f7ab1 6683 tt = create_tmp_reg (itype, "tt");
31712e83 6684 t = fold_build2 (TRUNC_MOD_EXPR, itype, n, nthreads);
6685 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
6686 gsi_insert_before (&gsi, gimple_build_assign (tt, t), GSI_SAME_STMT);
1e8e9920 6687
31712e83 6688 t = build2 (LT_EXPR, boolean_type_node, threadid, tt);
1a91d914 6689 gcond *cond_stmt = gimple_build_cond_empty (t);
6690 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
31712e83 6691
1a91d914 6692 second_bb = split_block (entry_bb, cond_stmt)->dest;
31712e83 6693 gsi = gsi_last_bb (second_bb);
6694 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6695
6696 gsi_insert_before (&gsi, gimple_build_assign (tt, build_int_cst (itype, 0)),
6697 GSI_SAME_STMT);
1a91d914 6698 gassign *assign_stmt
e9cf809e 6699 = gimple_build_assign (q, PLUS_EXPR, q, build_int_cst (itype, 1));
1a91d914 6700 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
31712e83 6701
1a91d914 6702 third_bb = split_block (second_bb, assign_stmt)->dest;
31712e83 6703 gsi = gsi_last_bb (third_bb);
6704 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
1e8e9920 6705
fd6481cf 6706 t = build2 (MULT_EXPR, itype, q, threadid);
31712e83 6707 t = build2 (PLUS_EXPR, itype, t, tt);
75a70cf9 6708 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
1e8e9920 6709
fd6481cf 6710 t = fold_build2 (PLUS_EXPR, itype, s0, q);
75a70cf9 6711 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
79acaae1 6712
1e8e9920 6713 t = build2 (GE_EXPR, boolean_type_node, s0, e0);
75a70cf9 6714 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
773c5ba7 6715
75a70cf9 6716 /* Remove the GIMPLE_OMP_FOR statement. */
6717 gsi_remove (&gsi, true);
773c5ba7 6718
6719 /* Setup code for sequential iteration goes in SEQ_START_BB. */
75a70cf9 6720 gsi = gsi_start_bb (seq_start_bb);
1e8e9920 6721
bc7bff74 6722 tree startvar = fd->loop.v;
6723 tree endvar = NULL_TREE;
6724
6725 if (gimple_omp_for_combined_p (fd->for_stmt))
6726 {
6727 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
6728 ? gimple_omp_parallel_clauses (inner_stmt)
6729 : gimple_omp_for_clauses (inner_stmt);
6730 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
6731 gcc_assert (innerc);
6732 startvar = OMP_CLAUSE_DECL (innerc);
6733 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6734 OMP_CLAUSE__LOOPTEMP_);
6735 gcc_assert (innerc);
6736 endvar = OMP_CLAUSE_DECL (innerc);
6737 }
fd6481cf 6738 t = fold_convert (itype, s0);
bc7bff74 6739 t = fold_build2 (MULT_EXPR, itype, t, step);
fd6481cf 6740 if (POINTER_TYPE_P (type))
bc7bff74 6741 t = fold_build_pointer_plus (n1, t);
fd6481cf 6742 else
bc7bff74 6743 t = fold_build2 (PLUS_EXPR, type, t, n1);
6744 t = fold_convert (TREE_TYPE (startvar), t);
4abecb72 6745 t = force_gimple_operand_gsi (&gsi, t,
bc7bff74 6746 DECL_P (startvar)
6747 && TREE_ADDRESSABLE (startvar),
4abecb72 6748 NULL_TREE, false, GSI_CONTINUE_LINKING);
1a91d914 6749 assign_stmt = gimple_build_assign (startvar, t);
6750 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
48e1416a 6751
fd6481cf 6752 t = fold_convert (itype, e0);
bc7bff74 6753 t = fold_build2 (MULT_EXPR, itype, t, step);
fd6481cf 6754 if (POINTER_TYPE_P (type))
bc7bff74 6755 t = fold_build_pointer_plus (n1, t);
fd6481cf 6756 else
bc7bff74 6757 t = fold_build2 (PLUS_EXPR, type, t, n1);
6758 t = fold_convert (TREE_TYPE (startvar), t);
75a70cf9 6759 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6760 false, GSI_CONTINUE_LINKING);
bc7bff74 6761 if (endvar)
6762 {
1a91d914 6763 assign_stmt = gimple_build_assign (endvar, e);
6764 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
d44f2f7c 6765 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
1a91d914 6766 assign_stmt = gimple_build_assign (fd->loop.v, e);
d44f2f7c 6767 else
e9cf809e 6768 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, e);
1a91d914 6769 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
bc7bff74 6770 }
6771 if (fd->collapse > 1)
6772 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
1e8e9920 6773
bc7bff74 6774 if (!broken_loop)
6775 {
6776 /* The code controlling the sequential loop replaces the
6777 GIMPLE_OMP_CONTINUE. */
6778 gsi = gsi_last_bb (cont_bb);
1a91d914 6779 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
6780 gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
6781 vmain = gimple_omp_continue_control_use (cont_stmt);
6782 vback = gimple_omp_continue_control_def (cont_stmt);
79acaae1 6783
bc7bff74 6784 if (!gimple_omp_for_combined_p (fd->for_stmt))
6785 {
6786 if (POINTER_TYPE_P (type))
6787 t = fold_build_pointer_plus (vmain, step);
6788 else
6789 t = fold_build2 (PLUS_EXPR, type, vmain, step);
6790 t = force_gimple_operand_gsi (&gsi, t,
6791 DECL_P (vback)
6792 && TREE_ADDRESSABLE (vback),
6793 NULL_TREE, true, GSI_SAME_STMT);
1a91d914 6794 assign_stmt = gimple_build_assign (vback, t);
6795 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
79acaae1 6796
bc7bff74 6797 t = build2 (fd->loop.cond_code, boolean_type_node,
6798 DECL_P (vback) && TREE_ADDRESSABLE (vback)
6799 ? t : vback, e);
6800 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
6801 }
1e8e9920 6802
bc7bff74 6803 /* Remove the GIMPLE_OMP_CONTINUE statement. */
6804 gsi_remove (&gsi, true);
6805
6806 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
6807 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
6808 }
773c5ba7 6809
75a70cf9 6810 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
6811 gsi = gsi_last_bb (exit_bb);
6812 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
bc7bff74 6813 {
6814 t = gimple_omp_return_lhs (gsi_stmt (gsi));
ca4c3545 6815 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_OACC_LOOP)
6816 gcc_checking_assert (t == NULL_TREE);
6817 else
6818 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
bc7bff74 6819 }
75a70cf9 6820 gsi_remove (&gsi, true);
773c5ba7 6821
6822 /* Connect all the blocks. */
31712e83 6823 ep = make_edge (entry_bb, third_bb, EDGE_FALSE_VALUE);
6824 ep->probability = REG_BR_PROB_BASE / 4 * 3;
6825 ep = find_edge (entry_bb, second_bb);
6826 ep->flags = EDGE_TRUE_VALUE;
6827 ep->probability = REG_BR_PROB_BASE / 4;
6828 find_edge (third_bb, seq_start_bb)->flags = EDGE_FALSE_VALUE;
6829 find_edge (third_bb, fin_bb)->flags = EDGE_TRUE_VALUE;
79acaae1 6830
bc7bff74 6831 if (!broken_loop)
6832 {
6833 ep = find_edge (cont_bb, body_bb);
6834 if (gimple_omp_for_combined_p (fd->for_stmt))
6835 {
6836 remove_edge (ep);
6837 ep = NULL;
6838 }
6839 else if (fd->collapse > 1)
6840 {
6841 remove_edge (ep);
6842 ep = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
6843 }
6844 else
6845 ep->flags = EDGE_TRUE_VALUE;
6846 find_edge (cont_bb, fin_bb)->flags
6847 = ep ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
6848 }
48e1416a 6849
31712e83 6850 set_immediate_dominator (CDI_DOMINATORS, second_bb, entry_bb);
6851 set_immediate_dominator (CDI_DOMINATORS, third_bb, entry_bb);
6852 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb, third_bb);
bc7bff74 6853
79acaae1 6854 set_immediate_dominator (CDI_DOMINATORS, body_bb,
6855 recompute_dominator (CDI_DOMINATORS, body_bb));
6856 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
6857 recompute_dominator (CDI_DOMINATORS, fin_bb));
04c2922b 6858
bc7bff74 6859 if (!broken_loop && !gimple_omp_for_combined_p (fd->for_stmt))
6860 {
6861 struct loop *loop = alloc_loop ();
6862 loop->header = body_bb;
6863 if (collapse_bb == NULL)
6864 loop->latch = cont_bb;
6865 add_loop (loop, body_bb->loop_father);
6866 }
1e8e9920 6867}
6868
773c5ba7 6869
6870/* A subroutine of expand_omp_for. Generate code for a parallel
6871 loop with static schedule and a specified chunk size. Given
6872 parameters:
1e8e9920 6873
6874 for (V = N1; V cond N2; V += STEP) BODY;
6875
6876 where COND is "<" or ">", we generate pseudocode
6877
8e6b4515 6878 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
1e8e9920 6879 if (cond is <)
6880 adj = STEP - 1;
6881 else
6882 adj = STEP + 1;
fd6481cf 6883 if ((__typeof (V)) -1 > 0 && cond is >)
6884 n = -(adj + N2 - N1) / -STEP;
6885 else
6886 n = (adj + N2 - N1) / STEP;
1e8e9920 6887 trip = 0;
79acaae1 6888 V = threadid * CHUNK * STEP + N1; -- this extra definition of V is
6889 here so that V is defined
6890 if the loop is not entered
1e8e9920 6891 L0:
6892 s0 = (trip * nthreads + threadid) * CHUNK;
6893 e0 = min(s0 + CHUNK, n);
6894 if (s0 < n) goto L1; else goto L4;
6895 L1:
6896 V = s0 * STEP + N1;
6897 e = e0 * STEP + N1;
6898 L2:
6899 BODY;
6900 V += STEP;
6901 if (V cond e) goto L2; else goto L3;
6902 L3:
6903 trip += 1;
6904 goto L0;
6905 L4:
1e8e9920 6906*/
6907
61e47ac8 6908static void
bc7bff74 6909expand_omp_for_static_chunk (struct omp_region *region,
6910 struct omp_for_data *fd, gimple inner_stmt)
1e8e9920 6911{
75a70cf9 6912 tree n, s0, e0, e, t;
79acaae1 6913 tree trip_var, trip_init, trip_main, trip_back, nthreads, threadid;
93481288 6914 tree type, itype, vmain, vback, vextra;
773c5ba7 6915 basic_block entry_bb, exit_bb, body_bb, seq_start_bb, iter_part_bb;
bc7bff74 6916 basic_block trip_update_bb = NULL, cont_bb, collapse_bb = NULL, fin_bb;
93481288 6917 gimple_stmt_iterator gsi;
75a70cf9 6918 edge se;
bc7bff74 6919 bool broken_loop = region->cont == NULL;
6920 tree *counts = NULL;
6921 tree n1, n2, step;
1e8e9920 6922
ca4c3545 6923 gcc_checking_assert ((gimple_omp_for_kind (fd->for_stmt)
6924 != GF_OMP_FOR_KIND_OACC_LOOP)
6925 || !inner_stmt);
6926
fd6481cf 6927 itype = type = TREE_TYPE (fd->loop.v);
6928 if (POINTER_TYPE_P (type))
3cea8318 6929 itype = signed_type_for (type);
1e8e9920 6930
61e47ac8 6931 entry_bb = region->entry;
ac6e3339 6932 se = split_block (entry_bb, last_stmt (entry_bb));
6933 entry_bb = se->src;
6934 iter_part_bb = se->dest;
61e47ac8 6935 cont_bb = region->cont;
ac6e3339 6936 gcc_assert (EDGE_COUNT (iter_part_bb->succs) == 2);
bc7bff74 6937 fin_bb = BRANCH_EDGE (iter_part_bb)->dest;
6938 gcc_assert (broken_loop
6939 || fin_bb == FALLTHRU_EDGE (cont_bb)->dest);
ac6e3339 6940 seq_start_bb = split_edge (FALLTHRU_EDGE (iter_part_bb));
6941 body_bb = single_succ (seq_start_bb);
bc7bff74 6942 if (!broken_loop)
6943 {
6944 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
6945 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
6946 trip_update_bb = split_edge (FALLTHRU_EDGE (cont_bb));
6947 }
61e47ac8 6948 exit_bb = region->exit;
773c5ba7 6949
773c5ba7 6950 /* Trip and adjustment setup goes in ENTRY_BB. */
93481288 6951 gsi = gsi_last_bb (entry_bb);
6952 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
773c5ba7 6953
bc7bff74 6954 if (fd->collapse > 1)
6955 {
6956 int first_zero_iter = -1;
6957 basic_block l2_dom_bb = NULL;
6958
6959 counts = XALLOCAVEC (tree, fd->collapse);
93481288 6960 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
bc7bff74 6961 fin_bb, first_zero_iter,
6962 l2_dom_bb);
6963 t = NULL_TREE;
6964 }
6965 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
6966 t = integer_one_node;
6967 else
6968 t = fold_binary (fd->loop.cond_code, boolean_type_node,
6969 fold_convert (type, fd->loop.n1),
6970 fold_convert (type, fd->loop.n2));
6971 if (fd->collapse == 1
6972 && TYPE_UNSIGNED (type)
8e6b4515 6973 && (t == NULL_TREE || !integer_onep (t)))
6974 {
8e6b4515 6975 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
93481288 6976 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
8e6b4515 6977 true, GSI_SAME_STMT);
6978 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
93481288 6979 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
8e6b4515 6980 true, GSI_SAME_STMT);
1a91d914 6981 gcond *cond_stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
6982 NULL_TREE, NULL_TREE);
6983 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
6984 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
8e6b4515 6985 expand_omp_regimplify_p, NULL, NULL)
1a91d914 6986 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
8e6b4515 6987 expand_omp_regimplify_p, NULL, NULL))
6988 {
1a91d914 6989 gsi = gsi_for_stmt (cond_stmt);
6990 gimple_regimplify_operands (cond_stmt, &gsi);
8e6b4515 6991 }
1a91d914 6992 se = split_block (entry_bb, cond_stmt);
8e6b4515 6993 se->flags = EDGE_TRUE_VALUE;
6994 entry_bb = se->dest;
6995 se->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
6996 se = make_edge (se->src, fin_bb, EDGE_FALSE_VALUE);
6997 se->probability = REG_BR_PROB_BASE / 2000 - 1;
6998 if (gimple_in_ssa_p (cfun))
6999 {
7000 int dest_idx = find_edge (entry_bb, fin_bb)->dest_idx;
1a91d914 7001 for (gphi_iterator gpi = gsi_start_phis (fin_bb);
7002 !gsi_end_p (gpi); gsi_next (&gpi))
8e6b4515 7003 {
1a91d914 7004 gphi *phi = gpi.phi ();
8e6b4515 7005 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
7006 se, UNKNOWN_LOCATION);
7007 }
7008 }
93481288 7009 gsi = gsi_last_bb (entry_bb);
8e6b4515 7010 }
7011
ca4c3545 7012 switch (gimple_omp_for_kind (fd->for_stmt))
7013 {
7014 case GF_OMP_FOR_KIND_FOR:
7015 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
7016 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
7017 break;
7018 case GF_OMP_FOR_KIND_DISTRIBUTE:
7019 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_TEAMS);
7020 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_TEAM_NUM);
7021 break;
7022 case GF_OMP_FOR_KIND_OACC_LOOP:
7023 nthreads = builtin_decl_explicit (BUILT_IN_GOACC_GET_NUM_THREADS);
7024 threadid = builtin_decl_explicit (BUILT_IN_GOACC_GET_THREAD_NUM);
7025 break;
7026 default:
7027 gcc_unreachable ();
7028 }
7029 nthreads = build_call_expr (nthreads, 0);
7030 nthreads = fold_convert (itype, nthreads);
7031 nthreads = force_gimple_operand_gsi (&gsi, nthreads, true, NULL_TREE,
75a70cf9 7032 true, GSI_SAME_STMT);
ca4c3545 7033 threadid = build_call_expr (threadid, 0);
7034 threadid = fold_convert (itype, threadid);
7035 threadid = force_gimple_operand_gsi (&gsi, threadid, true, NULL_TREE,
75a70cf9 7036 true, GSI_SAME_STMT);
79acaae1 7037
bc7bff74 7038 n1 = fd->loop.n1;
7039 n2 = fd->loop.n2;
7040 step = fd->loop.step;
7041 if (gimple_omp_for_combined_into_p (fd->for_stmt))
7042 {
7043 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7044 OMP_CLAUSE__LOOPTEMP_);
7045 gcc_assert (innerc);
7046 n1 = OMP_CLAUSE_DECL (innerc);
7047 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7048 OMP_CLAUSE__LOOPTEMP_);
7049 gcc_assert (innerc);
7050 n2 = OMP_CLAUSE_DECL (innerc);
7051 }
93481288 7052 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
bc7bff74 7053 true, NULL_TREE, true, GSI_SAME_STMT);
93481288 7054 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
bc7bff74 7055 true, NULL_TREE, true, GSI_SAME_STMT);
93481288 7056 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
bc7bff74 7057 true, NULL_TREE, true, GSI_SAME_STMT);
79acaae1 7058 fd->chunk_size
93481288 7059 = force_gimple_operand_gsi (&gsi, fold_convert (itype, fd->chunk_size),
75a70cf9 7060 true, NULL_TREE, true, GSI_SAME_STMT);
fd6481cf 7061
7062 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
bc7bff74 7063 t = fold_build2 (PLUS_EXPR, itype, step, t);
7064 t = fold_build2 (PLUS_EXPR, itype, t, n2);
7065 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
fd6481cf 7066 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
7067 t = fold_build2 (TRUNC_DIV_EXPR, itype,
7068 fold_build1 (NEGATE_EXPR, itype, t),
bc7bff74 7069 fold_build1 (NEGATE_EXPR, itype, step));
fd6481cf 7070 else
bc7bff74 7071 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
fd6481cf 7072 t = fold_convert (itype, t);
93481288 7073 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
75a70cf9 7074 true, GSI_SAME_STMT);
79acaae1 7075
083152fb 7076 trip_var = create_tmp_reg (itype, ".trip");
79acaae1 7077 if (gimple_in_ssa_p (cfun))
7078 {
f9e245b2 7079 trip_init = make_ssa_name (trip_var);
7080 trip_main = make_ssa_name (trip_var);
7081 trip_back = make_ssa_name (trip_var);
79acaae1 7082 }
1e8e9920 7083 else
79acaae1 7084 {
7085 trip_init = trip_var;
7086 trip_main = trip_var;
7087 trip_back = trip_var;
7088 }
1e8e9920 7089
1a91d914 7090 gassign *assign_stmt
7091 = gimple_build_assign (trip_init, build_int_cst (itype, 0));
7092 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
773c5ba7 7093
fd6481cf 7094 t = fold_build2 (MULT_EXPR, itype, threadid, fd->chunk_size);
bc7bff74 7095 t = fold_build2 (MULT_EXPR, itype, t, step);
fd6481cf 7096 if (POINTER_TYPE_P (type))
bc7bff74 7097 t = fold_build_pointer_plus (n1, t);
fd6481cf 7098 else
bc7bff74 7099 t = fold_build2 (PLUS_EXPR, type, t, n1);
93481288 7100 vextra = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7101 true, GSI_SAME_STMT);
79acaae1 7102
75a70cf9 7103 /* Remove the GIMPLE_OMP_FOR. */
93481288 7104 gsi_remove (&gsi, true);
773c5ba7 7105
7106 /* Iteration space partitioning goes in ITER_PART_BB. */
93481288 7107 gsi = gsi_last_bb (iter_part_bb);
1e8e9920 7108
fd6481cf 7109 t = fold_build2 (MULT_EXPR, itype, trip_main, nthreads);
7110 t = fold_build2 (PLUS_EXPR, itype, t, threadid);
7111 t = fold_build2 (MULT_EXPR, itype, t, fd->chunk_size);
93481288 7112 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
75a70cf9 7113 false, GSI_CONTINUE_LINKING);
1e8e9920 7114
fd6481cf 7115 t = fold_build2 (PLUS_EXPR, itype, s0, fd->chunk_size);
7116 t = fold_build2 (MIN_EXPR, itype, t, n);
93481288 7117 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
75a70cf9 7118 false, GSI_CONTINUE_LINKING);
1e8e9920 7119
7120 t = build2 (LT_EXPR, boolean_type_node, s0, n);
93481288 7121 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_CONTINUE_LINKING);
773c5ba7 7122
7123 /* Setup code for sequential iteration goes in SEQ_START_BB. */
93481288 7124 gsi = gsi_start_bb (seq_start_bb);
1e8e9920 7125
bc7bff74 7126 tree startvar = fd->loop.v;
7127 tree endvar = NULL_TREE;
7128
7129 if (gimple_omp_for_combined_p (fd->for_stmt))
7130 {
7131 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
7132 ? gimple_omp_parallel_clauses (inner_stmt)
7133 : gimple_omp_for_clauses (inner_stmt);
7134 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
7135 gcc_assert (innerc);
7136 startvar = OMP_CLAUSE_DECL (innerc);
7137 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7138 OMP_CLAUSE__LOOPTEMP_);
7139 gcc_assert (innerc);
7140 endvar = OMP_CLAUSE_DECL (innerc);
7141 }
7142
fd6481cf 7143 t = fold_convert (itype, s0);
bc7bff74 7144 t = fold_build2 (MULT_EXPR, itype, t, step);
fd6481cf 7145 if (POINTER_TYPE_P (type))
bc7bff74 7146 t = fold_build_pointer_plus (n1, t);
fd6481cf 7147 else
bc7bff74 7148 t = fold_build2 (PLUS_EXPR, type, t, n1);
7149 t = fold_convert (TREE_TYPE (startvar), t);
93481288 7150 t = force_gimple_operand_gsi (&gsi, t,
bc7bff74 7151 DECL_P (startvar)
7152 && TREE_ADDRESSABLE (startvar),
4abecb72 7153 NULL_TREE, false, GSI_CONTINUE_LINKING);
1a91d914 7154 assign_stmt = gimple_build_assign (startvar, t);
7155 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
1e8e9920 7156
fd6481cf 7157 t = fold_convert (itype, e0);
bc7bff74 7158 t = fold_build2 (MULT_EXPR, itype, t, step);
fd6481cf 7159 if (POINTER_TYPE_P (type))
bc7bff74 7160 t = fold_build_pointer_plus (n1, t);
fd6481cf 7161 else
bc7bff74 7162 t = fold_build2 (PLUS_EXPR, type, t, n1);
7163 t = fold_convert (TREE_TYPE (startvar), t);
93481288 7164 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
75a70cf9 7165 false, GSI_CONTINUE_LINKING);
bc7bff74 7166 if (endvar)
7167 {
1a91d914 7168 assign_stmt = gimple_build_assign (endvar, e);
7169 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
d44f2f7c 7170 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
1a91d914 7171 assign_stmt = gimple_build_assign (fd->loop.v, e);
d44f2f7c 7172 else
e9cf809e 7173 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, e);
1a91d914 7174 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
bc7bff74 7175 }
7176 if (fd->collapse > 1)
93481288 7177 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
bc7bff74 7178
7179 if (!broken_loop)
7180 {
7181 /* The code controlling the sequential loop goes in CONT_BB,
7182 replacing the GIMPLE_OMP_CONTINUE. */
93481288 7183 gsi = gsi_last_bb (cont_bb);
1a91d914 7184 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
7185 vmain = gimple_omp_continue_control_use (cont_stmt);
7186 vback = gimple_omp_continue_control_def (cont_stmt);
1e8e9920 7187
bc7bff74 7188 if (!gimple_omp_for_combined_p (fd->for_stmt))
7189 {
7190 if (POINTER_TYPE_P (type))
93481288 7191 t = fold_build_pointer_plus (vmain, step);
bc7bff74 7192 else
93481288 7193 t = fold_build2 (PLUS_EXPR, type, vmain, step);
7194 if (DECL_P (vback) && TREE_ADDRESSABLE (vback))
7195 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
bc7bff74 7196 true, GSI_SAME_STMT);
1a91d914 7197 assign_stmt = gimple_build_assign (vback, t);
7198 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
79acaae1 7199
bc7bff74 7200 t = build2 (fd->loop.cond_code, boolean_type_node,
93481288 7201 DECL_P (vback) && TREE_ADDRESSABLE (vback)
7202 ? t : vback, e);
7203 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
bc7bff74 7204 }
79acaae1 7205
bc7bff74 7206 /* Remove GIMPLE_OMP_CONTINUE. */
93481288 7207 gsi_remove (&gsi, true);
48e1416a 7208
bc7bff74 7209 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
7210 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
773c5ba7 7211
bc7bff74 7212 /* Trip update code goes into TRIP_UPDATE_BB. */
93481288 7213 gsi = gsi_start_bb (trip_update_bb);
1e8e9920 7214
bc7bff74 7215 t = build_int_cst (itype, 1);
7216 t = build2 (PLUS_EXPR, itype, trip_main, t);
1a91d914 7217 assign_stmt = gimple_build_assign (trip_back, t);
7218 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
bc7bff74 7219 }
1e8e9920 7220
75a70cf9 7221 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
93481288 7222 gsi = gsi_last_bb (exit_bb);
7223 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
bc7bff74 7224 {
93481288 7225 t = gimple_omp_return_lhs (gsi_stmt (gsi));
ca4c3545 7226 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_OACC_LOOP)
7227 gcc_checking_assert (t == NULL_TREE);
7228 else
7229 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
bc7bff74 7230 }
93481288 7231 gsi_remove (&gsi, true);
1e8e9920 7232
773c5ba7 7233 /* Connect the new blocks. */
ac6e3339 7234 find_edge (iter_part_bb, seq_start_bb)->flags = EDGE_TRUE_VALUE;
7235 find_edge (iter_part_bb, fin_bb)->flags = EDGE_FALSE_VALUE;
79acaae1 7236
bc7bff74 7237 if (!broken_loop)
7238 {
7239 se = find_edge (cont_bb, body_bb);
7240 if (gimple_omp_for_combined_p (fd->for_stmt))
7241 {
7242 remove_edge (se);
7243 se = NULL;
7244 }
7245 else if (fd->collapse > 1)
7246 {
7247 remove_edge (se);
7248 se = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
7249 }
7250 else
7251 se->flags = EDGE_TRUE_VALUE;
7252 find_edge (cont_bb, trip_update_bb)->flags
7253 = se ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
79acaae1 7254
bc7bff74 7255 redirect_edge_and_branch (single_succ_edge (trip_update_bb), iter_part_bb);
7256 }
79acaae1 7257
7258 if (gimple_in_ssa_p (cfun))
7259 {
1a91d914 7260 gphi_iterator psi;
7261 gphi *phi;
75a70cf9 7262 edge re, ene;
75a70cf9 7263 edge_var_map *vm;
7264 size_t i;
7265
bc7bff74 7266 gcc_assert (fd->collapse == 1 && !broken_loop);
7267
79acaae1 7268 /* When we redirect the edge from trip_update_bb to iter_part_bb, we
7269 remove arguments of the phi nodes in fin_bb. We need to create
7270 appropriate phi nodes in iter_part_bb instead. */
7271 se = single_pred_edge (fin_bb);
7272 re = single_succ_edge (trip_update_bb);
06ecf488 7273 vec<edge_var_map> *head = redirect_edge_var_map_vector (re);
79acaae1 7274 ene = single_succ_edge (entry_bb);
7275
75a70cf9 7276 psi = gsi_start_phis (fin_bb);
f1f41a6c 7277 for (i = 0; !gsi_end_p (psi) && head->iterate (i, &vm);
75a70cf9 7278 gsi_next (&psi), ++i)
79acaae1 7279 {
1a91d914 7280 gphi *nphi;
efbcb6de 7281 source_location locus;
75a70cf9 7282
1a91d914 7283 phi = psi.phi ();
75a70cf9 7284 t = gimple_phi_result (phi);
7285 gcc_assert (t == redirect_edge_var_map_result (vm));
79acaae1 7286 nphi = create_phi_node (t, iter_part_bb);
79acaae1 7287
7288 t = PHI_ARG_DEF_FROM_EDGE (phi, se);
efbcb6de 7289 locus = gimple_phi_arg_location_from_edge (phi, se);
7290
fd6481cf 7291 /* A special case -- fd->loop.v is not yet computed in
93481288 7292 iter_part_bb, we need to use vextra instead. */
fd6481cf 7293 if (t == fd->loop.v)
93481288 7294 t = vextra;
60d535d2 7295 add_phi_arg (nphi, t, ene, locus);
efbcb6de 7296 locus = redirect_edge_var_map_location (vm);
60d535d2 7297 add_phi_arg (nphi, redirect_edge_var_map_def (vm), re, locus);
75a70cf9 7298 }
a6f1094f 7299 gcc_assert (gsi_end_p (psi) && i == head->length ());
75a70cf9 7300 redirect_edge_var_map_clear (re);
7301 while (1)
7302 {
7303 psi = gsi_start_phis (fin_bb);
7304 if (gsi_end_p (psi))
7305 break;
7306 remove_phi_node (&psi, false);
79acaae1 7307 }
79acaae1 7308
7309 /* Make phi node for trip. */
7310 phi = create_phi_node (trip_main, iter_part_bb);
efbcb6de 7311 add_phi_arg (phi, trip_back, single_succ_edge (trip_update_bb),
60d535d2 7312 UNKNOWN_LOCATION);
efbcb6de 7313 add_phi_arg (phi, trip_init, single_succ_edge (entry_bb),
60d535d2 7314 UNKNOWN_LOCATION);
79acaae1 7315 }
7316
bc7bff74 7317 if (!broken_loop)
7318 set_immediate_dominator (CDI_DOMINATORS, trip_update_bb, cont_bb);
79acaae1 7319 set_immediate_dominator (CDI_DOMINATORS, iter_part_bb,
7320 recompute_dominator (CDI_DOMINATORS, iter_part_bb));
7321 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
7322 recompute_dominator (CDI_DOMINATORS, fin_bb));
7323 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb,
7324 recompute_dominator (CDI_DOMINATORS, seq_start_bb));
7325 set_immediate_dominator (CDI_DOMINATORS, body_bb,
7326 recompute_dominator (CDI_DOMINATORS, body_bb));
04c2922b 7327
bc7bff74 7328 if (!broken_loop)
7329 {
7330 struct loop *trip_loop = alloc_loop ();
7331 trip_loop->header = iter_part_bb;
7332 trip_loop->latch = trip_update_bb;
7333 add_loop (trip_loop, iter_part_bb->loop_father);
04c2922b 7334
bc7bff74 7335 if (!gimple_omp_for_combined_p (fd->for_stmt))
7336 {
7337 struct loop *loop = alloc_loop ();
7338 loop->header = body_bb;
33ee4d72 7339 if (collapse_bb == NULL)
7340 loop->latch = cont_bb;
bc7bff74 7341 add_loop (loop, trip_loop);
7342 }
7343 }
1e8e9920 7344}
7345
40750995 7346/* A subroutine of expand_omp_for. Generate code for _Cilk_for loop.
7347 Given parameters:
7348 for (V = N1; V cond N2; V += STEP) BODY;
7349
7350 where COND is "<" or ">" or "!=", we generate pseudocode
7351
7352 for (ind_var = low; ind_var < high; ind_var++)
7353 {
7354 V = n1 + (ind_var * STEP)
7355
7356 <BODY>
7357 }
7358
7359 In the above pseudocode, low and high are function parameters of the
7360 child function. In the function below, we are inserting a temp.
7361 variable that will be making a call to two OMP functions that will not be
7362 found in the body of _Cilk_for (since OMP_FOR cannot be mixed
7363 with _Cilk_for). These functions are replaced with low and high
7364 by the function that handles taskreg. */
7365
7366
7367static void
7368expand_cilk_for (struct omp_region *region, struct omp_for_data *fd)
7369{
7370 bool broken_loop = region->cont == NULL;
7371 basic_block entry_bb = region->entry;
7372 basic_block cont_bb = region->cont;
7373
7374 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
7375 gcc_assert (broken_loop
7376 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
7377 basic_block l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
7378 basic_block l1_bb, l2_bb;
7379
7380 if (!broken_loop)
7381 {
7382 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
7383 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
7384 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
7385 l2_bb = BRANCH_EDGE (entry_bb)->dest;
7386 }
7387 else
7388 {
7389 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
7390 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
7391 l2_bb = single_succ (l1_bb);
7392 }
7393 basic_block exit_bb = region->exit;
7394 basic_block l2_dom_bb = NULL;
7395
7396 gimple_stmt_iterator gsi = gsi_last_bb (entry_bb);
7397
7398 /* Below statements until the "tree high_val = ..." are pseudo statements
7399 used to pass information to be used by expand_omp_taskreg.
7400 low_val and high_val will be replaced by the __low and __high
7401 parameter from the child function.
7402
7403 The call_exprs part is a place-holder, it is mainly used
7404 to distinctly identify to the top-level part that this is
7405 where we should put low and high (reasoning given in header
7406 comment). */
7407
7408 tree child_fndecl
1a91d914 7409 = gimple_omp_parallel_child_fn (
7410 as_a <gomp_parallel *> (last_stmt (region->outer->entry)));
40750995 7411 tree t, low_val = NULL_TREE, high_val = NULL_TREE;
7412 for (t = DECL_ARGUMENTS (child_fndecl); t; t = TREE_CHAIN (t))
7413 {
7414 if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__high"))
7415 high_val = t;
7416 else if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__low"))
7417 low_val = t;
7418 }
7419 gcc_assert (low_val && high_val);
7420
7421 tree type = TREE_TYPE (low_val);
7422 tree ind_var = create_tmp_reg (type, "__cilk_ind_var");
7423 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
7424
7425 /* Not needed in SSA form right now. */
7426 gcc_assert (!gimple_in_ssa_p (cfun));
7427 if (l2_dom_bb == NULL)
7428 l2_dom_bb = l1_bb;
7429
7430 tree n1 = low_val;
7431 tree n2 = high_val;
7432
7433 gimple stmt = gimple_build_assign (ind_var, n1);
7434
7435 /* Replace the GIMPLE_OMP_FOR statement. */
7436 gsi_replace (&gsi, stmt, true);
7437
7438 if (!broken_loop)
7439 {
7440 /* Code to control the increment goes in the CONT_BB. */
7441 gsi = gsi_last_bb (cont_bb);
7442 stmt = gsi_stmt (gsi);
7443 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
e9cf809e 7444 stmt = gimple_build_assign (ind_var, PLUS_EXPR, ind_var,
7445 build_one_cst (type));
40750995 7446
7447 /* Replace GIMPLE_OMP_CONTINUE. */
7448 gsi_replace (&gsi, stmt, true);
7449 }
7450
7451 /* Emit the condition in L1_BB. */
7452 gsi = gsi_after_labels (l1_bb);
7453 t = fold_build2 (MULT_EXPR, TREE_TYPE (fd->loop.step),
7454 fold_convert (TREE_TYPE (fd->loop.step), ind_var),
7455 fd->loop.step);
7456 if (POINTER_TYPE_P (TREE_TYPE (fd->loop.n1)))
7457 t = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (fd->loop.n1),
7458 fd->loop.n1, fold_convert (sizetype, t));
7459 else
7460 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loop.n1),
7461 fd->loop.n1, fold_convert (TREE_TYPE (fd->loop.n1), t));
7462 t = fold_convert (TREE_TYPE (fd->loop.v), t);
7463 expand_omp_build_assign (&gsi, fd->loop.v, t);
7464
7465 /* The condition is always '<' since the runtime will fill in the low
7466 and high values. */
7467 stmt = gimple_build_cond (LT_EXPR, ind_var, n2, NULL_TREE, NULL_TREE);
7468 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
7469
7470 /* Remove GIMPLE_OMP_RETURN. */
7471 gsi = gsi_last_bb (exit_bb);
7472 gsi_remove (&gsi, true);
7473
7474 /* Connect the new blocks. */
7475 remove_edge (FALLTHRU_EDGE (entry_bb));
7476
7477 edge e, ne;
7478 if (!broken_loop)
7479 {
7480 remove_edge (BRANCH_EDGE (entry_bb));
7481 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
7482
7483 e = BRANCH_EDGE (l1_bb);
7484 ne = FALLTHRU_EDGE (l1_bb);
7485 e->flags = EDGE_TRUE_VALUE;
7486 }
7487 else
7488 {
7489 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7490
7491 ne = single_succ_edge (l1_bb);
7492 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
7493
7494 }
7495 ne->flags = EDGE_FALSE_VALUE;
7496 e->probability = REG_BR_PROB_BASE * 7 / 8;
7497 ne->probability = REG_BR_PROB_BASE / 8;
7498
7499 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
7500 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
7501 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
7502
7503 if (!broken_loop)
7504 {
7505 struct loop *loop = alloc_loop ();
7506 loop->header = l1_bb;
7507 loop->latch = cont_bb;
7508 add_loop (loop, l1_bb->loop_father);
7509 loop->safelen = INT_MAX;
7510 }
7511
7512 /* Pick the correct library function based on the precision of the
7513 induction variable type. */
7514 tree lib_fun = NULL_TREE;
7515 if (TYPE_PRECISION (type) == 32)
7516 lib_fun = cilk_for_32_fndecl;
7517 else if (TYPE_PRECISION (type) == 64)
7518 lib_fun = cilk_for_64_fndecl;
7519 else
7520 gcc_unreachable ();
7521
7522 gcc_assert (fd->sched_kind == OMP_CLAUSE_SCHEDULE_CILKFOR);
7523
7524 /* WS_ARGS contains the library function flavor to call:
7525 __libcilkrts_cilk_for_64 or __libcilkrts_cilk_for_32), and the
7526 user-defined grain value. If the user does not define one, then zero
7527 is passed in by the parser. */
7528 vec_alloc (region->ws_args, 2);
7529 region->ws_args->quick_push (lib_fun);
7530 region->ws_args->quick_push (fd->chunk_size);
7531}
bc7bff74 7532
3d483a94 7533/* A subroutine of expand_omp_for. Generate code for a simd non-worksharing
7534 loop. Given parameters:
7535
7536 for (V = N1; V cond N2; V += STEP) BODY;
7537
7538 where COND is "<" or ">", we generate pseudocode
7539
7540 V = N1;
7541 goto L1;
7542 L0:
7543 BODY;
7544 V += STEP;
7545 L1:
7546 if (V cond N2) goto L0; else goto L2;
7547 L2:
7548
7549 For collapsed loops, given parameters:
7550 collapse(3)
7551 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
7552 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
7553 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
7554 BODY;
7555
7556 we generate pseudocode
7557
7558 if (cond3 is <)
7559 adj = STEP3 - 1;
7560 else
7561 adj = STEP3 + 1;
7562 count3 = (adj + N32 - N31) / STEP3;
7563 if (cond2 is <)
7564 adj = STEP2 - 1;
7565 else
7566 adj = STEP2 + 1;
7567 count2 = (adj + N22 - N21) / STEP2;
7568 if (cond1 is <)
7569 adj = STEP1 - 1;
7570 else
7571 adj = STEP1 + 1;
7572 count1 = (adj + N12 - N11) / STEP1;
7573 count = count1 * count2 * count3;
7574 V = 0;
7575 V1 = N11;
7576 V2 = N21;
7577 V3 = N31;
7578 goto L1;
7579 L0:
7580 BODY;
7581 V += 1;
7582 V3 += STEP3;
7583 V2 += (V3 cond3 N32) ? 0 : STEP2;
7584 V3 = (V3 cond3 N32) ? V3 : N31;
7585 V1 += (V2 cond2 N22) ? 0 : STEP1;
7586 V2 = (V2 cond2 N22) ? V2 : N21;
7587 L1:
7588 if (V < count) goto L0; else goto L2;
7589 L2:
7590
7591 */
7592
7593static void
7594expand_omp_simd (struct omp_region *region, struct omp_for_data *fd)
7595{
7596 tree type, t;
7597 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, l2_bb, l2_dom_bb;
7598 gimple_stmt_iterator gsi;
7599 gimple stmt;
1a91d914 7600 gcond *cond_stmt;
3d483a94 7601 bool broken_loop = region->cont == NULL;
7602 edge e, ne;
7603 tree *counts = NULL;
7604 int i;
7605 tree safelen = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7606 OMP_CLAUSE_SAFELEN);
7607 tree simduid = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7608 OMP_CLAUSE__SIMDUID_);
bc7bff74 7609 tree n1, n2;
3d483a94 7610
7611 type = TREE_TYPE (fd->loop.v);
7612 entry_bb = region->entry;
7613 cont_bb = region->cont;
7614 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
7615 gcc_assert (broken_loop
7616 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
7617 l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
7618 if (!broken_loop)
7619 {
7620 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
7621 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
7622 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
7623 l2_bb = BRANCH_EDGE (entry_bb)->dest;
7624 }
7625 else
7626 {
7627 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
7628 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
7629 l2_bb = single_succ (l1_bb);
7630 }
7631 exit_bb = region->exit;
7632 l2_dom_bb = NULL;
7633
7634 gsi = gsi_last_bb (entry_bb);
7635
7636 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
7637 /* Not needed in SSA form right now. */
7638 gcc_assert (!gimple_in_ssa_p (cfun));
7639 if (fd->collapse > 1)
7640 {
7641 int first_zero_iter = -1;
7642 basic_block zero_iter_bb = l2_bb;
7643
7644 counts = XALLOCAVEC (tree, fd->collapse);
7645 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
7646 zero_iter_bb, first_zero_iter,
7647 l2_dom_bb);
7648 }
7649 if (l2_dom_bb == NULL)
7650 l2_dom_bb = l1_bb;
7651
bc7bff74 7652 n1 = fd->loop.n1;
3d483a94 7653 n2 = fd->loop.n2;
bc7bff74 7654 if (gimple_omp_for_combined_into_p (fd->for_stmt))
7655 {
7656 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7657 OMP_CLAUSE__LOOPTEMP_);
7658 gcc_assert (innerc);
7659 n1 = OMP_CLAUSE_DECL (innerc);
7660 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7661 OMP_CLAUSE__LOOPTEMP_);
7662 gcc_assert (innerc);
7663 n2 = OMP_CLAUSE_DECL (innerc);
7664 expand_omp_build_assign (&gsi, fd->loop.v,
7665 fold_convert (type, n1));
7666 if (fd->collapse > 1)
7667 {
7668 gsi_prev (&gsi);
7669 expand_omp_for_init_vars (fd, &gsi, counts, NULL, n1);
7670 gsi_next (&gsi);
7671 }
7672 }
3d483a94 7673 else
7674 {
7675 expand_omp_build_assign (&gsi, fd->loop.v,
7676 fold_convert (type, fd->loop.n1));
7677 if (fd->collapse > 1)
7678 for (i = 0; i < fd->collapse; i++)
7679 {
7680 tree itype = TREE_TYPE (fd->loops[i].v);
7681 if (POINTER_TYPE_P (itype))
7682 itype = signed_type_for (itype);
7683 t = fold_convert (TREE_TYPE (fd->loops[i].v), fd->loops[i].n1);
7684 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
7685 }
7686 }
7687
7688 /* Remove the GIMPLE_OMP_FOR statement. */
7689 gsi_remove (&gsi, true);
7690
7691 if (!broken_loop)
7692 {
7693 /* Code to control the increment goes in the CONT_BB. */
7694 gsi = gsi_last_bb (cont_bb);
7695 stmt = gsi_stmt (gsi);
7696 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
7697
7698 if (POINTER_TYPE_P (type))
7699 t = fold_build_pointer_plus (fd->loop.v, fd->loop.step);
7700 else
7701 t = fold_build2 (PLUS_EXPR, type, fd->loop.v, fd->loop.step);
7702 expand_omp_build_assign (&gsi, fd->loop.v, t);
7703
7704 if (fd->collapse > 1)
7705 {
7706 i = fd->collapse - 1;
7707 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v)))
7708 {
7709 t = fold_convert (sizetype, fd->loops[i].step);
7710 t = fold_build_pointer_plus (fd->loops[i].v, t);
7711 }
7712 else
7713 {
7714 t = fold_convert (TREE_TYPE (fd->loops[i].v),
7715 fd->loops[i].step);
7716 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loops[i].v),
7717 fd->loops[i].v, t);
7718 }
7719 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
7720
7721 for (i = fd->collapse - 1; i > 0; i--)
7722 {
7723 tree itype = TREE_TYPE (fd->loops[i].v);
7724 tree itype2 = TREE_TYPE (fd->loops[i - 1].v);
7725 if (POINTER_TYPE_P (itype2))
7726 itype2 = signed_type_for (itype2);
7727 t = build3 (COND_EXPR, itype2,
7728 build2 (fd->loops[i].cond_code, boolean_type_node,
7729 fd->loops[i].v,
7730 fold_convert (itype, fd->loops[i].n2)),
7731 build_int_cst (itype2, 0),
7732 fold_convert (itype2, fd->loops[i - 1].step));
7733 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i - 1].v)))
7734 t = fold_build_pointer_plus (fd->loops[i - 1].v, t);
7735 else
7736 t = fold_build2 (PLUS_EXPR, itype2, fd->loops[i - 1].v, t);
7737 expand_omp_build_assign (&gsi, fd->loops[i - 1].v, t);
7738
7739 t = build3 (COND_EXPR, itype,
7740 build2 (fd->loops[i].cond_code, boolean_type_node,
7741 fd->loops[i].v,
7742 fold_convert (itype, fd->loops[i].n2)),
7743 fd->loops[i].v,
7744 fold_convert (itype, fd->loops[i].n1));
7745 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
7746 }
7747 }
7748
7749 /* Remove GIMPLE_OMP_CONTINUE. */
7750 gsi_remove (&gsi, true);
7751 }
7752
7753 /* Emit the condition in L1_BB. */
7754 gsi = gsi_start_bb (l1_bb);
7755
7756 t = fold_convert (type, n2);
7757 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7758 false, GSI_CONTINUE_LINKING);
7759 t = build2 (fd->loop.cond_code, boolean_type_node, fd->loop.v, t);
1a91d914 7760 cond_stmt = gimple_build_cond_empty (t);
7761 gsi_insert_after (&gsi, cond_stmt, GSI_CONTINUE_LINKING);
7762 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt), expand_omp_regimplify_p,
3d483a94 7763 NULL, NULL)
1a91d914 7764 || walk_tree (gimple_cond_rhs_ptr (cond_stmt), expand_omp_regimplify_p,
3d483a94 7765 NULL, NULL))
7766 {
1a91d914 7767 gsi = gsi_for_stmt (cond_stmt);
7768 gimple_regimplify_operands (cond_stmt, &gsi);
3d483a94 7769 }
7770
7771 /* Remove GIMPLE_OMP_RETURN. */
7772 gsi = gsi_last_bb (exit_bb);
7773 gsi_remove (&gsi, true);
7774
7775 /* Connect the new blocks. */
7776 remove_edge (FALLTHRU_EDGE (entry_bb));
7777
7778 if (!broken_loop)
7779 {
7780 remove_edge (BRANCH_EDGE (entry_bb));
7781 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
7782
7783 e = BRANCH_EDGE (l1_bb);
7784 ne = FALLTHRU_EDGE (l1_bb);
7785 e->flags = EDGE_TRUE_VALUE;
7786 }
7787 else
7788 {
7789 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7790
7791 ne = single_succ_edge (l1_bb);
7792 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
7793
7794 }
7795 ne->flags = EDGE_FALSE_VALUE;
7796 e->probability = REG_BR_PROB_BASE * 7 / 8;
7797 ne->probability = REG_BR_PROB_BASE / 8;
7798
7799 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
7800 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
7801 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
7802
7803 if (!broken_loop)
7804 {
7805 struct loop *loop = alloc_loop ();
7806 loop->header = l1_bb;
33ee4d72 7807 loop->latch = cont_bb;
3d483a94 7808 add_loop (loop, l1_bb->loop_father);
7809 if (safelen == NULL_TREE)
7810 loop->safelen = INT_MAX;
7811 else
7812 {
7813 safelen = OMP_CLAUSE_SAFELEN_EXPR (safelen);
c3f3b68d 7814 if (TREE_CODE (safelen) != INTEGER_CST)
7815 loop->safelen = 0;
7816 else if (!tree_fits_uhwi_p (safelen)
7817 || tree_to_uhwi (safelen) > INT_MAX)
3d483a94 7818 loop->safelen = INT_MAX;
7819 else
d85a2013 7820 loop->safelen = tree_to_uhwi (safelen);
3d483a94 7821 if (loop->safelen == 1)
7822 loop->safelen = 0;
7823 }
7824 if (simduid)
7825 {
7826 loop->simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
7827 cfun->has_simduid_loops = true;
7828 }
043115ec 7829 /* If not -fno-tree-loop-vectorize, hint that we want to vectorize
3d483a94 7830 the loop. */
043115ec 7831 if ((flag_tree_loop_vectorize
7832 || (!global_options_set.x_flag_tree_loop_vectorize
7833 && !global_options_set.x_flag_tree_vectorize))
ad45e43e 7834 && flag_tree_loop_optimize
3d483a94 7835 && loop->safelen > 1)
7836 {
4c73695b 7837 loop->force_vectorize = true;
7838 cfun->has_force_vectorize_loops = true;
3d483a94 7839 }
7840 }
7841}
7842
1e8e9920 7843
ca4c3545 7844/* Expand the OMP loop defined by REGION. */
1e8e9920 7845
773c5ba7 7846static void
bc7bff74 7847expand_omp_for (struct omp_region *region, gimple inner_stmt)
773c5ba7 7848{
7849 struct omp_for_data fd;
fd6481cf 7850 struct omp_for_data_loop *loops;
1e8e9920 7851
fd6481cf 7852 loops
7853 = (struct omp_for_data_loop *)
75a70cf9 7854 alloca (gimple_omp_for_collapse (last_stmt (region->entry))
fd6481cf 7855 * sizeof (struct omp_for_data_loop));
1a91d914 7856 extract_omp_for_data (as_a <gomp_for *> (last_stmt (region->entry)),
7857 &fd, loops);
f77459c5 7858 region->sched_kind = fd.sched_kind;
1e8e9920 7859
b3a3ddec 7860 gcc_assert (EDGE_COUNT (region->entry->succs) == 2);
7861 BRANCH_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
7862 FALLTHRU_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
7863 if (region->cont)
7864 {
7865 gcc_assert (EDGE_COUNT (region->cont->succs) == 2);
7866 BRANCH_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
7867 FALLTHRU_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
7868 }
04c2922b 7869 else
75de4aa2 7870 /* If there isn't a continue then this is a degerate case where
04c2922b 7871 the introduction of abnormal edges during lowering will prevent
7872 original loops from being detected. Fix that up. */
7873 loops_state_set (LOOPS_NEED_FIXUP);
b3a3ddec 7874
10c55644 7875 if (gimple_omp_for_kind (fd.for_stmt) & GF_OMP_FOR_SIMD)
3d483a94 7876 expand_omp_simd (region, &fd);
40750995 7877 else if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_CILKFOR)
7878 expand_cilk_for (region, &fd);
3d483a94 7879 else if (fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
bc7bff74 7880 && !fd.have_ordered)
1e8e9920 7881 {
7882 if (fd.chunk_size == NULL)
bc7bff74 7883 expand_omp_for_static_nochunk (region, &fd, inner_stmt);
1e8e9920 7884 else
bc7bff74 7885 expand_omp_for_static_chunk (region, &fd, inner_stmt);
1e8e9920 7886 }
7887 else
7888 {
fd6481cf 7889 int fn_index, start_ix, next_ix;
7890
3d483a94 7891 gcc_assert (gimple_omp_for_kind (fd.for_stmt)
7892 == GF_OMP_FOR_KIND_FOR);
0416ca72 7893 if (fd.chunk_size == NULL
7894 && fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
7895 fd.chunk_size = integer_zero_node;
fd6481cf 7896 gcc_assert (fd.sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
7897 fn_index = (fd.sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
75a70cf9 7898 ? 3 : fd.sched_kind;
fd6481cf 7899 fn_index += fd.have_ordered * 4;
b9a16870 7900 start_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_START) + fn_index;
7901 next_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_NEXT) + fn_index;
fd6481cf 7902 if (fd.iter_type == long_long_unsigned_type_node)
7903 {
b9a16870 7904 start_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_START
7905 - (int)BUILT_IN_GOMP_LOOP_STATIC_START);
7906 next_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_NEXT
7907 - (int)BUILT_IN_GOMP_LOOP_STATIC_NEXT);
fd6481cf 7908 }
b9c74b4d 7909 expand_omp_for_generic (region, &fd, (enum built_in_function) start_ix,
bc7bff74 7910 (enum built_in_function) next_ix, inner_stmt);
1e8e9920 7911 }
28c92cbb 7912
083152fb 7913 if (gimple_in_ssa_p (cfun))
7914 update_ssa (TODO_update_ssa_only_virtuals);
1e8e9920 7915}
7916
1e8e9920 7917
7918/* Expand code for an OpenMP sections directive. In pseudo code, we generate
7919
1e8e9920 7920 v = GOMP_sections_start (n);
7921 L0:
7922 switch (v)
7923 {
7924 case 0:
7925 goto L2;
7926 case 1:
7927 section 1;
7928 goto L1;
7929 case 2:
7930 ...
7931 case n:
7932 ...
1e8e9920 7933 default:
7934 abort ();
7935 }
7936 L1:
7937 v = GOMP_sections_next ();
7938 goto L0;
7939 L2:
7940 reduction;
7941
773c5ba7 7942 If this is a combined parallel sections, replace the call to
79acaae1 7943 GOMP_sections_start with call to GOMP_sections_next. */
1e8e9920 7944
7945static void
773c5ba7 7946expand_omp_sections (struct omp_region *region)
1e8e9920 7947{
f018d957 7948 tree t, u, vin = NULL, vmain, vnext, l2;
75a70cf9 7949 unsigned len;
ac6e3339 7950 basic_block entry_bb, l0_bb, l1_bb, l2_bb, default_bb;
75a70cf9 7951 gimple_stmt_iterator si, switch_si;
1a91d914 7952 gomp_sections *sections_stmt;
7953 gimple stmt;
7954 gomp_continue *cont;
9884aaf8 7955 edge_iterator ei;
7956 edge e;
61e47ac8 7957 struct omp_region *inner;
75a70cf9 7958 unsigned i, casei;
ac6e3339 7959 bool exit_reachable = region->cont != NULL;
1e8e9920 7960
d244d9de 7961 gcc_assert (region->exit != NULL);
61e47ac8 7962 entry_bb = region->entry;
ac6e3339 7963 l0_bb = single_succ (entry_bb);
61e47ac8 7964 l1_bb = region->cont;
ac6e3339 7965 l2_bb = region->exit;
d244d9de 7966 if (single_pred_p (l2_bb) && single_pred (l2_bb) == l0_bb)
7967 l2 = gimple_block_label (l2_bb);
7968 else
03ed154b 7969 {
d244d9de 7970 /* This can happen if there are reductions. */
7971 len = EDGE_COUNT (l0_bb->succs);
7972 gcc_assert (len > 0);
7973 e = EDGE_SUCC (l0_bb, len - 1);
7974 si = gsi_last_bb (e->dest);
7975 l2 = NULL_TREE;
7976 if (gsi_end_p (si)
7977 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
7978 l2 = gimple_block_label (e->dest);
9884aaf8 7979 else
d244d9de 7980 FOR_EACH_EDGE (e, ei, l0_bb->succs)
7981 {
7982 si = gsi_last_bb (e->dest);
7983 if (gsi_end_p (si)
7984 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
9884aaf8 7985 {
d244d9de 7986 l2 = gimple_block_label (e->dest);
7987 break;
9884aaf8 7988 }
d244d9de 7989 }
03ed154b 7990 }
d244d9de 7991 if (exit_reachable)
7992 default_bb = create_empty_bb (l1_bb->prev_bb);
03ed154b 7993 else
d244d9de 7994 default_bb = create_empty_bb (l0_bb);
773c5ba7 7995
7996 /* We will build a switch() with enough cases for all the
75a70cf9 7997 GIMPLE_OMP_SECTION regions, a '0' case to handle the end of more work
773c5ba7 7998 and a default case to abort if something goes wrong. */
ac6e3339 7999 len = EDGE_COUNT (l0_bb->succs);
75a70cf9 8000
f1f41a6c 8001 /* Use vec::quick_push on label_vec throughout, since we know the size
75a70cf9 8002 in advance. */
c2078b80 8003 auto_vec<tree> label_vec (len);
1e8e9920 8004
61e47ac8 8005 /* The call to GOMP_sections_start goes in ENTRY_BB, replacing the
75a70cf9 8006 GIMPLE_OMP_SECTIONS statement. */
8007 si = gsi_last_bb (entry_bb);
1a91d914 8008 sections_stmt = as_a <gomp_sections *> (gsi_stmt (si));
75a70cf9 8009 gcc_assert (gimple_code (sections_stmt) == GIMPLE_OMP_SECTIONS);
8010 vin = gimple_omp_sections_control (sections_stmt);
773c5ba7 8011 if (!is_combined_parallel (region))
1e8e9920 8012 {
773c5ba7 8013 /* If we are not inside a combined parallel+sections region,
8014 call GOMP_sections_start. */
39cb6d68 8015 t = build_int_cst (unsigned_type_node, len - 1);
b9a16870 8016 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_START);
75a70cf9 8017 stmt = gimple_build_call (u, 1, t);
1e8e9920 8018 }
79acaae1 8019 else
8020 {
8021 /* Otherwise, call GOMP_sections_next. */
b9a16870 8022 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
75a70cf9 8023 stmt = gimple_build_call (u, 0);
79acaae1 8024 }
75a70cf9 8025 gimple_call_set_lhs (stmt, vin);
8026 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
8027 gsi_remove (&si, true);
8028
8029 /* The switch() statement replacing GIMPLE_OMP_SECTIONS_SWITCH goes in
8030 L0_BB. */
8031 switch_si = gsi_last_bb (l0_bb);
8032 gcc_assert (gimple_code (gsi_stmt (switch_si)) == GIMPLE_OMP_SECTIONS_SWITCH);
79acaae1 8033 if (exit_reachable)
8034 {
1a91d914 8035 cont = as_a <gomp_continue *> (last_stmt (l1_bb));
75a70cf9 8036 gcc_assert (gimple_code (cont) == GIMPLE_OMP_CONTINUE);
8037 vmain = gimple_omp_continue_control_use (cont);
8038 vnext = gimple_omp_continue_control_def (cont);
79acaae1 8039 }
8040 else
8041 {
8042 vmain = vin;
8043 vnext = NULL_TREE;
8044 }
1e8e9920 8045
d244d9de 8046 t = build_case_label (build_int_cst (unsigned_type_node, 0), NULL, l2);
f1f41a6c 8047 label_vec.quick_push (t);
d244d9de 8048 i = 1;
03ed154b 8049
75a70cf9 8050 /* Convert each GIMPLE_OMP_SECTION into a CASE_LABEL_EXPR. */
ac6e3339 8051 for (inner = region->inner, casei = 1;
8052 inner;
8053 inner = inner->next, i++, casei++)
1e8e9920 8054 {
773c5ba7 8055 basic_block s_entry_bb, s_exit_bb;
8056
9884aaf8 8057 /* Skip optional reduction region. */
75a70cf9 8058 if (inner->type == GIMPLE_OMP_ATOMIC_LOAD)
9884aaf8 8059 {
8060 --i;
8061 --casei;
8062 continue;
8063 }
8064
61e47ac8 8065 s_entry_bb = inner->entry;
8066 s_exit_bb = inner->exit;
1e8e9920 8067
75a70cf9 8068 t = gimple_block_label (s_entry_bb);
ac6e3339 8069 u = build_int_cst (unsigned_type_node, casei);
b6e3dd65 8070 u = build_case_label (u, NULL, t);
f1f41a6c 8071 label_vec.quick_push (u);
61e47ac8 8072
75a70cf9 8073 si = gsi_last_bb (s_entry_bb);
8074 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SECTION);
8075 gcc_assert (i < len || gimple_omp_section_last_p (gsi_stmt (si)));
8076 gsi_remove (&si, true);
61e47ac8 8077 single_succ_edge (s_entry_bb)->flags = EDGE_FALLTHRU;
03ed154b 8078
8079 if (s_exit_bb == NULL)
8080 continue;
8081
75a70cf9 8082 si = gsi_last_bb (s_exit_bb);
8083 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
8084 gsi_remove (&si, true);
03ed154b 8085
773c5ba7 8086 single_succ_edge (s_exit_bb)->flags = EDGE_FALLTHRU;
1e8e9920 8087 }
8088
773c5ba7 8089 /* Error handling code goes in DEFAULT_BB. */
75a70cf9 8090 t = gimple_block_label (default_bb);
b6e3dd65 8091 u = build_case_label (NULL, NULL, t);
61e47ac8 8092 make_edge (l0_bb, default_bb, 0);
b3083327 8093 add_bb_to_loop (default_bb, current_loops->tree_root);
1e8e9920 8094
49a70175 8095 stmt = gimple_build_switch (vmain, u, label_vec);
75a70cf9 8096 gsi_insert_after (&switch_si, stmt, GSI_SAME_STMT);
8097 gsi_remove (&switch_si, true);
75a70cf9 8098
8099 si = gsi_start_bb (default_bb);
b9a16870 8100 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
75a70cf9 8101 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
773c5ba7 8102
ac6e3339 8103 if (exit_reachable)
03ed154b 8104 {
b9a16870 8105 tree bfn_decl;
8106
ac6e3339 8107 /* Code to get the next section goes in L1_BB. */
75a70cf9 8108 si = gsi_last_bb (l1_bb);
8109 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CONTINUE);
1e8e9920 8110
b9a16870 8111 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
8112 stmt = gimple_build_call (bfn_decl, 0);
75a70cf9 8113 gimple_call_set_lhs (stmt, vnext);
8114 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
8115 gsi_remove (&si, true);
773c5ba7 8116
ac6e3339 8117 single_succ_edge (l1_bb)->flags = EDGE_FALLTHRU;
03ed154b 8118 }
773c5ba7 8119
d244d9de 8120 /* Cleanup function replaces GIMPLE_OMP_RETURN in EXIT_BB. */
8121 si = gsi_last_bb (l2_bb);
8122 if (gimple_omp_return_nowait_p (gsi_stmt (si)))
8123 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_NOWAIT);
bc7bff74 8124 else if (gimple_omp_return_lhs (gsi_stmt (si)))
8125 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_CANCEL);
d244d9de 8126 else
8127 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END);
8128 stmt = gimple_build_call (t, 0);
bc7bff74 8129 if (gimple_omp_return_lhs (gsi_stmt (si)))
8130 gimple_call_set_lhs (stmt, gimple_omp_return_lhs (gsi_stmt (si)));
d244d9de 8131 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
8132 gsi_remove (&si, true);
8133
79acaae1 8134 set_immediate_dominator (CDI_DOMINATORS, default_bb, l0_bb);
773c5ba7 8135}
1e8e9920 8136
1e8e9920 8137
61e47ac8 8138/* Expand code for an OpenMP single directive. We've already expanded
8139 much of the code, here we simply place the GOMP_barrier call. */
8140
8141static void
8142expand_omp_single (struct omp_region *region)
8143{
8144 basic_block entry_bb, exit_bb;
75a70cf9 8145 gimple_stmt_iterator si;
61e47ac8 8146
8147 entry_bb = region->entry;
8148 exit_bb = region->exit;
8149
75a70cf9 8150 si = gsi_last_bb (entry_bb);
75a70cf9 8151 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE);
8152 gsi_remove (&si, true);
61e47ac8 8153 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
8154
75a70cf9 8155 si = gsi_last_bb (exit_bb);
bc7bff74 8156 if (!gimple_omp_return_nowait_p (gsi_stmt (si)))
8157 {
8158 tree t = gimple_omp_return_lhs (gsi_stmt (si));
8159 gsi_insert_after (&si, build_omp_barrier (t), GSI_SAME_STMT);
8160 }
75a70cf9 8161 gsi_remove (&si, true);
61e47ac8 8162 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
8163}
8164
8165
8166/* Generic expansion for OpenMP synchronization directives: master,
8167 ordered and critical. All we need to do here is remove the entry
8168 and exit markers for REGION. */
773c5ba7 8169
8170static void
8171expand_omp_synch (struct omp_region *region)
8172{
8173 basic_block entry_bb, exit_bb;
75a70cf9 8174 gimple_stmt_iterator si;
773c5ba7 8175
61e47ac8 8176 entry_bb = region->entry;
8177 exit_bb = region->exit;
773c5ba7 8178
75a70cf9 8179 si = gsi_last_bb (entry_bb);
8180 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE
8181 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_MASTER
bc7bff74 8182 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TASKGROUP
75a70cf9 8183 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ORDERED
bc7bff74 8184 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CRITICAL
8185 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TEAMS);
75a70cf9 8186 gsi_remove (&si, true);
773c5ba7 8187 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
8188
03ed154b 8189 if (exit_bb)
8190 {
75a70cf9 8191 si = gsi_last_bb (exit_bb);
8192 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
8193 gsi_remove (&si, true);
03ed154b 8194 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
8195 }
773c5ba7 8196}
1e8e9920 8197
2169f33b 8198/* A subroutine of expand_omp_atomic. Attempt to implement the atomic
8199 operation as a normal volatile load. */
8200
8201static bool
3ec11c49 8202expand_omp_atomic_load (basic_block load_bb, tree addr,
8203 tree loaded_val, int index)
2169f33b 8204{
3ec11c49 8205 enum built_in_function tmpbase;
8206 gimple_stmt_iterator gsi;
8207 basic_block store_bb;
8208 location_t loc;
8209 gimple stmt;
8210 tree decl, call, type, itype;
8211
8212 gsi = gsi_last_bb (load_bb);
8213 stmt = gsi_stmt (gsi);
8214 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
8215 loc = gimple_location (stmt);
8216
8217 /* ??? If the target does not implement atomic_load_optab[mode], and mode
8218 is smaller than word size, then expand_atomic_load assumes that the load
8219 is atomic. We could avoid the builtin entirely in this case. */
8220
8221 tmpbase = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
8222 decl = builtin_decl_explicit (tmpbase);
8223 if (decl == NULL_TREE)
8224 return false;
8225
8226 type = TREE_TYPE (loaded_val);
8227 itype = TREE_TYPE (TREE_TYPE (decl));
8228
8229 call = build_call_expr_loc (loc, decl, 2, addr,
bc7bff74 8230 build_int_cst (NULL,
8231 gimple_omp_atomic_seq_cst_p (stmt)
8232 ? MEMMODEL_SEQ_CST
8233 : MEMMODEL_RELAXED));
3ec11c49 8234 if (!useless_type_conversion_p (type, itype))
8235 call = fold_build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
8236 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
8237
8238 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
8239 gsi_remove (&gsi, true);
8240
8241 store_bb = single_succ (load_bb);
8242 gsi = gsi_last_bb (store_bb);
8243 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
8244 gsi_remove (&gsi, true);
8245
8246 if (gimple_in_ssa_p (cfun))
8247 update_ssa (TODO_update_ssa_no_phi);
8248
8249 return true;
2169f33b 8250}
8251
8252/* A subroutine of expand_omp_atomic. Attempt to implement the atomic
8253 operation as a normal volatile store. */
8254
8255static bool
3ec11c49 8256expand_omp_atomic_store (basic_block load_bb, tree addr,
8257 tree loaded_val, tree stored_val, int index)
2169f33b 8258{
3ec11c49 8259 enum built_in_function tmpbase;
8260 gimple_stmt_iterator gsi;
8261 basic_block store_bb = single_succ (load_bb);
8262 location_t loc;
8263 gimple stmt;
8264 tree decl, call, type, itype;
3754d046 8265 machine_mode imode;
3ec11c49 8266 bool exchange;
8267
8268 gsi = gsi_last_bb (load_bb);
8269 stmt = gsi_stmt (gsi);
8270 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
8271
8272 /* If the load value is needed, then this isn't a store but an exchange. */
8273 exchange = gimple_omp_atomic_need_value_p (stmt);
8274
8275 gsi = gsi_last_bb (store_bb);
8276 stmt = gsi_stmt (gsi);
8277 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE);
8278 loc = gimple_location (stmt);
8279
8280 /* ??? If the target does not implement atomic_store_optab[mode], and mode
8281 is smaller than word size, then expand_atomic_store assumes that the store
8282 is atomic. We could avoid the builtin entirely in this case. */
8283
8284 tmpbase = (exchange ? BUILT_IN_ATOMIC_EXCHANGE_N : BUILT_IN_ATOMIC_STORE_N);
8285 tmpbase = (enum built_in_function) ((int) tmpbase + index + 1);
8286 decl = builtin_decl_explicit (tmpbase);
8287 if (decl == NULL_TREE)
8288 return false;
8289
8290 type = TREE_TYPE (stored_val);
8291
8292 /* Dig out the type of the function's second argument. */
8293 itype = TREE_TYPE (decl);
8294 itype = TYPE_ARG_TYPES (itype);
8295 itype = TREE_CHAIN (itype);
8296 itype = TREE_VALUE (itype);
8297 imode = TYPE_MODE (itype);
8298
8299 if (exchange && !can_atomic_exchange_p (imode, true))
8300 return false;
8301
8302 if (!useless_type_conversion_p (itype, type))
8303 stored_val = fold_build1_loc (loc, VIEW_CONVERT_EXPR, itype, stored_val);
8304 call = build_call_expr_loc (loc, decl, 3, addr, stored_val,
bc7bff74 8305 build_int_cst (NULL,
8306 gimple_omp_atomic_seq_cst_p (stmt)
8307 ? MEMMODEL_SEQ_CST
8308 : MEMMODEL_RELAXED));
3ec11c49 8309 if (exchange)
8310 {
8311 if (!useless_type_conversion_p (type, itype))
8312 call = build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
8313 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
8314 }
8315
8316 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
8317 gsi_remove (&gsi, true);
8318
8319 /* Remove the GIMPLE_OMP_ATOMIC_LOAD that we verified above. */
8320 gsi = gsi_last_bb (load_bb);
8321 gsi_remove (&gsi, true);
8322
8323 if (gimple_in_ssa_p (cfun))
8324 update_ssa (TODO_update_ssa_no_phi);
8325
8326 return true;
2169f33b 8327}
8328
cb7f680b 8329/* A subroutine of expand_omp_atomic. Attempt to implement the atomic
1cd6e20d 8330 operation as a __atomic_fetch_op builtin. INDEX is log2 of the
cb7f680b 8331 size of the data type, and thus usable to find the index of the builtin
8332 decl. Returns false if the expression is not of the proper form. */
8333
8334static bool
8335expand_omp_atomic_fetch_op (basic_block load_bb,
8336 tree addr, tree loaded_val,
8337 tree stored_val, int index)
8338{
b9a16870 8339 enum built_in_function oldbase, newbase, tmpbase;
cb7f680b 8340 tree decl, itype, call;
2169f33b 8341 tree lhs, rhs;
cb7f680b 8342 basic_block store_bb = single_succ (load_bb);
75a70cf9 8343 gimple_stmt_iterator gsi;
8344 gimple stmt;
389dd41b 8345 location_t loc;
1cd6e20d 8346 enum tree_code code;
2169f33b 8347 bool need_old, need_new;
3754d046 8348 machine_mode imode;
bc7bff74 8349 bool seq_cst;
cb7f680b 8350
8351 /* We expect to find the following sequences:
48e1416a 8352
cb7f680b 8353 load_bb:
75a70cf9 8354 GIMPLE_OMP_ATOMIC_LOAD (tmp, mem)
cb7f680b 8355
8356 store_bb:
8357 val = tmp OP something; (or: something OP tmp)
48e1416a 8358 GIMPLE_OMP_STORE (val)
cb7f680b 8359
48e1416a 8360 ???FIXME: Allow a more flexible sequence.
cb7f680b 8361 Perhaps use data flow to pick the statements.
48e1416a 8362
cb7f680b 8363 */
8364
75a70cf9 8365 gsi = gsi_after_labels (store_bb);
8366 stmt = gsi_stmt (gsi);
389dd41b 8367 loc = gimple_location (stmt);
75a70cf9 8368 if (!is_gimple_assign (stmt))
cb7f680b 8369 return false;
75a70cf9 8370 gsi_next (&gsi);
8371 if (gimple_code (gsi_stmt (gsi)) != GIMPLE_OMP_ATOMIC_STORE)
cb7f680b 8372 return false;
2169f33b 8373 need_new = gimple_omp_atomic_need_value_p (gsi_stmt (gsi));
8374 need_old = gimple_omp_atomic_need_value_p (last_stmt (load_bb));
bc7bff74 8375 seq_cst = gimple_omp_atomic_seq_cst_p (last_stmt (load_bb));
2169f33b 8376 gcc_checking_assert (!need_old || !need_new);
cb7f680b 8377
75a70cf9 8378 if (!operand_equal_p (gimple_assign_lhs (stmt), stored_val, 0))
cb7f680b 8379 return false;
8380
cb7f680b 8381 /* Check for one of the supported fetch-op operations. */
1cd6e20d 8382 code = gimple_assign_rhs_code (stmt);
8383 switch (code)
cb7f680b 8384 {
8385 case PLUS_EXPR:
8386 case POINTER_PLUS_EXPR:
1cd6e20d 8387 oldbase = BUILT_IN_ATOMIC_FETCH_ADD_N;
8388 newbase = BUILT_IN_ATOMIC_ADD_FETCH_N;
cb7f680b 8389 break;
8390 case MINUS_EXPR:
1cd6e20d 8391 oldbase = BUILT_IN_ATOMIC_FETCH_SUB_N;
8392 newbase = BUILT_IN_ATOMIC_SUB_FETCH_N;
cb7f680b 8393 break;
8394 case BIT_AND_EXPR:
1cd6e20d 8395 oldbase = BUILT_IN_ATOMIC_FETCH_AND_N;
8396 newbase = BUILT_IN_ATOMIC_AND_FETCH_N;
cb7f680b 8397 break;
8398 case BIT_IOR_EXPR:
1cd6e20d 8399 oldbase = BUILT_IN_ATOMIC_FETCH_OR_N;
8400 newbase = BUILT_IN_ATOMIC_OR_FETCH_N;
cb7f680b 8401 break;
8402 case BIT_XOR_EXPR:
1cd6e20d 8403 oldbase = BUILT_IN_ATOMIC_FETCH_XOR_N;
8404 newbase = BUILT_IN_ATOMIC_XOR_FETCH_N;
cb7f680b 8405 break;
8406 default:
8407 return false;
8408 }
1cd6e20d 8409
cb7f680b 8410 /* Make sure the expression is of the proper form. */
75a70cf9 8411 if (operand_equal_p (gimple_assign_rhs1 (stmt), loaded_val, 0))
8412 rhs = gimple_assign_rhs2 (stmt);
8413 else if (commutative_tree_code (gimple_assign_rhs_code (stmt))
8414 && operand_equal_p (gimple_assign_rhs2 (stmt), loaded_val, 0))
8415 rhs = gimple_assign_rhs1 (stmt);
cb7f680b 8416 else
8417 return false;
8418
b9a16870 8419 tmpbase = ((enum built_in_function)
8420 ((need_new ? newbase : oldbase) + index + 1));
8421 decl = builtin_decl_explicit (tmpbase);
0f94f46b 8422 if (decl == NULL_TREE)
8423 return false;
cb7f680b 8424 itype = TREE_TYPE (TREE_TYPE (decl));
1cd6e20d 8425 imode = TYPE_MODE (itype);
cb7f680b 8426
1cd6e20d 8427 /* We could test all of the various optabs involved, but the fact of the
8428 matter is that (with the exception of i486 vs i586 and xadd) all targets
8429 that support any atomic operaton optab also implements compare-and-swap.
8430 Let optabs.c take care of expanding any compare-and-swap loop. */
29139cdc 8431 if (!can_compare_and_swap_p (imode, true))
cb7f680b 8432 return false;
8433
75a70cf9 8434 gsi = gsi_last_bb (load_bb);
8435 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_LOAD);
1cd6e20d 8436
8437 /* OpenMP does not imply any barrier-like semantics on its atomic ops.
8438 It only requires that the operation happen atomically. Thus we can
8439 use the RELAXED memory model. */
8440 call = build_call_expr_loc (loc, decl, 3, addr,
8441 fold_convert_loc (loc, itype, rhs),
bc7bff74 8442 build_int_cst (NULL,
8443 seq_cst ? MEMMODEL_SEQ_CST
8444 : MEMMODEL_RELAXED));
1cd6e20d 8445
2169f33b 8446 if (need_old || need_new)
8447 {
8448 lhs = need_old ? loaded_val : stored_val;
8449 call = fold_convert_loc (loc, TREE_TYPE (lhs), call);
8450 call = build2_loc (loc, MODIFY_EXPR, void_type_node, lhs, call);
8451 }
8452 else
8453 call = fold_convert_loc (loc, void_type_node, call);
75a70cf9 8454 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
8455 gsi_remove (&gsi, true);
cb7f680b 8456
75a70cf9 8457 gsi = gsi_last_bb (store_bb);
8458 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
8459 gsi_remove (&gsi, true);
8460 gsi = gsi_last_bb (store_bb);
8461 gsi_remove (&gsi, true);
cb7f680b 8462
8463 if (gimple_in_ssa_p (cfun))
8464 update_ssa (TODO_update_ssa_no_phi);
8465
8466 return true;
8467}
8468
8469/* A subroutine of expand_omp_atomic. Implement the atomic operation as:
8470
8471 oldval = *addr;
8472 repeat:
8473 newval = rhs; // with oldval replacing *addr in rhs
8474 oldval = __sync_val_compare_and_swap (addr, oldval, newval);
8475 if (oldval != newval)
8476 goto repeat;
8477
8478 INDEX is log2 of the size of the data type, and thus usable to find the
8479 index of the builtin decl. */
8480
8481static bool
8482expand_omp_atomic_pipeline (basic_block load_bb, basic_block store_bb,
8483 tree addr, tree loaded_val, tree stored_val,
8484 int index)
8485{
790368c5 8486 tree loadedi, storedi, initial, new_storedi, old_vali;
cb7f680b 8487 tree type, itype, cmpxchg, iaddr;
75a70cf9 8488 gimple_stmt_iterator si;
cb7f680b 8489 basic_block loop_header = single_succ (load_bb);
75a70cf9 8490 gimple phi, stmt;
cb7f680b 8491 edge e;
b9a16870 8492 enum built_in_function fncode;
cb7f680b 8493
1cd6e20d 8494 /* ??? We need a non-pointer interface to __atomic_compare_exchange in
8495 order to use the RELAXED memory model effectively. */
b9a16870 8496 fncode = (enum built_in_function)((int)BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_N
8497 + index + 1);
8498 cmpxchg = builtin_decl_explicit (fncode);
0f94f46b 8499 if (cmpxchg == NULL_TREE)
8500 return false;
cb7f680b 8501 type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
8502 itype = TREE_TYPE (TREE_TYPE (cmpxchg));
8503
29139cdc 8504 if (!can_compare_and_swap_p (TYPE_MODE (itype), true))
cb7f680b 8505 return false;
8506
75a70cf9 8507 /* Load the initial value, replacing the GIMPLE_OMP_ATOMIC_LOAD. */
8508 si = gsi_last_bb (load_bb);
8509 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
8510
790368c5 8511 /* For floating-point values, we'll need to view-convert them to integers
8512 so that we can perform the atomic compare and swap. Simplify the
8513 following code by always setting up the "i"ntegral variables. */
8514 if (!INTEGRAL_TYPE_P (type) && !POINTER_TYPE_P (type))
8515 {
75a70cf9 8516 tree iaddr_val;
8517
072f7ab1 8518 iaddr = create_tmp_reg (build_pointer_type_for_mode (itype, ptr_mode,
f9e245b2 8519 true));
75a70cf9 8520 iaddr_val
8521 = force_gimple_operand_gsi (&si,
8522 fold_convert (TREE_TYPE (iaddr), addr),
8523 false, NULL_TREE, true, GSI_SAME_STMT);
8524 stmt = gimple_build_assign (iaddr, iaddr_val);
8525 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
f9e245b2 8526 loadedi = create_tmp_var (itype);
790368c5 8527 if (gimple_in_ssa_p (cfun))
f9e245b2 8528 loadedi = make_ssa_name (loadedi);
790368c5 8529 }
8530 else
8531 {
8532 iaddr = addr;
8533 loadedi = loaded_val;
8534 }
75a70cf9 8535
2ed72821 8536 fncode = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
8537 tree loaddecl = builtin_decl_explicit (fncode);
8538 if (loaddecl)
8539 initial
8540 = fold_convert (TREE_TYPE (TREE_TYPE (iaddr)),
8541 build_call_expr (loaddecl, 2, iaddr,
8542 build_int_cst (NULL_TREE,
8543 MEMMODEL_RELAXED)));
8544 else
8545 initial = build2 (MEM_REF, TREE_TYPE (TREE_TYPE (iaddr)), iaddr,
8546 build_int_cst (TREE_TYPE (iaddr), 0));
8547
182cf5a9 8548 initial
2ed72821 8549 = force_gimple_operand_gsi (&si, initial, true, NULL_TREE, true,
8550 GSI_SAME_STMT);
790368c5 8551
8552 /* Move the value to the LOADEDI temporary. */
cb7f680b 8553 if (gimple_in_ssa_p (cfun))
8554 {
75a70cf9 8555 gcc_assert (gimple_seq_empty_p (phi_nodes (loop_header)));
790368c5 8556 phi = create_phi_node (loadedi, loop_header);
cb7f680b 8557 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, single_succ_edge (load_bb)),
8558 initial);
8559 }
8560 else
75a70cf9 8561 gsi_insert_before (&si,
8562 gimple_build_assign (loadedi, initial),
8563 GSI_SAME_STMT);
790368c5 8564 if (loadedi != loaded_val)
8565 {
75a70cf9 8566 gimple_stmt_iterator gsi2;
8567 tree x;
790368c5 8568
8569 x = build1 (VIEW_CONVERT_EXPR, type, loadedi);
75a70cf9 8570 gsi2 = gsi_start_bb (loop_header);
790368c5 8571 if (gimple_in_ssa_p (cfun))
8572 {
1a91d914 8573 gassign *stmt;
75a70cf9 8574 x = force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
8575 true, GSI_SAME_STMT);
8576 stmt = gimple_build_assign (loaded_val, x);
8577 gsi_insert_before (&gsi2, stmt, GSI_SAME_STMT);
790368c5 8578 }
8579 else
8580 {
75a70cf9 8581 x = build2 (MODIFY_EXPR, TREE_TYPE (loaded_val), loaded_val, x);
8582 force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
8583 true, GSI_SAME_STMT);
790368c5 8584 }
8585 }
75a70cf9 8586 gsi_remove (&si, true);
cb7f680b 8587
75a70cf9 8588 si = gsi_last_bb (store_bb);
8589 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
cb7f680b 8590
790368c5 8591 if (iaddr == addr)
8592 storedi = stored_val;
cb7f680b 8593 else
790368c5 8594 storedi =
75a70cf9 8595 force_gimple_operand_gsi (&si,
790368c5 8596 build1 (VIEW_CONVERT_EXPR, itype,
8597 stored_val), true, NULL_TREE, true,
75a70cf9 8598 GSI_SAME_STMT);
cb7f680b 8599
8600 /* Build the compare&swap statement. */
8601 new_storedi = build_call_expr (cmpxchg, 3, iaddr, loadedi, storedi);
75a70cf9 8602 new_storedi = force_gimple_operand_gsi (&si,
87f9ffa4 8603 fold_convert (TREE_TYPE (loadedi),
8604 new_storedi),
cb7f680b 8605 true, NULL_TREE,
75a70cf9 8606 true, GSI_SAME_STMT);
cb7f680b 8607
8608 if (gimple_in_ssa_p (cfun))
8609 old_vali = loadedi;
8610 else
8611 {
f9e245b2 8612 old_vali = create_tmp_var (TREE_TYPE (loadedi));
75a70cf9 8613 stmt = gimple_build_assign (old_vali, loadedi);
8614 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
cb7f680b 8615
75a70cf9 8616 stmt = gimple_build_assign (loadedi, new_storedi);
8617 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
cb7f680b 8618 }
8619
8620 /* Note that we always perform the comparison as an integer, even for
48e1416a 8621 floating point. This allows the atomic operation to properly
cb7f680b 8622 succeed even with NaNs and -0.0. */
75a70cf9 8623 stmt = gimple_build_cond_empty
8624 (build2 (NE_EXPR, boolean_type_node,
8625 new_storedi, old_vali));
8626 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
cb7f680b 8627
8628 /* Update cfg. */
8629 e = single_succ_edge (store_bb);
8630 e->flags &= ~EDGE_FALLTHRU;
8631 e->flags |= EDGE_FALSE_VALUE;
8632
8633 e = make_edge (store_bb, loop_header, EDGE_TRUE_VALUE);
8634
790368c5 8635 /* Copy the new value to loadedi (we already did that before the condition
cb7f680b 8636 if we are not in SSA). */
8637 if (gimple_in_ssa_p (cfun))
8638 {
75a70cf9 8639 phi = gimple_seq_first_stmt (phi_nodes (loop_header));
790368c5 8640 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, e), new_storedi);
cb7f680b 8641 }
8642
75a70cf9 8643 /* Remove GIMPLE_OMP_ATOMIC_STORE. */
8644 gsi_remove (&si, true);
cb7f680b 8645
04c2922b 8646 struct loop *loop = alloc_loop ();
8647 loop->header = loop_header;
5f037457 8648 loop->latch = store_bb;
04c2922b 8649 add_loop (loop, loop_header->loop_father);
8650
cb7f680b 8651 if (gimple_in_ssa_p (cfun))
8652 update_ssa (TODO_update_ssa_no_phi);
8653
8654 return true;
8655}
8656
8657/* A subroutine of expand_omp_atomic. Implement the atomic operation as:
8658
8659 GOMP_atomic_start ();
8660 *addr = rhs;
8661 GOMP_atomic_end ();
8662
8663 The result is not globally atomic, but works so long as all parallel
8664 references are within #pragma omp atomic directives. According to
8665 responses received from omp@openmp.org, appears to be within spec.
8666 Which makes sense, since that's how several other compilers handle
48e1416a 8667 this situation as well.
75a70cf9 8668 LOADED_VAL and ADDR are the operands of GIMPLE_OMP_ATOMIC_LOAD we're
8669 expanding. STORED_VAL is the operand of the matching
8670 GIMPLE_OMP_ATOMIC_STORE.
cb7f680b 8671
48e1416a 8672 We replace
8673 GIMPLE_OMP_ATOMIC_LOAD (loaded_val, addr) with
cb7f680b 8674 loaded_val = *addr;
8675
8676 and replace
3ec11c49 8677 GIMPLE_OMP_ATOMIC_STORE (stored_val) with
48e1416a 8678 *addr = stored_val;
cb7f680b 8679*/
8680
8681static bool
8682expand_omp_atomic_mutex (basic_block load_bb, basic_block store_bb,
8683 tree addr, tree loaded_val, tree stored_val)
8684{
75a70cf9 8685 gimple_stmt_iterator si;
1a91d914 8686 gassign *stmt;
cb7f680b 8687 tree t;
8688
75a70cf9 8689 si = gsi_last_bb (load_bb);
8690 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
cb7f680b 8691
b9a16870 8692 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START);
414c3a2c 8693 t = build_call_expr (t, 0);
75a70cf9 8694 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
cb7f680b 8695
182cf5a9 8696 stmt = gimple_build_assign (loaded_val, build_simple_mem_ref (addr));
75a70cf9 8697 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8698 gsi_remove (&si, true);
cb7f680b 8699
75a70cf9 8700 si = gsi_last_bb (store_bb);
8701 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
cb7f680b 8702
182cf5a9 8703 stmt = gimple_build_assign (build_simple_mem_ref (unshare_expr (addr)),
8704 stored_val);
75a70cf9 8705 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
cb7f680b 8706
b9a16870 8707 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END);
414c3a2c 8708 t = build_call_expr (t, 0);
75a70cf9 8709 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
8710 gsi_remove (&si, true);
cb7f680b 8711
8712 if (gimple_in_ssa_p (cfun))
8713 update_ssa (TODO_update_ssa_no_phi);
8714 return true;
8715}
8716
48e1416a 8717/* Expand an GIMPLE_OMP_ATOMIC statement. We try to expand
8718 using expand_omp_atomic_fetch_op. If it failed, we try to
cb7f680b 8719 call expand_omp_atomic_pipeline, and if it fails too, the
8720 ultimate fallback is wrapping the operation in a mutex
48e1416a 8721 (expand_omp_atomic_mutex). REGION is the atomic region built
8722 by build_omp_regions_1(). */
cb7f680b 8723
8724static void
8725expand_omp_atomic (struct omp_region *region)
8726{
8727 basic_block load_bb = region->entry, store_bb = region->exit;
1a91d914 8728 gomp_atomic_load *load = as_a <gomp_atomic_load *> (last_stmt (load_bb));
8729 gomp_atomic_store *store = as_a <gomp_atomic_store *> (last_stmt (store_bb));
75a70cf9 8730 tree loaded_val = gimple_omp_atomic_load_lhs (load);
8731 tree addr = gimple_omp_atomic_load_rhs (load);
8732 tree stored_val = gimple_omp_atomic_store_val (store);
cb7f680b 8733 tree type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
8734 HOST_WIDE_INT index;
8735
8736 /* Make sure the type is one of the supported sizes. */
e913b5cd 8737 index = tree_to_uhwi (TYPE_SIZE_UNIT (type));
cb7f680b 8738 index = exact_log2 (index);
8739 if (index >= 0 && index <= 4)
8740 {
8741 unsigned int align = TYPE_ALIGN_UNIT (type);
8742
8743 /* __sync builtins require strict data alignment. */
dcf7024c 8744 if (exact_log2 (align) >= index)
cb7f680b 8745 {
3ec11c49 8746 /* Atomic load. */
2169f33b 8747 if (loaded_val == stored_val
8748 && (GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
8749 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
8750 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
3ec11c49 8751 && expand_omp_atomic_load (load_bb, addr, loaded_val, index))
2169f33b 8752 return;
8753
3ec11c49 8754 /* Atomic store. */
2169f33b 8755 if ((GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
8756 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
8757 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
8758 && store_bb == single_succ (load_bb)
8759 && first_stmt (store_bb) == store
3ec11c49 8760 && expand_omp_atomic_store (load_bb, addr, loaded_val,
8761 stored_val, index))
2169f33b 8762 return;
8763
cb7f680b 8764 /* When possible, use specialized atomic update functions. */
8765 if ((INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type))
3ec11c49 8766 && store_bb == single_succ (load_bb)
8767 && expand_omp_atomic_fetch_op (load_bb, addr,
8768 loaded_val, stored_val, index))
8769 return;
cb7f680b 8770
8771 /* If we don't have specialized __sync builtins, try and implement
8772 as a compare and swap loop. */
8773 if (expand_omp_atomic_pipeline (load_bb, store_bb, addr,
8774 loaded_val, stored_val, index))
8775 return;
8776 }
8777 }
8778
8779 /* The ultimate fallback is wrapping the operation in a mutex. */
8780 expand_omp_atomic_mutex (load_bb, store_bb, addr, loaded_val, stored_val);
8781}
8782
1e8e9920 8783
ca4c3545 8784/* Expand the GIMPLE_OMP_TARGET starting at REGION. */
773c5ba7 8785
8786static void
bc7bff74 8787expand_omp_target (struct omp_region *region)
773c5ba7 8788{
bc7bff74 8789 basic_block entry_bb, exit_bb, new_bb;
ca4c3545 8790 struct function *child_cfun;
8791 tree child_fn, block, t;
bc7bff74 8792 gimple_stmt_iterator gsi;
1a91d914 8793 gomp_target *entry_stmt;
8794 gimple stmt;
bc7bff74 8795 edge e;
ca4c3545 8796 bool offloaded, data_region;
bc7bff74 8797
1a91d914 8798 entry_stmt = as_a <gomp_target *> (last_stmt (region->entry));
bc7bff74 8799 new_bb = region->entry;
ca4c3545 8800
8801 offloaded = is_gimple_omp_offloaded (entry_stmt);
8802 switch (gimple_omp_target_kind (entry_stmt))
8803 {
8804 case GF_OMP_TARGET_KIND_REGION:
8805 case GF_OMP_TARGET_KIND_UPDATE:
8806 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
8807 case GF_OMP_TARGET_KIND_OACC_KERNELS:
8808 case GF_OMP_TARGET_KIND_OACC_UPDATE:
8809 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
8810 data_region = false;
8811 break;
8812 case GF_OMP_TARGET_KIND_DATA:
8813 case GF_OMP_TARGET_KIND_OACC_DATA:
8814 data_region = true;
8815 break;
8816 default:
8817 gcc_unreachable ();
8818 }
8819
8820 child_fn = NULL_TREE;
8821 child_cfun = NULL;
8822 if (offloaded)
bc7bff74 8823 {
8824 child_fn = gimple_omp_target_child_fn (entry_stmt);
8825 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
8826 }
8827
ca4c3545 8828 /* Supported by expand_omp_taskreg, but not here. */
8829 if (child_cfun != NULL)
8830 gcc_checking_assert (!child_cfun->cfg);
8831 gcc_checking_assert (!gimple_in_ssa_p (cfun));
8832
bc7bff74 8833 entry_bb = region->entry;
8834 exit_bb = region->exit;
8835
ca4c3545 8836 if (offloaded)
bc7bff74 8837 {
8838 unsigned srcidx, dstidx, num;
8839
ca4c3545 8840 /* If the offloading region needs data sent from the parent
bc7bff74 8841 function, then the very first statement (except possible
ca4c3545 8842 tree profile counter updates) of the offloading body
bc7bff74 8843 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
8844 &.OMP_DATA_O is passed as an argument to the child function,
8845 we need to replace it with the argument as seen by the child
8846 function.
8847
8848 In most cases, this will end up being the identity assignment
ca4c3545 8849 .OMP_DATA_I = .OMP_DATA_I. However, if the offloading body had
bc7bff74 8850 a function call that has been inlined, the original PARM_DECL
8851 .OMP_DATA_I may have been converted into a different local
8852 variable. In which case, we need to keep the assignment. */
ca4c3545 8853 tree data_arg = gimple_omp_target_data_arg (entry_stmt);
8854 if (data_arg)
bc7bff74 8855 {
8856 basic_block entry_succ_bb = single_succ (entry_bb);
8857 gimple_stmt_iterator gsi;
8858 tree arg;
8859 gimple tgtcopy_stmt = NULL;
ca4c3545 8860 tree sender = TREE_VEC_ELT (data_arg, 0);
bc7bff74 8861
8862 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
8863 {
8864 gcc_assert (!gsi_end_p (gsi));
8865 stmt = gsi_stmt (gsi);
8866 if (gimple_code (stmt) != GIMPLE_ASSIGN)
8867 continue;
8868
8869 if (gimple_num_ops (stmt) == 2)
8870 {
8871 tree arg = gimple_assign_rhs1 (stmt);
8872
8873 /* We're ignoring the subcode because we're
8874 effectively doing a STRIP_NOPS. */
8875
8876 if (TREE_CODE (arg) == ADDR_EXPR
8877 && TREE_OPERAND (arg, 0) == sender)
8878 {
8879 tgtcopy_stmt = stmt;
8880 break;
8881 }
8882 }
8883 }
8884
8885 gcc_assert (tgtcopy_stmt != NULL);
8886 arg = DECL_ARGUMENTS (child_fn);
8887
8888 gcc_assert (gimple_assign_lhs (tgtcopy_stmt) == arg);
8889 gsi_remove (&gsi, true);
8890 }
8891
8892 /* Declare local variables needed in CHILD_CFUN. */
8893 block = DECL_INITIAL (child_fn);
8894 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
ca4c3545 8895 /* The gimplifier could record temporaries in the offloading block
bc7bff74 8896 rather than in containing function's local_decls chain,
8897 which would mean cgraph missed finalizing them. Do it now. */
8898 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
8899 if (TREE_CODE (t) == VAR_DECL
8900 && TREE_STATIC (t)
8901 && !DECL_EXTERNAL (t))
97221fd7 8902 varpool_node::finalize_decl (t);
bc7bff74 8903 DECL_SAVED_TREE (child_fn) = NULL;
8904 /* We'll create a CFG for child_fn, so no gimple body is needed. */
8905 gimple_set_body (child_fn, NULL);
8906 TREE_USED (block) = 1;
8907
8908 /* Reset DECL_CONTEXT on function arguments. */
8909 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
8910 DECL_CONTEXT (t) = child_fn;
8911
ca4c3545 8912 /* Split ENTRY_BB at GIMPLE_*,
bc7bff74 8913 so that it can be moved to the child function. */
8914 gsi = gsi_last_bb (entry_bb);
8915 stmt = gsi_stmt (gsi);
ca4c3545 8916 gcc_assert (stmt
8917 && gimple_code (stmt) == gimple_code (entry_stmt));
bc7bff74 8918 e = split_block (entry_bb, stmt);
923635e7 8919 gsi_remove (&gsi, true);
bc7bff74 8920 entry_bb = e->dest;
8921 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
8922
8923 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
8924 if (exit_bb)
8925 {
8926 gsi = gsi_last_bb (exit_bb);
8927 gcc_assert (!gsi_end_p (gsi)
8928 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
8929 stmt = gimple_build_return (NULL);
8930 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
8931 gsi_remove (&gsi, true);
8932 }
8933
ca4c3545 8934 /* Move the offloading region into CHILD_CFUN. */
bc7bff74 8935
8936 block = gimple_block (entry_stmt);
8937
8938 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
8939 if (exit_bb)
8940 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
8941 /* When the OMP expansion process cannot guarantee an up-to-date
8942 loop tree arrange for the child function to fixup loops. */
8943 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
8944 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
8945
8946 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
8947 num = vec_safe_length (child_cfun->local_decls);
8948 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
8949 {
8950 t = (*child_cfun->local_decls)[srcidx];
8951 if (DECL_CONTEXT (t) == cfun->decl)
8952 continue;
8953 if (srcidx != dstidx)
8954 (*child_cfun->local_decls)[dstidx] = t;
8955 dstidx++;
8956 }
8957 if (dstidx != num)
8958 vec_safe_truncate (child_cfun->local_decls, dstidx);
8959
8960 /* Inform the callgraph about the new function. */
8961 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
415d1b9a 8962 cgraph_node::add_new_function (child_fn, true);
bc7bff74 8963
7114ebdd 8964#ifdef ENABLE_OFFLOADING
dccabdd1 8965 /* Add the new function to the offload table. */
8966 vec_safe_push (offload_funcs, child_fn);
7114ebdd 8967#endif
dccabdd1 8968
bc7bff74 8969 /* Fix the callgraph edges for child_cfun. Those for cfun will be
8970 fixed in a following pass. */
8971 push_cfun (child_cfun);
35ee1c66 8972 cgraph_edge::rebuild_edges ();
bc7bff74 8973
7114ebdd 8974#ifdef ENABLE_OFFLOADING
b0c5e347 8975 /* Prevent IPA from removing child_fn as unreachable, since there are no
8976 refs from the parent function to child_fn in offload LTO mode. */
7114ebdd 8977 struct cgraph_node *node = cgraph_node::get (child_fn);
b0c5e347 8978 node->mark_force_output ();
7114ebdd 8979#endif
b0c5e347 8980
bc7bff74 8981 /* Some EH regions might become dead, see PR34608. If
8982 pass_cleanup_cfg isn't the first pass to happen with the
8983 new child, these dead EH edges might cause problems.
8984 Clean them up now. */
8985 if (flag_exceptions)
8986 {
8987 basic_block bb;
8988 bool changed = false;
8989
fc00614f 8990 FOR_EACH_BB_FN (bb, cfun)
bc7bff74 8991 changed |= gimple_purge_dead_eh_edges (bb);
8992 if (changed)
8993 cleanup_tree_cfg ();
8994 }
8995 pop_cfun ();
8996 }
8997
ca4c3545 8998 /* Emit a library call to launch the offloading region, or do data
bc7bff74 8999 transfers. */
9000 tree t1, t2, t3, t4, device, cond, c, clauses;
9001 enum built_in_function start_ix;
9002 location_t clause_loc;
9003
ca4c3545 9004 switch (gimple_omp_target_kind (entry_stmt))
9005 {
9006 case GF_OMP_TARGET_KIND_REGION:
9007 start_ix = BUILT_IN_GOMP_TARGET;
9008 break;
9009 case GF_OMP_TARGET_KIND_DATA:
9010 start_ix = BUILT_IN_GOMP_TARGET_DATA;
9011 break;
9012 case GF_OMP_TARGET_KIND_UPDATE:
9013 start_ix = BUILT_IN_GOMP_TARGET_UPDATE;
9014 break;
9015 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
9016 case GF_OMP_TARGET_KIND_OACC_KERNELS:
9017 start_ix = BUILT_IN_GOACC_PARALLEL;
9018 break;
9019 case GF_OMP_TARGET_KIND_OACC_DATA:
9020 start_ix = BUILT_IN_GOACC_DATA_START;
9021 break;
9022 case GF_OMP_TARGET_KIND_OACC_UPDATE:
9023 start_ix = BUILT_IN_GOACC_UPDATE;
9024 break;
9025 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
9026 start_ix = BUILT_IN_GOACC_ENTER_EXIT_DATA;
9027 break;
9028 default:
9029 gcc_unreachable ();
9030 }
bc7bff74 9031
ca4c3545 9032 clauses = gimple_omp_target_clauses (entry_stmt);
bc7bff74 9033
ca4c3545 9034 /* By default, the value of DEVICE is GOMP_DEVICE_ICV (let runtime
9035 library choose) and there is no conditional. */
bc7bff74 9036 cond = NULL_TREE;
ca4c3545 9037 device = build_int_cst (integer_type_node, GOMP_DEVICE_ICV);
bc7bff74 9038
9039 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
9040 if (c)
9041 cond = OMP_CLAUSE_IF_EXPR (c);
9042
9043 c = find_omp_clause (clauses, OMP_CLAUSE_DEVICE);
9044 if (c)
9045 {
ca4c3545 9046 /* Even if we pass it to all library function calls, it is currently only
9047 defined/used for the OpenMP target ones. */
9048 gcc_checking_assert (start_ix == BUILT_IN_GOMP_TARGET
9049 || start_ix == BUILT_IN_GOMP_TARGET_DATA
9050 || start_ix == BUILT_IN_GOMP_TARGET_UPDATE);
9051
bc7bff74 9052 device = OMP_CLAUSE_DEVICE_ID (c);
9053 clause_loc = OMP_CLAUSE_LOCATION (c);
9054 }
9055 else
9056 clause_loc = gimple_location (entry_stmt);
9057
9058 /* Ensure 'device' is of the correct type. */
9059 device = fold_convert_loc (clause_loc, integer_type_node, device);
9060
9061 /* If we found the clause 'if (cond)', build
ca4c3545 9062 (cond ? device : GOMP_DEVICE_HOST_FALLBACK). */
bc7bff74 9063 if (cond)
9064 {
9065 cond = gimple_boolify (cond);
9066
9067 basic_block cond_bb, then_bb, else_bb;
9068 edge e;
9069 tree tmp_var;
9070
f9e245b2 9071 tmp_var = create_tmp_var (TREE_TYPE (device));
ca4c3545 9072 if (offloaded)
4302d619 9073 e = split_block_after_labels (new_bb);
ca4c3545 9074 else
bc7bff74 9075 {
9076 gsi = gsi_last_bb (new_bb);
9077 gsi_prev (&gsi);
9078 e = split_block (new_bb, gsi_stmt (gsi));
9079 }
bc7bff74 9080 cond_bb = e->src;
9081 new_bb = e->dest;
9082 remove_edge (e);
9083
9084 then_bb = create_empty_bb (cond_bb);
9085 else_bb = create_empty_bb (then_bb);
9086 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
9087 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
9088
9089 stmt = gimple_build_cond_empty (cond);
9090 gsi = gsi_last_bb (cond_bb);
9091 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
9092
9093 gsi = gsi_start_bb (then_bb);
9094 stmt = gimple_build_assign (tmp_var, device);
9095 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
9096
9097 gsi = gsi_start_bb (else_bb);
9098 stmt = gimple_build_assign (tmp_var,
ca4c3545 9099 build_int_cst (integer_type_node,
9100 GOMP_DEVICE_HOST_FALLBACK));
bc7bff74 9101 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
9102
9103 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
9104 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
b3083327 9105 add_bb_to_loop (then_bb, cond_bb->loop_father);
9106 add_bb_to_loop (else_bb, cond_bb->loop_father);
bc7bff74 9107 make_edge (then_bb, new_bb, EDGE_FALLTHRU);
9108 make_edge (else_bb, new_bb, EDGE_FALLTHRU);
9109
9110 device = tmp_var;
9111 }
9112
9113 gsi = gsi_last_bb (new_bb);
9114 t = gimple_omp_target_data_arg (entry_stmt);
9115 if (t == NULL)
9116 {
9117 t1 = size_zero_node;
9118 t2 = build_zero_cst (ptr_type_node);
9119 t3 = t2;
9120 t4 = t2;
9121 }
9122 else
9123 {
9124 t1 = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (TREE_VEC_ELT (t, 1))));
9125 t1 = size_binop (PLUS_EXPR, t1, size_int (1));
9126 t2 = build_fold_addr_expr (TREE_VEC_ELT (t, 0));
9127 t3 = build_fold_addr_expr (TREE_VEC_ELT (t, 1));
9128 t4 = build_fold_addr_expr (TREE_VEC_ELT (t, 2));
9129 }
9130
9131 gimple g;
ca4c3545 9132 /* The maximum number used by any start_ix, without varargs. */
02c05c9b 9133 auto_vec<tree, 11> args;
9134 args.quick_push (device);
ca4c3545 9135 if (offloaded)
02c05c9b 9136 args.quick_push (build_fold_addr_expr (child_fn));
dc19c8fd 9137 switch (start_ix)
9138 {
9139 case BUILT_IN_GOMP_TARGET:
9140 case BUILT_IN_GOMP_TARGET_DATA:
9141 case BUILT_IN_GOMP_TARGET_UPDATE:
9142 /* This const void * is part of the current ABI, but we're not actually
9143 using it. */
02c05c9b 9144 args.quick_push (build_zero_cst (ptr_type_node));
dc19c8fd 9145 break;
9146 case BUILT_IN_GOACC_DATA_START:
9147 case BUILT_IN_GOACC_ENTER_EXIT_DATA:
9148 case BUILT_IN_GOACC_PARALLEL:
9149 case BUILT_IN_GOACC_UPDATE:
9150 break;
9151 default:
9152 gcc_unreachable ();
9153 }
02c05c9b 9154 args.quick_push (t1);
9155 args.quick_push (t2);
9156 args.quick_push (t3);
9157 args.quick_push (t4);
ca4c3545 9158 switch (start_ix)
9159 {
9160 case BUILT_IN_GOACC_DATA_START:
9161 case BUILT_IN_GOMP_TARGET:
9162 case BUILT_IN_GOMP_TARGET_DATA:
9163 case BUILT_IN_GOMP_TARGET_UPDATE:
9164 break;
9165 case BUILT_IN_GOACC_PARALLEL:
9166 {
9167 tree t_num_gangs, t_num_workers, t_vector_length;
9168
9169 /* Default values for num_gangs, num_workers, and vector_length. */
9170 t_num_gangs = t_num_workers = t_vector_length
9171 = fold_convert_loc (gimple_location (entry_stmt),
9172 integer_type_node, integer_one_node);
9173 /* ..., but if present, use the value specified by the respective
9174 clause, making sure that are of the correct type. */
9175 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_GANGS);
9176 if (c)
9177 t_num_gangs = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
9178 integer_type_node,
9179 OMP_CLAUSE_NUM_GANGS_EXPR (c));
9180 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_WORKERS);
9181 if (c)
9182 t_num_workers = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
9183 integer_type_node,
9184 OMP_CLAUSE_NUM_WORKERS_EXPR (c));
9185 c = find_omp_clause (clauses, OMP_CLAUSE_VECTOR_LENGTH);
9186 if (c)
9187 t_vector_length = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
9188 integer_type_node,
9189 OMP_CLAUSE_VECTOR_LENGTH_EXPR (c));
02c05c9b 9190 args.quick_push (t_num_gangs);
9191 args.quick_push (t_num_workers);
9192 args.quick_push (t_vector_length);
ca4c3545 9193 }
9194 /* FALLTHRU */
9195 case BUILT_IN_GOACC_ENTER_EXIT_DATA:
9196 case BUILT_IN_GOACC_UPDATE:
9197 {
9198 tree t_async;
9199 int t_wait_idx;
9200
9201 /* Default values for t_async. */
9202 t_async = fold_convert_loc (gimple_location (entry_stmt),
9203 integer_type_node,
9204 build_int_cst (integer_type_node,
9205 GOMP_ASYNC_SYNC));
9206 /* ..., but if present, use the value specified by the respective
9207 clause, making sure that is of the correct type. */
9208 c = find_omp_clause (clauses, OMP_CLAUSE_ASYNC);
9209 if (c)
9210 t_async = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
9211 integer_type_node,
9212 OMP_CLAUSE_ASYNC_EXPR (c));
9213
02c05c9b 9214 args.quick_push (t_async);
ca4c3545 9215 /* Save the index, and... */
02c05c9b 9216 t_wait_idx = args.length ();
ca4c3545 9217 /* ... push a default value. */
02c05c9b 9218 args.quick_push (fold_convert_loc (gimple_location (entry_stmt),
9219 integer_type_node,
9220 integer_zero_node));
ca4c3545 9221 c = find_omp_clause (clauses, OMP_CLAUSE_WAIT);
9222 if (c)
9223 {
9224 int n = 0;
9225
9226 for (; c; c = OMP_CLAUSE_CHAIN (c))
9227 {
9228 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_WAIT)
9229 {
02c05c9b 9230 args.safe_push (fold_convert_loc (OMP_CLAUSE_LOCATION (c),
9231 integer_type_node,
9232 OMP_CLAUSE_WAIT_EXPR (c)));
ca4c3545 9233 n++;
9234 }
9235 }
9236
9237 /* Now that we know the number, replace the default value. */
02c05c9b 9238 args.ordered_remove (t_wait_idx);
9239 args.quick_insert (t_wait_idx,
9240 fold_convert_loc (gimple_location (entry_stmt),
9241 integer_type_node,
9242 build_int_cst (integer_type_node, n)));
ca4c3545 9243 }
9244 }
9245 break;
9246 default:
9247 gcc_unreachable ();
bc7bff74 9248 }
ca4c3545 9249
02c05c9b 9250 g = gimple_build_call_vec (builtin_decl_explicit (start_ix), args);
bc7bff74 9251 gimple_set_location (g, gimple_location (entry_stmt));
9252 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
ca4c3545 9253 if (!offloaded)
bc7bff74 9254 {
9255 g = gsi_stmt (gsi);
9256 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_TARGET);
9257 gsi_remove (&gsi, true);
9258 }
ca4c3545 9259 if (data_region
9260 && region->exit)
bc7bff74 9261 {
9262 gsi = gsi_last_bb (region->exit);
9263 g = gsi_stmt (gsi);
9264 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_RETURN);
9265 gsi_remove (&gsi, true);
9266 }
9267}
9268
9269
9270/* Expand the parallel region tree rooted at REGION. Expansion
9271 proceeds in depth-first order. Innermost regions are expanded
9272 first. This way, parallel regions that require a new function to
75a70cf9 9273 be created (e.g., GIMPLE_OMP_PARALLEL) can be expanded without having any
773c5ba7 9274 internal dependencies in their body. */
9275
9276static void
9277expand_omp (struct omp_region *region)
9278{
9279 while (region)
9280 {
1d22f541 9281 location_t saved_location;
bc7bff74 9282 gimple inner_stmt = NULL;
1d22f541 9283
d1d5b012 9284 /* First, determine whether this is a combined parallel+workshare
9285 region. */
75a70cf9 9286 if (region->type == GIMPLE_OMP_PARALLEL)
d1d5b012 9287 determine_parallel_type (region);
9288
bc7bff74 9289 if (region->type == GIMPLE_OMP_FOR
9290 && gimple_omp_for_combined_p (last_stmt (region->entry)))
9291 inner_stmt = last_stmt (region->inner->entry);
9292
773c5ba7 9293 if (region->inner)
9294 expand_omp (region->inner);
9295
1d22f541 9296 saved_location = input_location;
75a70cf9 9297 if (gimple_has_location (last_stmt (region->entry)))
9298 input_location = gimple_location (last_stmt (region->entry));
1d22f541 9299
61e47ac8 9300 switch (region->type)
773c5ba7 9301 {
75a70cf9 9302 case GIMPLE_OMP_PARALLEL:
9303 case GIMPLE_OMP_TASK:
fd6481cf 9304 expand_omp_taskreg (region);
9305 break;
9306
75a70cf9 9307 case GIMPLE_OMP_FOR:
bc7bff74 9308 expand_omp_for (region, inner_stmt);
61e47ac8 9309 break;
773c5ba7 9310
75a70cf9 9311 case GIMPLE_OMP_SECTIONS:
61e47ac8 9312 expand_omp_sections (region);
9313 break;
773c5ba7 9314
75a70cf9 9315 case GIMPLE_OMP_SECTION:
61e47ac8 9316 /* Individual omp sections are handled together with their
75a70cf9 9317 parent GIMPLE_OMP_SECTIONS region. */
61e47ac8 9318 break;
773c5ba7 9319
75a70cf9 9320 case GIMPLE_OMP_SINGLE:
61e47ac8 9321 expand_omp_single (region);
9322 break;
773c5ba7 9323
75a70cf9 9324 case GIMPLE_OMP_MASTER:
bc7bff74 9325 case GIMPLE_OMP_TASKGROUP:
75a70cf9 9326 case GIMPLE_OMP_ORDERED:
9327 case GIMPLE_OMP_CRITICAL:
bc7bff74 9328 case GIMPLE_OMP_TEAMS:
61e47ac8 9329 expand_omp_synch (region);
9330 break;
773c5ba7 9331
75a70cf9 9332 case GIMPLE_OMP_ATOMIC_LOAD:
cb7f680b 9333 expand_omp_atomic (region);
9334 break;
9335
bc7bff74 9336 case GIMPLE_OMP_TARGET:
9337 expand_omp_target (region);
9338 break;
9339
61e47ac8 9340 default:
9341 gcc_unreachable ();
9342 }
cc5982dc 9343
1d22f541 9344 input_location = saved_location;
773c5ba7 9345 region = region->next;
9346 }
9347}
9348
9349
9350/* Helper for build_omp_regions. Scan the dominator tree starting at
28c92cbb 9351 block BB. PARENT is the region that contains BB. If SINGLE_TREE is
9352 true, the function ends once a single tree is built (otherwise, whole
9353 forest of OMP constructs may be built). */
773c5ba7 9354
9355static void
28c92cbb 9356build_omp_regions_1 (basic_block bb, struct omp_region *parent,
9357 bool single_tree)
773c5ba7 9358{
75a70cf9 9359 gimple_stmt_iterator gsi;
9360 gimple stmt;
773c5ba7 9361 basic_block son;
9362
75a70cf9 9363 gsi = gsi_last_bb (bb);
9364 if (!gsi_end_p (gsi) && is_gimple_omp (gsi_stmt (gsi)))
773c5ba7 9365 {
9366 struct omp_region *region;
75a70cf9 9367 enum gimple_code code;
773c5ba7 9368
75a70cf9 9369 stmt = gsi_stmt (gsi);
9370 code = gimple_code (stmt);
9371 if (code == GIMPLE_OMP_RETURN)
773c5ba7 9372 {
9373 /* STMT is the return point out of region PARENT. Mark it
9374 as the exit point and make PARENT the immediately
9375 enclosing region. */
9376 gcc_assert (parent);
9377 region = parent;
61e47ac8 9378 region->exit = bb;
773c5ba7 9379 parent = parent->outer;
773c5ba7 9380 }
75a70cf9 9381 else if (code == GIMPLE_OMP_ATOMIC_STORE)
cb7f680b 9382 {
75a70cf9 9383 /* GIMPLE_OMP_ATOMIC_STORE is analoguous to
9384 GIMPLE_OMP_RETURN, but matches with
9385 GIMPLE_OMP_ATOMIC_LOAD. */
cb7f680b 9386 gcc_assert (parent);
75a70cf9 9387 gcc_assert (parent->type == GIMPLE_OMP_ATOMIC_LOAD);
cb7f680b 9388 region = parent;
9389 region->exit = bb;
9390 parent = parent->outer;
9391 }
75a70cf9 9392 else if (code == GIMPLE_OMP_CONTINUE)
61e47ac8 9393 {
9394 gcc_assert (parent);
9395 parent->cont = bb;
9396 }
75a70cf9 9397 else if (code == GIMPLE_OMP_SECTIONS_SWITCH)
ac6e3339 9398 {
75a70cf9 9399 /* GIMPLE_OMP_SECTIONS_SWITCH is part of
9400 GIMPLE_OMP_SECTIONS, and we do nothing for it. */
ac6e3339 9401 }
773c5ba7 9402 else
9403 {
61e47ac8 9404 region = new_omp_region (bb, code, parent);
ca4c3545 9405 /* Otherwise... */
9406 if (code == GIMPLE_OMP_TARGET)
9407 {
9408 switch (gimple_omp_target_kind (stmt))
9409 {
9410 case GF_OMP_TARGET_KIND_REGION:
9411 case GF_OMP_TARGET_KIND_DATA:
9412 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
9413 case GF_OMP_TARGET_KIND_OACC_KERNELS:
9414 case GF_OMP_TARGET_KIND_OACC_DATA:
9415 break;
9416 case GF_OMP_TARGET_KIND_UPDATE:
9417 case GF_OMP_TARGET_KIND_OACC_UPDATE:
9418 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
9419 /* ..., other than for those stand-alone directives... */
9420 region = NULL;
9421 break;
9422 default:
9423 gcc_unreachable ();
9424 }
9425 }
9426 /* ..., this directive becomes the parent for a new region. */
9427 if (region)
9428 parent = region;
773c5ba7 9429 }
773c5ba7 9430 }
9431
28c92cbb 9432 if (single_tree && !parent)
9433 return;
9434
773c5ba7 9435 for (son = first_dom_son (CDI_DOMINATORS, bb);
9436 son;
9437 son = next_dom_son (CDI_DOMINATORS, son))
28c92cbb 9438 build_omp_regions_1 (son, parent, single_tree);
9439}
9440
9441/* Builds the tree of OMP regions rooted at ROOT, storing it to
9442 root_omp_region. */
9443
9444static void
9445build_omp_regions_root (basic_block root)
9446{
9447 gcc_assert (root_omp_region == NULL);
9448 build_omp_regions_1 (root, NULL, true);
9449 gcc_assert (root_omp_region != NULL);
773c5ba7 9450}
9451
28c92cbb 9452/* Expands omp construct (and its subconstructs) starting in HEAD. */
9453
9454void
9455omp_expand_local (basic_block head)
9456{
9457 build_omp_regions_root (head);
9458 if (dump_file && (dump_flags & TDF_DETAILS))
9459 {
9460 fprintf (dump_file, "\nOMP region tree\n\n");
9461 dump_omp_region (dump_file, root_omp_region, 0);
9462 fprintf (dump_file, "\n");
9463 }
9464
9465 remove_exit_barriers (root_omp_region);
9466 expand_omp (root_omp_region);
9467
9468 free_omp_regions ();
9469}
773c5ba7 9470
9471/* Scan the CFG and build a tree of OMP regions. Return the root of
9472 the OMP region tree. */
9473
9474static void
9475build_omp_regions (void)
9476{
61e47ac8 9477 gcc_assert (root_omp_region == NULL);
773c5ba7 9478 calculate_dominance_info (CDI_DOMINATORS);
34154e27 9479 build_omp_regions_1 (ENTRY_BLOCK_PTR_FOR_FN (cfun), NULL, false);
773c5ba7 9480}
9481
773c5ba7 9482/* Main entry point for expanding OMP-GIMPLE into runtime calls. */
9483
2a1990e9 9484static unsigned int
773c5ba7 9485execute_expand_omp (void)
9486{
9487 build_omp_regions ();
9488
61e47ac8 9489 if (!root_omp_region)
9490 return 0;
773c5ba7 9491
61e47ac8 9492 if (dump_file)
9493 {
9494 fprintf (dump_file, "\nOMP region tree\n\n");
9495 dump_omp_region (dump_file, root_omp_region, 0);
9496 fprintf (dump_file, "\n");
773c5ba7 9497 }
61e47ac8 9498
9499 remove_exit_barriers (root_omp_region);
9500
9501 expand_omp (root_omp_region);
9502
61e47ac8 9503 cleanup_tree_cfg ();
9504
9505 free_omp_regions ();
9506
2a1990e9 9507 return 0;
773c5ba7 9508}
9509
79acaae1 9510/* OMP expansion -- the default pass, run before creation of SSA form. */
9511
cbe8bda8 9512namespace {
9513
9514const pass_data pass_data_expand_omp =
9515{
9516 GIMPLE_PASS, /* type */
9517 "ompexp", /* name */
9518 OPTGROUP_NONE, /* optinfo_flags */
cbe8bda8 9519 TV_NONE, /* tv_id */
9520 PROP_gimple_any, /* properties_required */
8917c50b 9521 PROP_gimple_eomp, /* properties_provided */
cbe8bda8 9522 0, /* properties_destroyed */
9523 0, /* todo_flags_start */
9524 0, /* todo_flags_finish */
773c5ba7 9525};
cbe8bda8 9526
9527class pass_expand_omp : public gimple_opt_pass
9528{
9529public:
9af5ce0c 9530 pass_expand_omp (gcc::context *ctxt)
9531 : gimple_opt_pass (pass_data_expand_omp, ctxt)
cbe8bda8 9532 {}
9533
9534 /* opt_pass methods: */
8917c50b 9535 virtual unsigned int execute (function *)
31315c24 9536 {
ca4c3545 9537 bool gate = ((flag_cilkplus != 0 || flag_openacc != 0 || flag_openmp != 0
9538 || flag_openmp_simd != 0)
9539 && !seen_error ());
31315c24 9540
8917c50b 9541 /* This pass always runs, to provide PROP_gimple_eomp.
ca4c3545 9542 But often, there is nothing to do. */
8917c50b 9543 if (!gate)
9544 return 0;
9545
9546 return execute_expand_omp ();
9547 }
cbe8bda8 9548
9549}; // class pass_expand_omp
9550
9551} // anon namespace
9552
9553gimple_opt_pass *
9554make_pass_expand_omp (gcc::context *ctxt)
9555{
9556 return new pass_expand_omp (ctxt);
9557}
8917c50b 9558
9559namespace {
9560
9561const pass_data pass_data_expand_omp_ssa =
9562{
9563 GIMPLE_PASS, /* type */
9564 "ompexpssa", /* name */
9565 OPTGROUP_NONE, /* optinfo_flags */
9566 TV_NONE, /* tv_id */
9567 PROP_cfg | PROP_ssa, /* properties_required */
9568 PROP_gimple_eomp, /* properties_provided */
9569 0, /* properties_destroyed */
9570 0, /* todo_flags_start */
9571 TODO_cleanup_cfg | TODO_rebuild_alias, /* todo_flags_finish */
9572};
9573
9574class pass_expand_omp_ssa : public gimple_opt_pass
9575{
9576public:
9577 pass_expand_omp_ssa (gcc::context *ctxt)
9578 : gimple_opt_pass (pass_data_expand_omp_ssa, ctxt)
9579 {}
9580
9581 /* opt_pass methods: */
9582 virtual bool gate (function *fun)
9583 {
9584 return !(fun->curr_properties & PROP_gimple_eomp);
9585 }
9586 virtual unsigned int execute (function *) { return execute_expand_omp (); }
9587
9588}; // class pass_expand_omp_ssa
9589
9590} // anon namespace
9591
9592gimple_opt_pass *
9593make_pass_expand_omp_ssa (gcc::context *ctxt)
9594{
9595 return new pass_expand_omp_ssa (ctxt);
9596}
773c5ba7 9597\f
ca4c3545 9598/* Routines to lower OMP directives into OMP-GIMPLE. */
9599
9600/* Helper function to preform, potentially COMPLEX_TYPE, operation and
9601 convert it to gimple. */
9602static void
9603oacc_gimple_assign (tree dest, tree_code op, tree src, gimple_seq *seq)
9604{
9605 gimple stmt;
9606
9607 if (TREE_CODE (TREE_TYPE (dest)) != COMPLEX_TYPE)
9608 {
9609 stmt = gimple_build_assign (dest, op, dest, src);
9610 gimple_seq_add_stmt (seq, stmt);
9611 return;
9612 }
9613
9614 tree t = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9615 tree rdest = fold_build1 (REALPART_EXPR, TREE_TYPE (TREE_TYPE (dest)), dest);
9616 gimplify_assign (t, rdest, seq);
9617 rdest = t;
9618
9619 t = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9620 tree idest = fold_build1 (IMAGPART_EXPR, TREE_TYPE (TREE_TYPE (dest)), dest);
9621 gimplify_assign (t, idest, seq);
9622 idest = t;
9623
9624 t = create_tmp_var (TREE_TYPE (TREE_TYPE (src)));
9625 tree rsrc = fold_build1 (REALPART_EXPR, TREE_TYPE (TREE_TYPE (src)), src);
9626 gimplify_assign (t, rsrc, seq);
9627 rsrc = t;
9628
9629 t = create_tmp_var (TREE_TYPE (TREE_TYPE (src)));
9630 tree isrc = fold_build1 (IMAGPART_EXPR, TREE_TYPE (TREE_TYPE (src)), src);
9631 gimplify_assign (t, isrc, seq);
9632 isrc = t;
9633
9634 tree r = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9635 tree i = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9636 tree result;
9637
9638 if (op == PLUS_EXPR)
9639 {
9640 stmt = gimple_build_assign (r, op, rdest, rsrc);
9641 gimple_seq_add_stmt (seq, stmt);
9642
9643 stmt = gimple_build_assign (i, op, idest, isrc);
9644 gimple_seq_add_stmt (seq, stmt);
9645 }
9646 else if (op == MULT_EXPR)
9647 {
9648 /* Let x = a + ib = dest, y = c + id = src.
9649 x * y = (ac - bd) + i(ad + bc) */
9650 tree ac = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9651 tree bd = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9652 tree ad = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9653 tree bc = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9654
9655 stmt = gimple_build_assign (ac, MULT_EXPR, rdest, rsrc);
9656 gimple_seq_add_stmt (seq, stmt);
9657
9658 stmt = gimple_build_assign (bd, MULT_EXPR, idest, isrc);
9659 gimple_seq_add_stmt (seq, stmt);
9660
9661 stmt = gimple_build_assign (r, MINUS_EXPR, ac, bd);
9662 gimple_seq_add_stmt (seq, stmt);
9663
9664 stmt = gimple_build_assign (ad, MULT_EXPR, rdest, isrc);
9665 gimple_seq_add_stmt (seq, stmt);
9666
9667 stmt = gimple_build_assign (bd, MULT_EXPR, idest, rsrc);
9668 gimple_seq_add_stmt (seq, stmt);
9669
9670 stmt = gimple_build_assign (i, PLUS_EXPR, ad, bc);
9671 gimple_seq_add_stmt (seq, stmt);
9672 }
9673 else
9674 gcc_unreachable ();
9675
9676 result = build2 (COMPLEX_EXPR, TREE_TYPE (dest), r, i);
9677 gimplify_assign (dest, result, seq);
9678}
9679
9680/* Helper function to initialize local data for the reduction arrays.
9681 The reduction arrays need to be placed inside the calling function
9682 for accelerators, or else the host won't be able to preform the final
9683 reduction. */
9684
9685static void
9686oacc_initialize_reduction_data (tree clauses, tree nthreads,
9687 gimple_seq *stmt_seqp, omp_context *ctx)
9688{
9689 tree c, t, oc;
9690 gimple stmt;
9691 omp_context *octx;
9692
9693 /* Find the innermost OpenACC parallel context. */
9694 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TARGET
9695 && (gimple_omp_target_kind (ctx->stmt)
9696 == GF_OMP_TARGET_KIND_OACC_PARALLEL))
9697 octx = ctx;
9698 else
9699 octx = ctx->outer;
9700 gcc_checking_assert (gimple_code (octx->stmt) == GIMPLE_OMP_TARGET
9701 && (gimple_omp_target_kind (octx->stmt)
9702 == GF_OMP_TARGET_KIND_OACC_PARALLEL));
9703
9704 /* Extract the clauses. */
9705 oc = gimple_omp_target_clauses (octx->stmt);
9706
9707 /* Find the last outer clause. */
9708 for (; oc && OMP_CLAUSE_CHAIN (oc); oc = OMP_CLAUSE_CHAIN (oc))
9709 ;
9710
9711 /* Allocate arrays for each reduction variable. */
9712 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
9713 {
9714 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
9715 continue;
9716
9717 tree var = OMP_CLAUSE_DECL (c);
9718 tree type = get_base_type (var);
9719 tree array = lookup_oacc_reduction (oacc_get_reduction_array_id (var),
9720 ctx);
9721 tree size, call;
9722
9723 /* Calculate size of the reduction array. */
9724 t = create_tmp_var (TREE_TYPE (nthreads));
9725 stmt = gimple_build_assign (t, MULT_EXPR, nthreads,
9726 fold_convert (TREE_TYPE (nthreads),
9727 TYPE_SIZE_UNIT (type)));
9728 gimple_seq_add_stmt (stmt_seqp, stmt);
9729
9730 size = create_tmp_var (sizetype);
9731 gimplify_assign (size, fold_build1 (NOP_EXPR, sizetype, t), stmt_seqp);
9732
9733 /* Now allocate memory for it. */
9734 call = unshare_expr (builtin_decl_explicit (BUILT_IN_ALLOCA));
9735 stmt = gimple_build_call (call, 1, size);
9736 gimple_call_set_lhs (stmt, array);
9737 gimple_seq_add_stmt (stmt_seqp, stmt);
9738
9739 /* Map this array into the accelerator. */
9740
9741 /* Add the reduction array to the list of clauses. */
9742 tree x = array;
9743 t = build_omp_clause (gimple_location (ctx->stmt), OMP_CLAUSE_MAP);
9744 OMP_CLAUSE_SET_MAP_KIND (t, GOMP_MAP_FORCE_FROM);
9745 OMP_CLAUSE_DECL (t) = x;
9746 OMP_CLAUSE_CHAIN (t) = NULL;
9747 if (oc)
9748 OMP_CLAUSE_CHAIN (oc) = t;
9749 else
9750 gimple_omp_target_set_clauses (as_a <gomp_target *> (octx->stmt), t);
9751 OMP_CLAUSE_SIZE (t) = size;
9752 oc = t;
9753 }
9754}
9755
9756/* Helper function to process the array of partial reductions. Nthreads
9757 indicates the number of threads. Unfortunately, GOACC_GET_NUM_THREADS
9758 cannot be used here, because nthreads on the host may be different than
9759 on the accelerator. */
9760
9761static void
9762oacc_finalize_reduction_data (tree clauses, tree nthreads,
9763 gimple_seq *stmt_seqp, omp_context *ctx)
9764{
9765 tree c, x, var, array, loop_header, loop_body, loop_exit, type;
9766 gimple stmt;
9767
9768 /* Create for loop.
9769
9770 let var = the original reduction variable
9771 let array = reduction variable array
9772
9773 for (i = 0; i < nthreads; i++)
9774 var op= array[i]
9775 */
9776
9777 loop_header = create_artificial_label (UNKNOWN_LOCATION);
9778 loop_body = create_artificial_label (UNKNOWN_LOCATION);
9779 loop_exit = create_artificial_label (UNKNOWN_LOCATION);
9780
9781 /* Create and initialize an index variable. */
9782 tree ix = create_tmp_var (sizetype);
9783 gimplify_assign (ix, fold_build1 (NOP_EXPR, sizetype, integer_zero_node),
9784 stmt_seqp);
9785
9786 /* Insert the loop header label here. */
9787 gimple_seq_add_stmt (stmt_seqp, gimple_build_label (loop_header));
9788
9789 /* Exit loop if ix >= nthreads. */
9790 x = create_tmp_var (sizetype);
9791 gimplify_assign (x, fold_build1 (NOP_EXPR, sizetype, nthreads), stmt_seqp);
9792 stmt = gimple_build_cond (GE_EXPR, ix, x, loop_exit, loop_body);
9793 gimple_seq_add_stmt (stmt_seqp, stmt);
9794
9795 /* Insert the loop body label here. */
9796 gimple_seq_add_stmt (stmt_seqp, gimple_build_label (loop_body));
9797
9798 /* Collapse each reduction array, one element at a time. */
9799 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
9800 {
9801 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
9802 continue;
9803
9804 tree_code reduction_code = OMP_CLAUSE_REDUCTION_CODE (c);
9805
9806 /* reduction(-:var) sums up the partial results, so it acts
9807 identically to reduction(+:var). */
9808 if (reduction_code == MINUS_EXPR)
9809 reduction_code = PLUS_EXPR;
9810
9811 /* Set up reduction variable var. */
9812 var = OMP_CLAUSE_DECL (c);
9813 type = get_base_type (var);
9814 array = lookup_oacc_reduction (oacc_get_reduction_array_id
9815 (OMP_CLAUSE_DECL (c)), ctx);
9816
9817 /* Calculate the array offset. */
9818 tree offset = create_tmp_var (sizetype);
9819 gimplify_assign (offset, TYPE_SIZE_UNIT (type), stmt_seqp);
9820 stmt = gimple_build_assign (offset, MULT_EXPR, offset, ix);
9821 gimple_seq_add_stmt (stmt_seqp, stmt);
9822
9823 tree ptr = create_tmp_var (TREE_TYPE (array));
9824 stmt = gimple_build_assign (ptr, POINTER_PLUS_EXPR, array, offset);
9825 gimple_seq_add_stmt (stmt_seqp, stmt);
9826
9827 /* Extract array[ix] into mem. */
9828 tree mem = create_tmp_var (type);
9829 gimplify_assign (mem, build_simple_mem_ref (ptr), stmt_seqp);
9830
9831 /* Find the original reduction variable. */
9832 if (is_reference (var))
9833 var = build_simple_mem_ref (var);
9834
9835 tree t = create_tmp_var (type);
9836
9837 x = lang_hooks.decls.omp_clause_assign_op (c, t, var);
9838 gimplify_and_add (unshare_expr(x), stmt_seqp);
9839
9840 /* var = var op mem */
9841 switch (OMP_CLAUSE_REDUCTION_CODE (c))
9842 {
9843 case TRUTH_ANDIF_EXPR:
9844 case TRUTH_ORIF_EXPR:
9845 t = fold_build2 (OMP_CLAUSE_REDUCTION_CODE (c), integer_type_node,
9846 t, mem);
9847 gimplify_and_add (t, stmt_seqp);
9848 break;
9849 default:
9850 /* The lhs isn't a gimple_reg when var is COMPLEX_TYPE. */
9851 oacc_gimple_assign (t, OMP_CLAUSE_REDUCTION_CODE (c), mem,
9852 stmt_seqp);
9853 }
9854
9855 t = fold_build1 (NOP_EXPR, TREE_TYPE (var), t);
9856 x = lang_hooks.decls.omp_clause_assign_op (c, var, t);
9857 gimplify_and_add (unshare_expr(x), stmt_seqp);
9858 }
9859
9860 /* Increment the induction variable. */
9861 tree one = fold_build1 (NOP_EXPR, sizetype, integer_one_node);
9862 stmt = gimple_build_assign (ix, PLUS_EXPR, ix, one);
9863 gimple_seq_add_stmt (stmt_seqp, stmt);
9864
9865 /* Go back to the top of the loop. */
9866 gimple_seq_add_stmt (stmt_seqp, gimple_build_goto (loop_header));
9867
9868 /* Place the loop exit label here. */
9869 gimple_seq_add_stmt (stmt_seqp, gimple_build_label (loop_exit));
9870}
9871
9872/* Scan through all of the gimple stmts searching for an OMP_FOR_EXPR, and
9873 scan that for reductions. */
9874
9875static void
9876oacc_process_reduction_data (gimple_seq *body, gimple_seq *in_stmt_seqp,
9877 gimple_seq *out_stmt_seqp, omp_context *ctx)
9878{
9879 gimple_stmt_iterator gsi;
9880 gimple_seq inner = NULL;
9881
9882 /* A collapse clause may have inserted a new bind block. */
9883 gsi = gsi_start (*body);
9884 while (!gsi_end_p (gsi))
9885 {
9886 gimple stmt = gsi_stmt (gsi);
9887 if (gbind *bind_stmt = dyn_cast <gbind *> (stmt))
9888 {
9889 inner = gimple_bind_body (bind_stmt);
9890 body = &inner;
9891 gsi = gsi_start (*body);
9892 }
9893 else if (dyn_cast <gomp_for *> (stmt))
9894 break;
9895 else
9896 gsi_next (&gsi);
9897 }
9898
9899 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
9900 {
9901 tree clauses, nthreads, t, c, acc_device, acc_device_host, call,
9902 enter, exit;
9903 bool reduction_found = false;
9904
9905 gimple stmt = gsi_stmt (gsi);
9906
9907 switch (gimple_code (stmt))
9908 {
9909 case GIMPLE_OMP_FOR:
9910 clauses = gimple_omp_for_clauses (stmt);
9911
9912 /* Search for a reduction clause. */
9913 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
9914 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
9915 {
9916 reduction_found = true;
9917 break;
9918 }
9919
9920 if (!reduction_found)
9921 break;
9922
9923 ctx = maybe_lookup_ctx (stmt);
9924 t = NULL_TREE;
9925
9926 /* Extract the number of threads. */
9927 nthreads = create_tmp_var (sizetype);
9928 t = oacc_max_threads (ctx);
9929 gimplify_assign (nthreads, t, in_stmt_seqp);
9930
9931 /* Determine if this is kernel will be executed on the host. */
9932 call = builtin_decl_explicit (BUILT_IN_ACC_GET_DEVICE_TYPE);
9933 acc_device = create_tmp_var (integer_type_node, ".acc_device_type");
9934 stmt = gimple_build_call (call, 0);
9935 gimple_call_set_lhs (stmt, acc_device);
9936 gimple_seq_add_stmt (in_stmt_seqp, stmt);
9937
9938 /* Set nthreads = 1 for ACC_DEVICE_TYPE=host. */
9939 acc_device_host = create_tmp_var (integer_type_node,
9940 ".acc_device_host");
9941 gimplify_assign (acc_device_host,
9942 build_int_cst (integer_type_node,
9943 GOMP_DEVICE_HOST),
9944 in_stmt_seqp);
9945
9946 enter = create_artificial_label (UNKNOWN_LOCATION);
9947 exit = create_artificial_label (UNKNOWN_LOCATION);
9948
9949 stmt = gimple_build_cond (EQ_EXPR, acc_device, acc_device_host,
9950 enter, exit);
9951 gimple_seq_add_stmt (in_stmt_seqp, stmt);
9952 gimple_seq_add_stmt (in_stmt_seqp, gimple_build_label (enter));
9953 gimplify_assign (nthreads, fold_build1 (NOP_EXPR, sizetype,
9954 integer_one_node),
9955 in_stmt_seqp);
9956 gimple_seq_add_stmt (in_stmt_seqp, gimple_build_label (exit));
9957
9958 /* Also, set nthreads = 1 for ACC_DEVICE_TYPE=host_nonshm. */
9959 gimplify_assign (acc_device_host,
9960 build_int_cst (integer_type_node,
9961 GOMP_DEVICE_HOST_NONSHM),
9962 in_stmt_seqp);
9963
9964 enter = create_artificial_label (UNKNOWN_LOCATION);
9965 exit = create_artificial_label (UNKNOWN_LOCATION);
9966
9967 stmt = gimple_build_cond (EQ_EXPR, acc_device, acc_device_host,
9968 enter, exit);
9969 gimple_seq_add_stmt (in_stmt_seqp, stmt);
9970 gimple_seq_add_stmt (in_stmt_seqp, gimple_build_label (enter));
9971 gimplify_assign (nthreads, fold_build1 (NOP_EXPR, sizetype,
9972 integer_one_node),
9973 in_stmt_seqp);
9974 gimple_seq_add_stmt (in_stmt_seqp, gimple_build_label (exit));
9975
9976 oacc_initialize_reduction_data (clauses, nthreads, in_stmt_seqp,
9977 ctx);
9978 oacc_finalize_reduction_data (clauses, nthreads, out_stmt_seqp, ctx);
9979 break;
9980 default:
9981 // Scan for other directives which support reduction here.
9982 break;
9983 }
9984 }
9985}
773c5ba7 9986
bc7bff74 9987/* If ctx is a worksharing context inside of a cancellable parallel
9988 region and it isn't nowait, add lhs to its GIMPLE_OMP_RETURN
9989 and conditional branch to parallel's cancel_label to handle
9990 cancellation in the implicit barrier. */
9991
9992static void
9993maybe_add_implicit_barrier_cancel (omp_context *ctx, gimple_seq *body)
9994{
9995 gimple omp_return = gimple_seq_last_stmt (*body);
9996 gcc_assert (gimple_code (omp_return) == GIMPLE_OMP_RETURN);
9997 if (gimple_omp_return_nowait_p (omp_return))
9998 return;
9999 if (ctx->outer
10000 && gimple_code (ctx->outer->stmt) == GIMPLE_OMP_PARALLEL
10001 && ctx->outer->cancellable)
10002 {
15b28553 10003 tree fndecl = builtin_decl_explicit (BUILT_IN_GOMP_CANCEL);
10004 tree c_bool_type = TREE_TYPE (TREE_TYPE (fndecl));
f9e245b2 10005 tree lhs = create_tmp_var (c_bool_type);
bc7bff74 10006 gimple_omp_return_set_lhs (omp_return, lhs);
10007 tree fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
15b28553 10008 gimple g = gimple_build_cond (NE_EXPR, lhs,
10009 fold_convert (c_bool_type,
10010 boolean_false_node),
bc7bff74 10011 ctx->outer->cancel_label, fallthru_label);
10012 gimple_seq_add_stmt (body, g);
10013 gimple_seq_add_stmt (body, gimple_build_label (fallthru_label));
10014 }
10015}
10016
75a70cf9 10017/* Lower the OpenMP sections directive in the current statement in GSI_P.
10018 CTX is the enclosing OMP context for the current statement. */
773c5ba7 10019
10020static void
75a70cf9 10021lower_omp_sections (gimple_stmt_iterator *gsi_p, omp_context *ctx)
773c5ba7 10022{
75a70cf9 10023 tree block, control;
10024 gimple_stmt_iterator tgsi;
1a91d914 10025 gomp_sections *stmt;
10026 gimple t;
10027 gbind *new_stmt, *bind;
e3a19533 10028 gimple_seq ilist, dlist, olist, new_body;
773c5ba7 10029
1a91d914 10030 stmt = as_a <gomp_sections *> (gsi_stmt (*gsi_p));
773c5ba7 10031
8a4a28a8 10032 push_gimplify_context ();
773c5ba7 10033
10034 dlist = NULL;
10035 ilist = NULL;
75a70cf9 10036 lower_rec_input_clauses (gimple_omp_sections_clauses (stmt),
bc7bff74 10037 &ilist, &dlist, ctx, NULL);
773c5ba7 10038
e3a19533 10039 new_body = gimple_omp_body (stmt);
10040 gimple_omp_set_body (stmt, NULL);
10041 tgsi = gsi_start (new_body);
10042 for (; !gsi_end_p (tgsi); gsi_next (&tgsi))
773c5ba7 10043 {
10044 omp_context *sctx;
75a70cf9 10045 gimple sec_start;
773c5ba7 10046
75a70cf9 10047 sec_start = gsi_stmt (tgsi);
773c5ba7 10048 sctx = maybe_lookup_ctx (sec_start);
10049 gcc_assert (sctx);
10050
e3a19533 10051 lower_omp (gimple_omp_body_ptr (sec_start), sctx);
10052 gsi_insert_seq_after (&tgsi, gimple_omp_body (sec_start),
10053 GSI_CONTINUE_LINKING);
75a70cf9 10054 gimple_omp_set_body (sec_start, NULL);
773c5ba7 10055
e3a19533 10056 if (gsi_one_before_end_p (tgsi))
773c5ba7 10057 {
75a70cf9 10058 gimple_seq l = NULL;
10059 lower_lastprivate_clauses (gimple_omp_sections_clauses (stmt), NULL,
773c5ba7 10060 &l, ctx);
e3a19533 10061 gsi_insert_seq_after (&tgsi, l, GSI_CONTINUE_LINKING);
75a70cf9 10062 gimple_omp_section_set_last (sec_start);
773c5ba7 10063 }
48e1416a 10064
e3a19533 10065 gsi_insert_after (&tgsi, gimple_build_omp_return (false),
10066 GSI_CONTINUE_LINKING);
773c5ba7 10067 }
1e8e9920 10068
10069 block = make_node (BLOCK);
e3a19533 10070 bind = gimple_build_bind (NULL, new_body, block);
1e8e9920 10071
75a70cf9 10072 olist = NULL;
10073 lower_reduction_clauses (gimple_omp_sections_clauses (stmt), &olist, ctx);
773c5ba7 10074
1d22f541 10075 block = make_node (BLOCK);
75a70cf9 10076 new_stmt = gimple_build_bind (NULL, NULL, block);
e3a19533 10077 gsi_replace (gsi_p, new_stmt, true);
773c5ba7 10078
1d22f541 10079 pop_gimplify_context (new_stmt);
75a70cf9 10080 gimple_bind_append_vars (new_stmt, ctx->block_vars);
10081 BLOCK_VARS (block) = gimple_bind_vars (bind);
1d22f541 10082 if (BLOCK_VARS (block))
10083 TREE_USED (block) = 1;
10084
75a70cf9 10085 new_body = NULL;
10086 gimple_seq_add_seq (&new_body, ilist);
10087 gimple_seq_add_stmt (&new_body, stmt);
10088 gimple_seq_add_stmt (&new_body, gimple_build_omp_sections_switch ());
10089 gimple_seq_add_stmt (&new_body, bind);
61e47ac8 10090
ac6e3339 10091 control = create_tmp_var (unsigned_type_node, ".section");
75a70cf9 10092 t = gimple_build_omp_continue (control, control);
10093 gimple_omp_sections_set_control (stmt, control);
10094 gimple_seq_add_stmt (&new_body, t);
61e47ac8 10095
75a70cf9 10096 gimple_seq_add_seq (&new_body, olist);
bc7bff74 10097 if (ctx->cancellable)
10098 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
75a70cf9 10099 gimple_seq_add_seq (&new_body, dlist);
773c5ba7 10100
75a70cf9 10101 new_body = maybe_catch_exception (new_body);
aade31a0 10102
75a70cf9 10103 t = gimple_build_omp_return
10104 (!!find_omp_clause (gimple_omp_sections_clauses (stmt),
10105 OMP_CLAUSE_NOWAIT));
10106 gimple_seq_add_stmt (&new_body, t);
bc7bff74 10107 maybe_add_implicit_barrier_cancel (ctx, &new_body);
61e47ac8 10108
75a70cf9 10109 gimple_bind_set_body (new_stmt, new_body);
1e8e9920 10110}
10111
10112
773c5ba7 10113/* A subroutine of lower_omp_single. Expand the simple form of
75a70cf9 10114 a GIMPLE_OMP_SINGLE, without a copyprivate clause:
1e8e9920 10115
10116 if (GOMP_single_start ())
10117 BODY;
10118 [ GOMP_barrier (); ] -> unless 'nowait' is present.
773c5ba7 10119
10120 FIXME. It may be better to delay expanding the logic of this until
10121 pass_expand_omp. The expanded logic may make the job more difficult
10122 to a synchronization analysis pass. */
1e8e9920 10123
10124static void
1a91d914 10125lower_omp_single_simple (gomp_single *single_stmt, gimple_seq *pre_p)
1e8e9920 10126{
e60a6f7b 10127 location_t loc = gimple_location (single_stmt);
10128 tree tlabel = create_artificial_label (loc);
10129 tree flabel = create_artificial_label (loc);
75a70cf9 10130 gimple call, cond;
10131 tree lhs, decl;
10132
b9a16870 10133 decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_START);
f9e245b2 10134 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (decl)));
75a70cf9 10135 call = gimple_build_call (decl, 0);
10136 gimple_call_set_lhs (call, lhs);
10137 gimple_seq_add_stmt (pre_p, call);
10138
10139 cond = gimple_build_cond (EQ_EXPR, lhs,
389dd41b 10140 fold_convert_loc (loc, TREE_TYPE (lhs),
10141 boolean_true_node),
75a70cf9 10142 tlabel, flabel);
10143 gimple_seq_add_stmt (pre_p, cond);
10144 gimple_seq_add_stmt (pre_p, gimple_build_label (tlabel));
10145 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
10146 gimple_seq_add_stmt (pre_p, gimple_build_label (flabel));
1e8e9920 10147}
10148
773c5ba7 10149
10150/* A subroutine of lower_omp_single. Expand the simple form of
75a70cf9 10151 a GIMPLE_OMP_SINGLE, with a copyprivate clause:
1e8e9920 10152
10153 #pragma omp single copyprivate (a, b, c)
10154
10155 Create a new structure to hold copies of 'a', 'b' and 'c' and emit:
10156
10157 {
10158 if ((copyout_p = GOMP_single_copy_start ()) == NULL)
10159 {
10160 BODY;
10161 copyout.a = a;
10162 copyout.b = b;
10163 copyout.c = c;
10164 GOMP_single_copy_end (&copyout);
10165 }
10166 else
10167 {
10168 a = copyout_p->a;
10169 b = copyout_p->b;
10170 c = copyout_p->c;
10171 }
10172 GOMP_barrier ();
10173 }
773c5ba7 10174
10175 FIXME. It may be better to delay expanding the logic of this until
10176 pass_expand_omp. The expanded logic may make the job more difficult
10177 to a synchronization analysis pass. */
1e8e9920 10178
10179static void
1a91d914 10180lower_omp_single_copy (gomp_single *single_stmt, gimple_seq *pre_p,
10181 omp_context *ctx)
1e8e9920 10182{
b9a16870 10183 tree ptr_type, t, l0, l1, l2, bfn_decl;
75a70cf9 10184 gimple_seq copyin_seq;
e60a6f7b 10185 location_t loc = gimple_location (single_stmt);
1e8e9920 10186
10187 ctx->sender_decl = create_tmp_var (ctx->record_type, ".omp_copy_o");
10188
10189 ptr_type = build_pointer_type (ctx->record_type);
10190 ctx->receiver_decl = create_tmp_var (ptr_type, ".omp_copy_i");
10191
e60a6f7b 10192 l0 = create_artificial_label (loc);
10193 l1 = create_artificial_label (loc);
10194 l2 = create_artificial_label (loc);
1e8e9920 10195
b9a16870 10196 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_START);
10197 t = build_call_expr_loc (loc, bfn_decl, 0);
389dd41b 10198 t = fold_convert_loc (loc, ptr_type, t);
75a70cf9 10199 gimplify_assign (ctx->receiver_decl, t, pre_p);
1e8e9920 10200
10201 t = build2 (EQ_EXPR, boolean_type_node, ctx->receiver_decl,
10202 build_int_cst (ptr_type, 0));
10203 t = build3 (COND_EXPR, void_type_node, t,
10204 build_and_jump (&l0), build_and_jump (&l1));
10205 gimplify_and_add (t, pre_p);
10206
75a70cf9 10207 gimple_seq_add_stmt (pre_p, gimple_build_label (l0));
1e8e9920 10208
75a70cf9 10209 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
1e8e9920 10210
10211 copyin_seq = NULL;
75a70cf9 10212 lower_copyprivate_clauses (gimple_omp_single_clauses (single_stmt), pre_p,
1e8e9920 10213 &copyin_seq, ctx);
10214
389dd41b 10215 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
b9a16870 10216 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_END);
10217 t = build_call_expr_loc (loc, bfn_decl, 1, t);
1e8e9920 10218 gimplify_and_add (t, pre_p);
10219
10220 t = build_and_jump (&l2);
10221 gimplify_and_add (t, pre_p);
10222
75a70cf9 10223 gimple_seq_add_stmt (pre_p, gimple_build_label (l1));
1e8e9920 10224
75a70cf9 10225 gimple_seq_add_seq (pre_p, copyin_seq);
1e8e9920 10226
75a70cf9 10227 gimple_seq_add_stmt (pre_p, gimple_build_label (l2));
1e8e9920 10228}
10229
773c5ba7 10230
1e8e9920 10231/* Expand code for an OpenMP single directive. */
10232
10233static void
75a70cf9 10234lower_omp_single (gimple_stmt_iterator *gsi_p, omp_context *ctx)
1e8e9920 10235{
75a70cf9 10236 tree block;
1a91d914 10237 gimple t;
10238 gomp_single *single_stmt = as_a <gomp_single *> (gsi_stmt (*gsi_p));
10239 gbind *bind;
bc7bff74 10240 gimple_seq bind_body, bind_body_tail = NULL, dlist;
1e8e9920 10241
8a4a28a8 10242 push_gimplify_context ();
1e8e9920 10243
e3a19533 10244 block = make_node (BLOCK);
10245 bind = gimple_build_bind (NULL, NULL, block);
10246 gsi_replace (gsi_p, bind, true);
75a70cf9 10247 bind_body = NULL;
e3a19533 10248 dlist = NULL;
75a70cf9 10249 lower_rec_input_clauses (gimple_omp_single_clauses (single_stmt),
bc7bff74 10250 &bind_body, &dlist, ctx, NULL);
e3a19533 10251 lower_omp (gimple_omp_body_ptr (single_stmt), ctx);
1e8e9920 10252
75a70cf9 10253 gimple_seq_add_stmt (&bind_body, single_stmt);
1e8e9920 10254
10255 if (ctx->record_type)
75a70cf9 10256 lower_omp_single_copy (single_stmt, &bind_body, ctx);
1e8e9920 10257 else
75a70cf9 10258 lower_omp_single_simple (single_stmt, &bind_body);
10259
10260 gimple_omp_set_body (single_stmt, NULL);
1e8e9920 10261
75a70cf9 10262 gimple_seq_add_seq (&bind_body, dlist);
61e47ac8 10263
75a70cf9 10264 bind_body = maybe_catch_exception (bind_body);
61e47ac8 10265
48e1416a 10266 t = gimple_build_omp_return
75a70cf9 10267 (!!find_omp_clause (gimple_omp_single_clauses (single_stmt),
10268 OMP_CLAUSE_NOWAIT));
bc7bff74 10269 gimple_seq_add_stmt (&bind_body_tail, t);
10270 maybe_add_implicit_barrier_cancel (ctx, &bind_body_tail);
10271 if (ctx->record_type)
10272 {
10273 gimple_stmt_iterator gsi = gsi_start (bind_body_tail);
10274 tree clobber = build_constructor (ctx->record_type, NULL);
10275 TREE_THIS_VOLATILE (clobber) = 1;
10276 gsi_insert_after (&gsi, gimple_build_assign (ctx->sender_decl,
10277 clobber), GSI_SAME_STMT);
10278 }
10279 gimple_seq_add_seq (&bind_body, bind_body_tail);
e3a19533 10280 gimple_bind_set_body (bind, bind_body);
61e47ac8 10281
1e8e9920 10282 pop_gimplify_context (bind);
773c5ba7 10283
75a70cf9 10284 gimple_bind_append_vars (bind, ctx->block_vars);
10285 BLOCK_VARS (block) = ctx->block_vars;
1d22f541 10286 if (BLOCK_VARS (block))
10287 TREE_USED (block) = 1;
1e8e9920 10288}
10289
773c5ba7 10290
1e8e9920 10291/* Expand code for an OpenMP master directive. */
10292
10293static void
75a70cf9 10294lower_omp_master (gimple_stmt_iterator *gsi_p, omp_context *ctx)
1e8e9920 10295{
b9a16870 10296 tree block, lab = NULL, x, bfn_decl;
1a91d914 10297 gimple stmt = gsi_stmt (*gsi_p);
10298 gbind *bind;
389dd41b 10299 location_t loc = gimple_location (stmt);
75a70cf9 10300 gimple_seq tseq;
1e8e9920 10301
8a4a28a8 10302 push_gimplify_context ();
1e8e9920 10303
10304 block = make_node (BLOCK);
e3a19533 10305 bind = gimple_build_bind (NULL, NULL, block);
10306 gsi_replace (gsi_p, bind, true);
10307 gimple_bind_add_stmt (bind, stmt);
61e47ac8 10308
b9a16870 10309 bfn_decl = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
10310 x = build_call_expr_loc (loc, bfn_decl, 0);
1e8e9920 10311 x = build2 (EQ_EXPR, boolean_type_node, x, integer_zero_node);
10312 x = build3 (COND_EXPR, void_type_node, x, NULL, build_and_jump (&lab));
75a70cf9 10313 tseq = NULL;
10314 gimplify_and_add (x, &tseq);
10315 gimple_bind_add_seq (bind, tseq);
1e8e9920 10316
e3a19533 10317 lower_omp (gimple_omp_body_ptr (stmt), ctx);
75a70cf9 10318 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
10319 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
10320 gimple_omp_set_body (stmt, NULL);
1e8e9920 10321
75a70cf9 10322 gimple_bind_add_stmt (bind, gimple_build_label (lab));
61e47ac8 10323
75a70cf9 10324 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
61e47ac8 10325
1e8e9920 10326 pop_gimplify_context (bind);
773c5ba7 10327
75a70cf9 10328 gimple_bind_append_vars (bind, ctx->block_vars);
10329 BLOCK_VARS (block) = ctx->block_vars;
1e8e9920 10330}
10331
773c5ba7 10332
bc7bff74 10333/* Expand code for an OpenMP taskgroup directive. */
10334
10335static void
10336lower_omp_taskgroup (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10337{
1a91d914 10338 gimple stmt = gsi_stmt (*gsi_p);
10339 gcall *x;
10340 gbind *bind;
bc7bff74 10341 tree block = make_node (BLOCK);
10342
10343 bind = gimple_build_bind (NULL, NULL, block);
10344 gsi_replace (gsi_p, bind, true);
10345 gimple_bind_add_stmt (bind, stmt);
10346
10347 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_TASKGROUP_START),
10348 0);
10349 gimple_bind_add_stmt (bind, x);
10350
10351 lower_omp (gimple_omp_body_ptr (stmt), ctx);
10352 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
10353 gimple_omp_set_body (stmt, NULL);
10354
10355 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
10356
10357 gimple_bind_append_vars (bind, ctx->block_vars);
10358 BLOCK_VARS (block) = ctx->block_vars;
10359}
10360
10361
1e8e9920 10362/* Expand code for an OpenMP ordered directive. */
10363
10364static void
75a70cf9 10365lower_omp_ordered (gimple_stmt_iterator *gsi_p, omp_context *ctx)
1e8e9920 10366{
75a70cf9 10367 tree block;
1a91d914 10368 gimple stmt = gsi_stmt (*gsi_p);
10369 gcall *x;
10370 gbind *bind;
1e8e9920 10371
8a4a28a8 10372 push_gimplify_context ();
1e8e9920 10373
10374 block = make_node (BLOCK);
e3a19533 10375 bind = gimple_build_bind (NULL, NULL, block);
10376 gsi_replace (gsi_p, bind, true);
10377 gimple_bind_add_stmt (bind, stmt);
61e47ac8 10378
b9a16870 10379 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_START),
10380 0);
75a70cf9 10381 gimple_bind_add_stmt (bind, x);
1e8e9920 10382
e3a19533 10383 lower_omp (gimple_omp_body_ptr (stmt), ctx);
75a70cf9 10384 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
10385 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
10386 gimple_omp_set_body (stmt, NULL);
1e8e9920 10387
b9a16870 10388 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_END), 0);
75a70cf9 10389 gimple_bind_add_stmt (bind, x);
61e47ac8 10390
75a70cf9 10391 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
61e47ac8 10392
1e8e9920 10393 pop_gimplify_context (bind);
773c5ba7 10394
75a70cf9 10395 gimple_bind_append_vars (bind, ctx->block_vars);
10396 BLOCK_VARS (block) = gimple_bind_vars (bind);
1e8e9920 10397}
10398
1e8e9920 10399
75a70cf9 10400/* Gimplify a GIMPLE_OMP_CRITICAL statement. This is a relatively simple
1e8e9920 10401 substitution of a couple of function calls. But in the NAMED case,
10402 requires that languages coordinate a symbol name. It is therefore
10403 best put here in common code. */
10404
d4786b13 10405static GTY(()) hash_map<tree, tree> *critical_name_mutexes;
1e8e9920 10406
10407static void
75a70cf9 10408lower_omp_critical (gimple_stmt_iterator *gsi_p, omp_context *ctx)
1e8e9920 10409{
75a70cf9 10410 tree block;
10411 tree name, lock, unlock;
1a91d914 10412 gomp_critical *stmt = as_a <gomp_critical *> (gsi_stmt (*gsi_p));
10413 gbind *bind;
389dd41b 10414 location_t loc = gimple_location (stmt);
75a70cf9 10415 gimple_seq tbody;
1e8e9920 10416
75a70cf9 10417 name = gimple_omp_critical_name (stmt);
1e8e9920 10418 if (name)
10419 {
c2f47e15 10420 tree decl;
1e8e9920 10421
10422 if (!critical_name_mutexes)
d4786b13 10423 critical_name_mutexes = hash_map<tree, tree>::create_ggc (10);
1e8e9920 10424
d4786b13 10425 tree *n = critical_name_mutexes->get (name);
1e8e9920 10426 if (n == NULL)
10427 {
10428 char *new_str;
10429
f9e245b2 10430 decl = create_tmp_var_raw (ptr_type_node);
1e8e9920 10431
10432 new_str = ACONCAT ((".gomp_critical_user_",
10433 IDENTIFIER_POINTER (name), NULL));
10434 DECL_NAME (decl) = get_identifier (new_str);
10435 TREE_PUBLIC (decl) = 1;
10436 TREE_STATIC (decl) = 1;
10437 DECL_COMMON (decl) = 1;
10438 DECL_ARTIFICIAL (decl) = 1;
10439 DECL_IGNORED_P (decl) = 1;
b0c5e347 10440
97221fd7 10441 varpool_node::finalize_decl (decl);
1e8e9920 10442
d4786b13 10443 critical_name_mutexes->put (name, decl);
1e8e9920 10444 }
10445 else
d4786b13 10446 decl = *n;
1e8e9920 10447
ca4c3545 10448 /* If '#pragma omp critical' is inside offloaded region or
351fb0ce 10449 inside function marked as offloadable, the symbol must be
10450 marked as offloadable too. */
10451 omp_context *octx;
10452 if (cgraph_node::get (current_function_decl)->offloadable)
10453 varpool_node::get_create (decl)->offloadable = 1;
10454 else
10455 for (octx = ctx->outer; octx; octx = octx->outer)
ca4c3545 10456 if (is_gimple_omp_offloaded (octx->stmt))
351fb0ce 10457 {
10458 varpool_node::get_create (decl)->offloadable = 1;
10459 break;
10460 }
10461
b9a16870 10462 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_START);
389dd41b 10463 lock = build_call_expr_loc (loc, lock, 1, build_fold_addr_expr_loc (loc, decl));
1e8e9920 10464
b9a16870 10465 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_END);
389dd41b 10466 unlock = build_call_expr_loc (loc, unlock, 1,
10467 build_fold_addr_expr_loc (loc, decl));
1e8e9920 10468 }
10469 else
10470 {
b9a16870 10471 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_START);
389dd41b 10472 lock = build_call_expr_loc (loc, lock, 0);
1e8e9920 10473
b9a16870 10474 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_END);
389dd41b 10475 unlock = build_call_expr_loc (loc, unlock, 0);
1e8e9920 10476 }
10477
8a4a28a8 10478 push_gimplify_context ();
1e8e9920 10479
10480 block = make_node (BLOCK);
e3a19533 10481 bind = gimple_build_bind (NULL, NULL, block);
10482 gsi_replace (gsi_p, bind, true);
10483 gimple_bind_add_stmt (bind, stmt);
61e47ac8 10484
75a70cf9 10485 tbody = gimple_bind_body (bind);
10486 gimplify_and_add (lock, &tbody);
10487 gimple_bind_set_body (bind, tbody);
1e8e9920 10488
e3a19533 10489 lower_omp (gimple_omp_body_ptr (stmt), ctx);
75a70cf9 10490 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
10491 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
10492 gimple_omp_set_body (stmt, NULL);
1e8e9920 10493
75a70cf9 10494 tbody = gimple_bind_body (bind);
10495 gimplify_and_add (unlock, &tbody);
10496 gimple_bind_set_body (bind, tbody);
61e47ac8 10497
75a70cf9 10498 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
1e8e9920 10499
10500 pop_gimplify_context (bind);
75a70cf9 10501 gimple_bind_append_vars (bind, ctx->block_vars);
10502 BLOCK_VARS (block) = gimple_bind_vars (bind);
773c5ba7 10503}
10504
10505
10506/* A subroutine of lower_omp_for. Generate code to emit the predicate
10507 for a lastprivate clause. Given a loop control predicate of (V
10508 cond N2), we gate the clause on (!(V cond N2)). The lowered form
1e4afe3c 10509 is appended to *DLIST, iterator initialization is appended to
10510 *BODY_P. */
773c5ba7 10511
10512static void
75a70cf9 10513lower_omp_for_lastprivate (struct omp_for_data *fd, gimple_seq *body_p,
10514 gimple_seq *dlist, struct omp_context *ctx)
773c5ba7 10515{
75a70cf9 10516 tree clauses, cond, vinit;
773c5ba7 10517 enum tree_code cond_code;
75a70cf9 10518 gimple_seq stmts;
48e1416a 10519
fd6481cf 10520 cond_code = fd->loop.cond_code;
773c5ba7 10521 cond_code = cond_code == LT_EXPR ? GE_EXPR : LE_EXPR;
10522
10523 /* When possible, use a strict equality expression. This can let VRP
10524 type optimizations deduce the value and remove a copy. */
e913b5cd 10525 if (tree_fits_shwi_p (fd->loop.step))
773c5ba7 10526 {
e913b5cd 10527 HOST_WIDE_INT step = tree_to_shwi (fd->loop.step);
773c5ba7 10528 if (step == 1 || step == -1)
10529 cond_code = EQ_EXPR;
10530 }
10531
d7729e26 10532 tree n2 = fd->loop.n2;
10533 if (fd->collapse > 1
10534 && TREE_CODE (n2) != INTEGER_CST
10535 && gimple_omp_for_combined_into_p (fd->for_stmt)
10536 && gimple_code (ctx->outer->stmt) == GIMPLE_OMP_FOR)
10537 {
10538 gomp_for *gfor = as_a <gomp_for *> (ctx->outer->stmt);
10539 if (gimple_omp_for_kind (gfor) == GF_OMP_FOR_KIND_FOR)
10540 {
10541 struct omp_for_data outer_fd;
10542 extract_omp_for_data (gfor, &outer_fd, NULL);
10543 n2 = fold_convert (TREE_TYPE (n2), outer_fd.loop.n2);
10544 }
10545 }
10546 cond = build2 (cond_code, boolean_type_node, fd->loop.v, n2);
773c5ba7 10547
75a70cf9 10548 clauses = gimple_omp_for_clauses (fd->for_stmt);
1e4afe3c 10549 stmts = NULL;
10550 lower_lastprivate_clauses (clauses, cond, &stmts, ctx);
75a70cf9 10551 if (!gimple_seq_empty_p (stmts))
1e4afe3c 10552 {
75a70cf9 10553 gimple_seq_add_seq (&stmts, *dlist);
fd6481cf 10554 *dlist = stmts;
1e4afe3c 10555
10556 /* Optimize: v = 0; is usually cheaper than v = some_other_constant. */
fd6481cf 10557 vinit = fd->loop.n1;
1e4afe3c 10558 if (cond_code == EQ_EXPR
e913b5cd 10559 && tree_fits_shwi_p (fd->loop.n2)
fd6481cf 10560 && ! integer_zerop (fd->loop.n2))
10561 vinit = build_int_cst (TREE_TYPE (fd->loop.v), 0);
3d483a94 10562 else
10563 vinit = unshare_expr (vinit);
1e4afe3c 10564
10565 /* Initialize the iterator variable, so that threads that don't execute
10566 any iterations don't execute the lastprivate clauses by accident. */
75a70cf9 10567 gimplify_assign (fd->loop.v, vinit, body_p);
1e4afe3c 10568 }
773c5ba7 10569}
10570
10571
ca4c3545 10572/* Lower code for an OMP loop directive. */
773c5ba7 10573
10574static void
75a70cf9 10575lower_omp_for (gimple_stmt_iterator *gsi_p, omp_context *ctx)
773c5ba7 10576{
75a70cf9 10577 tree *rhs_p, block;
bc7bff74 10578 struct omp_for_data fd, *fdp = NULL;
1a91d914 10579 gomp_for *stmt = as_a <gomp_for *> (gsi_stmt (*gsi_p));
10580 gbind *new_stmt;
f018d957 10581 gimple_seq omp_for_body, body, dlist;
75a70cf9 10582 size_t i;
773c5ba7 10583
8a4a28a8 10584 push_gimplify_context ();
773c5ba7 10585
e3a19533 10586 lower_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
773c5ba7 10587
1d22f541 10588 block = make_node (BLOCK);
75a70cf9 10589 new_stmt = gimple_build_bind (NULL, NULL, block);
e3a19533 10590 /* Replace at gsi right away, so that 'stmt' is no member
10591 of a sequence anymore as we're going to add to to a different
10592 one below. */
10593 gsi_replace (gsi_p, new_stmt, true);
1d22f541 10594
773c5ba7 10595 /* Move declaration of temporaries in the loop body before we make
10596 it go away. */
75a70cf9 10597 omp_for_body = gimple_omp_body (stmt);
10598 if (!gimple_seq_empty_p (omp_for_body)
10599 && gimple_code (gimple_seq_first_stmt (omp_for_body)) == GIMPLE_BIND)
10600 {
1a91d914 10601 gbind *inner_bind
10602 = as_a <gbind *> (gimple_seq_first_stmt (omp_for_body));
6d5a8d89 10603 tree vars = gimple_bind_vars (inner_bind);
75a70cf9 10604 gimple_bind_append_vars (new_stmt, vars);
6d5a8d89 10605 /* bind_vars/BLOCK_VARS are being moved to new_stmt/block, don't
10606 keep them on the inner_bind and it's block. */
10607 gimple_bind_set_vars (inner_bind, NULL_TREE);
10608 if (gimple_bind_block (inner_bind))
10609 BLOCK_VARS (gimple_bind_block (inner_bind)) = NULL_TREE;
75a70cf9 10610 }
773c5ba7 10611
bc7bff74 10612 if (gimple_omp_for_combined_into_p (stmt))
10613 {
10614 extract_omp_for_data (stmt, &fd, NULL);
10615 fdp = &fd;
10616
10617 /* We need two temporaries with fd.loop.v type (istart/iend)
10618 and then (fd.collapse - 1) temporaries with the same
10619 type for count2 ... countN-1 vars if not constant. */
10620 size_t count = 2;
10621 tree type = fd.iter_type;
10622 if (fd.collapse > 1
10623 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
10624 count += fd.collapse - 1;
10625 bool parallel_for = gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR;
10626 tree outerc = NULL, *pc = gimple_omp_for_clauses_ptr (stmt);
10627 tree clauses = *pc;
10628 if (parallel_for)
10629 outerc
10630 = find_omp_clause (gimple_omp_parallel_clauses (ctx->outer->stmt),
10631 OMP_CLAUSE__LOOPTEMP_);
10632 for (i = 0; i < count; i++)
10633 {
10634 tree temp;
10635 if (parallel_for)
10636 {
10637 gcc_assert (outerc);
10638 temp = lookup_decl (OMP_CLAUSE_DECL (outerc), ctx->outer);
10639 outerc = find_omp_clause (OMP_CLAUSE_CHAIN (outerc),
10640 OMP_CLAUSE__LOOPTEMP_);
10641 }
10642 else
691447ab 10643 {
f9e245b2 10644 temp = create_tmp_var (type);
691447ab 10645 insert_decl_map (&ctx->outer->cb, temp, temp);
10646 }
bc7bff74 10647 *pc = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__LOOPTEMP_);
10648 OMP_CLAUSE_DECL (*pc) = temp;
10649 pc = &OMP_CLAUSE_CHAIN (*pc);
10650 }
10651 *pc = clauses;
10652 }
10653
75a70cf9 10654 /* The pre-body and input clauses go before the lowered GIMPLE_OMP_FOR. */
773c5ba7 10655 dlist = NULL;
75a70cf9 10656 body = NULL;
bc7bff74 10657 lower_rec_input_clauses (gimple_omp_for_clauses (stmt), &body, &dlist, ctx,
10658 fdp);
75a70cf9 10659 gimple_seq_add_seq (&body, gimple_omp_for_pre_body (stmt));
773c5ba7 10660
3d483a94 10661 lower_omp (gimple_omp_body_ptr (stmt), ctx);
10662
773c5ba7 10663 /* Lower the header expressions. At this point, we can assume that
10664 the header is of the form:
10665
10666 #pragma omp for (V = VAL1; V {<|>|<=|>=} VAL2; V = V [+-] VAL3)
10667
10668 We just need to make sure that VAL1, VAL2 and VAL3 are lowered
10669 using the .omp_data_s mapping, if needed. */
75a70cf9 10670 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
fd6481cf 10671 {
75a70cf9 10672 rhs_p = gimple_omp_for_initial_ptr (stmt, i);
fd6481cf 10673 if (!is_gimple_min_invariant (*rhs_p))
75a70cf9 10674 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
fd6481cf 10675
75a70cf9 10676 rhs_p = gimple_omp_for_final_ptr (stmt, i);
fd6481cf 10677 if (!is_gimple_min_invariant (*rhs_p))
75a70cf9 10678 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
fd6481cf 10679
75a70cf9 10680 rhs_p = &TREE_OPERAND (gimple_omp_for_incr (stmt, i), 1);
fd6481cf 10681 if (!is_gimple_min_invariant (*rhs_p))
75a70cf9 10682 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
fd6481cf 10683 }
773c5ba7 10684
10685 /* Once lowered, extract the bounds and clauses. */
fd6481cf 10686 extract_omp_for_data (stmt, &fd, NULL);
773c5ba7 10687
75a70cf9 10688 lower_omp_for_lastprivate (&fd, &body, &dlist, ctx);
773c5ba7 10689
75a70cf9 10690 gimple_seq_add_stmt (&body, stmt);
10691 gimple_seq_add_seq (&body, gimple_omp_body (stmt));
61e47ac8 10692
75a70cf9 10693 gimple_seq_add_stmt (&body, gimple_build_omp_continue (fd.loop.v,
10694 fd.loop.v));
61e47ac8 10695
773c5ba7 10696 /* After the loop, add exit clauses. */
75a70cf9 10697 lower_reduction_clauses (gimple_omp_for_clauses (stmt), &body, ctx);
bc7bff74 10698
10699 if (ctx->cancellable)
10700 gimple_seq_add_stmt (&body, gimple_build_label (ctx->cancel_label));
10701
75a70cf9 10702 gimple_seq_add_seq (&body, dlist);
773c5ba7 10703
75a70cf9 10704 body = maybe_catch_exception (body);
aade31a0 10705
61e47ac8 10706 /* Region exit marker goes at the end of the loop body. */
75a70cf9 10707 gimple_seq_add_stmt (&body, gimple_build_omp_return (fd.have_nowait));
bc7bff74 10708 maybe_add_implicit_barrier_cancel (ctx, &body);
1d22f541 10709 pop_gimplify_context (new_stmt);
75a70cf9 10710
10711 gimple_bind_append_vars (new_stmt, ctx->block_vars);
10712 BLOCK_VARS (block) = gimple_bind_vars (new_stmt);
1d22f541 10713 if (BLOCK_VARS (block))
10714 TREE_USED (block) = 1;
773c5ba7 10715
75a70cf9 10716 gimple_bind_set_body (new_stmt, body);
10717 gimple_omp_set_body (stmt, NULL);
10718 gimple_omp_for_set_pre_body (stmt, NULL);
1e8e9920 10719}
10720
48e1416a 10721/* Callback for walk_stmts. Check if the current statement only contains
a7dfc4fe 10722 GIMPLE_OMP_FOR or GIMPLE_OMP_SECTIONS. */
de7ef844 10723
10724static tree
75a70cf9 10725check_combined_parallel (gimple_stmt_iterator *gsi_p,
10726 bool *handled_ops_p,
10727 struct walk_stmt_info *wi)
de7ef844 10728{
4077bf7a 10729 int *info = (int *) wi->info;
75a70cf9 10730 gimple stmt = gsi_stmt (*gsi_p);
de7ef844 10731
75a70cf9 10732 *handled_ops_p = true;
10733 switch (gimple_code (stmt))
de7ef844 10734 {
75a70cf9 10735 WALK_SUBSTMTS;
10736
10737 case GIMPLE_OMP_FOR:
10738 case GIMPLE_OMP_SECTIONS:
de7ef844 10739 *info = *info == 0 ? 1 : -1;
10740 break;
10741 default:
10742 *info = -1;
10743 break;
10744 }
10745 return NULL;
10746}
773c5ba7 10747
fd6481cf 10748struct omp_taskcopy_context
10749{
10750 /* This field must be at the beginning, as we do "inheritance": Some
10751 callback functions for tree-inline.c (e.g., omp_copy_decl)
10752 receive a copy_body_data pointer that is up-casted to an
10753 omp_context pointer. */
10754 copy_body_data cb;
10755 omp_context *ctx;
10756};
10757
10758static tree
10759task_copyfn_copy_decl (tree var, copy_body_data *cb)
10760{
10761 struct omp_taskcopy_context *tcctx = (struct omp_taskcopy_context *) cb;
10762
10763 if (splay_tree_lookup (tcctx->ctx->sfield_map, (splay_tree_key) var))
f9e245b2 10764 return create_tmp_var (TREE_TYPE (var));
fd6481cf 10765
10766 return var;
10767}
10768
10769static tree
10770task_copyfn_remap_type (struct omp_taskcopy_context *tcctx, tree orig_type)
10771{
10772 tree name, new_fields = NULL, type, f;
10773
10774 type = lang_hooks.types.make_type (RECORD_TYPE);
10775 name = DECL_NAME (TYPE_NAME (orig_type));
e60a6f7b 10776 name = build_decl (gimple_location (tcctx->ctx->stmt),
10777 TYPE_DECL, name, type);
fd6481cf 10778 TYPE_NAME (type) = name;
10779
10780 for (f = TYPE_FIELDS (orig_type); f ; f = TREE_CHAIN (f))
10781 {
10782 tree new_f = copy_node (f);
10783 DECL_CONTEXT (new_f) = type;
10784 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &tcctx->cb);
10785 TREE_CHAIN (new_f) = new_fields;
75a70cf9 10786 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &tcctx->cb, NULL);
10787 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r, &tcctx->cb, NULL);
10788 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
10789 &tcctx->cb, NULL);
fd6481cf 10790 new_fields = new_f;
06ecf488 10791 tcctx->cb.decl_map->put (f, new_f);
fd6481cf 10792 }
10793 TYPE_FIELDS (type) = nreverse (new_fields);
10794 layout_type (type);
10795 return type;
10796}
10797
10798/* Create task copyfn. */
10799
10800static void
1a91d914 10801create_task_copyfn (gomp_task *task_stmt, omp_context *ctx)
fd6481cf 10802{
10803 struct function *child_cfun;
10804 tree child_fn, t, c, src, dst, f, sf, arg, sarg, decl;
10805 tree record_type, srecord_type, bind, list;
10806 bool record_needs_remap = false, srecord_needs_remap = false;
10807 splay_tree_node n;
10808 struct omp_taskcopy_context tcctx;
389dd41b 10809 location_t loc = gimple_location (task_stmt);
fd6481cf 10810
75a70cf9 10811 child_fn = gimple_omp_task_copy_fn (task_stmt);
fd6481cf 10812 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
10813 gcc_assert (child_cfun->cfg == NULL);
fd6481cf 10814 DECL_SAVED_TREE (child_fn) = alloc_stmt_list ();
10815
10816 /* Reset DECL_CONTEXT on function arguments. */
1767a056 10817 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
fd6481cf 10818 DECL_CONTEXT (t) = child_fn;
10819
10820 /* Populate the function. */
8a4a28a8 10821 push_gimplify_context ();
9078126c 10822 push_cfun (child_cfun);
fd6481cf 10823
10824 bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
10825 TREE_SIDE_EFFECTS (bind) = 1;
10826 list = NULL;
10827 DECL_SAVED_TREE (child_fn) = bind;
75a70cf9 10828 DECL_SOURCE_LOCATION (child_fn) = gimple_location (task_stmt);
fd6481cf 10829
10830 /* Remap src and dst argument types if needed. */
10831 record_type = ctx->record_type;
10832 srecord_type = ctx->srecord_type;
1767a056 10833 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
fd6481cf 10834 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
10835 {
10836 record_needs_remap = true;
10837 break;
10838 }
1767a056 10839 for (f = TYPE_FIELDS (srecord_type); f ; f = DECL_CHAIN (f))
fd6481cf 10840 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
10841 {
10842 srecord_needs_remap = true;
10843 break;
10844 }
10845
10846 if (record_needs_remap || srecord_needs_remap)
10847 {
10848 memset (&tcctx, '\0', sizeof (tcctx));
10849 tcctx.cb.src_fn = ctx->cb.src_fn;
10850 tcctx.cb.dst_fn = child_fn;
415d1b9a 10851 tcctx.cb.src_node = cgraph_node::get (tcctx.cb.src_fn);
53f79206 10852 gcc_checking_assert (tcctx.cb.src_node);
fd6481cf 10853 tcctx.cb.dst_node = tcctx.cb.src_node;
10854 tcctx.cb.src_cfun = ctx->cb.src_cfun;
10855 tcctx.cb.copy_decl = task_copyfn_copy_decl;
e38def9c 10856 tcctx.cb.eh_lp_nr = 0;
fd6481cf 10857 tcctx.cb.transform_call_graph_edges = CB_CGE_MOVE;
06ecf488 10858 tcctx.cb.decl_map = new hash_map<tree, tree>;
fd6481cf 10859 tcctx.ctx = ctx;
10860
10861 if (record_needs_remap)
10862 record_type = task_copyfn_remap_type (&tcctx, record_type);
10863 if (srecord_needs_remap)
10864 srecord_type = task_copyfn_remap_type (&tcctx, srecord_type);
10865 }
10866 else
10867 tcctx.cb.decl_map = NULL;
10868
fd6481cf 10869 arg = DECL_ARGUMENTS (child_fn);
10870 TREE_TYPE (arg) = build_pointer_type (record_type);
1767a056 10871 sarg = DECL_CHAIN (arg);
fd6481cf 10872 TREE_TYPE (sarg) = build_pointer_type (srecord_type);
10873
10874 /* First pass: initialize temporaries used in record_type and srecord_type
10875 sizes and field offsets. */
10876 if (tcctx.cb.decl_map)
75a70cf9 10877 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
fd6481cf 10878 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
10879 {
10880 tree *p;
10881
10882 decl = OMP_CLAUSE_DECL (c);
06ecf488 10883 p = tcctx.cb.decl_map->get (decl);
fd6481cf 10884 if (p == NULL)
10885 continue;
10886 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
10887 sf = (tree) n->value;
06ecf488 10888 sf = *tcctx.cb.decl_map->get (sf);
182cf5a9 10889 src = build_simple_mem_ref_loc (loc, sarg);
445d06b6 10890 src = omp_build_component_ref (src, sf);
75a70cf9 10891 t = build2 (MODIFY_EXPR, TREE_TYPE (*p), *p, src);
fd6481cf 10892 append_to_statement_list (t, &list);
10893 }
10894
10895 /* Second pass: copy shared var pointers and copy construct non-VLA
10896 firstprivate vars. */
75a70cf9 10897 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
fd6481cf 10898 switch (OMP_CLAUSE_CODE (c))
10899 {
10900 case OMP_CLAUSE_SHARED:
10901 decl = OMP_CLAUSE_DECL (c);
10902 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
10903 if (n == NULL)
10904 break;
10905 f = (tree) n->value;
10906 if (tcctx.cb.decl_map)
06ecf488 10907 f = *tcctx.cb.decl_map->get (f);
fd6481cf 10908 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
10909 sf = (tree) n->value;
10910 if (tcctx.cb.decl_map)
06ecf488 10911 sf = *tcctx.cb.decl_map->get (sf);
182cf5a9 10912 src = build_simple_mem_ref_loc (loc, sarg);
445d06b6 10913 src = omp_build_component_ref (src, sf);
182cf5a9 10914 dst = build_simple_mem_ref_loc (loc, arg);
445d06b6 10915 dst = omp_build_component_ref (dst, f);
75a70cf9 10916 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
fd6481cf 10917 append_to_statement_list (t, &list);
10918 break;
10919 case OMP_CLAUSE_FIRSTPRIVATE:
10920 decl = OMP_CLAUSE_DECL (c);
10921 if (is_variable_sized (decl))
10922 break;
10923 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
10924 if (n == NULL)
10925 break;
10926 f = (tree) n->value;
10927 if (tcctx.cb.decl_map)
06ecf488 10928 f = *tcctx.cb.decl_map->get (f);
fd6481cf 10929 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
10930 if (n != NULL)
10931 {
10932 sf = (tree) n->value;
10933 if (tcctx.cb.decl_map)
06ecf488 10934 sf = *tcctx.cb.decl_map->get (sf);
182cf5a9 10935 src = build_simple_mem_ref_loc (loc, sarg);
445d06b6 10936 src = omp_build_component_ref (src, sf);
fd6481cf 10937 if (use_pointer_for_field (decl, NULL) || is_reference (decl))
182cf5a9 10938 src = build_simple_mem_ref_loc (loc, src);
fd6481cf 10939 }
10940 else
10941 src = decl;
182cf5a9 10942 dst = build_simple_mem_ref_loc (loc, arg);
445d06b6 10943 dst = omp_build_component_ref (dst, f);
fd6481cf 10944 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
10945 append_to_statement_list (t, &list);
10946 break;
10947 case OMP_CLAUSE_PRIVATE:
10948 if (! OMP_CLAUSE_PRIVATE_OUTER_REF (c))
10949 break;
10950 decl = OMP_CLAUSE_DECL (c);
10951 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
10952 f = (tree) n->value;
10953 if (tcctx.cb.decl_map)
06ecf488 10954 f = *tcctx.cb.decl_map->get (f);
fd6481cf 10955 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
10956 if (n != NULL)
10957 {
10958 sf = (tree) n->value;
10959 if (tcctx.cb.decl_map)
06ecf488 10960 sf = *tcctx.cb.decl_map->get (sf);
182cf5a9 10961 src = build_simple_mem_ref_loc (loc, sarg);
445d06b6 10962 src = omp_build_component_ref (src, sf);
fd6481cf 10963 if (use_pointer_for_field (decl, NULL))
182cf5a9 10964 src = build_simple_mem_ref_loc (loc, src);
fd6481cf 10965 }
10966 else
10967 src = decl;
182cf5a9 10968 dst = build_simple_mem_ref_loc (loc, arg);
445d06b6 10969 dst = omp_build_component_ref (dst, f);
75a70cf9 10970 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
fd6481cf 10971 append_to_statement_list (t, &list);
10972 break;
10973 default:
10974 break;
10975 }
10976
10977 /* Last pass: handle VLA firstprivates. */
10978 if (tcctx.cb.decl_map)
75a70cf9 10979 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
fd6481cf 10980 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
10981 {
10982 tree ind, ptr, df;
10983
10984 decl = OMP_CLAUSE_DECL (c);
10985 if (!is_variable_sized (decl))
10986 continue;
10987 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
10988 if (n == NULL)
10989 continue;
10990 f = (tree) n->value;
06ecf488 10991 f = *tcctx.cb.decl_map->get (f);
fd6481cf 10992 gcc_assert (DECL_HAS_VALUE_EXPR_P (decl));
10993 ind = DECL_VALUE_EXPR (decl);
10994 gcc_assert (TREE_CODE (ind) == INDIRECT_REF);
10995 gcc_assert (DECL_P (TREE_OPERAND (ind, 0)));
10996 n = splay_tree_lookup (ctx->sfield_map,
10997 (splay_tree_key) TREE_OPERAND (ind, 0));
10998 sf = (tree) n->value;
06ecf488 10999 sf = *tcctx.cb.decl_map->get (sf);
182cf5a9 11000 src = build_simple_mem_ref_loc (loc, sarg);
445d06b6 11001 src = omp_build_component_ref (src, sf);
182cf5a9 11002 src = build_simple_mem_ref_loc (loc, src);
11003 dst = build_simple_mem_ref_loc (loc, arg);
445d06b6 11004 dst = omp_build_component_ref (dst, f);
fd6481cf 11005 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
11006 append_to_statement_list (t, &list);
11007 n = splay_tree_lookup (ctx->field_map,
11008 (splay_tree_key) TREE_OPERAND (ind, 0));
11009 df = (tree) n->value;
06ecf488 11010 df = *tcctx.cb.decl_map->get (df);
182cf5a9 11011 ptr = build_simple_mem_ref_loc (loc, arg);
445d06b6 11012 ptr = omp_build_component_ref (ptr, df);
75a70cf9 11013 t = build2 (MODIFY_EXPR, TREE_TYPE (ptr), ptr,
389dd41b 11014 build_fold_addr_expr_loc (loc, dst));
fd6481cf 11015 append_to_statement_list (t, &list);
11016 }
11017
11018 t = build1 (RETURN_EXPR, void_type_node, NULL);
11019 append_to_statement_list (t, &list);
11020
11021 if (tcctx.cb.decl_map)
06ecf488 11022 delete tcctx.cb.decl_map;
fd6481cf 11023 pop_gimplify_context (NULL);
11024 BIND_EXPR_BODY (bind) = list;
11025 pop_cfun ();
fd6481cf 11026}
11027
bc7bff74 11028static void
11029lower_depend_clauses (gimple stmt, gimple_seq *iseq, gimple_seq *oseq)
11030{
11031 tree c, clauses;
11032 gimple g;
11033 size_t n_in = 0, n_out = 0, idx = 2, i;
11034
11035 clauses = find_omp_clause (gimple_omp_task_clauses (stmt),
11036 OMP_CLAUSE_DEPEND);
11037 gcc_assert (clauses);
11038 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
11039 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
11040 switch (OMP_CLAUSE_DEPEND_KIND (c))
11041 {
11042 case OMP_CLAUSE_DEPEND_IN:
11043 n_in++;
11044 break;
11045 case OMP_CLAUSE_DEPEND_OUT:
11046 case OMP_CLAUSE_DEPEND_INOUT:
11047 n_out++;
11048 break;
11049 default:
11050 gcc_unreachable ();
11051 }
11052 tree type = build_array_type_nelts (ptr_type_node, n_in + n_out + 2);
f9e245b2 11053 tree array = create_tmp_var (type);
bc7bff74 11054 tree r = build4 (ARRAY_REF, ptr_type_node, array, size_int (0), NULL_TREE,
11055 NULL_TREE);
11056 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_in + n_out));
11057 gimple_seq_add_stmt (iseq, g);
11058 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (1), NULL_TREE,
11059 NULL_TREE);
11060 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_out));
11061 gimple_seq_add_stmt (iseq, g);
11062 for (i = 0; i < 2; i++)
11063 {
11064 if ((i ? n_in : n_out) == 0)
11065 continue;
11066 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
11067 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
11068 && ((OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_IN) ^ i))
11069 {
11070 tree t = OMP_CLAUSE_DECL (c);
11071 t = fold_convert (ptr_type_node, t);
11072 gimplify_expr (&t, iseq, NULL, is_gimple_val, fb_rvalue);
11073 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (idx++),
11074 NULL_TREE, NULL_TREE);
11075 g = gimple_build_assign (r, t);
11076 gimple_seq_add_stmt (iseq, g);
11077 }
11078 }
11079 tree *p = gimple_omp_task_clauses_ptr (stmt);
11080 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_DEPEND);
11081 OMP_CLAUSE_DECL (c) = build_fold_addr_expr (array);
11082 OMP_CLAUSE_CHAIN (c) = *p;
11083 *p = c;
11084 tree clobber = build_constructor (type, NULL);
11085 TREE_THIS_VOLATILE (clobber) = 1;
11086 g = gimple_build_assign (array, clobber);
11087 gimple_seq_add_stmt (oseq, g);
11088}
11089
75a70cf9 11090/* Lower the OpenMP parallel or task directive in the current statement
11091 in GSI_P. CTX holds context information for the directive. */
773c5ba7 11092
11093static void
75a70cf9 11094lower_omp_taskreg (gimple_stmt_iterator *gsi_p, omp_context *ctx)
773c5ba7 11095{
75a70cf9 11096 tree clauses;
11097 tree child_fn, t;
11098 gimple stmt = gsi_stmt (*gsi_p);
1a91d914 11099 gbind *par_bind, *bind, *dep_bind = NULL;
bc7bff74 11100 gimple_seq par_body, olist, ilist, par_olist, par_rlist, par_ilist, new_body;
389dd41b 11101 location_t loc = gimple_location (stmt);
773c5ba7 11102
75a70cf9 11103 clauses = gimple_omp_taskreg_clauses (stmt);
1a91d914 11104 par_bind
11105 = as_a <gbind *> (gimple_seq_first_stmt (gimple_omp_body (stmt)));
75a70cf9 11106 par_body = gimple_bind_body (par_bind);
773c5ba7 11107 child_fn = ctx->cb.dst_fn;
75a70cf9 11108 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
11109 && !gimple_omp_parallel_combined_p (stmt))
de7ef844 11110 {
11111 struct walk_stmt_info wi;
11112 int ws_num = 0;
11113
11114 memset (&wi, 0, sizeof (wi));
de7ef844 11115 wi.info = &ws_num;
11116 wi.val_only = true;
75a70cf9 11117 walk_gimple_seq (par_body, check_combined_parallel, NULL, &wi);
de7ef844 11118 if (ws_num == 1)
75a70cf9 11119 gimple_omp_parallel_set_combined_p (stmt, true);
de7ef844 11120 }
bc7bff74 11121 gimple_seq dep_ilist = NULL;
11122 gimple_seq dep_olist = NULL;
11123 if (gimple_code (stmt) == GIMPLE_OMP_TASK
11124 && find_omp_clause (clauses, OMP_CLAUSE_DEPEND))
11125 {
8a4a28a8 11126 push_gimplify_context ();
bc7bff74 11127 dep_bind = gimple_build_bind (NULL, NULL, make_node (BLOCK));
11128 lower_depend_clauses (stmt, &dep_ilist, &dep_olist);
11129 }
11130
fd6481cf 11131 if (ctx->srecord_type)
1a91d914 11132 create_task_copyfn (as_a <gomp_task *> (stmt), ctx);
773c5ba7 11133
8a4a28a8 11134 push_gimplify_context ();
773c5ba7 11135
75a70cf9 11136 par_olist = NULL;
11137 par_ilist = NULL;
bc7bff74 11138 par_rlist = NULL;
11139 lower_rec_input_clauses (clauses, &par_ilist, &par_olist, ctx, NULL);
e3a19533 11140 lower_omp (&par_body, ctx);
75a70cf9 11141 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL)
bc7bff74 11142 lower_reduction_clauses (clauses, &par_rlist, ctx);
773c5ba7 11143
11144 /* Declare all the variables created by mapping and the variables
11145 declared in the scope of the parallel body. */
11146 record_vars_into (ctx->block_vars, child_fn);
75a70cf9 11147 record_vars_into (gimple_bind_vars (par_bind), child_fn);
773c5ba7 11148
11149 if (ctx->record_type)
11150 {
fd6481cf 11151 ctx->sender_decl
11152 = create_tmp_var (ctx->srecord_type ? ctx->srecord_type
11153 : ctx->record_type, ".omp_data_o");
84bfaaeb 11154 DECL_NAMELESS (ctx->sender_decl) = 1;
86f2ad37 11155 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
75a70cf9 11156 gimple_omp_taskreg_set_data_arg (stmt, ctx->sender_decl);
773c5ba7 11157 }
11158
75a70cf9 11159 olist = NULL;
11160 ilist = NULL;
773c5ba7 11161 lower_send_clauses (clauses, &ilist, &olist, ctx);
11162 lower_send_shared_vars (&ilist, &olist, ctx);
11163
bc7bff74 11164 if (ctx->record_type)
11165 {
11166 tree clobber = build_constructor (TREE_TYPE (ctx->sender_decl), NULL);
11167 TREE_THIS_VOLATILE (clobber) = 1;
11168 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
11169 clobber));
11170 }
11171
773c5ba7 11172 /* Once all the expansions are done, sequence all the different
75a70cf9 11173 fragments inside gimple_omp_body. */
773c5ba7 11174
75a70cf9 11175 new_body = NULL;
773c5ba7 11176
11177 if (ctx->record_type)
11178 {
389dd41b 11179 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
cc6b725b 11180 /* fixup_child_record_type might have changed receiver_decl's type. */
389dd41b 11181 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
75a70cf9 11182 gimple_seq_add_stmt (&new_body,
11183 gimple_build_assign (ctx->receiver_decl, t));
773c5ba7 11184 }
11185
75a70cf9 11186 gimple_seq_add_seq (&new_body, par_ilist);
11187 gimple_seq_add_seq (&new_body, par_body);
bc7bff74 11188 gimple_seq_add_seq (&new_body, par_rlist);
11189 if (ctx->cancellable)
11190 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
75a70cf9 11191 gimple_seq_add_seq (&new_body, par_olist);
11192 new_body = maybe_catch_exception (new_body);
b25f70fd 11193 if (gimple_code (stmt) == GIMPLE_OMP_TASK)
11194 gimple_seq_add_stmt (&new_body,
11195 gimple_build_omp_continue (integer_zero_node,
11196 integer_zero_node));
75a70cf9 11197 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
11198 gimple_omp_set_body (stmt, new_body);
773c5ba7 11199
75a70cf9 11200 bind = gimple_build_bind (NULL, NULL, gimple_bind_block (par_bind));
bc7bff74 11201 gsi_replace (gsi_p, dep_bind ? dep_bind : bind, true);
11202 gimple_bind_add_seq (bind, ilist);
11203 gimple_bind_add_stmt (bind, stmt);
11204 gimple_bind_add_seq (bind, olist);
11205
11206 pop_gimplify_context (NULL);
11207
11208 if (dep_bind)
11209 {
11210 gimple_bind_add_seq (dep_bind, dep_ilist);
11211 gimple_bind_add_stmt (dep_bind, bind);
11212 gimple_bind_add_seq (dep_bind, dep_olist);
11213 pop_gimplify_context (dep_bind);
11214 }
11215}
11216
ca4c3545 11217/* Lower the GIMPLE_OMP_TARGET in the current statement
bc7bff74 11218 in GSI_P. CTX holds context information for the directive. */
11219
11220static void
11221lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
11222{
11223 tree clauses;
11224 tree child_fn, t, c;
1a91d914 11225 gomp_target *stmt = as_a <gomp_target *> (gsi_stmt (*gsi_p));
ca4c3545 11226 gbind *tgt_bind, *bind;
11227 gimple_seq tgt_body, olist, ilist, orlist, irlist, new_body;
bc7bff74 11228 location_t loc = gimple_location (stmt);
ca4c3545 11229 bool offloaded, data_region;
bc7bff74 11230 unsigned int map_cnt = 0;
11231
ca4c3545 11232 offloaded = is_gimple_omp_offloaded (stmt);
11233 switch (gimple_omp_target_kind (stmt))
11234 {
11235 case GF_OMP_TARGET_KIND_REGION:
11236 case GF_OMP_TARGET_KIND_UPDATE:
11237 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
11238 case GF_OMP_TARGET_KIND_OACC_KERNELS:
11239 case GF_OMP_TARGET_KIND_OACC_UPDATE:
11240 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
11241 data_region = false;
11242 break;
11243 case GF_OMP_TARGET_KIND_DATA:
11244 case GF_OMP_TARGET_KIND_OACC_DATA:
11245 data_region = true;
11246 break;
11247 default:
11248 gcc_unreachable ();
11249 }
11250
bc7bff74 11251 clauses = gimple_omp_target_clauses (stmt);
ca4c3545 11252
11253 tgt_bind = NULL;
11254 tgt_body = NULL;
11255 if (offloaded)
bc7bff74 11256 {
1a91d914 11257 tgt_bind = gimple_seq_first_stmt_as_a_bind (gimple_omp_body (stmt));
bc7bff74 11258 tgt_body = gimple_bind_body (tgt_bind);
11259 }
ca4c3545 11260 else if (data_region)
bc7bff74 11261 tgt_body = gimple_omp_body (stmt);
11262 child_fn = ctx->cb.dst_fn;
11263
8a4a28a8 11264 push_gimplify_context ();
bc7bff74 11265
ca4c3545 11266 irlist = NULL;
11267 orlist = NULL;
11268 if (offloaded
11269 && is_gimple_omp_oacc (stmt))
11270 oacc_process_reduction_data (&tgt_body, &irlist, &orlist, ctx);
11271
bc7bff74 11272 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
11273 switch (OMP_CLAUSE_CODE (c))
11274 {
11275 tree var, x;
11276
11277 default:
11278 break;
11279 case OMP_CLAUSE_MAP:
ca4c3545 11280#ifdef ENABLE_CHECKING
11281 /* First check what we're prepared to handle in the following. */
11282 switch (OMP_CLAUSE_MAP_KIND (c))
11283 {
11284 case GOMP_MAP_ALLOC:
11285 case GOMP_MAP_TO:
11286 case GOMP_MAP_FROM:
11287 case GOMP_MAP_TOFROM:
11288 case GOMP_MAP_POINTER:
11289 case GOMP_MAP_TO_PSET:
11290 break;
11291 case GOMP_MAP_FORCE_ALLOC:
11292 case GOMP_MAP_FORCE_TO:
11293 case GOMP_MAP_FORCE_FROM:
11294 case GOMP_MAP_FORCE_TOFROM:
11295 case GOMP_MAP_FORCE_PRESENT:
11296 case GOMP_MAP_FORCE_DEALLOC:
11297 case GOMP_MAP_FORCE_DEVICEPTR:
11298 gcc_assert (is_gimple_omp_oacc (stmt));
11299 break;
11300 default:
11301 gcc_unreachable ();
11302 }
11303#endif
11304 /* FALLTHRU */
bc7bff74 11305 case OMP_CLAUSE_TO:
11306 case OMP_CLAUSE_FROM:
11307 var = OMP_CLAUSE_DECL (c);
11308 if (!DECL_P (var))
11309 {
11310 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP
11311 || !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
11312 map_cnt++;
11313 continue;
11314 }
11315
11316 if (DECL_SIZE (var)
11317 && TREE_CODE (DECL_SIZE (var)) != INTEGER_CST)
11318 {
11319 tree var2 = DECL_VALUE_EXPR (var);
11320 gcc_assert (TREE_CODE (var2) == INDIRECT_REF);
11321 var2 = TREE_OPERAND (var2, 0);
11322 gcc_assert (DECL_P (var2));
11323 var = var2;
11324 }
11325
11326 if (!maybe_lookup_field (var, ctx))
11327 continue;
11328
ca4c3545 11329 if (offloaded)
bc7bff74 11330 {
11331 x = build_receiver_ref (var, true, ctx);
11332 tree new_var = lookup_decl (var, ctx);
ca4c3545 11333 if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
bc7bff74 11334 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
11335 && TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
11336 x = build_simple_mem_ref (x);
11337 SET_DECL_VALUE_EXPR (new_var, x);
11338 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
11339 }
11340 map_cnt++;
11341 }
11342
ca4c3545 11343 if (offloaded)
bc7bff74 11344 {
11345 target_nesting_level++;
11346 lower_omp (&tgt_body, ctx);
11347 target_nesting_level--;
11348 }
ca4c3545 11349 else if (data_region)
bc7bff74 11350 lower_omp (&tgt_body, ctx);
11351
ca4c3545 11352 if (offloaded)
bc7bff74 11353 {
11354 /* Declare all the variables created by mapping and the variables
11355 declared in the scope of the target body. */
11356 record_vars_into (ctx->block_vars, child_fn);
11357 record_vars_into (gimple_bind_vars (tgt_bind), child_fn);
11358 }
11359
11360 olist = NULL;
11361 ilist = NULL;
11362 if (ctx->record_type)
11363 {
11364 ctx->sender_decl
11365 = create_tmp_var (ctx->record_type, ".omp_data_arr");
11366 DECL_NAMELESS (ctx->sender_decl) = 1;
11367 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
11368 t = make_tree_vec (3);
11369 TREE_VEC_ELT (t, 0) = ctx->sender_decl;
11370 TREE_VEC_ELT (t, 1)
11371 = create_tmp_var (build_array_type_nelts (size_type_node, map_cnt),
11372 ".omp_data_sizes");
11373 DECL_NAMELESS (TREE_VEC_ELT (t, 1)) = 1;
11374 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 1)) = 1;
11375 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 1;
ca4c3545 11376 tree tkind_type;
11377 int talign_shift;
11378 if (is_gimple_omp_oacc (stmt))
11379 {
11380 tkind_type = short_unsigned_type_node;
11381 talign_shift = 8;
11382 }
11383 else
11384 {
11385 tkind_type = unsigned_char_type_node;
11386 talign_shift = 3;
11387 }
bc7bff74 11388 TREE_VEC_ELT (t, 2)
ca4c3545 11389 = create_tmp_var (build_array_type_nelts (tkind_type, map_cnt),
bc7bff74 11390 ".omp_data_kinds");
11391 DECL_NAMELESS (TREE_VEC_ELT (t, 2)) = 1;
11392 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 2)) = 1;
11393 TREE_STATIC (TREE_VEC_ELT (t, 2)) = 1;
11394 gimple_omp_target_set_data_arg (stmt, t);
11395
11396 vec<constructor_elt, va_gc> *vsize;
11397 vec<constructor_elt, va_gc> *vkind;
11398 vec_alloc (vsize, map_cnt);
11399 vec_alloc (vkind, map_cnt);
11400 unsigned int map_idx = 0;
11401
11402 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
11403 switch (OMP_CLAUSE_CODE (c))
11404 {
11405 tree ovar, nc;
11406
11407 default:
11408 break;
11409 case OMP_CLAUSE_MAP:
11410 case OMP_CLAUSE_TO:
11411 case OMP_CLAUSE_FROM:
11412 nc = c;
11413 ovar = OMP_CLAUSE_DECL (c);
11414 if (!DECL_P (ovar))
11415 {
11416 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
11417 && OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
11418 {
11419 gcc_checking_assert (OMP_CLAUSE_DECL (OMP_CLAUSE_CHAIN (c))
11420 == get_base_address (ovar));
11421 nc = OMP_CLAUSE_CHAIN (c);
11422 ovar = OMP_CLAUSE_DECL (nc);
11423 }
11424 else
11425 {
11426 tree x = build_sender_ref (ovar, ctx);
11427 tree v
11428 = build_fold_addr_expr_with_type (ovar, ptr_type_node);
11429 gimplify_assign (x, v, &ilist);
11430 nc = NULL_TREE;
11431 }
11432 }
11433 else
11434 {
11435 if (DECL_SIZE (ovar)
11436 && TREE_CODE (DECL_SIZE (ovar)) != INTEGER_CST)
11437 {
11438 tree ovar2 = DECL_VALUE_EXPR (ovar);
11439 gcc_assert (TREE_CODE (ovar2) == INDIRECT_REF);
11440 ovar2 = TREE_OPERAND (ovar2, 0);
11441 gcc_assert (DECL_P (ovar2));
11442 ovar = ovar2;
11443 }
11444 if (!maybe_lookup_field (ovar, ctx))
11445 continue;
11446 }
11447
4f3b8d78 11448 unsigned int talign = TYPE_ALIGN_UNIT (TREE_TYPE (ovar));
11449 if (DECL_P (ovar) && DECL_ALIGN_UNIT (ovar) > talign)
11450 talign = DECL_ALIGN_UNIT (ovar);
bc7bff74 11451 if (nc)
11452 {
11453 tree var = lookup_decl_in_outer_ctx (ovar, ctx);
11454 tree x = build_sender_ref (ovar, ctx);
ca4c3545 11455 if (maybe_lookup_oacc_reduction (var, ctx))
11456 {
11457 gcc_checking_assert (offloaded
11458 && is_gimple_omp_oacc (stmt));
11459 gimplify_assign (x, var, &ilist);
11460 }
11461 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
11462 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
11463 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
11464 && TREE_CODE (TREE_TYPE (ovar)) == ARRAY_TYPE)
bc7bff74 11465 {
ca4c3545 11466 gcc_assert (offloaded);
bc7bff74 11467 tree avar
f9e245b2 11468 = create_tmp_var (TREE_TYPE (TREE_TYPE (x)));
bc7bff74 11469 mark_addressable (avar);
11470 gimplify_assign (avar, build_fold_addr_expr (var), &ilist);
4f3b8d78 11471 talign = DECL_ALIGN_UNIT (avar);
bc7bff74 11472 avar = build_fold_addr_expr (avar);
11473 gimplify_assign (x, avar, &ilist);
11474 }
11475 else if (is_gimple_reg (var))
11476 {
ca4c3545 11477 gcc_assert (offloaded);
f9e245b2 11478 tree avar = create_tmp_var (TREE_TYPE (var));
bc7bff74 11479 mark_addressable (avar);
ca4c3545 11480 enum gomp_map_kind map_kind = OMP_CLAUSE_MAP_KIND (c);
11481 if (GOMP_MAP_COPY_TO_P (map_kind)
11482 || map_kind == GOMP_MAP_POINTER
11483 || map_kind == GOMP_MAP_TO_PSET
11484 || map_kind == GOMP_MAP_FORCE_DEVICEPTR)
bc7bff74 11485 gimplify_assign (avar, var, &ilist);
11486 avar = build_fold_addr_expr (avar);
11487 gimplify_assign (x, avar, &ilist);
ca4c3545 11488 if ((GOMP_MAP_COPY_FROM_P (map_kind)
11489 || map_kind == GOMP_MAP_FORCE_DEVICEPTR)
bc7bff74 11490 && !TYPE_READONLY (TREE_TYPE (var)))
11491 {
11492 x = build_sender_ref (ovar, ctx);
11493 x = build_simple_mem_ref (x);
11494 gimplify_assign (var, x, &olist);
11495 }
11496 }
11497 else
11498 {
11499 var = build_fold_addr_expr (var);
11500 gimplify_assign (x, var, &ilist);
11501 }
11502 }
11503 tree s = OMP_CLAUSE_SIZE (c);
11504 if (s == NULL_TREE)
11505 s = TYPE_SIZE_UNIT (TREE_TYPE (ovar));
11506 s = fold_convert (size_type_node, s);
11507 tree purpose = size_int (map_idx++);
11508 CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
11509 if (TREE_CODE (s) != INTEGER_CST)
11510 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 0;
11511
ca4c3545 11512 unsigned HOST_WIDE_INT tkind;
bc7bff74 11513 switch (OMP_CLAUSE_CODE (c))
11514 {
11515 case OMP_CLAUSE_MAP:
11516 tkind = OMP_CLAUSE_MAP_KIND (c);
11517 break;
11518 case OMP_CLAUSE_TO:
ca4c3545 11519 tkind = GOMP_MAP_TO;
bc7bff74 11520 break;
11521 case OMP_CLAUSE_FROM:
ca4c3545 11522 tkind = GOMP_MAP_FROM;
bc7bff74 11523 break;
11524 default:
11525 gcc_unreachable ();
11526 }
ca4c3545 11527 gcc_checking_assert (tkind
11528 < (HOST_WIDE_INT_C (1U) << talign_shift));
bc7bff74 11529 talign = ceil_log2 (talign);
ca4c3545 11530 tkind |= talign << talign_shift;
11531 gcc_checking_assert (tkind
11532 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
bc7bff74 11533 CONSTRUCTOR_APPEND_ELT (vkind, purpose,
ca4c3545 11534 build_int_cstu (tkind_type, tkind));
bc7bff74 11535 if (nc && nc != c)
11536 c = nc;
11537 }
11538
11539 gcc_assert (map_idx == map_cnt);
11540
11541 DECL_INITIAL (TREE_VEC_ELT (t, 1))
11542 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)), vsize);
11543 DECL_INITIAL (TREE_VEC_ELT (t, 2))
11544 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 2)), vkind);
11545 if (!TREE_STATIC (TREE_VEC_ELT (t, 1)))
11546 {
11547 gimple_seq initlist = NULL;
11548 force_gimple_operand (build1 (DECL_EXPR, void_type_node,
11549 TREE_VEC_ELT (t, 1)),
11550 &initlist, true, NULL_TREE);
11551 gimple_seq_add_seq (&ilist, initlist);
d8e1e68d 11552
11553 tree clobber = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)),
11554 NULL);
11555 TREE_THIS_VOLATILE (clobber) = 1;
11556 gimple_seq_add_stmt (&olist,
11557 gimple_build_assign (TREE_VEC_ELT (t, 1),
11558 clobber));
bc7bff74 11559 }
11560
11561 tree clobber = build_constructor (ctx->record_type, NULL);
11562 TREE_THIS_VOLATILE (clobber) = 1;
11563 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
11564 clobber));
11565 }
11566
11567 /* Once all the expansions are done, sequence all the different
11568 fragments inside gimple_omp_body. */
11569
11570 new_body = NULL;
11571
ca4c3545 11572 if (offloaded
11573 && ctx->record_type)
bc7bff74 11574 {
11575 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
11576 /* fixup_child_record_type might have changed receiver_decl's type. */
11577 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
11578 gimple_seq_add_stmt (&new_body,
11579 gimple_build_assign (ctx->receiver_decl, t));
11580 }
11581
ca4c3545 11582 if (offloaded)
bc7bff74 11583 {
11584 gimple_seq_add_seq (&new_body, tgt_body);
11585 new_body = maybe_catch_exception (new_body);
11586 }
ca4c3545 11587 else if (data_region)
bc7bff74 11588 new_body = tgt_body;
ca4c3545 11589 if (offloaded || data_region)
bc7bff74 11590 {
11591 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
11592 gimple_omp_set_body (stmt, new_body);
11593 }
11594
11595 bind = gimple_build_bind (NULL, NULL,
11596 tgt_bind ? gimple_bind_block (tgt_bind)
11597 : NULL_TREE);
75a70cf9 11598 gsi_replace (gsi_p, bind, true);
ca4c3545 11599 gimple_bind_add_seq (bind, irlist);
e3a19533 11600 gimple_bind_add_seq (bind, ilist);
11601 gimple_bind_add_stmt (bind, stmt);
11602 gimple_bind_add_seq (bind, olist);
ca4c3545 11603 gimple_bind_add_seq (bind, orlist);
773c5ba7 11604
75a70cf9 11605 pop_gimplify_context (NULL);
773c5ba7 11606}
11607
bc7bff74 11608/* Expand code for an OpenMP teams directive. */
11609
11610static void
11611lower_omp_teams (gimple_stmt_iterator *gsi_p, omp_context *ctx)
11612{
1a91d914 11613 gomp_teams *teams_stmt = as_a <gomp_teams *> (gsi_stmt (*gsi_p));
8a4a28a8 11614 push_gimplify_context ();
bc7bff74 11615
11616 tree block = make_node (BLOCK);
1a91d914 11617 gbind *bind = gimple_build_bind (NULL, NULL, block);
bc7bff74 11618 gsi_replace (gsi_p, bind, true);
11619 gimple_seq bind_body = NULL;
11620 gimple_seq dlist = NULL;
11621 gimple_seq olist = NULL;
11622
11623 tree num_teams = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
11624 OMP_CLAUSE_NUM_TEAMS);
11625 if (num_teams == NULL_TREE)
11626 num_teams = build_int_cst (unsigned_type_node, 0);
11627 else
11628 {
11629 num_teams = OMP_CLAUSE_NUM_TEAMS_EXPR (num_teams);
11630 num_teams = fold_convert (unsigned_type_node, num_teams);
11631 gimplify_expr (&num_teams, &bind_body, NULL, is_gimple_val, fb_rvalue);
11632 }
11633 tree thread_limit = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
11634 OMP_CLAUSE_THREAD_LIMIT);
11635 if (thread_limit == NULL_TREE)
11636 thread_limit = build_int_cst (unsigned_type_node, 0);
11637 else
11638 {
11639 thread_limit = OMP_CLAUSE_THREAD_LIMIT_EXPR (thread_limit);
11640 thread_limit = fold_convert (unsigned_type_node, thread_limit);
11641 gimplify_expr (&thread_limit, &bind_body, NULL, is_gimple_val,
11642 fb_rvalue);
11643 }
11644
11645 lower_rec_input_clauses (gimple_omp_teams_clauses (teams_stmt),
11646 &bind_body, &dlist, ctx, NULL);
11647 lower_omp (gimple_omp_body_ptr (teams_stmt), ctx);
11648 lower_reduction_clauses (gimple_omp_teams_clauses (teams_stmt), &olist, ctx);
11649 gimple_seq_add_stmt (&bind_body, teams_stmt);
11650
11651 location_t loc = gimple_location (teams_stmt);
11652 tree decl = builtin_decl_explicit (BUILT_IN_GOMP_TEAMS);
11653 gimple call = gimple_build_call (decl, 2, num_teams, thread_limit);
11654 gimple_set_location (call, loc);
11655 gimple_seq_add_stmt (&bind_body, call);
11656
11657 gimple_seq_add_seq (&bind_body, gimple_omp_body (teams_stmt));
11658 gimple_omp_set_body (teams_stmt, NULL);
11659 gimple_seq_add_seq (&bind_body, olist);
11660 gimple_seq_add_seq (&bind_body, dlist);
11661 gimple_seq_add_stmt (&bind_body, gimple_build_omp_return (true));
11662 gimple_bind_set_body (bind, bind_body);
11663
11664 pop_gimplify_context (bind);
11665
11666 gimple_bind_append_vars (bind, ctx->block_vars);
11667 BLOCK_VARS (block) = ctx->block_vars;
11668 if (BLOCK_VARS (block))
11669 TREE_USED (block) = 1;
11670}
11671
11672
a4890dc9 11673/* Callback for lower_omp_1. Return non-NULL if *tp needs to be
75a70cf9 11674 regimplified. If DATA is non-NULL, lower_omp_1 is outside
ca4c3545 11675 of OMP context, but with task_shared_vars set. */
46515c92 11676
11677static tree
75a70cf9 11678lower_omp_regimplify_p (tree *tp, int *walk_subtrees,
11679 void *data)
46515c92 11680{
a4890dc9 11681 tree t = *tp;
46515c92 11682
a4890dc9 11683 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
75a70cf9 11684 if (TREE_CODE (t) == VAR_DECL && data == NULL && DECL_HAS_VALUE_EXPR_P (t))
9f49e155 11685 return t;
11686
11687 if (task_shared_vars
11688 && DECL_P (t)
11689 && bitmap_bit_p (task_shared_vars, DECL_UID (t)))
a4890dc9 11690 return t;
46515c92 11691
a4890dc9 11692 /* If a global variable has been privatized, TREE_CONSTANT on
11693 ADDR_EXPR might be wrong. */
75a70cf9 11694 if (data == NULL && TREE_CODE (t) == ADDR_EXPR)
a4890dc9 11695 recompute_tree_invariant_for_addr_expr (t);
46515c92 11696
a4890dc9 11697 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
11698 return NULL_TREE;
46515c92 11699}
773c5ba7 11700
a4890dc9 11701static void
75a70cf9 11702lower_omp_1 (gimple_stmt_iterator *gsi_p, omp_context *ctx)
1e8e9920 11703{
75a70cf9 11704 gimple stmt = gsi_stmt (*gsi_p);
11705 struct walk_stmt_info wi;
1a91d914 11706 gcall *call_stmt;
1e8e9920 11707
75a70cf9 11708 if (gimple_has_location (stmt))
11709 input_location = gimple_location (stmt);
a4890dc9 11710
75a70cf9 11711 if (task_shared_vars)
11712 memset (&wi, '\0', sizeof (wi));
a4890dc9 11713
773c5ba7 11714 /* If we have issued syntax errors, avoid doing any heavy lifting.
ca4c3545 11715 Just replace the OMP directives with a NOP to avoid
773c5ba7 11716 confusing RTL expansion. */
852f689e 11717 if (seen_error () && is_gimple_omp (stmt))
773c5ba7 11718 {
75a70cf9 11719 gsi_replace (gsi_p, gimple_build_nop (), true);
a4890dc9 11720 return;
773c5ba7 11721 }
11722
75a70cf9 11723 switch (gimple_code (stmt))
1e8e9920 11724 {
75a70cf9 11725 case GIMPLE_COND:
1a91d914 11726 {
11727 gcond *cond_stmt = as_a <gcond *> (stmt);
11728 if ((ctx || task_shared_vars)
11729 && (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
11730 lower_omp_regimplify_p,
11731 ctx ? NULL : &wi, NULL)
11732 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
11733 lower_omp_regimplify_p,
11734 ctx ? NULL : &wi, NULL)))
11735 gimple_regimplify_operands (cond_stmt, gsi_p);
11736 }
a4890dc9 11737 break;
75a70cf9 11738 case GIMPLE_CATCH:
1a91d914 11739 lower_omp (gimple_catch_handler_ptr (as_a <gcatch *> (stmt)), ctx);
a4890dc9 11740 break;
75a70cf9 11741 case GIMPLE_EH_FILTER:
e3a19533 11742 lower_omp (gimple_eh_filter_failure_ptr (stmt), ctx);
a4890dc9 11743 break;
75a70cf9 11744 case GIMPLE_TRY:
e3a19533 11745 lower_omp (gimple_try_eval_ptr (stmt), ctx);
11746 lower_omp (gimple_try_cleanup_ptr (stmt), ctx);
a4890dc9 11747 break;
35215227 11748 case GIMPLE_TRANSACTION:
1a91d914 11749 lower_omp (gimple_transaction_body_ptr (
11750 as_a <gtransaction *> (stmt)),
11751 ctx);
35215227 11752 break;
75a70cf9 11753 case GIMPLE_BIND:
1a91d914 11754 lower_omp (gimple_bind_body_ptr (as_a <gbind *> (stmt)), ctx);
a4890dc9 11755 break;
75a70cf9 11756 case GIMPLE_OMP_PARALLEL:
11757 case GIMPLE_OMP_TASK:
11758 ctx = maybe_lookup_ctx (stmt);
bc7bff74 11759 gcc_assert (ctx);
11760 if (ctx->cancellable)
11761 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
75a70cf9 11762 lower_omp_taskreg (gsi_p, ctx);
a4890dc9 11763 break;
75a70cf9 11764 case GIMPLE_OMP_FOR:
11765 ctx = maybe_lookup_ctx (stmt);
1e8e9920 11766 gcc_assert (ctx);
bc7bff74 11767 if (ctx->cancellable)
11768 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
75a70cf9 11769 lower_omp_for (gsi_p, ctx);
1e8e9920 11770 break;
75a70cf9 11771 case GIMPLE_OMP_SECTIONS:
11772 ctx = maybe_lookup_ctx (stmt);
1e8e9920 11773 gcc_assert (ctx);
bc7bff74 11774 if (ctx->cancellable)
11775 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
75a70cf9 11776 lower_omp_sections (gsi_p, ctx);
1e8e9920 11777 break;
75a70cf9 11778 case GIMPLE_OMP_SINGLE:
11779 ctx = maybe_lookup_ctx (stmt);
1e8e9920 11780 gcc_assert (ctx);
75a70cf9 11781 lower_omp_single (gsi_p, ctx);
1e8e9920 11782 break;
75a70cf9 11783 case GIMPLE_OMP_MASTER:
11784 ctx = maybe_lookup_ctx (stmt);
1e8e9920 11785 gcc_assert (ctx);
75a70cf9 11786 lower_omp_master (gsi_p, ctx);
1e8e9920 11787 break;
bc7bff74 11788 case GIMPLE_OMP_TASKGROUP:
11789 ctx = maybe_lookup_ctx (stmt);
11790 gcc_assert (ctx);
11791 lower_omp_taskgroup (gsi_p, ctx);
11792 break;
75a70cf9 11793 case GIMPLE_OMP_ORDERED:
11794 ctx = maybe_lookup_ctx (stmt);
1e8e9920 11795 gcc_assert (ctx);
75a70cf9 11796 lower_omp_ordered (gsi_p, ctx);
1e8e9920 11797 break;
75a70cf9 11798 case GIMPLE_OMP_CRITICAL:
11799 ctx = maybe_lookup_ctx (stmt);
1e8e9920 11800 gcc_assert (ctx);
75a70cf9 11801 lower_omp_critical (gsi_p, ctx);
11802 break;
11803 case GIMPLE_OMP_ATOMIC_LOAD:
11804 if ((ctx || task_shared_vars)
1a91d914 11805 && walk_tree (gimple_omp_atomic_load_rhs_ptr (
11806 as_a <gomp_atomic_load *> (stmt)),
75a70cf9 11807 lower_omp_regimplify_p, ctx ? NULL : &wi, NULL))
11808 gimple_regimplify_operands (stmt, gsi_p);
1e8e9920 11809 break;
bc7bff74 11810 case GIMPLE_OMP_TARGET:
11811 ctx = maybe_lookup_ctx (stmt);
11812 gcc_assert (ctx);
11813 lower_omp_target (gsi_p, ctx);
11814 break;
11815 case GIMPLE_OMP_TEAMS:
11816 ctx = maybe_lookup_ctx (stmt);
11817 gcc_assert (ctx);
11818 lower_omp_teams (gsi_p, ctx);
11819 break;
11820 case GIMPLE_CALL:
11821 tree fndecl;
1a91d914 11822 call_stmt = as_a <gcall *> (stmt);
11823 fndecl = gimple_call_fndecl (call_stmt);
bc7bff74 11824 if (fndecl
11825 && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
11826 switch (DECL_FUNCTION_CODE (fndecl))
11827 {
11828 case BUILT_IN_GOMP_BARRIER:
11829 if (ctx == NULL)
11830 break;
11831 /* FALLTHRU */
11832 case BUILT_IN_GOMP_CANCEL:
11833 case BUILT_IN_GOMP_CANCELLATION_POINT:
11834 omp_context *cctx;
11835 cctx = ctx;
11836 if (gimple_code (cctx->stmt) == GIMPLE_OMP_SECTION)
11837 cctx = cctx->outer;
1a91d914 11838 gcc_assert (gimple_call_lhs (call_stmt) == NULL_TREE);
bc7bff74 11839 if (!cctx->cancellable)
11840 {
11841 if (DECL_FUNCTION_CODE (fndecl)
11842 == BUILT_IN_GOMP_CANCELLATION_POINT)
11843 {
11844 stmt = gimple_build_nop ();
11845 gsi_replace (gsi_p, stmt, false);
11846 }
11847 break;
11848 }
bc7bff74 11849 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_GOMP_BARRIER)
11850 {
11851 fndecl = builtin_decl_explicit (BUILT_IN_GOMP_BARRIER_CANCEL);
1a91d914 11852 gimple_call_set_fndecl (call_stmt, fndecl);
11853 gimple_call_set_fntype (call_stmt, TREE_TYPE (fndecl));
bc7bff74 11854 }
15b28553 11855 tree lhs;
f9e245b2 11856 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (fndecl)));
1a91d914 11857 gimple_call_set_lhs (call_stmt, lhs);
bc7bff74 11858 tree fallthru_label;
11859 fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
11860 gimple g;
11861 g = gimple_build_label (fallthru_label);
11862 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
15b28553 11863 g = gimple_build_cond (NE_EXPR, lhs,
11864 fold_convert (TREE_TYPE (lhs),
11865 boolean_false_node),
bc7bff74 11866 cctx->cancel_label, fallthru_label);
11867 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
11868 break;
11869 default:
11870 break;
11871 }
11872 /* FALLTHRU */
a4890dc9 11873 default:
fd6481cf 11874 if ((ctx || task_shared_vars)
75a70cf9 11875 && walk_gimple_op (stmt, lower_omp_regimplify_p,
11876 ctx ? NULL : &wi))
ef8cfd4d 11877 {
11878 /* Just remove clobbers, this should happen only if we have
11879 "privatized" local addressable variables in SIMD regions,
11880 the clobber isn't needed in that case and gimplifying address
11881 of the ARRAY_REF into a pointer and creating MEM_REF based
11882 clobber would create worse code than we get with the clobber
11883 dropped. */
11884 if (gimple_clobber_p (stmt))
11885 {
11886 gsi_replace (gsi_p, gimple_build_nop (), true);
11887 break;
11888 }
11889 gimple_regimplify_operands (stmt, gsi_p);
11890 }
1e8e9920 11891 break;
1e8e9920 11892 }
1e8e9920 11893}
11894
11895static void
e3a19533 11896lower_omp (gimple_seq *body, omp_context *ctx)
1e8e9920 11897{
1d22f541 11898 location_t saved_location = input_location;
e3a19533 11899 gimple_stmt_iterator gsi;
11900 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
75a70cf9 11901 lower_omp_1 (&gsi, ctx);
ca4c3545 11902 /* During gimplification, we haven't folded statments inside offloading
11903 regions (gimplify.c:maybe_fold_stmt); do that now. */
bc7bff74 11904 if (target_nesting_level)
11905 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
11906 fold_stmt (&gsi);
1d22f541 11907 input_location = saved_location;
1e8e9920 11908}
11909\f
11910/* Main entry point. */
11911
2a1990e9 11912static unsigned int
1e8e9920 11913execute_lower_omp (void)
11914{
75a70cf9 11915 gimple_seq body;
37eaded9 11916 int i;
11917 omp_context *ctx;
75a70cf9 11918
41709826 11919 /* This pass always runs, to provide PROP_gimple_lomp.
ca4c3545 11920 But often, there is nothing to do. */
11921 if (flag_cilkplus == 0 && flag_openacc == 0 && flag_openmp == 0
11922 && flag_openmp_simd == 0)
41709826 11923 return 0;
11924
1e8e9920 11925 all_contexts = splay_tree_new (splay_tree_compare_pointers, 0,
11926 delete_omp_context);
11927
75a70cf9 11928 body = gimple_body (current_function_decl);
ab129075 11929 scan_omp (&body, NULL);
fd6481cf 11930 gcc_assert (taskreg_nesting_level == 0);
37eaded9 11931 FOR_EACH_VEC_ELT (taskreg_contexts, i, ctx)
11932 finish_taskreg_scan (ctx);
11933 taskreg_contexts.release ();
1e8e9920 11934
11935 if (all_contexts->root)
fd6481cf 11936 {
11937 if (task_shared_vars)
8a4a28a8 11938 push_gimplify_context ();
e3a19533 11939 lower_omp (&body, NULL);
fd6481cf 11940 if (task_shared_vars)
11941 pop_gimplify_context (NULL);
11942 }
1e8e9920 11943
773c5ba7 11944 if (all_contexts)
11945 {
11946 splay_tree_delete (all_contexts);
11947 all_contexts = NULL;
11948 }
fd6481cf 11949 BITMAP_FREE (task_shared_vars);
2a1990e9 11950 return 0;
1e8e9920 11951}
11952
cbe8bda8 11953namespace {
11954
11955const pass_data pass_data_lower_omp =
11956{
11957 GIMPLE_PASS, /* type */
11958 "omplower", /* name */
11959 OPTGROUP_NONE, /* optinfo_flags */
cbe8bda8 11960 TV_NONE, /* tv_id */
11961 PROP_gimple_any, /* properties_required */
11962 PROP_gimple_lomp, /* properties_provided */
11963 0, /* properties_destroyed */
11964 0, /* todo_flags_start */
11965 0, /* todo_flags_finish */
1e8e9920 11966};
cbe8bda8 11967
11968class pass_lower_omp : public gimple_opt_pass
11969{
11970public:
9af5ce0c 11971 pass_lower_omp (gcc::context *ctxt)
11972 : gimple_opt_pass (pass_data_lower_omp, ctxt)
cbe8bda8 11973 {}
11974
11975 /* opt_pass methods: */
65b0537f 11976 virtual unsigned int execute (function *) { return execute_lower_omp (); }
cbe8bda8 11977
11978}; // class pass_lower_omp
11979
11980} // anon namespace
11981
11982gimple_opt_pass *
11983make_pass_lower_omp (gcc::context *ctxt)
11984{
11985 return new pass_lower_omp (ctxt);
11986}
1e8e9920 11987\f
ca4c3545 11988/* The following is a utility to diagnose structured block violations.
61e47ac8 11989 It is not part of the "omplower" pass, as that's invoked too late. It
11990 should be invoked by the respective front ends after gimplification. */
1e8e9920 11991
11992static splay_tree all_labels;
11993
11994/* Check for mismatched contexts and generate an error if needed. Return
11995 true if an error is detected. */
11996
11997static bool
75a70cf9 11998diagnose_sb_0 (gimple_stmt_iterator *gsi_p,
11999 gimple branch_ctx, gimple label_ctx)
1e8e9920 12000{
ca4c3545 12001 gcc_checking_assert (!branch_ctx || is_gimple_omp (branch_ctx));
12002 gcc_checking_assert (!label_ctx || is_gimple_omp (label_ctx));
12003
75a70cf9 12004 if (label_ctx == branch_ctx)
1e8e9920 12005 return false;
12006
ca4c3545 12007 const char* kind = NULL;
12008
12009 if (flag_cilkplus)
12010 {
12011 if ((branch_ctx
12012 && gimple_code (branch_ctx) == GIMPLE_OMP_FOR
12013 && gimple_omp_for_kind (branch_ctx) == GF_OMP_FOR_KIND_CILKSIMD)
12014 || (label_ctx
12015 && gimple_code (label_ctx) == GIMPLE_OMP_FOR
12016 && gimple_omp_for_kind (label_ctx) == GF_OMP_FOR_KIND_CILKSIMD))
12017 kind = "Cilk Plus";
12018 }
12019 if (flag_openacc)
12020 {
12021 if ((branch_ctx && is_gimple_omp_oacc (branch_ctx))
12022 || (label_ctx && is_gimple_omp_oacc (label_ctx)))
12023 {
12024 gcc_checking_assert (kind == NULL);
12025 kind = "OpenACC";
12026 }
12027 }
12028 if (kind == NULL)
12029 {
12030 gcc_checking_assert (flag_openmp);
12031 kind = "OpenMP";
12032 }
48e1416a 12033
75a70cf9 12034 /*
12035 Previously we kept track of the label's entire context in diagnose_sb_[12]
12036 so we could traverse it and issue a correct "exit" or "enter" error
12037 message upon a structured block violation.
12038
12039 We built the context by building a list with tree_cons'ing, but there is
12040 no easy counterpart in gimple tuples. It seems like far too much work
12041 for issuing exit/enter error messages. If someone really misses the
12042 distinct error message... patches welcome.
12043 */
48e1416a 12044
75a70cf9 12045#if 0
1e8e9920 12046 /* Try to avoid confusing the user by producing and error message
f0b5f617 12047 with correct "exit" or "enter" verbiage. We prefer "exit"
1e8e9920 12048 unless we can show that LABEL_CTX is nested within BRANCH_CTX. */
12049 if (branch_ctx == NULL)
12050 exit_p = false;
12051 else
12052 {
12053 while (label_ctx)
12054 {
12055 if (TREE_VALUE (label_ctx) == branch_ctx)
12056 {
12057 exit_p = false;
12058 break;
12059 }
12060 label_ctx = TREE_CHAIN (label_ctx);
12061 }
12062 }
12063
12064 if (exit_p)
ca4c3545 12065 error ("invalid exit from %s structured block", kind);
1e8e9920 12066 else
ca4c3545 12067 error ("invalid entry to %s structured block", kind);
75a70cf9 12068#endif
1e8e9920 12069
75a70cf9 12070 /* If it's obvious we have an invalid entry, be specific about the error. */
12071 if (branch_ctx == NULL)
ca4c3545 12072 error ("invalid entry to %s structured block", kind);
75a70cf9 12073 else
f2697631 12074 {
12075 /* Otherwise, be vague and lazy, but efficient. */
ca4c3545 12076 error ("invalid branch to/from %s structured block", kind);
f2697631 12077 }
75a70cf9 12078
12079 gsi_replace (gsi_p, gimple_build_nop (), false);
1e8e9920 12080 return true;
12081}
12082
ca4c3545 12083/* Pass 1: Create a minimal tree of structured blocks, and record
75a70cf9 12084 where each label is found. */
1e8e9920 12085
12086static tree
75a70cf9 12087diagnose_sb_1 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
12088 struct walk_stmt_info *wi)
1e8e9920 12089{
75a70cf9 12090 gimple context = (gimple) wi->info;
12091 gimple inner_context;
12092 gimple stmt = gsi_stmt (*gsi_p);
1e8e9920 12093
75a70cf9 12094 *handled_ops_p = true;
12095
ca4c3545 12096 switch (gimple_code (stmt))
1e8e9920 12097 {
75a70cf9 12098 WALK_SUBSTMTS;
48e1416a 12099
75a70cf9 12100 case GIMPLE_OMP_PARALLEL:
12101 case GIMPLE_OMP_TASK:
12102 case GIMPLE_OMP_SECTIONS:
12103 case GIMPLE_OMP_SINGLE:
12104 case GIMPLE_OMP_SECTION:
12105 case GIMPLE_OMP_MASTER:
12106 case GIMPLE_OMP_ORDERED:
12107 case GIMPLE_OMP_CRITICAL:
bc7bff74 12108 case GIMPLE_OMP_TARGET:
12109 case GIMPLE_OMP_TEAMS:
12110 case GIMPLE_OMP_TASKGROUP:
75a70cf9 12111 /* The minimal context here is just the current OMP construct. */
12112 inner_context = stmt;
1e8e9920 12113 wi->info = inner_context;
75a70cf9 12114 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
1e8e9920 12115 wi->info = context;
12116 break;
12117
75a70cf9 12118 case GIMPLE_OMP_FOR:
12119 inner_context = stmt;
1e8e9920 12120 wi->info = inner_context;
75a70cf9 12121 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
12122 walk them. */
12123 walk_gimple_seq (gimple_omp_for_pre_body (stmt),
12124 diagnose_sb_1, NULL, wi);
12125 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
1e8e9920 12126 wi->info = context;
12127 break;
12128
75a70cf9 12129 case GIMPLE_LABEL:
1a91d914 12130 splay_tree_insert (all_labels,
12131 (splay_tree_key) gimple_label_label (
12132 as_a <glabel *> (stmt)),
1e8e9920 12133 (splay_tree_value) context);
12134 break;
12135
12136 default:
12137 break;
12138 }
12139
12140 return NULL_TREE;
12141}
12142
12143/* Pass 2: Check each branch and see if its context differs from that of
12144 the destination label's context. */
12145
12146static tree
75a70cf9 12147diagnose_sb_2 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
12148 struct walk_stmt_info *wi)
1e8e9920 12149{
75a70cf9 12150 gimple context = (gimple) wi->info;
1e8e9920 12151 splay_tree_node n;
75a70cf9 12152 gimple stmt = gsi_stmt (*gsi_p);
1e8e9920 12153
75a70cf9 12154 *handled_ops_p = true;
12155
12156 switch (gimple_code (stmt))
1e8e9920 12157 {
75a70cf9 12158 WALK_SUBSTMTS;
12159
12160 case GIMPLE_OMP_PARALLEL:
12161 case GIMPLE_OMP_TASK:
12162 case GIMPLE_OMP_SECTIONS:
12163 case GIMPLE_OMP_SINGLE:
12164 case GIMPLE_OMP_SECTION:
12165 case GIMPLE_OMP_MASTER:
12166 case GIMPLE_OMP_ORDERED:
12167 case GIMPLE_OMP_CRITICAL:
bc7bff74 12168 case GIMPLE_OMP_TARGET:
12169 case GIMPLE_OMP_TEAMS:
12170 case GIMPLE_OMP_TASKGROUP:
75a70cf9 12171 wi->info = stmt;
e3a19533 12172 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
1e8e9920 12173 wi->info = context;
12174 break;
12175
75a70cf9 12176 case GIMPLE_OMP_FOR:
12177 wi->info = stmt;
12178 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
12179 walk them. */
e3a19533 12180 walk_gimple_seq_mod (gimple_omp_for_pre_body_ptr (stmt),
12181 diagnose_sb_2, NULL, wi);
12182 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
1e8e9920 12183 wi->info = context;
12184 break;
12185
0e1818e7 12186 case GIMPLE_COND:
12187 {
1a91d914 12188 gcond *cond_stmt = as_a <gcond *> (stmt);
12189 tree lab = gimple_cond_true_label (cond_stmt);
0e1818e7 12190 if (lab)
12191 {
12192 n = splay_tree_lookup (all_labels,
12193 (splay_tree_key) lab);
12194 diagnose_sb_0 (gsi_p, context,
12195 n ? (gimple) n->value : NULL);
12196 }
1a91d914 12197 lab = gimple_cond_false_label (cond_stmt);
0e1818e7 12198 if (lab)
12199 {
12200 n = splay_tree_lookup (all_labels,
12201 (splay_tree_key) lab);
12202 diagnose_sb_0 (gsi_p, context,
12203 n ? (gimple) n->value : NULL);
12204 }
12205 }
12206 break;
12207
75a70cf9 12208 case GIMPLE_GOTO:
1e8e9920 12209 {
75a70cf9 12210 tree lab = gimple_goto_dest (stmt);
1e8e9920 12211 if (TREE_CODE (lab) != LABEL_DECL)
12212 break;
12213
12214 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
75a70cf9 12215 diagnose_sb_0 (gsi_p, context, n ? (gimple) n->value : NULL);
1e8e9920 12216 }
12217 break;
12218
75a70cf9 12219 case GIMPLE_SWITCH:
1e8e9920 12220 {
1a91d914 12221 gswitch *switch_stmt = as_a <gswitch *> (stmt);
75a70cf9 12222 unsigned int i;
1a91d914 12223 for (i = 0; i < gimple_switch_num_labels (switch_stmt); ++i)
1e8e9920 12224 {
1a91d914 12225 tree lab = CASE_LABEL (gimple_switch_label (switch_stmt, i));
1e8e9920 12226 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
75a70cf9 12227 if (n && diagnose_sb_0 (gsi_p, context, (gimple) n->value))
1e8e9920 12228 break;
12229 }
12230 }
12231 break;
12232
75a70cf9 12233 case GIMPLE_RETURN:
12234 diagnose_sb_0 (gsi_p, context, NULL);
1e8e9920 12235 break;
12236
12237 default:
12238 break;
12239 }
12240
12241 return NULL_TREE;
12242}
12243
ca4c3545 12244/* Called from tree-cfg.c::make_edges to create cfg edges for all relevant
12245 GIMPLE_* codes. */
7740abd8 12246bool
b2c0e0b7 12247make_gimple_omp_edges (basic_block bb, struct omp_region **region,
12248 int *region_idx)
7740abd8 12249{
12250 gimple last = last_stmt (bb);
12251 enum gimple_code code = gimple_code (last);
12252 struct omp_region *cur_region = *region;
12253 bool fallthru = false;
12254
12255 switch (code)
12256 {
12257 case GIMPLE_OMP_PARALLEL:
12258 case GIMPLE_OMP_TASK:
12259 case GIMPLE_OMP_FOR:
12260 case GIMPLE_OMP_SINGLE:
12261 case GIMPLE_OMP_TEAMS:
12262 case GIMPLE_OMP_MASTER:
12263 case GIMPLE_OMP_TASKGROUP:
12264 case GIMPLE_OMP_ORDERED:
12265 case GIMPLE_OMP_CRITICAL:
12266 case GIMPLE_OMP_SECTION:
12267 cur_region = new_omp_region (bb, code, cur_region);
12268 fallthru = true;
12269 break;
12270
12271 case GIMPLE_OMP_TARGET:
12272 cur_region = new_omp_region (bb, code, cur_region);
12273 fallthru = true;
ca4c3545 12274 switch (gimple_omp_target_kind (last))
12275 {
12276 case GF_OMP_TARGET_KIND_REGION:
12277 case GF_OMP_TARGET_KIND_DATA:
12278 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
12279 case GF_OMP_TARGET_KIND_OACC_KERNELS:
12280 case GF_OMP_TARGET_KIND_OACC_DATA:
12281 break;
12282 case GF_OMP_TARGET_KIND_UPDATE:
12283 case GF_OMP_TARGET_KIND_OACC_UPDATE:
12284 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
12285 cur_region = cur_region->outer;
12286 break;
12287 default:
12288 gcc_unreachable ();
12289 }
7740abd8 12290 break;
12291
12292 case GIMPLE_OMP_SECTIONS:
12293 cur_region = new_omp_region (bb, code, cur_region);
12294 fallthru = true;
12295 break;
12296
12297 case GIMPLE_OMP_SECTIONS_SWITCH:
12298 fallthru = false;
12299 break;
12300
12301 case GIMPLE_OMP_ATOMIC_LOAD:
12302 case GIMPLE_OMP_ATOMIC_STORE:
12303 fallthru = true;
12304 break;
12305
12306 case GIMPLE_OMP_RETURN:
12307 /* In the case of a GIMPLE_OMP_SECTION, the edge will go
12308 somewhere other than the next block. This will be
12309 created later. */
12310 cur_region->exit = bb;
b25f70fd 12311 if (cur_region->type == GIMPLE_OMP_TASK)
12312 /* Add an edge corresponding to not scheduling the task
12313 immediately. */
12314 make_edge (cur_region->entry, bb, EDGE_ABNORMAL);
7740abd8 12315 fallthru = cur_region->type != GIMPLE_OMP_SECTION;
12316 cur_region = cur_region->outer;
12317 break;
12318
12319 case GIMPLE_OMP_CONTINUE:
12320 cur_region->cont = bb;
12321 switch (cur_region->type)
12322 {
12323 case GIMPLE_OMP_FOR:
12324 /* Mark all GIMPLE_OMP_FOR and GIMPLE_OMP_CONTINUE
12325 succs edges as abnormal to prevent splitting
12326 them. */
12327 single_succ_edge (cur_region->entry)->flags |= EDGE_ABNORMAL;
12328 /* Make the loopback edge. */
12329 make_edge (bb, single_succ (cur_region->entry),
12330 EDGE_ABNORMAL);
12331
12332 /* Create an edge from GIMPLE_OMP_FOR to exit, which
12333 corresponds to the case that the body of the loop
12334 is not executed at all. */
12335 make_edge (cur_region->entry, bb->next_bb, EDGE_ABNORMAL);
12336 make_edge (bb, bb->next_bb, EDGE_FALLTHRU | EDGE_ABNORMAL);
12337 fallthru = false;
12338 break;
12339
12340 case GIMPLE_OMP_SECTIONS:
12341 /* Wire up the edges into and out of the nested sections. */
12342 {
12343 basic_block switch_bb = single_succ (cur_region->entry);
12344
12345 struct omp_region *i;
12346 for (i = cur_region->inner; i ; i = i->next)
12347 {
12348 gcc_assert (i->type == GIMPLE_OMP_SECTION);
12349 make_edge (switch_bb, i->entry, 0);
12350 make_edge (i->exit, bb, EDGE_FALLTHRU);
12351 }
12352
12353 /* Make the loopback edge to the block with
12354 GIMPLE_OMP_SECTIONS_SWITCH. */
12355 make_edge (bb, switch_bb, 0);
12356
12357 /* Make the edge from the switch to exit. */
12358 make_edge (switch_bb, bb->next_bb, 0);
12359 fallthru = false;
12360 }
12361 break;
12362
b25f70fd 12363 case GIMPLE_OMP_TASK:
12364 fallthru = true;
12365 break;
12366
7740abd8 12367 default:
12368 gcc_unreachable ();
12369 }
12370 break;
12371
12372 default:
12373 gcc_unreachable ();
12374 }
12375
12376 if (*region != cur_region)
b2c0e0b7 12377 {
12378 *region = cur_region;
12379 if (cur_region)
12380 *region_idx = cur_region->entry->index;
12381 else
12382 *region_idx = 0;
12383 }
7740abd8 12384
12385 return fallthru;
12386}
12387
bfec3452 12388static unsigned int
12389diagnose_omp_structured_block_errors (void)
1e8e9920 12390{
1e8e9920 12391 struct walk_stmt_info wi;
bfec3452 12392 gimple_seq body = gimple_body (current_function_decl);
1e8e9920 12393
12394 all_labels = splay_tree_new (splay_tree_compare_pointers, 0, 0);
12395
12396 memset (&wi, 0, sizeof (wi));
75a70cf9 12397 walk_gimple_seq (body, diagnose_sb_1, NULL, &wi);
1e8e9920 12398
12399 memset (&wi, 0, sizeof (wi));
1e8e9920 12400 wi.want_locations = true;
e3a19533 12401 walk_gimple_seq_mod (&body, diagnose_sb_2, NULL, &wi);
12402
12403 gimple_set_body (current_function_decl, body);
1e8e9920 12404
12405 splay_tree_delete (all_labels);
12406 all_labels = NULL;
12407
bfec3452 12408 return 0;
1e8e9920 12409}
12410
cbe8bda8 12411namespace {
12412
12413const pass_data pass_data_diagnose_omp_blocks =
12414{
12415 GIMPLE_PASS, /* type */
12416 "*diagnose_omp_blocks", /* name */
12417 OPTGROUP_NONE, /* optinfo_flags */
cbe8bda8 12418 TV_NONE, /* tv_id */
12419 PROP_gimple_any, /* properties_required */
12420 0, /* properties_provided */
12421 0, /* properties_destroyed */
12422 0, /* todo_flags_start */
12423 0, /* todo_flags_finish */
bfec3452 12424};
12425
cbe8bda8 12426class pass_diagnose_omp_blocks : public gimple_opt_pass
12427{
12428public:
9af5ce0c 12429 pass_diagnose_omp_blocks (gcc::context *ctxt)
12430 : gimple_opt_pass (pass_data_diagnose_omp_blocks, ctxt)
cbe8bda8 12431 {}
12432
12433 /* opt_pass methods: */
ca4c3545 12434 virtual bool gate (function *)
12435 {
12436 return flag_cilkplus || flag_openacc || flag_openmp;
12437 }
65b0537f 12438 virtual unsigned int execute (function *)
12439 {
12440 return diagnose_omp_structured_block_errors ();
12441 }
cbe8bda8 12442
12443}; // class pass_diagnose_omp_blocks
12444
12445} // anon namespace
12446
12447gimple_opt_pass *
12448make_pass_diagnose_omp_blocks (gcc::context *ctxt)
12449{
12450 return new pass_diagnose_omp_blocks (ctxt);
12451}
d09768a4 12452\f
12453/* SIMD clone supporting code. */
12454
12455/* Allocate a fresh `simd_clone' and return it. NARGS is the number
12456 of arguments to reserve space for. */
12457
12458static struct cgraph_simd_clone *
12459simd_clone_struct_alloc (int nargs)
12460{
12461 struct cgraph_simd_clone *clone_info;
12462 size_t len = (sizeof (struct cgraph_simd_clone)
12463 + nargs * sizeof (struct cgraph_simd_clone_arg));
12464 clone_info = (struct cgraph_simd_clone *)
ea7d8c7a 12465 ggc_internal_cleared_alloc (len);
d09768a4 12466 return clone_info;
12467}
12468
12469/* Make a copy of the `struct cgraph_simd_clone' in FROM to TO. */
12470
12471static inline void
12472simd_clone_struct_copy (struct cgraph_simd_clone *to,
12473 struct cgraph_simd_clone *from)
12474{
12475 memcpy (to, from, (sizeof (struct cgraph_simd_clone)
46c0fd4b 12476 + ((from->nargs - from->inbranch)
12477 * sizeof (struct cgraph_simd_clone_arg))));
d09768a4 12478}
12479
12480/* Return vector of parameter types of function FNDECL. This uses
12481 TYPE_ARG_TYPES if available, otherwise falls back to types of
12482 DECL_ARGUMENTS types. */
12483
12484vec<tree>
12485simd_clone_vector_of_formal_parm_types (tree fndecl)
12486{
12487 if (TYPE_ARG_TYPES (TREE_TYPE (fndecl)))
12488 return ipa_get_vector_of_formal_parm_types (TREE_TYPE (fndecl));
12489 vec<tree> args = ipa_get_vector_of_formal_parms (fndecl);
12490 unsigned int i;
12491 tree arg;
12492 FOR_EACH_VEC_ELT (args, i, arg)
12493 args[i] = TREE_TYPE (args[i]);
12494 return args;
12495}
12496
12497/* Given a simd function in NODE, extract the simd specific
12498 information from the OMP clauses passed in CLAUSES, and return
12499 the struct cgraph_simd_clone * if it should be cloned. *INBRANCH_SPECIFIED
12500 is set to TRUE if the `inbranch' or `notinbranch' clause specified,
12501 otherwise set to FALSE. */
12502
12503static struct cgraph_simd_clone *
12504simd_clone_clauses_extract (struct cgraph_node *node, tree clauses,
12505 bool *inbranch_specified)
12506{
12507 vec<tree> args = simd_clone_vector_of_formal_parm_types (node->decl);
12508 tree t;
12509 int n;
12510 *inbranch_specified = false;
12511
12512 n = args.length ();
12513 if (n > 0 && args.last () == void_type_node)
12514 n--;
12515
12516 /* To distinguish from an OpenMP simd clone, Cilk Plus functions to
12517 be cloned have a distinctive artificial label in addition to "omp
12518 declare simd". */
12519 bool cilk_clone
a89e6c15 12520 = (flag_cilkplus
74acc703 12521 && lookup_attribute ("cilk simd function",
d09768a4 12522 DECL_ATTRIBUTES (node->decl)));
12523
12524 /* Allocate one more than needed just in case this is an in-branch
12525 clone which will require a mask argument. */
12526 struct cgraph_simd_clone *clone_info = simd_clone_struct_alloc (n + 1);
12527 clone_info->nargs = n;
12528 clone_info->cilk_elemental = cilk_clone;
12529
12530 if (!clauses)
12531 {
12532 args.release ();
12533 return clone_info;
12534 }
12535 clauses = TREE_VALUE (clauses);
12536 if (!clauses || TREE_CODE (clauses) != OMP_CLAUSE)
12537 return clone_info;
12538
12539 for (t = clauses; t; t = OMP_CLAUSE_CHAIN (t))
12540 {
12541 switch (OMP_CLAUSE_CODE (t))
12542 {
12543 case OMP_CLAUSE_INBRANCH:
12544 clone_info->inbranch = 1;
12545 *inbranch_specified = true;
12546 break;
12547 case OMP_CLAUSE_NOTINBRANCH:
12548 clone_info->inbranch = 0;
12549 *inbranch_specified = true;
12550 break;
12551 case OMP_CLAUSE_SIMDLEN:
12552 clone_info->simdlen
12553 = TREE_INT_CST_LOW (OMP_CLAUSE_SIMDLEN_EXPR (t));
12554 break;
12555 case OMP_CLAUSE_LINEAR:
12556 {
12557 tree decl = OMP_CLAUSE_DECL (t);
12558 tree step = OMP_CLAUSE_LINEAR_STEP (t);
12559 int argno = TREE_INT_CST_LOW (decl);
12560 if (OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (t))
12561 {
12562 clone_info->args[argno].arg_type
12563 = SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP;
12564 clone_info->args[argno].linear_step = tree_to_shwi (step);
12565 gcc_assert (clone_info->args[argno].linear_step >= 0
12566 && clone_info->args[argno].linear_step < n);
12567 }
12568 else
12569 {
12570 if (POINTER_TYPE_P (args[argno]))
12571 step = fold_convert (ssizetype, step);
12572 if (!tree_fits_shwi_p (step))
12573 {
12574 warning_at (OMP_CLAUSE_LOCATION (t), 0,
12575 "ignoring large linear step");
12576 args.release ();
12577 return NULL;
12578 }
12579 else if (integer_zerop (step))
12580 {
12581 warning_at (OMP_CLAUSE_LOCATION (t), 0,
12582 "ignoring zero linear step");
12583 args.release ();
12584 return NULL;
12585 }
12586 else
12587 {
12588 clone_info->args[argno].arg_type
12589 = SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP;
12590 clone_info->args[argno].linear_step = tree_to_shwi (step);
12591 }
12592 }
12593 break;
12594 }
12595 case OMP_CLAUSE_UNIFORM:
12596 {
12597 tree decl = OMP_CLAUSE_DECL (t);
12598 int argno = tree_to_uhwi (decl);
12599 clone_info->args[argno].arg_type
12600 = SIMD_CLONE_ARG_TYPE_UNIFORM;
12601 break;
12602 }
12603 case OMP_CLAUSE_ALIGNED:
12604 {
12605 tree decl = OMP_CLAUSE_DECL (t);
12606 int argno = tree_to_uhwi (decl);
12607 clone_info->args[argno].alignment
12608 = TREE_INT_CST_LOW (OMP_CLAUSE_ALIGNED_ALIGNMENT (t));
12609 break;
12610 }
12611 default:
12612 break;
12613 }
12614 }
12615 args.release ();
12616 return clone_info;
12617}
12618
12619/* Given a SIMD clone in NODE, calculate the characteristic data
12620 type and return the coresponding type. The characteristic data
12621 type is computed as described in the Intel Vector ABI. */
12622
12623static tree
12624simd_clone_compute_base_data_type (struct cgraph_node *node,
12625 struct cgraph_simd_clone *clone_info)
12626{
12627 tree type = integer_type_node;
12628 tree fndecl = node->decl;
12629
12630 /* a) For non-void function, the characteristic data type is the
12631 return type. */
12632 if (TREE_CODE (TREE_TYPE (TREE_TYPE (fndecl))) != VOID_TYPE)
12633 type = TREE_TYPE (TREE_TYPE (fndecl));
12634
12635 /* b) If the function has any non-uniform, non-linear parameters,
12636 then the characteristic data type is the type of the first
12637 such parameter. */
12638 else
12639 {
12640 vec<tree> map = simd_clone_vector_of_formal_parm_types (fndecl);
12641 for (unsigned int i = 0; i < clone_info->nargs; ++i)
12642 if (clone_info->args[i].arg_type == SIMD_CLONE_ARG_TYPE_VECTOR)
12643 {
12644 type = map[i];
12645 break;
12646 }
12647 map.release ();
12648 }
12649
12650 /* c) If the characteristic data type determined by a) or b) above
12651 is struct, union, or class type which is pass-by-value (except
12652 for the type that maps to the built-in complex data type), the
12653 characteristic data type is int. */
12654 if (RECORD_OR_UNION_TYPE_P (type)
12655 && !aggregate_value_p (type, NULL)
12656 && TREE_CODE (type) != COMPLEX_TYPE)
12657 return integer_type_node;
12658
12659 /* d) If none of the above three classes is applicable, the
12660 characteristic data type is int. */
12661
12662 return type;
12663
12664 /* e) For Intel Xeon Phi native and offload compilation, if the
12665 resulting characteristic data type is 8-bit or 16-bit integer
12666 data type, the characteristic data type is int. */
12667 /* Well, we don't handle Xeon Phi yet. */
12668}
12669
12670static tree
12671simd_clone_mangle (struct cgraph_node *node,
12672 struct cgraph_simd_clone *clone_info)
12673{
12674 char vecsize_mangle = clone_info->vecsize_mangle;
12675 char mask = clone_info->inbranch ? 'M' : 'N';
12676 unsigned int simdlen = clone_info->simdlen;
12677 unsigned int n;
12678 pretty_printer pp;
12679
12680 gcc_assert (vecsize_mangle && simdlen);
12681
12682 pp_string (&pp, "_ZGV");
12683 pp_character (&pp, vecsize_mangle);
12684 pp_character (&pp, mask);
12685 pp_decimal_int (&pp, simdlen);
12686
12687 for (n = 0; n < clone_info->nargs; ++n)
12688 {
12689 struct cgraph_simd_clone_arg arg = clone_info->args[n];
12690
12691 if (arg.arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM)
12692 pp_character (&pp, 'u');
12693 else if (arg.arg_type == SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP)
12694 {
12695 gcc_assert (arg.linear_step != 0);
12696 pp_character (&pp, 'l');
12697 if (arg.linear_step > 1)
12698 pp_unsigned_wide_integer (&pp, arg.linear_step);
12699 else if (arg.linear_step < 0)
12700 {
12701 pp_character (&pp, 'n');
12702 pp_unsigned_wide_integer (&pp, (-(unsigned HOST_WIDE_INT)
12703 arg.linear_step));
12704 }
12705 }
12706 else if (arg.arg_type == SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP)
12707 {
12708 pp_character (&pp, 's');
12709 pp_unsigned_wide_integer (&pp, arg.linear_step);
12710 }
12711 else
12712 pp_character (&pp, 'v');
12713 if (arg.alignment)
12714 {
12715 pp_character (&pp, 'a');
12716 pp_decimal_int (&pp, arg.alignment);
12717 }
12718 }
12719
12720 pp_underscore (&pp);
4e4baaad 12721 const char *str = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (node->decl));
12722 if (*str == '*')
12723 ++str;
12724 pp_string (&pp, str);
12725 str = pp_formatted_text (&pp);
d09768a4 12726
12727 /* If there already is a SIMD clone with the same mangled name, don't
12728 add another one. This can happen e.g. for
12729 #pragma omp declare simd
12730 #pragma omp declare simd simdlen(8)
12731 int foo (int, int);
12732 if the simdlen is assumed to be 8 for the first one, etc. */
12733 for (struct cgraph_node *clone = node->simd_clones; clone;
12734 clone = clone->simdclone->next_clone)
12735 if (strcmp (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (clone->decl)),
12736 str) == 0)
12737 return NULL_TREE;
12738
12739 return get_identifier (str);
12740}
12741
12742/* Create a simd clone of OLD_NODE and return it. */
12743
12744static struct cgraph_node *
12745simd_clone_create (struct cgraph_node *old_node)
12746{
12747 struct cgraph_node *new_node;
12748 if (old_node->definition)
ea0695f9 12749 {
415d1b9a 12750 if (!old_node->has_gimple_body_p ())
ea0695f9 12751 return NULL;
415d1b9a 12752 old_node->get_body ();
12753 new_node = old_node->create_version_clone_with_body (vNULL, NULL, NULL,
12754 false, NULL, NULL,
12755 "simdclone");
ea0695f9 12756 }
d09768a4 12757 else
12758 {
12759 tree old_decl = old_node->decl;
12760 tree new_decl = copy_node (old_node->decl);
12761 DECL_NAME (new_decl) = clone_function_name (old_decl, "simdclone");
12762 SET_DECL_ASSEMBLER_NAME (new_decl, DECL_NAME (new_decl));
12763 SET_DECL_RTL (new_decl, NULL);
12764 DECL_STATIC_CONSTRUCTOR (new_decl) = 0;
12765 DECL_STATIC_DESTRUCTOR (new_decl) = 0;
415d1b9a 12766 new_node = old_node->create_version_clone (new_decl, vNULL, NULL);
35ee1c66 12767 symtab->call_cgraph_insertion_hooks (new_node);
d09768a4 12768 }
12769 if (new_node == NULL)
12770 return new_node;
12771
12772 TREE_PUBLIC (new_node->decl) = TREE_PUBLIC (old_node->decl);
12773
12774 /* The function cgraph_function_versioning () will force the new
12775 symbol local. Undo this, and inherit external visability from
12776 the old node. */
12777 new_node->local.local = old_node->local.local;
12778 new_node->externally_visible = old_node->externally_visible;
12779
12780 return new_node;
12781}
12782
12783/* Adjust the return type of the given function to its appropriate
12784 vector counterpart. Returns a simd array to be used throughout the
12785 function as a return value. */
12786
12787static tree
12788simd_clone_adjust_return_type (struct cgraph_node *node)
12789{
12790 tree fndecl = node->decl;
12791 tree orig_rettype = TREE_TYPE (TREE_TYPE (fndecl));
12792 unsigned int veclen;
12793 tree t;
12794
12795 /* Adjust the function return type. */
12796 if (orig_rettype == void_type_node)
12797 return NULL_TREE;
12798 TREE_TYPE (fndecl) = build_distinct_type_copy (TREE_TYPE (fndecl));
fdf7662c 12799 t = TREE_TYPE (TREE_TYPE (fndecl));
12800 if (INTEGRAL_TYPE_P (t) || POINTER_TYPE_P (t))
d09768a4 12801 veclen = node->simdclone->vecsize_int;
12802 else
12803 veclen = node->simdclone->vecsize_float;
fdf7662c 12804 veclen /= GET_MODE_BITSIZE (TYPE_MODE (t));
d09768a4 12805 if (veclen > node->simdclone->simdlen)
12806 veclen = node->simdclone->simdlen;
fdf7662c 12807 if (POINTER_TYPE_P (t))
12808 t = pointer_sized_int_node;
d09768a4 12809 if (veclen == node->simdclone->simdlen)
fdf7662c 12810 t = build_vector_type (t, node->simdclone->simdlen);
d09768a4 12811 else
12812 {
fdf7662c 12813 t = build_vector_type (t, veclen);
d09768a4 12814 t = build_array_type_nelts (t, node->simdclone->simdlen / veclen);
d09768a4 12815 }
fdf7662c 12816 TREE_TYPE (TREE_TYPE (fndecl)) = t;
d09768a4 12817 if (!node->definition)
12818 return NULL_TREE;
12819
12820 t = DECL_RESULT (fndecl);
12821 /* Adjust the DECL_RESULT. */
12822 gcc_assert (TREE_TYPE (t) != void_type_node);
12823 TREE_TYPE (t) = TREE_TYPE (TREE_TYPE (fndecl));
12824 relayout_decl (t);
12825
12826 tree atype = build_array_type_nelts (orig_rettype,
12827 node->simdclone->simdlen);
12828 if (veclen != node->simdclone->simdlen)
12829 return build1 (VIEW_CONVERT_EXPR, atype, t);
12830
12831 /* Set up a SIMD array to use as the return value. */
12832 tree retval = create_tmp_var_raw (atype, "retval");
12833 gimple_add_tmp_var (retval);
12834 return retval;
12835}
12836
12837/* Each vector argument has a corresponding array to be used locally
12838 as part of the eventual loop. Create such temporary array and
12839 return it.
12840
12841 PREFIX is the prefix to be used for the temporary.
12842
12843 TYPE is the inner element type.
12844
12845 SIMDLEN is the number of elements. */
12846
12847static tree
12848create_tmp_simd_array (const char *prefix, tree type, int simdlen)
12849{
12850 tree atype = build_array_type_nelts (type, simdlen);
12851 tree avar = create_tmp_var_raw (atype, prefix);
12852 gimple_add_tmp_var (avar);
12853 return avar;
12854}
12855
12856/* Modify the function argument types to their corresponding vector
12857 counterparts if appropriate. Also, create one array for each simd
12858 argument to be used locally when using the function arguments as
12859 part of the loop.
12860
12861 NODE is the function whose arguments are to be adjusted.
12862
12863 Returns an adjustment vector that will be filled describing how the
12864 argument types will be adjusted. */
12865
12866static ipa_parm_adjustment_vec
12867simd_clone_adjust_argument_types (struct cgraph_node *node)
12868{
12869 vec<tree> args;
12870 ipa_parm_adjustment_vec adjustments;
12871
12872 if (node->definition)
12873 args = ipa_get_vector_of_formal_parms (node->decl);
12874 else
12875 args = simd_clone_vector_of_formal_parm_types (node->decl);
12876 adjustments.create (args.length ());
12877 unsigned i, j, veclen;
12878 struct ipa_parm_adjustment adj;
12879 for (i = 0; i < node->simdclone->nargs; ++i)
12880 {
12881 memset (&adj, 0, sizeof (adj));
12882 tree parm = args[i];
12883 tree parm_type = node->definition ? TREE_TYPE (parm) : parm;
12884 adj.base_index = i;
12885 adj.base = parm;
12886
12887 node->simdclone->args[i].orig_arg = node->definition ? parm : NULL_TREE;
12888 node->simdclone->args[i].orig_type = parm_type;
12889
12890 if (node->simdclone->args[i].arg_type != SIMD_CLONE_ARG_TYPE_VECTOR)
12891 {
12892 /* No adjustment necessary for scalar arguments. */
12893 adj.op = IPA_PARM_OP_COPY;
12894 }
12895 else
12896 {
12897 if (INTEGRAL_TYPE_P (parm_type) || POINTER_TYPE_P (parm_type))
12898 veclen = node->simdclone->vecsize_int;
12899 else
12900 veclen = node->simdclone->vecsize_float;
12901 veclen /= GET_MODE_BITSIZE (TYPE_MODE (parm_type));
12902 if (veclen > node->simdclone->simdlen)
12903 veclen = node->simdclone->simdlen;
12904 adj.arg_prefix = "simd";
fdf7662c 12905 if (POINTER_TYPE_P (parm_type))
12906 adj.type = build_vector_type (pointer_sized_int_node, veclen);
12907 else
12908 adj.type = build_vector_type (parm_type, veclen);
d09768a4 12909 node->simdclone->args[i].vector_type = adj.type;
12910 for (j = veclen; j < node->simdclone->simdlen; j += veclen)
12911 {
12912 adjustments.safe_push (adj);
12913 if (j == veclen)
12914 {
12915 memset (&adj, 0, sizeof (adj));
12916 adj.op = IPA_PARM_OP_NEW;
12917 adj.arg_prefix = "simd";
12918 adj.base_index = i;
12919 adj.type = node->simdclone->args[i].vector_type;
12920 }
12921 }
12922
12923 if (node->definition)
12924 node->simdclone->args[i].simd_array
12925 = create_tmp_simd_array (IDENTIFIER_POINTER (DECL_NAME (parm)),
12926 parm_type, node->simdclone->simdlen);
12927 }
12928 adjustments.safe_push (adj);
12929 }
12930
12931 if (node->simdclone->inbranch)
12932 {
12933 tree base_type
12934 = simd_clone_compute_base_data_type (node->simdclone->origin,
12935 node->simdclone);
12936
12937 memset (&adj, 0, sizeof (adj));
12938 adj.op = IPA_PARM_OP_NEW;
12939 adj.arg_prefix = "mask";
12940
12941 adj.base_index = i;
12942 if (INTEGRAL_TYPE_P (base_type) || POINTER_TYPE_P (base_type))
12943 veclen = node->simdclone->vecsize_int;
12944 else
12945 veclen = node->simdclone->vecsize_float;
12946 veclen /= GET_MODE_BITSIZE (TYPE_MODE (base_type));
12947 if (veclen > node->simdclone->simdlen)
12948 veclen = node->simdclone->simdlen;
fdf7662c 12949 if (POINTER_TYPE_P (base_type))
12950 adj.type = build_vector_type (pointer_sized_int_node, veclen);
12951 else
12952 adj.type = build_vector_type (base_type, veclen);
d09768a4 12953 adjustments.safe_push (adj);
12954
12955 for (j = veclen; j < node->simdclone->simdlen; j += veclen)
12956 adjustments.safe_push (adj);
12957
12958 /* We have previously allocated one extra entry for the mask. Use
12959 it and fill it. */
12960 struct cgraph_simd_clone *sc = node->simdclone;
12961 sc->nargs++;
12962 if (node->definition)
12963 {
12964 sc->args[i].orig_arg
12965 = build_decl (UNKNOWN_LOCATION, PARM_DECL, NULL, base_type);
12966 sc->args[i].simd_array
12967 = create_tmp_simd_array ("mask", base_type, sc->simdlen);
12968 }
12969 sc->args[i].orig_type = base_type;
12970 sc->args[i].arg_type = SIMD_CLONE_ARG_TYPE_MASK;
12971 }
12972
12973 if (node->definition)
12974 ipa_modify_formal_parameters (node->decl, adjustments);
12975 else
12976 {
12977 tree new_arg_types = NULL_TREE, new_reversed;
12978 bool last_parm_void = false;
12979 if (args.length () > 0 && args.last () == void_type_node)
12980 last_parm_void = true;
12981
12982 gcc_assert (TYPE_ARG_TYPES (TREE_TYPE (node->decl)));
12983 j = adjustments.length ();
12984 for (i = 0; i < j; i++)
12985 {
12986 struct ipa_parm_adjustment *adj = &adjustments[i];
12987 tree ptype;
12988 if (adj->op == IPA_PARM_OP_COPY)
12989 ptype = args[adj->base_index];
12990 else
12991 ptype = adj->type;
12992 new_arg_types = tree_cons (NULL_TREE, ptype, new_arg_types);
12993 }
12994 new_reversed = nreverse (new_arg_types);
12995 if (last_parm_void)
12996 {
12997 if (new_reversed)
12998 TREE_CHAIN (new_arg_types) = void_list_node;
12999 else
13000 new_reversed = void_list_node;
13001 }
13002
13003 tree new_type = build_distinct_type_copy (TREE_TYPE (node->decl));
13004 TYPE_ARG_TYPES (new_type) = new_reversed;
13005 TREE_TYPE (node->decl) = new_type;
13006
13007 adjustments.release ();
13008 }
13009 args.release ();
13010 return adjustments;
13011}
13012
13013/* Initialize and copy the function arguments in NODE to their
13014 corresponding local simd arrays. Returns a fresh gimple_seq with
13015 the instruction sequence generated. */
13016
13017static gimple_seq
13018simd_clone_init_simd_arrays (struct cgraph_node *node,
13019 ipa_parm_adjustment_vec adjustments)
13020{
13021 gimple_seq seq = NULL;
13022 unsigned i = 0, j = 0, k;
13023
13024 for (tree arg = DECL_ARGUMENTS (node->decl);
13025 arg;
13026 arg = DECL_CHAIN (arg), i++, j++)
13027 {
13028 if (adjustments[j].op == IPA_PARM_OP_COPY)
13029 continue;
13030
13031 node->simdclone->args[i].vector_arg = arg;
13032
13033 tree array = node->simdclone->args[i].simd_array;
13034 if (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg)) == node->simdclone->simdlen)
13035 {
13036 tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
13037 tree ptr = build_fold_addr_expr (array);
13038 tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
13039 build_int_cst (ptype, 0));
13040 t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
13041 gimplify_and_add (t, &seq);
13042 }
13043 else
13044 {
13045 unsigned int simdlen = TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg));
13046 tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
13047 for (k = 0; k < node->simdclone->simdlen; k += simdlen)
13048 {
13049 tree ptr = build_fold_addr_expr (array);
13050 int elemsize;
13051 if (k)
13052 {
13053 arg = DECL_CHAIN (arg);
13054 j++;
13055 }
13056 elemsize
13057 = GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (arg))));
13058 tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
13059 build_int_cst (ptype, k * elemsize));
13060 t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
13061 gimplify_and_add (t, &seq);
13062 }
13063 }
13064 }
13065 return seq;
13066}
13067
13068/* Callback info for ipa_simd_modify_stmt_ops below. */
13069
13070struct modify_stmt_info {
13071 ipa_parm_adjustment_vec adjustments;
13072 gimple stmt;
13073 /* True if the parent statement was modified by
13074 ipa_simd_modify_stmt_ops. */
13075 bool modified;
13076};
13077
13078/* Callback for walk_gimple_op.
13079
13080 Adjust operands from a given statement as specified in the
13081 adjustments vector in the callback data. */
13082
13083static tree
13084ipa_simd_modify_stmt_ops (tree *tp, int *walk_subtrees, void *data)
13085{
13086 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
2d78e89f 13087 struct modify_stmt_info *info = (struct modify_stmt_info *) wi->info;
13088 tree *orig_tp = tp;
13089 if (TREE_CODE (*tp) == ADDR_EXPR)
13090 tp = &TREE_OPERAND (*tp, 0);
13091 struct ipa_parm_adjustment *cand = NULL;
13092 if (TREE_CODE (*tp) == PARM_DECL)
13093 cand = ipa_get_adjustment_candidate (&tp, NULL, info->adjustments, true);
13094 else
d09768a4 13095 {
d09768a4 13096 if (TYPE_P (*tp))
13097 *walk_subtrees = 0;
d09768a4 13098 }
d09768a4 13099
2d78e89f 13100 tree repl = NULL_TREE;
13101 if (cand)
13102 repl = unshare_expr (cand->new_decl);
13103 else
d09768a4 13104 {
2d78e89f 13105 if (tp != orig_tp)
13106 {
13107 *walk_subtrees = 0;
13108 bool modified = info->modified;
13109 info->modified = false;
13110 walk_tree (tp, ipa_simd_modify_stmt_ops, wi, wi->pset);
13111 if (!info->modified)
13112 {
13113 info->modified = modified;
13114 return NULL_TREE;
13115 }
13116 info->modified = modified;
13117 repl = *tp;
13118 }
13119 else
13120 return NULL_TREE;
d09768a4 13121 }
2d78e89f 13122
13123 if (tp != orig_tp)
d09768a4 13124 {
2d78e89f 13125 repl = build_fold_addr_expr (repl);
9c1dd4d9 13126 gimple stmt;
13127 if (is_gimple_debug (info->stmt))
13128 {
13129 tree vexpr = make_node (DEBUG_EXPR_DECL);
13130 stmt = gimple_build_debug_source_bind (vexpr, repl, NULL);
13131 DECL_ARTIFICIAL (vexpr) = 1;
13132 TREE_TYPE (vexpr) = TREE_TYPE (repl);
13133 DECL_MODE (vexpr) = TYPE_MODE (TREE_TYPE (repl));
13134 repl = vexpr;
13135 }
13136 else
13137 {
f9e245b2 13138 stmt = gimple_build_assign (make_ssa_name (TREE_TYPE (repl)), repl);
9c1dd4d9 13139 repl = gimple_assign_lhs (stmt);
13140 }
2d78e89f 13141 gimple_stmt_iterator gsi = gsi_for_stmt (info->stmt);
d09768a4 13142 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
2d78e89f 13143 *orig_tp = repl;
d09768a4 13144 }
2d78e89f 13145 else if (!useless_type_conversion_p (TREE_TYPE (*tp), TREE_TYPE (repl)))
d09768a4 13146 {
13147 tree vce = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (*tp), repl);
13148 *tp = vce;
13149 }
13150 else
13151 *tp = repl;
13152
13153 info->modified = true;
d09768a4 13154 return NULL_TREE;
13155}
13156
13157/* Traverse the function body and perform all modifications as
13158 described in ADJUSTMENTS. At function return, ADJUSTMENTS will be
13159 modified such that the replacement/reduction value will now be an
13160 offset into the corresponding simd_array.
13161
13162 This function will replace all function argument uses with their
13163 corresponding simd array elements, and ajust the return values
13164 accordingly. */
13165
13166static void
13167ipa_simd_modify_function_body (struct cgraph_node *node,
13168 ipa_parm_adjustment_vec adjustments,
13169 tree retval_array, tree iter)
13170{
13171 basic_block bb;
2d78e89f 13172 unsigned int i, j, l;
d09768a4 13173
13174 /* Re-use the adjustments array, but this time use it to replace
13175 every function argument use to an offset into the corresponding
13176 simd_array. */
13177 for (i = 0, j = 0; i < node->simdclone->nargs; ++i, ++j)
13178 {
13179 if (!node->simdclone->args[i].vector_arg)
13180 continue;
13181
13182 tree basetype = TREE_TYPE (node->simdclone->args[i].orig_arg);
13183 tree vectype = TREE_TYPE (node->simdclone->args[i].vector_arg);
13184 adjustments[j].new_decl
13185 = build4 (ARRAY_REF,
13186 basetype,
13187 node->simdclone->args[i].simd_array,
13188 iter,
13189 NULL_TREE, NULL_TREE);
13190 if (adjustments[j].op == IPA_PARM_OP_NONE
13191 && TYPE_VECTOR_SUBPARTS (vectype) < node->simdclone->simdlen)
13192 j += node->simdclone->simdlen / TYPE_VECTOR_SUBPARTS (vectype) - 1;
13193 }
13194
2d78e89f 13195 l = adjustments.length ();
13196 for (i = 1; i < num_ssa_names; i++)
13197 {
13198 tree name = ssa_name (i);
13199 if (name
13200 && SSA_NAME_VAR (name)
13201 && TREE_CODE (SSA_NAME_VAR (name)) == PARM_DECL)
13202 {
13203 for (j = 0; j < l; j++)
13204 if (SSA_NAME_VAR (name) == adjustments[j].base
13205 && adjustments[j].new_decl)
13206 {
13207 tree base_var;
13208 if (adjustments[j].new_ssa_base == NULL_TREE)
13209 {
13210 base_var
13211 = copy_var_decl (adjustments[j].base,
13212 DECL_NAME (adjustments[j].base),
13213 TREE_TYPE (adjustments[j].base));
13214 adjustments[j].new_ssa_base = base_var;
13215 }
13216 else
13217 base_var = adjustments[j].new_ssa_base;
13218 if (SSA_NAME_IS_DEFAULT_DEF (name))
13219 {
13220 bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
13221 gimple_stmt_iterator gsi = gsi_after_labels (bb);
13222 tree new_decl = unshare_expr (adjustments[j].new_decl);
13223 set_ssa_default_def (cfun, adjustments[j].base, NULL_TREE);
13224 SET_SSA_NAME_VAR_OR_IDENTIFIER (name, base_var);
13225 SSA_NAME_IS_DEFAULT_DEF (name) = 0;
13226 gimple stmt = gimple_build_assign (name, new_decl);
13227 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
13228 }
13229 else
13230 SET_SSA_NAME_VAR_OR_IDENTIFIER (name, base_var);
13231 }
13232 }
13233 }
13234
d09768a4 13235 struct modify_stmt_info info;
13236 info.adjustments = adjustments;
13237
13238 FOR_EACH_BB_FN (bb, DECL_STRUCT_FUNCTION (node->decl))
13239 {
13240 gimple_stmt_iterator gsi;
13241
13242 gsi = gsi_start_bb (bb);
13243 while (!gsi_end_p (gsi))
13244 {
13245 gimple stmt = gsi_stmt (gsi);
13246 info.stmt = stmt;
13247 struct walk_stmt_info wi;
13248
13249 memset (&wi, 0, sizeof (wi));
13250 info.modified = false;
13251 wi.info = &info;
13252 walk_gimple_op (stmt, ipa_simd_modify_stmt_ops, &wi);
13253
1a91d914 13254 if (greturn *return_stmt = dyn_cast <greturn *> (stmt))
d09768a4 13255 {
1a91d914 13256 tree retval = gimple_return_retval (return_stmt);
d09768a4 13257 if (!retval)
13258 {
13259 gsi_remove (&gsi, true);
13260 continue;
13261 }
13262
13263 /* Replace `return foo' with `retval_array[iter] = foo'. */
13264 tree ref = build4 (ARRAY_REF, TREE_TYPE (retval),
13265 retval_array, iter, NULL, NULL);
13266 stmt = gimple_build_assign (ref, retval);
13267 gsi_replace (&gsi, stmt, true);
13268 info.modified = true;
13269 }
13270
13271 if (info.modified)
13272 {
13273 update_stmt (stmt);
13274 if (maybe_clean_eh_stmt (stmt))
13275 gimple_purge_dead_eh_edges (gimple_bb (stmt));
13276 }
13277 gsi_next (&gsi);
13278 }
13279 }
13280}
13281
13282/* Adjust the argument types in NODE to their appropriate vector
13283 counterparts. */
13284
13285static void
13286simd_clone_adjust (struct cgraph_node *node)
13287{
13288 push_cfun (DECL_STRUCT_FUNCTION (node->decl));
13289
13290 targetm.simd_clone.adjust (node);
13291
13292 tree retval = simd_clone_adjust_return_type (node);
13293 ipa_parm_adjustment_vec adjustments
13294 = simd_clone_adjust_argument_types (node);
13295
13296 push_gimplify_context ();
13297
13298 gimple_seq seq = simd_clone_init_simd_arrays (node, adjustments);
13299
13300 /* Adjust all uses of vector arguments accordingly. Adjust all
13301 return values accordingly. */
13302 tree iter = create_tmp_var (unsigned_type_node, "iter");
f9e245b2 13303 tree iter1 = make_ssa_name (iter);
13304 tree iter2 = make_ssa_name (iter);
d09768a4 13305 ipa_simd_modify_function_body (node, adjustments, retval, iter1);
13306
13307 /* Initialize the iteration variable. */
13308 basic_block entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
13309 basic_block body_bb = split_block_after_labels (entry_bb)->dest;
13310 gimple_stmt_iterator gsi = gsi_after_labels (entry_bb);
13311 /* Insert the SIMD array and iv initialization at function
13312 entry. */
13313 gsi_insert_seq_before (&gsi, seq, GSI_NEW_STMT);
13314
13315 pop_gimplify_context (NULL);
13316
13317 /* Create a new BB right before the original exit BB, to hold the
13318 iteration increment and the condition/branch. */
13319 basic_block orig_exit = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), 0)->src;
13320 basic_block incr_bb = create_empty_bb (orig_exit);
343ee723 13321 add_bb_to_loop (incr_bb, body_bb->loop_father);
d09768a4 13322 /* The succ of orig_exit was EXIT_BLOCK_PTR_FOR_FN (cfun), with an empty
13323 flag. Set it now to be a FALLTHRU_EDGE. */
13324 gcc_assert (EDGE_COUNT (orig_exit->succs) == 1);
13325 EDGE_SUCC (orig_exit, 0)->flags |= EDGE_FALLTHRU;
13326 for (unsigned i = 0;
13327 i < EDGE_COUNT (EXIT_BLOCK_PTR_FOR_FN (cfun)->preds); ++i)
13328 {
13329 edge e = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), i);
13330 redirect_edge_succ (e, incr_bb);
13331 }
13332 edge e = make_edge (incr_bb, EXIT_BLOCK_PTR_FOR_FN (cfun), 0);
13333 e->probability = REG_BR_PROB_BASE;
13334 gsi = gsi_last_bb (incr_bb);
e9cf809e 13335 gimple g = gimple_build_assign (iter2, PLUS_EXPR, iter1,
13336 build_int_cst (unsigned_type_node, 1));
d09768a4 13337 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13338
13339 /* Mostly annotate the loop for the vectorizer (the rest is done below). */
13340 struct loop *loop = alloc_loop ();
4c73695b 13341 cfun->has_force_vectorize_loops = true;
d09768a4 13342 loop->safelen = node->simdclone->simdlen;
4c73695b 13343 loop->force_vectorize = true;
d09768a4 13344 loop->header = body_bb;
d09768a4 13345
13346 /* Branch around the body if the mask applies. */
13347 if (node->simdclone->inbranch)
13348 {
13349 gimple_stmt_iterator gsi = gsi_last_bb (loop->header);
13350 tree mask_array
13351 = node->simdclone->args[node->simdclone->nargs - 1].simd_array;
f9e245b2 13352 tree mask = make_ssa_name (TREE_TYPE (TREE_TYPE (mask_array)));
d09768a4 13353 tree aref = build4 (ARRAY_REF,
13354 TREE_TYPE (TREE_TYPE (mask_array)),
13355 mask_array, iter1,
13356 NULL, NULL);
13357 g = gimple_build_assign (mask, aref);
13358 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13359 int bitsize = GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (aref)));
13360 if (!INTEGRAL_TYPE_P (TREE_TYPE (aref)))
13361 {
13362 aref = build1 (VIEW_CONVERT_EXPR,
13363 build_nonstandard_integer_type (bitsize, 0), mask);
f9e245b2 13364 mask = make_ssa_name (TREE_TYPE (aref));
d09768a4 13365 g = gimple_build_assign (mask, aref);
13366 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13367 }
13368
13369 g = gimple_build_cond (EQ_EXPR, mask, build_zero_cst (TREE_TYPE (mask)),
13370 NULL, NULL);
13371 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13372 make_edge (loop->header, incr_bb, EDGE_TRUE_VALUE);
13373 FALLTHRU_EDGE (loop->header)->flags = EDGE_FALSE_VALUE;
13374 }
13375
13376 /* Generate the condition. */
13377 g = gimple_build_cond (LT_EXPR,
13378 iter2,
13379 build_int_cst (unsigned_type_node,
13380 node->simdclone->simdlen),
13381 NULL, NULL);
13382 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13383 e = split_block (incr_bb, gsi_stmt (gsi));
13384 basic_block latch_bb = e->dest;
343ee723 13385 basic_block new_exit_bb;
4302d619 13386 new_exit_bb = split_block_after_labels (latch_bb)->dest;
d09768a4 13387 loop->latch = latch_bb;
13388
13389 redirect_edge_succ (FALLTHRU_EDGE (latch_bb), body_bb);
13390
13391 make_edge (incr_bb, new_exit_bb, EDGE_FALSE_VALUE);
13392 /* The successor of incr_bb is already pointing to latch_bb; just
13393 change the flags.
13394 make_edge (incr_bb, latch_bb, EDGE_TRUE_VALUE); */
13395 FALLTHRU_EDGE (incr_bb)->flags = EDGE_TRUE_VALUE;
13396
1a91d914 13397 gphi *phi = create_phi_node (iter1, body_bb);
d09768a4 13398 edge preheader_edge = find_edge (entry_bb, body_bb);
13399 edge latch_edge = single_succ_edge (latch_bb);
13400 add_phi_arg (phi, build_zero_cst (unsigned_type_node), preheader_edge,
13401 UNKNOWN_LOCATION);
13402 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
13403
13404 /* Generate the new return. */
13405 gsi = gsi_last_bb (new_exit_bb);
13406 if (retval
13407 && TREE_CODE (retval) == VIEW_CONVERT_EXPR
13408 && TREE_CODE (TREE_OPERAND (retval, 0)) == RESULT_DECL)
13409 retval = TREE_OPERAND (retval, 0);
13410 else if (retval)
13411 {
13412 retval = build1 (VIEW_CONVERT_EXPR,
13413 TREE_TYPE (TREE_TYPE (node->decl)),
13414 retval);
13415 retval = force_gimple_operand_gsi (&gsi, retval, true, NULL,
13416 false, GSI_CONTINUE_LINKING);
13417 }
13418 g = gimple_build_return (retval);
13419 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13420
13421 /* Handle aligned clauses by replacing default defs of the aligned
13422 uniform args with __builtin_assume_aligned (arg_N(D), alignment)
13423 lhs. Handle linear by adding PHIs. */
13424 for (unsigned i = 0; i < node->simdclone->nargs; i++)
13425 if (node->simdclone->args[i].alignment
13426 && node->simdclone->args[i].arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM
13427 && (node->simdclone->args[i].alignment
13428 & (node->simdclone->args[i].alignment - 1)) == 0
13429 && TREE_CODE (TREE_TYPE (node->simdclone->args[i].orig_arg))
13430 == POINTER_TYPE)
13431 {
13432 unsigned int alignment = node->simdclone->args[i].alignment;
13433 tree orig_arg = node->simdclone->args[i].orig_arg;
13434 tree def = ssa_default_def (cfun, orig_arg);
6db33a3d 13435 if (def && !has_zero_uses (def))
d09768a4 13436 {
13437 tree fn = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
13438 gimple_seq seq = NULL;
13439 bool need_cvt = false;
1a91d914 13440 gcall *call
d09768a4 13441 = gimple_build_call (fn, 2, def, size_int (alignment));
13442 g = call;
13443 if (!useless_type_conversion_p (TREE_TYPE (orig_arg),
13444 ptr_type_node))
13445 need_cvt = true;
f9e245b2 13446 tree t = make_ssa_name (need_cvt ? ptr_type_node : orig_arg);
d09768a4 13447 gimple_call_set_lhs (g, t);
13448 gimple_seq_add_stmt_without_update (&seq, g);
13449 if (need_cvt)
13450 {
f9e245b2 13451 t = make_ssa_name (orig_arg);
e9cf809e 13452 g = gimple_build_assign (t, NOP_EXPR, gimple_call_lhs (g));
d09768a4 13453 gimple_seq_add_stmt_without_update (&seq, g);
13454 }
13455 gsi_insert_seq_on_edge_immediate
13456 (single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun)), seq);
13457
13458 entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
13459 int freq = compute_call_stmt_bb_frequency (current_function_decl,
13460 entry_bb);
415d1b9a 13461 node->create_edge (cgraph_node::get_create (fn),
13462 call, entry_bb->count, freq);
d09768a4 13463
13464 imm_use_iterator iter;
13465 use_operand_p use_p;
13466 gimple use_stmt;
13467 tree repl = gimple_get_lhs (g);
13468 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
13469 if (is_gimple_debug (use_stmt) || use_stmt == call)
13470 continue;
13471 else
13472 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
13473 SET_USE (use_p, repl);
13474 }
13475 }
13476 else if (node->simdclone->args[i].arg_type
13477 == SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP)
13478 {
13479 tree orig_arg = node->simdclone->args[i].orig_arg;
13480 tree def = ssa_default_def (cfun, orig_arg);
13481 gcc_assert (INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
13482 || POINTER_TYPE_P (TREE_TYPE (orig_arg)));
6db33a3d 13483 if (def && !has_zero_uses (def))
d09768a4 13484 {
f9e245b2 13485 iter1 = make_ssa_name (orig_arg);
13486 iter2 = make_ssa_name (orig_arg);
d09768a4 13487 phi = create_phi_node (iter1, body_bb);
13488 add_phi_arg (phi, def, preheader_edge, UNKNOWN_LOCATION);
13489 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
13490 enum tree_code code = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
13491 ? PLUS_EXPR : POINTER_PLUS_EXPR;
13492 tree addtype = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
13493 ? TREE_TYPE (orig_arg) : sizetype;
13494 tree addcst
13495 = build_int_cst (addtype, node->simdclone->args[i].linear_step);
e9cf809e 13496 g = gimple_build_assign (iter2, code, iter1, addcst);
d09768a4 13497 gsi = gsi_last_bb (incr_bb);
13498 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
13499
13500 imm_use_iterator iter;
13501 use_operand_p use_p;
13502 gimple use_stmt;
13503 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
13504 if (use_stmt == phi)
13505 continue;
13506 else
13507 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
13508 SET_USE (use_p, iter1);
13509 }
13510 }
13511
13512 calculate_dominance_info (CDI_DOMINATORS);
13513 add_loop (loop, loop->header->loop_father);
13514 update_ssa (TODO_update_ssa);
13515
13516 pop_cfun ();
13517}
13518
13519/* If the function in NODE is tagged as an elemental SIMD function,
13520 create the appropriate SIMD clones. */
13521
13522static void
13523expand_simd_clones (struct cgraph_node *node)
13524{
d09768a4 13525 tree attr = lookup_attribute ("omp declare simd",
13526 DECL_ATTRIBUTES (node->decl));
ea0695f9 13527 if (attr == NULL_TREE
13528 || node->global.inlined_to
13529 || lookup_attribute ("noclone", DECL_ATTRIBUTES (node->decl)))
d09768a4 13530 return;
ea0695f9 13531
d09768a4 13532 /* Ignore
13533 #pragma omp declare simd
13534 extern int foo ();
13535 in C, there we don't know the argument types at all. */
13536 if (!node->definition
13537 && TYPE_ARG_TYPES (TREE_TYPE (node->decl)) == NULL_TREE)
13538 return;
13539
13540 do
13541 {
13542 /* Start with parsing the "omp declare simd" attribute(s). */
13543 bool inbranch_clause_specified;
13544 struct cgraph_simd_clone *clone_info
13545 = simd_clone_clauses_extract (node, TREE_VALUE (attr),
13546 &inbranch_clause_specified);
13547 if (clone_info == NULL)
13548 continue;
13549
13550 int orig_simdlen = clone_info->simdlen;
13551 tree base_type = simd_clone_compute_base_data_type (node, clone_info);
13552 /* The target can return 0 (no simd clones should be created),
13553 1 (just one ISA of simd clones should be created) or higher
13554 count of ISA variants. In that case, clone_info is initialized
13555 for the first ISA variant. */
13556 int count
13557 = targetm.simd_clone.compute_vecsize_and_simdlen (node, clone_info,
13558 base_type, 0);
13559 if (count == 0)
13560 continue;
13561
13562 /* Loop over all COUNT ISA variants, and if !INBRANCH_CLAUSE_SPECIFIED,
13563 also create one inbranch and one !inbranch clone of it. */
13564 for (int i = 0; i < count * 2; i++)
13565 {
13566 struct cgraph_simd_clone *clone = clone_info;
13567 if (inbranch_clause_specified && (i & 1) != 0)
13568 continue;
13569
13570 if (i != 0)
13571 {
13572 clone = simd_clone_struct_alloc (clone_info->nargs
d09768a4 13573 + ((i & 1) != 0));
13574 simd_clone_struct_copy (clone, clone_info);
13575 /* Undo changes targetm.simd_clone.compute_vecsize_and_simdlen
13576 and simd_clone_adjust_argument_types did to the first
13577 clone's info. */
13578 clone->nargs -= clone_info->inbranch;
13579 clone->simdlen = orig_simdlen;
13580 /* And call the target hook again to get the right ISA. */
13581 targetm.simd_clone.compute_vecsize_and_simdlen (node, clone,
13582 base_type,
13583 i / 2);
13584 if ((i & 1) != 0)
13585 clone->inbranch = 1;
13586 }
13587
13588 /* simd_clone_mangle might fail if such a clone has been created
13589 already. */
13590 tree id = simd_clone_mangle (node, clone);
13591 if (id == NULL_TREE)
13592 continue;
13593
13594 /* Only when we are sure we want to create the clone actually
13595 clone the function (or definitions) or create another
13596 extern FUNCTION_DECL (for prototypes without definitions). */
13597 struct cgraph_node *n = simd_clone_create (node);
13598 if (n == NULL)
13599 continue;
13600
13601 n->simdclone = clone;
13602 clone->origin = node;
13603 clone->next_clone = NULL;
13604 if (node->simd_clones == NULL)
13605 {
13606 clone->prev_clone = n;
13607 node->simd_clones = n;
13608 }
13609 else
13610 {
13611 clone->prev_clone = node->simd_clones->simdclone->prev_clone;
13612 clone->prev_clone->simdclone->next_clone = n;
13613 node->simd_clones->simdclone->prev_clone = n;
13614 }
35ee1c66 13615 symtab->change_decl_assembler_name (n->decl, id);
d09768a4 13616 /* And finally adjust the return type, parameters and for
13617 definitions also function body. */
13618 if (node->definition)
13619 simd_clone_adjust (n);
13620 else
13621 {
13622 simd_clone_adjust_return_type (n);
13623 simd_clone_adjust_argument_types (n);
13624 }
13625 }
13626 }
13627 while ((attr = lookup_attribute ("omp declare simd", TREE_CHAIN (attr))));
13628}
13629
13630/* Entry point for IPA simd clone creation pass. */
13631
13632static unsigned int
13633ipa_omp_simd_clone (void)
13634{
13635 struct cgraph_node *node;
13636 FOR_EACH_FUNCTION (node)
13637 expand_simd_clones (node);
13638 return 0;
13639}
13640
13641namespace {
13642
13643const pass_data pass_data_omp_simd_clone =
13644{
13645 SIMPLE_IPA_PASS, /* type */
13646 "simdclone", /* name */
13647 OPTGROUP_NONE, /* optinfo_flags */
d09768a4 13648 TV_NONE, /* tv_id */
13649 ( PROP_ssa | PROP_cfg ), /* properties_required */
13650 0, /* properties_provided */
13651 0, /* properties_destroyed */
13652 0, /* todo_flags_start */
13653 0, /* todo_flags_finish */
13654};
13655
13656class pass_omp_simd_clone : public simple_ipa_opt_pass
13657{
13658public:
13659 pass_omp_simd_clone(gcc::context *ctxt)
13660 : simple_ipa_opt_pass(pass_data_omp_simd_clone, ctxt)
13661 {}
13662
13663 /* opt_pass methods: */
31315c24 13664 virtual bool gate (function *);
65b0537f 13665 virtual unsigned int execute (function *) { return ipa_omp_simd_clone (); }
d09768a4 13666};
13667
31315c24 13668bool
13669pass_omp_simd_clone::gate (function *)
13670{
13671 return ((flag_openmp || flag_openmp_simd
13672 || flag_cilkplus
13673 || (in_lto_p && !flag_wpa))
13674 && (targetm.simd_clone.compute_vecsize_and_simdlen != NULL));
13675}
13676
d09768a4 13677} // anon namespace
13678
13679simple_ipa_opt_pass *
13680make_pass_omp_simd_clone (gcc::context *ctxt)
13681{
13682 return new pass_omp_simd_clone (ctxt);
13683}
cbe8bda8 13684
dccabdd1 13685/* Helper function for omp_finish_file routine. Takes decls from V_DECLS and
13686 adds their addresses and sizes to constructor-vector V_CTOR. */
13687static void
13688add_decls_addresses_to_decl_constructor (vec<tree, va_gc> *v_decls,
13689 vec<constructor_elt, va_gc> *v_ctor)
13690{
13691 unsigned len = vec_safe_length (v_decls);
13692 for (unsigned i = 0; i < len; i++)
13693 {
13694 tree it = (*v_decls)[i];
13695 bool is_function = TREE_CODE (it) != VAR_DECL;
13696
13697 CONSTRUCTOR_APPEND_ELT (v_ctor, NULL_TREE, build_fold_addr_expr (it));
13698 if (!is_function)
13699 CONSTRUCTOR_APPEND_ELT (v_ctor, NULL_TREE,
13700 fold_convert (const_ptr_type_node,
13701 DECL_SIZE_UNIT (it)));
13702 }
13703}
13704
13705/* Create new symbols containing (address, size) pairs for global variables,
13706 marked with "omp declare target" attribute, as well as addresses for the
ca4c3545 13707 functions, which are outlined offloading regions. */
dccabdd1 13708void
13709omp_finish_file (void)
13710{
13711 unsigned num_funcs = vec_safe_length (offload_funcs);
13712 unsigned num_vars = vec_safe_length (offload_vars);
13713
13714 if (num_funcs == 0 && num_vars == 0)
13715 return;
13716
13717 if (targetm_common.have_named_sections)
13718 {
13719 vec<constructor_elt, va_gc> *v_f, *v_v;
13720 vec_alloc (v_f, num_funcs);
13721 vec_alloc (v_v, num_vars * 2);
13722
13723 add_decls_addresses_to_decl_constructor (offload_funcs, v_f);
13724 add_decls_addresses_to_decl_constructor (offload_vars, v_v);
13725
13726 tree vars_decl_type = build_array_type_nelts (pointer_sized_int_node,
13727 num_vars * 2);
13728 tree funcs_decl_type = build_array_type_nelts (pointer_sized_int_node,
13729 num_funcs);
13730 TYPE_ALIGN (vars_decl_type) = TYPE_ALIGN (pointer_sized_int_node);
13731 TYPE_ALIGN (funcs_decl_type) = TYPE_ALIGN (pointer_sized_int_node);
13732 tree ctor_v = build_constructor (vars_decl_type, v_v);
13733 tree ctor_f = build_constructor (funcs_decl_type, v_f);
13734 TREE_CONSTANT (ctor_v) = TREE_CONSTANT (ctor_f) = 1;
13735 TREE_STATIC (ctor_v) = TREE_STATIC (ctor_f) = 1;
13736 tree funcs_decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
13737 get_identifier (".offload_func_table"),
13738 funcs_decl_type);
13739 tree vars_decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
13740 get_identifier (".offload_var_table"),
13741 vars_decl_type);
13742 TREE_STATIC (funcs_decl) = TREE_STATIC (vars_decl) = 1;
13743 /* Do not align tables more than TYPE_ALIGN (pointer_sized_int_node),
13744 otherwise a joint table in a binary will contain padding between
13745 tables from multiple object files. */
13746 DECL_USER_ALIGN (funcs_decl) = DECL_USER_ALIGN (vars_decl) = 1;
13747 DECL_ALIGN (funcs_decl) = TYPE_ALIGN (funcs_decl_type);
13748 DECL_ALIGN (vars_decl) = TYPE_ALIGN (vars_decl_type);
13749 DECL_INITIAL (funcs_decl) = ctor_f;
13750 DECL_INITIAL (vars_decl) = ctor_v;
13751 set_decl_section_name (funcs_decl, OFFLOAD_FUNC_TABLE_SECTION_NAME);
13752 set_decl_section_name (vars_decl, OFFLOAD_VAR_TABLE_SECTION_NAME);
13753
13754 varpool_node::finalize_decl (vars_decl);
13755 varpool_node::finalize_decl (funcs_decl);
7114ebdd 13756 }
dccabdd1 13757 else
13758 {
13759 for (unsigned i = 0; i < num_funcs; i++)
13760 {
13761 tree it = (*offload_funcs)[i];
13762 targetm.record_offload_symbol (it);
13763 }
13764 for (unsigned i = 0; i < num_vars; i++)
13765 {
13766 tree it = (*offload_vars)[i];
13767 targetm.record_offload_symbol (it);
13768 }
13769 }
13770}
13771
1e8e9920 13772#include "gt-omp-low.h"