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