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