]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/omp-low.c
[PR c/71381] C/C++ OpenACC cache directive rejects valid syntax
[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
f1717362 7 Copyright (C) 2005-2016 Free Software Foundation, Inc.
1e8e9920 8
9This file is part of GCC.
10
11GCC is free software; you can redistribute it and/or modify it under
12the terms of the GNU General Public License as published by the Free
8c4c00c1 13Software Foundation; either version 3, or (at your option) any later
1e8e9920 14version.
15
16GCC is distributed in the hope that it will be useful, but WITHOUT ANY
17WARRANTY; without even the implied warranty of MERCHANTABILITY or
18FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19for more details.
20
21You should have received a copy of the GNU General Public License
8c4c00c1 22along with GCC; see the file COPYING3. If not see
23<http://www.gnu.org/licenses/>. */
1e8e9920 24
25#include "config.h"
26#include "system.h"
27#include "coretypes.h"
9ef16211 28#include "backend.h"
7c29e30e 29#include "target.h"
30#include "rtl.h"
1e8e9920 31#include "tree.h"
9ef16211 32#include "gimple.h"
7c29e30e 33#include "cfghooks.h"
34#include "alloc-pool.h"
35#include "tree-pass.h"
9ef16211 36#include "ssa.h"
7c29e30e 37#include "expmed.h"
38#include "optabs.h"
39#include "emit-rtl.h"
40#include "cgraph.h"
41#include "pretty-print.h"
42#include "diagnostic-core.h"
9ef16211 43#include "alias.h"
b20a8bb4 44#include "fold-const.h"
9ed99284 45#include "stor-layout.h"
94ea8568 46#include "cfganal.h"
bc61cadb 47#include "internal-fn.h"
48#include "gimple-fold.h"
a8783bee 49#include "gimplify.h"
dcf1a1ec 50#include "gimple-iterator.h"
e795d6e1 51#include "gimplify-me.h"
dcf1a1ec 52#include "gimple-walk.h"
75a70cf9 53#include "tree-iterator.h"
1e8e9920 54#include "tree-inline.h"
55#include "langhooks.h"
073c1fd5 56#include "tree-cfg.h"
073c1fd5 57#include "tree-into-ssa.h"
d53441c8 58#include "flags.h"
d53441c8 59#include "dojump.h"
60#include "explow.h"
61#include "calls.h"
d53441c8 62#include "varasm.h"
63#include "stmt.h"
9ed99284 64#include "expr.h"
073c1fd5 65#include "tree-dfa.h"
69ee5dbb 66#include "tree-ssa.h"
1e8e9920 67#include "except.h"
e3022db7 68#include "splay-tree.h"
cb7f680b 69#include "cfgloop.h"
dccabdd1 70#include "common/common-target.h"
7740abd8 71#include "omp-low.h"
424a4a92 72#include "gimple-low.h"
73#include "tree-cfgcleanup.h"
2cc80ac3 74#include "symbol-summary.h"
d09768a4 75#include "ipa-prop.h"
e797f49f 76#include "tree-nested.h"
d09768a4 77#include "tree-eh.h"
40750995 78#include "cilk.h"
b0c5e347 79#include "context.h"
dccabdd1 80#include "lto-section-names.h"
ca4c3545 81#include "gomp-constants.h"
cbba99a0 82#include "gimple-pretty-print.h"
56686608 83#include "symbol-summary.h"
84#include "hsa.h"
85#include "params.h"
1e8e9920 86
ca4c3545 87/* Lowering of OMP parallel and workshare constructs proceeds in two
1e8e9920 88 phases. The first phase scans the function looking for OMP statements
89 and then for variables that must be replaced to satisfy data sharing
90 clauses. The second phase expands code for the constructs, as well as
334ec2d8 91 re-gimplifying things when variables have been replaced with complex
1e8e9920 92 expressions.
93
d134bccc 94 Final code generation is done by pass_expand_omp. The flowgraph is
ca4c3545 95 scanned for regions which are then moved to a new
96 function, to be invoked by the thread library, or offloaded. */
1e8e9920 97
ca4c3545 98/* OMP region information. Every parallel and workshare
7740abd8 99 directive is enclosed between two markers, the OMP_* directive
43895be5 100 and a corresponding GIMPLE_OMP_RETURN statement. */
7740abd8 101
102struct omp_region
103{
104 /* The enclosing region. */
105 struct omp_region *outer;
106
107 /* First child region. */
108 struct omp_region *inner;
109
110 /* Next peer region. */
111 struct omp_region *next;
112
113 /* Block containing the omp directive as its last stmt. */
114 basic_block entry;
115
43895be5 116 /* Block containing the GIMPLE_OMP_RETURN as its last stmt. */
7740abd8 117 basic_block exit;
118
43895be5 119 /* Block containing the GIMPLE_OMP_CONTINUE as its last stmt. */
7740abd8 120 basic_block cont;
121
122 /* If this is a combined parallel+workshare region, this is a list
123 of additional arguments needed by the combined parallel+workshare
124 library call. */
125 vec<tree, va_gc> *ws_args;
126
127 /* The code for the omp directive of this region. */
128 enum gimple_code type;
129
43895be5 130 /* Schedule kind, only used for GIMPLE_OMP_FOR type regions. */
7740abd8 131 enum omp_clause_schedule_kind sched_kind;
132
9561765e 133 /* Schedule modifiers. */
134 unsigned char sched_modifiers;
135
7740abd8 136 /* True if this is a combined parallel+workshare region. */
137 bool is_combined_parallel;
43895be5 138
139 /* The ordered stmt if type is GIMPLE_OMP_ORDERED and it has
140 a depend clause. */
141 gomp_ordered *ord_stmt;
7740abd8 142};
143
1e8e9920 144/* Context structure. Used to store information about each parallel
145 directive in the code. */
146
6dc50383 147struct omp_context
1e8e9920 148{
149 /* This field must be at the beginning, as we do "inheritance": Some
150 callback functions for tree-inline.c (e.g., omp_copy_decl)
151 receive a copy_body_data pointer that is up-casted to an
152 omp_context pointer. */
153 copy_body_data cb;
154
155 /* The tree of contexts corresponding to the encountered constructs. */
156 struct omp_context *outer;
42acab1c 157 gimple *stmt;
1e8e9920 158
48e1416a 159 /* Map variables to fields in a structure that allows communication
1e8e9920 160 between sending and receiving threads. */
161 splay_tree field_map;
162 tree record_type;
163 tree sender_decl;
164 tree receiver_decl;
165
fd6481cf 166 /* These are used just by task contexts, if task firstprivate fn is
167 needed. srecord_type is used to communicate from the thread
168 that encountered the task construct to task firstprivate fn,
169 record_type is allocated by GOMP_task, initialized by task firstprivate
170 fn and passed to the task body fn. */
171 splay_tree sfield_map;
172 tree srecord_type;
173
1e8e9920 174 /* A chain of variables to add to the top-level block surrounding the
175 construct. In the case of a parallel, this is in the child function. */
176 tree block_vars;
177
bc7bff74 178 /* Label to which GOMP_cancel{,llation_point} and explicit and implicit
179 barriers should jump to during omplower pass. */
180 tree cancel_label;
181
1e8e9920 182 /* What to do with variables with implicitly determined sharing
183 attributes. */
184 enum omp_clause_default_kind default_kind;
185
186 /* Nesting depth of this context. Used to beautify error messages re
187 invalid gotos. The outermost ctx is depth 1, with depth 0 being
188 reserved for the main body of the function. */
189 int depth;
190
1e8e9920 191 /* True if this parallel directive is nested within another. */
192 bool is_nested;
bc7bff74 193
194 /* True if this construct can be cancelled. */
195 bool cancellable;
6dc50383 196};
1e8e9920 197
ca4c3545 198/* A structure holding the elements of:
199 for (V = N1; V cond N2; V += STEP) [...] */
1e8e9920 200
fd6481cf 201struct omp_for_data_loop
202{
203 tree v, n1, n2, step;
204 enum tree_code cond_code;
205};
206
773c5ba7 207/* A structure describing the main elements of a parallel loop. */
1e8e9920 208
773c5ba7 209struct omp_for_data
1e8e9920 210{
fd6481cf 211 struct omp_for_data_loop loop;
75a70cf9 212 tree chunk_size;
1a91d914 213 gomp_for *for_stmt;
fd6481cf 214 tree pre, iter_type;
215 int collapse;
43895be5 216 int ordered;
217 bool have_nowait, have_ordered, simd_schedule;
9561765e 218 unsigned char sched_modifiers;
1e8e9920 219 enum omp_clause_schedule_kind sched_kind;
fd6481cf 220 struct omp_for_data_loop *loops;
1e8e9920 221};
222
cbba99a0 223/* Describe the OpenACC looping structure of a function. The entire
224 function is held in a 'NULL' loop. */
225
226struct oacc_loop
227{
228 oacc_loop *parent; /* Containing loop. */
229
230 oacc_loop *child; /* First inner loop. */
231
232 oacc_loop *sibling; /* Next loop within same parent. */
233
234 location_t loc; /* Location of the loop start. */
235
236 gcall *marker; /* Initial head marker. */
237
238 gcall *heads[GOMP_DIM_MAX]; /* Head marker functions. */
239 gcall *tails[GOMP_DIM_MAX]; /* Tail marker functions. */
240
241 tree routine; /* Pseudo-loop enclosing a routine. */
242
243 unsigned mask; /* Partitioning mask. */
28e869d0 244 unsigned inner; /* Partitioning of inner loops. */
584fba4b 245 unsigned flags; /* Partitioning flags. */
246 unsigned ifns; /* Contained loop abstraction functions. */
247 tree chunk_size; /* Chunk size. */
cbba99a0 248 gcall *head_end; /* Final marker of head sequence. */
249};
250
251/* Flags for an OpenACC loop. */
252
253enum oacc_loop_flags {
254 OLF_SEQ = 1u << 0, /* Explicitly sequential */
255 OLF_AUTO = 1u << 1, /* Compiler chooses axes. */
256 OLF_INDEPENDENT = 1u << 2, /* Iterations are known independent. */
257 OLF_GANG_STATIC = 1u << 3, /* Gang partitioning is static (has op). */
258
259 /* Explicitly specified loop axes. */
260 OLF_DIM_BASE = 4,
261 OLF_DIM_GANG = 1u << (OLF_DIM_BASE + GOMP_DIM_GANG),
262 OLF_DIM_WORKER = 1u << (OLF_DIM_BASE + GOMP_DIM_WORKER),
263 OLF_DIM_VECTOR = 1u << (OLF_DIM_BASE + GOMP_DIM_VECTOR),
264
265 OLF_MAX = OLF_DIM_BASE + GOMP_DIM_MAX
266};
267
773c5ba7 268
1e8e9920 269static splay_tree all_contexts;
fd6481cf 270static int taskreg_nesting_level;
bc7bff74 271static int target_nesting_level;
7740abd8 272static struct omp_region *root_omp_region;
fd6481cf 273static bitmap task_shared_vars;
37eaded9 274static vec<omp_context *> taskreg_contexts;
9561765e 275static bool omp_any_child_fn_dumped;
1e8e9920 276
ab129075 277static void scan_omp (gimple_seq *, omp_context *);
75a70cf9 278static tree scan_omp_1_op (tree *, int *, void *);
2131a1a9 279static gphi *find_phi_with_arg_on_edge (tree, edge);
75a70cf9 280
281#define WALK_SUBSTMTS \
282 case GIMPLE_BIND: \
283 case GIMPLE_TRY: \
284 case GIMPLE_CATCH: \
285 case GIMPLE_EH_FILTER: \
4c0315d0 286 case GIMPLE_TRANSACTION: \
75a70cf9 287 /* The sub-statements for these should be walked. */ \
288 *handled_ops_p = false; \
289 break;
290
a8e785ba 291/* Return true if CTX corresponds to an oacc parallel region. */
292
293static bool
294is_oacc_parallel (omp_context *ctx)
295{
296 enum gimple_code outer_type = gimple_code (ctx->stmt);
297 return ((outer_type == GIMPLE_OMP_TARGET)
298 && (gimple_omp_target_kind (ctx->stmt)
299 == GF_OMP_TARGET_KIND_OACC_PARALLEL));
300}
301
302/* Return true if CTX corresponds to an oacc kernels region. */
303
304static bool
305is_oacc_kernels (omp_context *ctx)
306{
307 enum gimple_code outer_type = gimple_code (ctx->stmt);
308 return ((outer_type == GIMPLE_OMP_TARGET)
309 && (gimple_omp_target_kind (ctx->stmt)
310 == GF_OMP_TARGET_KIND_OACC_KERNELS));
311}
312
43895be5 313/* If DECL is the artificial dummy VAR_DECL created for non-static
314 data member privatization, return the underlying "this" parameter,
315 otherwise return NULL. */
316
317tree
318omp_member_access_dummy_var (tree decl)
319{
320 if (!VAR_P (decl)
321 || !DECL_ARTIFICIAL (decl)
322 || !DECL_IGNORED_P (decl)
323 || !DECL_HAS_VALUE_EXPR_P (decl)
324 || !lang_hooks.decls.omp_disregard_value_expr (decl, false))
325 return NULL_TREE;
326
327 tree v = DECL_VALUE_EXPR (decl);
328 if (TREE_CODE (v) != COMPONENT_REF)
329 return NULL_TREE;
330
331 while (1)
332 switch (TREE_CODE (v))
333 {
334 case COMPONENT_REF:
335 case MEM_REF:
336 case INDIRECT_REF:
337 CASE_CONVERT:
338 case POINTER_PLUS_EXPR:
339 v = TREE_OPERAND (v, 0);
340 continue;
341 case PARM_DECL:
342 if (DECL_CONTEXT (v) == current_function_decl
343 && DECL_ARTIFICIAL (v)
344 && TREE_CODE (TREE_TYPE (v)) == POINTER_TYPE)
345 return v;
346 return NULL_TREE;
347 default:
348 return NULL_TREE;
349 }
350}
351
352/* Helper for unshare_and_remap, called through walk_tree. */
353
354static tree
355unshare_and_remap_1 (tree *tp, int *walk_subtrees, void *data)
356{
357 tree *pair = (tree *) data;
358 if (*tp == pair[0])
359 {
360 *tp = unshare_expr (pair[1]);
361 *walk_subtrees = 0;
362 }
363 else if (IS_TYPE_OR_DECL_P (*tp))
364 *walk_subtrees = 0;
365 return NULL_TREE;
366}
367
368/* Return unshare_expr (X) with all occurrences of FROM
369 replaced with TO. */
370
371static tree
372unshare_and_remap (tree x, tree from, tree to)
373{
374 tree pair[2] = { from, to };
375 x = unshare_expr (x);
376 walk_tree (&x, unshare_and_remap_1, pair, NULL);
377 return x;
378}
379
dccabdd1 380/* Holds offload tables with decls. */
381vec<tree, va_gc> *offload_funcs, *offload_vars;
382
75a70cf9 383/* Convenience function for calling scan_omp_1_op on tree operands. */
384
385static inline tree
386scan_omp_op (tree *tp, omp_context *ctx)
387{
388 struct walk_stmt_info wi;
389
390 memset (&wi, 0, sizeof (wi));
391 wi.info = ctx;
392 wi.want_locations = true;
393
394 return walk_tree (tp, scan_omp_1_op, &wi, NULL);
395}
396
e3a19533 397static void lower_omp (gimple_seq *, omp_context *);
f49d7bb5 398static tree lookup_decl_in_outer_ctx (tree, omp_context *);
399static tree maybe_lookup_decl_in_outer_ctx (tree, omp_context *);
1e8e9920 400
ca4c3545 401/* Find an OMP clause of type KIND within CLAUSES. */
1e8e9920 402
79acaae1 403tree
590c3166 404find_omp_clause (tree clauses, enum omp_clause_code kind)
1e8e9920 405{
406 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
55d6e7cd 407 if (OMP_CLAUSE_CODE (clauses) == kind)
1e8e9920 408 return clauses;
409
410 return NULL_TREE;
411}
412
413/* Return true if CTX is for an omp parallel. */
414
415static inline bool
416is_parallel_ctx (omp_context *ctx)
417{
75a70cf9 418 return gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL;
1e8e9920 419}
420
773c5ba7 421
fd6481cf 422/* Return true if CTX is for an omp task. */
423
424static inline bool
425is_task_ctx (omp_context *ctx)
426{
75a70cf9 427 return gimple_code (ctx->stmt) == GIMPLE_OMP_TASK;
fd6481cf 428}
429
430
43895be5 431/* Return true if CTX is for an omp taskloop. */
432
433static inline bool
434is_taskloop_ctx (omp_context *ctx)
435{
436 return gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
437 && gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_TASKLOOP;
438}
439
440
fd6481cf 441/* Return true if CTX is for an omp parallel or omp task. */
442
443static inline bool
444is_taskreg_ctx (omp_context *ctx)
445{
43895be5 446 return is_parallel_ctx (ctx) || is_task_ctx (ctx);
fd6481cf 447}
448
449
773c5ba7 450/* Return true if REGION is a combined parallel+workshare region. */
1e8e9920 451
452static inline bool
773c5ba7 453is_combined_parallel (struct omp_region *region)
454{
455 return region->is_combined_parallel;
456}
457
56686608 458/* Adjust *COND_CODE and *N2 so that the former is either LT_EXPR or
459 GT_EXPR. */
460
461static void
462adjust_for_condition (location_t loc, enum tree_code *cond_code, tree *n2)
463{
464 switch (*cond_code)
465 {
466 case LT_EXPR:
467 case GT_EXPR:
468 case NE_EXPR:
469 break;
470 case LE_EXPR:
471 if (POINTER_TYPE_P (TREE_TYPE (*n2)))
472 *n2 = fold_build_pointer_plus_hwi_loc (loc, *n2, 1);
473 else
474 *n2 = fold_build2_loc (loc, PLUS_EXPR, TREE_TYPE (*n2), *n2,
475 build_int_cst (TREE_TYPE (*n2), 1));
476 *cond_code = LT_EXPR;
477 break;
478 case GE_EXPR:
479 if (POINTER_TYPE_P (TREE_TYPE (*n2)))
480 *n2 = fold_build_pointer_plus_hwi_loc (loc, *n2, -1);
481 else
482 *n2 = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (*n2), *n2,
483 build_int_cst (TREE_TYPE (*n2), 1));
484 *cond_code = GT_EXPR;
485 break;
486 default:
487 gcc_unreachable ();
488 }
489}
490
491/* Return the looping step from INCR, extracted from the step of a gimple omp
492 for statement. */
493
494static tree
495get_omp_for_step_from_incr (location_t loc, tree incr)
496{
497 tree step;
498 switch (TREE_CODE (incr))
499 {
500 case PLUS_EXPR:
501 step = TREE_OPERAND (incr, 1);
502 break;
503 case POINTER_PLUS_EXPR:
504 step = fold_convert (ssizetype, TREE_OPERAND (incr, 1));
505 break;
506 case MINUS_EXPR:
507 step = TREE_OPERAND (incr, 1);
508 step = fold_build1_loc (loc, NEGATE_EXPR, TREE_TYPE (step), step);
509 break;
510 default:
511 gcc_unreachable ();
512 }
513 return step;
514}
773c5ba7 515
516/* Extract the header elements of parallel loop FOR_STMT and store
517 them into *FD. */
518
519static void
1a91d914 520extract_omp_for_data (gomp_for *for_stmt, struct omp_for_data *fd,
fd6481cf 521 struct omp_for_data_loop *loops)
773c5ba7 522{
fd6481cf 523 tree t, var, *collapse_iter, *collapse_count;
524 tree count = NULL_TREE, iter_type = long_integer_type_node;
525 struct omp_for_data_loop *loop;
526 int i;
527 struct omp_for_data_loop dummy_loop;
389dd41b 528 location_t loc = gimple_location (for_stmt);
10c55644 529 bool simd = gimple_omp_for_kind (for_stmt) & GF_OMP_FOR_SIMD;
bc7bff74 530 bool distribute = gimple_omp_for_kind (for_stmt)
531 == GF_OMP_FOR_KIND_DISTRIBUTE;
43895be5 532 bool taskloop = gimple_omp_for_kind (for_stmt)
533 == GF_OMP_FOR_KIND_TASKLOOP;
534 tree iterv, countv;
773c5ba7 535
536 fd->for_stmt = for_stmt;
537 fd->pre = NULL;
43895be5 538 if (gimple_omp_for_collapse (for_stmt) > 1)
fd6481cf 539 fd->loops = loops;
540 else
541 fd->loops = &fd->loop;
773c5ba7 542
bc7bff74 543 fd->have_nowait = distribute || simd;
544 fd->have_ordered = false;
43895be5 545 fd->collapse = 1;
546 fd->ordered = 0;
773c5ba7 547 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
9561765e 548 fd->sched_modifiers = 0;
773c5ba7 549 fd->chunk_size = NULL_TREE;
43895be5 550 fd->simd_schedule = false;
40750995 551 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_CILKFOR)
552 fd->sched_kind = OMP_CLAUSE_SCHEDULE_CILKFOR;
fd6481cf 553 collapse_iter = NULL;
554 collapse_count = NULL;
773c5ba7 555
75a70cf9 556 for (t = gimple_omp_for_clauses (for_stmt); t ; t = OMP_CLAUSE_CHAIN (t))
55d6e7cd 557 switch (OMP_CLAUSE_CODE (t))
773c5ba7 558 {
559 case OMP_CLAUSE_NOWAIT:
560 fd->have_nowait = true;
561 break;
562 case OMP_CLAUSE_ORDERED:
563 fd->have_ordered = true;
43895be5 564 if (OMP_CLAUSE_ORDERED_EXPR (t))
565 fd->ordered = tree_to_shwi (OMP_CLAUSE_ORDERED_EXPR (t));
773c5ba7 566 break;
567 case OMP_CLAUSE_SCHEDULE:
43895be5 568 gcc_assert (!distribute && !taskloop);
9561765e 569 fd->sched_kind
570 = (enum omp_clause_schedule_kind)
571 (OMP_CLAUSE_SCHEDULE_KIND (t) & OMP_CLAUSE_SCHEDULE_MASK);
572 fd->sched_modifiers = (OMP_CLAUSE_SCHEDULE_KIND (t)
573 & ~OMP_CLAUSE_SCHEDULE_MASK);
773c5ba7 574 fd->chunk_size = OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (t);
43895be5 575 fd->simd_schedule = OMP_CLAUSE_SCHEDULE_SIMD (t);
773c5ba7 576 break;
bc7bff74 577 case OMP_CLAUSE_DIST_SCHEDULE:
578 gcc_assert (distribute);
579 fd->chunk_size = OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (t);
580 break;
fd6481cf 581 case OMP_CLAUSE_COLLAPSE:
43895be5 582 fd->collapse = tree_to_shwi (OMP_CLAUSE_COLLAPSE_EXPR (t));
fd6481cf 583 if (fd->collapse > 1)
584 {
585 collapse_iter = &OMP_CLAUSE_COLLAPSE_ITERVAR (t);
586 collapse_count = &OMP_CLAUSE_COLLAPSE_COUNT (t);
587 }
757abb46 588 break;
773c5ba7 589 default:
590 break;
591 }
43895be5 592 if (fd->ordered && fd->collapse == 1 && loops != NULL)
593 {
594 fd->loops = loops;
595 iterv = NULL_TREE;
596 countv = NULL_TREE;
597 collapse_iter = &iterv;
598 collapse_count = &countv;
599 }
773c5ba7 600
fd6481cf 601 /* FIXME: for now map schedule(auto) to schedule(static).
602 There should be analysis to determine whether all iterations
603 are approximately the same amount of work (then schedule(static)
bde357c8 604 is best) or if it varies (then schedule(dynamic,N) is better). */
fd6481cf 605 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_AUTO)
606 {
607 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
608 gcc_assert (fd->chunk_size == NULL);
609 }
610 gcc_assert (fd->collapse == 1 || collapse_iter != NULL);
43895be5 611 if (taskloop)
612 fd->sched_kind = OMP_CLAUSE_SCHEDULE_RUNTIME;
773c5ba7 613 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
614 gcc_assert (fd->chunk_size == NULL);
615 else if (fd->chunk_size == NULL)
616 {
617 /* We only need to compute a default chunk size for ordered
618 static loops and dynamic loops. */
fd6481cf 619 if (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
bc7bff74 620 || fd->have_ordered)
773c5ba7 621 fd->chunk_size = (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
622 ? integer_zero_node : integer_one_node;
623 }
fd6481cf 624
43895be5 625 int cnt = fd->ordered ? fd->ordered : fd->collapse;
626 for (i = 0; i < cnt; i++)
fd6481cf 627 {
43895be5 628 if (i == 0 && fd->collapse == 1 && (fd->ordered == 0 || loops == NULL))
fd6481cf 629 loop = &fd->loop;
630 else if (loops != NULL)
631 loop = loops + i;
632 else
633 loop = &dummy_loop;
634
75a70cf9 635 loop->v = gimple_omp_for_index (for_stmt, i);
fd6481cf 636 gcc_assert (SSA_VAR_P (loop->v));
637 gcc_assert (TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
638 || TREE_CODE (TREE_TYPE (loop->v)) == POINTER_TYPE);
639 var = TREE_CODE (loop->v) == SSA_NAME ? SSA_NAME_VAR (loop->v) : loop->v;
75a70cf9 640 loop->n1 = gimple_omp_for_initial (for_stmt, i);
fd6481cf 641
75a70cf9 642 loop->cond_code = gimple_omp_for_cond (for_stmt, i);
643 loop->n2 = gimple_omp_for_final (for_stmt, i);
56686608 644 gcc_assert (loop->cond_code != NE_EXPR
645 || gimple_omp_for_kind (for_stmt) == GF_OMP_FOR_KIND_CILKSIMD
646 || gimple_omp_for_kind (for_stmt) == GF_OMP_FOR_KIND_CILKFOR);
647 adjust_for_condition (loc, &loop->cond_code, &loop->n2);
fd6481cf 648
75a70cf9 649 t = gimple_omp_for_incr (for_stmt, i);
fd6481cf 650 gcc_assert (TREE_OPERAND (t, 0) == var);
56686608 651 loop->step = get_omp_for_step_from_incr (loc, t);
fd6481cf 652
bc7bff74 653 if (simd
654 || (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
655 && !fd->have_ordered))
3d483a94 656 {
657 if (fd->collapse == 1)
658 iter_type = TREE_TYPE (loop->v);
659 else if (i == 0
660 || TYPE_PRECISION (iter_type)
661 < TYPE_PRECISION (TREE_TYPE (loop->v)))
662 iter_type
663 = build_nonstandard_integer_type
bc7bff74 664 (TYPE_PRECISION (TREE_TYPE (loop->v)), 1);
3d483a94 665 }
666 else if (iter_type != long_long_unsigned_type_node)
fd6481cf 667 {
668 if (POINTER_TYPE_P (TREE_TYPE (loop->v)))
669 iter_type = long_long_unsigned_type_node;
670 else if (TYPE_UNSIGNED (TREE_TYPE (loop->v))
671 && TYPE_PRECISION (TREE_TYPE (loop->v))
672 >= TYPE_PRECISION (iter_type))
673 {
674 tree n;
675
676 if (loop->cond_code == LT_EXPR)
389dd41b 677 n = fold_build2_loc (loc,
678 PLUS_EXPR, TREE_TYPE (loop->v),
fd6481cf 679 loop->n2, loop->step);
680 else
681 n = loop->n1;
682 if (TREE_CODE (n) != INTEGER_CST
683 || tree_int_cst_lt (TYPE_MAX_VALUE (iter_type), n))
684 iter_type = long_long_unsigned_type_node;
685 }
686 else if (TYPE_PRECISION (TREE_TYPE (loop->v))
687 > TYPE_PRECISION (iter_type))
688 {
689 tree n1, n2;
690
691 if (loop->cond_code == LT_EXPR)
692 {
693 n1 = loop->n1;
389dd41b 694 n2 = fold_build2_loc (loc,
695 PLUS_EXPR, TREE_TYPE (loop->v),
fd6481cf 696 loop->n2, loop->step);
697 }
698 else
699 {
389dd41b 700 n1 = fold_build2_loc (loc,
701 MINUS_EXPR, TREE_TYPE (loop->v),
fd6481cf 702 loop->n2, loop->step);
703 n2 = loop->n1;
704 }
705 if (TREE_CODE (n1) != INTEGER_CST
706 || TREE_CODE (n2) != INTEGER_CST
707 || !tree_int_cst_lt (TYPE_MIN_VALUE (iter_type), n1)
708 || !tree_int_cst_lt (n2, TYPE_MAX_VALUE (iter_type)))
709 iter_type = long_long_unsigned_type_node;
710 }
711 }
712
43895be5 713 if (i >= fd->collapse)
714 continue;
715
fd6481cf 716 if (collapse_count && *collapse_count == NULL)
717 {
8e6b4515 718 t = fold_binary (loop->cond_code, boolean_type_node,
719 fold_convert (TREE_TYPE (loop->v), loop->n1),
720 fold_convert (TREE_TYPE (loop->v), loop->n2));
721 if (t && integer_zerop (t))
722 count = build_zero_cst (long_long_unsigned_type_node);
723 else if ((i == 0 || count != NULL_TREE)
724 && TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
725 && TREE_CONSTANT (loop->n1)
726 && TREE_CONSTANT (loop->n2)
727 && TREE_CODE (loop->step) == INTEGER_CST)
fd6481cf 728 {
729 tree itype = TREE_TYPE (loop->v);
730
731 if (POINTER_TYPE_P (itype))
3cea8318 732 itype = signed_type_for (itype);
fd6481cf 733 t = build_int_cst (itype, (loop->cond_code == LT_EXPR ? -1 : 1));
389dd41b 734 t = fold_build2_loc (loc,
735 PLUS_EXPR, itype,
736 fold_convert_loc (loc, itype, loop->step), t);
737 t = fold_build2_loc (loc, PLUS_EXPR, itype, t,
738 fold_convert_loc (loc, itype, loop->n2));
739 t = fold_build2_loc (loc, MINUS_EXPR, itype, t,
740 fold_convert_loc (loc, itype, loop->n1));
fd6481cf 741 if (TYPE_UNSIGNED (itype) && loop->cond_code == GT_EXPR)
389dd41b 742 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype,
743 fold_build1_loc (loc, NEGATE_EXPR, itype, t),
744 fold_build1_loc (loc, NEGATE_EXPR, itype,
745 fold_convert_loc (loc, itype,
746 loop->step)));
fd6481cf 747 else
389dd41b 748 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, t,
749 fold_convert_loc (loc, itype, loop->step));
750 t = fold_convert_loc (loc, long_long_unsigned_type_node, t);
fd6481cf 751 if (count != NULL_TREE)
389dd41b 752 count = fold_build2_loc (loc,
753 MULT_EXPR, long_long_unsigned_type_node,
fd6481cf 754 count, t);
755 else
756 count = t;
757 if (TREE_CODE (count) != INTEGER_CST)
758 count = NULL_TREE;
759 }
8e6b4515 760 else if (count && !integer_zerop (count))
fd6481cf 761 count = NULL_TREE;
762 }
763 }
764
3d483a94 765 if (count
bc7bff74 766 && !simd
767 && (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
768 || fd->have_ordered))
fd6481cf 769 {
770 if (!tree_int_cst_lt (count, TYPE_MAX_VALUE (long_integer_type_node)))
771 iter_type = long_long_unsigned_type_node;
772 else
773 iter_type = long_integer_type_node;
774 }
775 else if (collapse_iter && *collapse_iter != NULL)
776 iter_type = TREE_TYPE (*collapse_iter);
777 fd->iter_type = iter_type;
778 if (collapse_iter && *collapse_iter == NULL)
779 *collapse_iter = create_tmp_var (iter_type, ".iter");
780 if (collapse_count && *collapse_count == NULL)
781 {
782 if (count)
389dd41b 783 *collapse_count = fold_convert_loc (loc, iter_type, count);
fd6481cf 784 else
785 *collapse_count = create_tmp_var (iter_type, ".count");
786 }
787
43895be5 788 if (fd->collapse > 1 || (fd->ordered && loops))
fd6481cf 789 {
790 fd->loop.v = *collapse_iter;
791 fd->loop.n1 = build_int_cst (TREE_TYPE (fd->loop.v), 0);
792 fd->loop.n2 = *collapse_count;
793 fd->loop.step = build_int_cst (TREE_TYPE (fd->loop.v), 1);
794 fd->loop.cond_code = LT_EXPR;
795 }
43895be5 796 else if (loops)
797 loops[0] = fd->loop;
773c5ba7 798}
799
800
801/* Given two blocks PAR_ENTRY_BB and WS_ENTRY_BB such that WS_ENTRY_BB
802 is the immediate dominator of PAR_ENTRY_BB, return true if there
803 are no data dependencies that would prevent expanding the parallel
804 directive at PAR_ENTRY_BB as a combined parallel+workshare region.
805
806 When expanding a combined parallel+workshare region, the call to
807 the child function may need additional arguments in the case of
75a70cf9 808 GIMPLE_OMP_FOR regions. In some cases, these arguments are
809 computed out of variables passed in from the parent to the child
810 via 'struct .omp_data_s'. For instance:
773c5ba7 811
812 #pragma omp parallel for schedule (guided, i * 4)
813 for (j ...)
814
815 Is lowered into:
816
817 # BLOCK 2 (PAR_ENTRY_BB)
818 .omp_data_o.i = i;
819 #pragma omp parallel [child fn: bar.omp_fn.0 ( ..., D.1598)
48e1416a 820
773c5ba7 821 # BLOCK 3 (WS_ENTRY_BB)
822 .omp_data_i = &.omp_data_o;
823 D.1667 = .omp_data_i->i;
824 D.1598 = D.1667 * 4;
825 #pragma omp for schedule (guided, D.1598)
826
827 When we outline the parallel region, the call to the child function
828 'bar.omp_fn.0' will need the value D.1598 in its argument list, but
829 that value is computed *after* the call site. So, in principle we
830 cannot do the transformation.
831
832 To see whether the code in WS_ENTRY_BB blocks the combined
833 parallel+workshare call, we collect all the variables used in the
75a70cf9 834 GIMPLE_OMP_FOR header check whether they appear on the LHS of any
773c5ba7 835 statement in WS_ENTRY_BB. If so, then we cannot emit the combined
836 call.
837
838 FIXME. If we had the SSA form built at this point, we could merely
839 hoist the code in block 3 into block 2 and be done with it. But at
840 this point we don't have dataflow information and though we could
841 hack something up here, it is really not worth the aggravation. */
842
843static bool
f018d957 844workshare_safe_to_combine_p (basic_block ws_entry_bb)
773c5ba7 845{
846 struct omp_for_data fd;
42acab1c 847 gimple *ws_stmt = last_stmt (ws_entry_bb);
773c5ba7 848
75a70cf9 849 if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
773c5ba7 850 return true;
851
75a70cf9 852 gcc_assert (gimple_code (ws_stmt) == GIMPLE_OMP_FOR);
773c5ba7 853
1a91d914 854 extract_omp_for_data (as_a <gomp_for *> (ws_stmt), &fd, NULL);
fd6481cf 855
856 if (fd.collapse > 1 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
857 return false;
858 if (fd.iter_type != long_integer_type_node)
859 return false;
773c5ba7 860
861 /* FIXME. We give up too easily here. If any of these arguments
862 are not constants, they will likely involve variables that have
863 been mapped into fields of .omp_data_s for sharing with the child
864 function. With appropriate data flow, it would be possible to
865 see through this. */
fd6481cf 866 if (!is_gimple_min_invariant (fd.loop.n1)
867 || !is_gimple_min_invariant (fd.loop.n2)
868 || !is_gimple_min_invariant (fd.loop.step)
773c5ba7 869 || (fd.chunk_size && !is_gimple_min_invariant (fd.chunk_size)))
870 return false;
871
872 return true;
873}
874
875
43895be5 876static int omp_max_vf (void);
877
878/* Adjust CHUNK_SIZE from SCHEDULE clause, depending on simd modifier
879 presence (SIMD_SCHEDULE). */
880
881static tree
882omp_adjust_chunk_size (tree chunk_size, bool simd_schedule)
883{
884 if (!simd_schedule)
885 return chunk_size;
886
887 int vf = omp_max_vf ();
888 if (vf == 1)
889 return chunk_size;
890
891 tree type = TREE_TYPE (chunk_size);
892 chunk_size = fold_build2 (PLUS_EXPR, type, chunk_size,
893 build_int_cst (type, vf - 1));
894 return fold_build2 (BIT_AND_EXPR, type, chunk_size,
895 build_int_cst (type, -vf));
896}
897
898
773c5ba7 899/* Collect additional arguments needed to emit a combined
900 parallel+workshare call. WS_STMT is the workshare directive being
901 expanded. */
902
f1f41a6c 903static vec<tree, va_gc> *
42acab1c 904get_ws_args_for (gimple *par_stmt, gimple *ws_stmt)
773c5ba7 905{
906 tree t;
389dd41b 907 location_t loc = gimple_location (ws_stmt);
f1f41a6c 908 vec<tree, va_gc> *ws_args;
773c5ba7 909
1a91d914 910 if (gomp_for *for_stmt = dyn_cast <gomp_for *> (ws_stmt))
773c5ba7 911 {
912 struct omp_for_data fd;
bc7bff74 913 tree n1, n2;
773c5ba7 914
1a91d914 915 extract_omp_for_data (for_stmt, &fd, NULL);
bc7bff74 916 n1 = fd.loop.n1;
917 n2 = fd.loop.n2;
918
1a91d914 919 if (gimple_omp_for_combined_into_p (for_stmt))
bc7bff74 920 {
921 tree innerc
922 = find_omp_clause (gimple_omp_parallel_clauses (par_stmt),
923 OMP_CLAUSE__LOOPTEMP_);
924 gcc_assert (innerc);
925 n1 = OMP_CLAUSE_DECL (innerc);
926 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
927 OMP_CLAUSE__LOOPTEMP_);
928 gcc_assert (innerc);
929 n2 = OMP_CLAUSE_DECL (innerc);
930 }
773c5ba7 931
f1f41a6c 932 vec_alloc (ws_args, 3 + (fd.chunk_size != 0));
773c5ba7 933
bc7bff74 934 t = fold_convert_loc (loc, long_integer_type_node, n1);
f1f41a6c 935 ws_args->quick_push (t);
773c5ba7 936
bc7bff74 937 t = fold_convert_loc (loc, long_integer_type_node, n2);
f1f41a6c 938 ws_args->quick_push (t);
773c5ba7 939
414c3a2c 940 t = fold_convert_loc (loc, long_integer_type_node, fd.loop.step);
f1f41a6c 941 ws_args->quick_push (t);
414c3a2c 942
943 if (fd.chunk_size)
944 {
945 t = fold_convert_loc (loc, long_integer_type_node, fd.chunk_size);
43895be5 946 t = omp_adjust_chunk_size (t, fd.simd_schedule);
f1f41a6c 947 ws_args->quick_push (t);
414c3a2c 948 }
773c5ba7 949
950 return ws_args;
951 }
75a70cf9 952 else if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
773c5ba7 953 {
ac6e3339 954 /* Number of sections is equal to the number of edges from the
75a70cf9 955 GIMPLE_OMP_SECTIONS_SWITCH statement, except for the one to
956 the exit of the sections region. */
957 basic_block bb = single_succ (gimple_bb (ws_stmt));
ac6e3339 958 t = build_int_cst (unsigned_type_node, EDGE_COUNT (bb->succs) - 1);
f1f41a6c 959 vec_alloc (ws_args, 1);
960 ws_args->quick_push (t);
414c3a2c 961 return ws_args;
773c5ba7 962 }
963
964 gcc_unreachable ();
965}
966
967
968/* Discover whether REGION is a combined parallel+workshare region. */
969
970static void
971determine_parallel_type (struct omp_region *region)
1e8e9920 972{
773c5ba7 973 basic_block par_entry_bb, par_exit_bb;
974 basic_block ws_entry_bb, ws_exit_bb;
975
03ed154b 976 if (region == NULL || region->inner == NULL
ac6e3339 977 || region->exit == NULL || region->inner->exit == NULL
978 || region->inner->cont == NULL)
773c5ba7 979 return;
980
981 /* We only support parallel+for and parallel+sections. */
75a70cf9 982 if (region->type != GIMPLE_OMP_PARALLEL
983 || (region->inner->type != GIMPLE_OMP_FOR
984 && region->inner->type != GIMPLE_OMP_SECTIONS))
773c5ba7 985 return;
986
987 /* Check for perfect nesting PAR_ENTRY_BB -> WS_ENTRY_BB and
988 WS_EXIT_BB -> PAR_EXIT_BB. */
61e47ac8 989 par_entry_bb = region->entry;
990 par_exit_bb = region->exit;
991 ws_entry_bb = region->inner->entry;
992 ws_exit_bb = region->inner->exit;
773c5ba7 993
994 if (single_succ (par_entry_bb) == ws_entry_bb
995 && single_succ (ws_exit_bb) == par_exit_bb
f018d957 996 && workshare_safe_to_combine_p (ws_entry_bb)
75a70cf9 997 && (gimple_omp_parallel_combined_p (last_stmt (par_entry_bb))
de7ef844 998 || (last_and_only_stmt (ws_entry_bb)
999 && last_and_only_stmt (par_exit_bb))))
773c5ba7 1000 {
42acab1c 1001 gimple *par_stmt = last_stmt (par_entry_bb);
1002 gimple *ws_stmt = last_stmt (ws_entry_bb);
61e47ac8 1003
75a70cf9 1004 if (region->inner->type == GIMPLE_OMP_FOR)
773c5ba7 1005 {
1006 /* If this is a combined parallel loop, we need to determine
1007 whether or not to use the combined library calls. There
1008 are two cases where we do not apply the transformation:
1009 static loops and any kind of ordered loop. In the first
1010 case, we already open code the loop so there is no need
1011 to do anything else. In the latter case, the combined
1012 parallel loop call would still need extra synchronization
1013 to implement ordered semantics, so there would not be any
1014 gain in using the combined call. */
75a70cf9 1015 tree clauses = gimple_omp_for_clauses (ws_stmt);
773c5ba7 1016 tree c = find_omp_clause (clauses, OMP_CLAUSE_SCHEDULE);
1017 if (c == NULL
9561765e 1018 || ((OMP_CLAUSE_SCHEDULE_KIND (c) & OMP_CLAUSE_SCHEDULE_MASK)
1019 == OMP_CLAUSE_SCHEDULE_STATIC)
773c5ba7 1020 || find_omp_clause (clauses, OMP_CLAUSE_ORDERED))
1021 {
1022 region->is_combined_parallel = false;
1023 region->inner->is_combined_parallel = false;
1024 return;
1025 }
1026 }
1027
1028 region->is_combined_parallel = true;
1029 region->inner->is_combined_parallel = true;
bc7bff74 1030 region->ws_args = get_ws_args_for (par_stmt, ws_stmt);
773c5ba7 1031 }
1e8e9920 1032}
1033
773c5ba7 1034
1e8e9920 1035/* Return true if EXPR is variable sized. */
1036
1037static inline bool
1f1872fd 1038is_variable_sized (const_tree expr)
1e8e9920 1039{
1040 return !TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (expr)));
1041}
1042
1043/* Return true if DECL is a reference type. */
1044
1045static inline bool
1046is_reference (tree decl)
1047{
1048 return lang_hooks.decls.omp_privatize_by_reference (decl);
1049}
1050
ca4c3545 1051/* Return the type of a decl. If the decl is reference type,
1052 return its base type. */
1053static inline tree
1054get_base_type (tree decl)
1055{
1056 tree type = TREE_TYPE (decl);
1057 if (is_reference (decl))
1058 type = TREE_TYPE (type);
1059 return type;
1060}
1061
1062/* Lookup variables. The "maybe" form
1e8e9920 1063 allows for the variable form to not have been entered, otherwise we
1064 assert that the variable must have been entered. */
1065
1066static inline tree
1067lookup_decl (tree var, omp_context *ctx)
1068{
06ecf488 1069 tree *n = ctx->cb.decl_map->get (var);
e3022db7 1070 return *n;
1e8e9920 1071}
1072
1073static inline tree
e8a588af 1074maybe_lookup_decl (const_tree var, omp_context *ctx)
1e8e9920 1075{
06ecf488 1076 tree *n = ctx->cb.decl_map->get (const_cast<tree> (var));
e3022db7 1077 return n ? *n : NULL_TREE;
1e8e9920 1078}
1079
1080static inline tree
1081lookup_field (tree var, omp_context *ctx)
1082{
1083 splay_tree_node n;
1084 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
1085 return (tree) n->value;
1086}
1087
fd6481cf 1088static inline tree
43895be5 1089lookup_sfield (splay_tree_key key, omp_context *ctx)
fd6481cf 1090{
1091 splay_tree_node n;
1092 n = splay_tree_lookup (ctx->sfield_map
43895be5 1093 ? ctx->sfield_map : ctx->field_map, key);
fd6481cf 1094 return (tree) n->value;
1095}
1096
1e8e9920 1097static inline tree
43895be5 1098lookup_sfield (tree var, omp_context *ctx)
1099{
1100 return lookup_sfield ((splay_tree_key) var, ctx);
1101}
1102
1103static inline tree
1104maybe_lookup_field (splay_tree_key key, omp_context *ctx)
1e8e9920 1105{
1106 splay_tree_node n;
43895be5 1107 n = splay_tree_lookup (ctx->field_map, key);
1e8e9920 1108 return n ? (tree) n->value : NULL_TREE;
1109}
1110
43895be5 1111static inline tree
1112maybe_lookup_field (tree var, omp_context *ctx)
1113{
1114 return maybe_lookup_field ((splay_tree_key) var, ctx);
1115}
1116
e8a588af 1117/* Return true if DECL should be copied by pointer. SHARED_CTX is
1118 the parallel context if DECL is to be shared. */
1e8e9920 1119
1120static bool
fd6481cf 1121use_pointer_for_field (tree decl, omp_context *shared_ctx)
1e8e9920 1122{
1123 if (AGGREGATE_TYPE_P (TREE_TYPE (decl)))
1124 return true;
1125
554f2707 1126 /* We can only use copy-in/copy-out semantics for shared variables
1e8e9920 1127 when we know the value is not accessible from an outer scope. */
e8a588af 1128 if (shared_ctx)
1e8e9920 1129 {
ca4c3545 1130 gcc_assert (!is_gimple_omp_oacc (shared_ctx->stmt));
1131
1e8e9920 1132 /* ??? Trivially accessible from anywhere. But why would we even
1133 be passing an address in this case? Should we simply assert
1134 this to be false, or should we have a cleanup pass that removes
1135 these from the list of mappings? */
1136 if (TREE_STATIC (decl) || DECL_EXTERNAL (decl))
1137 return true;
1138
1139 /* For variables with DECL_HAS_VALUE_EXPR_P set, we cannot tell
1140 without analyzing the expression whether or not its location
1141 is accessible to anyone else. In the case of nested parallel
1142 regions it certainly may be. */
df2c34fc 1143 if (TREE_CODE (decl) != RESULT_DECL && DECL_HAS_VALUE_EXPR_P (decl))
1e8e9920 1144 return true;
1145
1146 /* Do not use copy-in/copy-out for variables that have their
1147 address taken. */
1148 if (TREE_ADDRESSABLE (decl))
1149 return true;
e8a588af 1150
b8214689 1151 /* lower_send_shared_vars only uses copy-in, but not copy-out
1152 for these. */
1153 if (TREE_READONLY (decl)
1154 || ((TREE_CODE (decl) == RESULT_DECL
1155 || TREE_CODE (decl) == PARM_DECL)
1156 && DECL_BY_REFERENCE (decl)))
1157 return false;
1158
e8a588af 1159 /* Disallow copy-in/out in nested parallel if
1160 decl is shared in outer parallel, otherwise
1161 each thread could store the shared variable
1162 in its own copy-in location, making the
1163 variable no longer really shared. */
b8214689 1164 if (shared_ctx->is_nested)
e8a588af 1165 {
1166 omp_context *up;
1167
1168 for (up = shared_ctx->outer; up; up = up->outer)
0cb159ec 1169 if (is_taskreg_ctx (up) && maybe_lookup_decl (decl, up))
e8a588af 1170 break;
1171
0cb159ec 1172 if (up)
e8a588af 1173 {
1174 tree c;
1175
75a70cf9 1176 for (c = gimple_omp_taskreg_clauses (up->stmt);
e8a588af 1177 c; c = OMP_CLAUSE_CHAIN (c))
1178 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
1179 && OMP_CLAUSE_DECL (c) == decl)
1180 break;
1181
1182 if (c)
784ad964 1183 goto maybe_mark_addressable_and_ret;
e8a588af 1184 }
1185 }
fd6481cf 1186
b8214689 1187 /* For tasks avoid using copy-in/out. As tasks can be
fd6481cf 1188 deferred or executed in different thread, when GOMP_task
1189 returns, the task hasn't necessarily terminated. */
b8214689 1190 if (is_task_ctx (shared_ctx))
fd6481cf 1191 {
784ad964 1192 tree outer;
1193 maybe_mark_addressable_and_ret:
1194 outer = maybe_lookup_decl_in_outer_ctx (decl, shared_ctx);
43895be5 1195 if (is_gimple_reg (outer) && !omp_member_access_dummy_var (outer))
fd6481cf 1196 {
1197 /* Taking address of OUTER in lower_send_shared_vars
1198 might need regimplification of everything that uses the
1199 variable. */
1200 if (!task_shared_vars)
1201 task_shared_vars = BITMAP_ALLOC (NULL);
1202 bitmap_set_bit (task_shared_vars, DECL_UID (outer));
1203 TREE_ADDRESSABLE (outer) = 1;
1204 }
1205 return true;
1206 }
1e8e9920 1207 }
1208
1209 return false;
1210}
1211
79acaae1 1212/* Construct a new automatic decl similar to VAR. */
1213
1214static tree
1215omp_copy_decl_2 (tree var, tree name, tree type, omp_context *ctx)
1216{
1217 tree copy = copy_var_decl (var, name, type);
1218
1219 DECL_CONTEXT (copy) = current_function_decl;
1767a056 1220 DECL_CHAIN (copy) = ctx->block_vars;
43895be5 1221 /* If VAR is listed in task_shared_vars, it means it wasn't
1222 originally addressable and is just because task needs to take
1223 it's address. But we don't need to take address of privatizations
1224 from that var. */
1225 if (TREE_ADDRESSABLE (var)
1226 && task_shared_vars
1227 && bitmap_bit_p (task_shared_vars, DECL_UID (var)))
1228 TREE_ADDRESSABLE (copy) = 0;
1e8e9920 1229 ctx->block_vars = copy;
1230
1231 return copy;
1232}
1233
1234static tree
1235omp_copy_decl_1 (tree var, omp_context *ctx)
1236{
1237 return omp_copy_decl_2 (var, DECL_NAME (var), TREE_TYPE (var), ctx);
1238}
1239
445d06b6 1240/* Build COMPONENT_REF and set TREE_THIS_VOLATILE and TREE_READONLY on it
1241 as appropriate. */
1242static tree
1243omp_build_component_ref (tree obj, tree field)
1244{
1245 tree ret = build3 (COMPONENT_REF, TREE_TYPE (field), obj, field, NULL);
1246 if (TREE_THIS_VOLATILE (field))
1247 TREE_THIS_VOLATILE (ret) |= 1;
1248 if (TREE_READONLY (field))
1249 TREE_READONLY (ret) |= 1;
1250 return ret;
1251}
1252
1e8e9920 1253/* Build tree nodes to access the field for VAR on the receiver side. */
1254
1255static tree
1256build_receiver_ref (tree var, bool by_ref, omp_context *ctx)
1257{
1258 tree x, field = lookup_field (var, ctx);
1259
1260 /* If the receiver record type was remapped in the child function,
1261 remap the field into the new record type. */
1262 x = maybe_lookup_field (field, ctx);
1263 if (x != NULL)
1264 field = x;
1265
182cf5a9 1266 x = build_simple_mem_ref (ctx->receiver_decl);
75c20a2e 1267 TREE_THIS_NOTRAP (x) = 1;
445d06b6 1268 x = omp_build_component_ref (x, field);
1e8e9920 1269 if (by_ref)
b16d27b9 1270 {
1271 x = build_simple_mem_ref (x);
1272 TREE_THIS_NOTRAP (x) = 1;
1273 }
1e8e9920 1274
1275 return x;
1276}
1277
1278/* Build tree nodes to access VAR in the scope outer to CTX. In the case
1279 of a parallel, this is a component reference; for workshare constructs
1280 this is some variable. */
1281
1282static tree
43895be5 1283build_outer_var_ref (tree var, omp_context *ctx, bool lastprivate = false)
1e8e9920 1284{
1285 tree x;
1286
f49d7bb5 1287 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx)))
1e8e9920 1288 x = var;
1289 else if (is_variable_sized (var))
1290 {
1291 x = TREE_OPERAND (DECL_VALUE_EXPR (var), 0);
43895be5 1292 x = build_outer_var_ref (x, ctx, lastprivate);
182cf5a9 1293 x = build_simple_mem_ref (x);
1e8e9920 1294 }
fd6481cf 1295 else if (is_taskreg_ctx (ctx))
1e8e9920 1296 {
e8a588af 1297 bool by_ref = use_pointer_for_field (var, NULL);
1e8e9920 1298 x = build_receiver_ref (var, by_ref, ctx);
1299 }
3d483a94 1300 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
10c55644 1301 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
3d483a94 1302 {
1303 /* #pragma omp simd isn't a worksharing construct, and can reference even
1304 private vars in its linear etc. clauses. */
1305 x = NULL_TREE;
1306 if (ctx->outer && is_taskreg_ctx (ctx))
1307 x = lookup_decl (var, ctx->outer);
1308 else if (ctx->outer)
84cb1020 1309 x = maybe_lookup_decl_in_outer_ctx (var, ctx);
3d483a94 1310 if (x == NULL_TREE)
1311 x = var;
1312 }
43895be5 1313 else if (lastprivate && is_taskloop_ctx (ctx))
1314 {
1315 gcc_assert (ctx->outer);
1316 splay_tree_node n
1317 = splay_tree_lookup (ctx->outer->field_map,
1318 (splay_tree_key) &DECL_UID (var));
1319 if (n == NULL)
1320 {
1321 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx->outer)))
1322 x = var;
1323 else
1324 x = lookup_decl (var, ctx->outer);
1325 }
1326 else
1327 {
1328 tree field = (tree) n->value;
1329 /* If the receiver record type was remapped in the child function,
1330 remap the field into the new record type. */
1331 x = maybe_lookup_field (field, ctx->outer);
1332 if (x != NULL)
1333 field = x;
1334
1335 x = build_simple_mem_ref (ctx->outer->receiver_decl);
1336 x = omp_build_component_ref (x, field);
1337 if (use_pointer_for_field (var, ctx->outer))
1338 x = build_simple_mem_ref (x);
1339 }
1340 }
1e8e9920 1341 else if (ctx->outer)
56686608 1342 {
1343 omp_context *outer = ctx->outer;
1344 if (gimple_code (outer->stmt) == GIMPLE_OMP_GRID_BODY)
1345 {
1346 outer = outer->outer;
1347 gcc_assert (outer
1348 && gimple_code (outer->stmt) != GIMPLE_OMP_GRID_BODY);
1349 }
1350 x = lookup_decl (var, outer);
1351 }
9438af57 1352 else if (is_reference (var))
1353 /* This can happen with orphaned constructs. If var is reference, it is
1354 possible it is shared and as such valid. */
1355 x = var;
43895be5 1356 else if (omp_member_access_dummy_var (var))
1357 x = var;
1e8e9920 1358 else
1359 gcc_unreachable ();
1360
43895be5 1361 if (x == var)
1362 {
1363 tree t = omp_member_access_dummy_var (var);
1364 if (t)
1365 {
1366 x = DECL_VALUE_EXPR (var);
1367 tree o = maybe_lookup_decl_in_outer_ctx (t, ctx);
1368 if (o != t)
1369 x = unshare_and_remap (x, t, o);
1370 else
1371 x = unshare_expr (x);
1372 }
1373 }
1374
1e8e9920 1375 if (is_reference (var))
182cf5a9 1376 x = build_simple_mem_ref (x);
1e8e9920 1377
1378 return x;
1379}
1380
1381/* Build tree nodes to access the field for VAR on the sender side. */
1382
1383static tree
43895be5 1384build_sender_ref (splay_tree_key key, omp_context *ctx)
1e8e9920 1385{
43895be5 1386 tree field = lookup_sfield (key, ctx);
445d06b6 1387 return omp_build_component_ref (ctx->sender_decl, field);
1e8e9920 1388}
1389
43895be5 1390static tree
1391build_sender_ref (tree var, omp_context *ctx)
1392{
1393 return build_sender_ref ((splay_tree_key) var, ctx);
1394}
1395
12dc9a16 1396/* Add a new field for VAR inside the structure CTX->SENDER_DECL. If
1397 BASE_POINTERS_RESTRICT, declare the field with restrict. */
1e8e9920 1398
1399static void
12dc9a16 1400install_var_field (tree var, bool by_ref, int mask, omp_context *ctx,
1401 bool base_pointers_restrict = false)
1e8e9920 1402{
fd6481cf 1403 tree field, type, sfield = NULL_TREE;
43895be5 1404 splay_tree_key key = (splay_tree_key) var;
1e8e9920 1405
43895be5 1406 if ((mask & 8) != 0)
1407 {
1408 key = (splay_tree_key) &DECL_UID (var);
1409 gcc_checking_assert (key != (splay_tree_key) var);
1410 }
fd6481cf 1411 gcc_assert ((mask & 1) == 0
43895be5 1412 || !splay_tree_lookup (ctx->field_map, key));
fd6481cf 1413 gcc_assert ((mask & 2) == 0 || !ctx->sfield_map
43895be5 1414 || !splay_tree_lookup (ctx->sfield_map, key));
ca4c3545 1415 gcc_assert ((mask & 3) == 3
1416 || !is_gimple_omp_oacc (ctx->stmt));
1e8e9920 1417
1418 type = TREE_TYPE (var);
44c0112f 1419 /* Prevent redeclaring the var in the split-off function with a restrict
1420 pointer type. Note that we only clear type itself, restrict qualifiers in
1421 the pointed-to type will be ignored by points-to analysis. */
1422 if (POINTER_TYPE_P (type)
1423 && TYPE_RESTRICT (type))
1424 type = build_qualified_type (type, TYPE_QUALS (type) & ~TYPE_QUAL_RESTRICT);
1425
bc7bff74 1426 if (mask & 4)
1427 {
1428 gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
1429 type = build_pointer_type (build_pointer_type (type));
1430 }
1431 else if (by_ref)
12dc9a16 1432 {
1433 type = build_pointer_type (type);
1434 if (base_pointers_restrict)
1435 type = build_qualified_type (type, TYPE_QUAL_RESTRICT);
1436 }
fd6481cf 1437 else if ((mask & 3) == 1 && is_reference (var))
1438 type = TREE_TYPE (type);
1e8e9920 1439
e60a6f7b 1440 field = build_decl (DECL_SOURCE_LOCATION (var),
1441 FIELD_DECL, DECL_NAME (var), type);
1e8e9920 1442
1443 /* Remember what variable this field was created for. This does have a
1444 side effect of making dwarf2out ignore this member, so for helpful
1445 debugging we clear it later in delete_omp_context. */
1446 DECL_ABSTRACT_ORIGIN (field) = var;
fd6481cf 1447 if (type == TREE_TYPE (var))
1448 {
5d4b30ea 1449 SET_DECL_ALIGN (field, DECL_ALIGN (var));
fd6481cf 1450 DECL_USER_ALIGN (field) = DECL_USER_ALIGN (var);
1451 TREE_THIS_VOLATILE (field) = TREE_THIS_VOLATILE (var);
1452 }
1453 else
5d4b30ea 1454 SET_DECL_ALIGN (field, TYPE_ALIGN (type));
1e8e9920 1455
fd6481cf 1456 if ((mask & 3) == 3)
1457 {
1458 insert_field_into_struct (ctx->record_type, field);
1459 if (ctx->srecord_type)
1460 {
e60a6f7b 1461 sfield = build_decl (DECL_SOURCE_LOCATION (var),
1462 FIELD_DECL, DECL_NAME (var), type);
fd6481cf 1463 DECL_ABSTRACT_ORIGIN (sfield) = var;
5d4b30ea 1464 SET_DECL_ALIGN (sfield, DECL_ALIGN (field));
fd6481cf 1465 DECL_USER_ALIGN (sfield) = DECL_USER_ALIGN (field);
1466 TREE_THIS_VOLATILE (sfield) = TREE_THIS_VOLATILE (field);
1467 insert_field_into_struct (ctx->srecord_type, sfield);
1468 }
1469 }
1470 else
1471 {
1472 if (ctx->srecord_type == NULL_TREE)
1473 {
1474 tree t;
1475
1476 ctx->srecord_type = lang_hooks.types.make_type (RECORD_TYPE);
1477 ctx->sfield_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
1478 for (t = TYPE_FIELDS (ctx->record_type); t ; t = TREE_CHAIN (t))
1479 {
43895be5 1480 sfield = build_decl (DECL_SOURCE_LOCATION (t),
e60a6f7b 1481 FIELD_DECL, DECL_NAME (t), TREE_TYPE (t));
fd6481cf 1482 DECL_ABSTRACT_ORIGIN (sfield) = DECL_ABSTRACT_ORIGIN (t);
1483 insert_field_into_struct (ctx->srecord_type, sfield);
1484 splay_tree_insert (ctx->sfield_map,
1485 (splay_tree_key) DECL_ABSTRACT_ORIGIN (t),
1486 (splay_tree_value) sfield);
1487 }
1488 }
1489 sfield = field;
1490 insert_field_into_struct ((mask & 1) ? ctx->record_type
1491 : ctx->srecord_type, field);
1492 }
1e8e9920 1493
fd6481cf 1494 if (mask & 1)
43895be5 1495 splay_tree_insert (ctx->field_map, key, (splay_tree_value) field);
fd6481cf 1496 if ((mask & 2) && ctx->sfield_map)
43895be5 1497 splay_tree_insert (ctx->sfield_map, key, (splay_tree_value) sfield);
1e8e9920 1498}
1499
1500static tree
1501install_var_local (tree var, omp_context *ctx)
1502{
1503 tree new_var = omp_copy_decl_1 (var, ctx);
1504 insert_decl_map (&ctx->cb, var, new_var);
1505 return new_var;
1506}
1507
1508/* Adjust the replacement for DECL in CTX for the new context. This means
1509 copying the DECL_VALUE_EXPR, and fixing up the type. */
1510
1511static void
1512fixup_remapped_decl (tree decl, omp_context *ctx, bool private_debug)
1513{
1514 tree new_decl, size;
1515
1516 new_decl = lookup_decl (decl, ctx);
1517
1518 TREE_TYPE (new_decl) = remap_type (TREE_TYPE (decl), &ctx->cb);
1519
1520 if ((!TREE_CONSTANT (DECL_SIZE (new_decl)) || private_debug)
1521 && DECL_HAS_VALUE_EXPR_P (decl))
1522 {
1523 tree ve = DECL_VALUE_EXPR (decl);
75a70cf9 1524 walk_tree (&ve, copy_tree_body_r, &ctx->cb, NULL);
1e8e9920 1525 SET_DECL_VALUE_EXPR (new_decl, ve);
1526 DECL_HAS_VALUE_EXPR_P (new_decl) = 1;
1527 }
1528
1529 if (!TREE_CONSTANT (DECL_SIZE (new_decl)))
1530 {
1531 size = remap_decl (DECL_SIZE (decl), &ctx->cb);
1532 if (size == error_mark_node)
1533 size = TYPE_SIZE (TREE_TYPE (new_decl));
1534 DECL_SIZE (new_decl) = size;
1535
1536 size = remap_decl (DECL_SIZE_UNIT (decl), &ctx->cb);
1537 if (size == error_mark_node)
1538 size = TYPE_SIZE_UNIT (TREE_TYPE (new_decl));
1539 DECL_SIZE_UNIT (new_decl) = size;
1540 }
1541}
1542
1543/* The callback for remap_decl. Search all containing contexts for a
1544 mapping of the variable; this avoids having to duplicate the splay
1545 tree ahead of time. We know a mapping doesn't already exist in the
1546 given context. Create new mappings to implement default semantics. */
1547
1548static tree
1549omp_copy_decl (tree var, copy_body_data *cb)
1550{
1551 omp_context *ctx = (omp_context *) cb;
1552 tree new_var;
1553
1e8e9920 1554 if (TREE_CODE (var) == LABEL_DECL)
1555 {
e60a6f7b 1556 new_var = create_artificial_label (DECL_SOURCE_LOCATION (var));
773c5ba7 1557 DECL_CONTEXT (new_var) = current_function_decl;
1e8e9920 1558 insert_decl_map (&ctx->cb, var, new_var);
1559 return new_var;
1560 }
1561
fd6481cf 1562 while (!is_taskreg_ctx (ctx))
1e8e9920 1563 {
1564 ctx = ctx->outer;
1565 if (ctx == NULL)
1566 return var;
1567 new_var = maybe_lookup_decl (var, ctx);
1568 if (new_var)
1569 return new_var;
1570 }
1571
f49d7bb5 1572 if (is_global_var (var) || decl_function_context (var) != ctx->cb.src_fn)
1573 return var;
1574
1e8e9920 1575 return error_mark_node;
1576}
1577
773c5ba7 1578
773c5ba7 1579/* Debugging dumps for parallel regions. */
1580void dump_omp_region (FILE *, struct omp_region *, int);
1581void debug_omp_region (struct omp_region *);
1582void debug_all_omp_regions (void);
1583
1584/* Dump the parallel region tree rooted at REGION. */
1585
1586void
1587dump_omp_region (FILE *file, struct omp_region *region, int indent)
1588{
61e47ac8 1589 fprintf (file, "%*sbb %d: %s\n", indent, "", region->entry->index,
75a70cf9 1590 gimple_code_name[region->type]);
773c5ba7 1591
1592 if (region->inner)
1593 dump_omp_region (file, region->inner, indent + 4);
1594
61e47ac8 1595 if (region->cont)
1596 {
75a70cf9 1597 fprintf (file, "%*sbb %d: GIMPLE_OMP_CONTINUE\n", indent, "",
61e47ac8 1598 region->cont->index);
1599 }
48e1416a 1600
773c5ba7 1601 if (region->exit)
75a70cf9 1602 fprintf (file, "%*sbb %d: GIMPLE_OMP_RETURN\n", indent, "",
61e47ac8 1603 region->exit->index);
773c5ba7 1604 else
61e47ac8 1605 fprintf (file, "%*s[no exit marker]\n", indent, "");
773c5ba7 1606
1607 if (region->next)
61e47ac8 1608 dump_omp_region (file, region->next, indent);
773c5ba7 1609}
1610
4b987fac 1611DEBUG_FUNCTION void
773c5ba7 1612debug_omp_region (struct omp_region *region)
1613{
1614 dump_omp_region (stderr, region, 0);
1615}
1616
4b987fac 1617DEBUG_FUNCTION void
773c5ba7 1618debug_all_omp_regions (void)
1619{
1620 dump_omp_region (stderr, root_omp_region, 0);
1621}
1622
1623
1624/* Create a new parallel region starting at STMT inside region PARENT. */
1625
7740abd8 1626static struct omp_region *
75a70cf9 1627new_omp_region (basic_block bb, enum gimple_code type,
1628 struct omp_region *parent)
773c5ba7 1629{
4077bf7a 1630 struct omp_region *region = XCNEW (struct omp_region);
773c5ba7 1631
1632 region->outer = parent;
61e47ac8 1633 region->entry = bb;
1634 region->type = type;
773c5ba7 1635
1636 if (parent)
1637 {
1638 /* This is a nested region. Add it to the list of inner
1639 regions in PARENT. */
1640 region->next = parent->inner;
1641 parent->inner = region;
1642 }
61e47ac8 1643 else
773c5ba7 1644 {
1645 /* This is a toplevel region. Add it to the list of toplevel
1646 regions in ROOT_OMP_REGION. */
1647 region->next = root_omp_region;
1648 root_omp_region = region;
1649 }
61e47ac8 1650
1651 return region;
1652}
1653
1654/* Release the memory associated with the region tree rooted at REGION. */
1655
1656static void
1657free_omp_region_1 (struct omp_region *region)
1658{
1659 struct omp_region *i, *n;
1660
1661 for (i = region->inner; i ; i = n)
773c5ba7 1662 {
61e47ac8 1663 n = i->next;
1664 free_omp_region_1 (i);
773c5ba7 1665 }
1666
61e47ac8 1667 free (region);
1668}
773c5ba7 1669
61e47ac8 1670/* Release the memory for the entire omp region tree. */
1671
1672void
1673free_omp_regions (void)
1674{
1675 struct omp_region *r, *n;
1676 for (r = root_omp_region; r ; r = n)
1677 {
1678 n = r->next;
1679 free_omp_region_1 (r);
1680 }
1681 root_omp_region = NULL;
773c5ba7 1682}
1683
1684
1e8e9920 1685/* Create a new context, with OUTER_CTX being the surrounding context. */
1686
1687static omp_context *
42acab1c 1688new_omp_context (gimple *stmt, omp_context *outer_ctx)
1e8e9920 1689{
1690 omp_context *ctx = XCNEW (omp_context);
1691
1692 splay_tree_insert (all_contexts, (splay_tree_key) stmt,
1693 (splay_tree_value) ctx);
1694 ctx->stmt = stmt;
1695
1696 if (outer_ctx)
1697 {
1698 ctx->outer = outer_ctx;
1699 ctx->cb = outer_ctx->cb;
1700 ctx->cb.block = NULL;
1701 ctx->depth = outer_ctx->depth + 1;
1702 }
1703 else
1704 {
1705 ctx->cb.src_fn = current_function_decl;
1706 ctx->cb.dst_fn = current_function_decl;
415d1b9a 1707 ctx->cb.src_node = cgraph_node::get (current_function_decl);
53f79206 1708 gcc_checking_assert (ctx->cb.src_node);
1e8e9920 1709 ctx->cb.dst_node = ctx->cb.src_node;
1710 ctx->cb.src_cfun = cfun;
1711 ctx->cb.copy_decl = omp_copy_decl;
e38def9c 1712 ctx->cb.eh_lp_nr = 0;
1e8e9920 1713 ctx->cb.transform_call_graph_edges = CB_CGE_MOVE;
1714 ctx->depth = 1;
1715 }
1716
06ecf488 1717 ctx->cb.decl_map = new hash_map<tree, tree>;
1e8e9920 1718
1719 return ctx;
1720}
1721
75a70cf9 1722static gimple_seq maybe_catch_exception (gimple_seq);
f6430caa 1723
1724/* Finalize task copyfn. */
1725
1726static void
1a91d914 1727finalize_task_copyfn (gomp_task *task_stmt)
f6430caa 1728{
1729 struct function *child_cfun;
9078126c 1730 tree child_fn;
e3a19533 1731 gimple_seq seq = NULL, new_seq;
1a91d914 1732 gbind *bind;
f6430caa 1733
75a70cf9 1734 child_fn = gimple_omp_task_copy_fn (task_stmt);
f6430caa 1735 if (child_fn == NULL_TREE)
1736 return;
1737
1738 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
82b40354 1739 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
f6430caa 1740
f6430caa 1741 push_cfun (child_cfun);
7e3aae05 1742 bind = gimplify_body (child_fn, false);
75a70cf9 1743 gimple_seq_add_stmt (&seq, bind);
1744 new_seq = maybe_catch_exception (seq);
1745 if (new_seq != seq)
1746 {
1747 bind = gimple_build_bind (NULL, new_seq, NULL);
e3a19533 1748 seq = NULL;
75a70cf9 1749 gimple_seq_add_stmt (&seq, bind);
1750 }
1751 gimple_set_body (child_fn, seq);
f6430caa 1752 pop_cfun ();
f6430caa 1753
82b40354 1754 /* Inform the callgraph about the new function. */
47300487 1755 cgraph_node *node = cgraph_node::get_create (child_fn);
1756 node->parallelized_function = 1;
415d1b9a 1757 cgraph_node::add_new_function (child_fn, false);
f6430caa 1758}
1759
1e8e9920 1760/* Destroy a omp_context data structures. Called through the splay tree
1761 value delete callback. */
1762
1763static void
1764delete_omp_context (splay_tree_value value)
1765{
1766 omp_context *ctx = (omp_context *) value;
1767
06ecf488 1768 delete ctx->cb.decl_map;
1e8e9920 1769
1770 if (ctx->field_map)
1771 splay_tree_delete (ctx->field_map);
fd6481cf 1772 if (ctx->sfield_map)
1773 splay_tree_delete (ctx->sfield_map);
1e8e9920 1774
1775 /* We hijacked DECL_ABSTRACT_ORIGIN earlier. We need to clear it before
1776 it produces corrupt debug information. */
1777 if (ctx->record_type)
1778 {
1779 tree t;
1767a056 1780 for (t = TYPE_FIELDS (ctx->record_type); t ; t = DECL_CHAIN (t))
1e8e9920 1781 DECL_ABSTRACT_ORIGIN (t) = NULL;
1782 }
fd6481cf 1783 if (ctx->srecord_type)
1784 {
1785 tree t;
1767a056 1786 for (t = TYPE_FIELDS (ctx->srecord_type); t ; t = DECL_CHAIN (t))
fd6481cf 1787 DECL_ABSTRACT_ORIGIN (t) = NULL;
1788 }
1e8e9920 1789
f6430caa 1790 if (is_task_ctx (ctx))
1a91d914 1791 finalize_task_copyfn (as_a <gomp_task *> (ctx->stmt));
f6430caa 1792
1e8e9920 1793 XDELETE (ctx);
1794}
1795
1796/* Fix up RECEIVER_DECL with a type that has been remapped to the child
1797 context. */
1798
1799static void
1800fixup_child_record_type (omp_context *ctx)
1801{
1802 tree f, type = ctx->record_type;
1803
56686608 1804 if (!ctx->receiver_decl)
1805 return;
1e8e9920 1806 /* ??? It isn't sufficient to just call remap_type here, because
1807 variably_modified_type_p doesn't work the way we expect for
1808 record types. Testing each field for whether it needs remapping
1809 and creating a new record by hand works, however. */
1767a056 1810 for (f = TYPE_FIELDS (type); f ; f = DECL_CHAIN (f))
1e8e9920 1811 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
1812 break;
1813 if (f)
1814 {
1815 tree name, new_fields = NULL;
1816
1817 type = lang_hooks.types.make_type (RECORD_TYPE);
1818 name = DECL_NAME (TYPE_NAME (ctx->record_type));
e60a6f7b 1819 name = build_decl (DECL_SOURCE_LOCATION (ctx->receiver_decl),
1820 TYPE_DECL, name, type);
1e8e9920 1821 TYPE_NAME (type) = name;
1822
1767a056 1823 for (f = TYPE_FIELDS (ctx->record_type); f ; f = DECL_CHAIN (f))
1e8e9920 1824 {
1825 tree new_f = copy_node (f);
1826 DECL_CONTEXT (new_f) = type;
1827 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &ctx->cb);
1767a056 1828 DECL_CHAIN (new_f) = new_fields;
75a70cf9 1829 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &ctx->cb, NULL);
1830 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r,
1831 &ctx->cb, NULL);
1832 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
1833 &ctx->cb, NULL);
1e8e9920 1834 new_fields = new_f;
1835
1836 /* Arrange to be able to look up the receiver field
1837 given the sender field. */
1838 splay_tree_insert (ctx->field_map, (splay_tree_key) f,
1839 (splay_tree_value) new_f);
1840 }
1841 TYPE_FIELDS (type) = nreverse (new_fields);
1842 layout_type (type);
1843 }
1844
43895be5 1845 /* In a target region we never modify any of the pointers in *.omp_data_i,
1846 so attempt to help the optimizers. */
1847 if (is_gimple_omp_offloaded (ctx->stmt))
1848 type = build_qualified_type (type, TYPE_QUAL_CONST);
1849
5455b100 1850 TREE_TYPE (ctx->receiver_decl)
1851 = build_qualified_type (build_reference_type (type), TYPE_QUAL_RESTRICT);
1e8e9920 1852}
1853
1854/* Instantiate decls as necessary in CTX to satisfy the data sharing
12dc9a16 1855 specified by CLAUSES. If BASE_POINTERS_RESTRICT, install var field with
1856 restrict. */
1e8e9920 1857
1858static void
12dc9a16 1859scan_sharing_clauses (tree clauses, omp_context *ctx,
1860 bool base_pointers_restrict = false)
1e8e9920 1861{
1862 tree c, decl;
1863 bool scan_array_reductions = false;
1864
1865 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1866 {
1867 bool by_ref;
1868
55d6e7cd 1869 switch (OMP_CLAUSE_CODE (c))
1e8e9920 1870 {
1871 case OMP_CLAUSE_PRIVATE:
1872 decl = OMP_CLAUSE_DECL (c);
fd6481cf 1873 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
1874 goto do_private;
1875 else if (!is_variable_sized (decl))
1e8e9920 1876 install_var_local (decl, ctx);
1877 break;
1878
1879 case OMP_CLAUSE_SHARED:
5fddcf34 1880 decl = OMP_CLAUSE_DECL (c);
bc7bff74 1881 /* Ignore shared directives in teams construct. */
1882 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
5fddcf34 1883 {
1884 /* Global variables don't need to be copied,
1885 the receiver side will use them directly. */
1886 tree odecl = maybe_lookup_decl_in_outer_ctx (decl, ctx);
1887 if (is_global_var (odecl))
1888 break;
1889 insert_decl_map (&ctx->cb, decl, odecl);
1890 break;
1891 }
fd6481cf 1892 gcc_assert (is_taskreg_ctx (ctx));
e7327393 1893 gcc_assert (!COMPLETE_TYPE_P (TREE_TYPE (decl))
1894 || !is_variable_sized (decl));
f49d7bb5 1895 /* Global variables don't need to be copied,
1896 the receiver side will use them directly. */
1897 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1898 break;
43895be5 1899 if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
98588013 1900 {
1901 use_pointer_for_field (decl, ctx);
1902 break;
1903 }
1904 by_ref = use_pointer_for_field (decl, NULL);
1905 if ((! TREE_READONLY (decl) && !OMP_CLAUSE_SHARED_READONLY (c))
1e8e9920 1906 || TREE_ADDRESSABLE (decl)
1907 || by_ref
1908 || is_reference (decl))
1909 {
98588013 1910 by_ref = use_pointer_for_field (decl, ctx);
fd6481cf 1911 install_var_field (decl, by_ref, 3, ctx);
1e8e9920 1912 install_var_local (decl, ctx);
1913 break;
1914 }
1915 /* We don't need to copy const scalar vars back. */
55d6e7cd 1916 OMP_CLAUSE_SET_CODE (c, OMP_CLAUSE_FIRSTPRIVATE);
1e8e9920 1917 goto do_private;
1918
43895be5 1919 case OMP_CLAUSE_REDUCTION:
1920 decl = OMP_CLAUSE_DECL (c);
1921 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1922 && TREE_CODE (decl) == MEM_REF)
1923 {
1924 tree t = TREE_OPERAND (decl, 0);
9561765e 1925 if (TREE_CODE (t) == POINTER_PLUS_EXPR)
1926 t = TREE_OPERAND (t, 0);
43895be5 1927 if (TREE_CODE (t) == INDIRECT_REF
1928 || TREE_CODE (t) == ADDR_EXPR)
1929 t = TREE_OPERAND (t, 0);
1930 install_var_local (t, ctx);
1931 if (is_taskreg_ctx (ctx)
1932 && !is_global_var (maybe_lookup_decl_in_outer_ctx (t, ctx))
1933 && !is_variable_sized (t))
1934 {
1935 by_ref = use_pointer_for_field (t, ctx);
1936 install_var_field (t, by_ref, 3, ctx);
1937 }
1938 break;
1939 }
1940 goto do_private;
1941
1e8e9920 1942 case OMP_CLAUSE_LASTPRIVATE:
1943 /* Let the corresponding firstprivate clause create
1944 the variable. */
1945 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1946 break;
1947 /* FALLTHRU */
1948
1949 case OMP_CLAUSE_FIRSTPRIVATE:
3d483a94 1950 case OMP_CLAUSE_LINEAR:
1e8e9920 1951 decl = OMP_CLAUSE_DECL (c);
1952 do_private:
43895be5 1953 if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE
1954 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IS_DEVICE_PTR)
1955 && is_gimple_omp_offloaded (ctx->stmt))
1956 {
1957 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
1958 install_var_field (decl, !is_reference (decl), 3, ctx);
1959 else if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1960 install_var_field (decl, true, 3, ctx);
1961 else
1962 install_var_field (decl, false, 3, ctx);
1963 }
1e8e9920 1964 if (is_variable_sized (decl))
1e8e9920 1965 {
fd6481cf 1966 if (is_task_ctx (ctx))
1967 install_var_field (decl, false, 1, ctx);
1968 break;
1969 }
1970 else if (is_taskreg_ctx (ctx))
1971 {
1972 bool global
1973 = is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx));
e8a588af 1974 by_ref = use_pointer_for_field (decl, NULL);
fd6481cf 1975
1976 if (is_task_ctx (ctx)
1977 && (global || by_ref || is_reference (decl)))
1978 {
1979 install_var_field (decl, false, 1, ctx);
1980 if (!global)
1981 install_var_field (decl, by_ref, 2, ctx);
1982 }
1983 else if (!global)
1984 install_var_field (decl, by_ref, 3, ctx);
1e8e9920 1985 }
1986 install_var_local (decl, ctx);
1987 break;
1988
43895be5 1989 case OMP_CLAUSE_USE_DEVICE_PTR:
1990 decl = OMP_CLAUSE_DECL (c);
1991 if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1992 install_var_field (decl, true, 3, ctx);
1993 else
1994 install_var_field (decl, false, 3, ctx);
1995 if (DECL_SIZE (decl)
1996 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
1997 {
1998 tree decl2 = DECL_VALUE_EXPR (decl);
1999 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
2000 decl2 = TREE_OPERAND (decl2, 0);
2001 gcc_assert (DECL_P (decl2));
2002 install_var_local (decl2, ctx);
2003 }
2004 install_var_local (decl, ctx);
2005 break;
2006
2007 case OMP_CLAUSE_IS_DEVICE_PTR:
2008 decl = OMP_CLAUSE_DECL (c);
2009 goto do_private;
2010
bc7bff74 2011 case OMP_CLAUSE__LOOPTEMP_:
43895be5 2012 gcc_assert (is_taskreg_ctx (ctx));
bc7bff74 2013 decl = OMP_CLAUSE_DECL (c);
2014 install_var_field (decl, false, 3, ctx);
2015 install_var_local (decl, ctx);
2016 break;
2017
1e8e9920 2018 case OMP_CLAUSE_COPYPRIVATE:
1e8e9920 2019 case OMP_CLAUSE_COPYIN:
2020 decl = OMP_CLAUSE_DECL (c);
e8a588af 2021 by_ref = use_pointer_for_field (decl, NULL);
fd6481cf 2022 install_var_field (decl, by_ref, 3, ctx);
1e8e9920 2023 break;
2024
2025 case OMP_CLAUSE_DEFAULT:
2026 ctx->default_kind = OMP_CLAUSE_DEFAULT_KIND (c);
2027 break;
2028
2169f33b 2029 case OMP_CLAUSE_FINAL:
1e8e9920 2030 case OMP_CLAUSE_IF:
2031 case OMP_CLAUSE_NUM_THREADS:
bc7bff74 2032 case OMP_CLAUSE_NUM_TEAMS:
2033 case OMP_CLAUSE_THREAD_LIMIT:
2034 case OMP_CLAUSE_DEVICE:
1e8e9920 2035 case OMP_CLAUSE_SCHEDULE:
bc7bff74 2036 case OMP_CLAUSE_DIST_SCHEDULE:
2037 case OMP_CLAUSE_DEPEND:
43895be5 2038 case OMP_CLAUSE_PRIORITY:
2039 case OMP_CLAUSE_GRAINSIZE:
2040 case OMP_CLAUSE_NUM_TASKS:
40750995 2041 case OMP_CLAUSE__CILK_FOR_COUNT_:
ca4c3545 2042 case OMP_CLAUSE_NUM_GANGS:
2043 case OMP_CLAUSE_NUM_WORKERS:
2044 case OMP_CLAUSE_VECTOR_LENGTH:
1e8e9920 2045 if (ctx->outer)
75a70cf9 2046 scan_omp_op (&OMP_CLAUSE_OPERAND (c, 0), ctx->outer);
1e8e9920 2047 break;
2048
bc7bff74 2049 case OMP_CLAUSE_TO:
2050 case OMP_CLAUSE_FROM:
2051 case OMP_CLAUSE_MAP:
2052 if (ctx->outer)
2053 scan_omp_op (&OMP_CLAUSE_SIZE (c), ctx->outer);
2054 decl = OMP_CLAUSE_DECL (c);
2055 /* Global variables with "omp declare target" attribute
2056 don't need to be copied, the receiver side will use them
c0998828 2057 directly. However, global variables with "omp declare target link"
2058 attribute need to be copied. */
bc7bff74 2059 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
2060 && DECL_P (decl)
9561765e 2061 && ((OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_FIRSTPRIVATE_POINTER
2062 && (OMP_CLAUSE_MAP_KIND (c)
2063 != GOMP_MAP_FIRSTPRIVATE_REFERENCE))
43895be5 2064 || TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
bc7bff74 2065 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
c0998828 2066 && varpool_node::get_create (decl)->offloadable
2067 && !lookup_attribute ("omp declare target link",
2068 DECL_ATTRIBUTES (decl)))
bc7bff74 2069 break;
2070 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
ca4c3545 2071 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER)
bc7bff74 2072 {
ca4c3545 2073 /* Ignore GOMP_MAP_POINTER kind for arrays in regions that are
2074 not offloaded; there is nothing to map for those. */
2075 if (!is_gimple_omp_offloaded (ctx->stmt)
c1a114c2 2076 && !POINTER_TYPE_P (TREE_TYPE (decl))
2077 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
bc7bff74 2078 break;
2079 }
43895be5 2080 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
9561765e 2081 && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
2082 || (OMP_CLAUSE_MAP_KIND (c)
2083 == GOMP_MAP_FIRSTPRIVATE_REFERENCE)))
43895be5 2084 {
2085 if (TREE_CODE (decl) == COMPONENT_REF
2086 || (TREE_CODE (decl) == INDIRECT_REF
2087 && TREE_CODE (TREE_OPERAND (decl, 0)) == COMPONENT_REF
2088 && (TREE_CODE (TREE_TYPE (TREE_OPERAND (decl, 0)))
2089 == REFERENCE_TYPE)))
2090 break;
2091 if (DECL_SIZE (decl)
2092 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
2093 {
2094 tree decl2 = DECL_VALUE_EXPR (decl);
2095 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
2096 decl2 = TREE_OPERAND (decl2, 0);
2097 gcc_assert (DECL_P (decl2));
2098 install_var_local (decl2, ctx);
2099 }
2100 install_var_local (decl, ctx);
2101 break;
2102 }
bc7bff74 2103 if (DECL_P (decl))
2104 {
2105 if (DECL_SIZE (decl)
2106 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
2107 {
2108 tree decl2 = DECL_VALUE_EXPR (decl);
2109 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
2110 decl2 = TREE_OPERAND (decl2, 0);
2111 gcc_assert (DECL_P (decl2));
9561765e 2112 install_var_field (decl2, true, 3, ctx);
bc7bff74 2113 install_var_local (decl2, ctx);
2114 install_var_local (decl, ctx);
2115 }
2116 else
2117 {
2118 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
ca4c3545 2119 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
bc7bff74 2120 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
2121 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
2122 install_var_field (decl, true, 7, ctx);
2123 else
12dc9a16 2124 install_var_field (decl, true, 3, ctx,
2125 base_pointers_restrict);
0c302595 2126 if (is_gimple_omp_offloaded (ctx->stmt)
2127 && !OMP_CLAUSE_MAP_IN_REDUCTION (c))
bc7bff74 2128 install_var_local (decl, ctx);
2129 }
2130 }
2131 else
2132 {
2133 tree base = get_base_address (decl);
2134 tree nc = OMP_CLAUSE_CHAIN (c);
2135 if (DECL_P (base)
2136 && nc != NULL_TREE
2137 && OMP_CLAUSE_CODE (nc) == OMP_CLAUSE_MAP
2138 && OMP_CLAUSE_DECL (nc) == base
ca4c3545 2139 && OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_POINTER
bc7bff74 2140 && integer_zerop (OMP_CLAUSE_SIZE (nc)))
2141 {
2142 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c) = 1;
2143 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (nc) = 1;
2144 }
2145 else
2146 {
691447ab 2147 if (ctx->outer)
2148 {
2149 scan_omp_op (&OMP_CLAUSE_DECL (c), ctx->outer);
2150 decl = OMP_CLAUSE_DECL (c);
2151 }
bc7bff74 2152 gcc_assert (!splay_tree_lookup (ctx->field_map,
2153 (splay_tree_key) decl));
2154 tree field
2155 = build_decl (OMP_CLAUSE_LOCATION (c),
2156 FIELD_DECL, NULL_TREE, ptr_type_node);
5d4b30ea 2157 SET_DECL_ALIGN (field, TYPE_ALIGN (ptr_type_node));
bc7bff74 2158 insert_field_into_struct (ctx->record_type, field);
2159 splay_tree_insert (ctx->field_map, (splay_tree_key) decl,
2160 (splay_tree_value) field);
2161 }
2162 }
2163 break;
2164
56686608 2165 case OMP_CLAUSE__GRIDDIM_:
2166 if (ctx->outer)
2167 {
2168 scan_omp_op (&OMP_CLAUSE__GRIDDIM__SIZE (c), ctx->outer);
2169 scan_omp_op (&OMP_CLAUSE__GRIDDIM__GROUP (c), ctx->outer);
2170 }
2171 break;
2172
1e8e9920 2173 case OMP_CLAUSE_NOWAIT:
2174 case OMP_CLAUSE_ORDERED:
fd6481cf 2175 case OMP_CLAUSE_COLLAPSE:
2176 case OMP_CLAUSE_UNTIED:
2169f33b 2177 case OMP_CLAUSE_MERGEABLE:
bc7bff74 2178 case OMP_CLAUSE_PROC_BIND:
3d483a94 2179 case OMP_CLAUSE_SAFELEN:
43895be5 2180 case OMP_CLAUSE_SIMDLEN:
2181 case OMP_CLAUSE_THREADS:
2182 case OMP_CLAUSE_SIMD:
2183 case OMP_CLAUSE_NOGROUP:
2184 case OMP_CLAUSE_DEFAULTMAP:
ca4c3545 2185 case OMP_CLAUSE_ASYNC:
2186 case OMP_CLAUSE_WAIT:
2187 case OMP_CLAUSE_GANG:
2188 case OMP_CLAUSE_WORKER:
2189 case OMP_CLAUSE_VECTOR:
ef014f95 2190 case OMP_CLAUSE_TILE:
f4f5b4b4 2191 case OMP_CLAUSE_INDEPENDENT:
2192 case OMP_CLAUSE_AUTO:
2193 case OMP_CLAUSE_SEQ:
1e8e9920 2194 break;
2195
bc7bff74 2196 case OMP_CLAUSE_ALIGNED:
2197 decl = OMP_CLAUSE_DECL (c);
2198 if (is_global_var (decl)
2199 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
2200 install_var_local (decl, ctx);
2201 break;
2202
ca4c3545 2203 case OMP_CLAUSE__CACHE_:
1e8e9920 2204 default:
2205 gcc_unreachable ();
2206 }
2207 }
2208
2209 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
2210 {
55d6e7cd 2211 switch (OMP_CLAUSE_CODE (c))
1e8e9920 2212 {
2213 case OMP_CLAUSE_LASTPRIVATE:
2214 /* Let the corresponding firstprivate clause create
2215 the variable. */
75a70cf9 2216 if (OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
fd6481cf 2217 scan_array_reductions = true;
1e8e9920 2218 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
2219 break;
2220 /* FALLTHRU */
2221
1e8e9920 2222 case OMP_CLAUSE_FIRSTPRIVATE:
ca4c3545 2223 case OMP_CLAUSE_PRIVATE:
3d483a94 2224 case OMP_CLAUSE_LINEAR:
43895be5 2225 case OMP_CLAUSE_IS_DEVICE_PTR:
1e8e9920 2226 decl = OMP_CLAUSE_DECL (c);
2227 if (is_variable_sized (decl))
43895be5 2228 {
2229 if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE
2230 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IS_DEVICE_PTR)
2231 && is_gimple_omp_offloaded (ctx->stmt))
2232 {
2233 tree decl2 = DECL_VALUE_EXPR (decl);
2234 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
2235 decl2 = TREE_OPERAND (decl2, 0);
2236 gcc_assert (DECL_P (decl2));
2237 install_var_local (decl2, ctx);
2238 fixup_remapped_decl (decl2, ctx, false);
2239 }
2240 install_var_local (decl, ctx);
2241 }
1e8e9920 2242 fixup_remapped_decl (decl, ctx,
55d6e7cd 2243 OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE
1e8e9920 2244 && OMP_CLAUSE_PRIVATE_DEBUG (c));
43895be5 2245 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
2246 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
1e8e9920 2247 scan_array_reductions = true;
43895be5 2248 break;
2249
2250 case OMP_CLAUSE_REDUCTION:
2251 decl = OMP_CLAUSE_DECL (c);
2252 if (TREE_CODE (decl) != MEM_REF)
2253 {
2254 if (is_variable_sized (decl))
2255 install_var_local (decl, ctx);
2256 fixup_remapped_decl (decl, ctx, false);
2257 }
2258 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
2b536a17 2259 scan_array_reductions = true;
1e8e9920 2260 break;
2261
2262 case OMP_CLAUSE_SHARED:
bc7bff74 2263 /* Ignore shared directives in teams construct. */
2264 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
2265 break;
1e8e9920 2266 decl = OMP_CLAUSE_DECL (c);
43895be5 2267 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
2268 break;
2269 if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
2270 {
2271 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl,
2272 ctx->outer)))
2273 break;
2274 bool by_ref = use_pointer_for_field (decl, ctx);
2275 install_var_field (decl, by_ref, 11, ctx);
2276 break;
2277 }
2278 fixup_remapped_decl (decl, ctx, false);
1e8e9920 2279 break;
2280
bc7bff74 2281 case OMP_CLAUSE_MAP:
ca4c3545 2282 if (!is_gimple_omp_offloaded (ctx->stmt))
bc7bff74 2283 break;
2284 decl = OMP_CLAUSE_DECL (c);
2285 if (DECL_P (decl)
9561765e 2286 && ((OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_FIRSTPRIVATE_POINTER
2287 && (OMP_CLAUSE_MAP_KIND (c)
2288 != GOMP_MAP_FIRSTPRIVATE_REFERENCE))
43895be5 2289 || TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
bc7bff74 2290 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
b0c5e347 2291 && varpool_node::get_create (decl)->offloadable)
bc7bff74 2292 break;
2293 if (DECL_P (decl))
2294 {
43895be5 2295 if ((OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
2296 || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER)
bc7bff74 2297 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
2298 && !COMPLETE_TYPE_P (TREE_TYPE (decl)))
2299 {
2300 tree new_decl = lookup_decl (decl, ctx);
2301 TREE_TYPE (new_decl)
2302 = remap_type (TREE_TYPE (decl), &ctx->cb);
2303 }
2304 else if (DECL_SIZE (decl)
2305 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
2306 {
2307 tree decl2 = DECL_VALUE_EXPR (decl);
2308 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
2309 decl2 = TREE_OPERAND (decl2, 0);
2310 gcc_assert (DECL_P (decl2));
2311 fixup_remapped_decl (decl2, ctx, false);
2312 fixup_remapped_decl (decl, ctx, true);
2313 }
2314 else
2315 fixup_remapped_decl (decl, ctx, false);
2316 }
2317 break;
2318
1e8e9920 2319 case OMP_CLAUSE_COPYPRIVATE:
2320 case OMP_CLAUSE_COPYIN:
2321 case OMP_CLAUSE_DEFAULT:
2322 case OMP_CLAUSE_IF:
2323 case OMP_CLAUSE_NUM_THREADS:
bc7bff74 2324 case OMP_CLAUSE_NUM_TEAMS:
2325 case OMP_CLAUSE_THREAD_LIMIT:
2326 case OMP_CLAUSE_DEVICE:
1e8e9920 2327 case OMP_CLAUSE_SCHEDULE:
bc7bff74 2328 case OMP_CLAUSE_DIST_SCHEDULE:
1e8e9920 2329 case OMP_CLAUSE_NOWAIT:
2330 case OMP_CLAUSE_ORDERED:
fd6481cf 2331 case OMP_CLAUSE_COLLAPSE:
2332 case OMP_CLAUSE_UNTIED:
2169f33b 2333 case OMP_CLAUSE_FINAL:
2334 case OMP_CLAUSE_MERGEABLE:
bc7bff74 2335 case OMP_CLAUSE_PROC_BIND:
3d483a94 2336 case OMP_CLAUSE_SAFELEN:
43895be5 2337 case OMP_CLAUSE_SIMDLEN:
bc7bff74 2338 case OMP_CLAUSE_ALIGNED:
2339 case OMP_CLAUSE_DEPEND:
2340 case OMP_CLAUSE__LOOPTEMP_:
2341 case OMP_CLAUSE_TO:
2342 case OMP_CLAUSE_FROM:
43895be5 2343 case OMP_CLAUSE_PRIORITY:
2344 case OMP_CLAUSE_GRAINSIZE:
2345 case OMP_CLAUSE_NUM_TASKS:
2346 case OMP_CLAUSE_THREADS:
2347 case OMP_CLAUSE_SIMD:
2348 case OMP_CLAUSE_NOGROUP:
2349 case OMP_CLAUSE_DEFAULTMAP:
2350 case OMP_CLAUSE_USE_DEVICE_PTR:
40750995 2351 case OMP_CLAUSE__CILK_FOR_COUNT_:
ca4c3545 2352 case OMP_CLAUSE_ASYNC:
2353 case OMP_CLAUSE_WAIT:
2354 case OMP_CLAUSE_NUM_GANGS:
2355 case OMP_CLAUSE_NUM_WORKERS:
2356 case OMP_CLAUSE_VECTOR_LENGTH:
2357 case OMP_CLAUSE_GANG:
2358 case OMP_CLAUSE_WORKER:
2359 case OMP_CLAUSE_VECTOR:
ef014f95 2360 case OMP_CLAUSE_TILE:
f4f5b4b4 2361 case OMP_CLAUSE_INDEPENDENT:
2362 case OMP_CLAUSE_AUTO:
2363 case OMP_CLAUSE_SEQ:
56686608 2364 case OMP_CLAUSE__GRIDDIM_:
ca4c3545 2365 break;
2366
ca4c3545 2367 case OMP_CLAUSE__CACHE_:
1e8e9920 2368 default:
2369 gcc_unreachable ();
2370 }
2371 }
2372
ca4c3545 2373 gcc_checking_assert (!scan_array_reductions
2374 || !is_gimple_omp_oacc (ctx->stmt));
1e8e9920 2375 if (scan_array_reductions)
d3831f71 2376 {
2377 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
2378 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
2379 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
2380 {
2381 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c), ctx);
2382 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
2383 }
2384 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
2385 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
2386 scan_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
2387 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
2388 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
2389 scan_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
2390 }
1e8e9920 2391}
2392
40750995 2393/* Create a new name for omp child function. Returns an identifier. If
2394 IS_CILK_FOR is true then the suffix for the child function is
2395 "_cilk_for_fn." */
1e8e9920 2396
1e8e9920 2397static tree
40750995 2398create_omp_child_function_name (bool task_copy, bool is_cilk_for)
1e8e9920 2399{
40750995 2400 if (is_cilk_for)
2401 return clone_function_name (current_function_decl, "_cilk_for_fn");
2402 return clone_function_name (current_function_decl,
2403 task_copy ? "_omp_cpyfn" : "_omp_fn");
2404}
2405
2406/* Returns the type of the induction variable for the child function for
2407 _Cilk_for and the types for _high and _low variables based on TYPE. */
2408
2409static tree
2410cilk_for_check_loop_diff_type (tree type)
2411{
2412 if (TYPE_PRECISION (type) <= TYPE_PRECISION (uint32_type_node))
2413 {
2414 if (TYPE_UNSIGNED (type))
2415 return uint32_type_node;
2416 else
2417 return integer_type_node;
2418 }
2419 else
2420 {
2421 if (TYPE_UNSIGNED (type))
2422 return uint64_type_node;
2423 else
2424 return long_long_integer_type_node;
2425 }
1e8e9920 2426}
2427
2428/* Build a decl for the omp child function. It'll not contain a body
2429 yet, just the bare decl. */
2430
2431static void
fd6481cf 2432create_omp_child_function (omp_context *ctx, bool task_copy)
1e8e9920 2433{
2434 tree decl, type, name, t;
2435
40750995 2436 tree cilk_for_count
2437 = (flag_cilkplus && gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL)
2438 ? find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
2439 OMP_CLAUSE__CILK_FOR_COUNT_) : NULL_TREE;
2440 tree cilk_var_type = NULL_TREE;
2441
2442 name = create_omp_child_function_name (task_copy,
2443 cilk_for_count != NULL_TREE);
fd6481cf 2444 if (task_copy)
2445 type = build_function_type_list (void_type_node, ptr_type_node,
2446 ptr_type_node, NULL_TREE);
40750995 2447 else if (cilk_for_count)
2448 {
2449 type = TREE_TYPE (OMP_CLAUSE_OPERAND (cilk_for_count, 0));
2450 cilk_var_type = cilk_for_check_loop_diff_type (type);
2451 type = build_function_type_list (void_type_node, ptr_type_node,
2452 cilk_var_type, cilk_var_type, NULL_TREE);
2453 }
fd6481cf 2454 else
2455 type = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
1e8e9920 2456
40750995 2457 decl = build_decl (gimple_location (ctx->stmt), FUNCTION_DECL, name, type);
1e8e9920 2458
ca4c3545 2459 gcc_checking_assert (!is_gimple_omp_oacc (ctx->stmt)
2460 || !task_copy);
fd6481cf 2461 if (!task_copy)
2462 ctx->cb.dst_fn = decl;
2463 else
75a70cf9 2464 gimple_omp_task_set_copy_fn (ctx->stmt, decl);
1e8e9920 2465
2466 TREE_STATIC (decl) = 1;
2467 TREE_USED (decl) = 1;
2468 DECL_ARTIFICIAL (decl) = 1;
2469 DECL_IGNORED_P (decl) = 0;
2470 TREE_PUBLIC (decl) = 0;
2471 DECL_UNINLINABLE (decl) = 1;
2472 DECL_EXTERNAL (decl) = 0;
2473 DECL_CONTEXT (decl) = NULL_TREE;
773c5ba7 2474 DECL_INITIAL (decl) = make_node (BLOCK);
b0c5e347 2475 if (cgraph_node::get (current_function_decl)->offloadable)
2476 cgraph_node::get_create (decl)->offloadable = 1;
bc7bff74 2477 else
2478 {
2479 omp_context *octx;
2480 for (octx = ctx; octx; octx = octx->outer)
ca4c3545 2481 if (is_gimple_omp_offloaded (octx->stmt))
bc7bff74 2482 {
b0c5e347 2483 cgraph_node::get_create (decl)->offloadable = 1;
5f3001a9 2484 if (ENABLE_OFFLOADING)
2485 g->have_offload = true;
2486
bc7bff74 2487 break;
2488 }
2489 }
1e8e9920 2490
ec12b31a 2491 if (cgraph_node::get_create (decl)->offloadable
2492 && !lookup_attribute ("omp declare target",
2493 DECL_ATTRIBUTES (current_function_decl)))
2494 DECL_ATTRIBUTES (decl)
2495 = tree_cons (get_identifier ("omp target entrypoint"),
2496 NULL_TREE, DECL_ATTRIBUTES (decl));
2497
e60a6f7b 2498 t = build_decl (DECL_SOURCE_LOCATION (decl),
2499 RESULT_DECL, NULL_TREE, void_type_node);
1e8e9920 2500 DECL_ARTIFICIAL (t) = 1;
2501 DECL_IGNORED_P (t) = 1;
8e5b4ed6 2502 DECL_CONTEXT (t) = decl;
1e8e9920 2503 DECL_RESULT (decl) = t;
2504
40750995 2505 /* _Cilk_for's child function requires two extra parameters called
2506 __low and __high that are set the by Cilk runtime when it calls this
2507 function. */
2508 if (cilk_for_count)
2509 {
2510 t = build_decl (DECL_SOURCE_LOCATION (decl),
2511 PARM_DECL, get_identifier ("__high"), cilk_var_type);
2512 DECL_ARTIFICIAL (t) = 1;
2513 DECL_NAMELESS (t) = 1;
2514 DECL_ARG_TYPE (t) = ptr_type_node;
2515 DECL_CONTEXT (t) = current_function_decl;
2516 TREE_USED (t) = 1;
2517 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2518 DECL_ARGUMENTS (decl) = t;
2519
2520 t = build_decl (DECL_SOURCE_LOCATION (decl),
2521 PARM_DECL, get_identifier ("__low"), cilk_var_type);
2522 DECL_ARTIFICIAL (t) = 1;
2523 DECL_NAMELESS (t) = 1;
2524 DECL_ARG_TYPE (t) = ptr_type_node;
2525 DECL_CONTEXT (t) = current_function_decl;
2526 TREE_USED (t) = 1;
2527 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2528 DECL_ARGUMENTS (decl) = t;
2529 }
2530
2531 tree data_name = get_identifier (".omp_data_i");
2532 t = build_decl (DECL_SOURCE_LOCATION (decl), PARM_DECL, data_name,
2533 ptr_type_node);
1e8e9920 2534 DECL_ARTIFICIAL (t) = 1;
84bfaaeb 2535 DECL_NAMELESS (t) = 1;
1e8e9920 2536 DECL_ARG_TYPE (t) = ptr_type_node;
773c5ba7 2537 DECL_CONTEXT (t) = current_function_decl;
1e8e9920 2538 TREE_USED (t) = 1;
43895be5 2539 TREE_READONLY (t) = 1;
40750995 2540 if (cilk_for_count)
2541 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
1e8e9920 2542 DECL_ARGUMENTS (decl) = t;
fd6481cf 2543 if (!task_copy)
2544 ctx->receiver_decl = t;
2545 else
2546 {
e60a6f7b 2547 t = build_decl (DECL_SOURCE_LOCATION (decl),
2548 PARM_DECL, get_identifier (".omp_data_o"),
fd6481cf 2549 ptr_type_node);
2550 DECL_ARTIFICIAL (t) = 1;
84bfaaeb 2551 DECL_NAMELESS (t) = 1;
fd6481cf 2552 DECL_ARG_TYPE (t) = ptr_type_node;
2553 DECL_CONTEXT (t) = current_function_decl;
2554 TREE_USED (t) = 1;
86f2ad37 2555 TREE_ADDRESSABLE (t) = 1;
1767a056 2556 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
fd6481cf 2557 DECL_ARGUMENTS (decl) = t;
2558 }
1e8e9920 2559
48e1416a 2560 /* Allocate memory for the function structure. The call to
773c5ba7 2561 allocate_struct_function clobbers CFUN, so we need to restore
1e8e9920 2562 it afterward. */
87d4aa85 2563 push_struct_function (decl);
75a70cf9 2564 cfun->function_end_locus = gimple_location (ctx->stmt);
9ae1b28a 2565 init_tree_ssa (cfun);
87d4aa85 2566 pop_cfun ();
1e8e9920 2567}
2568
bc7bff74 2569/* Callback for walk_gimple_seq. Check if combined parallel
2570 contains gimple_omp_for_combined_into_p OMP_FOR. */
2571
2572static tree
2573find_combined_for (gimple_stmt_iterator *gsi_p,
2574 bool *handled_ops_p,
2575 struct walk_stmt_info *wi)
2576{
42acab1c 2577 gimple *stmt = gsi_stmt (*gsi_p);
bc7bff74 2578
2579 *handled_ops_p = true;
2580 switch (gimple_code (stmt))
2581 {
2582 WALK_SUBSTMTS;
2583
2584 case GIMPLE_OMP_FOR:
2585 if (gimple_omp_for_combined_into_p (stmt)
43895be5 2586 && gimple_omp_for_kind (stmt)
2587 == *(const enum gf_mask *) (wi->info))
bc7bff74 2588 {
2589 wi->info = stmt;
2590 return integer_zero_node;
2591 }
2592 break;
2593 default:
2594 break;
2595 }
2596 return NULL;
2597}
2598
43895be5 2599/* Add _LOOPTEMP_ clauses on OpenMP parallel or task. */
2600
2601static void
2602add_taskreg_looptemp_clauses (enum gf_mask msk, gimple *stmt,
2603 omp_context *outer_ctx)
2604{
2605 struct walk_stmt_info wi;
2606
2607 memset (&wi, 0, sizeof (wi));
2608 wi.val_only = true;
2609 wi.info = (void *) &msk;
2610 walk_gimple_seq (gimple_omp_body (stmt), find_combined_for, NULL, &wi);
2611 if (wi.info != (void *) &msk)
2612 {
2613 gomp_for *for_stmt = as_a <gomp_for *> ((gimple *) wi.info);
2614 struct omp_for_data fd;
2615 extract_omp_for_data (for_stmt, &fd, NULL);
2616 /* We need two temporaries with fd.loop.v type (istart/iend)
2617 and then (fd.collapse - 1) temporaries with the same
2618 type for count2 ... countN-1 vars if not constant. */
2619 size_t count = 2, i;
2620 tree type = fd.iter_type;
2621 if (fd.collapse > 1
2622 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
2623 {
2624 count += fd.collapse - 1;
9561765e 2625 /* If there are lastprivate clauses on the inner
43895be5 2626 GIMPLE_OMP_FOR, add one more temporaries for the total number
2627 of iterations (product of count1 ... countN-1). */
9561765e 2628 if (find_omp_clause (gimple_omp_for_clauses (for_stmt),
2629 OMP_CLAUSE_LASTPRIVATE))
2630 count++;
2631 else if (msk == GF_OMP_FOR_KIND_FOR
2632 && find_omp_clause (gimple_omp_parallel_clauses (stmt),
2633 OMP_CLAUSE_LASTPRIVATE))
43895be5 2634 count++;
2635 }
2636 for (i = 0; i < count; i++)
2637 {
2638 tree temp = create_tmp_var (type);
2639 tree c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__LOOPTEMP_);
2640 insert_decl_map (&outer_ctx->cb, temp, temp);
2641 OMP_CLAUSE_DECL (c) = temp;
2642 OMP_CLAUSE_CHAIN (c) = gimple_omp_taskreg_clauses (stmt);
2643 gimple_omp_taskreg_set_clauses (stmt, c);
2644 }
2645 }
2646}
2647
1e8e9920 2648/* Scan an OpenMP parallel directive. */
2649
2650static void
75a70cf9 2651scan_omp_parallel (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
1e8e9920 2652{
2653 omp_context *ctx;
2654 tree name;
1a91d914 2655 gomp_parallel *stmt = as_a <gomp_parallel *> (gsi_stmt (*gsi));
1e8e9920 2656
2657 /* Ignore parallel directives with empty bodies, unless there
2658 are copyin clauses. */
2659 if (optimize > 0
75a70cf9 2660 && empty_body_p (gimple_omp_body (stmt))
2661 && find_omp_clause (gimple_omp_parallel_clauses (stmt),
2662 OMP_CLAUSE_COPYIN) == NULL)
1e8e9920 2663 {
75a70cf9 2664 gsi_replace (gsi, gimple_build_nop (), false);
1e8e9920 2665 return;
2666 }
2667
bc7bff74 2668 if (gimple_omp_parallel_combined_p (stmt))
43895be5 2669 add_taskreg_looptemp_clauses (GF_OMP_FOR_KIND_FOR, stmt, outer_ctx);
bc7bff74 2670
75a70cf9 2671 ctx = new_omp_context (stmt, outer_ctx);
37eaded9 2672 taskreg_contexts.safe_push (ctx);
fd6481cf 2673 if (taskreg_nesting_level > 1)
773c5ba7 2674 ctx->is_nested = true;
1e8e9920 2675 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
1e8e9920 2676 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2677 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
1e8e9920 2678 name = create_tmp_var_name (".omp_data_s");
e60a6f7b 2679 name = build_decl (gimple_location (stmt),
2680 TYPE_DECL, name, ctx->record_type);
84bfaaeb 2681 DECL_ARTIFICIAL (name) = 1;
2682 DECL_NAMELESS (name) = 1;
1e8e9920 2683 TYPE_NAME (ctx->record_type) = name;
240131b5 2684 TYPE_ARTIFICIAL (ctx->record_type) = 1;
56686608 2685 if (!gimple_omp_parallel_grid_phony (stmt))
2686 {
2687 create_omp_child_function (ctx, false);
2688 gimple_omp_parallel_set_child_fn (stmt, ctx->cb.dst_fn);
2689 }
1e8e9920 2690
75a70cf9 2691 scan_sharing_clauses (gimple_omp_parallel_clauses (stmt), ctx);
ab129075 2692 scan_omp (gimple_omp_body_ptr (stmt), ctx);
1e8e9920 2693
2694 if (TYPE_FIELDS (ctx->record_type) == NULL)
2695 ctx->record_type = ctx->receiver_decl = NULL;
1e8e9920 2696}
2697
fd6481cf 2698/* Scan an OpenMP task directive. */
2699
2700static void
75a70cf9 2701scan_omp_task (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
fd6481cf 2702{
2703 omp_context *ctx;
75a70cf9 2704 tree name, t;
1a91d914 2705 gomp_task *stmt = as_a <gomp_task *> (gsi_stmt (*gsi));
fd6481cf 2706
2707 /* Ignore task directives with empty bodies. */
2708 if (optimize > 0
75a70cf9 2709 && empty_body_p (gimple_omp_body (stmt)))
fd6481cf 2710 {
75a70cf9 2711 gsi_replace (gsi, gimple_build_nop (), false);
fd6481cf 2712 return;
2713 }
2714
43895be5 2715 if (gimple_omp_task_taskloop_p (stmt))
2716 add_taskreg_looptemp_clauses (GF_OMP_FOR_KIND_TASKLOOP, stmt, outer_ctx);
2717
75a70cf9 2718 ctx = new_omp_context (stmt, outer_ctx);
37eaded9 2719 taskreg_contexts.safe_push (ctx);
fd6481cf 2720 if (taskreg_nesting_level > 1)
2721 ctx->is_nested = true;
2722 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2723 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2724 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2725 name = create_tmp_var_name (".omp_data_s");
e60a6f7b 2726 name = build_decl (gimple_location (stmt),
2727 TYPE_DECL, name, ctx->record_type);
84bfaaeb 2728 DECL_ARTIFICIAL (name) = 1;
2729 DECL_NAMELESS (name) = 1;
fd6481cf 2730 TYPE_NAME (ctx->record_type) = name;
240131b5 2731 TYPE_ARTIFICIAL (ctx->record_type) = 1;
fd6481cf 2732 create_omp_child_function (ctx, false);
75a70cf9 2733 gimple_omp_task_set_child_fn (stmt, ctx->cb.dst_fn);
fd6481cf 2734
75a70cf9 2735 scan_sharing_clauses (gimple_omp_task_clauses (stmt), ctx);
fd6481cf 2736
2737 if (ctx->srecord_type)
2738 {
2739 name = create_tmp_var_name (".omp_data_a");
e60a6f7b 2740 name = build_decl (gimple_location (stmt),
2741 TYPE_DECL, name, ctx->srecord_type);
84bfaaeb 2742 DECL_ARTIFICIAL (name) = 1;
2743 DECL_NAMELESS (name) = 1;
fd6481cf 2744 TYPE_NAME (ctx->srecord_type) = name;
240131b5 2745 TYPE_ARTIFICIAL (ctx->srecord_type) = 1;
fd6481cf 2746 create_omp_child_function (ctx, true);
2747 }
2748
ab129075 2749 scan_omp (gimple_omp_body_ptr (stmt), ctx);
fd6481cf 2750
2751 if (TYPE_FIELDS (ctx->record_type) == NULL)
2752 {
2753 ctx->record_type = ctx->receiver_decl = NULL;
75a70cf9 2754 t = build_int_cst (long_integer_type_node, 0);
2755 gimple_omp_task_set_arg_size (stmt, t);
2756 t = build_int_cst (long_integer_type_node, 1);
2757 gimple_omp_task_set_arg_align (stmt, t);
fd6481cf 2758 }
37eaded9 2759}
2760
2761
2762/* If any decls have been made addressable during scan_omp,
2763 adjust their fields if needed, and layout record types
2764 of parallel/task constructs. */
2765
2766static void
2767finish_taskreg_scan (omp_context *ctx)
2768{
2769 if (ctx->record_type == NULL_TREE)
2770 return;
2771
2772 /* If any task_shared_vars were needed, verify all
2773 OMP_CLAUSE_SHARED clauses on GIMPLE_OMP_{PARALLEL,TASK}
2774 statements if use_pointer_for_field hasn't changed
2775 because of that. If it did, update field types now. */
2776 if (task_shared_vars)
2777 {
2778 tree c;
2779
2780 for (c = gimple_omp_taskreg_clauses (ctx->stmt);
2781 c; c = OMP_CLAUSE_CHAIN (c))
43895be5 2782 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
2783 && !OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
37eaded9 2784 {
2785 tree decl = OMP_CLAUSE_DECL (c);
2786
2787 /* Global variables don't need to be copied,
2788 the receiver side will use them directly. */
2789 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
2790 continue;
2791 if (!bitmap_bit_p (task_shared_vars, DECL_UID (decl))
2792 || !use_pointer_for_field (decl, ctx))
2793 continue;
2794 tree field = lookup_field (decl, ctx);
2795 if (TREE_CODE (TREE_TYPE (field)) == POINTER_TYPE
2796 && TREE_TYPE (TREE_TYPE (field)) == TREE_TYPE (decl))
2797 continue;
2798 TREE_TYPE (field) = build_pointer_type (TREE_TYPE (decl));
2799 TREE_THIS_VOLATILE (field) = 0;
2800 DECL_USER_ALIGN (field) = 0;
5d4b30ea 2801 SET_DECL_ALIGN (field, TYPE_ALIGN (TREE_TYPE (field)));
37eaded9 2802 if (TYPE_ALIGN (ctx->record_type) < DECL_ALIGN (field))
5d4b30ea 2803 SET_TYPE_ALIGN (ctx->record_type, DECL_ALIGN (field));
37eaded9 2804 if (ctx->srecord_type)
2805 {
2806 tree sfield = lookup_sfield (decl, ctx);
2807 TREE_TYPE (sfield) = TREE_TYPE (field);
2808 TREE_THIS_VOLATILE (sfield) = 0;
2809 DECL_USER_ALIGN (sfield) = 0;
5d4b30ea 2810 SET_DECL_ALIGN (sfield, DECL_ALIGN (field));
37eaded9 2811 if (TYPE_ALIGN (ctx->srecord_type) < DECL_ALIGN (sfield))
5d4b30ea 2812 SET_TYPE_ALIGN (ctx->srecord_type, DECL_ALIGN (sfield));
37eaded9 2813 }
2814 }
2815 }
2816
2817 if (gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL)
2818 {
2819 layout_type (ctx->record_type);
2820 fixup_child_record_type (ctx);
2821 }
fd6481cf 2822 else
2823 {
37eaded9 2824 location_t loc = gimple_location (ctx->stmt);
fd6481cf 2825 tree *p, vla_fields = NULL_TREE, *q = &vla_fields;
2826 /* Move VLA fields to the end. */
2827 p = &TYPE_FIELDS (ctx->record_type);
2828 while (*p)
2829 if (!TYPE_SIZE_UNIT (TREE_TYPE (*p))
2830 || ! TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (*p))))
2831 {
2832 *q = *p;
2833 *p = TREE_CHAIN (*p);
2834 TREE_CHAIN (*q) = NULL_TREE;
2835 q = &TREE_CHAIN (*q);
2836 }
2837 else
1767a056 2838 p = &DECL_CHAIN (*p);
fd6481cf 2839 *p = vla_fields;
43895be5 2840 if (gimple_omp_task_taskloop_p (ctx->stmt))
2841 {
2842 /* Move fields corresponding to first and second _looptemp_
2843 clause first. There are filled by GOMP_taskloop
2844 and thus need to be in specific positions. */
2845 tree c1 = gimple_omp_task_clauses (ctx->stmt);
2846 c1 = find_omp_clause (c1, OMP_CLAUSE__LOOPTEMP_);
2847 tree c2 = find_omp_clause (OMP_CLAUSE_CHAIN (c1),
2848 OMP_CLAUSE__LOOPTEMP_);
2849 tree f1 = lookup_field (OMP_CLAUSE_DECL (c1), ctx);
2850 tree f2 = lookup_field (OMP_CLAUSE_DECL (c2), ctx);
2851 p = &TYPE_FIELDS (ctx->record_type);
2852 while (*p)
2853 if (*p == f1 || *p == f2)
2854 *p = DECL_CHAIN (*p);
2855 else
2856 p = &DECL_CHAIN (*p);
2857 DECL_CHAIN (f1) = f2;
2858 DECL_CHAIN (f2) = TYPE_FIELDS (ctx->record_type);
2859 TYPE_FIELDS (ctx->record_type) = f1;
2860 if (ctx->srecord_type)
2861 {
2862 f1 = lookup_sfield (OMP_CLAUSE_DECL (c1), ctx);
2863 f2 = lookup_sfield (OMP_CLAUSE_DECL (c2), ctx);
2864 p = &TYPE_FIELDS (ctx->srecord_type);
2865 while (*p)
2866 if (*p == f1 || *p == f2)
2867 *p = DECL_CHAIN (*p);
2868 else
2869 p = &DECL_CHAIN (*p);
2870 DECL_CHAIN (f1) = f2;
2871 DECL_CHAIN (f2) = TYPE_FIELDS (ctx->srecord_type);
2872 TYPE_FIELDS (ctx->srecord_type) = f1;
2873 }
2874 }
fd6481cf 2875 layout_type (ctx->record_type);
2876 fixup_child_record_type (ctx);
2877 if (ctx->srecord_type)
2878 layout_type (ctx->srecord_type);
37eaded9 2879 tree t = fold_convert_loc (loc, long_integer_type_node,
2880 TYPE_SIZE_UNIT (ctx->record_type));
2881 gimple_omp_task_set_arg_size (ctx->stmt, t);
75a70cf9 2882 t = build_int_cst (long_integer_type_node,
fd6481cf 2883 TYPE_ALIGN_UNIT (ctx->record_type));
37eaded9 2884 gimple_omp_task_set_arg_align (ctx->stmt, t);
fd6481cf 2885 }
2886}
2887
a8e785ba 2888/* Find the enclosing offload context. */
1e8e9920 2889
ca4c3545 2890static omp_context *
2891enclosing_target_ctx (omp_context *ctx)
2892{
a8e785ba 2893 for (; ctx; ctx = ctx->outer)
2894 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TARGET)
2895 break;
2896
ca4c3545 2897 return ctx;
2898}
2899
a8e785ba 2900/* Return true if ctx is part of an oacc kernels region. */
2901
ca4c3545 2902static bool
a8e785ba 2903ctx_in_oacc_kernels_region (omp_context *ctx)
ca4c3545 2904{
a8e785ba 2905 for (;ctx != NULL; ctx = ctx->outer)
2906 {
2907 gimple *stmt = ctx->stmt;
2908 if (gimple_code (stmt) == GIMPLE_OMP_TARGET
2909 && gimple_omp_target_kind (stmt) == GF_OMP_TARGET_KIND_OACC_KERNELS)
2910 return true;
2911 }
2912
2913 return false;
2914}
2915
2916/* Check the parallelism clauses inside a kernels regions.
2917 Until kernels handling moves to use the same loop indirection
2918 scheme as parallel, we need to do this checking early. */
2919
2920static unsigned
2921check_oacc_kernel_gwv (gomp_for *stmt, omp_context *ctx)
2922{
2923 bool checking = true;
2924 unsigned outer_mask = 0;
2925 unsigned this_mask = 0;
2926 bool has_seq = false, has_auto = false;
2927
2928 if (ctx->outer)
2929 outer_mask = check_oacc_kernel_gwv (NULL, ctx->outer);
2930 if (!stmt)
2931 {
2932 checking = false;
2933 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR)
2934 return outer_mask;
2935 stmt = as_a <gomp_for *> (ctx->stmt);
2936 }
2937
2938 for (tree c = gimple_omp_for_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c))
2939 {
2940 switch (OMP_CLAUSE_CODE (c))
2941 {
2942 case OMP_CLAUSE_GANG:
2943 this_mask |= GOMP_DIM_MASK (GOMP_DIM_GANG);
2944 break;
2945 case OMP_CLAUSE_WORKER:
2946 this_mask |= GOMP_DIM_MASK (GOMP_DIM_WORKER);
2947 break;
2948 case OMP_CLAUSE_VECTOR:
2949 this_mask |= GOMP_DIM_MASK (GOMP_DIM_VECTOR);
2950 break;
2951 case OMP_CLAUSE_SEQ:
2952 has_seq = true;
2953 break;
2954 case OMP_CLAUSE_AUTO:
2955 has_auto = true;
2956 break;
2957 default:
2958 break;
2959 }
2960 }
2961
2962 if (checking)
2963 {
2964 if (has_seq && (this_mask || has_auto))
2965 error_at (gimple_location (stmt), "%<seq%> overrides other"
2966 " OpenACC loop specifiers");
2967 else if (has_auto && this_mask)
2968 error_at (gimple_location (stmt), "%<auto%> conflicts with other"
2969 " OpenACC loop specifiers");
2970
2971 if (this_mask & outer_mask)
2972 error_at (gimple_location (stmt), "inner loop uses same"
2973 " OpenACC parallelism as containing loop");
2974 }
2975
2976 return outer_mask | this_mask;
ca4c3545 2977}
2978
2979/* Scan a GIMPLE_OMP_FOR. */
1e8e9920 2980
2981static void
1a91d914 2982scan_omp_for (gomp_for *stmt, omp_context *outer_ctx)
1e8e9920 2983{
773c5ba7 2984 omp_context *ctx;
75a70cf9 2985 size_t i;
ca4c3545 2986 tree clauses = gimple_omp_for_clauses (stmt);
2987
773c5ba7 2988 ctx = new_omp_context (stmt, outer_ctx);
1e8e9920 2989
ca4c3545 2990 if (is_gimple_omp_oacc (stmt))
2991 {
a8e785ba 2992 omp_context *tgt = enclosing_target_ctx (outer_ctx);
2993
2994 if (!tgt || is_oacc_parallel (tgt))
2995 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
2996 {
2997 char const *check = NULL;
2998
2999 switch (OMP_CLAUSE_CODE (c))
3000 {
3001 case OMP_CLAUSE_GANG:
3002 check = "gang";
3003 break;
3004
3005 case OMP_CLAUSE_WORKER:
3006 check = "worker";
3007 break;
3008
3009 case OMP_CLAUSE_VECTOR:
3010 check = "vector";
3011 break;
3012
3013 default:
3014 break;
3015 }
3016
3017 if (check && OMP_CLAUSE_OPERAND (c, 0))
3018 error_at (gimple_location (stmt),
3019 "argument not permitted on %qs clause in"
3020 " OpenACC %<parallel%>", check);
3021 }
3022
3023 if (tgt && is_oacc_kernels (tgt))
3024 {
3025 /* Strip out reductions, as they are not handled yet. */
3026 tree *prev_ptr = &clauses;
3027
3028 while (tree probe = *prev_ptr)
ca4c3545 3029 {
a8e785ba 3030 tree *next_ptr = &OMP_CLAUSE_CHAIN (probe);
3031
3032 if (OMP_CLAUSE_CODE (probe) == OMP_CLAUSE_REDUCTION)
3033 *prev_ptr = *next_ptr;
3034 else
3035 prev_ptr = next_ptr;
ca4c3545 3036 }
a8e785ba 3037
3038 gimple_omp_for_set_clauses (stmt, clauses);
3039 check_oacc_kernel_gwv (stmt, ctx);
ca4c3545 3040 }
3041 }
3042
3043 scan_sharing_clauses (clauses, ctx);
1e8e9920 3044
ab129075 3045 scan_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
75a70cf9 3046 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
fd6481cf 3047 {
75a70cf9 3048 scan_omp_op (gimple_omp_for_index_ptr (stmt, i), ctx);
3049 scan_omp_op (gimple_omp_for_initial_ptr (stmt, i), ctx);
3050 scan_omp_op (gimple_omp_for_final_ptr (stmt, i), ctx);
3051 scan_omp_op (gimple_omp_for_incr_ptr (stmt, i), ctx);
fd6481cf 3052 }
ab129075 3053 scan_omp (gimple_omp_body_ptr (stmt), ctx);
1e8e9920 3054}
3055
3056/* Scan an OpenMP sections directive. */
3057
3058static void
1a91d914 3059scan_omp_sections (gomp_sections *stmt, omp_context *outer_ctx)
1e8e9920 3060{
1e8e9920 3061 omp_context *ctx;
3062
3063 ctx = new_omp_context (stmt, outer_ctx);
75a70cf9 3064 scan_sharing_clauses (gimple_omp_sections_clauses (stmt), ctx);
ab129075 3065 scan_omp (gimple_omp_body_ptr (stmt), ctx);
1e8e9920 3066}
3067
3068/* Scan an OpenMP single directive. */
3069
3070static void
1a91d914 3071scan_omp_single (gomp_single *stmt, omp_context *outer_ctx)
1e8e9920 3072{
1e8e9920 3073 omp_context *ctx;
3074 tree name;
3075
3076 ctx = new_omp_context (stmt, outer_ctx);
3077 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
3078 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
3079 name = create_tmp_var_name (".omp_copy_s");
e60a6f7b 3080 name = build_decl (gimple_location (stmt),
3081 TYPE_DECL, name, ctx->record_type);
1e8e9920 3082 TYPE_NAME (ctx->record_type) = name;
3083
75a70cf9 3084 scan_sharing_clauses (gimple_omp_single_clauses (stmt), ctx);
ab129075 3085 scan_omp (gimple_omp_body_ptr (stmt), ctx);
1e8e9920 3086
3087 if (TYPE_FIELDS (ctx->record_type) == NULL)
3088 ctx->record_type = NULL;
3089 else
3090 layout_type (ctx->record_type);
3091}
3092
12dc9a16 3093/* Return true if the CLAUSES of an omp target guarantee that the base pointers
3094 used in the corresponding offloaded function are restrict. */
3095
3096static bool
3097omp_target_base_pointers_restrict_p (tree clauses)
3098{
3099 /* The analysis relies on the GOMP_MAP_FORCE_* mapping kinds, which are only
3100 used by OpenACC. */
3101 if (flag_openacc == 0)
3102 return false;
3103
3104 /* I. Basic example:
3105
3106 void foo (void)
3107 {
3108 unsigned int a[2], b[2];
3109
3110 #pragma acc kernels \
3111 copyout (a) \
3112 copyout (b)
3113 {
3114 a[0] = 0;
3115 b[0] = 1;
3116 }
3117 }
3118
3119 After gimplification, we have:
3120
3121 #pragma omp target oacc_kernels \
3122 map(force_from:a [len: 8]) \
3123 map(force_from:b [len: 8])
3124 {
3125 a[0] = 0;
3126 b[0] = 1;
3127 }
3128
3129 Because both mappings have the force prefix, we know that they will be
3130 allocated when calling the corresponding offloaded function, which means we
3131 can mark the base pointers for a and b in the offloaded function as
3132 restrict. */
3133
3134 tree c;
3135 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
3136 {
3137 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP)
3138 return false;
3139
3140 switch (OMP_CLAUSE_MAP_KIND (c))
3141 {
3142 case GOMP_MAP_FORCE_ALLOC:
3143 case GOMP_MAP_FORCE_TO:
3144 case GOMP_MAP_FORCE_FROM:
3145 case GOMP_MAP_FORCE_TOFROM:
3146 break;
3147 default:
3148 return false;
3149 }
3150 }
3151
3152 return true;
3153}
3154
ca4c3545 3155/* Scan a GIMPLE_OMP_TARGET. */
bc7bff74 3156
3157static void
1a91d914 3158scan_omp_target (gomp_target *stmt, omp_context *outer_ctx)
bc7bff74 3159{
3160 omp_context *ctx;
3161 tree name;
ca4c3545 3162 bool offloaded = is_gimple_omp_offloaded (stmt);
3163 tree clauses = gimple_omp_target_clauses (stmt);
bc7bff74 3164
3165 ctx = new_omp_context (stmt, outer_ctx);
3166 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
3167 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
3168 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
3169 name = create_tmp_var_name (".omp_data_t");
3170 name = build_decl (gimple_location (stmt),
3171 TYPE_DECL, name, ctx->record_type);
3172 DECL_ARTIFICIAL (name) = 1;
3173 DECL_NAMELESS (name) = 1;
3174 TYPE_NAME (ctx->record_type) = name;
240131b5 3175 TYPE_ARTIFICIAL (ctx->record_type) = 1;
12dc9a16 3176
3177 bool base_pointers_restrict = false;
ca4c3545 3178 if (offloaded)
bc7bff74 3179 {
3180 create_omp_child_function (ctx, false);
3181 gimple_omp_target_set_child_fn (stmt, ctx->cb.dst_fn);
12dc9a16 3182
3183 base_pointers_restrict = omp_target_base_pointers_restrict_p (clauses);
3184 if (base_pointers_restrict
3185 && dump_file && (dump_flags & TDF_DETAILS))
3186 fprintf (dump_file,
3187 "Base pointers in offloaded function are restrict\n");
bc7bff74 3188 }
3189
12dc9a16 3190 scan_sharing_clauses (clauses, ctx, base_pointers_restrict);
bc7bff74 3191 scan_omp (gimple_omp_body_ptr (stmt), ctx);
3192
3193 if (TYPE_FIELDS (ctx->record_type) == NULL)
3194 ctx->record_type = ctx->receiver_decl = NULL;
3195 else
3196 {
3197 TYPE_FIELDS (ctx->record_type)
3198 = nreverse (TYPE_FIELDS (ctx->record_type));
382ecba7 3199 if (flag_checking)
3200 {
3201 unsigned int align = DECL_ALIGN (TYPE_FIELDS (ctx->record_type));
3202 for (tree field = TYPE_FIELDS (ctx->record_type);
3203 field;
3204 field = DECL_CHAIN (field))
3205 gcc_assert (DECL_ALIGN (field) == align);
3206 }
bc7bff74 3207 layout_type (ctx->record_type);
ca4c3545 3208 if (offloaded)
bc7bff74 3209 fixup_child_record_type (ctx);
3210 }
3211}
3212
3213/* Scan an OpenMP teams directive. */
3214
3215static void
1a91d914 3216scan_omp_teams (gomp_teams *stmt, omp_context *outer_ctx)
bc7bff74 3217{
3218 omp_context *ctx = new_omp_context (stmt, outer_ctx);
3219 scan_sharing_clauses (gimple_omp_teams_clauses (stmt), ctx);
3220 scan_omp (gimple_omp_body_ptr (stmt), ctx);
3221}
1e8e9920 3222
ca4c3545 3223/* Check nesting restrictions. */
ab129075 3224static bool
42acab1c 3225check_omp_nesting_restrictions (gimple *stmt, omp_context *ctx)
c1d127dd 3226{
43895be5 3227 tree c;
3228
56686608 3229 if (ctx && gimple_code (ctx->stmt) == GIMPLE_OMP_GRID_BODY)
3230 /* GRID_BODY is an artificial construct, nesting rules will be checked in
3231 the original copy of its contents. */
3232 return true;
3233
ca4c3545 3234 /* No nesting of non-OpenACC STMT (that is, an OpenMP one, or a GOMP builtin)
3235 inside an OpenACC CTX. */
3236 if (!(is_gimple_omp (stmt)
32f692e2 3237 && is_gimple_omp_oacc (stmt))
3238 /* Except for atomic codes that we share with OpenMP. */
3239 && !(gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD
3240 || gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE))
3241 {
3242 if (get_oacc_fn_attrib (cfun->decl) != NULL)
3243 {
3244 error_at (gimple_location (stmt),
3245 "non-OpenACC construct inside of OpenACC routine");
3246 return false;
3247 }
3248 else
3249 for (omp_context *octx = ctx; octx != NULL; octx = octx->outer)
3250 if (is_gimple_omp (octx->stmt)
3251 && is_gimple_omp_oacc (octx->stmt))
3252 {
3253 error_at (gimple_location (stmt),
3254 "non-OpenACC construct inside of OpenACC region");
3255 return false;
3256 }
ca4c3545 3257 }
3258
3d483a94 3259 if (ctx != NULL)
3260 {
3261 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
10c55644 3262 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
3d483a94 3263 {
43895be5 3264 c = NULL_TREE;
3265 if (gimple_code (stmt) == GIMPLE_OMP_ORDERED)
3266 {
3267 c = gimple_omp_ordered_clauses (as_a <gomp_ordered *> (stmt));
7821c1b5 3268 if (find_omp_clause (c, OMP_CLAUSE_SIMD))
3269 {
3270 if (find_omp_clause (c, OMP_CLAUSE_THREADS)
3271 && (ctx->outer == NULL
3272 || !gimple_omp_for_combined_into_p (ctx->stmt)
3273 || gimple_code (ctx->outer->stmt) != GIMPLE_OMP_FOR
3274 || (gimple_omp_for_kind (ctx->outer->stmt)
3275 != GF_OMP_FOR_KIND_FOR)
3276 || !gimple_omp_for_combined_p (ctx->outer->stmt)))
3277 {
3278 error_at (gimple_location (stmt),
3279 "%<ordered simd threads%> must be closely "
3280 "nested inside of %<for simd%> region");
3281 return false;
3282 }
3283 return true;
3284 }
43895be5 3285 }
3d483a94 3286 error_at (gimple_location (stmt),
43895be5 3287 "OpenMP constructs other than %<#pragma omp ordered simd%>"
7821c1b5 3288 " may not be nested inside %<simd%> region");
3d483a94 3289 return false;
3290 }
bc7bff74 3291 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
3292 {
3293 if ((gimple_code (stmt) != GIMPLE_OMP_FOR
3294 || (gimple_omp_for_kind (stmt)
3295 != GF_OMP_FOR_KIND_DISTRIBUTE))
3296 && gimple_code (stmt) != GIMPLE_OMP_PARALLEL)
3297 {
3298 error_at (gimple_location (stmt),
7821c1b5 3299 "only %<distribute%> or %<parallel%> regions are "
3300 "allowed to be strictly nested inside %<teams%> "
3301 "region");
bc7bff74 3302 return false;
3303 }
3304 }
3d483a94 3305 }
75a70cf9 3306 switch (gimple_code (stmt))
c1d127dd 3307 {
75a70cf9 3308 case GIMPLE_OMP_FOR:
10c55644 3309 if (gimple_omp_for_kind (stmt) & GF_OMP_FOR_SIMD)
3d483a94 3310 return true;
bc7bff74 3311 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
3312 {
3313 if (ctx != NULL && gimple_code (ctx->stmt) != GIMPLE_OMP_TEAMS)
3314 {
3315 error_at (gimple_location (stmt),
7821c1b5 3316 "%<distribute%> region must be strictly nested "
3317 "inside %<teams%> construct");
bc7bff74 3318 return false;
3319 }
3320 return true;
3321 }
43895be5 3322 /* We split taskloop into task and nested taskloop in it. */
3323 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_TASKLOOP)
3324 return true;
7a1ed40d 3325 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_OACC_LOOP)
3326 {
3327 bool ok = false;
3328
3329 if (ctx)
3330 switch (gimple_code (ctx->stmt))
3331 {
3332 case GIMPLE_OMP_FOR:
3333 ok = (gimple_omp_for_kind (ctx->stmt)
3334 == GF_OMP_FOR_KIND_OACC_LOOP);
3335 break;
3336
3337 case GIMPLE_OMP_TARGET:
3338 switch (gimple_omp_target_kind (ctx->stmt))
3339 {
3340 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
3341 case GF_OMP_TARGET_KIND_OACC_KERNELS:
3342 ok = true;
3343 break;
3344
3345 default:
3346 break;
3347 }
3348
3349 default:
3350 break;
3351 }
3352 else if (get_oacc_fn_attrib (current_function_decl))
3353 ok = true;
3354 if (!ok)
3355 {
3356 error_at (gimple_location (stmt),
3357 "OpenACC loop directive must be associated with"
3358 " an OpenACC compute region");
3359 return false;
3360 }
3361 }
bc7bff74 3362 /* FALLTHRU */
3363 case GIMPLE_CALL:
3364 if (is_gimple_call (stmt)
3365 && (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3366 == BUILT_IN_GOMP_CANCEL
3367 || DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3368 == BUILT_IN_GOMP_CANCELLATION_POINT))
3369 {
3370 const char *bad = NULL;
3371 const char *kind = NULL;
7821c1b5 3372 const char *construct
3373 = (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3374 == BUILT_IN_GOMP_CANCEL)
3375 ? "#pragma omp cancel"
3376 : "#pragma omp cancellation point";
bc7bff74 3377 if (ctx == NULL)
3378 {
3379 error_at (gimple_location (stmt), "orphaned %qs construct",
7821c1b5 3380 construct);
bc7bff74 3381 return false;
3382 }
6b409616 3383 switch (tree_fits_shwi_p (gimple_call_arg (stmt, 0))
3384 ? tree_to_shwi (gimple_call_arg (stmt, 0))
bc7bff74 3385 : 0)
3386 {
3387 case 1:
3388 if (gimple_code (ctx->stmt) != GIMPLE_OMP_PARALLEL)
3389 bad = "#pragma omp parallel";
3390 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3391 == BUILT_IN_GOMP_CANCEL
3392 && !integer_zerop (gimple_call_arg (stmt, 1)))
3393 ctx->cancellable = true;
3394 kind = "parallel";
3395 break;
3396 case 2:
3397 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
3398 || gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR)
3399 bad = "#pragma omp for";
3400 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3401 == BUILT_IN_GOMP_CANCEL
3402 && !integer_zerop (gimple_call_arg (stmt, 1)))
3403 {
3404 ctx->cancellable = true;
3405 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3406 OMP_CLAUSE_NOWAIT))
3407 warning_at (gimple_location (stmt), 0,
3408 "%<#pragma omp cancel for%> inside "
3409 "%<nowait%> for construct");
3410 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3411 OMP_CLAUSE_ORDERED))
3412 warning_at (gimple_location (stmt), 0,
3413 "%<#pragma omp cancel for%> inside "
3414 "%<ordered%> for construct");
3415 }
3416 kind = "for";
3417 break;
3418 case 4:
3419 if (gimple_code (ctx->stmt) != GIMPLE_OMP_SECTIONS
3420 && gimple_code (ctx->stmt) != GIMPLE_OMP_SECTION)
3421 bad = "#pragma omp sections";
3422 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3423 == BUILT_IN_GOMP_CANCEL
3424 && !integer_zerop (gimple_call_arg (stmt, 1)))
3425 {
3426 if (gimple_code (ctx->stmt) == GIMPLE_OMP_SECTIONS)
3427 {
3428 ctx->cancellable = true;
3429 if (find_omp_clause (gimple_omp_sections_clauses
3430 (ctx->stmt),
3431 OMP_CLAUSE_NOWAIT))
3432 warning_at (gimple_location (stmt), 0,
3433 "%<#pragma omp cancel sections%> inside "
3434 "%<nowait%> sections construct");
3435 }
3436 else
3437 {
3438 gcc_assert (ctx->outer
3439 && gimple_code (ctx->outer->stmt)
3440 == GIMPLE_OMP_SECTIONS);
3441 ctx->outer->cancellable = true;
3442 if (find_omp_clause (gimple_omp_sections_clauses
3443 (ctx->outer->stmt),
3444 OMP_CLAUSE_NOWAIT))
3445 warning_at (gimple_location (stmt), 0,
3446 "%<#pragma omp cancel sections%> inside "
3447 "%<nowait%> sections construct");
3448 }
3449 }
3450 kind = "sections";
3451 break;
3452 case 8:
3453 if (gimple_code (ctx->stmt) != GIMPLE_OMP_TASK)
3454 bad = "#pragma omp task";
3455 else
7821c1b5 3456 {
3457 for (omp_context *octx = ctx->outer;
3458 octx; octx = octx->outer)
3459 {
3460 switch (gimple_code (octx->stmt))
3461 {
3462 case GIMPLE_OMP_TASKGROUP:
3463 break;
3464 case GIMPLE_OMP_TARGET:
3465 if (gimple_omp_target_kind (octx->stmt)
3466 != GF_OMP_TARGET_KIND_REGION)
3467 continue;
3468 /* FALLTHRU */
3469 case GIMPLE_OMP_PARALLEL:
3470 case GIMPLE_OMP_TEAMS:
3471 error_at (gimple_location (stmt),
3472 "%<%s taskgroup%> construct not closely "
3473 "nested inside of %<taskgroup%> region",
3474 construct);
3475 return false;
3476 default:
3477 continue;
3478 }
3479 break;
3480 }
3481 ctx->cancellable = true;
3482 }
bc7bff74 3483 kind = "taskgroup";
3484 break;
3485 default:
3486 error_at (gimple_location (stmt), "invalid arguments");
3487 return false;
3488 }
3489 if (bad)
3490 {
3491 error_at (gimple_location (stmt),
3492 "%<%s %s%> construct not closely nested inside of %qs",
7821c1b5 3493 construct, kind, bad);
bc7bff74 3494 return false;
3495 }
3496 }
3d483a94 3497 /* FALLTHRU */
75a70cf9 3498 case GIMPLE_OMP_SECTIONS:
3499 case GIMPLE_OMP_SINGLE:
c1d127dd 3500 for (; ctx != NULL; ctx = ctx->outer)
75a70cf9 3501 switch (gimple_code (ctx->stmt))
c1d127dd 3502 {
75a70cf9 3503 case GIMPLE_OMP_FOR:
7821c1b5 3504 if (gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR
3505 && gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_TASKLOOP)
3506 break;
3507 /* FALLTHRU */
75a70cf9 3508 case GIMPLE_OMP_SECTIONS:
3509 case GIMPLE_OMP_SINGLE:
3510 case GIMPLE_OMP_ORDERED:
3511 case GIMPLE_OMP_MASTER:
3512 case GIMPLE_OMP_TASK:
bc7bff74 3513 case GIMPLE_OMP_CRITICAL:
75a70cf9 3514 if (is_gimple_call (stmt))
fd6481cf 3515 {
bc7bff74 3516 if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3517 != BUILT_IN_GOMP_BARRIER)
3518 return true;
ab129075 3519 error_at (gimple_location (stmt),
3520 "barrier region may not be closely nested inside "
7821c1b5 3521 "of work-sharing, %<critical%>, %<ordered%>, "
3522 "%<master%>, explicit %<task%> or %<taskloop%> "
3523 "region");
ab129075 3524 return false;
fd6481cf 3525 }
ab129075 3526 error_at (gimple_location (stmt),
3527 "work-sharing region may not be closely nested inside "
7821c1b5 3528 "of work-sharing, %<critical%>, %<ordered%>, "
3529 "%<master%>, explicit %<task%> or %<taskloop%> region");
ab129075 3530 return false;
75a70cf9 3531 case GIMPLE_OMP_PARALLEL:
7821c1b5 3532 case GIMPLE_OMP_TEAMS:
ab129075 3533 return true;
7821c1b5 3534 case GIMPLE_OMP_TARGET:
3535 if (gimple_omp_target_kind (ctx->stmt)
3536 == GF_OMP_TARGET_KIND_REGION)
3537 return true;
3538 break;
c1d127dd 3539 default:
3540 break;
3541 }
3542 break;
75a70cf9 3543 case GIMPLE_OMP_MASTER:
c1d127dd 3544 for (; ctx != NULL; ctx = ctx->outer)
75a70cf9 3545 switch (gimple_code (ctx->stmt))
c1d127dd 3546 {
75a70cf9 3547 case GIMPLE_OMP_FOR:
7821c1b5 3548 if (gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR
3549 && gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_TASKLOOP)
3550 break;
3551 /* FALLTHRU */
75a70cf9 3552 case GIMPLE_OMP_SECTIONS:
3553 case GIMPLE_OMP_SINGLE:
3554 case GIMPLE_OMP_TASK:
ab129075 3555 error_at (gimple_location (stmt),
7821c1b5 3556 "%<master%> region may not be closely nested inside "
3557 "of work-sharing, explicit %<task%> or %<taskloop%> "
3558 "region");
ab129075 3559 return false;
75a70cf9 3560 case GIMPLE_OMP_PARALLEL:
7821c1b5 3561 case GIMPLE_OMP_TEAMS:
ab129075 3562 return true;
7821c1b5 3563 case GIMPLE_OMP_TARGET:
3564 if (gimple_omp_target_kind (ctx->stmt)
3565 == GF_OMP_TARGET_KIND_REGION)
3566 return true;
3567 break;
c1d127dd 3568 default:
3569 break;
3570 }
3571 break;
43895be5 3572 case GIMPLE_OMP_TASK:
3573 for (c = gimple_omp_task_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c))
3574 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
3575 && (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SOURCE
3576 || OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK))
3577 {
3578 enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_KIND (c);
3579 error_at (OMP_CLAUSE_LOCATION (c),
3580 "%<depend(%s)%> is only allowed in %<omp ordered%>",
3581 kind == OMP_CLAUSE_DEPEND_SOURCE ? "source" : "sink");
3582 return false;
3583 }
3584 break;
75a70cf9 3585 case GIMPLE_OMP_ORDERED:
43895be5 3586 for (c = gimple_omp_ordered_clauses (as_a <gomp_ordered *> (stmt));
3587 c; c = OMP_CLAUSE_CHAIN (c))
3588 {
3589 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND)
3590 {
3591 gcc_assert (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_THREADS
7821c1b5 3592 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SIMD);
43895be5 3593 continue;
3594 }
3595 enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_KIND (c);
3596 if (kind == OMP_CLAUSE_DEPEND_SOURCE
3597 || kind == OMP_CLAUSE_DEPEND_SINK)
3598 {
3599 tree oclause;
3600 /* Look for containing ordered(N) loop. */
3601 if (ctx == NULL
3602 || gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
3603 || (oclause
3604 = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3605 OMP_CLAUSE_ORDERED)) == NULL_TREE)
3606 {
3607 error_at (OMP_CLAUSE_LOCATION (c),
7821c1b5 3608 "%<ordered%> construct with %<depend%> clause "
3609 "must be closely nested inside an %<ordered%> "
3610 "loop");
43895be5 3611 return false;
3612 }
3613 else if (OMP_CLAUSE_ORDERED_EXPR (oclause) == NULL_TREE)
3614 {
3615 error_at (OMP_CLAUSE_LOCATION (c),
7821c1b5 3616 "%<ordered%> construct with %<depend%> clause "
3617 "must be closely nested inside a loop with "
3618 "%<ordered%> clause with a parameter");
43895be5 3619 return false;
3620 }
3621 }
3622 else
3623 {
3624 error_at (OMP_CLAUSE_LOCATION (c),
7821c1b5 3625 "invalid depend kind in omp %<ordered%> %<depend%>");
3626 return false;
3627 }
3628 }
3629 c = gimple_omp_ordered_clauses (as_a <gomp_ordered *> (stmt));
3630 if (find_omp_clause (c, OMP_CLAUSE_SIMD))
3631 {
3632 /* ordered simd must be closely nested inside of simd region,
3633 and simd region must not encounter constructs other than
3634 ordered simd, therefore ordered simd may be either orphaned,
3635 or ctx->stmt must be simd. The latter case is handled already
3636 earlier. */
3637 if (ctx != NULL)
3638 {
3639 error_at (gimple_location (stmt),
3640 "%<ordered%> %<simd%> must be closely nested inside "
3641 "%<simd%> region");
43895be5 3642 return false;
3643 }
3644 }
c1d127dd 3645 for (; ctx != NULL; ctx = ctx->outer)
75a70cf9 3646 switch (gimple_code (ctx->stmt))
c1d127dd 3647 {
75a70cf9 3648 case GIMPLE_OMP_CRITICAL:
3649 case GIMPLE_OMP_TASK:
7821c1b5 3650 case GIMPLE_OMP_ORDERED:
3651 ordered_in_taskloop:
ab129075 3652 error_at (gimple_location (stmt),
7821c1b5 3653 "%<ordered%> region may not be closely nested inside "
3654 "of %<critical%>, %<ordered%>, explicit %<task%> or "
3655 "%<taskloop%> region");
ab129075 3656 return false;
75a70cf9 3657 case GIMPLE_OMP_FOR:
7821c1b5 3658 if (gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_TASKLOOP)
3659 goto ordered_in_taskloop;
75a70cf9 3660 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
c1d127dd 3661 OMP_CLAUSE_ORDERED) == NULL)
ab129075 3662 {
3663 error_at (gimple_location (stmt),
7821c1b5 3664 "%<ordered%> region must be closely nested inside "
3665 "a loop region with an %<ordered%> clause");
ab129075 3666 return false;
3667 }
3668 return true;
7821c1b5 3669 case GIMPLE_OMP_TARGET:
3670 if (gimple_omp_target_kind (ctx->stmt)
3671 != GF_OMP_TARGET_KIND_REGION)
3672 break;
3673 /* FALLTHRU */
75a70cf9 3674 case GIMPLE_OMP_PARALLEL:
7821c1b5 3675 case GIMPLE_OMP_TEAMS:
bc7bff74 3676 error_at (gimple_location (stmt),
7821c1b5 3677 "%<ordered%> region must be closely nested inside "
3678 "a loop region with an %<ordered%> clause");
bc7bff74 3679 return false;
c1d127dd 3680 default:
3681 break;
3682 }
3683 break;
75a70cf9 3684 case GIMPLE_OMP_CRITICAL:
1a91d914 3685 {
3686 tree this_stmt_name
3687 = gimple_omp_critical_name (as_a <gomp_critical *> (stmt));
3688 for (; ctx != NULL; ctx = ctx->outer)
3689 if (gomp_critical *other_crit
3690 = dyn_cast <gomp_critical *> (ctx->stmt))
3691 if (this_stmt_name == gimple_omp_critical_name (other_crit))
3692 {
3693 error_at (gimple_location (stmt),
7821c1b5 3694 "%<critical%> region may not be nested inside "
3695 "a %<critical%> region with the same name");
1a91d914 3696 return false;
3697 }
3698 }
c1d127dd 3699 break;
bc7bff74 3700 case GIMPLE_OMP_TEAMS:
3701 if (ctx == NULL
3702 || gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET
3703 || gimple_omp_target_kind (ctx->stmt) != GF_OMP_TARGET_KIND_REGION)
3704 {
3705 error_at (gimple_location (stmt),
7821c1b5 3706 "%<teams%> construct not closely nested inside of "
3707 "%<target%> construct");
bc7bff74 3708 return false;
3709 }
3710 break;
691447ab 3711 case GIMPLE_OMP_TARGET:
43895be5 3712 for (c = gimple_omp_target_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c))
3713 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
3714 && (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SOURCE
3715 || OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK))
3716 {
3717 enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_KIND (c);
3718 error_at (OMP_CLAUSE_LOCATION (c),
3719 "%<depend(%s)%> is only allowed in %<omp ordered%>",
3720 kind == OMP_CLAUSE_DEPEND_SOURCE ? "source" : "sink");
3721 return false;
3722 }
32f692e2 3723 if (is_gimple_omp_offloaded (stmt)
3724 && get_oacc_fn_attrib (cfun->decl) != NULL)
3725 {
3726 error_at (gimple_location (stmt),
3727 "OpenACC region inside of OpenACC routine, nested "
3728 "parallelism not supported yet");
3729 return false;
3730 }
691447ab 3731 for (; ctx != NULL; ctx = ctx->outer)
ca4c3545 3732 {
3733 if (gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET)
3734 {
3735 if (is_gimple_omp (stmt)
3736 && is_gimple_omp_oacc (stmt)
3737 && is_gimple_omp (ctx->stmt))
3738 {
3739 error_at (gimple_location (stmt),
3740 "OpenACC construct inside of non-OpenACC region");
3741 return false;
3742 }
3743 continue;
3744 }
3745
3746 const char *stmt_name, *ctx_stmt_name;
3747 switch (gimple_omp_target_kind (stmt))
3748 {
3749 case GF_OMP_TARGET_KIND_REGION: stmt_name = "target"; break;
3750 case GF_OMP_TARGET_KIND_DATA: stmt_name = "target data"; break;
3751 case GF_OMP_TARGET_KIND_UPDATE: stmt_name = "target update"; break;
43895be5 3752 case GF_OMP_TARGET_KIND_ENTER_DATA:
3753 stmt_name = "target enter data"; break;
3754 case GF_OMP_TARGET_KIND_EXIT_DATA:
3755 stmt_name = "target exit data"; break;
ca4c3545 3756 case GF_OMP_TARGET_KIND_OACC_PARALLEL: stmt_name = "parallel"; break;
3757 case GF_OMP_TARGET_KIND_OACC_KERNELS: stmt_name = "kernels"; break;
3758 case GF_OMP_TARGET_KIND_OACC_DATA: stmt_name = "data"; break;
3759 case GF_OMP_TARGET_KIND_OACC_UPDATE: stmt_name = "update"; break;
43895be5 3760 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
3761 stmt_name = "enter/exit data"; break;
571b3486 3762 case GF_OMP_TARGET_KIND_OACC_HOST_DATA: stmt_name = "host_data";
3763 break;
ca4c3545 3764 default: gcc_unreachable ();
3765 }
3766 switch (gimple_omp_target_kind (ctx->stmt))
3767 {
3768 case GF_OMP_TARGET_KIND_REGION: ctx_stmt_name = "target"; break;
3769 case GF_OMP_TARGET_KIND_DATA: ctx_stmt_name = "target data"; break;
43895be5 3770 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
3771 ctx_stmt_name = "parallel"; break;
3772 case GF_OMP_TARGET_KIND_OACC_KERNELS:
3773 ctx_stmt_name = "kernels"; break;
ca4c3545 3774 case GF_OMP_TARGET_KIND_OACC_DATA: ctx_stmt_name = "data"; break;
571b3486 3775 case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
3776 ctx_stmt_name = "host_data"; break;
ca4c3545 3777 default: gcc_unreachable ();
3778 }
3779
3780 /* OpenACC/OpenMP mismatch? */
3781 if (is_gimple_omp_oacc (stmt)
3782 != is_gimple_omp_oacc (ctx->stmt))
3783 {
3784 error_at (gimple_location (stmt),
7821c1b5 3785 "%s %qs construct inside of %s %qs region",
ca4c3545 3786 (is_gimple_omp_oacc (stmt)
3787 ? "OpenACC" : "OpenMP"), stmt_name,
3788 (is_gimple_omp_oacc (ctx->stmt)
3789 ? "OpenACC" : "OpenMP"), ctx_stmt_name);
3790 return false;
3791 }
3792 if (is_gimple_omp_offloaded (ctx->stmt))
3793 {
3794 /* No GIMPLE_OMP_TARGET inside offloaded OpenACC CTX. */
3795 if (is_gimple_omp_oacc (ctx->stmt))
3796 {
3797 error_at (gimple_location (stmt),
7821c1b5 3798 "%qs construct inside of %qs region",
ca4c3545 3799 stmt_name, ctx_stmt_name);
3800 return false;
3801 }
3802 else
3803 {
ca4c3545 3804 warning_at (gimple_location (stmt), 0,
7821c1b5 3805 "%qs construct inside of %qs region",
ca4c3545 3806 stmt_name, ctx_stmt_name);
3807 }
3808 }
3809 }
691447ab 3810 break;
c1d127dd 3811 default:
3812 break;
3813 }
ab129075 3814 return true;
c1d127dd 3815}
3816
3817
75a70cf9 3818/* Helper function scan_omp.
3819
3820 Callback for walk_tree or operators in walk_gimple_stmt used to
ca4c3545 3821 scan for OMP directives in TP. */
1e8e9920 3822
3823static tree
75a70cf9 3824scan_omp_1_op (tree *tp, int *walk_subtrees, void *data)
1e8e9920 3825{
4077bf7a 3826 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
3827 omp_context *ctx = (omp_context *) wi->info;
1e8e9920 3828 tree t = *tp;
3829
75a70cf9 3830 switch (TREE_CODE (t))
3831 {
3832 case VAR_DECL:
3833 case PARM_DECL:
3834 case LABEL_DECL:
3835 case RESULT_DECL:
3836 if (ctx)
56686608 3837 {
3838 tree repl = remap_decl (t, &ctx->cb);
3839 gcc_checking_assert (TREE_CODE (repl) != ERROR_MARK);
3840 *tp = repl;
3841 }
75a70cf9 3842 break;
3843
3844 default:
3845 if (ctx && TYPE_P (t))
3846 *tp = remap_type (t, &ctx->cb);
3847 else if (!DECL_P (t))
7cf869dd 3848 {
3849 *walk_subtrees = 1;
3850 if (ctx)
182cf5a9 3851 {
3852 tree tem = remap_type (TREE_TYPE (t), &ctx->cb);
3853 if (tem != TREE_TYPE (t))
3854 {
3855 if (TREE_CODE (t) == INTEGER_CST)
e913b5cd 3856 *tp = wide_int_to_tree (tem, t);
182cf5a9 3857 else
3858 TREE_TYPE (t) = tem;
3859 }
3860 }
7cf869dd 3861 }
75a70cf9 3862 break;
3863 }
3864
3865 return NULL_TREE;
3866}
3867
f2697631 3868/* Return true if FNDECL is a setjmp or a longjmp. */
3869
3870static bool
3871setjmp_or_longjmp_p (const_tree fndecl)
3872{
3873 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
3874 && (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_SETJMP
3875 || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_LONGJMP))
3876 return true;
3877
3878 tree declname = DECL_NAME (fndecl);
3879 if (!declname)
3880 return false;
3881 const char *name = IDENTIFIER_POINTER (declname);
3882 return !strcmp (name, "setjmp") || !strcmp (name, "longjmp");
3883}
3884
75a70cf9 3885
3886/* Helper function for scan_omp.
3887
ca4c3545 3888 Callback for walk_gimple_stmt used to scan for OMP directives in
75a70cf9 3889 the current statement in GSI. */
3890
3891static tree
3892scan_omp_1_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
3893 struct walk_stmt_info *wi)
3894{
42acab1c 3895 gimple *stmt = gsi_stmt (*gsi);
75a70cf9 3896 omp_context *ctx = (omp_context *) wi->info;
3897
3898 if (gimple_has_location (stmt))
3899 input_location = gimple_location (stmt);
1e8e9920 3900
ca4c3545 3901 /* Check the nesting restrictions. */
bc7bff74 3902 bool remove = false;
3903 if (is_gimple_omp (stmt))
3904 remove = !check_omp_nesting_restrictions (stmt, ctx);
3905 else if (is_gimple_call (stmt))
3906 {
3907 tree fndecl = gimple_call_fndecl (stmt);
f2697631 3908 if (fndecl)
3909 {
3910 if (setjmp_or_longjmp_p (fndecl)
3911 && ctx
3912 && gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
10c55644 3913 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
f2697631 3914 {
3915 remove = true;
3916 error_at (gimple_location (stmt),
3917 "setjmp/longjmp inside simd construct");
3918 }
3919 else if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
3920 switch (DECL_FUNCTION_CODE (fndecl))
3921 {
3922 case BUILT_IN_GOMP_BARRIER:
3923 case BUILT_IN_GOMP_CANCEL:
3924 case BUILT_IN_GOMP_CANCELLATION_POINT:
3925 case BUILT_IN_GOMP_TASKYIELD:
3926 case BUILT_IN_GOMP_TASKWAIT:
3927 case BUILT_IN_GOMP_TASKGROUP_START:
3928 case BUILT_IN_GOMP_TASKGROUP_END:
3929 remove = !check_omp_nesting_restrictions (stmt, ctx);
3930 break;
3931 default:
3932 break;
3933 }
3934 }
bc7bff74 3935 }
3936 if (remove)
3937 {
3938 stmt = gimple_build_nop ();
3939 gsi_replace (gsi, stmt, false);
fd6481cf 3940 }
c1d127dd 3941
75a70cf9 3942 *handled_ops_p = true;
3943
3944 switch (gimple_code (stmt))
1e8e9920 3945 {
75a70cf9 3946 case GIMPLE_OMP_PARALLEL:
fd6481cf 3947 taskreg_nesting_level++;
75a70cf9 3948 scan_omp_parallel (gsi, ctx);
fd6481cf 3949 taskreg_nesting_level--;
3950 break;
3951
75a70cf9 3952 case GIMPLE_OMP_TASK:
fd6481cf 3953 taskreg_nesting_level++;
75a70cf9 3954 scan_omp_task (gsi, ctx);
fd6481cf 3955 taskreg_nesting_level--;
1e8e9920 3956 break;
3957
75a70cf9 3958 case GIMPLE_OMP_FOR:
1a91d914 3959 scan_omp_for (as_a <gomp_for *> (stmt), ctx);
1e8e9920 3960 break;
3961
75a70cf9 3962 case GIMPLE_OMP_SECTIONS:
1a91d914 3963 scan_omp_sections (as_a <gomp_sections *> (stmt), ctx);
1e8e9920 3964 break;
3965
75a70cf9 3966 case GIMPLE_OMP_SINGLE:
1a91d914 3967 scan_omp_single (as_a <gomp_single *> (stmt), ctx);
1e8e9920 3968 break;
3969
75a70cf9 3970 case GIMPLE_OMP_SECTION:
3971 case GIMPLE_OMP_MASTER:
bc7bff74 3972 case GIMPLE_OMP_TASKGROUP:
75a70cf9 3973 case GIMPLE_OMP_ORDERED:
3974 case GIMPLE_OMP_CRITICAL:
56686608 3975 case GIMPLE_OMP_GRID_BODY:
75a70cf9 3976 ctx = new_omp_context (stmt, ctx);
ab129075 3977 scan_omp (gimple_omp_body_ptr (stmt), ctx);
1e8e9920 3978 break;
3979
bc7bff74 3980 case GIMPLE_OMP_TARGET:
1a91d914 3981 scan_omp_target (as_a <gomp_target *> (stmt), ctx);
bc7bff74 3982 break;
3983
3984 case GIMPLE_OMP_TEAMS:
1a91d914 3985 scan_omp_teams (as_a <gomp_teams *> (stmt), ctx);
bc7bff74 3986 break;
3987
75a70cf9 3988 case GIMPLE_BIND:
1e8e9920 3989 {
3990 tree var;
1e8e9920 3991
75a70cf9 3992 *handled_ops_p = false;
3993 if (ctx)
1a91d914 3994 for (var = gimple_bind_vars (as_a <gbind *> (stmt));
3995 var ;
3996 var = DECL_CHAIN (var))
75a70cf9 3997 insert_decl_map (&ctx->cb, var, var);
1e8e9920 3998 }
3999 break;
1e8e9920 4000 default:
75a70cf9 4001 *handled_ops_p = false;
1e8e9920 4002 break;
4003 }
4004
4005 return NULL_TREE;
4006}
4007
4008
75a70cf9 4009/* Scan all the statements starting at the current statement. CTX
ca4c3545 4010 contains context information about the OMP directives and
75a70cf9 4011 clauses found during the scan. */
1e8e9920 4012
4013static void
ab129075 4014scan_omp (gimple_seq *body_p, omp_context *ctx)
1e8e9920 4015{
4016 location_t saved_location;
4017 struct walk_stmt_info wi;
4018
4019 memset (&wi, 0, sizeof (wi));
1e8e9920 4020 wi.info = ctx;
1e8e9920 4021 wi.want_locations = true;
4022
4023 saved_location = input_location;
ab129075 4024 walk_gimple_seq_mod (body_p, scan_omp_1_stmt, scan_omp_1_op, &wi);
1e8e9920 4025 input_location = saved_location;
4026}
4027\f
4028/* Re-gimplification and code generation routines. */
4029
4030/* Build a call to GOMP_barrier. */
4031
42acab1c 4032static gimple *
bc7bff74 4033build_omp_barrier (tree lhs)
4034{
4035 tree fndecl = builtin_decl_explicit (lhs ? BUILT_IN_GOMP_BARRIER_CANCEL
4036 : BUILT_IN_GOMP_BARRIER);
1a91d914 4037 gcall *g = gimple_build_call (fndecl, 0);
bc7bff74 4038 if (lhs)
4039 gimple_call_set_lhs (g, lhs);
4040 return g;
1e8e9920 4041}
4042
4043/* If a context was created for STMT when it was scanned, return it. */
4044
4045static omp_context *
42acab1c 4046maybe_lookup_ctx (gimple *stmt)
1e8e9920 4047{
4048 splay_tree_node n;
4049 n = splay_tree_lookup (all_contexts, (splay_tree_key) stmt);
4050 return n ? (omp_context *) n->value : NULL;
4051}
4052
773c5ba7 4053
4054/* Find the mapping for DECL in CTX or the immediately enclosing
4055 context that has a mapping for DECL.
4056
4057 If CTX is a nested parallel directive, we may have to use the decl
4058 mappings created in CTX's parent context. Suppose that we have the
4059 following parallel nesting (variable UIDs showed for clarity):
4060
4061 iD.1562 = 0;
4062 #omp parallel shared(iD.1562) -> outer parallel
4063 iD.1562 = iD.1562 + 1;
4064
4065 #omp parallel shared (iD.1562) -> inner parallel
4066 iD.1562 = iD.1562 - 1;
4067
4068 Each parallel structure will create a distinct .omp_data_s structure
4069 for copying iD.1562 in/out of the directive:
4070
4071 outer parallel .omp_data_s.1.i -> iD.1562
4072 inner parallel .omp_data_s.2.i -> iD.1562
4073
4074 A shared variable mapping will produce a copy-out operation before
4075 the parallel directive and a copy-in operation after it. So, in
4076 this case we would have:
4077
4078 iD.1562 = 0;
4079 .omp_data_o.1.i = iD.1562;
4080 #omp parallel shared(iD.1562) -> outer parallel
4081 .omp_data_i.1 = &.omp_data_o.1
4082 .omp_data_i.1->i = .omp_data_i.1->i + 1;
4083
4084 .omp_data_o.2.i = iD.1562; -> **
4085 #omp parallel shared(iD.1562) -> inner parallel
4086 .omp_data_i.2 = &.omp_data_o.2
4087 .omp_data_i.2->i = .omp_data_i.2->i - 1;
4088
4089
4090 ** This is a problem. The symbol iD.1562 cannot be referenced
4091 inside the body of the outer parallel region. But since we are
4092 emitting this copy operation while expanding the inner parallel
4093 directive, we need to access the CTX structure of the outer
4094 parallel directive to get the correct mapping:
4095
4096 .omp_data_o.2.i = .omp_data_i.1->i
4097
4098 Since there may be other workshare or parallel directives enclosing
4099 the parallel directive, it may be necessary to walk up the context
4100 parent chain. This is not a problem in general because nested
4101 parallelism happens only rarely. */
4102
4103static tree
4104lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
4105{
4106 tree t;
4107 omp_context *up;
4108
773c5ba7 4109 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
4110 t = maybe_lookup_decl (decl, up);
4111
87b31375 4112 gcc_assert (!ctx->is_nested || t || is_global_var (decl));
773c5ba7 4113
c37594c7 4114 return t ? t : decl;
773c5ba7 4115}
4116
4117
f49d7bb5 4118/* Similar to lookup_decl_in_outer_ctx, but return DECL if not found
4119 in outer contexts. */
4120
4121static tree
4122maybe_lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
4123{
4124 tree t = NULL;
4125 omp_context *up;
4126
87b31375 4127 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
4128 t = maybe_lookup_decl (decl, up);
f49d7bb5 4129
4130 return t ? t : decl;
4131}
4132
4133
df67b98c 4134/* Construct the initialization value for reduction operation OP. */
1e8e9920 4135
4136tree
df67b98c 4137omp_reduction_init_op (location_t loc, enum tree_code op, tree type)
1e8e9920 4138{
df67b98c 4139 switch (op)
1e8e9920 4140 {
4141 case PLUS_EXPR:
4142 case MINUS_EXPR:
4143 case BIT_IOR_EXPR:
4144 case BIT_XOR_EXPR:
4145 case TRUTH_OR_EXPR:
4146 case TRUTH_ORIF_EXPR:
4147 case TRUTH_XOR_EXPR:
4148 case NE_EXPR:
385f3f36 4149 return build_zero_cst (type);
1e8e9920 4150
4151 case MULT_EXPR:
4152 case TRUTH_AND_EXPR:
4153 case TRUTH_ANDIF_EXPR:
4154 case EQ_EXPR:
389dd41b 4155 return fold_convert_loc (loc, type, integer_one_node);
1e8e9920 4156
4157 case BIT_AND_EXPR:
389dd41b 4158 return fold_convert_loc (loc, type, integer_minus_one_node);
1e8e9920 4159
4160 case MAX_EXPR:
4161 if (SCALAR_FLOAT_TYPE_P (type))
4162 {
4163 REAL_VALUE_TYPE max, min;
fe994837 4164 if (HONOR_INFINITIES (type))
1e8e9920 4165 {
4166 real_inf (&max);
4167 real_arithmetic (&min, NEGATE_EXPR, &max, NULL);
4168 }
4169 else
4170 real_maxval (&min, 1, TYPE_MODE (type));
4171 return build_real (type, min);
4172 }
5902cce5 4173 else if (POINTER_TYPE_P (type))
4174 {
4175 wide_int min
4176 = wi::min_value (TYPE_PRECISION (type), TYPE_SIGN (type));
4177 return wide_int_to_tree (type, min);
4178 }
1e8e9920 4179 else
4180 {
4181 gcc_assert (INTEGRAL_TYPE_P (type));
4182 return TYPE_MIN_VALUE (type);
4183 }
4184
4185 case MIN_EXPR:
4186 if (SCALAR_FLOAT_TYPE_P (type))
4187 {
4188 REAL_VALUE_TYPE max;
fe994837 4189 if (HONOR_INFINITIES (type))
1e8e9920 4190 real_inf (&max);
4191 else
4192 real_maxval (&max, 0, TYPE_MODE (type));
4193 return build_real (type, max);
4194 }
5902cce5 4195 else if (POINTER_TYPE_P (type))
4196 {
4197 wide_int max
4198 = wi::max_value (TYPE_PRECISION (type), TYPE_SIGN (type));
4199 return wide_int_to_tree (type, max);
4200 }
1e8e9920 4201 else
4202 {
4203 gcc_assert (INTEGRAL_TYPE_P (type));
4204 return TYPE_MAX_VALUE (type);
4205 }
4206
4207 default:
4208 gcc_unreachable ();
4209 }
4210}
4211
df67b98c 4212/* Construct the initialization value for reduction CLAUSE. */
4213
4214tree
4215omp_reduction_init (tree clause, tree type)
4216{
4217 return omp_reduction_init_op (OMP_CLAUSE_LOCATION (clause),
4218 OMP_CLAUSE_REDUCTION_CODE (clause), type);
4219}
4220
bc7bff74 4221/* Return alignment to be assumed for var in CLAUSE, which should be
4222 OMP_CLAUSE_ALIGNED. */
4223
4224static tree
4225omp_clause_aligned_alignment (tree clause)
4226{
4227 if (OMP_CLAUSE_ALIGNED_ALIGNMENT (clause))
4228 return OMP_CLAUSE_ALIGNED_ALIGNMENT (clause);
4229
4230 /* Otherwise return implementation defined alignment. */
4231 unsigned int al = 1;
3754d046 4232 machine_mode mode, vmode;
bc7bff74 4233 int vs = targetm.vectorize.autovectorize_vector_sizes ();
4234 if (vs)
4235 vs = 1 << floor_log2 (vs);
4236 static enum mode_class classes[]
4237 = { MODE_INT, MODE_VECTOR_INT, MODE_FLOAT, MODE_VECTOR_FLOAT };
4238 for (int i = 0; i < 4; i += 2)
4239 for (mode = GET_CLASS_NARROWEST_MODE (classes[i]);
4240 mode != VOIDmode;
4241 mode = GET_MODE_WIDER_MODE (mode))
4242 {
4243 vmode = targetm.vectorize.preferred_simd_mode (mode);
4244 if (GET_MODE_CLASS (vmode) != classes[i + 1])
4245 continue;
4246 while (vs
4247 && GET_MODE_SIZE (vmode) < vs
4248 && GET_MODE_2XWIDER_MODE (vmode) != VOIDmode)
4249 vmode = GET_MODE_2XWIDER_MODE (vmode);
4250
4251 tree type = lang_hooks.types.type_for_mode (mode, 1);
4252 if (type == NULL_TREE || TYPE_MODE (type) != mode)
4253 continue;
4254 type = build_vector_type (type, GET_MODE_SIZE (vmode)
4255 / GET_MODE_SIZE (mode));
4256 if (TYPE_MODE (type) != vmode)
4257 continue;
4258 if (TYPE_ALIGN_UNIT (type) > al)
4259 al = TYPE_ALIGN_UNIT (type);
4260 }
4261 return build_int_cst (integer_type_node, al);
4262}
4263
3d483a94 4264/* Return maximum possible vectorization factor for the target. */
4265
4266static int
4267omp_max_vf (void)
4268{
4269 if (!optimize
4270 || optimize_debug
ad45e43e 4271 || !flag_tree_loop_optimize
043115ec 4272 || (!flag_tree_loop_vectorize
4273 && (global_options_set.x_flag_tree_loop_vectorize
4274 || global_options_set.x_flag_tree_vectorize)))
3d483a94 4275 return 1;
4276
4277 int vs = targetm.vectorize.autovectorize_vector_sizes ();
4278 if (vs)
4279 {
4280 vs = 1 << floor_log2 (vs);
4281 return vs;
4282 }
3754d046 4283 machine_mode vqimode = targetm.vectorize.preferred_simd_mode (QImode);
3d483a94 4284 if (GET_MODE_CLASS (vqimode) == MODE_VECTOR_INT)
4285 return GET_MODE_NUNITS (vqimode);
4286 return 1;
4287}
4288
4289/* Helper function of lower_rec_input_clauses, used for #pragma omp simd
4290 privatization. */
4291
4292static bool
4293lower_rec_simd_input_clauses (tree new_var, omp_context *ctx, int &max_vf,
4294 tree &idx, tree &lane, tree &ivar, tree &lvar)
4295{
4296 if (max_vf == 0)
4297 {
4298 max_vf = omp_max_vf ();
4299 if (max_vf > 1)
4300 {
4301 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
4302 OMP_CLAUSE_SAFELEN);
c3f3b68d 4303 if (c && TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c)) != INTEGER_CST)
4304 max_vf = 1;
4305 else if (c && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
4306 max_vf) == -1)
d85a2013 4307 max_vf = tree_to_shwi (OMP_CLAUSE_SAFELEN_EXPR (c));
3d483a94 4308 }
4309 if (max_vf > 1)
4310 {
f9e245b2 4311 idx = create_tmp_var (unsigned_type_node);
4312 lane = create_tmp_var (unsigned_type_node);
3d483a94 4313 }
4314 }
4315 if (max_vf == 1)
4316 return false;
4317
4318 tree atype = build_array_type_nelts (TREE_TYPE (new_var), max_vf);
f9e245b2 4319 tree avar = create_tmp_var_raw (atype);
3d483a94 4320 if (TREE_ADDRESSABLE (new_var))
4321 TREE_ADDRESSABLE (avar) = 1;
4322 DECL_ATTRIBUTES (avar)
4323 = tree_cons (get_identifier ("omp simd array"), NULL,
4324 DECL_ATTRIBUTES (avar));
4325 gimple_add_tmp_var (avar);
4326 ivar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, idx,
4327 NULL_TREE, NULL_TREE);
4328 lvar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, lane,
4329 NULL_TREE, NULL_TREE);
bc7bff74 4330 if (DECL_P (new_var))
4331 {
4332 SET_DECL_VALUE_EXPR (new_var, lvar);
4333 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
4334 }
3d483a94 4335 return true;
4336}
4337
2712b6de 4338/* Helper function of lower_rec_input_clauses. For a reference
4339 in simd reduction, add an underlying variable it will reference. */
4340
4341static void
4342handle_simd_reference (location_t loc, tree new_vard, gimple_seq *ilist)
4343{
4344 tree z = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_vard)));
4345 if (TREE_CONSTANT (z))
4346 {
43895be5 4347 z = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_vard)),
4348 get_name (new_vard));
2712b6de 4349 gimple_add_tmp_var (z);
4350 TREE_ADDRESSABLE (z) = 1;
4351 z = build_fold_addr_expr_loc (loc, z);
4352 gimplify_assign (new_vard, z, ilist);
4353 }
4354}
4355
1e8e9920 4356/* Generate code to implement the input clauses, FIRSTPRIVATE and COPYIN,
4357 from the receiver (aka child) side and initializers for REFERENCE_TYPE
4358 private variables. Initialization statements go in ILIST, while calls
4359 to destructors go in DLIST. */
4360
4361static void
75a70cf9 4362lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
bc7bff74 4363 omp_context *ctx, struct omp_for_data *fd)
1e8e9920 4364{
c2f47e15 4365 tree c, dtor, copyin_seq, x, ptr;
1e8e9920 4366 bool copyin_by_ref = false;
f49d7bb5 4367 bool lastprivate_firstprivate = false;
bc7bff74 4368 bool reduction_omp_orig_ref = false;
1e8e9920 4369 int pass;
3d483a94 4370 bool is_simd = (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
10c55644 4371 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD);
3d483a94 4372 int max_vf = 0;
4373 tree lane = NULL_TREE, idx = NULL_TREE;
4374 tree ivar = NULL_TREE, lvar = NULL_TREE;
4375 gimple_seq llist[2] = { NULL, NULL };
1e8e9920 4376
1e8e9920 4377 copyin_seq = NULL;
4378
3d483a94 4379 /* Set max_vf=1 (which will later enforce safelen=1) in simd loops
4380 with data sharing clauses referencing variable sized vars. That
4381 is unnecessarily hard to support and very unlikely to result in
4382 vectorized code anyway. */
4383 if (is_simd)
4384 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4385 switch (OMP_CLAUSE_CODE (c))
4386 {
9580cb79 4387 case OMP_CLAUSE_LINEAR:
4388 if (OMP_CLAUSE_LINEAR_ARRAY (c))
4389 max_vf = 1;
4390 /* FALLTHRU */
3d483a94 4391 case OMP_CLAUSE_PRIVATE:
4392 case OMP_CLAUSE_FIRSTPRIVATE:
4393 case OMP_CLAUSE_LASTPRIVATE:
3d483a94 4394 if (is_variable_sized (OMP_CLAUSE_DECL (c)))
4395 max_vf = 1;
4396 break;
43895be5 4397 case OMP_CLAUSE_REDUCTION:
4398 if (TREE_CODE (OMP_CLAUSE_DECL (c)) == MEM_REF
4399 || is_variable_sized (OMP_CLAUSE_DECL (c)))
4400 max_vf = 1;
4401 break;
3d483a94 4402 default:
4403 continue;
4404 }
4405
1e8e9920 4406 /* Do all the fixed sized types in the first pass, and the variable sized
4407 types in the second pass. This makes sure that the scalar arguments to
48e1416a 4408 the variable sized types are processed before we use them in the
1e8e9920 4409 variable sized operations. */
4410 for (pass = 0; pass < 2; ++pass)
4411 {
4412 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4413 {
55d6e7cd 4414 enum omp_clause_code c_kind = OMP_CLAUSE_CODE (c);
1e8e9920 4415 tree var, new_var;
4416 bool by_ref;
389dd41b 4417 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
1e8e9920 4418
4419 switch (c_kind)
4420 {
4421 case OMP_CLAUSE_PRIVATE:
4422 if (OMP_CLAUSE_PRIVATE_DEBUG (c))
4423 continue;
4424 break;
4425 case OMP_CLAUSE_SHARED:
bc7bff74 4426 /* Ignore shared directives in teams construct. */
4427 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
4428 continue;
f49d7bb5 4429 if (maybe_lookup_decl (OMP_CLAUSE_DECL (c), ctx) == NULL)
4430 {
43895be5 4431 gcc_assert (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c)
4432 || is_global_var (OMP_CLAUSE_DECL (c)));
f49d7bb5 4433 continue;
4434 }
1e8e9920 4435 case OMP_CLAUSE_FIRSTPRIVATE:
1e8e9920 4436 case OMP_CLAUSE_COPYIN:
43895be5 4437 break;
bc7bff74 4438 case OMP_CLAUSE_LINEAR:
43895be5 4439 if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c)
4440 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
4441 lastprivate_firstprivate = true;
bc7bff74 4442 break;
1e8e9920 4443 case OMP_CLAUSE_REDUCTION:
bc7bff74 4444 if (OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c))
4445 reduction_omp_orig_ref = true;
1e8e9920 4446 break;
bc7bff74 4447 case OMP_CLAUSE__LOOPTEMP_:
43895be5 4448 /* Handle _looptemp_ clauses only on parallel/task. */
bc7bff74 4449 if (fd)
4450 continue;
3d483a94 4451 break;
df2c34fc 4452 case OMP_CLAUSE_LASTPRIVATE:
f49d7bb5 4453 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
4454 {
4455 lastprivate_firstprivate = true;
43895be5 4456 if (pass != 0 || is_taskloop_ctx (ctx))
f49d7bb5 4457 continue;
4458 }
cf5f881f 4459 /* Even without corresponding firstprivate, if
4460 decl is Fortran allocatable, it needs outer var
4461 reference. */
4462 else if (pass == 0
4463 && lang_hooks.decls.omp_private_outer_ref
4464 (OMP_CLAUSE_DECL (c)))
4465 lastprivate_firstprivate = true;
df2c34fc 4466 break;
bc7bff74 4467 case OMP_CLAUSE_ALIGNED:
4468 if (pass == 0)
4469 continue;
4470 var = OMP_CLAUSE_DECL (c);
4471 if (TREE_CODE (TREE_TYPE (var)) == POINTER_TYPE
4472 && !is_global_var (var))
4473 {
4474 new_var = maybe_lookup_decl (var, ctx);
4475 if (new_var == NULL_TREE)
4476 new_var = maybe_lookup_decl_in_outer_ctx (var, ctx);
4477 x = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
4478 x = build_call_expr_loc (clause_loc, x, 2, new_var,
4479 omp_clause_aligned_alignment (c));
4480 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
4481 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
4482 gimplify_and_add (x, ilist);
4483 }
4484 else if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE
4485 && is_global_var (var))
4486 {
4487 tree ptype = build_pointer_type (TREE_TYPE (var)), t, t2;
4488 new_var = lookup_decl (var, ctx);
4489 t = maybe_lookup_decl_in_outer_ctx (var, ctx);
4490 t = build_fold_addr_expr_loc (clause_loc, t);
4491 t2 = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
4492 t = build_call_expr_loc (clause_loc, t2, 2, t,
4493 omp_clause_aligned_alignment (c));
4494 t = fold_convert_loc (clause_loc, ptype, t);
f9e245b2 4495 x = create_tmp_var (ptype);
bc7bff74 4496 t = build2 (MODIFY_EXPR, ptype, x, t);
4497 gimplify_and_add (t, ilist);
4498 t = build_simple_mem_ref_loc (clause_loc, x);
4499 SET_DECL_VALUE_EXPR (new_var, t);
4500 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
4501 }
4502 continue;
1e8e9920 4503 default:
4504 continue;
4505 }
4506
4507 new_var = var = OMP_CLAUSE_DECL (c);
43895be5 4508 if (c_kind == OMP_CLAUSE_REDUCTION && TREE_CODE (var) == MEM_REF)
4509 {
4510 var = TREE_OPERAND (var, 0);
9561765e 4511 if (TREE_CODE (var) == POINTER_PLUS_EXPR)
4512 var = TREE_OPERAND (var, 0);
43895be5 4513 if (TREE_CODE (var) == INDIRECT_REF
4514 || TREE_CODE (var) == ADDR_EXPR)
4515 var = TREE_OPERAND (var, 0);
4516 if (is_variable_sized (var))
4517 {
4518 gcc_assert (DECL_HAS_VALUE_EXPR_P (var));
4519 var = DECL_VALUE_EXPR (var);
4520 gcc_assert (TREE_CODE (var) == INDIRECT_REF);
4521 var = TREE_OPERAND (var, 0);
4522 gcc_assert (DECL_P (var));
4523 }
4524 new_var = var;
4525 }
1e8e9920 4526 if (c_kind != OMP_CLAUSE_COPYIN)
4527 new_var = lookup_decl (var, ctx);
4528
4529 if (c_kind == OMP_CLAUSE_SHARED || c_kind == OMP_CLAUSE_COPYIN)
4530 {
4531 if (pass != 0)
4532 continue;
4533 }
43895be5 4534 /* C/C++ array section reductions. */
4535 else if (c_kind == OMP_CLAUSE_REDUCTION
4536 && var != OMP_CLAUSE_DECL (c))
1e8e9920 4537 {
4538 if (pass == 0)
4539 continue;
4540
9561765e 4541 tree bias = TREE_OPERAND (OMP_CLAUSE_DECL (c), 1);
43895be5 4542 tree orig_var = TREE_OPERAND (OMP_CLAUSE_DECL (c), 0);
9561765e 4543 if (TREE_CODE (orig_var) == POINTER_PLUS_EXPR)
4544 {
4545 tree b = TREE_OPERAND (orig_var, 1);
4546 b = maybe_lookup_decl (b, ctx);
4547 if (b == NULL)
4548 {
4549 b = TREE_OPERAND (orig_var, 1);
4550 b = maybe_lookup_decl_in_outer_ctx (b, ctx);
4551 }
4552 if (integer_zerop (bias))
4553 bias = b;
4554 else
4555 {
4556 bias = fold_convert_loc (clause_loc,
4557 TREE_TYPE (b), bias);
4558 bias = fold_build2_loc (clause_loc, PLUS_EXPR,
4559 TREE_TYPE (b), b, bias);
4560 }
4561 orig_var = TREE_OPERAND (orig_var, 0);
4562 }
43895be5 4563 if (TREE_CODE (orig_var) == INDIRECT_REF
4564 || TREE_CODE (orig_var) == ADDR_EXPR)
4565 orig_var = TREE_OPERAND (orig_var, 0);
4566 tree d = OMP_CLAUSE_DECL (c);
4567 tree type = TREE_TYPE (d);
4568 gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
4569 tree v = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
4570 const char *name = get_name (orig_var);
4571 if (TREE_CONSTANT (v))
fd6481cf 4572 {
43895be5 4573 x = create_tmp_var_raw (type, name);
4574 gimple_add_tmp_var (x);
4575 TREE_ADDRESSABLE (x) = 1;
4576 x = build_fold_addr_expr_loc (clause_loc, x);
4577 }
4578 else
4579 {
4580 tree atmp
4581 = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
4582 tree t = maybe_lookup_decl (v, ctx);
4583 if (t)
4584 v = t;
4585 else
4586 v = maybe_lookup_decl_in_outer_ctx (v, ctx);
4587 gimplify_expr (&v, ilist, NULL, is_gimple_val, fb_rvalue);
4588 t = fold_build2_loc (clause_loc, PLUS_EXPR,
4589 TREE_TYPE (v), v,
4590 build_int_cst (TREE_TYPE (v), 1));
4591 t = fold_build2_loc (clause_loc, MULT_EXPR,
4592 TREE_TYPE (v), t,
4593 TYPE_SIZE_UNIT (TREE_TYPE (type)));
4594 tree al = size_int (TYPE_ALIGN (TREE_TYPE (type)));
4595 x = build_call_expr_loc (clause_loc, atmp, 2, t, al);
4596 }
4597
4598 tree ptype = build_pointer_type (TREE_TYPE (type));
4599 x = fold_convert_loc (clause_loc, ptype, x);
4600 tree y = create_tmp_var (ptype, name);
4601 gimplify_assign (y, x, ilist);
4602 x = y;
9561765e 4603 tree yb = y;
4604
4605 if (!integer_zerop (bias))
4606 {
219e09fc 4607 bias = fold_convert_loc (clause_loc, pointer_sized_int_node,
4608 bias);
4609 yb = fold_convert_loc (clause_loc, pointer_sized_int_node,
4610 x);
4611 yb = fold_build2_loc (clause_loc, MINUS_EXPR,
4612 pointer_sized_int_node, yb, bias);
4613 x = fold_convert_loc (clause_loc, TREE_TYPE (x), yb);
9561765e 4614 yb = create_tmp_var (ptype, name);
4615 gimplify_assign (yb, x, ilist);
4616 x = yb;
4617 }
4618
4619 d = TREE_OPERAND (d, 0);
4620 if (TREE_CODE (d) == POINTER_PLUS_EXPR)
4621 d = TREE_OPERAND (d, 0);
4622 if (TREE_CODE (d) == ADDR_EXPR)
43895be5 4623 {
4624 if (orig_var != var)
4625 {
4626 gcc_assert (is_variable_sized (orig_var));
4627 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var),
4628 x);
4629 gimplify_assign (new_var, x, ilist);
4630 tree new_orig_var = lookup_decl (orig_var, ctx);
4631 tree t = build_fold_indirect_ref (new_var);
4632 DECL_IGNORED_P (new_var) = 0;
4633 TREE_THIS_NOTRAP (t);
4634 SET_DECL_VALUE_EXPR (new_orig_var, t);
4635 DECL_HAS_VALUE_EXPR_P (new_orig_var) = 1;
4636 }
4637 else
4638 {
4639 x = build2 (MEM_REF, TREE_TYPE (new_var), x,
4640 build_int_cst (ptype, 0));
4641 SET_DECL_VALUE_EXPR (new_var, x);
4642 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
4643 }
4644 }
4645 else
4646 {
4647 gcc_assert (orig_var == var);
9561765e 4648 if (TREE_CODE (d) == INDIRECT_REF)
43895be5 4649 {
4650 x = create_tmp_var (ptype, name);
4651 TREE_ADDRESSABLE (x) = 1;
9561765e 4652 gimplify_assign (x, yb, ilist);
43895be5 4653 x = build_fold_addr_expr_loc (clause_loc, x);
4654 }
4655 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
4656 gimplify_assign (new_var, x, ilist);
4657 }
4658 tree y1 = create_tmp_var (ptype, NULL);
4659 gimplify_assign (y1, y, ilist);
4660 tree i2 = NULL_TREE, y2 = NULL_TREE;
4661 tree body2 = NULL_TREE, end2 = NULL_TREE;
4662 tree y3 = NULL_TREE, y4 = NULL_TREE;
4663 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) || is_simd)
4664 {
4665 y2 = create_tmp_var (ptype, NULL);
4666 gimplify_assign (y2, y, ilist);
4667 tree ref = build_outer_var_ref (var, ctx);
4668 /* For ref build_outer_var_ref already performs this. */
9561765e 4669 if (TREE_CODE (d) == INDIRECT_REF)
43895be5 4670 gcc_assert (is_reference (var));
9561765e 4671 else if (TREE_CODE (d) == ADDR_EXPR)
43895be5 4672 ref = build_fold_addr_expr (ref);
4673 else if (is_reference (var))
4674 ref = build_fold_addr_expr (ref);
4675 ref = fold_convert_loc (clause_loc, ptype, ref);
4676 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)
4677 && OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c))
4678 {
4679 y3 = create_tmp_var (ptype, NULL);
4680 gimplify_assign (y3, unshare_expr (ref), ilist);
4681 }
4682 if (is_simd)
4683 {
4684 y4 = create_tmp_var (ptype, NULL);
4685 gimplify_assign (y4, ref, dlist);
4686 }
4687 }
4688 tree i = create_tmp_var (TREE_TYPE (v), NULL);
4689 gimplify_assign (i, build_int_cst (TREE_TYPE (v), 0), ilist);
4690 tree body = create_artificial_label (UNKNOWN_LOCATION);
4691 tree end = create_artificial_label (UNKNOWN_LOCATION);
4692 gimple_seq_add_stmt (ilist, gimple_build_label (body));
4693 if (y2)
4694 {
4695 i2 = create_tmp_var (TREE_TYPE (v), NULL);
4696 gimplify_assign (i2, build_int_cst (TREE_TYPE (v), 0), dlist);
4697 body2 = create_artificial_label (UNKNOWN_LOCATION);
4698 end2 = create_artificial_label (UNKNOWN_LOCATION);
4699 gimple_seq_add_stmt (dlist, gimple_build_label (body2));
4700 }
4701 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4702 {
4703 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
4704 tree decl_placeholder
4705 = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c);
4706 SET_DECL_VALUE_EXPR (decl_placeholder,
4707 build_simple_mem_ref (y1));
4708 DECL_HAS_VALUE_EXPR_P (decl_placeholder) = 1;
4709 SET_DECL_VALUE_EXPR (placeholder,
4710 y3 ? build_simple_mem_ref (y3)
4711 : error_mark_node);
4712 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
4713 x = lang_hooks.decls.omp_clause_default_ctor
4714 (c, build_simple_mem_ref (y1),
4715 y3 ? build_simple_mem_ref (y3) : NULL_TREE);
4716 if (x)
4717 gimplify_and_add (x, ilist);
4718 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
4719 {
4720 gimple_seq tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
4721 lower_omp (&tseq, ctx);
4722 gimple_seq_add_seq (ilist, tseq);
4723 }
4724 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
4725 if (is_simd)
4726 {
4727 SET_DECL_VALUE_EXPR (decl_placeholder,
4728 build_simple_mem_ref (y2));
4729 SET_DECL_VALUE_EXPR (placeholder,
4730 build_simple_mem_ref (y4));
4731 gimple_seq tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
4732 lower_omp (&tseq, ctx);
4733 gimple_seq_add_seq (dlist, tseq);
4734 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
4735 }
4736 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
4737 DECL_HAS_VALUE_EXPR_P (decl_placeholder) = 0;
4738 x = lang_hooks.decls.omp_clause_dtor
4739 (c, build_simple_mem_ref (y2));
4740 if (x)
4741 {
4742 gimple_seq tseq = NULL;
4743 dtor = x;
4744 gimplify_stmt (&dtor, &tseq);
4745 gimple_seq_add_seq (dlist, tseq);
4746 }
4747 }
4748 else
4749 {
4750 x = omp_reduction_init (c, TREE_TYPE (type));
4751 enum tree_code code = OMP_CLAUSE_REDUCTION_CODE (c);
4752
4753 /* reduction(-:var) sums up the partial results, so it
4754 acts identically to reduction(+:var). */
4755 if (code == MINUS_EXPR)
4756 code = PLUS_EXPR;
4757
4758 gimplify_assign (build_simple_mem_ref (y1), x, ilist);
4759 if (is_simd)
4760 {
4761 x = build2 (code, TREE_TYPE (type),
4762 build_simple_mem_ref (y4),
4763 build_simple_mem_ref (y2));
4764 gimplify_assign (build_simple_mem_ref (y4), x, dlist);
4765 }
4766 }
4767 gimple *g
4768 = gimple_build_assign (y1, POINTER_PLUS_EXPR, y1,
4769 TYPE_SIZE_UNIT (TREE_TYPE (type)));
4770 gimple_seq_add_stmt (ilist, g);
4771 if (y3)
4772 {
4773 g = gimple_build_assign (y3, POINTER_PLUS_EXPR, y3,
4774 TYPE_SIZE_UNIT (TREE_TYPE (type)));
4775 gimple_seq_add_stmt (ilist, g);
4776 }
4777 g = gimple_build_assign (i, PLUS_EXPR, i,
4778 build_int_cst (TREE_TYPE (i), 1));
4779 gimple_seq_add_stmt (ilist, g);
4780 g = gimple_build_cond (LE_EXPR, i, v, body, end);
4781 gimple_seq_add_stmt (ilist, g);
4782 gimple_seq_add_stmt (ilist, gimple_build_label (end));
4783 if (y2)
4784 {
4785 g = gimple_build_assign (y2, POINTER_PLUS_EXPR, y2,
4786 TYPE_SIZE_UNIT (TREE_TYPE (type)));
4787 gimple_seq_add_stmt (dlist, g);
4788 if (y4)
4789 {
4790 g = gimple_build_assign
4791 (y4, POINTER_PLUS_EXPR, y4,
4792 TYPE_SIZE_UNIT (TREE_TYPE (type)));
4793 gimple_seq_add_stmt (dlist, g);
4794 }
4795 g = gimple_build_assign (i2, PLUS_EXPR, i2,
4796 build_int_cst (TREE_TYPE (i2), 1));
4797 gimple_seq_add_stmt (dlist, g);
4798 g = gimple_build_cond (LE_EXPR, i2, v, body2, end2);
4799 gimple_seq_add_stmt (dlist, g);
4800 gimple_seq_add_stmt (dlist, gimple_build_label (end2));
4801 }
4802 continue;
4803 }
4804 else if (is_variable_sized (var))
4805 {
4806 /* For variable sized types, we need to allocate the
4807 actual storage here. Call alloca and store the
4808 result in the pointer decl that we created elsewhere. */
4809 if (pass == 0)
4810 continue;
4811
4812 if (c_kind != OMP_CLAUSE_FIRSTPRIVATE || !is_task_ctx (ctx))
4813 {
4814 gcall *stmt;
4815 tree tmp, atmp;
4816
4817 ptr = DECL_VALUE_EXPR (new_var);
4818 gcc_assert (TREE_CODE (ptr) == INDIRECT_REF);
4819 ptr = TREE_OPERAND (ptr, 0);
fd6481cf 4820 gcc_assert (DECL_P (ptr));
4821 x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
75a70cf9 4822
4823 /* void *tmp = __builtin_alloca */
43895be5 4824 atmp = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
4825 stmt = gimple_build_call (atmp, 2, x,
4826 size_int (DECL_ALIGN (var)));
f9e245b2 4827 tmp = create_tmp_var_raw (ptr_type_node);
75a70cf9 4828 gimple_add_tmp_var (tmp);
4829 gimple_call_set_lhs (stmt, tmp);
4830
4831 gimple_seq_add_stmt (ilist, stmt);
4832
389dd41b 4833 x = fold_convert_loc (clause_loc, TREE_TYPE (ptr), tmp);
75a70cf9 4834 gimplify_assign (ptr, x, ilist);
fd6481cf 4835 }
1e8e9920 4836 }
0c302595 4837 else if (is_reference (var))
1e8e9920 4838 {
773c5ba7 4839 /* For references that are being privatized for Fortran,
4840 allocate new backing storage for the new pointer
4841 variable. This allows us to avoid changing all the
4842 code that expects a pointer to something that expects
bc7bff74 4843 a direct variable. */
1e8e9920 4844 if (pass == 0)
4845 continue;
4846
4847 x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
fd6481cf 4848 if (c_kind == OMP_CLAUSE_FIRSTPRIVATE && is_task_ctx (ctx))
4849 {
4850 x = build_receiver_ref (var, false, ctx);
389dd41b 4851 x = build_fold_addr_expr_loc (clause_loc, x);
fd6481cf 4852 }
4853 else if (TREE_CONSTANT (x))
1e8e9920 4854 {
2712b6de 4855 /* For reduction in SIMD loop, defer adding the
4856 initialization of the reference, because if we decide
4857 to use SIMD array for it, the initilization could cause
4858 expansion ICE. */
4859 if (c_kind == OMP_CLAUSE_REDUCTION && is_simd)
09d1c205 4860 x = NULL_TREE;
4861 else
4862 {
09d1c205 4863 x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)),
43895be5 4864 get_name (var));
09d1c205 4865 gimple_add_tmp_var (x);
4866 TREE_ADDRESSABLE (x) = 1;
4867 x = build_fold_addr_expr_loc (clause_loc, x);
4868 }
1e8e9920 4869 }
4870 else
4871 {
43895be5 4872 tree atmp
4873 = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
4874 tree rtype = TREE_TYPE (TREE_TYPE (new_var));
4875 tree al = size_int (TYPE_ALIGN (rtype));
4876 x = build_call_expr_loc (clause_loc, atmp, 2, x, al);
1e8e9920 4877 }
4878
09d1c205 4879 if (x)
4880 {
4881 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
4882 gimplify_assign (new_var, x, ilist);
4883 }
1e8e9920 4884
182cf5a9 4885 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
1e8e9920 4886 }
4887 else if (c_kind == OMP_CLAUSE_REDUCTION
4888 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4889 {
4890 if (pass == 0)
4891 continue;
4892 }
4893 else if (pass != 0)
4894 continue;
4895
55d6e7cd 4896 switch (OMP_CLAUSE_CODE (c))
1e8e9920 4897 {
4898 case OMP_CLAUSE_SHARED:
bc7bff74 4899 /* Ignore shared directives in teams construct. */
4900 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
4901 continue;
f49d7bb5 4902 /* Shared global vars are just accessed directly. */
4903 if (is_global_var (new_var))
4904 break;
43895be5 4905 /* For taskloop firstprivate/lastprivate, represented
4906 as firstprivate and shared clause on the task, new_var
4907 is the firstprivate var. */
4908 if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
4909 break;
1e8e9920 4910 /* Set up the DECL_VALUE_EXPR for shared variables now. This
4911 needs to be delayed until after fixup_child_record_type so
4912 that we get the correct type during the dereference. */
e8a588af 4913 by_ref = use_pointer_for_field (var, ctx);
1e8e9920 4914 x = build_receiver_ref (var, by_ref, ctx);
4915 SET_DECL_VALUE_EXPR (new_var, x);
4916 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
4917
4918 /* ??? If VAR is not passed by reference, and the variable
4919 hasn't been initialized yet, then we'll get a warning for
4920 the store into the omp_data_s structure. Ideally, we'd be
48e1416a 4921 able to notice this and not store anything at all, but
1e8e9920 4922 we're generating code too early. Suppress the warning. */
4923 if (!by_ref)
4924 TREE_NO_WARNING (var) = 1;
4925 break;
4926
4927 case OMP_CLAUSE_LASTPRIVATE:
4928 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
4929 break;
4930 /* FALLTHRU */
4931
4932 case OMP_CLAUSE_PRIVATE:
fd6481cf 4933 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_PRIVATE)
4934 x = build_outer_var_ref (var, ctx);
4935 else if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
4936 {
4937 if (is_task_ctx (ctx))
4938 x = build_receiver_ref (var, false, ctx);
4939 else
4940 x = build_outer_var_ref (var, ctx);
4941 }
4942 else
4943 x = NULL;
3d483a94 4944 do_private:
bc7bff74 4945 tree nx;
43895be5 4946 nx = lang_hooks.decls.omp_clause_default_ctor
4947 (c, unshare_expr (new_var), x);
3d483a94 4948 if (is_simd)
4949 {
4950 tree y = lang_hooks.decls.omp_clause_dtor (c, new_var);
bc7bff74 4951 if ((TREE_ADDRESSABLE (new_var) || nx || y
3d483a94 4952 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE)
4953 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
4954 idx, lane, ivar, lvar))
4955 {
bc7bff74 4956 if (nx)
3d483a94 4957 x = lang_hooks.decls.omp_clause_default_ctor
4958 (c, unshare_expr (ivar), x);
bc7bff74 4959 if (nx && x)
3d483a94 4960 gimplify_and_add (x, &llist[0]);
4961 if (y)
4962 {
4963 y = lang_hooks.decls.omp_clause_dtor (c, ivar);
4964 if (y)
4965 {
4966 gimple_seq tseq = NULL;
4967
4968 dtor = y;
4969 gimplify_stmt (&dtor, &tseq);
4970 gimple_seq_add_seq (&llist[1], tseq);
4971 }
4972 }
4973 break;
4974 }
4975 }
bc7bff74 4976 if (nx)
4977 gimplify_and_add (nx, ilist);
1e8e9920 4978 /* FALLTHRU */
4979
4980 do_dtor:
4981 x = lang_hooks.decls.omp_clause_dtor (c, new_var);
4982 if (x)
4983 {
75a70cf9 4984 gimple_seq tseq = NULL;
4985
1e8e9920 4986 dtor = x;
75a70cf9 4987 gimplify_stmt (&dtor, &tseq);
e3a19533 4988 gimple_seq_add_seq (dlist, tseq);
1e8e9920 4989 }
4990 break;
4991
3d483a94 4992 case OMP_CLAUSE_LINEAR:
4993 if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c))
4994 goto do_firstprivate;
4995 if (OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
4996 x = NULL;
4997 else
4998 x = build_outer_var_ref (var, ctx);
4999 goto do_private;
5000
1e8e9920 5001 case OMP_CLAUSE_FIRSTPRIVATE:
fd6481cf 5002 if (is_task_ctx (ctx))
5003 {
5004 if (is_reference (var) || is_variable_sized (var))
5005 goto do_dtor;
5006 else if (is_global_var (maybe_lookup_decl_in_outer_ctx (var,
5007 ctx))
5008 || use_pointer_for_field (var, NULL))
5009 {
5010 x = build_receiver_ref (var, false, ctx);
5011 SET_DECL_VALUE_EXPR (new_var, x);
5012 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
5013 goto do_dtor;
5014 }
5015 }
3d483a94 5016 do_firstprivate:
1e8e9920 5017 x = build_outer_var_ref (var, ctx);
3d483a94 5018 if (is_simd)
5019 {
bc7bff74 5020 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
5021 && gimple_omp_for_combined_into_p (ctx->stmt))
5022 {
9580cb79 5023 tree t = OMP_CLAUSE_LINEAR_STEP (c);
5024 tree stept = TREE_TYPE (t);
5025 tree ct = find_omp_clause (clauses,
5026 OMP_CLAUSE__LOOPTEMP_);
5027 gcc_assert (ct);
5028 tree l = OMP_CLAUSE_DECL (ct);
e471cc6f 5029 tree n1 = fd->loop.n1;
5030 tree step = fd->loop.step;
5031 tree itype = TREE_TYPE (l);
5032 if (POINTER_TYPE_P (itype))
5033 itype = signed_type_for (itype);
5034 l = fold_build2 (MINUS_EXPR, itype, l, n1);
5035 if (TYPE_UNSIGNED (itype)
5036 && fd->loop.cond_code == GT_EXPR)
5037 l = fold_build2 (TRUNC_DIV_EXPR, itype,
5038 fold_build1 (NEGATE_EXPR, itype, l),
5039 fold_build1 (NEGATE_EXPR,
5040 itype, step));
5041 else
5042 l = fold_build2 (TRUNC_DIV_EXPR, itype, l, step);
bc7bff74 5043 t = fold_build2 (MULT_EXPR, stept,
5044 fold_convert (stept, l), t);
9580cb79 5045
5046 if (OMP_CLAUSE_LINEAR_ARRAY (c))
5047 {
5048 x = lang_hooks.decls.omp_clause_linear_ctor
5049 (c, new_var, x, t);
5050 gimplify_and_add (x, ilist);
5051 goto do_dtor;
5052 }
5053
bc7bff74 5054 if (POINTER_TYPE_P (TREE_TYPE (x)))
5055 x = fold_build2 (POINTER_PLUS_EXPR,
5056 TREE_TYPE (x), x, t);
5057 else
5058 x = fold_build2 (PLUS_EXPR, TREE_TYPE (x), x, t);
5059 }
5060
3d483a94 5061 if ((OMP_CLAUSE_CODE (c) != OMP_CLAUSE_LINEAR
5062 || TREE_ADDRESSABLE (new_var))
5063 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
5064 idx, lane, ivar, lvar))
5065 {
5066 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR)
5067 {
f9e245b2 5068 tree iv = create_tmp_var (TREE_TYPE (new_var));
3d483a94 5069 x = lang_hooks.decls.omp_clause_copy_ctor (c, iv, x);
5070 gimplify_and_add (x, ilist);
5071 gimple_stmt_iterator gsi
5072 = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
1a91d914 5073 gassign *g
3d483a94 5074 = gimple_build_assign (unshare_expr (lvar), iv);
5075 gsi_insert_before_without_update (&gsi, g,
5076 GSI_SAME_STMT);
9580cb79 5077 tree t = OMP_CLAUSE_LINEAR_STEP (c);
3d483a94 5078 enum tree_code code = PLUS_EXPR;
5079 if (POINTER_TYPE_P (TREE_TYPE (new_var)))
5080 code = POINTER_PLUS_EXPR;
e9cf809e 5081 g = gimple_build_assign (iv, code, iv, t);
3d483a94 5082 gsi_insert_before_without_update (&gsi, g,
5083 GSI_SAME_STMT);
5084 break;
5085 }
5086 x = lang_hooks.decls.omp_clause_copy_ctor
5087 (c, unshare_expr (ivar), x);
5088 gimplify_and_add (x, &llist[0]);
5089 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
5090 if (x)
5091 {
5092 gimple_seq tseq = NULL;
5093
5094 dtor = x;
5095 gimplify_stmt (&dtor, &tseq);
5096 gimple_seq_add_seq (&llist[1], tseq);
5097 }
5098 break;
5099 }
5100 }
43895be5 5101 x = lang_hooks.decls.omp_clause_copy_ctor
5102 (c, unshare_expr (new_var), x);
1e8e9920 5103 gimplify_and_add (x, ilist);
5104 goto do_dtor;
1e8e9920 5105
bc7bff74 5106 case OMP_CLAUSE__LOOPTEMP_:
43895be5 5107 gcc_assert (is_taskreg_ctx (ctx));
bc7bff74 5108 x = build_outer_var_ref (var, ctx);
5109 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
5110 gimplify_and_add (x, ilist);
5111 break;
5112
1e8e9920 5113 case OMP_CLAUSE_COPYIN:
e8a588af 5114 by_ref = use_pointer_for_field (var, NULL);
1e8e9920 5115 x = build_receiver_ref (var, by_ref, ctx);
5116 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, x);
5117 append_to_statement_list (x, &copyin_seq);
5118 copyin_by_ref |= by_ref;
5119 break;
5120
5121 case OMP_CLAUSE_REDUCTION:
641a0fa1 5122 /* OpenACC reductions are initialized using the
5123 GOACC_REDUCTION internal function. */
5124 if (is_gimple_omp_oacc (ctx->stmt))
5125 break;
1e8e9920 5126 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
5127 {
fd6481cf 5128 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
42acab1c 5129 gimple *tseq;
fd6481cf 5130 x = build_outer_var_ref (var, ctx);
5131
bc7bff74 5132 if (is_reference (var)
5133 && !useless_type_conversion_p (TREE_TYPE (placeholder),
5134 TREE_TYPE (x)))
389dd41b 5135 x = build_fold_addr_expr_loc (clause_loc, x);
fd6481cf 5136 SET_DECL_VALUE_EXPR (placeholder, x);
5137 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
bc7bff74 5138 tree new_vard = new_var;
5139 if (is_reference (var))
5140 {
5141 gcc_assert (TREE_CODE (new_var) == MEM_REF);
5142 new_vard = TREE_OPERAND (new_var, 0);
5143 gcc_assert (DECL_P (new_vard));
5144 }
3d483a94 5145 if (is_simd
5146 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
5147 idx, lane, ivar, lvar))
5148 {
bc7bff74 5149 if (new_vard == new_var)
5150 {
5151 gcc_assert (DECL_VALUE_EXPR (new_var) == lvar);
5152 SET_DECL_VALUE_EXPR (new_var, ivar);
5153 }
5154 else
5155 {
5156 SET_DECL_VALUE_EXPR (new_vard,
5157 build_fold_addr_expr (ivar));
5158 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
5159 }
5160 x = lang_hooks.decls.omp_clause_default_ctor
5161 (c, unshare_expr (ivar),
5162 build_outer_var_ref (var, ctx));
5163 if (x)
5164 gimplify_and_add (x, &llist[0]);
5165 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
5166 {
5167 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
5168 lower_omp (&tseq, ctx);
5169 gimple_seq_add_seq (&llist[0], tseq);
5170 }
5171 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
5172 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
5173 lower_omp (&tseq, ctx);
5174 gimple_seq_add_seq (&llist[1], tseq);
5175 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
5176 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
5177 if (new_vard == new_var)
5178 SET_DECL_VALUE_EXPR (new_var, lvar);
5179 else
5180 SET_DECL_VALUE_EXPR (new_vard,
5181 build_fold_addr_expr (lvar));
5182 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
5183 if (x)
5184 {
5185 tseq = NULL;
5186 dtor = x;
5187 gimplify_stmt (&dtor, &tseq);
5188 gimple_seq_add_seq (&llist[1], tseq);
5189 }
5190 break;
5191 }
09d1c205 5192 /* If this is a reference to constant size reduction var
5193 with placeholder, we haven't emitted the initializer
5194 for it because it is undesirable if SIMD arrays are used.
5195 But if they aren't used, we need to emit the deferred
5196 initialization now. */
5197 else if (is_reference (var) && is_simd)
2712b6de 5198 handle_simd_reference (clause_loc, new_vard, ilist);
bc7bff74 5199 x = lang_hooks.decls.omp_clause_default_ctor
cf5f881f 5200 (c, unshare_expr (new_var),
5201 build_outer_var_ref (var, ctx));
bc7bff74 5202 if (x)
5203 gimplify_and_add (x, ilist);
5204 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
5205 {
5206 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
5207 lower_omp (&tseq, ctx);
5208 gimple_seq_add_seq (ilist, tseq);
5209 }
75a70cf9 5210 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
bc7bff74 5211 if (is_simd)
5212 {
5213 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
5214 lower_omp (&tseq, ctx);
5215 gimple_seq_add_seq (dlist, tseq);
5216 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
5217 }
fd6481cf 5218 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
bc7bff74 5219 goto do_dtor;
1e8e9920 5220 }
5221 else
5222 {
5223 x = omp_reduction_init (c, TREE_TYPE (new_var));
5224 gcc_assert (TREE_CODE (TREE_TYPE (new_var)) != ARRAY_TYPE);
c22ad515 5225 enum tree_code code = OMP_CLAUSE_REDUCTION_CODE (c);
5226
5227 /* reduction(-:var) sums up the partial results, so it
5228 acts identically to reduction(+:var). */
5229 if (code == MINUS_EXPR)
5230 code = PLUS_EXPR;
5231
2712b6de 5232 tree new_vard = new_var;
5233 if (is_simd && is_reference (var))
5234 {
5235 gcc_assert (TREE_CODE (new_var) == MEM_REF);
5236 new_vard = TREE_OPERAND (new_var, 0);
5237 gcc_assert (DECL_P (new_vard));
5238 }
3d483a94 5239 if (is_simd
5240 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
5241 idx, lane, ivar, lvar))
5242 {
3d483a94 5243 tree ref = build_outer_var_ref (var, ctx);
5244
5245 gimplify_assign (unshare_expr (ivar), x, &llist[0]);
5246
3d483a94 5247 x = build2 (code, TREE_TYPE (ref), ref, ivar);
5248 ref = build_outer_var_ref (var, ctx);
5249 gimplify_assign (ref, x, &llist[1]);
2712b6de 5250
5251 if (new_vard != new_var)
5252 {
5253 SET_DECL_VALUE_EXPR (new_vard,
5254 build_fold_addr_expr (lvar));
5255 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
5256 }
3d483a94 5257 }
5258 else
5259 {
2712b6de 5260 if (is_reference (var) && is_simd)
5261 handle_simd_reference (clause_loc, new_vard, ilist);
3d483a94 5262 gimplify_assign (new_var, x, ilist);
5263 if (is_simd)
c22ad515 5264 {
5265 tree ref = build_outer_var_ref (var, ctx);
5266
5267 x = build2 (code, TREE_TYPE (ref), ref, new_var);
5268 ref = build_outer_var_ref (var, ctx);
5269 gimplify_assign (ref, x, dlist);
5270 }
3d483a94 5271 }
1e8e9920 5272 }
5273 break;
5274
5275 default:
5276 gcc_unreachable ();
5277 }
5278 }
5279 }
5280
3d483a94 5281 if (lane)
5282 {
5283 tree uid = create_tmp_var (ptr_type_node, "simduid");
8e1a382d 5284 /* Don't want uninit warnings on simduid, it is always uninitialized,
5285 but we use it not for the value, but for the DECL_UID only. */
5286 TREE_NO_WARNING (uid) = 1;
42acab1c 5287 gimple *g
3d483a94 5288 = gimple_build_call_internal (IFN_GOMP_SIMD_LANE, 1, uid);
5289 gimple_call_set_lhs (g, lane);
5290 gimple_stmt_iterator gsi = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
5291 gsi_insert_before_without_update (&gsi, g, GSI_SAME_STMT);
5292 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__SIMDUID_);
5293 OMP_CLAUSE__SIMDUID__DECL (c) = uid;
5294 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
5295 gimple_omp_for_set_clauses (ctx->stmt, c);
e9cf809e 5296 g = gimple_build_assign (lane, INTEGER_CST,
5297 build_int_cst (unsigned_type_node, 0));
3d483a94 5298 gimple_seq_add_stmt (ilist, g);
5299 for (int i = 0; i < 2; i++)
5300 if (llist[i])
5301 {
f9e245b2 5302 tree vf = create_tmp_var (unsigned_type_node);
3d483a94 5303 g = gimple_build_call_internal (IFN_GOMP_SIMD_VF, 1, uid);
5304 gimple_call_set_lhs (g, vf);
5305 gimple_seq *seq = i == 0 ? ilist : dlist;
5306 gimple_seq_add_stmt (seq, g);
5307 tree t = build_int_cst (unsigned_type_node, 0);
e9cf809e 5308 g = gimple_build_assign (idx, INTEGER_CST, t);
3d483a94 5309 gimple_seq_add_stmt (seq, g);
5310 tree body = create_artificial_label (UNKNOWN_LOCATION);
5311 tree header = create_artificial_label (UNKNOWN_LOCATION);
5312 tree end = create_artificial_label (UNKNOWN_LOCATION);
5313 gimple_seq_add_stmt (seq, gimple_build_goto (header));
5314 gimple_seq_add_stmt (seq, gimple_build_label (body));
5315 gimple_seq_add_seq (seq, llist[i]);
5316 t = build_int_cst (unsigned_type_node, 1);
e9cf809e 5317 g = gimple_build_assign (idx, PLUS_EXPR, idx, t);
3d483a94 5318 gimple_seq_add_stmt (seq, g);
5319 gimple_seq_add_stmt (seq, gimple_build_label (header));
5320 g = gimple_build_cond (LT_EXPR, idx, vf, body, end);
5321 gimple_seq_add_stmt (seq, g);
5322 gimple_seq_add_stmt (seq, gimple_build_label (end));
5323 }
5324 }
5325
1e8e9920 5326 /* The copyin sequence is not to be executed by the main thread, since
5327 that would result in self-copies. Perhaps not visible to scalars,
5328 but it certainly is to C++ operator=. */
5329 if (copyin_seq)
5330 {
b9a16870 5331 x = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM),
5332 0);
1e8e9920 5333 x = build2 (NE_EXPR, boolean_type_node, x,
5334 build_int_cst (TREE_TYPE (x), 0));
5335 x = build3 (COND_EXPR, void_type_node, x, copyin_seq, NULL);
5336 gimplify_and_add (x, ilist);
5337 }
5338
5339 /* If any copyin variable is passed by reference, we must ensure the
5340 master thread doesn't modify it before it is copied over in all
f49d7bb5 5341 threads. Similarly for variables in both firstprivate and
5342 lastprivate clauses we need to ensure the lastprivate copying
bc7bff74 5343 happens after firstprivate copying in all threads. And similarly
5344 for UDRs if initializer expression refers to omp_orig. */
5345 if (copyin_by_ref || lastprivate_firstprivate || reduction_omp_orig_ref)
3d483a94 5346 {
5347 /* Don't add any barrier for #pragma omp simd or
5348 #pragma omp distribute. */
5349 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
7c01fa6c 5350 || gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_FOR)
bc7bff74 5351 gimple_seq_add_stmt (ilist, build_omp_barrier (NULL_TREE));
3d483a94 5352 }
5353
5354 /* If max_vf is non-zero, then we can use only a vectorization factor
5355 up to the max_vf we chose. So stick it into the safelen clause. */
5356 if (max_vf)
5357 {
5358 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
5359 OMP_CLAUSE_SAFELEN);
5360 if (c == NULL_TREE
c3f3b68d 5361 || (TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c)) == INTEGER_CST
5362 && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
5363 max_vf) == 1))
3d483a94 5364 {
5365 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_SAFELEN);
5366 OMP_CLAUSE_SAFELEN_EXPR (c) = build_int_cst (integer_type_node,
5367 max_vf);
5368 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
5369 gimple_omp_for_set_clauses (ctx->stmt, c);
5370 }
5371 }
1e8e9920 5372}
5373
773c5ba7 5374
1e8e9920 5375/* Generate code to implement the LASTPRIVATE clauses. This is used for
5376 both parallel and workshare constructs. PREDICATE may be NULL if it's
5377 always true. */
5378
5379static void
75a70cf9 5380lower_lastprivate_clauses (tree clauses, tree predicate, gimple_seq *stmt_list,
bc7bff74 5381 omp_context *ctx)
1e8e9920 5382{
3d483a94 5383 tree x, c, label = NULL, orig_clauses = clauses;
fd6481cf 5384 bool par_clauses = false;
3d483a94 5385 tree simduid = NULL, lastlane = NULL;
1e8e9920 5386
3d483a94 5387 /* Early exit if there are no lastprivate or linear clauses. */
5388 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
5389 if (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LASTPRIVATE
5390 || (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LINEAR
5391 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (clauses)))
5392 break;
1e8e9920 5393 if (clauses == NULL)
5394 {
5395 /* If this was a workshare clause, see if it had been combined
5396 with its parallel. In that case, look for the clauses on the
5397 parallel statement itself. */
5398 if (is_parallel_ctx (ctx))
5399 return;
5400
5401 ctx = ctx->outer;
5402 if (ctx == NULL || !is_parallel_ctx (ctx))
5403 return;
5404
75a70cf9 5405 clauses = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
1e8e9920 5406 OMP_CLAUSE_LASTPRIVATE);
5407 if (clauses == NULL)
5408 return;
fd6481cf 5409 par_clauses = true;
1e8e9920 5410 }
5411
75a70cf9 5412 if (predicate)
5413 {
1a91d914 5414 gcond *stmt;
75a70cf9 5415 tree label_true, arm1, arm2;
5416
e60a6f7b 5417 label = create_artificial_label (UNKNOWN_LOCATION);
5418 label_true = create_artificial_label (UNKNOWN_LOCATION);
75a70cf9 5419 arm1 = TREE_OPERAND (predicate, 0);
5420 arm2 = TREE_OPERAND (predicate, 1);
5421 gimplify_expr (&arm1, stmt_list, NULL, is_gimple_val, fb_rvalue);
5422 gimplify_expr (&arm2, stmt_list, NULL, is_gimple_val, fb_rvalue);
5423 stmt = gimple_build_cond (TREE_CODE (predicate), arm1, arm2,
5424 label_true, label);
5425 gimple_seq_add_stmt (stmt_list, stmt);
5426 gimple_seq_add_stmt (stmt_list, gimple_build_label (label_true));
5427 }
1e8e9920 5428
3d483a94 5429 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
10c55644 5430 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
3d483a94 5431 {
5432 simduid = find_omp_clause (orig_clauses, OMP_CLAUSE__SIMDUID_);
5433 if (simduid)
5434 simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
5435 }
5436
fd6481cf 5437 for (c = clauses; c ;)
1e8e9920 5438 {
5439 tree var, new_var;
389dd41b 5440 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
1e8e9920 5441
3d483a94 5442 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
5443 || (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
5444 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c)))
fd6481cf 5445 {
5446 var = OMP_CLAUSE_DECL (c);
43895be5 5447 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
5448 && OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c)
5449 && is_taskloop_ctx (ctx))
5450 {
5451 gcc_checking_assert (ctx->outer && is_task_ctx (ctx->outer));
5452 new_var = lookup_decl (var, ctx->outer);
5453 }
5454 else
5455 new_var = lookup_decl (var, ctx);
1e8e9920 5456
3d483a94 5457 if (simduid && DECL_HAS_VALUE_EXPR_P (new_var))
5458 {
5459 tree val = DECL_VALUE_EXPR (new_var);
5460 if (TREE_CODE (val) == ARRAY_REF
5461 && VAR_P (TREE_OPERAND (val, 0))
5462 && lookup_attribute ("omp simd array",
5463 DECL_ATTRIBUTES (TREE_OPERAND (val,
5464 0))))
5465 {
5466 if (lastlane == NULL)
5467 {
f9e245b2 5468 lastlane = create_tmp_var (unsigned_type_node);
1a91d914 5469 gcall *g
3d483a94 5470 = gimple_build_call_internal (IFN_GOMP_SIMD_LAST_LANE,
5471 2, simduid,
5472 TREE_OPERAND (val, 1));
5473 gimple_call_set_lhs (g, lastlane);
5474 gimple_seq_add_stmt (stmt_list, g);
5475 }
5476 new_var = build4 (ARRAY_REF, TREE_TYPE (val),
5477 TREE_OPERAND (val, 0), lastlane,
5478 NULL_TREE, NULL_TREE);
5479 }
5480 }
5481
5482 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
5483 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
75a70cf9 5484 {
e3a19533 5485 lower_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
75a70cf9 5486 gimple_seq_add_seq (stmt_list,
5487 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c));
3d483a94 5488 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c) = NULL;
75a70cf9 5489 }
2b536a17 5490 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
5491 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
5492 {
5493 lower_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
5494 gimple_seq_add_seq (stmt_list,
5495 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c));
5496 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c) = NULL;
5497 }
1e8e9920 5498
43895be5 5499 x = NULL_TREE;
5500 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
5501 && OMP_CLAUSE_LASTPRIVATE_TASKLOOP_IV (c))
5502 {
5503 gcc_checking_assert (is_taskloop_ctx (ctx));
5504 tree ovar = maybe_lookup_decl_in_outer_ctx (var,
5505 ctx->outer->outer);
5506 if (is_global_var (ovar))
5507 x = ovar;
5508 }
5509 if (!x)
5510 x = build_outer_var_ref (var, ctx, true);
fd6481cf 5511 if (is_reference (var))
182cf5a9 5512 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
fd6481cf 5513 x = lang_hooks.decls.omp_clause_assign_op (c, x, new_var);
75a70cf9 5514 gimplify_and_add (x, stmt_list);
fd6481cf 5515 }
5516 c = OMP_CLAUSE_CHAIN (c);
5517 if (c == NULL && !par_clauses)
5518 {
5519 /* If this was a workshare clause, see if it had been combined
5520 with its parallel. In that case, continue looking for the
5521 clauses also on the parallel statement itself. */
5522 if (is_parallel_ctx (ctx))
5523 break;
5524
5525 ctx = ctx->outer;
5526 if (ctx == NULL || !is_parallel_ctx (ctx))
5527 break;
5528
75a70cf9 5529 c = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
fd6481cf 5530 OMP_CLAUSE_LASTPRIVATE);
5531 par_clauses = true;
5532 }
1e8e9920 5533 }
5534
75a70cf9 5535 if (label)
5536 gimple_seq_add_stmt (stmt_list, gimple_build_label (label));
1e8e9920 5537}
5538
641a0fa1 5539/* Lower the OpenACC reductions of CLAUSES for compute axis LEVEL
5540 (which might be a placeholder). INNER is true if this is an inner
5541 axis of a multi-axis loop. FORK and JOIN are (optional) fork and
5542 join markers. Generate the before-loop forking sequence in
5543 FORK_SEQ and the after-loop joining sequence to JOIN_SEQ. The
5544 general form of these sequences is
5545
5546 GOACC_REDUCTION_SETUP
5547 GOACC_FORK
5548 GOACC_REDUCTION_INIT
5549 ...
5550 GOACC_REDUCTION_FINI
5551 GOACC_JOIN
5552 GOACC_REDUCTION_TEARDOWN. */
5553
ca4c3545 5554static void
641a0fa1 5555lower_oacc_reductions (location_t loc, tree clauses, tree level, bool inner,
5556 gcall *fork, gcall *join, gimple_seq *fork_seq,
5557 gimple_seq *join_seq, omp_context *ctx)
ca4c3545 5558{
641a0fa1 5559 gimple_seq before_fork = NULL;
5560 gimple_seq after_fork = NULL;
5561 gimple_seq before_join = NULL;
5562 gimple_seq after_join = NULL;
5563 tree init_code = NULL_TREE, fini_code = NULL_TREE,
5564 setup_code = NULL_TREE, teardown_code = NULL_TREE;
5565 unsigned offset = 0;
5566
5567 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
5568 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
5569 {
5570 tree orig = OMP_CLAUSE_DECL (c);
5571 tree var = maybe_lookup_decl (orig, ctx);
5572 tree ref_to_res = NULL_TREE;
0c302595 5573 tree incoming, outgoing, v1, v2, v3;
5574 bool is_private = false;
641a0fa1 5575
5576 enum tree_code rcode = OMP_CLAUSE_REDUCTION_CODE (c);
5577 if (rcode == MINUS_EXPR)
5578 rcode = PLUS_EXPR;
5579 else if (rcode == TRUTH_ANDIF_EXPR)
5580 rcode = BIT_AND_EXPR;
5581 else if (rcode == TRUTH_ORIF_EXPR)
5582 rcode = BIT_IOR_EXPR;
5583 tree op = build_int_cst (unsigned_type_node, rcode);
5584
5585 if (!var)
5586 var = orig;
641a0fa1 5587
5588 incoming = outgoing = var;
5589
5590 if (!inner)
5591 {
5592 /* See if an outer construct also reduces this variable. */
5593 omp_context *outer = ctx;
ca4c3545 5594
641a0fa1 5595 while (omp_context *probe = outer->outer)
5596 {
5597 enum gimple_code type = gimple_code (probe->stmt);
5598 tree cls;
ca4c3545 5599
641a0fa1 5600 switch (type)
5601 {
5602 case GIMPLE_OMP_FOR:
5603 cls = gimple_omp_for_clauses (probe->stmt);
5604 break;
ca4c3545 5605
641a0fa1 5606 case GIMPLE_OMP_TARGET:
5607 if (gimple_omp_target_kind (probe->stmt)
5608 != GF_OMP_TARGET_KIND_OACC_PARALLEL)
5609 goto do_lookup;
ca4c3545 5610
641a0fa1 5611 cls = gimple_omp_target_clauses (probe->stmt);
5612 break;
ca4c3545 5613
641a0fa1 5614 default:
5615 goto do_lookup;
5616 }
5617
5618 outer = probe;
5619 for (; cls; cls = OMP_CLAUSE_CHAIN (cls))
5620 if (OMP_CLAUSE_CODE (cls) == OMP_CLAUSE_REDUCTION
5621 && orig == OMP_CLAUSE_DECL (cls))
0c302595 5622 {
5623 incoming = outgoing = lookup_decl (orig, probe);
5624 goto has_outer_reduction;
5625 }
5626 else if ((OMP_CLAUSE_CODE (cls) == OMP_CLAUSE_FIRSTPRIVATE
5627 || OMP_CLAUSE_CODE (cls) == OMP_CLAUSE_PRIVATE)
5628 && orig == OMP_CLAUSE_DECL (cls))
5629 {
5630 is_private = true;
5631 goto do_lookup;
5632 }
641a0fa1 5633 }
ca4c3545 5634
641a0fa1 5635 do_lookup:
5636 /* This is the outermost construct with this reduction,
5637 see if there's a mapping for it. */
5638 if (gimple_code (outer->stmt) == GIMPLE_OMP_TARGET
0c302595 5639 && maybe_lookup_field (orig, outer) && !is_private)
641a0fa1 5640 {
5641 ref_to_res = build_receiver_ref (orig, false, outer);
5642 if (is_reference (orig))
5643 ref_to_res = build_simple_mem_ref (ref_to_res);
ca4c3545 5644
0c302595 5645 tree type = TREE_TYPE (var);
5646 if (POINTER_TYPE_P (type))
5647 type = TREE_TYPE (type);
5648
641a0fa1 5649 outgoing = var;
0c302595 5650 incoming = omp_reduction_init_op (loc, rcode, type);
641a0fa1 5651 }
0c302595 5652 else if (ctx->outer)
5653 incoming = outgoing = lookup_decl (orig, ctx->outer);
641a0fa1 5654 else
5655 incoming = outgoing = orig;
5656
5657 has_outer_reduction:;
5658 }
ca4c3545 5659
641a0fa1 5660 if (!ref_to_res)
5661 ref_to_res = integer_zero_node;
ca4c3545 5662
0c302595 5663 if (is_reference (orig))
5664 {
5665 tree type = TREE_TYPE (var);
5666 const char *id = IDENTIFIER_POINTER (DECL_NAME (var));
5667
5668 if (!inner)
5669 {
5670 tree x = create_tmp_var (TREE_TYPE (type), id);
5671 gimplify_assign (var, build_fold_addr_expr (x), fork_seq);
5672 }
5673
5674 v1 = create_tmp_var (type, id);
5675 v2 = create_tmp_var (type, id);
5676 v3 = create_tmp_var (type, id);
5677
5678 gimplify_assign (v1, var, fork_seq);
5679 gimplify_assign (v2, var, fork_seq);
5680 gimplify_assign (v3, var, fork_seq);
5681
5682 var = build_simple_mem_ref (var);
5683 v1 = build_simple_mem_ref (v1);
5684 v2 = build_simple_mem_ref (v2);
5685 v3 = build_simple_mem_ref (v3);
5686 outgoing = build_simple_mem_ref (outgoing);
5687
eae3d589 5688 if (!TREE_CONSTANT (incoming))
0c302595 5689 incoming = build_simple_mem_ref (incoming);
5690 }
5691 else
5692 v1 = v2 = v3 = var;
5693
641a0fa1 5694 /* Determine position in reduction buffer, which may be used
5695 by target. */
5696 enum machine_mode mode = TYPE_MODE (TREE_TYPE (var));
5697 unsigned align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
5698 offset = (offset + align - 1) & ~(align - 1);
5699 tree off = build_int_cst (sizetype, offset);
5700 offset += GET_MODE_SIZE (mode);
ca4c3545 5701
641a0fa1 5702 if (!init_code)
5703 {
5704 init_code = build_int_cst (integer_type_node,
5705 IFN_GOACC_REDUCTION_INIT);
5706 fini_code = build_int_cst (integer_type_node,
5707 IFN_GOACC_REDUCTION_FINI);
5708 setup_code = build_int_cst (integer_type_node,
5709 IFN_GOACC_REDUCTION_SETUP);
5710 teardown_code = build_int_cst (integer_type_node,
5711 IFN_GOACC_REDUCTION_TEARDOWN);
5712 }
5713
5714 tree setup_call
5715 = build_call_expr_internal_loc (loc, IFN_GOACC_REDUCTION,
5716 TREE_TYPE (var), 6, setup_code,
5717 unshare_expr (ref_to_res),
5718 incoming, level, op, off);
5719 tree init_call
5720 = build_call_expr_internal_loc (loc, IFN_GOACC_REDUCTION,
5721 TREE_TYPE (var), 6, init_code,
5722 unshare_expr (ref_to_res),
0c302595 5723 v1, level, op, off);
641a0fa1 5724 tree fini_call
5725 = build_call_expr_internal_loc (loc, IFN_GOACC_REDUCTION,
5726 TREE_TYPE (var), 6, fini_code,
5727 unshare_expr (ref_to_res),
0c302595 5728 v2, level, op, off);
641a0fa1 5729 tree teardown_call
5730 = build_call_expr_internal_loc (loc, IFN_GOACC_REDUCTION,
5731 TREE_TYPE (var), 6, teardown_code,
0c302595 5732 ref_to_res, v3, level, op, off);
641a0fa1 5733
0c302595 5734 gimplify_assign (v1, setup_call, &before_fork);
5735 gimplify_assign (v2, init_call, &after_fork);
5736 gimplify_assign (v3, fini_call, &before_join);
641a0fa1 5737 gimplify_assign (outgoing, teardown_call, &after_join);
5738 }
5739
5740 /* Now stitch things together. */
5741 gimple_seq_add_seq (fork_seq, before_fork);
5742 if (fork)
5743 gimple_seq_add_stmt (fork_seq, fork);
5744 gimple_seq_add_seq (fork_seq, after_fork);
5745
5746 gimple_seq_add_seq (join_seq, before_join);
5747 if (join)
5748 gimple_seq_add_stmt (join_seq, join);
5749 gimple_seq_add_seq (join_seq, after_join);
ca4c3545 5750}
773c5ba7 5751
1e8e9920 5752/* Generate code to implement the REDUCTION clauses. */
5753
5754static void
75a70cf9 5755lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp, omp_context *ctx)
1e8e9920 5756{
75a70cf9 5757 gimple_seq sub_seq = NULL;
42acab1c 5758 gimple *stmt;
f69b8a4c 5759 tree x, c;
1e8e9920 5760 int count = 0;
5761
641a0fa1 5762 /* OpenACC loop reductions are handled elsewhere. */
5763 if (is_gimple_omp_oacc (ctx->stmt))
5764 return;
5765
3d483a94 5766 /* SIMD reductions are handled in lower_rec_input_clauses. */
5767 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
10c55644 5768 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
3d483a94 5769 return;
5770
1e8e9920 5771 /* First see if there is exactly one reduction clause. Use OMP_ATOMIC
5772 update in that case, otherwise use a lock. */
5773 for (c = clauses; c && count < 2; c = OMP_CLAUSE_CHAIN (c))
55d6e7cd 5774 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
1e8e9920 5775 {
43895be5 5776 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)
5777 || TREE_CODE (OMP_CLAUSE_DECL (c)) == MEM_REF)
1e8e9920 5778 {
bc7bff74 5779 /* Never use OMP_ATOMIC for array reductions or UDRs. */
1e8e9920 5780 count = -1;
5781 break;
5782 }
5783 count++;
5784 }
5785
5786 if (count == 0)
5787 return;
5788
5789 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
5790 {
43895be5 5791 tree var, ref, new_var, orig_var;
1e8e9920 5792 enum tree_code code;
389dd41b 5793 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
1e8e9920 5794
55d6e7cd 5795 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
1e8e9920 5796 continue;
5797
43895be5 5798 orig_var = var = OMP_CLAUSE_DECL (c);
5799 if (TREE_CODE (var) == MEM_REF)
5800 {
5801 var = TREE_OPERAND (var, 0);
9561765e 5802 if (TREE_CODE (var) == POINTER_PLUS_EXPR)
5803 var = TREE_OPERAND (var, 0);
43895be5 5804 if (TREE_CODE (var) == INDIRECT_REF
5805 || TREE_CODE (var) == ADDR_EXPR)
5806 var = TREE_OPERAND (var, 0);
5807 orig_var = var;
5808 if (is_variable_sized (var))
5809 {
5810 gcc_assert (DECL_HAS_VALUE_EXPR_P (var));
5811 var = DECL_VALUE_EXPR (var);
5812 gcc_assert (TREE_CODE (var) == INDIRECT_REF);
5813 var = TREE_OPERAND (var, 0);
5814 gcc_assert (DECL_P (var));
5815 }
5816 }
1e8e9920 5817 new_var = lookup_decl (var, ctx);
43895be5 5818 if (var == OMP_CLAUSE_DECL (c) && is_reference (var))
182cf5a9 5819 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
1e8e9920 5820 ref = build_outer_var_ref (var, ctx);
5821 code = OMP_CLAUSE_REDUCTION_CODE (c);
773c5ba7 5822
5823 /* reduction(-:var) sums up the partial results, so it acts
5824 identically to reduction(+:var). */
1e8e9920 5825 if (code == MINUS_EXPR)
5826 code = PLUS_EXPR;
5827
641a0fa1 5828 if (count == 1)
1e8e9920 5829 {
389dd41b 5830 tree addr = build_fold_addr_expr_loc (clause_loc, ref);
1e8e9920 5831
5832 addr = save_expr (addr);
5833 ref = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (addr)), addr);
389dd41b 5834 x = fold_build2_loc (clause_loc, code, TREE_TYPE (ref), ref, new_var);
1e8e9920 5835 x = build2 (OMP_ATOMIC, void_type_node, addr, x);
75a70cf9 5836 gimplify_and_add (x, stmt_seqp);
1e8e9920 5837 return;
5838 }
43895be5 5839 else if (TREE_CODE (OMP_CLAUSE_DECL (c)) == MEM_REF)
5840 {
5841 tree d = OMP_CLAUSE_DECL (c);
5842 tree type = TREE_TYPE (d);
5843 tree v = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
5844 tree i = create_tmp_var (TREE_TYPE (v), NULL);
5845 tree ptype = build_pointer_type (TREE_TYPE (type));
9561765e 5846 tree bias = TREE_OPERAND (d, 1);
5847 d = TREE_OPERAND (d, 0);
5848 if (TREE_CODE (d) == POINTER_PLUS_EXPR)
5849 {
5850 tree b = TREE_OPERAND (d, 1);
5851 b = maybe_lookup_decl (b, ctx);
5852 if (b == NULL)
5853 {
5854 b = TREE_OPERAND (d, 1);
5855 b = maybe_lookup_decl_in_outer_ctx (b, ctx);
5856 }
5857 if (integer_zerop (bias))
5858 bias = b;
5859 else
5860 {
5861 bias = fold_convert_loc (clause_loc, TREE_TYPE (b), bias);
5862 bias = fold_build2_loc (clause_loc, PLUS_EXPR,
5863 TREE_TYPE (b), b, bias);
5864 }
5865 d = TREE_OPERAND (d, 0);
5866 }
43895be5 5867 /* For ref build_outer_var_ref already performs this, so
5868 only new_var needs a dereference. */
9561765e 5869 if (TREE_CODE (d) == INDIRECT_REF)
43895be5 5870 {
5871 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
5872 gcc_assert (is_reference (var) && var == orig_var);
5873 }
9561765e 5874 else if (TREE_CODE (d) == ADDR_EXPR)
43895be5 5875 {
5876 if (orig_var == var)
5877 {
5878 new_var = build_fold_addr_expr (new_var);
5879 ref = build_fold_addr_expr (ref);
5880 }
5881 }
5882 else
5883 {
5884 gcc_assert (orig_var == var);
5885 if (is_reference (var))
5886 ref = build_fold_addr_expr (ref);
5887 }
5888 if (DECL_P (v))
5889 {
5890 tree t = maybe_lookup_decl (v, ctx);
5891 if (t)
5892 v = t;
5893 else
5894 v = maybe_lookup_decl_in_outer_ctx (v, ctx);
5895 gimplify_expr (&v, stmt_seqp, NULL, is_gimple_val, fb_rvalue);
5896 }
9561765e 5897 if (!integer_zerop (bias))
5898 {
5899 bias = fold_convert_loc (clause_loc, sizetype, bias);
5900 new_var = fold_build2_loc (clause_loc, POINTER_PLUS_EXPR,
5901 TREE_TYPE (new_var), new_var,
5902 unshare_expr (bias));
5903 ref = fold_build2_loc (clause_loc, POINTER_PLUS_EXPR,
5904 TREE_TYPE (ref), ref, bias);
5905 }
43895be5 5906 new_var = fold_convert_loc (clause_loc, ptype, new_var);
5907 ref = fold_convert_loc (clause_loc, ptype, ref);
5908 tree m = create_tmp_var (ptype, NULL);
5909 gimplify_assign (m, new_var, stmt_seqp);
5910 new_var = m;
5911 m = create_tmp_var (ptype, NULL);
5912 gimplify_assign (m, ref, stmt_seqp);
5913 ref = m;
5914 gimplify_assign (i, build_int_cst (TREE_TYPE (v), 0), stmt_seqp);
5915 tree body = create_artificial_label (UNKNOWN_LOCATION);
5916 tree end = create_artificial_label (UNKNOWN_LOCATION);
5917 gimple_seq_add_stmt (&sub_seq, gimple_build_label (body));
5918 tree priv = build_simple_mem_ref_loc (clause_loc, new_var);
5919 tree out = build_simple_mem_ref_loc (clause_loc, ref);
5920 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
5921 {
5922 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
5923 tree decl_placeholder
5924 = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c);
5925 SET_DECL_VALUE_EXPR (placeholder, out);
5926 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
5927 SET_DECL_VALUE_EXPR (decl_placeholder, priv);
5928 DECL_HAS_VALUE_EXPR_P (decl_placeholder) = 1;
5929 lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
5930 gimple_seq_add_seq (&sub_seq,
5931 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
5932 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
5933 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
5934 OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c) = NULL;
5935 }
5936 else
5937 {
5938 x = build2 (code, TREE_TYPE (out), out, priv);
5939 out = unshare_expr (out);
5940 gimplify_assign (out, x, &sub_seq);
5941 }
5942 gimple *g = gimple_build_assign (new_var, POINTER_PLUS_EXPR, new_var,
5943 TYPE_SIZE_UNIT (TREE_TYPE (type)));
5944 gimple_seq_add_stmt (&sub_seq, g);
5945 g = gimple_build_assign (ref, POINTER_PLUS_EXPR, ref,
5946 TYPE_SIZE_UNIT (TREE_TYPE (type)));
5947 gimple_seq_add_stmt (&sub_seq, g);
5948 g = gimple_build_assign (i, PLUS_EXPR, i,
5949 build_int_cst (TREE_TYPE (i), 1));
5950 gimple_seq_add_stmt (&sub_seq, g);
5951 g = gimple_build_cond (LE_EXPR, i, v, body, end);
5952 gimple_seq_add_stmt (&sub_seq, g);
5953 gimple_seq_add_stmt (&sub_seq, gimple_build_label (end));
5954 }
ca4c3545 5955 else if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1e8e9920 5956 {
5957 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
5958
bc7bff74 5959 if (is_reference (var)
5960 && !useless_type_conversion_p (TREE_TYPE (placeholder),
5961 TREE_TYPE (ref)))
389dd41b 5962 ref = build_fold_addr_expr_loc (clause_loc, ref);
1e8e9920 5963 SET_DECL_VALUE_EXPR (placeholder, ref);
5964 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
e3a19533 5965 lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
75a70cf9 5966 gimple_seq_add_seq (&sub_seq, OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
5967 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
1e8e9920 5968 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
5969 }
5970 else
5971 {
5972 x = build2 (code, TREE_TYPE (ref), ref, new_var);
5973 ref = build_outer_var_ref (var, ctx);
75a70cf9 5974 gimplify_assign (ref, x, &sub_seq);
1e8e9920 5975 }
5976 }
5977
b9a16870 5978 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START),
5979 0);
75a70cf9 5980 gimple_seq_add_stmt (stmt_seqp, stmt);
1e8e9920 5981
75a70cf9 5982 gimple_seq_add_seq (stmt_seqp, sub_seq);
1e8e9920 5983
b9a16870 5984 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END),
5985 0);
75a70cf9 5986 gimple_seq_add_stmt (stmt_seqp, stmt);
1e8e9920 5987}
5988
773c5ba7 5989
1e8e9920 5990/* Generate code to implement the COPYPRIVATE clauses. */
5991
5992static void
75a70cf9 5993lower_copyprivate_clauses (tree clauses, gimple_seq *slist, gimple_seq *rlist,
1e8e9920 5994 omp_context *ctx)
5995{
5996 tree c;
5997
5998 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
5999 {
cb561506 6000 tree var, new_var, ref, x;
1e8e9920 6001 bool by_ref;
389dd41b 6002 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
1e8e9920 6003
55d6e7cd 6004 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYPRIVATE)
1e8e9920 6005 continue;
6006
6007 var = OMP_CLAUSE_DECL (c);
e8a588af 6008 by_ref = use_pointer_for_field (var, NULL);
1e8e9920 6009
6010 ref = build_sender_ref (var, ctx);
cb561506 6011 x = new_var = lookup_decl_in_outer_ctx (var, ctx);
6012 if (by_ref)
6013 {
6014 x = build_fold_addr_expr_loc (clause_loc, new_var);
6015 x = fold_convert_loc (clause_loc, TREE_TYPE (ref), x);
6016 }
75a70cf9 6017 gimplify_assign (ref, x, slist);
1e8e9920 6018
cb561506 6019 ref = build_receiver_ref (var, false, ctx);
6020 if (by_ref)
6021 {
6022 ref = fold_convert_loc (clause_loc,
6023 build_pointer_type (TREE_TYPE (new_var)),
6024 ref);
6025 ref = build_fold_indirect_ref_loc (clause_loc, ref);
6026 }
1e8e9920 6027 if (is_reference (var))
6028 {
cb561506 6029 ref = fold_convert_loc (clause_loc, TREE_TYPE (new_var), ref);
182cf5a9 6030 ref = build_simple_mem_ref_loc (clause_loc, ref);
6031 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
1e8e9920 6032 }
cb561506 6033 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, ref);
1e8e9920 6034 gimplify_and_add (x, rlist);
6035 }
6036}
6037
773c5ba7 6038
1e8e9920 6039/* Generate code to implement the clauses, FIRSTPRIVATE, COPYIN, LASTPRIVATE,
6040 and REDUCTION from the sender (aka parent) side. */
6041
6042static void
75a70cf9 6043lower_send_clauses (tree clauses, gimple_seq *ilist, gimple_seq *olist,
6044 omp_context *ctx)
1e8e9920 6045{
43895be5 6046 tree c, t;
6047 int ignored_looptemp = 0;
6048 bool is_taskloop = false;
6049
6050 /* For taskloop, ignore first two _looptemp_ clauses, those are initialized
6051 by GOMP_taskloop. */
6052 if (is_task_ctx (ctx) && gimple_omp_task_taskloop_p (ctx->stmt))
6053 {
6054 ignored_looptemp = 2;
6055 is_taskloop = true;
6056 }
1e8e9920 6057
6058 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
6059 {
773c5ba7 6060 tree val, ref, x, var;
1e8e9920 6061 bool by_ref, do_in = false, do_out = false;
389dd41b 6062 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
1e8e9920 6063
55d6e7cd 6064 switch (OMP_CLAUSE_CODE (c))
1e8e9920 6065 {
fd6481cf 6066 case OMP_CLAUSE_PRIVATE:
6067 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
6068 break;
6069 continue;
1e8e9920 6070 case OMP_CLAUSE_FIRSTPRIVATE:
6071 case OMP_CLAUSE_COPYIN:
6072 case OMP_CLAUSE_LASTPRIVATE:
6073 case OMP_CLAUSE_REDUCTION:
43895be5 6074 break;
6075 case OMP_CLAUSE_SHARED:
6076 if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
6077 break;
6078 continue;
bc7bff74 6079 case OMP_CLAUSE__LOOPTEMP_:
43895be5 6080 if (ignored_looptemp)
6081 {
6082 ignored_looptemp--;
6083 continue;
6084 }
1e8e9920 6085 break;
6086 default:
6087 continue;
6088 }
6089
87b31375 6090 val = OMP_CLAUSE_DECL (c);
43895be5 6091 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
6092 && TREE_CODE (val) == MEM_REF)
6093 {
6094 val = TREE_OPERAND (val, 0);
9561765e 6095 if (TREE_CODE (val) == POINTER_PLUS_EXPR)
6096 val = TREE_OPERAND (val, 0);
43895be5 6097 if (TREE_CODE (val) == INDIRECT_REF
6098 || TREE_CODE (val) == ADDR_EXPR)
6099 val = TREE_OPERAND (val, 0);
6100 if (is_variable_sized (val))
6101 continue;
6102 }
6103
6104 /* For OMP_CLAUSE_SHARED_FIRSTPRIVATE, look beyond the
6105 outer taskloop region. */
6106 omp_context *ctx_for_o = ctx;
6107 if (is_taskloop
6108 && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
6109 && OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
6110 ctx_for_o = ctx->outer;
6111
6112 var = lookup_decl_in_outer_ctx (val, ctx_for_o);
773c5ba7 6113
f49d7bb5 6114 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYIN
6115 && is_global_var (var))
6116 continue;
43895be5 6117
6118 t = omp_member_access_dummy_var (var);
6119 if (t)
6120 {
6121 var = DECL_VALUE_EXPR (var);
6122 tree o = maybe_lookup_decl_in_outer_ctx (t, ctx_for_o);
6123 if (o != t)
6124 var = unshare_and_remap (var, t, o);
6125 else
6126 var = unshare_expr (var);
6127 }
6128
6129 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED)
6130 {
6131 /* Handle taskloop firstprivate/lastprivate, where the
6132 lastprivate on GIMPLE_OMP_TASK is represented as
6133 OMP_CLAUSE_SHARED_FIRSTPRIVATE. */
6134 tree f = lookup_sfield ((splay_tree_key) &DECL_UID (val), ctx);
6135 x = omp_build_component_ref (ctx->sender_decl, f);
6136 if (use_pointer_for_field (val, ctx))
6137 var = build_fold_addr_expr (var);
6138 gimplify_assign (x, var, ilist);
6139 DECL_ABSTRACT_ORIGIN (f) = NULL;
6140 continue;
6141 }
6142
6143 if ((OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION
6144 || val == OMP_CLAUSE_DECL (c))
6145 && is_variable_sized (val))
1e8e9920 6146 continue;
e8a588af 6147 by_ref = use_pointer_for_field (val, NULL);
1e8e9920 6148
55d6e7cd 6149 switch (OMP_CLAUSE_CODE (c))
1e8e9920 6150 {
6151 case OMP_CLAUSE_FIRSTPRIVATE:
585aefbb 6152 if (OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c)
6153 && !by_ref
6154 && is_task_ctx (ctx))
6155 TREE_NO_WARNING (var) = 1;
6156 do_in = true;
6157 break;
6158
6159 case OMP_CLAUSE_PRIVATE:
1e8e9920 6160 case OMP_CLAUSE_COPYIN:
bc7bff74 6161 case OMP_CLAUSE__LOOPTEMP_:
1e8e9920 6162 do_in = true;
6163 break;
6164
6165 case OMP_CLAUSE_LASTPRIVATE:
6166 if (by_ref || is_reference (val))
6167 {
6168 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
6169 continue;
6170 do_in = true;
6171 }
6172 else
fd6481cf 6173 {
6174 do_out = true;
6175 if (lang_hooks.decls.omp_private_outer_ref (val))
6176 do_in = true;
6177 }
1e8e9920 6178 break;
6179
6180 case OMP_CLAUSE_REDUCTION:
6181 do_in = true;
43895be5 6182 if (val == OMP_CLAUSE_DECL (c))
6183 do_out = !(by_ref || is_reference (val));
6184 else
6185 by_ref = TREE_CODE (TREE_TYPE (val)) == ARRAY_TYPE;
1e8e9920 6186 break;
6187
6188 default:
6189 gcc_unreachable ();
6190 }
6191
6192 if (do_in)
6193 {
6194 ref = build_sender_ref (val, ctx);
389dd41b 6195 x = by_ref ? build_fold_addr_expr_loc (clause_loc, var) : var;
75a70cf9 6196 gimplify_assign (ref, x, ilist);
fd6481cf 6197 if (is_task_ctx (ctx))
6198 DECL_ABSTRACT_ORIGIN (TREE_OPERAND (ref, 1)) = NULL;
1e8e9920 6199 }
773c5ba7 6200
1e8e9920 6201 if (do_out)
6202 {
6203 ref = build_sender_ref (val, ctx);
75a70cf9 6204 gimplify_assign (var, ref, olist);
1e8e9920 6205 }
6206 }
6207}
6208
75a70cf9 6209/* Generate code to implement SHARED from the sender (aka parent)
6210 side. This is trickier, since GIMPLE_OMP_PARALLEL_CLAUSES doesn't
6211 list things that got automatically shared. */
1e8e9920 6212
6213static void
75a70cf9 6214lower_send_shared_vars (gimple_seq *ilist, gimple_seq *olist, omp_context *ctx)
1e8e9920 6215{
43895be5 6216 tree var, ovar, nvar, t, f, x, record_type;
1e8e9920 6217
6218 if (ctx->record_type == NULL)
6219 return;
773c5ba7 6220
fd6481cf 6221 record_type = ctx->srecord_type ? ctx->srecord_type : ctx->record_type;
1767a056 6222 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
1e8e9920 6223 {
6224 ovar = DECL_ABSTRACT_ORIGIN (f);
43895be5 6225 if (!ovar || TREE_CODE (ovar) == FIELD_DECL)
6226 continue;
6227
1e8e9920 6228 nvar = maybe_lookup_decl (ovar, ctx);
6229 if (!nvar || !DECL_HAS_VALUE_EXPR_P (nvar))
6230 continue;
6231
773c5ba7 6232 /* If CTX is a nested parallel directive. Find the immediately
6233 enclosing parallel or workshare construct that contains a
6234 mapping for OVAR. */
87b31375 6235 var = lookup_decl_in_outer_ctx (ovar, ctx);
773c5ba7 6236
43895be5 6237 t = omp_member_access_dummy_var (var);
6238 if (t)
6239 {
6240 var = DECL_VALUE_EXPR (var);
6241 tree o = maybe_lookup_decl_in_outer_ctx (t, ctx);
6242 if (o != t)
6243 var = unshare_and_remap (var, t, o);
6244 else
6245 var = unshare_expr (var);
6246 }
6247
e8a588af 6248 if (use_pointer_for_field (ovar, ctx))
1e8e9920 6249 {
6250 x = build_sender_ref (ovar, ctx);
773c5ba7 6251 var = build_fold_addr_expr (var);
75a70cf9 6252 gimplify_assign (x, var, ilist);
1e8e9920 6253 }
6254 else
6255 {
6256 x = build_sender_ref (ovar, ctx);
75a70cf9 6257 gimplify_assign (x, var, ilist);
1e8e9920 6258
d2263ebb 6259 if (!TREE_READONLY (var)
6260 /* We don't need to receive a new reference to a result
6261 or parm decl. In fact we may not store to it as we will
6262 invalidate any pending RSO and generate wrong gimple
6263 during inlining. */
6264 && !((TREE_CODE (var) == RESULT_DECL
6265 || TREE_CODE (var) == PARM_DECL)
6266 && DECL_BY_REFERENCE (var)))
fd6481cf 6267 {
6268 x = build_sender_ref (ovar, ctx);
75a70cf9 6269 gimplify_assign (var, x, olist);
fd6481cf 6270 }
1e8e9920 6271 }
6272 }
6273}
6274
a8e785ba 6275/* Emit an OpenACC head marker call, encapulating the partitioning and
6276 other information that must be processed by the target compiler.
6277 Return the maximum number of dimensions the associated loop might
6278 be partitioned over. */
6279
6280static unsigned
6281lower_oacc_head_mark (location_t loc, tree ddvar, tree clauses,
6282 gimple_seq *seq, omp_context *ctx)
6283{
6284 unsigned levels = 0;
6285 unsigned tag = 0;
6286 tree gang_static = NULL_TREE;
6287 auto_vec<tree, 5> args;
6288
6289 args.quick_push (build_int_cst
6290 (integer_type_node, IFN_UNIQUE_OACC_HEAD_MARK));
6291 args.quick_push (ddvar);
6292 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
6293 {
6294 switch (OMP_CLAUSE_CODE (c))
6295 {
6296 case OMP_CLAUSE_GANG:
6297 tag |= OLF_DIM_GANG;
6298 gang_static = OMP_CLAUSE_GANG_STATIC_EXPR (c);
6299 /* static:* is represented by -1, and we can ignore it, as
6300 scheduling is always static. */
6301 if (gang_static && integer_minus_onep (gang_static))
6302 gang_static = NULL_TREE;
6303 levels++;
6304 break;
6305
6306 case OMP_CLAUSE_WORKER:
6307 tag |= OLF_DIM_WORKER;
6308 levels++;
6309 break;
6310
6311 case OMP_CLAUSE_VECTOR:
6312 tag |= OLF_DIM_VECTOR;
6313 levels++;
6314 break;
6315
6316 case OMP_CLAUSE_SEQ:
6317 tag |= OLF_SEQ;
6318 break;
6319
6320 case OMP_CLAUSE_AUTO:
6321 tag |= OLF_AUTO;
6322 break;
6323
6324 case OMP_CLAUSE_INDEPENDENT:
6325 tag |= OLF_INDEPENDENT;
6326 break;
6327
6328 default:
6329 continue;
6330 }
6331 }
6332
6333 if (gang_static)
6334 {
6335 if (DECL_P (gang_static))
6336 gang_static = build_outer_var_ref (gang_static, ctx);
6337 tag |= OLF_GANG_STATIC;
6338 }
6339
6340 /* In a parallel region, loops are implicitly INDEPENDENT. */
6341 omp_context *tgt = enclosing_target_ctx (ctx);
6342 if (!tgt || is_oacc_parallel (tgt))
6343 tag |= OLF_INDEPENDENT;
6344
6345 /* A loop lacking SEQ, GANG, WORKER and/or VECTOR is implicitly AUTO. */
6346 if (!(tag & (((GOMP_DIM_MASK (GOMP_DIM_MAX) - 1) << OLF_DIM_BASE)
6347 | OLF_SEQ)))
6348 tag |= OLF_AUTO;
6349
6350 /* Ensure at least one level. */
6351 if (!levels)
6352 levels++;
6353
6354 args.quick_push (build_int_cst (integer_type_node, levels));
6355 args.quick_push (build_int_cst (integer_type_node, tag));
6356 if (gang_static)
6357 args.quick_push (gang_static);
6358
6359 gcall *call = gimple_build_call_internal_vec (IFN_UNIQUE, args);
6360 gimple_set_location (call, loc);
6361 gimple_set_lhs (call, ddvar);
6362 gimple_seq_add_stmt (seq, call);
6363
6364 return levels;
6365}
6366
6367/* Emit an OpenACC lopp head or tail marker to SEQ. LEVEL is the
6368 partitioning level of the enclosed region. */
6369
6370static void
6371lower_oacc_loop_marker (location_t loc, tree ddvar, bool head,
6372 tree tofollow, gimple_seq *seq)
6373{
6374 int marker_kind = (head ? IFN_UNIQUE_OACC_HEAD_MARK
6375 : IFN_UNIQUE_OACC_TAIL_MARK);
6376 tree marker = build_int_cst (integer_type_node, marker_kind);
6377 int nargs = 2 + (tofollow != NULL_TREE);
6378 gcall *call = gimple_build_call_internal (IFN_UNIQUE, nargs,
6379 marker, ddvar, tofollow);
6380 gimple_set_location (call, loc);
6381 gimple_set_lhs (call, ddvar);
6382 gimple_seq_add_stmt (seq, call);
6383}
6384
6385/* Generate the before and after OpenACC loop sequences. CLAUSES are
6386 the loop clauses, from which we extract reductions. Initialize
6387 HEAD and TAIL. */
6388
6389static void
6390lower_oacc_head_tail (location_t loc, tree clauses,
6391 gimple_seq *head, gimple_seq *tail, omp_context *ctx)
6392{
6393 bool inner = false;
6394 tree ddvar = create_tmp_var (integer_type_node, ".data_dep");
6395 gimple_seq_add_stmt (head, gimple_build_assign (ddvar, integer_zero_node));
6396
6397 unsigned count = lower_oacc_head_mark (loc, ddvar, clauses, head, ctx);
a8e785ba 6398 tree fork_kind = build_int_cst (unsigned_type_node, IFN_UNIQUE_OACC_FORK);
6399 tree join_kind = build_int_cst (unsigned_type_node, IFN_UNIQUE_OACC_JOIN);
6400
cff84c1a 6401 gcc_assert (count);
a8e785ba 6402 for (unsigned done = 1; count; count--, done++)
6403 {
6404 gimple_seq fork_seq = NULL;
6405 gimple_seq join_seq = NULL;
6406
6407 tree place = build_int_cst (integer_type_node, -1);
6408 gcall *fork = gimple_build_call_internal (IFN_UNIQUE, 3,
6409 fork_kind, ddvar, place);
6410 gimple_set_location (fork, loc);
6411 gimple_set_lhs (fork, ddvar);
6412
6413 gcall *join = gimple_build_call_internal (IFN_UNIQUE, 3,
6414 join_kind, ddvar, place);
6415 gimple_set_location (join, loc);
6416 gimple_set_lhs (join, ddvar);
6417
6418 /* Mark the beginning of this level sequence. */
6419 if (inner)
6420 lower_oacc_loop_marker (loc, ddvar, true,
6421 build_int_cst (integer_type_node, count),
6422 &fork_seq);
6423 lower_oacc_loop_marker (loc, ddvar, false,
6424 build_int_cst (integer_type_node, done),
6425 &join_seq);
6426
641a0fa1 6427 lower_oacc_reductions (loc, clauses, place, inner,
6428 fork, join, &fork_seq, &join_seq, ctx);
a8e785ba 6429
6430 /* Append this level to head. */
6431 gimple_seq_add_seq (head, fork_seq);
6432 /* Prepend it to tail. */
6433 gimple_seq_add_seq (&join_seq, *tail);
6434 *tail = join_seq;
6435
6436 inner = true;
6437 }
6438
6439 /* Mark the end of the sequence. */
6440 lower_oacc_loop_marker (loc, ddvar, true, NULL_TREE, head);
6441 lower_oacc_loop_marker (loc, ddvar, false, NULL_TREE, tail);
6442}
75a70cf9 6443
6444/* A convenience function to build an empty GIMPLE_COND with just the
6445 condition. */
6446
1a91d914 6447static gcond *
75a70cf9 6448gimple_build_cond_empty (tree cond)
6449{
6450 enum tree_code pred_code;
6451 tree lhs, rhs;
6452
6453 gimple_cond_get_ops_from_tree (cond, &pred_code, &lhs, &rhs);
6454 return gimple_build_cond (pred_code, lhs, rhs, NULL_TREE, NULL_TREE);
6455}
6456
56686608 6457/* Return true if a parallel REGION is within a declare target function or
6458 within a target region and is not a part of a gridified target. */
6459
6460static bool
6461parallel_needs_hsa_kernel_p (struct omp_region *region)
6462{
6463 bool indirect = false;
6464 for (region = region->outer; region; region = region->outer)
6465 {
6466 if (region->type == GIMPLE_OMP_PARALLEL)
6467 indirect = true;
6468 else if (region->type == GIMPLE_OMP_TARGET)
6469 {
6470 gomp_target *tgt_stmt
6471 = as_a <gomp_target *> (last_stmt (region->entry));
6472
6473 if (find_omp_clause (gimple_omp_target_clauses (tgt_stmt),
6474 OMP_CLAUSE__GRIDDIM_))
6475 return indirect;
6476 else
6477 return true;
6478 }
6479 }
6480
6481 if (lookup_attribute ("omp declare target",
6482 DECL_ATTRIBUTES (current_function_decl)))
6483 return true;
6484
6485 return false;
6486}
6487
43895be5 6488static void expand_omp_build_assign (gimple_stmt_iterator *, tree, tree,
6489 bool = false);
75a70cf9 6490
48e1416a 6491/* Build the function calls to GOMP_parallel_start etc to actually
773c5ba7 6492 generate the parallel operation. REGION is the parallel region
6493 being expanded. BB is the block where to insert the code. WS_ARGS
6494 will be set if this is a call to a combined parallel+workshare
6495 construct, it contains the list of additional arguments needed by
6496 the workshare construct. */
1e8e9920 6497
6498static void
61e47ac8 6499expand_parallel_call (struct omp_region *region, basic_block bb,
1a91d914 6500 gomp_parallel *entry_stmt,
6501 vec<tree, va_gc> *ws_args)
1e8e9920 6502{
bc7bff74 6503 tree t, t1, t2, val, cond, c, clauses, flags;
75a70cf9 6504 gimple_stmt_iterator gsi;
42acab1c 6505 gimple *stmt;
b9a16870 6506 enum built_in_function start_ix;
6507 int start_ix2;
389dd41b 6508 location_t clause_loc;
f1f41a6c 6509 vec<tree, va_gc> *args;
773c5ba7 6510
75a70cf9 6511 clauses = gimple_omp_parallel_clauses (entry_stmt);
773c5ba7 6512
bc7bff74 6513 /* Determine what flavor of GOMP_parallel we will be
773c5ba7 6514 emitting. */
bc7bff74 6515 start_ix = BUILT_IN_GOMP_PARALLEL;
773c5ba7 6516 if (is_combined_parallel (region))
6517 {
61e47ac8 6518 switch (region->inner->type)
773c5ba7 6519 {
75a70cf9 6520 case GIMPLE_OMP_FOR:
fd6481cf 6521 gcc_assert (region->inner->sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
9561765e 6522 switch (region->inner->sched_kind)
6523 {
6524 case OMP_CLAUSE_SCHEDULE_RUNTIME:
6525 start_ix2 = 3;
6526 break;
6527 case OMP_CLAUSE_SCHEDULE_DYNAMIC:
6528 case OMP_CLAUSE_SCHEDULE_GUIDED:
6529 if (region->inner->sched_modifiers
6530 & OMP_CLAUSE_SCHEDULE_NONMONOTONIC)
6531 {
6532 start_ix2 = 3 + region->inner->sched_kind;
6533 break;
6534 }
6535 /* FALLTHRU */
6536 default:
6537 start_ix2 = region->inner->sched_kind;
6538 break;
6539 }
6540 start_ix2 += (int) BUILT_IN_GOMP_PARALLEL_LOOP_STATIC;
6541 start_ix = (enum built_in_function) start_ix2;
61e47ac8 6542 break;
75a70cf9 6543 case GIMPLE_OMP_SECTIONS:
bc7bff74 6544 start_ix = BUILT_IN_GOMP_PARALLEL_SECTIONS;
61e47ac8 6545 break;
6546 default:
6547 gcc_unreachable ();
773c5ba7 6548 }
773c5ba7 6549 }
1e8e9920 6550
6551 /* By default, the value of NUM_THREADS is zero (selected at run time)
6552 and there is no conditional. */
6553 cond = NULL_TREE;
6554 val = build_int_cst (unsigned_type_node, 0);
bc7bff74 6555 flags = build_int_cst (unsigned_type_node, 0);
1e8e9920 6556
6557 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
6558 if (c)
6559 cond = OMP_CLAUSE_IF_EXPR (c);
6560
6561 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_THREADS);
6562 if (c)
389dd41b 6563 {
6564 val = OMP_CLAUSE_NUM_THREADS_EXPR (c);
6565 clause_loc = OMP_CLAUSE_LOCATION (c);
6566 }
6567 else
6568 clause_loc = gimple_location (entry_stmt);
1e8e9920 6569
bc7bff74 6570 c = find_omp_clause (clauses, OMP_CLAUSE_PROC_BIND);
6571 if (c)
6572 flags = build_int_cst (unsigned_type_node, OMP_CLAUSE_PROC_BIND_KIND (c));
6573
1e8e9920 6574 /* Ensure 'val' is of the correct type. */
389dd41b 6575 val = fold_convert_loc (clause_loc, unsigned_type_node, val);
1e8e9920 6576
6577 /* If we found the clause 'if (cond)', build either
6578 (cond != 0) or (cond ? val : 1u). */
6579 if (cond)
6580 {
773c5ba7 6581 cond = gimple_boolify (cond);
6582
1e8e9920 6583 if (integer_zerop (val))
389dd41b 6584 val = fold_build2_loc (clause_loc,
6585 EQ_EXPR, unsigned_type_node, cond,
79acaae1 6586 build_int_cst (TREE_TYPE (cond), 0));
1e8e9920 6587 else
773c5ba7 6588 {
6589 basic_block cond_bb, then_bb, else_bb;
79acaae1 6590 edge e, e_then, e_else;
75a70cf9 6591 tree tmp_then, tmp_else, tmp_join, tmp_var;
79acaae1 6592
f9e245b2 6593 tmp_var = create_tmp_var (TREE_TYPE (val));
79acaae1 6594 if (gimple_in_ssa_p (cfun))
6595 {
f9e245b2 6596 tmp_then = make_ssa_name (tmp_var);
6597 tmp_else = make_ssa_name (tmp_var);
6598 tmp_join = make_ssa_name (tmp_var);
79acaae1 6599 }
6600 else
6601 {
6602 tmp_then = tmp_var;
6603 tmp_else = tmp_var;
6604 tmp_join = tmp_var;
6605 }
773c5ba7 6606
4302d619 6607 e = split_block_after_labels (bb);
773c5ba7 6608 cond_bb = e->src;
6609 bb = e->dest;
6610 remove_edge (e);
6611
6612 then_bb = create_empty_bb (cond_bb);
6613 else_bb = create_empty_bb (then_bb);
79acaae1 6614 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
6615 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
773c5ba7 6616
75a70cf9 6617 stmt = gimple_build_cond_empty (cond);
6618 gsi = gsi_start_bb (cond_bb);
6619 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
773c5ba7 6620
75a70cf9 6621 gsi = gsi_start_bb (then_bb);
43895be5 6622 expand_omp_build_assign (&gsi, tmp_then, val, true);
773c5ba7 6623
75a70cf9 6624 gsi = gsi_start_bb (else_bb);
43895be5 6625 expand_omp_build_assign (&gsi, tmp_else,
6626 build_int_cst (unsigned_type_node, 1),
6627 true);
773c5ba7 6628
6629 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
6630 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
b3083327 6631 add_bb_to_loop (then_bb, cond_bb->loop_father);
6632 add_bb_to_loop (else_bb, cond_bb->loop_father);
79acaae1 6633 e_then = make_edge (then_bb, bb, EDGE_FALLTHRU);
6634 e_else = make_edge (else_bb, bb, EDGE_FALLTHRU);
773c5ba7 6635
79acaae1 6636 if (gimple_in_ssa_p (cfun))
6637 {
1a91d914 6638 gphi *phi = create_phi_node (tmp_join, bb);
60d535d2 6639 add_phi_arg (phi, tmp_then, e_then, UNKNOWN_LOCATION);
6640 add_phi_arg (phi, tmp_else, e_else, UNKNOWN_LOCATION);
79acaae1 6641 }
6642
6643 val = tmp_join;
773c5ba7 6644 }
6645
75a70cf9 6646 gsi = gsi_start_bb (bb);
6647 val = force_gimple_operand_gsi (&gsi, val, true, NULL_TREE,
6648 false, GSI_CONTINUE_LINKING);
1e8e9920 6649 }
6650
75a70cf9 6651 gsi = gsi_last_bb (bb);
6652 t = gimple_omp_parallel_data_arg (entry_stmt);
1e8e9920 6653 if (t == NULL)
c2f47e15 6654 t1 = null_pointer_node;
1e8e9920 6655 else
c2f47e15 6656 t1 = build_fold_addr_expr (t);
56686608 6657 tree child_fndecl = gimple_omp_parallel_child_fn (entry_stmt);
6658 t2 = build_fold_addr_expr (child_fndecl);
773c5ba7 6659
bc7bff74 6660 vec_alloc (args, 4 + vec_safe_length (ws_args));
f1f41a6c 6661 args->quick_push (t2);
6662 args->quick_push (t1);
6663 args->quick_push (val);
6664 if (ws_args)
6665 args->splice (*ws_args);
bc7bff74 6666 args->quick_push (flags);
414c3a2c 6667
6668 t = build_call_expr_loc_vec (UNKNOWN_LOCATION,
b9a16870 6669 builtin_decl_explicit (start_ix), args);
773c5ba7 6670
75a70cf9 6671 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6672 false, GSI_CONTINUE_LINKING);
56686608 6673
6674 if (hsa_gen_requested_p ()
6675 && parallel_needs_hsa_kernel_p (region))
6676 {
6677 cgraph_node *child_cnode = cgraph_node::get (child_fndecl);
6678 hsa_register_kernel (child_cnode);
6679 }
1e8e9920 6680}
6681
40750995 6682/* Insert a function call whose name is FUNC_NAME with the information from
6683 ENTRY_STMT into the basic_block BB. */
6684
6685static void
1a91d914 6686expand_cilk_for_call (basic_block bb, gomp_parallel *entry_stmt,
40750995 6687 vec <tree, va_gc> *ws_args)
6688{
6689 tree t, t1, t2;
6690 gimple_stmt_iterator gsi;
6691 vec <tree, va_gc> *args;
6692
6693 gcc_assert (vec_safe_length (ws_args) == 2);
6694 tree func_name = (*ws_args)[0];
6695 tree grain = (*ws_args)[1];
6696
6697 tree clauses = gimple_omp_parallel_clauses (entry_stmt);
6698 tree count = find_omp_clause (clauses, OMP_CLAUSE__CILK_FOR_COUNT_);
6699 gcc_assert (count != NULL_TREE);
6700 count = OMP_CLAUSE_OPERAND (count, 0);
6701
6702 gsi = gsi_last_bb (bb);
6703 t = gimple_omp_parallel_data_arg (entry_stmt);
6704 if (t == NULL)
6705 t1 = null_pointer_node;
6706 else
6707 t1 = build_fold_addr_expr (t);
6708 t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
6709
6710 vec_alloc (args, 4);
6711 args->quick_push (t2);
6712 args->quick_push (t1);
6713 args->quick_push (count);
6714 args->quick_push (grain);
6715 t = build_call_expr_loc_vec (UNKNOWN_LOCATION, func_name, args);
6716
6717 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, false,
6718 GSI_CONTINUE_LINKING);
6719}
773c5ba7 6720
fd6481cf 6721/* Build the function call to GOMP_task to actually
6722 generate the task operation. BB is the block where to insert the code. */
6723
6724static void
43895be5 6725expand_task_call (struct omp_region *region, basic_block bb,
6726 gomp_task *entry_stmt)
fd6481cf 6727{
43895be5 6728 tree t1, t2, t3;
75a70cf9 6729 gimple_stmt_iterator gsi;
389dd41b 6730 location_t loc = gimple_location (entry_stmt);
fd6481cf 6731
43895be5 6732 tree clauses = gimple_omp_task_clauses (entry_stmt);
6733
6734 tree ifc = find_omp_clause (clauses, OMP_CLAUSE_IF);
6735 tree untied = find_omp_clause (clauses, OMP_CLAUSE_UNTIED);
6736 tree mergeable = find_omp_clause (clauses, OMP_CLAUSE_MERGEABLE);
6737 tree depend = find_omp_clause (clauses, OMP_CLAUSE_DEPEND);
6738 tree finalc = find_omp_clause (clauses, OMP_CLAUSE_FINAL);
6739 tree priority = find_omp_clause (clauses, OMP_CLAUSE_PRIORITY);
6740
6741 unsigned int iflags
6742 = (untied ? GOMP_TASK_FLAG_UNTIED : 0)
6743 | (mergeable ? GOMP_TASK_FLAG_MERGEABLE : 0)
6744 | (depend ? GOMP_TASK_FLAG_DEPEND : 0);
6745
6746 bool taskloop_p = gimple_omp_task_taskloop_p (entry_stmt);
6747 tree startvar = NULL_TREE, endvar = NULL_TREE, step = NULL_TREE;
6748 tree num_tasks = NULL_TREE;
6749 bool ull = false;
6750 if (taskloop_p)
6751 {
6752 gimple *g = last_stmt (region->outer->entry);
6753 gcc_assert (gimple_code (g) == GIMPLE_OMP_FOR
6754 && gimple_omp_for_kind (g) == GF_OMP_FOR_KIND_TASKLOOP);
6755 struct omp_for_data fd;
6756 extract_omp_for_data (as_a <gomp_for *> (g), &fd, NULL);
6757 startvar = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
6758 endvar = find_omp_clause (OMP_CLAUSE_CHAIN (startvar),
6759 OMP_CLAUSE__LOOPTEMP_);
6760 startvar = OMP_CLAUSE_DECL (startvar);
6761 endvar = OMP_CLAUSE_DECL (endvar);
6762 step = fold_convert_loc (loc, fd.iter_type, fd.loop.step);
6763 if (fd.loop.cond_code == LT_EXPR)
6764 iflags |= GOMP_TASK_FLAG_UP;
6765 tree tclauses = gimple_omp_for_clauses (g);
6766 num_tasks = find_omp_clause (tclauses, OMP_CLAUSE_NUM_TASKS);
6767 if (num_tasks)
6768 num_tasks = OMP_CLAUSE_NUM_TASKS_EXPR (num_tasks);
6769 else
6770 {
6771 num_tasks = find_omp_clause (tclauses, OMP_CLAUSE_GRAINSIZE);
6772 if (num_tasks)
6773 {
6774 iflags |= GOMP_TASK_FLAG_GRAINSIZE;
6775 num_tasks = OMP_CLAUSE_GRAINSIZE_EXPR (num_tasks);
6776 }
6777 else
6778 num_tasks = integer_zero_node;
6779 }
6780 num_tasks = fold_convert_loc (loc, long_integer_type_node, num_tasks);
6781 if (ifc == NULL_TREE)
6782 iflags |= GOMP_TASK_FLAG_IF;
6783 if (find_omp_clause (tclauses, OMP_CLAUSE_NOGROUP))
6784 iflags |= GOMP_TASK_FLAG_NOGROUP;
6785 ull = fd.iter_type == long_long_unsigned_type_node;
6786 }
6787 else if (priority)
6788 iflags |= GOMP_TASK_FLAG_PRIORITY;
fd6481cf 6789
43895be5 6790 tree flags = build_int_cst (unsigned_type_node, iflags);
fd6481cf 6791
43895be5 6792 tree cond = boolean_true_node;
6793 if (ifc)
6794 {
6795 if (taskloop_p)
6796 {
6797 tree t = gimple_boolify (OMP_CLAUSE_IF_EXPR (ifc));
6798 t = fold_build3_loc (loc, COND_EXPR, unsigned_type_node, t,
6799 build_int_cst (unsigned_type_node,
6800 GOMP_TASK_FLAG_IF),
6801 build_int_cst (unsigned_type_node, 0));
6802 flags = fold_build2_loc (loc, PLUS_EXPR, unsigned_type_node,
6803 flags, t);
6804 }
6805 else
6806 cond = gimple_boolify (OMP_CLAUSE_IF_EXPR (ifc));
6807 }
2169f33b 6808
43895be5 6809 if (finalc)
2169f33b 6810 {
43895be5 6811 tree t = gimple_boolify (OMP_CLAUSE_FINAL_EXPR (finalc));
6812 t = fold_build3_loc (loc, COND_EXPR, unsigned_type_node, t,
6813 build_int_cst (unsigned_type_node,
6814 GOMP_TASK_FLAG_FINAL),
2169f33b 6815 build_int_cst (unsigned_type_node, 0));
43895be5 6816 flags = fold_build2_loc (loc, PLUS_EXPR, unsigned_type_node, flags, t);
2169f33b 6817 }
bc7bff74 6818 if (depend)
6819 depend = OMP_CLAUSE_DECL (depend);
6820 else
6821 depend = build_int_cst (ptr_type_node, 0);
43895be5 6822 if (priority)
6823 priority = fold_convert (integer_type_node,
6824 OMP_CLAUSE_PRIORITY_EXPR (priority));
6825 else
6826 priority = integer_zero_node;
fd6481cf 6827
75a70cf9 6828 gsi = gsi_last_bb (bb);
43895be5 6829 tree t = gimple_omp_task_data_arg (entry_stmt);
fd6481cf 6830 if (t == NULL)
6831 t2 = null_pointer_node;
6832 else
389dd41b 6833 t2 = build_fold_addr_expr_loc (loc, t);
6834 t1 = build_fold_addr_expr_loc (loc, gimple_omp_task_child_fn (entry_stmt));
75a70cf9 6835 t = gimple_omp_task_copy_fn (entry_stmt);
fd6481cf 6836 if (t == NULL)
6837 t3 = null_pointer_node;
6838 else
389dd41b 6839 t3 = build_fold_addr_expr_loc (loc, t);
fd6481cf 6840
43895be5 6841 if (taskloop_p)
6842 t = build_call_expr (ull
6843 ? builtin_decl_explicit (BUILT_IN_GOMP_TASKLOOP_ULL)
6844 : builtin_decl_explicit (BUILT_IN_GOMP_TASKLOOP),
6845 11, t1, t2, t3,
6846 gimple_omp_task_arg_size (entry_stmt),
6847 gimple_omp_task_arg_align (entry_stmt), flags,
6848 num_tasks, priority, startvar, endvar, step);
6849 else
6850 t = build_call_expr (builtin_decl_explicit (BUILT_IN_GOMP_TASK),
6851 9, t1, t2, t3,
6852 gimple_omp_task_arg_size (entry_stmt),
6853 gimple_omp_task_arg_align (entry_stmt), cond, flags,
6854 depend, priority);
fd6481cf 6855
75a70cf9 6856 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6857 false, GSI_CONTINUE_LINKING);
fd6481cf 6858}
6859
6860
75a70cf9 6861/* If exceptions are enabled, wrap the statements in BODY in a MUST_NOT_THROW
6862 catch handler and return it. This prevents programs from violating the
6863 structured block semantics with throws. */
1e8e9920 6864
75a70cf9 6865static gimple_seq
6866maybe_catch_exception (gimple_seq body)
1e8e9920 6867{
42acab1c 6868 gimple *g;
e38def9c 6869 tree decl;
1e8e9920 6870
6871 if (!flag_exceptions)
75a70cf9 6872 return body;
1e8e9920 6873
596981c8 6874 if (lang_hooks.eh_protect_cleanup_actions != NULL)
6875 decl = lang_hooks.eh_protect_cleanup_actions ();
1e8e9920 6876 else
b9a16870 6877 decl = builtin_decl_explicit (BUILT_IN_TRAP);
75a70cf9 6878
e38def9c 6879 g = gimple_build_eh_must_not_throw (decl);
6880 g = gimple_build_try (body, gimple_seq_alloc_with_stmt (g),
75a70cf9 6881 GIMPLE_TRY_CATCH);
1e8e9920 6882
e38def9c 6883 return gimple_seq_alloc_with_stmt (g);
1e8e9920 6884}
6885
773c5ba7 6886/* Chain all the DECLs in LIST by their TREE_CHAIN fields. */
1e8e9920 6887
773c5ba7 6888static tree
f1f41a6c 6889vec2chain (vec<tree, va_gc> *v)
1e8e9920 6890{
2ab2ce89 6891 tree chain = NULL_TREE, t;
6892 unsigned ix;
1e8e9920 6893
f1f41a6c 6894 FOR_EACH_VEC_SAFE_ELT_REVERSE (v, ix, t)
773c5ba7 6895 {
1767a056 6896 DECL_CHAIN (t) = chain;
2ab2ce89 6897 chain = t;
773c5ba7 6898 }
1e8e9920 6899
2ab2ce89 6900 return chain;
773c5ba7 6901}
1e8e9920 6902
1e8e9920 6903
773c5ba7 6904/* Remove barriers in REGION->EXIT's block. Note that this is only
75a70cf9 6905 valid for GIMPLE_OMP_PARALLEL regions. Since the end of a parallel region
6906 is an implicit barrier, any workshare inside the GIMPLE_OMP_PARALLEL that
6907 left a barrier at the end of the GIMPLE_OMP_PARALLEL region can now be
773c5ba7 6908 removed. */
1e8e9920 6909
773c5ba7 6910static void
6911remove_exit_barrier (struct omp_region *region)
6912{
75a70cf9 6913 gimple_stmt_iterator gsi;
773c5ba7 6914 basic_block exit_bb;
61e47ac8 6915 edge_iterator ei;
6916 edge e;
42acab1c 6917 gimple *stmt;
4a04f4b4 6918 int any_addressable_vars = -1;
1e8e9920 6919
61e47ac8 6920 exit_bb = region->exit;
1e8e9920 6921
5056ba1a 6922 /* If the parallel region doesn't return, we don't have REGION->EXIT
6923 block at all. */
6924 if (! exit_bb)
6925 return;
6926
75a70cf9 6927 /* The last insn in the block will be the parallel's GIMPLE_OMP_RETURN. The
6928 workshare's GIMPLE_OMP_RETURN will be in a preceding block. The kinds of
61e47ac8 6929 statements that can appear in between are extremely limited -- no
6930 memory operations at all. Here, we allow nothing at all, so the
75a70cf9 6931 only thing we allow to precede this GIMPLE_OMP_RETURN is a label. */
6932 gsi = gsi_last_bb (exit_bb);
6933 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
6934 gsi_prev (&gsi);
6935 if (!gsi_end_p (gsi) && gimple_code (gsi_stmt (gsi)) != GIMPLE_LABEL)
773c5ba7 6936 return;
1e8e9920 6937
61e47ac8 6938 FOR_EACH_EDGE (e, ei, exit_bb->preds)
6939 {
75a70cf9 6940 gsi = gsi_last_bb (e->src);
6941 if (gsi_end_p (gsi))
61e47ac8 6942 continue;
75a70cf9 6943 stmt = gsi_stmt (gsi);
4a04f4b4 6944 if (gimple_code (stmt) == GIMPLE_OMP_RETURN
6945 && !gimple_omp_return_nowait_p (stmt))
6946 {
6947 /* OpenMP 3.0 tasks unfortunately prevent this optimization
6948 in many cases. If there could be tasks queued, the barrier
6949 might be needed to let the tasks run before some local
6950 variable of the parallel that the task uses as shared
6951 runs out of scope. The task can be spawned either
6952 from within current function (this would be easy to check)
6953 or from some function it calls and gets passed an address
6954 of such a variable. */
6955 if (any_addressable_vars < 0)
6956 {
1a91d914 6957 gomp_parallel *parallel_stmt
6958 = as_a <gomp_parallel *> (last_stmt (region->entry));
4a04f4b4 6959 tree child_fun = gimple_omp_parallel_child_fn (parallel_stmt);
2ab2ce89 6960 tree local_decls, block, decl;
6961 unsigned ix;
4a04f4b4 6962
6963 any_addressable_vars = 0;
2ab2ce89 6964 FOR_EACH_LOCAL_DECL (DECL_STRUCT_FUNCTION (child_fun), ix, decl)
6965 if (TREE_ADDRESSABLE (decl))
4a04f4b4 6966 {
6967 any_addressable_vars = 1;
6968 break;
6969 }
6970 for (block = gimple_block (stmt);
6971 !any_addressable_vars
6972 && block
6973 && TREE_CODE (block) == BLOCK;
6974 block = BLOCK_SUPERCONTEXT (block))
6975 {
6976 for (local_decls = BLOCK_VARS (block);
6977 local_decls;
1767a056 6978 local_decls = DECL_CHAIN (local_decls))
4a04f4b4 6979 if (TREE_ADDRESSABLE (local_decls))
6980 {
6981 any_addressable_vars = 1;
6982 break;
6983 }
6984 if (block == gimple_block (parallel_stmt))
6985 break;
6986 }
6987 }
6988 if (!any_addressable_vars)
6989 gimple_omp_return_set_nowait (stmt);
6990 }
61e47ac8 6991 }
1e8e9920 6992}
6993
61e47ac8 6994static void
6995remove_exit_barriers (struct omp_region *region)
6996{
75a70cf9 6997 if (region->type == GIMPLE_OMP_PARALLEL)
61e47ac8 6998 remove_exit_barrier (region);
6999
7000 if (region->inner)
7001 {
7002 region = region->inner;
7003 remove_exit_barriers (region);
7004 while (region->next)
7005 {
7006 region = region->next;
7007 remove_exit_barriers (region);
7008 }
7009 }
7010}
773c5ba7 7011
658b4427 7012/* Optimize omp_get_thread_num () and omp_get_num_threads ()
7013 calls. These can't be declared as const functions, but
7014 within one parallel body they are constant, so they can be
7015 transformed there into __builtin_omp_get_{thread_num,num_threads} ()
fd6481cf 7016 which are declared const. Similarly for task body, except
7017 that in untied task omp_get_thread_num () can change at any task
7018 scheduling point. */
658b4427 7019
7020static void
42acab1c 7021optimize_omp_library_calls (gimple *entry_stmt)
658b4427 7022{
7023 basic_block bb;
75a70cf9 7024 gimple_stmt_iterator gsi;
b9a16870 7025 tree thr_num_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
7026 tree thr_num_id = DECL_ASSEMBLER_NAME (thr_num_tree);
7027 tree num_thr_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
7028 tree num_thr_id = DECL_ASSEMBLER_NAME (num_thr_tree);
75a70cf9 7029 bool untied_task = (gimple_code (entry_stmt) == GIMPLE_OMP_TASK
7030 && find_omp_clause (gimple_omp_task_clauses (entry_stmt),
fd6481cf 7031 OMP_CLAUSE_UNTIED) != NULL);
658b4427 7032
fc00614f 7033 FOR_EACH_BB_FN (bb, cfun)
75a70cf9 7034 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
658b4427 7035 {
42acab1c 7036 gimple *call = gsi_stmt (gsi);
658b4427 7037 tree decl;
7038
75a70cf9 7039 if (is_gimple_call (call)
7040 && (decl = gimple_call_fndecl (call))
658b4427 7041 && DECL_EXTERNAL (decl)
7042 && TREE_PUBLIC (decl)
7043 && DECL_INITIAL (decl) == NULL)
7044 {
7045 tree built_in;
7046
7047 if (DECL_NAME (decl) == thr_num_id)
fd6481cf 7048 {
7049 /* In #pragma omp task untied omp_get_thread_num () can change
7050 during the execution of the task region. */
7051 if (untied_task)
7052 continue;
b9a16870 7053 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
fd6481cf 7054 }
658b4427 7055 else if (DECL_NAME (decl) == num_thr_id)
b9a16870 7056 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
658b4427 7057 else
7058 continue;
7059
7060 if (DECL_ASSEMBLER_NAME (decl) != DECL_ASSEMBLER_NAME (built_in)
75a70cf9 7061 || gimple_call_num_args (call) != 0)
658b4427 7062 continue;
7063
7064 if (flag_exceptions && !TREE_NOTHROW (decl))
7065 continue;
7066
7067 if (TREE_CODE (TREE_TYPE (decl)) != FUNCTION_TYPE
1ea6a73c 7068 || !types_compatible_p (TREE_TYPE (TREE_TYPE (decl)),
7069 TREE_TYPE (TREE_TYPE (built_in))))
658b4427 7070 continue;
7071
0acacf9e 7072 gimple_call_set_fndecl (call, built_in);
658b4427 7073 }
7074 }
7075}
7076
8e6b4515 7077/* Callback for expand_omp_build_assign. Return non-NULL if *tp needs to be
7078 regimplified. */
7079
7080static tree
7081expand_omp_regimplify_p (tree *tp, int *walk_subtrees, void *)
7082{
7083 tree t = *tp;
7084
7085 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
7086 if (TREE_CODE (t) == VAR_DECL && DECL_HAS_VALUE_EXPR_P (t))
7087 return t;
7088
7089 if (TREE_CODE (t) == ADDR_EXPR)
7090 recompute_tree_invariant_for_addr_expr (t);
7091
7092 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
7093 return NULL_TREE;
7094}
7095
43895be5 7096/* Prepend or append TO = FROM assignment before or after *GSI_P. */
3d483a94 7097
7098static void
43895be5 7099expand_omp_build_assign (gimple_stmt_iterator *gsi_p, tree to, tree from,
7100 bool after)
3d483a94 7101{
7102 bool simple_p = DECL_P (to) && TREE_ADDRESSABLE (to);
7103 from = force_gimple_operand_gsi (gsi_p, from, simple_p, NULL_TREE,
43895be5 7104 !after, after ? GSI_CONTINUE_LINKING
7105 : GSI_SAME_STMT);
42acab1c 7106 gimple *stmt = gimple_build_assign (to, from);
43895be5 7107 if (after)
7108 gsi_insert_after (gsi_p, stmt, GSI_CONTINUE_LINKING);
7109 else
7110 gsi_insert_before (gsi_p, stmt, GSI_SAME_STMT);
3d483a94 7111 if (walk_tree (&from, expand_omp_regimplify_p, NULL, NULL)
7112 || walk_tree (&to, expand_omp_regimplify_p, NULL, NULL))
7113 {
7114 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
7115 gimple_regimplify_operands (stmt, &gsi);
7116 }
7117}
7118
fd6481cf 7119/* Expand the OpenMP parallel or task directive starting at REGION. */
1e8e9920 7120
7121static void
fd6481cf 7122expand_omp_taskreg (struct omp_region *region)
1e8e9920 7123{
773c5ba7 7124 basic_block entry_bb, exit_bb, new_bb;
87d4aa85 7125 struct function *child_cfun;
414c3a2c 7126 tree child_fn, block, t;
75a70cf9 7127 gimple_stmt_iterator gsi;
42acab1c 7128 gimple *entry_stmt, *stmt;
773c5ba7 7129 edge e;
f1f41a6c 7130 vec<tree, va_gc> *ws_args;
773c5ba7 7131
61e47ac8 7132 entry_stmt = last_stmt (region->entry);
75a70cf9 7133 child_fn = gimple_omp_taskreg_child_fn (entry_stmt);
773c5ba7 7134 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
773c5ba7 7135
61e47ac8 7136 entry_bb = region->entry;
b25f70fd 7137 if (gimple_code (entry_stmt) == GIMPLE_OMP_TASK)
7138 exit_bb = region->cont;
7139 else
7140 exit_bb = region->exit;
773c5ba7 7141
40750995 7142 bool is_cilk_for
7143 = (flag_cilkplus
7144 && gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL
7145 && find_omp_clause (gimple_omp_parallel_clauses (entry_stmt),
7146 OMP_CLAUSE__CILK_FOR_COUNT_) != NULL_TREE);
7147
7148 if (is_cilk_for)
7149 /* If it is a _Cilk_for statement, it is modelled *like* a parallel for,
7150 and the inner statement contains the name of the built-in function
7151 and grain. */
7152 ws_args = region->inner->ws_args;
7153 else if (is_combined_parallel (region))
61e47ac8 7154 ws_args = region->ws_args;
773c5ba7 7155 else
414c3a2c 7156 ws_args = NULL;
1e8e9920 7157
61e47ac8 7158 if (child_cfun->cfg)
1e8e9920 7159 {
773c5ba7 7160 /* Due to inlining, it may happen that we have already outlined
7161 the region, in which case all we need to do is make the
7162 sub-graph unreachable and emit the parallel call. */
7163 edge entry_succ_e, exit_succ_e;
773c5ba7 7164
7165 entry_succ_e = single_succ_edge (entry_bb);
773c5ba7 7166
75a70cf9 7167 gsi = gsi_last_bb (entry_bb);
7168 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_PARALLEL
7169 || gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_TASK);
7170 gsi_remove (&gsi, true);
773c5ba7 7171
7172 new_bb = entry_bb;
03ed154b 7173 if (exit_bb)
7174 {
7175 exit_succ_e = single_succ_edge (exit_bb);
7176 make_edge (new_bb, exit_succ_e->dest, EDGE_FALLTHRU);
7177 }
79acaae1 7178 remove_edge_and_dominated_blocks (entry_succ_e);
1e8e9920 7179 }
773c5ba7 7180 else
7181 {
501bdd19 7182 unsigned srcidx, dstidx, num;
2ab2ce89 7183
773c5ba7 7184 /* If the parallel region needs data sent from the parent
3480139d 7185 function, then the very first statement (except possible
7186 tree profile counter updates) of the parallel body
773c5ba7 7187 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
7188 &.OMP_DATA_O is passed as an argument to the child function,
7189 we need to replace it with the argument as seen by the child
7190 function.
7191
7192 In most cases, this will end up being the identity assignment
7193 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
7194 a function call that has been inlined, the original PARM_DECL
7195 .OMP_DATA_I may have been converted into a different local
7196 variable. In which case, we need to keep the assignment. */
75a70cf9 7197 if (gimple_omp_taskreg_data_arg (entry_stmt))
773c5ba7 7198 {
b25f70fd 7199 basic_block entry_succ_bb
7200 = single_succ_p (entry_bb) ? single_succ (entry_bb)
7201 : FALLTHRU_EDGE (entry_bb)->dest;
883f001d 7202 tree arg;
42acab1c 7203 gimple *parcopy_stmt = NULL;
1e8e9920 7204
75a70cf9 7205 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
3480139d 7206 {
42acab1c 7207 gimple *stmt;
3480139d 7208
75a70cf9 7209 gcc_assert (!gsi_end_p (gsi));
7210 stmt = gsi_stmt (gsi);
7211 if (gimple_code (stmt) != GIMPLE_ASSIGN)
cc6b725b 7212 continue;
7213
75a70cf9 7214 if (gimple_num_ops (stmt) == 2)
3480139d 7215 {
75a70cf9 7216 tree arg = gimple_assign_rhs1 (stmt);
7217
7218 /* We're ignore the subcode because we're
7219 effectively doing a STRIP_NOPS. */
7220
7221 if (TREE_CODE (arg) == ADDR_EXPR
7222 && TREE_OPERAND (arg, 0)
7223 == gimple_omp_taskreg_data_arg (entry_stmt))
7224 {
7225 parcopy_stmt = stmt;
7226 break;
7227 }
3480139d 7228 }
7229 }
79acaae1 7230
75a70cf9 7231 gcc_assert (parcopy_stmt != NULL);
79acaae1 7232 arg = DECL_ARGUMENTS (child_fn);
7233
7234 if (!gimple_in_ssa_p (cfun))
7235 {
75a70cf9 7236 if (gimple_assign_lhs (parcopy_stmt) == arg)
7237 gsi_remove (&gsi, true);
79acaae1 7238 else
75a70cf9 7239 {
7240 /* ?? Is setting the subcode really necessary ?? */
7241 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (arg));
7242 gimple_assign_set_rhs1 (parcopy_stmt, arg);
7243 }
79acaae1 7244 }
7245 else
7246 {
883f001d 7247 tree lhs = gimple_assign_lhs (parcopy_stmt);
7248 gcc_assert (SSA_NAME_VAR (lhs) == arg);
7249 /* We'd like to set the rhs to the default def in the child_fn,
7250 but it's too early to create ssa names in the child_fn.
7251 Instead, we set the rhs to the parm. In
7252 move_sese_region_to_fn, we introduce a default def for the
7253 parm, map the parm to it's default def, and once we encounter
7254 this stmt, replace the parm with the default def. */
7255 gimple_assign_set_rhs1 (parcopy_stmt, arg);
79acaae1 7256 update_stmt (parcopy_stmt);
7257 }
773c5ba7 7258 }
7259
7260 /* Declare local variables needed in CHILD_CFUN. */
7261 block = DECL_INITIAL (child_fn);
2ab2ce89 7262 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
e1a7ccb9 7263 /* The gimplifier could record temporaries in parallel/task block
7264 rather than in containing function's local_decls chain,
7265 which would mean cgraph missed finalizing them. Do it now. */
1767a056 7266 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
e1a7ccb9 7267 if (TREE_CODE (t) == VAR_DECL
7268 && TREE_STATIC (t)
7269 && !DECL_EXTERNAL (t))
97221fd7 7270 varpool_node::finalize_decl (t);
75a70cf9 7271 DECL_SAVED_TREE (child_fn) = NULL;
e3a19533 7272 /* We'll create a CFG for child_fn, so no gimple body is needed. */
7273 gimple_set_body (child_fn, NULL);
1d22f541 7274 TREE_USED (block) = 1;
773c5ba7 7275
79acaae1 7276 /* Reset DECL_CONTEXT on function arguments. */
1767a056 7277 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
773c5ba7 7278 DECL_CONTEXT (t) = child_fn;
7279
75a70cf9 7280 /* Split ENTRY_BB at GIMPLE_OMP_PARALLEL or GIMPLE_OMP_TASK,
7281 so that it can be moved to the child function. */
7282 gsi = gsi_last_bb (entry_bb);
7283 stmt = gsi_stmt (gsi);
7284 gcc_assert (stmt && (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
7285 || gimple_code (stmt) == GIMPLE_OMP_TASK));
75a70cf9 7286 e = split_block (entry_bb, stmt);
923635e7 7287 gsi_remove (&gsi, true);
773c5ba7 7288 entry_bb = e->dest;
b25f70fd 7289 edge e2 = NULL;
7290 if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
7291 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7292 else
7293 {
7294 e2 = make_edge (e->src, BRANCH_EDGE (entry_bb)->dest, EDGE_ABNORMAL);
7295 gcc_assert (e2->dest == region->exit);
7296 remove_edge (BRANCH_EDGE (entry_bb));
7297 set_immediate_dominator (CDI_DOMINATORS, e2->dest, e->src);
7298 gsi = gsi_last_bb (region->exit);
7299 gcc_assert (!gsi_end_p (gsi)
7300 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
7301 gsi_remove (&gsi, true);
7302 }
773c5ba7 7303
b25f70fd 7304 /* Convert GIMPLE_OMP_{RETURN,CONTINUE} into a RETURN_EXPR. */
5056ba1a 7305 if (exit_bb)
7306 {
75a70cf9 7307 gsi = gsi_last_bb (exit_bb);
7308 gcc_assert (!gsi_end_p (gsi)
b25f70fd 7309 && (gimple_code (gsi_stmt (gsi))
7310 == (e2 ? GIMPLE_OMP_CONTINUE : GIMPLE_OMP_RETURN)));
75a70cf9 7311 stmt = gimple_build_return (NULL);
7312 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
7313 gsi_remove (&gsi, true);
5056ba1a 7314 }
79acaae1 7315
7316 /* Move the parallel region into CHILD_CFUN. */
48e1416a 7317
79acaae1 7318 if (gimple_in_ssa_p (cfun))
7319 {
bcaa2770 7320 init_tree_ssa (child_cfun);
5084b2e4 7321 init_ssa_operands (child_cfun);
7322 child_cfun->gimple_df->in_ssa_p = true;
1d22f541 7323 block = NULL_TREE;
79acaae1 7324 }
1d22f541 7325 else
75a70cf9 7326 block = gimple_block (entry_stmt);
1d22f541 7327
7328 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
79acaae1 7329 if (exit_bb)
7330 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
b25f70fd 7331 if (e2)
7332 {
7333 basic_block dest_bb = e2->dest;
7334 if (!exit_bb)
7335 make_edge (new_bb, dest_bb, EDGE_FALLTHRU);
7336 remove_edge (e2);
7337 set_immediate_dominator (CDI_DOMINATORS, dest_bb, new_bb);
7338 }
04c2922b 7339 /* When the OMP expansion process cannot guarantee an up-to-date
7340 loop tree arrange for the child function to fixup loops. */
7341 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
7342 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
79acaae1 7343
1d22f541 7344 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
f1f41a6c 7345 num = vec_safe_length (child_cfun->local_decls);
501bdd19 7346 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
7347 {
f1f41a6c 7348 t = (*child_cfun->local_decls)[srcidx];
501bdd19 7349 if (DECL_CONTEXT (t) == cfun->decl)
7350 continue;
7351 if (srcidx != dstidx)
f1f41a6c 7352 (*child_cfun->local_decls)[dstidx] = t;
501bdd19 7353 dstidx++;
7354 }
7355 if (dstidx != num)
f1f41a6c 7356 vec_safe_truncate (child_cfun->local_decls, dstidx);
1d22f541 7357
79acaae1 7358 /* Inform the callgraph about the new function. */
9918db44 7359 child_cfun->curr_properties = cfun->curr_properties;
7360 child_cfun->has_simduid_loops |= cfun->has_simduid_loops;
7361 child_cfun->has_force_vectorize_loops |= cfun->has_force_vectorize_loops;
47300487 7362 cgraph_node *node = cgraph_node::get_create (child_fn);
7363 node->parallelized_function = 1;
415d1b9a 7364 cgraph_node::add_new_function (child_fn, true);
79acaae1 7365
9561765e 7366 bool need_asm = DECL_ASSEMBLER_NAME_SET_P (current_function_decl)
7367 && !DECL_ASSEMBLER_NAME_SET_P (child_fn);
7368
79acaae1 7369 /* Fix the callgraph edges for child_cfun. Those for cfun will be
7370 fixed in a following pass. */
7371 push_cfun (child_cfun);
9561765e 7372 if (need_asm)
7373 assign_assembler_name_if_neeeded (child_fn);
7374
658b4427 7375 if (optimize)
fd6481cf 7376 optimize_omp_library_calls (entry_stmt);
35ee1c66 7377 cgraph_edge::rebuild_edges ();
fbe86b1b 7378
7379 /* Some EH regions might become dead, see PR34608. If
7380 pass_cleanup_cfg isn't the first pass to happen with the
7381 new child, these dead EH edges might cause problems.
7382 Clean them up now. */
7383 if (flag_exceptions)
7384 {
7385 basic_block bb;
fbe86b1b 7386 bool changed = false;
7387
fc00614f 7388 FOR_EACH_BB_FN (bb, cfun)
75a70cf9 7389 changed |= gimple_purge_dead_eh_edges (bb);
fbe86b1b 7390 if (changed)
7391 cleanup_tree_cfg ();
fbe86b1b 7392 }
dd277d48 7393 if (gimple_in_ssa_p (cfun))
7394 update_ssa (TODO_update_ssa);
382ecba7 7395 if (flag_checking && !loops_state_satisfies_p (LOOPS_NEED_FIXUP))
86a932e0 7396 verify_loop_structure ();
79acaae1 7397 pop_cfun ();
9561765e 7398
7399 if (dump_file && !gimple_in_ssa_p (cfun))
7400 {
7401 omp_any_child_fn_dumped = true;
7402 dump_function_header (dump_file, child_fn, dump_flags);
7403 dump_function_to_file (child_fn, dump_file, dump_flags);
7404 }
773c5ba7 7405 }
48e1416a 7406
773c5ba7 7407 /* Emit a library call to launch the children threads. */
40750995 7408 if (is_cilk_for)
1a91d914 7409 expand_cilk_for_call (new_bb,
7410 as_a <gomp_parallel *> (entry_stmt), ws_args);
40750995 7411 else if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
1a91d914 7412 expand_parallel_call (region, new_bb,
7413 as_a <gomp_parallel *> (entry_stmt), ws_args);
fd6481cf 7414 else
43895be5 7415 expand_task_call (region, new_bb, as_a <gomp_task *> (entry_stmt));
083152fb 7416 if (gimple_in_ssa_p (cfun))
7417 update_ssa (TODO_update_ssa_only_virtuals);
1e8e9920 7418}
7419
a8e785ba 7420/* Information about members of an OpenACC collapsed loop nest. */
7421
7422struct oacc_collapse
7423{
7424 tree base; /* Base value. */
7425 tree iters; /* Number of steps. */
7426 tree step; /* step size. */
7427};
7428
7429/* Helper for expand_oacc_for. Determine collapsed loop information.
7430 Fill in COUNTS array. Emit any initialization code before GSI.
7431 Return the calculated outer loop bound of BOUND_TYPE. */
7432
7433static tree
7434expand_oacc_collapse_init (const struct omp_for_data *fd,
7435 gimple_stmt_iterator *gsi,
7436 oacc_collapse *counts, tree bound_type)
7437{
7438 tree total = build_int_cst (bound_type, 1);
7439 int ix;
7440
7441 gcc_assert (integer_onep (fd->loop.step));
7442 gcc_assert (integer_zerop (fd->loop.n1));
7443
7444 for (ix = 0; ix != fd->collapse; ix++)
7445 {
7446 const omp_for_data_loop *loop = &fd->loops[ix];
7447
7448 tree iter_type = TREE_TYPE (loop->v);
7449 tree diff_type = iter_type;
7450 tree plus_type = iter_type;
7451
7452 gcc_assert (loop->cond_code == fd->loop.cond_code);
7453
7454 if (POINTER_TYPE_P (iter_type))
7455 plus_type = sizetype;
7456 if (POINTER_TYPE_P (diff_type) || TYPE_UNSIGNED (diff_type))
7457 diff_type = signed_type_for (diff_type);
7458
7459 tree b = loop->n1;
7460 tree e = loop->n2;
7461 tree s = loop->step;
7462 bool up = loop->cond_code == LT_EXPR;
7463 tree dir = build_int_cst (diff_type, up ? +1 : -1);
7464 bool negating;
7465 tree expr;
7466
7467 b = force_gimple_operand_gsi (gsi, b, true, NULL_TREE,
7468 true, GSI_SAME_STMT);
7469 e = force_gimple_operand_gsi (gsi, e, true, NULL_TREE,
7470 true, GSI_SAME_STMT);
7471
7472 /* Convert the step, avoiding possible unsigned->signed overflow. */
7473 negating = !up && TYPE_UNSIGNED (TREE_TYPE (s));
7474 if (negating)
7475 s = fold_build1 (NEGATE_EXPR, TREE_TYPE (s), s);
7476 s = fold_convert (diff_type, s);
7477 if (negating)
7478 s = fold_build1 (NEGATE_EXPR, diff_type, s);
7479 s = force_gimple_operand_gsi (gsi, s, true, NULL_TREE,
7480 true, GSI_SAME_STMT);
7481
7482 /* Determine the range, avoiding possible unsigned->signed overflow. */
7483 negating = !up && TYPE_UNSIGNED (iter_type);
7484 expr = fold_build2 (MINUS_EXPR, plus_type,
7485 fold_convert (plus_type, negating ? b : e),
7486 fold_convert (plus_type, negating ? e : b));
7487 expr = fold_convert (diff_type, expr);
7488 if (negating)
7489 expr = fold_build1 (NEGATE_EXPR, diff_type, expr);
7490 tree range = force_gimple_operand_gsi
7491 (gsi, expr, true, NULL_TREE, true, GSI_SAME_STMT);
7492
7493 /* Determine number of iterations. */
7494 expr = fold_build2 (MINUS_EXPR, diff_type, range, dir);
7495 expr = fold_build2 (PLUS_EXPR, diff_type, expr, s);
7496 expr = fold_build2 (TRUNC_DIV_EXPR, diff_type, expr, s);
7497
7498 tree iters = force_gimple_operand_gsi (gsi, expr, true, NULL_TREE,
7499 true, GSI_SAME_STMT);
7500
7501 counts[ix].base = b;
7502 counts[ix].iters = iters;
7503 counts[ix].step = s;
7504
7505 total = fold_build2 (MULT_EXPR, bound_type, total,
7506 fold_convert (bound_type, iters));
7507 }
7508
7509 return total;
7510}
7511
7512/* Emit initializers for collapsed loop members. IVAR is the outer
7513 loop iteration variable, from which collapsed loop iteration values
7514 are calculated. COUNTS array has been initialized by
7515 expand_oacc_collapse_inits. */
7516
7517static void
7518expand_oacc_collapse_vars (const struct omp_for_data *fd,
7519 gimple_stmt_iterator *gsi,
7520 const oacc_collapse *counts, tree ivar)
7521{
7522 tree ivar_type = TREE_TYPE (ivar);
7523
7524 /* The most rapidly changing iteration variable is the innermost
7525 one. */
7526 for (int ix = fd->collapse; ix--;)
7527 {
7528 const omp_for_data_loop *loop = &fd->loops[ix];
7529 const oacc_collapse *collapse = &counts[ix];
7530 tree iter_type = TREE_TYPE (loop->v);
7531 tree diff_type = TREE_TYPE (collapse->step);
7532 tree plus_type = iter_type;
7533 enum tree_code plus_code = PLUS_EXPR;
7534 tree expr;
7535
7536 if (POINTER_TYPE_P (iter_type))
7537 {
7538 plus_code = POINTER_PLUS_EXPR;
7539 plus_type = sizetype;
7540 }
7541
7542 expr = fold_build2 (TRUNC_MOD_EXPR, ivar_type, ivar,
7543 fold_convert (ivar_type, collapse->iters));
7544 expr = fold_build2 (MULT_EXPR, diff_type, fold_convert (diff_type, expr),
7545 collapse->step);
7546 expr = fold_build2 (plus_code, iter_type, collapse->base,
7547 fold_convert (plus_type, expr));
7548 expr = force_gimple_operand_gsi (gsi, expr, false, NULL_TREE,
7549 true, GSI_SAME_STMT);
7550 gassign *ass = gimple_build_assign (loop->v, expr);
7551 gsi_insert_before (gsi, ass, GSI_SAME_STMT);
7552
7553 if (ix)
7554 {
7555 expr = fold_build2 (TRUNC_DIV_EXPR, ivar_type, ivar,
7556 fold_convert (ivar_type, collapse->iters));
7557 ivar = force_gimple_operand_gsi (gsi, expr, true, NULL_TREE,
7558 true, GSI_SAME_STMT);
7559 }
7560 }
7561}
7562
773c5ba7 7563
3d483a94 7564/* Helper function for expand_omp_{for_*,simd}. If this is the outermost
7565 of the combined collapse > 1 loop constructs, generate code like:
7566 if (__builtin_expect (N32 cond3 N31, 0)) goto ZERO_ITER_BB;
7567 if (cond3 is <)
7568 adj = STEP3 - 1;
7569 else
7570 adj = STEP3 + 1;
7571 count3 = (adj + N32 - N31) / STEP3;
7572 if (__builtin_expect (N22 cond2 N21, 0)) goto ZERO_ITER_BB;
7573 if (cond2 is <)
7574 adj = STEP2 - 1;
7575 else
7576 adj = STEP2 + 1;
7577 count2 = (adj + N22 - N21) / STEP2;
7578 if (__builtin_expect (N12 cond1 N11, 0)) goto ZERO_ITER_BB;
7579 if (cond1 is <)
7580 adj = STEP1 - 1;
7581 else
7582 adj = STEP1 + 1;
7583 count1 = (adj + N12 - N11) / STEP1;
7584 count = count1 * count2 * count3;
7585 Furthermore, if ZERO_ITER_BB is NULL, create a BB which does:
7586 count = 0;
bc7bff74 7587 and set ZERO_ITER_BB to that bb. If this isn't the outermost
7588 of the combined loop constructs, just initialize COUNTS array
7589 from the _looptemp_ clauses. */
3d483a94 7590
7591/* NOTE: It *could* be better to moosh all of the BBs together,
7592 creating one larger BB with all the computation and the unexpected
7593 jump at the end. I.e.
7594
7595 bool zero3, zero2, zero1, zero;
7596
7597 zero3 = N32 c3 N31;
7598 count3 = (N32 - N31) /[cl] STEP3;
7599 zero2 = N22 c2 N21;
7600 count2 = (N22 - N21) /[cl] STEP2;
7601 zero1 = N12 c1 N11;
7602 count1 = (N12 - N11) /[cl] STEP1;
7603 zero = zero3 || zero2 || zero1;
7604 count = count1 * count2 * count3;
7605 if (__builtin_expect(zero, false)) goto zero_iter_bb;
7606
7607 After all, we expect the zero=false, and thus we expect to have to
7608 evaluate all of the comparison expressions, so short-circuiting
7609 oughtn't be a win. Since the condition isn't protecting a
7610 denominator, we're not concerned about divide-by-zero, so we can
7611 fully evaluate count even if a numerator turned out to be wrong.
7612
7613 It seems like putting this all together would create much better
7614 scheduling opportunities, and less pressure on the chip's branch
7615 predictor. */
7616
7617static void
7618expand_omp_for_init_counts (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
7619 basic_block &entry_bb, tree *counts,
43895be5 7620 basic_block &zero_iter1_bb, int &first_zero_iter1,
7621 basic_block &zero_iter2_bb, int &first_zero_iter2,
3d483a94 7622 basic_block &l2_dom_bb)
7623{
7624 tree t, type = TREE_TYPE (fd->loop.v);
3d483a94 7625 edge e, ne;
7626 int i;
7627
7628 /* Collapsed loops need work for expansion into SSA form. */
7629 gcc_assert (!gimple_in_ssa_p (cfun));
7630
bc7bff74 7631 if (gimple_omp_for_combined_into_p (fd->for_stmt)
7632 && TREE_CODE (fd->loop.n2) != INTEGER_CST)
7633 {
43895be5 7634 gcc_assert (fd->ordered == 0);
bc7bff74 7635 /* First two _looptemp_ clauses are for istart/iend, counts[0]
7636 isn't supposed to be handled, as the inner loop doesn't
7637 use it. */
7638 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7639 OMP_CLAUSE__LOOPTEMP_);
7640 gcc_assert (innerc);
7641 for (i = 0; i < fd->collapse; i++)
7642 {
7643 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7644 OMP_CLAUSE__LOOPTEMP_);
7645 gcc_assert (innerc);
7646 if (i)
7647 counts[i] = OMP_CLAUSE_DECL (innerc);
7648 else
7649 counts[0] = NULL_TREE;
7650 }
7651 return;
7652 }
7653
43895be5 7654 for (i = fd->collapse; i < fd->ordered; i++)
7655 {
7656 tree itype = TREE_TYPE (fd->loops[i].v);
7657 counts[i] = NULL_TREE;
7658 t = fold_binary (fd->loops[i].cond_code, boolean_type_node,
7659 fold_convert (itype, fd->loops[i].n1),
7660 fold_convert (itype, fd->loops[i].n2));
7661 if (t && integer_zerop (t))
7662 {
7663 for (i = fd->collapse; i < fd->ordered; i++)
7664 counts[i] = build_int_cst (type, 0);
7665 break;
7666 }
7667 }
7668 for (i = 0; i < (fd->ordered ? fd->ordered : fd->collapse); i++)
3d483a94 7669 {
7670 tree itype = TREE_TYPE (fd->loops[i].v);
7671
43895be5 7672 if (i >= fd->collapse && counts[i])
7673 continue;
7674 if ((SSA_VAR_P (fd->loop.n2) || i >= fd->collapse)
3d483a94 7675 && ((t = fold_binary (fd->loops[i].cond_code, boolean_type_node,
7676 fold_convert (itype, fd->loops[i].n1),
7677 fold_convert (itype, fd->loops[i].n2)))
7678 == NULL_TREE || !integer_onep (t)))
7679 {
1a91d914 7680 gcond *cond_stmt;
3d483a94 7681 tree n1, n2;
7682 n1 = fold_convert (itype, unshare_expr (fd->loops[i].n1));
7683 n1 = force_gimple_operand_gsi (gsi, n1, true, NULL_TREE,
7684 true, GSI_SAME_STMT);
7685 n2 = fold_convert (itype, unshare_expr (fd->loops[i].n2));
7686 n2 = force_gimple_operand_gsi (gsi, n2, true, NULL_TREE,
7687 true, GSI_SAME_STMT);
1a91d914 7688 cond_stmt = gimple_build_cond (fd->loops[i].cond_code, n1, n2,
7689 NULL_TREE, NULL_TREE);
7690 gsi_insert_before (gsi, cond_stmt, GSI_SAME_STMT);
7691 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
3d483a94 7692 expand_omp_regimplify_p, NULL, NULL)
1a91d914 7693 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
3d483a94 7694 expand_omp_regimplify_p, NULL, NULL))
7695 {
1a91d914 7696 *gsi = gsi_for_stmt (cond_stmt);
7697 gimple_regimplify_operands (cond_stmt, gsi);
3d483a94 7698 }
1a91d914 7699 e = split_block (entry_bb, cond_stmt);
43895be5 7700 basic_block &zero_iter_bb
7701 = i < fd->collapse ? zero_iter1_bb : zero_iter2_bb;
7702 int &first_zero_iter
7703 = i < fd->collapse ? first_zero_iter1 : first_zero_iter2;
3d483a94 7704 if (zero_iter_bb == NULL)
7705 {
1a91d914 7706 gassign *assign_stmt;
3d483a94 7707 first_zero_iter = i;
7708 zero_iter_bb = create_empty_bb (entry_bb);
b3083327 7709 add_bb_to_loop (zero_iter_bb, entry_bb->loop_father);
3d483a94 7710 *gsi = gsi_after_labels (zero_iter_bb);
43895be5 7711 if (i < fd->collapse)
7712 assign_stmt = gimple_build_assign (fd->loop.n2,
7713 build_zero_cst (type));
7714 else
7715 {
7716 counts[i] = create_tmp_reg (type, ".count");
7717 assign_stmt
7718 = gimple_build_assign (counts[i], build_zero_cst (type));
7719 }
1a91d914 7720 gsi_insert_before (gsi, assign_stmt, GSI_SAME_STMT);
3d483a94 7721 set_immediate_dominator (CDI_DOMINATORS, zero_iter_bb,
7722 entry_bb);
7723 }
7724 ne = make_edge (entry_bb, zero_iter_bb, EDGE_FALSE_VALUE);
7725 ne->probability = REG_BR_PROB_BASE / 2000 - 1;
7726 e->flags = EDGE_TRUE_VALUE;
7727 e->probability = REG_BR_PROB_BASE - ne->probability;
7728 if (l2_dom_bb == NULL)
7729 l2_dom_bb = entry_bb;
7730 entry_bb = e->dest;
7731 *gsi = gsi_last_bb (entry_bb);
7732 }
7733
7734 if (POINTER_TYPE_P (itype))
7735 itype = signed_type_for (itype);
7736 t = build_int_cst (itype, (fd->loops[i].cond_code == LT_EXPR
7737 ? -1 : 1));
7738 t = fold_build2 (PLUS_EXPR, itype,
7739 fold_convert (itype, fd->loops[i].step), t);
7740 t = fold_build2 (PLUS_EXPR, itype, t,
7741 fold_convert (itype, fd->loops[i].n2));
7742 t = fold_build2 (MINUS_EXPR, itype, t,
7743 fold_convert (itype, fd->loops[i].n1));
7744 /* ?? We could probably use CEIL_DIV_EXPR instead of
7745 TRUNC_DIV_EXPR and adjusting by hand. Unless we can't
7746 generate the same code in the end because generically we
7747 don't know that the values involved must be negative for
7748 GT?? */
7749 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
7750 t = fold_build2 (TRUNC_DIV_EXPR, itype,
7751 fold_build1 (NEGATE_EXPR, itype, t),
7752 fold_build1 (NEGATE_EXPR, itype,
7753 fold_convert (itype,
7754 fd->loops[i].step)));
7755 else
7756 t = fold_build2 (TRUNC_DIV_EXPR, itype, t,
7757 fold_convert (itype, fd->loops[i].step));
7758 t = fold_convert (type, t);
7759 if (TREE_CODE (t) == INTEGER_CST)
7760 counts[i] = t;
7761 else
7762 {
43895be5 7763 if (i < fd->collapse || i != first_zero_iter2)
7764 counts[i] = create_tmp_reg (type, ".count");
3d483a94 7765 expand_omp_build_assign (gsi, counts[i], t);
7766 }
43895be5 7767 if (SSA_VAR_P (fd->loop.n2) && i < fd->collapse)
3d483a94 7768 {
7769 if (i == 0)
7770 t = counts[0];
7771 else
7772 t = fold_build2 (MULT_EXPR, type, fd->loop.n2, counts[i]);
7773 expand_omp_build_assign (gsi, fd->loop.n2, t);
7774 }
7775 }
7776}
7777
7778
7779/* Helper function for expand_omp_{for_*,simd}. Generate code like:
7780 T = V;
7781 V3 = N31 + (T % count3) * STEP3;
7782 T = T / count3;
7783 V2 = N21 + (T % count2) * STEP2;
7784 T = T / count2;
7785 V1 = N11 + T * STEP1;
bc7bff74 7786 if this loop doesn't have an inner loop construct combined with it.
7787 If it does have an inner loop construct combined with it and the
7788 iteration count isn't known constant, store values from counts array
7789 into its _looptemp_ temporaries instead. */
3d483a94 7790
7791static void
7792expand_omp_for_init_vars (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
42acab1c 7793 tree *counts, gimple *inner_stmt, tree startvar)
3d483a94 7794{
7795 int i;
bc7bff74 7796 if (gimple_omp_for_combined_p (fd->for_stmt))
7797 {
7798 /* If fd->loop.n2 is constant, then no propagation of the counts
7799 is needed, they are constant. */
7800 if (TREE_CODE (fd->loop.n2) == INTEGER_CST)
7801 return;
7802
43895be5 7803 tree clauses = gimple_code (inner_stmt) != GIMPLE_OMP_FOR
7804 ? gimple_omp_taskreg_clauses (inner_stmt)
bc7bff74 7805 : gimple_omp_for_clauses (inner_stmt);
7806 /* First two _looptemp_ clauses are for istart/iend, counts[0]
7807 isn't supposed to be handled, as the inner loop doesn't
7808 use it. */
7809 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
7810 gcc_assert (innerc);
7811 for (i = 0; i < fd->collapse; i++)
7812 {
7813 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7814 OMP_CLAUSE__LOOPTEMP_);
7815 gcc_assert (innerc);
7816 if (i)
7817 {
7818 tree tem = OMP_CLAUSE_DECL (innerc);
7819 tree t = fold_convert (TREE_TYPE (tem), counts[i]);
7820 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
7821 false, GSI_CONTINUE_LINKING);
1a91d914 7822 gassign *stmt = gimple_build_assign (tem, t);
bc7bff74 7823 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
7824 }
7825 }
7826 return;
7827 }
7828
3d483a94 7829 tree type = TREE_TYPE (fd->loop.v);
7830 tree tem = create_tmp_reg (type, ".tem");
1a91d914 7831 gassign *stmt = gimple_build_assign (tem, startvar);
3d483a94 7832 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
7833
7834 for (i = fd->collapse - 1; i >= 0; i--)
7835 {
7836 tree vtype = TREE_TYPE (fd->loops[i].v), itype, t;
7837 itype = vtype;
7838 if (POINTER_TYPE_P (vtype))
7839 itype = signed_type_for (vtype);
7840 if (i != 0)
7841 t = fold_build2 (TRUNC_MOD_EXPR, type, tem, counts[i]);
7842 else
7843 t = tem;
7844 t = fold_convert (itype, t);
7845 t = fold_build2 (MULT_EXPR, itype, t,
7846 fold_convert (itype, fd->loops[i].step));
7847 if (POINTER_TYPE_P (vtype))
7848 t = fold_build_pointer_plus (fd->loops[i].n1, t);
7849 else
7850 t = fold_build2 (PLUS_EXPR, itype, fd->loops[i].n1, t);
7851 t = force_gimple_operand_gsi (gsi, t,
7852 DECL_P (fd->loops[i].v)
7853 && TREE_ADDRESSABLE (fd->loops[i].v),
7854 NULL_TREE, false,
7855 GSI_CONTINUE_LINKING);
7856 stmt = gimple_build_assign (fd->loops[i].v, t);
7857 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
7858 if (i != 0)
7859 {
7860 t = fold_build2 (TRUNC_DIV_EXPR, type, tem, counts[i]);
7861 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
7862 false, GSI_CONTINUE_LINKING);
7863 stmt = gimple_build_assign (tem, t);
7864 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
7865 }
7866 }
7867}
7868
7869
7870/* Helper function for expand_omp_for_*. Generate code like:
7871 L10:
7872 V3 += STEP3;
7873 if (V3 cond3 N32) goto BODY_BB; else goto L11;
7874 L11:
7875 V3 = N31;
7876 V2 += STEP2;
7877 if (V2 cond2 N22) goto BODY_BB; else goto L12;
7878 L12:
7879 V2 = N21;
7880 V1 += STEP1;
7881 goto BODY_BB; */
7882
7883static basic_block
7884extract_omp_for_update_vars (struct omp_for_data *fd, basic_block cont_bb,
7885 basic_block body_bb)
7886{
7887 basic_block last_bb, bb, collapse_bb = NULL;
7888 int i;
7889 gimple_stmt_iterator gsi;
7890 edge e;
7891 tree t;
42acab1c 7892 gimple *stmt;
3d483a94 7893
7894 last_bb = cont_bb;
7895 for (i = fd->collapse - 1; i >= 0; i--)
7896 {
7897 tree vtype = TREE_TYPE (fd->loops[i].v);
7898
7899 bb = create_empty_bb (last_bb);
b3083327 7900 add_bb_to_loop (bb, last_bb->loop_father);
3d483a94 7901 gsi = gsi_start_bb (bb);
7902
7903 if (i < fd->collapse - 1)
7904 {
7905 e = make_edge (last_bb, bb, EDGE_FALSE_VALUE);
7906 e->probability = REG_BR_PROB_BASE / 8;
7907
7908 t = fd->loops[i + 1].n1;
7909 t = force_gimple_operand_gsi (&gsi, t,
7910 DECL_P (fd->loops[i + 1].v)
7911 && TREE_ADDRESSABLE (fd->loops[i
7912 + 1].v),
7913 NULL_TREE, false,
7914 GSI_CONTINUE_LINKING);
7915 stmt = gimple_build_assign (fd->loops[i + 1].v, t);
7916 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
7917 }
7918 else
7919 collapse_bb = bb;
7920
7921 set_immediate_dominator (CDI_DOMINATORS, bb, last_bb);
7922
7923 if (POINTER_TYPE_P (vtype))
7924 t = fold_build_pointer_plus (fd->loops[i].v, fd->loops[i].step);
7925 else
7926 t = fold_build2 (PLUS_EXPR, vtype, fd->loops[i].v, fd->loops[i].step);
7927 t = force_gimple_operand_gsi (&gsi, t,
7928 DECL_P (fd->loops[i].v)
7929 && TREE_ADDRESSABLE (fd->loops[i].v),
7930 NULL_TREE, false, GSI_CONTINUE_LINKING);
7931 stmt = gimple_build_assign (fd->loops[i].v, t);
7932 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
7933
7934 if (i > 0)
7935 {
7936 t = fd->loops[i].n2;
7937 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7938 false, GSI_CONTINUE_LINKING);
7939 tree v = fd->loops[i].v;
7940 if (DECL_P (v) && TREE_ADDRESSABLE (v))
7941 v = force_gimple_operand_gsi (&gsi, v, true, NULL_TREE,
7942 false, GSI_CONTINUE_LINKING);
7943 t = fold_build2 (fd->loops[i].cond_code, boolean_type_node, v, t);
7944 stmt = gimple_build_cond_empty (t);
7945 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
7946 e = make_edge (bb, body_bb, EDGE_TRUE_VALUE);
7947 e->probability = REG_BR_PROB_BASE * 7 / 8;
7948 }
7949 else
7950 make_edge (bb, body_bb, EDGE_FALLTHRU);
7951 last_bb = bb;
7952 }
7953
7954 return collapse_bb;
7955}
7956
7957
43895be5 7958/* Expand #pragma omp ordered depend(source). */
1e8e9920 7959
43895be5 7960static void
7961expand_omp_ordered_source (gimple_stmt_iterator *gsi, struct omp_for_data *fd,
7962 tree *counts, location_t loc)
7963{
7964 enum built_in_function source_ix
7965 = fd->iter_type == long_integer_type_node
7966 ? BUILT_IN_GOMP_DOACROSS_POST : BUILT_IN_GOMP_DOACROSS_ULL_POST;
7967 gimple *g
7968 = gimple_build_call (builtin_decl_explicit (source_ix), 1,
7969 build_fold_addr_expr (counts[fd->ordered]));
7970 gimple_set_location (g, loc);
7971 gsi_insert_before (gsi, g, GSI_SAME_STMT);
7972}
1e8e9920 7973
43895be5 7974/* Expand a single depend from #pragma omp ordered depend(sink:...). */
1e8e9920 7975
43895be5 7976static void
7977expand_omp_ordered_sink (gimple_stmt_iterator *gsi, struct omp_for_data *fd,
7978 tree *counts, tree c, location_t loc)
7979{
7980 auto_vec<tree, 10> args;
7981 enum built_in_function sink_ix
7982 = fd->iter_type == long_integer_type_node
7983 ? BUILT_IN_GOMP_DOACROSS_WAIT : BUILT_IN_GOMP_DOACROSS_ULL_WAIT;
7984 tree t, off, coff = NULL_TREE, deps = OMP_CLAUSE_DECL (c), cond = NULL_TREE;
7985 int i;
7986 gimple_stmt_iterator gsi2 = *gsi;
7987 bool warned_step = false;
fd6481cf 7988
43895be5 7989 for (i = 0; i < fd->ordered; i++)
7990 {
7991 off = TREE_PURPOSE (deps);
7992 if (!integer_zerop (off))
7993 {
7994 gcc_assert (fd->loops[i].cond_code == LT_EXPR
7995 || fd->loops[i].cond_code == GT_EXPR);
7996 bool forward = fd->loops[i].cond_code == LT_EXPR;
7997 if (forward ^ OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
7998 warning_at (loc, 0, "%<depend(sink)%> clause waiting for "
7999 "lexically later iteration");
8000 break;
8001 }
8002 deps = TREE_CHAIN (deps);
8003 }
8004 /* If all offsets corresponding to the collapsed loops are zero,
8005 this depend clause can be ignored. FIXME: but there is still a
8006 flush needed. We need to emit one __sync_synchronize () for it
8007 though (perhaps conditionally)? Solve this together with the
8008 conservative dependence folding optimization.
8009 if (i >= fd->collapse)
8010 return; */
fd6481cf 8011
43895be5 8012 deps = OMP_CLAUSE_DECL (c);
8013 gsi_prev (&gsi2);
8014 edge e1 = split_block (gsi_bb (gsi2), gsi_stmt (gsi2));
8015 edge e2 = split_block_after_labels (e1->dest);
fd6481cf 8016
43895be5 8017 *gsi = gsi_after_labels (e1->dest);
8018 for (i = 0; i < fd->ordered; i++)
8019 {
8020 tree itype = TREE_TYPE (fd->loops[i].v);
8021 if (POINTER_TYPE_P (itype))
8022 itype = sizetype;
8023 if (i)
8024 deps = TREE_CHAIN (deps);
8025 off = TREE_PURPOSE (deps);
8026 tree s = fold_convert_loc (loc, itype, fd->loops[i].step);
8027
8028 if (integer_zerop (off))
8029 t = boolean_true_node;
8030 else
8031 {
8032 tree a;
8033 tree co = fold_convert_loc (loc, itype, off);
8034 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v)))
8035 {
8036 if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
8037 co = fold_build1_loc (loc, NEGATE_EXPR, itype, co);
8038 a = fold_build2_loc (loc, POINTER_PLUS_EXPR,
8039 TREE_TYPE (fd->loops[i].v), fd->loops[i].v,
8040 co);
8041 }
8042 else if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
8043 a = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (fd->loops[i].v),
8044 fd->loops[i].v, co);
8045 else
8046 a = fold_build2_loc (loc, PLUS_EXPR, TREE_TYPE (fd->loops[i].v),
8047 fd->loops[i].v, co);
8048 if (fd->loops[i].cond_code == LT_EXPR)
8049 {
8050 if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
8051 t = fold_build2_loc (loc, GE_EXPR, boolean_type_node, a,
8052 fd->loops[i].n1);
8053 else
8054 t = fold_build2_loc (loc, LT_EXPR, boolean_type_node, a,
8055 fd->loops[i].n2);
8056 }
8057 else if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
8058 t = fold_build2_loc (loc, GT_EXPR, boolean_type_node, a,
8059 fd->loops[i].n2);
8060 else
8061 t = fold_build2_loc (loc, LE_EXPR, boolean_type_node, a,
8062 fd->loops[i].n1);
8063 }
8064 if (cond)
8065 cond = fold_build2_loc (loc, BIT_AND_EXPR, boolean_type_node, cond, t);
8066 else
8067 cond = t;
8068
8069 off = fold_convert_loc (loc, itype, off);
8070
8071 if (fd->loops[i].cond_code == LT_EXPR
8072 ? !integer_onep (fd->loops[i].step)
8073 : !integer_minus_onep (fd->loops[i].step))
8074 {
8075 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
8076 t = fold_build2_loc (loc, TRUNC_MOD_EXPR, itype, off,
8077 fold_build1_loc (loc, NEGATE_EXPR, itype,
8078 s));
8079 else
8080 t = fold_build2_loc (loc, TRUNC_MOD_EXPR, itype, off, s);
8081 t = fold_build2_loc (loc, EQ_EXPR, boolean_type_node, t,
8082 build_int_cst (itype, 0));
8083 if (integer_zerop (t) && !warned_step)
8084 {
8085 warning_at (loc, 0, "%<depend(sink)%> refers to iteration never "
8086 "in the iteration space");
8087 warned_step = true;
8088 }
8089 cond = fold_build2_loc (loc, BIT_AND_EXPR, boolean_type_node,
8090 cond, t);
8091 }
8092
8093 if (i <= fd->collapse - 1 && fd->collapse > 1)
8094 t = fd->loop.v;
8095 else if (counts[i])
8096 t = counts[i];
8097 else
8098 {
8099 t = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (fd->loops[i].v),
8100 fd->loops[i].v, fd->loops[i].n1);
8101 t = fold_convert_loc (loc, fd->iter_type, t);
8102 }
8103 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
8104 off = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, off,
8105 fold_build1_loc (loc, NEGATE_EXPR, itype,
8106 s));
8107 else
8108 off = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, off, s);
8109 if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
8110 off = fold_build1_loc (loc, NEGATE_EXPR, itype, off);
8111 off = fold_convert_loc (loc, fd->iter_type, off);
8112 if (i <= fd->collapse - 1 && fd->collapse > 1)
8113 {
8114 if (i)
8115 off = fold_build2_loc (loc, PLUS_EXPR, fd->iter_type, coff,
8116 off);
8117 if (i < fd->collapse - 1)
8118 {
8119 coff = fold_build2_loc (loc, MULT_EXPR, fd->iter_type, off,
8120 counts[i]);
8121 continue;
8122 }
8123 }
8124 off = unshare_expr (off);
8125 t = fold_build2_loc (loc, PLUS_EXPR, fd->iter_type, t, off);
8126 t = force_gimple_operand_gsi (gsi, t, true, NULL_TREE,
8127 true, GSI_SAME_STMT);
8128 args.safe_push (t);
8129 }
8130 gimple *g = gimple_build_call_vec (builtin_decl_explicit (sink_ix), args);
8131 gimple_set_location (g, loc);
8132 gsi_insert_before (gsi, g, GSI_SAME_STMT);
8133
8134 *gsi = gsi_last_bb (e1->src);
8135 cond = unshare_expr (cond);
8136 cond = force_gimple_operand_gsi (gsi, cond, true, NULL_TREE, false,
8137 GSI_CONTINUE_LINKING);
8138 gsi_insert_after (gsi, gimple_build_cond_empty (cond), GSI_NEW_STMT);
8139 edge e3 = make_edge (e1->src, e2->dest, EDGE_FALSE_VALUE);
8140 e3->probability = REG_BR_PROB_BASE / 8;
8141 e1->probability = REG_BR_PROB_BASE - e3->probability;
8142 e1->flags = EDGE_TRUE_VALUE;
8143 set_immediate_dominator (CDI_DOMINATORS, e2->dest, e1->src);
8144
8145 *gsi = gsi_after_labels (e2->dest);
8146}
8147
8148/* Expand all #pragma omp ordered depend(source) and
8149 #pragma omp ordered depend(sink:...) constructs in the current
8150 #pragma omp for ordered(n) region. */
8151
8152static void
8153expand_omp_ordered_source_sink (struct omp_region *region,
8154 struct omp_for_data *fd, tree *counts,
8155 basic_block cont_bb)
8156{
8157 struct omp_region *inner;
8158 int i;
8159 for (i = fd->collapse - 1; i < fd->ordered; i++)
8160 if (i == fd->collapse - 1 && fd->collapse > 1)
8161 counts[i] = NULL_TREE;
8162 else if (i >= fd->collapse && !cont_bb)
8163 counts[i] = build_zero_cst (fd->iter_type);
8164 else if (!POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v))
8165 && integer_onep (fd->loops[i].step))
8166 counts[i] = NULL_TREE;
8167 else
8168 counts[i] = create_tmp_var (fd->iter_type, ".orditer");
8169 tree atype
8170 = build_array_type_nelts (fd->iter_type, fd->ordered - fd->collapse + 1);
8171 counts[fd->ordered] = create_tmp_var (atype, ".orditera");
8172 TREE_ADDRESSABLE (counts[fd->ordered]) = 1;
8173
8174 for (inner = region->inner; inner; inner = inner->next)
8175 if (inner->type == GIMPLE_OMP_ORDERED)
8176 {
8177 gomp_ordered *ord_stmt = inner->ord_stmt;
8178 gimple_stmt_iterator gsi = gsi_for_stmt (ord_stmt);
8179 location_t loc = gimple_location (ord_stmt);
8180 tree c;
8181 for (c = gimple_omp_ordered_clauses (ord_stmt);
8182 c; c = OMP_CLAUSE_CHAIN (c))
8183 if (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SOURCE)
8184 break;
8185 if (c)
8186 expand_omp_ordered_source (&gsi, fd, counts, loc);
8187 for (c = gimple_omp_ordered_clauses (ord_stmt);
8188 c; c = OMP_CLAUSE_CHAIN (c))
8189 if (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK)
8190 expand_omp_ordered_sink (&gsi, fd, counts, c, loc);
8191 gsi_remove (&gsi, true);
8192 }
8193}
8194
8195/* Wrap the body into fd->ordered - fd->collapse loops that aren't
8196 collapsed. */
8197
8198static basic_block
8199expand_omp_for_ordered_loops (struct omp_for_data *fd, tree *counts,
8200 basic_block cont_bb, basic_block body_bb,
8201 bool ordered_lastprivate)
8202{
8203 if (fd->ordered == fd->collapse)
8204 return cont_bb;
8205
8206 if (!cont_bb)
8207 {
8208 gimple_stmt_iterator gsi = gsi_after_labels (body_bb);
8209 for (int i = fd->collapse; i < fd->ordered; i++)
8210 {
8211 tree type = TREE_TYPE (fd->loops[i].v);
8212 tree n1 = fold_convert (type, fd->loops[i].n1);
8213 expand_omp_build_assign (&gsi, fd->loops[i].v, n1);
8214 tree aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
8215 size_int (i - fd->collapse + 1),
8216 NULL_TREE, NULL_TREE);
8217 expand_omp_build_assign (&gsi, aref, build_zero_cst (fd->iter_type));
8218 }
8219 return NULL;
8220 }
8221
8222 for (int i = fd->ordered - 1; i >= fd->collapse; i--)
8223 {
8224 tree t, type = TREE_TYPE (fd->loops[i].v);
8225 gimple_stmt_iterator gsi = gsi_after_labels (body_bb);
8226 expand_omp_build_assign (&gsi, fd->loops[i].v,
8227 fold_convert (type, fd->loops[i].n1));
8228 if (counts[i])
8229 expand_omp_build_assign (&gsi, counts[i],
8230 build_zero_cst (fd->iter_type));
8231 tree aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
8232 size_int (i - fd->collapse + 1),
8233 NULL_TREE, NULL_TREE);
8234 expand_omp_build_assign (&gsi, aref, build_zero_cst (fd->iter_type));
8235 if (!gsi_end_p (gsi))
8236 gsi_prev (&gsi);
8237 else
8238 gsi = gsi_last_bb (body_bb);
8239 edge e1 = split_block (body_bb, gsi_stmt (gsi));
8240 basic_block new_body = e1->dest;
8241 if (body_bb == cont_bb)
8242 cont_bb = new_body;
8243 edge e2 = NULL;
8244 basic_block new_header;
8245 if (EDGE_COUNT (cont_bb->preds) > 0)
8246 {
8247 gsi = gsi_last_bb (cont_bb);
8248 if (POINTER_TYPE_P (type))
8249 t = fold_build_pointer_plus (fd->loops[i].v,
8250 fold_convert (sizetype,
8251 fd->loops[i].step));
8252 else
8253 t = fold_build2 (PLUS_EXPR, type, fd->loops[i].v,
8254 fold_convert (type, fd->loops[i].step));
8255 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
8256 if (counts[i])
8257 {
8258 t = fold_build2 (PLUS_EXPR, fd->iter_type, counts[i],
8259 build_int_cst (fd->iter_type, 1));
8260 expand_omp_build_assign (&gsi, counts[i], t);
8261 t = counts[i];
8262 }
8263 else
8264 {
8265 t = fold_build2 (MINUS_EXPR, TREE_TYPE (fd->loops[i].v),
8266 fd->loops[i].v, fd->loops[i].n1);
8267 t = fold_convert (fd->iter_type, t);
8268 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8269 true, GSI_SAME_STMT);
8270 }
8271 aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
8272 size_int (i - fd->collapse + 1),
8273 NULL_TREE, NULL_TREE);
8274 expand_omp_build_assign (&gsi, aref, t);
8275 gsi_prev (&gsi);
8276 e2 = split_block (cont_bb, gsi_stmt (gsi));
8277 new_header = e2->dest;
8278 }
8279 else
8280 new_header = cont_bb;
8281 gsi = gsi_after_labels (new_header);
8282 tree v = force_gimple_operand_gsi (&gsi, fd->loops[i].v, true, NULL_TREE,
8283 true, GSI_SAME_STMT);
8284 tree n2
8285 = force_gimple_operand_gsi (&gsi, fold_convert (type, fd->loops[i].n2),
8286 true, NULL_TREE, true, GSI_SAME_STMT);
8287 t = build2 (fd->loops[i].cond_code, boolean_type_node, v, n2);
8288 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_NEW_STMT);
8289 edge e3 = split_block (new_header, gsi_stmt (gsi));
8290 cont_bb = e3->dest;
8291 remove_edge (e1);
8292 make_edge (body_bb, new_header, EDGE_FALLTHRU);
8293 e3->flags = EDGE_FALSE_VALUE;
8294 e3->probability = REG_BR_PROB_BASE / 8;
8295 e1 = make_edge (new_header, new_body, EDGE_TRUE_VALUE);
8296 e1->probability = REG_BR_PROB_BASE - e3->probability;
8297
8298 set_immediate_dominator (CDI_DOMINATORS, new_header, body_bb);
8299 set_immediate_dominator (CDI_DOMINATORS, new_body, new_header);
8300
8301 if (e2)
8302 {
8303 struct loop *loop = alloc_loop ();
8304 loop->header = new_header;
8305 loop->latch = e2->src;
8306 add_loop (loop, body_bb->loop_father);
8307 }
8308 }
8309
8310 /* If there are any lastprivate clauses and it is possible some loops
8311 might have zero iterations, ensure all the decls are initialized,
8312 otherwise we could crash evaluating C++ class iterators with lastprivate
8313 clauses. */
8314 bool need_inits = false;
8315 for (int i = fd->collapse; ordered_lastprivate && i < fd->ordered; i++)
8316 if (need_inits)
8317 {
8318 tree type = TREE_TYPE (fd->loops[i].v);
8319 gimple_stmt_iterator gsi = gsi_after_labels (body_bb);
8320 expand_omp_build_assign (&gsi, fd->loops[i].v,
8321 fold_convert (type, fd->loops[i].n1));
8322 }
8323 else
8324 {
8325 tree type = TREE_TYPE (fd->loops[i].v);
8326 tree this_cond = fold_build2 (fd->loops[i].cond_code,
8327 boolean_type_node,
8328 fold_convert (type, fd->loops[i].n1),
8329 fold_convert (type, fd->loops[i].n2));
8330 if (!integer_onep (this_cond))
8331 need_inits = true;
8332 }
8333
8334 return cont_bb;
8335}
8336
8337
8338/* A subroutine of expand_omp_for. Generate code for a parallel
8339 loop with any schedule. Given parameters:
8340
8341 for (V = N1; V cond N2; V += STEP) BODY;
8342
8343 where COND is "<" or ">", we generate pseudocode
8344
8345 more = GOMP_loop_foo_start (N1, N2, STEP, CHUNK, &istart0, &iend0);
8346 if (more) goto L0; else goto L3;
8347 L0:
8348 V = istart0;
8349 iend = iend0;
8350 L1:
8351 BODY;
8352 V += STEP;
8353 if (V cond iend) goto L1; else goto L2;
8354 L2:
8355 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
8356 L3:
8357
8358 If this is a combined omp parallel loop, instead of the call to
8359 GOMP_loop_foo_start, we call GOMP_loop_foo_next.
8360 If this is gimple_omp_for_combined_p loop, then instead of assigning
8361 V and iend in L0 we assign the first two _looptemp_ clause decls of the
8362 inner GIMPLE_OMP_FOR and V += STEP; and
8363 if (V cond iend) goto L1; else goto L2; are removed.
8364
8365 For collapsed loops, given parameters:
8366 collapse(3)
8367 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
8368 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
8369 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
8370 BODY;
8371
8372 we generate pseudocode
8373
8374 if (__builtin_expect (N32 cond3 N31, 0)) goto Z0;
8375 if (cond3 is <)
8376 adj = STEP3 - 1;
8377 else
8378 adj = STEP3 + 1;
8379 count3 = (adj + N32 - N31) / STEP3;
8380 if (__builtin_expect (N22 cond2 N21, 0)) goto Z0;
8381 if (cond2 is <)
8382 adj = STEP2 - 1;
8383 else
8384 adj = STEP2 + 1;
fd6481cf 8385 count2 = (adj + N22 - N21) / STEP2;
8e6b4515 8386 if (__builtin_expect (N12 cond1 N11, 0)) goto Z0;
fd6481cf 8387 if (cond1 is <)
8388 adj = STEP1 - 1;
8389 else
8390 adj = STEP1 + 1;
8391 count1 = (adj + N12 - N11) / STEP1;
8392 count = count1 * count2 * count3;
8e6b4515 8393 goto Z1;
8394 Z0:
8395 count = 0;
8396 Z1:
fd6481cf 8397 more = GOMP_loop_foo_start (0, count, 1, CHUNK, &istart0, &iend0);
8398 if (more) goto L0; else goto L3;
8399 L0:
8400 V = istart0;
8401 T = V;
8402 V3 = N31 + (T % count3) * STEP3;
8403 T = T / count3;
8404 V2 = N21 + (T % count2) * STEP2;
8405 T = T / count2;
8406 V1 = N11 + T * STEP1;
8407 iend = iend0;
8408 L1:
8409 BODY;
8410 V += 1;
8411 if (V < iend) goto L10; else goto L2;
8412 L10:
8413 V3 += STEP3;
8414 if (V3 cond3 N32) goto L1; else goto L11;
8415 L11:
8416 V3 = N31;
8417 V2 += STEP2;
8418 if (V2 cond2 N22) goto L1; else goto L12;
8419 L12:
8420 V2 = N21;
8421 V1 += STEP1;
8422 goto L1;
8423 L2:
8424 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
8425 L3:
8426
8427 */
1e8e9920 8428
61e47ac8 8429static void
773c5ba7 8430expand_omp_for_generic (struct omp_region *region,
8431 struct omp_for_data *fd,
1e8e9920 8432 enum built_in_function start_fn,
bc7bff74 8433 enum built_in_function next_fn,
42acab1c 8434 gimple *inner_stmt)
1e8e9920 8435{
75a70cf9 8436 tree type, istart0, iend0, iend;
fd6481cf 8437 tree t, vmain, vback, bias = NULL_TREE;
8438 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, collapse_bb;
03ed154b 8439 basic_block l2_bb = NULL, l3_bb = NULL;
75a70cf9 8440 gimple_stmt_iterator gsi;
1a91d914 8441 gassign *assign_stmt;
773c5ba7 8442 bool in_combined_parallel = is_combined_parallel (region);
ac6e3339 8443 bool broken_loop = region->cont == NULL;
79acaae1 8444 edge e, ne;
fd6481cf 8445 tree *counts = NULL;
8446 int i;
43895be5 8447 bool ordered_lastprivate = false;
ac6e3339 8448
8449 gcc_assert (!broken_loop || !in_combined_parallel);
fd6481cf 8450 gcc_assert (fd->iter_type == long_integer_type_node
8451 || !in_combined_parallel);
1e8e9920 8452
61e47ac8 8453 entry_bb = region->entry;
03ed154b 8454 cont_bb = region->cont;
fd6481cf 8455 collapse_bb = NULL;
ac6e3339 8456 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
8457 gcc_assert (broken_loop
8458 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
8459 l0_bb = split_edge (FALLTHRU_EDGE (entry_bb));
8460 l1_bb = single_succ (l0_bb);
8461 if (!broken_loop)
03ed154b 8462 {
8463 l2_bb = create_empty_bb (cont_bb);
95cd5725 8464 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l1_bb
8465 || (single_succ_edge (BRANCH_EDGE (cont_bb)->dest)->dest
8466 == l1_bb));
ac6e3339 8467 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
03ed154b 8468 }
ac6e3339 8469 else
8470 l2_bb = NULL;
8471 l3_bb = BRANCH_EDGE (entry_bb)->dest;
8472 exit_bb = region->exit;
773c5ba7 8473
75a70cf9 8474 gsi = gsi_last_bb (entry_bb);
fd6481cf 8475
75a70cf9 8476 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
43895be5 8477 if (fd->ordered
8478 && find_omp_clause (gimple_omp_for_clauses (gsi_stmt (gsi)),
8479 OMP_CLAUSE_LASTPRIVATE))
8480 ordered_lastprivate = false;
8481 if (fd->collapse > 1 || fd->ordered)
fd6481cf 8482 {
43895be5 8483 int first_zero_iter1 = -1, first_zero_iter2 = -1;
8484 basic_block zero_iter1_bb = NULL, zero_iter2_bb = NULL, l2_dom_bb = NULL;
8e6b4515 8485
43895be5 8486 counts = XALLOCAVEC (tree, fd->ordered ? fd->ordered + 1 : fd->collapse);
3d483a94 8487 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
43895be5 8488 zero_iter1_bb, first_zero_iter1,
8489 zero_iter2_bb, first_zero_iter2, l2_dom_bb);
fd6481cf 8490
43895be5 8491 if (zero_iter1_bb)
8e6b4515 8492 {
8493 /* Some counts[i] vars might be uninitialized if
8494 some loop has zero iterations. But the body shouldn't
8495 be executed in that case, so just avoid uninit warnings. */
43895be5 8496 for (i = first_zero_iter1;
8497 i < (fd->ordered ? fd->ordered : fd->collapse); i++)
8e6b4515 8498 if (SSA_VAR_P (counts[i]))
8499 TREE_NO_WARNING (counts[i]) = 1;
8500 gsi_prev (&gsi);
8501 e = split_block (entry_bb, gsi_stmt (gsi));
8502 entry_bb = e->dest;
43895be5 8503 make_edge (zero_iter1_bb, entry_bb, EDGE_FALLTHRU);
8e6b4515 8504 gsi = gsi_last_bb (entry_bb);
8505 set_immediate_dominator (CDI_DOMINATORS, entry_bb,
8506 get_immediate_dominator (CDI_DOMINATORS,
43895be5 8507 zero_iter1_bb));
8508 }
8509 if (zero_iter2_bb)
8510 {
8511 /* Some counts[i] vars might be uninitialized if
8512 some loop has zero iterations. But the body shouldn't
8513 be executed in that case, so just avoid uninit warnings. */
8514 for (i = first_zero_iter2; i < fd->ordered; i++)
8515 if (SSA_VAR_P (counts[i]))
8516 TREE_NO_WARNING (counts[i]) = 1;
8517 if (zero_iter1_bb)
8518 make_edge (zero_iter2_bb, entry_bb, EDGE_FALLTHRU);
8519 else
8520 {
8521 gsi_prev (&gsi);
8522 e = split_block (entry_bb, gsi_stmt (gsi));
8523 entry_bb = e->dest;
8524 make_edge (zero_iter2_bb, entry_bb, EDGE_FALLTHRU);
8525 gsi = gsi_last_bb (entry_bb);
8526 set_immediate_dominator (CDI_DOMINATORS, entry_bb,
8527 get_immediate_dominator
8528 (CDI_DOMINATORS, zero_iter2_bb));
8529 }
8530 }
8531 if (fd->collapse == 1)
8532 {
8533 counts[0] = fd->loop.n2;
8534 fd->loop = fd->loops[0];
8535 }
8536 }
8537
8538 type = TREE_TYPE (fd->loop.v);
8539 istart0 = create_tmp_var (fd->iter_type, ".istart0");
8540 iend0 = create_tmp_var (fd->iter_type, ".iend0");
8541 TREE_ADDRESSABLE (istart0) = 1;
8542 TREE_ADDRESSABLE (iend0) = 1;
8543
8544 /* See if we need to bias by LLONG_MIN. */
8545 if (fd->iter_type == long_long_unsigned_type_node
8546 && TREE_CODE (type) == INTEGER_TYPE
8547 && !TYPE_UNSIGNED (type)
8548 && fd->ordered == 0)
8549 {
8550 tree n1, n2;
8551
8552 if (fd->loop.cond_code == LT_EXPR)
8553 {
8554 n1 = fd->loop.n1;
8555 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
8e6b4515 8556 }
43895be5 8557 else
8558 {
8559 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
8560 n2 = fd->loop.n1;
8561 }
8562 if (TREE_CODE (n1) != INTEGER_CST
8563 || TREE_CODE (n2) != INTEGER_CST
8564 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
8565 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
fd6481cf 8566 }
43895be5 8567
8568 gimple_stmt_iterator gsif = gsi;
8569 gsi_prev (&gsif);
8570
8571 tree arr = NULL_TREE;
79acaae1 8572 if (in_combined_parallel)
8573 {
43895be5 8574 gcc_assert (fd->ordered == 0);
79acaae1 8575 /* In a combined parallel loop, emit a call to
8576 GOMP_loop_foo_next. */
b9a16870 8577 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
79acaae1 8578 build_fold_addr_expr (istart0),
8579 build_fold_addr_expr (iend0));
8580 }
8581 else
1e8e9920 8582 {
c2f47e15 8583 tree t0, t1, t2, t3, t4;
773c5ba7 8584 /* If this is not a combined parallel loop, emit a call to
8585 GOMP_loop_foo_start in ENTRY_BB. */
c2f47e15 8586 t4 = build_fold_addr_expr (iend0);
8587 t3 = build_fold_addr_expr (istart0);
43895be5 8588 if (fd->ordered)
c799f233 8589 {
43895be5 8590 t0 = build_int_cst (unsigned_type_node,
8591 fd->ordered - fd->collapse + 1);
8592 arr = create_tmp_var (build_array_type_nelts (fd->iter_type,
8593 fd->ordered
8594 - fd->collapse + 1),
8595 ".omp_counts");
8596 DECL_NAMELESS (arr) = 1;
8597 TREE_ADDRESSABLE (arr) = 1;
8598 TREE_STATIC (arr) = 1;
8599 vec<constructor_elt, va_gc> *v;
8600 vec_alloc (v, fd->ordered - fd->collapse + 1);
8601 int idx;
8602
8603 for (idx = 0; idx < fd->ordered - fd->collapse + 1; idx++)
8604 {
8605 tree c;
8606 if (idx == 0 && fd->collapse > 1)
8607 c = fd->loop.n2;
8608 else
8609 c = counts[idx + fd->collapse - 1];
8610 tree purpose = size_int (idx);
8611 CONSTRUCTOR_APPEND_ELT (v, purpose, c);
8612 if (TREE_CODE (c) != INTEGER_CST)
8613 TREE_STATIC (arr) = 0;
8614 }
8615
8616 DECL_INITIAL (arr) = build_constructor (TREE_TYPE (arr), v);
8617 if (!TREE_STATIC (arr))
8618 force_gimple_operand_gsi (&gsi, build1 (DECL_EXPR,
8619 void_type_node, arr),
8620 true, NULL_TREE, true, GSI_SAME_STMT);
8621 t1 = build_fold_addr_expr (arr);
8622 t2 = NULL_TREE;
c799f233 8623 }
8624 else
8625 {
43895be5 8626 t2 = fold_convert (fd->iter_type, fd->loop.step);
8627 t1 = fd->loop.n2;
8628 t0 = fd->loop.n1;
8629 if (gimple_omp_for_combined_into_p (fd->for_stmt))
8630 {
8631 tree innerc
8632 = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
8633 OMP_CLAUSE__LOOPTEMP_);
8634 gcc_assert (innerc);
8635 t0 = OMP_CLAUSE_DECL (innerc);
8636 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
8637 OMP_CLAUSE__LOOPTEMP_);
8638 gcc_assert (innerc);
8639 t1 = OMP_CLAUSE_DECL (innerc);
8640 }
8641 if (POINTER_TYPE_P (TREE_TYPE (t0))
8642 && TYPE_PRECISION (TREE_TYPE (t0))
8643 != TYPE_PRECISION (fd->iter_type))
8644 {
8645 /* Avoid casting pointers to integer of a different size. */
8646 tree itype = signed_type_for (type);
8647 t1 = fold_convert (fd->iter_type, fold_convert (itype, t1));
8648 t0 = fold_convert (fd->iter_type, fold_convert (itype, t0));
8649 }
8650 else
8651 {
8652 t1 = fold_convert (fd->iter_type, t1);
8653 t0 = fold_convert (fd->iter_type, t0);
8654 }
8655 if (bias)
8656 {
8657 t1 = fold_build2 (PLUS_EXPR, fd->iter_type, t1, bias);
8658 t0 = fold_build2 (PLUS_EXPR, fd->iter_type, t0, bias);
8659 }
fd6481cf 8660 }
43895be5 8661 if (fd->iter_type == long_integer_type_node || fd->ordered)
fd6481cf 8662 {
8663 if (fd->chunk_size)
8664 {
8665 t = fold_convert (fd->iter_type, fd->chunk_size);
43895be5 8666 t = omp_adjust_chunk_size (t, fd->simd_schedule);
8667 if (fd->ordered)
8668 t = build_call_expr (builtin_decl_explicit (start_fn),
8669 5, t0, t1, t, t3, t4);
8670 else
8671 t = build_call_expr (builtin_decl_explicit (start_fn),
8672 6, t0, t1, t2, t, t3, t4);
fd6481cf 8673 }
43895be5 8674 else if (fd->ordered)
8675 t = build_call_expr (builtin_decl_explicit (start_fn),
8676 4, t0, t1, t3, t4);
fd6481cf 8677 else
b9a16870 8678 t = build_call_expr (builtin_decl_explicit (start_fn),
8679 5, t0, t1, t2, t3, t4);
1e8e9920 8680 }
c2f47e15 8681 else
fd6481cf 8682 {
8683 tree t5;
8684 tree c_bool_type;
b9a16870 8685 tree bfn_decl;
fd6481cf 8686
8687 /* The GOMP_loop_ull_*start functions have additional boolean
8688 argument, true for < loops and false for > loops.
8689 In Fortran, the C bool type can be different from
8690 boolean_type_node. */
b9a16870 8691 bfn_decl = builtin_decl_explicit (start_fn);
8692 c_bool_type = TREE_TYPE (TREE_TYPE (bfn_decl));
fd6481cf 8693 t5 = build_int_cst (c_bool_type,
8694 fd->loop.cond_code == LT_EXPR ? 1 : 0);
8695 if (fd->chunk_size)
8696 {
b9a16870 8697 tree bfn_decl = builtin_decl_explicit (start_fn);
fd6481cf 8698 t = fold_convert (fd->iter_type, fd->chunk_size);
43895be5 8699 t = omp_adjust_chunk_size (t, fd->simd_schedule);
b9a16870 8700 t = build_call_expr (bfn_decl, 7, t5, t0, t1, t2, t, t3, t4);
fd6481cf 8701 }
8702 else
b9a16870 8703 t = build_call_expr (builtin_decl_explicit (start_fn),
8704 6, t5, t0, t1, t2, t3, t4);
fd6481cf 8705 }
1e8e9920 8706 }
fd6481cf 8707 if (TREE_TYPE (t) != boolean_type_node)
8708 t = fold_build2 (NE_EXPR, boolean_type_node,
8709 t, build_int_cst (TREE_TYPE (t), 0));
75a70cf9 8710 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8711 true, GSI_SAME_STMT);
43895be5 8712 if (arr && !TREE_STATIC (arr))
8713 {
8714 tree clobber = build_constructor (TREE_TYPE (arr), NULL);
8715 TREE_THIS_VOLATILE (clobber) = 1;
8716 gsi_insert_before (&gsi, gimple_build_assign (arr, clobber),
8717 GSI_SAME_STMT);
8718 }
75a70cf9 8719 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
79acaae1 8720
75a70cf9 8721 /* Remove the GIMPLE_OMP_FOR statement. */
8722 gsi_remove (&gsi, true);
1e8e9920 8723
43895be5 8724 if (gsi_end_p (gsif))
8725 gsif = gsi_after_labels (gsi_bb (gsif));
8726 gsi_next (&gsif);
8727
773c5ba7 8728 /* Iteration setup for sequential loop goes in L0_BB. */
3d483a94 8729 tree startvar = fd->loop.v;
8730 tree endvar = NULL_TREE;
8731
bc7bff74 8732 if (gimple_omp_for_combined_p (fd->for_stmt))
8733 {
8734 gcc_assert (gimple_code (inner_stmt) == GIMPLE_OMP_FOR
8735 && gimple_omp_for_kind (inner_stmt)
8736 == GF_OMP_FOR_KIND_SIMD);
8737 tree innerc = find_omp_clause (gimple_omp_for_clauses (inner_stmt),
8738 OMP_CLAUSE__LOOPTEMP_);
8739 gcc_assert (innerc);
8740 startvar = OMP_CLAUSE_DECL (innerc);
8741 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
8742 OMP_CLAUSE__LOOPTEMP_);
8743 gcc_assert (innerc);
8744 endvar = OMP_CLAUSE_DECL (innerc);
8745 }
8746
75a70cf9 8747 gsi = gsi_start_bb (l0_bb);
1efcacec 8748 t = istart0;
43895be5 8749 if (fd->ordered && fd->collapse == 1)
8750 t = fold_build2 (MULT_EXPR, fd->iter_type, t,
8751 fold_convert (fd->iter_type, fd->loop.step));
8752 else if (bias)
1efcacec 8753 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
43895be5 8754 if (fd->ordered && fd->collapse == 1)
8755 {
8756 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
8757 t = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (startvar),
8758 fd->loop.n1, fold_convert (sizetype, t));
8759 else
8760 {
8761 t = fold_convert (TREE_TYPE (startvar), t);
8762 t = fold_build2 (PLUS_EXPR, TREE_TYPE (startvar),
8763 fd->loop.n1, t);
8764 }
8765 }
8766 else
8767 {
8768 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
8769 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
8770 t = fold_convert (TREE_TYPE (startvar), t);
8771 }
4abecb72 8772 t = force_gimple_operand_gsi (&gsi, t,
3d483a94 8773 DECL_P (startvar)
8774 && TREE_ADDRESSABLE (startvar),
4abecb72 8775 NULL_TREE, false, GSI_CONTINUE_LINKING);
1a91d914 8776 assign_stmt = gimple_build_assign (startvar, t);
8777 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
1e8e9920 8778
1efcacec 8779 t = iend0;
43895be5 8780 if (fd->ordered && fd->collapse == 1)
8781 t = fold_build2 (MULT_EXPR, fd->iter_type, t,
8782 fold_convert (fd->iter_type, fd->loop.step));
8783 else if (bias)
1efcacec 8784 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
43895be5 8785 if (fd->ordered && fd->collapse == 1)
fd6481cf 8786 {
43895be5 8787 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
8788 t = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (startvar),
8789 fd->loop.n1, fold_convert (sizetype, t));
8790 else
8791 {
8792 t = fold_convert (TREE_TYPE (startvar), t);
8793 t = fold_build2 (PLUS_EXPR, TREE_TYPE (startvar),
8794 fd->loop.n1, t);
8795 }
8796 }
8797 else
8798 {
8799 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
8800 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
8801 t = fold_convert (TREE_TYPE (startvar), t);
8802 }
8803 iend = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8804 false, GSI_CONTINUE_LINKING);
8805 if (endvar)
8806 {
8807 assign_stmt = gimple_build_assign (endvar, iend);
1a91d914 8808 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
d44f2f7c 8809 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (iend)))
1a91d914 8810 assign_stmt = gimple_build_assign (fd->loop.v, iend);
d44f2f7c 8811 else
e9cf809e 8812 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, iend);
1a91d914 8813 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
fd6481cf 8814 }
43895be5 8815 /* Handle linear clause adjustments. */
8816 tree itercnt = NULL_TREE;
8817 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_FOR)
8818 for (tree c = gimple_omp_for_clauses (fd->for_stmt);
8819 c; c = OMP_CLAUSE_CHAIN (c))
8820 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
8821 && !OMP_CLAUSE_LINEAR_NO_COPYIN (c))
8822 {
8823 tree d = OMP_CLAUSE_DECL (c);
8824 bool is_ref = is_reference (d);
8825 tree t = d, a, dest;
8826 if (is_ref)
8827 t = build_simple_mem_ref_loc (OMP_CLAUSE_LOCATION (c), t);
8828 tree type = TREE_TYPE (t);
8829 if (POINTER_TYPE_P (type))
8830 type = sizetype;
8831 dest = unshare_expr (t);
8832 tree v = create_tmp_var (TREE_TYPE (t), NULL);
8833 expand_omp_build_assign (&gsif, v, t);
8834 if (itercnt == NULL_TREE)
8835 {
8836 itercnt = startvar;
8837 tree n1 = fd->loop.n1;
8838 if (POINTER_TYPE_P (TREE_TYPE (itercnt)))
8839 {
8840 itercnt
8841 = fold_convert (signed_type_for (TREE_TYPE (itercnt)),
8842 itercnt);
8843 n1 = fold_convert (TREE_TYPE (itercnt), n1);
8844 }
8845 itercnt = fold_build2 (MINUS_EXPR, TREE_TYPE (itercnt),
8846 itercnt, n1);
8847 itercnt = fold_build2 (EXACT_DIV_EXPR, TREE_TYPE (itercnt),
8848 itercnt, fd->loop.step);
8849 itercnt = force_gimple_operand_gsi (&gsi, itercnt, true,
8850 NULL_TREE, false,
8851 GSI_CONTINUE_LINKING);
8852 }
8853 a = fold_build2 (MULT_EXPR, type,
8854 fold_convert (type, itercnt),
8855 fold_convert (type, OMP_CLAUSE_LINEAR_STEP (c)));
8856 t = fold_build2 (type == TREE_TYPE (t) ? PLUS_EXPR
8857 : POINTER_PLUS_EXPR, TREE_TYPE (t), v, a);
8858 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8859 false, GSI_CONTINUE_LINKING);
8860 assign_stmt = gimple_build_assign (dest, t);
8861 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
8862 }
3d483a94 8863 if (fd->collapse > 1)
bc7bff74 8864 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
773c5ba7 8865
43895be5 8866 if (fd->ordered)
8867 {
8868 /* Until now, counts array contained number of iterations or
8869 variable containing it for ith loop. From now on, we need
8870 those counts only for collapsed loops, and only for the 2nd
8871 till the last collapsed one. Move those one element earlier,
8872 we'll use counts[fd->collapse - 1] for the first source/sink
8873 iteration counter and so on and counts[fd->ordered]
8874 as the array holding the current counter values for
8875 depend(source). */
8876 if (fd->collapse > 1)
8877 memmove (counts, counts + 1, (fd->collapse - 1) * sizeof (counts[0]));
8878 if (broken_loop)
8879 {
8880 int i;
8881 for (i = fd->collapse; i < fd->ordered; i++)
8882 {
8883 tree type = TREE_TYPE (fd->loops[i].v);
8884 tree this_cond
8885 = fold_build2 (fd->loops[i].cond_code, boolean_type_node,
8886 fold_convert (type, fd->loops[i].n1),
8887 fold_convert (type, fd->loops[i].n2));
8888 if (!integer_onep (this_cond))
8889 break;
8890 }
8891 if (i < fd->ordered)
8892 {
8893 cont_bb
8894 = create_empty_bb (EXIT_BLOCK_PTR_FOR_FN (cfun)->prev_bb);
8895 add_bb_to_loop (cont_bb, l1_bb->loop_father);
8896 gimple_stmt_iterator gsi = gsi_after_labels (cont_bb);
8897 gimple *g = gimple_build_omp_continue (fd->loop.v, fd->loop.v);
8898 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
8899 make_edge (cont_bb, l3_bb, EDGE_FALLTHRU);
8900 make_edge (cont_bb, l1_bb, 0);
8901 l2_bb = create_empty_bb (cont_bb);
8902 broken_loop = false;
8903 }
8904 }
8905 expand_omp_ordered_source_sink (region, fd, counts, cont_bb);
8906 cont_bb = expand_omp_for_ordered_loops (fd, counts, cont_bb, l1_bb,
8907 ordered_lastprivate);
8908 if (counts[fd->collapse - 1])
8909 {
8910 gcc_assert (fd->collapse == 1);
8911 gsi = gsi_last_bb (l0_bb);
8912 expand_omp_build_assign (&gsi, counts[fd->collapse - 1],
8913 istart0, true);
8914 gsi = gsi_last_bb (cont_bb);
8915 t = fold_build2 (PLUS_EXPR, fd->iter_type, counts[fd->collapse - 1],
8916 build_int_cst (fd->iter_type, 1));
8917 expand_omp_build_assign (&gsi, counts[fd->collapse - 1], t);
8918 tree aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
8919 size_zero_node, NULL_TREE, NULL_TREE);
8920 expand_omp_build_assign (&gsi, aref, counts[fd->collapse - 1]);
8921 t = counts[fd->collapse - 1];
8922 }
8923 else if (fd->collapse > 1)
8924 t = fd->loop.v;
8925 else
8926 {
8927 t = fold_build2 (MINUS_EXPR, TREE_TYPE (fd->loops[0].v),
8928 fd->loops[0].v, fd->loops[0].n1);
8929 t = fold_convert (fd->iter_type, t);
8930 }
8931 gsi = gsi_last_bb (l0_bb);
8932 tree aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
8933 size_zero_node, NULL_TREE, NULL_TREE);
8934 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8935 false, GSI_CONTINUE_LINKING);
8936 expand_omp_build_assign (&gsi, aref, t, true);
8937 }
8938
ac6e3339 8939 if (!broken_loop)
03ed154b 8940 {
ac6e3339 8941 /* Code to control the increment and predicate for the sequential
8942 loop goes in the CONT_BB. */
75a70cf9 8943 gsi = gsi_last_bb (cont_bb);
1a91d914 8944 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
8945 gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
8946 vmain = gimple_omp_continue_control_use (cont_stmt);
8947 vback = gimple_omp_continue_control_def (cont_stmt);
79acaae1 8948
bc7bff74 8949 if (!gimple_omp_for_combined_p (fd->for_stmt))
3d483a94 8950 {
8951 if (POINTER_TYPE_P (type))
8952 t = fold_build_pointer_plus (vmain, fd->loop.step);
8953 else
8954 t = fold_build2 (PLUS_EXPR, type, vmain, fd->loop.step);
8955 t = force_gimple_operand_gsi (&gsi, t,
8956 DECL_P (vback)
8957 && TREE_ADDRESSABLE (vback),
8958 NULL_TREE, true, GSI_SAME_STMT);
1a91d914 8959 assign_stmt = gimple_build_assign (vback, t);
8960 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
3d483a94 8961
43895be5 8962 if (fd->ordered && counts[fd->collapse - 1] == NULL_TREE)
8963 {
8964 if (fd->collapse > 1)
8965 t = fd->loop.v;
8966 else
8967 {
8968 t = fold_build2 (MINUS_EXPR, TREE_TYPE (fd->loops[0].v),
8969 fd->loops[0].v, fd->loops[0].n1);
8970 t = fold_convert (fd->iter_type, t);
8971 }
8972 tree aref = build4 (ARRAY_REF, fd->iter_type,
8973 counts[fd->ordered], size_zero_node,
8974 NULL_TREE, NULL_TREE);
8975 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8976 true, GSI_SAME_STMT);
8977 expand_omp_build_assign (&gsi, aref, t);
8978 }
8979
3d483a94 8980 t = build2 (fd->loop.cond_code, boolean_type_node,
8981 DECL_P (vback) && TREE_ADDRESSABLE (vback) ? t : vback,
8982 iend);
1a91d914 8983 gcond *cond_stmt = gimple_build_cond_empty (t);
8984 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
3d483a94 8985 }
773c5ba7 8986
75a70cf9 8987 /* Remove GIMPLE_OMP_CONTINUE. */
8988 gsi_remove (&gsi, true);
773c5ba7 8989
bc7bff74 8990 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
3d483a94 8991 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, l1_bb);
fd6481cf 8992
ac6e3339 8993 /* Emit code to get the next parallel iteration in L2_BB. */
75a70cf9 8994 gsi = gsi_start_bb (l2_bb);
773c5ba7 8995
b9a16870 8996 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
ac6e3339 8997 build_fold_addr_expr (istart0),
8998 build_fold_addr_expr (iend0));
75a70cf9 8999 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9000 false, GSI_CONTINUE_LINKING);
fd6481cf 9001 if (TREE_TYPE (t) != boolean_type_node)
9002 t = fold_build2 (NE_EXPR, boolean_type_node,
9003 t, build_int_cst (TREE_TYPE (t), 0));
1a91d914 9004 gcond *cond_stmt = gimple_build_cond_empty (t);
9005 gsi_insert_after (&gsi, cond_stmt, GSI_CONTINUE_LINKING);
ac6e3339 9006 }
1e8e9920 9007
61e47ac8 9008 /* Add the loop cleanup function. */
75a70cf9 9009 gsi = gsi_last_bb (exit_bb);
9010 if (gimple_omp_return_nowait_p (gsi_stmt (gsi)))
b9a16870 9011 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_NOWAIT);
bc7bff74 9012 else if (gimple_omp_return_lhs (gsi_stmt (gsi)))
9013 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_CANCEL);
61e47ac8 9014 else
b9a16870 9015 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END);
1a91d914 9016 gcall *call_stmt = gimple_build_call (t, 0);
bc7bff74 9017 if (gimple_omp_return_lhs (gsi_stmt (gsi)))
1a91d914 9018 gimple_call_set_lhs (call_stmt, gimple_omp_return_lhs (gsi_stmt (gsi)));
9019 gsi_insert_after (&gsi, call_stmt, GSI_SAME_STMT);
43895be5 9020 if (fd->ordered)
9021 {
9022 tree arr = counts[fd->ordered];
9023 tree clobber = build_constructor (TREE_TYPE (arr), NULL);
9024 TREE_THIS_VOLATILE (clobber) = 1;
9025 gsi_insert_after (&gsi, gimple_build_assign (arr, clobber),
9026 GSI_SAME_STMT);
9027 }
75a70cf9 9028 gsi_remove (&gsi, true);
773c5ba7 9029
9030 /* Connect the new blocks. */
79acaae1 9031 find_edge (entry_bb, l0_bb)->flags = EDGE_TRUE_VALUE;
9032 find_edge (entry_bb, l3_bb)->flags = EDGE_FALSE_VALUE;
1e8e9920 9033
ac6e3339 9034 if (!broken_loop)
9035 {
75a70cf9 9036 gimple_seq phis;
9037
79acaae1 9038 e = find_edge (cont_bb, l3_bb);
9039 ne = make_edge (l2_bb, l3_bb, EDGE_FALSE_VALUE);
9040
75a70cf9 9041 phis = phi_nodes (l3_bb);
9042 for (gsi = gsi_start (phis); !gsi_end_p (gsi); gsi_next (&gsi))
9043 {
42acab1c 9044 gimple *phi = gsi_stmt (gsi);
75a70cf9 9045 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, ne),
9046 PHI_ARG_DEF_FROM_EDGE (phi, e));
9047 }
79acaae1 9048 remove_edge (e);
9049
ac6e3339 9050 make_edge (cont_bb, l2_bb, EDGE_FALSE_VALUE);
3d483a94 9051 e = find_edge (cont_bb, l1_bb);
95cd5725 9052 if (e == NULL)
9053 {
9054 e = BRANCH_EDGE (cont_bb);
9055 gcc_assert (single_succ (e->dest) == l1_bb);
9056 }
bc7bff74 9057 if (gimple_omp_for_combined_p (fd->for_stmt))
9058 {
9059 remove_edge (e);
9060 e = NULL;
9061 }
3d483a94 9062 else if (fd->collapse > 1)
fd6481cf 9063 {
fd6481cf 9064 remove_edge (e);
9065 e = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
9066 }
9067 else
3d483a94 9068 e->flags = EDGE_TRUE_VALUE;
9069 if (e)
fd6481cf 9070 {
3d483a94 9071 e->probability = REG_BR_PROB_BASE * 7 / 8;
9072 find_edge (cont_bb, l2_bb)->probability = REG_BR_PROB_BASE / 8;
9073 }
9074 else
9075 {
9076 e = find_edge (cont_bb, l2_bb);
9077 e->flags = EDGE_FALLTHRU;
fd6481cf 9078 }
ac6e3339 9079 make_edge (l2_bb, l0_bb, EDGE_TRUE_VALUE);
79acaae1 9080
2131a1a9 9081 if (gimple_in_ssa_p (cfun))
9082 {
9083 /* Add phis to the outer loop that connect to the phis in the inner,
9084 original loop, and move the loop entry value of the inner phi to
9085 the loop entry value of the outer phi. */
9086 gphi_iterator psi;
9087 for (psi = gsi_start_phis (l3_bb); !gsi_end_p (psi); gsi_next (&psi))
9088 {
9089 source_location locus;
9090 gphi *nphi;
9091 gphi *exit_phi = psi.phi ();
9092
9093 edge l2_to_l3 = find_edge (l2_bb, l3_bb);
9094 tree exit_res = PHI_ARG_DEF_FROM_EDGE (exit_phi, l2_to_l3);
9095
9096 basic_block latch = BRANCH_EDGE (cont_bb)->dest;
9097 edge latch_to_l1 = find_edge (latch, l1_bb);
9098 gphi *inner_phi
9099 = find_phi_with_arg_on_edge (exit_res, latch_to_l1);
9100
9101 tree t = gimple_phi_result (exit_phi);
9102 tree new_res = copy_ssa_name (t, NULL);
9103 nphi = create_phi_node (new_res, l0_bb);
9104
9105 edge l0_to_l1 = find_edge (l0_bb, l1_bb);
9106 t = PHI_ARG_DEF_FROM_EDGE (inner_phi, l0_to_l1);
9107 locus = gimple_phi_arg_location_from_edge (inner_phi, l0_to_l1);
9108 edge entry_to_l0 = find_edge (entry_bb, l0_bb);
9109 add_phi_arg (nphi, t, entry_to_l0, locus);
9110
9111 edge l2_to_l0 = find_edge (l2_bb, l0_bb);
9112 add_phi_arg (nphi, exit_res, l2_to_l0, UNKNOWN_LOCATION);
9113
9114 add_phi_arg (inner_phi, new_res, l0_to_l1, UNKNOWN_LOCATION);
9115 };
9116 }
9117
79acaae1 9118 set_immediate_dominator (CDI_DOMINATORS, l2_bb,
9119 recompute_dominator (CDI_DOMINATORS, l2_bb));
9120 set_immediate_dominator (CDI_DOMINATORS, l3_bb,
9121 recompute_dominator (CDI_DOMINATORS, l3_bb));
9122 set_immediate_dominator (CDI_DOMINATORS, l0_bb,
9123 recompute_dominator (CDI_DOMINATORS, l0_bb));
9124 set_immediate_dominator (CDI_DOMINATORS, l1_bb,
9125 recompute_dominator (CDI_DOMINATORS, l1_bb));
04c2922b 9126
1c6a437b 9127 /* We enter expand_omp_for_generic with a loop. This original loop may
9128 have its own loop struct, or it may be part of an outer loop struct
9129 (which may be the fake loop). */
9130 struct loop *outer_loop = entry_bb->loop_father;
9131 bool orig_loop_has_loop_struct = l1_bb->loop_father != outer_loop;
9132
9133 add_bb_to_loop (l2_bb, outer_loop);
9134
9135 /* We've added a new loop around the original loop. Allocate the
9136 corresponding loop struct. */
9137 struct loop *new_loop = alloc_loop ();
9138 new_loop->header = l0_bb;
9139 new_loop->latch = l2_bb;
9140 add_loop (new_loop, outer_loop);
9141
9142 /* Allocate a loop structure for the original loop unless we already
9143 had one. */
9144 if (!orig_loop_has_loop_struct
9145 && !gimple_omp_for_combined_p (fd->for_stmt))
3d483a94 9146 {
1c6a437b 9147 struct loop *orig_loop = alloc_loop ();
9148 orig_loop->header = l1_bb;
3d483a94 9149 /* The loop may have multiple latches. */
1c6a437b 9150 add_loop (orig_loop, new_loop);
3d483a94 9151 }
ac6e3339 9152 }
1e8e9920 9153}
9154
9155
773c5ba7 9156/* A subroutine of expand_omp_for. Generate code for a parallel
9157 loop with static schedule and no specified chunk size. Given
9158 parameters:
1e8e9920 9159
9160 for (V = N1; V cond N2; V += STEP) BODY;
9161
9162 where COND is "<" or ">", we generate pseudocode
9163
8e6b4515 9164 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
1e8e9920 9165 if (cond is <)
9166 adj = STEP - 1;
9167 else
9168 adj = STEP + 1;
fd6481cf 9169 if ((__typeof (V)) -1 > 0 && cond is >)
9170 n = -(adj + N2 - N1) / -STEP;
9171 else
9172 n = (adj + N2 - N1) / STEP;
1e8e9920 9173 q = n / nthreads;
31712e83 9174 tt = n % nthreads;
9175 if (threadid < tt) goto L3; else goto L4;
9176 L3:
9177 tt = 0;
9178 q = q + 1;
9179 L4:
9180 s0 = q * threadid + tt;
9181 e0 = s0 + q;
79acaae1 9182 V = s0 * STEP + N1;
1e8e9920 9183 if (s0 >= e0) goto L2; else goto L0;
9184 L0:
1e8e9920 9185 e = e0 * STEP + N1;
9186 L1:
9187 BODY;
9188 V += STEP;
9189 if (V cond e) goto L1;
1e8e9920 9190 L2:
9191*/
9192
61e47ac8 9193static void
773c5ba7 9194expand_omp_for_static_nochunk (struct omp_region *region,
bc7bff74 9195 struct omp_for_data *fd,
42acab1c 9196 gimple *inner_stmt)
1e8e9920 9197{
31712e83 9198 tree n, q, s0, e0, e, t, tt, nthreads, threadid;
fd6481cf 9199 tree type, itype, vmain, vback;
31712e83 9200 basic_block entry_bb, second_bb, third_bb, exit_bb, seq_start_bb;
bc7bff74 9201 basic_block body_bb, cont_bb, collapse_bb = NULL;
61e47ac8 9202 basic_block fin_bb;
75a70cf9 9203 gimple_stmt_iterator gsi;
31712e83 9204 edge ep;
bc7bff74 9205 bool broken_loop = region->cont == NULL;
9206 tree *counts = NULL;
9207 tree n1, n2, step;
1e8e9920 9208
fd6481cf 9209 itype = type = TREE_TYPE (fd->loop.v);
9210 if (POINTER_TYPE_P (type))
3cea8318 9211 itype = signed_type_for (type);
1e8e9920 9212
61e47ac8 9213 entry_bb = region->entry;
61e47ac8 9214 cont_bb = region->cont;
ac6e3339 9215 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
bc7bff74 9216 fin_bb = BRANCH_EDGE (entry_bb)->dest;
9217 gcc_assert (broken_loop
9218 || (fin_bb == FALLTHRU_EDGE (cont_bb)->dest));
ac6e3339 9219 seq_start_bb = split_edge (FALLTHRU_EDGE (entry_bb));
9220 body_bb = single_succ (seq_start_bb);
bc7bff74 9221 if (!broken_loop)
9222 {
86a932e0 9223 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb
9224 || single_succ (BRANCH_EDGE (cont_bb)->dest) == body_bb);
bc7bff74 9225 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
9226 }
61e47ac8 9227 exit_bb = region->exit;
9228
773c5ba7 9229 /* Iteration space partitioning goes in ENTRY_BB. */
75a70cf9 9230 gsi = gsi_last_bb (entry_bb);
9231 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
61e47ac8 9232
bc7bff74 9233 if (fd->collapse > 1)
9234 {
43895be5 9235 int first_zero_iter = -1, dummy = -1;
9236 basic_block l2_dom_bb = NULL, dummy_bb = NULL;
bc7bff74 9237
9238 counts = XALLOCAVEC (tree, fd->collapse);
9239 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
9240 fin_bb, first_zero_iter,
43895be5 9241 dummy_bb, dummy, l2_dom_bb);
bc7bff74 9242 t = NULL_TREE;
9243 }
9244 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
9245 t = integer_one_node;
9246 else
9247 t = fold_binary (fd->loop.cond_code, boolean_type_node,
9248 fold_convert (type, fd->loop.n1),
9249 fold_convert (type, fd->loop.n2));
9250 if (fd->collapse == 1
9251 && TYPE_UNSIGNED (type)
8e6b4515 9252 && (t == NULL_TREE || !integer_onep (t)))
9253 {
8e6b4515 9254 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
9255 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
9256 true, GSI_SAME_STMT);
9257 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
9258 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
9259 true, GSI_SAME_STMT);
1a91d914 9260 gcond *cond_stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
9261 NULL_TREE, NULL_TREE);
9262 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
9263 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
8e6b4515 9264 expand_omp_regimplify_p, NULL, NULL)
1a91d914 9265 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
8e6b4515 9266 expand_omp_regimplify_p, NULL, NULL))
9267 {
1a91d914 9268 gsi = gsi_for_stmt (cond_stmt);
9269 gimple_regimplify_operands (cond_stmt, &gsi);
8e6b4515 9270 }
1a91d914 9271 ep = split_block (entry_bb, cond_stmt);
8e6b4515 9272 ep->flags = EDGE_TRUE_VALUE;
9273 entry_bb = ep->dest;
9274 ep->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
9275 ep = make_edge (ep->src, fin_bb, EDGE_FALSE_VALUE);
9276 ep->probability = REG_BR_PROB_BASE / 2000 - 1;
9277 if (gimple_in_ssa_p (cfun))
9278 {
9279 int dest_idx = find_edge (entry_bb, fin_bb)->dest_idx;
1a91d914 9280 for (gphi_iterator gpi = gsi_start_phis (fin_bb);
9281 !gsi_end_p (gpi); gsi_next (&gpi))
8e6b4515 9282 {
1a91d914 9283 gphi *phi = gpi.phi ();
8e6b4515 9284 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
9285 ep, UNKNOWN_LOCATION);
9286 }
9287 }
9288 gsi = gsi_last_bb (entry_bb);
9289 }
9290
ca4c3545 9291 switch (gimple_omp_for_kind (fd->for_stmt))
9292 {
9293 case GF_OMP_FOR_KIND_FOR:
9294 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
9295 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
9296 break;
9297 case GF_OMP_FOR_KIND_DISTRIBUTE:
9298 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_TEAMS);
9299 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_TEAM_NUM);
9300 break;
ca4c3545 9301 default:
9302 gcc_unreachable ();
9303 }
9304 nthreads = build_call_expr (nthreads, 0);
9305 nthreads = fold_convert (itype, nthreads);
9306 nthreads = force_gimple_operand_gsi (&gsi, nthreads, true, NULL_TREE,
75a70cf9 9307 true, GSI_SAME_STMT);
ca4c3545 9308 threadid = build_call_expr (threadid, 0);
9309 threadid = fold_convert (itype, threadid);
9310 threadid = force_gimple_operand_gsi (&gsi, threadid, true, NULL_TREE,
75a70cf9 9311 true, GSI_SAME_STMT);
1e8e9920 9312
bc7bff74 9313 n1 = fd->loop.n1;
9314 n2 = fd->loop.n2;
9315 step = fd->loop.step;
9316 if (gimple_omp_for_combined_into_p (fd->for_stmt))
9317 {
9318 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
9319 OMP_CLAUSE__LOOPTEMP_);
9320 gcc_assert (innerc);
9321 n1 = OMP_CLAUSE_DECL (innerc);
9322 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9323 OMP_CLAUSE__LOOPTEMP_);
9324 gcc_assert (innerc);
9325 n2 = OMP_CLAUSE_DECL (innerc);
9326 }
9327 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
9328 true, NULL_TREE, true, GSI_SAME_STMT);
9329 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
9330 true, NULL_TREE, true, GSI_SAME_STMT);
9331 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
9332 true, NULL_TREE, true, GSI_SAME_STMT);
fd6481cf 9333
9334 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
bc7bff74 9335 t = fold_build2 (PLUS_EXPR, itype, step, t);
9336 t = fold_build2 (PLUS_EXPR, itype, t, n2);
9337 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
fd6481cf 9338 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
9339 t = fold_build2 (TRUNC_DIV_EXPR, itype,
9340 fold_build1 (NEGATE_EXPR, itype, t),
bc7bff74 9341 fold_build1 (NEGATE_EXPR, itype, step));
fd6481cf 9342 else
bc7bff74 9343 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
fd6481cf 9344 t = fold_convert (itype, t);
75a70cf9 9345 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
1e8e9920 9346
072f7ab1 9347 q = create_tmp_reg (itype, "q");
fd6481cf 9348 t = fold_build2 (TRUNC_DIV_EXPR, itype, n, nthreads);
31712e83 9349 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
9350 gsi_insert_before (&gsi, gimple_build_assign (q, t), GSI_SAME_STMT);
9351
072f7ab1 9352 tt = create_tmp_reg (itype, "tt");
31712e83 9353 t = fold_build2 (TRUNC_MOD_EXPR, itype, n, nthreads);
9354 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
9355 gsi_insert_before (&gsi, gimple_build_assign (tt, t), GSI_SAME_STMT);
1e8e9920 9356
31712e83 9357 t = build2 (LT_EXPR, boolean_type_node, threadid, tt);
1a91d914 9358 gcond *cond_stmt = gimple_build_cond_empty (t);
9359 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
31712e83 9360
1a91d914 9361 second_bb = split_block (entry_bb, cond_stmt)->dest;
31712e83 9362 gsi = gsi_last_bb (second_bb);
9363 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
9364
9365 gsi_insert_before (&gsi, gimple_build_assign (tt, build_int_cst (itype, 0)),
9366 GSI_SAME_STMT);
1a91d914 9367 gassign *assign_stmt
e9cf809e 9368 = gimple_build_assign (q, PLUS_EXPR, q, build_int_cst (itype, 1));
1a91d914 9369 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
31712e83 9370
1a91d914 9371 third_bb = split_block (second_bb, assign_stmt)->dest;
31712e83 9372 gsi = gsi_last_bb (third_bb);
9373 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
1e8e9920 9374
fd6481cf 9375 t = build2 (MULT_EXPR, itype, q, threadid);
31712e83 9376 t = build2 (PLUS_EXPR, itype, t, tt);
75a70cf9 9377 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
1e8e9920 9378
fd6481cf 9379 t = fold_build2 (PLUS_EXPR, itype, s0, q);
75a70cf9 9380 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
79acaae1 9381
1e8e9920 9382 t = build2 (GE_EXPR, boolean_type_node, s0, e0);
75a70cf9 9383 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
773c5ba7 9384
75a70cf9 9385 /* Remove the GIMPLE_OMP_FOR statement. */
9386 gsi_remove (&gsi, true);
773c5ba7 9387
9388 /* Setup code for sequential iteration goes in SEQ_START_BB. */
75a70cf9 9389 gsi = gsi_start_bb (seq_start_bb);
1e8e9920 9390
bc7bff74 9391 tree startvar = fd->loop.v;
9392 tree endvar = NULL_TREE;
9393
9394 if (gimple_omp_for_combined_p (fd->for_stmt))
9395 {
9396 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
9397 ? gimple_omp_parallel_clauses (inner_stmt)
9398 : gimple_omp_for_clauses (inner_stmt);
9399 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
9400 gcc_assert (innerc);
9401 startvar = OMP_CLAUSE_DECL (innerc);
9402 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9403 OMP_CLAUSE__LOOPTEMP_);
9404 gcc_assert (innerc);
9405 endvar = OMP_CLAUSE_DECL (innerc);
9561765e 9406 if (fd->collapse > 1 && TREE_CODE (fd->loop.n2) != INTEGER_CST
9407 && gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
9408 {
9409 int i;
9410 for (i = 1; i < fd->collapse; i++)
9411 {
9412 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9413 OMP_CLAUSE__LOOPTEMP_);
9414 gcc_assert (innerc);
9415 }
9416 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9417 OMP_CLAUSE__LOOPTEMP_);
9418 if (innerc)
9419 {
9420 /* If needed (distribute parallel for with lastprivate),
9421 propagate down the total number of iterations. */
9422 tree t = fold_convert (TREE_TYPE (OMP_CLAUSE_DECL (innerc)),
9423 fd->loop.n2);
9424 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, false,
9425 GSI_CONTINUE_LINKING);
9426 assign_stmt = gimple_build_assign (OMP_CLAUSE_DECL (innerc), t);
9427 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9428 }
9429 }
bc7bff74 9430 }
fd6481cf 9431 t = fold_convert (itype, s0);
bc7bff74 9432 t = fold_build2 (MULT_EXPR, itype, t, step);
fd6481cf 9433 if (POINTER_TYPE_P (type))
bc7bff74 9434 t = fold_build_pointer_plus (n1, t);
fd6481cf 9435 else
bc7bff74 9436 t = fold_build2 (PLUS_EXPR, type, t, n1);
9437 t = fold_convert (TREE_TYPE (startvar), t);
4abecb72 9438 t = force_gimple_operand_gsi (&gsi, t,
bc7bff74 9439 DECL_P (startvar)
9440 && TREE_ADDRESSABLE (startvar),
4abecb72 9441 NULL_TREE, false, GSI_CONTINUE_LINKING);
1a91d914 9442 assign_stmt = gimple_build_assign (startvar, t);
9443 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
48e1416a 9444
fd6481cf 9445 t = fold_convert (itype, e0);
bc7bff74 9446 t = fold_build2 (MULT_EXPR, itype, t, step);
fd6481cf 9447 if (POINTER_TYPE_P (type))
bc7bff74 9448 t = fold_build_pointer_plus (n1, t);
fd6481cf 9449 else
bc7bff74 9450 t = fold_build2 (PLUS_EXPR, type, t, n1);
9451 t = fold_convert (TREE_TYPE (startvar), t);
75a70cf9 9452 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9453 false, GSI_CONTINUE_LINKING);
bc7bff74 9454 if (endvar)
9455 {
1a91d914 9456 assign_stmt = gimple_build_assign (endvar, e);
9457 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
d44f2f7c 9458 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
1a91d914 9459 assign_stmt = gimple_build_assign (fd->loop.v, e);
d44f2f7c 9460 else
e9cf809e 9461 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, e);
1a91d914 9462 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
bc7bff74 9463 }
43895be5 9464 /* Handle linear clause adjustments. */
9465 tree itercnt = NULL_TREE;
9466 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_FOR)
9467 for (tree c = gimple_omp_for_clauses (fd->for_stmt);
9468 c; c = OMP_CLAUSE_CHAIN (c))
9469 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
9470 && !OMP_CLAUSE_LINEAR_NO_COPYIN (c))
9471 {
9472 tree d = OMP_CLAUSE_DECL (c);
9473 bool is_ref = is_reference (d);
9474 tree t = d, a, dest;
9475 if (is_ref)
9476 t = build_simple_mem_ref_loc (OMP_CLAUSE_LOCATION (c), t);
9477 if (itercnt == NULL_TREE)
9478 {
9479 if (gimple_omp_for_combined_into_p (fd->for_stmt))
9480 {
9481 itercnt = fold_build2 (MINUS_EXPR, itype,
9482 fold_convert (itype, n1),
9483 fold_convert (itype, fd->loop.n1));
9484 itercnt = fold_build2 (EXACT_DIV_EXPR, itype, itercnt, step);
9485 itercnt = fold_build2 (PLUS_EXPR, itype, itercnt, s0);
9486 itercnt = force_gimple_operand_gsi (&gsi, itercnt, true,
9487 NULL_TREE, false,
9488 GSI_CONTINUE_LINKING);
9489 }
9490 else
9491 itercnt = s0;
9492 }
9493 tree type = TREE_TYPE (t);
9494 if (POINTER_TYPE_P (type))
9495 type = sizetype;
9496 a = fold_build2 (MULT_EXPR, type,
9497 fold_convert (type, itercnt),
9498 fold_convert (type, OMP_CLAUSE_LINEAR_STEP (c)));
9499 dest = unshare_expr (t);
9500 t = fold_build2 (type == TREE_TYPE (t) ? PLUS_EXPR
9501 : POINTER_PLUS_EXPR, TREE_TYPE (t), t, a);
9502 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9503 false, GSI_CONTINUE_LINKING);
9504 assign_stmt = gimple_build_assign (dest, t);
9505 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9506 }
bc7bff74 9507 if (fd->collapse > 1)
9508 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
1e8e9920 9509
bc7bff74 9510 if (!broken_loop)
9511 {
9512 /* The code controlling the sequential loop replaces the
9513 GIMPLE_OMP_CONTINUE. */
9514 gsi = gsi_last_bb (cont_bb);
1a91d914 9515 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
9516 gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
9517 vmain = gimple_omp_continue_control_use (cont_stmt);
9518 vback = gimple_omp_continue_control_def (cont_stmt);
79acaae1 9519
bc7bff74 9520 if (!gimple_omp_for_combined_p (fd->for_stmt))
9521 {
9522 if (POINTER_TYPE_P (type))
9523 t = fold_build_pointer_plus (vmain, step);
9524 else
9525 t = fold_build2 (PLUS_EXPR, type, vmain, step);
9526 t = force_gimple_operand_gsi (&gsi, t,
9527 DECL_P (vback)
9528 && TREE_ADDRESSABLE (vback),
9529 NULL_TREE, true, GSI_SAME_STMT);
1a91d914 9530 assign_stmt = gimple_build_assign (vback, t);
9531 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
79acaae1 9532
bc7bff74 9533 t = build2 (fd->loop.cond_code, boolean_type_node,
9534 DECL_P (vback) && TREE_ADDRESSABLE (vback)
9535 ? t : vback, e);
9536 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
9537 }
1e8e9920 9538
bc7bff74 9539 /* Remove the GIMPLE_OMP_CONTINUE statement. */
9540 gsi_remove (&gsi, true);
9541
9542 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
9543 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
9544 }
773c5ba7 9545
75a70cf9 9546 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
9547 gsi = gsi_last_bb (exit_bb);
9548 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
bc7bff74 9549 {
9550 t = gimple_omp_return_lhs (gsi_stmt (gsi));
a8e785ba 9551 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
bc7bff74 9552 }
75a70cf9 9553 gsi_remove (&gsi, true);
773c5ba7 9554
9555 /* Connect all the blocks. */
31712e83 9556 ep = make_edge (entry_bb, third_bb, EDGE_FALSE_VALUE);
9557 ep->probability = REG_BR_PROB_BASE / 4 * 3;
9558 ep = find_edge (entry_bb, second_bb);
9559 ep->flags = EDGE_TRUE_VALUE;
9560 ep->probability = REG_BR_PROB_BASE / 4;
9561 find_edge (third_bb, seq_start_bb)->flags = EDGE_FALSE_VALUE;
9562 find_edge (third_bb, fin_bb)->flags = EDGE_TRUE_VALUE;
79acaae1 9563
bc7bff74 9564 if (!broken_loop)
9565 {
9566 ep = find_edge (cont_bb, body_bb);
86a932e0 9567 if (ep == NULL)
9568 {
9569 ep = BRANCH_EDGE (cont_bb);
9570 gcc_assert (single_succ (ep->dest) == body_bb);
9571 }
bc7bff74 9572 if (gimple_omp_for_combined_p (fd->for_stmt))
9573 {
9574 remove_edge (ep);
9575 ep = NULL;
9576 }
9577 else if (fd->collapse > 1)
9578 {
9579 remove_edge (ep);
9580 ep = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
9581 }
9582 else
9583 ep->flags = EDGE_TRUE_VALUE;
9584 find_edge (cont_bb, fin_bb)->flags
9585 = ep ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
9586 }
48e1416a 9587
31712e83 9588 set_immediate_dominator (CDI_DOMINATORS, second_bb, entry_bb);
9589 set_immediate_dominator (CDI_DOMINATORS, third_bb, entry_bb);
9590 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb, third_bb);
bc7bff74 9591
79acaae1 9592 set_immediate_dominator (CDI_DOMINATORS, body_bb,
9593 recompute_dominator (CDI_DOMINATORS, body_bb));
9594 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
9595 recompute_dominator (CDI_DOMINATORS, fin_bb));
04c2922b 9596
86a932e0 9597 struct loop *loop = body_bb->loop_father;
9598 if (loop != entry_bb->loop_father)
9599 {
9600 gcc_assert (loop->header == body_bb);
9601 gcc_assert (broken_loop
9602 || loop->latch == region->cont
9603 || single_pred (loop->latch) == region->cont);
9604 return;
9605 }
9606
bc7bff74 9607 if (!broken_loop && !gimple_omp_for_combined_p (fd->for_stmt))
9608 {
86a932e0 9609 loop = alloc_loop ();
bc7bff74 9610 loop->header = body_bb;
9611 if (collapse_bb == NULL)
9612 loop->latch = cont_bb;
9613 add_loop (loop, body_bb->loop_father);
9614 }
1e8e9920 9615}
9616
281001a9 9617/* Return phi in E->DEST with ARG on edge E. */
9618
9619static gphi *
9620find_phi_with_arg_on_edge (tree arg, edge e)
9621{
9622 basic_block bb = e->dest;
9623
9624 for (gphi_iterator gpi = gsi_start_phis (bb);
9625 !gsi_end_p (gpi);
9626 gsi_next (&gpi))
9627 {
9628 gphi *phi = gpi.phi ();
9629 if (PHI_ARG_DEF_FROM_EDGE (phi, e) == arg)
9630 return phi;
9631 }
9632
9633 return NULL;
9634}
773c5ba7 9635
9636/* A subroutine of expand_omp_for. Generate code for a parallel
9637 loop with static schedule and a specified chunk size. Given
9638 parameters:
1e8e9920 9639
9640 for (V = N1; V cond N2; V += STEP) BODY;
9641
9642 where COND is "<" or ">", we generate pseudocode
9643
8e6b4515 9644 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
1e8e9920 9645 if (cond is <)
9646 adj = STEP - 1;
9647 else
9648 adj = STEP + 1;
fd6481cf 9649 if ((__typeof (V)) -1 > 0 && cond is >)
9650 n = -(adj + N2 - N1) / -STEP;
9651 else
9652 n = (adj + N2 - N1) / STEP;
1e8e9920 9653 trip = 0;
79acaae1 9654 V = threadid * CHUNK * STEP + N1; -- this extra definition of V is
9655 here so that V is defined
9656 if the loop is not entered
1e8e9920 9657 L0:
9658 s0 = (trip * nthreads + threadid) * CHUNK;
9659 e0 = min(s0 + CHUNK, n);
9660 if (s0 < n) goto L1; else goto L4;
9661 L1:
9662 V = s0 * STEP + N1;
9663 e = e0 * STEP + N1;
9664 L2:
9665 BODY;
9666 V += STEP;
9667 if (V cond e) goto L2; else goto L3;
9668 L3:
9669 trip += 1;
9670 goto L0;
9671 L4:
1e8e9920 9672*/
9673
61e47ac8 9674static void
bc7bff74 9675expand_omp_for_static_chunk (struct omp_region *region,
42acab1c 9676 struct omp_for_data *fd, gimple *inner_stmt)
1e8e9920 9677{
75a70cf9 9678 tree n, s0, e0, e, t;
79acaae1 9679 tree trip_var, trip_init, trip_main, trip_back, nthreads, threadid;
93481288 9680 tree type, itype, vmain, vback, vextra;
773c5ba7 9681 basic_block entry_bb, exit_bb, body_bb, seq_start_bb, iter_part_bb;
bc7bff74 9682 basic_block trip_update_bb = NULL, cont_bb, collapse_bb = NULL, fin_bb;
93481288 9683 gimple_stmt_iterator gsi;
75a70cf9 9684 edge se;
bc7bff74 9685 bool broken_loop = region->cont == NULL;
9686 tree *counts = NULL;
9687 tree n1, n2, step;
1e8e9920 9688
fd6481cf 9689 itype = type = TREE_TYPE (fd->loop.v);
9690 if (POINTER_TYPE_P (type))
3cea8318 9691 itype = signed_type_for (type);
1e8e9920 9692
61e47ac8 9693 entry_bb = region->entry;
ac6e3339 9694 se = split_block (entry_bb, last_stmt (entry_bb));
9695 entry_bb = se->src;
9696 iter_part_bb = se->dest;
61e47ac8 9697 cont_bb = region->cont;
ac6e3339 9698 gcc_assert (EDGE_COUNT (iter_part_bb->succs) == 2);
bc7bff74 9699 fin_bb = BRANCH_EDGE (iter_part_bb)->dest;
9700 gcc_assert (broken_loop
9701 || fin_bb == FALLTHRU_EDGE (cont_bb)->dest);
ac6e3339 9702 seq_start_bb = split_edge (FALLTHRU_EDGE (iter_part_bb));
9703 body_bb = single_succ (seq_start_bb);
bc7bff74 9704 if (!broken_loop)
9705 {
fc1d58e3 9706 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb
9707 || single_succ (BRANCH_EDGE (cont_bb)->dest) == body_bb);
bc7bff74 9708 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
9709 trip_update_bb = split_edge (FALLTHRU_EDGE (cont_bb));
9710 }
61e47ac8 9711 exit_bb = region->exit;
773c5ba7 9712
773c5ba7 9713 /* Trip and adjustment setup goes in ENTRY_BB. */
93481288 9714 gsi = gsi_last_bb (entry_bb);
9715 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
773c5ba7 9716
bc7bff74 9717 if (fd->collapse > 1)
9718 {
43895be5 9719 int first_zero_iter = -1, dummy = -1;
9720 basic_block l2_dom_bb = NULL, dummy_bb = NULL;
bc7bff74 9721
9722 counts = XALLOCAVEC (tree, fd->collapse);
93481288 9723 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
bc7bff74 9724 fin_bb, first_zero_iter,
43895be5 9725 dummy_bb, dummy, l2_dom_bb);
bc7bff74 9726 t = NULL_TREE;
9727 }
9728 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
9729 t = integer_one_node;
9730 else
9731 t = fold_binary (fd->loop.cond_code, boolean_type_node,
9732 fold_convert (type, fd->loop.n1),
9733 fold_convert (type, fd->loop.n2));
9734 if (fd->collapse == 1
9735 && TYPE_UNSIGNED (type)
8e6b4515 9736 && (t == NULL_TREE || !integer_onep (t)))
9737 {
8e6b4515 9738 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
93481288 9739 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
8e6b4515 9740 true, GSI_SAME_STMT);
9741 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
93481288 9742 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
8e6b4515 9743 true, GSI_SAME_STMT);
1a91d914 9744 gcond *cond_stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
9745 NULL_TREE, NULL_TREE);
9746 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
9747 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
8e6b4515 9748 expand_omp_regimplify_p, NULL, NULL)
1a91d914 9749 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
8e6b4515 9750 expand_omp_regimplify_p, NULL, NULL))
9751 {
1a91d914 9752 gsi = gsi_for_stmt (cond_stmt);
9753 gimple_regimplify_operands (cond_stmt, &gsi);
8e6b4515 9754 }
1a91d914 9755 se = split_block (entry_bb, cond_stmt);
8e6b4515 9756 se->flags = EDGE_TRUE_VALUE;
9757 entry_bb = se->dest;
9758 se->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
9759 se = make_edge (se->src, fin_bb, EDGE_FALSE_VALUE);
9760 se->probability = REG_BR_PROB_BASE / 2000 - 1;
9761 if (gimple_in_ssa_p (cfun))
9762 {
264aa959 9763 int dest_idx = find_edge (iter_part_bb, fin_bb)->dest_idx;
1a91d914 9764 for (gphi_iterator gpi = gsi_start_phis (fin_bb);
9765 !gsi_end_p (gpi); gsi_next (&gpi))
8e6b4515 9766 {
1a91d914 9767 gphi *phi = gpi.phi ();
8e6b4515 9768 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
9769 se, UNKNOWN_LOCATION);
9770 }
9771 }
93481288 9772 gsi = gsi_last_bb (entry_bb);
8e6b4515 9773 }
9774
ca4c3545 9775 switch (gimple_omp_for_kind (fd->for_stmt))
9776 {
9777 case GF_OMP_FOR_KIND_FOR:
9778 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
9779 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
9780 break;
9781 case GF_OMP_FOR_KIND_DISTRIBUTE:
9782 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_TEAMS);
9783 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_TEAM_NUM);
9784 break;
ca4c3545 9785 default:
9786 gcc_unreachable ();
9787 }
9788 nthreads = build_call_expr (nthreads, 0);
9789 nthreads = fold_convert (itype, nthreads);
9790 nthreads = force_gimple_operand_gsi (&gsi, nthreads, true, NULL_TREE,
75a70cf9 9791 true, GSI_SAME_STMT);
ca4c3545 9792 threadid = build_call_expr (threadid, 0);
9793 threadid = fold_convert (itype, threadid);
9794 threadid = force_gimple_operand_gsi (&gsi, threadid, true, NULL_TREE,
75a70cf9 9795 true, GSI_SAME_STMT);
79acaae1 9796
bc7bff74 9797 n1 = fd->loop.n1;
9798 n2 = fd->loop.n2;
9799 step = fd->loop.step;
9800 if (gimple_omp_for_combined_into_p (fd->for_stmt))
9801 {
9802 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
9803 OMP_CLAUSE__LOOPTEMP_);
9804 gcc_assert (innerc);
9805 n1 = OMP_CLAUSE_DECL (innerc);
9806 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9807 OMP_CLAUSE__LOOPTEMP_);
9808 gcc_assert (innerc);
9809 n2 = OMP_CLAUSE_DECL (innerc);
9810 }
93481288 9811 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
bc7bff74 9812 true, NULL_TREE, true, GSI_SAME_STMT);
93481288 9813 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
bc7bff74 9814 true, NULL_TREE, true, GSI_SAME_STMT);
93481288 9815 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
bc7bff74 9816 true, NULL_TREE, true, GSI_SAME_STMT);
43895be5 9817 tree chunk_size = fold_convert (itype, fd->chunk_size);
9818 chunk_size = omp_adjust_chunk_size (chunk_size, fd->simd_schedule);
9819 chunk_size
9820 = force_gimple_operand_gsi (&gsi, chunk_size, true, NULL_TREE, true,
9821 GSI_SAME_STMT);
fd6481cf 9822
9823 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
bc7bff74 9824 t = fold_build2 (PLUS_EXPR, itype, step, t);
9825 t = fold_build2 (PLUS_EXPR, itype, t, n2);
9826 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
fd6481cf 9827 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
9828 t = fold_build2 (TRUNC_DIV_EXPR, itype,
9829 fold_build1 (NEGATE_EXPR, itype, t),
bc7bff74 9830 fold_build1 (NEGATE_EXPR, itype, step));
fd6481cf 9831 else
bc7bff74 9832 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
fd6481cf 9833 t = fold_convert (itype, t);
93481288 9834 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
75a70cf9 9835 true, GSI_SAME_STMT);
79acaae1 9836
083152fb 9837 trip_var = create_tmp_reg (itype, ".trip");
79acaae1 9838 if (gimple_in_ssa_p (cfun))
9839 {
f9e245b2 9840 trip_init = make_ssa_name (trip_var);
9841 trip_main = make_ssa_name (trip_var);
9842 trip_back = make_ssa_name (trip_var);
79acaae1 9843 }
1e8e9920 9844 else
79acaae1 9845 {
9846 trip_init = trip_var;
9847 trip_main = trip_var;
9848 trip_back = trip_var;
9849 }
1e8e9920 9850
1a91d914 9851 gassign *assign_stmt
9852 = gimple_build_assign (trip_init, build_int_cst (itype, 0));
9853 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
773c5ba7 9854
43895be5 9855 t = fold_build2 (MULT_EXPR, itype, threadid, chunk_size);
bc7bff74 9856 t = fold_build2 (MULT_EXPR, itype, t, step);
fd6481cf 9857 if (POINTER_TYPE_P (type))
bc7bff74 9858 t = fold_build_pointer_plus (n1, t);
fd6481cf 9859 else
bc7bff74 9860 t = fold_build2 (PLUS_EXPR, type, t, n1);
93481288 9861 vextra = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9862 true, GSI_SAME_STMT);
79acaae1 9863
75a70cf9 9864 /* Remove the GIMPLE_OMP_FOR. */
93481288 9865 gsi_remove (&gsi, true);
773c5ba7 9866
43895be5 9867 gimple_stmt_iterator gsif = gsi;
9868
773c5ba7 9869 /* Iteration space partitioning goes in ITER_PART_BB. */
93481288 9870 gsi = gsi_last_bb (iter_part_bb);
1e8e9920 9871
fd6481cf 9872 t = fold_build2 (MULT_EXPR, itype, trip_main, nthreads);
9873 t = fold_build2 (PLUS_EXPR, itype, t, threadid);
43895be5 9874 t = fold_build2 (MULT_EXPR, itype, t, chunk_size);
93481288 9875 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
75a70cf9 9876 false, GSI_CONTINUE_LINKING);
1e8e9920 9877
43895be5 9878 t = fold_build2 (PLUS_EXPR, itype, s0, chunk_size);
fd6481cf 9879 t = fold_build2 (MIN_EXPR, itype, t, n);
93481288 9880 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
75a70cf9 9881 false, GSI_CONTINUE_LINKING);
1e8e9920 9882
9883 t = build2 (LT_EXPR, boolean_type_node, s0, n);
93481288 9884 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_CONTINUE_LINKING);
773c5ba7 9885
9886 /* Setup code for sequential iteration goes in SEQ_START_BB. */
93481288 9887 gsi = gsi_start_bb (seq_start_bb);
1e8e9920 9888
bc7bff74 9889 tree startvar = fd->loop.v;
9890 tree endvar = NULL_TREE;
9891
9892 if (gimple_omp_for_combined_p (fd->for_stmt))
9893 {
9894 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
9895 ? gimple_omp_parallel_clauses (inner_stmt)
9896 : gimple_omp_for_clauses (inner_stmt);
9897 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
9898 gcc_assert (innerc);
9899 startvar = OMP_CLAUSE_DECL (innerc);
9900 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9901 OMP_CLAUSE__LOOPTEMP_);
9902 gcc_assert (innerc);
9903 endvar = OMP_CLAUSE_DECL (innerc);
9561765e 9904 if (fd->collapse > 1 && TREE_CODE (fd->loop.n2) != INTEGER_CST
9905 && gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
9906 {
9907 int i;
9908 for (i = 1; i < fd->collapse; i++)
9909 {
9910 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9911 OMP_CLAUSE__LOOPTEMP_);
9912 gcc_assert (innerc);
9913 }
9914 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9915 OMP_CLAUSE__LOOPTEMP_);
9916 if (innerc)
9917 {
9918 /* If needed (distribute parallel for with lastprivate),
9919 propagate down the total number of iterations. */
9920 tree t = fold_convert (TREE_TYPE (OMP_CLAUSE_DECL (innerc)),
9921 fd->loop.n2);
9922 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, false,
9923 GSI_CONTINUE_LINKING);
9924 assign_stmt = gimple_build_assign (OMP_CLAUSE_DECL (innerc), t);
9925 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9926 }
9927 }
bc7bff74 9928 }
9929
fd6481cf 9930 t = fold_convert (itype, s0);
bc7bff74 9931 t = fold_build2 (MULT_EXPR, itype, t, step);
fd6481cf 9932 if (POINTER_TYPE_P (type))
bc7bff74 9933 t = fold_build_pointer_plus (n1, t);
fd6481cf 9934 else
bc7bff74 9935 t = fold_build2 (PLUS_EXPR, type, t, n1);
9936 t = fold_convert (TREE_TYPE (startvar), t);
93481288 9937 t = force_gimple_operand_gsi (&gsi, t,
bc7bff74 9938 DECL_P (startvar)
9939 && TREE_ADDRESSABLE (startvar),
4abecb72 9940 NULL_TREE, false, GSI_CONTINUE_LINKING);
1a91d914 9941 assign_stmt = gimple_build_assign (startvar, t);
9942 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
1e8e9920 9943
fd6481cf 9944 t = fold_convert (itype, e0);
bc7bff74 9945 t = fold_build2 (MULT_EXPR, itype, t, step);
fd6481cf 9946 if (POINTER_TYPE_P (type))
bc7bff74 9947 t = fold_build_pointer_plus (n1, t);
fd6481cf 9948 else
bc7bff74 9949 t = fold_build2 (PLUS_EXPR, type, t, n1);
9950 t = fold_convert (TREE_TYPE (startvar), t);
93481288 9951 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
75a70cf9 9952 false, GSI_CONTINUE_LINKING);
bc7bff74 9953 if (endvar)
9954 {
1a91d914 9955 assign_stmt = gimple_build_assign (endvar, e);
9956 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
d44f2f7c 9957 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
1a91d914 9958 assign_stmt = gimple_build_assign (fd->loop.v, e);
d44f2f7c 9959 else
e9cf809e 9960 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, e);
1a91d914 9961 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
bc7bff74 9962 }
43895be5 9963 /* Handle linear clause adjustments. */
9964 tree itercnt = NULL_TREE, itercntbias = NULL_TREE;
9965 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_FOR)
9966 for (tree c = gimple_omp_for_clauses (fd->for_stmt);
9967 c; c = OMP_CLAUSE_CHAIN (c))
9968 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
9969 && !OMP_CLAUSE_LINEAR_NO_COPYIN (c))
9970 {
9971 tree d = OMP_CLAUSE_DECL (c);
9972 bool is_ref = is_reference (d);
9973 tree t = d, a, dest;
9974 if (is_ref)
9975 t = build_simple_mem_ref_loc (OMP_CLAUSE_LOCATION (c), t);
9976 tree type = TREE_TYPE (t);
9977 if (POINTER_TYPE_P (type))
9978 type = sizetype;
9979 dest = unshare_expr (t);
9980 tree v = create_tmp_var (TREE_TYPE (t), NULL);
9981 expand_omp_build_assign (&gsif, v, t);
9982 if (itercnt == NULL_TREE)
9983 {
9984 if (gimple_omp_for_combined_into_p (fd->for_stmt))
9985 {
9986 itercntbias
9987 = fold_build2 (MINUS_EXPR, itype, fold_convert (itype, n1),
9988 fold_convert (itype, fd->loop.n1));
9989 itercntbias = fold_build2 (EXACT_DIV_EXPR, itype,
9990 itercntbias, step);
9991 itercntbias
9992 = force_gimple_operand_gsi (&gsif, itercntbias, true,
9993 NULL_TREE, true,
9994 GSI_SAME_STMT);
9995 itercnt = fold_build2 (PLUS_EXPR, itype, itercntbias, s0);
9996 itercnt = force_gimple_operand_gsi (&gsi, itercnt, true,
9997 NULL_TREE, false,
9998 GSI_CONTINUE_LINKING);
9999 }
10000 else
10001 itercnt = s0;
10002 }
10003 a = fold_build2 (MULT_EXPR, type,
10004 fold_convert (type, itercnt),
10005 fold_convert (type, OMP_CLAUSE_LINEAR_STEP (c)));
10006 t = fold_build2 (type == TREE_TYPE (t) ? PLUS_EXPR
10007 : POINTER_PLUS_EXPR, TREE_TYPE (t), v, a);
10008 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
10009 false, GSI_CONTINUE_LINKING);
10010 assign_stmt = gimple_build_assign (dest, t);
10011 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10012 }
bc7bff74 10013 if (fd->collapse > 1)
93481288 10014 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
bc7bff74 10015
10016 if (!broken_loop)
10017 {
10018 /* The code controlling the sequential loop goes in CONT_BB,
10019 replacing the GIMPLE_OMP_CONTINUE. */
93481288 10020 gsi = gsi_last_bb (cont_bb);
1a91d914 10021 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
10022 vmain = gimple_omp_continue_control_use (cont_stmt);
10023 vback = gimple_omp_continue_control_def (cont_stmt);
1e8e9920 10024
bc7bff74 10025 if (!gimple_omp_for_combined_p (fd->for_stmt))
10026 {
10027 if (POINTER_TYPE_P (type))
93481288 10028 t = fold_build_pointer_plus (vmain, step);
bc7bff74 10029 else
93481288 10030 t = fold_build2 (PLUS_EXPR, type, vmain, step);
10031 if (DECL_P (vback) && TREE_ADDRESSABLE (vback))
10032 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
bc7bff74 10033 true, GSI_SAME_STMT);
1a91d914 10034 assign_stmt = gimple_build_assign (vback, t);
10035 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
79acaae1 10036
345f9789 10037 if (tree_int_cst_equal (fd->chunk_size, integer_one_node))
10038 t = build2 (EQ_EXPR, boolean_type_node,
10039 build_int_cst (itype, 0),
10040 build_int_cst (itype, 1));
10041 else
10042 t = build2 (fd->loop.cond_code, boolean_type_node,
10043 DECL_P (vback) && TREE_ADDRESSABLE (vback)
10044 ? t : vback, e);
93481288 10045 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
bc7bff74 10046 }
79acaae1 10047
bc7bff74 10048 /* Remove GIMPLE_OMP_CONTINUE. */
93481288 10049 gsi_remove (&gsi, true);
48e1416a 10050
bc7bff74 10051 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
10052 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
773c5ba7 10053
bc7bff74 10054 /* Trip update code goes into TRIP_UPDATE_BB. */
93481288 10055 gsi = gsi_start_bb (trip_update_bb);
1e8e9920 10056
bc7bff74 10057 t = build_int_cst (itype, 1);
10058 t = build2 (PLUS_EXPR, itype, trip_main, t);
1a91d914 10059 assign_stmt = gimple_build_assign (trip_back, t);
10060 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
bc7bff74 10061 }
1e8e9920 10062
75a70cf9 10063 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
93481288 10064 gsi = gsi_last_bb (exit_bb);
10065 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
bc7bff74 10066 {
93481288 10067 t = gimple_omp_return_lhs (gsi_stmt (gsi));
a8e785ba 10068 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
bc7bff74 10069 }
93481288 10070 gsi_remove (&gsi, true);
1e8e9920 10071
773c5ba7 10072 /* Connect the new blocks. */
ac6e3339 10073 find_edge (iter_part_bb, seq_start_bb)->flags = EDGE_TRUE_VALUE;
10074 find_edge (iter_part_bb, fin_bb)->flags = EDGE_FALSE_VALUE;
79acaae1 10075
bc7bff74 10076 if (!broken_loop)
10077 {
10078 se = find_edge (cont_bb, body_bb);
fc1d58e3 10079 if (se == NULL)
10080 {
10081 se = BRANCH_EDGE (cont_bb);
10082 gcc_assert (single_succ (se->dest) == body_bb);
10083 }
bc7bff74 10084 if (gimple_omp_for_combined_p (fd->for_stmt))
10085 {
10086 remove_edge (se);
10087 se = NULL;
10088 }
10089 else if (fd->collapse > 1)
10090 {
10091 remove_edge (se);
10092 se = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
10093 }
10094 else
10095 se->flags = EDGE_TRUE_VALUE;
10096 find_edge (cont_bb, trip_update_bb)->flags
10097 = se ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
79acaae1 10098
bc7bff74 10099 redirect_edge_and_branch (single_succ_edge (trip_update_bb), iter_part_bb);
10100 }
79acaae1 10101
10102 if (gimple_in_ssa_p (cfun))
10103 {
1a91d914 10104 gphi_iterator psi;
10105 gphi *phi;
75a70cf9 10106 edge re, ene;
75a70cf9 10107 edge_var_map *vm;
10108 size_t i;
10109
bc7bff74 10110 gcc_assert (fd->collapse == 1 && !broken_loop);
10111
79acaae1 10112 /* When we redirect the edge from trip_update_bb to iter_part_bb, we
10113 remove arguments of the phi nodes in fin_bb. We need to create
10114 appropriate phi nodes in iter_part_bb instead. */
264aa959 10115 se = find_edge (iter_part_bb, fin_bb);
79acaae1 10116 re = single_succ_edge (trip_update_bb);
06ecf488 10117 vec<edge_var_map> *head = redirect_edge_var_map_vector (re);
79acaae1 10118 ene = single_succ_edge (entry_bb);
10119
75a70cf9 10120 psi = gsi_start_phis (fin_bb);
f1f41a6c 10121 for (i = 0; !gsi_end_p (psi) && head->iterate (i, &vm);
75a70cf9 10122 gsi_next (&psi), ++i)
79acaae1 10123 {
1a91d914 10124 gphi *nphi;
efbcb6de 10125 source_location locus;
75a70cf9 10126
1a91d914 10127 phi = psi.phi ();
75a70cf9 10128 t = gimple_phi_result (phi);
10129 gcc_assert (t == redirect_edge_var_map_result (vm));
264aa959 10130
10131 if (!single_pred_p (fin_bb))
10132 t = copy_ssa_name (t, phi);
10133
79acaae1 10134 nphi = create_phi_node (t, iter_part_bb);
79acaae1 10135
10136 t = PHI_ARG_DEF_FROM_EDGE (phi, se);
efbcb6de 10137 locus = gimple_phi_arg_location_from_edge (phi, se);
10138
fd6481cf 10139 /* A special case -- fd->loop.v is not yet computed in
93481288 10140 iter_part_bb, we need to use vextra instead. */
fd6481cf 10141 if (t == fd->loop.v)
93481288 10142 t = vextra;
60d535d2 10143 add_phi_arg (nphi, t, ene, locus);
efbcb6de 10144 locus = redirect_edge_var_map_location (vm);
281001a9 10145 tree back_arg = redirect_edge_var_map_def (vm);
10146 add_phi_arg (nphi, back_arg, re, locus);
10147 edge ce = find_edge (cont_bb, body_bb);
10148 if (ce == NULL)
10149 {
10150 ce = BRANCH_EDGE (cont_bb);
10151 gcc_assert (single_succ (ce->dest) == body_bb);
10152 ce = single_succ_edge (ce->dest);
10153 }
10154 gphi *inner_loop_phi = find_phi_with_arg_on_edge (back_arg, ce);
10155 gcc_assert (inner_loop_phi != NULL);
10156 add_phi_arg (inner_loop_phi, gimple_phi_result (nphi),
10157 find_edge (seq_start_bb, body_bb), locus);
264aa959 10158
10159 if (!single_pred_p (fin_bb))
10160 add_phi_arg (phi, gimple_phi_result (nphi), se, locus);
75a70cf9 10161 }
4d556e29 10162 gcc_assert (gsi_end_p (psi) && (head == NULL || i == head->length ()));
75a70cf9 10163 redirect_edge_var_map_clear (re);
264aa959 10164 if (single_pred_p (fin_bb))
10165 while (1)
10166 {
10167 psi = gsi_start_phis (fin_bb);
10168 if (gsi_end_p (psi))
10169 break;
10170 remove_phi_node (&psi, false);
10171 }
79acaae1 10172
10173 /* Make phi node for trip. */
10174 phi = create_phi_node (trip_main, iter_part_bb);
efbcb6de 10175 add_phi_arg (phi, trip_back, single_succ_edge (trip_update_bb),
60d535d2 10176 UNKNOWN_LOCATION);
efbcb6de 10177 add_phi_arg (phi, trip_init, single_succ_edge (entry_bb),
60d535d2 10178 UNKNOWN_LOCATION);
79acaae1 10179 }
10180
bc7bff74 10181 if (!broken_loop)
10182 set_immediate_dominator (CDI_DOMINATORS, trip_update_bb, cont_bb);
79acaae1 10183 set_immediate_dominator (CDI_DOMINATORS, iter_part_bb,
10184 recompute_dominator (CDI_DOMINATORS, iter_part_bb));
10185 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
10186 recompute_dominator (CDI_DOMINATORS, fin_bb));
10187 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb,
10188 recompute_dominator (CDI_DOMINATORS, seq_start_bb));
10189 set_immediate_dominator (CDI_DOMINATORS, body_bb,
10190 recompute_dominator (CDI_DOMINATORS, body_bb));
04c2922b 10191
bc7bff74 10192 if (!broken_loop)
10193 {
fc1d58e3 10194 struct loop *loop = body_bb->loop_father;
bc7bff74 10195 struct loop *trip_loop = alloc_loop ();
10196 trip_loop->header = iter_part_bb;
10197 trip_loop->latch = trip_update_bb;
10198 add_loop (trip_loop, iter_part_bb->loop_father);
04c2922b 10199
fc1d58e3 10200 if (loop != entry_bb->loop_father)
10201 {
10202 gcc_assert (loop->header == body_bb);
10203 gcc_assert (loop->latch == region->cont
10204 || single_pred (loop->latch) == region->cont);
10205 trip_loop->inner = loop;
10206 return;
10207 }
10208
bc7bff74 10209 if (!gimple_omp_for_combined_p (fd->for_stmt))
10210 {
fc1d58e3 10211 loop = alloc_loop ();
bc7bff74 10212 loop->header = body_bb;
33ee4d72 10213 if (collapse_bb == NULL)
10214 loop->latch = cont_bb;
bc7bff74 10215 add_loop (loop, trip_loop);
10216 }
10217 }
1e8e9920 10218}
10219
40750995 10220/* A subroutine of expand_omp_for. Generate code for _Cilk_for loop.
10221 Given parameters:
10222 for (V = N1; V cond N2; V += STEP) BODY;
10223
10224 where COND is "<" or ">" or "!=", we generate pseudocode
10225
10226 for (ind_var = low; ind_var < high; ind_var++)
10227 {
10228 V = n1 + (ind_var * STEP)
10229
10230 <BODY>
10231 }
10232
10233 In the above pseudocode, low and high are function parameters of the
10234 child function. In the function below, we are inserting a temp.
10235 variable that will be making a call to two OMP functions that will not be
10236 found in the body of _Cilk_for (since OMP_FOR cannot be mixed
10237 with _Cilk_for). These functions are replaced with low and high
10238 by the function that handles taskreg. */
10239
10240
10241static void
10242expand_cilk_for (struct omp_region *region, struct omp_for_data *fd)
10243{
10244 bool broken_loop = region->cont == NULL;
10245 basic_block entry_bb = region->entry;
10246 basic_block cont_bb = region->cont;
10247
10248 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
10249 gcc_assert (broken_loop
10250 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
10251 basic_block l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
10252 basic_block l1_bb, l2_bb;
10253
10254 if (!broken_loop)
10255 {
10256 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
10257 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
10258 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
10259 l2_bb = BRANCH_EDGE (entry_bb)->dest;
10260 }
10261 else
10262 {
10263 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
10264 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
10265 l2_bb = single_succ (l1_bb);
10266 }
10267 basic_block exit_bb = region->exit;
10268 basic_block l2_dom_bb = NULL;
10269
10270 gimple_stmt_iterator gsi = gsi_last_bb (entry_bb);
10271
10272 /* Below statements until the "tree high_val = ..." are pseudo statements
10273 used to pass information to be used by expand_omp_taskreg.
10274 low_val and high_val will be replaced by the __low and __high
10275 parameter from the child function.
10276
10277 The call_exprs part is a place-holder, it is mainly used
10278 to distinctly identify to the top-level part that this is
10279 where we should put low and high (reasoning given in header
10280 comment). */
10281
10282 tree child_fndecl
1a91d914 10283 = gimple_omp_parallel_child_fn (
10284 as_a <gomp_parallel *> (last_stmt (region->outer->entry)));
40750995 10285 tree t, low_val = NULL_TREE, high_val = NULL_TREE;
10286 for (t = DECL_ARGUMENTS (child_fndecl); t; t = TREE_CHAIN (t))
10287 {
10288 if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__high"))
10289 high_val = t;
10290 else if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__low"))
10291 low_val = t;
10292 }
10293 gcc_assert (low_val && high_val);
10294
10295 tree type = TREE_TYPE (low_val);
10296 tree ind_var = create_tmp_reg (type, "__cilk_ind_var");
10297 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
10298
10299 /* Not needed in SSA form right now. */
10300 gcc_assert (!gimple_in_ssa_p (cfun));
10301 if (l2_dom_bb == NULL)
10302 l2_dom_bb = l1_bb;
10303
10304 tree n1 = low_val;
10305 tree n2 = high_val;
10306
42acab1c 10307 gimple *stmt = gimple_build_assign (ind_var, n1);
40750995 10308
10309 /* Replace the GIMPLE_OMP_FOR statement. */
10310 gsi_replace (&gsi, stmt, true);
10311
10312 if (!broken_loop)
10313 {
10314 /* Code to control the increment goes in the CONT_BB. */
10315 gsi = gsi_last_bb (cont_bb);
10316 stmt = gsi_stmt (gsi);
10317 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
e9cf809e 10318 stmt = gimple_build_assign (ind_var, PLUS_EXPR, ind_var,
10319 build_one_cst (type));
40750995 10320
10321 /* Replace GIMPLE_OMP_CONTINUE. */
10322 gsi_replace (&gsi, stmt, true);
10323 }
10324
10325 /* Emit the condition in L1_BB. */
10326 gsi = gsi_after_labels (l1_bb);
10327 t = fold_build2 (MULT_EXPR, TREE_TYPE (fd->loop.step),
10328 fold_convert (TREE_TYPE (fd->loop.step), ind_var),
10329 fd->loop.step);
10330 if (POINTER_TYPE_P (TREE_TYPE (fd->loop.n1)))
10331 t = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (fd->loop.n1),
10332 fd->loop.n1, fold_convert (sizetype, t));
10333 else
10334 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loop.n1),
10335 fd->loop.n1, fold_convert (TREE_TYPE (fd->loop.n1), t));
10336 t = fold_convert (TREE_TYPE (fd->loop.v), t);
10337 expand_omp_build_assign (&gsi, fd->loop.v, t);
10338
10339 /* The condition is always '<' since the runtime will fill in the low
10340 and high values. */
10341 stmt = gimple_build_cond (LT_EXPR, ind_var, n2, NULL_TREE, NULL_TREE);
10342 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
10343
10344 /* Remove GIMPLE_OMP_RETURN. */
10345 gsi = gsi_last_bb (exit_bb);
10346 gsi_remove (&gsi, true);
10347
10348 /* Connect the new blocks. */
10349 remove_edge (FALLTHRU_EDGE (entry_bb));
10350
10351 edge e, ne;
10352 if (!broken_loop)
10353 {
10354 remove_edge (BRANCH_EDGE (entry_bb));
10355 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
10356
10357 e = BRANCH_EDGE (l1_bb);
10358 ne = FALLTHRU_EDGE (l1_bb);
10359 e->flags = EDGE_TRUE_VALUE;
10360 }
10361 else
10362 {
10363 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
10364
10365 ne = single_succ_edge (l1_bb);
10366 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
10367
10368 }
10369 ne->flags = EDGE_FALSE_VALUE;
10370 e->probability = REG_BR_PROB_BASE * 7 / 8;
10371 ne->probability = REG_BR_PROB_BASE / 8;
10372
10373 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
10374 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
10375 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
10376
10377 if (!broken_loop)
10378 {
10379 struct loop *loop = alloc_loop ();
10380 loop->header = l1_bb;
10381 loop->latch = cont_bb;
10382 add_loop (loop, l1_bb->loop_father);
10383 loop->safelen = INT_MAX;
10384 }
10385
10386 /* Pick the correct library function based on the precision of the
10387 induction variable type. */
10388 tree lib_fun = NULL_TREE;
10389 if (TYPE_PRECISION (type) == 32)
10390 lib_fun = cilk_for_32_fndecl;
10391 else if (TYPE_PRECISION (type) == 64)
10392 lib_fun = cilk_for_64_fndecl;
10393 else
10394 gcc_unreachable ();
10395
10396 gcc_assert (fd->sched_kind == OMP_CLAUSE_SCHEDULE_CILKFOR);
10397
10398 /* WS_ARGS contains the library function flavor to call:
10399 __libcilkrts_cilk_for_64 or __libcilkrts_cilk_for_32), and the
10400 user-defined grain value. If the user does not define one, then zero
10401 is passed in by the parser. */
10402 vec_alloc (region->ws_args, 2);
10403 region->ws_args->quick_push (lib_fun);
10404 region->ws_args->quick_push (fd->chunk_size);
10405}
bc7bff74 10406
3d483a94 10407/* A subroutine of expand_omp_for. Generate code for a simd non-worksharing
10408 loop. Given parameters:
10409
10410 for (V = N1; V cond N2; V += STEP) BODY;
10411
10412 where COND is "<" or ">", we generate pseudocode
10413
10414 V = N1;
10415 goto L1;
10416 L0:
10417 BODY;
10418 V += STEP;
10419 L1:
10420 if (V cond N2) goto L0; else goto L2;
10421 L2:
10422
10423 For collapsed loops, given parameters:
10424 collapse(3)
10425 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
10426 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
10427 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
10428 BODY;
10429
10430 we generate pseudocode
10431
10432 if (cond3 is <)
10433 adj = STEP3 - 1;
10434 else
10435 adj = STEP3 + 1;
10436 count3 = (adj + N32 - N31) / STEP3;
10437 if (cond2 is <)
10438 adj = STEP2 - 1;
10439 else
10440 adj = STEP2 + 1;
10441 count2 = (adj + N22 - N21) / STEP2;
10442 if (cond1 is <)
10443 adj = STEP1 - 1;
10444 else
10445 adj = STEP1 + 1;
10446 count1 = (adj + N12 - N11) / STEP1;
10447 count = count1 * count2 * count3;
10448 V = 0;
10449 V1 = N11;
10450 V2 = N21;
10451 V3 = N31;
10452 goto L1;
10453 L0:
10454 BODY;
10455 V += 1;
10456 V3 += STEP3;
10457 V2 += (V3 cond3 N32) ? 0 : STEP2;
10458 V3 = (V3 cond3 N32) ? V3 : N31;
10459 V1 += (V2 cond2 N22) ? 0 : STEP1;
10460 V2 = (V2 cond2 N22) ? V2 : N21;
10461 L1:
10462 if (V < count) goto L0; else goto L2;
10463 L2:
10464
10465 */
10466
10467static void
10468expand_omp_simd (struct omp_region *region, struct omp_for_data *fd)
10469{
10470 tree type, t;
10471 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, l2_bb, l2_dom_bb;
10472 gimple_stmt_iterator gsi;
42acab1c 10473 gimple *stmt;
1a91d914 10474 gcond *cond_stmt;
3d483a94 10475 bool broken_loop = region->cont == NULL;
10476 edge e, ne;
10477 tree *counts = NULL;
10478 int i;
10479 tree safelen = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
10480 OMP_CLAUSE_SAFELEN);
10481 tree simduid = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
10482 OMP_CLAUSE__SIMDUID_);
bc7bff74 10483 tree n1, n2;
3d483a94 10484
10485 type = TREE_TYPE (fd->loop.v);
10486 entry_bb = region->entry;
10487 cont_bb = region->cont;
10488 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
10489 gcc_assert (broken_loop
10490 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
10491 l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
10492 if (!broken_loop)
10493 {
10494 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
10495 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
10496 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
10497 l2_bb = BRANCH_EDGE (entry_bb)->dest;
10498 }
10499 else
10500 {
10501 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
10502 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
10503 l2_bb = single_succ (l1_bb);
10504 }
10505 exit_bb = region->exit;
10506 l2_dom_bb = NULL;
10507
10508 gsi = gsi_last_bb (entry_bb);
10509
10510 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
10511 /* Not needed in SSA form right now. */
10512 gcc_assert (!gimple_in_ssa_p (cfun));
10513 if (fd->collapse > 1)
10514 {
43895be5 10515 int first_zero_iter = -1, dummy = -1;
10516 basic_block zero_iter_bb = l2_bb, dummy_bb = NULL;
3d483a94 10517
10518 counts = XALLOCAVEC (tree, fd->collapse);
10519 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
10520 zero_iter_bb, first_zero_iter,
43895be5 10521 dummy_bb, dummy, l2_dom_bb);
3d483a94 10522 }
10523 if (l2_dom_bb == NULL)
10524 l2_dom_bb = l1_bb;
10525
bc7bff74 10526 n1 = fd->loop.n1;
3d483a94 10527 n2 = fd->loop.n2;
bc7bff74 10528 if (gimple_omp_for_combined_into_p (fd->for_stmt))
10529 {
10530 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
10531 OMP_CLAUSE__LOOPTEMP_);
10532 gcc_assert (innerc);
10533 n1 = OMP_CLAUSE_DECL (innerc);
10534 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
10535 OMP_CLAUSE__LOOPTEMP_);
10536 gcc_assert (innerc);
10537 n2 = OMP_CLAUSE_DECL (innerc);
10538 expand_omp_build_assign (&gsi, fd->loop.v,
10539 fold_convert (type, n1));
10540 if (fd->collapse > 1)
10541 {
10542 gsi_prev (&gsi);
10543 expand_omp_for_init_vars (fd, &gsi, counts, NULL, n1);
10544 gsi_next (&gsi);
10545 }
10546 }
3d483a94 10547 else
10548 {
10549 expand_omp_build_assign (&gsi, fd->loop.v,
10550 fold_convert (type, fd->loop.n1));
10551 if (fd->collapse > 1)
10552 for (i = 0; i < fd->collapse; i++)
10553 {
10554 tree itype = TREE_TYPE (fd->loops[i].v);
10555 if (POINTER_TYPE_P (itype))
10556 itype = signed_type_for (itype);
10557 t = fold_convert (TREE_TYPE (fd->loops[i].v), fd->loops[i].n1);
10558 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
10559 }
10560 }
10561
10562 /* Remove the GIMPLE_OMP_FOR statement. */
10563 gsi_remove (&gsi, true);
10564
10565 if (!broken_loop)
10566 {
10567 /* Code to control the increment goes in the CONT_BB. */
10568 gsi = gsi_last_bb (cont_bb);
10569 stmt = gsi_stmt (gsi);
10570 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
10571
10572 if (POINTER_TYPE_P (type))
10573 t = fold_build_pointer_plus (fd->loop.v, fd->loop.step);
10574 else
10575 t = fold_build2 (PLUS_EXPR, type, fd->loop.v, fd->loop.step);
10576 expand_omp_build_assign (&gsi, fd->loop.v, t);
10577
10578 if (fd->collapse > 1)
10579 {
10580 i = fd->collapse - 1;
10581 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v)))
10582 {
10583 t = fold_convert (sizetype, fd->loops[i].step);
10584 t = fold_build_pointer_plus (fd->loops[i].v, t);
10585 }
10586 else
10587 {
10588 t = fold_convert (TREE_TYPE (fd->loops[i].v),
10589 fd->loops[i].step);
10590 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loops[i].v),
10591 fd->loops[i].v, t);
10592 }
10593 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
10594
10595 for (i = fd->collapse - 1; i > 0; i--)
10596 {
10597 tree itype = TREE_TYPE (fd->loops[i].v);
10598 tree itype2 = TREE_TYPE (fd->loops[i - 1].v);
10599 if (POINTER_TYPE_P (itype2))
10600 itype2 = signed_type_for (itype2);
10601 t = build3 (COND_EXPR, itype2,
10602 build2 (fd->loops[i].cond_code, boolean_type_node,
10603 fd->loops[i].v,
10604 fold_convert (itype, fd->loops[i].n2)),
10605 build_int_cst (itype2, 0),
10606 fold_convert (itype2, fd->loops[i - 1].step));
10607 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i - 1].v)))
10608 t = fold_build_pointer_plus (fd->loops[i - 1].v, t);
10609 else
10610 t = fold_build2 (PLUS_EXPR, itype2, fd->loops[i - 1].v, t);
10611 expand_omp_build_assign (&gsi, fd->loops[i - 1].v, t);
10612
10613 t = build3 (COND_EXPR, itype,
10614 build2 (fd->loops[i].cond_code, boolean_type_node,
10615 fd->loops[i].v,
10616 fold_convert (itype, fd->loops[i].n2)),
10617 fd->loops[i].v,
10618 fold_convert (itype, fd->loops[i].n1));
10619 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
10620 }
10621 }
10622
10623 /* Remove GIMPLE_OMP_CONTINUE. */
10624 gsi_remove (&gsi, true);
10625 }
10626
10627 /* Emit the condition in L1_BB. */
10628 gsi = gsi_start_bb (l1_bb);
10629
10630 t = fold_convert (type, n2);
10631 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
10632 false, GSI_CONTINUE_LINKING);
43895be5 10633 tree v = fd->loop.v;
10634 if (DECL_P (v) && TREE_ADDRESSABLE (v))
10635 v = force_gimple_operand_gsi (&gsi, v, true, NULL_TREE,
10636 false, GSI_CONTINUE_LINKING);
10637 t = build2 (fd->loop.cond_code, boolean_type_node, v, t);
1a91d914 10638 cond_stmt = gimple_build_cond_empty (t);
10639 gsi_insert_after (&gsi, cond_stmt, GSI_CONTINUE_LINKING);
10640 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt), expand_omp_regimplify_p,
3d483a94 10641 NULL, NULL)
1a91d914 10642 || walk_tree (gimple_cond_rhs_ptr (cond_stmt), expand_omp_regimplify_p,
3d483a94 10643 NULL, NULL))
10644 {
1a91d914 10645 gsi = gsi_for_stmt (cond_stmt);
10646 gimple_regimplify_operands (cond_stmt, &gsi);
3d483a94 10647 }
10648
10649 /* Remove GIMPLE_OMP_RETURN. */
10650 gsi = gsi_last_bb (exit_bb);
10651 gsi_remove (&gsi, true);
10652
10653 /* Connect the new blocks. */
10654 remove_edge (FALLTHRU_EDGE (entry_bb));
10655
10656 if (!broken_loop)
10657 {
10658 remove_edge (BRANCH_EDGE (entry_bb));
10659 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
10660
10661 e = BRANCH_EDGE (l1_bb);
10662 ne = FALLTHRU_EDGE (l1_bb);
10663 e->flags = EDGE_TRUE_VALUE;
10664 }
10665 else
10666 {
10667 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
10668
10669 ne = single_succ_edge (l1_bb);
10670 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
10671
10672 }
10673 ne->flags = EDGE_FALSE_VALUE;
10674 e->probability = REG_BR_PROB_BASE * 7 / 8;
10675 ne->probability = REG_BR_PROB_BASE / 8;
10676
10677 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
10678 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
10679 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
10680
10681 if (!broken_loop)
10682 {
10683 struct loop *loop = alloc_loop ();
10684 loop->header = l1_bb;
33ee4d72 10685 loop->latch = cont_bb;
3d483a94 10686 add_loop (loop, l1_bb->loop_father);
10687 if (safelen == NULL_TREE)
10688 loop->safelen = INT_MAX;
10689 else
10690 {
10691 safelen = OMP_CLAUSE_SAFELEN_EXPR (safelen);
c3f3b68d 10692 if (TREE_CODE (safelen) != INTEGER_CST)
10693 loop->safelen = 0;
10694 else if (!tree_fits_uhwi_p (safelen)
10695 || tree_to_uhwi (safelen) > INT_MAX)
3d483a94 10696 loop->safelen = INT_MAX;
10697 else
d85a2013 10698 loop->safelen = tree_to_uhwi (safelen);
3d483a94 10699 if (loop->safelen == 1)
10700 loop->safelen = 0;
10701 }
10702 if (simduid)
10703 {
43895be5 10704 loop->simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
10705 cfun->has_simduid_loops = true;
10706 }
10707 /* If not -fno-tree-loop-vectorize, hint that we want to vectorize
10708 the loop. */
10709 if ((flag_tree_loop_vectorize
10710 || (!global_options_set.x_flag_tree_loop_vectorize
10711 && !global_options_set.x_flag_tree_vectorize))
10712 && flag_tree_loop_optimize
10713 && loop->safelen > 1)
10714 {
10715 loop->force_vectorize = true;
10716 cfun->has_force_vectorize_loops = true;
10717 }
10718 }
10719 else if (simduid)
10720 cfun->has_simduid_loops = true;
10721}
10722
10723/* Taskloop construct is represented after gimplification with
10724 two GIMPLE_OMP_FOR constructs with GIMPLE_OMP_TASK sandwiched
10725 in between them. This routine expands the outer GIMPLE_OMP_FOR,
10726 which should just compute all the needed loop temporaries
10727 for GIMPLE_OMP_TASK. */
10728
10729static void
10730expand_omp_taskloop_for_outer (struct omp_region *region,
10731 struct omp_for_data *fd,
10732 gimple *inner_stmt)
10733{
10734 tree type, bias = NULL_TREE;
10735 basic_block entry_bb, cont_bb, exit_bb;
10736 gimple_stmt_iterator gsi;
10737 gassign *assign_stmt;
10738 tree *counts = NULL;
10739 int i;
10740
10741 gcc_assert (inner_stmt);
10742 gcc_assert (region->cont);
10743 gcc_assert (gimple_code (inner_stmt) == GIMPLE_OMP_TASK
10744 && gimple_omp_task_taskloop_p (inner_stmt));
10745 type = TREE_TYPE (fd->loop.v);
10746
10747 /* See if we need to bias by LLONG_MIN. */
10748 if (fd->iter_type == long_long_unsigned_type_node
10749 && TREE_CODE (type) == INTEGER_TYPE
10750 && !TYPE_UNSIGNED (type))
10751 {
10752 tree n1, n2;
10753
10754 if (fd->loop.cond_code == LT_EXPR)
10755 {
10756 n1 = fd->loop.n1;
10757 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
10758 }
10759 else
10760 {
10761 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
10762 n2 = fd->loop.n1;
10763 }
10764 if (TREE_CODE (n1) != INTEGER_CST
10765 || TREE_CODE (n2) != INTEGER_CST
10766 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
10767 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
10768 }
10769
10770 entry_bb = region->entry;
10771 cont_bb = region->cont;
10772 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
10773 gcc_assert (BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
10774 exit_bb = region->exit;
10775
10776 gsi = gsi_last_bb (entry_bb);
10777 gimple *for_stmt = gsi_stmt (gsi);
10778 gcc_assert (gimple_code (for_stmt) == GIMPLE_OMP_FOR);
10779 if (fd->collapse > 1)
10780 {
10781 int first_zero_iter = -1, dummy = -1;
10782 basic_block zero_iter_bb = NULL, dummy_bb = NULL, l2_dom_bb = NULL;
10783
10784 counts = XALLOCAVEC (tree, fd->collapse);
10785 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
10786 zero_iter_bb, first_zero_iter,
10787 dummy_bb, dummy, l2_dom_bb);
10788
10789 if (zero_iter_bb)
10790 {
10791 /* Some counts[i] vars might be uninitialized if
10792 some loop has zero iterations. But the body shouldn't
10793 be executed in that case, so just avoid uninit warnings. */
10794 for (i = first_zero_iter; i < fd->collapse; i++)
10795 if (SSA_VAR_P (counts[i]))
10796 TREE_NO_WARNING (counts[i]) = 1;
10797 gsi_prev (&gsi);
10798 edge e = split_block (entry_bb, gsi_stmt (gsi));
10799 entry_bb = e->dest;
10800 make_edge (zero_iter_bb, entry_bb, EDGE_FALLTHRU);
10801 gsi = gsi_last_bb (entry_bb);
10802 set_immediate_dominator (CDI_DOMINATORS, entry_bb,
10803 get_immediate_dominator (CDI_DOMINATORS,
10804 zero_iter_bb));
10805 }
10806 }
10807
10808 tree t0, t1;
10809 t1 = fd->loop.n2;
10810 t0 = fd->loop.n1;
10811 if (POINTER_TYPE_P (TREE_TYPE (t0))
10812 && TYPE_PRECISION (TREE_TYPE (t0))
10813 != TYPE_PRECISION (fd->iter_type))
10814 {
10815 /* Avoid casting pointers to integer of a different size. */
10816 tree itype = signed_type_for (type);
10817 t1 = fold_convert (fd->iter_type, fold_convert (itype, t1));
10818 t0 = fold_convert (fd->iter_type, fold_convert (itype, t0));
10819 }
10820 else
10821 {
10822 t1 = fold_convert (fd->iter_type, t1);
10823 t0 = fold_convert (fd->iter_type, t0);
10824 }
10825 if (bias)
10826 {
10827 t1 = fold_build2 (PLUS_EXPR, fd->iter_type, t1, bias);
10828 t0 = fold_build2 (PLUS_EXPR, fd->iter_type, t0, bias);
10829 }
10830
10831 tree innerc = find_omp_clause (gimple_omp_task_clauses (inner_stmt),
10832 OMP_CLAUSE__LOOPTEMP_);
10833 gcc_assert (innerc);
10834 tree startvar = OMP_CLAUSE_DECL (innerc);
10835 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc), OMP_CLAUSE__LOOPTEMP_);
10836 gcc_assert (innerc);
10837 tree endvar = OMP_CLAUSE_DECL (innerc);
10838 if (fd->collapse > 1 && TREE_CODE (fd->loop.n2) != INTEGER_CST)
10839 {
10840 gcc_assert (innerc);
10841 for (i = 1; i < fd->collapse; i++)
10842 {
10843 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
10844 OMP_CLAUSE__LOOPTEMP_);
10845 gcc_assert (innerc);
10846 }
10847 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
10848 OMP_CLAUSE__LOOPTEMP_);
10849 if (innerc)
10850 {
10851 /* If needed (inner taskloop has lastprivate clause), propagate
10852 down the total number of iterations. */
10853 tree t = force_gimple_operand_gsi (&gsi, fd->loop.n2, false,
10854 NULL_TREE, false,
10855 GSI_CONTINUE_LINKING);
10856 assign_stmt = gimple_build_assign (OMP_CLAUSE_DECL (innerc), t);
10857 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10858 }
10859 }
10860
10861 t0 = force_gimple_operand_gsi (&gsi, t0, false, NULL_TREE, false,
10862 GSI_CONTINUE_LINKING);
10863 assign_stmt = gimple_build_assign (startvar, t0);
10864 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10865
10866 t1 = force_gimple_operand_gsi (&gsi, t1, false, NULL_TREE, false,
10867 GSI_CONTINUE_LINKING);
10868 assign_stmt = gimple_build_assign (endvar, t1);
10869 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10870 if (fd->collapse > 1)
10871 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
10872
10873 /* Remove the GIMPLE_OMP_FOR statement. */
10874 gsi = gsi_for_stmt (for_stmt);
10875 gsi_remove (&gsi, true);
10876
10877 gsi = gsi_last_bb (cont_bb);
10878 gsi_remove (&gsi, true);
10879
10880 gsi = gsi_last_bb (exit_bb);
10881 gsi_remove (&gsi, true);
10882
10883 FALLTHRU_EDGE (entry_bb)->probability = REG_BR_PROB_BASE;
10884 remove_edge (BRANCH_EDGE (entry_bb));
10885 FALLTHRU_EDGE (cont_bb)->probability = REG_BR_PROB_BASE;
10886 remove_edge (BRANCH_EDGE (cont_bb));
10887 set_immediate_dominator (CDI_DOMINATORS, exit_bb, cont_bb);
10888 set_immediate_dominator (CDI_DOMINATORS, region->entry,
10889 recompute_dominator (CDI_DOMINATORS, region->entry));
10890}
10891
10892/* Taskloop construct is represented after gimplification with
10893 two GIMPLE_OMP_FOR constructs with GIMPLE_OMP_TASK sandwiched
10894 in between them. This routine expands the inner GIMPLE_OMP_FOR.
10895 GOMP_taskloop{,_ull} function arranges for each task to be given just
10896 a single range of iterations. */
10897
10898static void
10899expand_omp_taskloop_for_inner (struct omp_region *region,
10900 struct omp_for_data *fd,
10901 gimple *inner_stmt)
10902{
10903 tree e, t, type, itype, vmain, vback, bias = NULL_TREE;
10904 basic_block entry_bb, exit_bb, body_bb, cont_bb, collapse_bb = NULL;
10905 basic_block fin_bb;
10906 gimple_stmt_iterator gsi;
10907 edge ep;
10908 bool broken_loop = region->cont == NULL;
10909 tree *counts = NULL;
10910 tree n1, n2, step;
10911
10912 itype = type = TREE_TYPE (fd->loop.v);
10913 if (POINTER_TYPE_P (type))
10914 itype = signed_type_for (type);
10915
10916 /* See if we need to bias by LLONG_MIN. */
10917 if (fd->iter_type == long_long_unsigned_type_node
10918 && TREE_CODE (type) == INTEGER_TYPE
10919 && !TYPE_UNSIGNED (type))
10920 {
10921 tree n1, n2;
10922
10923 if (fd->loop.cond_code == LT_EXPR)
10924 {
10925 n1 = fd->loop.n1;
10926 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
10927 }
10928 else
10929 {
10930 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
10931 n2 = fd->loop.n1;
10932 }
10933 if (TREE_CODE (n1) != INTEGER_CST
10934 || TREE_CODE (n2) != INTEGER_CST
10935 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
10936 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
10937 }
10938
10939 entry_bb = region->entry;
10940 cont_bb = region->cont;
10941 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
10942 fin_bb = BRANCH_EDGE (entry_bb)->dest;
10943 gcc_assert (broken_loop
10944 || (fin_bb == FALLTHRU_EDGE (cont_bb)->dest));
10945 body_bb = FALLTHRU_EDGE (entry_bb)->dest;
10946 if (!broken_loop)
10947 {
10948 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
10949 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
10950 }
10951 exit_bb = region->exit;
10952
10953 /* Iteration space partitioning goes in ENTRY_BB. */
10954 gsi = gsi_last_bb (entry_bb);
10955 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
10956
10957 if (fd->collapse > 1)
10958 {
10959 int first_zero_iter = -1, dummy = -1;
10960 basic_block l2_dom_bb = NULL, dummy_bb = NULL;
10961
10962 counts = XALLOCAVEC (tree, fd->collapse);
10963 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
10964 fin_bb, first_zero_iter,
10965 dummy_bb, dummy, l2_dom_bb);
10966 t = NULL_TREE;
10967 }
10968 else
10969 t = integer_one_node;
10970
10971 step = fd->loop.step;
10972 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
10973 OMP_CLAUSE__LOOPTEMP_);
10974 gcc_assert (innerc);
10975 n1 = OMP_CLAUSE_DECL (innerc);
10976 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc), OMP_CLAUSE__LOOPTEMP_);
10977 gcc_assert (innerc);
10978 n2 = OMP_CLAUSE_DECL (innerc);
10979 if (bias)
10980 {
10981 n1 = fold_build2 (PLUS_EXPR, fd->iter_type, n1, bias);
10982 n2 = fold_build2 (PLUS_EXPR, fd->iter_type, n2, bias);
10983 }
10984 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
10985 true, NULL_TREE, true, GSI_SAME_STMT);
10986 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
10987 true, NULL_TREE, true, GSI_SAME_STMT);
10988 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
10989 true, NULL_TREE, true, GSI_SAME_STMT);
10990
10991 tree startvar = fd->loop.v;
10992 tree endvar = NULL_TREE;
10993
10994 if (gimple_omp_for_combined_p (fd->for_stmt))
10995 {
10996 tree clauses = gimple_omp_for_clauses (inner_stmt);
10997 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
10998 gcc_assert (innerc);
10999 startvar = OMP_CLAUSE_DECL (innerc);
11000 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
11001 OMP_CLAUSE__LOOPTEMP_);
11002 gcc_assert (innerc);
11003 endvar = OMP_CLAUSE_DECL (innerc);
11004 }
11005 t = fold_convert (TREE_TYPE (startvar), n1);
11006 t = force_gimple_operand_gsi (&gsi, t,
11007 DECL_P (startvar)
11008 && TREE_ADDRESSABLE (startvar),
11009 NULL_TREE, false, GSI_CONTINUE_LINKING);
11010 gimple *assign_stmt = gimple_build_assign (startvar, t);
11011 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
11012
11013 t = fold_convert (TREE_TYPE (startvar), n2);
11014 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
11015 false, GSI_CONTINUE_LINKING);
11016 if (endvar)
11017 {
11018 assign_stmt = gimple_build_assign (endvar, e);
11019 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
11020 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
11021 assign_stmt = gimple_build_assign (fd->loop.v, e);
11022 else
11023 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, e);
11024 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
11025 }
11026 if (fd->collapse > 1)
11027 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
11028
11029 if (!broken_loop)
11030 {
11031 /* The code controlling the sequential loop replaces the
11032 GIMPLE_OMP_CONTINUE. */
11033 gsi = gsi_last_bb (cont_bb);
11034 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
11035 gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
11036 vmain = gimple_omp_continue_control_use (cont_stmt);
11037 vback = gimple_omp_continue_control_def (cont_stmt);
11038
11039 if (!gimple_omp_for_combined_p (fd->for_stmt))
11040 {
11041 if (POINTER_TYPE_P (type))
11042 t = fold_build_pointer_plus (vmain, step);
11043 else
11044 t = fold_build2 (PLUS_EXPR, type, vmain, step);
11045 t = force_gimple_operand_gsi (&gsi, t,
11046 DECL_P (vback)
11047 && TREE_ADDRESSABLE (vback),
11048 NULL_TREE, true, GSI_SAME_STMT);
11049 assign_stmt = gimple_build_assign (vback, t);
11050 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
11051
11052 t = build2 (fd->loop.cond_code, boolean_type_node,
11053 DECL_P (vback) && TREE_ADDRESSABLE (vback)
11054 ? t : vback, e);
11055 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
11056 }
11057
11058 /* Remove the GIMPLE_OMP_CONTINUE statement. */
11059 gsi_remove (&gsi, true);
11060
11061 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
11062 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
11063 }
11064
11065 /* Remove the GIMPLE_OMP_FOR statement. */
11066 gsi = gsi_for_stmt (fd->for_stmt);
11067 gsi_remove (&gsi, true);
11068
11069 /* Remove the GIMPLE_OMP_RETURN statement. */
11070 gsi = gsi_last_bb (exit_bb);
11071 gsi_remove (&gsi, true);
11072
11073 FALLTHRU_EDGE (entry_bb)->probability = REG_BR_PROB_BASE;
11074 if (!broken_loop)
11075 remove_edge (BRANCH_EDGE (entry_bb));
11076 else
11077 {
11078 remove_edge_and_dominated_blocks (BRANCH_EDGE (entry_bb));
11079 region->outer->cont = NULL;
11080 }
11081
11082 /* Connect all the blocks. */
11083 if (!broken_loop)
11084 {
11085 ep = find_edge (cont_bb, body_bb);
11086 if (gimple_omp_for_combined_p (fd->for_stmt))
11087 {
11088 remove_edge (ep);
11089 ep = NULL;
3d483a94 11090 }
43895be5 11091 else if (fd->collapse > 1)
3d483a94 11092 {
43895be5 11093 remove_edge (ep);
11094 ep = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
3d483a94 11095 }
43895be5 11096 else
11097 ep->flags = EDGE_TRUE_VALUE;
11098 find_edge (cont_bb, fin_bb)->flags
11099 = ep ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
3d483a94 11100 }
3d483a94 11101
43895be5 11102 set_immediate_dominator (CDI_DOMINATORS, body_bb,
11103 recompute_dominator (CDI_DOMINATORS, body_bb));
11104 if (!broken_loop)
11105 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
11106 recompute_dominator (CDI_DOMINATORS, fin_bb));
11107
11108 if (!broken_loop && !gimple_omp_for_combined_p (fd->for_stmt))
11109 {
11110 struct loop *loop = alloc_loop ();
11111 loop->header = body_bb;
11112 if (collapse_bb == NULL)
11113 loop->latch = cont_bb;
11114 add_loop (loop, body_bb->loop_father);
11115 }
11116}
1e8e9920 11117
a8e785ba 11118/* A subroutine of expand_omp_for. Generate code for an OpenACC
11119 partitioned loop. The lowering here is abstracted, in that the
11120 loop parameters are passed through internal functions, which are
11121 further lowered by oacc_device_lower, once we get to the target
11122 compiler. The loop is of the form:
11123
11124 for (V = B; V LTGT E; V += S) {BODY}
11125
11126 where LTGT is < or >. We may have a specified chunking size, CHUNKING
11127 (constant 0 for no chunking) and we will have a GWV partitioning
11128 mask, specifying dimensions over which the loop is to be
11129 partitioned (see note below). We generate code that looks like:
11130
11131 <entry_bb> [incoming FALL->body, BRANCH->exit]
11132 typedef signedintify (typeof (V)) T; // underlying signed integral type
11133 T range = E - B;
11134 T chunk_no = 0;
11135 T DIR = LTGT == '<' ? +1 : -1;
11136 T chunk_max = GOACC_LOOP_CHUNK (dir, range, S, CHUNK_SIZE, GWV);
11137 T step = GOACC_LOOP_STEP (dir, range, S, CHUNK_SIZE, GWV);
11138
11139 <head_bb> [created by splitting end of entry_bb]
11140 T offset = GOACC_LOOP_OFFSET (dir, range, S, CHUNK_SIZE, GWV, chunk_no);
11141 T bound = GOACC_LOOP_BOUND (dir, range, S, CHUNK_SIZE, GWV, offset);
11142 if (!(offset LTGT bound)) goto bottom_bb;
11143
11144 <body_bb> [incoming]
11145 V = B + offset;
11146 {BODY}
11147
11148 <cont_bb> [incoming, may == body_bb FALL->exit_bb, BRANCH->body_bb]
11149 offset += step;
11150 if (offset LTGT bound) goto body_bb; [*]
11151
11152 <bottom_bb> [created by splitting start of exit_bb] insert BRANCH->head_bb
11153 chunk_no++;
11154 if (chunk < chunk_max) goto head_bb;
11155
11156 <exit_bb> [incoming]
11157 V = B + ((range -/+ 1) / S +/- 1) * S [*]
11158
11159 [*] Needed if V live at end of loop
11160
11161 Note: CHUNKING & GWV mask are specified explicitly here. This is a
11162 transition, and will be specified by a more general mechanism shortly.
11163 */
11164
11165static void
11166expand_oacc_for (struct omp_region *region, struct omp_for_data *fd)
11167{
11168 tree v = fd->loop.v;
11169 enum tree_code cond_code = fd->loop.cond_code;
11170 enum tree_code plus_code = PLUS_EXPR;
11171
11172 tree chunk_size = integer_minus_one_node;
11173 tree gwv = integer_zero_node;
11174 tree iter_type = TREE_TYPE (v);
11175 tree diff_type = iter_type;
11176 tree plus_type = iter_type;
11177 struct oacc_collapse *counts = NULL;
11178
11179 gcc_checking_assert (gimple_omp_for_kind (fd->for_stmt)
11180 == GF_OMP_FOR_KIND_OACC_LOOP);
11181 gcc_assert (!gimple_omp_for_combined_into_p (fd->for_stmt));
11182 gcc_assert (cond_code == LT_EXPR || cond_code == GT_EXPR);
11183
11184 if (POINTER_TYPE_P (iter_type))
11185 {
11186 plus_code = POINTER_PLUS_EXPR;
11187 plus_type = sizetype;
11188 }
11189 if (POINTER_TYPE_P (diff_type) || TYPE_UNSIGNED (diff_type))
11190 diff_type = signed_type_for (diff_type);
11191
11192 basic_block entry_bb = region->entry; /* BB ending in OMP_FOR */
11193 basic_block exit_bb = region->exit; /* BB ending in OMP_RETURN */
11194 basic_block cont_bb = region->cont; /* BB ending in OMP_CONTINUE */
11195 basic_block bottom_bb = NULL;
11196
11197 /* entry_bb has two sucessors; the branch edge is to the exit
11198 block, fallthrough edge to body. */
11199 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2
11200 && BRANCH_EDGE (entry_bb)->dest == exit_bb);
11201
11202 /* If cont_bb non-NULL, it has 2 successors. The branch successor is
11203 body_bb, or to a block whose only successor is the body_bb. Its
11204 fallthrough successor is the final block (same as the branch
11205 successor of the entry_bb). */
11206 if (cont_bb)
11207 {
11208 basic_block body_bb = FALLTHRU_EDGE (entry_bb)->dest;
11209 basic_block bed = BRANCH_EDGE (cont_bb)->dest;
11210
11211 gcc_assert (FALLTHRU_EDGE (cont_bb)->dest == exit_bb);
11212 gcc_assert (bed == body_bb || single_succ_edge (bed)->dest == body_bb);
11213 }
11214 else
11215 gcc_assert (!gimple_in_ssa_p (cfun));
11216
11217 /* The exit block only has entry_bb and cont_bb as predecessors. */
11218 gcc_assert (EDGE_COUNT (exit_bb->preds) == 1 + (cont_bb != NULL));
11219
11220 tree chunk_no;
11221 tree chunk_max = NULL_TREE;
11222 tree bound, offset;
11223 tree step = create_tmp_var (diff_type, ".step");
11224 bool up = cond_code == LT_EXPR;
11225 tree dir = build_int_cst (diff_type, up ? +1 : -1);
11226 bool chunking = !gimple_in_ssa_p (cfun);;
11227 bool negating;
11228
11229 /* SSA instances. */
11230 tree offset_incr = NULL_TREE;
11231 tree offset_init = NULL_TREE;
11232
11233 gimple_stmt_iterator gsi;
11234 gassign *ass;
11235 gcall *call;
11236 gimple *stmt;
11237 tree expr;
11238 location_t loc;
11239 edge split, be, fte;
11240
11241 /* Split the end of entry_bb to create head_bb. */
11242 split = split_block (entry_bb, last_stmt (entry_bb));
11243 basic_block head_bb = split->dest;
11244 entry_bb = split->src;
11245
11246 /* Chunk setup goes at end of entry_bb, replacing the omp_for. */
11247 gsi = gsi_last_bb (entry_bb);
11248 gomp_for *for_stmt = as_a <gomp_for *> (gsi_stmt (gsi));
11249 loc = gimple_location (for_stmt);
11250
11251 if (gimple_in_ssa_p (cfun))
11252 {
11253 offset_init = gimple_omp_for_index (for_stmt, 0);
11254 gcc_assert (integer_zerop (fd->loop.n1));
11255 /* The SSA parallelizer does gang parallelism. */
11256 gwv = build_int_cst (integer_type_node, GOMP_DIM_MASK (GOMP_DIM_GANG));
11257 }
11258
11259 if (fd->collapse > 1)
11260 {
11261 counts = XALLOCAVEC (struct oacc_collapse, fd->collapse);
11262 tree total = expand_oacc_collapse_init (fd, &gsi, counts,
11263 TREE_TYPE (fd->loop.n2));
11264
11265 if (SSA_VAR_P (fd->loop.n2))
11266 {
11267 total = force_gimple_operand_gsi (&gsi, total, false, NULL_TREE,
11268 true, GSI_SAME_STMT);
11269 ass = gimple_build_assign (fd->loop.n2, total);
11270 gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
11271 }
11272
11273 }
11274
11275 tree b = fd->loop.n1;
11276 tree e = fd->loop.n2;
11277 tree s = fd->loop.step;
11278
11279 b = force_gimple_operand_gsi (&gsi, b, true, NULL_TREE, true, GSI_SAME_STMT);
11280 e = force_gimple_operand_gsi (&gsi, e, true, NULL_TREE, true, GSI_SAME_STMT);
11281
11282 /* Convert the step, avoiding possible unsigned->signed overflow. */
11283 negating = !up && TYPE_UNSIGNED (TREE_TYPE (s));
11284 if (negating)
11285 s = fold_build1 (NEGATE_EXPR, TREE_TYPE (s), s);
11286 s = fold_convert (diff_type, s);
11287 if (negating)
11288 s = fold_build1 (NEGATE_EXPR, diff_type, s);
11289 s = force_gimple_operand_gsi (&gsi, s, true, NULL_TREE, true, GSI_SAME_STMT);
11290
11291 if (!chunking)
11292 chunk_size = integer_zero_node;
11293 expr = fold_convert (diff_type, chunk_size);
11294 chunk_size = force_gimple_operand_gsi (&gsi, expr, true,
11295 NULL_TREE, true, GSI_SAME_STMT);
11296 /* Determine the range, avoiding possible unsigned->signed overflow. */
11297 negating = !up && TYPE_UNSIGNED (iter_type);
11298 expr = fold_build2 (MINUS_EXPR, plus_type,
11299 fold_convert (plus_type, negating ? b : e),
11300 fold_convert (plus_type, negating ? e : b));
11301 expr = fold_convert (diff_type, expr);
11302 if (negating)
11303 expr = fold_build1 (NEGATE_EXPR, diff_type, expr);
11304 tree range = force_gimple_operand_gsi (&gsi, expr, true,
11305 NULL_TREE, true, GSI_SAME_STMT);
11306
11307 chunk_no = build_int_cst (diff_type, 0);
11308 if (chunking)
11309 {
11310 gcc_assert (!gimple_in_ssa_p (cfun));
11311
11312 expr = chunk_no;
11313 chunk_max = create_tmp_var (diff_type, ".chunk_max");
11314 chunk_no = create_tmp_var (diff_type, ".chunk_no");
11315
11316 ass = gimple_build_assign (chunk_no, expr);
11317 gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
11318
11319 call = gimple_build_call_internal (IFN_GOACC_LOOP, 6,
11320 build_int_cst (integer_type_node,
11321 IFN_GOACC_LOOP_CHUNKS),
11322 dir, range, s, chunk_size, gwv);
11323 gimple_call_set_lhs (call, chunk_max);
11324 gimple_set_location (call, loc);
11325 gsi_insert_before (&gsi, call, GSI_SAME_STMT);
11326 }
11327 else
11328 chunk_size = chunk_no;
11329
11330 call = gimple_build_call_internal (IFN_GOACC_LOOP, 6,
11331 build_int_cst (integer_type_node,
11332 IFN_GOACC_LOOP_STEP),
11333 dir, range, s, chunk_size, gwv);
11334 gimple_call_set_lhs (call, step);
11335 gimple_set_location (call, loc);
11336 gsi_insert_before (&gsi, call, GSI_SAME_STMT);
11337
11338 /* Remove the GIMPLE_OMP_FOR. */
11339 gsi_remove (&gsi, true);
11340
11341 /* Fixup edges from head_bb */
11342 be = BRANCH_EDGE (head_bb);
11343 fte = FALLTHRU_EDGE (head_bb);
11344 be->flags |= EDGE_FALSE_VALUE;
11345 fte->flags ^= EDGE_FALLTHRU | EDGE_TRUE_VALUE;
11346
11347 basic_block body_bb = fte->dest;
11348
11349 if (gimple_in_ssa_p (cfun))
11350 {
11351 gsi = gsi_last_bb (cont_bb);
11352 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
11353
11354 offset = gimple_omp_continue_control_use (cont_stmt);
11355 offset_incr = gimple_omp_continue_control_def (cont_stmt);
11356 }
11357 else
11358 {
11359 offset = create_tmp_var (diff_type, ".offset");
11360 offset_init = offset_incr = offset;
11361 }
11362 bound = create_tmp_var (TREE_TYPE (offset), ".bound");
11363
11364 /* Loop offset & bound go into head_bb. */
11365 gsi = gsi_start_bb (head_bb);
11366
11367 call = gimple_build_call_internal (IFN_GOACC_LOOP, 7,
11368 build_int_cst (integer_type_node,
11369 IFN_GOACC_LOOP_OFFSET),
11370 dir, range, s,
11371 chunk_size, gwv, chunk_no);
11372 gimple_call_set_lhs (call, offset_init);
11373 gimple_set_location (call, loc);
11374 gsi_insert_after (&gsi, call, GSI_CONTINUE_LINKING);
11375
11376 call = gimple_build_call_internal (IFN_GOACC_LOOP, 7,
11377 build_int_cst (integer_type_node,
11378 IFN_GOACC_LOOP_BOUND),
11379 dir, range, s,
11380 chunk_size, gwv, offset_init);
11381 gimple_call_set_lhs (call, bound);
11382 gimple_set_location (call, loc);
11383 gsi_insert_after (&gsi, call, GSI_CONTINUE_LINKING);
11384
11385 expr = build2 (cond_code, boolean_type_node, offset_init, bound);
11386 gsi_insert_after (&gsi, gimple_build_cond_empty (expr),
11387 GSI_CONTINUE_LINKING);
11388
11389 /* V assignment goes into body_bb. */
11390 if (!gimple_in_ssa_p (cfun))
11391 {
11392 gsi = gsi_start_bb (body_bb);
11393
11394 expr = build2 (plus_code, iter_type, b,
11395 fold_convert (plus_type, offset));
11396 expr = force_gimple_operand_gsi (&gsi, expr, false, NULL_TREE,
11397 true, GSI_SAME_STMT);
11398 ass = gimple_build_assign (v, expr);
11399 gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
11400 if (fd->collapse > 1)
11401 expand_oacc_collapse_vars (fd, &gsi, counts, v);
11402 }
11403
11404 /* Loop increment goes into cont_bb. If this is not a loop, we
11405 will have spawned threads as if it was, and each one will
11406 execute one iteration. The specification is not explicit about
11407 whether such constructs are ill-formed or not, and they can
11408 occur, especially when noreturn routines are involved. */
11409 if (cont_bb)
11410 {
11411 gsi = gsi_last_bb (cont_bb);
11412 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
11413 loc = gimple_location (cont_stmt);
11414
11415 /* Increment offset. */
11416 if (gimple_in_ssa_p (cfun))
11417 expr= build2 (plus_code, iter_type, offset,
11418 fold_convert (plus_type, step));
11419 else
11420 expr = build2 (PLUS_EXPR, diff_type, offset, step);
11421 expr = force_gimple_operand_gsi (&gsi, expr, false, NULL_TREE,
11422 true, GSI_SAME_STMT);
11423 ass = gimple_build_assign (offset_incr, expr);
11424 gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
11425 expr = build2 (cond_code, boolean_type_node, offset_incr, bound);
11426 gsi_insert_before (&gsi, gimple_build_cond_empty (expr), GSI_SAME_STMT);
11427
11428 /* Remove the GIMPLE_OMP_CONTINUE. */
11429 gsi_remove (&gsi, true);
11430
11431 /* Fixup edges from cont_bb */
11432 be = BRANCH_EDGE (cont_bb);
11433 fte = FALLTHRU_EDGE (cont_bb);
11434 be->flags |= EDGE_TRUE_VALUE;
11435 fte->flags ^= EDGE_FALLTHRU | EDGE_FALSE_VALUE;
11436
11437 if (chunking)
11438 {
11439 /* Split the beginning of exit_bb to make bottom_bb. We
11440 need to insert a nop at the start, because splitting is
11441 after a stmt, not before. */
11442 gsi = gsi_start_bb (exit_bb);
11443 stmt = gimple_build_nop ();
11444 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
11445 split = split_block (exit_bb, stmt);
11446 bottom_bb = split->src;
11447 exit_bb = split->dest;
11448 gsi = gsi_last_bb (bottom_bb);
11449
11450 /* Chunk increment and test goes into bottom_bb. */
11451 expr = build2 (PLUS_EXPR, diff_type, chunk_no,
11452 build_int_cst (diff_type, 1));
11453 ass = gimple_build_assign (chunk_no, expr);
11454 gsi_insert_after (&gsi, ass, GSI_CONTINUE_LINKING);
11455
11456 /* Chunk test at end of bottom_bb. */
11457 expr = build2 (LT_EXPR, boolean_type_node, chunk_no, chunk_max);
11458 gsi_insert_after (&gsi, gimple_build_cond_empty (expr),
11459 GSI_CONTINUE_LINKING);
11460
11461 /* Fixup edges from bottom_bb. */
11462 split->flags ^= EDGE_FALLTHRU | EDGE_FALSE_VALUE;
11463 make_edge (bottom_bb, head_bb, EDGE_TRUE_VALUE);
11464 }
11465 }
11466
11467 gsi = gsi_last_bb (exit_bb);
11468 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
11469 loc = gimple_location (gsi_stmt (gsi));
11470
11471 if (!gimple_in_ssa_p (cfun))
11472 {
11473 /* Insert the final value of V, in case it is live. This is the
11474 value for the only thread that survives past the join. */
11475 expr = fold_build2 (MINUS_EXPR, diff_type, range, dir);
11476 expr = fold_build2 (PLUS_EXPR, diff_type, expr, s);
11477 expr = fold_build2 (TRUNC_DIV_EXPR, diff_type, expr, s);
11478 expr = fold_build2 (MULT_EXPR, diff_type, expr, s);
11479 expr = build2 (plus_code, iter_type, b, fold_convert (plus_type, expr));
11480 expr = force_gimple_operand_gsi (&gsi, expr, false, NULL_TREE,
11481 true, GSI_SAME_STMT);
11482 ass = gimple_build_assign (v, expr);
11483 gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
11484 }
11485
11486 /* Remove the OMP_RETURN. */
11487 gsi_remove (&gsi, true);
11488
11489 if (cont_bb)
11490 {
11491 /* We now have one or two nested loops. Update the loop
11492 structures. */
11493 struct loop *parent = entry_bb->loop_father;
11494 struct loop *body = body_bb->loop_father;
11495
11496 if (chunking)
11497 {
11498 struct loop *chunk_loop = alloc_loop ();
11499 chunk_loop->header = head_bb;
11500 chunk_loop->latch = bottom_bb;
11501 add_loop (chunk_loop, parent);
11502 parent = chunk_loop;
11503 }
11504 else if (parent != body)
11505 {
11506 gcc_assert (body->header == body_bb);
11507 gcc_assert (body->latch == cont_bb
11508 || single_pred (body->latch) == cont_bb);
11509 parent = NULL;
11510 }
11511
11512 if (parent)
11513 {
11514 struct loop *body_loop = alloc_loop ();
11515 body_loop->header = body_bb;
11516 body_loop->latch = cont_bb;
11517 add_loop (body_loop, parent);
11518 }
11519 }
11520}
11521
ca4c3545 11522/* Expand the OMP loop defined by REGION. */
1e8e9920 11523
773c5ba7 11524static void
42acab1c 11525expand_omp_for (struct omp_region *region, gimple *inner_stmt)
773c5ba7 11526{
11527 struct omp_for_data fd;
fd6481cf 11528 struct omp_for_data_loop *loops;
1e8e9920 11529
fd6481cf 11530 loops
11531 = (struct omp_for_data_loop *)
75a70cf9 11532 alloca (gimple_omp_for_collapse (last_stmt (region->entry))
fd6481cf 11533 * sizeof (struct omp_for_data_loop));
1a91d914 11534 extract_omp_for_data (as_a <gomp_for *> (last_stmt (region->entry)),
11535 &fd, loops);
f77459c5 11536 region->sched_kind = fd.sched_kind;
9561765e 11537 region->sched_modifiers = fd.sched_modifiers;
1e8e9920 11538
b3a3ddec 11539 gcc_assert (EDGE_COUNT (region->entry->succs) == 2);
11540 BRANCH_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
11541 FALLTHRU_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
11542 if (region->cont)
11543 {
11544 gcc_assert (EDGE_COUNT (region->cont->succs) == 2);
11545 BRANCH_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
11546 FALLTHRU_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
11547 }
04c2922b 11548 else
75de4aa2 11549 /* If there isn't a continue then this is a degerate case where
04c2922b 11550 the introduction of abnormal edges during lowering will prevent
11551 original loops from being detected. Fix that up. */
11552 loops_state_set (LOOPS_NEED_FIXUP);
b3a3ddec 11553
10c55644 11554 if (gimple_omp_for_kind (fd.for_stmt) & GF_OMP_FOR_SIMD)
3d483a94 11555 expand_omp_simd (region, &fd);
40750995 11556 else if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_CILKFOR)
11557 expand_cilk_for (region, &fd);
a8e785ba 11558 else if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_OACC_LOOP)
11559 {
11560 gcc_assert (!inner_stmt);
11561 expand_oacc_for (region, &fd);
11562 }
43895be5 11563 else if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_TASKLOOP)
11564 {
11565 if (gimple_omp_for_combined_into_p (fd.for_stmt))
11566 expand_omp_taskloop_for_inner (region, &fd, inner_stmt);
11567 else
11568 expand_omp_taskloop_for_outer (region, &fd, inner_stmt);
11569 }
3d483a94 11570 else if (fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
bc7bff74 11571 && !fd.have_ordered)
1e8e9920 11572 {
11573 if (fd.chunk_size == NULL)
bc7bff74 11574 expand_omp_for_static_nochunk (region, &fd, inner_stmt);
1e8e9920 11575 else
bc7bff74 11576 expand_omp_for_static_chunk (region, &fd, inner_stmt);
1e8e9920 11577 }
11578 else
11579 {
fd6481cf 11580 int fn_index, start_ix, next_ix;
11581
3d483a94 11582 gcc_assert (gimple_omp_for_kind (fd.for_stmt)
11583 == GF_OMP_FOR_KIND_FOR);
0416ca72 11584 if (fd.chunk_size == NULL
11585 && fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
11586 fd.chunk_size = integer_zero_node;
fd6481cf 11587 gcc_assert (fd.sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
9561765e 11588 switch (fd.sched_kind)
11589 {
11590 case OMP_CLAUSE_SCHEDULE_RUNTIME:
11591 fn_index = 3;
11592 break;
11593 case OMP_CLAUSE_SCHEDULE_DYNAMIC:
11594 case OMP_CLAUSE_SCHEDULE_GUIDED:
11595 if ((fd.sched_modifiers & OMP_CLAUSE_SCHEDULE_NONMONOTONIC)
11596 && !fd.ordered
11597 && !fd.have_ordered)
11598 {
11599 fn_index = 3 + fd.sched_kind;
11600 break;
11601 }
11602 /* FALLTHRU */
11603 default:
11604 fn_index = fd.sched_kind;
11605 break;
11606 }
43895be5 11607 if (!fd.ordered)
9561765e 11608 fn_index += fd.have_ordered * 6;
43895be5 11609 if (fd.ordered)
11610 start_ix = ((int)BUILT_IN_GOMP_LOOP_DOACROSS_STATIC_START) + fn_index;
11611 else
11612 start_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_START) + fn_index;
b9a16870 11613 next_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_NEXT) + fn_index;
fd6481cf 11614 if (fd.iter_type == long_long_unsigned_type_node)
11615 {
b9a16870 11616 start_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_START
11617 - (int)BUILT_IN_GOMP_LOOP_STATIC_START);
11618 next_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_NEXT
11619 - (int)BUILT_IN_GOMP_LOOP_STATIC_NEXT);
fd6481cf 11620 }
b9c74b4d 11621 expand_omp_for_generic (region, &fd, (enum built_in_function) start_ix,
bc7bff74 11622 (enum built_in_function) next_ix, inner_stmt);
1e8e9920 11623 }
28c92cbb 11624
083152fb 11625 if (gimple_in_ssa_p (cfun))
11626 update_ssa (TODO_update_ssa_only_virtuals);
1e8e9920 11627}
11628
1e8e9920 11629
11630/* Expand code for an OpenMP sections directive. In pseudo code, we generate
11631
1e8e9920 11632 v = GOMP_sections_start (n);
11633 L0:
11634 switch (v)
11635 {
11636 case 0:
11637 goto L2;
11638 case 1:
11639 section 1;
11640 goto L1;
11641 case 2:
11642 ...
11643 case n:
11644 ...
1e8e9920 11645 default:
11646 abort ();
11647 }
11648 L1:
11649 v = GOMP_sections_next ();
11650 goto L0;
11651 L2:
11652 reduction;
11653
773c5ba7 11654 If this is a combined parallel sections, replace the call to
79acaae1 11655 GOMP_sections_start with call to GOMP_sections_next. */
1e8e9920 11656
11657static void
773c5ba7 11658expand_omp_sections (struct omp_region *region)
1e8e9920 11659{
f018d957 11660 tree t, u, vin = NULL, vmain, vnext, l2;
75a70cf9 11661 unsigned len;
ac6e3339 11662 basic_block entry_bb, l0_bb, l1_bb, l2_bb, default_bb;
75a70cf9 11663 gimple_stmt_iterator si, switch_si;
1a91d914 11664 gomp_sections *sections_stmt;
42acab1c 11665 gimple *stmt;
1a91d914 11666 gomp_continue *cont;
9884aaf8 11667 edge_iterator ei;
11668 edge e;
61e47ac8 11669 struct omp_region *inner;
75a70cf9 11670 unsigned i, casei;
ac6e3339 11671 bool exit_reachable = region->cont != NULL;
1e8e9920 11672
d244d9de 11673 gcc_assert (region->exit != NULL);
61e47ac8 11674 entry_bb = region->entry;
ac6e3339 11675 l0_bb = single_succ (entry_bb);
61e47ac8 11676 l1_bb = region->cont;
ac6e3339 11677 l2_bb = region->exit;
d244d9de 11678 if (single_pred_p (l2_bb) && single_pred (l2_bb) == l0_bb)
11679 l2 = gimple_block_label (l2_bb);
11680 else
03ed154b 11681 {
d244d9de 11682 /* This can happen if there are reductions. */
11683 len = EDGE_COUNT (l0_bb->succs);
11684 gcc_assert (len > 0);
11685 e = EDGE_SUCC (l0_bb, len - 1);
11686 si = gsi_last_bb (e->dest);
11687 l2 = NULL_TREE;
11688 if (gsi_end_p (si)
11689 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
11690 l2 = gimple_block_label (e->dest);
9884aaf8 11691 else
d244d9de 11692 FOR_EACH_EDGE (e, ei, l0_bb->succs)
11693 {
11694 si = gsi_last_bb (e->dest);
11695 if (gsi_end_p (si)
11696 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
9884aaf8 11697 {
d244d9de 11698 l2 = gimple_block_label (e->dest);
11699 break;
9884aaf8 11700 }
d244d9de 11701 }
03ed154b 11702 }
d244d9de 11703 if (exit_reachable)
11704 default_bb = create_empty_bb (l1_bb->prev_bb);
03ed154b 11705 else
d244d9de 11706 default_bb = create_empty_bb (l0_bb);
773c5ba7 11707
11708 /* We will build a switch() with enough cases for all the
75a70cf9 11709 GIMPLE_OMP_SECTION regions, a '0' case to handle the end of more work
773c5ba7 11710 and a default case to abort if something goes wrong. */
ac6e3339 11711 len = EDGE_COUNT (l0_bb->succs);
75a70cf9 11712
f1f41a6c 11713 /* Use vec::quick_push on label_vec throughout, since we know the size
75a70cf9 11714 in advance. */
c2078b80 11715 auto_vec<tree> label_vec (len);
1e8e9920 11716
61e47ac8 11717 /* The call to GOMP_sections_start goes in ENTRY_BB, replacing the
75a70cf9 11718 GIMPLE_OMP_SECTIONS statement. */
11719 si = gsi_last_bb (entry_bb);
1a91d914 11720 sections_stmt = as_a <gomp_sections *> (gsi_stmt (si));
75a70cf9 11721 gcc_assert (gimple_code (sections_stmt) == GIMPLE_OMP_SECTIONS);
11722 vin = gimple_omp_sections_control (sections_stmt);
773c5ba7 11723 if (!is_combined_parallel (region))
1e8e9920 11724 {
773c5ba7 11725 /* If we are not inside a combined parallel+sections region,
11726 call GOMP_sections_start. */
39cb6d68 11727 t = build_int_cst (unsigned_type_node, len - 1);
b9a16870 11728 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_START);
75a70cf9 11729 stmt = gimple_build_call (u, 1, t);
1e8e9920 11730 }
79acaae1 11731 else
11732 {
11733 /* Otherwise, call GOMP_sections_next. */
b9a16870 11734 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
75a70cf9 11735 stmt = gimple_build_call (u, 0);
79acaae1 11736 }
75a70cf9 11737 gimple_call_set_lhs (stmt, vin);
11738 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
11739 gsi_remove (&si, true);
11740
11741 /* The switch() statement replacing GIMPLE_OMP_SECTIONS_SWITCH goes in
11742 L0_BB. */
11743 switch_si = gsi_last_bb (l0_bb);
11744 gcc_assert (gimple_code (gsi_stmt (switch_si)) == GIMPLE_OMP_SECTIONS_SWITCH);
79acaae1 11745 if (exit_reachable)
11746 {
1a91d914 11747 cont = as_a <gomp_continue *> (last_stmt (l1_bb));
75a70cf9 11748 gcc_assert (gimple_code (cont) == GIMPLE_OMP_CONTINUE);
11749 vmain = gimple_omp_continue_control_use (cont);
11750 vnext = gimple_omp_continue_control_def (cont);
79acaae1 11751 }
11752 else
11753 {
11754 vmain = vin;
11755 vnext = NULL_TREE;
11756 }
1e8e9920 11757
d244d9de 11758 t = build_case_label (build_int_cst (unsigned_type_node, 0), NULL, l2);
f1f41a6c 11759 label_vec.quick_push (t);
d244d9de 11760 i = 1;
03ed154b 11761
75a70cf9 11762 /* Convert each GIMPLE_OMP_SECTION into a CASE_LABEL_EXPR. */
ac6e3339 11763 for (inner = region->inner, casei = 1;
11764 inner;
11765 inner = inner->next, i++, casei++)
1e8e9920 11766 {
773c5ba7 11767 basic_block s_entry_bb, s_exit_bb;
11768
9884aaf8 11769 /* Skip optional reduction region. */
75a70cf9 11770 if (inner->type == GIMPLE_OMP_ATOMIC_LOAD)
9884aaf8 11771 {
11772 --i;
11773 --casei;
11774 continue;
11775 }
11776
61e47ac8 11777 s_entry_bb = inner->entry;
11778 s_exit_bb = inner->exit;
1e8e9920 11779
75a70cf9 11780 t = gimple_block_label (s_entry_bb);
ac6e3339 11781 u = build_int_cst (unsigned_type_node, casei);
b6e3dd65 11782 u = build_case_label (u, NULL, t);
f1f41a6c 11783 label_vec.quick_push (u);
61e47ac8 11784
75a70cf9 11785 si = gsi_last_bb (s_entry_bb);
11786 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SECTION);
11787 gcc_assert (i < len || gimple_omp_section_last_p (gsi_stmt (si)));
11788 gsi_remove (&si, true);
61e47ac8 11789 single_succ_edge (s_entry_bb)->flags = EDGE_FALLTHRU;
03ed154b 11790
11791 if (s_exit_bb == NULL)
11792 continue;
11793
75a70cf9 11794 si = gsi_last_bb (s_exit_bb);
11795 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
11796 gsi_remove (&si, true);
03ed154b 11797
773c5ba7 11798 single_succ_edge (s_exit_bb)->flags = EDGE_FALLTHRU;
1e8e9920 11799 }
11800
773c5ba7 11801 /* Error handling code goes in DEFAULT_BB. */
75a70cf9 11802 t = gimple_block_label (default_bb);
b6e3dd65 11803 u = build_case_label (NULL, NULL, t);
61e47ac8 11804 make_edge (l0_bb, default_bb, 0);
b3083327 11805 add_bb_to_loop (default_bb, current_loops->tree_root);
1e8e9920 11806
49a70175 11807 stmt = gimple_build_switch (vmain, u, label_vec);
75a70cf9 11808 gsi_insert_after (&switch_si, stmt, GSI_SAME_STMT);
11809 gsi_remove (&switch_si, true);
75a70cf9 11810
11811 si = gsi_start_bb (default_bb);
b9a16870 11812 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
75a70cf9 11813 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
773c5ba7 11814
ac6e3339 11815 if (exit_reachable)
03ed154b 11816 {
b9a16870 11817 tree bfn_decl;
11818
ac6e3339 11819 /* Code to get the next section goes in L1_BB. */
75a70cf9 11820 si = gsi_last_bb (l1_bb);
11821 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CONTINUE);
1e8e9920 11822
b9a16870 11823 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
11824 stmt = gimple_build_call (bfn_decl, 0);
75a70cf9 11825 gimple_call_set_lhs (stmt, vnext);
11826 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
11827 gsi_remove (&si, true);
773c5ba7 11828
ac6e3339 11829 single_succ_edge (l1_bb)->flags = EDGE_FALLTHRU;
03ed154b 11830 }
773c5ba7 11831
d244d9de 11832 /* Cleanup function replaces GIMPLE_OMP_RETURN in EXIT_BB. */
11833 si = gsi_last_bb (l2_bb);
11834 if (gimple_omp_return_nowait_p (gsi_stmt (si)))
11835 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_NOWAIT);
bc7bff74 11836 else if (gimple_omp_return_lhs (gsi_stmt (si)))
11837 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_CANCEL);
d244d9de 11838 else
11839 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END);
11840 stmt = gimple_build_call (t, 0);
bc7bff74 11841 if (gimple_omp_return_lhs (gsi_stmt (si)))
11842 gimple_call_set_lhs (stmt, gimple_omp_return_lhs (gsi_stmt (si)));
d244d9de 11843 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
11844 gsi_remove (&si, true);
11845
79acaae1 11846 set_immediate_dominator (CDI_DOMINATORS, default_bb, l0_bb);
773c5ba7 11847}
1e8e9920 11848
1e8e9920 11849
61e47ac8 11850/* Expand code for an OpenMP single directive. We've already expanded
11851 much of the code, here we simply place the GOMP_barrier call. */
11852
11853static void
11854expand_omp_single (struct omp_region *region)
11855{
11856 basic_block entry_bb, exit_bb;
75a70cf9 11857 gimple_stmt_iterator si;
61e47ac8 11858
11859 entry_bb = region->entry;
11860 exit_bb = region->exit;
11861
75a70cf9 11862 si = gsi_last_bb (entry_bb);
75a70cf9 11863 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE);
11864 gsi_remove (&si, true);
61e47ac8 11865 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
11866
75a70cf9 11867 si = gsi_last_bb (exit_bb);
bc7bff74 11868 if (!gimple_omp_return_nowait_p (gsi_stmt (si)))
11869 {
11870 tree t = gimple_omp_return_lhs (gsi_stmt (si));
11871 gsi_insert_after (&si, build_omp_barrier (t), GSI_SAME_STMT);
11872 }
75a70cf9 11873 gsi_remove (&si, true);
61e47ac8 11874 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
11875}
11876
11877
11878/* Generic expansion for OpenMP synchronization directives: master,
11879 ordered and critical. All we need to do here is remove the entry
11880 and exit markers for REGION. */
773c5ba7 11881
11882static void
11883expand_omp_synch (struct omp_region *region)
11884{
11885 basic_block entry_bb, exit_bb;
75a70cf9 11886 gimple_stmt_iterator si;
773c5ba7 11887
61e47ac8 11888 entry_bb = region->entry;
11889 exit_bb = region->exit;
773c5ba7 11890
75a70cf9 11891 si = gsi_last_bb (entry_bb);
11892 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE
11893 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_MASTER
bc7bff74 11894 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TASKGROUP
75a70cf9 11895 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ORDERED
bc7bff74 11896 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CRITICAL
11897 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TEAMS);
75a70cf9 11898 gsi_remove (&si, true);
773c5ba7 11899 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
11900
03ed154b 11901 if (exit_bb)
11902 {
75a70cf9 11903 si = gsi_last_bb (exit_bb);
11904 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
11905 gsi_remove (&si, true);
03ed154b 11906 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
11907 }
773c5ba7 11908}
1e8e9920 11909
2169f33b 11910/* A subroutine of expand_omp_atomic. Attempt to implement the atomic
11911 operation as a normal volatile load. */
11912
11913static bool
3ec11c49 11914expand_omp_atomic_load (basic_block load_bb, tree addr,
11915 tree loaded_val, int index)
2169f33b 11916{
3ec11c49 11917 enum built_in_function tmpbase;
11918 gimple_stmt_iterator gsi;
11919 basic_block store_bb;
11920 location_t loc;
42acab1c 11921 gimple *stmt;
3ec11c49 11922 tree decl, call, type, itype;
11923
11924 gsi = gsi_last_bb (load_bb);
11925 stmt = gsi_stmt (gsi);
11926 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
11927 loc = gimple_location (stmt);
11928
11929 /* ??? If the target does not implement atomic_load_optab[mode], and mode
11930 is smaller than word size, then expand_atomic_load assumes that the load
11931 is atomic. We could avoid the builtin entirely in this case. */
11932
11933 tmpbase = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
11934 decl = builtin_decl_explicit (tmpbase);
11935 if (decl == NULL_TREE)
11936 return false;
11937
11938 type = TREE_TYPE (loaded_val);
11939 itype = TREE_TYPE (TREE_TYPE (decl));
11940
11941 call = build_call_expr_loc (loc, decl, 2, addr,
bc7bff74 11942 build_int_cst (NULL,
11943 gimple_omp_atomic_seq_cst_p (stmt)
11944 ? MEMMODEL_SEQ_CST
11945 : MEMMODEL_RELAXED));
3ec11c49 11946 if (!useless_type_conversion_p (type, itype))
11947 call = fold_build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
11948 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
11949
11950 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
11951 gsi_remove (&gsi, true);
11952
11953 store_bb = single_succ (load_bb);
11954 gsi = gsi_last_bb (store_bb);
11955 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
11956 gsi_remove (&gsi, true);
11957
11958 if (gimple_in_ssa_p (cfun))
11959 update_ssa (TODO_update_ssa_no_phi);
11960
11961 return true;
2169f33b 11962}
11963
11964/* A subroutine of expand_omp_atomic. Attempt to implement the atomic
11965 operation as a normal volatile store. */
11966
11967static bool
3ec11c49 11968expand_omp_atomic_store (basic_block load_bb, tree addr,
11969 tree loaded_val, tree stored_val, int index)
2169f33b 11970{
3ec11c49 11971 enum built_in_function tmpbase;
11972 gimple_stmt_iterator gsi;
11973 basic_block store_bb = single_succ (load_bb);
11974 location_t loc;
42acab1c 11975 gimple *stmt;
3ec11c49 11976 tree decl, call, type, itype;
3754d046 11977 machine_mode imode;
3ec11c49 11978 bool exchange;
11979
11980 gsi = gsi_last_bb (load_bb);
11981 stmt = gsi_stmt (gsi);
11982 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
11983
11984 /* If the load value is needed, then this isn't a store but an exchange. */
11985 exchange = gimple_omp_atomic_need_value_p (stmt);
11986
11987 gsi = gsi_last_bb (store_bb);
11988 stmt = gsi_stmt (gsi);
11989 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE);
11990 loc = gimple_location (stmt);
11991
11992 /* ??? If the target does not implement atomic_store_optab[mode], and mode
11993 is smaller than word size, then expand_atomic_store assumes that the store
11994 is atomic. We could avoid the builtin entirely in this case. */
11995
11996 tmpbase = (exchange ? BUILT_IN_ATOMIC_EXCHANGE_N : BUILT_IN_ATOMIC_STORE_N);
11997 tmpbase = (enum built_in_function) ((int) tmpbase + index + 1);
11998 decl = builtin_decl_explicit (tmpbase);
11999 if (decl == NULL_TREE)
12000 return false;
12001
12002 type = TREE_TYPE (stored_val);
12003
12004 /* Dig out the type of the function's second argument. */
12005 itype = TREE_TYPE (decl);
12006 itype = TYPE_ARG_TYPES (itype);
12007 itype = TREE_CHAIN (itype);
12008 itype = TREE_VALUE (itype);
12009 imode = TYPE_MODE (itype);
12010
12011 if (exchange && !can_atomic_exchange_p (imode, true))
12012 return false;
12013
12014 if (!useless_type_conversion_p (itype, type))
12015 stored_val = fold_build1_loc (loc, VIEW_CONVERT_EXPR, itype, stored_val);
12016 call = build_call_expr_loc (loc, decl, 3, addr, stored_val,
bc7bff74 12017 build_int_cst (NULL,
12018 gimple_omp_atomic_seq_cst_p (stmt)
12019 ? MEMMODEL_SEQ_CST
12020 : MEMMODEL_RELAXED));
3ec11c49 12021 if (exchange)
12022 {
12023 if (!useless_type_conversion_p (type, itype))
12024 call = build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
12025 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
12026 }
12027
12028 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
12029 gsi_remove (&gsi, true);
12030
12031 /* Remove the GIMPLE_OMP_ATOMIC_LOAD that we verified above. */
12032 gsi = gsi_last_bb (load_bb);
12033 gsi_remove (&gsi, true);
12034
12035 if (gimple_in_ssa_p (cfun))
12036 update_ssa (TODO_update_ssa_no_phi);
12037
12038 return true;
2169f33b 12039}
12040
cb7f680b 12041/* A subroutine of expand_omp_atomic. Attempt to implement the atomic
1cd6e20d 12042 operation as a __atomic_fetch_op builtin. INDEX is log2 of the
cb7f680b 12043 size of the data type, and thus usable to find the index of the builtin
12044 decl. Returns false if the expression is not of the proper form. */
12045
12046static bool
12047expand_omp_atomic_fetch_op (basic_block load_bb,
12048 tree addr, tree loaded_val,
12049 tree stored_val, int index)
12050{
b9a16870 12051 enum built_in_function oldbase, newbase, tmpbase;
cb7f680b 12052 tree decl, itype, call;
2169f33b 12053 tree lhs, rhs;
cb7f680b 12054 basic_block store_bb = single_succ (load_bb);
75a70cf9 12055 gimple_stmt_iterator gsi;
42acab1c 12056 gimple *stmt;
389dd41b 12057 location_t loc;
1cd6e20d 12058 enum tree_code code;
2169f33b 12059 bool need_old, need_new;
3754d046 12060 machine_mode imode;
bc7bff74 12061 bool seq_cst;
cb7f680b 12062
12063 /* We expect to find the following sequences:
48e1416a 12064
cb7f680b 12065 load_bb:
75a70cf9 12066 GIMPLE_OMP_ATOMIC_LOAD (tmp, mem)
cb7f680b 12067
12068 store_bb:
12069 val = tmp OP something; (or: something OP tmp)
48e1416a 12070 GIMPLE_OMP_STORE (val)
cb7f680b 12071
48e1416a 12072 ???FIXME: Allow a more flexible sequence.
cb7f680b 12073 Perhaps use data flow to pick the statements.
48e1416a 12074
cb7f680b 12075 */
12076
75a70cf9 12077 gsi = gsi_after_labels (store_bb);
12078 stmt = gsi_stmt (gsi);
389dd41b 12079 loc = gimple_location (stmt);
75a70cf9 12080 if (!is_gimple_assign (stmt))
cb7f680b 12081 return false;
75a70cf9 12082 gsi_next (&gsi);
12083 if (gimple_code (gsi_stmt (gsi)) != GIMPLE_OMP_ATOMIC_STORE)
cb7f680b 12084 return false;
2169f33b 12085 need_new = gimple_omp_atomic_need_value_p (gsi_stmt (gsi));
12086 need_old = gimple_omp_atomic_need_value_p (last_stmt (load_bb));
bc7bff74 12087 seq_cst = gimple_omp_atomic_seq_cst_p (last_stmt (load_bb));
2169f33b 12088 gcc_checking_assert (!need_old || !need_new);
cb7f680b 12089
75a70cf9 12090 if (!operand_equal_p (gimple_assign_lhs (stmt), stored_val, 0))
cb7f680b 12091 return false;
12092
cb7f680b 12093 /* Check for one of the supported fetch-op operations. */
1cd6e20d 12094 code = gimple_assign_rhs_code (stmt);
12095 switch (code)
cb7f680b 12096 {
12097 case PLUS_EXPR:
12098 case POINTER_PLUS_EXPR:
1cd6e20d 12099 oldbase = BUILT_IN_ATOMIC_FETCH_ADD_N;
12100 newbase = BUILT_IN_ATOMIC_ADD_FETCH_N;
cb7f680b 12101 break;
12102 case MINUS_EXPR:
1cd6e20d 12103 oldbase = BUILT_IN_ATOMIC_FETCH_SUB_N;
12104 newbase = BUILT_IN_ATOMIC_SUB_FETCH_N;
cb7f680b 12105 break;
12106 case BIT_AND_EXPR:
1cd6e20d 12107 oldbase = BUILT_IN_ATOMIC_FETCH_AND_N;
12108 newbase = BUILT_IN_ATOMIC_AND_FETCH_N;
cb7f680b 12109 break;
12110 case BIT_IOR_EXPR:
1cd6e20d 12111 oldbase = BUILT_IN_ATOMIC_FETCH_OR_N;
12112 newbase = BUILT_IN_ATOMIC_OR_FETCH_N;
cb7f680b 12113 break;
12114 case BIT_XOR_EXPR:
1cd6e20d 12115 oldbase = BUILT_IN_ATOMIC_FETCH_XOR_N;
12116 newbase = BUILT_IN_ATOMIC_XOR_FETCH_N;
cb7f680b 12117 break;
12118 default:
12119 return false;
12120 }
1cd6e20d 12121
cb7f680b 12122 /* Make sure the expression is of the proper form. */
75a70cf9 12123 if (operand_equal_p (gimple_assign_rhs1 (stmt), loaded_val, 0))
12124 rhs = gimple_assign_rhs2 (stmt);
12125 else if (commutative_tree_code (gimple_assign_rhs_code (stmt))
12126 && operand_equal_p (gimple_assign_rhs2 (stmt), loaded_val, 0))
12127 rhs = gimple_assign_rhs1 (stmt);
cb7f680b 12128 else
12129 return false;
12130
b9a16870 12131 tmpbase = ((enum built_in_function)
12132 ((need_new ? newbase : oldbase) + index + 1));
12133 decl = builtin_decl_explicit (tmpbase);
0f94f46b 12134 if (decl == NULL_TREE)
12135 return false;
cb7f680b 12136 itype = TREE_TYPE (TREE_TYPE (decl));
1cd6e20d 12137 imode = TYPE_MODE (itype);
cb7f680b 12138
1cd6e20d 12139 /* We could test all of the various optabs involved, but the fact of the
12140 matter is that (with the exception of i486 vs i586 and xadd) all targets
12141 that support any atomic operaton optab also implements compare-and-swap.
12142 Let optabs.c take care of expanding any compare-and-swap loop. */
29139cdc 12143 if (!can_compare_and_swap_p (imode, true))
cb7f680b 12144 return false;
12145
75a70cf9 12146 gsi = gsi_last_bb (load_bb);
12147 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_LOAD);
1cd6e20d 12148
12149 /* OpenMP does not imply any barrier-like semantics on its atomic ops.
12150 It only requires that the operation happen atomically. Thus we can
12151 use the RELAXED memory model. */
12152 call = build_call_expr_loc (loc, decl, 3, addr,
12153 fold_convert_loc (loc, itype, rhs),
bc7bff74 12154 build_int_cst (NULL,
12155 seq_cst ? MEMMODEL_SEQ_CST
12156 : MEMMODEL_RELAXED));
1cd6e20d 12157
2169f33b 12158 if (need_old || need_new)
12159 {
12160 lhs = need_old ? loaded_val : stored_val;
12161 call = fold_convert_loc (loc, TREE_TYPE (lhs), call);
12162 call = build2_loc (loc, MODIFY_EXPR, void_type_node, lhs, call);
12163 }
12164 else
12165 call = fold_convert_loc (loc, void_type_node, call);
75a70cf9 12166 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
12167 gsi_remove (&gsi, true);
cb7f680b 12168
75a70cf9 12169 gsi = gsi_last_bb (store_bb);
12170 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
12171 gsi_remove (&gsi, true);
12172 gsi = gsi_last_bb (store_bb);
97d59451 12173 stmt = gsi_stmt (gsi);
75a70cf9 12174 gsi_remove (&gsi, true);
cb7f680b 12175
12176 if (gimple_in_ssa_p (cfun))
97d59451 12177 {
12178 release_defs (stmt);
12179 update_ssa (TODO_update_ssa_no_phi);
12180 }
cb7f680b 12181
12182 return true;
12183}
12184
12185/* A subroutine of expand_omp_atomic. Implement the atomic operation as:
12186
12187 oldval = *addr;
12188 repeat:
12189 newval = rhs; // with oldval replacing *addr in rhs
12190 oldval = __sync_val_compare_and_swap (addr, oldval, newval);
12191 if (oldval != newval)
12192 goto repeat;
12193
12194 INDEX is log2 of the size of the data type, and thus usable to find the
12195 index of the builtin decl. */
12196
12197static bool
12198expand_omp_atomic_pipeline (basic_block load_bb, basic_block store_bb,
12199 tree addr, tree loaded_val, tree stored_val,
12200 int index)
12201{
790368c5 12202 tree loadedi, storedi, initial, new_storedi, old_vali;
cb7f680b 12203 tree type, itype, cmpxchg, iaddr;
75a70cf9 12204 gimple_stmt_iterator si;
cb7f680b 12205 basic_block loop_header = single_succ (load_bb);
42acab1c 12206 gimple *phi, *stmt;
cb7f680b 12207 edge e;
b9a16870 12208 enum built_in_function fncode;
cb7f680b 12209
1cd6e20d 12210 /* ??? We need a non-pointer interface to __atomic_compare_exchange in
12211 order to use the RELAXED memory model effectively. */
b9a16870 12212 fncode = (enum built_in_function)((int)BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_N
12213 + index + 1);
12214 cmpxchg = builtin_decl_explicit (fncode);
0f94f46b 12215 if (cmpxchg == NULL_TREE)
12216 return false;
cb7f680b 12217 type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
12218 itype = TREE_TYPE (TREE_TYPE (cmpxchg));
12219
29139cdc 12220 if (!can_compare_and_swap_p (TYPE_MODE (itype), true))
cb7f680b 12221 return false;
12222
75a70cf9 12223 /* Load the initial value, replacing the GIMPLE_OMP_ATOMIC_LOAD. */
12224 si = gsi_last_bb (load_bb);
12225 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
12226
790368c5 12227 /* For floating-point values, we'll need to view-convert them to integers
12228 so that we can perform the atomic compare and swap. Simplify the
12229 following code by always setting up the "i"ntegral variables. */
12230 if (!INTEGRAL_TYPE_P (type) && !POINTER_TYPE_P (type))
12231 {
75a70cf9 12232 tree iaddr_val;
12233
072f7ab1 12234 iaddr = create_tmp_reg (build_pointer_type_for_mode (itype, ptr_mode,
f9e245b2 12235 true));
75a70cf9 12236 iaddr_val
12237 = force_gimple_operand_gsi (&si,
12238 fold_convert (TREE_TYPE (iaddr), addr),
12239 false, NULL_TREE, true, GSI_SAME_STMT);
12240 stmt = gimple_build_assign (iaddr, iaddr_val);
12241 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
f9e245b2 12242 loadedi = create_tmp_var (itype);
790368c5 12243 if (gimple_in_ssa_p (cfun))
f9e245b2 12244 loadedi = make_ssa_name (loadedi);
790368c5 12245 }
12246 else
12247 {
12248 iaddr = addr;
12249 loadedi = loaded_val;
12250 }
75a70cf9 12251
2ed72821 12252 fncode = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
12253 tree loaddecl = builtin_decl_explicit (fncode);
12254 if (loaddecl)
12255 initial
12256 = fold_convert (TREE_TYPE (TREE_TYPE (iaddr)),
12257 build_call_expr (loaddecl, 2, iaddr,
12258 build_int_cst (NULL_TREE,
12259 MEMMODEL_RELAXED)));
12260 else
12261 initial = build2 (MEM_REF, TREE_TYPE (TREE_TYPE (iaddr)), iaddr,
12262 build_int_cst (TREE_TYPE (iaddr), 0));
12263
182cf5a9 12264 initial
2ed72821 12265 = force_gimple_operand_gsi (&si, initial, true, NULL_TREE, true,
12266 GSI_SAME_STMT);
790368c5 12267
12268 /* Move the value to the LOADEDI temporary. */
cb7f680b 12269 if (gimple_in_ssa_p (cfun))
12270 {
75a70cf9 12271 gcc_assert (gimple_seq_empty_p (phi_nodes (loop_header)));
790368c5 12272 phi = create_phi_node (loadedi, loop_header);
cb7f680b 12273 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, single_succ_edge (load_bb)),
12274 initial);
12275 }
12276 else
75a70cf9 12277 gsi_insert_before (&si,
12278 gimple_build_assign (loadedi, initial),
12279 GSI_SAME_STMT);
790368c5 12280 if (loadedi != loaded_val)
12281 {
75a70cf9 12282 gimple_stmt_iterator gsi2;
12283 tree x;
790368c5 12284
12285 x = build1 (VIEW_CONVERT_EXPR, type, loadedi);
75a70cf9 12286 gsi2 = gsi_start_bb (loop_header);
790368c5 12287 if (gimple_in_ssa_p (cfun))
12288 {
1a91d914 12289 gassign *stmt;
75a70cf9 12290 x = force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
12291 true, GSI_SAME_STMT);
12292 stmt = gimple_build_assign (loaded_val, x);
12293 gsi_insert_before (&gsi2, stmt, GSI_SAME_STMT);
790368c5 12294 }
12295 else
12296 {
75a70cf9 12297 x = build2 (MODIFY_EXPR, TREE_TYPE (loaded_val), loaded_val, x);
12298 force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
12299 true, GSI_SAME_STMT);
790368c5 12300 }
12301 }
75a70cf9 12302 gsi_remove (&si, true);
cb7f680b 12303
75a70cf9 12304 si = gsi_last_bb (store_bb);
12305 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
cb7f680b 12306
790368c5 12307 if (iaddr == addr)
12308 storedi = stored_val;
cb7f680b 12309 else
790368c5 12310 storedi =
75a70cf9 12311 force_gimple_operand_gsi (&si,
790368c5 12312 build1 (VIEW_CONVERT_EXPR, itype,
12313 stored_val), true, NULL_TREE, true,
75a70cf9 12314 GSI_SAME_STMT);
cb7f680b 12315
12316 /* Build the compare&swap statement. */
12317 new_storedi = build_call_expr (cmpxchg, 3, iaddr, loadedi, storedi);
75a70cf9 12318 new_storedi = force_gimple_operand_gsi (&si,
87f9ffa4 12319 fold_convert (TREE_TYPE (loadedi),
12320 new_storedi),
cb7f680b 12321 true, NULL_TREE,
75a70cf9 12322 true, GSI_SAME_STMT);
cb7f680b 12323
12324 if (gimple_in_ssa_p (cfun))
12325 old_vali = loadedi;
12326 else
12327 {
f9e245b2 12328 old_vali = create_tmp_var (TREE_TYPE (loadedi));
75a70cf9 12329 stmt = gimple_build_assign (old_vali, loadedi);
12330 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
cb7f680b 12331
75a70cf9 12332 stmt = gimple_build_assign (loadedi, new_storedi);
12333 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
cb7f680b 12334 }
12335
12336 /* Note that we always perform the comparison as an integer, even for
48e1416a 12337 floating point. This allows the atomic operation to properly
cb7f680b 12338 succeed even with NaNs and -0.0. */
75a70cf9 12339 stmt = gimple_build_cond_empty
12340 (build2 (NE_EXPR, boolean_type_node,
12341 new_storedi, old_vali));
12342 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
cb7f680b 12343
12344 /* Update cfg. */
12345 e = single_succ_edge (store_bb);
12346 e->flags &= ~EDGE_FALLTHRU;
12347 e->flags |= EDGE_FALSE_VALUE;
12348
12349 e = make_edge (store_bb, loop_header, EDGE_TRUE_VALUE);
12350
790368c5 12351 /* Copy the new value to loadedi (we already did that before the condition
cb7f680b 12352 if we are not in SSA). */
12353 if (gimple_in_ssa_p (cfun))
12354 {
75a70cf9 12355 phi = gimple_seq_first_stmt (phi_nodes (loop_header));
790368c5 12356 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, e), new_storedi);
cb7f680b 12357 }
12358
75a70cf9 12359 /* Remove GIMPLE_OMP_ATOMIC_STORE. */
12360 gsi_remove (&si, true);
cb7f680b 12361
04c2922b 12362 struct loop *loop = alloc_loop ();
12363 loop->header = loop_header;
5f037457 12364 loop->latch = store_bb;
04c2922b 12365 add_loop (loop, loop_header->loop_father);
12366
cb7f680b 12367 if (gimple_in_ssa_p (cfun))
12368 update_ssa (TODO_update_ssa_no_phi);
12369
12370 return true;
12371}
12372
12373/* A subroutine of expand_omp_atomic. Implement the atomic operation as:
12374
12375 GOMP_atomic_start ();
12376 *addr = rhs;
12377 GOMP_atomic_end ();
12378
12379 The result is not globally atomic, but works so long as all parallel
12380 references are within #pragma omp atomic directives. According to
12381 responses received from omp@openmp.org, appears to be within spec.
12382 Which makes sense, since that's how several other compilers handle
48e1416a 12383 this situation as well.
75a70cf9 12384 LOADED_VAL and ADDR are the operands of GIMPLE_OMP_ATOMIC_LOAD we're
12385 expanding. STORED_VAL is the operand of the matching
12386 GIMPLE_OMP_ATOMIC_STORE.
cb7f680b 12387
48e1416a 12388 We replace
12389 GIMPLE_OMP_ATOMIC_LOAD (loaded_val, addr) with
cb7f680b 12390 loaded_val = *addr;
12391
12392 and replace
3ec11c49 12393 GIMPLE_OMP_ATOMIC_STORE (stored_val) with
48e1416a 12394 *addr = stored_val;
cb7f680b 12395*/
12396
12397static bool
12398expand_omp_atomic_mutex (basic_block load_bb, basic_block store_bb,
12399 tree addr, tree loaded_val, tree stored_val)
12400{
75a70cf9 12401 gimple_stmt_iterator si;
1a91d914 12402 gassign *stmt;
cb7f680b 12403 tree t;
12404
75a70cf9 12405 si = gsi_last_bb (load_bb);
12406 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
cb7f680b 12407
b9a16870 12408 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START);
414c3a2c 12409 t = build_call_expr (t, 0);
75a70cf9 12410 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
cb7f680b 12411
182cf5a9 12412 stmt = gimple_build_assign (loaded_val, build_simple_mem_ref (addr));
75a70cf9 12413 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
12414 gsi_remove (&si, true);
cb7f680b 12415
75a70cf9 12416 si = gsi_last_bb (store_bb);
12417 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
cb7f680b 12418
182cf5a9 12419 stmt = gimple_build_assign (build_simple_mem_ref (unshare_expr (addr)),
12420 stored_val);
75a70cf9 12421 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
cb7f680b 12422
b9a16870 12423 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END);
414c3a2c 12424 t = build_call_expr (t, 0);
75a70cf9 12425 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
12426 gsi_remove (&si, true);
cb7f680b 12427
12428 if (gimple_in_ssa_p (cfun))
12429 update_ssa (TODO_update_ssa_no_phi);
12430 return true;
12431}
12432
48e1416a 12433/* Expand an GIMPLE_OMP_ATOMIC statement. We try to expand
12434 using expand_omp_atomic_fetch_op. If it failed, we try to
cb7f680b 12435 call expand_omp_atomic_pipeline, and if it fails too, the
12436 ultimate fallback is wrapping the operation in a mutex
48e1416a 12437 (expand_omp_atomic_mutex). REGION is the atomic region built
12438 by build_omp_regions_1(). */
cb7f680b 12439
12440static void
12441expand_omp_atomic (struct omp_region *region)
12442{
12443 basic_block load_bb = region->entry, store_bb = region->exit;
1a91d914 12444 gomp_atomic_load *load = as_a <gomp_atomic_load *> (last_stmt (load_bb));
12445 gomp_atomic_store *store = as_a <gomp_atomic_store *> (last_stmt (store_bb));
75a70cf9 12446 tree loaded_val = gimple_omp_atomic_load_lhs (load);
12447 tree addr = gimple_omp_atomic_load_rhs (load);
12448 tree stored_val = gimple_omp_atomic_store_val (store);
cb7f680b 12449 tree type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
12450 HOST_WIDE_INT index;
12451
12452 /* Make sure the type is one of the supported sizes. */
e913b5cd 12453 index = tree_to_uhwi (TYPE_SIZE_UNIT (type));
cb7f680b 12454 index = exact_log2 (index);
12455 if (index >= 0 && index <= 4)
12456 {
12457 unsigned int align = TYPE_ALIGN_UNIT (type);
12458
12459 /* __sync builtins require strict data alignment. */
dcf7024c 12460 if (exact_log2 (align) >= index)
cb7f680b 12461 {
3ec11c49 12462 /* Atomic load. */
2169f33b 12463 if (loaded_val == stored_val
12464 && (GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
12465 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
12466 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
3ec11c49 12467 && expand_omp_atomic_load (load_bb, addr, loaded_val, index))
2169f33b 12468 return;
12469
3ec11c49 12470 /* Atomic store. */
2169f33b 12471 if ((GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
12472 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
12473 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
12474 && store_bb == single_succ (load_bb)
12475 && first_stmt (store_bb) == store
3ec11c49 12476 && expand_omp_atomic_store (load_bb, addr, loaded_val,
12477 stored_val, index))
2169f33b 12478 return;
12479
cb7f680b 12480 /* When possible, use specialized atomic update functions. */
12481 if ((INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type))
3ec11c49 12482 && store_bb == single_succ (load_bb)
12483 && expand_omp_atomic_fetch_op (load_bb, addr,
12484 loaded_val, stored_val, index))
12485 return;
cb7f680b 12486
12487 /* If we don't have specialized __sync builtins, try and implement
12488 as a compare and swap loop. */
12489 if (expand_omp_atomic_pipeline (load_bb, store_bb, addr,
12490 loaded_val, stored_val, index))
12491 return;
12492 }
12493 }
12494
12495 /* The ultimate fallback is wrapping the operation in a mutex. */
12496 expand_omp_atomic_mutex (load_bb, store_bb, addr, loaded_val, stored_val);
12497}
12498
1e8e9920 12499
f69b8a4c 12500/* Encode an oacc launch argument. This matches the GOMP_LAUNCH_PACK
e561d5e1 12501 macro on gomp-constants.h. We do not check for overflow. */
12502
12503static tree
12504oacc_launch_pack (unsigned code, tree device, unsigned op)
12505{
12506 tree res;
12507
12508 res = build_int_cst (unsigned_type_node, GOMP_LAUNCH_PACK (code, 0, op));
12509 if (device)
12510 {
12511 device = fold_build2 (LSHIFT_EXPR, unsigned_type_node,
12512 device, build_int_cst (unsigned_type_node,
12513 GOMP_LAUNCH_DEVICE_SHIFT));
12514 res = fold_build2 (BIT_IOR_EXPR, unsigned_type_node, res, device);
12515 }
12516 return res;
12517}
12518
12519/* Look for compute grid dimension clauses and convert to an attribute
12520 attached to FN. This permits the target-side code to (a) massage
12521 the dimensions, (b) emit that data and (c) optimize. Non-constant
12522 dimensions are pushed onto ARGS.
12523
12524 The attribute value is a TREE_LIST. A set of dimensions is
12525 represented as a list of INTEGER_CST. Those that are runtime
f69b8a4c 12526 exprs are represented as an INTEGER_CST of zero.
e561d5e1 12527
12528 TOOO. Normally the attribute will just contain a single such list. If
12529 however it contains a list of lists, this will represent the use of
12530 device_type. Each member of the outer list is an assoc list of
12531 dimensions, keyed by the device type. The first entry will be the
12532 default. Well, that's the plan. */
12533
12534#define OACC_FN_ATTRIB "oacc function"
12535
12536/* Replace any existing oacc fn attribute with updated dimensions. */
12537
12538void
12539replace_oacc_fn_attrib (tree fn, tree dims)
12540{
12541 tree ident = get_identifier (OACC_FN_ATTRIB);
12542 tree attribs = DECL_ATTRIBUTES (fn);
12543
12544 /* If we happen to be present as the first attrib, drop it. */
12545 if (attribs && TREE_PURPOSE (attribs) == ident)
12546 attribs = TREE_CHAIN (attribs);
12547 DECL_ATTRIBUTES (fn) = tree_cons (ident, dims, attribs);
12548}
12549
12550/* Scan CLAUSES for launch dimensions and attach them to the oacc
12551 function attribute. Push any that are non-constant onto the ARGS
6f431819 12552 list, along with an appropriate GOMP_LAUNCH_DIM tag. IS_KERNEL is
12553 true, if these are for a kernels region offload function. */
e561d5e1 12554
31c2b13b 12555void
6f431819 12556set_oacc_fn_attrib (tree fn, tree clauses, bool is_kernel, vec<tree> *args)
e561d5e1 12557{
12558 /* Must match GOMP_DIM ordering. */
12559 static const omp_clause_code ids[]
12560 = { OMP_CLAUSE_NUM_GANGS, OMP_CLAUSE_NUM_WORKERS,
12561 OMP_CLAUSE_VECTOR_LENGTH };
12562 unsigned ix;
12563 tree dims[GOMP_DIM_MAX];
12564 tree attr = NULL_TREE;
12565 unsigned non_const = 0;
12566
12567 for (ix = GOMP_DIM_MAX; ix--;)
12568 {
12569 tree clause = find_omp_clause (clauses, ids[ix]);
12570 tree dim = NULL_TREE;
12571
12572 if (clause)
12573 dim = OMP_CLAUSE_EXPR (clause, ids[ix]);
12574 dims[ix] = dim;
12575 if (dim && TREE_CODE (dim) != INTEGER_CST)
12576 {
12577 dim = integer_zero_node;
12578 non_const |= GOMP_DIM_MASK (ix);
12579 }
12580 attr = tree_cons (NULL_TREE, dim, attr);
6f431819 12581 /* Note kernelness with TREE_PUBLIC. */
12582 if (is_kernel)
12583 TREE_PUBLIC (attr) = 1;
e561d5e1 12584 }
12585
12586 replace_oacc_fn_attrib (fn, attr);
12587
12588 if (non_const)
12589 {
12590 /* Push a dynamic argument set. */
12591 args->safe_push (oacc_launch_pack (GOMP_LAUNCH_DIM,
12592 NULL_TREE, non_const));
12593 for (unsigned ix = 0; ix != GOMP_DIM_MAX; ix++)
12594 if (non_const & GOMP_DIM_MASK (ix))
12595 args->safe_push (dims[ix]);
12596 }
12597}
12598
a1b7fe4b 12599/* Process the routine's dimension clauess to generate an attribute
12600 value. Issue diagnostics as appropriate. We default to SEQ
12601 (OpenACC 2.5 clarifies this). All dimensions have a size of zero
12602 (dynamic). TREE_PURPOSE is set to indicate whether that dimension
12603 can have a loop partitioned on it. non-zero indicates
12604 yes, zero indicates no. By construction once a non-zero has been
12605 reached, further inner dimensions must also be non-zero. We set
12606 TREE_VALUE to zero for the dimensions that may be partitioned and
12607 1 for the other ones -- if a loop is (erroneously) spawned at
12608 an outer level, we don't want to try and partition it. */
12609
12610tree
12611build_oacc_routine_dims (tree clauses)
12612{
12613 /* Must match GOMP_DIM ordering. */
12614 static const omp_clause_code ids[] =
12615 {OMP_CLAUSE_GANG, OMP_CLAUSE_WORKER, OMP_CLAUSE_VECTOR, OMP_CLAUSE_SEQ};
12616 int ix;
12617 int level = -1;
12618
12619 for (; clauses; clauses = OMP_CLAUSE_CHAIN (clauses))
12620 for (ix = GOMP_DIM_MAX + 1; ix--;)
12621 if (OMP_CLAUSE_CODE (clauses) == ids[ix])
12622 {
12623 if (level >= 0)
12624 error_at (OMP_CLAUSE_LOCATION (clauses),
12625 "multiple loop axes specified for routine");
12626 level = ix;
12627 break;
12628 }
12629
12630 /* Default to SEQ. */
12631 if (level < 0)
12632 level = GOMP_DIM_MAX;
12633
12634 tree dims = NULL_TREE;
12635
12636 for (ix = GOMP_DIM_MAX; ix--;)
12637 dims = tree_cons (build_int_cst (boolean_type_node, ix >= level),
12638 build_int_cst (integer_type_node, ix < level), dims);
12639
12640 return dims;
12641}
12642
e561d5e1 12643/* Retrieve the oacc function attrib and return it. Non-oacc
12644 functions will return NULL. */
12645
12646tree
12647get_oacc_fn_attrib (tree fn)
12648{
12649 return lookup_attribute (OACC_FN_ATTRIB, DECL_ATTRIBUTES (fn));
12650}
12651
6f431819 12652/* Return true if this oacc fn attrib is for a kernels offload
12653 region. We use the TREE_PUBLIC flag of each dimension -- only
12654 need to check the first one. */
12655
12656bool
12657oacc_fn_attrib_kernels_p (tree attr)
12658{
12659 return TREE_PUBLIC (TREE_VALUE (attr));
12660}
12661
12662/* Return level at which oacc routine may spawn a partitioned loop, or
12663 -1 if it is not a routine (i.e. is an offload fn). */
12664
12665static int
12666oacc_fn_attrib_level (tree attr)
12667{
12668 tree pos = TREE_VALUE (attr);
12669
12670 if (!TREE_PURPOSE (pos))
12671 return -1;
12672
12673 int ix = 0;
12674 for (ix = 0; ix != GOMP_DIM_MAX;
12675 ix++, pos = TREE_CHAIN (pos))
12676 if (!integer_zerop (TREE_PURPOSE (pos)))
12677 break;
12678
12679 return ix;
12680}
12681
e1037942 12682/* Extract an oacc execution dimension from FN. FN must be an
12683 offloaded function or routine that has already had its execution
12684 dimensions lowered to the target-specific values. */
12685
12686int
12687get_oacc_fn_dim_size (tree fn, int axis)
12688{
12689 tree attrs = get_oacc_fn_attrib (fn);
12690
12691 gcc_assert (axis < GOMP_DIM_MAX);
12692
12693 tree dims = TREE_VALUE (attrs);
12694 while (axis--)
12695 dims = TREE_CHAIN (dims);
12696
12697 int size = TREE_INT_CST_LOW (TREE_VALUE (dims));
12698
12699 return size;
12700}
12701
12702/* Extract the dimension axis from an IFN_GOACC_DIM_POS or
12703 IFN_GOACC_DIM_SIZE call. */
12704
12705int
12706get_oacc_ifn_dim_arg (const gimple *stmt)
12707{
12708 gcc_checking_assert (gimple_call_internal_fn (stmt) == IFN_GOACC_DIM_SIZE
12709 || gimple_call_internal_fn (stmt) == IFN_GOACC_DIM_POS);
12710 tree arg = gimple_call_arg (stmt, 0);
12711 HOST_WIDE_INT axis = TREE_INT_CST_LOW (arg);
12712
12713 gcc_checking_assert (axis >= 0 && axis < GOMP_DIM_MAX);
12714 return (int) axis;
12715}
12716
1a40f20b 12717/* Mark the loops inside the kernels region starting at REGION_ENTRY and ending
12718 at REGION_EXIT. */
12719
12720static void
12721mark_loops_in_oacc_kernels_region (basic_block region_entry,
12722 basic_block region_exit)
12723{
12724 struct loop *outer = region_entry->loop_father;
12725 gcc_assert (region_exit == NULL || outer == region_exit->loop_father);
12726
12727 /* Don't parallelize the kernels region if it contains more than one outer
12728 loop. */
12729 unsigned int nr_outer_loops = 0;
4dae4a1a 12730 struct loop *single_outer = NULL;
1a40f20b 12731 for (struct loop *loop = outer->inner; loop != NULL; loop = loop->next)
12732 {
12733 gcc_assert (loop_outer (loop) == outer);
12734
12735 if (!dominated_by_p (CDI_DOMINATORS, loop->header, region_entry))
12736 continue;
12737
12738 if (region_exit != NULL
12739 && dominated_by_p (CDI_DOMINATORS, loop->header, region_exit))
12740 continue;
12741
12742 nr_outer_loops++;
12743 single_outer = loop;
12744 }
12745 if (nr_outer_loops != 1)
12746 return;
12747
12748 for (struct loop *loop = single_outer->inner; loop != NULL; loop = loop->inner)
12749 if (loop->next)
12750 return;
12751
12752 /* Mark the loops in the region. */
12753 for (struct loop *loop = single_outer; loop != NULL; loop = loop->inner)
12754 loop->in_oacc_kernels_region = true;
12755}
12756
56686608 12757/* Types used to pass grid and wortkgroup sizes to kernel invocation. */
12758
12759struct GTY(()) grid_launch_attributes_trees
12760{
12761 tree kernel_dim_array_type;
12762 tree kernel_lattrs_dimnum_decl;
12763 tree kernel_lattrs_grid_decl;
12764 tree kernel_lattrs_group_decl;
12765 tree kernel_launch_attributes_type;
12766};
12767
12768static GTY(()) struct grid_launch_attributes_trees *grid_attr_trees;
12769
12770/* Create types used to pass kernel launch attributes to target. */
12771
12772static void
12773grid_create_kernel_launch_attr_types (void)
12774{
12775 if (grid_attr_trees)
12776 return;
12777 grid_attr_trees = ggc_alloc <grid_launch_attributes_trees> ();
12778
12779 tree dim_arr_index_type
12780 = build_index_type (build_int_cst (integer_type_node, 2));
12781 grid_attr_trees->kernel_dim_array_type
12782 = build_array_type (uint32_type_node, dim_arr_index_type);
12783
12784 grid_attr_trees->kernel_launch_attributes_type = make_node (RECORD_TYPE);
12785 grid_attr_trees->kernel_lattrs_dimnum_decl
12786 = build_decl (BUILTINS_LOCATION, FIELD_DECL, get_identifier ("ndim"),
12787 uint32_type_node);
12788 DECL_CHAIN (grid_attr_trees->kernel_lattrs_dimnum_decl) = NULL_TREE;
12789
12790 grid_attr_trees->kernel_lattrs_grid_decl
12791 = build_decl (BUILTINS_LOCATION, FIELD_DECL, get_identifier ("grid_size"),
12792 grid_attr_trees->kernel_dim_array_type);
12793 DECL_CHAIN (grid_attr_trees->kernel_lattrs_grid_decl)
12794 = grid_attr_trees->kernel_lattrs_dimnum_decl;
12795 grid_attr_trees->kernel_lattrs_group_decl
12796 = build_decl (BUILTINS_LOCATION, FIELD_DECL, get_identifier ("group_size"),
12797 grid_attr_trees->kernel_dim_array_type);
12798 DECL_CHAIN (grid_attr_trees->kernel_lattrs_group_decl)
12799 = grid_attr_trees->kernel_lattrs_grid_decl;
12800 finish_builtin_struct (grid_attr_trees->kernel_launch_attributes_type,
12801 "__gomp_kernel_launch_attributes",
12802 grid_attr_trees->kernel_lattrs_group_decl, NULL_TREE);
12803}
12804
12805/* Insert before the current statement in GSI a store of VALUE to INDEX of
12806 array (of type kernel_dim_array_type) FLD_DECL of RANGE_VAR. VALUE must be
12807 of type uint32_type_node. */
12808
12809static void
12810grid_insert_store_range_dim (gimple_stmt_iterator *gsi, tree range_var,
12811 tree fld_decl, int index, tree value)
12812{
12813 tree ref = build4 (ARRAY_REF, uint32_type_node,
12814 build3 (COMPONENT_REF,
12815 grid_attr_trees->kernel_dim_array_type,
12816 range_var, fld_decl, NULL_TREE),
12817 build_int_cst (integer_type_node, index),
12818 NULL_TREE, NULL_TREE);
12819 gsi_insert_before (gsi, gimple_build_assign (ref, value), GSI_SAME_STMT);
12820}
12821
12822/* Return a tree representation of a pointer to a structure with grid and
12823 work-group size information. Statements filling that information will be
12824 inserted before GSI, TGT_STMT is the target statement which has the
12825 necessary information in it. */
12826
12827static tree
12828grid_get_kernel_launch_attributes (gimple_stmt_iterator *gsi,
12829 gomp_target *tgt_stmt)
12830{
12831 grid_create_kernel_launch_attr_types ();
12832 tree u32_one = build_one_cst (uint32_type_node);
12833 tree lattrs = create_tmp_var (grid_attr_trees->kernel_launch_attributes_type,
12834 "__kernel_launch_attrs");
12835
12836 unsigned max_dim = 0;
12837 for (tree clause = gimple_omp_target_clauses (tgt_stmt);
12838 clause;
12839 clause = OMP_CLAUSE_CHAIN (clause))
12840 {
12841 if (OMP_CLAUSE_CODE (clause) != OMP_CLAUSE__GRIDDIM_)
12842 continue;
12843
12844 unsigned dim = OMP_CLAUSE__GRIDDIM__DIMENSION (clause);
12845 max_dim = MAX (dim, max_dim);
12846
12847 grid_insert_store_range_dim (gsi, lattrs,
12848 grid_attr_trees->kernel_lattrs_grid_decl,
12849 dim, OMP_CLAUSE__GRIDDIM__SIZE (clause));
12850 grid_insert_store_range_dim (gsi, lattrs,
12851 grid_attr_trees->kernel_lattrs_group_decl,
12852 dim, OMP_CLAUSE__GRIDDIM__GROUP (clause));
12853 }
12854
12855 tree dimref = build3 (COMPONENT_REF, uint32_type_node, lattrs,
12856 grid_attr_trees->kernel_lattrs_dimnum_decl, NULL_TREE);
12857 /* At this moment we cannot gridify a loop with a collapse clause. */
12858 /* TODO: Adjust when we support bigger collapse. */
12859 gcc_assert (max_dim == 0);
12860 gsi_insert_before (gsi, gimple_build_assign (dimref, u32_one), GSI_SAME_STMT);
12861 TREE_ADDRESSABLE (lattrs) = 1;
12862 return build_fold_addr_expr (lattrs);
12863}
12864
12865/* Build target argument identifier from the DEVICE identifier, value
12866 identifier ID and whether the element also has a SUBSEQUENT_PARAM. */
12867
12868static tree
12869get_target_argument_identifier_1 (int device, bool subseqent_param, int id)
12870{
12871 tree t = build_int_cst (integer_type_node, device);
12872 if (subseqent_param)
12873 t = fold_build2 (BIT_IOR_EXPR, integer_type_node, t,
12874 build_int_cst (integer_type_node,
12875 GOMP_TARGET_ARG_SUBSEQUENT_PARAM));
12876 t = fold_build2 (BIT_IOR_EXPR, integer_type_node, t,
12877 build_int_cst (integer_type_node, id));
12878 return t;
12879}
12880
12881/* Like above but return it in type that can be directly stored as an element
12882 of the argument array. */
12883
12884static tree
12885get_target_argument_identifier (int device, bool subseqent_param, int id)
12886{
12887 tree t = get_target_argument_identifier_1 (device, subseqent_param, id);
12888 return fold_convert (ptr_type_node, t);
12889}
12890
12891/* Return a target argument consisting of DEVICE identifier, value identifier
12892 ID, and the actual VALUE. */
12893
12894static tree
12895get_target_argument_value (gimple_stmt_iterator *gsi, int device, int id,
12896 tree value)
12897{
12898 tree t = fold_build2 (LSHIFT_EXPR, integer_type_node,
12899 fold_convert (integer_type_node, value),
12900 build_int_cst (unsigned_type_node,
12901 GOMP_TARGET_ARG_VALUE_SHIFT));
12902 t = fold_build2 (BIT_IOR_EXPR, integer_type_node, t,
12903 get_target_argument_identifier_1 (device, false, id));
12904 t = fold_convert (ptr_type_node, t);
12905 return force_gimple_operand_gsi (gsi, t, true, NULL, true, GSI_SAME_STMT);
12906}
12907
12908/* If VALUE is an integer constant greater than -2^15 and smaller than 2^15,
12909 push one argument to ARGS with both the DEVICE, ID and VALUE embedded in it,
12910 otherwise push an identifier (with DEVICE and ID) and the VALUE in two
12911 arguments. */
12912
12913static void
12914push_target_argument_according_to_value (gimple_stmt_iterator *gsi, int device,
12915 int id, tree value, vec <tree> *args)
12916{
12917 if (tree_fits_shwi_p (value)
12918 && tree_to_shwi (value) > -(1 << 15)
12919 && tree_to_shwi (value) < (1 << 15))
12920 args->quick_push (get_target_argument_value (gsi, device, id, value));
12921 else
12922 {
12923 args->quick_push (get_target_argument_identifier (device, true, id));
12924 value = fold_convert (ptr_type_node, value);
12925 value = force_gimple_operand_gsi (gsi, value, true, NULL, true,
12926 GSI_SAME_STMT);
12927 args->quick_push (value);
12928 }
12929}
12930
12931/* Create an array of arguments that is then passed to GOMP_target. */
12932
12933static tree
12934get_target_arguments (gimple_stmt_iterator *gsi, gomp_target *tgt_stmt)
12935{
12936 auto_vec <tree, 6> args;
12937 tree clauses = gimple_omp_target_clauses (tgt_stmt);
12938 tree t, c = find_omp_clause (clauses, OMP_CLAUSE_NUM_TEAMS);
12939 if (c)
12940 t = OMP_CLAUSE_NUM_TEAMS_EXPR (c);
12941 else
12942 t = integer_minus_one_node;
12943 push_target_argument_according_to_value (gsi, GOMP_TARGET_ARG_DEVICE_ALL,
12944 GOMP_TARGET_ARG_NUM_TEAMS, t, &args);
12945
12946 c = find_omp_clause (clauses, OMP_CLAUSE_THREAD_LIMIT);
12947 if (c)
12948 t = OMP_CLAUSE_THREAD_LIMIT_EXPR (c);
12949 else
12950 t = integer_minus_one_node;
12951 push_target_argument_according_to_value (gsi, GOMP_TARGET_ARG_DEVICE_ALL,
12952 GOMP_TARGET_ARG_THREAD_LIMIT, t,
12953 &args);
12954
12955 /* Add HSA-specific grid sizes, if available. */
12956 if (find_omp_clause (gimple_omp_target_clauses (tgt_stmt),
12957 OMP_CLAUSE__GRIDDIM_))
12958 {
12959 t = get_target_argument_identifier (GOMP_DEVICE_HSA, true,
12960 GOMP_TARGET_ARG_HSA_KERNEL_ATTRIBUTES);
12961 args.quick_push (t);
12962 args.quick_push (grid_get_kernel_launch_attributes (gsi, tgt_stmt));
12963 }
12964
12965 /* Produce more, perhaps device specific, arguments here. */
12966
12967 tree argarray = create_tmp_var (build_array_type_nelts (ptr_type_node,
12968 args.length () + 1),
12969 ".omp_target_args");
12970 for (unsigned i = 0; i < args.length (); i++)
12971 {
12972 tree ref = build4 (ARRAY_REF, ptr_type_node, argarray,
12973 build_int_cst (integer_type_node, i),
12974 NULL_TREE, NULL_TREE);
12975 gsi_insert_before (gsi, gimple_build_assign (ref, args[i]),
12976 GSI_SAME_STMT);
12977 }
12978 tree ref = build4 (ARRAY_REF, ptr_type_node, argarray,
12979 build_int_cst (integer_type_node, args.length ()),
12980 NULL_TREE, NULL_TREE);
12981 gsi_insert_before (gsi, gimple_build_assign (ref, null_pointer_node),
12982 GSI_SAME_STMT);
12983 TREE_ADDRESSABLE (argarray) = 1;
12984 return build_fold_addr_expr (argarray);
12985}
12986
ca4c3545 12987/* Expand the GIMPLE_OMP_TARGET starting at REGION. */
773c5ba7 12988
12989static void
bc7bff74 12990expand_omp_target (struct omp_region *region)
773c5ba7 12991{
bc7bff74 12992 basic_block entry_bb, exit_bb, new_bb;
ca4c3545 12993 struct function *child_cfun;
12994 tree child_fn, block, t;
bc7bff74 12995 gimple_stmt_iterator gsi;
1a91d914 12996 gomp_target *entry_stmt;
42acab1c 12997 gimple *stmt;
bc7bff74 12998 edge e;
ca4c3545 12999 bool offloaded, data_region;
bc7bff74 13000
1a91d914 13001 entry_stmt = as_a <gomp_target *> (last_stmt (region->entry));
bc7bff74 13002 new_bb = region->entry;
ca4c3545 13003
13004 offloaded = is_gimple_omp_offloaded (entry_stmt);
13005 switch (gimple_omp_target_kind (entry_stmt))
13006 {
e561d5e1 13007 case GF_OMP_TARGET_KIND_REGION:
13008 case GF_OMP_TARGET_KIND_UPDATE:
43895be5 13009 case GF_OMP_TARGET_KIND_ENTER_DATA:
13010 case GF_OMP_TARGET_KIND_EXIT_DATA:
13011 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
13012 case GF_OMP_TARGET_KIND_OACC_KERNELS:
ca4c3545 13013 case GF_OMP_TARGET_KIND_OACC_UPDATE:
13014 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
2fc5e987 13015 case GF_OMP_TARGET_KIND_OACC_DECLARE:
ca4c3545 13016 data_region = false;
13017 break;
13018 case GF_OMP_TARGET_KIND_DATA:
13019 case GF_OMP_TARGET_KIND_OACC_DATA:
571b3486 13020 case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
ca4c3545 13021 data_region = true;
13022 break;
13023 default:
13024 gcc_unreachable ();
13025 }
13026
13027 child_fn = NULL_TREE;
13028 child_cfun = NULL;
13029 if (offloaded)
bc7bff74 13030 {
13031 child_fn = gimple_omp_target_child_fn (entry_stmt);
13032 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
13033 }
13034
ca4c3545 13035 /* Supported by expand_omp_taskreg, but not here. */
13036 if (child_cfun != NULL)
13037 gcc_checking_assert (!child_cfun->cfg);
13038 gcc_checking_assert (!gimple_in_ssa_p (cfun));
13039
bc7bff74 13040 entry_bb = region->entry;
13041 exit_bb = region->exit;
13042
1a40f20b 13043 if (gimple_omp_target_kind (entry_stmt) == GF_OMP_TARGET_KIND_OACC_KERNELS)
13044 mark_loops_in_oacc_kernels_region (region->entry, region->exit);
13045
ca4c3545 13046 if (offloaded)
bc7bff74 13047 {
13048 unsigned srcidx, dstidx, num;
13049
ca4c3545 13050 /* If the offloading region needs data sent from the parent
bc7bff74 13051 function, then the very first statement (except possible
ca4c3545 13052 tree profile counter updates) of the offloading body
bc7bff74 13053 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
13054 &.OMP_DATA_O is passed as an argument to the child function,
13055 we need to replace it with the argument as seen by the child
13056 function.
13057
13058 In most cases, this will end up being the identity assignment
ca4c3545 13059 .OMP_DATA_I = .OMP_DATA_I. However, if the offloading body had
bc7bff74 13060 a function call that has been inlined, the original PARM_DECL
13061 .OMP_DATA_I may have been converted into a different local
13062 variable. In which case, we need to keep the assignment. */
ca4c3545 13063 tree data_arg = gimple_omp_target_data_arg (entry_stmt);
13064 if (data_arg)
bc7bff74 13065 {
13066 basic_block entry_succ_bb = single_succ (entry_bb);
13067 gimple_stmt_iterator gsi;
13068 tree arg;
42acab1c 13069 gimple *tgtcopy_stmt = NULL;
ca4c3545 13070 tree sender = TREE_VEC_ELT (data_arg, 0);
bc7bff74 13071
13072 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
13073 {
13074 gcc_assert (!gsi_end_p (gsi));
13075 stmt = gsi_stmt (gsi);
13076 if (gimple_code (stmt) != GIMPLE_ASSIGN)
13077 continue;
13078
13079 if (gimple_num_ops (stmt) == 2)
13080 {
13081 tree arg = gimple_assign_rhs1 (stmt);
13082
13083 /* We're ignoring the subcode because we're
13084 effectively doing a STRIP_NOPS. */
13085
13086 if (TREE_CODE (arg) == ADDR_EXPR
13087 && TREE_OPERAND (arg, 0) == sender)
13088 {
13089 tgtcopy_stmt = stmt;
13090 break;
13091 }
13092 }
13093 }
13094
13095 gcc_assert (tgtcopy_stmt != NULL);
13096 arg = DECL_ARGUMENTS (child_fn);
13097
13098 gcc_assert (gimple_assign_lhs (tgtcopy_stmt) == arg);
13099 gsi_remove (&gsi, true);
13100 }
13101
13102 /* Declare local variables needed in CHILD_CFUN. */
13103 block = DECL_INITIAL (child_fn);
13104 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
ca4c3545 13105 /* The gimplifier could record temporaries in the offloading block
bc7bff74 13106 rather than in containing function's local_decls chain,
13107 which would mean cgraph missed finalizing them. Do it now. */
13108 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
13109 if (TREE_CODE (t) == VAR_DECL
13110 && TREE_STATIC (t)
13111 && !DECL_EXTERNAL (t))
97221fd7 13112 varpool_node::finalize_decl (t);
bc7bff74 13113 DECL_SAVED_TREE (child_fn) = NULL;
13114 /* We'll create a CFG for child_fn, so no gimple body is needed. */
13115 gimple_set_body (child_fn, NULL);
13116 TREE_USED (block) = 1;
13117
13118 /* Reset DECL_CONTEXT on function arguments. */
13119 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
13120 DECL_CONTEXT (t) = child_fn;
13121
ca4c3545 13122 /* Split ENTRY_BB at GIMPLE_*,
bc7bff74 13123 so that it can be moved to the child function. */
13124 gsi = gsi_last_bb (entry_bb);
13125 stmt = gsi_stmt (gsi);
ca4c3545 13126 gcc_assert (stmt
13127 && gimple_code (stmt) == gimple_code (entry_stmt));
bc7bff74 13128 e = split_block (entry_bb, stmt);
923635e7 13129 gsi_remove (&gsi, true);
bc7bff74 13130 entry_bb = e->dest;
13131 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
13132
13133 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
13134 if (exit_bb)
13135 {
13136 gsi = gsi_last_bb (exit_bb);
13137 gcc_assert (!gsi_end_p (gsi)
13138 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
13139 stmt = gimple_build_return (NULL);
13140 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
13141 gsi_remove (&gsi, true);
13142 }
13143
ca4c3545 13144 /* Move the offloading region into CHILD_CFUN. */
bc7bff74 13145
13146 block = gimple_block (entry_stmt);
13147
13148 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
13149 if (exit_bb)
13150 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
13151 /* When the OMP expansion process cannot guarantee an up-to-date
13152 loop tree arrange for the child function to fixup loops. */
13153 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
13154 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
13155
13156 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
13157 num = vec_safe_length (child_cfun->local_decls);
13158 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
13159 {
13160 t = (*child_cfun->local_decls)[srcidx];
13161 if (DECL_CONTEXT (t) == cfun->decl)
13162 continue;
13163 if (srcidx != dstidx)
13164 (*child_cfun->local_decls)[dstidx] = t;
13165 dstidx++;
13166 }
13167 if (dstidx != num)
13168 vec_safe_truncate (child_cfun->local_decls, dstidx);
13169
13170 /* Inform the callgraph about the new function. */
613f2c38 13171 child_cfun->curr_properties = cfun->curr_properties;
13172 child_cfun->has_simduid_loops |= cfun->has_simduid_loops;
13173 child_cfun->has_force_vectorize_loops |= cfun->has_force_vectorize_loops;
6a77ed3d 13174 cgraph_node *node = cgraph_node::get_create (child_fn);
13175 node->parallelized_function = 1;
415d1b9a 13176 cgraph_node::add_new_function (child_fn, true);
bc7bff74 13177
dccabdd1 13178 /* Add the new function to the offload table. */
5f3001a9 13179 if (ENABLE_OFFLOADING)
13180 vec_safe_push (offload_funcs, child_fn);
dccabdd1 13181
9561765e 13182 bool need_asm = DECL_ASSEMBLER_NAME_SET_P (current_function_decl)
13183 && !DECL_ASSEMBLER_NAME_SET_P (child_fn);
13184
bc7bff74 13185 /* Fix the callgraph edges for child_cfun. Those for cfun will be
13186 fixed in a following pass. */
13187 push_cfun (child_cfun);
9561765e 13188 if (need_asm)
13189 assign_assembler_name_if_neeeded (child_fn);
35ee1c66 13190 cgraph_edge::rebuild_edges ();
bc7bff74 13191
13192 /* Some EH regions might become dead, see PR34608. If
13193 pass_cleanup_cfg isn't the first pass to happen with the
13194 new child, these dead EH edges might cause problems.
13195 Clean them up now. */
13196 if (flag_exceptions)
13197 {
13198 basic_block bb;
13199 bool changed = false;
13200
fc00614f 13201 FOR_EACH_BB_FN (bb, cfun)
bc7bff74 13202 changed |= gimple_purge_dead_eh_edges (bb);
13203 if (changed)
13204 cleanup_tree_cfg ();
13205 }
382ecba7 13206 if (flag_checking && !loops_state_satisfies_p (LOOPS_NEED_FIXUP))
86a932e0 13207 verify_loop_structure ();
bc7bff74 13208 pop_cfun ();
9561765e 13209
13210 if (dump_file && !gimple_in_ssa_p (cfun))
13211 {
13212 omp_any_child_fn_dumped = true;
13213 dump_function_header (dump_file, child_fn, dump_flags);
13214 dump_function_to_file (child_fn, dump_file, dump_flags);
13215 }
bc7bff74 13216 }
13217
ca4c3545 13218 /* Emit a library call to launch the offloading region, or do data
bc7bff74 13219 transfers. */
43895be5 13220 tree t1, t2, t3, t4, device, cond, depend, c, clauses;
bc7bff74 13221 enum built_in_function start_ix;
13222 location_t clause_loc;
43895be5 13223 unsigned int flags_i = 0;
6f431819 13224 bool oacc_kernels_p = false;
bc7bff74 13225
ca4c3545 13226 switch (gimple_omp_target_kind (entry_stmt))
13227 {
13228 case GF_OMP_TARGET_KIND_REGION:
13229 start_ix = BUILT_IN_GOMP_TARGET;
13230 break;
13231 case GF_OMP_TARGET_KIND_DATA:
13232 start_ix = BUILT_IN_GOMP_TARGET_DATA;
13233 break;
13234 case GF_OMP_TARGET_KIND_UPDATE:
13235 start_ix = BUILT_IN_GOMP_TARGET_UPDATE;
13236 break;
43895be5 13237 case GF_OMP_TARGET_KIND_ENTER_DATA:
13238 start_ix = BUILT_IN_GOMP_TARGET_ENTER_EXIT_DATA;
13239 break;
13240 case GF_OMP_TARGET_KIND_EXIT_DATA:
13241 start_ix = BUILT_IN_GOMP_TARGET_ENTER_EXIT_DATA;
13242 flags_i |= GOMP_TARGET_FLAG_EXIT_DATA;
13243 break;
ca4c3545 13244 case GF_OMP_TARGET_KIND_OACC_KERNELS:
6f431819 13245 oacc_kernels_p = true;
13246 /* FALLTHROUGH */
13247 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
ca4c3545 13248 start_ix = BUILT_IN_GOACC_PARALLEL;
13249 break;
13250 case GF_OMP_TARGET_KIND_OACC_DATA:
2bf3f448 13251 case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
ca4c3545 13252 start_ix = BUILT_IN_GOACC_DATA_START;
13253 break;
13254 case GF_OMP_TARGET_KIND_OACC_UPDATE:
13255 start_ix = BUILT_IN_GOACC_UPDATE;
13256 break;
13257 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
13258 start_ix = BUILT_IN_GOACC_ENTER_EXIT_DATA;
13259 break;
2fc5e987 13260 case GF_OMP_TARGET_KIND_OACC_DECLARE:
13261 start_ix = BUILT_IN_GOACC_DECLARE;
13262 break;
ca4c3545 13263 default:
13264 gcc_unreachable ();
13265 }
bc7bff74 13266
ca4c3545 13267 clauses = gimple_omp_target_clauses (entry_stmt);
bc7bff74 13268
ca4c3545 13269 /* By default, the value of DEVICE is GOMP_DEVICE_ICV (let runtime
13270 library choose) and there is no conditional. */
bc7bff74 13271 cond = NULL_TREE;
ca4c3545 13272 device = build_int_cst (integer_type_node, GOMP_DEVICE_ICV);
bc7bff74 13273
13274 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
13275 if (c)
13276 cond = OMP_CLAUSE_IF_EXPR (c);
13277
13278 c = find_omp_clause (clauses, OMP_CLAUSE_DEVICE);
13279 if (c)
13280 {
ca4c3545 13281 /* Even if we pass it to all library function calls, it is currently only
13282 defined/used for the OpenMP target ones. */
13283 gcc_checking_assert (start_ix == BUILT_IN_GOMP_TARGET
13284 || start_ix == BUILT_IN_GOMP_TARGET_DATA
43895be5 13285 || start_ix == BUILT_IN_GOMP_TARGET_UPDATE
13286 || start_ix == BUILT_IN_GOMP_TARGET_ENTER_EXIT_DATA);
ca4c3545 13287
bc7bff74 13288 device = OMP_CLAUSE_DEVICE_ID (c);
13289 clause_loc = OMP_CLAUSE_LOCATION (c);
13290 }
13291 else
13292 clause_loc = gimple_location (entry_stmt);
13293
43895be5 13294 c = find_omp_clause (clauses, OMP_CLAUSE_NOWAIT);
13295 if (c)
13296 flags_i |= GOMP_TARGET_FLAG_NOWAIT;
13297
bc7bff74 13298 /* Ensure 'device' is of the correct type. */
13299 device = fold_convert_loc (clause_loc, integer_type_node, device);
13300
13301 /* If we found the clause 'if (cond)', build
ca4c3545 13302 (cond ? device : GOMP_DEVICE_HOST_FALLBACK). */
bc7bff74 13303 if (cond)
13304 {
13305 cond = gimple_boolify (cond);
13306
13307 basic_block cond_bb, then_bb, else_bb;
13308 edge e;
13309 tree tmp_var;
13310
f9e245b2 13311 tmp_var = create_tmp_var (TREE_TYPE (device));
ca4c3545 13312 if (offloaded)
4302d619 13313 e = split_block_after_labels (new_bb);
ca4c3545 13314 else
bc7bff74 13315 {
13316 gsi = gsi_last_bb (new_bb);
13317 gsi_prev (&gsi);
13318 e = split_block (new_bb, gsi_stmt (gsi));
13319 }
bc7bff74 13320 cond_bb = e->src;
13321 new_bb = e->dest;
13322 remove_edge (e);
13323
13324 then_bb = create_empty_bb (cond_bb);
13325 else_bb = create_empty_bb (then_bb);
13326 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
13327 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
13328
13329 stmt = gimple_build_cond_empty (cond);
13330 gsi = gsi_last_bb (cond_bb);
13331 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
13332
13333 gsi = gsi_start_bb (then_bb);
13334 stmt = gimple_build_assign (tmp_var, device);
13335 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
13336
13337 gsi = gsi_start_bb (else_bb);
13338 stmt = gimple_build_assign (tmp_var,
ca4c3545 13339 build_int_cst (integer_type_node,
13340 GOMP_DEVICE_HOST_FALLBACK));
bc7bff74 13341 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
13342
13343 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
13344 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
b3083327 13345 add_bb_to_loop (then_bb, cond_bb->loop_father);
13346 add_bb_to_loop (else_bb, cond_bb->loop_father);
bc7bff74 13347 make_edge (then_bb, new_bb, EDGE_FALLTHRU);
13348 make_edge (else_bb, new_bb, EDGE_FALLTHRU);
13349
13350 device = tmp_var;
13351 }
13352
13353 gsi = gsi_last_bb (new_bb);
13354 t = gimple_omp_target_data_arg (entry_stmt);
13355 if (t == NULL)
13356 {
13357 t1 = size_zero_node;
13358 t2 = build_zero_cst (ptr_type_node);
13359 t3 = t2;
13360 t4 = t2;
13361 }
13362 else
13363 {
13364 t1 = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (TREE_VEC_ELT (t, 1))));
13365 t1 = size_binop (PLUS_EXPR, t1, size_int (1));
13366 t2 = build_fold_addr_expr (TREE_VEC_ELT (t, 0));
13367 t3 = build_fold_addr_expr (TREE_VEC_ELT (t, 1));
13368 t4 = build_fold_addr_expr (TREE_VEC_ELT (t, 2));
13369 }
13370
42acab1c 13371 gimple *g;
e561d5e1 13372 bool tagging = false;
ca4c3545 13373 /* The maximum number used by any start_ix, without varargs. */
02c05c9b 13374 auto_vec<tree, 11> args;
13375 args.quick_push (device);
ca4c3545 13376 if (offloaded)
02c05c9b 13377 args.quick_push (build_fold_addr_expr (child_fn));
02c05c9b 13378 args.quick_push (t1);
13379 args.quick_push (t2);
13380 args.quick_push (t3);
13381 args.quick_push (t4);
ca4c3545 13382 switch (start_ix)
13383 {
13384 case BUILT_IN_GOACC_DATA_START:
2fc5e987 13385 case BUILT_IN_GOACC_DECLARE:
ca4c3545 13386 case BUILT_IN_GOMP_TARGET_DATA:
43895be5 13387 break;
13388 case BUILT_IN_GOMP_TARGET:
ca4c3545 13389 case BUILT_IN_GOMP_TARGET_UPDATE:
43895be5 13390 case BUILT_IN_GOMP_TARGET_ENTER_EXIT_DATA:
13391 args.quick_push (build_int_cst (unsigned_type_node, flags_i));
13392 c = find_omp_clause (clauses, OMP_CLAUSE_DEPEND);
13393 if (c)
13394 depend = OMP_CLAUSE_DECL (c);
13395 else
13396 depend = build_int_cst (ptr_type_node, 0);
13397 args.quick_push (depend);
9561765e 13398 if (start_ix == BUILT_IN_GOMP_TARGET)
56686608 13399 args.quick_push (get_target_arguments (&gsi, entry_stmt));
ca4c3545 13400 break;
13401 case BUILT_IN_GOACC_PARALLEL:
13402 {
6f431819 13403 set_oacc_fn_attrib (child_fn, clauses, oacc_kernels_p, &args);
e561d5e1 13404 tagging = true;
ca4c3545 13405 }
13406 /* FALLTHRU */
13407 case BUILT_IN_GOACC_ENTER_EXIT_DATA:
13408 case BUILT_IN_GOACC_UPDATE:
13409 {
e561d5e1 13410 tree t_async = NULL_TREE;
13411
13412 /* If present, use the value specified by the respective
ca4c3545 13413 clause, making sure that is of the correct type. */
13414 c = find_omp_clause (clauses, OMP_CLAUSE_ASYNC);
13415 if (c)
13416 t_async = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
13417 integer_type_node,
13418 OMP_CLAUSE_ASYNC_EXPR (c));
e561d5e1 13419 else if (!tagging)
13420 /* Default values for t_async. */
13421 t_async = fold_convert_loc (gimple_location (entry_stmt),
13422 integer_type_node,
13423 build_int_cst (integer_type_node,
13424 GOMP_ASYNC_SYNC));
13425 if (tagging && t_async)
ca4c3545 13426 {
a6258f5a 13427 unsigned HOST_WIDE_INT i_async = GOMP_LAUNCH_OP_MAX;
ca4c3545 13428
e561d5e1 13429 if (TREE_CODE (t_async) == INTEGER_CST)
ca4c3545 13430 {
e561d5e1 13431 /* See if we can pack the async arg in to the tag's
13432 operand. */
13433 i_async = TREE_INT_CST_LOW (t_async);
e561d5e1 13434 if (i_async < GOMP_LAUNCH_OP_MAX)
13435 t_async = NULL_TREE;
a6258f5a 13436 else
13437 i_async = GOMP_LAUNCH_OP_MAX;
ca4c3545 13438 }
a6258f5a 13439 args.safe_push (oacc_launch_pack (GOMP_LAUNCH_ASYNC, NULL_TREE,
13440 i_async));
e561d5e1 13441 }
13442 if (t_async)
13443 args.safe_push (t_async);
ca4c3545 13444
e561d5e1 13445 /* Save the argument index, and ... */
13446 unsigned t_wait_idx = args.length ();
13447 unsigned num_waits = 0;
13448 c = find_omp_clause (clauses, OMP_CLAUSE_WAIT);
13449 if (!tagging || c)
13450 /* ... push a placeholder. */
13451 args.safe_push (integer_zero_node);
13452
13453 for (; c; c = OMP_CLAUSE_CHAIN (c))
13454 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_WAIT)
13455 {
13456 args.safe_push (fold_convert_loc (OMP_CLAUSE_LOCATION (c),
13457 integer_type_node,
13458 OMP_CLAUSE_WAIT_EXPR (c)));
13459 num_waits++;
13460 }
13461
13462 if (!tagging || num_waits)
13463 {
13464 tree len;
13465
13466 /* Now that we know the number, update the placeholder. */
13467 if (tagging)
13468 len = oacc_launch_pack (GOMP_LAUNCH_WAIT, NULL_TREE, num_waits);
13469 else
13470 len = build_int_cst (integer_type_node, num_waits);
13471 len = fold_convert_loc (gimple_location (entry_stmt),
13472 unsigned_type_node, len);
13473 args[t_wait_idx] = len;
ca4c3545 13474 }
13475 }
13476 break;
13477 default:
13478 gcc_unreachable ();
bc7bff74 13479 }
e561d5e1 13480 if (tagging)
13481 /* Push terminal marker - zero. */
13482 args.safe_push (oacc_launch_pack (0, NULL_TREE, 0));
ca4c3545 13483
02c05c9b 13484 g = gimple_build_call_vec (builtin_decl_explicit (start_ix), args);
bc7bff74 13485 gimple_set_location (g, gimple_location (entry_stmt));
13486 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
ca4c3545 13487 if (!offloaded)
bc7bff74 13488 {
13489 g = gsi_stmt (gsi);
13490 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_TARGET);
13491 gsi_remove (&gsi, true);
13492 }
43895be5 13493 if (data_region && region->exit)
bc7bff74 13494 {
13495 gsi = gsi_last_bb (region->exit);
13496 g = gsi_stmt (gsi);
13497 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_RETURN);
13498 gsi_remove (&gsi, true);
13499 }
13500}
13501
56686608 13502/* Expand KFOR loop as a GPGPU kernel, i.e. as a body only with iteration
13503 variable derived from the thread number. */
773c5ba7 13504
13505static void
56686608 13506grid_expand_omp_for_loop (struct omp_region *kfor)
773c5ba7 13507{
56686608 13508 tree t, threadid;
13509 tree type, itype;
13510 gimple_stmt_iterator gsi;
13511 tree n1, step;
13512 struct omp_for_data fd;
1d22f541 13513
56686608 13514 gomp_for *for_stmt = as_a <gomp_for *> (last_stmt (kfor->entry));
13515 gcc_checking_assert (gimple_omp_for_kind (for_stmt)
13516 == GF_OMP_FOR_KIND_GRID_LOOP);
13517 basic_block body_bb = FALLTHRU_EDGE (kfor->entry)->dest;
d1d5b012 13518
56686608 13519 gcc_assert (gimple_omp_for_collapse (for_stmt) == 1);
13520 gcc_assert (kfor->cont);
13521 extract_omp_for_data (for_stmt, &fd, NULL);
bc7bff74 13522
56686608 13523 itype = type = TREE_TYPE (fd.loop.v);
13524 if (POINTER_TYPE_P (type))
13525 itype = signed_type_for (type);
773c5ba7 13526
56686608 13527 gsi = gsi_start_bb (body_bb);
1d22f541 13528
56686608 13529 n1 = fd.loop.n1;
13530 step = fd.loop.step;
13531 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
13532 true, NULL_TREE, true, GSI_SAME_STMT);
13533 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
13534 true, NULL_TREE, true, GSI_SAME_STMT);
13535 threadid = build_call_expr (builtin_decl_explicit
13536 (BUILT_IN_OMP_GET_THREAD_NUM), 0);
13537 threadid = fold_convert (itype, threadid);
13538 threadid = force_gimple_operand_gsi (&gsi, threadid, true, NULL_TREE,
13539 true, GSI_SAME_STMT);
fd6481cf 13540
56686608 13541 tree startvar = fd.loop.v;
13542 t = fold_build2 (MULT_EXPR, itype, threadid, step);
13543 if (POINTER_TYPE_P (type))
13544 t = fold_build_pointer_plus (n1, t);
13545 else
13546 t = fold_build2 (PLUS_EXPR, type, t, n1);
13547 t = fold_convert (type, t);
13548 t = force_gimple_operand_gsi (&gsi, t,
13549 DECL_P (startvar)
13550 && TREE_ADDRESSABLE (startvar),
13551 NULL_TREE, true, GSI_SAME_STMT);
13552 gassign *assign_stmt = gimple_build_assign (startvar, t);
13553 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
773c5ba7 13554
56686608 13555 /* Remove the omp for statement */
13556 gsi = gsi_last_bb (kfor->entry);
13557 gsi_remove (&gsi, true);
773c5ba7 13558
56686608 13559 /* Remove the GIMPLE_OMP_CONTINUE statement. */
13560 gsi = gsi_last_bb (kfor->cont);
13561 gcc_assert (!gsi_end_p (gsi)
13562 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_CONTINUE);
13563 gsi_remove (&gsi, true);
773c5ba7 13564
56686608 13565 /* Replace the GIMPLE_OMP_RETURN with a real return. */
13566 gsi = gsi_last_bb (kfor->exit);
13567 gcc_assert (!gsi_end_p (gsi)
13568 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
13569 gsi_remove (&gsi, true);
773c5ba7 13570
56686608 13571 /* Fixup the much simpler CFG. */
13572 remove_edge (find_edge (kfor->cont, body_bb));
773c5ba7 13573
56686608 13574 if (kfor->cont != body_bb)
13575 set_immediate_dominator (CDI_DOMINATORS, kfor->cont, body_bb);
13576 set_immediate_dominator (CDI_DOMINATORS, kfor->exit, kfor->cont);
13577}
cb7f680b 13578
56686608 13579/* Structure passed to grid_remap_kernel_arg_accesses so that it can remap
13580 argument_decls. */
13581
13582struct grid_arg_decl_map
13583{
13584 tree old_arg;
13585 tree new_arg;
13586};
13587
13588/* Invoked through walk_gimple_op, will remap all PARM_DECLs to the ones
13589 pertaining to kernel function. */
13590
13591static tree
13592grid_remap_kernel_arg_accesses (tree *tp, int *walk_subtrees, void *data)
13593{
13594 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
13595 struct grid_arg_decl_map *adm = (struct grid_arg_decl_map *) wi->info;
13596 tree t = *tp;
13597
13598 if (t == adm->old_arg)
13599 *tp = adm->new_arg;
13600 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
13601 return NULL_TREE;
13602}
13603
13604static void expand_omp (struct omp_region *region);
13605
13606/* If TARGET region contains a kernel body for loop, remove its region from the
13607 TARGET and expand it in GPGPU kernel fashion. */
13608
13609static void
13610grid_expand_target_grid_body (struct omp_region *target)
13611{
13612 if (!hsa_gen_requested_p ())
13613 return;
13614
13615 gomp_target *tgt_stmt = as_a <gomp_target *> (last_stmt (target->entry));
13616 struct omp_region **pp;
13617
13618 for (pp = &target->inner; *pp; pp = &(*pp)->next)
13619 if ((*pp)->type == GIMPLE_OMP_GRID_BODY)
13620 break;
13621
13622 struct omp_region *gpukernel = *pp;
13623
13624 tree orig_child_fndecl = gimple_omp_target_child_fn (tgt_stmt);
13625 if (!gpukernel)
13626 {
13627 /* HSA cannot handle OACC stuff. */
13628 if (gimple_omp_target_kind (tgt_stmt) != GF_OMP_TARGET_KIND_REGION)
13629 return;
13630 gcc_checking_assert (orig_child_fndecl);
13631 gcc_assert (!find_omp_clause (gimple_omp_target_clauses (tgt_stmt),
13632 OMP_CLAUSE__GRIDDIM_));
13633 cgraph_node *n = cgraph_node::get (orig_child_fndecl);
13634
13635 hsa_register_kernel (n);
13636 return;
13637 }
13638
13639 gcc_assert (find_omp_clause (gimple_omp_target_clauses (tgt_stmt),
13640 OMP_CLAUSE__GRIDDIM_));
13641 tree inside_block = gimple_block (first_stmt (single_succ (gpukernel->entry)));
13642 *pp = gpukernel->next;
13643 for (pp = &gpukernel->inner; *pp; pp = &(*pp)->next)
13644 if ((*pp)->type == GIMPLE_OMP_FOR)
13645 break;
13646
13647 struct omp_region *kfor = *pp;
13648 gcc_assert (kfor);
13649 gcc_assert (gimple_omp_for_kind (last_stmt ((kfor)->entry))
13650 == GF_OMP_FOR_KIND_GRID_LOOP);
13651 *pp = kfor->next;
13652 if (kfor->inner)
13653 expand_omp (kfor->inner);
13654 if (gpukernel->inner)
13655 expand_omp (gpukernel->inner);
13656
13657 tree kern_fndecl = copy_node (orig_child_fndecl);
13658 DECL_NAME (kern_fndecl) = clone_function_name (kern_fndecl, "kernel");
13659 SET_DECL_ASSEMBLER_NAME (kern_fndecl, DECL_NAME (kern_fndecl));
13660 tree tgtblock = gimple_block (tgt_stmt);
13661 tree fniniblock = make_node (BLOCK);
13662 BLOCK_ABSTRACT_ORIGIN (fniniblock) = tgtblock;
13663 BLOCK_SOURCE_LOCATION (fniniblock) = BLOCK_SOURCE_LOCATION (tgtblock);
13664 BLOCK_SOURCE_END_LOCATION (fniniblock) = BLOCK_SOURCE_END_LOCATION (tgtblock);
13665 DECL_INITIAL (kern_fndecl) = fniniblock;
13666 push_struct_function (kern_fndecl);
13667 cfun->function_end_locus = gimple_location (tgt_stmt);
9ae1b28a 13668 init_tree_ssa (cfun);
56686608 13669 pop_cfun ();
13670
13671 tree old_parm_decl = DECL_ARGUMENTS (kern_fndecl);
13672 gcc_assert (!DECL_CHAIN (old_parm_decl));
13673 tree new_parm_decl = copy_node (DECL_ARGUMENTS (kern_fndecl));
13674 DECL_CONTEXT (new_parm_decl) = kern_fndecl;
13675 DECL_ARGUMENTS (kern_fndecl) = new_parm_decl;
769a3348 13676 gcc_assert (VOID_TYPE_P (TREE_TYPE (DECL_RESULT (kern_fndecl))));
13677 DECL_RESULT (kern_fndecl) = copy_node (DECL_RESULT (kern_fndecl));
13678 DECL_CONTEXT (DECL_RESULT (kern_fndecl)) = kern_fndecl;
56686608 13679 struct function *kern_cfun = DECL_STRUCT_FUNCTION (kern_fndecl);
13680 kern_cfun->curr_properties = cfun->curr_properties;
13681
13682 remove_edge (BRANCH_EDGE (kfor->entry));
13683 grid_expand_omp_for_loop (kfor);
13684
13685 /* Remove the omp for statement */
13686 gimple_stmt_iterator gsi = gsi_last_bb (gpukernel->entry);
13687 gsi_remove (&gsi, true);
13688 /* Replace the GIMPLE_OMP_RETURN at the end of the kernel region with a real
13689 return. */
13690 gsi = gsi_last_bb (gpukernel->exit);
13691 gcc_assert (!gsi_end_p (gsi)
13692 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
13693 gimple *ret_stmt = gimple_build_return (NULL);
13694 gsi_insert_after (&gsi, ret_stmt, GSI_SAME_STMT);
13695 gsi_remove (&gsi, true);
13696
13697 /* Statements in the first BB in the target construct have been produced by
13698 target lowering and must be copied inside the GPUKERNEL, with the two
13699 exceptions of the first OMP statement and the OMP_DATA assignment
13700 statement. */
13701 gsi = gsi_start_bb (single_succ (gpukernel->entry));
13702 tree data_arg = gimple_omp_target_data_arg (tgt_stmt);
13703 tree sender = data_arg ? TREE_VEC_ELT (data_arg, 0) : NULL;
13704 for (gimple_stmt_iterator tsi = gsi_start_bb (single_succ (target->entry));
13705 !gsi_end_p (tsi); gsi_next (&tsi))
13706 {
13707 gimple *stmt = gsi_stmt (tsi);
13708 if (is_gimple_omp (stmt))
13709 break;
13710 if (sender
13711 && is_gimple_assign (stmt)
13712 && TREE_CODE (gimple_assign_rhs1 (stmt)) == ADDR_EXPR
13713 && TREE_OPERAND (gimple_assign_rhs1 (stmt), 0) == sender)
13714 continue;
13715 gimple *copy = gimple_copy (stmt);
13716 gsi_insert_before (&gsi, copy, GSI_SAME_STMT);
13717 gimple_set_block (copy, fniniblock);
13718 }
13719
13720 move_sese_region_to_fn (kern_cfun, single_succ (gpukernel->entry),
13721 gpukernel->exit, inside_block);
13722
13723 cgraph_node *kcn = cgraph_node::get_create (kern_fndecl);
13724 kcn->mark_force_output ();
13725 cgraph_node *orig_child = cgraph_node::get (orig_child_fndecl);
13726
13727 hsa_register_kernel (kcn, orig_child);
13728
13729 cgraph_node::add_new_function (kern_fndecl, true);
13730 push_cfun (kern_cfun);
13731 cgraph_edge::rebuild_edges ();
13732
13733 /* Re-map any mention of the PARM_DECL of the original function to the
13734 PARM_DECL of the new one.
13735
13736 TODO: It would be great if lowering produced references into the GPU
13737 kernel decl straight away and we did not have to do this. */
13738 struct grid_arg_decl_map adm;
13739 adm.old_arg = old_parm_decl;
13740 adm.new_arg = new_parm_decl;
13741 basic_block bb;
13742 FOR_EACH_BB_FN (bb, kern_cfun)
13743 {
13744 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
13745 {
13746 gimple *stmt = gsi_stmt (gsi);
13747 struct walk_stmt_info wi;
13748 memset (&wi, 0, sizeof (wi));
13749 wi.info = &adm;
13750 walk_gimple_op (stmt, grid_remap_kernel_arg_accesses, &wi);
13751 }
13752 }
13753 pop_cfun ();
13754
13755 return;
13756}
13757
13758/* Expand the parallel region tree rooted at REGION. Expansion
13759 proceeds in depth-first order. Innermost regions are expanded
13760 first. This way, parallel regions that require a new function to
13761 be created (e.g., GIMPLE_OMP_PARALLEL) can be expanded without having any
13762 internal dependencies in their body. */
13763
13764static void
13765expand_omp (struct omp_region *region)
13766{
13767 omp_any_child_fn_dumped = false;
13768 while (region)
13769 {
13770 location_t saved_location;
13771 gimple *inner_stmt = NULL;
13772
13773 /* First, determine whether this is a combined parallel+workshare
13774 region. */
13775 if (region->type == GIMPLE_OMP_PARALLEL)
13776 determine_parallel_type (region);
13777 else if (region->type == GIMPLE_OMP_TARGET)
13778 grid_expand_target_grid_body (region);
13779
13780 if (region->type == GIMPLE_OMP_FOR
13781 && gimple_omp_for_combined_p (last_stmt (region->entry)))
13782 inner_stmt = last_stmt (region->inner->entry);
13783
13784 if (region->inner)
13785 expand_omp (region->inner);
13786
13787 saved_location = input_location;
13788 if (gimple_has_location (last_stmt (region->entry)))
13789 input_location = gimple_location (last_stmt (region->entry));
13790
13791 switch (region->type)
13792 {
13793 case GIMPLE_OMP_PARALLEL:
13794 case GIMPLE_OMP_TASK:
13795 expand_omp_taskreg (region);
13796 break;
13797
13798 case GIMPLE_OMP_FOR:
13799 expand_omp_for (region, inner_stmt);
13800 break;
13801
13802 case GIMPLE_OMP_SECTIONS:
13803 expand_omp_sections (region);
13804 break;
13805
13806 case GIMPLE_OMP_SECTION:
13807 /* Individual omp sections are handled together with their
13808 parent GIMPLE_OMP_SECTIONS region. */
13809 break;
13810
13811 case GIMPLE_OMP_SINGLE:
13812 expand_omp_single (region);
13813 break;
13814
13815 case GIMPLE_OMP_ORDERED:
13816 {
13817 gomp_ordered *ord_stmt
13818 = as_a <gomp_ordered *> (last_stmt (region->entry));
13819 if (find_omp_clause (gimple_omp_ordered_clauses (ord_stmt),
13820 OMP_CLAUSE_DEPEND))
13821 {
13822 /* We'll expand these when expanding corresponding
13823 worksharing region with ordered(n) clause. */
13824 gcc_assert (region->outer
13825 && region->outer->type == GIMPLE_OMP_FOR);
13826 region->ord_stmt = ord_stmt;
13827 break;
13828 }
13829 }
13830 /* FALLTHRU */
13831 case GIMPLE_OMP_MASTER:
13832 case GIMPLE_OMP_TASKGROUP:
13833 case GIMPLE_OMP_CRITICAL:
13834 case GIMPLE_OMP_TEAMS:
13835 expand_omp_synch (region);
13836 break;
13837
13838 case GIMPLE_OMP_ATOMIC_LOAD:
13839 expand_omp_atomic (region);
13840 break;
13841
13842 case GIMPLE_OMP_TARGET:
bc7bff74 13843 expand_omp_target (region);
13844 break;
13845
61e47ac8 13846 default:
13847 gcc_unreachable ();
13848 }
cc5982dc 13849
1d22f541 13850 input_location = saved_location;
773c5ba7 13851 region = region->next;
13852 }
9561765e 13853 if (omp_any_child_fn_dumped)
13854 {
13855 if (dump_file)
13856 dump_function_header (dump_file, current_function_decl, dump_flags);
13857 omp_any_child_fn_dumped = false;
13858 }
773c5ba7 13859}
13860
13861
13862/* Helper for build_omp_regions. Scan the dominator tree starting at
28c92cbb 13863 block BB. PARENT is the region that contains BB. If SINGLE_TREE is
13864 true, the function ends once a single tree is built (otherwise, whole
13865 forest of OMP constructs may be built). */
773c5ba7 13866
13867static void
28c92cbb 13868build_omp_regions_1 (basic_block bb, struct omp_region *parent,
13869 bool single_tree)
773c5ba7 13870{
75a70cf9 13871 gimple_stmt_iterator gsi;
42acab1c 13872 gimple *stmt;
773c5ba7 13873 basic_block son;
13874
75a70cf9 13875 gsi = gsi_last_bb (bb);
13876 if (!gsi_end_p (gsi) && is_gimple_omp (gsi_stmt (gsi)))
773c5ba7 13877 {
13878 struct omp_region *region;
75a70cf9 13879 enum gimple_code code;
773c5ba7 13880
75a70cf9 13881 stmt = gsi_stmt (gsi);
13882 code = gimple_code (stmt);
13883 if (code == GIMPLE_OMP_RETURN)
773c5ba7 13884 {
13885 /* STMT is the return point out of region PARENT. Mark it
13886 as the exit point and make PARENT the immediately
13887 enclosing region. */
13888 gcc_assert (parent);
13889 region = parent;
61e47ac8 13890 region->exit = bb;
773c5ba7 13891 parent = parent->outer;
773c5ba7 13892 }
75a70cf9 13893 else if (code == GIMPLE_OMP_ATOMIC_STORE)
cb7f680b 13894 {
75a70cf9 13895 /* GIMPLE_OMP_ATOMIC_STORE is analoguous to
13896 GIMPLE_OMP_RETURN, but matches with
13897 GIMPLE_OMP_ATOMIC_LOAD. */
cb7f680b 13898 gcc_assert (parent);
75a70cf9 13899 gcc_assert (parent->type == GIMPLE_OMP_ATOMIC_LOAD);
cb7f680b 13900 region = parent;
13901 region->exit = bb;
13902 parent = parent->outer;
13903 }
75a70cf9 13904 else if (code == GIMPLE_OMP_CONTINUE)
61e47ac8 13905 {
13906 gcc_assert (parent);
13907 parent->cont = bb;
13908 }
75a70cf9 13909 else if (code == GIMPLE_OMP_SECTIONS_SWITCH)
ac6e3339 13910 {
75a70cf9 13911 /* GIMPLE_OMP_SECTIONS_SWITCH is part of
13912 GIMPLE_OMP_SECTIONS, and we do nothing for it. */
ac6e3339 13913 }
773c5ba7 13914 else
13915 {
61e47ac8 13916 region = new_omp_region (bb, code, parent);
ca4c3545 13917 /* Otherwise... */
13918 if (code == GIMPLE_OMP_TARGET)
13919 {
13920 switch (gimple_omp_target_kind (stmt))
13921 {
13922 case GF_OMP_TARGET_KIND_REGION:
13923 case GF_OMP_TARGET_KIND_DATA:
13924 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
13925 case GF_OMP_TARGET_KIND_OACC_KERNELS:
13926 case GF_OMP_TARGET_KIND_OACC_DATA:
571b3486 13927 case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
ca4c3545 13928 break;
13929 case GF_OMP_TARGET_KIND_UPDATE:
43895be5 13930 case GF_OMP_TARGET_KIND_ENTER_DATA:
13931 case GF_OMP_TARGET_KIND_EXIT_DATA:
ca4c3545 13932 case GF_OMP_TARGET_KIND_OACC_UPDATE:
13933 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
2fc5e987 13934 case GF_OMP_TARGET_KIND_OACC_DECLARE:
ca4c3545 13935 /* ..., other than for those stand-alone directives... */
13936 region = NULL;
13937 break;
13938 default:
13939 gcc_unreachable ();
13940 }
13941 }
43895be5 13942 else if (code == GIMPLE_OMP_ORDERED
13943 && find_omp_clause (gimple_omp_ordered_clauses
13944 (as_a <gomp_ordered *> (stmt)),
13945 OMP_CLAUSE_DEPEND))
13946 /* #pragma omp ordered depend is also just a stand-alone
13947 directive. */
13948 region = NULL;
ca4c3545 13949 /* ..., this directive becomes the parent for a new region. */
13950 if (region)
13951 parent = region;
773c5ba7 13952 }
773c5ba7 13953 }
13954
28c92cbb 13955 if (single_tree && !parent)
13956 return;
13957
773c5ba7 13958 for (son = first_dom_son (CDI_DOMINATORS, bb);
13959 son;
13960 son = next_dom_son (CDI_DOMINATORS, son))
28c92cbb 13961 build_omp_regions_1 (son, parent, single_tree);
13962}
13963
13964/* Builds the tree of OMP regions rooted at ROOT, storing it to
13965 root_omp_region. */
13966
13967static void
13968build_omp_regions_root (basic_block root)
13969{
13970 gcc_assert (root_omp_region == NULL);
13971 build_omp_regions_1 (root, NULL, true);
13972 gcc_assert (root_omp_region != NULL);
773c5ba7 13973}
13974
28c92cbb 13975/* Expands omp construct (and its subconstructs) starting in HEAD. */
13976
13977void
13978omp_expand_local (basic_block head)
13979{
13980 build_omp_regions_root (head);
13981 if (dump_file && (dump_flags & TDF_DETAILS))
13982 {
13983 fprintf (dump_file, "\nOMP region tree\n\n");
13984 dump_omp_region (dump_file, root_omp_region, 0);
13985 fprintf (dump_file, "\n");
13986 }
13987
13988 remove_exit_barriers (root_omp_region);
13989 expand_omp (root_omp_region);
13990
13991 free_omp_regions ();
13992}
773c5ba7 13993
13994/* Scan the CFG and build a tree of OMP regions. Return the root of
13995 the OMP region tree. */
13996
13997static void
13998build_omp_regions (void)
13999{
61e47ac8 14000 gcc_assert (root_omp_region == NULL);
773c5ba7 14001 calculate_dominance_info (CDI_DOMINATORS);
34154e27 14002 build_omp_regions_1 (ENTRY_BLOCK_PTR_FOR_FN (cfun), NULL, false);
773c5ba7 14003}
14004
773c5ba7 14005/* Main entry point for expanding OMP-GIMPLE into runtime calls. */
14006
2a1990e9 14007static unsigned int
773c5ba7 14008execute_expand_omp (void)
14009{
14010 build_omp_regions ();
14011
61e47ac8 14012 if (!root_omp_region)
14013 return 0;
773c5ba7 14014
61e47ac8 14015 if (dump_file)
14016 {
14017 fprintf (dump_file, "\nOMP region tree\n\n");
14018 dump_omp_region (dump_file, root_omp_region, 0);
14019 fprintf (dump_file, "\n");
773c5ba7 14020 }
61e47ac8 14021
14022 remove_exit_barriers (root_omp_region);
14023
14024 expand_omp (root_omp_region);
14025
382ecba7 14026 if (flag_checking && !loops_state_satisfies_p (LOOPS_NEED_FIXUP))
86a932e0 14027 verify_loop_structure ();
61e47ac8 14028 cleanup_tree_cfg ();
14029
14030 free_omp_regions ();
14031
2a1990e9 14032 return 0;
773c5ba7 14033}
14034
79acaae1 14035/* OMP expansion -- the default pass, run before creation of SSA form. */
14036
7620bc82 14037namespace {
14038
14039const pass_data pass_data_expand_omp =
cbe8bda8 14040{
14041 GIMPLE_PASS, /* type */
14042 "ompexp", /* name */
14043 OPTGROUP_NONE, /* optinfo_flags */
cbe8bda8 14044 TV_NONE, /* tv_id */
14045 PROP_gimple_any, /* properties_required */
8917c50b 14046 PROP_gimple_eomp, /* properties_provided */
cbe8bda8 14047 0, /* properties_destroyed */
14048 0, /* todo_flags_start */
14049 0, /* todo_flags_finish */
773c5ba7 14050};
cbe8bda8 14051
7620bc82 14052class pass_expand_omp : public gimple_opt_pass
cbe8bda8 14053{
14054public:
9af5ce0c 14055 pass_expand_omp (gcc::context *ctxt)
14056 : gimple_opt_pass (pass_data_expand_omp, ctxt)
cbe8bda8 14057 {}
14058
14059 /* opt_pass methods: */
8917c50b 14060 virtual unsigned int execute (function *)
31315c24 14061 {
ca4c3545 14062 bool gate = ((flag_cilkplus != 0 || flag_openacc != 0 || flag_openmp != 0
14063 || flag_openmp_simd != 0)
14064 && !seen_error ());
31315c24 14065
8917c50b 14066 /* This pass always runs, to provide PROP_gimple_eomp.
ca4c3545 14067 But often, there is nothing to do. */
8917c50b 14068 if (!gate)
14069 return 0;
14070
14071 return execute_expand_omp ();
14072 }
cbe8bda8 14073
14074}; // class pass_expand_omp
14075
7620bc82 14076} // anon namespace
14077
cbe8bda8 14078gimple_opt_pass *
14079make_pass_expand_omp (gcc::context *ctxt)
14080{
14081 return new pass_expand_omp (ctxt);
14082}
8917c50b 14083
7620bc82 14084namespace {
14085
14086const pass_data pass_data_expand_omp_ssa =
8917c50b 14087{
14088 GIMPLE_PASS, /* type */
14089 "ompexpssa", /* name */
14090 OPTGROUP_NONE, /* optinfo_flags */
14091 TV_NONE, /* tv_id */
14092 PROP_cfg | PROP_ssa, /* properties_required */
14093 PROP_gimple_eomp, /* properties_provided */
14094 0, /* properties_destroyed */
14095 0, /* todo_flags_start */
14096 TODO_cleanup_cfg | TODO_rebuild_alias, /* todo_flags_finish */
14097};
14098
7620bc82 14099class pass_expand_omp_ssa : public gimple_opt_pass
8917c50b 14100{
14101public:
14102 pass_expand_omp_ssa (gcc::context *ctxt)
14103 : gimple_opt_pass (pass_data_expand_omp_ssa, ctxt)
14104 {}
14105
14106 /* opt_pass methods: */
14107 virtual bool gate (function *fun)
14108 {
14109 return !(fun->curr_properties & PROP_gimple_eomp);
14110 }
14111 virtual unsigned int execute (function *) { return execute_expand_omp (); }
e1e1688c 14112 opt_pass * clone () { return new pass_expand_omp_ssa (m_ctxt); }
8917c50b 14113
14114}; // class pass_expand_omp_ssa
14115
7620bc82 14116} // anon namespace
14117
8917c50b 14118gimple_opt_pass *
14119make_pass_expand_omp_ssa (gcc::context *ctxt)
14120{
14121 return new pass_expand_omp_ssa (ctxt);
14122}
773c5ba7 14123\f
ca4c3545 14124/* Routines to lower OMP directives into OMP-GIMPLE. */
14125
bc7bff74 14126/* If ctx is a worksharing context inside of a cancellable parallel
14127 region and it isn't nowait, add lhs to its GIMPLE_OMP_RETURN
14128 and conditional branch to parallel's cancel_label to handle
14129 cancellation in the implicit barrier. */
14130
14131static void
14132maybe_add_implicit_barrier_cancel (omp_context *ctx, gimple_seq *body)
14133{
42acab1c 14134 gimple *omp_return = gimple_seq_last_stmt (*body);
bc7bff74 14135 gcc_assert (gimple_code (omp_return) == GIMPLE_OMP_RETURN);
14136 if (gimple_omp_return_nowait_p (omp_return))
14137 return;
14138 if (ctx->outer
14139 && gimple_code (ctx->outer->stmt) == GIMPLE_OMP_PARALLEL
14140 && ctx->outer->cancellable)
14141 {
15b28553 14142 tree fndecl = builtin_decl_explicit (BUILT_IN_GOMP_CANCEL);
14143 tree c_bool_type = TREE_TYPE (TREE_TYPE (fndecl));
f9e245b2 14144 tree lhs = create_tmp_var (c_bool_type);
bc7bff74 14145 gimple_omp_return_set_lhs (omp_return, lhs);
14146 tree fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
42acab1c 14147 gimple *g = gimple_build_cond (NE_EXPR, lhs,
15b28553 14148 fold_convert (c_bool_type,
14149 boolean_false_node),
bc7bff74 14150 ctx->outer->cancel_label, fallthru_label);
14151 gimple_seq_add_stmt (body, g);
14152 gimple_seq_add_stmt (body, gimple_build_label (fallthru_label));
14153 }
14154}
14155
75a70cf9 14156/* Lower the OpenMP sections directive in the current statement in GSI_P.
14157 CTX is the enclosing OMP context for the current statement. */
773c5ba7 14158
14159static void
75a70cf9 14160lower_omp_sections (gimple_stmt_iterator *gsi_p, omp_context *ctx)
773c5ba7 14161{
75a70cf9 14162 tree block, control;
14163 gimple_stmt_iterator tgsi;
1a91d914 14164 gomp_sections *stmt;
42acab1c 14165 gimple *t;
1a91d914 14166 gbind *new_stmt, *bind;
e3a19533 14167 gimple_seq ilist, dlist, olist, new_body;
773c5ba7 14168
1a91d914 14169 stmt = as_a <gomp_sections *> (gsi_stmt (*gsi_p));
773c5ba7 14170
8a4a28a8 14171 push_gimplify_context ();
773c5ba7 14172
14173 dlist = NULL;
14174 ilist = NULL;
75a70cf9 14175 lower_rec_input_clauses (gimple_omp_sections_clauses (stmt),
bc7bff74 14176 &ilist, &dlist, ctx, NULL);
773c5ba7 14177
e3a19533 14178 new_body = gimple_omp_body (stmt);
14179 gimple_omp_set_body (stmt, NULL);
14180 tgsi = gsi_start (new_body);
14181 for (; !gsi_end_p (tgsi); gsi_next (&tgsi))
773c5ba7 14182 {
14183 omp_context *sctx;
42acab1c 14184 gimple *sec_start;
773c5ba7 14185
75a70cf9 14186 sec_start = gsi_stmt (tgsi);
773c5ba7 14187 sctx = maybe_lookup_ctx (sec_start);
14188 gcc_assert (sctx);
14189
e3a19533 14190 lower_omp (gimple_omp_body_ptr (sec_start), sctx);
14191 gsi_insert_seq_after (&tgsi, gimple_omp_body (sec_start),
14192 GSI_CONTINUE_LINKING);
75a70cf9 14193 gimple_omp_set_body (sec_start, NULL);
773c5ba7 14194
e3a19533 14195 if (gsi_one_before_end_p (tgsi))
773c5ba7 14196 {
75a70cf9 14197 gimple_seq l = NULL;
14198 lower_lastprivate_clauses (gimple_omp_sections_clauses (stmt), NULL,
773c5ba7 14199 &l, ctx);
e3a19533 14200 gsi_insert_seq_after (&tgsi, l, GSI_CONTINUE_LINKING);
75a70cf9 14201 gimple_omp_section_set_last (sec_start);
773c5ba7 14202 }
48e1416a 14203
e3a19533 14204 gsi_insert_after (&tgsi, gimple_build_omp_return (false),
14205 GSI_CONTINUE_LINKING);
773c5ba7 14206 }
1e8e9920 14207
14208 block = make_node (BLOCK);
e3a19533 14209 bind = gimple_build_bind (NULL, new_body, block);
1e8e9920 14210
75a70cf9 14211 olist = NULL;
14212 lower_reduction_clauses (gimple_omp_sections_clauses (stmt), &olist, ctx);
773c5ba7 14213
1d22f541 14214 block = make_node (BLOCK);
75a70cf9 14215 new_stmt = gimple_build_bind (NULL, NULL, block);
e3a19533 14216 gsi_replace (gsi_p, new_stmt, true);
773c5ba7 14217
1d22f541 14218 pop_gimplify_context (new_stmt);
75a70cf9 14219 gimple_bind_append_vars (new_stmt, ctx->block_vars);
14220 BLOCK_VARS (block) = gimple_bind_vars (bind);
1d22f541 14221 if (BLOCK_VARS (block))
14222 TREE_USED (block) = 1;
14223
75a70cf9 14224 new_body = NULL;
14225 gimple_seq_add_seq (&new_body, ilist);
14226 gimple_seq_add_stmt (&new_body, stmt);
14227 gimple_seq_add_stmt (&new_body, gimple_build_omp_sections_switch ());
14228 gimple_seq_add_stmt (&new_body, bind);
61e47ac8 14229
ac6e3339 14230 control = create_tmp_var (unsigned_type_node, ".section");
75a70cf9 14231 t = gimple_build_omp_continue (control, control);
14232 gimple_omp_sections_set_control (stmt, control);
14233 gimple_seq_add_stmt (&new_body, t);
61e47ac8 14234
75a70cf9 14235 gimple_seq_add_seq (&new_body, olist);
bc7bff74 14236 if (ctx->cancellable)
14237 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
75a70cf9 14238 gimple_seq_add_seq (&new_body, dlist);
773c5ba7 14239
75a70cf9 14240 new_body = maybe_catch_exception (new_body);
aade31a0 14241
75a70cf9 14242 t = gimple_build_omp_return
14243 (!!find_omp_clause (gimple_omp_sections_clauses (stmt),
14244 OMP_CLAUSE_NOWAIT));
14245 gimple_seq_add_stmt (&new_body, t);
bc7bff74 14246 maybe_add_implicit_barrier_cancel (ctx, &new_body);
61e47ac8 14247
75a70cf9 14248 gimple_bind_set_body (new_stmt, new_body);
1e8e9920 14249}
14250
14251
773c5ba7 14252/* A subroutine of lower_omp_single. Expand the simple form of
75a70cf9 14253 a GIMPLE_OMP_SINGLE, without a copyprivate clause:
1e8e9920 14254
14255 if (GOMP_single_start ())
14256 BODY;
14257 [ GOMP_barrier (); ] -> unless 'nowait' is present.
773c5ba7 14258
14259 FIXME. It may be better to delay expanding the logic of this until
14260 pass_expand_omp. The expanded logic may make the job more difficult
14261 to a synchronization analysis pass. */
1e8e9920 14262
14263static void
1a91d914 14264lower_omp_single_simple (gomp_single *single_stmt, gimple_seq *pre_p)
1e8e9920 14265{
e60a6f7b 14266 location_t loc = gimple_location (single_stmt);
14267 tree tlabel = create_artificial_label (loc);
14268 tree flabel = create_artificial_label (loc);
42acab1c 14269 gimple *call, *cond;
75a70cf9 14270 tree lhs, decl;
14271
b9a16870 14272 decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_START);
f9e245b2 14273 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (decl)));
75a70cf9 14274 call = gimple_build_call (decl, 0);
14275 gimple_call_set_lhs (call, lhs);
14276 gimple_seq_add_stmt (pre_p, call);
14277
14278 cond = gimple_build_cond (EQ_EXPR, lhs,
389dd41b 14279 fold_convert_loc (loc, TREE_TYPE (lhs),
14280 boolean_true_node),
75a70cf9 14281 tlabel, flabel);
14282 gimple_seq_add_stmt (pre_p, cond);
14283 gimple_seq_add_stmt (pre_p, gimple_build_label (tlabel));
14284 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
14285 gimple_seq_add_stmt (pre_p, gimple_build_label (flabel));
1e8e9920 14286}
14287
773c5ba7 14288
14289/* A subroutine of lower_omp_single. Expand the simple form of
75a70cf9 14290 a GIMPLE_OMP_SINGLE, with a copyprivate clause:
1e8e9920 14291
14292 #pragma omp single copyprivate (a, b, c)
14293
14294 Create a new structure to hold copies of 'a', 'b' and 'c' and emit:
14295
14296 {
14297 if ((copyout_p = GOMP_single_copy_start ()) == NULL)
14298 {
14299 BODY;
14300 copyout.a = a;
14301 copyout.b = b;
14302 copyout.c = c;
14303 GOMP_single_copy_end (&copyout);
14304 }
14305 else
14306 {
14307 a = copyout_p->a;
14308 b = copyout_p->b;
14309 c = copyout_p->c;
14310 }
14311 GOMP_barrier ();
14312 }
773c5ba7 14313
14314 FIXME. It may be better to delay expanding the logic of this until
14315 pass_expand_omp. The expanded logic may make the job more difficult
14316 to a synchronization analysis pass. */
1e8e9920 14317
14318static void
1a91d914 14319lower_omp_single_copy (gomp_single *single_stmt, gimple_seq *pre_p,
14320 omp_context *ctx)
1e8e9920 14321{
b9a16870 14322 tree ptr_type, t, l0, l1, l2, bfn_decl;
75a70cf9 14323 gimple_seq copyin_seq;
e60a6f7b 14324 location_t loc = gimple_location (single_stmt);
1e8e9920 14325
14326 ctx->sender_decl = create_tmp_var (ctx->record_type, ".omp_copy_o");
14327
14328 ptr_type = build_pointer_type (ctx->record_type);
14329 ctx->receiver_decl = create_tmp_var (ptr_type, ".omp_copy_i");
14330
e60a6f7b 14331 l0 = create_artificial_label (loc);
14332 l1 = create_artificial_label (loc);
14333 l2 = create_artificial_label (loc);
1e8e9920 14334
b9a16870 14335 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_START);
14336 t = build_call_expr_loc (loc, bfn_decl, 0);
389dd41b 14337 t = fold_convert_loc (loc, ptr_type, t);
75a70cf9 14338 gimplify_assign (ctx->receiver_decl, t, pre_p);
1e8e9920 14339
14340 t = build2 (EQ_EXPR, boolean_type_node, ctx->receiver_decl,
14341 build_int_cst (ptr_type, 0));
14342 t = build3 (COND_EXPR, void_type_node, t,
14343 build_and_jump (&l0), build_and_jump (&l1));
14344 gimplify_and_add (t, pre_p);
14345
75a70cf9 14346 gimple_seq_add_stmt (pre_p, gimple_build_label (l0));
1e8e9920 14347
75a70cf9 14348 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
1e8e9920 14349
14350 copyin_seq = NULL;
75a70cf9 14351 lower_copyprivate_clauses (gimple_omp_single_clauses (single_stmt), pre_p,
1e8e9920 14352 &copyin_seq, ctx);
14353
389dd41b 14354 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
b9a16870 14355 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_END);
14356 t = build_call_expr_loc (loc, bfn_decl, 1, t);
1e8e9920 14357 gimplify_and_add (t, pre_p);
14358
14359 t = build_and_jump (&l2);
14360 gimplify_and_add (t, pre_p);
14361
75a70cf9 14362 gimple_seq_add_stmt (pre_p, gimple_build_label (l1));
1e8e9920 14363
75a70cf9 14364 gimple_seq_add_seq (pre_p, copyin_seq);
1e8e9920 14365
75a70cf9 14366 gimple_seq_add_stmt (pre_p, gimple_build_label (l2));
1e8e9920 14367}
14368
773c5ba7 14369
1e8e9920 14370/* Expand code for an OpenMP single directive. */
14371
14372static void
75a70cf9 14373lower_omp_single (gimple_stmt_iterator *gsi_p, omp_context *ctx)
1e8e9920 14374{
75a70cf9 14375 tree block;
42acab1c 14376 gimple *t;
1a91d914 14377 gomp_single *single_stmt = as_a <gomp_single *> (gsi_stmt (*gsi_p));
14378 gbind *bind;
bc7bff74 14379 gimple_seq bind_body, bind_body_tail = NULL, dlist;
1e8e9920 14380
8a4a28a8 14381 push_gimplify_context ();
1e8e9920 14382
e3a19533 14383 block = make_node (BLOCK);
14384 bind = gimple_build_bind (NULL, NULL, block);
14385 gsi_replace (gsi_p, bind, true);
75a70cf9 14386 bind_body = NULL;
e3a19533 14387 dlist = NULL;
75a70cf9 14388 lower_rec_input_clauses (gimple_omp_single_clauses (single_stmt),
bc7bff74 14389 &bind_body, &dlist, ctx, NULL);
e3a19533 14390 lower_omp (gimple_omp_body_ptr (single_stmt), ctx);
1e8e9920 14391
75a70cf9 14392 gimple_seq_add_stmt (&bind_body, single_stmt);
1e8e9920 14393
14394 if (ctx->record_type)
75a70cf9 14395 lower_omp_single_copy (single_stmt, &bind_body, ctx);
1e8e9920 14396 else
75a70cf9 14397 lower_omp_single_simple (single_stmt, &bind_body);
14398
14399 gimple_omp_set_body (single_stmt, NULL);
1e8e9920 14400
75a70cf9 14401 gimple_seq_add_seq (&bind_body, dlist);
61e47ac8 14402
75a70cf9 14403 bind_body = maybe_catch_exception (bind_body);
61e47ac8 14404
48e1416a 14405 t = gimple_build_omp_return
75a70cf9 14406 (!!find_omp_clause (gimple_omp_single_clauses (single_stmt),
14407 OMP_CLAUSE_NOWAIT));
bc7bff74 14408 gimple_seq_add_stmt (&bind_body_tail, t);
14409 maybe_add_implicit_barrier_cancel (ctx, &bind_body_tail);
14410 if (ctx->record_type)
14411 {
14412 gimple_stmt_iterator gsi = gsi_start (bind_body_tail);
14413 tree clobber = build_constructor (ctx->record_type, NULL);
14414 TREE_THIS_VOLATILE (clobber) = 1;
14415 gsi_insert_after (&gsi, gimple_build_assign (ctx->sender_decl,
14416 clobber), GSI_SAME_STMT);
14417 }
14418 gimple_seq_add_seq (&bind_body, bind_body_tail);
e3a19533 14419 gimple_bind_set_body (bind, bind_body);
61e47ac8 14420
1e8e9920 14421 pop_gimplify_context (bind);
773c5ba7 14422
75a70cf9 14423 gimple_bind_append_vars (bind, ctx->block_vars);
14424 BLOCK_VARS (block) = ctx->block_vars;
1d22f541 14425 if (BLOCK_VARS (block))
14426 TREE_USED (block) = 1;
1e8e9920 14427}
14428
773c5ba7 14429
1e8e9920 14430/* Expand code for an OpenMP master directive. */
14431
14432static void
75a70cf9 14433lower_omp_master (gimple_stmt_iterator *gsi_p, omp_context *ctx)
1e8e9920 14434{
b9a16870 14435 tree block, lab = NULL, x, bfn_decl;
42acab1c 14436 gimple *stmt = gsi_stmt (*gsi_p);
1a91d914 14437 gbind *bind;
389dd41b 14438 location_t loc = gimple_location (stmt);
75a70cf9 14439 gimple_seq tseq;
1e8e9920 14440
8a4a28a8 14441 push_gimplify_context ();
1e8e9920 14442
14443 block = make_node (BLOCK);
e3a19533 14444 bind = gimple_build_bind (NULL, NULL, block);
14445 gsi_replace (gsi_p, bind, true);
14446 gimple_bind_add_stmt (bind, stmt);
61e47ac8 14447
b9a16870 14448 bfn_decl = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
14449 x = build_call_expr_loc (loc, bfn_decl, 0);
1e8e9920 14450 x = build2 (EQ_EXPR, boolean_type_node, x, integer_zero_node);
14451 x = build3 (COND_EXPR, void_type_node, x, NULL, build_and_jump (&lab));
75a70cf9 14452 tseq = NULL;
14453 gimplify_and_add (x, &tseq);
14454 gimple_bind_add_seq (bind, tseq);
1e8e9920 14455
e3a19533 14456 lower_omp (gimple_omp_body_ptr (stmt), ctx);
75a70cf9 14457 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
14458 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
14459 gimple_omp_set_body (stmt, NULL);
1e8e9920 14460
75a70cf9 14461 gimple_bind_add_stmt (bind, gimple_build_label (lab));
61e47ac8 14462
75a70cf9 14463 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
61e47ac8 14464
1e8e9920 14465 pop_gimplify_context (bind);
773c5ba7 14466
75a70cf9 14467 gimple_bind_append_vars (bind, ctx->block_vars);
14468 BLOCK_VARS (block) = ctx->block_vars;
1e8e9920 14469}
14470
773c5ba7 14471
bc7bff74 14472/* Expand code for an OpenMP taskgroup directive. */
14473
14474static void
14475lower_omp_taskgroup (gimple_stmt_iterator *gsi_p, omp_context *ctx)
14476{
42acab1c 14477 gimple *stmt = gsi_stmt (*gsi_p);
1a91d914 14478 gcall *x;
14479 gbind *bind;
bc7bff74 14480 tree block = make_node (BLOCK);
14481
14482 bind = gimple_build_bind (NULL, NULL, block);
14483 gsi_replace (gsi_p, bind, true);
14484 gimple_bind_add_stmt (bind, stmt);
14485
14486 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_TASKGROUP_START),
14487 0);
14488 gimple_bind_add_stmt (bind, x);
14489
14490 lower_omp (gimple_omp_body_ptr (stmt), ctx);
14491 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
14492 gimple_omp_set_body (stmt, NULL);
14493
14494 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
14495
14496 gimple_bind_append_vars (bind, ctx->block_vars);
14497 BLOCK_VARS (block) = ctx->block_vars;
14498}
14499
14500
43895be5 14501/* Fold the OMP_ORDERED_CLAUSES for the OMP_ORDERED in STMT if possible. */
14502
14503static void
14504lower_omp_ordered_clauses (gimple_stmt_iterator *gsi_p, gomp_ordered *ord_stmt,
14505 omp_context *ctx)
14506{
14507 struct omp_for_data fd;
14508 if (!ctx->outer || gimple_code (ctx->outer->stmt) != GIMPLE_OMP_FOR)
14509 return;
14510
14511 unsigned int len = gimple_omp_for_collapse (ctx->outer->stmt);
14512 struct omp_for_data_loop *loops = XALLOCAVEC (struct omp_for_data_loop, len);
14513 extract_omp_for_data (as_a <gomp_for *> (ctx->outer->stmt), &fd, loops);
14514 if (!fd.ordered)
14515 return;
14516
14517 tree *list_p = gimple_omp_ordered_clauses_ptr (ord_stmt);
14518 tree c = gimple_omp_ordered_clauses (ord_stmt);
14519 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
14520 && OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK)
14521 {
14522 /* Merge depend clauses from multiple adjacent
14523 #pragma omp ordered depend(sink:...) constructs
14524 into one #pragma omp ordered depend(sink:...), so that
14525 we can optimize them together. */
14526 gimple_stmt_iterator gsi = *gsi_p;
14527 gsi_next (&gsi);
14528 while (!gsi_end_p (gsi))
14529 {
14530 gimple *stmt = gsi_stmt (gsi);
14531 if (is_gimple_debug (stmt)
14532 || gimple_code (stmt) == GIMPLE_NOP)
14533 {
14534 gsi_next (&gsi);
14535 continue;
14536 }
14537 if (gimple_code (stmt) != GIMPLE_OMP_ORDERED)
14538 break;
14539 gomp_ordered *ord_stmt2 = as_a <gomp_ordered *> (stmt);
14540 c = gimple_omp_ordered_clauses (ord_stmt2);
14541 if (c == NULL_TREE
14542 || OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND
14543 || OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_SINK)
14544 break;
14545 while (*list_p)
14546 list_p = &OMP_CLAUSE_CHAIN (*list_p);
14547 *list_p = c;
14548 gsi_remove (&gsi, true);
14549 }
14550 }
14551
14552 /* Canonicalize sink dependence clauses into one folded clause if
14553 possible.
14554
14555 The basic algorithm is to create a sink vector whose first
14556 element is the GCD of all the first elements, and whose remaining
14557 elements are the minimum of the subsequent columns.
14558
14559 We ignore dependence vectors whose first element is zero because
14560 such dependencies are known to be executed by the same thread.
14561
14562 We take into account the direction of the loop, so a minimum
14563 becomes a maximum if the loop is iterating forwards. We also
14564 ignore sink clauses where the loop direction is unknown, or where
14565 the offsets are clearly invalid because they are not a multiple
14566 of the loop increment.
14567
14568 For example:
14569
14570 #pragma omp for ordered(2)
14571 for (i=0; i < N; ++i)
14572 for (j=0; j < M; ++j)
14573 {
14574 #pragma omp ordered \
14575 depend(sink:i-8,j-2) \
14576 depend(sink:i,j-1) \ // Completely ignored because i+0.
14577 depend(sink:i-4,j-3) \
14578 depend(sink:i-6,j-4)
14579 #pragma omp ordered depend(source)
14580 }
14581
14582 Folded clause is:
14583
14584 depend(sink:-gcd(8,4,6),-min(2,3,4))
14585 -or-
14586 depend(sink:-2,-2)
14587 */
14588
14589 /* FIXME: Computing GCD's where the first element is zero is
14590 non-trivial in the presence of collapsed loops. Do this later. */
14591 if (fd.collapse > 1)
14592 return;
14593
14594 wide_int *folded_deps = XALLOCAVEC (wide_int, 2 * len - 1);
14595 memset (folded_deps, 0, sizeof (*folded_deps) * (2 * len - 1));
14596 tree folded_dep = NULL_TREE;
14597 /* TRUE if the first dimension's offset is negative. */
14598 bool neg_offset_p = false;
14599
14600 list_p = gimple_omp_ordered_clauses_ptr (ord_stmt);
14601 unsigned int i;
14602 while ((c = *list_p) != NULL)
14603 {
14604 bool remove = false;
14605
14606 gcc_assert (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND);
14607 if (OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_SINK)
14608 goto next_ordered_clause;
14609
14610 tree vec;
14611 for (vec = OMP_CLAUSE_DECL (c), i = 0;
14612 vec && TREE_CODE (vec) == TREE_LIST;
14613 vec = TREE_CHAIN (vec), ++i)
14614 {
14615 gcc_assert (i < len);
14616
14617 /* extract_omp_for_data has canonicalized the condition. */
14618 gcc_assert (fd.loops[i].cond_code == LT_EXPR
14619 || fd.loops[i].cond_code == GT_EXPR);
14620 bool forward = fd.loops[i].cond_code == LT_EXPR;
14621 bool maybe_lexically_later = true;
14622
14623 /* While the committee makes up its mind, bail if we have any
14624 non-constant steps. */
14625 if (TREE_CODE (fd.loops[i].step) != INTEGER_CST)
14626 goto lower_omp_ordered_ret;
14627
14628 tree itype = TREE_TYPE (TREE_VALUE (vec));
14629 if (POINTER_TYPE_P (itype))
14630 itype = sizetype;
14631 wide_int offset = wide_int::from (TREE_PURPOSE (vec),
14632 TYPE_PRECISION (itype),
14633 TYPE_SIGN (itype));
14634
14635 /* Ignore invalid offsets that are not multiples of the step. */
14636 if (!wi::multiple_of_p
14637 (wi::abs (offset), wi::abs ((wide_int) fd.loops[i].step),
14638 UNSIGNED))
14639 {
14640 warning_at (OMP_CLAUSE_LOCATION (c), 0,
14641 "ignoring sink clause with offset that is not "
14642 "a multiple of the loop step");
14643 remove = true;
14644 goto next_ordered_clause;
14645 }
14646
14647 /* Calculate the first dimension. The first dimension of
14648 the folded dependency vector is the GCD of the first
14649 elements, while ignoring any first elements whose offset
14650 is 0. */
14651 if (i == 0)
14652 {
14653 /* Ignore dependence vectors whose first dimension is 0. */
14654 if (offset == 0)
14655 {
14656 remove = true;
14657 goto next_ordered_clause;
14658 }
14659 else
14660 {
14661 if (!TYPE_UNSIGNED (itype) && (forward ^ wi::neg_p (offset)))
14662 {
14663 error_at (OMP_CLAUSE_LOCATION (c),
14664 "first offset must be in opposite direction "
14665 "of loop iterations");
14666 goto lower_omp_ordered_ret;
14667 }
14668 if (forward)
14669 offset = -offset;
14670 neg_offset_p = forward;
14671 /* Initialize the first time around. */
14672 if (folded_dep == NULL_TREE)
14673 {
14674 folded_dep = c;
14675 folded_deps[0] = offset;
14676 }
14677 else
14678 folded_deps[0] = wi::gcd (folded_deps[0],
14679 offset, UNSIGNED);
14680 }
14681 }
14682 /* Calculate minimum for the remaining dimensions. */
14683 else
14684 {
14685 folded_deps[len + i - 1] = offset;
14686 if (folded_dep == c)
14687 folded_deps[i] = offset;
14688 else if (maybe_lexically_later
14689 && !wi::eq_p (folded_deps[i], offset))
14690 {
14691 if (forward ^ wi::gts_p (folded_deps[i], offset))
14692 {
14693 unsigned int j;
14694 folded_dep = c;
14695 for (j = 1; j <= i; j++)
14696 folded_deps[j] = folded_deps[len + j - 1];
14697 }
14698 else
14699 maybe_lexically_later = false;
14700 }
14701 }
14702 }
14703 gcc_assert (i == len);
14704
14705 remove = true;
14706
14707 next_ordered_clause:
14708 if (remove)
14709 *list_p = OMP_CLAUSE_CHAIN (c);
14710 else
14711 list_p = &OMP_CLAUSE_CHAIN (c);
14712 }
14713
14714 if (folded_dep)
14715 {
14716 if (neg_offset_p)
14717 folded_deps[0] = -folded_deps[0];
14718
14719 tree itype = TREE_TYPE (TREE_VALUE (OMP_CLAUSE_DECL (folded_dep)));
14720 if (POINTER_TYPE_P (itype))
14721 itype = sizetype;
14722
14723 TREE_PURPOSE (OMP_CLAUSE_DECL (folded_dep))
14724 = wide_int_to_tree (itype, folded_deps[0]);
14725 OMP_CLAUSE_CHAIN (folded_dep) = gimple_omp_ordered_clauses (ord_stmt);
14726 *gimple_omp_ordered_clauses_ptr (ord_stmt) = folded_dep;
14727 }
14728
14729 lower_omp_ordered_ret:
14730
14731 /* Ordered without clauses is #pragma omp threads, while we want
14732 a nop instead if we remove all clauses. */
14733 if (gimple_omp_ordered_clauses (ord_stmt) == NULL_TREE)
14734 gsi_replace (gsi_p, gimple_build_nop (), true);
14735}
14736
14737
1e8e9920 14738/* Expand code for an OpenMP ordered directive. */
14739
14740static void
75a70cf9 14741lower_omp_ordered (gimple_stmt_iterator *gsi_p, omp_context *ctx)
1e8e9920 14742{
75a70cf9 14743 tree block;
42acab1c 14744 gimple *stmt = gsi_stmt (*gsi_p);
43895be5 14745 gomp_ordered *ord_stmt = as_a <gomp_ordered *> (stmt);
1a91d914 14746 gcall *x;
14747 gbind *bind;
a9833286 14748 bool simd = find_omp_clause (gimple_omp_ordered_clauses (ord_stmt),
14749 OMP_CLAUSE_SIMD);
14750 bool threads = find_omp_clause (gimple_omp_ordered_clauses (ord_stmt),
14751 OMP_CLAUSE_THREADS);
43895be5 14752
14753 if (find_omp_clause (gimple_omp_ordered_clauses (ord_stmt),
14754 OMP_CLAUSE_DEPEND))
14755 {
14756 /* FIXME: This is needs to be moved to the expansion to verify various
14757 conditions only testable on cfg with dominators computed, and also
14758 all the depend clauses to be merged still might need to be available
14759 for the runtime checks. */
14760 if (0)
14761 lower_omp_ordered_clauses (gsi_p, ord_stmt, ctx);
14762 return;
14763 }
1e8e9920 14764
8a4a28a8 14765 push_gimplify_context ();
1e8e9920 14766
14767 block = make_node (BLOCK);
e3a19533 14768 bind = gimple_build_bind (NULL, NULL, block);
14769 gsi_replace (gsi_p, bind, true);
14770 gimple_bind_add_stmt (bind, stmt);
61e47ac8 14771
43895be5 14772 if (simd)
14773 {
a9833286 14774 x = gimple_build_call_internal (IFN_GOMP_SIMD_ORDERED_START, 1,
14775 build_int_cst (NULL_TREE, threads));
43895be5 14776 cfun->has_simduid_loops = true;
14777 }
14778 else
14779 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_START),
14780 0);
75a70cf9 14781 gimple_bind_add_stmt (bind, x);
1e8e9920 14782
e3a19533 14783 lower_omp (gimple_omp_body_ptr (stmt), ctx);
75a70cf9 14784 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
14785 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
14786 gimple_omp_set_body (stmt, NULL);
1e8e9920 14787
43895be5 14788 if (simd)
a9833286 14789 x = gimple_build_call_internal (IFN_GOMP_SIMD_ORDERED_END, 1,
14790 build_int_cst (NULL_TREE, threads));
43895be5 14791 else
14792 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_END),
14793 0);
75a70cf9 14794 gimple_bind_add_stmt (bind, x);
61e47ac8 14795
75a70cf9 14796 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
61e47ac8 14797
1e8e9920 14798 pop_gimplify_context (bind);
773c5ba7 14799
75a70cf9 14800 gimple_bind_append_vars (bind, ctx->block_vars);
14801 BLOCK_VARS (block) = gimple_bind_vars (bind);
1e8e9920 14802}
14803
1e8e9920 14804
75a70cf9 14805/* Gimplify a GIMPLE_OMP_CRITICAL statement. This is a relatively simple
1e8e9920 14806 substitution of a couple of function calls. But in the NAMED case,
14807 requires that languages coordinate a symbol name. It is therefore
14808 best put here in common code. */
14809
d4786b13 14810static GTY(()) hash_map<tree, tree> *critical_name_mutexes;
1e8e9920 14811
14812static void
75a70cf9 14813lower_omp_critical (gimple_stmt_iterator *gsi_p, omp_context *ctx)
1e8e9920 14814{
75a70cf9 14815 tree block;
14816 tree name, lock, unlock;
1a91d914 14817 gomp_critical *stmt = as_a <gomp_critical *> (gsi_stmt (*gsi_p));
14818 gbind *bind;
389dd41b 14819 location_t loc = gimple_location (stmt);
75a70cf9 14820 gimple_seq tbody;
1e8e9920 14821
75a70cf9 14822 name = gimple_omp_critical_name (stmt);
1e8e9920 14823 if (name)
14824 {
c2f47e15 14825 tree decl;
1e8e9920 14826
14827 if (!critical_name_mutexes)
d4786b13 14828 critical_name_mutexes = hash_map<tree, tree>::create_ggc (10);
1e8e9920 14829
d4786b13 14830 tree *n = critical_name_mutexes->get (name);
1e8e9920 14831 if (n == NULL)
14832 {
14833 char *new_str;
14834
f9e245b2 14835 decl = create_tmp_var_raw (ptr_type_node);
1e8e9920 14836
14837 new_str = ACONCAT ((".gomp_critical_user_",
14838 IDENTIFIER_POINTER (name), NULL));
14839 DECL_NAME (decl) = get_identifier (new_str);
14840 TREE_PUBLIC (decl) = 1;
14841 TREE_STATIC (decl) = 1;
14842 DECL_COMMON (decl) = 1;
14843 DECL_ARTIFICIAL (decl) = 1;
14844 DECL_IGNORED_P (decl) = 1;
b0c5e347 14845
97221fd7 14846 varpool_node::finalize_decl (decl);
1e8e9920 14847
d4786b13 14848 critical_name_mutexes->put (name, decl);
1e8e9920 14849 }
14850 else
d4786b13 14851 decl = *n;
1e8e9920 14852
ca4c3545 14853 /* If '#pragma omp critical' is inside offloaded region or
351fb0ce 14854 inside function marked as offloadable, the symbol must be
14855 marked as offloadable too. */
14856 omp_context *octx;
14857 if (cgraph_node::get (current_function_decl)->offloadable)
14858 varpool_node::get_create (decl)->offloadable = 1;
14859 else
14860 for (octx = ctx->outer; octx; octx = octx->outer)
ca4c3545 14861 if (is_gimple_omp_offloaded (octx->stmt))
351fb0ce 14862 {
14863 varpool_node::get_create (decl)->offloadable = 1;
14864 break;
14865 }
14866
b9a16870 14867 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_START);
389dd41b 14868 lock = build_call_expr_loc (loc, lock, 1, build_fold_addr_expr_loc (loc, decl));
1e8e9920 14869
b9a16870 14870 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_END);
389dd41b 14871 unlock = build_call_expr_loc (loc, unlock, 1,
14872 build_fold_addr_expr_loc (loc, decl));
1e8e9920 14873 }
14874 else
14875 {
b9a16870 14876 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_START);
389dd41b 14877 lock = build_call_expr_loc (loc, lock, 0);
1e8e9920 14878
b9a16870 14879 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_END);
389dd41b 14880 unlock = build_call_expr_loc (loc, unlock, 0);
1e8e9920 14881 }
14882
8a4a28a8 14883 push_gimplify_context ();
1e8e9920 14884
14885 block = make_node (BLOCK);
e3a19533 14886 bind = gimple_build_bind (NULL, NULL, block);
14887 gsi_replace (gsi_p, bind, true);
14888 gimple_bind_add_stmt (bind, stmt);
61e47ac8 14889
75a70cf9 14890 tbody = gimple_bind_body (bind);
14891 gimplify_and_add (lock, &tbody);
14892 gimple_bind_set_body (bind, tbody);
1e8e9920 14893
e3a19533 14894 lower_omp (gimple_omp_body_ptr (stmt), ctx);
75a70cf9 14895 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
14896 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
14897 gimple_omp_set_body (stmt, NULL);
1e8e9920 14898
75a70cf9 14899 tbody = gimple_bind_body (bind);
14900 gimplify_and_add (unlock, &tbody);
14901 gimple_bind_set_body (bind, tbody);
61e47ac8 14902
75a70cf9 14903 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
1e8e9920 14904
14905 pop_gimplify_context (bind);
75a70cf9 14906 gimple_bind_append_vars (bind, ctx->block_vars);
14907 BLOCK_VARS (block) = gimple_bind_vars (bind);
773c5ba7 14908}
14909
14910
14911/* A subroutine of lower_omp_for. Generate code to emit the predicate
14912 for a lastprivate clause. Given a loop control predicate of (V
14913 cond N2), we gate the clause on (!(V cond N2)). The lowered form
1e4afe3c 14914 is appended to *DLIST, iterator initialization is appended to
14915 *BODY_P. */
773c5ba7 14916
14917static void
75a70cf9 14918lower_omp_for_lastprivate (struct omp_for_data *fd, gimple_seq *body_p,
14919 gimple_seq *dlist, struct omp_context *ctx)
773c5ba7 14920{
75a70cf9 14921 tree clauses, cond, vinit;
773c5ba7 14922 enum tree_code cond_code;
75a70cf9 14923 gimple_seq stmts;
48e1416a 14924
fd6481cf 14925 cond_code = fd->loop.cond_code;
773c5ba7 14926 cond_code = cond_code == LT_EXPR ? GE_EXPR : LE_EXPR;
14927
14928 /* When possible, use a strict equality expression. This can let VRP
14929 type optimizations deduce the value and remove a copy. */
e913b5cd 14930 if (tree_fits_shwi_p (fd->loop.step))
773c5ba7 14931 {
e913b5cd 14932 HOST_WIDE_INT step = tree_to_shwi (fd->loop.step);
773c5ba7 14933 if (step == 1 || step == -1)
14934 cond_code = EQ_EXPR;
14935 }
14936
d7729e26 14937 tree n2 = fd->loop.n2;
14938 if (fd->collapse > 1
14939 && TREE_CODE (n2) != INTEGER_CST
43895be5 14940 && gimple_omp_for_combined_into_p (fd->for_stmt))
d7729e26 14941 {
9561765e 14942 struct omp_context *taskreg_ctx = NULL;
43895be5 14943 if (gimple_code (ctx->outer->stmt) == GIMPLE_OMP_FOR)
14944 {
14945 gomp_for *gfor = as_a <gomp_for *> (ctx->outer->stmt);
9561765e 14946 if (gimple_omp_for_kind (gfor) == GF_OMP_FOR_KIND_FOR
14947 || gimple_omp_for_kind (gfor) == GF_OMP_FOR_KIND_DISTRIBUTE)
43895be5 14948 {
9561765e 14949 if (gimple_omp_for_combined_into_p (gfor))
14950 {
14951 gcc_assert (ctx->outer->outer
14952 && is_parallel_ctx (ctx->outer->outer));
14953 taskreg_ctx = ctx->outer->outer;
14954 }
14955 else
14956 {
14957 struct omp_for_data outer_fd;
14958 extract_omp_for_data (gfor, &outer_fd, NULL);
14959 n2 = fold_convert (TREE_TYPE (n2), outer_fd.loop.n2);
14960 }
43895be5 14961 }
14962 else if (gimple_omp_for_kind (gfor) == GF_OMP_FOR_KIND_TASKLOOP)
9561765e 14963 taskreg_ctx = ctx->outer->outer;
43895be5 14964 }
9561765e 14965 else if (is_taskreg_ctx (ctx->outer))
14966 taskreg_ctx = ctx->outer;
14967 if (taskreg_ctx)
d7729e26 14968 {
43895be5 14969 int i;
14970 tree innerc
9561765e 14971 = find_omp_clause (gimple_omp_taskreg_clauses (taskreg_ctx->stmt),
43895be5 14972 OMP_CLAUSE__LOOPTEMP_);
14973 gcc_assert (innerc);
14974 for (i = 0; i < fd->collapse; i++)
14975 {
14976 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
14977 OMP_CLAUSE__LOOPTEMP_);
14978 gcc_assert (innerc);
14979 }
14980 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
14981 OMP_CLAUSE__LOOPTEMP_);
14982 if (innerc)
14983 n2 = fold_convert (TREE_TYPE (n2),
14984 lookup_decl (OMP_CLAUSE_DECL (innerc),
9561765e 14985 taskreg_ctx));
d7729e26 14986 }
14987 }
14988 cond = build2 (cond_code, boolean_type_node, fd->loop.v, n2);
773c5ba7 14989
75a70cf9 14990 clauses = gimple_omp_for_clauses (fd->for_stmt);
1e4afe3c 14991 stmts = NULL;
14992 lower_lastprivate_clauses (clauses, cond, &stmts, ctx);
75a70cf9 14993 if (!gimple_seq_empty_p (stmts))
1e4afe3c 14994 {
75a70cf9 14995 gimple_seq_add_seq (&stmts, *dlist);
fd6481cf 14996 *dlist = stmts;
1e4afe3c 14997
14998 /* Optimize: v = 0; is usually cheaper than v = some_other_constant. */
fd6481cf 14999 vinit = fd->loop.n1;
1e4afe3c 15000 if (cond_code == EQ_EXPR
e913b5cd 15001 && tree_fits_shwi_p (fd->loop.n2)
fd6481cf 15002 && ! integer_zerop (fd->loop.n2))
15003 vinit = build_int_cst (TREE_TYPE (fd->loop.v), 0);
3d483a94 15004 else
15005 vinit = unshare_expr (vinit);
1e4afe3c 15006
15007 /* Initialize the iterator variable, so that threads that don't execute
15008 any iterations don't execute the lastprivate clauses by accident. */
75a70cf9 15009 gimplify_assign (fd->loop.v, vinit, body_p);
1e4afe3c 15010 }
773c5ba7 15011}
15012
15013
ca4c3545 15014/* Lower code for an OMP loop directive. */
773c5ba7 15015
15016static void
75a70cf9 15017lower_omp_for (gimple_stmt_iterator *gsi_p, omp_context *ctx)
773c5ba7 15018{
75a70cf9 15019 tree *rhs_p, block;
bc7bff74 15020 struct omp_for_data fd, *fdp = NULL;
1a91d914 15021 gomp_for *stmt = as_a <gomp_for *> (gsi_stmt (*gsi_p));
15022 gbind *new_stmt;
f018d957 15023 gimple_seq omp_for_body, body, dlist;
a8e785ba 15024 gimple_seq oacc_head = NULL, oacc_tail = NULL;
75a70cf9 15025 size_t i;
773c5ba7 15026
8a4a28a8 15027 push_gimplify_context ();
773c5ba7 15028
e3a19533 15029 lower_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
773c5ba7 15030
1d22f541 15031 block = make_node (BLOCK);
75a70cf9 15032 new_stmt = gimple_build_bind (NULL, NULL, block);
e3a19533 15033 /* Replace at gsi right away, so that 'stmt' is no member
47ae02b7 15034 of a sequence anymore as we're going to add to a different
e3a19533 15035 one below. */
15036 gsi_replace (gsi_p, new_stmt, true);
1d22f541 15037
773c5ba7 15038 /* Move declaration of temporaries in the loop body before we make
15039 it go away. */
75a70cf9 15040 omp_for_body = gimple_omp_body (stmt);
15041 if (!gimple_seq_empty_p (omp_for_body)
15042 && gimple_code (gimple_seq_first_stmt (omp_for_body)) == GIMPLE_BIND)
15043 {
1a91d914 15044 gbind *inner_bind
15045 = as_a <gbind *> (gimple_seq_first_stmt (omp_for_body));
6d5a8d89 15046 tree vars = gimple_bind_vars (inner_bind);
75a70cf9 15047 gimple_bind_append_vars (new_stmt, vars);
6d5a8d89 15048 /* bind_vars/BLOCK_VARS are being moved to new_stmt/block, don't
15049 keep them on the inner_bind and it's block. */
15050 gimple_bind_set_vars (inner_bind, NULL_TREE);
15051 if (gimple_bind_block (inner_bind))
15052 BLOCK_VARS (gimple_bind_block (inner_bind)) = NULL_TREE;
75a70cf9 15053 }
773c5ba7 15054
bc7bff74 15055 if (gimple_omp_for_combined_into_p (stmt))
15056 {
15057 extract_omp_for_data (stmt, &fd, NULL);
15058 fdp = &fd;
15059
15060 /* We need two temporaries with fd.loop.v type (istart/iend)
15061 and then (fd.collapse - 1) temporaries with the same
15062 type for count2 ... countN-1 vars if not constant. */
15063 size_t count = 2;
15064 tree type = fd.iter_type;
15065 if (fd.collapse > 1
15066 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
15067 count += fd.collapse - 1;
43895be5 15068 bool taskreg_for
15069 = (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR
15070 || gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_TASKLOOP);
bc7bff74 15071 tree outerc = NULL, *pc = gimple_omp_for_clauses_ptr (stmt);
15072 tree clauses = *pc;
43895be5 15073 if (taskreg_for)
bc7bff74 15074 outerc
43895be5 15075 = find_omp_clause (gimple_omp_taskreg_clauses (ctx->outer->stmt),
bc7bff74 15076 OMP_CLAUSE__LOOPTEMP_);
15077 for (i = 0; i < count; i++)
15078 {
15079 tree temp;
43895be5 15080 if (taskreg_for)
bc7bff74 15081 {
15082 gcc_assert (outerc);
15083 temp = lookup_decl (OMP_CLAUSE_DECL (outerc), ctx->outer);
15084 outerc = find_omp_clause (OMP_CLAUSE_CHAIN (outerc),
15085 OMP_CLAUSE__LOOPTEMP_);
15086 }
15087 else
691447ab 15088 {
f9e245b2 15089 temp = create_tmp_var (type);
691447ab 15090 insert_decl_map (&ctx->outer->cb, temp, temp);
15091 }
bc7bff74 15092 *pc = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__LOOPTEMP_);
15093 OMP_CLAUSE_DECL (*pc) = temp;
15094 pc = &OMP_CLAUSE_CHAIN (*pc);
15095 }
15096 *pc = clauses;
15097 }
15098
75a70cf9 15099 /* The pre-body and input clauses go before the lowered GIMPLE_OMP_FOR. */
773c5ba7 15100 dlist = NULL;
75a70cf9 15101 body = NULL;
bc7bff74 15102 lower_rec_input_clauses (gimple_omp_for_clauses (stmt), &body, &dlist, ctx,
15103 fdp);
75a70cf9 15104 gimple_seq_add_seq (&body, gimple_omp_for_pre_body (stmt));
773c5ba7 15105
3d483a94 15106 lower_omp (gimple_omp_body_ptr (stmt), ctx);
15107
773c5ba7 15108 /* Lower the header expressions. At this point, we can assume that
15109 the header is of the form:
15110
15111 #pragma omp for (V = VAL1; V {<|>|<=|>=} VAL2; V = V [+-] VAL3)
15112
15113 We just need to make sure that VAL1, VAL2 and VAL3 are lowered
15114 using the .omp_data_s mapping, if needed. */
75a70cf9 15115 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
fd6481cf 15116 {
75a70cf9 15117 rhs_p = gimple_omp_for_initial_ptr (stmt, i);
fd6481cf 15118 if (!is_gimple_min_invariant (*rhs_p))
75a70cf9 15119 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
fd6481cf 15120
75a70cf9 15121 rhs_p = gimple_omp_for_final_ptr (stmt, i);
fd6481cf 15122 if (!is_gimple_min_invariant (*rhs_p))
75a70cf9 15123 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
fd6481cf 15124
75a70cf9 15125 rhs_p = &TREE_OPERAND (gimple_omp_for_incr (stmt, i), 1);
fd6481cf 15126 if (!is_gimple_min_invariant (*rhs_p))
75a70cf9 15127 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
fd6481cf 15128 }
773c5ba7 15129
15130 /* Once lowered, extract the bounds and clauses. */
fd6481cf 15131 extract_omp_for_data (stmt, &fd, NULL);
773c5ba7 15132
a8e785ba 15133 if (is_gimple_omp_oacc (ctx->stmt)
15134 && !ctx_in_oacc_kernels_region (ctx))
15135 lower_oacc_head_tail (gimple_location (stmt),
15136 gimple_omp_for_clauses (stmt),
15137 &oacc_head, &oacc_tail, ctx);
15138
f69b8a4c 15139 /* Add OpenACC partitioning and reduction markers just before the loop */
a8e785ba 15140 if (oacc_head)
15141 gimple_seq_add_seq (&body, oacc_head);
15142
75a70cf9 15143 lower_omp_for_lastprivate (&fd, &body, &dlist, ctx);
773c5ba7 15144
43895be5 15145 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR)
15146 for (tree c = gimple_omp_for_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c))
15147 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
15148 && !OMP_CLAUSE_LINEAR_NO_COPYIN (c))
15149 {
15150 OMP_CLAUSE_DECL (c) = lookup_decl (OMP_CLAUSE_DECL (c), ctx);
15151 if (DECL_P (OMP_CLAUSE_LINEAR_STEP (c)))
15152 OMP_CLAUSE_LINEAR_STEP (c)
15153 = maybe_lookup_decl_in_outer_ctx (OMP_CLAUSE_LINEAR_STEP (c),
15154 ctx);
15155 }
15156
56686608 15157 if (!gimple_omp_for_grid_phony (stmt))
15158 gimple_seq_add_stmt (&body, stmt);
75a70cf9 15159 gimple_seq_add_seq (&body, gimple_omp_body (stmt));
61e47ac8 15160
56686608 15161 if (!gimple_omp_for_grid_phony (stmt))
15162 gimple_seq_add_stmt (&body, gimple_build_omp_continue (fd.loop.v,
15163 fd.loop.v));
61e47ac8 15164
773c5ba7 15165 /* After the loop, add exit clauses. */
75a70cf9 15166 lower_reduction_clauses (gimple_omp_for_clauses (stmt), &body, ctx);
bc7bff74 15167
15168 if (ctx->cancellable)
15169 gimple_seq_add_stmt (&body, gimple_build_label (ctx->cancel_label));
15170
75a70cf9 15171 gimple_seq_add_seq (&body, dlist);
773c5ba7 15172
75a70cf9 15173 body = maybe_catch_exception (body);
aade31a0 15174
56686608 15175 if (!gimple_omp_for_grid_phony (stmt))
15176 {
15177 /* Region exit marker goes at the end of the loop body. */
15178 gimple_seq_add_stmt (&body, gimple_build_omp_return (fd.have_nowait));
15179 maybe_add_implicit_barrier_cancel (ctx, &body);
15180 }
a8e785ba 15181
15182 /* Add OpenACC joining and reduction markers just after the loop. */
15183 if (oacc_tail)
15184 gimple_seq_add_seq (&body, oacc_tail);
15185
1d22f541 15186 pop_gimplify_context (new_stmt);
75a70cf9 15187
15188 gimple_bind_append_vars (new_stmt, ctx->block_vars);
15189 BLOCK_VARS (block) = gimple_bind_vars (new_stmt);
1d22f541 15190 if (BLOCK_VARS (block))
15191 TREE_USED (block) = 1;
773c5ba7 15192
75a70cf9 15193 gimple_bind_set_body (new_stmt, body);
15194 gimple_omp_set_body (stmt, NULL);
15195 gimple_omp_for_set_pre_body (stmt, NULL);
1e8e9920 15196}
15197
48e1416a 15198/* Callback for walk_stmts. Check if the current statement only contains
a7dfc4fe 15199 GIMPLE_OMP_FOR or GIMPLE_OMP_SECTIONS. */
de7ef844 15200
15201static tree
75a70cf9 15202check_combined_parallel (gimple_stmt_iterator *gsi_p,
15203 bool *handled_ops_p,
15204 struct walk_stmt_info *wi)
de7ef844 15205{
4077bf7a 15206 int *info = (int *) wi->info;
42acab1c 15207 gimple *stmt = gsi_stmt (*gsi_p);
de7ef844 15208
75a70cf9 15209 *handled_ops_p = true;
15210 switch (gimple_code (stmt))
de7ef844 15211 {
75a70cf9 15212 WALK_SUBSTMTS;
15213
15214 case GIMPLE_OMP_FOR:
15215 case GIMPLE_OMP_SECTIONS:
de7ef844 15216 *info = *info == 0 ? 1 : -1;
15217 break;
15218 default:
15219 *info = -1;
15220 break;
15221 }
15222 return NULL;
15223}
773c5ba7 15224
fd6481cf 15225struct omp_taskcopy_context
15226{
15227 /* This field must be at the beginning, as we do "inheritance": Some
15228 callback functions for tree-inline.c (e.g., omp_copy_decl)
15229 receive a copy_body_data pointer that is up-casted to an
15230 omp_context pointer. */
15231 copy_body_data cb;
15232 omp_context *ctx;
15233};
15234
15235static tree
15236task_copyfn_copy_decl (tree var, copy_body_data *cb)
15237{
15238 struct omp_taskcopy_context *tcctx = (struct omp_taskcopy_context *) cb;
15239
15240 if (splay_tree_lookup (tcctx->ctx->sfield_map, (splay_tree_key) var))
f9e245b2 15241 return create_tmp_var (TREE_TYPE (var));
fd6481cf 15242
15243 return var;
15244}
15245
15246static tree
15247task_copyfn_remap_type (struct omp_taskcopy_context *tcctx, tree orig_type)
15248{
15249 tree name, new_fields = NULL, type, f;
15250
15251 type = lang_hooks.types.make_type (RECORD_TYPE);
15252 name = DECL_NAME (TYPE_NAME (orig_type));
e60a6f7b 15253 name = build_decl (gimple_location (tcctx->ctx->stmt),
15254 TYPE_DECL, name, type);
fd6481cf 15255 TYPE_NAME (type) = name;
15256
15257 for (f = TYPE_FIELDS (orig_type); f ; f = TREE_CHAIN (f))
15258 {
15259 tree new_f = copy_node (f);
15260 DECL_CONTEXT (new_f) = type;
15261 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &tcctx->cb);
15262 TREE_CHAIN (new_f) = new_fields;
75a70cf9 15263 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &tcctx->cb, NULL);
15264 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r, &tcctx->cb, NULL);
15265 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
15266 &tcctx->cb, NULL);
fd6481cf 15267 new_fields = new_f;
06ecf488 15268 tcctx->cb.decl_map->put (f, new_f);
fd6481cf 15269 }
15270 TYPE_FIELDS (type) = nreverse (new_fields);
15271 layout_type (type);
15272 return type;
15273}
15274
15275/* Create task copyfn. */
15276
15277static void
1a91d914 15278create_task_copyfn (gomp_task *task_stmt, omp_context *ctx)
fd6481cf 15279{
15280 struct function *child_cfun;
15281 tree child_fn, t, c, src, dst, f, sf, arg, sarg, decl;
15282 tree record_type, srecord_type, bind, list;
15283 bool record_needs_remap = false, srecord_needs_remap = false;
15284 splay_tree_node n;
15285 struct omp_taskcopy_context tcctx;
389dd41b 15286 location_t loc = gimple_location (task_stmt);
fd6481cf 15287
75a70cf9 15288 child_fn = gimple_omp_task_copy_fn (task_stmt);
fd6481cf 15289 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
15290 gcc_assert (child_cfun->cfg == NULL);
fd6481cf 15291 DECL_SAVED_TREE (child_fn) = alloc_stmt_list ();
15292
15293 /* Reset DECL_CONTEXT on function arguments. */
1767a056 15294 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
fd6481cf 15295 DECL_CONTEXT (t) = child_fn;
15296
15297 /* Populate the function. */
8a4a28a8 15298 push_gimplify_context ();
9078126c 15299 push_cfun (child_cfun);
fd6481cf 15300
15301 bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
15302 TREE_SIDE_EFFECTS (bind) = 1;
15303 list = NULL;
15304 DECL_SAVED_TREE (child_fn) = bind;
75a70cf9 15305 DECL_SOURCE_LOCATION (child_fn) = gimple_location (task_stmt);
fd6481cf 15306
15307 /* Remap src and dst argument types if needed. */
15308 record_type = ctx->record_type;
15309 srecord_type = ctx->srecord_type;
1767a056 15310 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
fd6481cf 15311 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
15312 {
15313 record_needs_remap = true;
15314 break;
15315 }
1767a056 15316 for (f = TYPE_FIELDS (srecord_type); f ; f = DECL_CHAIN (f))
fd6481cf 15317 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
15318 {
15319 srecord_needs_remap = true;
15320 break;
15321 }
15322
15323 if (record_needs_remap || srecord_needs_remap)
15324 {
15325 memset (&tcctx, '\0', sizeof (tcctx));
15326 tcctx.cb.src_fn = ctx->cb.src_fn;
15327 tcctx.cb.dst_fn = child_fn;
415d1b9a 15328 tcctx.cb.src_node = cgraph_node::get (tcctx.cb.src_fn);
53f79206 15329 gcc_checking_assert (tcctx.cb.src_node);
fd6481cf 15330 tcctx.cb.dst_node = tcctx.cb.src_node;
15331 tcctx.cb.src_cfun = ctx->cb.src_cfun;
15332 tcctx.cb.copy_decl = task_copyfn_copy_decl;
e38def9c 15333 tcctx.cb.eh_lp_nr = 0;
fd6481cf 15334 tcctx.cb.transform_call_graph_edges = CB_CGE_MOVE;
06ecf488 15335 tcctx.cb.decl_map = new hash_map<tree, tree>;
fd6481cf 15336 tcctx.ctx = ctx;
15337
15338 if (record_needs_remap)
15339 record_type = task_copyfn_remap_type (&tcctx, record_type);
15340 if (srecord_needs_remap)
15341 srecord_type = task_copyfn_remap_type (&tcctx, srecord_type);
15342 }
15343 else
15344 tcctx.cb.decl_map = NULL;
15345
fd6481cf 15346 arg = DECL_ARGUMENTS (child_fn);
15347 TREE_TYPE (arg) = build_pointer_type (record_type);
1767a056 15348 sarg = DECL_CHAIN (arg);
fd6481cf 15349 TREE_TYPE (sarg) = build_pointer_type (srecord_type);
15350
15351 /* First pass: initialize temporaries used in record_type and srecord_type
15352 sizes and field offsets. */
15353 if (tcctx.cb.decl_map)
75a70cf9 15354 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
fd6481cf 15355 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
15356 {
15357 tree *p;
15358
15359 decl = OMP_CLAUSE_DECL (c);
06ecf488 15360 p = tcctx.cb.decl_map->get (decl);
fd6481cf 15361 if (p == NULL)
15362 continue;
15363 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
15364 sf = (tree) n->value;
06ecf488 15365 sf = *tcctx.cb.decl_map->get (sf);
182cf5a9 15366 src = build_simple_mem_ref_loc (loc, sarg);
445d06b6 15367 src = omp_build_component_ref (src, sf);
75a70cf9 15368 t = build2 (MODIFY_EXPR, TREE_TYPE (*p), *p, src);
fd6481cf 15369 append_to_statement_list (t, &list);
15370 }
15371
15372 /* Second pass: copy shared var pointers and copy construct non-VLA
15373 firstprivate vars. */
75a70cf9 15374 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
fd6481cf 15375 switch (OMP_CLAUSE_CODE (c))
15376 {
43895be5 15377 splay_tree_key key;
fd6481cf 15378 case OMP_CLAUSE_SHARED:
15379 decl = OMP_CLAUSE_DECL (c);
43895be5 15380 key = (splay_tree_key) decl;
15381 if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
15382 key = (splay_tree_key) &DECL_UID (decl);
15383 n = splay_tree_lookup (ctx->field_map, key);
fd6481cf 15384 if (n == NULL)
15385 break;
15386 f = (tree) n->value;
15387 if (tcctx.cb.decl_map)
06ecf488 15388 f = *tcctx.cb.decl_map->get (f);
43895be5 15389 n = splay_tree_lookup (ctx->sfield_map, key);
fd6481cf 15390 sf = (tree) n->value;
15391 if (tcctx.cb.decl_map)
06ecf488 15392 sf = *tcctx.cb.decl_map->get (sf);
182cf5a9 15393 src = build_simple_mem_ref_loc (loc, sarg);
445d06b6 15394 src = omp_build_component_ref (src, sf);
182cf5a9 15395 dst = build_simple_mem_ref_loc (loc, arg);
445d06b6 15396 dst = omp_build_component_ref (dst, f);
75a70cf9 15397 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
fd6481cf 15398 append_to_statement_list (t, &list);
15399 break;
15400 case OMP_CLAUSE_FIRSTPRIVATE:
15401 decl = OMP_CLAUSE_DECL (c);
15402 if (is_variable_sized (decl))
15403 break;
15404 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
15405 if (n == NULL)
15406 break;
15407 f = (tree) n->value;
15408 if (tcctx.cb.decl_map)
06ecf488 15409 f = *tcctx.cb.decl_map->get (f);
fd6481cf 15410 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
15411 if (n != NULL)
15412 {
15413 sf = (tree) n->value;
15414 if (tcctx.cb.decl_map)
06ecf488 15415 sf = *tcctx.cb.decl_map->get (sf);
182cf5a9 15416 src = build_simple_mem_ref_loc (loc, sarg);
445d06b6 15417 src = omp_build_component_ref (src, sf);
fd6481cf 15418 if (use_pointer_for_field (decl, NULL) || is_reference (decl))
182cf5a9 15419 src = build_simple_mem_ref_loc (loc, src);
fd6481cf 15420 }
15421 else
15422 src = decl;
182cf5a9 15423 dst = build_simple_mem_ref_loc (loc, arg);
445d06b6 15424 dst = omp_build_component_ref (dst, f);
fd6481cf 15425 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
15426 append_to_statement_list (t, &list);
15427 break;
15428 case OMP_CLAUSE_PRIVATE:
15429 if (! OMP_CLAUSE_PRIVATE_OUTER_REF (c))
15430 break;
15431 decl = OMP_CLAUSE_DECL (c);
15432 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
15433 f = (tree) n->value;
15434 if (tcctx.cb.decl_map)
06ecf488 15435 f = *tcctx.cb.decl_map->get (f);
fd6481cf 15436 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
15437 if (n != NULL)
15438 {
15439 sf = (tree) n->value;
15440 if (tcctx.cb.decl_map)
06ecf488 15441 sf = *tcctx.cb.decl_map->get (sf);
182cf5a9 15442 src = build_simple_mem_ref_loc (loc, sarg);
445d06b6 15443 src = omp_build_component_ref (src, sf);
fd6481cf 15444 if (use_pointer_for_field (decl, NULL))
182cf5a9 15445 src = build_simple_mem_ref_loc (loc, src);
fd6481cf 15446 }
15447 else
15448 src = decl;
182cf5a9 15449 dst = build_simple_mem_ref_loc (loc, arg);
445d06b6 15450 dst = omp_build_component_ref (dst, f);
75a70cf9 15451 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
fd6481cf 15452 append_to_statement_list (t, &list);
15453 break;
15454 default:
15455 break;
15456 }
15457
15458 /* Last pass: handle VLA firstprivates. */
15459 if (tcctx.cb.decl_map)
75a70cf9 15460 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
fd6481cf 15461 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
15462 {
15463 tree ind, ptr, df;
15464
15465 decl = OMP_CLAUSE_DECL (c);
15466 if (!is_variable_sized (decl))
15467 continue;
15468 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
15469 if (n == NULL)
15470 continue;
15471 f = (tree) n->value;
06ecf488 15472 f = *tcctx.cb.decl_map->get (f);
fd6481cf 15473 gcc_assert (DECL_HAS_VALUE_EXPR_P (decl));
15474 ind = DECL_VALUE_EXPR (decl);
15475 gcc_assert (TREE_CODE (ind) == INDIRECT_REF);
15476 gcc_assert (DECL_P (TREE_OPERAND (ind, 0)));
15477 n = splay_tree_lookup (ctx->sfield_map,
15478 (splay_tree_key) TREE_OPERAND (ind, 0));
15479 sf = (tree) n->value;
06ecf488 15480 sf = *tcctx.cb.decl_map->get (sf);
182cf5a9 15481 src = build_simple_mem_ref_loc (loc, sarg);
445d06b6 15482 src = omp_build_component_ref (src, sf);
182cf5a9 15483 src = build_simple_mem_ref_loc (loc, src);
15484 dst = build_simple_mem_ref_loc (loc, arg);
445d06b6 15485 dst = omp_build_component_ref (dst, f);
fd6481cf 15486 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
15487 append_to_statement_list (t, &list);
15488 n = splay_tree_lookup (ctx->field_map,
15489 (splay_tree_key) TREE_OPERAND (ind, 0));
15490 df = (tree) n->value;
06ecf488 15491 df = *tcctx.cb.decl_map->get (df);
182cf5a9 15492 ptr = build_simple_mem_ref_loc (loc, arg);
445d06b6 15493 ptr = omp_build_component_ref (ptr, df);
75a70cf9 15494 t = build2 (MODIFY_EXPR, TREE_TYPE (ptr), ptr,
389dd41b 15495 build_fold_addr_expr_loc (loc, dst));
fd6481cf 15496 append_to_statement_list (t, &list);
15497 }
15498
15499 t = build1 (RETURN_EXPR, void_type_node, NULL);
15500 append_to_statement_list (t, &list);
15501
15502 if (tcctx.cb.decl_map)
06ecf488 15503 delete tcctx.cb.decl_map;
fd6481cf 15504 pop_gimplify_context (NULL);
15505 BIND_EXPR_BODY (bind) = list;
15506 pop_cfun ();
fd6481cf 15507}
15508
bc7bff74 15509static void
43895be5 15510lower_depend_clauses (tree *pclauses, gimple_seq *iseq, gimple_seq *oseq)
bc7bff74 15511{
15512 tree c, clauses;
42acab1c 15513 gimple *g;
bc7bff74 15514 size_t n_in = 0, n_out = 0, idx = 2, i;
15515
43895be5 15516 clauses = find_omp_clause (*pclauses, OMP_CLAUSE_DEPEND);
bc7bff74 15517 gcc_assert (clauses);
15518 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
15519 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
15520 switch (OMP_CLAUSE_DEPEND_KIND (c))
15521 {
15522 case OMP_CLAUSE_DEPEND_IN:
15523 n_in++;
15524 break;
15525 case OMP_CLAUSE_DEPEND_OUT:
15526 case OMP_CLAUSE_DEPEND_INOUT:
15527 n_out++;
15528 break;
43895be5 15529 case OMP_CLAUSE_DEPEND_SOURCE:
15530 case OMP_CLAUSE_DEPEND_SINK:
15531 /* FALLTHRU */
bc7bff74 15532 default:
15533 gcc_unreachable ();
15534 }
15535 tree type = build_array_type_nelts (ptr_type_node, n_in + n_out + 2);
f9e245b2 15536 tree array = create_tmp_var (type);
43895be5 15537 TREE_ADDRESSABLE (array) = 1;
bc7bff74 15538 tree r = build4 (ARRAY_REF, ptr_type_node, array, size_int (0), NULL_TREE,
15539 NULL_TREE);
15540 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_in + n_out));
15541 gimple_seq_add_stmt (iseq, g);
15542 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (1), NULL_TREE,
15543 NULL_TREE);
15544 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_out));
15545 gimple_seq_add_stmt (iseq, g);
15546 for (i = 0; i < 2; i++)
15547 {
15548 if ((i ? n_in : n_out) == 0)
15549 continue;
15550 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
15551 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
15552 && ((OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_IN) ^ i))
15553 {
15554 tree t = OMP_CLAUSE_DECL (c);
15555 t = fold_convert (ptr_type_node, t);
15556 gimplify_expr (&t, iseq, NULL, is_gimple_val, fb_rvalue);
15557 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (idx++),
15558 NULL_TREE, NULL_TREE);
15559 g = gimple_build_assign (r, t);
15560 gimple_seq_add_stmt (iseq, g);
15561 }
15562 }
bc7bff74 15563 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_DEPEND);
15564 OMP_CLAUSE_DECL (c) = build_fold_addr_expr (array);
43895be5 15565 OMP_CLAUSE_CHAIN (c) = *pclauses;
15566 *pclauses = c;
bc7bff74 15567 tree clobber = build_constructor (type, NULL);
15568 TREE_THIS_VOLATILE (clobber) = 1;
15569 g = gimple_build_assign (array, clobber);
15570 gimple_seq_add_stmt (oseq, g);
15571}
15572
75a70cf9 15573/* Lower the OpenMP parallel or task directive in the current statement
15574 in GSI_P. CTX holds context information for the directive. */
773c5ba7 15575
15576static void
75a70cf9 15577lower_omp_taskreg (gimple_stmt_iterator *gsi_p, omp_context *ctx)
773c5ba7 15578{
75a70cf9 15579 tree clauses;
15580 tree child_fn, t;
42acab1c 15581 gimple *stmt = gsi_stmt (*gsi_p);
1a91d914 15582 gbind *par_bind, *bind, *dep_bind = NULL;
bc7bff74 15583 gimple_seq par_body, olist, ilist, par_olist, par_rlist, par_ilist, new_body;
389dd41b 15584 location_t loc = gimple_location (stmt);
773c5ba7 15585
75a70cf9 15586 clauses = gimple_omp_taskreg_clauses (stmt);
1a91d914 15587 par_bind
15588 = as_a <gbind *> (gimple_seq_first_stmt (gimple_omp_body (stmt)));
75a70cf9 15589 par_body = gimple_bind_body (par_bind);
773c5ba7 15590 child_fn = ctx->cb.dst_fn;
75a70cf9 15591 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
15592 && !gimple_omp_parallel_combined_p (stmt))
de7ef844 15593 {
15594 struct walk_stmt_info wi;
15595 int ws_num = 0;
15596
15597 memset (&wi, 0, sizeof (wi));
de7ef844 15598 wi.info = &ws_num;
15599 wi.val_only = true;
75a70cf9 15600 walk_gimple_seq (par_body, check_combined_parallel, NULL, &wi);
de7ef844 15601 if (ws_num == 1)
75a70cf9 15602 gimple_omp_parallel_set_combined_p (stmt, true);
de7ef844 15603 }
bc7bff74 15604 gimple_seq dep_ilist = NULL;
15605 gimple_seq dep_olist = NULL;
15606 if (gimple_code (stmt) == GIMPLE_OMP_TASK
15607 && find_omp_clause (clauses, OMP_CLAUSE_DEPEND))
15608 {
8a4a28a8 15609 push_gimplify_context ();
bc7bff74 15610 dep_bind = gimple_build_bind (NULL, NULL, make_node (BLOCK));
43895be5 15611 lower_depend_clauses (gimple_omp_task_clauses_ptr (stmt),
15612 &dep_ilist, &dep_olist);
bc7bff74 15613 }
15614
fd6481cf 15615 if (ctx->srecord_type)
1a91d914 15616 create_task_copyfn (as_a <gomp_task *> (stmt), ctx);
773c5ba7 15617
8a4a28a8 15618 push_gimplify_context ();
773c5ba7 15619
75a70cf9 15620 par_olist = NULL;
15621 par_ilist = NULL;
bc7bff74 15622 par_rlist = NULL;
56686608 15623 bool phony_construct = gimple_code (stmt) == GIMPLE_OMP_PARALLEL
15624 && gimple_omp_parallel_grid_phony (as_a <gomp_parallel *> (stmt));
15625 if (phony_construct && ctx->record_type)
15626 {
15627 gcc_checking_assert (!ctx->receiver_decl);
15628 ctx->receiver_decl = create_tmp_var
15629 (build_reference_type (ctx->record_type), ".omp_rec");
15630 }
bc7bff74 15631 lower_rec_input_clauses (clauses, &par_ilist, &par_olist, ctx, NULL);
e3a19533 15632 lower_omp (&par_body, ctx);
75a70cf9 15633 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL)
bc7bff74 15634 lower_reduction_clauses (clauses, &par_rlist, ctx);
773c5ba7 15635
15636 /* Declare all the variables created by mapping and the variables
15637 declared in the scope of the parallel body. */
15638 record_vars_into (ctx->block_vars, child_fn);
75a70cf9 15639 record_vars_into (gimple_bind_vars (par_bind), child_fn);
773c5ba7 15640
15641 if (ctx->record_type)
15642 {
fd6481cf 15643 ctx->sender_decl
15644 = create_tmp_var (ctx->srecord_type ? ctx->srecord_type
15645 : ctx->record_type, ".omp_data_o");
84bfaaeb 15646 DECL_NAMELESS (ctx->sender_decl) = 1;
86f2ad37 15647 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
75a70cf9 15648 gimple_omp_taskreg_set_data_arg (stmt, ctx->sender_decl);
773c5ba7 15649 }
15650
75a70cf9 15651 olist = NULL;
15652 ilist = NULL;
773c5ba7 15653 lower_send_clauses (clauses, &ilist, &olist, ctx);
15654 lower_send_shared_vars (&ilist, &olist, ctx);
15655
bc7bff74 15656 if (ctx->record_type)
15657 {
15658 tree clobber = build_constructor (TREE_TYPE (ctx->sender_decl), NULL);
15659 TREE_THIS_VOLATILE (clobber) = 1;
15660 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
15661 clobber));
15662 }
15663
773c5ba7 15664 /* Once all the expansions are done, sequence all the different
75a70cf9 15665 fragments inside gimple_omp_body. */
773c5ba7 15666
75a70cf9 15667 new_body = NULL;
773c5ba7 15668
15669 if (ctx->record_type)
15670 {
389dd41b 15671 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
cc6b725b 15672 /* fixup_child_record_type might have changed receiver_decl's type. */
389dd41b 15673 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
75a70cf9 15674 gimple_seq_add_stmt (&new_body,
15675 gimple_build_assign (ctx->receiver_decl, t));
773c5ba7 15676 }
15677
75a70cf9 15678 gimple_seq_add_seq (&new_body, par_ilist);
15679 gimple_seq_add_seq (&new_body, par_body);
bc7bff74 15680 gimple_seq_add_seq (&new_body, par_rlist);
15681 if (ctx->cancellable)
15682 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
75a70cf9 15683 gimple_seq_add_seq (&new_body, par_olist);
15684 new_body = maybe_catch_exception (new_body);
b25f70fd 15685 if (gimple_code (stmt) == GIMPLE_OMP_TASK)
15686 gimple_seq_add_stmt (&new_body,
15687 gimple_build_omp_continue (integer_zero_node,
15688 integer_zero_node));
56686608 15689 if (!phony_construct)
15690 {
15691 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
15692 gimple_omp_set_body (stmt, new_body);
15693 }
773c5ba7 15694
75a70cf9 15695 bind = gimple_build_bind (NULL, NULL, gimple_bind_block (par_bind));
bc7bff74 15696 gsi_replace (gsi_p, dep_bind ? dep_bind : bind, true);
15697 gimple_bind_add_seq (bind, ilist);
56686608 15698 if (!phony_construct)
15699 gimple_bind_add_stmt (bind, stmt);
15700 else
15701 gimple_bind_add_seq (bind, new_body);
bc7bff74 15702 gimple_bind_add_seq (bind, olist);
15703
15704 pop_gimplify_context (NULL);
15705
15706 if (dep_bind)
15707 {
15708 gimple_bind_add_seq (dep_bind, dep_ilist);
15709 gimple_bind_add_stmt (dep_bind, bind);
15710 gimple_bind_add_seq (dep_bind, dep_olist);
15711 pop_gimplify_context (dep_bind);
15712 }
15713}
15714
ca4c3545 15715/* Lower the GIMPLE_OMP_TARGET in the current statement
bc7bff74 15716 in GSI_P. CTX holds context information for the directive. */
15717
15718static void
15719lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
15720{
15721 tree clauses;
15722 tree child_fn, t, c;
1a91d914 15723 gomp_target *stmt = as_a <gomp_target *> (gsi_stmt (*gsi_p));
43895be5 15724 gbind *tgt_bind, *bind, *dep_bind = NULL;
b656be3a 15725 gimple_seq tgt_body, olist, ilist, fplist, new_body;
bc7bff74 15726 location_t loc = gimple_location (stmt);
ca4c3545 15727 bool offloaded, data_region;
bc7bff74 15728 unsigned int map_cnt = 0;
15729
ca4c3545 15730 offloaded = is_gimple_omp_offloaded (stmt);
15731 switch (gimple_omp_target_kind (stmt))
15732 {
15733 case GF_OMP_TARGET_KIND_REGION:
15734 case GF_OMP_TARGET_KIND_UPDATE:
43895be5 15735 case GF_OMP_TARGET_KIND_ENTER_DATA:
15736 case GF_OMP_TARGET_KIND_EXIT_DATA:
ca4c3545 15737 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
15738 case GF_OMP_TARGET_KIND_OACC_KERNELS:
15739 case GF_OMP_TARGET_KIND_OACC_UPDATE:
15740 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
2fc5e987 15741 case GF_OMP_TARGET_KIND_OACC_DECLARE:
ca4c3545 15742 data_region = false;
15743 break;
15744 case GF_OMP_TARGET_KIND_DATA:
15745 case GF_OMP_TARGET_KIND_OACC_DATA:
571b3486 15746 case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
ca4c3545 15747 data_region = true;
15748 break;
15749 default:
15750 gcc_unreachable ();
15751 }
15752
bc7bff74 15753 clauses = gimple_omp_target_clauses (stmt);
ca4c3545 15754
43895be5 15755 gimple_seq dep_ilist = NULL;
15756 gimple_seq dep_olist = NULL;
15757 if (find_omp_clause (clauses, OMP_CLAUSE_DEPEND))
15758 {
15759 push_gimplify_context ();
15760 dep_bind = gimple_build_bind (NULL, NULL, make_node (BLOCK));
15761 lower_depend_clauses (gimple_omp_target_clauses_ptr (stmt),
15762 &dep_ilist, &dep_olist);
43895be5 15763 }
15764
ca4c3545 15765 tgt_bind = NULL;
15766 tgt_body = NULL;
15767 if (offloaded)
bc7bff74 15768 {
1a91d914 15769 tgt_bind = gimple_seq_first_stmt_as_a_bind (gimple_omp_body (stmt));
bc7bff74 15770 tgt_body = gimple_bind_body (tgt_bind);
15771 }
ca4c3545 15772 else if (data_region)
bc7bff74 15773 tgt_body = gimple_omp_body (stmt);
15774 child_fn = ctx->cb.dst_fn;
15775
8a4a28a8 15776 push_gimplify_context ();
b656be3a 15777 fplist = NULL;
bc7bff74 15778
15779 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
15780 switch (OMP_CLAUSE_CODE (c))
15781 {
15782 tree var, x;
15783
15784 default:
15785 break;
15786 case OMP_CLAUSE_MAP:
382ecba7 15787#if CHECKING_P
ca4c3545 15788 /* First check what we're prepared to handle in the following. */
15789 switch (OMP_CLAUSE_MAP_KIND (c))
15790 {
15791 case GOMP_MAP_ALLOC:
15792 case GOMP_MAP_TO:
15793 case GOMP_MAP_FROM:
15794 case GOMP_MAP_TOFROM:
15795 case GOMP_MAP_POINTER:
15796 case GOMP_MAP_TO_PSET:
5cb6b0b9 15797 case GOMP_MAP_DELETE:
43895be5 15798 case GOMP_MAP_RELEASE:
15799 case GOMP_MAP_ALWAYS_TO:
15800 case GOMP_MAP_ALWAYS_FROM:
15801 case GOMP_MAP_ALWAYS_TOFROM:
15802 case GOMP_MAP_FIRSTPRIVATE_POINTER:
9561765e 15803 case GOMP_MAP_FIRSTPRIVATE_REFERENCE:
43895be5 15804 case GOMP_MAP_STRUCT:
9561765e 15805 case GOMP_MAP_ALWAYS_POINTER:
ca4c3545 15806 break;
15807 case GOMP_MAP_FORCE_ALLOC:
15808 case GOMP_MAP_FORCE_TO:
15809 case GOMP_MAP_FORCE_FROM:
15810 case GOMP_MAP_FORCE_TOFROM:
15811 case GOMP_MAP_FORCE_PRESENT:
ca4c3545 15812 case GOMP_MAP_FORCE_DEVICEPTR:
2fc5e987 15813 case GOMP_MAP_DEVICE_RESIDENT:
15814 case GOMP_MAP_LINK:
ca4c3545 15815 gcc_assert (is_gimple_omp_oacc (stmt));
15816 break;
15817 default:
15818 gcc_unreachable ();
15819 }
15820#endif
15821 /* FALLTHRU */
bc7bff74 15822 case OMP_CLAUSE_TO:
15823 case OMP_CLAUSE_FROM:
b656be3a 15824 oacc_firstprivate:
bc7bff74 15825 var = OMP_CLAUSE_DECL (c);
15826 if (!DECL_P (var))
15827 {
15828 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP
43895be5 15829 || (!OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
15830 && (OMP_CLAUSE_MAP_KIND (c)
15831 != GOMP_MAP_FIRSTPRIVATE_POINTER)))
bc7bff74 15832 map_cnt++;
15833 continue;
15834 }
15835
15836 if (DECL_SIZE (var)
15837 && TREE_CODE (DECL_SIZE (var)) != INTEGER_CST)
15838 {
15839 tree var2 = DECL_VALUE_EXPR (var);
15840 gcc_assert (TREE_CODE (var2) == INDIRECT_REF);
15841 var2 = TREE_OPERAND (var2, 0);
15842 gcc_assert (DECL_P (var2));
15843 var = var2;
15844 }
15845
43895be5 15846 if (offloaded
b656be3a 15847 && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
9561765e 15848 && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
15849 || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_REFERENCE))
43895be5 15850 {
15851 if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
15852 {
15853 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx))
15854 && varpool_node::get_create (var)->offloadable)
15855 continue;
15856
15857 tree type = build_pointer_type (TREE_TYPE (var));
15858 tree new_var = lookup_decl (var, ctx);
15859 x = create_tmp_var_raw (type, get_name (new_var));
15860 gimple_add_tmp_var (x);
15861 x = build_simple_mem_ref (x);
15862 SET_DECL_VALUE_EXPR (new_var, x);
15863 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15864 }
15865 continue;
15866 }
15867
bc7bff74 15868 if (!maybe_lookup_field (var, ctx))
15869 continue;
15870
0c302595 15871 /* Don't remap oacc parallel reduction variables, because the
15872 intermediate result must be local to each gang. */
15873 if (offloaded && !(OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
15874 && OMP_CLAUSE_MAP_IN_REDUCTION (c)))
bc7bff74 15875 {
15876 x = build_receiver_ref (var, true, ctx);
15877 tree new_var = lookup_decl (var, ctx);
43895be5 15878
b656be3a 15879 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
15880 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
bc7bff74 15881 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
15882 && TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
15883 x = build_simple_mem_ref (x);
b656be3a 15884 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
15885 {
15886 gcc_assert (is_gimple_omp_oacc (ctx->stmt));
15887 if (is_reference (new_var))
15888 {
15889 /* Create a local object to hold the instance
15890 value. */
15891 tree type = TREE_TYPE (TREE_TYPE (new_var));
15892 const char *id = IDENTIFIER_POINTER (DECL_NAME (new_var));
15893 tree inst = create_tmp_var (type, id);
15894 gimplify_assign (inst, fold_indirect_ref (x), &fplist);
15895 x = build_fold_addr_expr (inst);
15896 }
15897 gimplify_assign (new_var, x, &fplist);
15898 }
15899 else if (DECL_P (new_var))
15900 {
15901 SET_DECL_VALUE_EXPR (new_var, x);
15902 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15903 }
15904 else
15905 gcc_unreachable ();
bc7bff74 15906 }
15907 map_cnt++;
43895be5 15908 break;
15909
15910 case OMP_CLAUSE_FIRSTPRIVATE:
b656be3a 15911 if (is_oacc_parallel (ctx))
15912 goto oacc_firstprivate;
43895be5 15913 map_cnt++;
15914 var = OMP_CLAUSE_DECL (c);
15915 if (!is_reference (var)
15916 && !is_gimple_reg_type (TREE_TYPE (var)))
15917 {
15918 tree new_var = lookup_decl (var, ctx);
15919 if (is_variable_sized (var))
15920 {
15921 tree pvar = DECL_VALUE_EXPR (var);
15922 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
15923 pvar = TREE_OPERAND (pvar, 0);
15924 gcc_assert (DECL_P (pvar));
15925 tree new_pvar = lookup_decl (pvar, ctx);
15926 x = build_fold_indirect_ref (new_pvar);
15927 TREE_THIS_NOTRAP (x) = 1;
15928 }
15929 else
15930 x = build_receiver_ref (var, true, ctx);
15931 SET_DECL_VALUE_EXPR (new_var, x);
15932 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15933 }
15934 break;
15935
15936 case OMP_CLAUSE_PRIVATE:
b656be3a 15937 if (is_gimple_omp_oacc (ctx->stmt))
15938 break;
43895be5 15939 var = OMP_CLAUSE_DECL (c);
15940 if (is_variable_sized (var))
15941 {
15942 tree new_var = lookup_decl (var, ctx);
15943 tree pvar = DECL_VALUE_EXPR (var);
15944 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
15945 pvar = TREE_OPERAND (pvar, 0);
15946 gcc_assert (DECL_P (pvar));
15947 tree new_pvar = lookup_decl (pvar, ctx);
15948 x = build_fold_indirect_ref (new_pvar);
15949 TREE_THIS_NOTRAP (x) = 1;
15950 SET_DECL_VALUE_EXPR (new_var, x);
15951 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15952 }
15953 break;
15954
15955 case OMP_CLAUSE_USE_DEVICE_PTR:
15956 case OMP_CLAUSE_IS_DEVICE_PTR:
15957 var = OMP_CLAUSE_DECL (c);
15958 map_cnt++;
15959 if (is_variable_sized (var))
15960 {
15961 tree new_var = lookup_decl (var, ctx);
15962 tree pvar = DECL_VALUE_EXPR (var);
15963 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
15964 pvar = TREE_OPERAND (pvar, 0);
15965 gcc_assert (DECL_P (pvar));
15966 tree new_pvar = lookup_decl (pvar, ctx);
15967 x = build_fold_indirect_ref (new_pvar);
15968 TREE_THIS_NOTRAP (x) = 1;
15969 SET_DECL_VALUE_EXPR (new_var, x);
15970 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15971 }
15972 else if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
15973 {
15974 tree new_var = lookup_decl (var, ctx);
15975 tree type = build_pointer_type (TREE_TYPE (var));
15976 x = create_tmp_var_raw (type, get_name (new_var));
15977 gimple_add_tmp_var (x);
15978 x = build_simple_mem_ref (x);
15979 SET_DECL_VALUE_EXPR (new_var, x);
15980 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15981 }
b86e24ea 15982 else
15983 {
15984 tree new_var = lookup_decl (var, ctx);
15985 x = create_tmp_var_raw (TREE_TYPE (new_var), get_name (new_var));
15986 gimple_add_tmp_var (x);
15987 SET_DECL_VALUE_EXPR (new_var, x);
15988 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15989 }
43895be5 15990 break;
bc7bff74 15991 }
15992
ca4c3545 15993 if (offloaded)
bc7bff74 15994 {
15995 target_nesting_level++;
15996 lower_omp (&tgt_body, ctx);
15997 target_nesting_level--;
15998 }
ca4c3545 15999 else if (data_region)
bc7bff74 16000 lower_omp (&tgt_body, ctx);
16001
ca4c3545 16002 if (offloaded)
bc7bff74 16003 {
16004 /* Declare all the variables created by mapping and the variables
16005 declared in the scope of the target body. */
16006 record_vars_into (ctx->block_vars, child_fn);
16007 record_vars_into (gimple_bind_vars (tgt_bind), child_fn);
16008 }
16009
16010 olist = NULL;
16011 ilist = NULL;
16012 if (ctx->record_type)
16013 {
16014 ctx->sender_decl
16015 = create_tmp_var (ctx->record_type, ".omp_data_arr");
16016 DECL_NAMELESS (ctx->sender_decl) = 1;
16017 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
16018 t = make_tree_vec (3);
16019 TREE_VEC_ELT (t, 0) = ctx->sender_decl;
16020 TREE_VEC_ELT (t, 1)
16021 = create_tmp_var (build_array_type_nelts (size_type_node, map_cnt),
16022 ".omp_data_sizes");
16023 DECL_NAMELESS (TREE_VEC_ELT (t, 1)) = 1;
16024 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 1)) = 1;
16025 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 1;
43895be5 16026 tree tkind_type = short_unsigned_type_node;
16027 int talign_shift = 8;
bc7bff74 16028 TREE_VEC_ELT (t, 2)
ca4c3545 16029 = create_tmp_var (build_array_type_nelts (tkind_type, map_cnt),
bc7bff74 16030 ".omp_data_kinds");
16031 DECL_NAMELESS (TREE_VEC_ELT (t, 2)) = 1;
16032 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 2)) = 1;
16033 TREE_STATIC (TREE_VEC_ELT (t, 2)) = 1;
16034 gimple_omp_target_set_data_arg (stmt, t);
16035
16036 vec<constructor_elt, va_gc> *vsize;
16037 vec<constructor_elt, va_gc> *vkind;
16038 vec_alloc (vsize, map_cnt);
16039 vec_alloc (vkind, map_cnt);
16040 unsigned int map_idx = 0;
16041
16042 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
16043 switch (OMP_CLAUSE_CODE (c))
16044 {
43895be5 16045 tree ovar, nc, s, purpose, var, x, type;
16046 unsigned int talign;
bc7bff74 16047
16048 default:
16049 break;
b656be3a 16050
bc7bff74 16051 case OMP_CLAUSE_MAP:
16052 case OMP_CLAUSE_TO:
16053 case OMP_CLAUSE_FROM:
b656be3a 16054 oacc_firstprivate_map:
bc7bff74 16055 nc = c;
16056 ovar = OMP_CLAUSE_DECL (c);
43895be5 16057 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
9561765e 16058 && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
16059 || (OMP_CLAUSE_MAP_KIND (c)
16060 == GOMP_MAP_FIRSTPRIVATE_REFERENCE)))
43895be5 16061 break;
bc7bff74 16062 if (!DECL_P (ovar))
16063 {
16064 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
16065 && OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
16066 {
16067 gcc_checking_assert (OMP_CLAUSE_DECL (OMP_CLAUSE_CHAIN (c))
16068 == get_base_address (ovar));
16069 nc = OMP_CLAUSE_CHAIN (c);
16070 ovar = OMP_CLAUSE_DECL (nc);
16071 }
16072 else
16073 {
16074 tree x = build_sender_ref (ovar, ctx);
16075 tree v
16076 = build_fold_addr_expr_with_type (ovar, ptr_type_node);
16077 gimplify_assign (x, v, &ilist);
16078 nc = NULL_TREE;
16079 }
16080 }
16081 else
16082 {
16083 if (DECL_SIZE (ovar)
16084 && TREE_CODE (DECL_SIZE (ovar)) != INTEGER_CST)
16085 {
16086 tree ovar2 = DECL_VALUE_EXPR (ovar);
16087 gcc_assert (TREE_CODE (ovar2) == INDIRECT_REF);
16088 ovar2 = TREE_OPERAND (ovar2, 0);
16089 gcc_assert (DECL_P (ovar2));
16090 ovar = ovar2;
16091 }
9561765e 16092 if (!maybe_lookup_field (ovar, ctx))
bc7bff74 16093 continue;
16094 }
16095
43895be5 16096 talign = TYPE_ALIGN_UNIT (TREE_TYPE (ovar));
4f3b8d78 16097 if (DECL_P (ovar) && DECL_ALIGN_UNIT (ovar) > talign)
16098 talign = DECL_ALIGN_UNIT (ovar);
bc7bff74 16099 if (nc)
16100 {
43895be5 16101 var = lookup_decl_in_outer_ctx (ovar, ctx);
9561765e 16102 x = build_sender_ref (ovar, ctx);
abe55632 16103
16104 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
b656be3a 16105 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
16106 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
16107 && TREE_CODE (TREE_TYPE (ovar)) == ARRAY_TYPE)
bc7bff74 16108 {
ca4c3545 16109 gcc_assert (offloaded);
bc7bff74 16110 tree avar
f9e245b2 16111 = create_tmp_var (TREE_TYPE (TREE_TYPE (x)));
bc7bff74 16112 mark_addressable (avar);
16113 gimplify_assign (avar, build_fold_addr_expr (var), &ilist);
4f3b8d78 16114 talign = DECL_ALIGN_UNIT (avar);
bc7bff74 16115 avar = build_fold_addr_expr (avar);
16116 gimplify_assign (x, avar, &ilist);
16117 }
b656be3a 16118 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
16119 {
16120 gcc_assert (is_gimple_omp_oacc (ctx->stmt));
16121 if (!is_reference (var))
0aabcddf 16122 {
16123 if (is_gimple_reg (var)
16124 && OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c))
16125 TREE_NO_WARNING (var) = 1;
16126 var = build_fold_addr_expr (var);
16127 }
b656be3a 16128 else
16129 talign = TYPE_ALIGN_UNIT (TREE_TYPE (TREE_TYPE (ovar)));
16130 gimplify_assign (x, var, &ilist);
16131 }
bc7bff74 16132 else if (is_gimple_reg (var))
16133 {
ca4c3545 16134 gcc_assert (offloaded);
f9e245b2 16135 tree avar = create_tmp_var (TREE_TYPE (var));
bc7bff74 16136 mark_addressable (avar);
ca4c3545 16137 enum gomp_map_kind map_kind = OMP_CLAUSE_MAP_KIND (c);
16138 if (GOMP_MAP_COPY_TO_P (map_kind)
16139 || map_kind == GOMP_MAP_POINTER
16140 || map_kind == GOMP_MAP_TO_PSET
16141 || map_kind == GOMP_MAP_FORCE_DEVICEPTR)
585aefbb 16142 {
16143 /* If we need to initialize a temporary
16144 with VAR because it is not addressable, and
16145 the variable hasn't been initialized yet, then
16146 we'll get a warning for the store to avar.
16147 Don't warn in that case, the mapping might
16148 be implicit. */
16149 TREE_NO_WARNING (var) = 1;
16150 gimplify_assign (avar, var, &ilist);
16151 }
bc7bff74 16152 avar = build_fold_addr_expr (avar);
16153 gimplify_assign (x, avar, &ilist);
ca4c3545 16154 if ((GOMP_MAP_COPY_FROM_P (map_kind)
16155 || map_kind == GOMP_MAP_FORCE_DEVICEPTR)
bc7bff74 16156 && !TYPE_READONLY (TREE_TYPE (var)))
16157 {
43895be5 16158 x = unshare_expr (x);
bc7bff74 16159 x = build_simple_mem_ref (x);
16160 gimplify_assign (var, x, &olist);
16161 }
16162 }
16163 else
16164 {
16165 var = build_fold_addr_expr (var);
16166 gimplify_assign (x, var, &ilist);
16167 }
16168 }
b656be3a 16169 s = NULL_TREE;
16170 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
16171 {
16172 gcc_checking_assert (is_gimple_omp_oacc (ctx->stmt));
16173 s = TREE_TYPE (ovar);
16174 if (TREE_CODE (s) == REFERENCE_TYPE)
16175 s = TREE_TYPE (s);
16176 s = TYPE_SIZE_UNIT (s);
16177 }
16178 else
16179 s = OMP_CLAUSE_SIZE (c);
bc7bff74 16180 if (s == NULL_TREE)
16181 s = TYPE_SIZE_UNIT (TREE_TYPE (ovar));
16182 s = fold_convert (size_type_node, s);
43895be5 16183 purpose = size_int (map_idx++);
bc7bff74 16184 CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
16185 if (TREE_CODE (s) != INTEGER_CST)
16186 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 0;
16187
43895be5 16188 unsigned HOST_WIDE_INT tkind, tkind_zero;
bc7bff74 16189 switch (OMP_CLAUSE_CODE (c))
16190 {
16191 case OMP_CLAUSE_MAP:
16192 tkind = OMP_CLAUSE_MAP_KIND (c);
43895be5 16193 tkind_zero = tkind;
16194 if (OMP_CLAUSE_MAP_MAYBE_ZERO_LENGTH_ARRAY_SECTION (c))
16195 switch (tkind)
16196 {
16197 case GOMP_MAP_ALLOC:
16198 case GOMP_MAP_TO:
16199 case GOMP_MAP_FROM:
16200 case GOMP_MAP_TOFROM:
16201 case GOMP_MAP_ALWAYS_TO:
16202 case GOMP_MAP_ALWAYS_FROM:
16203 case GOMP_MAP_ALWAYS_TOFROM:
16204 case GOMP_MAP_RELEASE:
16205 tkind_zero = GOMP_MAP_ZERO_LEN_ARRAY_SECTION;
16206 break;
16207 case GOMP_MAP_DELETE:
16208 tkind_zero = GOMP_MAP_DELETE_ZERO_LEN_ARRAY_SECTION;
16209 default:
16210 break;
16211 }
16212 if (tkind_zero != tkind)
16213 {
16214 if (integer_zerop (s))
16215 tkind = tkind_zero;
16216 else if (integer_nonzerop (s))
16217 tkind_zero = tkind;
16218 }
bc7bff74 16219 break;
b656be3a 16220 case OMP_CLAUSE_FIRSTPRIVATE:
16221 gcc_checking_assert (is_gimple_omp_oacc (ctx->stmt));
16222 tkind = GOMP_MAP_TO;
16223 tkind_zero = tkind;
16224 break;
bc7bff74 16225 case OMP_CLAUSE_TO:
ca4c3545 16226 tkind = GOMP_MAP_TO;
43895be5 16227 tkind_zero = tkind;
bc7bff74 16228 break;
16229 case OMP_CLAUSE_FROM:
ca4c3545 16230 tkind = GOMP_MAP_FROM;
43895be5 16231 tkind_zero = tkind;
bc7bff74 16232 break;
16233 default:
16234 gcc_unreachable ();
16235 }
ca4c3545 16236 gcc_checking_assert (tkind
16237 < (HOST_WIDE_INT_C (1U) << talign_shift));
43895be5 16238 gcc_checking_assert (tkind_zero
16239 < (HOST_WIDE_INT_C (1U) << talign_shift));
bc7bff74 16240 talign = ceil_log2 (talign);
ca4c3545 16241 tkind |= talign << talign_shift;
43895be5 16242 tkind_zero |= talign << talign_shift;
ca4c3545 16243 gcc_checking_assert (tkind
16244 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
43895be5 16245 gcc_checking_assert (tkind_zero
16246 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
16247 if (tkind == tkind_zero)
16248 x = build_int_cstu (tkind_type, tkind);
16249 else
16250 {
16251 TREE_STATIC (TREE_VEC_ELT (t, 2)) = 0;
16252 x = build3 (COND_EXPR, tkind_type,
16253 fold_build2 (EQ_EXPR, boolean_type_node,
16254 unshare_expr (s), size_zero_node),
16255 build_int_cstu (tkind_type, tkind_zero),
16256 build_int_cstu (tkind_type, tkind));
16257 }
16258 CONSTRUCTOR_APPEND_ELT (vkind, purpose, x);
bc7bff74 16259 if (nc && nc != c)
16260 c = nc;
43895be5 16261 break;
16262
16263 case OMP_CLAUSE_FIRSTPRIVATE:
b656be3a 16264 if (is_oacc_parallel (ctx))
16265 goto oacc_firstprivate_map;
43895be5 16266 ovar = OMP_CLAUSE_DECL (c);
16267 if (is_reference (ovar))
16268 talign = TYPE_ALIGN_UNIT (TREE_TYPE (TREE_TYPE (ovar)));
16269 else
16270 talign = DECL_ALIGN_UNIT (ovar);
16271 var = lookup_decl_in_outer_ctx (ovar, ctx);
16272 x = build_sender_ref (ovar, ctx);
16273 tkind = GOMP_MAP_FIRSTPRIVATE;
16274 type = TREE_TYPE (ovar);
16275 if (is_reference (ovar))
16276 type = TREE_TYPE (type);
43895be5 16277 if ((INTEGRAL_TYPE_P (type)
16278 && TYPE_PRECISION (type) <= POINTER_SIZE)
16279 || TREE_CODE (type) == POINTER_TYPE)
43895be5 16280 {
16281 tkind = GOMP_MAP_FIRSTPRIVATE_INT;
16282 tree t = var;
16283 if (is_reference (var))
16284 t = build_simple_mem_ref (var);
585aefbb 16285 else if (OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c))
16286 TREE_NO_WARNING (var) = 1;
43895be5 16287 if (TREE_CODE (type) != POINTER_TYPE)
16288 t = fold_convert (pointer_sized_int_node, t);
16289 t = fold_convert (TREE_TYPE (x), t);
16290 gimplify_assign (x, t, &ilist);
16291 }
16292 else if (is_reference (var))
16293 gimplify_assign (x, var, &ilist);
84217e9d 16294 else if (is_gimple_reg (var))
43895be5 16295 {
16296 tree avar = create_tmp_var (TREE_TYPE (var));
16297 mark_addressable (avar);
585aefbb 16298 if (OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c))
16299 TREE_NO_WARNING (var) = 1;
43895be5 16300 gimplify_assign (avar, var, &ilist);
16301 avar = build_fold_addr_expr (avar);
16302 gimplify_assign (x, avar, &ilist);
16303 }
16304 else
16305 {
16306 var = build_fold_addr_expr (var);
16307 gimplify_assign (x, var, &ilist);
16308 }
16309 if (tkind == GOMP_MAP_FIRSTPRIVATE_INT)
16310 s = size_int (0);
16311 else if (is_reference (var))
16312 s = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (ovar)));
16313 else
16314 s = TYPE_SIZE_UNIT (TREE_TYPE (ovar));
16315 s = fold_convert (size_type_node, s);
16316 purpose = size_int (map_idx++);
16317 CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
16318 if (TREE_CODE (s) != INTEGER_CST)
16319 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 0;
16320
16321 gcc_checking_assert (tkind
16322 < (HOST_WIDE_INT_C (1U) << talign_shift));
16323 talign = ceil_log2 (talign);
16324 tkind |= talign << talign_shift;
16325 gcc_checking_assert (tkind
16326 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
16327 CONSTRUCTOR_APPEND_ELT (vkind, purpose,
16328 build_int_cstu (tkind_type, tkind));
16329 break;
16330
16331 case OMP_CLAUSE_USE_DEVICE_PTR:
16332 case OMP_CLAUSE_IS_DEVICE_PTR:
16333 ovar = OMP_CLAUSE_DECL (c);
16334 var = lookup_decl_in_outer_ctx (ovar, ctx);
16335 x = build_sender_ref (ovar, ctx);
9d5fd7c6 16336 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_USE_DEVICE_PTR)
43895be5 16337 tkind = GOMP_MAP_USE_DEVICE_PTR;
16338 else
16339 tkind = GOMP_MAP_FIRSTPRIVATE_INT;
16340 type = TREE_TYPE (ovar);
16341 if (TREE_CODE (type) == ARRAY_TYPE)
16342 var = build_fold_addr_expr (var);
16343 else
16344 {
16345 if (is_reference (ovar))
16346 {
16347 type = TREE_TYPE (type);
16348 if (TREE_CODE (type) != ARRAY_TYPE)
16349 var = build_simple_mem_ref (var);
16350 var = fold_convert (TREE_TYPE (x), var);
16351 }
16352 }
16353 gimplify_assign (x, var, &ilist);
16354 s = size_int (0);
16355 purpose = size_int (map_idx++);
16356 CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
16357 gcc_checking_assert (tkind
16358 < (HOST_WIDE_INT_C (1U) << talign_shift));
16359 gcc_checking_assert (tkind
16360 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
16361 CONSTRUCTOR_APPEND_ELT (vkind, purpose,
16362 build_int_cstu (tkind_type, tkind));
16363 break;
bc7bff74 16364 }
16365
16366 gcc_assert (map_idx == map_cnt);
16367
16368 DECL_INITIAL (TREE_VEC_ELT (t, 1))
16369 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)), vsize);
16370 DECL_INITIAL (TREE_VEC_ELT (t, 2))
16371 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 2)), vkind);
43895be5 16372 for (int i = 1; i <= 2; i++)
16373 if (!TREE_STATIC (TREE_VEC_ELT (t, i)))
16374 {
16375 gimple_seq initlist = NULL;
16376 force_gimple_operand (build1 (DECL_EXPR, void_type_node,
16377 TREE_VEC_ELT (t, i)),
16378 &initlist, true, NULL_TREE);
16379 gimple_seq_add_seq (&ilist, initlist);
16380
16381 tree clobber = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, i)),
16382 NULL);
16383 TREE_THIS_VOLATILE (clobber) = 1;
16384 gimple_seq_add_stmt (&olist,
16385 gimple_build_assign (TREE_VEC_ELT (t, i),
16386 clobber));
16387 }
bc7bff74 16388
16389 tree clobber = build_constructor (ctx->record_type, NULL);
16390 TREE_THIS_VOLATILE (clobber) = 1;
16391 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
16392 clobber));
16393 }
16394
16395 /* Once all the expansions are done, sequence all the different
16396 fragments inside gimple_omp_body. */
16397
16398 new_body = NULL;
16399
ca4c3545 16400 if (offloaded
16401 && ctx->record_type)
bc7bff74 16402 {
16403 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
16404 /* fixup_child_record_type might have changed receiver_decl's type. */
16405 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
16406 gimple_seq_add_stmt (&new_body,
16407 gimple_build_assign (ctx->receiver_decl, t));
16408 }
b656be3a 16409 gimple_seq_add_seq (&new_body, fplist);
bc7bff74 16410
43895be5 16411 if (offloaded || data_region)
bc7bff74 16412 {
43895be5 16413 tree prev = NULL_TREE;
16414 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
16415 switch (OMP_CLAUSE_CODE (c))
16416 {
16417 tree var, x;
16418 default:
16419 break;
16420 case OMP_CLAUSE_FIRSTPRIVATE:
b656be3a 16421 if (is_gimple_omp_oacc (ctx->stmt))
16422 break;
43895be5 16423 var = OMP_CLAUSE_DECL (c);
16424 if (is_reference (var)
16425 || is_gimple_reg_type (TREE_TYPE (var)))
16426 {
16427 tree new_var = lookup_decl (var, ctx);
16428 tree type;
16429 type = TREE_TYPE (var);
16430 if (is_reference (var))
16431 type = TREE_TYPE (type);
43895be5 16432 if ((INTEGRAL_TYPE_P (type)
16433 && TYPE_PRECISION (type) <= POINTER_SIZE)
16434 || TREE_CODE (type) == POINTER_TYPE)
43895be5 16435 {
16436 x = build_receiver_ref (var, false, ctx);
16437 if (TREE_CODE (type) != POINTER_TYPE)
16438 x = fold_convert (pointer_sized_int_node, x);
16439 x = fold_convert (type, x);
16440 gimplify_expr (&x, &new_body, NULL, is_gimple_val,
16441 fb_rvalue);
16442 if (is_reference (var))
16443 {
16444 tree v = create_tmp_var_raw (type, get_name (var));
16445 gimple_add_tmp_var (v);
16446 TREE_ADDRESSABLE (v) = 1;
16447 gimple_seq_add_stmt (&new_body,
16448 gimple_build_assign (v, x));
16449 x = build_fold_addr_expr (v);
16450 }
16451 gimple_seq_add_stmt (&new_body,
16452 gimple_build_assign (new_var, x));
16453 }
16454 else
16455 {
16456 x = build_receiver_ref (var, !is_reference (var), ctx);
16457 gimplify_expr (&x, &new_body, NULL, is_gimple_val,
16458 fb_rvalue);
16459 gimple_seq_add_stmt (&new_body,
16460 gimple_build_assign (new_var, x));
16461 }
16462 }
16463 else if (is_variable_sized (var))
16464 {
16465 tree pvar = DECL_VALUE_EXPR (var);
16466 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
16467 pvar = TREE_OPERAND (pvar, 0);
16468 gcc_assert (DECL_P (pvar));
16469 tree new_var = lookup_decl (pvar, ctx);
16470 x = build_receiver_ref (var, false, ctx);
16471 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
16472 gimple_seq_add_stmt (&new_body,
16473 gimple_build_assign (new_var, x));
16474 }
16475 break;
16476 case OMP_CLAUSE_PRIVATE:
b656be3a 16477 if (is_gimple_omp_oacc (ctx->stmt))
16478 break;
43895be5 16479 var = OMP_CLAUSE_DECL (c);
16480 if (is_reference (var))
16481 {
16482 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
16483 tree new_var = lookup_decl (var, ctx);
16484 x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
16485 if (TREE_CONSTANT (x))
16486 {
16487 x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)),
16488 get_name (var));
16489 gimple_add_tmp_var (x);
16490 TREE_ADDRESSABLE (x) = 1;
16491 x = build_fold_addr_expr_loc (clause_loc, x);
16492 }
16493 else
00e3f095 16494 break;
43895be5 16495
16496 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
16497 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
16498 gimple_seq_add_stmt (&new_body,
16499 gimple_build_assign (new_var, x));
16500 }
16501 break;
16502 case OMP_CLAUSE_USE_DEVICE_PTR:
16503 case OMP_CLAUSE_IS_DEVICE_PTR:
16504 var = OMP_CLAUSE_DECL (c);
9d5fd7c6 16505 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_USE_DEVICE_PTR)
43895be5 16506 x = build_sender_ref (var, ctx);
16507 else
16508 x = build_receiver_ref (var, false, ctx);
16509 if (is_variable_sized (var))
16510 {
16511 tree pvar = DECL_VALUE_EXPR (var);
16512 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
16513 pvar = TREE_OPERAND (pvar, 0);
16514 gcc_assert (DECL_P (pvar));
16515 tree new_var = lookup_decl (pvar, ctx);
16516 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
16517 gimple_seq_add_stmt (&new_body,
16518 gimple_build_assign (new_var, x));
16519 }
16520 else if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
16521 {
16522 tree new_var = lookup_decl (var, ctx);
16523 new_var = DECL_VALUE_EXPR (new_var);
16524 gcc_assert (TREE_CODE (new_var) == MEM_REF);
16525 new_var = TREE_OPERAND (new_var, 0);
16526 gcc_assert (DECL_P (new_var));
16527 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
16528 gimple_seq_add_stmt (&new_body,
16529 gimple_build_assign (new_var, x));
16530 }
16531 else
16532 {
16533 tree type = TREE_TYPE (var);
16534 tree new_var = lookup_decl (var, ctx);
16535 if (is_reference (var))
16536 {
16537 type = TREE_TYPE (type);
16538 if (TREE_CODE (type) != ARRAY_TYPE)
16539 {
16540 tree v = create_tmp_var_raw (type, get_name (var));
16541 gimple_add_tmp_var (v);
16542 TREE_ADDRESSABLE (v) = 1;
16543 x = fold_convert (type, x);
16544 gimplify_expr (&x, &new_body, NULL, is_gimple_val,
16545 fb_rvalue);
16546 gimple_seq_add_stmt (&new_body,
16547 gimple_build_assign (v, x));
16548 x = build_fold_addr_expr (v);
16549 }
16550 }
b86e24ea 16551 new_var = DECL_VALUE_EXPR (new_var);
43895be5 16552 x = fold_convert (TREE_TYPE (new_var), x);
16553 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
16554 gimple_seq_add_stmt (&new_body,
16555 gimple_build_assign (new_var, x));
16556 }
16557 break;
16558 }
9561765e 16559 /* Handle GOMP_MAP_FIRSTPRIVATE_{POINTER,REFERENCE} in second pass,
43895be5 16560 so that firstprivate vars holding OMP_CLAUSE_SIZE if needed
00e3f095 16561 are already handled. Similarly OMP_CLAUSE_PRIVATE for VLAs
16562 or references to VLAs. */
b656be3a 16563 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
43895be5 16564 switch (OMP_CLAUSE_CODE (c))
16565 {
16566 tree var;
16567 default:
16568 break;
16569 case OMP_CLAUSE_MAP:
9561765e 16570 if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
16571 || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_REFERENCE)
43895be5 16572 {
16573 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
16574 HOST_WIDE_INT offset = 0;
16575 gcc_assert (prev);
16576 var = OMP_CLAUSE_DECL (c);
16577 if (DECL_P (var)
16578 && TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE
16579 && is_global_var (maybe_lookup_decl_in_outer_ctx (var,
16580 ctx))
16581 && varpool_node::get_create (var)->offloadable)
16582 break;
16583 if (TREE_CODE (var) == INDIRECT_REF
16584 && TREE_CODE (TREE_OPERAND (var, 0)) == COMPONENT_REF)
16585 var = TREE_OPERAND (var, 0);
16586 if (TREE_CODE (var) == COMPONENT_REF)
16587 {
16588 var = get_addr_base_and_unit_offset (var, &offset);
16589 gcc_assert (var != NULL_TREE && DECL_P (var));
16590 }
16591 else if (DECL_SIZE (var)
16592 && TREE_CODE (DECL_SIZE (var)) != INTEGER_CST)
16593 {
16594 tree var2 = DECL_VALUE_EXPR (var);
16595 gcc_assert (TREE_CODE (var2) == INDIRECT_REF);
16596 var2 = TREE_OPERAND (var2, 0);
16597 gcc_assert (DECL_P (var2));
16598 var = var2;
16599 }
16600 tree new_var = lookup_decl (var, ctx), x;
16601 tree type = TREE_TYPE (new_var);
16602 bool is_ref;
16603 if (TREE_CODE (OMP_CLAUSE_DECL (c)) == INDIRECT_REF
16604 && (TREE_CODE (TREE_OPERAND (OMP_CLAUSE_DECL (c), 0))
16605 == COMPONENT_REF))
16606 {
16607 type = TREE_TYPE (TREE_OPERAND (OMP_CLAUSE_DECL (c), 0));
16608 is_ref = true;
16609 new_var = build2 (MEM_REF, type,
16610 build_fold_addr_expr (new_var),
16611 build_int_cst (build_pointer_type (type),
16612 offset));
16613 }
16614 else if (TREE_CODE (OMP_CLAUSE_DECL (c)) == COMPONENT_REF)
16615 {
16616 type = TREE_TYPE (OMP_CLAUSE_DECL (c));
16617 is_ref = TREE_CODE (type) == REFERENCE_TYPE;
16618 new_var = build2 (MEM_REF, type,
16619 build_fold_addr_expr (new_var),
16620 build_int_cst (build_pointer_type (type),
16621 offset));
16622 }
16623 else
16624 is_ref = is_reference (var);
9561765e 16625 if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_REFERENCE)
16626 is_ref = false;
43895be5 16627 bool ref_to_array = false;
16628 if (is_ref)
16629 {
16630 type = TREE_TYPE (type);
16631 if (TREE_CODE (type) == ARRAY_TYPE)
16632 {
16633 type = build_pointer_type (type);
16634 ref_to_array = true;
16635 }
16636 }
16637 else if (TREE_CODE (type) == ARRAY_TYPE)
16638 {
16639 tree decl2 = DECL_VALUE_EXPR (new_var);
16640 gcc_assert (TREE_CODE (decl2) == MEM_REF);
16641 decl2 = TREE_OPERAND (decl2, 0);
16642 gcc_assert (DECL_P (decl2));
16643 new_var = decl2;
16644 type = TREE_TYPE (new_var);
16645 }
16646 x = build_receiver_ref (OMP_CLAUSE_DECL (prev), false, ctx);
16647 x = fold_convert_loc (clause_loc, type, x);
16648 if (!integer_zerop (OMP_CLAUSE_SIZE (c)))
16649 {
16650 tree bias = OMP_CLAUSE_SIZE (c);
16651 if (DECL_P (bias))
16652 bias = lookup_decl (bias, ctx);
16653 bias = fold_convert_loc (clause_loc, sizetype, bias);
16654 bias = fold_build1_loc (clause_loc, NEGATE_EXPR, sizetype,
16655 bias);
16656 x = fold_build2_loc (clause_loc, POINTER_PLUS_EXPR,
16657 TREE_TYPE (x), x, bias);
16658 }
16659 if (ref_to_array)
16660 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
16661 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
16662 if (is_ref && !ref_to_array)
16663 {
16664 tree t = create_tmp_var_raw (type, get_name (var));
16665 gimple_add_tmp_var (t);
16666 TREE_ADDRESSABLE (t) = 1;
16667 gimple_seq_add_stmt (&new_body,
16668 gimple_build_assign (t, x));
16669 x = build_fold_addr_expr_loc (clause_loc, t);
16670 }
16671 gimple_seq_add_stmt (&new_body,
16672 gimple_build_assign (new_var, x));
16673 prev = NULL_TREE;
16674 }
16675 else if (OMP_CLAUSE_CHAIN (c)
16676 && OMP_CLAUSE_CODE (OMP_CLAUSE_CHAIN (c))
16677 == OMP_CLAUSE_MAP
9561765e 16678 && (OMP_CLAUSE_MAP_KIND (OMP_CLAUSE_CHAIN (c))
16679 == GOMP_MAP_FIRSTPRIVATE_POINTER
16680 || (OMP_CLAUSE_MAP_KIND (OMP_CLAUSE_CHAIN (c))
16681 == GOMP_MAP_FIRSTPRIVATE_REFERENCE)))
43895be5 16682 prev = c;
16683 break;
16684 case OMP_CLAUSE_PRIVATE:
16685 var = OMP_CLAUSE_DECL (c);
16686 if (is_variable_sized (var))
16687 {
16688 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
16689 tree new_var = lookup_decl (var, ctx);
16690 tree pvar = DECL_VALUE_EXPR (var);
16691 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
16692 pvar = TREE_OPERAND (pvar, 0);
16693 gcc_assert (DECL_P (pvar));
16694 tree new_pvar = lookup_decl (pvar, ctx);
16695 tree atmp = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
16696 tree al = size_int (DECL_ALIGN (var));
16697 tree x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
16698 x = build_call_expr_loc (clause_loc, atmp, 2, x, al);
16699 x = fold_convert_loc (clause_loc, TREE_TYPE (new_pvar), x);
16700 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
16701 gimple_seq_add_stmt (&new_body,
16702 gimple_build_assign (new_pvar, x));
16703 }
00e3f095 16704 else if (is_reference (var) && !is_gimple_omp_oacc (ctx->stmt))
16705 {
16706 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
16707 tree new_var = lookup_decl (var, ctx);
16708 tree x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
16709 if (TREE_CONSTANT (x))
16710 break;
16711 else
16712 {
16713 tree atmp
16714 = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
16715 tree rtype = TREE_TYPE (TREE_TYPE (new_var));
16716 tree al = size_int (TYPE_ALIGN (rtype));
16717 x = build_call_expr_loc (clause_loc, atmp, 2, x, al);
16718 }
16719
16720 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
16721 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
16722 gimple_seq_add_stmt (&new_body,
16723 gimple_build_assign (new_var, x));
16724 }
43895be5 16725 break;
16726 }
2eab8648 16727
641a0fa1 16728 gimple_seq fork_seq = NULL;
16729 gimple_seq join_seq = NULL;
16730
16731 if (is_oacc_parallel (ctx))
16732 {
16733 /* If there are reductions on the offloaded region itself, treat
16734 them as a dummy GANG loop. */
16735 tree level = build_int_cst (integer_type_node, GOMP_DIM_GANG);
16736
16737 lower_oacc_reductions (gimple_location (ctx->stmt), clauses, level,
16738 false, NULL, NULL, &fork_seq, &join_seq, ctx);
16739 }
16740
16741 gimple_seq_add_seq (&new_body, fork_seq);
bc7bff74 16742 gimple_seq_add_seq (&new_body, tgt_body);
641a0fa1 16743 gimple_seq_add_seq (&new_body, join_seq);
2eab8648 16744
43895be5 16745 if (offloaded)
16746 new_body = maybe_catch_exception (new_body);
2eab8648 16747
bc7bff74 16748 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
16749 gimple_omp_set_body (stmt, new_body);
16750 }
16751
16752 bind = gimple_build_bind (NULL, NULL,
16753 tgt_bind ? gimple_bind_block (tgt_bind)
16754 : NULL_TREE);
43895be5 16755 gsi_replace (gsi_p, dep_bind ? dep_bind : bind, true);
e3a19533 16756 gimple_bind_add_seq (bind, ilist);
16757 gimple_bind_add_stmt (bind, stmt);
16758 gimple_bind_add_seq (bind, olist);
773c5ba7 16759
75a70cf9 16760 pop_gimplify_context (NULL);
43895be5 16761
16762 if (dep_bind)
16763 {
16764 gimple_bind_add_seq (dep_bind, dep_ilist);
16765 gimple_bind_add_stmt (dep_bind, bind);
16766 gimple_bind_add_seq (dep_bind, dep_olist);
16767 pop_gimplify_context (dep_bind);
16768 }
773c5ba7 16769}
16770
bc7bff74 16771/* Expand code for an OpenMP teams directive. */
16772
16773static void
16774lower_omp_teams (gimple_stmt_iterator *gsi_p, omp_context *ctx)
16775{
1a91d914 16776 gomp_teams *teams_stmt = as_a <gomp_teams *> (gsi_stmt (*gsi_p));
8a4a28a8 16777 push_gimplify_context ();
bc7bff74 16778
16779 tree block = make_node (BLOCK);
1a91d914 16780 gbind *bind = gimple_build_bind (NULL, NULL, block);
bc7bff74 16781 gsi_replace (gsi_p, bind, true);
16782 gimple_seq bind_body = NULL;
16783 gimple_seq dlist = NULL;
16784 gimple_seq olist = NULL;
16785
16786 tree num_teams = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
16787 OMP_CLAUSE_NUM_TEAMS);
16788 if (num_teams == NULL_TREE)
16789 num_teams = build_int_cst (unsigned_type_node, 0);
16790 else
16791 {
16792 num_teams = OMP_CLAUSE_NUM_TEAMS_EXPR (num_teams);
16793 num_teams = fold_convert (unsigned_type_node, num_teams);
16794 gimplify_expr (&num_teams, &bind_body, NULL, is_gimple_val, fb_rvalue);
16795 }
16796 tree thread_limit = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
16797 OMP_CLAUSE_THREAD_LIMIT);
16798 if (thread_limit == NULL_TREE)
16799 thread_limit = build_int_cst (unsigned_type_node, 0);
16800 else
16801 {
16802 thread_limit = OMP_CLAUSE_THREAD_LIMIT_EXPR (thread_limit);
16803 thread_limit = fold_convert (unsigned_type_node, thread_limit);
16804 gimplify_expr (&thread_limit, &bind_body, NULL, is_gimple_val,
16805 fb_rvalue);
16806 }
16807
16808 lower_rec_input_clauses (gimple_omp_teams_clauses (teams_stmt),
16809 &bind_body, &dlist, ctx, NULL);
16810 lower_omp (gimple_omp_body_ptr (teams_stmt), ctx);
16811 lower_reduction_clauses (gimple_omp_teams_clauses (teams_stmt), &olist, ctx);
56686608 16812 if (!gimple_omp_teams_grid_phony (teams_stmt))
16813 {
16814 gimple_seq_add_stmt (&bind_body, teams_stmt);
16815 location_t loc = gimple_location (teams_stmt);
16816 tree decl = builtin_decl_explicit (BUILT_IN_GOMP_TEAMS);
16817 gimple *call = gimple_build_call (decl, 2, num_teams, thread_limit);
16818 gimple_set_location (call, loc);
16819 gimple_seq_add_stmt (&bind_body, call);
16820 }
bc7bff74 16821
16822 gimple_seq_add_seq (&bind_body, gimple_omp_body (teams_stmt));
16823 gimple_omp_set_body (teams_stmt, NULL);
16824 gimple_seq_add_seq (&bind_body, olist);
16825 gimple_seq_add_seq (&bind_body, dlist);
56686608 16826 if (!gimple_omp_teams_grid_phony (teams_stmt))
16827 gimple_seq_add_stmt (&bind_body, gimple_build_omp_return (true));
bc7bff74 16828 gimple_bind_set_body (bind, bind_body);
16829
16830 pop_gimplify_context (bind);
16831
16832 gimple_bind_append_vars (bind, ctx->block_vars);
16833 BLOCK_VARS (block) = ctx->block_vars;
16834 if (BLOCK_VARS (block))
16835 TREE_USED (block) = 1;
16836}
16837
56686608 16838/* Expand code within an artificial GIMPLE_OMP_GRID_BODY OMP construct. */
16839
16840static void
16841lower_omp_grid_body (gimple_stmt_iterator *gsi_p, omp_context *ctx)
16842{
16843 gimple *stmt = gsi_stmt (*gsi_p);
16844 lower_omp (gimple_omp_body_ptr (stmt), ctx);
16845 gimple_seq_add_stmt (gimple_omp_body_ptr (stmt),
16846 gimple_build_omp_return (false));
16847}
16848
bc7bff74 16849
a4890dc9 16850/* Callback for lower_omp_1. Return non-NULL if *tp needs to be
75a70cf9 16851 regimplified. If DATA is non-NULL, lower_omp_1 is outside
ca4c3545 16852 of OMP context, but with task_shared_vars set. */
46515c92 16853
16854static tree
75a70cf9 16855lower_omp_regimplify_p (tree *tp, int *walk_subtrees,
16856 void *data)
46515c92 16857{
a4890dc9 16858 tree t = *tp;
46515c92 16859
a4890dc9 16860 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
75a70cf9 16861 if (TREE_CODE (t) == VAR_DECL && data == NULL && DECL_HAS_VALUE_EXPR_P (t))
9f49e155 16862 return t;
16863
16864 if (task_shared_vars
16865 && DECL_P (t)
16866 && bitmap_bit_p (task_shared_vars, DECL_UID (t)))
a4890dc9 16867 return t;
46515c92 16868
a4890dc9 16869 /* If a global variable has been privatized, TREE_CONSTANT on
16870 ADDR_EXPR might be wrong. */
75a70cf9 16871 if (data == NULL && TREE_CODE (t) == ADDR_EXPR)
a4890dc9 16872 recompute_tree_invariant_for_addr_expr (t);
46515c92 16873
43895be5 16874 *walk_subtrees = !IS_TYPE_OR_DECL_P (t);
16875 return NULL_TREE;
16876}
16877
16878/* Data to be communicated between lower_omp_regimplify_operands and
16879 lower_omp_regimplify_operands_p. */
16880
16881struct lower_omp_regimplify_operands_data
16882{
16883 omp_context *ctx;
16884 vec<tree> *decls;
16885};
16886
16887/* Helper function for lower_omp_regimplify_operands. Find
16888 omp_member_access_dummy_var vars and adjust temporarily their
16889 DECL_VALUE_EXPRs if needed. */
16890
16891static tree
16892lower_omp_regimplify_operands_p (tree *tp, int *walk_subtrees,
16893 void *data)
16894{
16895 tree t = omp_member_access_dummy_var (*tp);
16896 if (t)
16897 {
16898 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
16899 lower_omp_regimplify_operands_data *ldata
16900 = (lower_omp_regimplify_operands_data *) wi->info;
16901 tree o = maybe_lookup_decl (t, ldata->ctx);
16902 if (o != t)
16903 {
16904 ldata->decls->safe_push (DECL_VALUE_EXPR (*tp));
16905 ldata->decls->safe_push (*tp);
16906 tree v = unshare_and_remap (DECL_VALUE_EXPR (*tp), t, o);
16907 SET_DECL_VALUE_EXPR (*tp, v);
16908 }
16909 }
16910 *walk_subtrees = !IS_TYPE_OR_DECL_P (*tp);
a4890dc9 16911 return NULL_TREE;
46515c92 16912}
773c5ba7 16913
43895be5 16914/* Wrapper around gimple_regimplify_operands that adjusts DECL_VALUE_EXPRs
16915 of omp_member_access_dummy_var vars during regimplification. */
16916
16917static void
16918lower_omp_regimplify_operands (omp_context *ctx, gimple *stmt,
16919 gimple_stmt_iterator *gsi_p)
16920{
16921 auto_vec<tree, 10> decls;
16922 if (ctx)
16923 {
16924 struct walk_stmt_info wi;
16925 memset (&wi, '\0', sizeof (wi));
16926 struct lower_omp_regimplify_operands_data data;
16927 data.ctx = ctx;
16928 data.decls = &decls;
16929 wi.info = &data;
16930 walk_gimple_op (stmt, lower_omp_regimplify_operands_p, &wi);
16931 }
16932 gimple_regimplify_operands (stmt, gsi_p);
16933 while (!decls.is_empty ())
16934 {
16935 tree t = decls.pop ();
16936 tree v = decls.pop ();
16937 SET_DECL_VALUE_EXPR (t, v);
16938 }
16939}
16940
a4890dc9 16941static void
75a70cf9 16942lower_omp_1 (gimple_stmt_iterator *gsi_p, omp_context *ctx)
1e8e9920 16943{
42acab1c 16944 gimple *stmt = gsi_stmt (*gsi_p);
75a70cf9 16945 struct walk_stmt_info wi;
1a91d914 16946 gcall *call_stmt;
1e8e9920 16947
75a70cf9 16948 if (gimple_has_location (stmt))
16949 input_location = gimple_location (stmt);
a4890dc9 16950
75a70cf9 16951 if (task_shared_vars)
16952 memset (&wi, '\0', sizeof (wi));
a4890dc9 16953
773c5ba7 16954 /* If we have issued syntax errors, avoid doing any heavy lifting.
ca4c3545 16955 Just replace the OMP directives with a NOP to avoid
773c5ba7 16956 confusing RTL expansion. */
852f689e 16957 if (seen_error () && is_gimple_omp (stmt))
773c5ba7 16958 {
75a70cf9 16959 gsi_replace (gsi_p, gimple_build_nop (), true);
a4890dc9 16960 return;
773c5ba7 16961 }
16962
75a70cf9 16963 switch (gimple_code (stmt))
1e8e9920 16964 {
75a70cf9 16965 case GIMPLE_COND:
1a91d914 16966 {
16967 gcond *cond_stmt = as_a <gcond *> (stmt);
16968 if ((ctx || task_shared_vars)
16969 && (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
16970 lower_omp_regimplify_p,
16971 ctx ? NULL : &wi, NULL)
16972 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
16973 lower_omp_regimplify_p,
16974 ctx ? NULL : &wi, NULL)))
43895be5 16975 lower_omp_regimplify_operands (ctx, cond_stmt, gsi_p);
1a91d914 16976 }
a4890dc9 16977 break;
75a70cf9 16978 case GIMPLE_CATCH:
1a91d914 16979 lower_omp (gimple_catch_handler_ptr (as_a <gcatch *> (stmt)), ctx);
a4890dc9 16980 break;
75a70cf9 16981 case GIMPLE_EH_FILTER:
e3a19533 16982 lower_omp (gimple_eh_filter_failure_ptr (stmt), ctx);
a4890dc9 16983 break;
75a70cf9 16984 case GIMPLE_TRY:
e3a19533 16985 lower_omp (gimple_try_eval_ptr (stmt), ctx);
16986 lower_omp (gimple_try_cleanup_ptr (stmt), ctx);
a4890dc9 16987 break;
35215227 16988 case GIMPLE_TRANSACTION:
1a91d914 16989 lower_omp (gimple_transaction_body_ptr (
16990 as_a <gtransaction *> (stmt)),
16991 ctx);
35215227 16992 break;
75a70cf9 16993 case GIMPLE_BIND:
1a91d914 16994 lower_omp (gimple_bind_body_ptr (as_a <gbind *> (stmt)), ctx);
a4890dc9 16995 break;
75a70cf9 16996 case GIMPLE_OMP_PARALLEL:
16997 case GIMPLE_OMP_TASK:
16998 ctx = maybe_lookup_ctx (stmt);
bc7bff74 16999 gcc_assert (ctx);
17000 if (ctx->cancellable)
17001 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
75a70cf9 17002 lower_omp_taskreg (gsi_p, ctx);
a4890dc9 17003 break;
75a70cf9 17004 case GIMPLE_OMP_FOR:
17005 ctx = maybe_lookup_ctx (stmt);
1e8e9920 17006 gcc_assert (ctx);
bc7bff74 17007 if (ctx->cancellable)
17008 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
75a70cf9 17009 lower_omp_for (gsi_p, ctx);
1e8e9920 17010 break;
75a70cf9 17011 case GIMPLE_OMP_SECTIONS:
17012 ctx = maybe_lookup_ctx (stmt);
1e8e9920 17013 gcc_assert (ctx);
bc7bff74 17014 if (ctx->cancellable)
17015 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
75a70cf9 17016 lower_omp_sections (gsi_p, ctx);
1e8e9920 17017 break;
75a70cf9 17018 case GIMPLE_OMP_SINGLE:
17019 ctx = maybe_lookup_ctx (stmt);
1e8e9920 17020 gcc_assert (ctx);
75a70cf9 17021 lower_omp_single (gsi_p, ctx);
1e8e9920 17022 break;
75a70cf9 17023 case GIMPLE_OMP_MASTER:
17024 ctx = maybe_lookup_ctx (stmt);
1e8e9920 17025 gcc_assert (ctx);
75a70cf9 17026 lower_omp_master (gsi_p, ctx);
1e8e9920 17027 break;
bc7bff74 17028 case GIMPLE_OMP_TASKGROUP:
17029 ctx = maybe_lookup_ctx (stmt);
17030 gcc_assert (ctx);
17031 lower_omp_taskgroup (gsi_p, ctx);
17032 break;
75a70cf9 17033 case GIMPLE_OMP_ORDERED:
17034 ctx = maybe_lookup_ctx (stmt);
1e8e9920 17035 gcc_assert (ctx);
75a70cf9 17036 lower_omp_ordered (gsi_p, ctx);
1e8e9920 17037 break;
75a70cf9 17038 case GIMPLE_OMP_CRITICAL:
17039 ctx = maybe_lookup_ctx (stmt);
1e8e9920 17040 gcc_assert (ctx);
75a70cf9 17041 lower_omp_critical (gsi_p, ctx);
17042 break;
17043 case GIMPLE_OMP_ATOMIC_LOAD:
17044 if ((ctx || task_shared_vars)
1a91d914 17045 && walk_tree (gimple_omp_atomic_load_rhs_ptr (
17046 as_a <gomp_atomic_load *> (stmt)),
75a70cf9 17047 lower_omp_regimplify_p, ctx ? NULL : &wi, NULL))
43895be5 17048 lower_omp_regimplify_operands (ctx, stmt, gsi_p);
1e8e9920 17049 break;
bc7bff74 17050 case GIMPLE_OMP_TARGET:
17051 ctx = maybe_lookup_ctx (stmt);
17052 gcc_assert (ctx);
17053 lower_omp_target (gsi_p, ctx);
17054 break;
17055 case GIMPLE_OMP_TEAMS:
17056 ctx = maybe_lookup_ctx (stmt);
17057 gcc_assert (ctx);
17058 lower_omp_teams (gsi_p, ctx);
17059 break;
56686608 17060 case GIMPLE_OMP_GRID_BODY:
17061 ctx = maybe_lookup_ctx (stmt);
17062 gcc_assert (ctx);
17063 lower_omp_grid_body (gsi_p, ctx);
17064 break;
bc7bff74 17065 case GIMPLE_CALL:
17066 tree fndecl;
1a91d914 17067 call_stmt = as_a <gcall *> (stmt);
17068 fndecl = gimple_call_fndecl (call_stmt);
bc7bff74 17069 if (fndecl
17070 && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
17071 switch (DECL_FUNCTION_CODE (fndecl))
17072 {
17073 case BUILT_IN_GOMP_BARRIER:
17074 if (ctx == NULL)
17075 break;
17076 /* FALLTHRU */
17077 case BUILT_IN_GOMP_CANCEL:
17078 case BUILT_IN_GOMP_CANCELLATION_POINT:
17079 omp_context *cctx;
17080 cctx = ctx;
17081 if (gimple_code (cctx->stmt) == GIMPLE_OMP_SECTION)
17082 cctx = cctx->outer;
1a91d914 17083 gcc_assert (gimple_call_lhs (call_stmt) == NULL_TREE);
bc7bff74 17084 if (!cctx->cancellable)
17085 {
17086 if (DECL_FUNCTION_CODE (fndecl)
17087 == BUILT_IN_GOMP_CANCELLATION_POINT)
17088 {
17089 stmt = gimple_build_nop ();
17090 gsi_replace (gsi_p, stmt, false);
17091 }
17092 break;
17093 }
bc7bff74 17094 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_GOMP_BARRIER)
17095 {
17096 fndecl = builtin_decl_explicit (BUILT_IN_GOMP_BARRIER_CANCEL);
1a91d914 17097 gimple_call_set_fndecl (call_stmt, fndecl);
17098 gimple_call_set_fntype (call_stmt, TREE_TYPE (fndecl));
bc7bff74 17099 }
15b28553 17100 tree lhs;
f9e245b2 17101 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (fndecl)));
1a91d914 17102 gimple_call_set_lhs (call_stmt, lhs);
bc7bff74 17103 tree fallthru_label;
17104 fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
42acab1c 17105 gimple *g;
bc7bff74 17106 g = gimple_build_label (fallthru_label);
17107 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
15b28553 17108 g = gimple_build_cond (NE_EXPR, lhs,
17109 fold_convert (TREE_TYPE (lhs),
17110 boolean_false_node),
bc7bff74 17111 cctx->cancel_label, fallthru_label);
17112 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
17113 break;
17114 default:
17115 break;
17116 }
17117 /* FALLTHRU */
a4890dc9 17118 default:
fd6481cf 17119 if ((ctx || task_shared_vars)
75a70cf9 17120 && walk_gimple_op (stmt, lower_omp_regimplify_p,
17121 ctx ? NULL : &wi))
ef8cfd4d 17122 {
17123 /* Just remove clobbers, this should happen only if we have
17124 "privatized" local addressable variables in SIMD regions,
17125 the clobber isn't needed in that case and gimplifying address
17126 of the ARRAY_REF into a pointer and creating MEM_REF based
17127 clobber would create worse code than we get with the clobber
17128 dropped. */
17129 if (gimple_clobber_p (stmt))
17130 {
17131 gsi_replace (gsi_p, gimple_build_nop (), true);
17132 break;
17133 }
43895be5 17134 lower_omp_regimplify_operands (ctx, stmt, gsi_p);
ef8cfd4d 17135 }
1e8e9920 17136 break;
1e8e9920 17137 }
1e8e9920 17138}
17139
17140static void
e3a19533 17141lower_omp (gimple_seq *body, omp_context *ctx)
1e8e9920 17142{
1d22f541 17143 location_t saved_location = input_location;
e3a19533 17144 gimple_stmt_iterator gsi;
17145 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
75a70cf9 17146 lower_omp_1 (&gsi, ctx);
ca4c3545 17147 /* During gimplification, we haven't folded statments inside offloading
c3a81971 17148 or taskreg regions (gimplify.c:maybe_fold_stmt); do that now. */
17149 if (target_nesting_level || taskreg_nesting_level)
bc7bff74 17150 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
17151 fold_stmt (&gsi);
1d22f541 17152 input_location = saved_location;
1e8e9920 17153}
56686608 17154
17155/* Returen true if STMT is an assignment of a register-type into a local
17156 VAR_DECL. */
17157
17158static bool
17159grid_reg_assignment_to_local_var_p (gimple *stmt)
17160{
17161 gassign *assign = dyn_cast <gassign *> (stmt);
17162 if (!assign)
17163 return false;
17164 tree lhs = gimple_assign_lhs (assign);
17165 if (TREE_CODE (lhs) != VAR_DECL
17166 || !is_gimple_reg_type (TREE_TYPE (lhs))
17167 || is_global_var (lhs))
17168 return false;
17169 return true;
17170}
17171
17172/* Return true if all statements in SEQ are assignments to local register-type
17173 variables. */
17174
17175static bool
17176grid_seq_only_contains_local_assignments (gimple_seq seq)
17177{
17178 if (!seq)
17179 return true;
17180
17181 gimple_stmt_iterator gsi;
17182 for (gsi = gsi_start (seq); !gsi_end_p (gsi); gsi_next (&gsi))
17183 if (!grid_reg_assignment_to_local_var_p (gsi_stmt (gsi)))
17184 return false;
17185 return true;
17186}
17187
17188/* Scan statements in SEQ and call itself recursively on any bind. If during
17189 whole search only assignments to register-type local variables and one
17190 single OMP statement is encountered, return true, otherwise return false.
17191 RET is where we store any OMP statement encountered. TARGET_LOC and NAME
17192 are used for dumping a note about a failure. */
17193
17194static bool
17195grid_find_single_omp_among_assignments_1 (gimple_seq seq, location_t target_loc,
17196 const char *name, gimple **ret)
17197{
17198 gimple_stmt_iterator gsi;
17199 for (gsi = gsi_start (seq); !gsi_end_p (gsi); gsi_next (&gsi))
17200 {
17201 gimple *stmt = gsi_stmt (gsi);
17202
17203 if (grid_reg_assignment_to_local_var_p (stmt))
17204 continue;
17205 if (gbind *bind = dyn_cast <gbind *> (stmt))
17206 {
17207 if (!grid_find_single_omp_among_assignments_1 (gimple_bind_body (bind),
17208 target_loc, name, ret))
17209 return false;
17210 }
17211 else if (is_gimple_omp (stmt))
17212 {
17213 if (*ret)
17214 {
17215 if (dump_enabled_p ())
17216 dump_printf_loc (MSG_NOTE, target_loc,
17217 "Will not turn target construct into a simple "
17218 "GPGPU kernel because %s construct contains "
17219 "multiple OpenMP constructs\n", name);
17220 return false;
17221 }
17222 *ret = stmt;
17223 }
17224 else
17225 {
17226 if (dump_enabled_p ())
17227 dump_printf_loc (MSG_NOTE, target_loc,
17228 "Will not turn target construct into a simple "
17229 "GPGPU kernel because %s construct contains "
17230 "a complex statement\n", name);
17231 return false;
17232 }
17233 }
17234 return true;
17235}
17236
17237/* Scan statements in SEQ and make sure that it and any binds in it contain
17238 only assignments to local register-type variables and one OMP construct. If
17239 so, return that construct, otherwise return NULL. If dumping is enabled and
17240 function fails, use TARGET_LOC and NAME to dump a note with the reason for
17241 failure. */
17242
17243static gimple *
17244grid_find_single_omp_among_assignments (gimple_seq seq, location_t target_loc,
17245 const char *name)
17246{
17247 if (!seq)
17248 {
17249 if (dump_enabled_p ())
17250 dump_printf_loc (MSG_NOTE, target_loc,
17251 "Will not turn target construct into a simple "
17252 "GPGPU kernel because %s construct has empty "
17253 "body\n",
17254 name);
17255 return NULL;
17256 }
17257
17258 gimple *ret = NULL;
17259 if (grid_find_single_omp_among_assignments_1 (seq, target_loc, name, &ret))
17260 {
17261 if (!ret && dump_enabled_p ())
17262 dump_printf_loc (MSG_NOTE, target_loc,
17263 "Will not turn target construct into a simple "
17264 "GPGPU kernel because %s construct does not contain"
17265 "any other OpenMP construct\n", name);
17266 return ret;
17267 }
17268 else
17269 return NULL;
17270}
17271
17272/* Walker function looking for statements there is no point gridifying (and for
17273 noreturn function calls which we cannot do). Return non-NULL if such a
17274 function is found. */
17275
17276static tree
17277grid_find_ungridifiable_statement (gimple_stmt_iterator *gsi,
17278 bool *handled_ops_p,
ece566e7 17279 struct walk_stmt_info *wi)
56686608 17280{
17281 *handled_ops_p = false;
17282 gimple *stmt = gsi_stmt (*gsi);
17283 switch (gimple_code (stmt))
17284 {
17285 case GIMPLE_CALL:
17286 if (gimple_call_noreturn_p (as_a <gcall *> (stmt)))
17287 {
17288 *handled_ops_p = true;
ece566e7 17289 wi->info = stmt;
56686608 17290 return error_mark_node;
17291 }
17292 break;
17293
17294 /* We may reduce the following list if we find a way to implement the
17295 clauses, but now there is no point trying further. */
17296 case GIMPLE_OMP_CRITICAL:
17297 case GIMPLE_OMP_TASKGROUP:
17298 case GIMPLE_OMP_TASK:
17299 case GIMPLE_OMP_SECTION:
17300 case GIMPLE_OMP_SECTIONS:
17301 case GIMPLE_OMP_SECTIONS_SWITCH:
17302 case GIMPLE_OMP_TARGET:
17303 case GIMPLE_OMP_ORDERED:
17304 *handled_ops_p = true;
ece566e7 17305 wi->info = stmt;
56686608 17306 return error_mark_node;
17307
ece566e7 17308 case GIMPLE_OMP_FOR:
17309 if ((gimple_omp_for_kind (stmt) & GF_OMP_FOR_SIMD)
17310 && gimple_omp_for_combined_into_p (stmt))
17311 {
17312 *handled_ops_p = true;
17313 wi->info = stmt;
17314 return error_mark_node;
17315 }
17316 break;
17317
56686608 17318 default:
17319 break;
17320 }
17321 return NULL;
17322}
17323
17324
17325/* If TARGET follows a pattern that can be turned into a gridified GPGPU
17326 kernel, return true, otherwise return false. In the case of success, also
17327 fill in GROUP_SIZE_P with the requested group size or NULL if there is
17328 none. */
17329
17330static bool
17331grid_target_follows_gridifiable_pattern (gomp_target *target, tree *group_size_p)
17332{
17333 if (gimple_omp_target_kind (target) != GF_OMP_TARGET_KIND_REGION)
17334 return false;
17335
17336 location_t tloc = gimple_location (target);
17337 gimple *stmt
17338 = grid_find_single_omp_among_assignments (gimple_omp_body (target),
17339 tloc, "target");
17340 if (!stmt)
17341 return false;
17342 gomp_teams *teams = dyn_cast <gomp_teams *> (stmt);
17343 tree group_size = NULL;
17344 if (!teams)
17345 {
17346 dump_printf_loc (MSG_NOTE, tloc,
17347 "Will not turn target construct into a simple "
17348 "GPGPU kernel because it does not have a sole teams "
17349 "construct in it.\n");
17350 return false;
17351 }
17352
17353 tree clauses = gimple_omp_teams_clauses (teams);
17354 while (clauses)
17355 {
17356 switch (OMP_CLAUSE_CODE (clauses))
17357 {
17358 case OMP_CLAUSE_NUM_TEAMS:
17359 if (dump_enabled_p ())
17360 dump_printf_loc (MSG_NOTE, tloc,
17361 "Will not turn target construct into a "
17362 "gridified GPGPU kernel because we cannot "
17363 "handle num_teams clause of teams "
17364 "construct\n ");
17365 return false;
17366
17367 case OMP_CLAUSE_REDUCTION:
17368 if (dump_enabled_p ())
17369 dump_printf_loc (MSG_NOTE, tloc,
17370 "Will not turn target construct into a "
17371 "gridified GPGPU kernel because a reduction "
17372 "clause is present\n ");
17373 return false;
17374
17375 case OMP_CLAUSE_LASTPRIVATE:
17376 if (dump_enabled_p ())
17377 dump_printf_loc (MSG_NOTE, tloc,
17378 "Will not turn target construct into a "
17379 "gridified GPGPU kernel because a lastprivate "
17380 "clause is present\n ");
17381 return false;
17382
17383 case OMP_CLAUSE_THREAD_LIMIT:
17384 group_size = OMP_CLAUSE_OPERAND (clauses, 0);
17385 break;
17386
17387 default:
17388 break;
17389 }
17390 clauses = OMP_CLAUSE_CHAIN (clauses);
17391 }
17392
17393 stmt = grid_find_single_omp_among_assignments (gimple_omp_body (teams), tloc,
17394 "teams");
17395 if (!stmt)
17396 return false;
17397 gomp_for *dist = dyn_cast <gomp_for *> (stmt);
17398 if (!dist)
17399 {
17400 dump_printf_loc (MSG_NOTE, tloc,
17401 "Will not turn target construct into a simple "
17402 "GPGPU kernel because the teams construct does not have "
17403 "a sole distribute construct in it.\n");
17404 return false;
17405 }
17406
17407 gcc_assert (gimple_omp_for_kind (dist) == GF_OMP_FOR_KIND_DISTRIBUTE);
17408 if (!gimple_omp_for_combined_p (dist))
17409 {
17410 if (dump_enabled_p ())
17411 dump_printf_loc (MSG_NOTE, tloc,
17412 "Will not turn target construct into a gridified GPGPU "
17413 "kernel because we cannot handle a standalone "
17414 "distribute construct\n ");
17415 return false;
17416 }
17417 if (dist->collapse > 1)
17418 {
17419 if (dump_enabled_p ())
17420 dump_printf_loc (MSG_NOTE, tloc,
17421 "Will not turn target construct into a gridified GPGPU "
17422 "kernel because the distribute construct contains "
17423 "collapse clause\n");
17424 return false;
17425 }
17426 struct omp_for_data fd;
17427 extract_omp_for_data (dist, &fd, NULL);
17428 if (fd.chunk_size)
17429 {
17430 if (group_size && !operand_equal_p (group_size, fd.chunk_size, 0))
17431 {
17432 if (dump_enabled_p ())
17433 dump_printf_loc (MSG_NOTE, tloc,
17434 "Will not turn target construct into a "
17435 "gridified GPGPU kernel because the teams "
17436 "thread limit is different from distribute "
17437 "schedule chunk\n");
17438 return false;
17439 }
17440 group_size = fd.chunk_size;
17441 }
17442 stmt = grid_find_single_omp_among_assignments (gimple_omp_body (dist), tloc,
17443 "distribute");
17444 gomp_parallel *par;
17445 if (!stmt || !(par = dyn_cast <gomp_parallel *> (stmt)))
17446 return false;
17447
17448 clauses = gimple_omp_parallel_clauses (par);
17449 while (clauses)
17450 {
17451 switch (OMP_CLAUSE_CODE (clauses))
17452 {
17453 case OMP_CLAUSE_NUM_THREADS:
17454 if (dump_enabled_p ())
17455 dump_printf_loc (MSG_NOTE, tloc,
17456 "Will not turn target construct into a gridified"
17457 "GPGPU kernel because there is a num_threads "
17458 "clause of the parallel construct\n");
17459 return false;
17460
17461 case OMP_CLAUSE_REDUCTION:
17462 if (dump_enabled_p ())
17463 dump_printf_loc (MSG_NOTE, tloc,
17464 "Will not turn target construct into a "
17465 "gridified GPGPU kernel because a reduction "
17466 "clause is present\n ");
17467 return false;
17468
17469 case OMP_CLAUSE_LASTPRIVATE:
17470 if (dump_enabled_p ())
17471 dump_printf_loc (MSG_NOTE, tloc,
17472 "Will not turn target construct into a "
17473 "gridified GPGPU kernel because a lastprivate "
17474 "clause is present\n ");
17475 return false;
17476
17477 default:
17478 break;
17479 }
17480 clauses = OMP_CLAUSE_CHAIN (clauses);
17481 }
17482
17483 stmt = grid_find_single_omp_among_assignments (gimple_omp_body (par), tloc,
17484 "parallel");
17485 gomp_for *gfor;
17486 if (!stmt || !(gfor = dyn_cast <gomp_for *> (stmt)))
17487 return false;
17488
17489 if (gimple_omp_for_kind (gfor) != GF_OMP_FOR_KIND_FOR)
17490 {
17491 if (dump_enabled_p ())
17492 dump_printf_loc (MSG_NOTE, tloc,
17493 "Will not turn target construct into a gridified GPGPU "
17494 "kernel because the inner loop is not a simple for "
17495 "loop\n");
17496 return false;
17497 }
17498 if (gfor->collapse > 1)
17499 {
17500 if (dump_enabled_p ())
17501 dump_printf_loc (MSG_NOTE, tloc,
17502 "Will not turn target construct into a gridified GPGPU "
17503 "kernel because the inner loop contains collapse "
17504 "clause\n");
17505 return false;
17506 }
17507
17508 if (!grid_seq_only_contains_local_assignments (gimple_omp_for_pre_body (gfor)))
17509 {
17510 if (dump_enabled_p ())
17511 dump_printf_loc (MSG_NOTE, tloc,
17512 "Will not turn target construct into a gridified GPGPU "
17513 "kernel because the inner loop pre_body contains"
17514 "a complex instruction\n");
17515 return false;
17516 }
17517
17518 clauses = gimple_omp_for_clauses (gfor);
17519 while (clauses)
17520 {
17521 switch (OMP_CLAUSE_CODE (clauses))
17522 {
17523 case OMP_CLAUSE_SCHEDULE:
17524 if (OMP_CLAUSE_SCHEDULE_KIND (clauses) != OMP_CLAUSE_SCHEDULE_AUTO)
17525 {
17526 if (dump_enabled_p ())
17527 dump_printf_loc (MSG_NOTE, tloc,
17528 "Will not turn target construct into a "
17529 "gridified GPGPU kernel because the inner "
17530 "loop has a non-automatic scheduling clause\n");
17531 return false;
17532 }
17533 break;
17534
17535 case OMP_CLAUSE_REDUCTION:
17536 if (dump_enabled_p ())
17537 dump_printf_loc (MSG_NOTE, tloc,
17538 "Will not turn target construct into a "
17539 "gridified GPGPU kernel because a reduction "
17540 "clause is present\n ");
17541 return false;
17542
17543 case OMP_CLAUSE_LASTPRIVATE:
17544 if (dump_enabled_p ())
17545 dump_printf_loc (MSG_NOTE, tloc,
17546 "Will not turn target construct into a "
17547 "gridified GPGPU kernel because a lastprivate "
17548 "clause is present\n ");
17549 return false;
17550
17551 default:
17552 break;
17553 }
17554 clauses = OMP_CLAUSE_CHAIN (clauses);
17555 }
17556
17557 struct walk_stmt_info wi;
17558 memset (&wi, 0, sizeof (wi));
ece566e7 17559 if (walk_gimple_seq (gimple_omp_body (gfor),
17560 grid_find_ungridifiable_statement,
17561 NULL, &wi))
56686608 17562 {
ece566e7 17563 gimple *bad = (gimple *) wi.info;
56686608 17564 if (dump_enabled_p ())
17565 {
17566 if (is_gimple_call (bad))
17567 dump_printf_loc (MSG_NOTE, tloc,
17568 "Will not turn target construct into a gridified "
17569 " GPGPU kernel because the inner loop contains "
17570 "call to a noreturn function\n");
ece566e7 17571 if (gimple_code (bad) == GIMPLE_OMP_FOR)
17572 dump_printf_loc (MSG_NOTE, tloc,
17573 "Will not turn target construct into a gridified "
17574 " GPGPU kernel because the inner loop contains "
17575 "a simd construct\n");
56686608 17576 else
17577 dump_printf_loc (MSG_NOTE, tloc,
17578 "Will not turn target construct into a gridified "
17579 "GPGPU kernel because the inner loop contains "
17580 "statement %s which cannot be transformed\n",
17581 gimple_code_name[(int) gimple_code (bad)]);
17582 }
17583 return false;
17584 }
17585
17586 *group_size_p = group_size;
17587 return true;
17588}
17589
17590/* Operand walker, used to remap pre-body declarations according to a hash map
17591 provided in DATA. */
17592
17593static tree
17594grid_remap_prebody_decls (tree *tp, int *walk_subtrees, void *data)
17595{
17596 tree t = *tp;
17597
17598 if (DECL_P (t) || TYPE_P (t))
17599 *walk_subtrees = 0;
17600 else
17601 *walk_subtrees = 1;
17602
17603 if (TREE_CODE (t) == VAR_DECL)
17604 {
17605 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
17606 hash_map<tree, tree> *declmap = (hash_map<tree, tree> *) wi->info;
17607 tree *repl = declmap->get (t);
17608 if (repl)
17609 *tp = *repl;
17610 }
17611 return NULL_TREE;
17612}
17613
17614/* Copy leading register-type assignments to local variables in SRC to just
17615 before DST, Creating temporaries, adjusting mapping of operands in WI and
17616 remapping operands as necessary. Add any new temporaries to TGT_BIND.
17617 Return the first statement that does not conform to
17618 grid_reg_assignment_to_local_var_p or NULL. */
17619
17620static gimple *
17621grid_copy_leading_local_assignments (gimple_seq src, gimple_stmt_iterator *dst,
17622 gbind *tgt_bind, struct walk_stmt_info *wi)
17623{
17624 hash_map<tree, tree> *declmap = (hash_map<tree, tree> *) wi->info;
17625 gimple_stmt_iterator gsi;
17626 for (gsi = gsi_start (src); !gsi_end_p (gsi); gsi_next (&gsi))
17627 {
17628 gimple *stmt = gsi_stmt (gsi);
17629 if (gbind *bind = dyn_cast <gbind *> (stmt))
17630 {
17631 gimple *r = grid_copy_leading_local_assignments
17632 (gimple_bind_body (bind), dst, tgt_bind, wi);
17633 if (r)
17634 return r;
17635 else
17636 continue;
17637 }
17638 if (!grid_reg_assignment_to_local_var_p (stmt))
17639 return stmt;
17640 tree lhs = gimple_assign_lhs (as_a <gassign *> (stmt));
17641 tree repl = copy_var_decl (lhs, create_tmp_var_name (NULL),
17642 TREE_TYPE (lhs));
17643 DECL_CONTEXT (repl) = current_function_decl;
17644 gimple_bind_append_vars (tgt_bind, repl);
17645
17646 declmap->put (lhs, repl);
17647 gassign *copy = as_a <gassign *> (gimple_copy (stmt));
17648 walk_gimple_op (copy, grid_remap_prebody_decls, wi);
17649 gsi_insert_before (dst, copy, GSI_SAME_STMT);
17650 }
17651 return NULL;
17652}
17653
17654/* Given freshly copied top level kernel SEQ, identify the individual OMP
17655 components, mark them as part of kernel and return the inner loop, and copy
17656 assignment leading to them just before DST, remapping them using WI and
17657 adding new temporaries to TGT_BIND. */
17658
17659static gomp_for *
17660grid_process_kernel_body_copy (gimple_seq seq, gimple_stmt_iterator *dst,
17661 gbind *tgt_bind, struct walk_stmt_info *wi)
17662{
17663 gimple *stmt = grid_copy_leading_local_assignments (seq, dst, tgt_bind, wi);
17664 gomp_teams *teams = dyn_cast <gomp_teams *> (stmt);
17665 gcc_assert (teams);
17666 gimple_omp_teams_set_grid_phony (teams, true);
17667 stmt = grid_copy_leading_local_assignments (gimple_omp_body (teams), dst,
17668 tgt_bind, wi);
17669 gcc_checking_assert (stmt);
17670 gomp_for *dist = dyn_cast <gomp_for *> (stmt);
17671 gcc_assert (dist);
17672 gimple_seq prebody = gimple_omp_for_pre_body (dist);
17673 if (prebody)
17674 grid_copy_leading_local_assignments (prebody, dst, tgt_bind, wi);
17675 gimple_omp_for_set_grid_phony (dist, true);
17676 stmt = grid_copy_leading_local_assignments (gimple_omp_body (dist), dst,
17677 tgt_bind, wi);
17678 gcc_checking_assert (stmt);
17679
17680 gomp_parallel *parallel = as_a <gomp_parallel *> (stmt);
17681 gimple_omp_parallel_set_grid_phony (parallel, true);
17682 stmt = grid_copy_leading_local_assignments (gimple_omp_body (parallel), dst,
17683 tgt_bind, wi);
17684 gomp_for *inner_loop = as_a <gomp_for *> (stmt);
17685 gimple_omp_for_set_kind (inner_loop, GF_OMP_FOR_KIND_GRID_LOOP);
17686 prebody = gimple_omp_for_pre_body (inner_loop);
17687 if (prebody)
17688 grid_copy_leading_local_assignments (prebody, dst, tgt_bind, wi);
17689
17690 return inner_loop;
17691}
17692
17693/* If TARGET points to a GOMP_TARGET which follows a gridifiable pattern,
17694 create a GPU kernel for it. GSI must point to the same statement, TGT_BIND
17695 is the bind into which temporaries inserted before TARGET should be
17696 added. */
17697
17698static void
17699grid_attempt_target_gridification (gomp_target *target,
17700 gimple_stmt_iterator *gsi,
17701 gbind *tgt_bind)
17702{
17703 tree group_size;
17704 if (!target || !grid_target_follows_gridifiable_pattern (target, &group_size))
17705 return;
17706
17707 location_t loc = gimple_location (target);
17708 if (dump_enabled_p ())
17709 dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, loc,
17710 "Target construct will be turned into a gridified GPGPU "
17711 "kernel\n");
17712
17713 /* Copy target body to a GPUKERNEL construct: */
17714 gimple_seq kernel_seq = copy_gimple_seq_and_replace_locals
17715 (gimple_omp_body (target));
17716
17717 hash_map<tree, tree> *declmap = new hash_map<tree, tree>;
17718 struct walk_stmt_info wi;
17719 memset (&wi, 0, sizeof (struct walk_stmt_info));
17720 wi.info = declmap;
17721
17722 /* Copy assignments in between OMP statements before target, mark OMP
17723 statements within copy appropriatly. */
17724 gomp_for *inner_loop = grid_process_kernel_body_copy (kernel_seq, gsi,
17725 tgt_bind, &wi);
17726
17727 gbind *old_bind = as_a <gbind *> (gimple_seq_first (gimple_omp_body (target)));
17728 gbind *new_bind = as_a <gbind *> (gimple_seq_first (kernel_seq));
17729 tree new_block = gimple_bind_block (new_bind);
17730 tree enc_block = BLOCK_SUPERCONTEXT (gimple_bind_block (old_bind));
17731 BLOCK_CHAIN (new_block) = BLOCK_SUBBLOCKS (enc_block);
17732 BLOCK_SUBBLOCKS (enc_block) = new_block;
17733 BLOCK_SUPERCONTEXT (new_block) = enc_block;
17734 gimple *gpukernel = gimple_build_omp_grid_body (kernel_seq);
17735 gimple_seq_add_stmt
17736 (gimple_bind_body_ptr (as_a <gbind *> (gimple_omp_body (target))),
17737 gpukernel);
17738
17739 walk_tree (&group_size, grid_remap_prebody_decls, &wi, NULL);
17740 push_gimplify_context ();
17741 size_t collapse = gimple_omp_for_collapse (inner_loop);
17742 for (size_t i = 0; i < collapse; i++)
17743 {
17744 tree itype, type = TREE_TYPE (gimple_omp_for_index (inner_loop, i));
17745 if (POINTER_TYPE_P (type))
17746 itype = signed_type_for (type);
17747 else
17748 itype = type;
17749
17750 enum tree_code cond_code = gimple_omp_for_cond (inner_loop, i);
17751 tree n1 = unshare_expr (gimple_omp_for_initial (inner_loop, i));
17752 walk_tree (&n1, grid_remap_prebody_decls, &wi, NULL);
17753 tree n2 = unshare_expr (gimple_omp_for_final (inner_loop, i));
17754 walk_tree (&n2, grid_remap_prebody_decls, &wi, NULL);
17755 adjust_for_condition (loc, &cond_code, &n2);
17756 tree step;
17757 step = get_omp_for_step_from_incr (loc,
17758 gimple_omp_for_incr (inner_loop, i));
17759 gimple_seq tmpseq = NULL;
17760 n1 = fold_convert (itype, n1);
17761 n2 = fold_convert (itype, n2);
17762 tree t = build_int_cst (itype, (cond_code == LT_EXPR ? -1 : 1));
17763 t = fold_build2 (PLUS_EXPR, itype, step, t);
17764 t = fold_build2 (PLUS_EXPR, itype, t, n2);
17765 t = fold_build2 (MINUS_EXPR, itype, t, n1);
17766 if (TYPE_UNSIGNED (itype) && cond_code == GT_EXPR)
17767 t = fold_build2 (TRUNC_DIV_EXPR, itype,
17768 fold_build1 (NEGATE_EXPR, itype, t),
17769 fold_build1 (NEGATE_EXPR, itype, step));
17770 else
17771 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
17772 tree gs = fold_convert (uint32_type_node, t);
17773 gimplify_expr (&gs, &tmpseq, NULL, is_gimple_val, fb_rvalue);
17774 if (!gimple_seq_empty_p (tmpseq))
17775 gsi_insert_seq_before (gsi, tmpseq, GSI_SAME_STMT);
17776
17777 tree ws;
17778 if (i == 0 && group_size)
17779 {
17780 ws = fold_convert (uint32_type_node, group_size);
17781 tmpseq = NULL;
17782 gimplify_expr (&ws, &tmpseq, NULL, is_gimple_val, fb_rvalue);
17783 if (!gimple_seq_empty_p (tmpseq))
17784 gsi_insert_seq_before (gsi, tmpseq, GSI_SAME_STMT);
17785 }
17786 else
17787 ws = build_zero_cst (uint32_type_node);
17788
17789 tree c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__GRIDDIM_);
17790 OMP_CLAUSE__GRIDDIM__DIMENSION (c) = i;
17791 OMP_CLAUSE__GRIDDIM__SIZE (c) = gs;
17792 OMP_CLAUSE__GRIDDIM__GROUP (c) = ws;
17793 OMP_CLAUSE_CHAIN (c) = gimple_omp_target_clauses (target);
17794 gimple_omp_target_set_clauses (target, c);
17795 }
17796 pop_gimplify_context (tgt_bind);
17797 delete declmap;
17798 return;
17799}
17800
17801/* Walker function doing all the work for create_target_kernels. */
17802
17803static tree
17804grid_gridify_all_targets_stmt (gimple_stmt_iterator *gsi,
17805 bool *handled_ops_p,
17806 struct walk_stmt_info *incoming)
17807{
17808 *handled_ops_p = false;
17809
17810 gimple *stmt = gsi_stmt (*gsi);
17811 gomp_target *target = dyn_cast <gomp_target *> (stmt);
17812 if (target)
17813 {
17814 gbind *tgt_bind = (gbind *) incoming->info;
17815 gcc_checking_assert (tgt_bind);
17816 grid_attempt_target_gridification (target, gsi, tgt_bind);
17817 return NULL_TREE;
17818 }
17819 gbind *bind = dyn_cast <gbind *> (stmt);
17820 if (bind)
17821 {
17822 *handled_ops_p = true;
17823 struct walk_stmt_info wi;
17824 memset (&wi, 0, sizeof (wi));
17825 wi.info = bind;
17826 walk_gimple_seq_mod (gimple_bind_body_ptr (bind),
17827 grid_gridify_all_targets_stmt, NULL, &wi);
17828 }
17829 return NULL_TREE;
17830}
17831
17832/* Attempt to gridify all target constructs in BODY_P. All such targets will
17833 have their bodies duplicated, with the new copy being put into a
17834 gimple_omp_grid_body statement. All kernel-related construct within the
17835 grid_body will be marked with phony flags or kernel kinds. Moreover, some
17836 re-structuring is often needed, such as copying pre-bodies before the target
17837 construct so that kernel grid sizes can be computed. */
17838
17839static void
17840grid_gridify_all_targets (gimple_seq *body_p)
17841{
17842 struct walk_stmt_info wi;
17843 memset (&wi, 0, sizeof (wi));
17844 walk_gimple_seq_mod (body_p, grid_gridify_all_targets_stmt, NULL, &wi);
17845}
1e8e9920 17846\f
56686608 17847
1e8e9920 17848/* Main entry point. */
17849
2a1990e9 17850static unsigned int
1e8e9920 17851execute_lower_omp (void)
17852{
75a70cf9 17853 gimple_seq body;
37eaded9 17854 int i;
17855 omp_context *ctx;
75a70cf9 17856
41709826 17857 /* This pass always runs, to provide PROP_gimple_lomp.
ca4c3545 17858 But often, there is nothing to do. */
17859 if (flag_cilkplus == 0 && flag_openacc == 0 && flag_openmp == 0
17860 && flag_openmp_simd == 0)
41709826 17861 return 0;
17862
1e8e9920 17863 all_contexts = splay_tree_new (splay_tree_compare_pointers, 0,
17864 delete_omp_context);
17865
75a70cf9 17866 body = gimple_body (current_function_decl);
56686608 17867
17868 if (hsa_gen_requested_p ())
17869 grid_gridify_all_targets (&body);
17870
ab129075 17871 scan_omp (&body, NULL);
fd6481cf 17872 gcc_assert (taskreg_nesting_level == 0);
37eaded9 17873 FOR_EACH_VEC_ELT (taskreg_contexts, i, ctx)
17874 finish_taskreg_scan (ctx);
17875 taskreg_contexts.release ();
1e8e9920 17876
17877 if (all_contexts->root)
fd6481cf 17878 {
17879 if (task_shared_vars)
8a4a28a8 17880 push_gimplify_context ();
e3a19533 17881 lower_omp (&body, NULL);
fd6481cf 17882 if (task_shared_vars)
17883 pop_gimplify_context (NULL);
17884 }
1e8e9920 17885
773c5ba7 17886 if (all_contexts)
17887 {
17888 splay_tree_delete (all_contexts);
17889 all_contexts = NULL;
17890 }
fd6481cf 17891 BITMAP_FREE (task_shared_vars);
2a1990e9 17892 return 0;
1e8e9920 17893}
17894
7620bc82 17895namespace {
17896
17897const pass_data pass_data_lower_omp =
cbe8bda8 17898{
17899 GIMPLE_PASS, /* type */
17900 "omplower", /* name */
17901 OPTGROUP_NONE, /* optinfo_flags */
cbe8bda8 17902 TV_NONE, /* tv_id */
17903 PROP_gimple_any, /* properties_required */
17904 PROP_gimple_lomp, /* properties_provided */
17905 0, /* properties_destroyed */
17906 0, /* todo_flags_start */
17907 0, /* todo_flags_finish */
1e8e9920 17908};
cbe8bda8 17909
7620bc82 17910class pass_lower_omp : public gimple_opt_pass
cbe8bda8 17911{
17912public:
9af5ce0c 17913 pass_lower_omp (gcc::context *ctxt)
17914 : gimple_opt_pass (pass_data_lower_omp, ctxt)
cbe8bda8 17915 {}
17916
17917 /* opt_pass methods: */
65b0537f 17918 virtual unsigned int execute (function *) { return execute_lower_omp (); }
cbe8bda8 17919
17920}; // class pass_lower_omp
17921
7620bc82 17922} // anon namespace
17923
cbe8bda8 17924gimple_opt_pass *
17925make_pass_lower_omp (gcc::context *ctxt)
17926{
17927 return new pass_lower_omp (ctxt);
17928}
1e8e9920 17929\f
ca4c3545 17930/* The following is a utility to diagnose structured block violations.
61e47ac8 17931 It is not part of the "omplower" pass, as that's invoked too late. It
17932 should be invoked by the respective front ends after gimplification. */
1e8e9920 17933
17934static splay_tree all_labels;
17935
17936/* Check for mismatched contexts and generate an error if needed. Return
17937 true if an error is detected. */
17938
17939static bool
75a70cf9 17940diagnose_sb_0 (gimple_stmt_iterator *gsi_p,
42acab1c 17941 gimple *branch_ctx, gimple *label_ctx)
1e8e9920 17942{
ca4c3545 17943 gcc_checking_assert (!branch_ctx || is_gimple_omp (branch_ctx));
17944 gcc_checking_assert (!label_ctx || is_gimple_omp (label_ctx));
17945
75a70cf9 17946 if (label_ctx == branch_ctx)
1e8e9920 17947 return false;
17948
ca4c3545 17949 const char* kind = NULL;
17950
17951 if (flag_cilkplus)
17952 {
17953 if ((branch_ctx
17954 && gimple_code (branch_ctx) == GIMPLE_OMP_FOR
17955 && gimple_omp_for_kind (branch_ctx) == GF_OMP_FOR_KIND_CILKSIMD)
17956 || (label_ctx
17957 && gimple_code (label_ctx) == GIMPLE_OMP_FOR
17958 && gimple_omp_for_kind (label_ctx) == GF_OMP_FOR_KIND_CILKSIMD))
17959 kind = "Cilk Plus";
17960 }
17961 if (flag_openacc)
17962 {
17963 if ((branch_ctx && is_gimple_omp_oacc (branch_ctx))
17964 || (label_ctx && is_gimple_omp_oacc (label_ctx)))
17965 {
17966 gcc_checking_assert (kind == NULL);
17967 kind = "OpenACC";
17968 }
17969 }
17970 if (kind == NULL)
17971 {
17972 gcc_checking_assert (flag_openmp);
17973 kind = "OpenMP";
17974 }
48e1416a 17975
75a70cf9 17976 /*
17977 Previously we kept track of the label's entire context in diagnose_sb_[12]
17978 so we could traverse it and issue a correct "exit" or "enter" error
17979 message upon a structured block violation.
17980
17981 We built the context by building a list with tree_cons'ing, but there is
17982 no easy counterpart in gimple tuples. It seems like far too much work
17983 for issuing exit/enter error messages. If someone really misses the
17984 distinct error message... patches welcome.
17985 */
48e1416a 17986
75a70cf9 17987#if 0
1e8e9920 17988 /* Try to avoid confusing the user by producing and error message
f0b5f617 17989 with correct "exit" or "enter" verbiage. We prefer "exit"
1e8e9920 17990 unless we can show that LABEL_CTX is nested within BRANCH_CTX. */
17991 if (branch_ctx == NULL)
17992 exit_p = false;
17993 else
17994 {
17995 while (label_ctx)
17996 {
17997 if (TREE_VALUE (label_ctx) == branch_ctx)
17998 {
17999 exit_p = false;
18000 break;
18001 }
18002 label_ctx = TREE_CHAIN (label_ctx);
18003 }
18004 }
18005
18006 if (exit_p)
ca4c3545 18007 error ("invalid exit from %s structured block", kind);
1e8e9920 18008 else
ca4c3545 18009 error ("invalid entry to %s structured block", kind);
75a70cf9 18010#endif
1e8e9920 18011
75a70cf9 18012 /* If it's obvious we have an invalid entry, be specific about the error. */
18013 if (branch_ctx == NULL)
ca4c3545 18014 error ("invalid entry to %s structured block", kind);
75a70cf9 18015 else
f2697631 18016 {
18017 /* Otherwise, be vague and lazy, but efficient. */
ca4c3545 18018 error ("invalid branch to/from %s structured block", kind);
f2697631 18019 }
75a70cf9 18020
18021 gsi_replace (gsi_p, gimple_build_nop (), false);
1e8e9920 18022 return true;
18023}
18024
ca4c3545 18025/* Pass 1: Create a minimal tree of structured blocks, and record
75a70cf9 18026 where each label is found. */
1e8e9920 18027
18028static tree
75a70cf9 18029diagnose_sb_1 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
18030 struct walk_stmt_info *wi)
1e8e9920 18031{
42acab1c 18032 gimple *context = (gimple *) wi->info;
18033 gimple *inner_context;
18034 gimple *stmt = gsi_stmt (*gsi_p);
1e8e9920 18035
75a70cf9 18036 *handled_ops_p = true;
18037
ca4c3545 18038 switch (gimple_code (stmt))
1e8e9920 18039 {
75a70cf9 18040 WALK_SUBSTMTS;
48e1416a 18041
75a70cf9 18042 case GIMPLE_OMP_PARALLEL:
18043 case GIMPLE_OMP_TASK:
18044 case GIMPLE_OMP_SECTIONS:
18045 case GIMPLE_OMP_SINGLE:
18046 case GIMPLE_OMP_SECTION:
18047 case GIMPLE_OMP_MASTER:
18048 case GIMPLE_OMP_ORDERED:
18049 case GIMPLE_OMP_CRITICAL:
bc7bff74 18050 case GIMPLE_OMP_TARGET:
18051 case GIMPLE_OMP_TEAMS:
18052 case GIMPLE_OMP_TASKGROUP:
75a70cf9 18053 /* The minimal context here is just the current OMP construct. */
18054 inner_context = stmt;
1e8e9920 18055 wi->info = inner_context;
75a70cf9 18056 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
1e8e9920 18057 wi->info = context;
18058 break;
18059
75a70cf9 18060 case GIMPLE_OMP_FOR:
18061 inner_context = stmt;
1e8e9920 18062 wi->info = inner_context;
75a70cf9 18063 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
18064 walk them. */
18065 walk_gimple_seq (gimple_omp_for_pre_body (stmt),
18066 diagnose_sb_1, NULL, wi);
18067 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
1e8e9920 18068 wi->info = context;
18069 break;
18070
75a70cf9 18071 case GIMPLE_LABEL:
1a91d914 18072 splay_tree_insert (all_labels,
18073 (splay_tree_key) gimple_label_label (
18074 as_a <glabel *> (stmt)),
1e8e9920 18075 (splay_tree_value) context);
18076 break;
18077
18078 default:
18079 break;
18080 }
18081
18082 return NULL_TREE;
18083}
18084
18085/* Pass 2: Check each branch and see if its context differs from that of
18086 the destination label's context. */
18087
18088static tree
75a70cf9 18089diagnose_sb_2 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
18090 struct walk_stmt_info *wi)
1e8e9920 18091{
42acab1c 18092 gimple *context = (gimple *) wi->info;
1e8e9920 18093 splay_tree_node n;
42acab1c 18094 gimple *stmt = gsi_stmt (*gsi_p);
1e8e9920 18095
75a70cf9 18096 *handled_ops_p = true;
18097
18098 switch (gimple_code (stmt))
1e8e9920 18099 {
75a70cf9 18100 WALK_SUBSTMTS;
18101
18102 case GIMPLE_OMP_PARALLEL:
18103 case GIMPLE_OMP_TASK:
18104 case GIMPLE_OMP_SECTIONS:
18105 case GIMPLE_OMP_SINGLE:
18106 case GIMPLE_OMP_SECTION:
18107 case GIMPLE_OMP_MASTER:
18108 case GIMPLE_OMP_ORDERED:
18109 case GIMPLE_OMP_CRITICAL:
bc7bff74 18110 case GIMPLE_OMP_TARGET:
18111 case GIMPLE_OMP_TEAMS:
18112 case GIMPLE_OMP_TASKGROUP:
75a70cf9 18113 wi->info = stmt;
e3a19533 18114 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
1e8e9920 18115 wi->info = context;
18116 break;
18117
75a70cf9 18118 case GIMPLE_OMP_FOR:
18119 wi->info = stmt;
18120 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
18121 walk them. */
e3a19533 18122 walk_gimple_seq_mod (gimple_omp_for_pre_body_ptr (stmt),
18123 diagnose_sb_2, NULL, wi);
18124 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
1e8e9920 18125 wi->info = context;
18126 break;
18127
0e1818e7 18128 case GIMPLE_COND:
18129 {
1a91d914 18130 gcond *cond_stmt = as_a <gcond *> (stmt);
18131 tree lab = gimple_cond_true_label (cond_stmt);
0e1818e7 18132 if (lab)
18133 {
18134 n = splay_tree_lookup (all_labels,
18135 (splay_tree_key) lab);
18136 diagnose_sb_0 (gsi_p, context,
42acab1c 18137 n ? (gimple *) n->value : NULL);
0e1818e7 18138 }
1a91d914 18139 lab = gimple_cond_false_label (cond_stmt);
0e1818e7 18140 if (lab)
18141 {
18142 n = splay_tree_lookup (all_labels,
18143 (splay_tree_key) lab);
18144 diagnose_sb_0 (gsi_p, context,
42acab1c 18145 n ? (gimple *) n->value : NULL);
0e1818e7 18146 }
18147 }
18148 break;
18149
75a70cf9 18150 case GIMPLE_GOTO:
1e8e9920 18151 {
75a70cf9 18152 tree lab = gimple_goto_dest (stmt);
1e8e9920 18153 if (TREE_CODE (lab) != LABEL_DECL)
18154 break;
18155
18156 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
42acab1c 18157 diagnose_sb_0 (gsi_p, context, n ? (gimple *) n->value : NULL);
1e8e9920 18158 }
18159 break;
18160
75a70cf9 18161 case GIMPLE_SWITCH:
1e8e9920 18162 {
1a91d914 18163 gswitch *switch_stmt = as_a <gswitch *> (stmt);
75a70cf9 18164 unsigned int i;
1a91d914 18165 for (i = 0; i < gimple_switch_num_labels (switch_stmt); ++i)
1e8e9920 18166 {
1a91d914 18167 tree lab = CASE_LABEL (gimple_switch_label (switch_stmt, i));
1e8e9920 18168 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
42acab1c 18169 if (n && diagnose_sb_0 (gsi_p, context, (gimple *) n->value))
1e8e9920 18170 break;
18171 }
18172 }
18173 break;
18174
75a70cf9 18175 case GIMPLE_RETURN:
18176 diagnose_sb_0 (gsi_p, context, NULL);
1e8e9920 18177 break;
18178
18179 default:
18180 break;
18181 }
18182
18183 return NULL_TREE;
18184}
18185
ca4c3545 18186/* Called from tree-cfg.c::make_edges to create cfg edges for all relevant
18187 GIMPLE_* codes. */
7740abd8 18188bool
b2c0e0b7 18189make_gimple_omp_edges (basic_block bb, struct omp_region **region,
18190 int *region_idx)
7740abd8 18191{
42acab1c 18192 gimple *last = last_stmt (bb);
7740abd8 18193 enum gimple_code code = gimple_code (last);
18194 struct omp_region *cur_region = *region;
18195 bool fallthru = false;
18196
18197 switch (code)
18198 {
18199 case GIMPLE_OMP_PARALLEL:
18200 case GIMPLE_OMP_TASK:
18201 case GIMPLE_OMP_FOR:
18202 case GIMPLE_OMP_SINGLE:
18203 case GIMPLE_OMP_TEAMS:
18204 case GIMPLE_OMP_MASTER:
18205 case GIMPLE_OMP_TASKGROUP:
7740abd8 18206 case GIMPLE_OMP_CRITICAL:
18207 case GIMPLE_OMP_SECTION:
56686608 18208 case GIMPLE_OMP_GRID_BODY:
7740abd8 18209 cur_region = new_omp_region (bb, code, cur_region);
18210 fallthru = true;
18211 break;
18212
43895be5 18213 case GIMPLE_OMP_ORDERED:
18214 cur_region = new_omp_region (bb, code, cur_region);
18215 fallthru = true;
18216 if (find_omp_clause (gimple_omp_ordered_clauses
18217 (as_a <gomp_ordered *> (last)),
18218 OMP_CLAUSE_DEPEND))
18219 cur_region = cur_region->outer;
18220 break;
18221
7740abd8 18222 case GIMPLE_OMP_TARGET:
18223 cur_region = new_omp_region (bb, code, cur_region);
18224 fallthru = true;
ca4c3545 18225 switch (gimple_omp_target_kind (last))
18226 {
18227 case GF_OMP_TARGET_KIND_REGION:
18228 case GF_OMP_TARGET_KIND_DATA:
18229 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
18230 case GF_OMP_TARGET_KIND_OACC_KERNELS:
18231 case GF_OMP_TARGET_KIND_OACC_DATA:
571b3486 18232 case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
ca4c3545 18233 break;
18234 case GF_OMP_TARGET_KIND_UPDATE:
43895be5 18235 case GF_OMP_TARGET_KIND_ENTER_DATA:
18236 case GF_OMP_TARGET_KIND_EXIT_DATA:
ca4c3545 18237 case GF_OMP_TARGET_KIND_OACC_UPDATE:
18238 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
2fc5e987 18239 case GF_OMP_TARGET_KIND_OACC_DECLARE:
ca4c3545 18240 cur_region = cur_region->outer;
18241 break;
18242 default:
18243 gcc_unreachable ();
18244 }
7740abd8 18245 break;
18246
18247 case GIMPLE_OMP_SECTIONS:
18248 cur_region = new_omp_region (bb, code, cur_region);
18249 fallthru = true;
18250 break;
18251
18252 case GIMPLE_OMP_SECTIONS_SWITCH:
18253 fallthru = false;
18254 break;
18255
18256 case GIMPLE_OMP_ATOMIC_LOAD:
18257 case GIMPLE_OMP_ATOMIC_STORE:
18258 fallthru = true;
18259 break;
18260
18261 case GIMPLE_OMP_RETURN:
18262 /* In the case of a GIMPLE_OMP_SECTION, the edge will go
18263 somewhere other than the next block. This will be
18264 created later. */
18265 cur_region->exit = bb;
b25f70fd 18266 if (cur_region->type == GIMPLE_OMP_TASK)
18267 /* Add an edge corresponding to not scheduling the task
18268 immediately. */
18269 make_edge (cur_region->entry, bb, EDGE_ABNORMAL);
7740abd8 18270 fallthru = cur_region->type != GIMPLE_OMP_SECTION;
18271 cur_region = cur_region->outer;
18272 break;
18273
18274 case GIMPLE_OMP_CONTINUE:
18275 cur_region->cont = bb;
18276 switch (cur_region->type)
18277 {
18278 case GIMPLE_OMP_FOR:
18279 /* Mark all GIMPLE_OMP_FOR and GIMPLE_OMP_CONTINUE
18280 succs edges as abnormal to prevent splitting
18281 them. */
18282 single_succ_edge (cur_region->entry)->flags |= EDGE_ABNORMAL;
18283 /* Make the loopback edge. */
18284 make_edge (bb, single_succ (cur_region->entry),
18285 EDGE_ABNORMAL);
18286
18287 /* Create an edge from GIMPLE_OMP_FOR to exit, which
18288 corresponds to the case that the body of the loop
18289 is not executed at all. */
18290 make_edge (cur_region->entry, bb->next_bb, EDGE_ABNORMAL);
18291 make_edge (bb, bb->next_bb, EDGE_FALLTHRU | EDGE_ABNORMAL);
18292 fallthru = false;
18293 break;
18294
18295 case GIMPLE_OMP_SECTIONS:
18296 /* Wire up the edges into and out of the nested sections. */
18297 {
18298 basic_block switch_bb = single_succ (cur_region->entry);
18299
18300 struct omp_region *i;
18301 for (i = cur_region->inner; i ; i = i->next)
18302 {
18303 gcc_assert (i->type == GIMPLE_OMP_SECTION);
18304 make_edge (switch_bb, i->entry, 0);
18305 make_edge (i->exit, bb, EDGE_FALLTHRU);
18306 }
18307
18308 /* Make the loopback edge to the block with
18309 GIMPLE_OMP_SECTIONS_SWITCH. */
18310 make_edge (bb, switch_bb, 0);
18311
18312 /* Make the edge from the switch to exit. */
18313 make_edge (switch_bb, bb->next_bb, 0);
18314 fallthru = false;
18315 }
18316 break;
18317
b25f70fd 18318 case GIMPLE_OMP_TASK:
18319 fallthru = true;
18320 break;
18321
7740abd8 18322 default:
18323 gcc_unreachable ();
18324 }
18325 break;
18326
18327 default:
18328 gcc_unreachable ();
18329 }
18330
18331 if (*region != cur_region)
b2c0e0b7 18332 {
18333 *region = cur_region;
18334 if (cur_region)
18335 *region_idx = cur_region->entry->index;
18336 else
18337 *region_idx = 0;
18338 }
7740abd8 18339
18340 return fallthru;
18341}
18342
bfec3452 18343static unsigned int
18344diagnose_omp_structured_block_errors (void)
1e8e9920 18345{
1e8e9920 18346 struct walk_stmt_info wi;
bfec3452 18347 gimple_seq body = gimple_body (current_function_decl);
1e8e9920 18348
18349 all_labels = splay_tree_new (splay_tree_compare_pointers, 0, 0);
18350
18351 memset (&wi, 0, sizeof (wi));
75a70cf9 18352 walk_gimple_seq (body, diagnose_sb_1, NULL, &wi);
1e8e9920 18353
18354 memset (&wi, 0, sizeof (wi));
1e8e9920 18355 wi.want_locations = true;
e3a19533 18356 walk_gimple_seq_mod (&body, diagnose_sb_2, NULL, &wi);
18357
18358 gimple_set_body (current_function_decl, body);
1e8e9920 18359
18360 splay_tree_delete (all_labels);
18361 all_labels = NULL;
18362
bfec3452 18363 return 0;
1e8e9920 18364}
18365
7620bc82 18366namespace {
18367
18368const pass_data pass_data_diagnose_omp_blocks =
cbe8bda8 18369{
18370 GIMPLE_PASS, /* type */
18371 "*diagnose_omp_blocks", /* name */
18372 OPTGROUP_NONE, /* optinfo_flags */
cbe8bda8 18373 TV_NONE, /* tv_id */
18374 PROP_gimple_any, /* properties_required */
18375 0, /* properties_provided */
18376 0, /* properties_destroyed */
18377 0, /* todo_flags_start */
18378 0, /* todo_flags_finish */
bfec3452 18379};
18380
7620bc82 18381class pass_diagnose_omp_blocks : public gimple_opt_pass
cbe8bda8 18382{
18383public:
9af5ce0c 18384 pass_diagnose_omp_blocks (gcc::context *ctxt)
18385 : gimple_opt_pass (pass_data_diagnose_omp_blocks, ctxt)
cbe8bda8 18386 {}
18387
18388 /* opt_pass methods: */
ca4c3545 18389 virtual bool gate (function *)
18390 {
18391 return flag_cilkplus || flag_openacc || flag_openmp;
18392 }
65b0537f 18393 virtual unsigned int execute (function *)
18394 {
18395 return diagnose_omp_structured_block_errors ();
18396 }
cbe8bda8 18397
18398}; // class pass_diagnose_omp_blocks
18399
7620bc82 18400} // anon namespace
18401
cbe8bda8 18402gimple_opt_pass *
18403make_pass_diagnose_omp_blocks (gcc::context *ctxt)
18404{
18405 return new pass_diagnose_omp_blocks (ctxt);
18406}
d09768a4 18407\f
dccabdd1 18408/* Helper function for omp_finish_file routine. Takes decls from V_DECLS and
18409 adds their addresses and sizes to constructor-vector V_CTOR. */
18410static void
18411add_decls_addresses_to_decl_constructor (vec<tree, va_gc> *v_decls,
18412 vec<constructor_elt, va_gc> *v_ctor)
18413{
18414 unsigned len = vec_safe_length (v_decls);
18415 for (unsigned i = 0; i < len; i++)
18416 {
18417 tree it = (*v_decls)[i];
c0998828 18418 bool is_var = TREE_CODE (it) == VAR_DECL;
18419 bool is_link_var
18420 = is_var
18421#ifdef ACCEL_COMPILER
18422 && DECL_HAS_VALUE_EXPR_P (it)
18423#endif
18424 && lookup_attribute ("omp declare target link", DECL_ATTRIBUTES (it));
dccabdd1 18425
c0998828 18426 tree size = NULL_TREE;
18427 if (is_var)
18428 size = fold_convert (const_ptr_type_node, DECL_SIZE_UNIT (it));
18429
18430 tree addr;
18431 if (!is_link_var)
18432 addr = build_fold_addr_expr (it);
18433 else
18434 {
18435#ifdef ACCEL_COMPILER
18436 /* For "omp declare target link" vars add address of the pointer to
18437 the target table, instead of address of the var. */
18438 tree value_expr = DECL_VALUE_EXPR (it);
18439 tree link_ptr_decl = TREE_OPERAND (value_expr, 0);
18440 varpool_node::finalize_decl (link_ptr_decl);
18441 addr = build_fold_addr_expr (link_ptr_decl);
18442#else
18443 addr = build_fold_addr_expr (it);
18444#endif
18445
18446 /* Most significant bit of the size marks "omp declare target link"
18447 vars in host and target tables. */
18448 unsigned HOST_WIDE_INT isize = tree_to_uhwi (size);
18449 isize |= 1ULL << (int_size_in_bytes (const_ptr_type_node)
18450 * BITS_PER_UNIT - 1);
18451 size = wide_int_to_tree (const_ptr_type_node, isize);
18452 }
18453
18454 CONSTRUCTOR_APPEND_ELT (v_ctor, NULL_TREE, addr);
18455 if (is_var)
18456 CONSTRUCTOR_APPEND_ELT (v_ctor, NULL_TREE, size);
dccabdd1 18457 }
18458}
18459
18460/* Create new symbols containing (address, size) pairs for global variables,
18461 marked with "omp declare target" attribute, as well as addresses for the
ca4c3545 18462 functions, which are outlined offloading regions. */
dccabdd1 18463void
18464omp_finish_file (void)
18465{
18466 unsigned num_funcs = vec_safe_length (offload_funcs);
18467 unsigned num_vars = vec_safe_length (offload_vars);
18468
18469 if (num_funcs == 0 && num_vars == 0)
18470 return;
18471
18472 if (targetm_common.have_named_sections)
18473 {
18474 vec<constructor_elt, va_gc> *v_f, *v_v;
18475 vec_alloc (v_f, num_funcs);
18476 vec_alloc (v_v, num_vars * 2);
18477
18478 add_decls_addresses_to_decl_constructor (offload_funcs, v_f);
18479 add_decls_addresses_to_decl_constructor (offload_vars, v_v);
18480
18481 tree vars_decl_type = build_array_type_nelts (pointer_sized_int_node,
18482 num_vars * 2);
18483 tree funcs_decl_type = build_array_type_nelts (pointer_sized_int_node,
18484 num_funcs);
5d4b30ea 18485 SET_TYPE_ALIGN (vars_decl_type, TYPE_ALIGN (pointer_sized_int_node));
18486 SET_TYPE_ALIGN (funcs_decl_type, TYPE_ALIGN (pointer_sized_int_node));
dccabdd1 18487 tree ctor_v = build_constructor (vars_decl_type, v_v);
18488 tree ctor_f = build_constructor (funcs_decl_type, v_f);
18489 TREE_CONSTANT (ctor_v) = TREE_CONSTANT (ctor_f) = 1;
18490 TREE_STATIC (ctor_v) = TREE_STATIC (ctor_f) = 1;
18491 tree funcs_decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
18492 get_identifier (".offload_func_table"),
18493 funcs_decl_type);
18494 tree vars_decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
18495 get_identifier (".offload_var_table"),
18496 vars_decl_type);
18497 TREE_STATIC (funcs_decl) = TREE_STATIC (vars_decl) = 1;
18498 /* Do not align tables more than TYPE_ALIGN (pointer_sized_int_node),
18499 otherwise a joint table in a binary will contain padding between
18500 tables from multiple object files. */
18501 DECL_USER_ALIGN (funcs_decl) = DECL_USER_ALIGN (vars_decl) = 1;
5d4b30ea 18502 SET_DECL_ALIGN (funcs_decl, TYPE_ALIGN (funcs_decl_type));
18503 SET_DECL_ALIGN (vars_decl, TYPE_ALIGN (vars_decl_type));
dccabdd1 18504 DECL_INITIAL (funcs_decl) = ctor_f;
18505 DECL_INITIAL (vars_decl) = ctor_v;
18506 set_decl_section_name (funcs_decl, OFFLOAD_FUNC_TABLE_SECTION_NAME);
18507 set_decl_section_name (vars_decl, OFFLOAD_VAR_TABLE_SECTION_NAME);
18508
18509 varpool_node::finalize_decl (vars_decl);
18510 varpool_node::finalize_decl (funcs_decl);
7114ebdd 18511 }
dccabdd1 18512 else
18513 {
18514 for (unsigned i = 0; i < num_funcs; i++)
18515 {
18516 tree it = (*offload_funcs)[i];
18517 targetm.record_offload_symbol (it);
18518 }
18519 for (unsigned i = 0; i < num_vars; i++)
18520 {
18521 tree it = (*offload_vars)[i];
18522 targetm.record_offload_symbol (it);
18523 }
18524 }
18525}
18526
cbba99a0 18527/* Find the number of threads (POS = false), or thread number (POS =
18528 true) for an OpenACC region partitioned as MASK. Setup code
18529 required for the calculation is added to SEQ. */
18530
18531static tree
18532oacc_thread_numbers (bool pos, int mask, gimple_seq *seq)
18533{
18534 tree res = pos ? NULL_TREE : build_int_cst (unsigned_type_node, 1);
18535 unsigned ix;
18536
18537 /* Start at gang level, and examine relevant dimension indices. */
18538 for (ix = GOMP_DIM_GANG; ix != GOMP_DIM_MAX; ix++)
18539 if (GOMP_DIM_MASK (ix) & mask)
18540 {
18541 tree arg = build_int_cst (unsigned_type_node, ix);
18542
18543 if (res)
18544 {
18545 /* We had an outer index, so scale that by the size of
18546 this dimension. */
18547 tree n = create_tmp_var (integer_type_node);
18548 gimple *call
18549 = gimple_build_call_internal (IFN_GOACC_DIM_SIZE, 1, arg);
18550
18551 gimple_call_set_lhs (call, n);
18552 gimple_seq_add_stmt (seq, call);
18553 res = fold_build2 (MULT_EXPR, integer_type_node, res, n);
18554 }
18555 if (pos)
18556 {
18557 /* Determine index in this dimension. */
18558 tree id = create_tmp_var (integer_type_node);
18559 gimple *call = gimple_build_call_internal
18560 (IFN_GOACC_DIM_POS, 1, arg);
18561
18562 gimple_call_set_lhs (call, id);
18563 gimple_seq_add_stmt (seq, call);
18564 if (res)
18565 res = fold_build2 (PLUS_EXPR, integer_type_node, res, id);
18566 else
18567 res = id;
18568 }
18569 }
18570
18571 if (res == NULL_TREE)
18572 res = integer_zero_node;
18573
18574 return res;
18575}
18576
18577/* Transform IFN_GOACC_LOOP calls to actual code. See
18578 expand_oacc_for for where these are generated. At the vector
18579 level, we stride loops, such that each member of a warp will
18580 operate on adjacent iterations. At the worker and gang level,
18581 each gang/warp executes a set of contiguous iterations. Chunking
18582 can override this such that each iteration engine executes a
18583 contiguous chunk, and then moves on to stride to the next chunk. */
18584
18585static void
18586oacc_xform_loop (gcall *call)
18587{
18588 gimple_stmt_iterator gsi = gsi_for_stmt (call);
18589 enum ifn_goacc_loop_kind code
18590 = (enum ifn_goacc_loop_kind) TREE_INT_CST_LOW (gimple_call_arg (call, 0));
18591 tree dir = gimple_call_arg (call, 1);
18592 tree range = gimple_call_arg (call, 2);
18593 tree step = gimple_call_arg (call, 3);
18594 tree chunk_size = NULL_TREE;
18595 unsigned mask = (unsigned) TREE_INT_CST_LOW (gimple_call_arg (call, 5));
18596 tree lhs = gimple_call_lhs (call);
18597 tree type = TREE_TYPE (lhs);
18598 tree diff_type = TREE_TYPE (range);
18599 tree r = NULL_TREE;
18600 gimple_seq seq = NULL;
18601 bool chunking = false, striding = true;
18602 unsigned outer_mask = mask & (~mask + 1); // Outermost partitioning
18603 unsigned inner_mask = mask & ~outer_mask; // Inner partitioning (if any)
18604
18605#ifdef ACCEL_COMPILER
18606 chunk_size = gimple_call_arg (call, 4);
18607 if (integer_minus_onep (chunk_size) /* Force static allocation. */
18608 || integer_zerop (chunk_size)) /* Default (also static). */
18609 {
18610 /* If we're at the gang level, we want each to execute a
18611 contiguous run of iterations. Otherwise we want each element
18612 to stride. */
18613 striding = !(outer_mask & GOMP_DIM_MASK (GOMP_DIM_GANG));
18614 chunking = false;
18615 }
18616 else
18617 {
18618 /* Chunk of size 1 is striding. */
18619 striding = integer_onep (chunk_size);
18620 chunking = !striding;
18621 }
18622#endif
18623
18624 /* striding=true, chunking=true
18625 -> invalid.
18626 striding=true, chunking=false
18627 -> chunks=1
18628 striding=false,chunking=true
18629 -> chunks=ceil (range/(chunksize*threads*step))
18630 striding=false,chunking=false
18631 -> chunk_size=ceil(range/(threads*step)),chunks=1 */
18632 push_gimplify_context (true);
18633
18634 switch (code)
18635 {
18636 default: gcc_unreachable ();
18637
18638 case IFN_GOACC_LOOP_CHUNKS:
18639 if (!chunking)
18640 r = build_int_cst (type, 1);
18641 else
18642 {
18643 /* chunk_max
18644 = (range - dir) / (chunks * step * num_threads) + dir */
18645 tree per = oacc_thread_numbers (false, mask, &seq);
18646 per = fold_convert (type, per);
18647 chunk_size = fold_convert (type, chunk_size);
18648 per = fold_build2 (MULT_EXPR, type, per, chunk_size);
18649 per = fold_build2 (MULT_EXPR, type, per, step);
18650 r = build2 (MINUS_EXPR, type, range, dir);
18651 r = build2 (PLUS_EXPR, type, r, per);
18652 r = build2 (TRUNC_DIV_EXPR, type, r, per);
18653 }
18654 break;
18655
18656 case IFN_GOACC_LOOP_STEP:
18657 {
18658 /* If striding, step by the entire compute volume, otherwise
18659 step by the inner volume. */
18660 unsigned volume = striding ? mask : inner_mask;
18661
18662 r = oacc_thread_numbers (false, volume, &seq);
18663 r = build2 (MULT_EXPR, type, fold_convert (type, r), step);
18664 }
18665 break;
18666
18667 case IFN_GOACC_LOOP_OFFSET:
18668 if (striding)
18669 {
18670 r = oacc_thread_numbers (true, mask, &seq);
18671 r = fold_convert (diff_type, r);
18672 }
18673 else
18674 {
18675 tree inner_size = oacc_thread_numbers (false, inner_mask, &seq);
18676 tree outer_size = oacc_thread_numbers (false, outer_mask, &seq);
18677 tree volume = fold_build2 (MULT_EXPR, TREE_TYPE (inner_size),
18678 inner_size, outer_size);
18679
18680 volume = fold_convert (diff_type, volume);
18681 if (chunking)
18682 chunk_size = fold_convert (diff_type, chunk_size);
18683 else
18684 {
18685 tree per = fold_build2 (MULT_EXPR, diff_type, volume, step);
18686
18687 chunk_size = build2 (MINUS_EXPR, diff_type, range, dir);
18688 chunk_size = build2 (PLUS_EXPR, diff_type, chunk_size, per);
18689 chunk_size = build2 (TRUNC_DIV_EXPR, diff_type, chunk_size, per);
18690 }
18691
18692 tree span = build2 (MULT_EXPR, diff_type, chunk_size,
18693 fold_convert (diff_type, inner_size));
18694 r = oacc_thread_numbers (true, outer_mask, &seq);
18695 r = fold_convert (diff_type, r);
18696 r = build2 (MULT_EXPR, diff_type, r, span);
18697
18698 tree inner = oacc_thread_numbers (true, inner_mask, &seq);
18699 inner = fold_convert (diff_type, inner);
18700 r = fold_build2 (PLUS_EXPR, diff_type, r, inner);
18701
18702 if (chunking)
18703 {
18704 tree chunk = fold_convert (diff_type, gimple_call_arg (call, 6));
18705 tree per
18706 = fold_build2 (MULT_EXPR, diff_type, volume, chunk_size);
18707 per = build2 (MULT_EXPR, diff_type, per, chunk);
18708
18709 r = build2 (PLUS_EXPR, diff_type, r, per);
18710 }
18711 }
18712 r = fold_build2 (MULT_EXPR, diff_type, r, step);
18713 if (type != diff_type)
18714 r = fold_convert (type, r);
18715 break;
18716
18717 case IFN_GOACC_LOOP_BOUND:
18718 if (striding)
18719 r = range;
18720 else
18721 {
18722 tree inner_size = oacc_thread_numbers (false, inner_mask, &seq);
18723 tree outer_size = oacc_thread_numbers (false, outer_mask, &seq);
18724 tree volume = fold_build2 (MULT_EXPR, TREE_TYPE (inner_size),
18725 inner_size, outer_size);
18726
18727 volume = fold_convert (diff_type, volume);
18728 if (chunking)
18729 chunk_size = fold_convert (diff_type, chunk_size);
18730 else
18731 {
18732 tree per = fold_build2 (MULT_EXPR, diff_type, volume, step);
18733
18734 chunk_size = build2 (MINUS_EXPR, diff_type, range, dir);
18735 chunk_size = build2 (PLUS_EXPR, diff_type, chunk_size, per);
18736 chunk_size = build2 (TRUNC_DIV_EXPR, diff_type, chunk_size, per);
18737 }
18738
18739 tree span = build2 (MULT_EXPR, diff_type, chunk_size,
18740 fold_convert (diff_type, inner_size));
18741
18742 r = fold_build2 (MULT_EXPR, diff_type, span, step);
18743
18744 tree offset = gimple_call_arg (call, 6);
18745 r = build2 (PLUS_EXPR, diff_type, r,
18746 fold_convert (diff_type, offset));
18747 r = build2 (integer_onep (dir) ? MIN_EXPR : MAX_EXPR,
18748 diff_type, r, range);
18749 }
18750 if (diff_type != type)
18751 r = fold_convert (type, r);
18752 break;
18753 }
18754
18755 gimplify_assign (lhs, r, &seq);
18756
18757 pop_gimplify_context (NULL);
18758
18759 gsi_replace_with_seq (&gsi, seq, true);
18760}
18761
948eee2f 18762/* Default partitioned and minimum partitioned dimensions. */
18763
18764static int oacc_default_dims[GOMP_DIM_MAX];
18765static int oacc_min_dims[GOMP_DIM_MAX];
18766
18767/* Parse the default dimension parameter. This is a set of
18768 :-separated optional compute dimensions. Each specified dimension
18769 is a positive integer. When device type support is added, it is
18770 planned to be a comma separated list of such compute dimensions,
18771 with all but the first prefixed by the colon-terminated device
18772 type. */
18773
18774static void
18775oacc_parse_default_dims (const char *dims)
18776{
18777 int ix;
18778
18779 for (ix = GOMP_DIM_MAX; ix--;)
18780 {
18781 oacc_default_dims[ix] = -1;
18782 oacc_min_dims[ix] = 1;
18783 }
18784
18785#ifndef ACCEL_COMPILER
18786 /* Cannot be overridden on the host. */
18787 dims = NULL;
18788#endif
18789 if (dims)
18790 {
18791 const char *pos = dims;
18792
18793 for (ix = 0; *pos && ix != GOMP_DIM_MAX; ix++)
18794 {
18795 if (ix)
18796 {
18797 if (*pos != ':')
18798 goto malformed;
18799 pos++;
18800 }
18801
18802 if (*pos != ':')
18803 {
18804 long val;
18805 const char *eptr;
18806
18807 errno = 0;
18808 val = strtol (pos, CONST_CAST (char **, &eptr), 10);
bd1b9075 18809 if (errno || val <= 0 || (int) val != val)
948eee2f 18810 goto malformed;
18811 pos = eptr;
bd1b9075 18812 oacc_default_dims[ix] = (int) val;
948eee2f 18813 }
18814 }
18815 if (*pos)
18816 {
18817 malformed:
18818 error_at (UNKNOWN_LOCATION,
18819 "-fopenacc-dim operand is malformed at '%s'", pos);
18820 }
18821 }
18822
18823 /* Allow the backend to validate the dimensions. */
18824 targetm.goacc.validate_dims (NULL_TREE, oacc_default_dims, -1);
18825 targetm.goacc.validate_dims (NULL_TREE, oacc_min_dims, -2);
18826}
18827
0bb0f256 18828/* Validate and update the dimensions for offloaded FN. ATTRS is the
6f431819 18829 raw attribute. DIMS is an array of dimensions, which is filled in.
18830 LEVEL is the partitioning level of a routine, or -1 for an offload
948eee2f 18831 region itself. USED is the mask of partitioned execution in the
18832 function. */
0bb0f256 18833
6f431819 18834static void
948eee2f 18835oacc_validate_dims (tree fn, tree attrs, int *dims, int level, unsigned used)
0bb0f256 18836{
18837 tree purpose[GOMP_DIM_MAX];
18838 unsigned ix;
18839 tree pos = TREE_VALUE (attrs);
6f431819 18840 bool is_kernel = oacc_fn_attrib_kernels_p (attrs);
0bb0f256 18841
18842 /* Make sure the attribute creator attached the dimension
18843 information. */
18844 gcc_assert (pos);
18845
18846 for (ix = 0; ix != GOMP_DIM_MAX; ix++)
18847 {
18848 purpose[ix] = TREE_PURPOSE (pos);
0bb0f256 18849 tree val = TREE_VALUE (pos);
18850 dims[ix] = val ? TREE_INT_CST_LOW (val) : -1;
18851 pos = TREE_CHAIN (pos);
18852 }
18853
6f431819 18854 bool changed = targetm.goacc.validate_dims (fn, dims, level);
0bb0f256 18855
948eee2f 18856 /* Default anything left to 1 or a partitioned default. */
0bb0f256 18857 for (ix = 0; ix != GOMP_DIM_MAX; ix++)
18858 if (dims[ix] < 0)
18859 {
948eee2f 18860 /* The OpenACC spec says 'If the [num_gangs] clause is not
18861 specified, an implementation-defined default will be used;
18862 the default may depend on the code within the construct.'
18863 (2.5.6). Thus an implementation is free to choose
18864 non-unity default for a parallel region that doesn't have
18865 any gang-partitioned loops. However, it appears that there
18866 is a sufficient body of user code that expects non-gang
18867 partitioned regions to not execute in gang-redundant mode.
18868 So we (a) don't warn about the non-portability and (b) pick
18869 the minimum permissible dimension size when there is no
18870 partitioned execution. Otherwise we pick the global
18871 default for the dimension, which the user can control. The
18872 same wording and logic applies to num_workers and
18873 vector_length, however the worker- or vector- single
18874 execution doesn't have the same impact as gang-redundant
18875 execution. (If the minimum gang-level partioning is not 1,
18876 the target is probably too confusing.) */
18877 dims[ix] = (used & GOMP_DIM_MASK (ix)
18878 ? oacc_default_dims[ix] : oacc_min_dims[ix]);
0bb0f256 18879 changed = true;
18880 }
18881
18882 if (changed)
18883 {
18884 /* Replace the attribute with new values. */
18885 pos = NULL_TREE;
18886 for (ix = GOMP_DIM_MAX; ix--;)
6f431819 18887 {
18888 pos = tree_cons (purpose[ix],
18889 build_int_cst (integer_type_node, dims[ix]),
18890 pos);
18891 if (is_kernel)
18892 TREE_PUBLIC (pos) = 1;
18893 }
0bb0f256 18894 replace_oacc_fn_attrib (fn, pos);
18895 }
0bb0f256 18896}
18897
cbba99a0 18898/* Create an empty OpenACC loop structure at LOC. */
18899
18900static oacc_loop *
18901new_oacc_loop_raw (oacc_loop *parent, location_t loc)
18902{
18903 oacc_loop *loop = XCNEW (oacc_loop);
18904
18905 loop->parent = parent;
18906 loop->child = loop->sibling = NULL;
18907
18908 if (parent)
18909 {
18910 loop->sibling = parent->child;
18911 parent->child = loop;
18912 }
18913
18914 loop->loc = loc;
18915 loop->marker = NULL;
18916 memset (loop->heads, 0, sizeof (loop->heads));
18917 memset (loop->tails, 0, sizeof (loop->tails));
18918 loop->routine = NULL_TREE;
18919
28e869d0 18920 loop->mask = loop->flags = loop->inner = 0;
584fba4b 18921 loop->ifns = 0;
cbba99a0 18922 loop->chunk_size = 0;
18923 loop->head_end = NULL;
18924
18925 return loop;
18926}
18927
18928/* Create an outermost, dummy OpenACC loop for offloaded function
18929 DECL. */
18930
18931static oacc_loop *
18932new_oacc_loop_outer (tree decl)
18933{
18934 return new_oacc_loop_raw (NULL, DECL_SOURCE_LOCATION (decl));
18935}
18936
18937/* Start a new OpenACC loop structure beginning at head marker HEAD.
18938 Link into PARENT loop. Return the new loop. */
18939
18940static oacc_loop *
18941new_oacc_loop (oacc_loop *parent, gcall *marker)
18942{
18943 oacc_loop *loop = new_oacc_loop_raw (parent, gimple_location (marker));
18944
18945 loop->marker = marker;
18946
18947 /* TODO: This is where device_type flattening would occur for the loop
18948 flags. */
18949
18950 loop->flags = TREE_INT_CST_LOW (gimple_call_arg (marker, 3));
18951
18952 tree chunk_size = integer_zero_node;
18953 if (loop->flags & OLF_GANG_STATIC)
18954 chunk_size = gimple_call_arg (marker, 4);
18955 loop->chunk_size = chunk_size;
18956
18957 return loop;
18958}
18959
18960/* Create a dummy loop encompassing a call to a openACC routine.
18961 Extract the routine's partitioning requirements. */
18962
18963static void
18964new_oacc_loop_routine (oacc_loop *parent, gcall *call, tree decl, tree attrs)
18965{
18966 oacc_loop *loop = new_oacc_loop_raw (parent, gimple_location (call));
6f431819 18967 int level = oacc_fn_attrib_level (attrs);
cbba99a0 18968
18969 gcc_assert (level >= 0);
18970
18971 loop->marker = call;
18972 loop->routine = decl;
18973 loop->mask = ((GOMP_DIM_MASK (GOMP_DIM_MAX) - 1)
18974 ^ (GOMP_DIM_MASK (level) - 1));
18975}
18976
18977/* Finish off the current OpenACC loop ending at tail marker TAIL.
18978 Return the parent loop. */
18979
18980static oacc_loop *
18981finish_oacc_loop (oacc_loop *loop)
18982{
584fba4b 18983 /* If the loop has been collapsed, don't partition it. */
18984 if (!loop->ifns)
18985 loop->mask = loop->flags = 0;
cbba99a0 18986 return loop->parent;
18987}
18988
18989/* Free all OpenACC loop structures within LOOP (inclusive). */
18990
18991static void
18992free_oacc_loop (oacc_loop *loop)
18993{
18994 if (loop->sibling)
18995 free_oacc_loop (loop->sibling);
18996 if (loop->child)
18997 free_oacc_loop (loop->child);
18998
18999 free (loop);
19000}
19001
19002/* Dump out the OpenACC loop head or tail beginning at FROM. */
19003
19004static void
19005dump_oacc_loop_part (FILE *file, gcall *from, int depth,
19006 const char *title, int level)
19007{
19008 enum ifn_unique_kind kind
19009 = (enum ifn_unique_kind) TREE_INT_CST_LOW (gimple_call_arg (from, 0));
19010
19011 fprintf (file, "%*s%s-%d:\n", depth * 2, "", title, level);
19012 for (gimple_stmt_iterator gsi = gsi_for_stmt (from);;)
19013 {
19014 gimple *stmt = gsi_stmt (gsi);
19015
19016 if (is_gimple_call (stmt)
19017 && gimple_call_internal_p (stmt)
19018 && gimple_call_internal_fn (stmt) == IFN_UNIQUE)
19019 {
19020 enum ifn_unique_kind k
19021 = ((enum ifn_unique_kind) TREE_INT_CST_LOW
19022 (gimple_call_arg (stmt, 0)));
19023
19024 if (k == kind && stmt != from)
19025 break;
19026 }
19027 print_gimple_stmt (file, stmt, depth * 2 + 2, 0);
19028
19029 gsi_next (&gsi);
19030 while (gsi_end_p (gsi))
19031 gsi = gsi_start_bb (single_succ (gsi_bb (gsi)));
19032 }
19033}
19034
19035/* Dump OpenACC loops LOOP, its siblings and its children. */
19036
19037static void
19038dump_oacc_loop (FILE *file, oacc_loop *loop, int depth)
19039{
19040 int ix;
19041
19042 fprintf (file, "%*sLoop %x(%x) %s:%u\n", depth * 2, "",
19043 loop->flags, loop->mask,
19044 LOCATION_FILE (loop->loc), LOCATION_LINE (loop->loc));
19045
19046 if (loop->marker)
19047 print_gimple_stmt (file, loop->marker, depth * 2, 0);
19048
19049 if (loop->routine)
19050 fprintf (file, "%*sRoutine %s:%u:%s\n",
19051 depth * 2, "", DECL_SOURCE_FILE (loop->routine),
19052 DECL_SOURCE_LINE (loop->routine),
19053 IDENTIFIER_POINTER (DECL_NAME (loop->routine)));
19054
19055 for (ix = GOMP_DIM_GANG; ix != GOMP_DIM_MAX; ix++)
19056 if (loop->heads[ix])
19057 dump_oacc_loop_part (file, loop->heads[ix], depth, "Head", ix);
19058 for (ix = GOMP_DIM_MAX; ix--;)
19059 if (loop->tails[ix])
19060 dump_oacc_loop_part (file, loop->tails[ix], depth, "Tail", ix);
19061
19062 if (loop->child)
19063 dump_oacc_loop (file, loop->child, depth + 1);
19064 if (loop->sibling)
19065 dump_oacc_loop (file, loop->sibling, depth);
19066}
19067
19068void debug_oacc_loop (oacc_loop *);
19069
19070/* Dump loops to stderr. */
19071
19072DEBUG_FUNCTION void
19073debug_oacc_loop (oacc_loop *loop)
19074{
19075 dump_oacc_loop (stderr, loop, 0);
19076}
19077
19078/* DFS walk of basic blocks BB onwards, creating OpenACC loop
19079 structures as we go. By construction these loops are properly
19080 nested. */
19081
19082static void
19083oacc_loop_discover_walk (oacc_loop *loop, basic_block bb)
19084{
19085 int marker = 0;
19086 int remaining = 0;
19087
19088 if (bb->flags & BB_VISITED)
19089 return;
19090
19091 follow:
19092 bb->flags |= BB_VISITED;
19093
19094 /* Scan for loop markers. */
19095 for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi);
19096 gsi_next (&gsi))
19097 {
19098 gimple *stmt = gsi_stmt (gsi);
19099
19100 if (!is_gimple_call (stmt))
19101 continue;
19102
19103 gcall *call = as_a <gcall *> (stmt);
19104
19105 /* If this is a routine, make a dummy loop for it. */
19106 if (tree decl = gimple_call_fndecl (call))
19107 if (tree attrs = get_oacc_fn_attrib (decl))
19108 {
19109 gcc_assert (!marker);
19110 new_oacc_loop_routine (loop, call, decl, attrs);
19111 }
19112
19113 if (!gimple_call_internal_p (call))
19114 continue;
19115
584fba4b 19116 switch (gimple_call_internal_fn (call))
cbba99a0 19117 {
584fba4b 19118 default:
19119 break;
19120
19121 case IFN_GOACC_LOOP:
19122 /* Count the goacc loop abstraction fns, to determine if the
19123 loop was collapsed already. */
19124 loop->ifns++;
19125 break;
cbba99a0 19126
584fba4b 19127 case IFN_UNIQUE:
19128 enum ifn_unique_kind kind
19129 = (enum ifn_unique_kind) (TREE_INT_CST_LOW
19130 (gimple_call_arg (call, 0)));
19131 if (kind == IFN_UNIQUE_OACC_HEAD_MARK
19132 || kind == IFN_UNIQUE_OACC_TAIL_MARK)
19133 {
19134 if (gimple_call_num_args (call) == 2)
cbba99a0 19135 {
584fba4b 19136 gcc_assert (marker && !remaining);
19137 marker = 0;
19138 if (kind == IFN_UNIQUE_OACC_TAIL_MARK)
19139 loop = finish_oacc_loop (loop);
19140 else
19141 loop->head_end = call;
cbba99a0 19142 }
584fba4b 19143 else
cbba99a0 19144 {
584fba4b 19145 int count = TREE_INT_CST_LOW (gimple_call_arg (call, 2));
19146
19147 if (!marker)
19148 {
19149 if (kind == IFN_UNIQUE_OACC_HEAD_MARK)
19150 loop = new_oacc_loop (loop, call);
19151 remaining = count;
19152 }
19153 gcc_assert (count == remaining);
19154 if (remaining)
19155 {
19156 remaining--;
19157 if (kind == IFN_UNIQUE_OACC_HEAD_MARK)
19158 loop->heads[marker] = call;
19159 else
19160 loop->tails[remaining] = call;
19161 }
19162 marker++;
cbba99a0 19163 }
cbba99a0 19164 }
19165 }
19166 }
19167 if (remaining || marker)
19168 {
19169 bb = single_succ (bb);
19170 gcc_assert (single_pred_p (bb) && !(bb->flags & BB_VISITED));
19171 goto follow;
19172 }
19173
19174 /* Walk successor blocks. */
19175 edge e;
19176 edge_iterator ei;
19177
19178 FOR_EACH_EDGE (e, ei, bb->succs)
19179 oacc_loop_discover_walk (loop, e->dest);
19180}
19181
19182/* LOOP is the first sibling. Reverse the order in place and return
19183 the new first sibling. Recurse to child loops. */
19184
19185static oacc_loop *
19186oacc_loop_sibling_nreverse (oacc_loop *loop)
19187{
19188 oacc_loop *last = NULL;
19189 do
19190 {
19191 if (loop->child)
19192 loop->child = oacc_loop_sibling_nreverse (loop->child);
19193
19194 oacc_loop *next = loop->sibling;
19195 loop->sibling = last;
19196 last = loop;
19197 loop = next;
19198 }
19199 while (loop);
19200
19201 return last;
19202}
19203
19204/* Discover the OpenACC loops marked up by HEAD and TAIL markers for
19205 the current function. */
19206
19207static oacc_loop *
19208oacc_loop_discovery ()
19209{
19210 basic_block bb;
19211
19212 oacc_loop *top = new_oacc_loop_outer (current_function_decl);
19213 oacc_loop_discover_walk (top, ENTRY_BLOCK_PTR_FOR_FN (cfun));
19214
19215 /* The siblings were constructed in reverse order, reverse them so
19216 that diagnostics come out in an unsurprising order. */
19217 top = oacc_loop_sibling_nreverse (top);
19218
19219 /* Reset the visited flags. */
19220 FOR_ALL_BB_FN (bb, cfun)
19221 bb->flags &= ~BB_VISITED;
19222
19223 return top;
19224}
19225
19226/* Transform the abstract internal function markers starting at FROM
19227 to be for partitioning level LEVEL. Stop when we meet another HEAD
19228 or TAIL marker. */
19229
19230static void
19231oacc_loop_xform_head_tail (gcall *from, int level)
19232{
19233 enum ifn_unique_kind kind
19234 = (enum ifn_unique_kind) TREE_INT_CST_LOW (gimple_call_arg (from, 0));
19235 tree replacement = build_int_cst (unsigned_type_node, level);
19236
19237 for (gimple_stmt_iterator gsi = gsi_for_stmt (from);;)
19238 {
19239 gimple *stmt = gsi_stmt (gsi);
19240
19241 if (is_gimple_call (stmt)
19242 && gimple_call_internal_p (stmt)
19243 && gimple_call_internal_fn (stmt) == IFN_UNIQUE)
19244 {
19245 enum ifn_unique_kind k
19246 = ((enum ifn_unique_kind)
19247 TREE_INT_CST_LOW (gimple_call_arg (stmt, 0)));
19248
19249 if (k == IFN_UNIQUE_OACC_FORK || k == IFN_UNIQUE_OACC_JOIN)
19250 *gimple_call_arg_ptr (stmt, 2) = replacement;
19251 else if (k == kind && stmt != from)
19252 break;
19253 }
641a0fa1 19254 else if (is_gimple_call (stmt)
19255 && gimple_call_internal_p (stmt)
19256 && gimple_call_internal_fn (stmt) == IFN_GOACC_REDUCTION)
19257 *gimple_call_arg_ptr (stmt, 3) = replacement;
19258
cbba99a0 19259 gsi_next (&gsi);
19260 while (gsi_end_p (gsi))
19261 gsi = gsi_start_bb (single_succ (gsi_bb (gsi)));
19262 }
19263}
19264
19265/* Transform the IFN_GOACC_LOOP internal functions by providing the
584fba4b 19266 determined partitioning mask and chunking argument. END_MARKER
19267 points at the end IFN_HEAD_TAIL call intgroducing the loop. IFNS
19268 is the number of IFN_GOACC_LOOP calls for the loop. MASK_ARG is
19269 the replacement partitioning mask and CHUNK_ARG is the replacement
19270 chunking arg. */
cbba99a0 19271
19272static void
584fba4b 19273oacc_loop_xform_loop (gcall *end_marker, unsigned ifns,
19274 tree mask_arg, tree chunk_arg)
cbba99a0 19275{
19276 gimple_stmt_iterator gsi = gsi_for_stmt (end_marker);
19277
584fba4b 19278 gcc_checking_assert (ifns);
cbba99a0 19279 for (;;)
19280 {
19281 for (; !gsi_end_p (gsi); gsi_next (&gsi))
19282 {
19283 gimple *stmt = gsi_stmt (gsi);
19284
19285 if (!is_gimple_call (stmt))
19286 continue;
19287
19288 gcall *call = as_a <gcall *> (stmt);
19289
19290 if (!gimple_call_internal_p (call))
19291 continue;
19292
19293 if (gimple_call_internal_fn (call) != IFN_GOACC_LOOP)
19294 continue;
19295
19296 *gimple_call_arg_ptr (call, 5) = mask_arg;
19297 *gimple_call_arg_ptr (call, 4) = chunk_arg;
584fba4b 19298 ifns--;
19299 if (!ifns)
cbba99a0 19300 return;
19301 }
19302
584fba4b 19303 /* The LOOP_BOUND ifn could be in the single successor
19304 block. */
cbba99a0 19305 basic_block bb = single_succ (gsi_bb (gsi));
19306 gsi = gsi_start_bb (bb);
19307 }
19308}
19309
19310/* Process the discovered OpenACC loops, setting the correct
19311 partitioning level etc. */
19312
19313static void
19314oacc_loop_process (oacc_loop *loop)
19315{
19316 if (loop->child)
19317 oacc_loop_process (loop->child);
19318
19319 if (loop->mask && !loop->routine)
19320 {
19321 int ix;
19322 unsigned mask = loop->mask;
19323 unsigned dim = GOMP_DIM_GANG;
19324 tree mask_arg = build_int_cst (unsigned_type_node, mask);
19325 tree chunk_arg = loop->chunk_size;
19326
584fba4b 19327 oacc_loop_xform_loop (loop->head_end, loop->ifns, mask_arg, chunk_arg);
cbba99a0 19328
cff84c1a 19329 for (ix = 0; ix != GOMP_DIM_MAX && mask; ix++)
cbba99a0 19330 {
cbba99a0 19331 while (!(GOMP_DIM_MASK (dim) & mask))
19332 dim++;
19333
19334 oacc_loop_xform_head_tail (loop->heads[ix], dim);
19335 oacc_loop_xform_head_tail (loop->tails[ix], dim);
19336
19337 mask ^= GOMP_DIM_MASK (dim);
19338 }
19339 }
19340
19341 if (loop->sibling)
19342 oacc_loop_process (loop->sibling);
19343}
19344
19345/* Walk the OpenACC loop heirarchy checking and assigning the
19346 programmer-specified partitionings. OUTER_MASK is the partitioning
948eee2f 19347 this loop is contained within. Return mask of partitioning
19348 encountered. If any auto loops are discovered, set GOMP_DIM_MAX
19349 bit. */
cbba99a0 19350
948eee2f 19351static unsigned
cbba99a0 19352oacc_loop_fixed_partitions (oacc_loop *loop, unsigned outer_mask)
19353{
19354 unsigned this_mask = loop->mask;
948eee2f 19355 unsigned mask_all = 0;
cbba99a0 19356 bool noisy = true;
19357
19358#ifdef ACCEL_COMPILER
19359 /* When device_type is supported, we want the device compiler to be
19360 noisy, if the loop parameters are device_type-specific. */
19361 noisy = false;
19362#endif
19363
19364 if (!loop->routine)
19365 {
19366 bool auto_par = (loop->flags & OLF_AUTO) != 0;
19367 bool seq_par = (loop->flags & OLF_SEQ) != 0;
19368
19369 this_mask = ((loop->flags >> OLF_DIM_BASE)
19370 & (GOMP_DIM_MASK (GOMP_DIM_MAX) - 1));
19371
19372 if ((this_mask != 0) + auto_par + seq_par > 1)
19373 {
19374 if (noisy)
19375 error_at (loop->loc,
19376 seq_par
19377 ? "%<seq%> overrides other OpenACC loop specifiers"
19378 : "%<auto%> conflicts with other OpenACC loop specifiers");
19379 auto_par = false;
19380 loop->flags &= ~OLF_AUTO;
19381 if (seq_par)
19382 {
19383 loop->flags &=
19384 ~((GOMP_DIM_MASK (GOMP_DIM_MAX) - 1) << OLF_DIM_BASE);
19385 this_mask = 0;
19386 }
19387 }
19388 if (auto_par && (loop->flags & OLF_INDEPENDENT))
948eee2f 19389 mask_all |= GOMP_DIM_MASK (GOMP_DIM_MAX);
cbba99a0 19390 }
19391
19392 if (this_mask & outer_mask)
19393 {
19394 const oacc_loop *outer;
19395 for (outer = loop->parent; outer; outer = outer->parent)
19396 if (outer->mask & this_mask)
19397 break;
19398
19399 if (noisy)
19400 {
19401 if (outer)
19402 {
19403 error_at (loop->loc,
19404 "%s uses same OpenACC parallelism as containing loop",
19405 loop->routine ? "routine call" : "inner loop");
19406 inform (outer->loc, "containing loop here");
19407 }
19408 else
19409 error_at (loop->loc,
19410 "%s uses OpenACC parallelism disallowed by containing routine",
19411 loop->routine ? "routine call" : "loop");
19412
19413 if (loop->routine)
19414 inform (DECL_SOURCE_LOCATION (loop->routine),
19415 "routine %qD declared here", loop->routine);
19416 }
19417 this_mask &= ~outer_mask;
19418 }
19419 else
19420 {
19421 unsigned outermost = this_mask & -this_mask;
19422
19423 if (outermost && outermost <= outer_mask)
19424 {
19425 if (noisy)
19426 {
19427 error_at (loop->loc,
19428 "incorrectly nested OpenACC loop parallelism");
19429
19430 const oacc_loop *outer;
19431 for (outer = loop->parent;
19432 outer->flags && outer->flags < outermost;
19433 outer = outer->parent)
19434 continue;
19435 inform (outer->loc, "containing loop here");
19436 }
19437
19438 this_mask &= ~outermost;
19439 }
19440 }
19441
19442 loop->mask = this_mask;
948eee2f 19443 mask_all |= this_mask;
19444
19445 if (loop->child)
28e869d0 19446 {
19447 loop->inner = oacc_loop_fixed_partitions (loop->child,
19448 outer_mask | this_mask);
19449 mask_all |= loop->inner;
19450 }
cbba99a0 19451
948eee2f 19452 if (loop->sibling)
19453 mask_all |= oacc_loop_fixed_partitions (loop->sibling, outer_mask);
cbba99a0 19454
948eee2f 19455 return mask_all;
cbba99a0 19456}
19457
f4f5b4b4 19458/* Walk the OpenACC loop heirarchy to assign auto-partitioned loops.
19459 OUTER_MASK is the partitioning this loop is contained within.
19460 Return the cumulative partitioning used by this loop, siblings and
19461 children. */
19462
19463static unsigned
19464oacc_loop_auto_partitions (oacc_loop *loop, unsigned outer_mask)
19465{
28e869d0 19466 bool assign = (loop->flags & OLF_AUTO) && (loop->flags & OLF_INDEPENDENT);
f4f5b4b4 19467 bool noisy = true;
19468
19469#ifdef ACCEL_COMPILER
19470 /* When device_type is supported, we want the device compiler to be
19471 noisy, if the loop parameters are device_type-specific. */
19472 noisy = false;
19473#endif
19474
28e869d0 19475 if (assign && outer_mask < GOMP_DIM_MASK (GOMP_DIM_MAX - 1))
19476 {
19477 /* Allocate the outermost loop at the outermost available
19478 level. */
19479 unsigned this_mask = outer_mask + 1;
19480
19481 if (!(this_mask & loop->inner))
19482 loop->mask = this_mask;
19483 }
19484
f4f5b4b4 19485 if (loop->child)
28e869d0 19486 {
19487 unsigned child_mask = outer_mask | loop->mask;
19488
19489 if (loop->mask || assign)
19490 child_mask |= GOMP_DIM_MASK (GOMP_DIM_MAX);
f4f5b4b4 19491
28e869d0 19492 loop->inner = oacc_loop_auto_partitions (loop->child, child_mask);
19493 }
19494
19495 if (assign && !loop->mask)
f4f5b4b4 19496 {
28e869d0 19497 /* Allocate the loop at the innermost available level. */
f4f5b4b4 19498 unsigned this_mask = 0;
19499
19500 /* Determine the outermost partitioning used within this loop. */
28e869d0 19501 this_mask = loop->inner | GOMP_DIM_MASK (GOMP_DIM_MAX);
f4f5b4b4 19502 this_mask = (this_mask & -this_mask);
19503
19504 /* Pick the partitioning just inside that one. */
19505 this_mask >>= 1;
19506
19507 /* And avoid picking one use by an outer loop. */
19508 this_mask &= ~outer_mask;
19509
19510 if (!this_mask && noisy)
19511 warning_at (loop->loc, 0,
19512 "insufficient partitioning available to parallelize loop");
19513
19514 loop->mask = this_mask;
19515 }
28e869d0 19516
19517 if (assign && dump_file)
19518 fprintf (dump_file, "Auto loop %s:%d assigned %d\n",
19519 LOCATION_FILE (loop->loc), LOCATION_LINE (loop->loc),
19520 loop->mask);
19521
19522 unsigned inner_mask = 0;
f4f5b4b4 19523
19524 if (loop->sibling)
19525 inner_mask |= oacc_loop_auto_partitions (loop->sibling, outer_mask);
28e869d0 19526
19527 inner_mask |= loop->inner | loop->mask;
f4f5b4b4 19528
19529 return inner_mask;
19530}
19531
cbba99a0 19532/* Walk the OpenACC loop heirarchy to check and assign partitioning
948eee2f 19533 axes. Return mask of partitioning. */
cbba99a0 19534
948eee2f 19535static unsigned
f4f5b4b4 19536oacc_loop_partition (oacc_loop *loop, unsigned outer_mask)
cbba99a0 19537{
948eee2f 19538 unsigned mask_all = oacc_loop_fixed_partitions (loop, outer_mask);
19539
19540 if (mask_all & GOMP_DIM_MASK (GOMP_DIM_MAX))
19541 {
19542 mask_all ^= GOMP_DIM_MASK (GOMP_DIM_MAX);
19543 mask_all |= oacc_loop_auto_partitions (loop, outer_mask);
19544 }
19545 return mask_all;
cbba99a0 19546}
19547
c25f1934 19548/* Default fork/join early expander. Delete the function calls if
19549 there is no RTL expander. */
19550
19551bool
19552default_goacc_fork_join (gcall *ARG_UNUSED (call),
19553 const int *ARG_UNUSED (dims), bool is_fork)
19554{
19555 if (is_fork)
19556 return targetm.have_oacc_fork ();
19557 else
19558 return targetm.have_oacc_join ();
19559}
19560
641a0fa1 19561/* Default goacc.reduction early expander.
19562
19563 LHS-opt = IFN_REDUCTION (KIND, RES_PTR, VAR, LEVEL, OP, OFFSET)
19564 If RES_PTR is not integer-zerop:
19565 SETUP - emit 'LHS = *RES_PTR', LHS = NULL
19566 TEARDOWN - emit '*RES_PTR = VAR'
19567 If LHS is not NULL
19568 emit 'LHS = VAR' */
19569
19570void
19571default_goacc_reduction (gcall *call)
19572{
19573 unsigned code = (unsigned)TREE_INT_CST_LOW (gimple_call_arg (call, 0));
19574 gimple_stmt_iterator gsi = gsi_for_stmt (call);
19575 tree lhs = gimple_call_lhs (call);
19576 tree var = gimple_call_arg (call, 2);
19577 gimple_seq seq = NULL;
19578
19579 if (code == IFN_GOACC_REDUCTION_SETUP
19580 || code == IFN_GOACC_REDUCTION_TEARDOWN)
19581 {
19582 /* Setup and Teardown need to copy from/to the receiver object,
19583 if there is one. */
19584 tree ref_to_res = gimple_call_arg (call, 1);
19585
19586 if (!integer_zerop (ref_to_res))
19587 {
19588 tree dst = build_simple_mem_ref (ref_to_res);
19589 tree src = var;
19590
19591 if (code == IFN_GOACC_REDUCTION_SETUP)
19592 {
19593 src = dst;
19594 dst = lhs;
19595 lhs = NULL;
19596 }
19597 gimple_seq_add_stmt (&seq, gimple_build_assign (dst, src));
19598 }
19599 }
19600
19601 /* Copy VAR to LHS, if there is an LHS. */
19602 if (lhs)
19603 gimple_seq_add_stmt (&seq, gimple_build_assign (lhs, var));
19604
19605 gsi_replace_with_seq (&gsi, seq, true);
19606}
19607
0bb0f256 19608/* Main entry point for oacc transformations which run on the device
19609 compiler after LTO, so we know what the target device is at this
19610 point (including the host fallback). */
19611
19612static unsigned int
19613execute_oacc_device_lower ()
19614{
19615 tree attrs = get_oacc_fn_attrib (current_function_decl);
0bb0f256 19616
19617 if (!attrs)
19618 /* Not an offloaded function. */
19619 return 0;
19620
948eee2f 19621 /* Parse the default dim argument exactly once. */
19622 if ((const void *)flag_openacc_dims != &flag_openacc_dims)
19623 {
19624 oacc_parse_default_dims (flag_openacc_dims);
19625 flag_openacc_dims = (char *)&flag_openacc_dims;
19626 }
19627
cbba99a0 19628 /* Discover, partition and process the loops. */
19629 oacc_loop *loops = oacc_loop_discovery ();
6f431819 19630 int fn_level = oacc_fn_attrib_level (attrs);
19631
19632 if (dump_file)
19633 fprintf (dump_file, oacc_fn_attrib_kernels_p (attrs)
19634 ? "Function is kernels offload\n"
19635 : fn_level < 0 ? "Function is parallel offload\n"
19636 : "Function is routine level %d\n", fn_level);
19637
f4f5b4b4 19638 unsigned outer_mask = fn_level >= 0 ? GOMP_DIM_MASK (fn_level) - 1 : 0;
948eee2f 19639 unsigned used_mask = oacc_loop_partition (loops, outer_mask);
6f431819 19640 int dims[GOMP_DIM_MAX];
948eee2f 19641
19642 oacc_validate_dims (current_function_decl, attrs, dims, fn_level, used_mask);
6f431819 19643
19644 if (dump_file)
19645 {
19646 const char *comma = "Compute dimensions [";
19647 for (int ix = 0; ix != GOMP_DIM_MAX; ix++, comma = ", ")
19648 fprintf (dump_file, "%s%d", comma, dims[ix]);
19649 fprintf (dump_file, "]\n");
19650 }
19651
cbba99a0 19652 oacc_loop_process (loops);
19653 if (dump_file)
19654 {
19655 fprintf (dump_file, "OpenACC loops\n");
19656 dump_oacc_loop (dump_file, loops, 0);
19657 fprintf (dump_file, "\n");
19658 }
19659
641a0fa1 19660 /* Offloaded targets may introduce new basic blocks, which require
19661 dominance information to update SSA. */
19662 calculate_dominance_info (CDI_DOMINATORS);
19663
cbba99a0 19664 /* Now lower internal loop functions to target-specific code
19665 sequences. */
19666 basic_block bb;
19667 FOR_ALL_BB_FN (bb, cfun)
19668 for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi);)
19669 {
19670 gimple *stmt = gsi_stmt (gsi);
19671 if (!is_gimple_call (stmt))
19672 {
19673 gsi_next (&gsi);
19674 continue;
19675 }
19676
19677 gcall *call = as_a <gcall *> (stmt);
19678 if (!gimple_call_internal_p (call))
19679 {
19680 gsi_next (&gsi);
19681 continue;
19682 }
19683
19684 /* Rewind to allow rescan. */
19685 gsi_prev (&gsi);
19686 bool rescan = false, remove = false;
19687 enum internal_fn ifn_code = gimple_call_internal_fn (call);
19688
19689 switch (ifn_code)
19690 {
19691 default: break;
19692
19693 case IFN_GOACC_LOOP:
19694 oacc_xform_loop (call);
19695 rescan = true;
19696 break;
19697
641a0fa1 19698 case IFN_GOACC_REDUCTION:
19699 /* Mark the function for SSA renaming. */
19700 mark_virtual_operands_for_renaming (cfun);
19701
19702 /* If the level is -1, this ended up being an unused
19703 axis. Handle as a default. */
19704 if (integer_minus_onep (gimple_call_arg (call, 3)))
19705 default_goacc_reduction (call);
19706 else
19707 targetm.goacc.reduction (call);
19708 rescan = true;
19709 break;
19710
cbba99a0 19711 case IFN_UNIQUE:
19712 {
19713 enum ifn_unique_kind kind
19714 = ((enum ifn_unique_kind)
19715 TREE_INT_CST_LOW (gimple_call_arg (call, 0)));
19716
19717 switch (kind)
19718 {
19719 default:
19720 gcc_unreachable ();
19721
19722 case IFN_UNIQUE_OACC_FORK:
19723 case IFN_UNIQUE_OACC_JOIN:
19724 if (integer_minus_onep (gimple_call_arg (call, 2)))
19725 remove = true;
19726 else if (!targetm.goacc.fork_join
19727 (call, dims, kind == IFN_UNIQUE_OACC_FORK))
19728 remove = true;
19729 break;
19730
19731 case IFN_UNIQUE_OACC_HEAD_MARK:
19732 case IFN_UNIQUE_OACC_TAIL_MARK:
19733 remove = true;
19734 break;
19735 }
19736 break;
19737 }
19738 }
19739
19740 if (gsi_end_p (gsi))
19741 /* We rewound past the beginning of the BB. */
19742 gsi = gsi_start_bb (bb);
19743 else
19744 /* Undo the rewind. */
19745 gsi_next (&gsi);
19746
19747 if (remove)
19748 {
19749 if (gimple_vdef (call))
19750 replace_uses_by (gimple_vdef (call), gimple_vuse (call));
19751 if (gimple_call_lhs (call))
19752 {
19753 /* Propagate the data dependency var. */
19754 gimple *ass = gimple_build_assign (gimple_call_lhs (call),
19755 gimple_call_arg (call, 1));
19756 gsi_replace (&gsi, ass, false);
19757 }
19758 else
19759 gsi_remove (&gsi, true);
19760 }
19761 else if (!rescan)
19762 /* If not rescanning, advance over the call. */
19763 gsi_next (&gsi);
19764 }
19765
19766 free_oacc_loop (loops);
19767
0bb0f256 19768 return 0;
19769}
19770
19771/* Default launch dimension validator. Force everything to 1. A
19772 backend that wants to provide larger dimensions must override this
19773 hook. */
19774
19775bool
19776default_goacc_validate_dims (tree ARG_UNUSED (decl), int *dims,
19777 int ARG_UNUSED (fn_level))
19778{
19779 bool changed = false;
19780
19781 for (unsigned ix = 0; ix != GOMP_DIM_MAX; ix++)
19782 {
19783 if (dims[ix] != 1)
19784 {
19785 dims[ix] = 1;
19786 changed = true;
19787 }
19788 }
19789
19790 return changed;
19791}
19792
e1037942 19793/* Default dimension bound is unknown on accelerator and 1 on host. */
19794
19795int
19796default_goacc_dim_limit (int ARG_UNUSED (axis))
19797{
19798#ifdef ACCEL_COMPILER
19799 return 0;
19800#else
19801 return 1;
19802#endif
19803}
19804
0bb0f256 19805namespace {
19806
19807const pass_data pass_data_oacc_device_lower =
19808{
19809 GIMPLE_PASS, /* type */
19810 "oaccdevlow", /* name */
19811 OPTGROUP_NONE, /* optinfo_flags */
19812 TV_NONE, /* tv_id */
19813 PROP_cfg, /* properties_required */
19814 0 /* Possibly PROP_gimple_eomp. */, /* properties_provided */
19815 0, /* properties_destroyed */
19816 0, /* todo_flags_start */
19817 TODO_update_ssa | TODO_cleanup_cfg, /* todo_flags_finish */
19818};
19819
19820class pass_oacc_device_lower : public gimple_opt_pass
19821{
19822public:
19823 pass_oacc_device_lower (gcc::context *ctxt)
19824 : gimple_opt_pass (pass_data_oacc_device_lower, ctxt)
19825 {}
19826
19827 /* opt_pass methods: */
19828 virtual unsigned int execute (function *)
19829 {
173dfdf5 19830 bool gate = flag_openacc != 0;
0bb0f256 19831
19832 if (!gate)
19833 return 0;
19834
19835 return execute_oacc_device_lower ();
19836 }
19837
f69b8a4c 19838}; // class pass_oacc_device_lower
0bb0f256 19839
19840} // anon namespace
19841
19842gimple_opt_pass *
19843make_pass_oacc_device_lower (gcc::context *ctxt)
19844{
19845 return new pass_oacc_device_lower (ctxt);
19846}
19847
c0998828 19848/* "omp declare target link" handling pass. */
19849
19850namespace {
19851
19852const pass_data pass_data_omp_target_link =
19853{
19854 GIMPLE_PASS, /* type */
19855 "omptargetlink", /* name */
19856 OPTGROUP_NONE, /* optinfo_flags */
19857 TV_NONE, /* tv_id */
19858 PROP_ssa, /* properties_required */
19859 0, /* properties_provided */
19860 0, /* properties_destroyed */
19861 0, /* todo_flags_start */
19862 TODO_update_ssa, /* todo_flags_finish */
19863};
19864
19865class pass_omp_target_link : public gimple_opt_pass
19866{
19867public:
19868 pass_omp_target_link (gcc::context *ctxt)
19869 : gimple_opt_pass (pass_data_omp_target_link, ctxt)
19870 {}
19871
19872 /* opt_pass methods: */
19873 virtual bool gate (function *fun)
19874 {
19875#ifdef ACCEL_COMPILER
19876 tree attrs = DECL_ATTRIBUTES (fun->decl);
19877 return lookup_attribute ("omp declare target", attrs)
19878 || lookup_attribute ("omp target entrypoint", attrs);
19879#else
19880 (void) fun;
19881 return false;
19882#endif
19883 }
19884
19885 virtual unsigned execute (function *);
19886};
19887
19888/* Callback for walk_gimple_stmt used to scan for link var operands. */
19889
19890static tree
19891find_link_var_op (tree *tp, int *walk_subtrees, void *)
19892{
19893 tree t = *tp;
19894
19895 if (TREE_CODE (t) == VAR_DECL && DECL_HAS_VALUE_EXPR_P (t)
19896 && lookup_attribute ("omp declare target link", DECL_ATTRIBUTES (t)))
19897 {
19898 *walk_subtrees = 0;
19899 return t;
19900 }
19901
19902 return NULL_TREE;
19903}
19904
19905unsigned
19906pass_omp_target_link::execute (function *fun)
19907{
19908 basic_block bb;
19909 FOR_EACH_BB_FN (bb, fun)
19910 {
19911 gimple_stmt_iterator gsi;
19912 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
19913 if (walk_gimple_stmt (&gsi, NULL, find_link_var_op, NULL))
19914 gimple_regimplify_operands (gsi_stmt (gsi), &gsi);
19915 }
19916
19917 return 0;
19918}
19919
19920} // anon namespace
19921
19922gimple_opt_pass *
19923make_pass_omp_target_link (gcc::context *ctxt)
19924{
19925 return new pass_omp_target_link (ctxt);
19926}
19927
1e8e9920 19928#include "gt-omp-low.h"