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