decl.c (gnat_to_gnu_entity): For a derived untagged type that renames discriminants...
[gcc.git] / gcc / omp-low.c
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
6 Copyright (C) 2005-2014 Free Software Foundation, Inc.
7
8 This file is part of GCC.
9
10 GCC is free software; you can redistribute it and/or modify it under
11 the terms of the GNU General Public License as published by the Free
12 Software Foundation; either version 3, or (at your option) any later
13 version.
14
15 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
16 WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18 for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with GCC; see the file COPYING3. If not see
22 <http://www.gnu.org/licenses/>. */
23
24 #include "config.h"
25 #include "system.h"
26 #include "coretypes.h"
27 #include "tm.h"
28 #include "tree.h"
29 #include "stringpool.h"
30 #include "stor-layout.h"
31 #include "rtl.h"
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"
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"
49 #include "gimple.h"
50 #include "gimplify.h"
51 #include "gimple-iterator.h"
52 #include "gimplify-me.h"
53 #include "gimple-walk.h"
54 #include "tree-iterator.h"
55 #include "tree-inline.h"
56 #include "langhooks.h"
57 #include "diagnostic-core.h"
58 #include "gimple-ssa.h"
59 #include "hash-map.h"
60 #include "plugin-api.h"
61 #include "ipa-ref.h"
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"
68 #include "expr.h"
69 #include "tree-dfa.h"
70 #include "tree-ssa.h"
71 #include "flags.h"
72 #include "expr.h"
73 #include "tree-pass.h"
74 #include "except.h"
75 #include "splay-tree.h"
76 #include "insn-codes.h"
77 #include "optabs.h"
78 #include "cfgloop.h"
79 #include "target.h"
80 #include "omp-low.h"
81 #include "gimple-low.h"
82 #include "tree-cfgcleanup.h"
83 #include "pretty-print.h"
84 #include "alloc-pool.h"
85 #include "ipa-prop.h"
86 #include "tree-nested.h"
87 #include "tree-eh.h"
88 #include "cilk.h"
89
90
91 /* Lowering of OpenMP parallel and workshare constructs proceeds in two
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
95 re-gimplifying things when variables have been replaced with complex
96 expressions.
97
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. */
101
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
106 struct 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
141 /* Context structure. Used to store information about each parallel
142 directive in the code. */
143
144 typedef 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;
154 gimple stmt;
155
156 /* Map variables to fields in a structure that allows communication
157 between sending and receiving threads. */
158 splay_tree field_map;
159 tree record_type;
160 tree sender_decl;
161 tree receiver_decl;
162
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
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
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
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
188 /* True if this parallel directive is nested within another. */
189 bool is_nested;
190
191 /* True if this construct can be cancelled. */
192 bool cancellable;
193 } omp_context;
194
195
196 struct omp_for_data_loop
197 {
198 tree v, n1, n2, step;
199 enum tree_code cond_code;
200 };
201
202 /* A structure describing the main elements of a parallel loop. */
203
204 struct omp_for_data
205 {
206 struct omp_for_data_loop loop;
207 tree chunk_size;
208 gimple for_stmt;
209 tree pre, iter_type;
210 int collapse;
211 bool have_nowait, have_ordered;
212 enum omp_clause_schedule_kind sched_kind;
213 struct omp_for_data_loop *loops;
214 };
215
216
217 static splay_tree all_contexts;
218 static int taskreg_nesting_level;
219 static int target_nesting_level;
220 static struct omp_region *root_omp_region;
221 static bitmap task_shared_vars;
222 static vec<omp_context *> taskreg_contexts;
223
224 static void scan_omp (gimple_seq *, omp_context *);
225 static 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: \
232 case GIMPLE_TRANSACTION: \
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
239 static inline tree
240 scan_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
251 static void lower_omp (gimple_seq *, omp_context *);
252 static tree lookup_decl_in_outer_ctx (tree, omp_context *);
253 static tree maybe_lookup_decl_in_outer_ctx (tree, omp_context *);
254
255 /* Find an OpenMP clause of type KIND within CLAUSES. */
256
257 tree
258 find_omp_clause (tree clauses, enum omp_clause_code kind)
259 {
260 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
261 if (OMP_CLAUSE_CODE (clauses) == kind)
262 return clauses;
263
264 return NULL_TREE;
265 }
266
267 /* Return true if CTX is for an omp parallel. */
268
269 static inline bool
270 is_parallel_ctx (omp_context *ctx)
271 {
272 return gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL;
273 }
274
275
276 /* Return true if CTX is for an omp task. */
277
278 static inline bool
279 is_task_ctx (omp_context *ctx)
280 {
281 return gimple_code (ctx->stmt) == GIMPLE_OMP_TASK;
282 }
283
284
285 /* Return true if CTX is for an omp parallel or omp task. */
286
287 static inline bool
288 is_taskreg_ctx (omp_context *ctx)
289 {
290 return gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL
291 || gimple_code (ctx->stmt) == GIMPLE_OMP_TASK;
292 }
293
294
295 /* Return true if REGION is a combined parallel+workshare region. */
296
297 static inline bool
298 is_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
307 static void
308 extract_omp_for_data (gimple for_stmt, struct omp_for_data *fd,
309 struct omp_for_data_loop *loops)
310 {
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;
316 location_t loc = gimple_location (for_stmt);
317 bool simd = gimple_omp_for_kind (for_stmt) & GF_OMP_FOR_SIMD;
318 bool distribute = gimple_omp_for_kind (for_stmt)
319 == GF_OMP_FOR_KIND_DISTRIBUTE;
320
321 fd->for_stmt = for_stmt;
322 fd->pre = NULL;
323 fd->collapse = gimple_omp_for_collapse (for_stmt);
324 if (fd->collapse > 1)
325 fd->loops = loops;
326 else
327 fd->loops = &fd->loop;
328
329 fd->have_nowait = distribute || simd;
330 fd->have_ordered = false;
331 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
332 fd->chunk_size = NULL_TREE;
333 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_CILKFOR)
334 fd->sched_kind = OMP_CLAUSE_SCHEDULE_CILKFOR;
335 collapse_iter = NULL;
336 collapse_count = NULL;
337
338 for (t = gimple_omp_for_clauses (for_stmt); t ; t = OMP_CLAUSE_CHAIN (t))
339 switch (OMP_CLAUSE_CODE (t))
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:
348 gcc_assert (!distribute);
349 fd->sched_kind = OMP_CLAUSE_SCHEDULE_KIND (t);
350 fd->chunk_size = OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (t);
351 break;
352 case OMP_CLAUSE_DIST_SCHEDULE:
353 gcc_assert (distribute);
354 fd->chunk_size = OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (t);
355 break;
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 }
362 break;
363 default:
364 break;
365 }
366
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)
370 is best) or if it varies (then schedule(dynamic,N) is better). */
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);
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. */
383 if (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
384 || fd->have_ordered)
385 fd->chunk_size = (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
386 ? integer_zero_node : integer_one_node;
387 }
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
398 loop->v = gimple_omp_for_index (for_stmt, i);
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;
403 loop->n1 = gimple_omp_for_initial (for_stmt, i);
404
405 loop->cond_code = gimple_omp_for_cond (for_stmt, i);
406 loop->n2 = gimple_omp_for_final (for_stmt, i);
407 switch (loop->cond_code)
408 {
409 case LT_EXPR:
410 case GT_EXPR:
411 break;
412 case NE_EXPR:
413 gcc_assert (gimple_omp_for_kind (for_stmt)
414 == GF_OMP_FOR_KIND_CILKSIMD
415 || (gimple_omp_for_kind (for_stmt)
416 == GF_OMP_FOR_KIND_CILKFOR));
417 break;
418 case LE_EXPR:
419 if (POINTER_TYPE_P (TREE_TYPE (loop->n2)))
420 loop->n2 = fold_build_pointer_plus_hwi_loc (loc, loop->n2, 1);
421 else
422 loop->n2 = fold_build2_loc (loc,
423 PLUS_EXPR, TREE_TYPE (loop->n2), loop->n2,
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)))
429 loop->n2 = fold_build_pointer_plus_hwi_loc (loc, loop->n2, -1);
430 else
431 loop->n2 = fold_build2_loc (loc,
432 MINUS_EXPR, TREE_TYPE (loop->n2), loop->n2,
433 build_int_cst (TREE_TYPE (loop->n2), 1));
434 loop->cond_code = GT_EXPR;
435 break;
436 default:
437 gcc_unreachable ();
438 }
439
440 t = gimple_omp_for_incr (for_stmt, i);
441 gcc_assert (TREE_OPERAND (t, 0) == var);
442 switch (TREE_CODE (t))
443 {
444 case PLUS_EXPR:
445 loop->step = TREE_OPERAND (t, 1);
446 break;
447 case POINTER_PLUS_EXPR:
448 loop->step = fold_convert (ssizetype, TREE_OPERAND (t, 1));
449 break;
450 case MINUS_EXPR:
451 loop->step = TREE_OPERAND (t, 1);
452 loop->step = fold_build1_loc (loc,
453 NEGATE_EXPR, TREE_TYPE (loop->step),
454 loop->step);
455 break;
456 default:
457 gcc_unreachable ();
458 }
459
460 if (simd
461 || (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
462 && !fd->have_ordered))
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
471 (TYPE_PRECISION (TREE_TYPE (loop->v)), 1);
472 }
473 else if (iter_type != long_long_unsigned_type_node)
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)
484 n = fold_build2_loc (loc,
485 PLUS_EXPR, TREE_TYPE (loop->v),
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;
501 n2 = fold_build2_loc (loc,
502 PLUS_EXPR, TREE_TYPE (loop->v),
503 loop->n2, loop->step);
504 }
505 else
506 {
507 n1 = fold_build2_loc (loc,
508 MINUS_EXPR, TREE_TYPE (loop->v),
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 {
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)
532 {
533 tree itype = TREE_TYPE (loop->v);
534
535 if (POINTER_TYPE_P (itype))
536 itype = signed_type_for (itype);
537 t = build_int_cst (itype, (loop->cond_code == LT_EXPR ? -1 : 1));
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));
545 if (TYPE_UNSIGNED (itype) && loop->cond_code == GT_EXPR)
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)));
551 else
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);
555 if (count != NULL_TREE)
556 count = fold_build2_loc (loc,
557 MULT_EXPR, long_long_unsigned_type_node,
558 count, t);
559 else
560 count = t;
561 if (TREE_CODE (count) != INTEGER_CST)
562 count = NULL_TREE;
563 }
564 else if (count && !integer_zerop (count))
565 count = NULL_TREE;
566 }
567 }
568
569 if (count
570 && !simd
571 && (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
572 || fd->have_ordered))
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)
587 *collapse_count = fold_convert_loc (loc, iter_type, count);
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 }
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
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:
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)
622
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
636 GIMPLE_OMP_FOR header check whether they appear on the LHS of any
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
645 static bool
646 workshare_safe_to_combine_p (basic_block ws_entry_bb)
647 {
648 struct omp_for_data fd;
649 gimple ws_stmt = last_stmt (ws_entry_bb);
650
651 if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
652 return true;
653
654 gcc_assert (gimple_code (ws_stmt) == GIMPLE_OMP_FOR);
655
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;
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. */
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)
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
682 static vec<tree, va_gc> *
683 get_ws_args_for (gimple par_stmt, gimple ws_stmt)
684 {
685 tree t;
686 location_t loc = gimple_location (ws_stmt);
687 vec<tree, va_gc> *ws_args;
688
689 if (gimple_code (ws_stmt) == GIMPLE_OMP_FOR)
690 {
691 struct omp_for_data fd;
692 tree n1, n2;
693
694 extract_omp_for_data (ws_stmt, &fd, NULL);
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 }
710
711 vec_alloc (ws_args, 3 + (fd.chunk_size != 0));
712
713 t = fold_convert_loc (loc, long_integer_type_node, n1);
714 ws_args->quick_push (t);
715
716 t = fold_convert_loc (loc, long_integer_type_node, n2);
717 ws_args->quick_push (t);
718
719 t = fold_convert_loc (loc, long_integer_type_node, fd.loop.step);
720 ws_args->quick_push (t);
721
722 if (fd.chunk_size)
723 {
724 t = fold_convert_loc (loc, long_integer_type_node, fd.chunk_size);
725 ws_args->quick_push (t);
726 }
727
728 return ws_args;
729 }
730 else if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
731 {
732 /* Number of sections is equal to the number of edges from the
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));
736 t = build_int_cst (unsigned_type_node, EDGE_COUNT (bb->succs) - 1);
737 vec_alloc (ws_args, 1);
738 ws_args->quick_push (t);
739 return ws_args;
740 }
741
742 gcc_unreachable ();
743 }
744
745
746 /* Discover whether REGION is a combined parallel+workshare region. */
747
748 static void
749 determine_parallel_type (struct omp_region *region)
750 {
751 basic_block par_entry_bb, par_exit_bb;
752 basic_block ws_entry_bb, ws_exit_bb;
753
754 if (region == NULL || region->inner == NULL
755 || region->exit == NULL || region->inner->exit == NULL
756 || region->inner->cont == NULL)
757 return;
758
759 /* We only support parallel+for and parallel+sections. */
760 if (region->type != GIMPLE_OMP_PARALLEL
761 || (region->inner->type != GIMPLE_OMP_FOR
762 && region->inner->type != GIMPLE_OMP_SECTIONS))
763 return;
764
765 /* Check for perfect nesting PAR_ENTRY_BB -> WS_ENTRY_BB and
766 WS_EXIT_BB -> PAR_EXIT_BB. */
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;
771
772 if (single_succ (par_entry_bb) == ws_entry_bb
773 && single_succ (ws_exit_bb) == par_exit_bb
774 && workshare_safe_to_combine_p (ws_entry_bb)
775 && (gimple_omp_parallel_combined_p (last_stmt (par_entry_bb))
776 || (last_and_only_stmt (ws_entry_bb)
777 && last_and_only_stmt (par_exit_bb))))
778 {
779 gimple par_stmt = last_stmt (par_entry_bb);
780 gimple ws_stmt = last_stmt (ws_entry_bb);
781
782 if (region->inner->type == GIMPLE_OMP_FOR)
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. */
793 tree clauses = gimple_omp_for_clauses (ws_stmt);
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;
807 region->ws_args = get_ws_args_for (par_stmt, ws_stmt);
808 }
809 }
810
811
812 /* Return true if EXPR is variable sized. */
813
814 static inline bool
815 is_variable_sized (const_tree expr)
816 {
817 return !TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (expr)));
818 }
819
820 /* Return true if DECL is a reference type. */
821
822 static inline bool
823 is_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
832 static inline tree
833 lookup_decl (tree var, omp_context *ctx)
834 {
835 tree *n = ctx->cb.decl_map->get (var);
836 return *n;
837 }
838
839 static inline tree
840 maybe_lookup_decl (const_tree var, omp_context *ctx)
841 {
842 tree *n = ctx->cb.decl_map->get (const_cast<tree> (var));
843 return n ? *n : NULL_TREE;
844 }
845
846 static inline tree
847 lookup_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
854 static inline tree
855 lookup_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
864 static inline tree
865 maybe_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
872 /* Return true if DECL should be copied by pointer. SHARED_CTX is
873 the parallel context if DECL is to be shared. */
874
875 static bool
876 use_pointer_for_field (tree decl, omp_context *shared_ctx)
877 {
878 if (AGGREGATE_TYPE_P (TREE_TYPE (decl)))
879 return true;
880
881 /* We can only use copy-in/copy-out semantics for shared variables
882 when we know the value is not accessible from an outer scope. */
883 if (shared_ctx)
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. */
896 if (TREE_CODE (decl) != RESULT_DECL && DECL_HAS_VALUE_EXPR_P (decl))
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;
903
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
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. */
917 if (shared_ctx->is_nested)
918 {
919 omp_context *up;
920
921 for (up = shared_ctx->outer; up; up = up->outer)
922 if (is_taskreg_ctx (up) && maybe_lookup_decl (decl, up))
923 break;
924
925 if (up)
926 {
927 tree c;
928
929 for (c = gimple_omp_taskreg_clauses (up->stmt);
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)
936 goto maybe_mark_addressable_and_ret;
937 }
938 }
939
940 /* For tasks avoid using copy-in/out. As tasks can be
941 deferred or executed in different thread, when GOMP_task
942 returns, the task hasn't necessarily terminated. */
943 if (is_task_ctx (shared_ctx))
944 {
945 tree outer;
946 maybe_mark_addressable_and_ret:
947 outer = maybe_lookup_decl_in_outer_ctx (decl, shared_ctx);
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 }
960 }
961
962 return false;
963 }
964
965 /* Construct a new automatic decl similar to VAR. */
966
967 static tree
968 omp_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;
973 DECL_CHAIN (copy) = ctx->block_vars;
974 ctx->block_vars = copy;
975
976 return copy;
977 }
978
979 static tree
980 omp_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
985 /* Build COMPONENT_REF and set TREE_THIS_VOLATILE and TREE_READONLY on it
986 as appropriate. */
987 static tree
988 omp_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
998 /* Build tree nodes to access the field for VAR on the receiver side. */
999
1000 static tree
1001 build_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
1011 x = build_simple_mem_ref (ctx->receiver_decl);
1012 x = omp_build_component_ref (x, field);
1013 if (by_ref)
1014 x = build_simple_mem_ref (x);
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
1023 static tree
1024 build_outer_var_ref (tree var, omp_context *ctx)
1025 {
1026 tree x;
1027
1028 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx)))
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);
1034 x = build_simple_mem_ref (x);
1035 }
1036 else if (is_taskreg_ctx (ctx))
1037 {
1038 bool by_ref = use_pointer_for_field (var, NULL);
1039 x = build_receiver_ref (var, by_ref, ctx);
1040 }
1041 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
1042 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
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)
1050 x = maybe_lookup_decl_in_outer_ctx (var, ctx);
1051 if (x == NULL_TREE)
1052 x = var;
1053 }
1054 else if (ctx->outer)
1055 x = lookup_decl (var, ctx->outer);
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;
1060 else
1061 gcc_unreachable ();
1062
1063 if (is_reference (var))
1064 x = build_simple_mem_ref (x);
1065
1066 return x;
1067 }
1068
1069 /* Build tree nodes to access the field for VAR on the sender side. */
1070
1071 static tree
1072 build_sender_ref (tree var, omp_context *ctx)
1073 {
1074 tree field = lookup_sfield (var, ctx);
1075 return omp_build_component_ref (ctx->sender_decl, field);
1076 }
1077
1078 /* Add a new field for VAR inside the structure CTX->SENDER_DECL. */
1079
1080 static void
1081 install_var_field (tree var, bool by_ref, int mask, omp_context *ctx)
1082 {
1083 tree field, type, sfield = NULL_TREE;
1084
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));
1089
1090 type = TREE_TYPE (var);
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)
1097 type = build_pointer_type (type);
1098 else if ((mask & 3) == 1 && is_reference (var))
1099 type = TREE_TYPE (type);
1100
1101 field = build_decl (DECL_SOURCE_LOCATION (var),
1102 FIELD_DECL, DECL_NAME (var), type);
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;
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);
1116
1117 if ((mask & 3) == 3)
1118 {
1119 insert_field_into_struct (ctx->record_type, field);
1120 if (ctx->srecord_type)
1121 {
1122 sfield = build_decl (DECL_SOURCE_LOCATION (var),
1123 FIELD_DECL, DECL_NAME (var), type);
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 {
1141 sfield = build_decl (DECL_SOURCE_LOCATION (var),
1142 FIELD_DECL, DECL_NAME (t), TREE_TYPE (t));
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 }
1154
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);
1161 }
1162
1163 static tree
1164 install_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
1174 static void
1175 fixup_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);
1187 walk_tree (&ve, copy_tree_body_r, &ctx->cb, NULL);
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
1211 static tree
1212 omp_copy_decl (tree var, copy_body_data *cb)
1213 {
1214 omp_context *ctx = (omp_context *) cb;
1215 tree new_var;
1216
1217 if (TREE_CODE (var) == LABEL_DECL)
1218 {
1219 new_var = create_artificial_label (DECL_SOURCE_LOCATION (var));
1220 DECL_CONTEXT (new_var) = current_function_decl;
1221 insert_decl_map (&ctx->cb, var, new_var);
1222 return new_var;
1223 }
1224
1225 while (!is_taskreg_ctx (ctx))
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
1235 if (is_global_var (var) || decl_function_context (var) != ctx->cb.src_fn)
1236 return var;
1237
1238 return error_mark_node;
1239 }
1240
1241
1242 /* Debugging dumps for parallel regions. */
1243 void dump_omp_region (FILE *, struct omp_region *, int);
1244 void debug_omp_region (struct omp_region *);
1245 void debug_all_omp_regions (void);
1246
1247 /* Dump the parallel region tree rooted at REGION. */
1248
1249 void
1250 dump_omp_region (FILE *file, struct omp_region *region, int indent)
1251 {
1252 fprintf (file, "%*sbb %d: %s\n", indent, "", region->entry->index,
1253 gimple_code_name[region->type]);
1254
1255 if (region->inner)
1256 dump_omp_region (file, region->inner, indent + 4);
1257
1258 if (region->cont)
1259 {
1260 fprintf (file, "%*sbb %d: GIMPLE_OMP_CONTINUE\n", indent, "",
1261 region->cont->index);
1262 }
1263
1264 if (region->exit)
1265 fprintf (file, "%*sbb %d: GIMPLE_OMP_RETURN\n", indent, "",
1266 region->exit->index);
1267 else
1268 fprintf (file, "%*s[no exit marker]\n", indent, "");
1269
1270 if (region->next)
1271 dump_omp_region (file, region->next, indent);
1272 }
1273
1274 DEBUG_FUNCTION void
1275 debug_omp_region (struct omp_region *region)
1276 {
1277 dump_omp_region (stderr, region, 0);
1278 }
1279
1280 DEBUG_FUNCTION void
1281 debug_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
1289 static struct omp_region *
1290 new_omp_region (basic_block bb, enum gimple_code type,
1291 struct omp_region *parent)
1292 {
1293 struct omp_region *region = XCNEW (struct omp_region);
1294
1295 region->outer = parent;
1296 region->entry = bb;
1297 region->type = type;
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 }
1306 else
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 }
1313
1314 return region;
1315 }
1316
1317 /* Release the memory associated with the region tree rooted at REGION. */
1318
1319 static void
1320 free_omp_region_1 (struct omp_region *region)
1321 {
1322 struct omp_region *i, *n;
1323
1324 for (i = region->inner; i ; i = n)
1325 {
1326 n = i->next;
1327 free_omp_region_1 (i);
1328 }
1329
1330 free (region);
1331 }
1332
1333 /* Release the memory for the entire omp region tree. */
1334
1335 void
1336 free_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;
1345 }
1346
1347
1348 /* Create a new context, with OUTER_CTX being the surrounding context. */
1349
1350 static omp_context *
1351 new_omp_context (gimple stmt, omp_context *outer_ctx)
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;
1370 ctx->cb.src_node = cgraph_node::get (current_function_decl);
1371 gcc_checking_assert (ctx->cb.src_node);
1372 ctx->cb.dst_node = ctx->cb.src_node;
1373 ctx->cb.src_cfun = cfun;
1374 ctx->cb.copy_decl = omp_copy_decl;
1375 ctx->cb.eh_lp_nr = 0;
1376 ctx->cb.transform_call_graph_edges = CB_CGE_MOVE;
1377 ctx->depth = 1;
1378 }
1379
1380 ctx->cb.decl_map = new hash_map<tree, tree>;
1381
1382 return ctx;
1383 }
1384
1385 static gimple_seq maybe_catch_exception (gimple_seq);
1386
1387 /* Finalize task copyfn. */
1388
1389 static void
1390 finalize_task_copyfn (gimple task_stmt)
1391 {
1392 struct function *child_cfun;
1393 tree child_fn;
1394 gimple_seq seq = NULL, new_seq;
1395 gimple bind;
1396
1397 child_fn = gimple_omp_task_copy_fn (task_stmt);
1398 if (child_fn == NULL_TREE)
1399 return;
1400
1401 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
1402 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
1403
1404 push_cfun (child_cfun);
1405 bind = gimplify_body (child_fn, false);
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);
1411 seq = NULL;
1412 gimple_seq_add_stmt (&seq, bind);
1413 }
1414 gimple_set_body (child_fn, seq);
1415 pop_cfun ();
1416
1417 /* Inform the callgraph about the new function. */
1418 cgraph_node::add_new_function (child_fn, false);
1419 }
1420
1421 /* Destroy a omp_context data structures. Called through the splay tree
1422 value delete callback. */
1423
1424 static void
1425 delete_omp_context (splay_tree_value value)
1426 {
1427 omp_context *ctx = (omp_context *) value;
1428
1429 delete ctx->cb.decl_map;
1430
1431 if (ctx->field_map)
1432 splay_tree_delete (ctx->field_map);
1433 if (ctx->sfield_map)
1434 splay_tree_delete (ctx->sfield_map);
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;
1441 for (t = TYPE_FIELDS (ctx->record_type); t ; t = DECL_CHAIN (t))
1442 DECL_ABSTRACT_ORIGIN (t) = NULL;
1443 }
1444 if (ctx->srecord_type)
1445 {
1446 tree t;
1447 for (t = TYPE_FIELDS (ctx->srecord_type); t ; t = DECL_CHAIN (t))
1448 DECL_ABSTRACT_ORIGIN (t) = NULL;
1449 }
1450
1451 if (is_task_ctx (ctx))
1452 finalize_task_copyfn (ctx->stmt);
1453
1454 XDELETE (ctx);
1455 }
1456
1457 /* Fix up RECEIVER_DECL with a type that has been remapped to the child
1458 context. */
1459
1460 static void
1461 fixup_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. */
1469 for (f = TYPE_FIELDS (type); f ; f = DECL_CHAIN (f))
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));
1478 name = build_decl (DECL_SOURCE_LOCATION (ctx->receiver_decl),
1479 TYPE_DECL, name, type);
1480 TYPE_NAME (type) = name;
1481
1482 for (f = TYPE_FIELDS (ctx->record_type); f ; f = DECL_CHAIN (f))
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);
1487 DECL_CHAIN (new_f) = new_fields;
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);
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
1510 static void
1511 scan_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
1520 switch (OMP_CLAUSE_CODE (c))
1521 {
1522 case OMP_CLAUSE_PRIVATE:
1523 decl = OMP_CLAUSE_DECL (c);
1524 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
1525 goto do_private;
1526 else if (!is_variable_sized (decl))
1527 install_var_local (decl, ctx);
1528 break;
1529
1530 case OMP_CLAUSE_SHARED:
1531 decl = OMP_CLAUSE_DECL (c);
1532 /* Ignore shared directives in teams construct. */
1533 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
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 }
1543 gcc_assert (is_taskreg_ctx (ctx));
1544 gcc_assert (!COMPLETE_TYPE_P (TREE_TYPE (decl))
1545 || !is_variable_sized (decl));
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;
1550 by_ref = use_pointer_for_field (decl, ctx);
1551 if (! TREE_READONLY (decl)
1552 || TREE_ADDRESSABLE (decl)
1553 || by_ref
1554 || is_reference (decl))
1555 {
1556 install_var_field (decl, by_ref, 3, ctx);
1557 install_var_local (decl, ctx);
1558 break;
1559 }
1560 /* We don't need to copy const scalar vars back. */
1561 OMP_CLAUSE_SET_CODE (c, OMP_CLAUSE_FIRSTPRIVATE);
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:
1573 case OMP_CLAUSE_LINEAR:
1574 decl = OMP_CLAUSE_DECL (c);
1575 do_private:
1576 if (is_variable_sized (decl))
1577 {
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));
1586 by_ref = use_pointer_for_field (decl, NULL);
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);
1597 }
1598 install_var_local (decl, ctx);
1599 break;
1600
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
1608 case OMP_CLAUSE_COPYPRIVATE:
1609 case OMP_CLAUSE_COPYIN:
1610 decl = OMP_CLAUSE_DECL (c);
1611 by_ref = use_pointer_for_field (decl, NULL);
1612 install_var_field (decl, by_ref, 3, ctx);
1613 break;
1614
1615 case OMP_CLAUSE_DEFAULT:
1616 ctx->default_kind = OMP_CLAUSE_DEFAULT_KIND (c);
1617 break;
1618
1619 case OMP_CLAUSE_FINAL:
1620 case OMP_CLAUSE_IF:
1621 case OMP_CLAUSE_NUM_THREADS:
1622 case OMP_CLAUSE_NUM_TEAMS:
1623 case OMP_CLAUSE_THREAD_LIMIT:
1624 case OMP_CLAUSE_DEVICE:
1625 case OMP_CLAUSE_SCHEDULE:
1626 case OMP_CLAUSE_DIST_SCHEDULE:
1627 case OMP_CLAUSE_DEPEND:
1628 case OMP_CLAUSE__CILK_FOR_COUNT_:
1629 if (ctx->outer)
1630 scan_omp_op (&OMP_CLAUSE_OPERAND (c, 0), ctx->outer);
1631 break;
1632
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 {
1701 if (ctx->outer)
1702 {
1703 scan_omp_op (&OMP_CLAUSE_DECL (c), ctx->outer);
1704 decl = OMP_CLAUSE_DECL (c);
1705 }
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
1719 case OMP_CLAUSE_NOWAIT:
1720 case OMP_CLAUSE_ORDERED:
1721 case OMP_CLAUSE_COLLAPSE:
1722 case OMP_CLAUSE_UNTIED:
1723 case OMP_CLAUSE_MERGEABLE:
1724 case OMP_CLAUSE_PROC_BIND:
1725 case OMP_CLAUSE_SAFELEN:
1726 break;
1727
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
1735 default:
1736 gcc_unreachable ();
1737 }
1738 }
1739
1740 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1741 {
1742 switch (OMP_CLAUSE_CODE (c))
1743 {
1744 case OMP_CLAUSE_LASTPRIVATE:
1745 /* Let the corresponding firstprivate clause create
1746 the variable. */
1747 if (OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
1748 scan_array_reductions = true;
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:
1756 case OMP_CLAUSE_LINEAR:
1757 decl = OMP_CLAUSE_DECL (c);
1758 if (is_variable_sized (decl))
1759 install_var_local (decl, ctx);
1760 fixup_remapped_decl (decl, ctx,
1761 OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE
1762 && OMP_CLAUSE_PRIVATE_DEBUG (c));
1763 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1764 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1765 scan_array_reductions = true;
1766 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
1767 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
1768 scan_array_reductions = true;
1769 break;
1770
1771 case OMP_CLAUSE_SHARED:
1772 /* Ignore shared directives in teams construct. */
1773 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
1774 break;
1775 decl = OMP_CLAUSE_DECL (c);
1776 if (! is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1777 fixup_remapped_decl (decl, ctx, false);
1778 break;
1779
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
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:
1819 case OMP_CLAUSE_NUM_TEAMS:
1820 case OMP_CLAUSE_THREAD_LIMIT:
1821 case OMP_CLAUSE_DEVICE:
1822 case OMP_CLAUSE_SCHEDULE:
1823 case OMP_CLAUSE_DIST_SCHEDULE:
1824 case OMP_CLAUSE_NOWAIT:
1825 case OMP_CLAUSE_ORDERED:
1826 case OMP_CLAUSE_COLLAPSE:
1827 case OMP_CLAUSE_UNTIED:
1828 case OMP_CLAUSE_FINAL:
1829 case OMP_CLAUSE_MERGEABLE:
1830 case OMP_CLAUSE_PROC_BIND:
1831 case OMP_CLAUSE_SAFELEN:
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:
1837 case OMP_CLAUSE__CILK_FOR_COUNT_:
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))
1847 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1848 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1849 {
1850 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c), ctx);
1851 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
1852 }
1853 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
1854 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
1855 scan_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
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);
1859 }
1860
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." */
1864
1865 static tree
1866 create_omp_child_function_name (bool task_copy, bool is_cilk_for)
1867 {
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
1877 static tree
1878 cilk_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 }
1894 }
1895
1896 /* Build a decl for the omp child function. It'll not contain a body
1897 yet, just the bare decl. */
1898
1899 static void
1900 create_omp_child_function (omp_context *ctx, bool task_copy)
1901 {
1902 tree decl, type, name, t;
1903
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);
1912 if (task_copy)
1913 type = build_function_type_list (void_type_node, ptr_type_node,
1914 ptr_type_node, NULL_TREE);
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 }
1922 else
1923 type = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
1924
1925 decl = build_decl (gimple_location (ctx->stmt), FUNCTION_DECL, name, type);
1926
1927 if (!task_copy)
1928 ctx->cb.dst_fn = decl;
1929 else
1930 gimple_omp_task_set_copy_fn (ctx->stmt, decl);
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;
1940 DECL_INITIAL (decl) = make_node (BLOCK);
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));
1961
1962 t = build_decl (DECL_SOURCE_LOCATION (decl),
1963 RESULT_DECL, NULL_TREE, void_type_node);
1964 DECL_ARTIFICIAL (t) = 1;
1965 DECL_IGNORED_P (t) = 1;
1966 DECL_CONTEXT (t) = decl;
1967 DECL_RESULT (decl) = t;
1968
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);
1998 DECL_ARTIFICIAL (t) = 1;
1999 DECL_NAMELESS (t) = 1;
2000 DECL_ARG_TYPE (t) = ptr_type_node;
2001 DECL_CONTEXT (t) = current_function_decl;
2002 TREE_USED (t) = 1;
2003 if (cilk_for_count)
2004 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2005 DECL_ARGUMENTS (decl) = t;
2006 if (!task_copy)
2007 ctx->receiver_decl = t;
2008 else
2009 {
2010 t = build_decl (DECL_SOURCE_LOCATION (decl),
2011 PARM_DECL, get_identifier (".omp_data_o"),
2012 ptr_type_node);
2013 DECL_ARTIFICIAL (t) = 1;
2014 DECL_NAMELESS (t) = 1;
2015 DECL_ARG_TYPE (t) = ptr_type_node;
2016 DECL_CONTEXT (t) = current_function_decl;
2017 TREE_USED (t) = 1;
2018 TREE_ADDRESSABLE (t) = 1;
2019 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2020 DECL_ARGUMENTS (decl) = t;
2021 }
2022
2023 /* Allocate memory for the function structure. The call to
2024 allocate_struct_function clobbers CFUN, so we need to restore
2025 it afterward. */
2026 push_struct_function (decl);
2027 cfun->function_end_locus = gimple_location (ctx->stmt);
2028 pop_cfun ();
2029 }
2030
2031 /* Callback for walk_gimple_seq. Check if combined parallel
2032 contains gimple_omp_for_combined_into_p OMP_FOR. */
2033
2034 static tree
2035 find_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
2060 /* Scan an OpenMP parallel directive. */
2061
2062 static void
2063 scan_omp_parallel (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
2064 {
2065 omp_context *ctx;
2066 tree name;
2067 gimple stmt = gsi_stmt (*gsi);
2068
2069 /* Ignore parallel directives with empty bodies, unless there
2070 are copyin clauses. */
2071 if (optimize > 0
2072 && empty_body_p (gimple_omp_body (stmt))
2073 && find_omp_clause (gimple_omp_parallel_clauses (stmt),
2074 OMP_CLAUSE_COPYIN) == NULL)
2075 {
2076 gsi_replace (gsi, gimple_build_nop (), false);
2077 return;
2078 }
2079
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_);
2107 insert_decl_map (&outer_ctx->cb, temp, temp);
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
2115 ctx = new_omp_context (stmt, outer_ctx);
2116 taskreg_contexts.safe_push (ctx);
2117 if (taskreg_nesting_level > 1)
2118 ctx->is_nested = true;
2119 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2120 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2121 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2122 name = create_tmp_var_name (".omp_data_s");
2123 name = build_decl (gimple_location (stmt),
2124 TYPE_DECL, name, ctx->record_type);
2125 DECL_ARTIFICIAL (name) = 1;
2126 DECL_NAMELESS (name) = 1;
2127 TYPE_NAME (ctx->record_type) = name;
2128 create_omp_child_function (ctx, false);
2129 gimple_omp_parallel_set_child_fn (stmt, ctx->cb.dst_fn);
2130
2131 scan_sharing_clauses (gimple_omp_parallel_clauses (stmt), ctx);
2132 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2133
2134 if (TYPE_FIELDS (ctx->record_type) == NULL)
2135 ctx->record_type = ctx->receiver_decl = NULL;
2136 }
2137
2138 /* Scan an OpenMP task directive. */
2139
2140 static void
2141 scan_omp_task (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
2142 {
2143 omp_context *ctx;
2144 tree name, t;
2145 gimple stmt = gsi_stmt (*gsi);
2146
2147 /* Ignore task directives with empty bodies. */
2148 if (optimize > 0
2149 && empty_body_p (gimple_omp_body (stmt)))
2150 {
2151 gsi_replace (gsi, gimple_build_nop (), false);
2152 return;
2153 }
2154
2155 ctx = new_omp_context (stmt, outer_ctx);
2156 taskreg_contexts.safe_push (ctx);
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");
2163 name = build_decl (gimple_location (stmt),
2164 TYPE_DECL, name, ctx->record_type);
2165 DECL_ARTIFICIAL (name) = 1;
2166 DECL_NAMELESS (name) = 1;
2167 TYPE_NAME (ctx->record_type) = name;
2168 create_omp_child_function (ctx, false);
2169 gimple_omp_task_set_child_fn (stmt, ctx->cb.dst_fn);
2170
2171 scan_sharing_clauses (gimple_omp_task_clauses (stmt), ctx);
2172
2173 if (ctx->srecord_type)
2174 {
2175 name = create_tmp_var_name (".omp_data_a");
2176 name = build_decl (gimple_location (stmt),
2177 TYPE_DECL, name, ctx->srecord_type);
2178 DECL_ARTIFICIAL (name) = 1;
2179 DECL_NAMELESS (name) = 1;
2180 TYPE_NAME (ctx->srecord_type) = name;
2181 create_omp_child_function (ctx, true);
2182 }
2183
2184 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2185
2186 if (TYPE_FIELDS (ctx->record_type) == NULL)
2187 {
2188 ctx->record_type = ctx->receiver_decl = NULL;
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);
2193 }
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
2201 static void
2202 finish_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 }
2256 else
2257 {
2258 location_t loc = gimple_location (ctx->stmt);
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
2272 p = &DECL_CHAIN (*p);
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);
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);
2281 t = build_int_cst (long_integer_type_node,
2282 TYPE_ALIGN_UNIT (ctx->record_type));
2283 gimple_omp_task_set_arg_align (ctx->stmt, t);
2284 }
2285 }
2286
2287
2288 /* Scan an OpenMP loop directive. */
2289
2290 static void
2291 scan_omp_for (gimple stmt, omp_context *outer_ctx)
2292 {
2293 omp_context *ctx;
2294 size_t i;
2295
2296 ctx = new_omp_context (stmt, outer_ctx);
2297
2298 scan_sharing_clauses (gimple_omp_for_clauses (stmt), ctx);
2299
2300 scan_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
2301 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
2302 {
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);
2307 }
2308 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2309 }
2310
2311 /* Scan an OpenMP sections directive. */
2312
2313 static void
2314 scan_omp_sections (gimple stmt, omp_context *outer_ctx)
2315 {
2316 omp_context *ctx;
2317
2318 ctx = new_omp_context (stmt, outer_ctx);
2319 scan_sharing_clauses (gimple_omp_sections_clauses (stmt), ctx);
2320 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2321 }
2322
2323 /* Scan an OpenMP single directive. */
2324
2325 static void
2326 scan_omp_single (gimple stmt, omp_context *outer_ctx)
2327 {
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");
2335 name = build_decl (gimple_location (stmt),
2336 TYPE_DECL, name, ctx->record_type);
2337 TYPE_NAME (ctx->record_type) = name;
2338
2339 scan_sharing_clauses (gimple_omp_single_clauses (stmt), ctx);
2340 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2341
2342 if (TYPE_FIELDS (ctx->record_type) == NULL)
2343 ctx->record_type = NULL;
2344 else
2345 layout_type (ctx->record_type);
2346 }
2347
2348 /* Scan an OpenMP target{, data, update} directive. */
2349
2350 static void
2351 scan_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
2398 static void
2399 scan_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 }
2405
2406 /* Check OpenMP nesting restrictions. */
2407 static bool
2408 check_omp_nesting_restrictions (gimple stmt, omp_context *ctx)
2409 {
2410 if (ctx != NULL)
2411 {
2412 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
2413 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
2414 {
2415 error_at (gimple_location (stmt),
2416 "OpenMP constructs may not be nested inside simd region");
2417 return false;
2418 }
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 }
2432 }
2433 switch (gimple_code (stmt))
2434 {
2435 case GIMPLE_OMP_FOR:
2436 if (gimple_omp_for_kind (stmt) & GF_OMP_FOR_SIMD)
2437 return true;
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 }
2468 switch (tree_fits_shwi_p (gimple_call_arg (stmt, 0))
2469 ? tree_to_shwi (gimple_call_arg (stmt, 0))
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 }
2559 /* FALLTHRU */
2560 case GIMPLE_OMP_SECTIONS:
2561 case GIMPLE_OMP_SINGLE:
2562 for (; ctx != NULL; ctx = ctx->outer)
2563 switch (gimple_code (ctx->stmt))
2564 {
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:
2571 case GIMPLE_OMP_CRITICAL:
2572 if (is_gimple_call (stmt))
2573 {
2574 if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2575 != BUILT_IN_GOMP_BARRIER)
2576 return true;
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;
2582 }
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;
2588 case GIMPLE_OMP_PARALLEL:
2589 return true;
2590 default:
2591 break;
2592 }
2593 break;
2594 case GIMPLE_OMP_MASTER:
2595 for (; ctx != NULL; ctx = ctx->outer)
2596 switch (gimple_code (ctx->stmt))
2597 {
2598 case GIMPLE_OMP_FOR:
2599 case GIMPLE_OMP_SECTIONS:
2600 case GIMPLE_OMP_SINGLE:
2601 case GIMPLE_OMP_TASK:
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;
2606 case GIMPLE_OMP_PARALLEL:
2607 return true;
2608 default:
2609 break;
2610 }
2611 break;
2612 case GIMPLE_OMP_ORDERED:
2613 for (; ctx != NULL; ctx = ctx->outer)
2614 switch (gimple_code (ctx->stmt))
2615 {
2616 case GIMPLE_OMP_CRITICAL:
2617 case GIMPLE_OMP_TASK:
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;
2622 case GIMPLE_OMP_FOR:
2623 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2624 OMP_CLAUSE_ORDERED) == NULL)
2625 {
2626 error_at (gimple_location (stmt),
2627 "ordered region must be closely nested inside "
2628 "a loop region with an ordered clause");
2629 return false;
2630 }
2631 return true;
2632 case GIMPLE_OMP_PARALLEL:
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;
2637 default:
2638 break;
2639 }
2640 break;
2641 case GIMPLE_OMP_CRITICAL:
2642 for (; ctx != NULL; ctx = ctx->outer)
2643 if (gimple_code (ctx->stmt) == GIMPLE_OMP_CRITICAL
2644 && (gimple_omp_critical_name (stmt)
2645 == gimple_omp_critical_name (ctx->stmt)))
2646 {
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;
2651 }
2652 break;
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;
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;
2681 default:
2682 break;
2683 }
2684 return true;
2685 }
2686
2687
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. */
2692
2693 static tree
2694 scan_omp_1_op (tree *tp, int *walk_subtrees, void *data)
2695 {
2696 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
2697 omp_context *ctx = (omp_context *) wi->info;
2698 tree t = *tp;
2699
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))
2714 {
2715 *walk_subtrees = 1;
2716 if (ctx)
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)
2722 *tp = wide_int_to_tree (tem, t);
2723 else
2724 TREE_TYPE (t) = tem;
2725 }
2726 }
2727 }
2728 break;
2729 }
2730
2731 return NULL_TREE;
2732 }
2733
2734 /* Return true if FNDECL is a setjmp or a longjmp. */
2735
2736 static bool
2737 setjmp_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
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
2757 static tree
2758 scan_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);
2766
2767 /* Check the OpenMP nesting restrictions. */
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);
2774 if (fndecl)
2775 {
2776 if (setjmp_or_longjmp_p (fndecl)
2777 && ctx
2778 && gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
2779 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
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 }
2801 }
2802 if (remove)
2803 {
2804 stmt = gimple_build_nop ();
2805 gsi_replace (gsi, stmt, false);
2806 }
2807
2808 *handled_ops_p = true;
2809
2810 switch (gimple_code (stmt))
2811 {
2812 case GIMPLE_OMP_PARALLEL:
2813 taskreg_nesting_level++;
2814 scan_omp_parallel (gsi, ctx);
2815 taskreg_nesting_level--;
2816 break;
2817
2818 case GIMPLE_OMP_TASK:
2819 taskreg_nesting_level++;
2820 scan_omp_task (gsi, ctx);
2821 taskreg_nesting_level--;
2822 break;
2823
2824 case GIMPLE_OMP_FOR:
2825 scan_omp_for (stmt, ctx);
2826 break;
2827
2828 case GIMPLE_OMP_SECTIONS:
2829 scan_omp_sections (stmt, ctx);
2830 break;
2831
2832 case GIMPLE_OMP_SINGLE:
2833 scan_omp_single (stmt, ctx);
2834 break;
2835
2836 case GIMPLE_OMP_SECTION:
2837 case GIMPLE_OMP_MASTER:
2838 case GIMPLE_OMP_TASKGROUP:
2839 case GIMPLE_OMP_ORDERED:
2840 case GIMPLE_OMP_CRITICAL:
2841 ctx = new_omp_context (stmt, ctx);
2842 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2843 break;
2844
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
2853 case GIMPLE_BIND:
2854 {
2855 tree var;
2856
2857 *handled_ops_p = false;
2858 if (ctx)
2859 for (var = gimple_bind_vars (stmt); var ; var = DECL_CHAIN (var))
2860 insert_decl_map (&ctx->cb, var, var);
2861 }
2862 break;
2863 default:
2864 *handled_ops_p = false;
2865 break;
2866 }
2867
2868 return NULL_TREE;
2869 }
2870
2871
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. */
2875
2876 static void
2877 scan_omp (gimple_seq *body_p, omp_context *ctx)
2878 {
2879 location_t saved_location;
2880 struct walk_stmt_info wi;
2881
2882 memset (&wi, 0, sizeof (wi));
2883 wi.info = ctx;
2884 wi.want_locations = true;
2885
2886 saved_location = input_location;
2887 walk_gimple_seq_mod (body_p, scan_omp_1_stmt, scan_omp_1_op, &wi);
2888 input_location = saved_location;
2889 }
2890 \f
2891 /* Re-gimplification and code generation routines. */
2892
2893 /* Build a call to GOMP_barrier. */
2894
2895 static gimple
2896 build_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;
2904 }
2905
2906 /* If a context was created for STMT when it was scanned, return it. */
2907
2908 static omp_context *
2909 maybe_lookup_ctx (gimple stmt)
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
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
2966 static tree
2967 lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
2968 {
2969 tree t;
2970 omp_context *up;
2971
2972 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
2973 t = maybe_lookup_decl (decl, up);
2974
2975 gcc_assert (!ctx->is_nested || t || is_global_var (decl));
2976
2977 return t ? t : decl;
2978 }
2979
2980
2981 /* Similar to lookup_decl_in_outer_ctx, but return DECL if not found
2982 in outer contexts. */
2983
2984 static tree
2985 maybe_lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
2986 {
2987 tree t = NULL;
2988 omp_context *up;
2989
2990 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
2991 t = maybe_lookup_decl (decl, up);
2992
2993 return t ? t : decl;
2994 }
2995
2996
2997 /* Construct the initialization value for reduction CLAUSE. */
2998
2999 tree
3000 omp_reduction_init (tree clause, tree type)
3001 {
3002 location_t loc = OMP_CLAUSE_LOCATION (clause);
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:
3013 return build_zero_cst (type);
3014
3015 case MULT_EXPR:
3016 case TRUTH_AND_EXPR:
3017 case TRUTH_ANDIF_EXPR:
3018 case EQ_EXPR:
3019 return fold_convert_loc (loc, type, integer_one_node);
3020
3021 case BIT_AND_EXPR:
3022 return fold_convert_loc (loc, type, integer_minus_one_node);
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
3064 /* Return alignment to be assumed for var in CLAUSE, which should be
3065 OMP_CLAUSE_ALIGNED. */
3066
3067 static tree
3068 omp_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;
3075 machine_mode mode, vmode;
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
3107 /* Return maximum possible vectorization factor for the target. */
3108
3109 static int
3110 omp_max_vf (void)
3111 {
3112 if (!optimize
3113 || optimize_debug
3114 || !flag_tree_loop_optimize
3115 || (!flag_tree_loop_vectorize
3116 && (global_options_set.x_flag_tree_loop_vectorize
3117 || global_options_set.x_flag_tree_vectorize)))
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 }
3126 machine_mode vqimode = targetm.vectorize.preferred_simd_mode (QImode);
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
3135 static bool
3136 lower_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);
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)
3150 max_vf = tree_to_shwi (OMP_CLAUSE_SAFELEN_EXPR (c));
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);
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 }
3178 return true;
3179 }
3180
3181 /* Helper function of lower_rec_input_clauses. For a reference
3182 in simd reduction, add an underlying variable it will reference. */
3183
3184 static void
3185 handle_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
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
3207 static void
3208 lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
3209 omp_context *ctx, struct omp_for_data *fd)
3210 {
3211 tree c, dtor, copyin_seq, x, ptr;
3212 bool copyin_by_ref = false;
3213 bool lastprivate_firstprivate = false;
3214 bool reduction_omp_orig_ref = false;
3215 int pass;
3216 bool is_simd = (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3217 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD);
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 };
3222
3223 copyin_seq = NULL;
3224
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 {
3233 case OMP_CLAUSE_LINEAR:
3234 if (OMP_CLAUSE_LINEAR_ARRAY (c))
3235 max_vf = 1;
3236 /* FALLTHRU */
3237 case OMP_CLAUSE_REDUCTION:
3238 case OMP_CLAUSE_PRIVATE:
3239 case OMP_CLAUSE_FIRSTPRIVATE:
3240 case OMP_CLAUSE_LASTPRIVATE:
3241 if (is_variable_sized (OMP_CLAUSE_DECL (c)))
3242 max_vf = 1;
3243 break;
3244 default:
3245 continue;
3246 }
3247
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
3250 the variable sized types are processed before we use them in the
3251 variable sized operations. */
3252 for (pass = 0; pass < 2; ++pass)
3253 {
3254 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
3255 {
3256 enum omp_clause_code c_kind = OMP_CLAUSE_CODE (c);
3257 tree var, new_var;
3258 bool by_ref;
3259 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
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:
3268 /* Ignore shared directives in teams construct. */
3269 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
3270 continue;
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 }
3276 case OMP_CLAUSE_FIRSTPRIVATE:
3277 case OMP_CLAUSE_COPYIN:
3278 case OMP_CLAUSE_LINEAR:
3279 break;
3280 case OMP_CLAUSE_REDUCTION:
3281 if (OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c))
3282 reduction_omp_orig_ref = true;
3283 break;
3284 case OMP_CLAUSE__LOOPTEMP_:
3285 /* Handle _looptemp_ clauses only on parallel. */
3286 if (fd)
3287 continue;
3288 break;
3289 case OMP_CLAUSE_LASTPRIVATE:
3290 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
3291 {
3292 lastprivate_firstprivate = true;
3293 if (pass != 0)
3294 continue;
3295 }
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;
3303 break;
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;
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 }
3353 else if (is_variable_sized (var))
3354 {
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. */
3358 if (pass == 0)
3359 continue;
3360
3361 if (c_kind != OMP_CLAUSE_FIRSTPRIVATE || !is_task_ctx (ctx))
3362 {
3363 gimple stmt;
3364 tree tmp, atmp;
3365
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));
3371
3372 /* void *tmp = __builtin_alloca */
3373 atmp = builtin_decl_explicit (BUILT_IN_ALLOCA);
3374 stmt = gimple_build_call (atmp, 1, x);
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
3381 x = fold_convert_loc (clause_loc, TREE_TYPE (ptr), tmp);
3382 gimplify_assign (ptr, x, ilist);
3383 }
3384 }
3385 else if (is_reference (var))
3386 {
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
3391 a direct variable. */
3392 if (pass == 0)
3393 continue;
3394
3395 x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
3396 if (c_kind == OMP_CLAUSE_FIRSTPRIVATE && is_task_ctx (ctx))
3397 {
3398 x = build_receiver_ref (var, false, ctx);
3399 x = build_fold_addr_expr_loc (clause_loc, x);
3400 }
3401 else if (TREE_CONSTANT (x))
3402 {
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)
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 }
3421 }
3422 else
3423 {
3424 tree atmp = builtin_decl_explicit (BUILT_IN_ALLOCA);
3425 x = build_call_expr_loc (clause_loc, atmp, 1, x);
3426 }
3427
3428 if (x)
3429 {
3430 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
3431 gimplify_assign (new_var, x, ilist);
3432 }
3433
3434 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
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
3445 switch (OMP_CLAUSE_CODE (c))
3446 {
3447 case OMP_CLAUSE_SHARED:
3448 /* Ignore shared directives in teams construct. */
3449 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
3450 continue;
3451 /* Shared global vars are just accessed directly. */
3452 if (is_global_var (new_var))
3453 break;
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. */
3457 by_ref = use_pointer_for_field (var, ctx);
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
3465 able to notice this and not store anything at all, but
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:
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;
3488 do_private:
3489 tree nx;
3490 nx = lang_hooks.decls.omp_clause_default_ctor (c, new_var, x);
3491 if (is_simd)
3492 {
3493 tree y = lang_hooks.decls.omp_clause_dtor (c, new_var);
3494 if ((TREE_ADDRESSABLE (new_var) || nx || y
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 {
3499 if (nx)
3500 x = lang_hooks.decls.omp_clause_default_ctor
3501 (c, unshare_expr (ivar), x);
3502 if (nx && x)
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 }
3519 if (nx)
3520 gimplify_and_add (nx, ilist);
3521 /* FALLTHRU */
3522
3523 do_dtor:
3524 x = lang_hooks.decls.omp_clause_dtor (c, new_var);
3525 if (x)
3526 {
3527 gimple_seq tseq = NULL;
3528
3529 dtor = x;
3530 gimplify_stmt (&dtor, &tseq);
3531 gimple_seq_add_seq (dlist, tseq);
3532 }
3533 break;
3534
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
3544 case OMP_CLAUSE_FIRSTPRIVATE:
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 }
3559 do_firstprivate:
3560 x = build_outer_var_ref (var, ctx);
3561 if (is_simd)
3562 {
3563 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
3564 && gimple_omp_for_combined_into_p (ctx->stmt))
3565 {
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);
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);
3586 t = fold_build2 (MULT_EXPR, stept,
3587 fold_convert (stept, l), t);
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
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
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);
3620 tree t = OMP_CLAUSE_LINEAR_STEP (c);
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 }
3644 x = lang_hooks.decls.omp_clause_copy_ctor (c, new_var, x);
3645 gimplify_and_add (x, ilist);
3646 goto do_dtor;
3647
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
3655 case OMP_CLAUSE_COPYIN:
3656 by_ref = use_pointer_for_field (var, NULL);
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 {
3666 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
3667 gimple tseq;
3668 x = build_outer_var_ref (var, ctx);
3669
3670 if (is_reference (var)
3671 && !useless_type_conversion_p (TREE_TYPE (placeholder),
3672 TREE_TYPE (x)))
3673 x = build_fold_addr_expr_loc (clause_loc, x);
3674 SET_DECL_VALUE_EXPR (placeholder, x);
3675 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
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 }
3683 if (is_simd
3684 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3685 idx, lane, ivar, lvar))
3686 {
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 }
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)
3736 handle_simd_reference (clause_loc, new_vard, ilist);
3737 x = lang_hooks.decls.omp_clause_default_ctor
3738 (c, unshare_expr (new_var),
3739 build_outer_var_ref (var, ctx));
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);
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
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 }
3777 if (is_simd
3778 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3779 idx, lane, ivar, lvar))
3780 {
3781 tree ref = build_outer_var_ref (var, ctx);
3782
3783 gimplify_assign (unshare_expr (ivar), x, &llist[0]);
3784
3785 x = build2 (code, TREE_TYPE (ref), ref, ivar);
3786 ref = build_outer_var_ref (var, ctx);
3787 gimplify_assign (ref, x, &llist[1]);
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 }
3795 }
3796 else
3797 {
3798 if (is_reference (var) && is_simd)
3799 handle_simd_reference (clause_loc, new_vard, ilist);
3800 gimplify_assign (new_var, x, ilist);
3801 if (is_simd)
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 }
3809 }
3810 }
3811 break;
3812
3813 default:
3814 gcc_unreachable ();
3815 }
3816 }
3817 }
3818
3819 if (lane)
3820 {
3821 tree uid = create_tmp_var (ptr_type_node, "simduid");
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;
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
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 {
3870 x = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM),
3871 0);
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
3880 threads. Similarly for variables in both firstprivate and
3881 lastprivate clauses we need to ensure the lastprivate copying
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)
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
3889 || gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_FOR)
3890 gimple_seq_add_stmt (ilist, build_omp_barrier (NULL_TREE));
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
3900 || (TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c)) == INTEGER_CST
3901 && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
3902 max_vf) == 1))
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 }
3911 }
3912
3913
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
3918 static void
3919 lower_lastprivate_clauses (tree clauses, tree predicate, gimple_seq *stmt_list,
3920 omp_context *ctx)
3921 {
3922 tree x, c, label = NULL, orig_clauses = clauses;
3923 bool par_clauses = false;
3924 tree simduid = NULL, lastlane = NULL;
3925
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;
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
3944 clauses = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
3945 OMP_CLAUSE_LASTPRIVATE);
3946 if (clauses == NULL)
3947 return;
3948 par_clauses = true;
3949 }
3950
3951 if (predicate)
3952 {
3953 gimple stmt;
3954 tree label_true, arm1, arm2;
3955
3956 label = create_artificial_label (UNKNOWN_LOCATION);
3957 label_true = create_artificial_label (UNKNOWN_LOCATION);
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 }
3967
3968 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3969 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
3970 {
3971 simduid = find_omp_clause (orig_clauses, OMP_CLAUSE__SIMDUID_);
3972 if (simduid)
3973 simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
3974 }
3975
3976 for (c = clauses; c ;)
3977 {
3978 tree var, new_var;
3979 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
3980
3981 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
3982 || (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
3983 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c)))
3984 {
3985 var = OMP_CLAUSE_DECL (c);
3986 new_var = lookup_decl (var, ctx);
3987
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))
4015 {
4016 lower_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
4017 gimple_seq_add_seq (stmt_list,
4018 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c));
4019 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c) = NULL;
4020 }
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 }
4029
4030 x = build_outer_var_ref (var, ctx);
4031 if (is_reference (var))
4032 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
4033 x = lang_hooks.decls.omp_clause_assign_op (c, x, new_var);
4034 gimplify_and_add (x, stmt_list);
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
4049 c = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
4050 OMP_CLAUSE_LASTPRIVATE);
4051 par_clauses = true;
4052 }
4053 }
4054
4055 if (label)
4056 gimple_seq_add_stmt (stmt_list, gimple_build_label (label));
4057 }
4058
4059
4060 /* Generate code to implement the REDUCTION clauses. */
4061
4062 static void
4063 lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp, omp_context *ctx)
4064 {
4065 gimple_seq sub_seq = NULL;
4066 gimple stmt;
4067 tree x, c;
4068 int count = 0;
4069
4070 /* SIMD reductions are handled in lower_rec_input_clauses. */
4071 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
4072 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
4073 return;
4074
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))
4078 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
4079 {
4080 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4081 {
4082 /* Never use OMP_ATOMIC for array reductions or UDRs. */
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;
4096 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4097
4098 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
4099 continue;
4100
4101 var = OMP_CLAUSE_DECL (c);
4102 new_var = lookup_decl (var, ctx);
4103 if (is_reference (var))
4104 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
4105 ref = build_outer_var_ref (var, ctx);
4106 code = OMP_CLAUSE_REDUCTION_CODE (c);
4107
4108 /* reduction(-:var) sums up the partial results, so it acts
4109 identically to reduction(+:var). */
4110 if (code == MINUS_EXPR)
4111 code = PLUS_EXPR;
4112
4113 if (count == 1)
4114 {
4115 tree addr = build_fold_addr_expr_loc (clause_loc, ref);
4116
4117 addr = save_expr (addr);
4118 ref = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (addr)), addr);
4119 x = fold_build2_loc (clause_loc, code, TREE_TYPE (ref), ref, new_var);
4120 x = build2 (OMP_ATOMIC, void_type_node, addr, x);
4121 gimplify_and_add (x, stmt_seqp);
4122 return;
4123 }
4124
4125 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4126 {
4127 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
4128
4129 if (is_reference (var)
4130 && !useless_type_conversion_p (TREE_TYPE (placeholder),
4131 TREE_TYPE (ref)))
4132 ref = build_fold_addr_expr_loc (clause_loc, ref);
4133 SET_DECL_VALUE_EXPR (placeholder, ref);
4134 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
4135 lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
4136 gimple_seq_add_seq (&sub_seq, OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
4137 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
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);
4144 gimplify_assign (ref, x, &sub_seq);
4145 }
4146 }
4147
4148 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START),
4149 0);
4150 gimple_seq_add_stmt (stmt_seqp, stmt);
4151
4152 gimple_seq_add_seq (stmt_seqp, sub_seq);
4153
4154 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END),
4155 0);
4156 gimple_seq_add_stmt (stmt_seqp, stmt);
4157 }
4158
4159
4160 /* Generate code to implement the COPYPRIVATE clauses. */
4161
4162 static void
4163 lower_copyprivate_clauses (tree clauses, gimple_seq *slist, gimple_seq *rlist,
4164 omp_context *ctx)
4165 {
4166 tree c;
4167
4168 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4169 {
4170 tree var, new_var, ref, x;
4171 bool by_ref;
4172 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4173
4174 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYPRIVATE)
4175 continue;
4176
4177 var = OMP_CLAUSE_DECL (c);
4178 by_ref = use_pointer_for_field (var, NULL);
4179
4180 ref = build_sender_ref (var, ctx);
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 }
4187 gimplify_assign (ref, x, slist);
4188
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 }
4197 if (is_reference (var))
4198 {
4199 ref = fold_convert_loc (clause_loc, TREE_TYPE (new_var), ref);
4200 ref = build_simple_mem_ref_loc (clause_loc, ref);
4201 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
4202 }
4203 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, ref);
4204 gimplify_and_add (x, rlist);
4205 }
4206 }
4207
4208
4209 /* Generate code to implement the clauses, FIRSTPRIVATE, COPYIN, LASTPRIVATE,
4210 and REDUCTION from the sender (aka parent) side. */
4211
4212 static void
4213 lower_send_clauses (tree clauses, gimple_seq *ilist, gimple_seq *olist,
4214 omp_context *ctx)
4215 {
4216 tree c;
4217
4218 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4219 {
4220 tree val, ref, x, var;
4221 bool by_ref, do_in = false, do_out = false;
4222 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4223
4224 switch (OMP_CLAUSE_CODE (c))
4225 {
4226 case OMP_CLAUSE_PRIVATE:
4227 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
4228 break;
4229 continue;
4230 case OMP_CLAUSE_FIRSTPRIVATE:
4231 case OMP_CLAUSE_COPYIN:
4232 case OMP_CLAUSE_LASTPRIVATE:
4233 case OMP_CLAUSE_REDUCTION:
4234 case OMP_CLAUSE__LOOPTEMP_:
4235 break;
4236 default:
4237 continue;
4238 }
4239
4240 val = OMP_CLAUSE_DECL (c);
4241 var = lookup_decl_in_outer_ctx (val, ctx);
4242
4243 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYIN
4244 && is_global_var (var))
4245 continue;
4246 if (is_variable_sized (val))
4247 continue;
4248 by_ref = use_pointer_for_field (val, NULL);
4249
4250 switch (OMP_CLAUSE_CODE (c))
4251 {
4252 case OMP_CLAUSE_PRIVATE:
4253 case OMP_CLAUSE_FIRSTPRIVATE:
4254 case OMP_CLAUSE_COPYIN:
4255 case OMP_CLAUSE__LOOPTEMP_:
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
4267 {
4268 do_out = true;
4269 if (lang_hooks.decls.omp_private_outer_ref (val))
4270 do_in = true;
4271 }
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);
4286 x = by_ref ? build_fold_addr_expr_loc (clause_loc, var) : var;
4287 gimplify_assign (ref, x, ilist);
4288 if (is_task_ctx (ctx))
4289 DECL_ABSTRACT_ORIGIN (TREE_OPERAND (ref, 1)) = NULL;
4290 }
4291
4292 if (do_out)
4293 {
4294 ref = build_sender_ref (val, ctx);
4295 gimplify_assign (var, ref, olist);
4296 }
4297 }
4298 }
4299
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. */
4303
4304 static void
4305 lower_send_shared_vars (gimple_seq *ilist, gimple_seq *olist, omp_context *ctx)
4306 {
4307 tree var, ovar, nvar, f, x, record_type;
4308
4309 if (ctx->record_type == NULL)
4310 return;
4311
4312 record_type = ctx->srecord_type ? ctx->srecord_type : ctx->record_type;
4313 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
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
4320 /* If CTX is a nested parallel directive. Find the immediately
4321 enclosing parallel or workshare construct that contains a
4322 mapping for OVAR. */
4323 var = lookup_decl_in_outer_ctx (ovar, ctx);
4324
4325 if (use_pointer_for_field (ovar, ctx))
4326 {
4327 x = build_sender_ref (ovar, ctx);
4328 var = build_fold_addr_expr (var);
4329 gimplify_assign (x, var, ilist);
4330 }
4331 else
4332 {
4333 x = build_sender_ref (ovar, ctx);
4334 gimplify_assign (x, var, ilist);
4335
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)))
4344 {
4345 x = build_sender_ref (ovar, ctx);
4346 gimplify_assign (var, x, olist);
4347 }
4348 }
4349 }
4350 }
4351
4352
4353 /* A convenience function to build an empty GIMPLE_COND with just the
4354 condition. */
4355
4356 static gimple
4357 gimple_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
4367 /* Build the function calls to GOMP_parallel_start etc to actually
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. */
4373
4374 static void
4375 expand_parallel_call (struct omp_region *region, basic_block bb,
4376 gimple entry_stmt, vec<tree, va_gc> *ws_args)
4377 {
4378 tree t, t1, t2, val, cond, c, clauses, flags;
4379 gimple_stmt_iterator gsi;
4380 gimple stmt;
4381 enum built_in_function start_ix;
4382 int start_ix2;
4383 location_t clause_loc;
4384 vec<tree, va_gc> *args;
4385
4386 clauses = gimple_omp_parallel_clauses (entry_stmt);
4387
4388 /* Determine what flavor of GOMP_parallel we will be
4389 emitting. */
4390 start_ix = BUILT_IN_GOMP_PARALLEL;
4391 if (is_combined_parallel (region))
4392 {
4393 switch (region->inner->type)
4394 {
4395 case GIMPLE_OMP_FOR:
4396 gcc_assert (region->inner->sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
4397 start_ix2 = ((int)BUILT_IN_GOMP_PARALLEL_LOOP_STATIC
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;
4402 break;
4403 case GIMPLE_OMP_SECTIONS:
4404 start_ix = BUILT_IN_GOMP_PARALLEL_SECTIONS;
4405 break;
4406 default:
4407 gcc_unreachable ();
4408 }
4409 }
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);
4415 flags = build_int_cst (unsigned_type_node, 0);
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)
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);
4429
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
4434 /* Ensure 'val' is of the correct type. */
4435 val = fold_convert_loc (clause_loc, unsigned_type_node, val);
4436
4437 /* If we found the clause 'if (cond)', build either
4438 (cond != 0) or (cond ? val : 1u). */
4439 if (cond)
4440 {
4441 cond = gimple_boolify (cond);
4442
4443 if (integer_zerop (val))
4444 val = fold_build2_loc (clause_loc,
4445 EQ_EXPR, unsigned_type_node, cond,
4446 build_int_cst (TREE_TYPE (cond), 0));
4447 else
4448 {
4449 basic_block cond_bb, then_bb, else_bb;
4450 edge e, e_then, e_else;
4451 tree tmp_then, tmp_else, tmp_join, tmp_var;
4452
4453 tmp_var = create_tmp_var (TREE_TYPE (val), NULL);
4454 if (gimple_in_ssa_p (cfun))
4455 {
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);
4459 }
4460 else
4461 {
4462 tmp_then = tmp_var;
4463 tmp_else = tmp_var;
4464 tmp_join = tmp_var;
4465 }
4466
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);
4474 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
4475 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
4476
4477 stmt = gimple_build_cond_empty (cond);
4478 gsi = gsi_start_bb (cond_bb);
4479 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4480
4481 gsi = gsi_start_bb (then_bb);
4482 stmt = gimple_build_assign (tmp_then, val);
4483 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4484
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);
4489
4490 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
4491 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
4492 add_bb_to_loop (then_bb, cond_bb->loop_father);
4493 add_bb_to_loop (else_bb, cond_bb->loop_father);
4494 e_then = make_edge (then_bb, bb, EDGE_FALLTHRU);
4495 e_else = make_edge (else_bb, bb, EDGE_FALLTHRU);
4496
4497 if (gimple_in_ssa_p (cfun))
4498 {
4499 gimple phi = create_phi_node (tmp_join, bb);
4500 add_phi_arg (phi, tmp_then, e_then, UNKNOWN_LOCATION);
4501 add_phi_arg (phi, tmp_else, e_else, UNKNOWN_LOCATION);
4502 }
4503
4504 val = tmp_join;
4505 }
4506
4507 gsi = gsi_start_bb (bb);
4508 val = force_gimple_operand_gsi (&gsi, val, true, NULL_TREE,
4509 false, GSI_CONTINUE_LINKING);
4510 }
4511
4512 gsi = gsi_last_bb (bb);
4513 t = gimple_omp_parallel_data_arg (entry_stmt);
4514 if (t == NULL)
4515 t1 = null_pointer_node;
4516 else
4517 t1 = build_fold_addr_expr (t);
4518 t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
4519
4520 vec_alloc (args, 4 + vec_safe_length (ws_args));
4521 args->quick_push (t2);
4522 args->quick_push (t1);
4523 args->quick_push (val);
4524 if (ws_args)
4525 args->splice (*ws_args);
4526 args->quick_push (flags);
4527
4528 t = build_call_expr_loc_vec (UNKNOWN_LOCATION,
4529 builtin_decl_explicit (start_ix), args);
4530
4531 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
4532 false, GSI_CONTINUE_LINKING);
4533 }
4534
4535 /* Insert a function call whose name is FUNC_NAME with the information from
4536 ENTRY_STMT into the basic_block BB. */
4537
4538 static void
4539 expand_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 }
4573
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
4577 static void
4578 expand_task_call (basic_block bb, gimple entry_stmt)
4579 {
4580 tree t, t1, t2, t3, flags, cond, c, c2, clauses, depend;
4581 gimple_stmt_iterator gsi;
4582 location_t loc = gimple_location (entry_stmt);
4583
4584 clauses = gimple_omp_task_clauses (entry_stmt);
4585
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);
4593 c2 = find_omp_clause (clauses, OMP_CLAUSE_MERGEABLE);
4594 depend = find_omp_clause (clauses, OMP_CLAUSE_DEPEND);
4595 flags = build_int_cst (unsigned_type_node,
4596 (c ? 1 : 0) + (c2 ? 4 : 0) + (depend ? 8 : 0));
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 }
4607 if (depend)
4608 depend = OMP_CLAUSE_DECL (depend);
4609 else
4610 depend = build_int_cst (ptr_type_node, 0);
4611
4612 gsi = gsi_last_bb (bb);
4613 t = gimple_omp_task_data_arg (entry_stmt);
4614 if (t == NULL)
4615 t2 = null_pointer_node;
4616 else
4617 t2 = build_fold_addr_expr_loc (loc, t);
4618 t1 = build_fold_addr_expr_loc (loc, gimple_omp_task_child_fn (entry_stmt));
4619 t = gimple_omp_task_copy_fn (entry_stmt);
4620 if (t == NULL)
4621 t3 = null_pointer_node;
4622 else
4623 t3 = build_fold_addr_expr_loc (loc, t);
4624
4625 t = build_call_expr (builtin_decl_explicit (BUILT_IN_GOMP_TASK),
4626 8, t1, t2, t3,
4627 gimple_omp_task_arg_size (entry_stmt),
4628 gimple_omp_task_arg_align (entry_stmt), cond, flags,
4629 depend);
4630
4631 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
4632 false, GSI_CONTINUE_LINKING);
4633 }
4634
4635
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. */
4639
4640 static gimple_seq
4641 maybe_catch_exception (gimple_seq body)
4642 {
4643 gimple g;
4644 tree decl;
4645
4646 if (!flag_exceptions)
4647 return body;
4648
4649 if (lang_hooks.eh_protect_cleanup_actions != NULL)
4650 decl = lang_hooks.eh_protect_cleanup_actions ();
4651 else
4652 decl = builtin_decl_explicit (BUILT_IN_TRAP);
4653
4654 g = gimple_build_eh_must_not_throw (decl);
4655 g = gimple_build_try (body, gimple_seq_alloc_with_stmt (g),
4656 GIMPLE_TRY_CATCH);
4657
4658 return gimple_seq_alloc_with_stmt (g);
4659 }
4660
4661 /* Chain all the DECLs in LIST by their TREE_CHAIN fields. */
4662
4663 static tree
4664 vec2chain (vec<tree, va_gc> *v)
4665 {
4666 tree chain = NULL_TREE, t;
4667 unsigned ix;
4668
4669 FOR_EACH_VEC_SAFE_ELT_REVERSE (v, ix, t)
4670 {
4671 DECL_CHAIN (t) = chain;
4672 chain = t;
4673 }
4674
4675 return chain;
4676 }
4677
4678
4679 /* Remove barriers in REGION->EXIT's block. Note that this is only
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
4683 removed. */
4684
4685 static void
4686 remove_exit_barrier (struct omp_region *region)
4687 {
4688 gimple_stmt_iterator gsi;
4689 basic_block exit_bb;
4690 edge_iterator ei;
4691 edge e;
4692 gimple stmt;
4693 int any_addressable_vars = -1;
4694
4695 exit_bb = region->exit;
4696
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
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
4704 statements that can appear in between are extremely limited -- no
4705 memory operations at all. Here, we allow nothing at all, so the
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)
4711 return;
4712
4713 FOR_EACH_EDGE (e, ei, exit_bb->preds)
4714 {
4715 gsi = gsi_last_bb (e->src);
4716 if (gsi_end_p (gsi))
4717 continue;
4718 stmt = gsi_stmt (gsi);
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);
4734 tree local_decls, block, decl;
4735 unsigned ix;
4736
4737 any_addressable_vars = 0;
4738 FOR_EACH_LOCAL_DECL (DECL_STRUCT_FUNCTION (child_fun), ix, decl)
4739 if (TREE_ADDRESSABLE (decl))
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;
4752 local_decls = DECL_CHAIN (local_decls))
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 }
4765 }
4766 }
4767
4768 static void
4769 remove_exit_barriers (struct omp_region *region)
4770 {
4771 if (region->type == GIMPLE_OMP_PARALLEL)
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 }
4785
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} ()
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. */
4793
4794 static void
4795 optimize_omp_library_calls (gimple entry_stmt)
4796 {
4797 basic_block bb;
4798 gimple_stmt_iterator gsi;
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);
4803 bool untied_task = (gimple_code (entry_stmt) == GIMPLE_OMP_TASK
4804 && find_omp_clause (gimple_omp_task_clauses (entry_stmt),
4805 OMP_CLAUSE_UNTIED) != NULL);
4806
4807 FOR_EACH_BB_FN (bb, cfun)
4808 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
4809 {
4810 gimple call = gsi_stmt (gsi);
4811 tree decl;
4812
4813 if (is_gimple_call (call)
4814 && (decl = gimple_call_fndecl (call))
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)
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;
4827 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
4828 }
4829 else if (DECL_NAME (decl) == num_thr_id)
4830 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
4831 else
4832 continue;
4833
4834 if (DECL_ASSEMBLER_NAME (decl) != DECL_ASSEMBLER_NAME (built_in)
4835 || gimple_call_num_args (call) != 0)
4836 continue;
4837
4838 if (flag_exceptions && !TREE_NOTHROW (decl))
4839 continue;
4840
4841 if (TREE_CODE (TREE_TYPE (decl)) != FUNCTION_TYPE
4842 || !types_compatible_p (TREE_TYPE (TREE_TYPE (decl)),
4843 TREE_TYPE (TREE_TYPE (built_in))))
4844 continue;
4845
4846 gimple_call_set_fndecl (call, built_in);
4847 }
4848 }
4849 }
4850
4851 /* Callback for expand_omp_build_assign. Return non-NULL if *tp needs to be
4852 regimplified. */
4853
4854 static tree
4855 expand_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
4870 /* Prepend TO = FROM assignment before *GSI_P. */
4871
4872 static void
4873 expand_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
4888 /* Expand the OpenMP parallel or task directive starting at REGION. */
4889
4890 static void
4891 expand_omp_taskreg (struct omp_region *region)
4892 {
4893 basic_block entry_bb, exit_bb, new_bb;
4894 struct function *child_cfun;
4895 tree child_fn, block, t;
4896 gimple_stmt_iterator gsi;
4897 gimple entry_stmt, stmt;
4898 edge e;
4899 vec<tree, va_gc> *ws_args;
4900
4901 entry_stmt = last_stmt (region->entry);
4902 child_fn = gimple_omp_taskreg_child_fn (entry_stmt);
4903 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
4904
4905 entry_bb = region->entry;
4906 exit_bb = region->exit;
4907
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))
4920 ws_args = region->ws_args;
4921 else
4922 ws_args = NULL;
4923
4924 if (child_cfun->cfg)
4925 {
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;
4930
4931 entry_succ_e = single_succ_edge (entry_bb);
4932
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);
4937
4938 new_bb = entry_bb;
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 }
4944 remove_edge_and_dominated_blocks (entry_succ_e);
4945 }
4946 else
4947 {
4948 unsigned srcidx, dstidx, num;
4949
4950 /* If the parallel region needs data sent from the parent
4951 function, then the very first statement (except possible
4952 tree profile counter updates) of the parallel body
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. */
4963 if (gimple_omp_taskreg_data_arg (entry_stmt))
4964 {
4965 basic_block entry_succ_bb = single_succ (entry_bb);
4966 tree arg, narg;
4967 gimple parcopy_stmt = NULL;
4968
4969 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
4970 {
4971 gimple stmt;
4972
4973 gcc_assert (!gsi_end_p (gsi));
4974 stmt = gsi_stmt (gsi);
4975 if (gimple_code (stmt) != GIMPLE_ASSIGN)
4976 continue;
4977
4978 if (gimple_num_ops (stmt) == 2)
4979 {
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 }
4992 }
4993 }
4994
4995 gcc_assert (parcopy_stmt != NULL);
4996 arg = DECL_ARGUMENTS (child_fn);
4997
4998 if (!gimple_in_ssa_p (cfun))
4999 {
5000 if (gimple_assign_lhs (parcopy_stmt) == arg)
5001 gsi_remove (&gsi, true);
5002 else
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 }
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. */
5014 gcc_assert (ssa_default_def (cfun, arg) == NULL);
5015 narg = make_ssa_name (arg, gimple_build_nop ());
5016 set_ssa_default_def (cfun, arg, narg);
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);
5020 update_stmt (parcopy_stmt);
5021 }
5022 }
5023
5024 /* Declare local variables needed in CHILD_CFUN. */
5025 block = DECL_INITIAL (child_fn);
5026 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
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. */
5030 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
5031 if (TREE_CODE (t) == VAR_DECL
5032 && TREE_STATIC (t)
5033 && !DECL_EXTERNAL (t))
5034 varpool_node::finalize_decl (t);
5035 DECL_SAVED_TREE (child_fn) = NULL;
5036 /* We'll create a CFG for child_fn, so no gimple body is needed. */
5037 gimple_set_body (child_fn, NULL);
5038 TREE_USED (block) = 1;
5039
5040 /* Reset DECL_CONTEXT on function arguments. */
5041 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
5042 DECL_CONTEXT (t) = child_fn;
5043
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);
5052 entry_bb = e->dest;
5053 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
5054
5055 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
5056 if (exit_bb)
5057 {
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);
5064 }
5065
5066 /* Move the parallel region into CHILD_CFUN. */
5067
5068 if (gimple_in_ssa_p (cfun))
5069 {
5070 init_tree_ssa (child_cfun);
5071 init_ssa_operands (child_cfun);
5072 child_cfun->gimple_df->in_ssa_p = true;
5073 block = NULL_TREE;
5074 }
5075 else
5076 block = gimple_block (entry_stmt);
5077
5078 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
5079 if (exit_bb)
5080 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
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;
5085
5086 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
5087 num = vec_safe_length (child_cfun->local_decls);
5088 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
5089 {
5090 t = (*child_cfun->local_decls)[srcidx];
5091 if (DECL_CONTEXT (t) == cfun->decl)
5092 continue;
5093 if (srcidx != dstidx)
5094 (*child_cfun->local_decls)[dstidx] = t;
5095 dstidx++;
5096 }
5097 if (dstidx != num)
5098 vec_safe_truncate (child_cfun->local_decls, dstidx);
5099
5100 /* Inform the callgraph about the new function. */
5101 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
5102 cgraph_node::add_new_function (child_fn, true);
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);
5107 if (optimize)
5108 optimize_omp_library_calls (entry_stmt);
5109 cgraph_edge::rebuild_edges ();
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;
5118 bool changed = false;
5119
5120 FOR_EACH_BB_FN (bb, cfun)
5121 changed |= gimple_purge_dead_eh_edges (bb);
5122 if (changed)
5123 cleanup_tree_cfg ();
5124 }
5125 if (gimple_in_ssa_p (cfun))
5126 update_ssa (TODO_update_ssa);
5127 pop_cfun ();
5128 }
5129
5130 /* Emit a library call to launch the children threads. */
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)
5134 expand_parallel_call (region, new_bb, entry_stmt, ws_args);
5135 else
5136 expand_task_call (new_bb, entry_stmt);
5137 if (gimple_in_ssa_p (cfun))
5138 update_ssa (TODO_update_ssa_only_virtuals);
5139 }
5140
5141
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;
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. */
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
5195 static void
5196 expand_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
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
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);
5264 add_bb_to_loop (zero_iter_bb, entry_bb->loop_father);
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;
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. */
5337
5338 static void
5339 expand_omp_for_init_vars (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
5340 tree *counts, gimple inner_stmt, tree startvar)
5341 {
5342 int i;
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
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
5430 static basic_block
5431 extract_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);
5447 add_bb_to_loop (bb, last_bb->loop_father);
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
5505 /* A subroutine of expand_omp_for. Generate code for a parallel
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);
5513 if (more) goto L0; else goto L3;
5514 L0:
5515 V = istart0;
5516 iend = iend0;
5517 L1:
5518 BODY;
5519 V += STEP;
5520 if (V cond iend) goto L1; else goto L2;
5521 L2:
5522 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
5523 L3:
5524
5525 If this is a combined omp parallel loop, instead of the call to
5526 GOMP_loop_foo_start, we call GOMP_loop_foo_next.
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.
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
5541 if (__builtin_expect (N32 cond3 N31, 0)) goto Z0;
5542 if (cond3 is <)
5543 adj = STEP3 - 1;
5544 else
5545 adj = STEP3 + 1;
5546 count3 = (adj + N32 - N31) / STEP3;
5547 if (__builtin_expect (N22 cond2 N21, 0)) goto Z0;
5548 if (cond2 is <)
5549 adj = STEP2 - 1;
5550 else
5551 adj = STEP2 + 1;
5552 count2 = (adj + N22 - N21) / STEP2;
5553 if (__builtin_expect (N12 cond1 N11, 0)) goto Z0;
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;
5560 goto Z1;
5561 Z0:
5562 count = 0;
5563 Z1:
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 */
5595
5596 static void
5597 expand_omp_for_generic (struct omp_region *region,
5598 struct omp_for_data *fd,
5599 enum built_in_function start_fn,
5600 enum built_in_function next_fn,
5601 gimple inner_stmt)
5602 {
5603 tree type, istart0, iend0, iend;
5604 tree t, vmain, vback, bias = NULL_TREE;
5605 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, collapse_bb;
5606 basic_block l2_bb = NULL, l3_bb = NULL;
5607 gimple_stmt_iterator gsi;
5608 gimple stmt;
5609 bool in_combined_parallel = is_combined_parallel (region);
5610 bool broken_loop = region->cont == NULL;
5611 edge e, ne;
5612 tree *counts = NULL;
5613 int i;
5614
5615 gcc_assert (!broken_loop || !in_combined_parallel);
5616 gcc_assert (fd->iter_type == long_integer_type_node
5617 || !in_combined_parallel);
5618
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");
5622 TREE_ADDRESSABLE (istart0) = 1;
5623 TREE_ADDRESSABLE (iend0) = 1;
5624
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
5648 entry_bb = region->entry;
5649 cont_bb = region->cont;
5650 collapse_bb = NULL;
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)
5657 {
5658 l2_bb = create_empty_bb (cont_bb);
5659 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l1_bb);
5660 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
5661 }
5662 else
5663 l2_bb = NULL;
5664 l3_bb = BRANCH_EDGE (entry_bb)->dest;
5665 exit_bb = region->exit;
5666
5667 gsi = gsi_last_bb (entry_bb);
5668
5669 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
5670 if (fd->collapse > 1)
5671 {
5672 int first_zero_iter = -1;
5673 basic_block zero_iter_bb = NULL, l2_dom_bb = NULL;
5674
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);
5679
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 }
5697 }
5698 if (in_combined_parallel)
5699 {
5700 /* In a combined parallel loop, emit a call to
5701 GOMP_loop_foo_next. */
5702 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
5703 build_fold_addr_expr (istart0),
5704 build_fold_addr_expr (iend0));
5705 }
5706 else
5707 {
5708 tree t0, t1, t2, t3, t4;
5709 /* If this is not a combined parallel loop, emit a call to
5710 GOMP_loop_foo_start in ENTRY_BB. */
5711 t4 = build_fold_addr_expr (iend0);
5712 t3 = build_fold_addr_expr (istart0);
5713 t2 = fold_convert (fd->iter_type, fd->loop.step);
5714 t1 = fd->loop.n2;
5715 t0 = fd->loop.n1;
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 }
5727 if (POINTER_TYPE_P (TREE_TYPE (t0))
5728 && TYPE_PRECISION (TREE_TYPE (t0))
5729 != TYPE_PRECISION (fd->iter_type))
5730 {
5731 /* Avoid casting pointers to integer of a different size. */
5732 tree itype = signed_type_for (type);
5733 t1 = fold_convert (fd->iter_type, fold_convert (itype, t1));
5734 t0 = fold_convert (fd->iter_type, fold_convert (itype, t0));
5735 }
5736 else
5737 {
5738 t1 = fold_convert (fd->iter_type, t1);
5739 t0 = fold_convert (fd->iter_type, t0);
5740 }
5741 if (bias)
5742 {
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);
5751 t = build_call_expr (builtin_decl_explicit (start_fn),
5752 6, t0, t1, t2, t, t3, t4);
5753 }
5754 else
5755 t = build_call_expr (builtin_decl_explicit (start_fn),
5756 5, t0, t1, t2, t3, t4);
5757 }
5758 else
5759 {
5760 tree t5;
5761 tree c_bool_type;
5762 tree bfn_decl;
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. */
5768 bfn_decl = builtin_decl_explicit (start_fn);
5769 c_bool_type = TREE_TYPE (TREE_TYPE (bfn_decl));
5770 t5 = build_int_cst (c_bool_type,
5771 fd->loop.cond_code == LT_EXPR ? 1 : 0);
5772 if (fd->chunk_size)
5773 {
5774 tree bfn_decl = builtin_decl_explicit (start_fn);
5775 t = fold_convert (fd->iter_type, fd->chunk_size);
5776 t = build_call_expr (bfn_decl, 7, t5, t0, t1, t2, t, t3, t4);
5777 }
5778 else
5779 t = build_call_expr (builtin_decl_explicit (start_fn),
5780 6, t5, t0, t1, t2, t3, t4);
5781 }
5782 }
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));
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);
5789
5790 /* Remove the GIMPLE_OMP_FOR statement. */
5791 gsi_remove (&gsi, true);
5792
5793 /* Iteration setup for sequential loop goes in L0_BB. */
5794 tree startvar = fd->loop.v;
5795 tree endvar = NULL_TREE;
5796
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
5812 gsi = gsi_start_bb (l0_bb);
5813 t = istart0;
5814 if (bias)
5815 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
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);
5819 t = force_gimple_operand_gsi (&gsi, t,
5820 DECL_P (startvar)
5821 && TREE_ADDRESSABLE (startvar),
5822 NULL_TREE, false, GSI_CONTINUE_LINKING);
5823 stmt = gimple_build_assign (startvar, t);
5824 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5825
5826 t = iend0;
5827 if (bias)
5828 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
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);
5832 iend = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5833 false, GSI_CONTINUE_LINKING);
5834 if (endvar)
5835 {
5836 stmt = gimple_build_assign (endvar, iend);
5837 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
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);
5844 }
5845 if (fd->collapse > 1)
5846 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
5847
5848 if (!broken_loop)
5849 {
5850 /* Code to control the increment and predicate for the sequential
5851 loop goes in the CONT_BB. */
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);
5857
5858 if (!gimple_omp_for_combined_p (fd->for_stmt))
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 }
5877
5878 /* Remove GIMPLE_OMP_CONTINUE. */
5879 gsi_remove (&gsi, true);
5880
5881 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
5882 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, l1_bb);
5883
5884 /* Emit code to get the next parallel iteration in L2_BB. */
5885 gsi = gsi_start_bb (l2_bb);
5886
5887 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
5888 build_fold_addr_expr (istart0),
5889 build_fold_addr_expr (iend0));
5890 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5891 false, GSI_CONTINUE_LINKING);
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));
5895 stmt = gimple_build_cond_empty (t);
5896 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5897 }
5898
5899 /* Add the loop cleanup function. */
5900 gsi = gsi_last_bb (exit_bb);
5901 if (gimple_omp_return_nowait_p (gsi_stmt (gsi)))
5902 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_NOWAIT);
5903 else if (gimple_omp_return_lhs (gsi_stmt (gsi)))
5904 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_CANCEL);
5905 else
5906 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END);
5907 stmt = gimple_build_call (t, 0);
5908 if (gimple_omp_return_lhs (gsi_stmt (gsi)))
5909 gimple_call_set_lhs (stmt, gimple_omp_return_lhs (gsi_stmt (gsi)));
5910 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
5911 gsi_remove (&gsi, true);
5912
5913 /* Connect the new blocks. */
5914 find_edge (entry_bb, l0_bb)->flags = EDGE_TRUE_VALUE;
5915 find_edge (entry_bb, l3_bb)->flags = EDGE_FALSE_VALUE;
5916
5917 if (!broken_loop)
5918 {
5919 gimple_seq phis;
5920
5921 e = find_edge (cont_bb, l3_bb);
5922 ne = make_edge (l2_bb, l3_bb, EDGE_FALSE_VALUE);
5923
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 }
5931 remove_edge (e);
5932
5933 make_edge (cont_bb, l2_bb, EDGE_FALSE_VALUE);
5934 add_bb_to_loop (l2_bb, cont_bb->loop_father);
5935 e = find_edge (cont_bb, l1_bb);
5936 if (gimple_omp_for_combined_p (fd->for_stmt))
5937 {
5938 remove_edge (e);
5939 e = NULL;
5940 }
5941 else if (fd->collapse > 1)
5942 {
5943 remove_edge (e);
5944 e = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
5945 }
5946 else
5947 e->flags = EDGE_TRUE_VALUE;
5948 if (e)
5949 {
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;
5957 }
5958 make_edge (l2_bb, l0_bb, EDGE_TRUE_VALUE);
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));
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
5974 if (!gimple_omp_for_combined_p (fd->for_stmt))
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 }
5981 }
5982 }
5983
5984
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:
5988
5989 for (V = N1; V cond N2; V += STEP) BODY;
5990
5991 where COND is "<" or ">", we generate pseudocode
5992
5993 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
5994 if (cond is <)
5995 adj = STEP - 1;
5996 else
5997 adj = STEP + 1;
5998 if ((__typeof (V)) -1 > 0 && cond is >)
5999 n = -(adj + N2 - N1) / -STEP;
6000 else
6001 n = (adj + N2 - N1) / STEP;
6002 q = n / nthreads;
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;
6011 V = s0 * STEP + N1;
6012 if (s0 >= e0) goto L2; else goto L0;
6013 L0:
6014 e = e0 * STEP + N1;
6015 L1:
6016 BODY;
6017 V += STEP;
6018 if (V cond e) goto L1;
6019 L2:
6020 */
6021
6022 static void
6023 expand_omp_for_static_nochunk (struct omp_region *region,
6024 struct omp_for_data *fd,
6025 gimple inner_stmt)
6026 {
6027 tree n, q, s0, e0, e, t, tt, nthreads, threadid;
6028 tree type, itype, vmain, vback;
6029 basic_block entry_bb, second_bb, third_bb, exit_bb, seq_start_bb;
6030 basic_block body_bb, cont_bb, collapse_bb = NULL;
6031 basic_block fin_bb;
6032 gimple_stmt_iterator gsi;
6033 gimple stmt;
6034 edge ep;
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;
6040
6041 itype = type = TREE_TYPE (fd->loop.v);
6042 if (POINTER_TYPE_P (type))
6043 itype = signed_type_for (type);
6044
6045 entry_bb = region->entry;
6046 cont_bb = region->cont;
6047 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
6048 fin_bb = BRANCH_EDGE (entry_bb)->dest;
6049 gcc_assert (broken_loop
6050 || (fin_bb == FALLTHRU_EDGE (cont_bb)->dest));
6051 seq_start_bb = split_edge (FALLTHRU_EDGE (entry_bb));
6052 body_bb = single_succ (seq_start_bb);
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 }
6058 exit_bb = region->exit;
6059
6060 /* Iteration space partitioning goes in ENTRY_BB. */
6061 gsi = gsi_last_bb (entry_bb);
6062 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6063
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)
6089 && (t == NULL_TREE || !integer_onep (t)))
6090 {
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
6128 t = build_call_expr (builtin_decl_explicit (get_num_threads), 0);
6129 t = fold_convert (itype, t);
6130 nthreads = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6131 true, GSI_SAME_STMT);
6132
6133 t = build_call_expr (builtin_decl_explicit (get_thread_num), 0);
6134 t = fold_convert (itype, t);
6135 threadid = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6136 true, GSI_SAME_STMT);
6137
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);
6158
6159 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
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));
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),
6166 fold_build1 (NEGATE_EXPR, itype, step));
6167 else
6168 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
6169 t = fold_convert (itype, t);
6170 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
6171
6172 q = create_tmp_reg (itype, "q");
6173 t = fold_build2 (TRUNC_DIV_EXPR, itype, n, nthreads);
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
6177 tt = create_tmp_reg (itype, "tt");
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);
6181
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);
6199
6200 t = build2 (MULT_EXPR, itype, q, threadid);
6201 t = build2 (PLUS_EXPR, itype, t, tt);
6202 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
6203
6204 t = fold_build2 (PLUS_EXPR, itype, s0, q);
6205 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
6206
6207 t = build2 (GE_EXPR, boolean_type_node, s0, e0);
6208 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
6209
6210 /* Remove the GIMPLE_OMP_FOR statement. */
6211 gsi_remove (&gsi, true);
6212
6213 /* Setup code for sequential iteration goes in SEQ_START_BB. */
6214 gsi = gsi_start_bb (seq_start_bb);
6215
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 }
6232 t = fold_convert (itype, s0);
6233 t = fold_build2 (MULT_EXPR, itype, t, step);
6234 if (POINTER_TYPE_P (type))
6235 t = fold_build_pointer_plus (n1, t);
6236 else
6237 t = fold_build2 (PLUS_EXPR, type, t, n1);
6238 t = fold_convert (TREE_TYPE (startvar), t);
6239 t = force_gimple_operand_gsi (&gsi, t,
6240 DECL_P (startvar)
6241 && TREE_ADDRESSABLE (startvar),
6242 NULL_TREE, false, GSI_CONTINUE_LINKING);
6243 stmt = gimple_build_assign (startvar, t);
6244 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
6245
6246 t = fold_convert (itype, e0);
6247 t = fold_build2 (MULT_EXPR, itype, t, step);
6248 if (POINTER_TYPE_P (type))
6249 t = fold_build_pointer_plus (n1, t);
6250 else
6251 t = fold_build2 (PLUS_EXPR, type, t, n1);
6252 t = fold_convert (TREE_TYPE (startvar), t);
6253 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6254 false, GSI_CONTINUE_LINKING);
6255 if (endvar)
6256 {
6257 stmt = gimple_build_assign (endvar, e);
6258 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
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);
6265 }
6266 if (fd->collapse > 1)
6267 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
6268
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);
6278
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);
6291
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 }
6297
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 }
6304
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)))
6308 {
6309 t = gimple_omp_return_lhs (gsi_stmt (gsi));
6310 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
6311 }
6312 gsi_remove (&gsi, true);
6313
6314 /* Connect all the blocks. */
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;
6322
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 }
6341
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);
6345
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));
6350
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 }
6359 }
6360
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:
6365
6366 for (V = N1; V cond N2; V += STEP) BODY;
6367
6368 where COND is "<" or ">", we generate pseudocode
6369
6370 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
6371 if (cond is <)
6372 adj = STEP - 1;
6373 else
6374 adj = STEP + 1;
6375 if ((__typeof (V)) -1 > 0 && cond is >)
6376 n = -(adj + N2 - N1) / -STEP;
6377 else
6378 n = (adj + N2 - N1) / STEP;
6379 trip = 0;
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
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:
6398 */
6399
6400 static void
6401 expand_omp_for_static_chunk (struct omp_region *region,
6402 struct omp_for_data *fd, gimple inner_stmt)
6403 {
6404 tree n, s0, e0, e, t;
6405 tree trip_var, trip_init, trip_main, trip_back, nthreads, threadid;
6406 tree type, itype, vmain, vback, vextra;
6407 basic_block entry_bb, exit_bb, body_bb, seq_start_bb, iter_part_bb;
6408 basic_block trip_update_bb = NULL, cont_bb, collapse_bb = NULL, fin_bb;
6409 gimple_stmt_iterator gsi;
6410 gimple stmt;
6411 edge se;
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;
6417
6418 itype = type = TREE_TYPE (fd->loop.v);
6419 if (POINTER_TYPE_P (type))
6420 itype = signed_type_for (type);
6421
6422 entry_bb = region->entry;
6423 se = split_block (entry_bb, last_stmt (entry_bb));
6424 entry_bb = se->src;
6425 iter_part_bb = se->dest;
6426 cont_bb = region->cont;
6427 gcc_assert (EDGE_COUNT (iter_part_bb->succs) == 2);
6428 fin_bb = BRANCH_EDGE (iter_part_bb)->dest;
6429 gcc_assert (broken_loop
6430 || fin_bb == FALLTHRU_EDGE (cont_bb)->dest);
6431 seq_start_bb = split_edge (FALLTHRU_EDGE (iter_part_bb));
6432 body_bb = single_succ (seq_start_bb);
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 }
6439 exit_bb = region->exit;
6440
6441 /* Trip and adjustment setup goes in ENTRY_BB. */
6442 gsi = gsi_last_bb (entry_bb);
6443 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6444
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);
6457 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
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)
6470 && (t == NULL_TREE || !integer_onep (t)))
6471 {
6472 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
6473 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
6474 true, GSI_SAME_STMT);
6475 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
6476 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
6477 true, GSI_SAME_STMT);
6478 stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
6479 NULL_TREE, NULL_TREE);
6480 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
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 {
6486 gsi = gsi_for_stmt (stmt);
6487 gimple_regimplify_operands (stmt, &gsi);
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;
6498 for (gsi = gsi_start_phis (fin_bb);
6499 !gsi_end_p (gsi); gsi_next (&gsi))
6500 {
6501 gimple phi = gsi_stmt (gsi);
6502 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
6503 se, UNKNOWN_LOCATION);
6504 }
6505 }
6506 gsi = gsi_last_bb (entry_bb);
6507 }
6508
6509 t = build_call_expr (builtin_decl_explicit (get_num_threads), 0);
6510 t = fold_convert (itype, t);
6511 nthreads = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6512 true, GSI_SAME_STMT);
6513
6514 t = build_call_expr (builtin_decl_explicit (get_thread_num), 0);
6515 t = fold_convert (itype, t);
6516 threadid = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6517 true, GSI_SAME_STMT);
6518
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 }
6533 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
6534 true, NULL_TREE, true, GSI_SAME_STMT);
6535 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
6536 true, NULL_TREE, true, GSI_SAME_STMT);
6537 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
6538 true, NULL_TREE, true, GSI_SAME_STMT);
6539 fd->chunk_size
6540 = force_gimple_operand_gsi (&gsi, fold_convert (itype, fd->chunk_size),
6541 true, NULL_TREE, true, GSI_SAME_STMT);
6542
6543 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
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));
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),
6550 fold_build1 (NEGATE_EXPR, itype, step));
6551 else
6552 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
6553 t = fold_convert (itype, t);
6554 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6555 true, GSI_SAME_STMT);
6556
6557 trip_var = create_tmp_reg (itype, ".trip");
6558 if (gimple_in_ssa_p (cfun))
6559 {
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);
6563 }
6564 else
6565 {
6566 trip_init = trip_var;
6567 trip_main = trip_var;
6568 trip_back = trip_var;
6569 }
6570
6571 stmt = gimple_build_assign (trip_init, build_int_cst (itype, 0));
6572 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
6573
6574 t = fold_build2 (MULT_EXPR, itype, threadid, fd->chunk_size);
6575 t = fold_build2 (MULT_EXPR, itype, t, step);
6576 if (POINTER_TYPE_P (type))
6577 t = fold_build_pointer_plus (n1, t);
6578 else
6579 t = fold_build2 (PLUS_EXPR, type, t, n1);
6580 vextra = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6581 true, GSI_SAME_STMT);
6582
6583 /* Remove the GIMPLE_OMP_FOR. */
6584 gsi_remove (&gsi, true);
6585
6586 /* Iteration space partitioning goes in ITER_PART_BB. */
6587 gsi = gsi_last_bb (iter_part_bb);
6588
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);
6592 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6593 false, GSI_CONTINUE_LINKING);
6594
6595 t = fold_build2 (PLUS_EXPR, itype, s0, fd->chunk_size);
6596 t = fold_build2 (MIN_EXPR, itype, t, n);
6597 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6598 false, GSI_CONTINUE_LINKING);
6599
6600 t = build2 (LT_EXPR, boolean_type_node, s0, n);
6601 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_CONTINUE_LINKING);
6602
6603 /* Setup code for sequential iteration goes in SEQ_START_BB. */
6604 gsi = gsi_start_bb (seq_start_bb);
6605
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
6623 t = fold_convert (itype, s0);
6624 t = fold_build2 (MULT_EXPR, itype, t, step);
6625 if (POINTER_TYPE_P (type))
6626 t = fold_build_pointer_plus (n1, t);
6627 else
6628 t = fold_build2 (PLUS_EXPR, type, t, n1);
6629 t = fold_convert (TREE_TYPE (startvar), t);
6630 t = force_gimple_operand_gsi (&gsi, t,
6631 DECL_P (startvar)
6632 && TREE_ADDRESSABLE (startvar),
6633 NULL_TREE, false, GSI_CONTINUE_LINKING);
6634 stmt = gimple_build_assign (startvar, t);
6635 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
6636
6637 t = fold_convert (itype, e0);
6638 t = fold_build2 (MULT_EXPR, itype, t, step);
6639 if (POINTER_TYPE_P (type))
6640 t = fold_build_pointer_plus (n1, t);
6641 else
6642 t = fold_build2 (PLUS_EXPR, type, t, n1);
6643 t = fold_convert (TREE_TYPE (startvar), t);
6644 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6645 false, GSI_CONTINUE_LINKING);
6646 if (endvar)
6647 {
6648 stmt = gimple_build_assign (endvar, e);
6649 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
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);
6655 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
6656 }
6657 if (fd->collapse > 1)
6658 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
6659
6660 if (!broken_loop)
6661 {
6662 /* The code controlling the sequential loop goes in CONT_BB,
6663 replacing the GIMPLE_OMP_CONTINUE. */
6664 gsi = gsi_last_bb (cont_bb);
6665 stmt = gsi_stmt (gsi);
6666 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
6667 vmain = gimple_omp_continue_control_use (stmt);
6668 vback = gimple_omp_continue_control_def (stmt);
6669
6670 if (!gimple_omp_for_combined_p (fd->for_stmt))
6671 {
6672 if (POINTER_TYPE_P (type))
6673 t = fold_build_pointer_plus (vmain, step);
6674 else
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,
6678 true, GSI_SAME_STMT);
6679 stmt = gimple_build_assign (vback, t);
6680 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
6681
6682 t = build2 (fd->loop.cond_code, boolean_type_node,
6683 DECL_P (vback) && TREE_ADDRESSABLE (vback)
6684 ? t : vback, e);
6685 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
6686 }
6687
6688 /* Remove GIMPLE_OMP_CONTINUE. */
6689 gsi_remove (&gsi, true);
6690
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);
6693
6694 /* Trip update code goes into TRIP_UPDATE_BB. */
6695 gsi = gsi_start_bb (trip_update_bb);
6696
6697 t = build_int_cst (itype, 1);
6698 t = build2 (PLUS_EXPR, itype, trip_main, t);
6699 stmt = gimple_build_assign (trip_back, t);
6700 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
6701 }
6702
6703 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
6704 gsi = gsi_last_bb (exit_bb);
6705 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
6706 {
6707 t = gimple_omp_return_lhs (gsi_stmt (gsi));
6708 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
6709 }
6710 gsi_remove (&gsi, true);
6711
6712 /* Connect the new blocks. */
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;
6715
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;
6733
6734 redirect_edge_and_branch (single_succ_edge (trip_update_bb), iter_part_bb);
6735 }
6736
6737 if (gimple_in_ssa_p (cfun))
6738 {
6739 gimple_stmt_iterator psi;
6740 gimple phi;
6741 edge re, ene;
6742 edge_var_map *vm;
6743 size_t i;
6744
6745 gcc_assert (fd->collapse == 1 && !broken_loop);
6746
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);
6752 vec<edge_var_map> *head = redirect_edge_var_map_vector (re);
6753 ene = single_succ_edge (entry_bb);
6754
6755 psi = gsi_start_phis (fin_bb);
6756 for (i = 0; !gsi_end_p (psi) && head->iterate (i, &vm);
6757 gsi_next (&psi), ++i)
6758 {
6759 gimple nphi;
6760 source_location locus;
6761
6762 phi = gsi_stmt (psi);
6763 t = gimple_phi_result (phi);
6764 gcc_assert (t == redirect_edge_var_map_result (vm));
6765 nphi = create_phi_node (t, iter_part_bb);
6766
6767 t = PHI_ARG_DEF_FROM_EDGE (phi, se);
6768 locus = gimple_phi_arg_location_from_edge (phi, se);
6769
6770 /* A special case -- fd->loop.v is not yet computed in
6771 iter_part_bb, we need to use vextra instead. */
6772 if (t == fd->loop.v)
6773 t = vextra;
6774 add_phi_arg (nphi, t, ene, locus);
6775 locus = redirect_edge_var_map_location (vm);
6776 add_phi_arg (nphi, redirect_edge_var_map_def (vm), re, locus);
6777 }
6778 gcc_assert (!gsi_end_p (psi) && i == head->length ());
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);
6786 }
6787
6788 /* Make phi node for trip. */
6789 phi = create_phi_node (trip_main, iter_part_bb);
6790 add_phi_arg (phi, trip_back, single_succ_edge (trip_update_bb),
6791 UNKNOWN_LOCATION);
6792 add_phi_arg (phi, trip_init, single_succ_edge (entry_bb),
6793 UNKNOWN_LOCATION);
6794 }
6795
6796 if (!broken_loop)
6797 set_immediate_dominator (CDI_DOMINATORS, trip_update_bb, cont_bb);
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));
6806
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);
6813
6814 if (!gimple_omp_for_combined_p (fd->for_stmt))
6815 {
6816 struct loop *loop = alloc_loop ();
6817 loop->header = body_bb;
6818 if (collapse_bb == NULL)
6819 loop->latch = cont_bb;
6820 add_loop (loop, trip_loop);
6821 }
6822 }
6823 }
6824
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
6846 static void
6847 expand_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 }
7010
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
7071 static void
7072 expand_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_);
7086 tree n1, n2;
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
7129 n1 = fd->loop.n1;
7130 n2 = fd->loop.n2;
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 }
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;
7284 loop->latch = cont_bb;
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);
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)
7295 loop->safelen = INT_MAX;
7296 else
7297 loop->safelen = tree_to_uhwi (safelen);
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 }
7306 /* If not -fno-tree-loop-vectorize, hint that we want to vectorize
7307 the loop. */
7308 if ((flag_tree_loop_vectorize
7309 || (!global_options_set.x_flag_tree_loop_vectorize
7310 && !global_options_set.x_flag_tree_vectorize))
7311 && flag_tree_loop_optimize
7312 && loop->safelen > 1)
7313 {
7314 loop->force_vectorize = true;
7315 cfun->has_force_vectorize_loops = true;
7316 }
7317 }
7318 }
7319
7320
7321 /* Expand the OpenMP loop defined by REGION. */
7322
7323 static void
7324 expand_omp_for (struct omp_region *region, gimple inner_stmt)
7325 {
7326 struct omp_for_data fd;
7327 struct omp_for_data_loop *loops;
7328
7329 loops
7330 = (struct omp_for_data_loop *)
7331 alloca (gimple_omp_for_collapse (last_stmt (region->entry))
7332 * sizeof (struct omp_for_data_loop));
7333 extract_omp_for_data (last_stmt (region->entry), &fd, loops);
7334 region->sched_kind = fd.sched_kind;
7335
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 }
7345 else
7346 /* If there isn't a continue then this is a degerate case where
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);
7350
7351 if (gimple_omp_for_kind (fd.for_stmt) & GF_OMP_FOR_SIMD)
7352 expand_omp_simd (region, &fd);
7353 else if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_CILKFOR)
7354 expand_cilk_for (region, &fd);
7355 else if (fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
7356 && !fd.have_ordered)
7357 {
7358 if (fd.chunk_size == NULL)
7359 expand_omp_for_static_nochunk (region, &fd, inner_stmt);
7360 else
7361 expand_omp_for_static_chunk (region, &fd, inner_stmt);
7362 }
7363 else
7364 {
7365 int fn_index, start_ix, next_ix;
7366
7367 gcc_assert (gimple_omp_for_kind (fd.for_stmt)
7368 == GF_OMP_FOR_KIND_FOR);
7369 if (fd.chunk_size == NULL
7370 && fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
7371 fd.chunk_size = integer_zero_node;
7372 gcc_assert (fd.sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
7373 fn_index = (fd.sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
7374 ? 3 : fd.sched_kind;
7375 fn_index += fd.have_ordered * 4;
7376 start_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_START) + fn_index;
7377 next_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_NEXT) + fn_index;
7378 if (fd.iter_type == long_long_unsigned_type_node)
7379 {
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);
7384 }
7385 expand_omp_for_generic (region, &fd, (enum built_in_function) start_ix,
7386 (enum built_in_function) next_ix, inner_stmt);
7387 }
7388
7389 if (gimple_in_ssa_p (cfun))
7390 update_ssa (TODO_update_ssa_only_virtuals);
7391 }
7392
7393
7394 /* Expand code for an OpenMP sections directive. In pseudo code, we generate
7395
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 ...
7409 default:
7410 abort ();
7411 }
7412 L1:
7413 v = GOMP_sections_next ();
7414 goto L0;
7415 L2:
7416 reduction;
7417
7418 If this is a combined parallel sections, replace the call to
7419 GOMP_sections_start with call to GOMP_sections_next. */
7420
7421 static void
7422 expand_omp_sections (struct omp_region *region)
7423 {
7424 tree t, u, vin = NULL, vmain, vnext, l2;
7425 unsigned len;
7426 basic_block entry_bb, l0_bb, l1_bb, l2_bb, default_bb;
7427 gimple_stmt_iterator si, switch_si;
7428 gimple sections_stmt, stmt, cont;
7429 edge_iterator ei;
7430 edge e;
7431 struct omp_region *inner;
7432 unsigned i, casei;
7433 bool exit_reachable = region->cont != NULL;
7434
7435 gcc_assert (region->exit != NULL);
7436 entry_bb = region->entry;
7437 l0_bb = single_succ (entry_bb);
7438 l1_bb = region->cont;
7439 l2_bb = region->exit;
7440 if (single_pred_p (l2_bb) && single_pred (l2_bb) == l0_bb)
7441 l2 = gimple_block_label (l2_bb);
7442 else
7443 {
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);
7453 else
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)
7459 {
7460 l2 = gimple_block_label (e->dest);
7461 break;
7462 }
7463 }
7464 }
7465 if (exit_reachable)
7466 default_bb = create_empty_bb (l1_bb->prev_bb);
7467 else
7468 default_bb = create_empty_bb (l0_bb);
7469
7470 /* We will build a switch() with enough cases for all the
7471 GIMPLE_OMP_SECTION regions, a '0' case to handle the end of more work
7472 and a default case to abort if something goes wrong. */
7473 len = EDGE_COUNT (l0_bb->succs);
7474
7475 /* Use vec::quick_push on label_vec throughout, since we know the size
7476 in advance. */
7477 auto_vec<tree> label_vec (len);
7478
7479 /* The call to GOMP_sections_start goes in ENTRY_BB, replacing the
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);
7485 if (!is_combined_parallel (region))
7486 {
7487 /* If we are not inside a combined parallel+sections region,
7488 call GOMP_sections_start. */
7489 t = build_int_cst (unsigned_type_node, len - 1);
7490 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_START);
7491 stmt = gimple_build_call (u, 1, t);
7492 }
7493 else
7494 {
7495 /* Otherwise, call GOMP_sections_next. */
7496 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
7497 stmt = gimple_build_call (u, 0);
7498 }
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);
7507 if (exit_reachable)
7508 {
7509 cont = last_stmt (l1_bb);
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);
7513 }
7514 else
7515 {
7516 vmain = vin;
7517 vnext = NULL_TREE;
7518 }
7519
7520 t = build_case_label (build_int_cst (unsigned_type_node, 0), NULL, l2);
7521 label_vec.quick_push (t);
7522 i = 1;
7523
7524 /* Convert each GIMPLE_OMP_SECTION into a CASE_LABEL_EXPR. */
7525 for (inner = region->inner, casei = 1;
7526 inner;
7527 inner = inner->next, i++, casei++)
7528 {
7529 basic_block s_entry_bb, s_exit_bb;
7530
7531 /* Skip optional reduction region. */
7532 if (inner->type == GIMPLE_OMP_ATOMIC_LOAD)
7533 {
7534 --i;
7535 --casei;
7536 continue;
7537 }
7538
7539 s_entry_bb = inner->entry;
7540 s_exit_bb = inner->exit;
7541
7542 t = gimple_block_label (s_entry_bb);
7543 u = build_int_cst (unsigned_type_node, casei);
7544 u = build_case_label (u, NULL, t);
7545 label_vec.quick_push (u);
7546
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);
7551 single_succ_edge (s_entry_bb)->flags = EDGE_FALLTHRU;
7552
7553 if (s_exit_bb == NULL)
7554 continue;
7555
7556 si = gsi_last_bb (s_exit_bb);
7557 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
7558 gsi_remove (&si, true);
7559
7560 single_succ_edge (s_exit_bb)->flags = EDGE_FALLTHRU;
7561 }
7562
7563 /* Error handling code goes in DEFAULT_BB. */
7564 t = gimple_block_label (default_bb);
7565 u = build_case_label (NULL, NULL, t);
7566 make_edge (l0_bb, default_bb, 0);
7567 add_bb_to_loop (default_bb, current_loops->tree_root);
7568
7569 stmt = gimple_build_switch (vmain, u, label_vec);
7570 gsi_insert_after (&switch_si, stmt, GSI_SAME_STMT);
7571 gsi_remove (&switch_si, true);
7572
7573 si = gsi_start_bb (default_bb);
7574 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
7575 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
7576
7577 if (exit_reachable)
7578 {
7579 tree bfn_decl;
7580
7581 /* Code to get the next section goes in L1_BB. */
7582 si = gsi_last_bb (l1_bb);
7583 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CONTINUE);
7584
7585 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
7586 stmt = gimple_build_call (bfn_decl, 0);
7587 gimple_call_set_lhs (stmt, vnext);
7588 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
7589 gsi_remove (&si, true);
7590
7591 single_succ_edge (l1_bb)->flags = EDGE_FALLTHRU;
7592 }
7593
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);
7598 else if (gimple_omp_return_lhs (gsi_stmt (si)))
7599 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_CANCEL);
7600 else
7601 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END);
7602 stmt = gimple_build_call (t, 0);
7603 if (gimple_omp_return_lhs (gsi_stmt (si)))
7604 gimple_call_set_lhs (stmt, gimple_omp_return_lhs (gsi_stmt (si)));
7605 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
7606 gsi_remove (&si, true);
7607
7608 set_immediate_dominator (CDI_DOMINATORS, default_bb, l0_bb);
7609 }
7610
7611
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
7615 static void
7616 expand_omp_single (struct omp_region *region)
7617 {
7618 basic_block entry_bb, exit_bb;
7619 gimple_stmt_iterator si;
7620
7621 entry_bb = region->entry;
7622 exit_bb = region->exit;
7623
7624 si = gsi_last_bb (entry_bb);
7625 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE);
7626 gsi_remove (&si, true);
7627 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7628
7629 si = gsi_last_bb (exit_bb);
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 }
7635 gsi_remove (&si, true);
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. */
7643
7644 static void
7645 expand_omp_synch (struct omp_region *region)
7646 {
7647 basic_block entry_bb, exit_bb;
7648 gimple_stmt_iterator si;
7649
7650 entry_bb = region->entry;
7651 exit_bb = region->exit;
7652
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
7656 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TASKGROUP
7657 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ORDERED
7658 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CRITICAL
7659 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TEAMS);
7660 gsi_remove (&si, true);
7661 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7662
7663 if (exit_bb)
7664 {
7665 si = gsi_last_bb (exit_bb);
7666 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
7667 gsi_remove (&si, true);
7668 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
7669 }
7670 }
7671
7672 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
7673 operation as a normal volatile load. */
7674
7675 static bool
7676 expand_omp_atomic_load (basic_block load_bb, tree addr,
7677 tree loaded_val, int index)
7678 {
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,
7704 build_int_cst (NULL,
7705 gimple_omp_atomic_seq_cst_p (stmt)
7706 ? MEMMODEL_SEQ_CST
7707 : MEMMODEL_RELAXED));
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;
7724 }
7725
7726 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
7727 operation as a normal volatile store. */
7728
7729 static bool
7730 expand_omp_atomic_store (basic_block load_bb, tree addr,
7731 tree loaded_val, tree stored_val, int index)
7732 {
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;
7739 machine_mode imode;
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,
7779 build_int_cst (NULL,
7780 gimple_omp_atomic_seq_cst_p (stmt)
7781 ? MEMMODEL_SEQ_CST
7782 : MEMMODEL_RELAXED));
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;
7801 }
7802
7803 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
7804 operation as a __atomic_fetch_op builtin. INDEX is log2 of the
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
7808 static bool
7809 expand_omp_atomic_fetch_op (basic_block load_bb,
7810 tree addr, tree loaded_val,
7811 tree stored_val, int index)
7812 {
7813 enum built_in_function oldbase, newbase, tmpbase;
7814 tree decl, itype, call;
7815 tree lhs, rhs;
7816 basic_block store_bb = single_succ (load_bb);
7817 gimple_stmt_iterator gsi;
7818 gimple stmt;
7819 location_t loc;
7820 enum tree_code code;
7821 bool need_old, need_new;
7822 machine_mode imode;
7823 bool seq_cst;
7824
7825 /* We expect to find the following sequences:
7826
7827 load_bb:
7828 GIMPLE_OMP_ATOMIC_LOAD (tmp, mem)
7829
7830 store_bb:
7831 val = tmp OP something; (or: something OP tmp)
7832 GIMPLE_OMP_STORE (val)
7833
7834 ???FIXME: Allow a more flexible sequence.
7835 Perhaps use data flow to pick the statements.
7836
7837 */
7838
7839 gsi = gsi_after_labels (store_bb);
7840 stmt = gsi_stmt (gsi);
7841 loc = gimple_location (stmt);
7842 if (!is_gimple_assign (stmt))
7843 return false;
7844 gsi_next (&gsi);
7845 if (gimple_code (gsi_stmt (gsi)) != GIMPLE_OMP_ATOMIC_STORE)
7846 return false;
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));
7849 seq_cst = gimple_omp_atomic_seq_cst_p (last_stmt (load_bb));
7850 gcc_checking_assert (!need_old || !need_new);
7851
7852 if (!operand_equal_p (gimple_assign_lhs (stmt), stored_val, 0))
7853 return false;
7854
7855 /* Check for one of the supported fetch-op operations. */
7856 code = gimple_assign_rhs_code (stmt);
7857 switch (code)
7858 {
7859 case PLUS_EXPR:
7860 case POINTER_PLUS_EXPR:
7861 oldbase = BUILT_IN_ATOMIC_FETCH_ADD_N;
7862 newbase = BUILT_IN_ATOMIC_ADD_FETCH_N;
7863 break;
7864 case MINUS_EXPR:
7865 oldbase = BUILT_IN_ATOMIC_FETCH_SUB_N;
7866 newbase = BUILT_IN_ATOMIC_SUB_FETCH_N;
7867 break;
7868 case BIT_AND_EXPR:
7869 oldbase = BUILT_IN_ATOMIC_FETCH_AND_N;
7870 newbase = BUILT_IN_ATOMIC_AND_FETCH_N;
7871 break;
7872 case BIT_IOR_EXPR:
7873 oldbase = BUILT_IN_ATOMIC_FETCH_OR_N;
7874 newbase = BUILT_IN_ATOMIC_OR_FETCH_N;
7875 break;
7876 case BIT_XOR_EXPR:
7877 oldbase = BUILT_IN_ATOMIC_FETCH_XOR_N;
7878 newbase = BUILT_IN_ATOMIC_XOR_FETCH_N;
7879 break;
7880 default:
7881 return false;
7882 }
7883
7884 /* Make sure the expression is of the proper form. */
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);
7890 else
7891 return false;
7892
7893 tmpbase = ((enum built_in_function)
7894 ((need_new ? newbase : oldbase) + index + 1));
7895 decl = builtin_decl_explicit (tmpbase);
7896 if (decl == NULL_TREE)
7897 return false;
7898 itype = TREE_TYPE (TREE_TYPE (decl));
7899 imode = TYPE_MODE (itype);
7900
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. */
7905 if (!can_compare_and_swap_p (imode, true))
7906 return false;
7907
7908 gsi = gsi_last_bb (load_bb);
7909 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_LOAD);
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),
7916 build_int_cst (NULL,
7917 seq_cst ? MEMMODEL_SEQ_CST
7918 : MEMMODEL_RELAXED));
7919
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);
7928 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
7929 gsi_remove (&gsi, true);
7930
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);
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
7955 static bool
7956 expand_omp_atomic_pipeline (basic_block load_bb, basic_block store_bb,
7957 tree addr, tree loaded_val, tree stored_val,
7958 int index)
7959 {
7960 tree loadedi, storedi, initial, new_storedi, old_vali;
7961 tree type, itype, cmpxchg, iaddr;
7962 gimple_stmt_iterator si;
7963 basic_block loop_header = single_succ (load_bb);
7964 gimple phi, stmt;
7965 edge e;
7966 enum built_in_function fncode;
7967
7968 /* ??? We need a non-pointer interface to __atomic_compare_exchange in
7969 order to use the RELAXED memory model effectively. */
7970 fncode = (enum built_in_function)((int)BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_N
7971 + index + 1);
7972 cmpxchg = builtin_decl_explicit (fncode);
7973 if (cmpxchg == NULL_TREE)
7974 return false;
7975 type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
7976 itype = TREE_TYPE (TREE_TYPE (cmpxchg));
7977
7978 if (!can_compare_and_swap_p (TYPE_MODE (itype), true))
7979 return false;
7980
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
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 {
7990 tree iaddr_val;
7991
7992 iaddr = create_tmp_reg (build_pointer_type_for_mode (itype, ptr_mode,
7993 true), NULL);
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);
8000 loadedi = create_tmp_var (itype, NULL);
8001 if (gimple_in_ssa_p (cfun))
8002 loadedi = make_ssa_name (loadedi, NULL);
8003 }
8004 else
8005 {
8006 iaddr = addr;
8007 loadedi = loaded_val;
8008 }
8009
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
8022 initial
8023 = force_gimple_operand_gsi (&si, initial, true, NULL_TREE, true,
8024 GSI_SAME_STMT);
8025
8026 /* Move the value to the LOADEDI temporary. */
8027 if (gimple_in_ssa_p (cfun))
8028 {
8029 gcc_assert (gimple_seq_empty_p (phi_nodes (loop_header)));
8030 phi = create_phi_node (loadedi, loop_header);
8031 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, single_succ_edge (load_bb)),
8032 initial);
8033 }
8034 else
8035 gsi_insert_before (&si,
8036 gimple_build_assign (loadedi, initial),
8037 GSI_SAME_STMT);
8038 if (loadedi != loaded_val)
8039 {
8040 gimple_stmt_iterator gsi2;
8041 tree x;
8042
8043 x = build1 (VIEW_CONVERT_EXPR, type, loadedi);
8044 gsi2 = gsi_start_bb (loop_header);
8045 if (gimple_in_ssa_p (cfun))
8046 {
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);
8052 }
8053 else
8054 {
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);
8058 }
8059 }
8060 gsi_remove (&si, true);
8061
8062 si = gsi_last_bb (store_bb);
8063 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
8064
8065 if (iaddr == addr)
8066 storedi = stored_val;
8067 else
8068 storedi =
8069 force_gimple_operand_gsi (&si,
8070 build1 (VIEW_CONVERT_EXPR, itype,
8071 stored_val), true, NULL_TREE, true,
8072 GSI_SAME_STMT);
8073
8074 /* Build the compare&swap statement. */
8075 new_storedi = build_call_expr (cmpxchg, 3, iaddr, loadedi, storedi);
8076 new_storedi = force_gimple_operand_gsi (&si,
8077 fold_convert (TREE_TYPE (loadedi),
8078 new_storedi),
8079 true, NULL_TREE,
8080 true, GSI_SAME_STMT);
8081
8082 if (gimple_in_ssa_p (cfun))
8083 old_vali = loadedi;
8084 else
8085 {
8086 old_vali = create_tmp_var (TREE_TYPE (loadedi), NULL);
8087 stmt = gimple_build_assign (old_vali, loadedi);
8088 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8089
8090 stmt = gimple_build_assign (loadedi, new_storedi);
8091 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8092 }
8093
8094 /* Note that we always perform the comparison as an integer, even for
8095 floating point. This allows the atomic operation to properly
8096 succeed even with NaNs and -0.0. */
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);
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
8109 /* Copy the new value to loadedi (we already did that before the condition
8110 if we are not in SSA). */
8111 if (gimple_in_ssa_p (cfun))
8112 {
8113 phi = gimple_seq_first_stmt (phi_nodes (loop_header));
8114 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, e), new_storedi);
8115 }
8116
8117 /* Remove GIMPLE_OMP_ATOMIC_STORE. */
8118 gsi_remove (&si, true);
8119
8120 struct loop *loop = alloc_loop ();
8121 loop->header = loop_header;
8122 loop->latch = store_bb;
8123 add_loop (loop, loop_header->loop_father);
8124
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
8141 this situation as well.
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.
8145
8146 We replace
8147 GIMPLE_OMP_ATOMIC_LOAD (loaded_val, addr) with
8148 loaded_val = *addr;
8149
8150 and replace
8151 GIMPLE_OMP_ATOMIC_STORE (stored_val) with
8152 *addr = stored_val;
8153 */
8154
8155 static bool
8156 expand_omp_atomic_mutex (basic_block load_bb, basic_block store_bb,
8157 tree addr, tree loaded_val, tree stored_val)
8158 {
8159 gimple_stmt_iterator si;
8160 gimple stmt;
8161 tree t;
8162
8163 si = gsi_last_bb (load_bb);
8164 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
8165
8166 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START);
8167 t = build_call_expr (t, 0);
8168 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
8169
8170 stmt = gimple_build_assign (loaded_val, build_simple_mem_ref (addr));
8171 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8172 gsi_remove (&si, true);
8173
8174 si = gsi_last_bb (store_bb);
8175 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
8176
8177 stmt = gimple_build_assign (build_simple_mem_ref (unshare_expr (addr)),
8178 stored_val);
8179 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8180
8181 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END);
8182 t = build_call_expr (t, 0);
8183 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
8184 gsi_remove (&si, true);
8185
8186 if (gimple_in_ssa_p (cfun))
8187 update_ssa (TODO_update_ssa_no_phi);
8188 return true;
8189 }
8190
8191 /* Expand an GIMPLE_OMP_ATOMIC statement. We try to expand
8192 using expand_omp_atomic_fetch_op. If it failed, we try to
8193 call expand_omp_atomic_pipeline, and if it fails too, the
8194 ultimate fallback is wrapping the operation in a mutex
8195 (expand_omp_atomic_mutex). REGION is the atomic region built
8196 by build_omp_regions_1(). */
8197
8198 static void
8199 expand_omp_atomic (struct omp_region *region)
8200 {
8201 basic_block load_bb = region->entry, store_bb = region->exit;
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);
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. */
8210 index = tree_to_uhwi (TYPE_SIZE_UNIT (type));
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. */
8217 if (exact_log2 (align) >= index)
8218 {
8219 /* Atomic load. */
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
8224 && expand_omp_atomic_load (load_bb, addr, loaded_val, index))
8225 return;
8226
8227 /* Atomic store. */
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
8233 && expand_omp_atomic_store (load_bb, addr, loaded_val,
8234 stored_val, index))
8235 return;
8236
8237 /* When possible, use specialized atomic update functions. */
8238 if ((INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type))
8239 && store_bb == single_succ (load_bb)
8240 && expand_omp_atomic_fetch_op (load_bb, addr,
8241 loaded_val, stored_val, index))
8242 return;
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
8256
8257 /* Expand the OpenMP target{, data, update} directive starting at REGION. */
8258
8259 static void
8260 expand_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))
8347 varpool_node::finalize_decl (t);
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;
8408 cgraph_node::add_new_function (child_fn, true);
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);
8413 cgraph_edge::rebuild_edges ();
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
8424 FOR_EACH_BB_FN (bb, cfun)
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);
8511 add_bb_to_loop (then_bb, cond_bb->loop_father);
8512 add_bb_to_loop (else_bb, cond_bb->loop_father);
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
8572 be created (e.g., GIMPLE_OMP_PARALLEL) can be expanded without having any
8573 internal dependencies in their body. */
8574
8575 static void
8576 expand_omp (struct omp_region *region)
8577 {
8578 while (region)
8579 {
8580 location_t saved_location;
8581 gimple inner_stmt = NULL;
8582
8583 /* First, determine whether this is a combined parallel+workshare
8584 region. */
8585 if (region->type == GIMPLE_OMP_PARALLEL)
8586 determine_parallel_type (region);
8587
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
8592 if (region->inner)
8593 expand_omp (region->inner);
8594
8595 saved_location = input_location;
8596 if (gimple_has_location (last_stmt (region->entry)))
8597 input_location = gimple_location (last_stmt (region->entry));
8598
8599 switch (region->type)
8600 {
8601 case GIMPLE_OMP_PARALLEL:
8602 case GIMPLE_OMP_TASK:
8603 expand_omp_taskreg (region);
8604 break;
8605
8606 case GIMPLE_OMP_FOR:
8607 expand_omp_for (region, inner_stmt);
8608 break;
8609
8610 case GIMPLE_OMP_SECTIONS:
8611 expand_omp_sections (region);
8612 break;
8613
8614 case GIMPLE_OMP_SECTION:
8615 /* Individual omp sections are handled together with their
8616 parent GIMPLE_OMP_SECTIONS region. */
8617 break;
8618
8619 case GIMPLE_OMP_SINGLE:
8620 expand_omp_single (region);
8621 break;
8622
8623 case GIMPLE_OMP_MASTER:
8624 case GIMPLE_OMP_TASKGROUP:
8625 case GIMPLE_OMP_ORDERED:
8626 case GIMPLE_OMP_CRITICAL:
8627 case GIMPLE_OMP_TEAMS:
8628 expand_omp_synch (region);
8629 break;
8630
8631 case GIMPLE_OMP_ATOMIC_LOAD:
8632 expand_omp_atomic (region);
8633 break;
8634
8635 case GIMPLE_OMP_TARGET:
8636 expand_omp_target (region);
8637 break;
8638
8639 default:
8640 gcc_unreachable ();
8641 }
8642
8643 input_location = saved_location;
8644 region = region->next;
8645 }
8646 }
8647
8648
8649 /* Helper for build_omp_regions. Scan the dominator tree starting at
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). */
8653
8654 static void
8655 build_omp_regions_1 (basic_block bb, struct omp_region *parent,
8656 bool single_tree)
8657 {
8658 gimple_stmt_iterator gsi;
8659 gimple stmt;
8660 basic_block son;
8661
8662 gsi = gsi_last_bb (bb);
8663 if (!gsi_end_p (gsi) && is_gimple_omp (gsi_stmt (gsi)))
8664 {
8665 struct omp_region *region;
8666 enum gimple_code code;
8667
8668 stmt = gsi_stmt (gsi);
8669 code = gimple_code (stmt);
8670 if (code == GIMPLE_OMP_RETURN)
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;
8677 region->exit = bb;
8678 parent = parent->outer;
8679 }
8680 else if (code == GIMPLE_OMP_ATOMIC_STORE)
8681 {
8682 /* GIMPLE_OMP_ATOMIC_STORE is analoguous to
8683 GIMPLE_OMP_RETURN, but matches with
8684 GIMPLE_OMP_ATOMIC_LOAD. */
8685 gcc_assert (parent);
8686 gcc_assert (parent->type == GIMPLE_OMP_ATOMIC_LOAD);
8687 region = parent;
8688 region->exit = bb;
8689 parent = parent->outer;
8690 }
8691
8692 else if (code == GIMPLE_OMP_CONTINUE)
8693 {
8694 gcc_assert (parent);
8695 parent->cont = bb;
8696 }
8697 else if (code == GIMPLE_OMP_SECTIONS_SWITCH)
8698 {
8699 /* GIMPLE_OMP_SECTIONS_SWITCH is part of
8700 GIMPLE_OMP_SECTIONS, and we do nothing for it. */
8701 ;
8702 }
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);
8706 else
8707 {
8708 /* Otherwise, this directive becomes the parent for a new
8709 region. */
8710 region = new_omp_region (bb, code, parent);
8711 parent = region;
8712 }
8713 }
8714
8715 if (single_tree && !parent)
8716 return;
8717
8718 for (son = first_dom_son (CDI_DOMINATORS, bb);
8719 son;
8720 son = next_dom_son (CDI_DOMINATORS, son))
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
8727 static void
8728 build_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);
8733 }
8734
8735 /* Expands omp construct (and its subconstructs) starting in HEAD. */
8736
8737 void
8738 omp_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 }
8753
8754 /* Scan the CFG and build a tree of OMP regions. Return the root of
8755 the OMP region tree. */
8756
8757 static void
8758 build_omp_regions (void)
8759 {
8760 gcc_assert (root_omp_region == NULL);
8761 calculate_dominance_info (CDI_DOMINATORS);
8762 build_omp_regions_1 (ENTRY_BLOCK_PTR_FOR_FN (cfun), NULL, false);
8763 }
8764
8765 /* Main entry point for expanding OMP-GIMPLE into runtime calls. */
8766
8767 static unsigned int
8768 execute_expand_omp (void)
8769 {
8770 build_omp_regions ();
8771
8772 if (!root_omp_region)
8773 return 0;
8774
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");
8780 }
8781
8782 remove_exit_barriers (root_omp_region);
8783
8784 expand_omp (root_omp_region);
8785
8786 cleanup_tree_cfg ();
8787
8788 free_omp_regions ();
8789
8790 return 0;
8791 }
8792
8793 /* OMP expansion -- the default pass, run before creation of SSA form. */
8794
8795 namespace {
8796
8797 const pass_data pass_data_expand_omp =
8798 {
8799 GIMPLE_PASS, /* type */
8800 "ompexp", /* name */
8801 OPTGROUP_NONE, /* optinfo_flags */
8802 TV_NONE, /* tv_id */
8803 PROP_gimple_any, /* properties_required */
8804 0, /* properties_provided */
8805 0, /* properties_destroyed */
8806 0, /* todo_flags_start */
8807 0, /* todo_flags_finish */
8808 };
8809
8810 class pass_expand_omp : public gimple_opt_pass
8811 {
8812 public:
8813 pass_expand_omp (gcc::context *ctxt)
8814 : gimple_opt_pass (pass_data_expand_omp, ctxt)
8815 {}
8816
8817 /* opt_pass methods: */
8818 virtual bool gate (function *)
8819 {
8820 return ((flag_openmp != 0 || flag_openmp_simd != 0
8821 || flag_cilkplus != 0) && !seen_error ());
8822 }
8823
8824 virtual unsigned int execute (function *) { return execute_expand_omp (); }
8825
8826 }; // class pass_expand_omp
8827
8828 } // anon namespace
8829
8830 gimple_opt_pass *
8831 make_pass_expand_omp (gcc::context *ctxt)
8832 {
8833 return new pass_expand_omp (ctxt);
8834 }
8835 \f
8836 /* Routines to lower OpenMP directives into OMP-GIMPLE. */
8837
8838 /* If ctx is a worksharing context inside of a cancellable parallel
8839 region and it isn't nowait, add lhs to its GIMPLE_OMP_RETURN
8840 and conditional branch to parallel's cancel_label to handle
8841 cancellation in the implicit barrier. */
8842
8843 static void
8844 maybe_add_implicit_barrier_cancel (omp_context *ctx, gimple_seq *body)
8845 {
8846 gimple omp_return = gimple_seq_last_stmt (*body);
8847 gcc_assert (gimple_code (omp_return) == GIMPLE_OMP_RETURN);
8848 if (gimple_omp_return_nowait_p (omp_return))
8849 return;
8850 if (ctx->outer
8851 && gimple_code (ctx->outer->stmt) == GIMPLE_OMP_PARALLEL
8852 && ctx->outer->cancellable)
8853 {
8854 tree fndecl = builtin_decl_explicit (BUILT_IN_GOMP_CANCEL);
8855 tree c_bool_type = TREE_TYPE (TREE_TYPE (fndecl));
8856 tree lhs = create_tmp_var (c_bool_type, NULL);
8857 gimple_omp_return_set_lhs (omp_return, lhs);
8858 tree fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
8859 gimple g = gimple_build_cond (NE_EXPR, lhs,
8860 fold_convert (c_bool_type,
8861 boolean_false_node),
8862 ctx->outer->cancel_label, fallthru_label);
8863 gimple_seq_add_stmt (body, g);
8864 gimple_seq_add_stmt (body, gimple_build_label (fallthru_label));
8865 }
8866 }
8867
8868 /* Lower the OpenMP sections directive in the current statement in GSI_P.
8869 CTX is the enclosing OMP context for the current statement. */
8870
8871 static void
8872 lower_omp_sections (gimple_stmt_iterator *gsi_p, omp_context *ctx)
8873 {
8874 tree block, control;
8875 gimple_stmt_iterator tgsi;
8876 gimple stmt, new_stmt, bind, t;
8877 gimple_seq ilist, dlist, olist, new_body;
8878
8879 stmt = gsi_stmt (*gsi_p);
8880
8881 push_gimplify_context ();
8882
8883 dlist = NULL;
8884 ilist = NULL;
8885 lower_rec_input_clauses (gimple_omp_sections_clauses (stmt),
8886 &ilist, &dlist, ctx, NULL);
8887
8888 new_body = gimple_omp_body (stmt);
8889 gimple_omp_set_body (stmt, NULL);
8890 tgsi = gsi_start (new_body);
8891 for (; !gsi_end_p (tgsi); gsi_next (&tgsi))
8892 {
8893 omp_context *sctx;
8894 gimple sec_start;
8895
8896 sec_start = gsi_stmt (tgsi);
8897 sctx = maybe_lookup_ctx (sec_start);
8898 gcc_assert (sctx);
8899
8900 lower_omp (gimple_omp_body_ptr (sec_start), sctx);
8901 gsi_insert_seq_after (&tgsi, gimple_omp_body (sec_start),
8902 GSI_CONTINUE_LINKING);
8903 gimple_omp_set_body (sec_start, NULL);
8904
8905 if (gsi_one_before_end_p (tgsi))
8906 {
8907 gimple_seq l = NULL;
8908 lower_lastprivate_clauses (gimple_omp_sections_clauses (stmt), NULL,
8909 &l, ctx);
8910 gsi_insert_seq_after (&tgsi, l, GSI_CONTINUE_LINKING);
8911 gimple_omp_section_set_last (sec_start);
8912 }
8913
8914 gsi_insert_after (&tgsi, gimple_build_omp_return (false),
8915 GSI_CONTINUE_LINKING);
8916 }
8917
8918 block = make_node (BLOCK);
8919 bind = gimple_build_bind (NULL, new_body, block);
8920
8921 olist = NULL;
8922 lower_reduction_clauses (gimple_omp_sections_clauses (stmt), &olist, ctx);
8923
8924 block = make_node (BLOCK);
8925 new_stmt = gimple_build_bind (NULL, NULL, block);
8926 gsi_replace (gsi_p, new_stmt, true);
8927
8928 pop_gimplify_context (new_stmt);
8929 gimple_bind_append_vars (new_stmt, ctx->block_vars);
8930 BLOCK_VARS (block) = gimple_bind_vars (bind);
8931 if (BLOCK_VARS (block))
8932 TREE_USED (block) = 1;
8933
8934 new_body = NULL;
8935 gimple_seq_add_seq (&new_body, ilist);
8936 gimple_seq_add_stmt (&new_body, stmt);
8937 gimple_seq_add_stmt (&new_body, gimple_build_omp_sections_switch ());
8938 gimple_seq_add_stmt (&new_body, bind);
8939
8940 control = create_tmp_var (unsigned_type_node, ".section");
8941 t = gimple_build_omp_continue (control, control);
8942 gimple_omp_sections_set_control (stmt, control);
8943 gimple_seq_add_stmt (&new_body, t);
8944
8945 gimple_seq_add_seq (&new_body, olist);
8946 if (ctx->cancellable)
8947 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
8948 gimple_seq_add_seq (&new_body, dlist);
8949
8950 new_body = maybe_catch_exception (new_body);
8951
8952 t = gimple_build_omp_return
8953 (!!find_omp_clause (gimple_omp_sections_clauses (stmt),
8954 OMP_CLAUSE_NOWAIT));
8955 gimple_seq_add_stmt (&new_body, t);
8956 maybe_add_implicit_barrier_cancel (ctx, &new_body);
8957
8958 gimple_bind_set_body (new_stmt, new_body);
8959 }
8960
8961
8962 /* A subroutine of lower_omp_single. Expand the simple form of
8963 a GIMPLE_OMP_SINGLE, without a copyprivate clause:
8964
8965 if (GOMP_single_start ())
8966 BODY;
8967 [ GOMP_barrier (); ] -> unless 'nowait' is present.
8968
8969 FIXME. It may be better to delay expanding the logic of this until
8970 pass_expand_omp. The expanded logic may make the job more difficult
8971 to a synchronization analysis pass. */
8972
8973 static void
8974 lower_omp_single_simple (gimple single_stmt, gimple_seq *pre_p)
8975 {
8976 location_t loc = gimple_location (single_stmt);
8977 tree tlabel = create_artificial_label (loc);
8978 tree flabel = create_artificial_label (loc);
8979 gimple call, cond;
8980 tree lhs, decl;
8981
8982 decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_START);
8983 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (decl)), NULL);
8984 call = gimple_build_call (decl, 0);
8985 gimple_call_set_lhs (call, lhs);
8986 gimple_seq_add_stmt (pre_p, call);
8987
8988 cond = gimple_build_cond (EQ_EXPR, lhs,
8989 fold_convert_loc (loc, TREE_TYPE (lhs),
8990 boolean_true_node),
8991 tlabel, flabel);
8992 gimple_seq_add_stmt (pre_p, cond);
8993 gimple_seq_add_stmt (pre_p, gimple_build_label (tlabel));
8994 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
8995 gimple_seq_add_stmt (pre_p, gimple_build_label (flabel));
8996 }
8997
8998
8999 /* A subroutine of lower_omp_single. Expand the simple form of
9000 a GIMPLE_OMP_SINGLE, with a copyprivate clause:
9001
9002 #pragma omp single copyprivate (a, b, c)
9003
9004 Create a new structure to hold copies of 'a', 'b' and 'c' and emit:
9005
9006 {
9007 if ((copyout_p = GOMP_single_copy_start ()) == NULL)
9008 {
9009 BODY;
9010 copyout.a = a;
9011 copyout.b = b;
9012 copyout.c = c;
9013 GOMP_single_copy_end (&copyout);
9014 }
9015 else
9016 {
9017 a = copyout_p->a;
9018 b = copyout_p->b;
9019 c = copyout_p->c;
9020 }
9021 GOMP_barrier ();
9022 }
9023
9024 FIXME. It may be better to delay expanding the logic of this until
9025 pass_expand_omp. The expanded logic may make the job more difficult
9026 to a synchronization analysis pass. */
9027
9028 static void
9029 lower_omp_single_copy (gimple single_stmt, gimple_seq *pre_p, omp_context *ctx)
9030 {
9031 tree ptr_type, t, l0, l1, l2, bfn_decl;
9032 gimple_seq copyin_seq;
9033 location_t loc = gimple_location (single_stmt);
9034
9035 ctx->sender_decl = create_tmp_var (ctx->record_type, ".omp_copy_o");
9036
9037 ptr_type = build_pointer_type (ctx->record_type);
9038 ctx->receiver_decl = create_tmp_var (ptr_type, ".omp_copy_i");
9039
9040 l0 = create_artificial_label (loc);
9041 l1 = create_artificial_label (loc);
9042 l2 = create_artificial_label (loc);
9043
9044 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_START);
9045 t = build_call_expr_loc (loc, bfn_decl, 0);
9046 t = fold_convert_loc (loc, ptr_type, t);
9047 gimplify_assign (ctx->receiver_decl, t, pre_p);
9048
9049 t = build2 (EQ_EXPR, boolean_type_node, ctx->receiver_decl,
9050 build_int_cst (ptr_type, 0));
9051 t = build3 (COND_EXPR, void_type_node, t,
9052 build_and_jump (&l0), build_and_jump (&l1));
9053 gimplify_and_add (t, pre_p);
9054
9055 gimple_seq_add_stmt (pre_p, gimple_build_label (l0));
9056
9057 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
9058
9059 copyin_seq = NULL;
9060 lower_copyprivate_clauses (gimple_omp_single_clauses (single_stmt), pre_p,
9061 &copyin_seq, ctx);
9062
9063 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
9064 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_END);
9065 t = build_call_expr_loc (loc, bfn_decl, 1, t);
9066 gimplify_and_add (t, pre_p);
9067
9068 t = build_and_jump (&l2);
9069 gimplify_and_add (t, pre_p);
9070
9071 gimple_seq_add_stmt (pre_p, gimple_build_label (l1));
9072
9073 gimple_seq_add_seq (pre_p, copyin_seq);
9074
9075 gimple_seq_add_stmt (pre_p, gimple_build_label (l2));
9076 }
9077
9078
9079 /* Expand code for an OpenMP single directive. */
9080
9081 static void
9082 lower_omp_single (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9083 {
9084 tree block;
9085 gimple t, bind, single_stmt = gsi_stmt (*gsi_p);
9086 gimple_seq bind_body, bind_body_tail = NULL, dlist;
9087
9088 push_gimplify_context ();
9089
9090 block = make_node (BLOCK);
9091 bind = gimple_build_bind (NULL, NULL, block);
9092 gsi_replace (gsi_p, bind, true);
9093 bind_body = NULL;
9094 dlist = NULL;
9095 lower_rec_input_clauses (gimple_omp_single_clauses (single_stmt),
9096 &bind_body, &dlist, ctx, NULL);
9097 lower_omp (gimple_omp_body_ptr (single_stmt), ctx);
9098
9099 gimple_seq_add_stmt (&bind_body, single_stmt);
9100
9101 if (ctx->record_type)
9102 lower_omp_single_copy (single_stmt, &bind_body, ctx);
9103 else
9104 lower_omp_single_simple (single_stmt, &bind_body);
9105
9106 gimple_omp_set_body (single_stmt, NULL);
9107
9108 gimple_seq_add_seq (&bind_body, dlist);
9109
9110 bind_body = maybe_catch_exception (bind_body);
9111
9112 t = gimple_build_omp_return
9113 (!!find_omp_clause (gimple_omp_single_clauses (single_stmt),
9114 OMP_CLAUSE_NOWAIT));
9115 gimple_seq_add_stmt (&bind_body_tail, t);
9116 maybe_add_implicit_barrier_cancel (ctx, &bind_body_tail);
9117 if (ctx->record_type)
9118 {
9119 gimple_stmt_iterator gsi = gsi_start (bind_body_tail);
9120 tree clobber = build_constructor (ctx->record_type, NULL);
9121 TREE_THIS_VOLATILE (clobber) = 1;
9122 gsi_insert_after (&gsi, gimple_build_assign (ctx->sender_decl,
9123 clobber), GSI_SAME_STMT);
9124 }
9125 gimple_seq_add_seq (&bind_body, bind_body_tail);
9126 gimple_bind_set_body (bind, bind_body);
9127
9128 pop_gimplify_context (bind);
9129
9130 gimple_bind_append_vars (bind, ctx->block_vars);
9131 BLOCK_VARS (block) = ctx->block_vars;
9132 if (BLOCK_VARS (block))
9133 TREE_USED (block) = 1;
9134 }
9135
9136
9137 /* Expand code for an OpenMP master directive. */
9138
9139 static void
9140 lower_omp_master (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9141 {
9142 tree block, lab = NULL, x, bfn_decl;
9143 gimple stmt = gsi_stmt (*gsi_p), bind;
9144 location_t loc = gimple_location (stmt);
9145 gimple_seq tseq;
9146
9147 push_gimplify_context ();
9148
9149 block = make_node (BLOCK);
9150 bind = gimple_build_bind (NULL, NULL, block);
9151 gsi_replace (gsi_p, bind, true);
9152 gimple_bind_add_stmt (bind, stmt);
9153
9154 bfn_decl = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
9155 x = build_call_expr_loc (loc, bfn_decl, 0);
9156 x = build2 (EQ_EXPR, boolean_type_node, x, integer_zero_node);
9157 x = build3 (COND_EXPR, void_type_node, x, NULL, build_and_jump (&lab));
9158 tseq = NULL;
9159 gimplify_and_add (x, &tseq);
9160 gimple_bind_add_seq (bind, tseq);
9161
9162 lower_omp (gimple_omp_body_ptr (stmt), ctx);
9163 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
9164 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
9165 gimple_omp_set_body (stmt, NULL);
9166
9167 gimple_bind_add_stmt (bind, gimple_build_label (lab));
9168
9169 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
9170
9171 pop_gimplify_context (bind);
9172
9173 gimple_bind_append_vars (bind, ctx->block_vars);
9174 BLOCK_VARS (block) = ctx->block_vars;
9175 }
9176
9177
9178 /* Expand code for an OpenMP taskgroup directive. */
9179
9180 static void
9181 lower_omp_taskgroup (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9182 {
9183 gimple stmt = gsi_stmt (*gsi_p), bind, x;
9184 tree block = make_node (BLOCK);
9185
9186 bind = gimple_build_bind (NULL, NULL, block);
9187 gsi_replace (gsi_p, bind, true);
9188 gimple_bind_add_stmt (bind, stmt);
9189
9190 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_TASKGROUP_START),
9191 0);
9192 gimple_bind_add_stmt (bind, x);
9193
9194 lower_omp (gimple_omp_body_ptr (stmt), ctx);
9195 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
9196 gimple_omp_set_body (stmt, NULL);
9197
9198 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
9199
9200 gimple_bind_append_vars (bind, ctx->block_vars);
9201 BLOCK_VARS (block) = ctx->block_vars;
9202 }
9203
9204
9205 /* Expand code for an OpenMP ordered directive. */
9206
9207 static void
9208 lower_omp_ordered (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9209 {
9210 tree block;
9211 gimple stmt = gsi_stmt (*gsi_p), bind, x;
9212
9213 push_gimplify_context ();
9214
9215 block = make_node (BLOCK);
9216 bind = gimple_build_bind (NULL, NULL, block);
9217 gsi_replace (gsi_p, bind, true);
9218 gimple_bind_add_stmt (bind, stmt);
9219
9220 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_START),
9221 0);
9222 gimple_bind_add_stmt (bind, x);
9223
9224 lower_omp (gimple_omp_body_ptr (stmt), ctx);
9225 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
9226 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
9227 gimple_omp_set_body (stmt, NULL);
9228
9229 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_END), 0);
9230 gimple_bind_add_stmt (bind, x);
9231
9232 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
9233
9234 pop_gimplify_context (bind);
9235
9236 gimple_bind_append_vars (bind, ctx->block_vars);
9237 BLOCK_VARS (block) = gimple_bind_vars (bind);
9238 }
9239
9240
9241 /* Gimplify a GIMPLE_OMP_CRITICAL statement. This is a relatively simple
9242 substitution of a couple of function calls. But in the NAMED case,
9243 requires that languages coordinate a symbol name. It is therefore
9244 best put here in common code. */
9245
9246 static GTY((param1_is (tree), param2_is (tree)))
9247 splay_tree critical_name_mutexes;
9248
9249 static void
9250 lower_omp_critical (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9251 {
9252 tree block;
9253 tree name, lock, unlock;
9254 gimple stmt = gsi_stmt (*gsi_p), bind;
9255 location_t loc = gimple_location (stmt);
9256 gimple_seq tbody;
9257
9258 name = gimple_omp_critical_name (stmt);
9259 if (name)
9260 {
9261 tree decl;
9262 splay_tree_node n;
9263
9264 if (!critical_name_mutexes)
9265 critical_name_mutexes
9266 = splay_tree_new_ggc (splay_tree_compare_pointers,
9267 ggc_alloc_splay_tree_tree_node_tree_node_splay_tree_s,
9268 ggc_alloc_splay_tree_tree_node_tree_node_splay_tree_node_s);
9269
9270 n = splay_tree_lookup (critical_name_mutexes, (splay_tree_key) name);
9271 if (n == NULL)
9272 {
9273 char *new_str;
9274
9275 decl = create_tmp_var_raw (ptr_type_node, NULL);
9276
9277 new_str = ACONCAT ((".gomp_critical_user_",
9278 IDENTIFIER_POINTER (name), NULL));
9279 DECL_NAME (decl) = get_identifier (new_str);
9280 TREE_PUBLIC (decl) = 1;
9281 TREE_STATIC (decl) = 1;
9282 DECL_COMMON (decl) = 1;
9283 DECL_ARTIFICIAL (decl) = 1;
9284 DECL_IGNORED_P (decl) = 1;
9285 varpool_node::finalize_decl (decl);
9286
9287 splay_tree_insert (critical_name_mutexes, (splay_tree_key) name,
9288 (splay_tree_value) decl);
9289 }
9290 else
9291 decl = (tree) n->value;
9292
9293 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_START);
9294 lock = build_call_expr_loc (loc, lock, 1, build_fold_addr_expr_loc (loc, decl));
9295
9296 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_END);
9297 unlock = build_call_expr_loc (loc, unlock, 1,
9298 build_fold_addr_expr_loc (loc, decl));
9299 }
9300 else
9301 {
9302 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_START);
9303 lock = build_call_expr_loc (loc, lock, 0);
9304
9305 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_END);
9306 unlock = build_call_expr_loc (loc, unlock, 0);
9307 }
9308
9309 push_gimplify_context ();
9310
9311 block = make_node (BLOCK);
9312 bind = gimple_build_bind (NULL, NULL, block);
9313 gsi_replace (gsi_p, bind, true);
9314 gimple_bind_add_stmt (bind, stmt);
9315
9316 tbody = gimple_bind_body (bind);
9317 gimplify_and_add (lock, &tbody);
9318 gimple_bind_set_body (bind, tbody);
9319
9320 lower_omp (gimple_omp_body_ptr (stmt), ctx);
9321 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
9322 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
9323 gimple_omp_set_body (stmt, NULL);
9324
9325 tbody = gimple_bind_body (bind);
9326 gimplify_and_add (unlock, &tbody);
9327 gimple_bind_set_body (bind, tbody);
9328
9329 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
9330
9331 pop_gimplify_context (bind);
9332 gimple_bind_append_vars (bind, ctx->block_vars);
9333 BLOCK_VARS (block) = gimple_bind_vars (bind);
9334 }
9335
9336
9337 /* A subroutine of lower_omp_for. Generate code to emit the predicate
9338 for a lastprivate clause. Given a loop control predicate of (V
9339 cond N2), we gate the clause on (!(V cond N2)). The lowered form
9340 is appended to *DLIST, iterator initialization is appended to
9341 *BODY_P. */
9342
9343 static void
9344 lower_omp_for_lastprivate (struct omp_for_data *fd, gimple_seq *body_p,
9345 gimple_seq *dlist, struct omp_context *ctx)
9346 {
9347 tree clauses, cond, vinit;
9348 enum tree_code cond_code;
9349 gimple_seq stmts;
9350
9351 cond_code = fd->loop.cond_code;
9352 cond_code = cond_code == LT_EXPR ? GE_EXPR : LE_EXPR;
9353
9354 /* When possible, use a strict equality expression. This can let VRP
9355 type optimizations deduce the value and remove a copy. */
9356 if (tree_fits_shwi_p (fd->loop.step))
9357 {
9358 HOST_WIDE_INT step = tree_to_shwi (fd->loop.step);
9359 if (step == 1 || step == -1)
9360 cond_code = EQ_EXPR;
9361 }
9362
9363 cond = build2 (cond_code, boolean_type_node, fd->loop.v, fd->loop.n2);
9364
9365 clauses = gimple_omp_for_clauses (fd->for_stmt);
9366 stmts = NULL;
9367 lower_lastprivate_clauses (clauses, cond, &stmts, ctx);
9368 if (!gimple_seq_empty_p (stmts))
9369 {
9370 gimple_seq_add_seq (&stmts, *dlist);
9371 *dlist = stmts;
9372
9373 /* Optimize: v = 0; is usually cheaper than v = some_other_constant. */
9374 vinit = fd->loop.n1;
9375 if (cond_code == EQ_EXPR
9376 && tree_fits_shwi_p (fd->loop.n2)
9377 && ! integer_zerop (fd->loop.n2))
9378 vinit = build_int_cst (TREE_TYPE (fd->loop.v), 0);
9379 else
9380 vinit = unshare_expr (vinit);
9381
9382 /* Initialize the iterator variable, so that threads that don't execute
9383 any iterations don't execute the lastprivate clauses by accident. */
9384 gimplify_assign (fd->loop.v, vinit, body_p);
9385 }
9386 }
9387
9388
9389 /* Lower code for an OpenMP loop directive. */
9390
9391 static void
9392 lower_omp_for (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9393 {
9394 tree *rhs_p, block;
9395 struct omp_for_data fd, *fdp = NULL;
9396 gimple stmt = gsi_stmt (*gsi_p), new_stmt;
9397 gimple_seq omp_for_body, body, dlist;
9398 size_t i;
9399
9400 push_gimplify_context ();
9401
9402 lower_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
9403
9404 block = make_node (BLOCK);
9405 new_stmt = gimple_build_bind (NULL, NULL, block);
9406 /* Replace at gsi right away, so that 'stmt' is no member
9407 of a sequence anymore as we're going to add to to a different
9408 one below. */
9409 gsi_replace (gsi_p, new_stmt, true);
9410
9411 /* Move declaration of temporaries in the loop body before we make
9412 it go away. */
9413 omp_for_body = gimple_omp_body (stmt);
9414 if (!gimple_seq_empty_p (omp_for_body)
9415 && gimple_code (gimple_seq_first_stmt (omp_for_body)) == GIMPLE_BIND)
9416 {
9417 gimple inner_bind = gimple_seq_first_stmt (omp_for_body);
9418 tree vars = gimple_bind_vars (inner_bind);
9419 gimple_bind_append_vars (new_stmt, vars);
9420 /* bind_vars/BLOCK_VARS are being moved to new_stmt/block, don't
9421 keep them on the inner_bind and it's block. */
9422 gimple_bind_set_vars (inner_bind, NULL_TREE);
9423 if (gimple_bind_block (inner_bind))
9424 BLOCK_VARS (gimple_bind_block (inner_bind)) = NULL_TREE;
9425 }
9426
9427 if (gimple_omp_for_combined_into_p (stmt))
9428 {
9429 extract_omp_for_data (stmt, &fd, NULL);
9430 fdp = &fd;
9431
9432 /* We need two temporaries with fd.loop.v type (istart/iend)
9433 and then (fd.collapse - 1) temporaries with the same
9434 type for count2 ... countN-1 vars if not constant. */
9435 size_t count = 2;
9436 tree type = fd.iter_type;
9437 if (fd.collapse > 1
9438 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
9439 count += fd.collapse - 1;
9440 bool parallel_for = gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR;
9441 tree outerc = NULL, *pc = gimple_omp_for_clauses_ptr (stmt);
9442 tree clauses = *pc;
9443 if (parallel_for)
9444 outerc
9445 = find_omp_clause (gimple_omp_parallel_clauses (ctx->outer->stmt),
9446 OMP_CLAUSE__LOOPTEMP_);
9447 for (i = 0; i < count; i++)
9448 {
9449 tree temp;
9450 if (parallel_for)
9451 {
9452 gcc_assert (outerc);
9453 temp = lookup_decl (OMP_CLAUSE_DECL (outerc), ctx->outer);
9454 outerc = find_omp_clause (OMP_CLAUSE_CHAIN (outerc),
9455 OMP_CLAUSE__LOOPTEMP_);
9456 }
9457 else
9458 {
9459 temp = create_tmp_var (type, NULL);
9460 insert_decl_map (&ctx->outer->cb, temp, temp);
9461 }
9462 *pc = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__LOOPTEMP_);
9463 OMP_CLAUSE_DECL (*pc) = temp;
9464 pc = &OMP_CLAUSE_CHAIN (*pc);
9465 }
9466 *pc = clauses;
9467 }
9468
9469 /* The pre-body and input clauses go before the lowered GIMPLE_OMP_FOR. */
9470 dlist = NULL;
9471 body = NULL;
9472 lower_rec_input_clauses (gimple_omp_for_clauses (stmt), &body, &dlist, ctx,
9473 fdp);
9474 gimple_seq_add_seq (&body, gimple_omp_for_pre_body (stmt));
9475
9476 lower_omp (gimple_omp_body_ptr (stmt), ctx);
9477
9478 /* Lower the header expressions. At this point, we can assume that
9479 the header is of the form:
9480
9481 #pragma omp for (V = VAL1; V {<|>|<=|>=} VAL2; V = V [+-] VAL3)
9482
9483 We just need to make sure that VAL1, VAL2 and VAL3 are lowered
9484 using the .omp_data_s mapping, if needed. */
9485 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
9486 {
9487 rhs_p = gimple_omp_for_initial_ptr (stmt, i);
9488 if (!is_gimple_min_invariant (*rhs_p))
9489 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
9490
9491 rhs_p = gimple_omp_for_final_ptr (stmt, i);
9492 if (!is_gimple_min_invariant (*rhs_p))
9493 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
9494
9495 rhs_p = &TREE_OPERAND (gimple_omp_for_incr (stmt, i), 1);
9496 if (!is_gimple_min_invariant (*rhs_p))
9497 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
9498 }
9499
9500 /* Once lowered, extract the bounds and clauses. */
9501 extract_omp_for_data (stmt, &fd, NULL);
9502
9503 lower_omp_for_lastprivate (&fd, &body, &dlist, ctx);
9504
9505 gimple_seq_add_stmt (&body, stmt);
9506 gimple_seq_add_seq (&body, gimple_omp_body (stmt));
9507
9508 gimple_seq_add_stmt (&body, gimple_build_omp_continue (fd.loop.v,
9509 fd.loop.v));
9510
9511 /* After the loop, add exit clauses. */
9512 lower_reduction_clauses (gimple_omp_for_clauses (stmt), &body, ctx);
9513
9514 if (ctx->cancellable)
9515 gimple_seq_add_stmt (&body, gimple_build_label (ctx->cancel_label));
9516
9517 gimple_seq_add_seq (&body, dlist);
9518
9519 body = maybe_catch_exception (body);
9520
9521 /* Region exit marker goes at the end of the loop body. */
9522 gimple_seq_add_stmt (&body, gimple_build_omp_return (fd.have_nowait));
9523 maybe_add_implicit_barrier_cancel (ctx, &body);
9524 pop_gimplify_context (new_stmt);
9525
9526 gimple_bind_append_vars (new_stmt, ctx->block_vars);
9527 BLOCK_VARS (block) = gimple_bind_vars (new_stmt);
9528 if (BLOCK_VARS (block))
9529 TREE_USED (block) = 1;
9530
9531 gimple_bind_set_body (new_stmt, body);
9532 gimple_omp_set_body (stmt, NULL);
9533 gimple_omp_for_set_pre_body (stmt, NULL);
9534 }
9535
9536 /* Callback for walk_stmts. Check if the current statement only contains
9537 GIMPLE_OMP_FOR or GIMPLE_OMP_SECTIONS. */
9538
9539 static tree
9540 check_combined_parallel (gimple_stmt_iterator *gsi_p,
9541 bool *handled_ops_p,
9542 struct walk_stmt_info *wi)
9543 {
9544 int *info = (int *) wi->info;
9545 gimple stmt = gsi_stmt (*gsi_p);
9546
9547 *handled_ops_p = true;
9548 switch (gimple_code (stmt))
9549 {
9550 WALK_SUBSTMTS;
9551
9552 case GIMPLE_OMP_FOR:
9553 case GIMPLE_OMP_SECTIONS:
9554 *info = *info == 0 ? 1 : -1;
9555 break;
9556 default:
9557 *info = -1;
9558 break;
9559 }
9560 return NULL;
9561 }
9562
9563 struct omp_taskcopy_context
9564 {
9565 /* This field must be at the beginning, as we do "inheritance": Some
9566 callback functions for tree-inline.c (e.g., omp_copy_decl)
9567 receive a copy_body_data pointer that is up-casted to an
9568 omp_context pointer. */
9569 copy_body_data cb;
9570 omp_context *ctx;
9571 };
9572
9573 static tree
9574 task_copyfn_copy_decl (tree var, copy_body_data *cb)
9575 {
9576 struct omp_taskcopy_context *tcctx = (struct omp_taskcopy_context *) cb;
9577
9578 if (splay_tree_lookup (tcctx->ctx->sfield_map, (splay_tree_key) var))
9579 return create_tmp_var (TREE_TYPE (var), NULL);
9580
9581 return var;
9582 }
9583
9584 static tree
9585 task_copyfn_remap_type (struct omp_taskcopy_context *tcctx, tree orig_type)
9586 {
9587 tree name, new_fields = NULL, type, f;
9588
9589 type = lang_hooks.types.make_type (RECORD_TYPE);
9590 name = DECL_NAME (TYPE_NAME (orig_type));
9591 name = build_decl (gimple_location (tcctx->ctx->stmt),
9592 TYPE_DECL, name, type);
9593 TYPE_NAME (type) = name;
9594
9595 for (f = TYPE_FIELDS (orig_type); f ; f = TREE_CHAIN (f))
9596 {
9597 tree new_f = copy_node (f);
9598 DECL_CONTEXT (new_f) = type;
9599 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &tcctx->cb);
9600 TREE_CHAIN (new_f) = new_fields;
9601 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &tcctx->cb, NULL);
9602 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r, &tcctx->cb, NULL);
9603 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
9604 &tcctx->cb, NULL);
9605 new_fields = new_f;
9606 tcctx->cb.decl_map->put (f, new_f);
9607 }
9608 TYPE_FIELDS (type) = nreverse (new_fields);
9609 layout_type (type);
9610 return type;
9611 }
9612
9613 /* Create task copyfn. */
9614
9615 static void
9616 create_task_copyfn (gimple task_stmt, omp_context *ctx)
9617 {
9618 struct function *child_cfun;
9619 tree child_fn, t, c, src, dst, f, sf, arg, sarg, decl;
9620 tree record_type, srecord_type, bind, list;
9621 bool record_needs_remap = false, srecord_needs_remap = false;
9622 splay_tree_node n;
9623 struct omp_taskcopy_context tcctx;
9624 location_t loc = gimple_location (task_stmt);
9625
9626 child_fn = gimple_omp_task_copy_fn (task_stmt);
9627 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
9628 gcc_assert (child_cfun->cfg == NULL);
9629 DECL_SAVED_TREE (child_fn) = alloc_stmt_list ();
9630
9631 /* Reset DECL_CONTEXT on function arguments. */
9632 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
9633 DECL_CONTEXT (t) = child_fn;
9634
9635 /* Populate the function. */
9636 push_gimplify_context ();
9637 push_cfun (child_cfun);
9638
9639 bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
9640 TREE_SIDE_EFFECTS (bind) = 1;
9641 list = NULL;
9642 DECL_SAVED_TREE (child_fn) = bind;
9643 DECL_SOURCE_LOCATION (child_fn) = gimple_location (task_stmt);
9644
9645 /* Remap src and dst argument types if needed. */
9646 record_type = ctx->record_type;
9647 srecord_type = ctx->srecord_type;
9648 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
9649 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
9650 {
9651 record_needs_remap = true;
9652 break;
9653 }
9654 for (f = TYPE_FIELDS (srecord_type); f ; f = DECL_CHAIN (f))
9655 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
9656 {
9657 srecord_needs_remap = true;
9658 break;
9659 }
9660
9661 if (record_needs_remap || srecord_needs_remap)
9662 {
9663 memset (&tcctx, '\0', sizeof (tcctx));
9664 tcctx.cb.src_fn = ctx->cb.src_fn;
9665 tcctx.cb.dst_fn = child_fn;
9666 tcctx.cb.src_node = cgraph_node::get (tcctx.cb.src_fn);
9667 gcc_checking_assert (tcctx.cb.src_node);
9668 tcctx.cb.dst_node = tcctx.cb.src_node;
9669 tcctx.cb.src_cfun = ctx->cb.src_cfun;
9670 tcctx.cb.copy_decl = task_copyfn_copy_decl;
9671 tcctx.cb.eh_lp_nr = 0;
9672 tcctx.cb.transform_call_graph_edges = CB_CGE_MOVE;
9673 tcctx.cb.decl_map = new hash_map<tree, tree>;
9674 tcctx.ctx = ctx;
9675
9676 if (record_needs_remap)
9677 record_type = task_copyfn_remap_type (&tcctx, record_type);
9678 if (srecord_needs_remap)
9679 srecord_type = task_copyfn_remap_type (&tcctx, srecord_type);
9680 }
9681 else
9682 tcctx.cb.decl_map = NULL;
9683
9684 arg = DECL_ARGUMENTS (child_fn);
9685 TREE_TYPE (arg) = build_pointer_type (record_type);
9686 sarg = DECL_CHAIN (arg);
9687 TREE_TYPE (sarg) = build_pointer_type (srecord_type);
9688
9689 /* First pass: initialize temporaries used in record_type and srecord_type
9690 sizes and field offsets. */
9691 if (tcctx.cb.decl_map)
9692 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
9693 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
9694 {
9695 tree *p;
9696
9697 decl = OMP_CLAUSE_DECL (c);
9698 p = tcctx.cb.decl_map->get (decl);
9699 if (p == NULL)
9700 continue;
9701 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
9702 sf = (tree) n->value;
9703 sf = *tcctx.cb.decl_map->get (sf);
9704 src = build_simple_mem_ref_loc (loc, sarg);
9705 src = omp_build_component_ref (src, sf);
9706 t = build2 (MODIFY_EXPR, TREE_TYPE (*p), *p, src);
9707 append_to_statement_list (t, &list);
9708 }
9709
9710 /* Second pass: copy shared var pointers and copy construct non-VLA
9711 firstprivate vars. */
9712 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
9713 switch (OMP_CLAUSE_CODE (c))
9714 {
9715 case OMP_CLAUSE_SHARED:
9716 decl = OMP_CLAUSE_DECL (c);
9717 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
9718 if (n == NULL)
9719 break;
9720 f = (tree) n->value;
9721 if (tcctx.cb.decl_map)
9722 f = *tcctx.cb.decl_map->get (f);
9723 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
9724 sf = (tree) n->value;
9725 if (tcctx.cb.decl_map)
9726 sf = *tcctx.cb.decl_map->get (sf);
9727 src = build_simple_mem_ref_loc (loc, sarg);
9728 src = omp_build_component_ref (src, sf);
9729 dst = build_simple_mem_ref_loc (loc, arg);
9730 dst = omp_build_component_ref (dst, f);
9731 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
9732 append_to_statement_list (t, &list);
9733 break;
9734 case OMP_CLAUSE_FIRSTPRIVATE:
9735 decl = OMP_CLAUSE_DECL (c);
9736 if (is_variable_sized (decl))
9737 break;
9738 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
9739 if (n == NULL)
9740 break;
9741 f = (tree) n->value;
9742 if (tcctx.cb.decl_map)
9743 f = *tcctx.cb.decl_map->get (f);
9744 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
9745 if (n != NULL)
9746 {
9747 sf = (tree) n->value;
9748 if (tcctx.cb.decl_map)
9749 sf = *tcctx.cb.decl_map->get (sf);
9750 src = build_simple_mem_ref_loc (loc, sarg);
9751 src = omp_build_component_ref (src, sf);
9752 if (use_pointer_for_field (decl, NULL) || is_reference (decl))
9753 src = build_simple_mem_ref_loc (loc, src);
9754 }
9755 else
9756 src = decl;
9757 dst = build_simple_mem_ref_loc (loc, arg);
9758 dst = omp_build_component_ref (dst, f);
9759 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
9760 append_to_statement_list (t, &list);
9761 break;
9762 case OMP_CLAUSE_PRIVATE:
9763 if (! OMP_CLAUSE_PRIVATE_OUTER_REF (c))
9764 break;
9765 decl = OMP_CLAUSE_DECL (c);
9766 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
9767 f = (tree) n->value;
9768 if (tcctx.cb.decl_map)
9769 f = *tcctx.cb.decl_map->get (f);
9770 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
9771 if (n != NULL)
9772 {
9773 sf = (tree) n->value;
9774 if (tcctx.cb.decl_map)
9775 sf = *tcctx.cb.decl_map->get (sf);
9776 src = build_simple_mem_ref_loc (loc, sarg);
9777 src = omp_build_component_ref (src, sf);
9778 if (use_pointer_for_field (decl, NULL))
9779 src = build_simple_mem_ref_loc (loc, src);
9780 }
9781 else
9782 src = decl;
9783 dst = build_simple_mem_ref_loc (loc, arg);
9784 dst = omp_build_component_ref (dst, f);
9785 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
9786 append_to_statement_list (t, &list);
9787 break;
9788 default:
9789 break;
9790 }
9791
9792 /* Last pass: handle VLA firstprivates. */
9793 if (tcctx.cb.decl_map)
9794 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
9795 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
9796 {
9797 tree ind, ptr, df;
9798
9799 decl = OMP_CLAUSE_DECL (c);
9800 if (!is_variable_sized (decl))
9801 continue;
9802 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
9803 if (n == NULL)
9804 continue;
9805 f = (tree) n->value;
9806 f = *tcctx.cb.decl_map->get (f);
9807 gcc_assert (DECL_HAS_VALUE_EXPR_P (decl));
9808 ind = DECL_VALUE_EXPR (decl);
9809 gcc_assert (TREE_CODE (ind) == INDIRECT_REF);
9810 gcc_assert (DECL_P (TREE_OPERAND (ind, 0)));
9811 n = splay_tree_lookup (ctx->sfield_map,
9812 (splay_tree_key) TREE_OPERAND (ind, 0));
9813 sf = (tree) n->value;
9814 sf = *tcctx.cb.decl_map->get (sf);
9815 src = build_simple_mem_ref_loc (loc, sarg);
9816 src = omp_build_component_ref (src, sf);
9817 src = build_simple_mem_ref_loc (loc, src);
9818 dst = build_simple_mem_ref_loc (loc, arg);
9819 dst = omp_build_component_ref (dst, f);
9820 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
9821 append_to_statement_list (t, &list);
9822 n = splay_tree_lookup (ctx->field_map,
9823 (splay_tree_key) TREE_OPERAND (ind, 0));
9824 df = (tree) n->value;
9825 df = *tcctx.cb.decl_map->get (df);
9826 ptr = build_simple_mem_ref_loc (loc, arg);
9827 ptr = omp_build_component_ref (ptr, df);
9828 t = build2 (MODIFY_EXPR, TREE_TYPE (ptr), ptr,
9829 build_fold_addr_expr_loc (loc, dst));
9830 append_to_statement_list (t, &list);
9831 }
9832
9833 t = build1 (RETURN_EXPR, void_type_node, NULL);
9834 append_to_statement_list (t, &list);
9835
9836 if (tcctx.cb.decl_map)
9837 delete tcctx.cb.decl_map;
9838 pop_gimplify_context (NULL);
9839 BIND_EXPR_BODY (bind) = list;
9840 pop_cfun ();
9841 }
9842
9843 static void
9844 lower_depend_clauses (gimple stmt, gimple_seq *iseq, gimple_seq *oseq)
9845 {
9846 tree c, clauses;
9847 gimple g;
9848 size_t n_in = 0, n_out = 0, idx = 2, i;
9849
9850 clauses = find_omp_clause (gimple_omp_task_clauses (stmt),
9851 OMP_CLAUSE_DEPEND);
9852 gcc_assert (clauses);
9853 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
9854 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
9855 switch (OMP_CLAUSE_DEPEND_KIND (c))
9856 {
9857 case OMP_CLAUSE_DEPEND_IN:
9858 n_in++;
9859 break;
9860 case OMP_CLAUSE_DEPEND_OUT:
9861 case OMP_CLAUSE_DEPEND_INOUT:
9862 n_out++;
9863 break;
9864 default:
9865 gcc_unreachable ();
9866 }
9867 tree type = build_array_type_nelts (ptr_type_node, n_in + n_out + 2);
9868 tree array = create_tmp_var (type, NULL);
9869 tree r = build4 (ARRAY_REF, ptr_type_node, array, size_int (0), NULL_TREE,
9870 NULL_TREE);
9871 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_in + n_out));
9872 gimple_seq_add_stmt (iseq, g);
9873 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (1), NULL_TREE,
9874 NULL_TREE);
9875 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_out));
9876 gimple_seq_add_stmt (iseq, g);
9877 for (i = 0; i < 2; i++)
9878 {
9879 if ((i ? n_in : n_out) == 0)
9880 continue;
9881 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
9882 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
9883 && ((OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_IN) ^ i))
9884 {
9885 tree t = OMP_CLAUSE_DECL (c);
9886 t = fold_convert (ptr_type_node, t);
9887 gimplify_expr (&t, iseq, NULL, is_gimple_val, fb_rvalue);
9888 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (idx++),
9889 NULL_TREE, NULL_TREE);
9890 g = gimple_build_assign (r, t);
9891 gimple_seq_add_stmt (iseq, g);
9892 }
9893 }
9894 tree *p = gimple_omp_task_clauses_ptr (stmt);
9895 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_DEPEND);
9896 OMP_CLAUSE_DECL (c) = build_fold_addr_expr (array);
9897 OMP_CLAUSE_CHAIN (c) = *p;
9898 *p = c;
9899 tree clobber = build_constructor (type, NULL);
9900 TREE_THIS_VOLATILE (clobber) = 1;
9901 g = gimple_build_assign (array, clobber);
9902 gimple_seq_add_stmt (oseq, g);
9903 }
9904
9905 /* Lower the OpenMP parallel or task directive in the current statement
9906 in GSI_P. CTX holds context information for the directive. */
9907
9908 static void
9909 lower_omp_taskreg (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9910 {
9911 tree clauses;
9912 tree child_fn, t;
9913 gimple stmt = gsi_stmt (*gsi_p);
9914 gimple par_bind, bind, dep_bind = NULL;
9915 gimple_seq par_body, olist, ilist, par_olist, par_rlist, par_ilist, new_body;
9916 location_t loc = gimple_location (stmt);
9917
9918 clauses = gimple_omp_taskreg_clauses (stmt);
9919 par_bind = gimple_seq_first_stmt (gimple_omp_body (stmt));
9920 par_body = gimple_bind_body (par_bind);
9921 child_fn = ctx->cb.dst_fn;
9922 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
9923 && !gimple_omp_parallel_combined_p (stmt))
9924 {
9925 struct walk_stmt_info wi;
9926 int ws_num = 0;
9927
9928 memset (&wi, 0, sizeof (wi));
9929 wi.info = &ws_num;
9930 wi.val_only = true;
9931 walk_gimple_seq (par_body, check_combined_parallel, NULL, &wi);
9932 if (ws_num == 1)
9933 gimple_omp_parallel_set_combined_p (stmt, true);
9934 }
9935 gimple_seq dep_ilist = NULL;
9936 gimple_seq dep_olist = NULL;
9937 if (gimple_code (stmt) == GIMPLE_OMP_TASK
9938 && find_omp_clause (clauses, OMP_CLAUSE_DEPEND))
9939 {
9940 push_gimplify_context ();
9941 dep_bind = gimple_build_bind (NULL, NULL, make_node (BLOCK));
9942 lower_depend_clauses (stmt, &dep_ilist, &dep_olist);
9943 }
9944
9945 if (ctx->srecord_type)
9946 create_task_copyfn (stmt, ctx);
9947
9948 push_gimplify_context ();
9949
9950 par_olist = NULL;
9951 par_ilist = NULL;
9952 par_rlist = NULL;
9953 lower_rec_input_clauses (clauses, &par_ilist, &par_olist, ctx, NULL);
9954 lower_omp (&par_body, ctx);
9955 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL)
9956 lower_reduction_clauses (clauses, &par_rlist, ctx);
9957
9958 /* Declare all the variables created by mapping and the variables
9959 declared in the scope of the parallel body. */
9960 record_vars_into (ctx->block_vars, child_fn);
9961 record_vars_into (gimple_bind_vars (par_bind), child_fn);
9962
9963 if (ctx->record_type)
9964 {
9965 ctx->sender_decl
9966 = create_tmp_var (ctx->srecord_type ? ctx->srecord_type
9967 : ctx->record_type, ".omp_data_o");
9968 DECL_NAMELESS (ctx->sender_decl) = 1;
9969 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
9970 gimple_omp_taskreg_set_data_arg (stmt, ctx->sender_decl);
9971 }
9972
9973 olist = NULL;
9974 ilist = NULL;
9975 lower_send_clauses (clauses, &ilist, &olist, ctx);
9976 lower_send_shared_vars (&ilist, &olist, ctx);
9977
9978 if (ctx->record_type)
9979 {
9980 tree clobber = build_constructor (TREE_TYPE (ctx->sender_decl), NULL);
9981 TREE_THIS_VOLATILE (clobber) = 1;
9982 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
9983 clobber));
9984 }
9985
9986 /* Once all the expansions are done, sequence all the different
9987 fragments inside gimple_omp_body. */
9988
9989 new_body = NULL;
9990
9991 if (ctx->record_type)
9992 {
9993 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
9994 /* fixup_child_record_type might have changed receiver_decl's type. */
9995 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
9996 gimple_seq_add_stmt (&new_body,
9997 gimple_build_assign (ctx->receiver_decl, t));
9998 }
9999
10000 gimple_seq_add_seq (&new_body, par_ilist);
10001 gimple_seq_add_seq (&new_body, par_body);
10002 gimple_seq_add_seq (&new_body, par_rlist);
10003 if (ctx->cancellable)
10004 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
10005 gimple_seq_add_seq (&new_body, par_olist);
10006 new_body = maybe_catch_exception (new_body);
10007 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
10008 gimple_omp_set_body (stmt, new_body);
10009
10010 bind = gimple_build_bind (NULL, NULL, gimple_bind_block (par_bind));
10011 gsi_replace (gsi_p, dep_bind ? dep_bind : bind, true);
10012 gimple_bind_add_seq (bind, ilist);
10013 gimple_bind_add_stmt (bind, stmt);
10014 gimple_bind_add_seq (bind, olist);
10015
10016 pop_gimplify_context (NULL);
10017
10018 if (dep_bind)
10019 {
10020 gimple_bind_add_seq (dep_bind, dep_ilist);
10021 gimple_bind_add_stmt (dep_bind, bind);
10022 gimple_bind_add_seq (dep_bind, dep_olist);
10023 pop_gimplify_context (dep_bind);
10024 }
10025 }
10026
10027 /* Lower the OpenMP target directive in the current statement
10028 in GSI_P. CTX holds context information for the directive. */
10029
10030 static void
10031 lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10032 {
10033 tree clauses;
10034 tree child_fn, t, c;
10035 gimple stmt = gsi_stmt (*gsi_p);
10036 gimple tgt_bind = NULL, bind;
10037 gimple_seq tgt_body = NULL, olist, ilist, new_body;
10038 location_t loc = gimple_location (stmt);
10039 int kind = gimple_omp_target_kind (stmt);
10040 unsigned int map_cnt = 0;
10041
10042 clauses = gimple_omp_target_clauses (stmt);
10043 if (kind == GF_OMP_TARGET_KIND_REGION)
10044 {
10045 tgt_bind = gimple_seq_first_stmt (gimple_omp_body (stmt));
10046 tgt_body = gimple_bind_body (tgt_bind);
10047 }
10048 else if (kind == GF_OMP_TARGET_KIND_DATA)
10049 tgt_body = gimple_omp_body (stmt);
10050 child_fn = ctx->cb.dst_fn;
10051
10052 push_gimplify_context ();
10053
10054 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
10055 switch (OMP_CLAUSE_CODE (c))
10056 {
10057 tree var, x;
10058
10059 default:
10060 break;
10061 case OMP_CLAUSE_MAP:
10062 case OMP_CLAUSE_TO:
10063 case OMP_CLAUSE_FROM:
10064 var = OMP_CLAUSE_DECL (c);
10065 if (!DECL_P (var))
10066 {
10067 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP
10068 || !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
10069 map_cnt++;
10070 continue;
10071 }
10072
10073 if (DECL_SIZE (var)
10074 && TREE_CODE (DECL_SIZE (var)) != INTEGER_CST)
10075 {
10076 tree var2 = DECL_VALUE_EXPR (var);
10077 gcc_assert (TREE_CODE (var2) == INDIRECT_REF);
10078 var2 = TREE_OPERAND (var2, 0);
10079 gcc_assert (DECL_P (var2));
10080 var = var2;
10081 }
10082
10083 if (!maybe_lookup_field (var, ctx))
10084 continue;
10085
10086 if (kind == GF_OMP_TARGET_KIND_REGION)
10087 {
10088 x = build_receiver_ref (var, true, ctx);
10089 tree new_var = lookup_decl (var, ctx);
10090 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
10091 && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER
10092 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
10093 && TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
10094 x = build_simple_mem_ref (x);
10095 SET_DECL_VALUE_EXPR (new_var, x);
10096 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
10097 }
10098 map_cnt++;
10099 }
10100
10101 if (kind == GF_OMP_TARGET_KIND_REGION)
10102 {
10103 target_nesting_level++;
10104 lower_omp (&tgt_body, ctx);
10105 target_nesting_level--;
10106 }
10107 else if (kind == GF_OMP_TARGET_KIND_DATA)
10108 lower_omp (&tgt_body, ctx);
10109
10110 if (kind == GF_OMP_TARGET_KIND_REGION)
10111 {
10112 /* Declare all the variables created by mapping and the variables
10113 declared in the scope of the target body. */
10114 record_vars_into (ctx->block_vars, child_fn);
10115 record_vars_into (gimple_bind_vars (tgt_bind), child_fn);
10116 }
10117
10118 olist = NULL;
10119 ilist = NULL;
10120 if (ctx->record_type)
10121 {
10122 ctx->sender_decl
10123 = create_tmp_var (ctx->record_type, ".omp_data_arr");
10124 DECL_NAMELESS (ctx->sender_decl) = 1;
10125 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
10126 t = make_tree_vec (3);
10127 TREE_VEC_ELT (t, 0) = ctx->sender_decl;
10128 TREE_VEC_ELT (t, 1)
10129 = create_tmp_var (build_array_type_nelts (size_type_node, map_cnt),
10130 ".omp_data_sizes");
10131 DECL_NAMELESS (TREE_VEC_ELT (t, 1)) = 1;
10132 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 1)) = 1;
10133 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 1;
10134 TREE_VEC_ELT (t, 2)
10135 = create_tmp_var (build_array_type_nelts (unsigned_char_type_node,
10136 map_cnt),
10137 ".omp_data_kinds");
10138 DECL_NAMELESS (TREE_VEC_ELT (t, 2)) = 1;
10139 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 2)) = 1;
10140 TREE_STATIC (TREE_VEC_ELT (t, 2)) = 1;
10141 gimple_omp_target_set_data_arg (stmt, t);
10142
10143 vec<constructor_elt, va_gc> *vsize;
10144 vec<constructor_elt, va_gc> *vkind;
10145 vec_alloc (vsize, map_cnt);
10146 vec_alloc (vkind, map_cnt);
10147 unsigned int map_idx = 0;
10148
10149 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
10150 switch (OMP_CLAUSE_CODE (c))
10151 {
10152 tree ovar, nc;
10153
10154 default:
10155 break;
10156 case OMP_CLAUSE_MAP:
10157 case OMP_CLAUSE_TO:
10158 case OMP_CLAUSE_FROM:
10159 nc = c;
10160 ovar = OMP_CLAUSE_DECL (c);
10161 if (!DECL_P (ovar))
10162 {
10163 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
10164 && OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
10165 {
10166 gcc_checking_assert (OMP_CLAUSE_DECL (OMP_CLAUSE_CHAIN (c))
10167 == get_base_address (ovar));
10168 nc = OMP_CLAUSE_CHAIN (c);
10169 ovar = OMP_CLAUSE_DECL (nc);
10170 }
10171 else
10172 {
10173 tree x = build_sender_ref (ovar, ctx);
10174 tree v
10175 = build_fold_addr_expr_with_type (ovar, ptr_type_node);
10176 gimplify_assign (x, v, &ilist);
10177 nc = NULL_TREE;
10178 }
10179 }
10180 else
10181 {
10182 if (DECL_SIZE (ovar)
10183 && TREE_CODE (DECL_SIZE (ovar)) != INTEGER_CST)
10184 {
10185 tree ovar2 = DECL_VALUE_EXPR (ovar);
10186 gcc_assert (TREE_CODE (ovar2) == INDIRECT_REF);
10187 ovar2 = TREE_OPERAND (ovar2, 0);
10188 gcc_assert (DECL_P (ovar2));
10189 ovar = ovar2;
10190 }
10191 if (!maybe_lookup_field (ovar, ctx))
10192 continue;
10193 }
10194
10195 unsigned int talign = TYPE_ALIGN_UNIT (TREE_TYPE (ovar));
10196 if (DECL_P (ovar) && DECL_ALIGN_UNIT (ovar) > talign)
10197 talign = DECL_ALIGN_UNIT (ovar);
10198 if (nc)
10199 {
10200 tree var = lookup_decl_in_outer_ctx (ovar, ctx);
10201 tree x = build_sender_ref (ovar, ctx);
10202 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
10203 && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER
10204 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
10205 && TREE_CODE (TREE_TYPE (ovar)) == ARRAY_TYPE)
10206 {
10207 gcc_assert (kind == GF_OMP_TARGET_KIND_REGION);
10208 tree avar
10209 = create_tmp_var (TREE_TYPE (TREE_TYPE (x)), NULL);
10210 mark_addressable (avar);
10211 gimplify_assign (avar, build_fold_addr_expr (var), &ilist);
10212 talign = DECL_ALIGN_UNIT (avar);
10213 avar = build_fold_addr_expr (avar);
10214 gimplify_assign (x, avar, &ilist);
10215 }
10216 else if (is_gimple_reg (var))
10217 {
10218 gcc_assert (kind == GF_OMP_TARGET_KIND_REGION);
10219 tree avar = create_tmp_var (TREE_TYPE (var), NULL);
10220 mark_addressable (avar);
10221 if (OMP_CLAUSE_MAP_KIND (c) != OMP_CLAUSE_MAP_ALLOC
10222 && OMP_CLAUSE_MAP_KIND (c) != OMP_CLAUSE_MAP_FROM)
10223 gimplify_assign (avar, var, &ilist);
10224 avar = build_fold_addr_expr (avar);
10225 gimplify_assign (x, avar, &ilist);
10226 if ((OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_FROM
10227 || OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_TOFROM)
10228 && !TYPE_READONLY (TREE_TYPE (var)))
10229 {
10230 x = build_sender_ref (ovar, ctx);
10231 x = build_simple_mem_ref (x);
10232 gimplify_assign (var, x, &olist);
10233 }
10234 }
10235 else
10236 {
10237 var = build_fold_addr_expr (var);
10238 gimplify_assign (x, var, &ilist);
10239 }
10240 }
10241 tree s = OMP_CLAUSE_SIZE (c);
10242 if (s == NULL_TREE)
10243 s = TYPE_SIZE_UNIT (TREE_TYPE (ovar));
10244 s = fold_convert (size_type_node, s);
10245 tree purpose = size_int (map_idx++);
10246 CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
10247 if (TREE_CODE (s) != INTEGER_CST)
10248 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 0;
10249
10250 unsigned char tkind = 0;
10251 switch (OMP_CLAUSE_CODE (c))
10252 {
10253 case OMP_CLAUSE_MAP:
10254 tkind = OMP_CLAUSE_MAP_KIND (c);
10255 break;
10256 case OMP_CLAUSE_TO:
10257 tkind = OMP_CLAUSE_MAP_TO;
10258 break;
10259 case OMP_CLAUSE_FROM:
10260 tkind = OMP_CLAUSE_MAP_FROM;
10261 break;
10262 default:
10263 gcc_unreachable ();
10264 }
10265 talign = ceil_log2 (talign);
10266 tkind |= talign << 3;
10267 CONSTRUCTOR_APPEND_ELT (vkind, purpose,
10268 build_int_cst (unsigned_char_type_node,
10269 tkind));
10270 if (nc && nc != c)
10271 c = nc;
10272 }
10273
10274 gcc_assert (map_idx == map_cnt);
10275
10276 DECL_INITIAL (TREE_VEC_ELT (t, 1))
10277 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)), vsize);
10278 DECL_INITIAL (TREE_VEC_ELT (t, 2))
10279 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 2)), vkind);
10280 if (!TREE_STATIC (TREE_VEC_ELT (t, 1)))
10281 {
10282 gimple_seq initlist = NULL;
10283 force_gimple_operand (build1 (DECL_EXPR, void_type_node,
10284 TREE_VEC_ELT (t, 1)),
10285 &initlist, true, NULL_TREE);
10286 gimple_seq_add_seq (&ilist, initlist);
10287
10288 tree clobber = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)),
10289 NULL);
10290 TREE_THIS_VOLATILE (clobber) = 1;
10291 gimple_seq_add_stmt (&olist,
10292 gimple_build_assign (TREE_VEC_ELT (t, 1),
10293 clobber));
10294 }
10295
10296 tree clobber = build_constructor (ctx->record_type, NULL);
10297 TREE_THIS_VOLATILE (clobber) = 1;
10298 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
10299 clobber));
10300 }
10301
10302 /* Once all the expansions are done, sequence all the different
10303 fragments inside gimple_omp_body. */
10304
10305 new_body = NULL;
10306
10307 if (ctx->record_type && kind == GF_OMP_TARGET_KIND_REGION)
10308 {
10309 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
10310 /* fixup_child_record_type might have changed receiver_decl's type. */
10311 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
10312 gimple_seq_add_stmt (&new_body,
10313 gimple_build_assign (ctx->receiver_decl, t));
10314 }
10315
10316 if (kind == GF_OMP_TARGET_KIND_REGION)
10317 {
10318 gimple_seq_add_seq (&new_body, tgt_body);
10319 new_body = maybe_catch_exception (new_body);
10320 }
10321 else if (kind == GF_OMP_TARGET_KIND_DATA)
10322 new_body = tgt_body;
10323 if (kind != GF_OMP_TARGET_KIND_UPDATE)
10324 {
10325 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
10326 gimple_omp_set_body (stmt, new_body);
10327 }
10328
10329 bind = gimple_build_bind (NULL, NULL,
10330 tgt_bind ? gimple_bind_block (tgt_bind)
10331 : NULL_TREE);
10332 gsi_replace (gsi_p, bind, true);
10333 gimple_bind_add_seq (bind, ilist);
10334 gimple_bind_add_stmt (bind, stmt);
10335 gimple_bind_add_seq (bind, olist);
10336
10337 pop_gimplify_context (NULL);
10338 }
10339
10340 /* Expand code for an OpenMP teams directive. */
10341
10342 static void
10343 lower_omp_teams (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10344 {
10345 gimple teams_stmt = gsi_stmt (*gsi_p);
10346 push_gimplify_context ();
10347
10348 tree block = make_node (BLOCK);
10349 gimple bind = gimple_build_bind (NULL, NULL, block);
10350 gsi_replace (gsi_p, bind, true);
10351 gimple_seq bind_body = NULL;
10352 gimple_seq dlist = NULL;
10353 gimple_seq olist = NULL;
10354
10355 tree num_teams = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
10356 OMP_CLAUSE_NUM_TEAMS);
10357 if (num_teams == NULL_TREE)
10358 num_teams = build_int_cst (unsigned_type_node, 0);
10359 else
10360 {
10361 num_teams = OMP_CLAUSE_NUM_TEAMS_EXPR (num_teams);
10362 num_teams = fold_convert (unsigned_type_node, num_teams);
10363 gimplify_expr (&num_teams, &bind_body, NULL, is_gimple_val, fb_rvalue);
10364 }
10365 tree thread_limit = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
10366 OMP_CLAUSE_THREAD_LIMIT);
10367 if (thread_limit == NULL_TREE)
10368 thread_limit = build_int_cst (unsigned_type_node, 0);
10369 else
10370 {
10371 thread_limit = OMP_CLAUSE_THREAD_LIMIT_EXPR (thread_limit);
10372 thread_limit = fold_convert (unsigned_type_node, thread_limit);
10373 gimplify_expr (&thread_limit, &bind_body, NULL, is_gimple_val,
10374 fb_rvalue);
10375 }
10376
10377 lower_rec_input_clauses (gimple_omp_teams_clauses (teams_stmt),
10378 &bind_body, &dlist, ctx, NULL);
10379 lower_omp (gimple_omp_body_ptr (teams_stmt), ctx);
10380 lower_reduction_clauses (gimple_omp_teams_clauses (teams_stmt), &olist, ctx);
10381 gimple_seq_add_stmt (&bind_body, teams_stmt);
10382
10383 location_t loc = gimple_location (teams_stmt);
10384 tree decl = builtin_decl_explicit (BUILT_IN_GOMP_TEAMS);
10385 gimple call = gimple_build_call (decl, 2, num_teams, thread_limit);
10386 gimple_set_location (call, loc);
10387 gimple_seq_add_stmt (&bind_body, call);
10388
10389 gimple_seq_add_seq (&bind_body, gimple_omp_body (teams_stmt));
10390 gimple_omp_set_body (teams_stmt, NULL);
10391 gimple_seq_add_seq (&bind_body, olist);
10392 gimple_seq_add_seq (&bind_body, dlist);
10393 gimple_seq_add_stmt (&bind_body, gimple_build_omp_return (true));
10394 gimple_bind_set_body (bind, bind_body);
10395
10396 pop_gimplify_context (bind);
10397
10398 gimple_bind_append_vars (bind, ctx->block_vars);
10399 BLOCK_VARS (block) = ctx->block_vars;
10400 if (BLOCK_VARS (block))
10401 TREE_USED (block) = 1;
10402 }
10403
10404
10405 /* Callback for lower_omp_1. Return non-NULL if *tp needs to be
10406 regimplified. If DATA is non-NULL, lower_omp_1 is outside
10407 of OpenMP context, but with task_shared_vars set. */
10408
10409 static tree
10410 lower_omp_regimplify_p (tree *tp, int *walk_subtrees,
10411 void *data)
10412 {
10413 tree t = *tp;
10414
10415 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
10416 if (TREE_CODE (t) == VAR_DECL && data == NULL && DECL_HAS_VALUE_EXPR_P (t))
10417 return t;
10418
10419 if (task_shared_vars
10420 && DECL_P (t)
10421 && bitmap_bit_p (task_shared_vars, DECL_UID (t)))
10422 return t;
10423
10424 /* If a global variable has been privatized, TREE_CONSTANT on
10425 ADDR_EXPR might be wrong. */
10426 if (data == NULL && TREE_CODE (t) == ADDR_EXPR)
10427 recompute_tree_invariant_for_addr_expr (t);
10428
10429 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
10430 return NULL_TREE;
10431 }
10432
10433 static void
10434 lower_omp_1 (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10435 {
10436 gimple stmt = gsi_stmt (*gsi_p);
10437 struct walk_stmt_info wi;
10438
10439 if (gimple_has_location (stmt))
10440 input_location = gimple_location (stmt);
10441
10442 if (task_shared_vars)
10443 memset (&wi, '\0', sizeof (wi));
10444
10445 /* If we have issued syntax errors, avoid doing any heavy lifting.
10446 Just replace the OpenMP directives with a NOP to avoid
10447 confusing RTL expansion. */
10448 if (seen_error () && is_gimple_omp (stmt))
10449 {
10450 gsi_replace (gsi_p, gimple_build_nop (), true);
10451 return;
10452 }
10453
10454 switch (gimple_code (stmt))
10455 {
10456 case GIMPLE_COND:
10457 if ((ctx || task_shared_vars)
10458 && (walk_tree (gimple_cond_lhs_ptr (stmt), lower_omp_regimplify_p,
10459 ctx ? NULL : &wi, NULL)
10460 || walk_tree (gimple_cond_rhs_ptr (stmt), lower_omp_regimplify_p,
10461 ctx ? NULL : &wi, NULL)))
10462 gimple_regimplify_operands (stmt, gsi_p);
10463 break;
10464 case GIMPLE_CATCH:
10465 lower_omp (gimple_catch_handler_ptr (stmt), ctx);
10466 break;
10467 case GIMPLE_EH_FILTER:
10468 lower_omp (gimple_eh_filter_failure_ptr (stmt), ctx);
10469 break;
10470 case GIMPLE_TRY:
10471 lower_omp (gimple_try_eval_ptr (stmt), ctx);
10472 lower_omp (gimple_try_cleanup_ptr (stmt), ctx);
10473 break;
10474 case GIMPLE_TRANSACTION:
10475 lower_omp (gimple_transaction_body_ptr (stmt), ctx);
10476 break;
10477 case GIMPLE_BIND:
10478 lower_omp (gimple_bind_body_ptr (stmt), ctx);
10479 break;
10480 case GIMPLE_OMP_PARALLEL:
10481 case GIMPLE_OMP_TASK:
10482 ctx = maybe_lookup_ctx (stmt);
10483 gcc_assert (ctx);
10484 if (ctx->cancellable)
10485 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
10486 lower_omp_taskreg (gsi_p, ctx);
10487 break;
10488 case GIMPLE_OMP_FOR:
10489 ctx = maybe_lookup_ctx (stmt);
10490 gcc_assert (ctx);
10491 if (ctx->cancellable)
10492 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
10493 lower_omp_for (gsi_p, ctx);
10494 break;
10495 case GIMPLE_OMP_SECTIONS:
10496 ctx = maybe_lookup_ctx (stmt);
10497 gcc_assert (ctx);
10498 if (ctx->cancellable)
10499 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
10500 lower_omp_sections (gsi_p, ctx);
10501 break;
10502 case GIMPLE_OMP_SINGLE:
10503 ctx = maybe_lookup_ctx (stmt);
10504 gcc_assert (ctx);
10505 lower_omp_single (gsi_p, ctx);
10506 break;
10507 case GIMPLE_OMP_MASTER:
10508 ctx = maybe_lookup_ctx (stmt);
10509 gcc_assert (ctx);
10510 lower_omp_master (gsi_p, ctx);
10511 break;
10512 case GIMPLE_OMP_TASKGROUP:
10513 ctx = maybe_lookup_ctx (stmt);
10514 gcc_assert (ctx);
10515 lower_omp_taskgroup (gsi_p, ctx);
10516 break;
10517 case GIMPLE_OMP_ORDERED:
10518 ctx = maybe_lookup_ctx (stmt);
10519 gcc_assert (ctx);
10520 lower_omp_ordered (gsi_p, ctx);
10521 break;
10522 case GIMPLE_OMP_CRITICAL:
10523 ctx = maybe_lookup_ctx (stmt);
10524 gcc_assert (ctx);
10525 lower_omp_critical (gsi_p, ctx);
10526 break;
10527 case GIMPLE_OMP_ATOMIC_LOAD:
10528 if ((ctx || task_shared_vars)
10529 && walk_tree (gimple_omp_atomic_load_rhs_ptr (stmt),
10530 lower_omp_regimplify_p, ctx ? NULL : &wi, NULL))
10531 gimple_regimplify_operands (stmt, gsi_p);
10532 break;
10533 case GIMPLE_OMP_TARGET:
10534 ctx = maybe_lookup_ctx (stmt);
10535 gcc_assert (ctx);
10536 lower_omp_target (gsi_p, ctx);
10537 break;
10538 case GIMPLE_OMP_TEAMS:
10539 ctx = maybe_lookup_ctx (stmt);
10540 gcc_assert (ctx);
10541 lower_omp_teams (gsi_p, ctx);
10542 break;
10543 case GIMPLE_CALL:
10544 tree fndecl;
10545 fndecl = gimple_call_fndecl (stmt);
10546 if (fndecl
10547 && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
10548 switch (DECL_FUNCTION_CODE (fndecl))
10549 {
10550 case BUILT_IN_GOMP_BARRIER:
10551 if (ctx == NULL)
10552 break;
10553 /* FALLTHRU */
10554 case BUILT_IN_GOMP_CANCEL:
10555 case BUILT_IN_GOMP_CANCELLATION_POINT:
10556 omp_context *cctx;
10557 cctx = ctx;
10558 if (gimple_code (cctx->stmt) == GIMPLE_OMP_SECTION)
10559 cctx = cctx->outer;
10560 gcc_assert (gimple_call_lhs (stmt) == NULL_TREE);
10561 if (!cctx->cancellable)
10562 {
10563 if (DECL_FUNCTION_CODE (fndecl)
10564 == BUILT_IN_GOMP_CANCELLATION_POINT)
10565 {
10566 stmt = gimple_build_nop ();
10567 gsi_replace (gsi_p, stmt, false);
10568 }
10569 break;
10570 }
10571 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_GOMP_BARRIER)
10572 {
10573 fndecl = builtin_decl_explicit (BUILT_IN_GOMP_BARRIER_CANCEL);
10574 gimple_call_set_fndecl (stmt, fndecl);
10575 gimple_call_set_fntype (stmt, TREE_TYPE (fndecl));
10576 }
10577 tree lhs;
10578 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (fndecl)), NULL);
10579 gimple_call_set_lhs (stmt, lhs);
10580 tree fallthru_label;
10581 fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
10582 gimple g;
10583 g = gimple_build_label (fallthru_label);
10584 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
10585 g = gimple_build_cond (NE_EXPR, lhs,
10586 fold_convert (TREE_TYPE (lhs),
10587 boolean_false_node),
10588 cctx->cancel_label, fallthru_label);
10589 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
10590 break;
10591 default:
10592 break;
10593 }
10594 /* FALLTHRU */
10595 default:
10596 if ((ctx || task_shared_vars)
10597 && walk_gimple_op (stmt, lower_omp_regimplify_p,
10598 ctx ? NULL : &wi))
10599 {
10600 /* Just remove clobbers, this should happen only if we have
10601 "privatized" local addressable variables in SIMD regions,
10602 the clobber isn't needed in that case and gimplifying address
10603 of the ARRAY_REF into a pointer and creating MEM_REF based
10604 clobber would create worse code than we get with the clobber
10605 dropped. */
10606 if (gimple_clobber_p (stmt))
10607 {
10608 gsi_replace (gsi_p, gimple_build_nop (), true);
10609 break;
10610 }
10611 gimple_regimplify_operands (stmt, gsi_p);
10612 }
10613 break;
10614 }
10615 }
10616
10617 static void
10618 lower_omp (gimple_seq *body, omp_context *ctx)
10619 {
10620 location_t saved_location = input_location;
10621 gimple_stmt_iterator gsi;
10622 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
10623 lower_omp_1 (&gsi, ctx);
10624 /* During gimplification, we have not always invoked fold_stmt
10625 (gimplify.c:maybe_fold_stmt); call it now. */
10626 if (target_nesting_level)
10627 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
10628 fold_stmt (&gsi);
10629 input_location = saved_location;
10630 }
10631 \f
10632 /* Main entry point. */
10633
10634 static unsigned int
10635 execute_lower_omp (void)
10636 {
10637 gimple_seq body;
10638 int i;
10639 omp_context *ctx;
10640
10641 /* This pass always runs, to provide PROP_gimple_lomp.
10642 But there is nothing to do unless -fopenmp is given. */
10643 if (flag_openmp == 0 && flag_openmp_simd == 0 && flag_cilkplus == 0)
10644 return 0;
10645
10646 all_contexts = splay_tree_new (splay_tree_compare_pointers, 0,
10647 delete_omp_context);
10648
10649 body = gimple_body (current_function_decl);
10650 scan_omp (&body, NULL);
10651 gcc_assert (taskreg_nesting_level == 0);
10652 FOR_EACH_VEC_ELT (taskreg_contexts, i, ctx)
10653 finish_taskreg_scan (ctx);
10654 taskreg_contexts.release ();
10655
10656 if (all_contexts->root)
10657 {
10658 if (task_shared_vars)
10659 push_gimplify_context ();
10660 lower_omp (&body, NULL);
10661 if (task_shared_vars)
10662 pop_gimplify_context (NULL);
10663 }
10664
10665 if (all_contexts)
10666 {
10667 splay_tree_delete (all_contexts);
10668 all_contexts = NULL;
10669 }
10670 BITMAP_FREE (task_shared_vars);
10671 return 0;
10672 }
10673
10674 namespace {
10675
10676 const pass_data pass_data_lower_omp =
10677 {
10678 GIMPLE_PASS, /* type */
10679 "omplower", /* name */
10680 OPTGROUP_NONE, /* optinfo_flags */
10681 TV_NONE, /* tv_id */
10682 PROP_gimple_any, /* properties_required */
10683 PROP_gimple_lomp, /* properties_provided */
10684 0, /* properties_destroyed */
10685 0, /* todo_flags_start */
10686 0, /* todo_flags_finish */
10687 };
10688
10689 class pass_lower_omp : public gimple_opt_pass
10690 {
10691 public:
10692 pass_lower_omp (gcc::context *ctxt)
10693 : gimple_opt_pass (pass_data_lower_omp, ctxt)
10694 {}
10695
10696 /* opt_pass methods: */
10697 virtual unsigned int execute (function *) { return execute_lower_omp (); }
10698
10699 }; // class pass_lower_omp
10700
10701 } // anon namespace
10702
10703 gimple_opt_pass *
10704 make_pass_lower_omp (gcc::context *ctxt)
10705 {
10706 return new pass_lower_omp (ctxt);
10707 }
10708 \f
10709 /* The following is a utility to diagnose OpenMP structured block violations.
10710 It is not part of the "omplower" pass, as that's invoked too late. It
10711 should be invoked by the respective front ends after gimplification. */
10712
10713 static splay_tree all_labels;
10714
10715 /* Check for mismatched contexts and generate an error if needed. Return
10716 true if an error is detected. */
10717
10718 static bool
10719 diagnose_sb_0 (gimple_stmt_iterator *gsi_p,
10720 gimple branch_ctx, gimple label_ctx)
10721 {
10722 if (label_ctx == branch_ctx)
10723 return false;
10724
10725
10726 /*
10727 Previously we kept track of the label's entire context in diagnose_sb_[12]
10728 so we could traverse it and issue a correct "exit" or "enter" error
10729 message upon a structured block violation.
10730
10731 We built the context by building a list with tree_cons'ing, but there is
10732 no easy counterpart in gimple tuples. It seems like far too much work
10733 for issuing exit/enter error messages. If someone really misses the
10734 distinct error message... patches welcome.
10735 */
10736
10737 #if 0
10738 /* Try to avoid confusing the user by producing and error message
10739 with correct "exit" or "enter" verbiage. We prefer "exit"
10740 unless we can show that LABEL_CTX is nested within BRANCH_CTX. */
10741 if (branch_ctx == NULL)
10742 exit_p = false;
10743 else
10744 {
10745 while (label_ctx)
10746 {
10747 if (TREE_VALUE (label_ctx) == branch_ctx)
10748 {
10749 exit_p = false;
10750 break;
10751 }
10752 label_ctx = TREE_CHAIN (label_ctx);
10753 }
10754 }
10755
10756 if (exit_p)
10757 error ("invalid exit from OpenMP structured block");
10758 else
10759 error ("invalid entry to OpenMP structured block");
10760 #endif
10761
10762 bool cilkplus_block = false;
10763 if (flag_cilkplus)
10764 {
10765 if ((branch_ctx
10766 && gimple_code (branch_ctx) == GIMPLE_OMP_FOR
10767 && gimple_omp_for_kind (branch_ctx) == GF_OMP_FOR_KIND_CILKSIMD)
10768 || (label_ctx
10769 && gimple_code (label_ctx) == GIMPLE_OMP_FOR
10770 && gimple_omp_for_kind (label_ctx) == GF_OMP_FOR_KIND_CILKSIMD))
10771 cilkplus_block = true;
10772 }
10773
10774 /* If it's obvious we have an invalid entry, be specific about the error. */
10775 if (branch_ctx == NULL)
10776 {
10777 if (cilkplus_block)
10778 error ("invalid entry to Cilk Plus structured block");
10779 else
10780 error ("invalid entry to OpenMP structured block");
10781 }
10782 else
10783 {
10784 /* Otherwise, be vague and lazy, but efficient. */
10785 if (cilkplus_block)
10786 error ("invalid branch to/from a Cilk Plus structured block");
10787 else
10788 error ("invalid branch to/from an OpenMP structured block");
10789 }
10790
10791 gsi_replace (gsi_p, gimple_build_nop (), false);
10792 return true;
10793 }
10794
10795 /* Pass 1: Create a minimal tree of OpenMP structured blocks, and record
10796 where each label is found. */
10797
10798 static tree
10799 diagnose_sb_1 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
10800 struct walk_stmt_info *wi)
10801 {
10802 gimple context = (gimple) wi->info;
10803 gimple inner_context;
10804 gimple stmt = gsi_stmt (*gsi_p);
10805
10806 *handled_ops_p = true;
10807
10808 switch (gimple_code (stmt))
10809 {
10810 WALK_SUBSTMTS;
10811
10812 case GIMPLE_OMP_PARALLEL:
10813 case GIMPLE_OMP_TASK:
10814 case GIMPLE_OMP_SECTIONS:
10815 case GIMPLE_OMP_SINGLE:
10816 case GIMPLE_OMP_SECTION:
10817 case GIMPLE_OMP_MASTER:
10818 case GIMPLE_OMP_ORDERED:
10819 case GIMPLE_OMP_CRITICAL:
10820 case GIMPLE_OMP_TARGET:
10821 case GIMPLE_OMP_TEAMS:
10822 case GIMPLE_OMP_TASKGROUP:
10823 /* The minimal context here is just the current OMP construct. */
10824 inner_context = stmt;
10825 wi->info = inner_context;
10826 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
10827 wi->info = context;
10828 break;
10829
10830 case GIMPLE_OMP_FOR:
10831 inner_context = stmt;
10832 wi->info = inner_context;
10833 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
10834 walk them. */
10835 walk_gimple_seq (gimple_omp_for_pre_body (stmt),
10836 diagnose_sb_1, NULL, wi);
10837 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
10838 wi->info = context;
10839 break;
10840
10841 case GIMPLE_LABEL:
10842 splay_tree_insert (all_labels, (splay_tree_key) gimple_label_label (stmt),
10843 (splay_tree_value) context);
10844 break;
10845
10846 default:
10847 break;
10848 }
10849
10850 return NULL_TREE;
10851 }
10852
10853 /* Pass 2: Check each branch and see if its context differs from that of
10854 the destination label's context. */
10855
10856 static tree
10857 diagnose_sb_2 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
10858 struct walk_stmt_info *wi)
10859 {
10860 gimple context = (gimple) wi->info;
10861 splay_tree_node n;
10862 gimple stmt = gsi_stmt (*gsi_p);
10863
10864 *handled_ops_p = true;
10865
10866 switch (gimple_code (stmt))
10867 {
10868 WALK_SUBSTMTS;
10869
10870 case GIMPLE_OMP_PARALLEL:
10871 case GIMPLE_OMP_TASK:
10872 case GIMPLE_OMP_SECTIONS:
10873 case GIMPLE_OMP_SINGLE:
10874 case GIMPLE_OMP_SECTION:
10875 case GIMPLE_OMP_MASTER:
10876 case GIMPLE_OMP_ORDERED:
10877 case GIMPLE_OMP_CRITICAL:
10878 case GIMPLE_OMP_TARGET:
10879 case GIMPLE_OMP_TEAMS:
10880 case GIMPLE_OMP_TASKGROUP:
10881 wi->info = stmt;
10882 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
10883 wi->info = context;
10884 break;
10885
10886 case GIMPLE_OMP_FOR:
10887 wi->info = stmt;
10888 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
10889 walk them. */
10890 walk_gimple_seq_mod (gimple_omp_for_pre_body_ptr (stmt),
10891 diagnose_sb_2, NULL, wi);
10892 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
10893 wi->info = context;
10894 break;
10895
10896 case GIMPLE_COND:
10897 {
10898 tree lab = gimple_cond_true_label (stmt);
10899 if (lab)
10900 {
10901 n = splay_tree_lookup (all_labels,
10902 (splay_tree_key) lab);
10903 diagnose_sb_0 (gsi_p, context,
10904 n ? (gimple) n->value : NULL);
10905 }
10906 lab = gimple_cond_false_label (stmt);
10907 if (lab)
10908 {
10909 n = splay_tree_lookup (all_labels,
10910 (splay_tree_key) lab);
10911 diagnose_sb_0 (gsi_p, context,
10912 n ? (gimple) n->value : NULL);
10913 }
10914 }
10915 break;
10916
10917 case GIMPLE_GOTO:
10918 {
10919 tree lab = gimple_goto_dest (stmt);
10920 if (TREE_CODE (lab) != LABEL_DECL)
10921 break;
10922
10923 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
10924 diagnose_sb_0 (gsi_p, context, n ? (gimple) n->value : NULL);
10925 }
10926 break;
10927
10928 case GIMPLE_SWITCH:
10929 {
10930 unsigned int i;
10931 for (i = 0; i < gimple_switch_num_labels (stmt); ++i)
10932 {
10933 tree lab = CASE_LABEL (gimple_switch_label (stmt, i));
10934 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
10935 if (n && diagnose_sb_0 (gsi_p, context, (gimple) n->value))
10936 break;
10937 }
10938 }
10939 break;
10940
10941 case GIMPLE_RETURN:
10942 diagnose_sb_0 (gsi_p, context, NULL);
10943 break;
10944
10945 default:
10946 break;
10947 }
10948
10949 return NULL_TREE;
10950 }
10951
10952 /* Called from tree-cfg.c::make_edges to create cfg edges for all GIMPLE_OMP
10953 codes. */
10954 bool
10955 make_gimple_omp_edges (basic_block bb, struct omp_region **region,
10956 int *region_idx)
10957 {
10958 gimple last = last_stmt (bb);
10959 enum gimple_code code = gimple_code (last);
10960 struct omp_region *cur_region = *region;
10961 bool fallthru = false;
10962
10963 switch (code)
10964 {
10965 case GIMPLE_OMP_PARALLEL:
10966 case GIMPLE_OMP_TASK:
10967 case GIMPLE_OMP_FOR:
10968 case GIMPLE_OMP_SINGLE:
10969 case GIMPLE_OMP_TEAMS:
10970 case GIMPLE_OMP_MASTER:
10971 case GIMPLE_OMP_TASKGROUP:
10972 case GIMPLE_OMP_ORDERED:
10973 case GIMPLE_OMP_CRITICAL:
10974 case GIMPLE_OMP_SECTION:
10975 cur_region = new_omp_region (bb, code, cur_region);
10976 fallthru = true;
10977 break;
10978
10979 case GIMPLE_OMP_TARGET:
10980 cur_region = new_omp_region (bb, code, cur_region);
10981 fallthru = true;
10982 if (gimple_omp_target_kind (last) == GF_OMP_TARGET_KIND_UPDATE)
10983 cur_region = cur_region->outer;
10984 break;
10985
10986 case GIMPLE_OMP_SECTIONS:
10987 cur_region = new_omp_region (bb, code, cur_region);
10988 fallthru = true;
10989 break;
10990
10991 case GIMPLE_OMP_SECTIONS_SWITCH:
10992 fallthru = false;
10993 break;
10994
10995 case GIMPLE_OMP_ATOMIC_LOAD:
10996 case GIMPLE_OMP_ATOMIC_STORE:
10997 fallthru = true;
10998 break;
10999
11000 case GIMPLE_OMP_RETURN:
11001 /* In the case of a GIMPLE_OMP_SECTION, the edge will go
11002 somewhere other than the next block. This will be
11003 created later. */
11004 cur_region->exit = bb;
11005 fallthru = cur_region->type != GIMPLE_OMP_SECTION;
11006 cur_region = cur_region->outer;
11007 break;
11008
11009 case GIMPLE_OMP_CONTINUE:
11010 cur_region->cont = bb;
11011 switch (cur_region->type)
11012 {
11013 case GIMPLE_OMP_FOR:
11014 /* Mark all GIMPLE_OMP_FOR and GIMPLE_OMP_CONTINUE
11015 succs edges as abnormal to prevent splitting
11016 them. */
11017 single_succ_edge (cur_region->entry)->flags |= EDGE_ABNORMAL;
11018 /* Make the loopback edge. */
11019 make_edge (bb, single_succ (cur_region->entry),
11020 EDGE_ABNORMAL);
11021
11022 /* Create an edge from GIMPLE_OMP_FOR to exit, which
11023 corresponds to the case that the body of the loop
11024 is not executed at all. */
11025 make_edge (cur_region->entry, bb->next_bb, EDGE_ABNORMAL);
11026 make_edge (bb, bb->next_bb, EDGE_FALLTHRU | EDGE_ABNORMAL);
11027 fallthru = false;
11028 break;
11029
11030 case GIMPLE_OMP_SECTIONS:
11031 /* Wire up the edges into and out of the nested sections. */
11032 {
11033 basic_block switch_bb = single_succ (cur_region->entry);
11034
11035 struct omp_region *i;
11036 for (i = cur_region->inner; i ; i = i->next)
11037 {
11038 gcc_assert (i->type == GIMPLE_OMP_SECTION);
11039 make_edge (switch_bb, i->entry, 0);
11040 make_edge (i->exit, bb, EDGE_FALLTHRU);
11041 }
11042
11043 /* Make the loopback edge to the block with
11044 GIMPLE_OMP_SECTIONS_SWITCH. */
11045 make_edge (bb, switch_bb, 0);
11046
11047 /* Make the edge from the switch to exit. */
11048 make_edge (switch_bb, bb->next_bb, 0);
11049 fallthru = false;
11050 }
11051 break;
11052
11053 default:
11054 gcc_unreachable ();
11055 }
11056 break;
11057
11058 default:
11059 gcc_unreachable ();
11060 }
11061
11062 if (*region != cur_region)
11063 {
11064 *region = cur_region;
11065 if (cur_region)
11066 *region_idx = cur_region->entry->index;
11067 else
11068 *region_idx = 0;
11069 }
11070
11071 return fallthru;
11072 }
11073
11074 static unsigned int
11075 diagnose_omp_structured_block_errors (void)
11076 {
11077 struct walk_stmt_info wi;
11078 gimple_seq body = gimple_body (current_function_decl);
11079
11080 all_labels = splay_tree_new (splay_tree_compare_pointers, 0, 0);
11081
11082 memset (&wi, 0, sizeof (wi));
11083 walk_gimple_seq (body, diagnose_sb_1, NULL, &wi);
11084
11085 memset (&wi, 0, sizeof (wi));
11086 wi.want_locations = true;
11087 walk_gimple_seq_mod (&body, diagnose_sb_2, NULL, &wi);
11088
11089 gimple_set_body (current_function_decl, body);
11090
11091 splay_tree_delete (all_labels);
11092 all_labels = NULL;
11093
11094 return 0;
11095 }
11096
11097 namespace {
11098
11099 const pass_data pass_data_diagnose_omp_blocks =
11100 {
11101 GIMPLE_PASS, /* type */
11102 "*diagnose_omp_blocks", /* name */
11103 OPTGROUP_NONE, /* optinfo_flags */
11104 TV_NONE, /* tv_id */
11105 PROP_gimple_any, /* properties_required */
11106 0, /* properties_provided */
11107 0, /* properties_destroyed */
11108 0, /* todo_flags_start */
11109 0, /* todo_flags_finish */
11110 };
11111
11112 class pass_diagnose_omp_blocks : public gimple_opt_pass
11113 {
11114 public:
11115 pass_diagnose_omp_blocks (gcc::context *ctxt)
11116 : gimple_opt_pass (pass_data_diagnose_omp_blocks, ctxt)
11117 {}
11118
11119 /* opt_pass methods: */
11120 virtual bool gate (function *) { return flag_openmp || flag_cilkplus; }
11121 virtual unsigned int execute (function *)
11122 {
11123 return diagnose_omp_structured_block_errors ();
11124 }
11125
11126 }; // class pass_diagnose_omp_blocks
11127
11128 } // anon namespace
11129
11130 gimple_opt_pass *
11131 make_pass_diagnose_omp_blocks (gcc::context *ctxt)
11132 {
11133 return new pass_diagnose_omp_blocks (ctxt);
11134 }
11135 \f
11136 /* SIMD clone supporting code. */
11137
11138 /* Allocate a fresh `simd_clone' and return it. NARGS is the number
11139 of arguments to reserve space for. */
11140
11141 static struct cgraph_simd_clone *
11142 simd_clone_struct_alloc (int nargs)
11143 {
11144 struct cgraph_simd_clone *clone_info;
11145 size_t len = (sizeof (struct cgraph_simd_clone)
11146 + nargs * sizeof (struct cgraph_simd_clone_arg));
11147 clone_info = (struct cgraph_simd_clone *)
11148 ggc_internal_cleared_alloc (len);
11149 return clone_info;
11150 }
11151
11152 /* Make a copy of the `struct cgraph_simd_clone' in FROM to TO. */
11153
11154 static inline void
11155 simd_clone_struct_copy (struct cgraph_simd_clone *to,
11156 struct cgraph_simd_clone *from)
11157 {
11158 memcpy (to, from, (sizeof (struct cgraph_simd_clone)
11159 + ((from->nargs - from->inbranch)
11160 * sizeof (struct cgraph_simd_clone_arg))));
11161 }
11162
11163 /* Return vector of parameter types of function FNDECL. This uses
11164 TYPE_ARG_TYPES if available, otherwise falls back to types of
11165 DECL_ARGUMENTS types. */
11166
11167 vec<tree>
11168 simd_clone_vector_of_formal_parm_types (tree fndecl)
11169 {
11170 if (TYPE_ARG_TYPES (TREE_TYPE (fndecl)))
11171 return ipa_get_vector_of_formal_parm_types (TREE_TYPE (fndecl));
11172 vec<tree> args = ipa_get_vector_of_formal_parms (fndecl);
11173 unsigned int i;
11174 tree arg;
11175 FOR_EACH_VEC_ELT (args, i, arg)
11176 args[i] = TREE_TYPE (args[i]);
11177 return args;
11178 }
11179
11180 /* Given a simd function in NODE, extract the simd specific
11181 information from the OMP clauses passed in CLAUSES, and return
11182 the struct cgraph_simd_clone * if it should be cloned. *INBRANCH_SPECIFIED
11183 is set to TRUE if the `inbranch' or `notinbranch' clause specified,
11184 otherwise set to FALSE. */
11185
11186 static struct cgraph_simd_clone *
11187 simd_clone_clauses_extract (struct cgraph_node *node, tree clauses,
11188 bool *inbranch_specified)
11189 {
11190 vec<tree> args = simd_clone_vector_of_formal_parm_types (node->decl);
11191 tree t;
11192 int n;
11193 *inbranch_specified = false;
11194
11195 n = args.length ();
11196 if (n > 0 && args.last () == void_type_node)
11197 n--;
11198
11199 /* To distinguish from an OpenMP simd clone, Cilk Plus functions to
11200 be cloned have a distinctive artificial label in addition to "omp
11201 declare simd". */
11202 bool cilk_clone
11203 = (flag_cilkplus
11204 && lookup_attribute ("cilk simd function",
11205 DECL_ATTRIBUTES (node->decl)));
11206
11207 /* Allocate one more than needed just in case this is an in-branch
11208 clone which will require a mask argument. */
11209 struct cgraph_simd_clone *clone_info = simd_clone_struct_alloc (n + 1);
11210 clone_info->nargs = n;
11211 clone_info->cilk_elemental = cilk_clone;
11212
11213 if (!clauses)
11214 {
11215 args.release ();
11216 return clone_info;
11217 }
11218 clauses = TREE_VALUE (clauses);
11219 if (!clauses || TREE_CODE (clauses) != OMP_CLAUSE)
11220 return clone_info;
11221
11222 for (t = clauses; t; t = OMP_CLAUSE_CHAIN (t))
11223 {
11224 switch (OMP_CLAUSE_CODE (t))
11225 {
11226 case OMP_CLAUSE_INBRANCH:
11227 clone_info->inbranch = 1;
11228 *inbranch_specified = true;
11229 break;
11230 case OMP_CLAUSE_NOTINBRANCH:
11231 clone_info->inbranch = 0;
11232 *inbranch_specified = true;
11233 break;
11234 case OMP_CLAUSE_SIMDLEN:
11235 clone_info->simdlen
11236 = TREE_INT_CST_LOW (OMP_CLAUSE_SIMDLEN_EXPR (t));
11237 break;
11238 case OMP_CLAUSE_LINEAR:
11239 {
11240 tree decl = OMP_CLAUSE_DECL (t);
11241 tree step = OMP_CLAUSE_LINEAR_STEP (t);
11242 int argno = TREE_INT_CST_LOW (decl);
11243 if (OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (t))
11244 {
11245 clone_info->args[argno].arg_type
11246 = SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP;
11247 clone_info->args[argno].linear_step = tree_to_shwi (step);
11248 gcc_assert (clone_info->args[argno].linear_step >= 0
11249 && clone_info->args[argno].linear_step < n);
11250 }
11251 else
11252 {
11253 if (POINTER_TYPE_P (args[argno]))
11254 step = fold_convert (ssizetype, step);
11255 if (!tree_fits_shwi_p (step))
11256 {
11257 warning_at (OMP_CLAUSE_LOCATION (t), 0,
11258 "ignoring large linear step");
11259 args.release ();
11260 return NULL;
11261 }
11262 else if (integer_zerop (step))
11263 {
11264 warning_at (OMP_CLAUSE_LOCATION (t), 0,
11265 "ignoring zero linear step");
11266 args.release ();
11267 return NULL;
11268 }
11269 else
11270 {
11271 clone_info->args[argno].arg_type
11272 = SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP;
11273 clone_info->args[argno].linear_step = tree_to_shwi (step);
11274 }
11275 }
11276 break;
11277 }
11278 case OMP_CLAUSE_UNIFORM:
11279 {
11280 tree decl = OMP_CLAUSE_DECL (t);
11281 int argno = tree_to_uhwi (decl);
11282 clone_info->args[argno].arg_type
11283 = SIMD_CLONE_ARG_TYPE_UNIFORM;
11284 break;
11285 }
11286 case OMP_CLAUSE_ALIGNED:
11287 {
11288 tree decl = OMP_CLAUSE_DECL (t);
11289 int argno = tree_to_uhwi (decl);
11290 clone_info->args[argno].alignment
11291 = TREE_INT_CST_LOW (OMP_CLAUSE_ALIGNED_ALIGNMENT (t));
11292 break;
11293 }
11294 default:
11295 break;
11296 }
11297 }
11298 args.release ();
11299 return clone_info;
11300 }
11301
11302 /* Given a SIMD clone in NODE, calculate the characteristic data
11303 type and return the coresponding type. The characteristic data
11304 type is computed as described in the Intel Vector ABI. */
11305
11306 static tree
11307 simd_clone_compute_base_data_type (struct cgraph_node *node,
11308 struct cgraph_simd_clone *clone_info)
11309 {
11310 tree type = integer_type_node;
11311 tree fndecl = node->decl;
11312
11313 /* a) For non-void function, the characteristic data type is the
11314 return type. */
11315 if (TREE_CODE (TREE_TYPE (TREE_TYPE (fndecl))) != VOID_TYPE)
11316 type = TREE_TYPE (TREE_TYPE (fndecl));
11317
11318 /* b) If the function has any non-uniform, non-linear parameters,
11319 then the characteristic data type is the type of the first
11320 such parameter. */
11321 else
11322 {
11323 vec<tree> map = simd_clone_vector_of_formal_parm_types (fndecl);
11324 for (unsigned int i = 0; i < clone_info->nargs; ++i)
11325 if (clone_info->args[i].arg_type == SIMD_CLONE_ARG_TYPE_VECTOR)
11326 {
11327 type = map[i];
11328 break;
11329 }
11330 map.release ();
11331 }
11332
11333 /* c) If the characteristic data type determined by a) or b) above
11334 is struct, union, or class type which is pass-by-value (except
11335 for the type that maps to the built-in complex data type), the
11336 characteristic data type is int. */
11337 if (RECORD_OR_UNION_TYPE_P (type)
11338 && !aggregate_value_p (type, NULL)
11339 && TREE_CODE (type) != COMPLEX_TYPE)
11340 return integer_type_node;
11341
11342 /* d) If none of the above three classes is applicable, the
11343 characteristic data type is int. */
11344
11345 return type;
11346
11347 /* e) For Intel Xeon Phi native and offload compilation, if the
11348 resulting characteristic data type is 8-bit or 16-bit integer
11349 data type, the characteristic data type is int. */
11350 /* Well, we don't handle Xeon Phi yet. */
11351 }
11352
11353 static tree
11354 simd_clone_mangle (struct cgraph_node *node,
11355 struct cgraph_simd_clone *clone_info)
11356 {
11357 char vecsize_mangle = clone_info->vecsize_mangle;
11358 char mask = clone_info->inbranch ? 'M' : 'N';
11359 unsigned int simdlen = clone_info->simdlen;
11360 unsigned int n;
11361 pretty_printer pp;
11362
11363 gcc_assert (vecsize_mangle && simdlen);
11364
11365 pp_string (&pp, "_ZGV");
11366 pp_character (&pp, vecsize_mangle);
11367 pp_character (&pp, mask);
11368 pp_decimal_int (&pp, simdlen);
11369
11370 for (n = 0; n < clone_info->nargs; ++n)
11371 {
11372 struct cgraph_simd_clone_arg arg = clone_info->args[n];
11373
11374 if (arg.arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM)
11375 pp_character (&pp, 'u');
11376 else if (arg.arg_type == SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP)
11377 {
11378 gcc_assert (arg.linear_step != 0);
11379 pp_character (&pp, 'l');
11380 if (arg.linear_step > 1)
11381 pp_unsigned_wide_integer (&pp, arg.linear_step);
11382 else if (arg.linear_step < 0)
11383 {
11384 pp_character (&pp, 'n');
11385 pp_unsigned_wide_integer (&pp, (-(unsigned HOST_WIDE_INT)
11386 arg.linear_step));
11387 }
11388 }
11389 else if (arg.arg_type == SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP)
11390 {
11391 pp_character (&pp, 's');
11392 pp_unsigned_wide_integer (&pp, arg.linear_step);
11393 }
11394 else
11395 pp_character (&pp, 'v');
11396 if (arg.alignment)
11397 {
11398 pp_character (&pp, 'a');
11399 pp_decimal_int (&pp, arg.alignment);
11400 }
11401 }
11402
11403 pp_underscore (&pp);
11404 pp_string (&pp,
11405 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (node->decl)));
11406 const char *str = pp_formatted_text (&pp);
11407
11408 /* If there already is a SIMD clone with the same mangled name, don't
11409 add another one. This can happen e.g. for
11410 #pragma omp declare simd
11411 #pragma omp declare simd simdlen(8)
11412 int foo (int, int);
11413 if the simdlen is assumed to be 8 for the first one, etc. */
11414 for (struct cgraph_node *clone = node->simd_clones; clone;
11415 clone = clone->simdclone->next_clone)
11416 if (strcmp (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (clone->decl)),
11417 str) == 0)
11418 return NULL_TREE;
11419
11420 return get_identifier (str);
11421 }
11422
11423 /* Create a simd clone of OLD_NODE and return it. */
11424
11425 static struct cgraph_node *
11426 simd_clone_create (struct cgraph_node *old_node)
11427 {
11428 struct cgraph_node *new_node;
11429 if (old_node->definition)
11430 {
11431 if (!old_node->has_gimple_body_p ())
11432 return NULL;
11433 old_node->get_body ();
11434 new_node = old_node->create_version_clone_with_body (vNULL, NULL, NULL,
11435 false, NULL, NULL,
11436 "simdclone");
11437 }
11438 else
11439 {
11440 tree old_decl = old_node->decl;
11441 tree new_decl = copy_node (old_node->decl);
11442 DECL_NAME (new_decl) = clone_function_name (old_decl, "simdclone");
11443 SET_DECL_ASSEMBLER_NAME (new_decl, DECL_NAME (new_decl));
11444 SET_DECL_RTL (new_decl, NULL);
11445 DECL_STATIC_CONSTRUCTOR (new_decl) = 0;
11446 DECL_STATIC_DESTRUCTOR (new_decl) = 0;
11447 new_node = old_node->create_version_clone (new_decl, vNULL, NULL);
11448 symtab->call_cgraph_insertion_hooks (new_node);
11449 }
11450 if (new_node == NULL)
11451 return new_node;
11452
11453 TREE_PUBLIC (new_node->decl) = TREE_PUBLIC (old_node->decl);
11454
11455 /* The function cgraph_function_versioning () will force the new
11456 symbol local. Undo this, and inherit external visability from
11457 the old node. */
11458 new_node->local.local = old_node->local.local;
11459 new_node->externally_visible = old_node->externally_visible;
11460
11461 return new_node;
11462 }
11463
11464 /* Adjust the return type of the given function to its appropriate
11465 vector counterpart. Returns a simd array to be used throughout the
11466 function as a return value. */
11467
11468 static tree
11469 simd_clone_adjust_return_type (struct cgraph_node *node)
11470 {
11471 tree fndecl = node->decl;
11472 tree orig_rettype = TREE_TYPE (TREE_TYPE (fndecl));
11473 unsigned int veclen;
11474 tree t;
11475
11476 /* Adjust the function return type. */
11477 if (orig_rettype == void_type_node)
11478 return NULL_TREE;
11479 TREE_TYPE (fndecl) = build_distinct_type_copy (TREE_TYPE (fndecl));
11480 if (INTEGRAL_TYPE_P (TREE_TYPE (TREE_TYPE (fndecl)))
11481 || POINTER_TYPE_P (TREE_TYPE (TREE_TYPE (fndecl))))
11482 veclen = node->simdclone->vecsize_int;
11483 else
11484 veclen = node->simdclone->vecsize_float;
11485 veclen /= GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (fndecl))));
11486 if (veclen > node->simdclone->simdlen)
11487 veclen = node->simdclone->simdlen;
11488 if (veclen == node->simdclone->simdlen)
11489 TREE_TYPE (TREE_TYPE (fndecl))
11490 = build_vector_type (TREE_TYPE (TREE_TYPE (fndecl)),
11491 node->simdclone->simdlen);
11492 else
11493 {
11494 t = build_vector_type (TREE_TYPE (TREE_TYPE (fndecl)), veclen);
11495 t = build_array_type_nelts (t, node->simdclone->simdlen / veclen);
11496 TREE_TYPE (TREE_TYPE (fndecl)) = t;
11497 }
11498 if (!node->definition)
11499 return NULL_TREE;
11500
11501 t = DECL_RESULT (fndecl);
11502 /* Adjust the DECL_RESULT. */
11503 gcc_assert (TREE_TYPE (t) != void_type_node);
11504 TREE_TYPE (t) = TREE_TYPE (TREE_TYPE (fndecl));
11505 relayout_decl (t);
11506
11507 tree atype = build_array_type_nelts (orig_rettype,
11508 node->simdclone->simdlen);
11509 if (veclen != node->simdclone->simdlen)
11510 return build1 (VIEW_CONVERT_EXPR, atype, t);
11511
11512 /* Set up a SIMD array to use as the return value. */
11513 tree retval = create_tmp_var_raw (atype, "retval");
11514 gimple_add_tmp_var (retval);
11515 return retval;
11516 }
11517
11518 /* Each vector argument has a corresponding array to be used locally
11519 as part of the eventual loop. Create such temporary array and
11520 return it.
11521
11522 PREFIX is the prefix to be used for the temporary.
11523
11524 TYPE is the inner element type.
11525
11526 SIMDLEN is the number of elements. */
11527
11528 static tree
11529 create_tmp_simd_array (const char *prefix, tree type, int simdlen)
11530 {
11531 tree atype = build_array_type_nelts (type, simdlen);
11532 tree avar = create_tmp_var_raw (atype, prefix);
11533 gimple_add_tmp_var (avar);
11534 return avar;
11535 }
11536
11537 /* Modify the function argument types to their corresponding vector
11538 counterparts if appropriate. Also, create one array for each simd
11539 argument to be used locally when using the function arguments as
11540 part of the loop.
11541
11542 NODE is the function whose arguments are to be adjusted.
11543
11544 Returns an adjustment vector that will be filled describing how the
11545 argument types will be adjusted. */
11546
11547 static ipa_parm_adjustment_vec
11548 simd_clone_adjust_argument_types (struct cgraph_node *node)
11549 {
11550 vec<tree> args;
11551 ipa_parm_adjustment_vec adjustments;
11552
11553 if (node->definition)
11554 args = ipa_get_vector_of_formal_parms (node->decl);
11555 else
11556 args = simd_clone_vector_of_formal_parm_types (node->decl);
11557 adjustments.create (args.length ());
11558 unsigned i, j, veclen;
11559 struct ipa_parm_adjustment adj;
11560 for (i = 0; i < node->simdclone->nargs; ++i)
11561 {
11562 memset (&adj, 0, sizeof (adj));
11563 tree parm = args[i];
11564 tree parm_type = node->definition ? TREE_TYPE (parm) : parm;
11565 adj.base_index = i;
11566 adj.base = parm;
11567
11568 node->simdclone->args[i].orig_arg = node->definition ? parm : NULL_TREE;
11569 node->simdclone->args[i].orig_type = parm_type;
11570
11571 if (node->simdclone->args[i].arg_type != SIMD_CLONE_ARG_TYPE_VECTOR)
11572 {
11573 /* No adjustment necessary for scalar arguments. */
11574 adj.op = IPA_PARM_OP_COPY;
11575 }
11576 else
11577 {
11578 if (INTEGRAL_TYPE_P (parm_type) || POINTER_TYPE_P (parm_type))
11579 veclen = node->simdclone->vecsize_int;
11580 else
11581 veclen = node->simdclone->vecsize_float;
11582 veclen /= GET_MODE_BITSIZE (TYPE_MODE (parm_type));
11583 if (veclen > node->simdclone->simdlen)
11584 veclen = node->simdclone->simdlen;
11585 adj.arg_prefix = "simd";
11586 adj.type = build_vector_type (parm_type, veclen);
11587 node->simdclone->args[i].vector_type = adj.type;
11588 for (j = veclen; j < node->simdclone->simdlen; j += veclen)
11589 {
11590 adjustments.safe_push (adj);
11591 if (j == veclen)
11592 {
11593 memset (&adj, 0, sizeof (adj));
11594 adj.op = IPA_PARM_OP_NEW;
11595 adj.arg_prefix = "simd";
11596 adj.base_index = i;
11597 adj.type = node->simdclone->args[i].vector_type;
11598 }
11599 }
11600
11601 if (node->definition)
11602 node->simdclone->args[i].simd_array
11603 = create_tmp_simd_array (IDENTIFIER_POINTER (DECL_NAME (parm)),
11604 parm_type, node->simdclone->simdlen);
11605 }
11606 adjustments.safe_push (adj);
11607 }
11608
11609 if (node->simdclone->inbranch)
11610 {
11611 tree base_type
11612 = simd_clone_compute_base_data_type (node->simdclone->origin,
11613 node->simdclone);
11614
11615 memset (&adj, 0, sizeof (adj));
11616 adj.op = IPA_PARM_OP_NEW;
11617 adj.arg_prefix = "mask";
11618
11619 adj.base_index = i;
11620 if (INTEGRAL_TYPE_P (base_type) || POINTER_TYPE_P (base_type))
11621 veclen = node->simdclone->vecsize_int;
11622 else
11623 veclen = node->simdclone->vecsize_float;
11624 veclen /= GET_MODE_BITSIZE (TYPE_MODE (base_type));
11625 if (veclen > node->simdclone->simdlen)
11626 veclen = node->simdclone->simdlen;
11627 adj.type = build_vector_type (base_type, veclen);
11628 adjustments.safe_push (adj);
11629
11630 for (j = veclen; j < node->simdclone->simdlen; j += veclen)
11631 adjustments.safe_push (adj);
11632
11633 /* We have previously allocated one extra entry for the mask. Use
11634 it and fill it. */
11635 struct cgraph_simd_clone *sc = node->simdclone;
11636 sc->nargs++;
11637 if (node->definition)
11638 {
11639 sc->args[i].orig_arg
11640 = build_decl (UNKNOWN_LOCATION, PARM_DECL, NULL, base_type);
11641 sc->args[i].simd_array
11642 = create_tmp_simd_array ("mask", base_type, sc->simdlen);
11643 }
11644 sc->args[i].orig_type = base_type;
11645 sc->args[i].arg_type = SIMD_CLONE_ARG_TYPE_MASK;
11646 }
11647
11648 if (node->definition)
11649 ipa_modify_formal_parameters (node->decl, adjustments);
11650 else
11651 {
11652 tree new_arg_types = NULL_TREE, new_reversed;
11653 bool last_parm_void = false;
11654 if (args.length () > 0 && args.last () == void_type_node)
11655 last_parm_void = true;
11656
11657 gcc_assert (TYPE_ARG_TYPES (TREE_TYPE (node->decl)));
11658 j = adjustments.length ();
11659 for (i = 0; i < j; i++)
11660 {
11661 struct ipa_parm_adjustment *adj = &adjustments[i];
11662 tree ptype;
11663 if (adj->op == IPA_PARM_OP_COPY)
11664 ptype = args[adj->base_index];
11665 else
11666 ptype = adj->type;
11667 new_arg_types = tree_cons (NULL_TREE, ptype, new_arg_types);
11668 }
11669 new_reversed = nreverse (new_arg_types);
11670 if (last_parm_void)
11671 {
11672 if (new_reversed)
11673 TREE_CHAIN (new_arg_types) = void_list_node;
11674 else
11675 new_reversed = void_list_node;
11676 }
11677
11678 tree new_type = build_distinct_type_copy (TREE_TYPE (node->decl));
11679 TYPE_ARG_TYPES (new_type) = new_reversed;
11680 TREE_TYPE (node->decl) = new_type;
11681
11682 adjustments.release ();
11683 }
11684 args.release ();
11685 return adjustments;
11686 }
11687
11688 /* Initialize and copy the function arguments in NODE to their
11689 corresponding local simd arrays. Returns a fresh gimple_seq with
11690 the instruction sequence generated. */
11691
11692 static gimple_seq
11693 simd_clone_init_simd_arrays (struct cgraph_node *node,
11694 ipa_parm_adjustment_vec adjustments)
11695 {
11696 gimple_seq seq = NULL;
11697 unsigned i = 0, j = 0, k;
11698
11699 for (tree arg = DECL_ARGUMENTS (node->decl);
11700 arg;
11701 arg = DECL_CHAIN (arg), i++, j++)
11702 {
11703 if (adjustments[j].op == IPA_PARM_OP_COPY)
11704 continue;
11705
11706 node->simdclone->args[i].vector_arg = arg;
11707
11708 tree array = node->simdclone->args[i].simd_array;
11709 if (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg)) == node->simdclone->simdlen)
11710 {
11711 tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
11712 tree ptr = build_fold_addr_expr (array);
11713 tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
11714 build_int_cst (ptype, 0));
11715 t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
11716 gimplify_and_add (t, &seq);
11717 }
11718 else
11719 {
11720 unsigned int simdlen = TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg));
11721 tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
11722 for (k = 0; k < node->simdclone->simdlen; k += simdlen)
11723 {
11724 tree ptr = build_fold_addr_expr (array);
11725 int elemsize;
11726 if (k)
11727 {
11728 arg = DECL_CHAIN (arg);
11729 j++;
11730 }
11731 elemsize
11732 = GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (arg))));
11733 tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
11734 build_int_cst (ptype, k * elemsize));
11735 t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
11736 gimplify_and_add (t, &seq);
11737 }
11738 }
11739 }
11740 return seq;
11741 }
11742
11743 /* Callback info for ipa_simd_modify_stmt_ops below. */
11744
11745 struct modify_stmt_info {
11746 ipa_parm_adjustment_vec adjustments;
11747 gimple stmt;
11748 /* True if the parent statement was modified by
11749 ipa_simd_modify_stmt_ops. */
11750 bool modified;
11751 };
11752
11753 /* Callback for walk_gimple_op.
11754
11755 Adjust operands from a given statement as specified in the
11756 adjustments vector in the callback data. */
11757
11758 static tree
11759 ipa_simd_modify_stmt_ops (tree *tp, int *walk_subtrees, void *data)
11760 {
11761 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
11762 struct modify_stmt_info *info = (struct modify_stmt_info *) wi->info;
11763 tree *orig_tp = tp;
11764 if (TREE_CODE (*tp) == ADDR_EXPR)
11765 tp = &TREE_OPERAND (*tp, 0);
11766 struct ipa_parm_adjustment *cand = NULL;
11767 if (TREE_CODE (*tp) == PARM_DECL)
11768 cand = ipa_get_adjustment_candidate (&tp, NULL, info->adjustments, true);
11769 else
11770 {
11771 if (TYPE_P (*tp))
11772 *walk_subtrees = 0;
11773 }
11774
11775 tree repl = NULL_TREE;
11776 if (cand)
11777 repl = unshare_expr (cand->new_decl);
11778 else
11779 {
11780 if (tp != orig_tp)
11781 {
11782 *walk_subtrees = 0;
11783 bool modified = info->modified;
11784 info->modified = false;
11785 walk_tree (tp, ipa_simd_modify_stmt_ops, wi, wi->pset);
11786 if (!info->modified)
11787 {
11788 info->modified = modified;
11789 return NULL_TREE;
11790 }
11791 info->modified = modified;
11792 repl = *tp;
11793 }
11794 else
11795 return NULL_TREE;
11796 }
11797
11798 if (tp != orig_tp)
11799 {
11800 repl = build_fold_addr_expr (repl);
11801 gimple stmt;
11802 if (is_gimple_debug (info->stmt))
11803 {
11804 tree vexpr = make_node (DEBUG_EXPR_DECL);
11805 stmt = gimple_build_debug_source_bind (vexpr, repl, NULL);
11806 DECL_ARTIFICIAL (vexpr) = 1;
11807 TREE_TYPE (vexpr) = TREE_TYPE (repl);
11808 DECL_MODE (vexpr) = TYPE_MODE (TREE_TYPE (repl));
11809 repl = vexpr;
11810 }
11811 else
11812 {
11813 stmt = gimple_build_assign (make_ssa_name (TREE_TYPE (repl),
11814 NULL), repl);
11815 repl = gimple_assign_lhs (stmt);
11816 }
11817 gimple_stmt_iterator gsi = gsi_for_stmt (info->stmt);
11818 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
11819 *orig_tp = repl;
11820 }
11821 else if (!useless_type_conversion_p (TREE_TYPE (*tp), TREE_TYPE (repl)))
11822 {
11823 tree vce = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (*tp), repl);
11824 *tp = vce;
11825 }
11826 else
11827 *tp = repl;
11828
11829 info->modified = true;
11830 return NULL_TREE;
11831 }
11832
11833 /* Traverse the function body and perform all modifications as
11834 described in ADJUSTMENTS. At function return, ADJUSTMENTS will be
11835 modified such that the replacement/reduction value will now be an
11836 offset into the corresponding simd_array.
11837
11838 This function will replace all function argument uses with their
11839 corresponding simd array elements, and ajust the return values
11840 accordingly. */
11841
11842 static void
11843 ipa_simd_modify_function_body (struct cgraph_node *node,
11844 ipa_parm_adjustment_vec adjustments,
11845 tree retval_array, tree iter)
11846 {
11847 basic_block bb;
11848 unsigned int i, j, l;
11849
11850 /* Re-use the adjustments array, but this time use it to replace
11851 every function argument use to an offset into the corresponding
11852 simd_array. */
11853 for (i = 0, j = 0; i < node->simdclone->nargs; ++i, ++j)
11854 {
11855 if (!node->simdclone->args[i].vector_arg)
11856 continue;
11857
11858 tree basetype = TREE_TYPE (node->simdclone->args[i].orig_arg);
11859 tree vectype = TREE_TYPE (node->simdclone->args[i].vector_arg);
11860 adjustments[j].new_decl
11861 = build4 (ARRAY_REF,
11862 basetype,
11863 node->simdclone->args[i].simd_array,
11864 iter,
11865 NULL_TREE, NULL_TREE);
11866 if (adjustments[j].op == IPA_PARM_OP_NONE
11867 && TYPE_VECTOR_SUBPARTS (vectype) < node->simdclone->simdlen)
11868 j += node->simdclone->simdlen / TYPE_VECTOR_SUBPARTS (vectype) - 1;
11869 }
11870
11871 l = adjustments.length ();
11872 for (i = 1; i < num_ssa_names; i++)
11873 {
11874 tree name = ssa_name (i);
11875 if (name
11876 && SSA_NAME_VAR (name)
11877 && TREE_CODE (SSA_NAME_VAR (name)) == PARM_DECL)
11878 {
11879 for (j = 0; j < l; j++)
11880 if (SSA_NAME_VAR (name) == adjustments[j].base
11881 && adjustments[j].new_decl)
11882 {
11883 tree base_var;
11884 if (adjustments[j].new_ssa_base == NULL_TREE)
11885 {
11886 base_var
11887 = copy_var_decl (adjustments[j].base,
11888 DECL_NAME (adjustments[j].base),
11889 TREE_TYPE (adjustments[j].base));
11890 adjustments[j].new_ssa_base = base_var;
11891 }
11892 else
11893 base_var = adjustments[j].new_ssa_base;
11894 if (SSA_NAME_IS_DEFAULT_DEF (name))
11895 {
11896 bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
11897 gimple_stmt_iterator gsi = gsi_after_labels (bb);
11898 tree new_decl = unshare_expr (adjustments[j].new_decl);
11899 set_ssa_default_def (cfun, adjustments[j].base, NULL_TREE);
11900 SET_SSA_NAME_VAR_OR_IDENTIFIER (name, base_var);
11901 SSA_NAME_IS_DEFAULT_DEF (name) = 0;
11902 gimple stmt = gimple_build_assign (name, new_decl);
11903 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
11904 }
11905 else
11906 SET_SSA_NAME_VAR_OR_IDENTIFIER (name, base_var);
11907 }
11908 }
11909 }
11910
11911 struct modify_stmt_info info;
11912 info.adjustments = adjustments;
11913
11914 FOR_EACH_BB_FN (bb, DECL_STRUCT_FUNCTION (node->decl))
11915 {
11916 gimple_stmt_iterator gsi;
11917
11918 gsi = gsi_start_bb (bb);
11919 while (!gsi_end_p (gsi))
11920 {
11921 gimple stmt = gsi_stmt (gsi);
11922 info.stmt = stmt;
11923 struct walk_stmt_info wi;
11924
11925 memset (&wi, 0, sizeof (wi));
11926 info.modified = false;
11927 wi.info = &info;
11928 walk_gimple_op (stmt, ipa_simd_modify_stmt_ops, &wi);
11929
11930 if (gimple_code (stmt) == GIMPLE_RETURN)
11931 {
11932 tree retval = gimple_return_retval (stmt);
11933 if (!retval)
11934 {
11935 gsi_remove (&gsi, true);
11936 continue;
11937 }
11938
11939 /* Replace `return foo' with `retval_array[iter] = foo'. */
11940 tree ref = build4 (ARRAY_REF, TREE_TYPE (retval),
11941 retval_array, iter, NULL, NULL);
11942 stmt = gimple_build_assign (ref, retval);
11943 gsi_replace (&gsi, stmt, true);
11944 info.modified = true;
11945 }
11946
11947 if (info.modified)
11948 {
11949 update_stmt (stmt);
11950 if (maybe_clean_eh_stmt (stmt))
11951 gimple_purge_dead_eh_edges (gimple_bb (stmt));
11952 }
11953 gsi_next (&gsi);
11954 }
11955 }
11956 }
11957
11958 /* Adjust the argument types in NODE to their appropriate vector
11959 counterparts. */
11960
11961 static void
11962 simd_clone_adjust (struct cgraph_node *node)
11963 {
11964 push_cfun (DECL_STRUCT_FUNCTION (node->decl));
11965
11966 targetm.simd_clone.adjust (node);
11967
11968 tree retval = simd_clone_adjust_return_type (node);
11969 ipa_parm_adjustment_vec adjustments
11970 = simd_clone_adjust_argument_types (node);
11971
11972 push_gimplify_context ();
11973
11974 gimple_seq seq = simd_clone_init_simd_arrays (node, adjustments);
11975
11976 /* Adjust all uses of vector arguments accordingly. Adjust all
11977 return values accordingly. */
11978 tree iter = create_tmp_var (unsigned_type_node, "iter");
11979 tree iter1 = make_ssa_name (iter, NULL);
11980 tree iter2 = make_ssa_name (iter, NULL);
11981 ipa_simd_modify_function_body (node, adjustments, retval, iter1);
11982
11983 /* Initialize the iteration variable. */
11984 basic_block entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
11985 basic_block body_bb = split_block_after_labels (entry_bb)->dest;
11986 gimple_stmt_iterator gsi = gsi_after_labels (entry_bb);
11987 /* Insert the SIMD array and iv initialization at function
11988 entry. */
11989 gsi_insert_seq_before (&gsi, seq, GSI_NEW_STMT);
11990
11991 pop_gimplify_context (NULL);
11992
11993 /* Create a new BB right before the original exit BB, to hold the
11994 iteration increment and the condition/branch. */
11995 basic_block orig_exit = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), 0)->src;
11996 basic_block incr_bb = create_empty_bb (orig_exit);
11997 add_bb_to_loop (incr_bb, body_bb->loop_father);
11998 /* The succ of orig_exit was EXIT_BLOCK_PTR_FOR_FN (cfun), with an empty
11999 flag. Set it now to be a FALLTHRU_EDGE. */
12000 gcc_assert (EDGE_COUNT (orig_exit->succs) == 1);
12001 EDGE_SUCC (orig_exit, 0)->flags |= EDGE_FALLTHRU;
12002 for (unsigned i = 0;
12003 i < EDGE_COUNT (EXIT_BLOCK_PTR_FOR_FN (cfun)->preds); ++i)
12004 {
12005 edge e = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), i);
12006 redirect_edge_succ (e, incr_bb);
12007 }
12008 edge e = make_edge (incr_bb, EXIT_BLOCK_PTR_FOR_FN (cfun), 0);
12009 e->probability = REG_BR_PROB_BASE;
12010 gsi = gsi_last_bb (incr_bb);
12011 gimple g = gimple_build_assign_with_ops (PLUS_EXPR, iter2, iter1,
12012 build_int_cst (unsigned_type_node,
12013 1));
12014 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
12015
12016 /* Mostly annotate the loop for the vectorizer (the rest is done below). */
12017 struct loop *loop = alloc_loop ();
12018 cfun->has_force_vectorize_loops = true;
12019 loop->safelen = node->simdclone->simdlen;
12020 loop->force_vectorize = true;
12021 loop->header = body_bb;
12022
12023 /* Branch around the body if the mask applies. */
12024 if (node->simdclone->inbranch)
12025 {
12026 gimple_stmt_iterator gsi = gsi_last_bb (loop->header);
12027 tree mask_array
12028 = node->simdclone->args[node->simdclone->nargs - 1].simd_array;
12029 tree mask = make_ssa_name (TREE_TYPE (TREE_TYPE (mask_array)), NULL);
12030 tree aref = build4 (ARRAY_REF,
12031 TREE_TYPE (TREE_TYPE (mask_array)),
12032 mask_array, iter1,
12033 NULL, NULL);
12034 g = gimple_build_assign (mask, aref);
12035 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
12036 int bitsize = GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (aref)));
12037 if (!INTEGRAL_TYPE_P (TREE_TYPE (aref)))
12038 {
12039 aref = build1 (VIEW_CONVERT_EXPR,
12040 build_nonstandard_integer_type (bitsize, 0), mask);
12041 mask = make_ssa_name (TREE_TYPE (aref), NULL);
12042 g = gimple_build_assign (mask, aref);
12043 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
12044 }
12045
12046 g = gimple_build_cond (EQ_EXPR, mask, build_zero_cst (TREE_TYPE (mask)),
12047 NULL, NULL);
12048 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
12049 make_edge (loop->header, incr_bb, EDGE_TRUE_VALUE);
12050 FALLTHRU_EDGE (loop->header)->flags = EDGE_FALSE_VALUE;
12051 }
12052
12053 /* Generate the condition. */
12054 g = gimple_build_cond (LT_EXPR,
12055 iter2,
12056 build_int_cst (unsigned_type_node,
12057 node->simdclone->simdlen),
12058 NULL, NULL);
12059 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
12060 e = split_block (incr_bb, gsi_stmt (gsi));
12061 basic_block latch_bb = e->dest;
12062 basic_block new_exit_bb;
12063 new_exit_bb = split_block (latch_bb, NULL)->dest;
12064 loop->latch = latch_bb;
12065
12066 redirect_edge_succ (FALLTHRU_EDGE (latch_bb), body_bb);
12067
12068 make_edge (incr_bb, new_exit_bb, EDGE_FALSE_VALUE);
12069 /* The successor of incr_bb is already pointing to latch_bb; just
12070 change the flags.
12071 make_edge (incr_bb, latch_bb, EDGE_TRUE_VALUE); */
12072 FALLTHRU_EDGE (incr_bb)->flags = EDGE_TRUE_VALUE;
12073
12074 gimple phi = create_phi_node (iter1, body_bb);
12075 edge preheader_edge = find_edge (entry_bb, body_bb);
12076 edge latch_edge = single_succ_edge (latch_bb);
12077 add_phi_arg (phi, build_zero_cst (unsigned_type_node), preheader_edge,
12078 UNKNOWN_LOCATION);
12079 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
12080
12081 /* Generate the new return. */
12082 gsi = gsi_last_bb (new_exit_bb);
12083 if (retval
12084 && TREE_CODE (retval) == VIEW_CONVERT_EXPR
12085 && TREE_CODE (TREE_OPERAND (retval, 0)) == RESULT_DECL)
12086 retval = TREE_OPERAND (retval, 0);
12087 else if (retval)
12088 {
12089 retval = build1 (VIEW_CONVERT_EXPR,
12090 TREE_TYPE (TREE_TYPE (node->decl)),
12091 retval);
12092 retval = force_gimple_operand_gsi (&gsi, retval, true, NULL,
12093 false, GSI_CONTINUE_LINKING);
12094 }
12095 g = gimple_build_return (retval);
12096 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
12097
12098 /* Handle aligned clauses by replacing default defs of the aligned
12099 uniform args with __builtin_assume_aligned (arg_N(D), alignment)
12100 lhs. Handle linear by adding PHIs. */
12101 for (unsigned i = 0; i < node->simdclone->nargs; i++)
12102 if (node->simdclone->args[i].alignment
12103 && node->simdclone->args[i].arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM
12104 && (node->simdclone->args[i].alignment
12105 & (node->simdclone->args[i].alignment - 1)) == 0
12106 && TREE_CODE (TREE_TYPE (node->simdclone->args[i].orig_arg))
12107 == POINTER_TYPE)
12108 {
12109 unsigned int alignment = node->simdclone->args[i].alignment;
12110 tree orig_arg = node->simdclone->args[i].orig_arg;
12111 tree def = ssa_default_def (cfun, orig_arg);
12112 if (def && !has_zero_uses (def))
12113 {
12114 tree fn = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
12115 gimple_seq seq = NULL;
12116 bool need_cvt = false;
12117 gimple call
12118 = gimple_build_call (fn, 2, def, size_int (alignment));
12119 g = call;
12120 if (!useless_type_conversion_p (TREE_TYPE (orig_arg),
12121 ptr_type_node))
12122 need_cvt = true;
12123 tree t = make_ssa_name (need_cvt ? ptr_type_node : orig_arg, NULL);
12124 gimple_call_set_lhs (g, t);
12125 gimple_seq_add_stmt_without_update (&seq, g);
12126 if (need_cvt)
12127 {
12128 t = make_ssa_name (orig_arg, NULL);
12129 g = gimple_build_assign_with_ops (NOP_EXPR, t,
12130 gimple_call_lhs (g),
12131 NULL_TREE);
12132 gimple_seq_add_stmt_without_update (&seq, g);
12133 }
12134 gsi_insert_seq_on_edge_immediate
12135 (single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun)), seq);
12136
12137 entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
12138 int freq = compute_call_stmt_bb_frequency (current_function_decl,
12139 entry_bb);
12140 node->create_edge (cgraph_node::get_create (fn),
12141 call, entry_bb->count, freq);
12142
12143 imm_use_iterator iter;
12144 use_operand_p use_p;
12145 gimple use_stmt;
12146 tree repl = gimple_get_lhs (g);
12147 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
12148 if (is_gimple_debug (use_stmt) || use_stmt == call)
12149 continue;
12150 else
12151 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
12152 SET_USE (use_p, repl);
12153 }
12154 }
12155 else if (node->simdclone->args[i].arg_type
12156 == SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP)
12157 {
12158 tree orig_arg = node->simdclone->args[i].orig_arg;
12159 tree def = ssa_default_def (cfun, orig_arg);
12160 gcc_assert (INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
12161 || POINTER_TYPE_P (TREE_TYPE (orig_arg)));
12162 if (def && !has_zero_uses (def))
12163 {
12164 iter1 = make_ssa_name (orig_arg, NULL);
12165 iter2 = make_ssa_name (orig_arg, NULL);
12166 phi = create_phi_node (iter1, body_bb);
12167 add_phi_arg (phi, def, preheader_edge, UNKNOWN_LOCATION);
12168 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
12169 enum tree_code code = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
12170 ? PLUS_EXPR : POINTER_PLUS_EXPR;
12171 tree addtype = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
12172 ? TREE_TYPE (orig_arg) : sizetype;
12173 tree addcst
12174 = build_int_cst (addtype, node->simdclone->args[i].linear_step);
12175 g = gimple_build_assign_with_ops (code, iter2, iter1, addcst);
12176 gsi = gsi_last_bb (incr_bb);
12177 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
12178
12179 imm_use_iterator iter;
12180 use_operand_p use_p;
12181 gimple use_stmt;
12182 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
12183 if (use_stmt == phi)
12184 continue;
12185 else
12186 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
12187 SET_USE (use_p, iter1);
12188 }
12189 }
12190
12191 calculate_dominance_info (CDI_DOMINATORS);
12192 add_loop (loop, loop->header->loop_father);
12193 update_ssa (TODO_update_ssa);
12194
12195 pop_cfun ();
12196 }
12197
12198 /* If the function in NODE is tagged as an elemental SIMD function,
12199 create the appropriate SIMD clones. */
12200
12201 static void
12202 expand_simd_clones (struct cgraph_node *node)
12203 {
12204 tree attr = lookup_attribute ("omp declare simd",
12205 DECL_ATTRIBUTES (node->decl));
12206 if (attr == NULL_TREE
12207 || node->global.inlined_to
12208 || lookup_attribute ("noclone", DECL_ATTRIBUTES (node->decl)))
12209 return;
12210
12211 /* Ignore
12212 #pragma omp declare simd
12213 extern int foo ();
12214 in C, there we don't know the argument types at all. */
12215 if (!node->definition
12216 && TYPE_ARG_TYPES (TREE_TYPE (node->decl)) == NULL_TREE)
12217 return;
12218
12219 do
12220 {
12221 /* Start with parsing the "omp declare simd" attribute(s). */
12222 bool inbranch_clause_specified;
12223 struct cgraph_simd_clone *clone_info
12224 = simd_clone_clauses_extract (node, TREE_VALUE (attr),
12225 &inbranch_clause_specified);
12226 if (clone_info == NULL)
12227 continue;
12228
12229 int orig_simdlen = clone_info->simdlen;
12230 tree base_type = simd_clone_compute_base_data_type (node, clone_info);
12231 /* The target can return 0 (no simd clones should be created),
12232 1 (just one ISA of simd clones should be created) or higher
12233 count of ISA variants. In that case, clone_info is initialized
12234 for the first ISA variant. */
12235 int count
12236 = targetm.simd_clone.compute_vecsize_and_simdlen (node, clone_info,
12237 base_type, 0);
12238 if (count == 0)
12239 continue;
12240
12241 /* Loop over all COUNT ISA variants, and if !INBRANCH_CLAUSE_SPECIFIED,
12242 also create one inbranch and one !inbranch clone of it. */
12243 for (int i = 0; i < count * 2; i++)
12244 {
12245 struct cgraph_simd_clone *clone = clone_info;
12246 if (inbranch_clause_specified && (i & 1) != 0)
12247 continue;
12248
12249 if (i != 0)
12250 {
12251 clone = simd_clone_struct_alloc (clone_info->nargs
12252 + ((i & 1) != 0));
12253 simd_clone_struct_copy (clone, clone_info);
12254 /* Undo changes targetm.simd_clone.compute_vecsize_and_simdlen
12255 and simd_clone_adjust_argument_types did to the first
12256 clone's info. */
12257 clone->nargs -= clone_info->inbranch;
12258 clone->simdlen = orig_simdlen;
12259 /* And call the target hook again to get the right ISA. */
12260 targetm.simd_clone.compute_vecsize_and_simdlen (node, clone,
12261 base_type,
12262 i / 2);
12263 if ((i & 1) != 0)
12264 clone->inbranch = 1;
12265 }
12266
12267 /* simd_clone_mangle might fail if such a clone has been created
12268 already. */
12269 tree id = simd_clone_mangle (node, clone);
12270 if (id == NULL_TREE)
12271 continue;
12272
12273 /* Only when we are sure we want to create the clone actually
12274 clone the function (or definitions) or create another
12275 extern FUNCTION_DECL (for prototypes without definitions). */
12276 struct cgraph_node *n = simd_clone_create (node);
12277 if (n == NULL)
12278 continue;
12279
12280 n->simdclone = clone;
12281 clone->origin = node;
12282 clone->next_clone = NULL;
12283 if (node->simd_clones == NULL)
12284 {
12285 clone->prev_clone = n;
12286 node->simd_clones = n;
12287 }
12288 else
12289 {
12290 clone->prev_clone = node->simd_clones->simdclone->prev_clone;
12291 clone->prev_clone->simdclone->next_clone = n;
12292 node->simd_clones->simdclone->prev_clone = n;
12293 }
12294 symtab->change_decl_assembler_name (n->decl, id);
12295 /* And finally adjust the return type, parameters and for
12296 definitions also function body. */
12297 if (node->definition)
12298 simd_clone_adjust (n);
12299 else
12300 {
12301 simd_clone_adjust_return_type (n);
12302 simd_clone_adjust_argument_types (n);
12303 }
12304 }
12305 }
12306 while ((attr = lookup_attribute ("omp declare simd", TREE_CHAIN (attr))));
12307 }
12308
12309 /* Entry point for IPA simd clone creation pass. */
12310
12311 static unsigned int
12312 ipa_omp_simd_clone (void)
12313 {
12314 struct cgraph_node *node;
12315 FOR_EACH_FUNCTION (node)
12316 expand_simd_clones (node);
12317 return 0;
12318 }
12319
12320 namespace {
12321
12322 const pass_data pass_data_omp_simd_clone =
12323 {
12324 SIMPLE_IPA_PASS, /* type */
12325 "simdclone", /* name */
12326 OPTGROUP_NONE, /* optinfo_flags */
12327 TV_NONE, /* tv_id */
12328 ( PROP_ssa | PROP_cfg ), /* properties_required */
12329 0, /* properties_provided */
12330 0, /* properties_destroyed */
12331 0, /* todo_flags_start */
12332 0, /* todo_flags_finish */
12333 };
12334
12335 class pass_omp_simd_clone : public simple_ipa_opt_pass
12336 {
12337 public:
12338 pass_omp_simd_clone(gcc::context *ctxt)
12339 : simple_ipa_opt_pass(pass_data_omp_simd_clone, ctxt)
12340 {}
12341
12342 /* opt_pass methods: */
12343 virtual bool gate (function *);
12344 virtual unsigned int execute (function *) { return ipa_omp_simd_clone (); }
12345 };
12346
12347 bool
12348 pass_omp_simd_clone::gate (function *)
12349 {
12350 return ((flag_openmp || flag_openmp_simd
12351 || flag_cilkplus
12352 || (in_lto_p && !flag_wpa))
12353 && (targetm.simd_clone.compute_vecsize_and_simdlen != NULL));
12354 }
12355
12356 } // anon namespace
12357
12358 simple_ipa_opt_pass *
12359 make_pass_omp_simd_clone (gcc::context *ctxt)
12360 {
12361 return new pass_omp_simd_clone (ctxt);
12362 }
12363
12364 #include "gt-omp-low.h"